--- /dev/null
+-------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+-------------------------------------------------------------------------
+
======================================================================
This file covers how to build and install the Imagination Technologies
-SGX DDK for the Linux kernel.
+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
+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.
+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
+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
+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
+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 SGX DDK configures different target builds within directories under
+eurasiacon/build/linux/.
The supported build targets are:
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.
+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.
+ 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
Become an ordinary user again:
$ exit
-
-
-
-
--- /dev/null
+
+This software is Copyright (C) Imagination Technologies Ltd.
+
+You may use, distribute and copy this software under the terms of the MIT
+license displayed below.
+
+-----------------------------------------------------------------------------
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, this Software may be used under the terms of the GNU General
+Public License Version 2 ("GPL") in which case the provisions of GPL are
+applicable instead of those above.
+
+If you wish to allow use of your version of this Software only under the terms
+of GPL, and not to allow others to use your version of this file under the
+terms of the MIT license, indicate your decision by deleting from each file
+the provisions above and replace them with the notice and other provisions
+required by GPL as set out in the file called "GPL-COPYING" included in this
+distribution. If you do not delete the provisions above, a recipient may use
+your version of this file under the terms of either the MIT license or GPL.
+
+-----------------------------------------------------------------------------
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-----------------------------------------------------------------------------
SUPPORT_LINUX_X86_PAT ?=1
SUPPORT_LINUX_X86_WRITECOMBINE ?=1
SUPPORT_SGX_LOW_LATENCY_SCHEDULING ?=1
+SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER ?=1
ifeq ($(SUPPORT_XORG),1)
SUPPORT_PDUMP_MULTI_PROCESS = 1
SYS_CFLAGS.$(SUPPORT_PERCONTEXT_PB) += -DSUPPORT_PERCONTEXT_PB
SYS_CFLAGS.$(SUPPORT_DYNAMIC_PBRESIZE) += -DSUPPORT_DYNAMIC_PBRESIZE
SYS_CFLAGS.$(DISABLE_SGX_PB_GROW_SHRINK) += -DDISABLE_SGX_PB_GROW_SHRINK
+SYS_CFLAGS.$(SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER) += -DSUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER
SYS_CFLAGS.$(USE_FBDEV) += -DUSE_FBDEV
SYS_CFLAGS.$(USE_FBDEV) += -DFBDEV_NAME="\"$(FBDEV_NAME)\""
About
-------------------------------------------
-This is the Imagination Technologies SGX DDK for the Linux kernel.
+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.
+You may use, distribute and copy this software under the terms of the MIT
+license. Details of this license can be found in the file "MIT-COPYING".
-The full GNU General Public License version 2 is included in this
-distribution in the file called "COPYING".
+Alternatively, you may use, distribute and copy this software under the terms
+of the GNU General Public License version 2. The full GNU General Public
+License version 2 can be found in the file "GPL-COPYING".
Build and Install Instructions
$ su
Install the DDK software:
-$ make install
+# make install
Become an ordinary user again:
$ exit
-------------------------------------------
Imagination Technologies Ltd. <gpl-support@imgtec.com>
-Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Title Useful special targets which don't build anything
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
-
-# Useful special targets which don't build anything
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
ifneq ($(filter dumpvar-%,$(MAKECMDGOALS)),)
dumpvar-%: ;
$(foreach _file_to_find,$(patsubst whatis-%,%,$(filter whatis-%,$(MAKECMDGOALS))),$(info $(strip $(foreach _m,$(ALL_MODULES),$(if $(filter $(_file_to_find),$(INTERNAL_TARGETS_FOR_$(_m))),$(_file_to_find) is in $(_m) which is defined in $(INTERNAL_MAKEFILE_FOR_MODULE_$(_m)),)))))
endif
-.PHONY: ls-modules ls-modules-v
+.PHONY: ls-modules
ls-modules:
- @: $(foreach _m,$(ALL_MODULES),$(info $(_m)))
-ls-modules-v:
@: $(foreach _m,$(ALL_MODULES),$(info $($(_m)_type) $(_m) $(patsubst $(TOP)/%,%,$(INTERNAL_MAKEFILE_FOR_MODULE_$(_m)))))
ifeq ($(strip $(MAKECMDGOALS)),visualise)
.PHONY: help
help:
@echo 'Build targets'
- @echo ' make, make build Build the UM/KM components of the build and scripts'
- @echo ' make components Build only the UM components'
- @echo ' make kbuild Build only the KM components'
- @echo ' make scripts Build only the scripts (rc.pvr and install.sh)'
- @echo ' make MODULE Build the module MODULE and all its dependencies'
+ @echo ' make, make build Build all components of the build'
+ @echo ' make components Build only the user-mode components'
+ @echo ' make kbuild Build only the kernel-mode components'
+ @echo ' make MODULE Build the module MODULE and all of its dependencies'
@echo ' make eurasiacon/binary2_.../target/libsomething.so'
@echo ' Build a particular file (including intermediates)'
@echo 'Variables'
@echo ' make V=1 ... Print the commands that are executed'
+ @echo ' make W=1 ... Enable extra compiler warnings'
+ @echo ' make D=opt ... Set build system debug option (D=help for a list)'
@echo ' make OUT=dir ... Place output+intermediates in specified directory'
- @echo ' make SOMEOPTION=1 ... Set configuration options (see Makefile.config)'
- @echo ''
+ @echo ' EXCLUDED_APIS=... List of APIs to remove from the build'
+ @echo ' make SOMEOPTION=1 ... Set configuration options (see config/core.mk)'
+ @echo ' Defaults are set by $(PVR_BUILD_DIR)/Makefile'
@echo 'Clean targets'
@echo ' make clean Remove only intermediates for the current build'
@echo ' make clobber As "make clean", but remove output files too'
@echo 'Special targets'
@echo ' make whereis-MODULE Show the path to the Linux.mk defining MODULE'
@echo ' make whatis-FILE Show which module builds an output FILE'
- @echo ' make ls-modules[-v] List all modules [with type+makefile]'
+ @echo ' make ls-modules List all modules defined by makefiles'
+
+ifneq ($(filter help,$(D)),)
+empty :=
+space := $(empty) $(empty)
+$(info Debug options)
+$(info $(space)D=modules dump module info)
+$(info $(space)D=freeze-config prevent config changes)
+$(info $(space)D=config-changes dump diffs when config changes)
+$(info Options may be combined: make D=freeze-config,config-changes)
+$(error D=help given)
+endif
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Title Define global variables
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@Description This file is read once at the start of the build, after reading
+# in config.mk. It should define the non-MODULE_* variables used
+# in commands, like ALL_CFLAGS
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
-
-#
-# This file is read once at the start of the build, after reading in
-# config.mk. It should define the non-MODULE_* variables used in commands,
-# like ALL_CFLAGS
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
ifeq ($(BUILD),debug)
-COMMON_FLAGS := -O0
+COMMON_USER_FLAGS := -O0
else
OPTIM ?= -O2
-COMMON_FLAGS := $(OPTIM)
+COMMON_USER_FLAGS := $(OPTIM)
endif
# FIXME: We should probably audit the driver for aliasing
#
-COMMON_FLAGS += -fno-strict-aliasing
+COMMON_USER_FLAGS += -fno-strict-aliasing
# We always enable debugging. Either the release binaries are stripped
# and the symbols put in the symbolpackage, or we're building debug.
#
-COMMON_FLAGS += -g
+COMMON_USER_FLAGS += -g
# These flags are used for kernel, User C and User C++
#
-COMMON_FLAGS += \
- -W -Wall -Wno-missing-field-initializers -Wmissing-format-attribute
+COMMON_FLAGS = -W -Wall
# Some GCC warnings are C only, so we must mask them from C++
#
-Wdeclaration-after-statement -Wno-format-zero-length \
-Wmissing-prototypes -Wstrict-prototypes
-# If we saw W=1, turn on some extra warnings.
-# Most of these flags are new, so cc-option check them.
+# Additional warnings, and optional warnings.
#
+WARNING_CFLAGS := \
+ -Wpointer-arith -Wunused-parameter \
+ -Wmissing-format-attribute \
+ $(call cc-option,-Wno-missing-field-initializers) \
+ $(call cc-option,-fdiagnostics-show-option)
+
ifeq ($(W),1)
-COMMON_CFLAGS += \
+WARNING_CFLAGS += \
$(call cc-option,-Wbad-function-cast) \
$(call cc-option,-Wcast-qual) \
$(call cc-option,-Wcast-align) \
$(call cc-option,-Wwrite-strings)
endif
+WARNING_CFLAGS += \
+ $(call cc-optional-warning,-Wunused-but-set-variable)
+
+HOST_WARNING_CFLAGS := \
+ -Wpointer-arith -Wunused-parameter \
+ -Wmissing-format-attribute \
+ $(call host-cc-option,-Wno-missing-field-initializers) \
+ $(call host-cc-option,-fdiagnostics-show-option)
+
+ifeq ($(W),1)
+HOST_WARNING_CFLAGS += \
+ $(call host-cc-option,-Wbad-function-cast) \
+ $(call host-cc-option,-Wcast-qual) \
+ $(call host-cc-option,-Wcast-align) \
+ $(call host-cc-option,-Wconversion) \
+ $(call host-cc-option,-Wdisabled-optimization) \
+ $(call host-cc-option,-Wlogical-op) \
+ $(call host-cc-option,-Wmissing-declarations) \
+ $(call host-cc-option,-Wmissing-include-dirs) \
+ $(call host-cc-option,-Wnested-externs) \
+ $(call host-cc-option,-Wold-style-definition) \
+ $(call host-cc-option,-Woverlength-strings) \
+ $(call host-cc-option,-Wpacked) \
+ $(call host-cc-option,-Wpacked-bitfield-compat) \
+ $(call host-cc-option,-Wpadded) \
+ $(call host-cc-option,-Wredundant-decls) \
+ $(call host-cc-option,-Wshadow) \
+ $(call host-cc-option,-Wswitch-default) \
+ $(call host-cc-option,-Wvla) \
+ $(call host-cc-option,-Wwrite-strings)
+endif
+
+HOST_WARNING_CFLAGS += \
+ $(call host-cc-optional-warning,-Wunused-but-set-variable)
+
+KBUILD_WARNING_CFLAGS := \
+ -Wno-unused-parameter -Wno-sign-compare
+KBUILD_WARNING_CFLAGS += \
+ $(call kernel-cc-optional-warning,-Wbad-function-cast) \
+ $(call kernel-cc-optional-warning,-Wcast-qual) \
+ $(call kernel-cc-optional-warning,-Wcast-align) \
+ $(call kernel-cc-optional-warning,-Wconversion) \
+ $(call kernel-cc-optional-warning,-Wdisabled-optimization) \
+ $(call kernel-cc-optional-warning,-Wlogical-op) \
+ $(call kernel-cc-optional-warning,-Wmissing-declarations) \
+ $(call kernel-cc-optional-warning,-Wmissing-include-dirs) \
+ $(call kernel-cc-optional-warning,-Wnested-externs) \
+ $(call kernel-cc-optional-warning,-Wno-missing-field-initializers) \
+ $(call kernel-cc-optional-warning,-Wold-style-definition) \
+ $(call kernel-cc-optional-warning,-Woverlength-strings) \
+ $(call kernel-cc-optional-warning,-Wpacked) \
+ $(call kernel-cc-optional-warning,-Wpacked-bitfield-compat) \
+ $(call kernel-cc-optional-warning,-Wpadded) \
+ $(call kernel-cc-optional-warning,-Wredundant-decls) \
+ $(call kernel-cc-optional-warning,-Wshadow) \
+ $(call kernel-cc-optional-warning,-Wswitch-default) \
+ $(call kernel-cc-optional-warning,-Wvla) \
+ $(call kernel-cc-optional-warning,-Wwrite-strings)
+
# User C only
#
ALL_CFLAGS := \
- $(COMMON_CFLAGS) -Wpointer-arith -Wunused-parameter $(SYS_CFLAGS)
+ $(COMMON_USER_FLAGS) $(COMMON_CFLAGS) $(WARNING_CFLAGS) \
+ $(SYS_CFLAGS)
+
ALL_HOST_CFLAGS := \
- $(COMMON_CFLAGS) -Wpointer-arith -Wunused-parameter
+ $(COMMON_USER_FLAGS) $(COMMON_CFLAGS) $(HOST_WARNING_CFLAGS)
# User C++ only
#
ALL_CXXFLAGS := \
- $(COMMON_FLAGS) -fno-rtti -fno-exceptions \
- -Wpointer-arith -Wunused-parameter $(SYS_CXXFLAGS)
+ $(COMMON_USER_FLAGS) $(COMMON_FLAGS) \
+ -fno-rtti -fno-exceptions \
+ -Wpointer-arith -Wunused-parameter \
+ $(SYS_CXXFLAGS)
+
+ALL_HOST_CXXFLAGS := \
+ $(COMMON_USER_FLAGS) $(COMMON_CFLAGS) -Wall
# User C and C++
#
# Kernel C only
#
-ALL_KBUILD_CFLAGS := $(COMMON_CFLAGS) -Wno-unused-parameter -Wno-sign-compare \
- $(call cc-option,-Wno-type-limits) \
- $(call cc-option,-Wno-unused-but-set-variable)
+ALL_KBUILD_CFLAGS := $(COMMON_CFLAGS) $(KBUILD_WARNING_CFLAGS) \
+ $(call kernel-cc-option,-Wno-type-limits) \
+ $(call kernel-cc-option,-Wno-pointer-arith) \
+ $(call kernel-cc-option,-Wno-aggregate-return) \
+ $(call kernel-cc-option,-Wno-unused-but-set-variable)
# This variable contains a list of all modules built by kbuild
ALL_KBUILD_MODULES :=
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
# from-one-* recipes make a thing from one source file, so they use $<. Others
# use $(MODULE_something) instead of $^
override CXX := $(if $(V),,@)$(CROSS_COMPILE)$(CXX)
override CHMOD := $(if $(V),,@)chmod
override CP := $(if $(V),,@)cp
-override DOS2UNIX := $(if $(V),,@)\
- $(shell if [ -z `which fromdos` ]; then echo dos2unix -f -q; else echo fromdos -f -p; fi)
override ECHO := $(if $(V),,@)echo
override FLEX := $(if $(V),,@)flex
override GAWK := $(if $(V),,@)gawk
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Title XOrg root makefile
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
ifeq ($(filter xorg,$(EXCLUDED_APIS)),)
- COMPONENTS += xorg pvr_conf pvr_video wsegl_dri2_linux
+ COMPONENTS += xorg pvr_conf pvr_video pvr_video_bin wsegl_dri2_linux
-include ../common/apis/xorg_opengl.mk
+ifeq ($(SUPPORT_PVR_REMOTE),1)
+ COMPONENTS += pvr_input
+endif
endif
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
$(eval $(call TunableBothConfigC,SUPPORT_DRI_DRM,))
$(eval $(call TunableBothConfigC,SUPPORT_DRI_DRM_EXT,))
+$(eval $(call TunableKernelConfigC,SUPPORT_DRI_DRM_PLUGIN,))
$(eval $(call TunableBothConfigMake,SUPPORT_DRI_DRM,))
ifeq ($(SUPPORT_DRI_DRM_NO_LIBDRM),1)
endif
$(eval $(call TunableKernelConfigC,PVR_SECURE_DRM_AUTH_EXPORT,))
+$(eval $(call TunableKernelConfigC,SUPPORT_DRM_MODESET,))
endif
$(eval $(call TunableKernelConfigC,PVR_DISPLAY_CONTROLLER_DRM_IOCTL,))
$(eval $(call TunableKernelConfigC,PVR_DRI_DRM_PLATFORM_DEV,))
+
export EXTERNAL_3PDD_TARBALL
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
-$(eval $(call TunableBothConfigC,PVR_NO_FULL_CACHE_OPS,))
$(eval $(call TunableKernelConfigC,PVR_NO_OMAP_TIMER,))
+$(eval $(call TunableKernelConfigC,PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY,))
+$(eval $(call TunableKernelConfigC,PVR_OMAPLFB_DRM_FB,))
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
PVR_SECURE_DRM_AUTH_EXPORT := 1
$(eval $(call TunableKernelConfigC,XPROC_WORKAROUND_NUM_SHAREABLES,4095))
+ifeq ($(SUPPORT_PVR_REMOTE),1)
+else
+endif
+
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
# FIXME: Will go away when SUPPORT_DRI_DRM is untangled from
# the old meaning of SUPPORT_XORG=1.
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Title Root build configuration.
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
# Configuration wrapper for new build system. This file deals with
# configuration of the build. Add to this file anything that deals
############################### END MACROS ##################################
-DOS2UNIX := $(shell \
- if [ -z `which fromdos` ]; then echo dos2unix -f -q; else echo fromdos -f -p; fi \
-)
-
# Check we have a new enough version of GNU make.
#
need := 3.81
endif
override EURASIAROOT := $(_GUESSED_EURASIAROOT)
TOP := $(EURASIAROOT)
+
+ifneq ($(words $(TOP)),1)
+$(warning This source tree is located in a path which contains whitespace,)
+$(warning which is not supported.)
+$(warning $(space)The root is: $(TOP))
+$(error Whitespace found in $$(TOP))
+endif
+
$(call directory-must-exist,$(TOP))
include ../defs.mk
#
BUILD ?= release
OUT ?= $(TOP)/eurasiacon/binary2_$(PVR_BUILD_DIR)_$(BUILD)
+override OUT := $(if $(filter /%,$(OUT)),$(OUT),$(TOP)/$(OUT))
CONFIG_MK := $(OUT)/config.mk
CONFIG_H := $(OUT)/config.h
override SUPPORT_ACTIVE_POWER_MANAGEMENT := 0
endif
+# We're bumping against USSE limits on older cores because the ukernel
+# is too large when building both SGX_DISABLE_VISTEST_SUPPORT=0 and
+# PVRSRV_USSE_EDM_STATUS_DEBUG=1.
+#
+# Automatically disable vistest support if debugging the ukernel to
+# prevent build failures.
+#
+ifneq ($(filter 520 530 531 535 540,$(SGXCORE)),)
+ifneq ($(SGX_DISABLE_VISTEST_SUPPORT),1)
+SGX_DISABLE_VISTEST_SUPPORT ?= not-overridden
+ifeq ($(SGX_DISABLE_VISTEST_SUPPORT),not-overridden)
+$(warning Setting SGX_DISABLE_VISTEST_SUPPORT=1 because PVRSRV_USSE_EDM_STATUS_DEBUG=1)
+SGX_DISABLE_VISTEST_SUPPORT := 1
+endif
+endif
+endif
+
ifeq ($(SGXCORE),535)
+ifeq ($(PVRSRV_USSE_EDM_STATUS_DEBUG),1)
+SUPPORT_SGX_HWPERF ?= not-overridden
+ifeq ($(SUPPORT_SGX_HWPERF),not-overridden)
+$(warning Setting SUPPORT_SGX_HWPERF=0 because PVRSRV_USSE_EDM_STATUS_DEBUG=1)
+SUPPORT_SGX_HWPERF := 0
+endif
+endif
PVR2D_ALT_2DHW ?= 0
endif
# Check for words in EXCLUDED_APIS that aren't understood by the
# common/apis/*.mk files. This should be kept in sync with all the tests on
# EXCLUDED_APIS in those files
-_excludable_apis := opencl opengl opengles1 opengles2 openvg ews unittests xorg xorg_unittests
+_excludable_apis := opencl opengl opengles1 opengles2 openvg ews unittests xorg xorg_unittests scripts
_unrecognised := $(strip $(filter-out $(_excludable_apis),$(EXCLUDED_APIS)))
ifneq ($(_unrecognised),)
$(warning *** Unrecognised entries in EXCLUDED_APIS: $(_unrecognised))
endif
endif
+ifeq ($(SUPPORT_PVR_REMOTE),1)
+ifneq ($(filter pvr2d,$(COMPONENTS)),)
+COMPONENTS += null_pvr2d_remote
+endif
+COMPONENTS += pvrvncsrv
+endif
+
# If KERNELDIR is set, write it out to the config.mk, with
# KERNEL_COMPONENTS and KERNEL_ID
#
ifneq ($(strip $(KERNELDIR)),)
include ../kernel_version.mk
+PVRSRV_MODULE_BASEDIR ?= /lib/modules/$(KERNEL_ID)/extra/
$(eval $(call KernelConfigMake,KERNELDIR,$(KERNELDIR)))
# Needed only by install script
$(eval $(call KernelConfigMake,KERNEL_COMPONENTS,$(KERNEL_COMPONENTS)))
-$(eval $(call TunableKernelConfigMake,KERNEL_CROSS_COMPILE,))
$(eval $(call TunableKernelConfigMake,EXTRA_PVRSRVKM_COMPONENTS,))
$(eval $(call TunableKernelConfigMake,EXTRA_KBUILD_SOURCE,))
+
+# If KERNEL_CROSS_COMPILE is set to "undef", this is magically
+# equivalent to being unset. If it is unset, we use CROSS_COMPILE
+# (which might also be unset). If it is set, use it directly.
+ifneq ($(KERNEL_CROSS_COMPILE),undef)
+KERNEL_CROSS_COMPILE ?= $(CROSS_COMPILE)
+$(eval $(call TunableBothConfigMake,KERNEL_CROSS_COMPILE,))
+endif
+
+# Check the KERNELDIR has a kernel built and also check that it is
+# not 64-bit, which we do not support.
+VMLINUX := $(strip $(wildcard $(KERNELDIR)/vmlinux))
+ifneq ($(VMLINUX),)
+VMLINUX_IS_64BIT := $(shell file $(VMLINUX) | grep -q 64-bit || echo false)
+ifneq ($(VMLINUX_IS_64BIT),false)
+$(warning $$(KERNELDIR)/vmlinux is 64-bit, which is not supported. Kbuild may fail.)
+endif
+else
+$(warning $$(KERNELDIR)/vmlinux does not exist. Kbuild may fail.)
endif
+endif
+
# Ideally configured by platform Makefiles, as necessary
#
$(eval $(call BothConfigC,LINUX,))
$(eval $(call BothConfigC,PVR_BUILD_DIR,"\"$(PVR_BUILD_DIR)\""))
-$(eval $(call BothConfigC,PVR_BUILD_DATE,"\"\""))
$(eval $(call BothConfigC,PVR_BUILD_TYPE,"\"$(BUILD)\""))
$(eval $(call BothConfigC,PVRSRV_MODNAME,"\"$(PVRSRV_MODNAME)\""))
$(eval $(call BothConfigC,TRANSFER_QUEUE,))
$(eval $(call BothConfigC,PVR_SECURE_HANDLES,))
-$(eval $(call KernelConfigC,DISPLAY_CONTROLLER,$(DISPLAY_CONTROLLER)))
+ifneq ($(DISPLAY_CONTROLLER),)
+$(eval $(call BothConfigC,DISPLAY_CONTROLLER,$(DISPLAY_CONTROLLER)))
+endif
+
+PVR_LINUX_MEM_AREA_POOL_MAX_PAGES ?= 0
+ifneq ($(PVR_LINUX_MEM_AREA_POOL_MAX_PAGES),0)
+PVR_LINUX_MEM_AREA_USE_VMAP ?= 1
+include ../kernel_version.mk
+ifeq ($(call kernel-version-at-least,3,0),true)
+PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK ?= 1
+endif
+endif
+$(eval $(call KernelConfigC,PVR_LINUX_MEM_AREA_POOL_MAX_PAGES,$(PVR_LINUX_MEM_AREA_POOL_MAX_PAGES)))
+$(eval $(call TunableKernelConfigC,PVR_LINUX_MEM_AREA_USE_VMAP,))
+$(eval $(call TunableKernelConfigC,PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK,))
$(eval $(call BothConfigMake,PVR_SYSTEM,$(PVR_SYSTEM)))
$(eval $(call TunableBothConfigC,SUPPORT_SGX_NEW_STATUS_VALS,1))
$(eval $(call TunableBothConfigC,SUPPORT_PDUMP_MULTI_PROCESS,))
$(eval $(call TunableBothConfigC,SUPPORT_DBGDRV_EVENT_OBJECTS,1))
-$(eval $(call TunableBothConfigC,PVR_DBG_BREAK_ASSERT_FAIL,))
$(eval $(call TunableBothConfigC,SGX_FEATURE_SYSTEM_CACHE,))
$(eval $(call TunableBothConfigC,SGX_BYPASS_SYSTEM_CACHE,))
$(eval $(call TunableBothConfigC,SGX_BYPASS_DCU,))
$(eval $(call TunableBothConfigC,NO_HARDWARE,))
$(eval $(call TunableBothConfigC,PDUMP_DEBUG_OUTFILES,))
$(eval $(call TunableBothConfigC,PVRSRV_USSE_EDM_STATUS_DEBUG,))
+$(eval $(call TunableBothConfigC,SGX_DISABLE_VISTEST_SUPPORT,))
$(eval $(call TunableBothConfigC,PVRSRV_RESET_ON_HWTIMEOUT,))
$(eval $(call TunableBothConfigC,SYS_USING_INTERRUPTS,1))
$(eval $(call TunableBothConfigC,SUPPORT_EXTERNAL_SYSTEM_CACHE,))
+$(eval $(call TunableBothConfigC,PVRSRV_NEW_PVR_DPF,))
$(eval $(call TunableBothConfigC,PVRSRV_NEED_PVR_DPF,))
$(eval $(call TunableBothConfigC,PVRSRV_NEED_PVR_ASSERT,))
$(eval $(call TunableBothConfigC,PVRSRV_NEED_PVR_TRACE,))
$(eval $(call TunableBothConfigC,SUPPORT_SECURE_33657_FIX,))
+$(eval $(call TunableBothConfigC,SUPPORT_ION,))
+$(eval $(call TunableBothConfigC,SUPPORT_HWRECOVERY_TRACE_LIMIT,))
+$(eval $(call TunableBothConfigC,SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER,1))
+$(eval $(call TunableBothConfigC,SUPPORT_NV12_FROM_2_HWADDRS,))
$(eval $(call TunableKernelConfigC,SUPPORT_LINUX_X86_WRITECOMBINE,1))
$(eval $(call TunableKernelConfigC,SUPPORT_LINUX_X86_PAT,1))
$(eval $(call TunableKernelConfigC,SGX_DYNAMIC_TIMING_INFO,))
$(eval $(call TunableKernelConfigC,SYS_SGX_ACTIVE_POWER_LATENCY_MS,))
$(eval $(call TunableKernelConfigC,SYS_CUSTOM_POWERLOCK_WRAP,))
+$(eval $(call TunableKernelConfigC,SYS_SUPPORTS_SGX_IDLE_CALLBACK,))
$(eval $(call TunableKernelConfigC,PVR_LINUX_USING_WORKQUEUES,))
$(eval $(call TunableKernelConfigC,PVR_LINUX_MISR_USING_WORKQUEUE,))
$(eval $(call TunableKernelConfigC,PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE,))
$(eval $(call TunableKernelConfigC,PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE,))
$(eval $(call TunableKernelConfigC,LDM_PLATFORM,))
$(eval $(call TunableKernelConfigC,PVR_LDM_PLATFORM_PRE_REGISTERED,))
+$(eval $(call TunableKernelConfigC,PVR_LDM_PLATFORM_PRE_REGISTERED_DEV,))
+$(eval $(call TunableKernelConfigC,PVR_LDM_DRIVER_REGISTRATION_NAME,"\"$(PVRSRV_MODNAME)\""))
$(eval $(call TunableKernelConfigC,LDM_PCI,))
$(eval $(call TunableKernelConfigC,PVRSRV_DUMP_MK_TRACE,))
$(eval $(call TunableKernelConfigC,PVRSRV_DUMP_KERNEL_CCB,))
+$(eval $(call TunableKernelConfigC,PVRSRV_REFCOUNT_DEBUG,))
+$(eval $(call TunableKernelConfigC,PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND,))
$(eval $(call TunableKernelConfigC,HYBRID_SHARED_PB_SIZE,))
+$(eval $(call TunableKernelConfigC,SUPPORT_LARGE_GENERAL_HEAP,))
+$(eval $(call TunableKernelConfigC,TTRACE,))
-$(eval $(call TunableBothConfigMake,LDM_PLATFORM,))
-$(eval $(call TunableBothConfigMake,LDM_PCI,))
+$(eval $(call TunableBothConfigMake,SUPPORT_ION,))
$(eval $(call TunableBothConfigMake,OPTIM,))
+$(eval $(call TunableKernelConfigMake,TTRACE,))
+
endif # INTERNAL_CLOBBER_ONLY
export INTERNAL_CLOBBER_ONLY
export TOP
export OUT
-MAKE_ETC := -Rr --no-print-directory -C $(TOP) TOP=$(TOP) \
+MAKE_ETC := -Rr --no-print-directory -C $(TOP) TOP=$(TOP) OUT=$(OUT) \
-f eurasiacon/build/linux2/toplevel.mk
# This must match the default value of MAKECMDGOALS below, and the default
autogen:
ifeq ($(INTERNAL_CLOBBER_ONLY),)
@$(MAKE) -s --no-print-directory -C $(EURASIAROOT) \
- DOS2UNIX="$(DOS2UNIX)" \
- -f eurasiacon/build/linux2/prepare_tree.mk
+ -f eurasiacon/build/linux2/prepare_tree.mk \
+ LDM_PCI=$(LDM_PCI) LDM_PLATFORM=$(LDM_PLATFORM)
else
@:
endif
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
define must-be-defined
$(if $(filter undefined,$(origin $(1))),$(error In makefile $(THIS_MAKEFILE): $$($(1)) must be defined),)
define cc-check
$(shell \
CC_CHECK=$(patsubst @%,%,$(CC_CHECK)) && \
- $(patsubst @%,%,$(DOS2UNIX)) $$CC_CHECK && \
$(patsubst @%,%,$(CHMOD)) +x $$CC_CHECK && \
$$CC_CHECK --cc "$(1)" --out "$(2)" $(3))
endef
define host-cc-option
$(call cc-check,$(patsubst @%,%,$(HOST_CC)),$(OUT),$(1))
endef
+
+define kernel-cc-option
+$(call cc-check,$(KERNEL_CROSS_COMPILE)gcc,$(OUT),$(1))
+endef
+
+# Turn a particular warning on, or explicitly turn it off, depending on
+# the value of W. The "-W" or "-Wno-" part of the warning need not be
+# specified.
+define cc-optional-warning
+$(call cc-option,-W$(if $(W),,no-)$(patsubst -W%,%,$(patsubst -Wno-%,%,$(1))))
+endef
+
+define host-cc-optional-warning
+$(call host-cc-option,-W$(if $(W),,no-)$(patsubst -W%,%,$(patsubst -Wno-%,%,$(1))))
+endef
+
+define kernel-cc-optional-warning
+$(call kernel-cc-option,-W$(if $(W),,no-)$(patsubst -W%,%,$(patsubst -Wno-%,%,$(1))))
+endef
+
+define module-info-line
+$(if $(filter modules,$(D)),$(info $(1)),)
+endef
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Title Root kernel makefile
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
# This top-level kbuild makefile builds all the Linux kernel modules in the
# DDK. To run kbuild, this makefile is copied to $(TARGET_OUT)/kbuild/Makefile
-I$(TOP)/services4/include \
-I$(TOP)/services4/system/$(PVR_SYSTEM) \
-I$(TOP)/services4/system/include \
- -I$(TOP)/services4/srvkm/hwdefs \
-I$(TOP)/services4/srvkm/bridged \
-I$(TOP)/services4/srvkm/bridged/sgx \
-I$(TOP)/services4/srvkm/common \
-I$(TOP)/services4/srvkm/env/linux \
-I$(TOP)/services4/srvkm/include
+ifeq ($(PVR_LOCAL_HWDEFS),)
+ccflags-y += -I$(TOP)/services4/srvkm/hwdefs
+else
+ccflags-y += -I$(TOP)/hwdefs
+endif
+
include $(INTERNAL_KBUILD_MAKEFILES)
$(if $(pvrsrvkm-y),,$(error pvrsrvkm-y was empty, which could mean that srvkm is missing from $$(KERNEL_COMPONENTS)))
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
ifneq ($(EXTERNAL_3PDD_TARBALL),)
TAR_OPT_STRIP_COMPONENTS ?= --strip-components
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
-
-include $(CONFIG_KERNEL_MK)
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
$(if $(strip $(KERNELDIR)),,$(error KERNELDIR must be set))
$(call directory-must-exist,$(KERNELDIR))
-KERNEL_CROSS_COMPILE ?= $(CROSS_COMPILE)
-
$(TARGET_OUT)/kbuild/Makefile: $(MAKE_TOP)/kbuild/Makefile.template
@[ ! -e $(dir $@) ] && mkdir -p $(dir $@) || true
$(CP) -f $< $@
EXTRA_CFLAGS="$(ALL_KBUILD_CFLAGS)" \
V=$(V) W=$(W) \
TOP=$(TOP)
-ifeq ($(DEBUGLINK),1)
- @for kernel_module in $(addprefix $(TARGET_OUT)/kbuild/,$(INTERNAL_KBUILD_OBJECTS:.o=.ko)); do \
- $(patsubst @%,%,$(STRIP)) --strip-unneeded $$kernel_module; \
- done
-endif
@for kernel_module in $(addprefix $(TARGET_OUT)/kbuild/,$(INTERNAL_KBUILD_OBJECTS:.o=.ko)); do \
cp $$kernel_module $(TARGET_OUT); \
done
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
# Rules for making kernel modules with kbuild. This makefile doesn't define
# any rules that build the modules, it only copies the kbuild Makefile into
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
$(if $(KERNELDIR),,$(error KERNELDIR must be set to obtain a version))
override KERNEL_EXTRAVERSION := \
$(shell grep "^EXTRAVERSION = " $(KERNELDIR)/Makefile | cut -f3 -d' ')
+# Break the kernel version up into a space separated list
+kernel_version_as_list := $(KERNEL_VERSION) \
+ $(KERNEL_PATCHLEVEL) \
+ $(KERNEL_SUBLEVEL) \
+ $(patsubst .%,%,$(KERNEL_EXTRAVERSION))
+
# The base ID doesn't have to be accurate; we only use it for
# feature checks which will not care about extraversion bits
#
override KERNEL_BASE_ID := \
$(KERNEL_VERSION).$(KERNEL_PATCHLEVEL).$(KERNEL_SUBLEVEL)
-# UTS_RELEASE is more accurate, if we can find it
-# If we can't, fall back to manufacturing the version
-#
+# Try to get the kernel ID from the kernel.release file.
+#
KERNEL_ID ?= \
- $(shell grep -h '\#define UTS_RELEASE' \
- $(KERNELDIR)/include/linux/* | cut -f3 -d' ' | sed s/\"//g)
+ $(shell cat $(KERNELDIR)/include/config/kernel.release 2>/dev/null)
+# If the kernel ID isn't set yet, try to set it from the UTS_RELEASE
+# macro.
+#
ifeq ($(strip $(KERNEL_ID)),)
-# kernel.release, it it exists, contains what UTS_RELEASE would have
-# been set to.
-#
KERNEL_ID := \
- $(shell cat $(KERNELDIR)/include/config/kernel.release 2>/dev/null)
+ $(shell grep -h '\#define UTS_RELEASE' \
+ $(KERNELDIR)/include/linux/* | cut -f3 -d' ' | sed s/\"//g)
endif
ifeq ($(strip $(KERNEL_ID)),)
KERNEL_ID := \
$(KERNEL_VERSION).$(KERNEL_PATCHLEVEL).$(KERNEL_SUBLEVEL)$(KERNEL_EXTRAVERSION)
endif
+
+# Return 1 if the kernel version is at least the value passed to the
+# function, else return nothing.
+# Examples
+# $(call kernel-version-at-least,2,6,35)
+# $(call kernel-version-at-least,2,6,35,7)
+#
+define kernel-version-at-least
+$(shell set -- $(kernel_version_as_list) 0 0 0 0; \
+ Y=true; \
+ for D in $1 $2 $3 $4; \
+ do \
+ [ $$1 ] || break; \
+ [ $$1 -eq $$D ] && { shift; continue; };\
+ [ $$1 -lt $$D ] && Y=; \
+ break; \
+ done; \
+ echo $$Y)
+endef
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
MODULE_TARGETS :=
MODULE_CFLAGS := $(ALL_CFLAGS) $($(THIS_MODULE)_cflags)
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Title Module processing
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
# Bits for processing $(modules) after reading in each Linux.mk
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Title Root makefile for OMAP4430 Linux. Builds everything else.
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
PVR_SYSTEM := omap4
include ../kernel_version.mk
-OMAP_KERNEL_AT_LEAST_2_6_35 := $(shell test $(KERNEL_VERSION) -ge 2 -a \
- $(KERNEL_PATCHLEVEL) -ge 6 -a \
- $(KERNEL_SUBLEVEL) -ge 35 && echo 1 || echo 0)
-
# 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
SYS_CFLAGS += -ftree-vectorize -mfpu=neon -mfloat-abi=softfp
endif
-PVR_NO_FULL_CACHE_OPS := 1
-
LIBGCC := $(shell $(CROSS_COMPILE)gcc -print-libgcc-file-name)
SGXCORE := 540
OPK_DEFAULT := libpvrPVR2D_FLIPWSEGL.so
endif
-ifeq ($(OMAP_KERNEL_AT_LEAST_2_6_35),1)
+ifeq ($(call kernel-version-at-least,2,6,35),true)
+# Work around flipping problems seen with the Taal LCDs on Blaze.
+# The work around is safe to use with other types of screen on Blaze
+# (e.g. HDMI) and on other platforms (e.g. Panda board).
+PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY := 1
ifeq ($(LDM_PLATFORM),1)
PVR_LDM_PLATFORM_PRE_REGISTERED := 1
+ifeq ($(call kernel-version-at-least,2,6,35,7),true)
+# Not all variants of the OMAP4 kernel have a DRM based framebuffer.
+# Note that a non-X.Org version of the driver does not have to be built
+# with DRM support if the kernel has a DRM based framebuffer.
+PVR_OMAPLFB_DRM_FB ?= 1
+ifeq ($(PVR_OMAPLFB_DRM_FB),1)
+PVR_LDM_PLATFORM_PRE_REGISTERED_DEV := "\"pvrsrvkm_pvr\""
+# There is already a "pvrsrvkm" driver (part of the DRM framebuffer code),
+# so use the pre-registered device name instead.
+PVR_LDM_DRIVER_REGISTRATION_NAME := "\"pvrsrvkm_pvr"\"
+# The DRM library will not load the Services module on behalf of the X Server,
+# as a DRM module has already been loaded (the DRM based framebuffer), so
+# load the Services module before starting the X Server.
+XORG_EXPLICIT_PVR_SERVICES_LOAD := 1
+else
+PVR_LDM_PLATFORM_PRE_REGISTERED_DEV := "\"pvrsrvkm\""
+endif
+endif
endif
endif
SUPPORT_DRI_DRM := 1
-ifeq ($(OMAP_KERNEL_AT_LEAST_2_6_35),1)
+ifeq ($(call kernel-version-at-least,2,6,35),true)
PVR_DRI_DRM_PLATFORM_DEV := 1
PVR_DRI_DRM_STATIC_BUS_ID := 1
+ifeq ($(call kernel-version-at-least,2,6,35,7),true)
+ifeq ($(PVR_OMAPLFB_DRM_FB),1)
+SUPPORT_DRI_DRM_PLUGIN := 1
+endif
+ifeq ($(call kernel-version-at-least,2,6,36),true)
+PVR_DRI_DRM_DEV_BUS_ID := "\"platform:pvrsrvkm"\"
+else
+PVR_DRI_DRM_DEV_BUS_ID := "\"platform:pvrsrvkm:00"\"
+endif
+# A client DRI authorisation failure, whilst switched away from the X Server
+# VT, prevents all other attempts at DRI authorisation, even after
+# switching back to the X server VT, so don't perform a DRM drop master
+# call.
+PVR_XORG_DONT_DROP_MASTER_IN_LEAVE_VT := 1
+endif
else
PVR_DRI_DRM_NOT_PCI := 1
endif
-XORG_TOOLCHAIN := tarballs-omap4-ubuntu-10.10-cross
+XORG_TOOLCHAIN ?= tarballs-omap4-ubuntu-10.10-cross
XORG_PVR_CONF := omap4
XORG_PVR_VIDEO := omap4
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
-
--include $(OUT)/config.mk.new
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
.PHONY: prepare_tree
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
# Find out the path of the Linux.mk makefile currently being processed, and
# set paths used by the build rules
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+#!/bin/sh
+########################################################################### ###
+#@Title Test the nature of the C compiler.
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
+#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
+
+LANG=C
+export LANG
usage() {
echo "usage: $0 [--64] --cc CC --out OUT [cflag]"
exit 1
}
+# NOTE: The program passed to the compiler is deliberately incorrect
+# (`return;' should be `return 0;') but we do this to emit a warning.
+#
+# Emitting a warning is necessary to get GCC to print out additional
+# warnings about any unsupported -Wno options, so we can handle these
+# as unsupported by the build.
+#
do_cc() {
- echo "int main(void){return 0;}" | $CC $1 -xc -c - -o $ccof 2>/dev/null
+ echo "int main(void){return;}" | $CC -W -Wall $3 -xc -c - -o $1 >$2 2>&1
}
while [ 1 ]; do
[ "x$CC" = "x" ] && usage
[ "x$OUT" = "x" ] && usage
ccof=$OUT/cc-sanity-check
+log=${ccof}.log
if [ "x$BIT_CHECK" = "x1" ]; then
- do_cc ""
- file $ccof | grep -q 64-bit
+ do_cc $ccof $log ""
+ file $ccof | grep 64-bit >/dev/null 2>&1
[ "$?" = "0" ] && echo true || echo false
else
[ "x$1" = "x" ] && usage
- do_cc $1
- [ "$?" = "0" ] && echo $1
+ do_cc $ccof $log $1
+ if [ "$?" = "0" ]; then
+ # compile passed, but was the warning unrecognized?
+ grep -q "^cc1: warning: unrecognized command line option \"$1\"" $log
+ [ "$?" = "1" ] && echo $1
+ fi
fi
-rm -f $ccof
+rm -f $ccof $log
exit 0
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
-
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
# Define the default goal. This masks a previous definition of the default
# goal in Makefile.config, which must match this one
.PHONY: build
-build: components kbuild scripts
+build: components kbuild
ifeq ($(OUT),)
$(error "Must specify output directory with OUT=")
MAKE_TOP := eurasiacon/build/linux2
THIS_MAKEFILE := (top-level makefiles)
+# Convert commas to spaces in $(D). This is so you can say "make
+# D=config-changes,freeze-config" and have $(filter config-changes,$(D))
+# still work.
+comma := ,
+empty :=
+space := $(empty) $(empty)
+override D := $(subst $(comma),$(space),$(D))
+
include $(MAKE_TOP)/defs.mk
ifneq ($(INTERNAL_CLOBBER_ONLY),true)
# If these generated files differ from any pre-existing ones,
# replace them, causing affected parts of the driver to rebuild.
#
-$(shell \
+_want_config_diff := $(filter config-changes,$(D))
+_freeze_config := $(strip $(filter freeze-config,$(D)))
+_updated_config_files := $(shell \
+ $(if $(_want_config_diff),rm -f $(OUT)/config.diff;,) \
for file in $(CONFIG_MK) $(CONFIG_H) \
$(CONFIG_KERNEL_MK) $(CONFIG_KERNEL_H); do \
- diff -q $$file $$file.new >/dev/null 2>/dev/null \
+ diff -U 0 $$file $$file.new \
+ >>$(if $(_want_config_diff),$(OUT)/config.diff,/dev/null) 2>/dev/null \
&& rm -f $$file.new \
- || mv -f $$file.new $$file >/dev/null 2>/dev/null; \
+ || echo $$file; \
done)
+
+ifneq ($(_want_config_diff),)
+# We send the diff to stderr so it isn't captured by $(shell)
+$(shell [ -s $(OUT)/config.diff ] && echo >&2 "Configuration changed in $(RELATIVE_OUT):" && cat >&2 $(OUT)/config.diff)
+endif
+
+ifneq ($(_freeze_config),)
+$(if $(_updated_config_files),$(error Configuration change in $(RELATIVE_OUT) prevented by D=freeze-config),)
endif
+# Update the config, if changed
+$(foreach _f,$(_updated_config_files), \
+ $(shell mv -f $(_f).new $(_f) >/dev/null 2>/dev/null))
+
+endif # INTERNAL_CLOBBER_ONLY
+
MAKEFLAGS := -Rr --no-print-directory
ifneq ($(INTERNAL_CLOBBER_ONLY),true)
# This is so you can say "find $(TOP) -name Linux.mk > /tmp/something; export
# ALL_MAKEFILES=/tmp/something; make" and avoid having to run find. This is
# handy if your source tree is mounted over NFS or something
-override ALL_MAKEFILES := $(call relative-to-top,$(if $(strip $(ALL_MAKEFILES)),$(shell cat $(ALL_MAKEFILES)),$(shell find $(TOP) -type f -name Linux.mk)))
+override ALL_MAKEFILES := $(call relative-to-top,$(if $(strip $(ALL_MAKEFILES)),$(shell cat $(ALL_MAKEFILES)),$(shell find $(TOP) -type f -name Linux.mk -print -o -type d -name '.*' -prune)))
ifeq ($(strip $(ALL_MAKEFILES)),)
$(info ** Unable to find any Linux.mk files under $$(TOP). This could mean that)
$(info ** there are no makefiles, or that ALL_MAKEFILES is set in the environment)
ALL_MAKEFILES :=
endif
+unexport ALL_MAKEFILES
+
REMAINING_MAKEFILES := $(ALL_MAKEFILES)
ALL_MODULES :=
INTERNAL_INCLUDED_ALL_MAKEFILES :=
ifneq ($(INTERNAL_CLOBBER_ONLY),true)
--include $(CONFIG_MK)
+# Please do not change the format of the following lines
+-include $(CONFIG_KERNEL_MK)
# These files may not exist in GPL km source packages
-include $(MAKE_TOP)/xorgconf.mk
-include $(MAKE_TOP)/llvm.mk
# each module: for each module in $(ALL_MODULES), set per-makefile variables
$(foreach _m,$(ALL_MODULES),$(eval $(call process-module,$(_m))))
-.PHONY: kbuild scripts install
-kbuild scripts install:
+.PHONY: kbuild install
+kbuild install:
ifneq ($(INTERNAL_CLOBBER_ONLY),true)
-include $(MAKE_TOP)/scripts.mk
# You can say 'make all_modules' to attempt to make everything, or 'make
# components' to only make the things which are listed (in the per-build
-# makefiles) as components of the build. 'make scripts' generates the
-# install.sh and rc.pvr scripts.
-.PHONY: all_modules components scripts
+# makefiles) as components of the build.
+.PHONY: all_modules components
all_modules: $(ALL_MODULES)
components: $(COMPONENTS)
-# 'make opk' builds the OEM Porting Kit. The build should set OPK_COMPONENTS
-# in components.mk if it should be possible to build the OPK for it
-.PHONY: opk
-ifneq ($(strip $(OPK_COMPONENTS)),)
-opk: $(OPK_COMPONENTS)
-
-opk_clobber: MODULE_DIRS_TO_REMOVE := $(addprefix $(OUT)/target/intermediates/,$(OPK_COMPONENTS))
-opk_clobber: OPK_OUTFILES := $(addprefix $(RELATIVE_OUT)/target/,$(foreach _c,$(OPK_COMPONENTS),$(if $($(_c)_target),$($(_c)_target),$(error Module $(_c) must be a shared library which sets $$($(_c)_target) for OPK clobbering))))
-opk_clobber:
- $(clean-dirs)
- $(if $(V),,@echo " RM " $(call relative-to-top,$(OPK_OUTFILES)))
- $(RM) -f $(OPK_OUTFILES)
-else
-# OPK_COMPONENTS is empty or unset
-opk:
- @echo
- @echo "** This build ($(PVR_BUILD_DIR)) is unable to build the OPK, because"
- @echo "** OPK_COMPONENTS is empty or unset. Cannot continue."
- @echo
- @false
-endif
-
# Cleaning
.PHONY: clean clobber
clean: MODULE_DIRS_TO_REMOVE := $(OUT)/host/intermediates $(OUT)/target/intermediates $(OUT)/target/kbuild
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Debug driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Debug Driver Interface
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _DBGDRVIF_
#define _DBGDRVIF_
#endif
+/*****************************************************************************
+ Stream mode stuff.
+*****************************************************************************/
#define DEBUG_CAPMODE_FRAMED 0x00000001UL
#define DEBUG_CAPMODE_CONTINUOUS 0x00000002UL
#define DEBUG_CAPMODE_HOTKEY 0x00000004UL
#define DEBUG_FLAGS_TEXTSTREAM 0x80000000UL
+/*****************************************************************************
+ Debug level control. Only bothered with the first 12 levels, I suspect you
+ get the idea...
+*****************************************************************************/
#define DEBUG_LEVEL_0 0x00000001UL
#define DEBUG_LEVEL_1 0x00000003UL
#define DEBUG_LEVEL_2 0x00000007UL
#define DEBUG_LEVEL_SEL10 0x00000400UL
#define DEBUG_LEVEL_SEL11 0x00000800UL
+/*****************************************************************************
+ IOCTL values.
+*****************************************************************************/
#define DEBUG_SERVICE_IOCTL_BASE 0x800UL
#define DEBUG_SERVICE_CREATESTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define DEBUG_SERVICE_DESTROYSTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
} DBG_EVENT;
+/*****************************************************************************
+ In/Out Structures
+*****************************************************************************/
typedef struct _DBG_IN_CREATESTREAM_
{
union
IMG_UINT32 ui32BufferSize;
} DBG_IN_WRITE_LF, *PDBG_IN_WRITE_LF;
+/*
+ Flags for above struct
+*/
#define WRITELF_FLAGS_RESETBUF 0x00000001UL
+/*
+ Common control structure (don't duplicate control in main stream
+ and init phase stream).
+*/
typedef struct _DBG_STREAM_CONTROL_
{
- IMG_BOOL bInitPhaseComplete;
- IMG_UINT32 ui32Flags;
+ IMG_BOOL bInitPhaseComplete; /*!< init phase has finished */
+ IMG_UINT32 ui32Flags; /*!< flags (see DEBUG_FLAGS above) */
- IMG_UINT32 ui32CapMode;
- IMG_UINT32 ui32OutMode;
+ IMG_UINT32 ui32CapMode; /*!< capturing mode framed/hot key */
+ IMG_UINT32 ui32OutMode; /*!< output mode, e.g. files */
IMG_UINT32 ui32DebugLevel;
IMG_UINT32 ui32DefaultMode;
- IMG_UINT32 ui32Start;
- IMG_UINT32 ui32End;
- IMG_UINT32 ui32Current;
- IMG_UINT32 ui32SampleRate;
+ IMG_UINT32 ui32Start; /*!< first capture frame */
+ IMG_UINT32 ui32End; /*!< last frame */
+ IMG_UINT32 ui32Current; /*!< current frame */
+ IMG_UINT32 ui32SampleRate; /*!< capture frequency */
IMG_UINT32 ui32Reserved;
} DBG_STREAM_CONTROL, *PDBG_STREAM_CONTROL;
+/*
+ Per-buffer control structure.
+*/
typedef struct _DBG_STREAM_
{
struct _DBG_STREAM_ *psNext;
IMG_UINT32 ui32RPtr;
IMG_UINT32 ui32WPtr;
IMG_UINT32 ui32DataWritten;
- IMG_UINT32 ui32Marker;
- IMG_UINT32 ui32InitPhaseWOff;
-
-
-
-
- IMG_CHAR szName[30];
+ IMG_UINT32 ui32Marker; /*!< marker for file splitting */
+ IMG_UINT32 ui32InitPhaseWOff; /*!< snapshot offset for init phase end for follow-on pdump */
+ IMG_CHAR szName[30]; /* Give this a size, some compilers don't like [] */
} DBG_STREAM,*PDBG_STREAM;
+/*
+ * Allows dbgdrv to notify services when events happen, e.g. pdump.exe starts.
+ * (better than resetting psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0
+ * in SGXGetClientInfoKM.)
+ */
typedef struct _DBGKM_CONNECT_NOTIFIER_
{
IMG_VOID (IMG_CALLCONV *pfnConnectNotifier) (IMG_VOID);
} DBGKM_CONNECT_NOTIFIER, *PDBGKM_CONNECT_NOTIFIER;
+/*****************************************************************************
+ Kernel mode service table
+*****************************************************************************/
typedef struct _DBGKM_SERVICE_TABLE_
{
IMG_UINT32 ui32Size;
IMG_UINT32 (IMG_CALLCONV *pfnWritePersist) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
} DBGKM_SERVICE_TABLE, *PDBGKM_SERVICE_TABLE;
+#if defined(__linux__)
+/*****************************************************************************
+ Function to export service table from debug driver to the PDUMP component.
+*****************************************************************************/
+IMG_VOID DBGDrvGetServiceTable(DBGKM_SERVICE_TABLE **fn_table);
+#endif
+
#endif
+/*****************************************************************************
+ End of file (DBGDRVIF.H)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Common header containing type definitions for portability
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Contains variable and structure definitions. Any platform
+ specific types should be defined in this file.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined (__IMG_DEFS_H__)
#define __IMG_DEFS_H__
#endif
+/* Use this in any file, or use attributes under GCC - see below */
#ifndef PVR_UNREFERENCED_PARAMETER
#define PVR_UNREFERENCED_PARAMETER(param) (param) = (param)
#endif
+/* The best way to supress unused parameter warnings using GCC is to use a
+ * variable attribute. Place the unref__ between the type and name of an
+ * unused parameter in a function parameter list, eg `int unref__ var'. This
+ * should only be used in GCC build environments, for example, in files that
+ * compile only on Linux. Other files should use UNREFERENCED_PARAMETER */
#ifdef __GNUC__
#define unref__ __attribute__ ((unused))
#else
#define unref__
#endif
+/*
+ Wide character definitions
+*/
#ifndef _TCHAR_DEFINED
#if defined(UNICODE)
typedef unsigned short TCHAR, *PTCHAR, *PTSTR;
-#else
+#else /* #if defined(UNICODE) */
typedef char TCHAR, *PTCHAR, *PTSTR;
-#endif
+#endif /* #if defined(UNICODE) */
#define _TCHAR_DEFINED
-#endif
+#endif /* #ifndef _TCHAR_DEFINED */
#if defined(__linux__) || defined(__QNXNTO__) || defined(__METAG)
#error("define an OS")
#endif
+// Use default definition if not overridden
#ifndef IMG_ABORT
#define IMG_ABORT() abort()
#endif
#define IMG_FORMAT_PRINTF(x,y)
#endif
+/*
+ * Cleanup request defines
+ */
#define CLEANUP_WITH_POLL IMG_FALSE
#define FORCE_CLEANUP IMG_TRUE
#define IMG_UNDEF (~0UL)
#endif
-#endif
+#endif /* #if !defined (__IMG_DEFS_H__) */
+/*****************************************************************************
+ End of file (IMG_DEFS.H)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Global types for use by IMG APIs
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines type aliases for use by IMG APIs.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __IMG_TYPES_H__
#define __IMG_TYPES_H__
+/* define all address space bit depths: */
+/* CPU virtual address space defaults to 32bits */
#if !defined(IMG_ADDRSPACE_CPUVADDR_BITS)
#define IMG_ADDRSPACE_CPUVADDR_BITS 32
#endif
+/* Physical address space defaults to 32bits */
#if !defined(IMG_ADDRSPACE_PHYSADDR_BITS)
#define IMG_ADDRSPACE_PHYSADDR_BITS 32
#endif
#define IMG_UINT32_MAX 0xFFFFFFFFUL
#endif
-#if defined(USE_CODE)
+#if defined(USE_CODE)
typedef unsigned __int64 IMG_UINT64, *IMG_PUINT64;
typedef __int64 IMG_INT64, *IMG_PINT64;
#else
- #if ((defined(LINUX) || defined(__METAG)) || defined(__QNXNTO__))
+ #if defined(LINUX) || defined(__METAG) || defined (__QNXNTO__)
typedef unsigned long long IMG_UINT64, *IMG_PUINT64;
typedef long long IMG_INT64, *IMG_PINT64;
#else
#endif
#if !(defined(LINUX) && defined (__KERNEL__))
+/* Linux kernel mode does not use floating point */
typedef float IMG_FLOAT, *IMG_PFLOAT;
typedef double IMG_DOUBLE, *IMG_PDOUBLE;
#endif
#define IMG_NULL 0
+/* services/stream ID */
typedef IMG_UINT32 IMG_SID;
typedef IMG_UINT32 IMG_EVENTSID;
-#if defined(SUPPORT_SID_INTERFACE)
- typedef IMG_SID IMG_S_HANDLE;
-#else
- typedef IMG_HANDLE IMG_S_HANDLE;
-#endif
+/*
+ * Address types.
+ * All types used to refer to a block of memory are wrapped in structures
+ * to enforce some degree of type safety, i.e. a IMG_DEV_VIRTADDR cannot
+ * be assigned to a variable of type IMG_DEV_PHYADDR because they are not the
+ * same thing.
+ *
+ * There is an assumption that the system contains at most one non-cpu mmu,
+ * and a memory block is only mapped by the MMU once.
+ *
+ * Different devices could have offset views of the physical address space.
+ *
+ */
+
+
+/*
+ *
+ * +------------+ +------------+ +------------+ +------------+
+ * | CPU | | DEV | | DEV | | DEV |
+ * +------------+ +------------+ +------------+ +------------+
+ * | | | |
+ * | PVOID |IMG_DEV_VIRTADDR |IMG_DEV_VIRTADDR |
+ * | \-------------------/ |
+ * | | |
+ * +------------+ +------------+ |
+ * | MMU | | MMU | |
+ * +------------+ +------------+ |
+ * | | |
+ * | | |
+ * | | |
+ * +--------+ +---------+ +--------+
+ * | Offset | | (Offset)| | Offset |
+ * +--------+ +---------+ +--------+
+ * | | IMG_DEV_PHYADDR |
+ * | | |
+ * | | IMG_DEV_PHYADDR |
+ * +---------------------------------------------------------------------+
+ * | System Address bus |
+ * +---------------------------------------------------------------------+
+ *
+ */
typedef IMG_PVOID IMG_CPU_VIRTADDR;
+/* device virtual address */
typedef struct _IMG_DEV_VIRTADDR
{
-
+ /* device virtual addresses are 32bit for now */
IMG_UINT32 uiAddr;
#define IMG_CAST_TO_DEVVADDR_UINT(var) (IMG_UINT32)(var)
typedef IMG_UINT32 IMG_DEVMEM_SIZE_T;
+/* cpu physical address */
typedef struct _IMG_CPU_PHYADDR
{
-
+ /* variable sized type (32,64) */
IMG_UINTPTR_T uiAddr;
} IMG_CPU_PHYADDR;
+/* device physical address */
typedef struct _IMG_DEV_PHYADDR
{
#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
-
+ /* variable sized type (32,64) */
IMG_UINTPTR_T uiAddr;
#else
IMG_UINT32 uiAddr;
#endif
} IMG_DEV_PHYADDR;
+/* system physical address */
typedef struct _IMG_SYS_PHYADDR
{
-
+ /* variable sized type (32,64) */
IMG_UINTPTR_T uiAddr;
} IMG_SYS_PHYADDR;
#include "img_defs.h"
-#endif
+#endif /* __IMG_TYPES_H__ */
+/******************************************************************************
+ End of file (img_types.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PDUMP definitions header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description PDUMP definitions header
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined (__PDUMPDEFS_H__)
#define __PDUMPDEFS_H__
} PDUMP_POLL_OPERATOR;
-#endif
+#endif /* __PDUMPDEFS_H__ */
+/*****************************************************************************
+ End of file (pdumpdefs.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
-******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title PVR Debug Declarations
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides debug functionality
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __PVR_DEBUG_H__
#define __PVR_DEBUG_H__
#define PVR_MAX_DEBUG_MESSAGE_LEN (512)
/* These are privately used by pvr_debug, use the PVR_DBG_ defines instead */
-#define DBGPRIV_FATAL 0x01UL
-#define DBGPRIV_ERROR 0x02UL
-#define DBGPRIV_WARNING 0x04UL
-#define DBGPRIV_MESSAGE 0x08UL
-#define DBGPRIV_VERBOSE 0x10UL
-#define DBGPRIV_CALLTRACE 0x20UL
-#define DBGPRIV_ALLOC 0x40UL
-
-#define DBGPRIV_DBGDRV_MESSAGE 0x1000UL
-
-#define DBGPRIV_ALLLEVELS (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING | DBGPRIV_MESSAGE | DBGPRIV_VERBOSE)
-
+#define DBGPRIV_FATAL 0x01UL
+#define DBGPRIV_ERROR 0x02UL
+#define DBGPRIV_WARNING 0x04UL
+#define DBGPRIV_MESSAGE 0x08UL
+#define DBGPRIV_VERBOSE 0x10UL
+#define DBGPRIV_CALLTRACE 0x20UL
+#define DBGPRIV_ALLOC 0x40UL
+#define DBGPRIV_DBGDRV_MESSAGE 0x80UL
-
-#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__
-
-/*
- * Debug driver debugging
- */
-#define PVR_DBGDRIV_MESSAGE DBGPRIV_DBGDRV_MESSAGE, "", 0
+#define DBGPRIV_DBGLEVEL_COUNT 8
#if !defined(PVRSRV_NEED_PVR_ASSERT) && defined(DEBUG)
#define PVRSRV_NEED_PVR_ASSERT
#define PVRSRV_NEED_PVR_TRACE
#endif
-
/* PVR_ASSERT() and PVR_DBG_BREAK handling */
#if defined(PVRSRV_NEED_PVR_ASSERT)
- #define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__);
+#if defined(LINUX) && defined(__KERNEL__)
+/* In Linux kernel mode, use BUG() directly. This produces the correct
+ filename and line number in the panic message. */
+#define PVR_ASSERT(EXPR) do \
+ { \
+ if (!(EXPR)) \
+ { \
+ PVRSRVDebugPrintf(DBGPRIV_FATAL, __FILE__, __LINE__, \
+ "Debug assertion failed!"); \
+ BUG(); \
+ } \
+ } while (0)
+
+#else /* defined(LINUX) && defined(__KERNEL__) */
IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
IMG_UINT32 ui32Line);
- #if defined(PVR_DBG_BREAK_ASSERT_FAIL)
- #define PVR_DBG_BREAK PVRSRVDebugAssertFail("PVR_DBG_BREAK", 0)
+#if defined(LINUX)
+ #define PVR_ASSERT(EXPR) do \
+ { \
+ if (!(EXPR)) \
+ PVRSRVDebugAssertFail(__FILE__, __LINE__); \
+ } while (0)
+#else
+ #if defined (__QNXNTO__)
+ #define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__);
+ #else
+ #define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__)
+ #endif
+#endif
+
+#endif /* defined(LINUX) && defined(__KERNEL__) */
+
+
+ #if defined(LINUX) && defined(__KERNEL__)
+ #define PVR_DBG_BREAK BUG()
#else
- #define PVR_DBG_BREAK
+ #define PVR_DBG_BREAK PVRSRVDebugAssertFail(__FILE__, __LINE__)
#endif
#else /* defined(PVRSRV_NEED_PVR_ASSERT) */
#if defined(PVRSRV_NEED_PVR_DPF)
- #define PVR_DPF(X) PVRSRVDebugPrintf X
+#if defined(PVRSRV_NEW_PVR_DPF)
+
+ /* New logging mechanism */
+ #define PVR_DBG_FATAL DBGPRIV_FATAL
+ #define PVR_DBG_ERROR DBGPRIV_ERROR
+ #define PVR_DBG_WARNING DBGPRIV_WARNING
+ #define PVR_DBG_MESSAGE DBGPRIV_MESSAGE
+ #define PVR_DBG_VERBOSE DBGPRIV_VERBOSE
+ #define PVR_DBG_CALLTRACE DBGPRIV_CALLTRACE
+ #define PVR_DBG_ALLOC DBGPRIV_ALLOC
+ #define PVR_DBGDRIV_MESSAGE DBGPRIV_DBGDRV_MESSAGE
+
+ /* These levels are always on with PVRSRV_NEED_PVR_DPF */
+ #define __PVR_DPF_0x01UL(x...) PVRSRVDebugPrintf(DBGPRIV_FATAL, x)
+ #define __PVR_DPF_0x02UL(x...) PVRSRVDebugPrintf(DBGPRIV_ERROR, x)
+
+ /* Some are compiled out completely in release builds */
+#if defined(DEBUG)
+ #define __PVR_DPF_0x04UL(x...) PVRSRVDebugPrintf(DBGPRIV_WARNING, x)
+ #define __PVR_DPF_0x08UL(x...) PVRSRVDebugPrintf(DBGPRIV_MESSAGE, x)
+ #define __PVR_DPF_0x10UL(x...) PVRSRVDebugPrintf(DBGPRIV_VERBOSE, x)
+ #define __PVR_DPF_0x20UL(x...) PVRSRVDebugPrintf(DBGPRIV_CALLTRACE, x)
+ #define __PVR_DPF_0x40UL(x...) PVRSRVDebugPrintf(DBGPRIV_ALLOC, x)
+ #define __PVR_DPF_0x80UL(x...) PVRSRVDebugPrintf(DBGPRIV_DBGDRV_MESSAGE, x)
+#else
+ #define __PVR_DPF_0x04UL(x...)
+ #define __PVR_DPF_0x08UL(x...)
+ #define __PVR_DPF_0x10UL(x...)
+ #define __PVR_DPF_0x20UL(x...)
+ #define __PVR_DPF_0x40UL(x...)
+ #define __PVR_DPF_0x80UL(x...)
+#endif
+
+ /* Translate the different log levels to separate macros
+ * so they can each be compiled out.
+ */
+#if defined(DEBUG)
+ #define __PVR_DPF(lvl, x...) __PVR_DPF_ ## lvl (__FILE__, __LINE__, x)
+#else
+ #define __PVR_DPF(lvl, x...) __PVR_DPF_ ## lvl ("", 0, x)
+#endif
+
+ /* Get rid of the double bracketing */
+ #define PVR_DPF(x) __PVR_DPF x
+
+#else /* defined(PVRSRV_NEW_PVR_DPF) */
+
+ /* Old logging mechanism */
+ #define PVR_DBG_FATAL DBGPRIV_FATAL,__FILE__, __LINE__
+ #define PVR_DBG_ERROR DBGPRIV_ERROR,__FILE__, __LINE__
+ #define PVR_DBG_WARNING DBGPRIV_WARNING,__FILE__, __LINE__
+ #define PVR_DBG_MESSAGE DBGPRIV_MESSAGE,__FILE__, __LINE__
+ #define PVR_DBG_VERBOSE DBGPRIV_VERBOSE,__FILE__, __LINE__
+ #define PVR_DBG_CALLTRACE DBGPRIV_CALLTRACE,__FILE__, __LINE__
+ #define PVR_DBG_ALLOC DBGPRIV_ALLOC,__FILE__, __LINE__
+ #define PVR_DBGDRIV_MESSAGE DBGPRIV_DBGDRV_MESSAGE, "", 0
+
+ #define PVR_DPF(X) PVRSRVDebugPrintf X
+
+#endif /* defined(PVRSRV_NEW_PVR_DPF) */
IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
const IMG_CHAR *pszFileName,
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Module Author and License.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _PVRMODULE_H_
#define _PVRMODULE_H_
+
MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
-MODULE_LICENSE("GPL");
-#endif
+MODULE_LICENSE("Dual MIT/GPL");
+
+#endif /* _PVRMODULE_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
-
-
-
-
-
-
-
-
-
+/*************************************************************************/ /*!
+@File
+@Title Version numbers and strings.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Version numbers and strings for PVR Consumer services
+ components.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _PVRVERSION_H_
#define _PVRVERSION_H_
#define PVR_STR2(X) PVR_STR(X)
#define PVRVERSION_MAJ 1
-#define PVRVERSION_MIN 7
-#define PVRVERSION_BRANCH 17
+#define PVRVERSION_MIN 9
+#define PVRVERSION_BRANCH 19
#define PVRVERSION_FAMILY "sgxddk"
-#define PVRVERSION_BRANCHNAME "1.7"
-#define PVRVERSION_BUILD 867897
-#define PVRVERSION_BSCONTROL "CustomerTI_OMAP4430_Linux_GPL"
+#define PVRVERSION_BRANCHNAME "1.9.RC2"
+#define PVRVERSION_BUILD 2139099
+#define PVRVERSION_BSCONTROL "SGX_DDK_Linux_CustomerTI"
-#define PVRVERSION_STRING "CustomerTI_OMAP4430_Linux_GPL sgxddk 17 1.7@" PVR_STR2(PVRVERSION_BUILD)
-#define PVRVERSION_STRING_SHORT "1.7@" PVR_STR2(PVRVERSION_BUILD)
+#define PVRVERSION_STRING "SGX_DDK_Linux_CustomerTI sgxddk 19 1.9.RC2@" PVR_STR2(PVRVERSION_BUILD)
+#define PVRVERSION_STRING_SHORT "1.9.RC2@" PVR_STR2(PVRVERSION_BUILD)
#define COPYRIGHT_TXT "Copyright (c) Imagination Technologies Ltd. All Rights Reserved."
-#define PVRVERSION_BUILD_HI 86
-#define PVRVERSION_BUILD_LO 7897
+#define PVRVERSION_BUILD_HI 213
+#define PVRVERSION_BUILD_LO 9099
#define PVRVERSION_STRING_NUMERIC PVR_STR2(PVRVERSION_MAJ) "." PVR_STR2(PVRVERSION_MIN) "." PVR_STR2(PVRVERSION_BUILD_HI) "." PVR_STR2(PVRVERSION_BUILD_LO)
-#endif
+#endif /* _PVRVERSION_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Services API Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Exported services API details
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __SERVICES_H__
#define __SERVICES_H__
#include "pdumpdefs.h"
+/* The comment below is the front page for code-generated doxygen documentation */
+/*!
+ ******************************************************************************
+ @mainpage
+ This document details the APIs and implementation of the Consumer Services.
+ It is intended to be used in conjunction with the Consumer Services
+ Software Architectural Specification and the Consumer Services Software
+ Functional Specification.
+ *****************************************************************************/
+
+/******************************************************************************
+ * #defines
+ *****************************************************************************/
+
+/* 4k page size definition */
#define PVRSRV_4K_PAGE_SIZE 4096UL
-#define PVRSRV_MAX_CMD_SIZE 1024
+#define PVRSRV_MAX_CMD_SIZE 1024/*!< max size in bytes of a command */
-#define PVRSRV_MAX_DEVICES 16
+#define PVRSRV_MAX_DEVICES 16 /*!< Largest supported number of devices on the system */
#define EVENTOBJNAME_MAXLENGTH (50)
+/*
+ Flags associated with memory allocation
+ (bits 0-11)
+*/
#define PVRSRV_MEM_READ (1U<<0)
#define PVRSRV_MEM_WRITE (1U<<1)
#define PVRSRV_MEM_CACHE_CONSISTENT (1U<<2)
#define PVRSRV_MEM_EXPORTED (1U<<11)
+/*
+ Heap Attribute flags
+ (bits 12-23)
+*/
#define PVRSRV_HAP_CACHED (1U<<12)
#define PVRSRV_HAP_UNCACHED (1U<<13)
#define PVRSRV_HAP_WRITECOMBINE (1U<<14)
|PVRSRV_HAP_FROM_EXISTING_PROCESS \
|PVRSRV_HAP_NO_CPU_VIRTUAL)
+/*
+ Allows user allocations to override heap attributes
+ (Bits shared with heap flags)
+*/
#define PVRSRV_MEM_CACHED PVRSRV_HAP_CACHED
#define PVRSRV_MEM_UNCACHED PVRSRV_HAP_UNCACHED
#define PVRSRV_MEM_WRITECOMBINE PVRSRV_HAP_WRITECOMBINE
+/*
+ Backing store flags (defined internally)
+ (bits 24-26)
+*/
#define PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT (24)
+/*
+ Per allocation/mapping flags
+ (bits 27-30)
+ */
#define PVRSRV_MAP_NOUSERVIRTUAL (1UL<<27)
#define PVRSRV_MEM_XPROC (1U<<28)
-
-#define PVRSRV_NO_CONTEXT_LOSS 0
-#define PVRSRV_SEVERE_LOSS_OF_CONTEXT 1
-#define PVRSRV_PRE_STATE_CHANGE_MASK 0x80
-
-
-#define PVRSRV_DEFAULT_DEV_COOKIE (1)
-
-
-#define PVRSRV_MISC_INFO_TIMER_PRESENT (1U<<0)
-#define PVRSRV_MISC_INFO_CLOCKGATE_PRESENT (1U<<1)
-#define PVRSRV_MISC_INFO_MEMSTATS_PRESENT (1U<<2)
-#define PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT (1U<<3)
-#define PVRSRV_MISC_INFO_DDKVERSION_PRESENT (1U<<4)
-#define PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT (1U<<5)
-#define PVRSRV_MISC_INFO_FREEMEM_PRESENT (1U<<6)
-
-#define PVRSRV_MISC_INFO_RESET_PRESENT (1U<<31)
-
+#define PVRSRV_MEM_ION (1U<<29)
+#define PVRSRV_MEM_ALLOCATENONCACHEDMEM (1UL<<30)
+
+/*
+ Internal allocation/mapping flags
+ (bit 31)
+*/
+#define PVRSRV_MEM_SPARSE (1U<<31)
+
+
+/*
+ * How much context we lose on a (power) mode change
+ */
+#define PVRSRV_NO_CONTEXT_LOSS 0 /*!< Do not lose state on power down */
+#define PVRSRV_SEVERE_LOSS_OF_CONTEXT 1 /*!< lose state on power down */
+#define PVRSRV_PRE_STATE_CHANGE_MASK 0x80 /*!< power state change mask */
+
+
+/*
+ * Device cookie defines
+ */
+#define PVRSRV_DEFAULT_DEV_COOKIE (1) /*!< default device cookie */
+
+
+/*
+ * Misc Info. present flags
+ */
+#define PVRSRV_MISC_INFO_TIMER_PRESENT (1U<<0)
+#define PVRSRV_MISC_INFO_CLOCKGATE_PRESENT (1U<<1)
+#define PVRSRV_MISC_INFO_MEMSTATS_PRESENT (1U<<2)
+#define PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT (1U<<3)
+#define PVRSRV_MISC_INFO_DDKVERSION_PRESENT (1U<<4)
+#define PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT (1U<<5)
+#define PVRSRV_MISC_INFO_FREEMEM_PRESENT (1U<<6)
+#define PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT (1U<<7)
+#define PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT (1U<<8)
+#define PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT (1U<<9)
+
+#define PVRSRV_MISC_INFO_RESET_PRESENT (1U<<31)
+
+/* PDUMP defines */
#define PVRSRV_PDUMP_MAX_FILENAME_SIZE 20
#define PVRSRV_PDUMP_MAX_COMMENT_SIZE 200
+/*
+ Flags for PVRSRVChangeDeviceMemoryAttributes call.
+*/
#define PVRSRV_CHANGEDEVMEM_ATTRIBS_CACHECOHERENT 0x00000001
+/*
+ Flags for PVRSRVMapExtMemory and PVRSRVUnmapExtMemory
+ ALTERNATEVA - Used when mapping multiple virtual addresses to the same physical address. Set this flag on extra maps.
+ PHYSCONTIG - Physical pages are contiguous (unused)
+*/
#define PVRSRV_MAPEXTMEMORY_FLAGS_ALTERNATEVA 0x00000001
#define PVRSRV_MAPEXTMEMORY_FLAGS_PHYSCONTIG 0x00000002
+/*
+ Flags for PVRSRVModifySyncOps
+ WO_INC - Used to increment "WriteOpsPending/complete of sync info"
+ RO_INC - Used to increment "ReadOpsPending/complete of sync info"
+*/
#define PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC 0x00000001
#define PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC 0x00000002
+/*
+ Flags for Services connection.
+ Allows to define per-client policy for Services
+*/
#define SRV_FLAGS_PERSIST 0x1
#define SRV_FLAGS_PDUMP_ACTIVE 0x2
+/*
+ Pdump flags which are accessible to Services clients
+*/
#define PVRSRV_PDUMP_FLAGS_CONTINUOUS 0x1
+/******************************************************************************
+ * Enums
+ *****************************************************************************/
+
+/*!
+ ******************************************************************************
+ * List of known device types.
+ *****************************************************************************/
typedef enum _PVRSRV_DEVICE_TYPE_
{
PVRSRV_DEVICE_TYPE_UNKNOWN = 0 ,
PVRSRV_DEVICE_TYPE_VGX = 8,
-
+ /* 3rd party devices take ext type */
PVRSRV_DEVICE_TYPE_EXT = 9,
PVRSRV_DEVICE_TYPE_LAST = 9,
#define HEAP_IDX( _heap_id_ ) ( (_heap_id_)&((1<<24) - 1 ) )
#define HEAP_DEV( _heap_id_ ) ( (_heap_id_)>>24 )
+/* common undefined heap ID define */
#define PVRSRV_UNDEFINED_HEAP_ID (~0LU)
+/*!
+ ******************************************************************************
+ * User Module type
+ *****************************************************************************/
typedef enum
{
IMG_EGL = 0x00000001,
#define APPHINT_MAX_STRING_SIZE 256
+/*!
+ ******************************************************************************
+ * IMG data types
+ *****************************************************************************/
typedef enum
{
IMG_STRING_TYPE = 1,
}IMG_DATA_TYPE;
+/******************************************************************************
+ * Structure definitions.
+ *****************************************************************************/
+
+/*!
+ * Forward declaration
+ */
typedef struct _PVRSRV_DEV_DATA_ *PPVRSRV_DEV_DATA;
+/*!
+ ******************************************************************************
+ * Device identifier structure
+ *****************************************************************************/
typedef struct _PVRSRV_DEVICE_IDENTIFIER_
{
- PVRSRV_DEVICE_TYPE eDeviceType;
- PVRSRV_DEVICE_CLASS eDeviceClass;
- IMG_UINT32 ui32DeviceIndex;
- IMG_CHAR *pszPDumpDevName;
- IMG_CHAR *pszPDumpRegName;
+ PVRSRV_DEVICE_TYPE eDeviceType; /*!< Identifies the type of the device */
+ PVRSRV_DEVICE_CLASS eDeviceClass; /*!< Identifies more general class of device - display/3d/mpeg etc */
+ IMG_UINT32 ui32DeviceIndex; /*!< Index of the device within the system */
+ IMG_CHAR *pszPDumpDevName; /*!< Pdump memory bank name */
+ IMG_CHAR *pszPDumpRegName; /*!< Pdump register bank name */
} PVRSRV_DEVICE_IDENTIFIER;
+/******************************************************************************
+ * Client dev info
+ ******************************************************************************
+ */
typedef struct _PVRSRV_CLIENT_DEV_DATA_
{
- IMG_UINT32 ui32NumDevices;
- PVRSRV_DEVICE_IDENTIFIER asDevID[PVRSRV_MAX_DEVICES];
- PVRSRV_ERROR (*apfnDevConnect[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);
- PVRSRV_ERROR (*apfnDumpTrace[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);
+ IMG_UINT32 ui32NumDevices; /*!< Number of services-managed devices connected */
+ PVRSRV_DEVICE_IDENTIFIER asDevID[PVRSRV_MAX_DEVICES]; /*!< Device identifiers */
+ PVRSRV_ERROR (*apfnDevConnect[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA); /*< device-specific connection callback */
+ PVRSRV_ERROR (*apfnDumpTrace[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA); /*!< device-specific debug trace callback */
} PVRSRV_CLIENT_DEV_DATA;
+/*!
+ ******************************************************************************
+ * Kernel Services connection structure
+ *****************************************************************************/
typedef struct _PVRSRV_CONNECTION_
{
- IMG_HANDLE hServices;
- IMG_UINT32 ui32ProcessID;
- PVRSRV_CLIENT_DEV_DATA sClientDevData;
- IMG_UINT32 ui32SrvFlags;
+ IMG_HANDLE hServices; /*!< UM IOCTL handle */
+ IMG_UINT32 ui32ProcessID; /*!< Process ID for resource locking */
+ PVRSRV_CLIENT_DEV_DATA sClientDevData; /*!< Client device data */
+ IMG_UINT32 ui32SrvFlags; /*!< Per-client Services flags */
}PVRSRV_CONNECTION;
+/*!
+ ******************************************************************************
+ * This structure allows the user mode glue code to have an OS independent
+ * set of prototypes.
+ *****************************************************************************/
typedef struct _PVRSRV_DEV_DATA_
{
- IMG_CONST PVRSRV_CONNECTION *psConnection;
+ IMG_CONST PVRSRV_CONNECTION *psConnection; /*!< Services connection info */
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hDevCookie;
+ IMG_SID hDevCookie; /*!< Dev cookie */
#else
- IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevCookie; /*!< Dev cookie */
#endif
} PVRSRV_DEV_DATA;
+/*!
+ ******************************************************************************
+ * address:value update structure
+ *****************************************************************************/
typedef struct _PVRSRV_MEMUPDATE_
{
- IMG_UINT32 ui32UpdateAddr;
- IMG_UINT32 ui32UpdateVal;
+ IMG_UINT32 ui32UpdateAddr; /*!< Address */
+ IMG_UINT32 ui32UpdateVal; /*!< value */
} PVRSRV_MEMUPDATE;
+/*!
+ ******************************************************************************
+ * address:value register structure
+ *****************************************************************************/
typedef struct _PVRSRV_HWREG_
{
- IMG_UINT32 ui32RegAddr;
- IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32RegAddr; /*!< Address */
+ IMG_UINT32 ui32RegVal; /*!< value */
} PVRSRV_HWREG;
+/*!
+ ******************************************************************************
+ * Implementation details for memory handling
+ *****************************************************************************/
typedef struct _PVRSRV_MEMBLK_
{
- IMG_DEV_VIRTADDR sDevVirtAddr;
- IMG_HANDLE hOSMemHandle;
- IMG_HANDLE hOSWrapMem;
- IMG_HANDLE hBuffer;
- IMG_HANDLE hResItem;
+ IMG_DEV_VIRTADDR sDevVirtAddr; /*!< Address of the memory in the IMG MMUs address space */
+ IMG_HANDLE hOSMemHandle; /*!< Stores the underlying memory allocation handle */
+ IMG_HANDLE hOSWrapMem; /*!< FIXME: better way to solve this problem */
+ IMG_HANDLE hBuffer; /*!< Stores the BM_HANDLE for the underlying memory management */
+ IMG_HANDLE hResItem; /*!< handle to resource item for allocate */
IMG_SYS_PHYADDR *psIntSysPAddr;
} PVRSRV_MEMBLK;
+/*!
+ ******************************************************************************
+ * Memory Management (externel interface)
+ *****************************************************************************/
typedef struct _PVRSRV_KERNEL_MEM_INFO_ *PPVRSRV_KERNEL_MEM_INFO;
typedef struct _PVRSRV_CLIENT_MEM_INFO_
{
-
+ /* CPU Virtual Address */
IMG_PVOID pvLinAddr;
-
+ /* CPU Virtual Address (for kernel mode) */
IMG_PVOID pvLinAddrKM;
-
+ /* Device Virtual Address */
IMG_DEV_VIRTADDR sDevVAddr;
-
-
-
-
-
- IMG_CPU_PHYADDR sCpuPAddr;
-
-
+ /* allocation flags */
IMG_UINT32 ui32Flags;
-
-
-
+ /* client allocation flags */
IMG_UINT32 ui32ClientFlags;
-
+ /* allocation size in bytes */
IMG_SIZE_T uAllocSize;
-
+ /* ptr to associated client sync info - NULL if no sync */
struct _PVRSRV_CLIENT_SYNC_INFO_ *psClientSyncInfo;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* handle to client mapping data (OS specific) */
IMG_SID hMappingInfo;
-
+ /* handle to kernel mem info */
IMG_SID hKernelMemInfo;
-
+ /* resman handle for UM mapping clean-up */
IMG_SID hResItem;
#else
-
+ /* handle to client mapping data (OS specific) */
IMG_HANDLE hMappingInfo;
-
+ /* handle to kernel mem info */
IMG_HANDLE hKernelMemInfo;
-
+ /* resman handle for UM mapping clean-up */
IMG_HANDLE hResItem;
#endif
#if defined(SUPPORT_MEMINFO_IDS)
#if !defined(USE_CODE)
-
+ /* Globally unique "stamp" for allocation (not re-used until wrap) */
IMG_UINT64 ui64Stamp;
- #else
+ #else /* !defined(USE_CODE) */
IMG_UINT32 dummy1;
IMG_UINT32 dummy2;
- #endif
-#endif
-
-
-
+ #endif /* !defined(USE_CODE) */
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
+ /*
+ ptr to next mem info
+ D3D uses psNext for mid-scene texture reload.
+ */
struct _PVRSRV_CLIENT_MEM_INFO_ *psNext;
} PVRSRV_CLIENT_MEM_INFO, *PPVRSRV_CLIENT_MEM_INFO;
+/*!
+ ******************************************************************************
+ * Memory Heap Information
+ *****************************************************************************/
#define PVRSRV_MAX_CLIENT_HEAPS (32)
typedef struct _PVRSRV_HEAP_INFO_
{
+/*
+ Event Object information structure
+*/
typedef struct _PVRSRV_EVENTOBJECT_
{
-
+ /* globally unique name of the event object */
IMG_CHAR szName[EVENTOBJNAME_MAXLENGTH];
-
+ /* kernel specific handle for the event object */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hOSEventKM;
#else
} PVRSRV_EVENTOBJECT;
+/*
+ Cache operation type
+*/
typedef enum
{
PVRSRV_MISC_INFO_CPUCACHEOP_NONE = 0,
PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH
} PVRSRV_MISC_INFO_CPUCACHEOP_TYPE;
+/*!
+ ******************************************************************************
+ * Structure to retrieve misc. information from services
+ *****************************************************************************/
typedef struct _PVRSRV_MISC_INFO_
{
- IMG_UINT32 ui32StateRequest;
- IMG_UINT32 ui32StatePresent;
+ IMG_UINT32 ui32StateRequest; /*!< requested State Flags */
+ IMG_UINT32 ui32StatePresent; /*!< Present/Valid State Flags */
-
+ /*!< SOC Timer register */
IMG_VOID *pvSOCTimerRegisterKM;
IMG_VOID *pvSOCTimerRegisterUM;
#if defined (SUPPORT_SID_INTERFACE)
IMG_HANDLE hSOCTimerRegisterMappingInfo;
#endif
-
+ /*!< SOC Clock Gating registers */
IMG_VOID *pvSOCClockGateRegs;
IMG_UINT32 ui32SOCClockGateRegsSize;
-
+ /* Memory Stats/DDK version string depending on ui32StateRequest flags */
IMG_CHAR *pszMemoryStr;
IMG_UINT32 ui32MemoryStrLen;
-
- PVRSRV_EVENTOBJECT sGlobalEventObject;
+ /* global event object */
+ PVRSRV_EVENTOBJECT sGlobalEventObject;//FIXME: should be private to services
#if defined (SUPPORT_SID_INTERFACE)
IMG_EVENTSID hOSGlobalEvent;
#else
IMG_HANDLE hOSGlobalEvent;
#endif
-
+ /* Note: add misc. items as required */
IMG_UINT32 aui32DDKVersion[4];
-
+ /*!< CPU cache flush controls: */
struct
{
-
+ /*!< Defer the CPU cache op to the next HW op to be submitted (else flush now) */
IMG_BOOL bDeferOp;
-
+ /*!< Type of cache operation to perform */
PVRSRV_MISC_INFO_CPUCACHEOP_TYPE eCacheOpType;
-
+ /* This union is a bit unsightly. We need it because we'll use the psMemInfo
+ * directly in the srvclient PVRSRVGetMiscInfo code, and then convert it
+ * to a kernel meminfo if required. Try to not waste space.
+ */
#if !defined (SUPPORT_SID_INTERFACE)
union
{
-
+ /*!< Input client meminfo (UM side) */
PVRSRV_CLIENT_MEM_INFO *psClientMemInfo;
-
+ /*!< Output kernel meminfo (Bridge+KM side) */
struct _PVRSRV_KERNEL_MEM_INFO_ *psKernelMemInfo;
} u;
#endif
-
+ /*!< Offset in MemInfo to start cache op */
IMG_VOID *pvBaseVAddr;
-
+ /*!< Length of range to perform cache op */
IMG_UINT32 ui32Length;
} sCacheOpCtl;
+
+ /*!< Meminfo refcount controls: */
+ struct
+ {
+ /* This union is a bit unsightly. We need it because we'll use the psMemInfo
+ * directly in the srvclient PVRSRVGetMiscInfo code, and then convert it
+ * to a kernel meminfo if required. Try to not waste space.
+ */
+#if !defined(SUPPORT_SID_INTERFACE)
+ union
+ {
+ /*!< Input client meminfo (UM side) */
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo;
+
+ /*!< Output kernel meminfo (Bridge+KM side) */
+ struct _PVRSRV_KERNEL_MEM_INFO_ *psKernelMemInfo;
+ } u;
+#endif
+
+ /*!< Resulting refcount */
+ IMG_UINT32 ui32RefCount;
+ } sGetRefCountCtl;
+
+ IMG_UINT32 ui32PageSize;
} PVRSRV_MISC_INFO;
+/*!
+ ******************************************************************************
+ * Synchronisation token
+ *****************************************************************************/
typedef struct _PVRSRV_SYNC_TOKEN_
{
-
-
+ /* This token is supposed to be passed around as an opaque object
+ - caller should not rely on the internal fields staying the same.
+ The fields are hidden in sPrivate in order to reinforce this. */
struct
{
#if defined (SUPPORT_SID_INTERFACE)
#endif
IMG_UINT32 ui32ReadOpsPendingSnapshot;
IMG_UINT32 ui32WriteOpsPendingSnapshot;
+ IMG_UINT32 ui32ReadOps2PendingSnapshot;
} sPrivate;
} PVRSRV_SYNC_TOKEN;
+/******************************************************************************
+ * PVR Client Event handling in Services
+ *****************************************************************************/
typedef enum _PVRSRV_CLIENT_EVENT_
{
PVRSRV_CLIENT_EVENT_HWTIMEOUT = 0,
} PVRSRV_CLIENT_EVENT;
+typedef IMG_VOID (*PFN_QUEUE_COMMAND_COMPLETE)(IMG_HANDLE hCallbackData);
+
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVClientEvent(IMG_CONST PVRSRV_CLIENT_EVENT eEvent,
PVRSRV_DEV_DATA *psDevData,
IMG_PVOID pvData);
+/******************************************************************************
+ * PVR Services API prototypes.
+ *****************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVConnect(PVRSRV_CONNECTION **ppsConnection, IMG_UINT32 ui32SrvFlags);
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
-#if 1
-IMG_IMPORT
-IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
-
-IMG_IMPORT
-IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
-
-IMG_IMPORT IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs);
-#endif
-
IMG_IMPORT
PVRSRV_ERROR PVRSRVPollForValue ( const PVRSRV_CONNECTION *psConnection,
#if defined (SUPPORT_SID_INTERFACE)
IMG_UINT32 ui32Waitus,
IMG_UINT32 ui32Tries);
+/* memory APIs */
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
#if defined (SUPPORT_SID_INTERFACE)
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hDevMemContext);
+ IMG_SID hDevMemContext
#else
- IMG_HANDLE hDevMemContext);
+ IMG_HANDLE hDevMemContext
#endif
+ );
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
#endif
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem2(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemHeap,
+#else
+ IMG_HANDLE hDevMemHeap,
+#endif
+ IMG_UINT32 ui32Attribs,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR IMG_CALLCONV PVRSRVExportDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
PVRSRV_CLIENT_MEM_INFO *psMemInfo,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID *phMemInfo);
+ IMG_SID *phMemInfo
#else
- IMG_HANDLE *phMemInfo);
+ IMG_HANDLE *phMemInfo
#endif
+ );
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
IMG_HANDLE hDstDevMemHeap,
#endif
PVRSRV_CLIENT_MEM_INFO **ppsDstMemInfo);
-#endif
+#endif /* defined(LINUX) */
+
+#if defined(SUPPORT_ION)
+PVRSRV_ERROR PVRSRVMapIonHandle(const PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemContext,
+#else
+ IMG_HANDLE hDevMemContext,
+#endif
+ IMG_INT32 uiFD,
+ IMG_UINT32 uiSize,
+ IMG_UINT32 ui32Attribs,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
+PVRSRV_ERROR PVRSRVUnmapIonHandle(const PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+#endif /* defined (SUPPORT_ION) */
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMemSparse(const PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemHeap,
+#else
+ IMG_HANDLE hDevMemHeap,
+#endif
+ IMG_UINT32 ui32Attribs,
+ IMG_SIZE_T uAlignment,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
+/******************************************************************************
+ * PVR Allocation Synchronisation Functionality...
+ *****************************************************************************/
typedef enum _PVRSRV_SYNCVAL_MODE_
{
PVRSRV_SYNCVAL_MODE eMode);
+/******************************************************************************
+ * Common Device Class Enumeration
+ *****************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDeviceClass(IMG_CONST PVRSRV_CONNECTION *psConnection,
PVRSRV_DEVICE_CLASS DeviceClass,
IMG_UINT32 *pui32DevCount,
IMG_UINT32 *pui32DevID);
+/******************************************************************************
+ * Display Device Class API definition
+ *****************************************************************************/
IMG_IMPORT
IMG_HANDLE IMG_CALLCONV PVRSRVOpenDCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
IMG_UINT32 ui32DeviceID);
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCSystemBuffer(IMG_HANDLE hDevice,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID *phBuffer);
+ IMG_SID *phBuffer
#else
- IMG_HANDLE *phBuffer);
+ IMG_HANDLE *phBuffer
#endif
+ );
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCInfo(IMG_HANDLE hDevice,
IMG_UINT32 ui32OEMFlags,
IMG_UINT32 *pui32SwapChainID,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID *phSwapChain);
+ IMG_SID *phSwapChain
#else
- IMG_HANDLE *phSwapChain);
+ IMG_HANDLE *phSwapChain
#endif
+ );
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDCSwapChain (IMG_HANDLE hDevice,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hSwapChain);
+ IMG_SID hSwapChain
#else
- IMG_HANDLE hSwapChain);
+ IMG_HANDLE hSwapChain
#endif
+ );
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstRect (IMG_HANDLE hDevice,
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCBuffers(IMG_HANDLE hDevice,
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hSwapChain,
- IMG_SID *phBuffer);
+ IMG_SID *phBuffer
#else
IMG_HANDLE hSwapChain,
- IMG_HANDLE *phBuffer);
+ IMG_HANDLE *phBuffer
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCBuffers2(IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain,
+ IMG_SID *phBuffer,
+#else
+ IMG_HANDLE hSwapChain,
+ IMG_HANDLE *phBuffer,
#endif
+ IMG_SYS_PHYADDR *psPhyAddr);
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCBuffer (IMG_HANDLE hDevice,
IMG_RECT *psClipRect,
IMG_UINT32 ui32SwapInterval,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hPrivateTag);
+ IMG_SID hPrivateTag
#else
- IMG_HANDLE hPrivateTag);
+ IMG_HANDLE hPrivateTag
#endif
+ );
IMG_IMPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCSystem (IMG_HANDLE hDevice,
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCBuffer2 (IMG_HANDLE hDevice,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hSwapChain);
+ IMG_SID hBuffer,
#else
- IMG_HANDLE hSwapChain);
+ IMG_HANDLE hBuffer,
#endif
+ IMG_UINT32 ui32SwapInterval,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfos,
+ IMG_UINT32 ui32NumMemInfos,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCSystem (IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain
+#else
+ IMG_HANDLE hSwapChain
+#endif
+ );
+/******************************************************************************
+ * Buffer Device Class API definition
+ *****************************************************************************/
IMG_IMPORT
IMG_HANDLE IMG_CALLCONV PVRSRVOpenBCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
IMG_UINT32 ui32DeviceID);
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBuffer(IMG_HANDLE hDevice,
IMG_UINT32 ui32BufferIndex,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID *phBuffer);
+ IMG_SID *phBuffer
#else
- IMG_HANDLE *phBuffer);
+ IMG_HANDLE *phBuffer
#endif
+ );
+/******************************************************************************
+ * PDUMP Function prototypes...
+ *****************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpInit(IMG_CONST PVRSRV_CONNECTION *psConnection);
const IMG_VOID *pvDefault,
IMG_VOID *pvReturn);
+/******************************************************************************
+ * Memory API(s)
+ *****************************************************************************/
+
+/* Exported APIs */
IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMem (IMG_SIZE_T ui32Size);
IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMem (IMG_SIZE_T ui32Size);
IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMem (IMG_PVOID pvBase, IMG_SIZE_T uNewSize);
struct _PVRSRV_MUTEX_OPAQUE_STRUCT_;
typedef struct _PVRSRV_MUTEX_OPAQUE_STRUCT_ *PVRSRV_MUTEX_HANDLE;
+
+#if defined(PVR_DEBUG_MUTEXES)
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateMutex(PVRSRV_MUTEX_HANDLE *phMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyMutex(PVRSRV_MUTEX_HANDLE hMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockMutex(PVRSRV_MUTEX_HANDLE hMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockMutex(PVRSRV_MUTEX_HANDLE hMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+
+#define PVRSRVCreateMutex(phMutex) PVRSRVCreateMutex(phMutex, #phMutex, __FILE__, __LINE__)
+#define PVRSRVDestroyMutex(hMutex) PVRSRVDestroyMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#define PVRSRVLockMutex(hMutex) PVRSRVLockMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#define PVRSRVUnlockMutex(hMutex) PVRSRVUnlockMutex(hMutex, #hMutex, __FILE__, __LINE__)
+
+#else /* defined(PVR_DEBUG_MUTEXES) */
+
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);
+#endif /* defined(PVR_DEBUG_MUTEXES) */
+
+
+struct _PVRSRV_RECMUTEX_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_RECMUTEX_OPAQUE_STRUCT_ *PVRSRV_RECMUTEX_HANDLE;
+
+
+#if defined(PVR_DEBUG_MUTEXES)
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateRecursiveMutex(PVRSRV_RECMUTEX_HANDLE *phMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+
+#define PVRSRVCreateRecursiveMutex(phMutex) PVRSRVCreateRecursiveMutex(phMutex, #phMutex, __FILE__, __LINE__)
+#define PVRSRVDestroyRecursiveMutex(hMutex) PVRSRVDestroyRecursiveMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#define PVRSRVLockRecursiveMutex(hMutex) PVRSRVLockRecursiveMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#define PVRSRVUnlockRecursiveMutex(hMutex) PVRSRVUnlockRecursiveMutex(hMutex, #hMutex, __FILE__, __LINE__)
+
+#else /* defined(PVR_DEBUG_MUTEXES) */
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateRecursiveMutex(PVRSRV_RECMUTEX_HANDLE *phMutex);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex);
+
+#endif /* defined(PVR_DEBUG_MUTEXES) */
+
+/* Non-recursive coarse-grained mutex shared between all threads in a proccess */
IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockProcessGlobalMutex(void);
IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockProcessGlobalMutex(void);
PVR_UNREFERENCED_PARAMETER(iPostCount);
}
-#endif
+#endif /* !defined(USE_CODE) */
-#if (defined(DEBUG) && (defined(__linux__) || defined(__QNXNTO__)))
+/* Non-exported APIs */
+#if defined(DEBUG) && (defined(__linux__) || defined(__QNXNTO__) )
IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMemTracking(IMG_VOID *pvMem, IMG_SIZE_T ui32NewSize,
IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
-#endif
+#endif /* defined(DEBUG) && (defined(__linux__) || defined(_UITRON_)) */
+
+/******************************************************************************
+ * PVR Event Object API(s)
+ *****************************************************************************/
IMG_IMPORT PVRSRV_ERROR PVRSRVEventObjectWait(const PVRSRV_CONNECTION *psConnection,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_EVENTSID hOSEvent);
+ IMG_EVENTSID hOSEvent
#else
- IMG_HANDLE hOSEvent);
+ IMG_HANDLE hOSEvent
#endif
+ );
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVCreateSyncInfoModObj
+
+ @Description Creates an empty Modification object to be later used by PVRSRVModifyPendingSyncOps
+
+ ******************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateSyncInfoModObj(const PVRSRV_CONNECTION *psConnection,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID *phKernelSyncInfoModObj);
+ IMG_SID *phKernelSyncInfoModObj
#else
- IMG_HANDLE *phKernelSyncInfoModObj);
+ IMG_HANDLE *phKernelSyncInfoModObj
#endif
+ );
+
+/*!
+ ******************************************************************************
+ @Function PVRSRVDestroySyncInfoModObj
+
+ @Description Destroys a Modification object. Must be empty.
+
+ ******************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroySyncInfoModObj(const PVRSRV_CONNECTION *psConnection,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hKernelSyncInfoModObj);
+ IMG_SID hKernelSyncInfoModObj
#else
- IMG_HANDLE hKernelSyncInfoModObj);
+ IMG_HANDLE hKernelSyncInfoModObj
#endif
+ );
+
+/*!
+ ******************************************************************************
+ @Function PVRSRVModifyPendingSyncOps
+
+ @Description Returns PRE-INCREMENTED sync op values. Performs thread safe increment
+ of sync ops values as specified by ui32ModifyFlags.
+
+ PVRSRV_ERROR_RETRY is returned if the supplied modification object
+ is not empty. This is on the assumption that a different thread
+ will imminently call PVRSRVModifyCompleteSyncOps. This thread should
+ sleep before retrying. It should be regarded as an error if no such
+ other thread exists.
+
+ Note that this API has implied locking semantics, as follows:
+
+ PVRSRVModifyPendingSyncOps()
+ - announces an operation on the buffer is "pending", and
+ conceptually takes a ticket to represent your place in the queue.
+ - NB: ** exclusive access to the resource is _NOT_ granted at this time **
+ PVRSRVSyncOpsFlushToModObj()
+ - ensures you have exclusive access to the resource (conceptually, a LOCK)
+ - the previously "pending" operation can now be regarded as "in progress"
+ PVRSRVModifyCompleteSyncOps()
+ - declares that the previously "in progress" operation is now complete. (UNLOCK)
+
+
+ ******************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyPendingSyncOps(const PVRSRV_CONNECTION *psConnection,
#if defined (SUPPORT_SID_INTERFACE)
IMG_UINT32 *pui32ReadOpsPending,
IMG_UINT32 *pui32WriteOpsPending);
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVModifyCompleteSyncOps
+
+ @Description Performs thread safe increment of sync ops values as specified
+ by the ui32ModifyFlags that were given to PVRSRVModifyPendingSyncOps.
+ The supplied Modification Object will become empty.
+
+ Note that this API has implied locking semantics, as
+ described above in PVRSRVModifyPendingSyncOps
+
+ ******************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyCompleteSyncOps(const PVRSRV_CONNECTION *psConnection,
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hKernelSyncInfoModObj);
+ IMG_SID hKernelSyncInfoModObj
#else
- IMG_HANDLE hKernelSyncInfoModObj);
+ IMG_HANDLE hKernelSyncInfoModObj
#endif
+ );
+
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVSyncOpsTakeToken
+
+ @Description Takes a "deli-counter" style token for future use with
+ PVRSRVSyncOpsFlushToToken(). In practice this means
+ recording a snapshot of the current "pending" values. A
+ future PVRSRVSyncOpsFlushToToken() will ensure that all
+ operations that were pending at the time of this
+ PVRSRVSyncOpsTakeToken() call will be flushed.
+ Operations may be subsequently queued after this call
+ and would not be flushed. The caller is required to
+ provide storage for the token. The token is disposable
+ - i.e. the caller can simply let the token go out of
+ scope without telling us... in particular, there is no
+ obligation to call PVRSRVSyncOpsFlushToToken().
+ Multiple tokens may be taken. There is no implied
+ locking with this API.
+ ******************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsTakeToken(const PVRSRV_CONNECTION *psConnection,
#if defined (SUPPORT_SID_INTERFACE)
const PVRSRV_CLIENT_SYNC_INFO *psSyncInfo,
#endif
PVRSRV_SYNC_TOKEN *psSyncToken);
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVSyncOpsFlushToToken
+
+ @Description Tests whether the dependencies for a pending sync op modification
+ have been satisfied. If this function returns PVRSRV_OK, then the
+ "complete" counts have caught up with the snapshot of the "pending"
+ values taken when PVRSRVSyncOpsTakeToken() was called.
+ In the event that the dependencies are not (yet) met,
+ this call will auto-retry if bWait is specified, otherwise, it will
+ return PVRSRV_ERROR_RETRY. (Not really an "error")
+
+ (auto-retry behaviour not implemented)
+
+ ******************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToToken(const PVRSRV_CONNECTION *psConnection,
#if defined (SUPPORT_SID_INTERFACE)
#endif
const PVRSRV_SYNC_TOKEN *psSyncToken,
IMG_BOOL bWait);
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVSyncOpsFlushToModObj
+
+ @Description Tests whether the dependencies for a pending sync op modification
+ have been satisfied. If this function returns PVRSRV_OK, then the
+ "complete" counts have caught up with the snapshot of the "pending"
+ values taken when PVRSRVModifyPendingSyncOps() was called.
+ PVRSRVModifyCompleteSyncOps() can then be called without risk of
+ stalling. In the event that the dependencies are not (yet) met,
+ this call will auto-retry if bWait is specified, otherwise, it will
+ return PVRSRV_ERROR_RETRY. (Not really an "error")
+
+ Note that this API has implied locking semantics, as
+ described above in PVRSRVModifyPendingSyncOps
+
+ ******************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToModObj(const PVRSRV_CONNECTION *psConnection,
#if defined (SUPPORT_SID_INTERFACE)
#endif
IMG_BOOL bWait);
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVSyncOpsFlushToDelta
+
+ @Description Compares the number of outstanding operations (pending count minus
+ complete count) with the limit specified. If no more than ui32Delta
+ operations are outstanding, this function returns PVRSRV_OK.
+ In the event that there are too many outstanding operations,
+ this call will auto-retry if bWait is specified, otherwise, it will
+ return PVRSRV_ERROR_RETRY. (Not really an "error")
+
+ ******************************************************************************/
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToDelta(const PVRSRV_CONNECTION *psConnection,
PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
IMG_UINT32 ui32Delta,
IMG_BOOL bWait);
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVAllocSyncInfo
+
+ @Description Creates a Sync Object. Unlike the sync objects created
+ automatically with "PVRSRVAllocDeviceMem", the sync objects
+ returned by this function do _not_ have a UM mapping to the
+ sync data and they do _not_ have the device virtual address
+ of the "opscomplete" fields. These data are to be deprecated.
+
+ ******************************************************************************/
+
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
PVRSRV_CLIENT_SYNC_INFO **ppsSyncInfo);
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVFreeSyncInfo
+
+ @Description Destroys a Sync Object created via
+ PVRSRVAllocSyncInfo.
+
+ ******************************************************************************/
+
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
PVRSRV_CLIENT_SYNC_INFO *psSyncInfo);
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVGetErrorString
+
+ @Description Returns a text string relating to the PVRSRV_ERROR enum.
+
+ ******************************************************************************/
IMG_IMPORT
const IMG_CHAR *PVRSRVGetErrorString(PVRSRV_ERROR eError);
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVCacheInvalidate
+
+ @Description Invalidate the CPU cache for a specified memory
+ area. Note that PVRSRVGetMiscInfo provides similar cpu
+ cache flush/invalidate functionality for some platforms.
+
+ ******************************************************************************/
+
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVCacheInvalidate(const PVRSRV_CONNECTION *psConnection,
IMG_PVOID pvLinearAddress,
IMG_UINT32 ui32Size);
+/******************************************************************************
+ Time wrapping macro
+******************************************************************************/
#define TIME_NOT_PASSED_UINT32(a,b,c) (((a) - (b)) < (c))
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* __SERVICES_H__ */
+/******************************************************************************
+ End of file (services.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Services definitions required by external drivers
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides services data structures, defines and prototypes
+ required by external drivers.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined (__SERVICESEXT_H__)
#define __SERVICESEXT_H__
-#define PVRSRV_LOCKFLG_READONLY (1)
+/*
+ * Lock buffer read/write flags
+ */
+#define PVRSRV_LOCKFLG_READONLY (1) /*!< The locking process will only read the locked surface */
+/*!
+ *****************************************************************************
+ * Error values
+ *
+ * NOTE: If you change this, make sure you update the error texts in
+ * services4/include/pvrsrv_errors.h to match.
+ *
+ *****************************************************************************/
typedef enum _PVRSRV_ERROR_
{
PVRSRV_OK = 0,
} PVRSRV_ERROR;
+/*!
+ *****************************************************************************
+ * List of known device classes.
+ *****************************************************************************/
typedef enum _PVRSRV_DEVICE_CLASS_
{
PVRSRV_DEVICE_CLASS_3D = 0 ,
} PVRSRV_DEVICE_CLASS;
+/*!
+ *****************************************************************************
+ * States for power management
+ *****************************************************************************/
typedef enum _PVRSRV_SYS_POWER_STATE_
{
- PVRSRV_SYS_POWER_STATE_Unspecified = -1,
- PVRSRV_SYS_POWER_STATE_D0 = 0,
- PVRSRV_SYS_POWER_STATE_D1 = 1,
- PVRSRV_SYS_POWER_STATE_D2 = 2,
- PVRSRV_SYS_POWER_STATE_D3 = 3,
- PVRSRV_SYS_POWER_STATE_D4 = 4,
+ PVRSRV_SYS_POWER_STATE_Unspecified = -1, /*!< Unspecified : Uninitialised */
+ PVRSRV_SYS_POWER_STATE_D0 = 0, /*!< On */
+ PVRSRV_SYS_POWER_STATE_D1 = 1, /*!< User Idle */
+ PVRSRV_SYS_POWER_STATE_D2 = 2, /*!< System Idle / sleep */
+ PVRSRV_SYS_POWER_STATE_D3 = 3, /*!< Suspend / Hibernate */
+ PVRSRV_SYS_POWER_STATE_D4 = 4, /*!< shutdown */
PVRSRV_SYS_POWER_STATE_FORCE_I32 = 0x7fffffff
typedef enum _PVRSRV_DEV_POWER_STATE_
{
- PVRSRV_DEV_POWER_STATE_DEFAULT = -1,
- PVRSRV_DEV_POWER_STATE_ON = 0,
- PVRSRV_DEV_POWER_STATE_IDLE = 1,
- PVRSRV_DEV_POWER_STATE_OFF = 2,
+ PVRSRV_DEV_POWER_STATE_DEFAULT = -1, /*!< Default state for the device */
+ PVRSRV_DEV_POWER_STATE_ON = 0, /*!< Running */
+ PVRSRV_DEV_POWER_STATE_IDLE = 1, /*!< Powered but operation paused */
+ PVRSRV_DEV_POWER_STATE_OFF = 2, /*!< Unpowered */
PVRSRV_DEV_POWER_STATE_FORCE_I32 = 0x7fffffff
-} PVRSRV_DEV_POWER_STATE, *PPVRSRV_DEV_POWER_STATE;
+} PVRSRV_DEV_POWER_STATE, *PPVRSRV_DEV_POWER_STATE; /* PRQA S 3205 */
+/* Power transition handler prototypes */
typedef PVRSRV_ERROR (*PFN_PRE_POWER) (IMG_HANDLE hDevHandle,
PVRSRV_DEV_POWER_STATE eNewPowerState,
PVRSRV_DEV_POWER_STATE eCurrentPowerState);
PVRSRV_DEV_POWER_STATE eNewPowerState,
PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+/* Clock speed handler prototypes */
typedef PVRSRV_ERROR (*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
IMG_BOOL bIdleDevice,
PVRSRV_DEV_POWER_STATE eCurrentPowerState);
PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+/*****************************************************************************
+ * Enumeration of all possible pixel types. Where applicable, Ordering of name
+ * is in reverse order of memory bytes (i.e. as a word in little endian).
+ * e.g. A8R8G8B8 is in memory as 4 bytes in order: BB GG RR AA
+ *
+ * NOTE: When modifying this structure please update the client driver format
+ * tables located in %WORKROOT%/eurasia/codegen/pixfmts using the tool
+ * located in %WORKROOT%/eurasia/tools/intern/TextureFormatParser.
+ *
+ *****************************************************************************/
typedef enum _PVRSRV_PIXEL_FORMAT_ {
-
+ /* Basic types */
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_RGB888 = 3, /*!< 24bit */
+ PVRSRV_PIXEL_FORMAT_BGR888 = 4, /*!< 24bit */
PVRSRV_PIXEL_FORMAT_GREY_SCALE = 8,
PVRSRV_PIXEL_FORMAT_PAL12 = 13,
PVRSRV_PIXEL_FORMAT_PAL8 = 14,
PVRSRV_PIXEL_FORMAT_BGRA8888 = 28,
PVRSRV_PIXEL_FORMAT_XRGB4444 = 29,
PVRSRV_PIXEL_FORMAT_ARGB8332 = 30,
- PVRSRV_PIXEL_FORMAT_A2RGB10 = 31,
- PVRSRV_PIXEL_FORMAT_A2BGR10 = 32,
+ PVRSRV_PIXEL_FORMAT_A2RGB10 = 31, /*!< 32bpp, 10 bits for R, G, B, 2 bits for A */
+ PVRSRV_PIXEL_FORMAT_A2BGR10 = 32, /*!< 32bpp, 10 bits for B, G, R, 2 bits for A */
PVRSRV_PIXEL_FORMAT_P8 = 33,
PVRSRV_PIXEL_FORMAT_L8 = 34,
PVRSRV_PIXEL_FORMAT_A8L8 = 35,
PVRSRV_PIXEL_FORMAT_D24S8 = 45,
PVRSRV_PIXEL_FORMAT_D24X8 = 46,
-
+ /* Added to ensure TQ build */
PVRSRV_PIXEL_FORMAT_ABGR16 = 47,
PVRSRV_PIXEL_FORMAT_ABGR16F = 48,
PVRSRV_PIXEL_FORMAT_ABGR32 = 49,
PVRSRV_PIXEL_FORMAT_GR32 = 54,
PVRSRV_PIXEL_FORMAT_E5BGR9 = 55,
-
+ /* reserved types */
PVRSRV_PIXEL_FORMAT_RESERVED1 = 56,
PVRSRV_PIXEL_FORMAT_RESERVED2 = 57,
PVRSRV_PIXEL_FORMAT_RESERVED3 = 58,
PVRSRV_PIXEL_FORMAT_RESERVED4 = 59,
PVRSRV_PIXEL_FORMAT_RESERVED5 = 60,
-
+ /* RGB space packed formats */
PVRSRV_PIXEL_FORMAT_R8G8_B8G8 = 61,
PVRSRV_PIXEL_FORMAT_G8R8_G8B8 = 62,
-
+ /* YUV space planar formats */
PVRSRV_PIXEL_FORMAT_NV11 = 63,
PVRSRV_PIXEL_FORMAT_NV12 = 64,
-
+ /* YUV space packed formats */
PVRSRV_PIXEL_FORMAT_YUY2 = 65,
PVRSRV_PIXEL_FORMAT_YUV420 = 66,
PVRSRV_PIXEL_FORMAT_YUV444 = 67,
PVRSRV_PIXEL_FORMAT_UYVY = 71,
PVRSRV_PIXEL_FORMAT_VYUY = 72,
- PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY = 73,
- PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV = 74,
- PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU = 75,
- PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY = 76,
- PVRSRV_PIXEL_FORMAT_FOURCC_ORG_AYUV = 77,
-
-
- PVRSRV_PIXEL_FORMAT_A32B32G32R32 = 78,
- PVRSRV_PIXEL_FORMAT_A32B32G32R32F = 79,
- PVRSRV_PIXEL_FORMAT_A32B32G32R32_UINT = 80,
- PVRSRV_PIXEL_FORMAT_A32B32G32R32_SINT = 81,
-
-
- PVRSRV_PIXEL_FORMAT_B32G32R32 = 82,
- PVRSRV_PIXEL_FORMAT_B32G32R32F = 83,
- PVRSRV_PIXEL_FORMAT_B32G32R32_UINT = 84,
- PVRSRV_PIXEL_FORMAT_B32G32R32_SINT = 85,
-
-
- PVRSRV_PIXEL_FORMAT_G32R32 = 86,
- PVRSRV_PIXEL_FORMAT_G32R32F = 87,
- PVRSRV_PIXEL_FORMAT_G32R32_UINT = 88,
- PVRSRV_PIXEL_FORMAT_G32R32_SINT = 89,
-
-
- PVRSRV_PIXEL_FORMAT_D32F = 90,
- PVRSRV_PIXEL_FORMAT_R32 = 91,
- PVRSRV_PIXEL_FORMAT_R32F = 92,
- PVRSRV_PIXEL_FORMAT_R32_UINT = 93,
- PVRSRV_PIXEL_FORMAT_R32_SINT = 94,
-
-
- PVRSRV_PIXEL_FORMAT_A16B16G16R16 = 95,
- PVRSRV_PIXEL_FORMAT_A16B16G16R16F = 96,
- PVRSRV_PIXEL_FORMAT_A16B16G16R16_SINT = 97,
- PVRSRV_PIXEL_FORMAT_A16B16G16R16_SNORM = 98,
- PVRSRV_PIXEL_FORMAT_A16B16G16R16_UINT = 99,
- PVRSRV_PIXEL_FORMAT_A16B16G16R16_UNORM = 100,
-
-
- PVRSRV_PIXEL_FORMAT_G16R16 = 101,
- PVRSRV_PIXEL_FORMAT_G16R16F = 102,
- PVRSRV_PIXEL_FORMAT_G16R16_UINT = 103,
- PVRSRV_PIXEL_FORMAT_G16R16_UNORM = 104,
- PVRSRV_PIXEL_FORMAT_G16R16_SINT = 105,
- PVRSRV_PIXEL_FORMAT_G16R16_SNORM = 106,
-
-
- PVRSRV_PIXEL_FORMAT_R16 = 107,
- PVRSRV_PIXEL_FORMAT_R16F = 108,
- PVRSRV_PIXEL_FORMAT_R16_UINT = 109,
- PVRSRV_PIXEL_FORMAT_R16_UNORM = 110,
- PVRSRV_PIXEL_FORMAT_R16_SINT = 111,
- PVRSRV_PIXEL_FORMAT_R16_SNORM = 112,
-
-
- PVRSRV_PIXEL_FORMAT_X8R8G8B8 = 113,
- PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM = 114,
- PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM_SRGB = 115,
-
- PVRSRV_PIXEL_FORMAT_A8R8G8B8 = 116,
- PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM = 117,
- PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM_SRGB = 118,
-
- PVRSRV_PIXEL_FORMAT_A8B8G8R8 = 119,
- PVRSRV_PIXEL_FORMAT_A8B8G8R8_UINT = 120,
- PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM = 121,
- PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM_SRGB = 122,
- PVRSRV_PIXEL_FORMAT_A8B8G8R8_SINT = 123,
- PVRSRV_PIXEL_FORMAT_A8B8G8R8_SNORM = 124,
-
-
- PVRSRV_PIXEL_FORMAT_G8R8 = 125,
- PVRSRV_PIXEL_FORMAT_G8R8_UINT = 126,
- PVRSRV_PIXEL_FORMAT_G8R8_UNORM = 127,
- PVRSRV_PIXEL_FORMAT_G8R8_SINT = 128,
- PVRSRV_PIXEL_FORMAT_G8R8_SNORM = 129,
-
-
- PVRSRV_PIXEL_FORMAT_A8 = 130,
- PVRSRV_PIXEL_FORMAT_R8 = 131,
- PVRSRV_PIXEL_FORMAT_R8_UINT = 132,
- PVRSRV_PIXEL_FORMAT_R8_UNORM = 133,
- PVRSRV_PIXEL_FORMAT_R8_SINT = 134,
- PVRSRV_PIXEL_FORMAT_R8_SNORM = 135,
-
-
- PVRSRV_PIXEL_FORMAT_A2B10G10R10 = 136,
- PVRSRV_PIXEL_FORMAT_A2B10G10R10_UNORM = 137,
- PVRSRV_PIXEL_FORMAT_A2B10G10R10_UINT = 138,
-
-
- PVRSRV_PIXEL_FORMAT_B10G11R11 = 139,
- PVRSRV_PIXEL_FORMAT_B10G11R11F = 140,
-
-
- PVRSRV_PIXEL_FORMAT_X24G8R32 = 141,
- PVRSRV_PIXEL_FORMAT_G8R24 = 142,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY = 73, /*!< See http://www.fourcc.org/yuv.php#UYVY */
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV = 74, /*!< See http://www.fourcc.org/yuv.php#YUYV */
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU = 75, /*!< See http://www.fourcc.org/yuv.php#YVYU */
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY = 76, /*!< No fourcc.org link */
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_AYUV = 77, /*!< See http://www.fourcc.org/yuv.php#AYUV */
+
+ /* 4 component, 32 bits per component types */
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32 = 78, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32F = 79, /*!< float type */
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_UINT = 80, /*!< uint type */
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_SINT = 81, /*!< sint type */
+
+ /* 3 component, 32 bits per component types */
+ PVRSRV_PIXEL_FORMAT_B32G32R32 = 82, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_B32G32R32F = 83, /*!< float data */
+ PVRSRV_PIXEL_FORMAT_B32G32R32_UINT = 84, /*!< uint data */
+ PVRSRV_PIXEL_FORMAT_B32G32R32_SINT = 85, /*!< signed int data */
+
+ /* 2 component, 32 bits per component types */
+ PVRSRV_PIXEL_FORMAT_G32R32 = 86, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_G32R32F = 87, /*!< float */
+ PVRSRV_PIXEL_FORMAT_G32R32_UINT = 88, /*!< uint */
+ PVRSRV_PIXEL_FORMAT_G32R32_SINT = 89, /*!< signed int */
+
+ /* 1 component, 32 bits per component types */
+ PVRSRV_PIXEL_FORMAT_D32F = 90, /*!< float depth */
+ PVRSRV_PIXEL_FORMAT_R32 = 91, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_R32F = 92, /*!< float type */
+ PVRSRV_PIXEL_FORMAT_R32_UINT = 93, /*!< unsigned int type */
+ PVRSRV_PIXEL_FORMAT_R32_SINT = 94, /*!< signed int type */
+
+ /* 4 component, 16 bits per component types */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16 = 95, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16F = 96, /*!< type float */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SINT = 97, /*!< signed ints */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SNORM = 98, /*!< signed normalised int */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UINT = 99, /*!< unsigned ints */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UNORM = 100, /*!< normalised unsigned int */
+
+ /* 2 component, 16 bits per component types */
+ PVRSRV_PIXEL_FORMAT_G16R16 = 101, /*!< unspecified type */
+ PVRSRV_PIXEL_FORMAT_G16R16F = 102, /*!< float type */
+ PVRSRV_PIXEL_FORMAT_G16R16_UINT = 103, /*!< unsigned int type */
+ PVRSRV_PIXEL_FORMAT_G16R16_UNORM = 104, /*!< unsigned normalised */
+ PVRSRV_PIXEL_FORMAT_G16R16_SINT = 105, /*!< signed int */
+ PVRSRV_PIXEL_FORMAT_G16R16_SNORM = 106, /*!< signed normalised */
+
+ /* 1 component, 16 bits per component types */
+ PVRSRV_PIXEL_FORMAT_R16 = 107, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_R16F = 108, /*!< float type */
+ PVRSRV_PIXEL_FORMAT_R16_UINT = 109, /*!< unsigned int type */
+ PVRSRV_PIXEL_FORMAT_R16_UNORM = 110, /*!< unsigned normalised int type */
+ PVRSRV_PIXEL_FORMAT_R16_SINT = 111, /*!< signed int type */
+ PVRSRV_PIXEL_FORMAT_R16_SNORM = 112, /*!< signed normalised int type */
+
+ /* 4 component, 8 bits per component types */
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8 = 113, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM = 114, /*!< normalised unsigned int */
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM_SRGB = 115, /*!< normalised uint with sRGB */
+
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8 = 116, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM = 117, /*!< normalised unsigned int */
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM_SRGB = 118, /*!< normalised uint with sRGB */
+
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8 = 119, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UINT = 120, /*!< unsigned int */
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM = 121, /*!< normalised unsigned int */
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM_SRGB = 122, /*!< normalised unsigned int */
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SINT = 123, /*!< signed int */
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SNORM = 124, /*!< normalised signed int */
+
+ /* 2 component, 8 bits per component types */
+ PVRSRV_PIXEL_FORMAT_G8R8 = 125, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_G8R8_UINT = 126, /*!< unsigned int type */
+ PVRSRV_PIXEL_FORMAT_G8R8_UNORM = 127, /*!< unsigned int normalised */
+ PVRSRV_PIXEL_FORMAT_G8R8_SINT = 128, /*!< signed int type */
+ PVRSRV_PIXEL_FORMAT_G8R8_SNORM = 129, /*!< signed int normalised */
+
+ /* 1 component, 8 bits per component types */
+ PVRSRV_PIXEL_FORMAT_A8 = 130, /*!< type unspecified, alpha channel */
+ PVRSRV_PIXEL_FORMAT_R8 = 131, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_R8_UINT = 132, /*!< unsigned int */
+ PVRSRV_PIXEL_FORMAT_R8_UNORM = 133, /*!< unsigned normalised int */
+ PVRSRV_PIXEL_FORMAT_R8_SINT = 134, /*!< signed int */
+ PVRSRV_PIXEL_FORMAT_R8_SNORM = 135, /*!< signed normalised int */
+
+ /* A2RGB10 types */
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10 = 136, /*!< Type unspecified */
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UNORM = 137, /*!< normalised unsigned int */
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UINT = 138, /*!< unsigned int */
+
+ /* F11F11F10 types */
+ PVRSRV_PIXEL_FORMAT_B10G11R11 = 139, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_B10G11R11F = 140, /*!< float type */
+
+ /* esoteric types */
+ PVRSRV_PIXEL_FORMAT_X24G8R32 = 141, /*!< 64 bit, type unspecified (Usually typed to D32S8 style) */
+ PVRSRV_PIXEL_FORMAT_G8R24 = 142, /*!< 32 bit, type unspecified (Usually typed to D24S8 style) */
PVRSRV_PIXEL_FORMAT_X8R24 = 143,
- PVRSRV_PIXEL_FORMAT_E5B9G9R9 = 144,
- PVRSRV_PIXEL_FORMAT_R1 = 145,
+ PVRSRV_PIXEL_FORMAT_E5B9G9R9 = 144, /*!< 32 bit, shared exponent (RGBE). */
+ PVRSRV_PIXEL_FORMAT_R1 = 145, /*!< 1 bit monochrome */
PVRSRV_PIXEL_FORMAT_RESERVED6 = 146,
PVRSRV_PIXEL_FORMAT_RESERVED7 = 147,
PVRSRV_PIXEL_FORMAT_RESERVED19 = 159,
PVRSRV_PIXEL_FORMAT_RESERVED20 = 160,
-
- PVRSRV_PIXEL_FORMAT_UBYTE4 = 161,
- PVRSRV_PIXEL_FORMAT_SHORT4 = 162,
- PVRSRV_PIXEL_FORMAT_SHORT4N = 163,
- PVRSRV_PIXEL_FORMAT_USHORT4N = 164,
- PVRSRV_PIXEL_FORMAT_SHORT2N = 165,
- PVRSRV_PIXEL_FORMAT_SHORT2 = 166,
- PVRSRV_PIXEL_FORMAT_USHORT2N = 167,
- PVRSRV_PIXEL_FORMAT_UDEC3 = 168,
- PVRSRV_PIXEL_FORMAT_DEC3N = 169,
- PVRSRV_PIXEL_FORMAT_F16_2 = 170,
- PVRSRV_PIXEL_FORMAT_F16_4 = 171,
-
-
+ /* DXLegacy vertex types */
+ PVRSRV_PIXEL_FORMAT_UBYTE4 = 161, /*!< 4 channels, 1 byte per channel, normalised */
+ PVRSRV_PIXEL_FORMAT_SHORT4 = 162, /*!< 4 signed channels, 16 bits each, unnormalised */
+ PVRSRV_PIXEL_FORMAT_SHORT4N = 163, /*!< 4 signed channels, 16 bits each, normalised */
+ PVRSRV_PIXEL_FORMAT_USHORT4N = 164, /*!< 4 unsigned channels, 16 bits each, normalised */
+ PVRSRV_PIXEL_FORMAT_SHORT2N = 165, /*!< 2 signed channels, 16 bits each, normalised */
+ PVRSRV_PIXEL_FORMAT_SHORT2 = 166, /*!< 2 signed channels, 16 bits each, unnormalised */
+ PVRSRV_PIXEL_FORMAT_USHORT2N = 167, /*!< 2 unsigned channels, 16 bits each, normalised */
+ PVRSRV_PIXEL_FORMAT_UDEC3 = 168, /*!< 3 10-bit channels, unnormalised, unsigned*/
+ PVRSRV_PIXEL_FORMAT_DEC3N = 169, /*!< 3 10-bit channels, signed normalised */
+ PVRSRV_PIXEL_FORMAT_F16_2 = 170, /*!< 2 F16 channels */
+ PVRSRV_PIXEL_FORMAT_F16_4 = 171, /*!< 4 F16 channels */
+
+ /* misc float types */
PVRSRV_PIXEL_FORMAT_L_F16 = 172,
PVRSRV_PIXEL_FORMAT_L_F16_REP = 173,
PVRSRV_PIXEL_FORMAT_L_F16_A_F16 = 174,
PVRSRV_PIXEL_FORMAT_A_F32 = 178,
PVRSRV_PIXEL_FORMAT_L_F32_A_F32 = 179,
-
+ /* powervr types */
PVRSRV_PIXEL_FORMAT_PVRTC2 = 180,
PVRSRV_PIXEL_FORMAT_PVRTC4 = 181,
PVRSRV_PIXEL_FORMAT_PVRTCII2 = 182,
PVRSRV_PIXEL_FORMAT_MONO8 = 193,
PVRSRV_PIXEL_FORMAT_MONO16 = 194,
-
+ /* additional YUV types */
PVRSRV_PIXEL_FORMAT_C0_YUYV = 195,
PVRSRV_PIXEL_FORMAT_C0_UYVY = 196,
PVRSRV_PIXEL_FORMAT_C0_YVYU = 197,
PVRSRV_PIXEL_FORMAT_C1_YVYU = 201,
PVRSRV_PIXEL_FORMAT_C1_VYUY = 202,
-
+ /* planar YUV types */
PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_UV = 203,
PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_VU = 204,
PVRSRV_PIXEL_FORMAT_C0_YUV420_3P = 205,
PVRSRV_PIXEL_FORMAT_ABGR1555 = 213,
PVRSRV_PIXEL_FORMAT_BGR565 = 214,
-
+ /* 4k aligned planar YUV */
PVRSRV_PIXEL_FORMAT_C0_4KYUV420_2P_UV = 215,
PVRSRV_PIXEL_FORMAT_C0_4KYUV420_2P_VU = 216,
PVRSRV_PIXEL_FORMAT_C1_4KYUV420_2P_UV = 217,
} PVRSRV_PIXEL_FORMAT;
+/*!
+ *****************************************************************************
+ * Enumeration of possible alpha types.
+ *****************************************************************************/
typedef enum _PVRSRV_ALPHA_FORMAT_ {
PVRSRV_ALPHA_FORMAT_UNKNOWN = 0x00000000,
PVRSRV_ALPHA_FORMAT_PRE = 0x00000001,
PVRSRV_ALPHA_FORMAT_MASK = 0x0000000F,
} PVRSRV_ALPHA_FORMAT;
+/*!
+ *****************************************************************************
+ * Enumeration of possible alpha types.
+ *****************************************************************************/
typedef enum _PVRSRV_COLOURSPACE_FORMAT_ {
PVRSRV_COLOURSPACE_FORMAT_UNKNOWN = 0x00000000,
PVRSRV_COLOURSPACE_FORMAT_LINEAR = 0x00010000,
} PVRSRV_COLOURSPACE_FORMAT;
+/*
+ * Drawable orientation (in degrees clockwise).
+ * Opposite sense from WSEGL.
+ */
typedef enum _PVRSRV_ROTATION_ {
PVRSRV_ROTATE_0 = 0,
PVRSRV_ROTATE_90 = 1,
} PVRSRV_ROTATION;
+/*!
+ * Flags for DisplayClassCreateSwapChain.
+ */
#define PVRSRV_CREATE_SWAPCHAIN_SHARED (1<<0)
#define PVRSRV_CREATE_SWAPCHAIN_QUERY (1<<1)
#define PVRSRV_CREATE_SWAPCHAIN_OEMOVERLAY (1<<2)
+/*!
+ *****************************************************************************
+ * Structure providing implementation details for serialisation and
+ * synchronisation of operations. This is the fundamental unit on which operations
+ * are synced, and would typically be included in any data structures that require
+ * serialised accesses etc. e.g. MEM_INFO structures
+ *
+ *****************************************************************************/
+/*
+ Sync Data to be shared/mapped between user/kernel
+*/
typedef struct _PVRSRV_SYNC_DATA_
{
-
+ /* CPU accessible WriteOp Info */
IMG_UINT32 ui32WriteOpsPending;
volatile IMG_UINT32 ui32WriteOpsComplete;
-
+ /* CPU accessible ReadOp Info */
IMG_UINT32 ui32ReadOpsPending;
volatile IMG_UINT32 ui32ReadOpsComplete;
-
+ /* CPU accessible ReadOp2 Info */
+ IMG_UINT32 ui32ReadOps2Pending;
+ volatile IMG_UINT32 ui32ReadOps2Complete;
+
+ /* pdump specific value */
IMG_UINT32 ui32LastOpDumpVal;
IMG_UINT32 ui32LastReadOpDumpVal;
+ /* Last write oprtation on this sync */
+ IMG_UINT64 ui64LastWrite;
+
} PVRSRV_SYNC_DATA;
+/*
+ Client Sync Info structure
+*/
typedef struct _PVRSRV_CLIENT_SYNC_INFO_
{
-
+ /* mapping of the kernel sync data */
PVRSRV_SYNC_DATA *psSyncData;
-
-
-
-
+ /* Device accessible WriteOp Info */
IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
-
+ /* Device accessible ReadOp Info */
IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
-
+ /* Device accessible ReadOp2 Info */
+ IMG_DEV_VIRTADDR sReadOps2CompleteDevVAddr;
+
+ /* handle to client mapping data (OS specific) */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hMappingInfo;
-
+ /* handle to kernel sync info */
IMG_SID hKernelSyncInfo;
#else
IMG_HANDLE hMappingInfo;
-
+ /* handle to kernel sync info */
IMG_HANDLE hKernelSyncInfo;
#endif
} PVRSRV_CLIENT_SYNC_INFO, *PPVRSRV_CLIENT_SYNC_INFO;
+/*!
+ *****************************************************************************
+ * Resource locking structure
+ *****************************************************************************/
typedef struct PVRSRV_RESOURCE_TAG
{
volatile IMG_UINT32 ui32Lock;
typedef PVRSRV_RESOURCE PVRSRV_RES_HANDLE;
+/* command complete callback pfn prototype */
typedef IMG_VOID (*PFN_CMD_COMPLETE) (IMG_HANDLE);
typedef IMG_VOID (**PPFN_CMD_COMPLETE) (IMG_HANDLE);
+/* private command handler prototype */
typedef IMG_BOOL (*PFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
typedef IMG_BOOL (**PPFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+/*
+ rectangle structure required by Lock API
+*/
typedef struct _IMG_RECT_
{
IMG_INT32 x0;
}IMG_RECT_16;
+/* common pfn between BC/DC */
typedef PVRSRV_ERROR (*PFN_GET_BUFFER_ADDR)(IMG_HANDLE,
IMG_HANDLE,
IMG_SYS_PHYADDR**,
IMG_UINT32*);
+/*
+ Display dimension structure definition
+*/
typedef struct DISPLAY_DIMS_TAG
{
IMG_UINT32 ui32ByteStride;
} DISPLAY_DIMS;
+/*
+ Display format structure definition
+*/
typedef struct DISPLAY_FORMAT_TAG
{
-
+ /* pixel format type */
PVRSRV_PIXEL_FORMAT pixelformat;
} DISPLAY_FORMAT;
+/*
+ Display Surface Attributes structure definition
+*/
typedef struct DISPLAY_SURF_ATTRIBUTES_TAG
{
-
+ /* pixel format type */
PVRSRV_PIXEL_FORMAT pixelformat;
-
+ /* dimensions information structure array */
DISPLAY_DIMS sDims;
} DISPLAY_SURF_ATTRIBUTES;
+/*
+ Display Mode information structure definition
+*/
typedef struct DISPLAY_MODE_INFO_TAG
{
-
+ /* pixel format type */
PVRSRV_PIXEL_FORMAT pixelformat;
-
+ /* dimensions information structure array */
DISPLAY_DIMS sDims;
-
+ /* refresh rate of the display */
IMG_UINT32 ui32RefreshHZ;
-
+ /* OEM specific flags */
IMG_UINT32 ui32OEMFlags;
} DISPLAY_MODE_INFO;
-#define MAX_DISPLAY_NAME_SIZE (50)
+#define MAX_DISPLAY_NAME_SIZE (50) /* arbitrary choice! */
+/*
+ Display info structure definition
+*/
typedef struct DISPLAY_INFO_TAG
{
-
+ /* max swapchains supported */
IMG_UINT32 ui32MaxSwapChains;
-
+ /* max buffers in a swapchain */
IMG_UINT32 ui32MaxSwapChainBuffers;
-
+ /* min swap interval supported */
IMG_UINT32 ui32MinSwapInterval;
-
+ /* max swap interval supported */
IMG_UINT32 ui32MaxSwapInterval;
-
+ /* physical dimensions of the display required for DPI calc. */
IMG_UINT32 ui32PhysicalWidthmm;
IMG_UINT32 ui32PhysicalHeightmm;
-
+ /* display name */
IMG_CHAR szDisplayName[MAX_DISPLAY_NAME_SIZE];
#if defined(SUPPORT_HW_CURSOR)
-
+ /* cursor dimensions */
IMG_UINT16 ui32CursorWidth;
IMG_UINT16 ui32CursorHeight;
#endif
{
IMG_UINT32 ui32Size;
IMG_UINT32 ui32FBPhysBaseAddress;
- IMG_UINT32 ui32FBMemAvailable;
+ IMG_UINT32 ui32FBMemAvailable; /* size of usable FB memory */
IMG_UINT32 ui32SysPhysBaseAddress;
IMG_UINT32 ui32SysSize;
IMG_UINT32 ui32DevIRQ;
#if defined(PDUMP_SUSPEND_IS_PER_THREAD)
+/** Present only on WinMobile 6.5 */
+
typedef struct {
IMG_UINT32 threadId;
IMG_INT suspendCount;
#define PVRSRV_PDUMP_SUSPEND_Q_NAME "PVRSRVPDumpSuspendMsgQ"
#define PVRSRV_PDUMP_SUSPEND_Q_LENGTH 8
-#endif
+#endif /* defined(PDUMP_SUSPEND_IS_PER_THREAD) */
+/*!
+ *****************************************************************************
+ * This structure is used for OS independent registry (profile) access
+ *****************************************************************************/
typedef struct _PVRSRV_REGISTRY_INFO_
{
IMG_UINT32 ui32DevCookie;
#define PVRSRV_BC_FLAGS_YUVCSC_BT601 (0 << 1)
#define PVRSRV_BC_FLAGS_YUVCSC_BT709 (1 << 1)
-#define MAX_BUFFER_DEVICE_NAME_SIZE (50)
+#define MAX_BUFFER_DEVICE_NAME_SIZE (50) /* arbitrary choice! */
+/* buffer information structure */
typedef struct BUFFER_INFO_TAG
{
IMG_UINT32 ui32BufferCount;
BOB_EVEN_NONINTERLEAVED
} OVERLAY_DEINTERLACE_MODE;
-#endif
+#endif /* __SERVICESEXT_H__ */
+/*****************************************************************************
+ End of file (servicesext.h)
+*****************************************************************************/
-/**********************************************************************
+/*************************************************************************/ /*!
+@Title
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/* Each build option listed here is packed into a dword which
+ * provides up to 32 flags (or up to 28 flags plus a numeric
+ * value in the range 0-15 which corresponds to the number of
+ * cores minus one if SGX_FEATURE_MP is defined). The corresponding
+ * bit is set if the build option was enabled at compile time.
*
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
+ * In order to extract the enabled build flags the INTERNAL_TEST
+ * switch should be enabled in a client program which includes this
+ * header. Then the client can test specific build flags by reading
+ * the bit value at ##OPTIONNAME##_SET_OFFSET in SGX_BUILD_OPTIONS.
*
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+ * IMPORTANT: add new options to unused bits or define a new dword
+ * (e.g. SGX_BUILD_OPTIONS2) so that the bitfield remains backwards
+ * compatible.
+ */
+
#if defined(DEBUG) || defined (INTERNAL_TEST)
#define DEBUG_SET_OFFSET OPTIONS_BIT0
#define OPTIONS_BIT0 0x1U
#else
#define OPTIONS_BIT0 0x0
-#endif
+#endif /* DEBUG */
#if defined(PDUMP) || defined (INTERNAL_TEST)
#define PDUMP_SET_OFFSET OPTIONS_BIT1
#define OPTIONS_BIT1 (0x1U << 1)
#else
#define OPTIONS_BIT1 0x0
-#endif
+#endif /* PDUMP */
#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined (INTERNAL_TEST)
#define PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET OPTIONS_BIT2
#define OPTIONS_BIT2 (0x1U << 2)
#else
#define OPTIONS_BIT2 0x0
-#endif
+#endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */
#if defined(SUPPORT_HW_RECOVERY) || defined (INTERNAL_TEST)
#define SUPPORT_HW_RECOVERY_SET_OFFSET OPTIONS_BIT3
#define OPTIONS_BIT3 (0x1U << 3)
#else
#define OPTIONS_BIT3 0x0
-#endif
+#endif /* SUPPORT_HW_RECOVERY */
#define OPTIONS_BIT4 (0x1U << 4)
#else
#define OPTIONS_BIT4 0x0
-#endif
+#endif /* PVR_SECURE_HANDLES */
#endif
#if defined(SGX_BYPASS_SYSTEM_CACHE) || defined (INTERNAL_TEST)
#define OPTIONS_BIT5 (0x1U << 5)
#else
#define OPTIONS_BIT5 0x0
-#endif
+#endif /* SGX_BYPASS_SYSTEM_CACHE */
#if defined(SGX_DMS_AGE_ENABLE) || defined (INTERNAL_TEST)
#define SGX_DMS_AGE_ENABLE_SET_OFFSET OPTIONS_BIT6
#define OPTIONS_BIT6 (0x1U << 6)
#else
#define OPTIONS_BIT6 0x0
-#endif
+#endif /* SGX_DMS_AGE_ENABLE */
#if defined(SGX_FAST_DPM_INIT) || defined (INTERNAL_TEST)
#define SGX_FAST_DPM_INIT_SET_OFFSET OPTIONS_BIT8
#define OPTIONS_BIT8 (0x1U << 8)
#else
#define OPTIONS_BIT8 0x0
-#endif
+#endif /* SGX_FAST_DPM_INIT */
#if defined(SGX_FEATURE_WRITEBACK_DCU) || defined (INTERNAL_TEST)
#define SGX_FEATURE_DCU_SET_OFFSET OPTIONS_BIT9
#define OPTIONS_BIT9 (0x1U << 9)
#else
#define OPTIONS_BIT9 0x0
-#endif
+#endif /* SGX_FEATURE_WRITEBACK_DCU */
#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
#define SGX_FEATURE_MP_SET_OFFSET OPTIONS_BIT10
#define OPTIONS_BIT10 (0x1U << 10)
#else
#define OPTIONS_BIT10 0x0
-#endif
+#endif /* SGX_FEATURE_MP */
-#if defined(SGX_FEATURE_MULTITHREADED_UKERNEL) || defined (INTERNAL_TEST)
-#define SGX_FEATURE_MULTITHREADED_UKERNEL_SET_OFFSET OPTIONS_BIT11
-#define OPTIONS_BIT11 (0x1U << 11)
-#else
#define OPTIONS_BIT11 0x0
-#endif
-
#if defined(SGX_FEATURE_OVERLAPPED_SPM) || defined (INTERNAL_TEST)
#define OPTIONS_BIT12 (0x1U << 12)
#else
#define OPTIONS_BIT12 0x0
-#endif
+#endif /* SGX_FEATURE_RENDER_TARGET_ARRAYS */
#if defined(SGX_FEATURE_SYSTEM_CACHE) || defined (INTERNAL_TEST)
#define OPTIONS_BIT13 (0x1U << 13)
#else
#define OPTIONS_BIT13 0x0
-#endif
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
#if defined(SGX_SUPPORT_HWPROFILING) || defined (INTERNAL_TEST)
#define SGX_SUPPORT_HWPROFILING_SET_OFFSET OPTIONS_BIT14
#define OPTIONS_BIT14 (0x1U << 14)
#else
#define OPTIONS_BIT14 0x0
-#endif
+#endif /* SGX_SUPPORT_HWPROFILING */
#define OPTIONS_BIT15 (0x1U << 15)
#else
#define OPTIONS_BIT15 0x0
-#endif
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
#if defined(SUPPORT_DISPLAYCONTROLLER_TILING) || defined (INTERNAL_TEST)
#define SUPPORT_DISPLAYCONTROLLER_TILING_SET_OFFSET OPTIONS_BIT16
#define OPTIONS_BIT16 (0x1U << 16)
#else
#define OPTIONS_BIT16 0x0
-#endif
+#endif /* SUPPORT_DISPLAYCONTROLLER_TILING */
#if defined(SUPPORT_PERCONTEXT_PB) || defined (INTERNAL_TEST)
#define SUPPORT_PERCONTEXT_PB_SET_OFFSET OPTIONS_BIT17
#define OPTIONS_BIT17 (0x1U << 17)
#else
#define OPTIONS_BIT17 0x0
-#endif
+#endif /* SUPPORT_PERCONTEXT_PB */
#if defined(SUPPORT_SGX_HWPERF) || defined (INTERNAL_TEST)
#define SUPPORT_SGX_HWPERF_SET_OFFSET OPTIONS_BIT18
#define OPTIONS_BIT18 (0x1U << 18)
#else
#define OPTIONS_BIT18 0x0
-#endif
+#endif /* SUPPORT_SGX_HWPERF */
#define OPTIONS_BIT19 (0x1U << 19)
#else
#define OPTIONS_BIT19 0x0
-#endif
+#endif /* SUPPORT_SGX_MMU_DUMMY_PAGE */
#if defined(SUPPORT_SGX_PRIORITY_SCHEDULING) || defined (INTERNAL_TEST)
#define SUPPORT_SGX_PRIORITY_SCHEDULING_SET_OFFSET OPTIONS_BIT20
#define OPTIONS_BIT20 (0x1U << 20)
#else
#define OPTIONS_BIT20 0x0
-#endif
+#endif /* SUPPORT_SGX_PRIORITY_SCHEDULING */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) || defined (INTERNAL_TEST)
#define SUPPORT_SGX_LOW_LATENCY_SCHEDULING_SET_OFFSET OPTIONS_BIT21
#define OPTIONS_BIT21 (0x1U << 21)
#else
#define OPTIONS_BIT21 0x0
-#endif
+#endif /* SUPPORT_SGX_LOW_LATENCY_SCHEDULING */
#if defined(USE_SUPPORT_NO_TA3D_OVERLAP) || defined (INTERNAL_TEST)
#define USE_SUPPORT_NO_TA3D_OVERLAP_SET_OFFSET OPTIONS_BIT22
#define OPTIONS_BIT22 (0x1U << 22)
#else
#define OPTIONS_BIT22 0x0
-#endif
+#endif /* USE_SUPPORT_NO_TA3D_OVERLAP */
#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
#if defined(SGX_FEATURE_MP_CORE_COUNT)
#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET_3D 28UL
#define SGX_FEATURE_MP_CORE_COUNT_SET_MASK 0xFF
#endif
-#else
+#else /* SGX_FEATURE_MP */
#define OPTIONS_HIGHBYTE 0x0
-#endif
+#endif /* SGX_FEATURE_MP */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX KM API Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Exported SGX API details
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __SGXAPI_KM_H__
#define __SGXAPI_KM_H__
#endif
#endif
+/******************************************************************************
+ Some defines...
+******************************************************************************/
+
+/* SGX Heap IDs, note: not all heaps are available to clients */
#define SGX_UNDEFINED_HEAP_ID (~0LU)
#define SGX_GENERAL_HEAP_ID 0
#define SGX_TADATA_HEAP_ID 1
#endif
#if defined(SGX_FEATURE_2D_HARDWARE)
#define SGX_2D_HEAP_ID 12
-#else
-#if defined(FIX_HW_BRN_26915)
-#define SGX_CGBUFFER_HEAP_ID 13
#endif
+#if defined(SUPPORT_MEMORY_TILING)
+#define SGX_VPB_TILED_HEAP_ID 14
+#endif
+#if defined(SUPPORT_ION)
+#define SGX_ION_HEAP_ID 15
#endif
-#define SGX_MAX_HEAP_ID 14
+#define SGX_MAX_HEAP_ID 16
+
+/*
+ * Keep SGX_3DPARAMETERS_HEAP_ID as TQ full custom
+ * shaders need it to select which heap to write
+ * their ISP controll stream to.
+ */
#if (defined(SUPPORT_PERCONTEXT_PB) || defined(SUPPORT_HYBRID_PB))
#define SGX_3DPARAMETERS_HEAP_ID SGX_PERCONTEXT_3DPARAMETERS_HEAP_ID
#else
#define SGX_3DPARAMETERS_HEAP_ID SGX_SHARED_3DPARAMETERS_HEAP_ID
#endif
+/* Define for number of bytes between consecutive code base registers */
#if defined(SGX543) || defined(SGX544) || defined(SGX554)
#define SGX_USE_CODE_SEGMENT_RANGE_BITS 23
#else
#define SGX_MAX_3D_STATUS_VALS 4
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+/* sync info structure array size */
#define SGX_MAX_TA_DST_SYNCS 1
#define SGX_MAX_TA_SRC_SYNCS 1
#define SGX_MAX_3D_SRC_SYNCS 4
+/* note: there is implicitly 1 3D Dst Sync */
#else
-#define SGX_MAX_SRC_SYNCS 8
-#define SGX_MAX_DST_SYNCS 1
+/* sync info structure array size */
+#define SGX_MAX_SRC_SYNCS_TA 32
+#define SGX_MAX_DST_SYNCS_TA 1
+/* note: there is implicitly 1 3D Dst Sync */
+#define SGX_MAX_SRC_SYNCS_TQ 8
+#define SGX_MAX_DST_SYNCS_TQ 1
#endif
#else
#define PVRSRV_SGX_HWPERF_NUM_COUNTERS 9
#define PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS 8
-#endif
+#endif /* SGX543 */
#define PVRSRV_SGX_HWPERF_INVALID 0x1
#define PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON (1UL << 3)
+/*!
+ *****************************************************************************
+ * One entry in the HWPerf Circular Buffer.
+ *****************************************************************************/
typedef struct _PVRSRV_SGX_HWPERF_CB_ENTRY_
{
IMG_UINT32 ui32FrameNo;
IMG_UINT32 ui32Ordinal;
IMG_UINT32 ui32Info;
IMG_UINT32 ui32Clocksx16;
-
+ /* NOTE: There should always be at least as many 3D cores as TA cores. */
IMG_UINT32 ui32Counters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_COUNTERS];
IMG_UINT32 ui32MiscCounters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS];
} PVRSRV_SGX_HWPERF_CB_ENTRY;
+/*
+ Status values control structure
+*/
typedef struct _CTL_STATUS_
{
IMG_DEV_VIRTADDR sStatusDevAddr;
} CTL_STATUS;
+/*!
+ List of possible requests/commands to SGXGetMiscInfo()
+*/
typedef enum _SGX_MISC_INFO_REQUEST_
{
SGX_MISC_INFO_REQUEST_CLOCKSPEED = 0,
#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
SGX_MISC_INFO_REQUEST_MEMREAD,
SGX_MISC_INFO_REQUEST_MEMCOPY,
-#endif
+#endif /* SUPPORT_SGX_EDM_MEMORY_DEBUG */
SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS,
#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
SGX_MISC_INFO_REQUEST_SET_BREAKPOINT,
SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT,
SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT,
-#endif
+#endif /* SGX_FEATURE_DATA_BREAKPOINTS */
SGX_MISC_INFO_DUMP_DEBUG_INFO,
+ SGX_MISC_INFO_DUMP_DEBUG_INFO_FORCE_REGS,
SGX_MISC_INFO_PANIC,
SGX_MISC_INFO_REQUEST_SPM,
SGX_MISC_INFO_REQUEST_ACTIVEPOWER,
} SGX_MISC_INFO_REQUEST;
+/******************************************************************************
+ * Struct for passing SGX core rev/features from ukernel to driver.
+ * This is accessed from the kernel part of the driver and microkernel; it is
+ * only accessed in user space during buffer allocation in srvinit.
+ ******************************************************************************/
typedef struct _PVRSRV_SGX_MISCINFO_FEATURES
{
- IMG_UINT32 ui32CoreRev;
- IMG_UINT32 ui32CoreID;
- IMG_UINT32 ui32DDKVersion;
- IMG_UINT32 ui32DDKBuild;
- IMG_UINT32 ui32CoreIdSW;
- IMG_UINT32 ui32CoreRevSW;
- IMG_UINT32 ui32BuildOptions;
+ IMG_UINT32 ui32CoreRev; /*!< SGX Core revision from HW register */
+ IMG_UINT32 ui32CoreID; /*!< SGX Core ID from HW register */
+ IMG_UINT32 ui32DDKVersion; /*!< software DDK version */
+ IMG_UINT32 ui32DDKBuild; /*!< software DDK build no. */
+ IMG_UINT32 ui32CoreIdSW; /*!< software core version (ID), e.g. SGX535, SGX540 */
+ IMG_UINT32 ui32CoreRevSW; /*!< software core revision */
+ IMG_UINT32 ui32BuildOptions; /*!< build options bit-field */
#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
- IMG_UINT32 ui32DeviceMemValue;
+ IMG_UINT32 ui32DeviceMemValue; /*!< device mem value read from ukernel */
#endif
#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
- IMG_DEV_VIRTADDR sDevVAEDMStatusBuffer;
- IMG_PVOID pvEDMStatusBuffer;
+ IMG_DEV_VIRTADDR sDevVAEDMStatusBuffer; /*!< DevVAddr of the EDM status buffer */
+ IMG_PVOID pvEDMStatusBuffer; /*!< CPUVAddr of the EDM status buffer */
#endif
} PVRSRV_SGX_MISCINFO_FEATURES;
+/******************************************************************************
+ * Struct for getting lock-up stats from the kernel driver
+ ******************************************************************************/
typedef struct _PVRSRV_SGX_MISCINFO_LOCKUPS
{
- IMG_UINT32 ui32HostDetectedLockups;
- IMG_UINT32 ui32uKernelDetectedLockups;
+ IMG_UINT32 ui32HostDetectedLockups; /*!< Host timer detected lockups */
+ IMG_UINT32 ui32uKernelDetectedLockups; /*!< Microkernel detected lockups */
} PVRSRV_SGX_MISCINFO_LOCKUPS;
+/******************************************************************************
+ * Struct for getting lock-up stats from the kernel driver
+ ******************************************************************************/
typedef struct _PVRSRV_SGX_MISCINFO_ACTIVEPOWER
{
- IMG_UINT32 ui32NumActivePowerEvents;
+ IMG_UINT32 ui32NumActivePowerEvents; /*!< active power events */
} PVRSRV_SGX_MISCINFO_ACTIVEPOWER;
+/******************************************************************************
+ * Struct for getting SPM stats fro the kernel driver
+ ******************************************************************************/
typedef struct _PVRSRV_SGX_MISCINFO_SPM
{
- IMG_HANDLE hRTDataSet;
- IMG_UINT32 ui32NumOutOfMemSignals;
- IMG_UINT32 ui32NumSPMRenders;
+ IMG_HANDLE hRTDataSet; /*!< render target data set handle returned from SGXAddRenderTarget */
+ IMG_UINT32 ui32NumOutOfMemSignals; /*!< Number of Out of Mem Signals */
+ IMG_UINT32 ui32NumSPMRenders; /*!< Number of SPM renders */
} PVRSRV_SGX_MISCINFO_SPM;
#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+/*!
+ ******************************************************************************
+ * Structure for SGX break points control
+ *****************************************************************************/
typedef struct _SGX_BREAKPOINT_INFO
{
-
+ /* set/clear BP boolean */
IMG_BOOL bBPEnable;
-
+ /* Index of BP to set */
IMG_UINT32 ui32BPIndex;
-
+ /* On which DataMaster(s) should the breakpoint fire? */
IMG_UINT32 ui32DataMasterMask;
-
+ /* DevVAddr of BP to set */
IMG_DEV_VIRTADDR sBPDevVAddr, sBPDevVAddrEnd;
-
+ /* Whether or not the desired breakpoint will be trapped */
IMG_BOOL bTrapped;
-
+ /* Will the requested breakpoint fire for reads? */
IMG_BOOL bRead;
-
+ /* Will the requested breakpoint fire for writes? */
IMG_BOOL bWrite;
-
+ /* Has a breakpoint been trapped? */
IMG_BOOL bTrappedBP;
-
+ /* Extra information recorded about a trapped breakpoint */
IMG_UINT32 ui32CoreNum;
IMG_DEV_VIRTADDR sTrappedBPDevVAddr;
IMG_UINT32 ui32TrappedBPBurstLength;
IMG_UINT32 ui32TrappedBPDataMaster;
IMG_UINT32 ui32TrappedBPTag;
} SGX_BREAKPOINT_INFO;
-#endif
+#endif /* SGX_FEATURE_DATA_BREAKPOINTS */
+/*!
+ ******************************************************************************
+ * Structure for setting the hardware performance status
+ *****************************************************************************/
typedef struct _PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS
{
-
+ /* See PVRSRV_SGX_HWPERF_STATUS_* */
IMG_UINT32 ui32NewHWPerfStatus;
#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
-
+ /* Specifies the HW's active group selectors */
IMG_UINT32 aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
-
+ /* Specifies the HW's active bit selectors */
IMG_UINT32 aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+ /* Specifies the HW's counter bit selectors */
+ IMG_UINT32 ui32PerfCounterBitSelect;
+ /* Specifies the HW's sum_mux selectors */
+ IMG_UINT32 ui32PerfSumMux;
#else
-
+ /* Specifies the HW's active group */
IMG_UINT32 ui32PerfGroup;
- #endif
+ #endif /* SGX_FEATURE_EXTENDED_PERF_COUNTERS */
} PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS;
+/*!
+ ******************************************************************************
+ * Structure for misc SGX commands in services
+ *****************************************************************************/
typedef struct _SGX_MISC_INFO_
{
- SGX_MISC_INFO_REQUEST eRequest;
+ SGX_MISC_INFO_REQUEST eRequest; /*!< Command request to SGXGetMiscInfo() */
IMG_UINT32 ui32Padding;
#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
- IMG_DEV_VIRTADDR sDevVAddrSrc;
- IMG_DEV_VIRTADDR sDevVAddrDest;
- IMG_HANDLE hDevMemContext;
+ IMG_DEV_VIRTADDR sDevVAddrSrc; /*!< dev virtual addr for mem read */
+ IMG_DEV_VIRTADDR sDevVAddrDest; /*!< dev virtual addr for mem write */
+ IMG_HANDLE hDevMemContext; /*!< device memory context for mem debug */
#endif
union
{
- IMG_UINT32 reserved;
+ IMG_UINT32 reserved; /*!< Unused: ensures valid code in the case everything else is compiled out */
PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures;
IMG_UINT32 ui32SGXClockSpeed;
PVRSRV_SGX_MISCINFO_ACTIVEPOWER sActivePower;
} SGX_MISC_INFO;
#if defined(SGX_FEATURE_2D_HARDWARE)
+/*
+ * The largest number of source sync objects that can be associated with a blit
+ * command. Allows for src, pattern, and mask
+ */
#define PVRSRV_MAX_BLT_SRC_SYNCS 3
#endif
#define SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH 256
+/*
+ Structure for dumping bitmaps
+*/
typedef struct _SGX_KICKTA_DUMPBITMAP_
{
IMG_DEV_VIRTADDR sDevBaseAddr;
#define PVRSRV_SGX_PDUMP_CONTEXT_MAX_BITMAP_ARRAY_SIZE (16)
+/*!
+ ******************************************************************************
+ * Data required only when dumping parameters
+ *****************************************************************************/
typedef struct _PVRSRV_SGX_PDUMP_CONTEXT_
{
-
+ /* cache control word for micro kernel cache flush/invalidates */
IMG_UINT32 ui32CacheControl;
} PVRSRV_SGX_PDUMP_CONTEXT;
#if !defined (SUPPORT_SID_INTERFACE)
typedef struct _SGX_KICKTA_DUMP_ROFF_
{
- IMG_HANDLE hKernelMemInfo;
- IMG_UINT32 uiAllocIndex;
- IMG_UINT32 ui32Offset;
- IMG_UINT32 ui32Value;
- IMG_PCHAR pszName;
+ IMG_HANDLE hKernelMemInfo; /*< Buffer handle */
+ IMG_UINT32 uiAllocIndex; /*< Alloc index for LDDM */
+ IMG_UINT32 ui32Offset; /*< Byte offset to value to dump */
+ IMG_UINT32 ui32Value; /*< Actual value to dump */
+ IMG_PCHAR pszName; /*< Name of buffer */
} SGX_KICKTA_DUMP_ROFF, *PSGX_KICKTA_DUMP_ROFF;
#endif
#endif
{
IMG_UINT32 ui32SpaceUsed;
- IMG_UINT32 ui32Start;
- IMG_UINT32 ui32End;
- IMG_UINT32 ui32BufferSize;
- IMG_UINT32 ui32BackEndLength;
+ IMG_UINT32 ui32Start; /*< Byte offset of start to dump */
+ IMG_UINT32 ui32End; /*< Byte offset of end of dump (non-inclusive) */
+ IMG_UINT32 ui32BufferSize; /*< Size of buffer */
+ IMG_UINT32 ui32BackEndLength; /*< Size of back end portion, if End < Start */
IMG_UINT32 uiAllocIndex;
- IMG_HANDLE hKernelMemInfo;
+ IMG_HANDLE hKernelMemInfo; /*< MemInfo handle for the circular buffer */
IMG_PVOID pvLinAddr;
#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
- IMG_HANDLE hCtrlKernelMemInfo;
- IMG_DEV_VIRTADDR sCtrlDevVAddr;
+ IMG_HANDLE hCtrlKernelMemInfo; /*< MemInfo handle for the control structure of the
+ circular buffer */
+ IMG_DEV_VIRTADDR sCtrlDevVAddr; /*< Device virtual address of the memory in the
+ control structure to be checked */
+#endif
+ IMG_PCHAR pszName; /*< Name of buffer */
+
+#if defined (__QNXNTO__)
+ IMG_UINT32 ui32NameLength; /*< Number of characters in buffer name */
#endif
- IMG_PCHAR pszName;
#if defined (SUPPORT_SID_INTERFACE)
} SGX_KICKTA_DUMP_BUFFER_KM, *PSGX_KICKTA_DUMP_BUFFER_KM;
#else
#if !defined (SUPPORT_SID_INTERFACE)
#ifdef PDUMP
+/*
+ PDUMP version of above kick structure
+*/
typedef struct _SGX_KICKTA_PDUMP_
{
-
+ // Bitmaps to dump
PSGX_KICKTA_DUMPBITMAP psPDumpBitmapArray;
IMG_UINT32 ui32PDumpBitmapSize;
-
+ // Misc buffers to dump (e.g. TA, PDS etc..)
PSGX_KICKTA_DUMP_BUFFER psBufferArray;
IMG_UINT32 ui32BufferArraySize;
-
+ // Roffs to dump
PSGX_KICKTA_DUMP_ROFF psROffArray;
IMG_UINT32 ui32ROffArraySize;
} SGX_KICKTA_PDUMP, *PSGX_KICKTA_PDUMP;
-#endif
-#endif
+#endif /* PDUMP */
+#endif /* #if !defined (SUPPORT_SID_INTERFACE) */
#if defined(TRANSFER_QUEUE)
#if defined(SGX_FEATURE_2D_HARDWARE)
+/* Maximum size of ctrl stream for 2d blit command (in 32 bit words) */
#define SGX_MAX_2D_BLIT_CMD_SIZE 26
#define SGX_MAX_2D_SRC_SYNC_OPS 3
#endif
}
#endif
-#endif
+#endif /* __SGXAPI_KM_H__ */
+/******************************************************************************
+ End of file (sgxapi_km.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX kernel services structues/functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description SGX initialisation script definitions.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __SGXSCRIPT_H__
#define __SGXSCRIPT_H__
{
SGX_INIT_OP_ILLEGAL = 0,
SGX_INIT_OP_WRITE_HW_REG,
+ SGX_INIT_OP_READ_HW_REG,
#if defined(PDUMP)
SGX_INIT_OP_PDUMP_HW_REG,
#endif
IMG_UINT32 ui32Offset;
IMG_UINT32 ui32Value;
} sWriteHWReg;
+ struct {
+ SGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ } sReadHWReg;
#if defined(PDUMP)
struct {
SGX_INIT_OPERATION eOp;
IMG_UINT32 ui32Value;
} sPDumpHWReg;
#endif
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
- struct {
- SGX_INIT_OPERATION eOp;
- } sWorkaroundBRN22997;
-#endif
} SGX_INIT_COMMAND;
typedef struct _SGX_INIT_SCRIPTS_
}
#endif
-#endif
+#endif /* __SGXSCRIPT_H__ */
+/*****************************************************************************
+ End of file (sgxscript.h)
+*****************************************************************************/
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
-
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
ccflags-y += -I$(TOP)/services4/3rdparty/bufferclass_example
bc_example-y += \
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
modules := bufferclass_example
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title bufferclass_example kernel driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/**************************************************************************
+ The 3rd party driver is a specification of an API to integrate the IMG POWERVR
+ Services driver with a 3rd Party 'buffer device'. It is NOT a specification for
+ a 'buffer device' driver, rather a specification to extend the API for a
+ pre-existing driver for the 'buffer device' hardware.
+
+ The 3rd party driver interface provides IMG POWERVR client drivers (e.g. PVR2D)
+ with an API abstraction of the system's underlying buffer device hardware,
+ allowing the client drivers to indirectly control the buffer device hardware
+ and access its associated memory.
+
+ Functions of the API include
+ - query buffer device surface attributes (width, height, stride, pixel format,
+ CPU physical and virtual address)
+
+ Note: having queried surface attributes the client drivers are able to map the
+ buffer device memory to any IMG POWERVR Services device by calling
+ PVRSRVMapDeviceClassMemory with the buffer device surface handle.
+
+ This code is intended to be an example of how a pre-existing buffer device
+ driver may be extended to support the 3rd Party buffer device interface to
+ POWERVR Services
+ - IMG is not providing a buffer device driver implementation.
+ **************************************************************************/
#if defined(__linux__)
#include <linux/string.h>
#else
#define BUFFERCLASS_DEVICE_NAME "Example Bufferclass Device (SW)"
+/* top level 'hook ptr' */
static void *gpvAnchor = NULL;
static PFN_BC_GET_PVRJTABLE pfnGetPVRJTable = IMG_NULL;
+/*
+ Kernel services is a kernel module and must be loaded first.
+ This driver is also a kernel module and must be loaded after the pvr services module.
+ This driver should be able to retrieve the
+ address of the services PVRGetBufferClassJTable from (the already loaded)
+ kernel services module.
+*/
+
+/* returns anchor pointer */
BC_EXAMPLE_DEVINFO * GetAnchorPtr(void)
{
return (BC_EXAMPLE_DEVINFO *)gpvAnchor;
}
+/* sets anchor pointer */
static void SetAnchorPtr(BC_EXAMPLE_DEVINFO *psDevInfo)
{
gpvAnchor = (void *)psDevInfo;
}
+/* Open device function, called from services */
static PVRSRV_ERROR OpenBCDevice(IMG_UINT32 ui32DeviceID, IMG_HANDLE *phDevice)
{
BC_EXAMPLE_DEVINFO *psDevInfo;
-
-
-
+ /*
+ bufferclass_example manages only one BufferClass device
+ therefore there is no need to track ID numbers.
+ */
UNREFERENCED_PARAMETER(ui32DeviceID);
psDevInfo = GetAnchorPtr();
-
+ /* return handle to the devinfo */
*phDevice = (IMG_HANDLE)psDevInfo;
return (PVRSRV_OK);
}
+/* Close device function, called from services */
static PVRSRV_ERROR CloseBCDevice(IMG_UINT32 ui32DeviceID, IMG_HANDLE hDevice)
{
UNREFERENCED_PARAMETER(hDevice);
return (PVRSRV_OK);
}
+/* Passes in the sync data for a buffer, and returns the handle */
+/* called from services */
static PVRSRV_ERROR GetBCBuffer(IMG_HANDLE hDevice,
IMG_UINT32 ui32BufferNumber,
PVRSRV_SYNC_DATA *psSyncData,
}
+/* get buffer info function, called from services */
static PVRSRV_ERROR GetBCInfo(IMG_HANDLE hDevice, BUFFER_INFO *psBCInfo)
{
BC_EXAMPLE_DEVINFO *psDevInfo;
}
+/* get buffer address function, called from services */
static PVRSRV_ERROR GetBCBufferAddr(IMG_HANDLE hDevice,
IMG_HANDLE hBuffer,
IMG_SYS_PHYADDR **ppsSysAddr,
}
+/*
+ * Register the device with services module srvkm.
+ * This should only be done once at boot time.
+ */
BCE_ERROR BC_Example_Register(void)
{
BC_EXAMPLE_DEVINFO *psDevInfo;
-
-
-
-
-
+ /*
+ - connect to services
+ - register with services
+ - allocate and setup private data structure
+ */
+ /*
+ in kernel driver, data structures must be anchored to something for subsequent retrieval
+ this may be a single global pointer or TLS or something else - up to you
+ call API to retrieve this ptr
+ */
-
-
+ /*
+ get the anchor pointer
+ */
psDevInfo = GetAnchorPtr();
if (psDevInfo == NULL)
{
-
+ /* allocate device info. structure */
psDevInfo = (BC_EXAMPLE_DEVINFO *)BCAllocKernelMem(sizeof(BC_EXAMPLE_DEVINFO));
if(!psDevInfo)
{
- return (BCE_ERROR_OUT_OF_MEMORY);
+ return (BCE_ERROR_OUT_OF_MEMORY);/* failure */
}
-
+ /* set the top-level anchor */
SetAnchorPtr((void*)psDevInfo);
-
+ /* set ref count */
psDevInfo->ulRefCount = 0;
if(BCOpenPVRServices(&psDevInfo->hPVRServices) != BCE_OK)
{
- return (BCE_ERROR_INIT_FAILURE);
+ return (BCE_ERROR_INIT_FAILURE);/* failure */
}
if(BCGetLibFuncAddr (psDevInfo->hPVRServices, "PVRGetBufferClassJTable", &pfnGetPVRJTable) != BCE_OK)
{
- return (BCE_ERROR_INIT_FAILURE);
+ return (BCE_ERROR_INIT_FAILURE);/* failure */
}
-
+ /* got the kernel services function table */
if(!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable))
{
- return (BCE_ERROR_INIT_FAILURE);
+ return (BCE_ERROR_INIT_FAILURE);/* failure */
}
-
+ /*
+ Setup the devinfo
+ */
psDevInfo->ulNumBuffers = 0;
if(!psDevInfo->psSystemBuffer)
{
- return (BCE_ERROR_OUT_OF_MEMORY);
+ return (BCE_ERROR_OUT_OF_MEMORY);/* failure */
}
-
+ /* Setup Buffer Info */
psDevInfo->sBufferInfo.pixelformat = PVRSRV_PIXEL_FORMAT_UNKNOWN;
psDevInfo->sBufferInfo.ui32Width = 0;
psDevInfo->sBufferInfo.ui32Height = 0;
strncpy(psDevInfo->sBufferInfo.szDeviceName, BUFFERCLASS_DEVICE_NAME, MAX_BUFFER_DEVICE_NAME_SIZE);
-
-
+ /*
+ Bsetup the BC Jtable so SRVKM can call into this driver
+ */
psDevInfo->sBCJTable.ui32TableSize = sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE);
psDevInfo->sBCJTable.pfnOpenBCDevice = OpenBCDevice;
psDevInfo->sBCJTable.pfnCloseBCDevice = CloseBCDevice;
psDevInfo->sBCJTable.pfnGetBufferAddr = GetBCBufferAddr;
-
-
+ /* register device with services and retrieve device index */
+ /* This example only registers 1 device, but for multiple buffer streams, register more devices */
if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterBCDevice (&psDevInfo->sBCJTable,
(IMG_UINT32*)&psDevInfo->ulDeviceID ) != PVRSRV_OK)
{
- return (BCE_ERROR_DEVICE_REGISTER_FAILED);
+ return (BCE_ERROR_DEVICE_REGISTER_FAILED);/* failure */
}
}
-
+ /* increment the ref count */
psDevInfo->ulRefCount++;
-
+ /* return success */
return (BCE_OK);
}
+/*
+ * Unregister the device with services module srvkm.
+ */
BCE_ERROR BC_Example_Unregister(void)
{
BC_EXAMPLE_DEVINFO *psDevInfo;
psDevInfo = GetAnchorPtr();
-
+ /* check DevInfo has been setup */
if (psDevInfo == NULL)
{
- return (BCE_ERROR_GENERIC);
+ return (BCE_ERROR_GENERIC);/* failure */
}
-
+ /* decrement ref count */
psDevInfo->ulRefCount--;
if (psDevInfo->ulRefCount == 0)
{
-
+ /* all references gone - de-init device information */
PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable = &psDevInfo->sPVRJTable;
-
+ /* Remove the device from kernel services device register */
if (psJTable->pfnPVRSRVRemoveBCDevice(psDevInfo->ulDeviceID) != PVRSRV_OK)
{
- return (BCE_ERROR_GENERIC);
+ return (BCE_ERROR_GENERIC);/* failure */
}
if (BCClosePVRServices(psDevInfo->hPVRServices) != BCE_OK)
{
psDevInfo->hPVRServices = NULL;
- return (BCE_ERROR_GENERIC);
+ return (BCE_ERROR_GENERIC);/* failure */
}
if (psDevInfo->psSystemBuffer)
BCFreeKernelMem(psDevInfo->psSystemBuffer);
}
-
+ /* de-allocate data structure */
BCFreeKernelMem(psDevInfo);
-
+ /* clear the top-level anchor */
SetAnchorPtr(NULL);
}
-
+ /* return success */
return (BCE_OK);
}
+/*
+ * Create shared buffers.
+ */
BCE_ERROR BC_Example_Buffers_Create(void)
{
BC_EXAMPLE_DEVINFO *psDevInfo;
IMG_UINT32 ui32MaxWidth = 320 * 4;
-
-
+ /*
+ get the anchor pointer
+ */
psDevInfo = GetAnchorPtr();
if (psDevInfo == NULL)
{
-
+ /*
+ * This device was not correctly registered/created.
+ */
return (BCE_ERROR_DEVICE_REGISTER_FAILED);
}
if (psDevInfo->ulNumBuffers)
{
-
+ /* Buffers already allocated */
return (BCE_ERROR_GENERIC);
}
-
+ /* Setup Buffer Info */
psDevInfo->sBufferInfo.pixelformat = BC_EXAMPLE_PIXELFORMAT;
psDevInfo->sBufferInfo.ui32Width = ui32Width;
psDevInfo->sBufferInfo.ui32Height = ui32Height;
if(psDevInfo->sBufferInfo.pixelformat == PVRSRV_PIXEL_FORMAT_NV12)
{
-
+ /* Second plane is quarter size, but 2bytes per pixel */
ulSize += ((ui32ByteStride >> 1) * (ui32Height >> 1) << 1);
}
- else if(psDevInfo->sBufferInfo.pixelformat == PVRSRV_PIXEL_FORMAT_I420)
+ else if(psDevInfo->sBufferInfo.pixelformat == PVRSRV_PIXEL_FORMAT_YV12)
{
-
+ /* Second plane is quarter size, but 1byte per pixel */
ulSize += (ui32ByteStride >> 1) * (ui32Height >> 1);
-
+ /* third plane is quarter size, but 1byte per pixel */
ulSize += (ui32ByteStride >> 1) * (ui32Height >> 1);
}
break;
}
#else
-
+ /* Setup system buffer */
if (BCAllocContigMemory(ulSize,
&psDevInfo->psSystemBuffer[i].hMemHandle,
&psDevInfo->psSystemBuffer[i].sCPUVAddr,
psDevInfo->sBufferInfo.ui32BufferCount = (IMG_UINT32)psDevInfo->ulNumBuffers;
-
-
+ /*
+ Bsetup the BC Jtable so SRVKM can call into this driver
+ */
psDevInfo->sBCJTable.ui32TableSize = sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE);
psDevInfo->sBCJTable.pfnOpenBCDevice = OpenBCDevice;
psDevInfo->sBCJTable.pfnCloseBCDevice = CloseBCDevice;
-
+ /* Update buffer's parameters for reconfiguration next time */
if (ui32Width < ui32MaxWidth)
{
switch(pixelformat)
{
case PVRSRV_PIXEL_FORMAT_NV12:
- case PVRSRV_PIXEL_FORMAT_I420:
+ case PVRSRV_PIXEL_FORMAT_YV12:
{
ui32Width += 320;
ui32Height += 160;
ui32ByteStride = BC_EXAMPLE_STRIDE;
}
-
+ /* return success */
return (BCE_OK);
}
+/*
+ * Destroy shared buffers.
+ */
BCE_ERROR BC_Example_Buffers_Destroy(void)
{
BC_EXAMPLE_DEVINFO *psDevInfo;
psDevInfo = GetAnchorPtr();
-
+ /* check DevInfo has been setup */
if (psDevInfo == NULL)
{
-
-
+ /*
+ This device was not correctly registered/created.
+ */
return (BCE_ERROR_DEVICE_REGISTER_FAILED);
}
-
-
+ /*
+ Free all allocated surfaces
+ */
for(i = 0; i < psDevInfo->ulNumBuffers; i++)
{
#if defined(BC_DISCONTIG_BUFFERS)
}
psDevInfo->ulNumBuffers = 0;
-
+ /* Reset buffer info */
psDevInfo->sBufferInfo.pixelformat = PVRSRV_PIXEL_FORMAT_UNKNOWN;
psDevInfo->sBufferInfo.ui32Width = 0;
psDevInfo->sBufferInfo.ui32Height = 0;
psDevInfo->sBufferInfo.ui32Flags = 0;
psDevInfo->sBufferInfo.ui32BufferCount = (IMG_UINT32)psDevInfo->ulNumBuffers;
-
+ /* return success */
return (BCE_OK);
}
+/*
+ * This function does both registration and buffer allocation at
+ * boot time.
+ */
BCE_ERROR BC_Example_Init(void)
{
BCE_ERROR eError;
return (BCE_OK);
}
+/*
+ * Destroy buffers and unregister device.
+ */
BCE_ERROR BC_Example_Deinit(void)
{
BCE_ERROR eError;
return (BCE_OK);
}
+/******************************************************************************
+ End of file (bufferclass_example.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title bufferclass_example kernel driver structures and prototypes
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __BC_EXAMPLE_H__
#define __BC_EXAMPLE_H__
+/* IMG services headers */
#include "img_defs.h"
#include "servicesext.h"
#include "kernelbuffer.h"
#define BC_EXAMPLE_NUM_BUFFERS 3
#define NV12 1
+//#define YV12 1
+//#define YUV422 1
+
#ifdef NV12
#define BC_EXAMPLE_WIDTH (320)
#define BC_EXAMPLE_PIXELFORMAT (PVRSRV_PIXEL_FORMAT_NV12)
#else
-#ifdef I420
+#ifdef YV12
#define BC_EXAMPLE_WIDTH (320)
#define BC_EXAMPLE_HEIGHT (160)
#define BC_EXAMPLE_STRIDE (320)
-#define BC_EXAMPLE_PIXELFORMAT (PVRSRV_PIXEL_FORMAT_I420)
+#define BC_EXAMPLE_PIXELFORMAT (PVRSRV_PIXEL_FORMAT_YV12)
#else
#ifdef YUV422
BCE_TRUE = 1,
} BCE_BOOL, *BCE_PBOOL;
+/* BC_NOHW buffer structure */
typedef struct BC_EXAMPLE_BUFFER_TAG
{
unsigned long ulSize;
BCE_HANDLE hMemHandle;
-
-
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
#if defined(BC_DISCONTIG_BUFFERS)
IMG_SYS_PHYADDR *psSysAddr;
#else
} BC_EXAMPLE_BUFFER;
+/* kernel device information structure */
typedef struct BC_EXAMPLE_DEVINFO_TAG
{
unsigned long ulDeviceID;
BC_EXAMPLE_BUFFER *psSystemBuffer;
-
+ /* number of supported buffers */
unsigned long ulNumBuffers;
-
+ /* jump table into PVR services */
PVRSRV_BC_BUFFER2SRV_KMJTABLE sPVRJTable;
-
+ /* jump table into BC */
PVRSRV_BC_SRV2BUFFER_KMJTABLE sBCJTable;
-
-
-
+ /*
+ handle for connection to kernel services
+ - OS specific - may not be required
+ */
BCE_HANDLE hPVRServices;
-
+ /* ref count */
unsigned long ulRefCount;
-
-
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
BUFFER_INFO sBufferInfo;
} BC_EXAMPLE_DEVINFO;
+/*!
+ *****************************************************************************
+ * Error values
+ *****************************************************************************/
typedef enum _BCE_ERROR_
{
BCE_OK = 0,
BCE_ERROR BC_Example_Init(void);
BCE_ERROR BC_Example_Deinit(void);
+/* OS Specific APIs */
BCE_ERROR BCOpenPVRServices(BCE_HANDLE *phPVRServices);
BCE_ERROR BCClosePVRServices(BCE_HANDLE hPVRServices);
}
#endif
-#endif
+#endif /* __BC_EXAMPLE_H__ */
+
+/******************************************************************************
+ End of file (bufferclass_example.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title bufferclass example linux specific implementations
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/**************************************************************************
+ The 3rd party driver is a specification of an API to integrate the IMG POWERVR
+ Services driver with 3rd Party display hardware. It is NOT a specification for
+ a display controller driver, rather a specification to extend the API for a
+ pre-existing driver for the display hardware.
+
+ The 3rd party driver interface provides IMG POWERVR client drivers (e.g. PVR2D)
+ with an API abstraction of the system's underlying display hardware, allowing
+ the client drivers to indirectly control the display hardware and access its
+ associated memory.
+
+ Functions of the API include
+ - query primary surface attributes (width, height, stride, pixel format, CPU
+ physical and virtual address)
+ - swap/flip chain creation and subsequent query of surface attributes
+ - asynchronous display surface flipping, taking account of asynchronous read
+ (flip) and write (render) operations to the display surface
+
+ Note: having queried surface attributes the client drivers are able to map the
+ display memory to any IMG POWERVR Services device by calling
+ PVRSRVMapDeviceClassMemory with the display surface handle.
+
+ This code is intended to be an example of how a pre-existing display driver may
+ be extended to support the 3rd Party Display interface to POWERVR Services
+ - IMG is not providing a display driver implementation.
+ **************************************************************************/
#include <linux/version.h>
#include <linux/kernel.h>
#endif
#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+/*
+ * Device class used for /sys entries (and udev device node creation)
+ */
static struct class *psPvrClass;
#endif
+/*
+ * This is the major number we use for all nodes in /dev.
+ */
static int AssignedMajorNumber;
static struct file_operations bufferclass_example_fops = {
#define unref__ __attribute__ ((unused))
#if defined(LMA)
-#define PVR_BUFFERCLASS_MEMOFFSET (220 * 1024 * 1024)
-#define PVR_BUFFERCLASS_MEMSIZE (4 * 1024 * 1024)
+#define PVR_BUFFERCLASS_MEMOFFSET (220 * 1024 * 1024) /* Must be after services localmem region */
+#define PVR_BUFFERCLASS_MEMSIZE (4 * 1024 * 1024) /* Must be before displayclass localmem region */
unsigned long g_ulMemBase = 0;
unsigned long g_ulMemCurrent = 0;
+/* PVR device vendor ID */
#define VENDOR_ID_PVR 0x1010
#define DEVICE_ID_PVR 0x1CF1
#define DEVICE_ID1_PVR 0x1CF2
+/* PDP mem (including HP mapping) on base register 2 */
#define PVR_MEM_PCI_BASENUM 2
#endif
+/*****************************************************************************
+ Function Name: BC_Example_ModInit
+ Description : Insert the driver into the kernel.
+
+ The device major number is allocated by the kernel dynamically
+ if AssignedMajorNumber is zero on entry. This means that the
+ device node (nominally /dev/bc_example) may need to be re-made if
+ the kernel varies the major number it assigns. The number
+ does seem to stay constant between runs, but I don't think
+ this is guaranteed. The node is made as root on the shell
+ with:
+
+ mknod /dev/bc_example c ? 0
+
+ where ? is the major number reported by the printk() - look
+ at the boot log using `dmesg' to see this).
+
+ __init places the function in a special memory section that
+ the kernel frees once the function has been run. Refer also
+ to module_init() macro call below.
+
+*****************************************************************************/
static int __init BC_Example_ModInit(void)
{
#if defined(LDM_PLATFORM) || defined(LDM_PCI)
psPCIDev = pci_get_device(VENDOR_ID_PVR, DEVICE_ID_PVR, NULL);
if (psPCIDev == NULL)
{
-
+ /* Try an alternative PCI ID */
psPCIDev = pci_get_device(VENDOR_ID_PVR, DEVICE_ID1_PVR, NULL);
}
#endif
#if defined(LDM_PLATFORM) || defined(LDM_PCI)
-
+ /*
+ * This code (using GPL symbols) facilitates automatic device
+ * node creation on platforms with udev (or similar).
+ */
psPvrClass = class_create(THIS_MODULE, "bc_example");
if (IS_ERR(psPvrClass))
psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
NULL,
-#endif
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) */
DEVNAME);
if (IS_ERR(psDev))
{
printk(KERN_ERR DRVNAME ": BC_Example_ModInit: unable to create device (%ld)", PTR_ERR(psDev));
goto ExitDestroyClass;
}
-#endif
+#endif /* defined(LDM_PLATFORM) || defined(LDM_PCI) */
#if defined(LMA)
-
+ /*
+ * We don't do a pci_request_region for PVR_MEM_PCI_BASENUM,
+ * we assume the SGX driver has done this already.
+ */
g_ulMemBase = pci_resource_start(psPCIDev, PVR_MEM_PCI_BASENUM) + PVR_BUFFERCLASS_MEMOFFSET;
#endif
}
#if defined(LMA)
-
+ /*
+ * To prevent possible problems with system suspend/resume, we don't
+ * keep the device enabled, but rely on the fact that the SGX driver
+ * will have done a pci_enable_device.
+ */
pci_disable_device(psPCIDev);
#endif
ExitError:
#endif
return -EBUSY;
-}
+} /*BC_Example_ModInit*/
+
+/*****************************************************************************
+ Function Name: BC_Example_ModInit
+ Description : Remove the driver from the kernel.
+ __exit places the function in a special memory section that
+ the kernel frees once the function has been run. Refer also
+ to module_exit() macro call below.
+
+*****************************************************************************/
static void __exit BC_Example_ModCleanup(void)
{
#if defined(LDM_PLATFORM) || defined(LDM_PCI)
printk (KERN_ERR DRVNAME ": BC_Example_ModCleanup: can't deinit device\n");
}
-}
+} /*BC_Example_ModCleanup*/
void *BCAllocKernelMem(unsigned long ulSize)
vfree(LinAddr);
}
-#else
+#else /* defined(BC_DISCONTIG_BUFFERS) */
BCE_ERROR BCAllocContigMemory(unsigned long ulSize,
BCE_HANDLE unref__ *phMemHandle,
#if defined(LMA)
void *pvLinAddr;
-
+ /* Only allowed a certain amount of memory for bufferclass buffers */
if(g_ulMemCurrent + ulSize >= PVR_BUFFERCLASS_MEMSIZE)
{
return (BCE_ERROR_OUT_OF_MEMORY);
pPhysAddr->uiAddr = g_ulMemBase + g_ulMemCurrent;
*pLinAddr = pvLinAddr;
-
+ /* Not a real allocator; just increment the current address */
g_ulMemCurrent += ulSize;
return (BCE_OK);
}
return (BCE_ERROR_OUT_OF_MEMORY);
-#else
+#else /* defined(LMA) */
#if defined(BCE_USE_SET_MEMORY)
void *pvLinAddr;
unsigned long ulAlignedSize = PAGE_ALIGN(ulSize);
*pLinAddr = pvLinAddr;
return (BCE_OK);
-#else
+#else /* BCE_USE_SET_MEMORY */
dma_addr_t dma;
void *pvLinAddr;
*pLinAddr = pvLinAddr;
return (BCE_OK);
-#endif
-#endif
+#endif /* BCE_USE_SET_MEMORY */
+#endif /* defined(LMA) */
}
void BCFreeContigMemory(unsigned long ulSize,
#if defined(LMA)
g_ulMemCurrent -= ulSize;
iounmap(LinAddr);
-#else
+#else /* defined(LMA) */
#if defined(BCE_USE_SET_MEMORY)
unsigned long ulAlignedSize = PAGE_ALIGN(ulSize);
int iError;
printk(KERN_ERR DRVNAME ": BCFreeContigMemory: set_memory_wb failed (%d)\n", iError);
}
kfree(LinAddr);
-#else
+#else /* BCE_USE_SET_MEMORY */
dma_free_coherent(NULL, ulSize, LinAddr, (dma_addr_t)PhysAddr.uiAddr);
-#endif
-#endif
+#endif /* BCE_USE_SET_MEMORY */
+#endif /* defined(LMA) */
}
-#endif
-
+#endif /* defined(BC_DISCONTIG_BUFFERS) */
+
+/**************************************************************************
+ FUNCTION: CpuPAddrToSysPAddrBC
+ PURPOSE: Compute a system physical address from a cpu physical
+ address.
+ PARAMETERS: In: cpu_paddr - cpu physical address.
+ RETURNS: system physical address.
+ **************************************************************************/
IMG_SYS_PHYADDR CpuPAddrToSysPAddrBC(IMG_CPU_PHYADDR cpu_paddr)
{
IMG_SYS_PHYADDR sys_paddr;
-
+ /* This would only be an inequality if the CPU's MMU did not point to sys address 0,
+ ie. multi CPU system */
sys_paddr.uiAddr = cpu_paddr.uiAddr;
return sys_paddr;
}
+/**************************************************************************
+ FUNCTION: SysPAddrToCpuPAddrBC
+ PURPOSE: Compute a cpu physical address
+ from a system physical address.
+ PARAMETERS: In: cpu_paddr - system physical address.
+ RETURNS: cpu physical address.
+ **************************************************************************/
IMG_CPU_PHYADDR SysPAddrToCpuPAddrBC(IMG_SYS_PHYADDR sys_paddr)
{
IMG_CPU_PHYADDR cpu_paddr;
-
+ /* This would only be an inequality if the CPU's MMU did not point to sys address 0,
+ ie. multi CPU system */
cpu_paddr.uiAddr = sys_paddr.uiAddr;
return cpu_paddr;
}
BCE_ERROR BCOpenPVRServices (BCE_HANDLE *phPVRServices)
{
-
+ /* Nothing to do - we have already checked services module insertion */
*phPVRServices = 0;
return (BCE_OK);
}
BCE_ERROR BCClosePVRServices (BCE_HANDLE unref__ hPVRServices)
{
-
+ /* Nothing to do */
return (BCE_OK);
}
return (BCE_ERROR_INVALID_PARAMS);
}
-
+ /* Nothing to do - should be exported from pvrsrv.ko */
*ppfnFuncTable = PVRGetBufferClassJTable;
return (BCE_OK);
}
#endif
+/*
+ These macro calls define the initialisation and removal functions of the
+ driver. Although they are prefixed `module_', they apply when compiling
+ statically as well; in both cases they define the function the kernel will
+ run to start/stop the driver.
+*/
module_init(BC_Example_ModInit);
module_exit(BC_Example_ModCleanup);
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title bufferclass_example kernel driver interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __BC_EXAMPLE_LINUX_H__
#define __BC_EXAMPLE_LINUX_H__
}BC_Example_ioctl_package;
+/*!< Nov 2006: according to ioctl-number.txt 'g' wasn't in use. */
#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_get_buffer_count BC_EXAMPLE_IOWR(1)
#define BC_Example_ioctl_reconfigure_buffer BC_EXAMPLE_IOWR(2)
-#endif
+#endif /* __BC_EXAMPLE_H__ */
+
+/******************************************************************************
+ End of file (bufferclass_example.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Bufferclass example private functions.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/**************************************************************************
+ The 3rd party driver is a specification of an API to integrate the IMG POWERVR
+ Services driver with 3rd Party display hardware. It is NOT a specification for
+ a display controller driver, rather a specification to extend the API for a
+ pre-existing driver for the display hardware.
+
+ The 3rd party driver interface provides IMG POWERVR client drivers (e.g. PVR2D)
+ with an API abstraction of the system's underlying display hardware, allowing
+ the client drivers to indirectly control the display hardware and access its
+ associated memory.
+
+ Functions of the API include
+ - query primary surface attributes (width, height, stride, pixel format, CPU
+ physical and virtual address)
+ - swap/flip chain creation and subsequent query of surface attributes
+ - asynchronous display surface flipping, taking account of asynchronous read
+ (flip) and write (render) operations to the display surface
+
+ Note: having queried surface attributes the client drivers are able to map the
+ display memory to any IMG POWERVR Services device by calling
+ PVRSRVMapDeviceClassMemory with the display surface handle.
+
+ This code is intended to be an example of how a pre-existing display driver may
+ be extended to support the 3rd Party Display interface to POWERVR Services
+ - IMG is not providing a display driver implementation.
+ **************************************************************************/
#include "bufferclass_example.h"
#include "bufferclass_example_private.h"
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);
-
+ /* Byte order is VU */
pui16uv[count++] = (v << 8) | u;
}
iPhase++;
}
-static void FillI420Image(void *pvDest, int width, int height, int bytestride)
+static void FillYV12Image(void *pvDest, int width, int height, int bytestride)
{
static int iPhase = 0;
int i, j;
for(j=0;j<height;j+=2)
{
- pui8u = (unsigned char *)pvDest + (height * bytestride) + ((j / 2) * uvplanestride);
+ pui8v = (unsigned char *)pvDest + (height * bytestride) + ((j / 2) * uvplanestride);
count = 0;
for(i=0;i<width;i+=2)
{
- u = (j<(height/2))? ((i<(width/2))? 0xFF:0x33) : ((i<(width/2))? 0x33:0xAA);
-
- pui8u[count++] = u;
+ v = (j<(height/2))? ((i<(width/2))? 0xAC:0x0) : ((i<(width/2))? 0x03:0xEE);
+ pui8v[count++] = v;
}
}
for(j=0;j<height;j+=2)
{
- pui8v = (unsigned char *)pvDest + (height * bytestride) + (uvplaneheight * uvplanestride) + (j / 2) * uvplanestride;
+ pui8u = (unsigned char *)pvDest + (height * bytestride) + (uvplaneheight * uvplanestride) + (j / 2) * uvplanestride;
count = 0;
for(i=0;i<width;i+=2)
{
- v = (j<(height/2))? ((i<(width/2))? 0xAC:0x0) : ((i<(width/2))? 0x03:0xEE);
+ u = (j<(height/2))? ((i<(width/2))? 0xFF:0x33) : ((i<(width/2))? 0x33:0xAA);
+
+ pui8u[count++] = u;
- pui8v[count++] = v;
}
}
unsigned short *pui16Addr = (unsigned short *)pvDest;
unsigned long Colour32;
unsigned short Colour16;
- static unsigned char Colour8 = 0;
+ static unsigned char Colour8 = 0;//debug colour
Colour16 = (Colour8>>3) | ((Colour8>>2)<<5) | ((Colour8>>3)<<11);
Colour32 = Colour16 | Colour16 << 16;
pui32Addr[i] = 0x001F001FUL;
}
-
+ /* advance the colour */
Colour8 = (Colour8 + 1) % MIN(height - 1, 0xFFU);
}
+/*!
+******************************************************************************
+
+ @Function FillBuffer
+
+ @Description
+
+ Fills pixels into a buffer specified by index
+
+ @Input ui32BufferIndex - buffer index
+
+ @Return 0 - success, -1 - failure
+
+******************************************************************************/
int FillBuffer(unsigned int uiBufferIndex)
{
BC_EXAMPLE_DEVINFO *psDevInfo = GetAnchorPtr();
BUFFER_INFO *psBufferInfo;
PVRSRV_SYNC_DATA *psSyncData;
-
+ /* check DevInfo has been setup */
if(psDevInfo == NULL)
{
- return -1;
+ return -1;/* failure */
}
psBuffer = &psDevInfo->psSystemBuffer[uiBufferIndex];
psBufferInfo = &psDevInfo->sBufferInfo;
-
+ /* This may be NULL, as it is only registered once texture streaming starts. */
psSyncData = psBuffer->psSyncData;
if(psSyncData)
{
-
+ /* ensure all reads have flushed on the buffer */
if(psSyncData->ui32ReadOpsPending != psSyncData->ui32ReadOpsComplete)
{
- return -1;
+ return -1;/* failure */
}
-
+ /* take a write-lock on the new buffer to capture to */
psSyncData->ui32WriteOpsPending++;
}
psBufferInfo->ui32ByteStride);
break;
}
- case PVRSRV_PIXEL_FORMAT_I420:
+ case PVRSRV_PIXEL_FORMAT_YV12:
{
- FillI420Image(psBuffer->sCPUVAddr,
+ FillYV12Image(psBuffer->sCPUVAddr,
psBufferInfo->ui32Width,
psBufferInfo->ui32Height,
psBufferInfo->ui32ByteStride);
}
}
-
+ /* unlock the buffer, signalling the writes are complete */
if(psSyncData)
{
psSyncData->ui32WriteOpsComplete++;
}
+/*!
+******************************************************************************
+
+ @Function GetBufferCount
+
+ @Description
+
+ returns buffer count
+
+ @Output pulBufferCount - buffer count
+
+ @Return 0 - success, -1 - failure
+
+******************************************************************************/
int GetBufferCount(unsigned int *puiBufferCount)
{
BC_EXAMPLE_DEVINFO *psDevInfo = GetAnchorPtr();
-
+ /* check DevInfo has been setup */
if(psDevInfo == IMG_NULL)
{
- return -1;
+ return -1;/* failure */
}
-
+ /* return buffer count */
*puiBufferCount = (unsigned int)psDevInfo->sBufferInfo.ui32BufferCount;
return 0;
+/******************************************************************************
+
+ @Function ReconfigureBuffer
+
+ @Description
+
+ returns whether reconfiguration succeeds or not
+
+ @Output uiSucceed : 1 - succeeded, 0 - failed
+
+ @Return 0 - success, -1 - failure
+
+******************************************************************************/
int ReconfigureBuffer(unsigned int *uiSucceed)
{
BCE_ERROR eError;
-
+ /* Destroy the shared buffers of the current buffer class device */
eError = BC_Example_Buffers_Destroy();
if (eError != BCE_OK)
return -1;
}
-
+ /* No need to un-register and then re-register the device with services module srvkm */
-
+ /* Recreate shared buffers with reconfigured parameters */
eError = BC_Example_Buffers_Create();
if (eError != BCE_OK)
return -1;
}
-
+ /* return uiSucceed as succeeded 1 */
*uiSucceed = 1;
return 0;
}
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Bufferclass example internal interfaces.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _BUFFERCLASS_EXAMPLE_PRIVATE_H_
#define _BUFFERCLASS_EXAMPLE_PRIVATE_H_
int GetBufferCount(unsigned int *puiBufferCount);
int ReconfigureBuffer(unsigned int *uiSucceed);
-#endif
+#endif /* _BUFFERCLASS_EXAMPLE_PRIVATE_H_ */
#define DEVNAME "bccat"
#define DRVNAME DEVNAME
-#define DEVICE_COUNT 1
+#define DEVICE_COUNT 10
#define BC_EXAMPLE_NUM_BUFFERS 3
#define BUFFERCLASS_DEVICE_NAME "Example Bufferclass Device (SW)"
return -EINVAL;
switch (p->fourcc) {
+ case BC_PIX_FMT_YV12:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_YV12;
+ stride = p->width;
+ break;
+ case BC_PIX_FMT_I420:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_I420;
+ stride = p->width;
+ break;
+
case BC_PIX_FMT_NV12:
pixel_fmt = PVRSRV_PIXEL_FORMAT_NV12;
stride = p->width;
if (pixel_fmt == PVRSRV_PIXEL_FORMAT_NV12)
ulSize += (stride >> 1) * (p->height >> 1) << 1;
+ if ((pixel_fmt == PVRSRV_PIXEL_FORMAT_I420) || (pixel_fmt == PVRSRV_PIXEL_FORMAT_YV12) )
+ {
+ ulSize += (stride >> 1) * (p->height >> 1);
+ ulSize += (stride >> 1) * (p->height >> 1);
+ }
+
for (i=0; i < p->count; i++) {
if (psDevInfo->buf_type == BC_MEMORY_MMAP) {
#ifdef PLAT_TI8168
width_align = 8;
#else
- width_align = cpu_is_omap3530() && ( omap_rev() < OMAP3430_REV_ES3_0 ) ? 32 : 8;
+ width_align = 8;
+ //width_align = cpu_is_omap3530() && ( omap_rev() < OMAP3430_REV_ES3_0 ) ? 32 : 8;
#endif
major = register_chrdev(0, DEVNAME, &bc_cat_fops);
#define BC_FOURCC(a,b,c,d) \
((unsigned long) ((a) | (b)<<8 | (c)<<16 | (d)<<24))
+#define BC_PIX_FMT_I420 BC_FOURCC('I', '4', '2', '0') /*YUV 4:2:0*/
+#define BC_PIX_FMT_YV12 BC_FOURCC('Y', 'V', '1', '2') /*YUV 4:2:0*/
#define BC_PIX_FMT_NV12 BC_FOURCC('N', 'V', '1', '2') /*YUV 4:2:0*/
#define BC_PIX_FMT_UYVY BC_FOURCC('U', 'Y', 'V', 'Y') /*YUV 4:2:2*/
#define BC_PIX_FMT_YUYV BC_FOURCC('Y', 'U', 'Y', 'V') /*YUV 4:2:2*/
-/**********************************************************************
- *
- * Copyright(c) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OMAP Linux display driver shared DRM structures
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OMAP Linux display driver DRM structures shared between
+ kernel and user space.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __3RDPARTY_DC_DRM_SHARED_H__
#define __3RDPARTY_DC_DRM_SHARED_H__
#if defined(SUPPORT_DRI_DRM)
#define PVR_DRM_DISP_ARG_DEV 1
#define PVR_DRM_DISP_NUM_ARGS 2
-#endif
-#endif
+#endif /* defined(SUPPORT_DRI_DRM) */
+#endif /* __3RDPARTY_DC_DRM_SHARED_H__ */
+/******************************************************************************
+ End of file (3rdparty_dc_drm_shared.h)
+******************************************************************************/
--- /dev/null
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
+#
+# The contents of this file are subject to the MIT license as set out below.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
+#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+### ###########################################################################
+
+ccflags-y += \
+ -I$(TOP)/services4/3rdparty/dc_omapfb3_linux \
+ -I$(KERNELDIR)/drivers/video/omap2 \
+ -I$(KERNELDIR)/arch/arm/plat-omap/include
+
+omaplfb-y += \
+ services4/3rdparty/dc_omapfb3_linux/omaplfb_displayclass.o \
+ services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.o
--- /dev/null
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
+#
+# The contents of this file are subject to the MIT license as set out below.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
+#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+### ###########################################################################
+
+modules := dc_omapfb3_linux
+
+dc_omapfb3_linux_type := kernel_module
+dc_omapfb3_linux_target := omaplfb.ko
+dc_omapfb3_linux_makefile := $(THIS_DIR)/Kbuild.mk
+++ /dev/null
-#
-# Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
-#
-#
-
-MODULE = $(DISPLAY_CONTROLLER)
-
-INCLUDES =
-
-SOURCES =
-
-SYM_VERS_DEPS = $(EURASIAROOT)/services4/srvkm/env/linux
-
-include $(EURASIAROOT)/services4/$(DISPLAY_CONTROLLER_DIR)/makefile.linux.common
-
-include $(EURASIAROOT)/eurasiacon/build/linux/kbuild/Makefile.kbuild_subdir_common
+++ /dev/null
-#
-# Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
-#
-#
-#
-
-ifeq ($(SUPPORT_DRI_DRM),1)
-DISPLAY_CONTROLLER_SOURCES_ROOT = $(KBUILDROOT)/$(DISPLAY_CONTROLLER_DIR)
-MODULE_CFLAGS += -DPVR_DISPLAY_CONTROLLER_DRM_IOCTL
-else
-DISPLAY_CONTROLLER_SOURCES_ROOT = ..
-endif
-
-INCLUDES += -I$(EURASIAROOT)/include4 \
- -I$(EURASIAROOT)/services4/include \
- -I$(EURASIAROOT)/services4/system/$(PVR_SYSTEM) \
- -I$(EURASIAROOT)/services4/system/include \
- -I$(KERNELDIR)/drivers/video/omap2 \
- -I$(KERNELDIR)/arch/arm/plat-omap/include
-
-SOURCES += $(DISPLAY_CONTROLLER_SOURCES_ROOT)/omaplfb_displayclass.c \
- $(DISPLAY_CONTROLLER_SOURCES_ROOT)/omaplfb_linux.c
-/**********************************************************************
- *
- * Copyright(c) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title OMAP Linux display driver structures and prototypes
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __OMAPLFB_H__
#define __OMAPLFB_H__
#include <linux/earlysuspend.h>
#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+#define OMAPLFB_CONSOLE_LOCK() console_lock()
+#define OMAPLFB_CONSOLE_UNLOCK() console_unlock()
+#else
+#define OMAPLFB_CONSOLE_LOCK() acquire_console_sem()
+#define OMAPLFB_CONSOLE_UNLOCK() release_console_sem()
+#endif
+
#define unref__ __attribute__ ((unused))
typedef void * OMAPLFB_HANDLE;
typedef atomic_t OMAPLFB_ATOMIC_INT;
+/* OMAPLFB buffer structure */
typedef struct OMAPLFB_BUFFER_TAG
{
struct OMAPLFB_BUFFER_TAG *psNext;
struct work_struct sWork;
-
+ /* Position of this buffer in the virtual framebuffer */
unsigned long ulYOffset;
-
-
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
IMG_SYS_PHYADDR sSysAddr;
IMG_CPU_VIRTADDR sCPUVAddr;
PVRSRV_SYNC_DATA *psSyncData;
unsigned long ulSwapInterval;
} OMAPLFB_BUFFER;
+/* OMAPLFB swapchain structure */
typedef struct OMAPLFB_SWAPCHAIN_TAG
{
-
+ /* Swap chain ID */
unsigned int uiSwapChainID;
-
+ /* number of buffers in swapchain */
unsigned long ulBufferCount;
-
+ /* list of buffers in the swapchain */
OMAPLFB_BUFFER *psBuffer;
-
+ /* Swap chain work queue */
struct workqueue_struct *psWorkQueue;
-
+ /*
+ * Set if we didn't manage to wait for VSync on last swap,
+ * or if we think we need to wait for VSync on the next flip.
+ * The flag helps to avoid jitter when the screen is
+ * unblanked, by forcing an extended wait for VSync before
+ * attempting the next flip.
+ */
OMAPLFB_BOOL bNotVSynced;
-
+ /* Previous number of blank events */
int iBlankEvents;
-
+ /* Framebuffer Device ID for messages (e.g. printk) */
unsigned int uiFBDevID;
} OMAPLFB_SWAPCHAIN;
unsigned long ulPhysicalWidthmm;
unsigned long ulPhysicalHeightmm;
-
-
- IMG_SYS_PHYADDR sSysAddr;
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
+ IMG_SYS_PHYADDR sSysAddr;//system physical address
IMG_CPU_VIRTADDR sCPUVAddr;
-
+ /* pixelformat of system/primary surface */
PVRSRV_PIXEL_FORMAT ePixelFormat;
-}OMAPLFB_FBINFO;
+#if defined(CONFIG_DSSCOMP)
+ OMAPLFB_BOOL bIs2D;
+ IMG_SYS_PHYADDR *psPageList;
+ struct ion_handle *psIONHandle;
+ IMG_UINT32 uiBytesPerPixel;
+#endif
+} OMAPLFB_FBINFO;
+
+/* kernel device information structure */
typedef struct OMAPLFB_DEVINFO_TAG
{
-
+ /* Framebuffer Device ID */
unsigned int uiFBDevID;
-
+ /* PVR Device ID */
unsigned int uiPVRDevID;
-
+ /* Swapchain create/destroy mutex */
struct mutex sCreateSwapChainMutex;
-
+ /* system surface info */
OMAPLFB_BUFFER sSystemBuffer;
-
+ /* jump table into PVR services */
PVRSRV_DC_DISP2SRV_KMJTABLE sPVRJTable;
-
+ /* jump table into DC */
PVRSRV_DC_SRV2DISP_KMJTABLE sDCJTable;
-
+ /* fb info structure */
OMAPLFB_FBINFO sFBInfo;
-
+ /* Only one swapchain supported by this device so hang it here */
OMAPLFB_SWAPCHAIN *psSwapChain;
-
+ /* Swap chain ID */
unsigned int uiSwapChainID;
-
+ /* True if PVR Services is flushing its command queues */
OMAPLFB_ATOMIC_BOOL sFlushCommands;
-
+ /* pointer to linux frame buffer information structure */
struct fb_info *psLINFBInfo;
-
+ /* Linux Framebuffer event notification block */
struct notifier_block sLINNotifBlock;
-
-
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
-
+ /* Address of the surface being displayed */
IMG_DEV_VIRTADDR sDisplayDevVAddr;
DISPLAY_INFO sDisplayInfo;
-
+ /* Display format */
DISPLAY_FORMAT sDisplayFormat;
-
+ /* Display dimensions */
DISPLAY_DIMS sDisplayDim;
-
+ /* True if screen is blanked */
OMAPLFB_ATOMIC_BOOL sBlanked;
-
+ /* Number of blank/unblank events */
OMAPLFB_ATOMIC_INT sBlankEvents;
#ifdef CONFIG_HAS_EARLYSUSPEND
-
+ /* Set by early suspend */
OMAPLFB_ATOMIC_BOOL sEarlySuspendFlag;
struct early_suspend sEarlySuspend;
#define OMAPLFB_PAGE_SIZE 4096
+/* DEBUG only printk */
#ifdef DEBUG
#define DEBUG_PRINTK(x) printk x
#else
#define DEVNAME DRVNAME
#define DRIVER_PREFIX DRVNAME
+/*!
+ *****************************************************************************
+ * Error values
+ *****************************************************************************/
typedef enum _OMAPLFB_ERROR_
{
OMAPLFB_OK = 0,
OMAPLFB_ERROR OMAPLFBInit(void);
OMAPLFB_ERROR OMAPLFBDeInit(void);
+/* OS Specific APIs */
OMAPLFB_DEVINFO *OMAPLFBGetDevInfoPtr(unsigned uiFBDevID);
unsigned OMAPLFBMaxFBDevIDPlusOne(void);
void *OMAPLFBAllocKernelMem(unsigned long ulSize);
int OMAPLFBAtomicIntRead(OMAPLFB_ATOMIC_INT *psAtomic);
void OMAPLFBAtomicIntInc(OMAPLFB_ATOMIC_INT *psAtomic);
-#endif
+#if defined(DEBUG)
+void OMAPLFBPrintInfo(OMAPLFB_DEVINFO *psDevInfo);
+#else
+#define OMAPLFBPrintInfo(psDevInfo)
+#endif
+
+#endif /* __OMAPLFB_H__ */
+
+/******************************************************************************
+ End of file (omaplfb.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright(c) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OMAP common display driver components
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
+/**************************************************************************
+ The 3rd party driver is a specification of an API to integrate the IMG POWERVR
+ Services driver with 3rd Party display hardware. It is NOT a specification for
+ a display controller driver, rather a specification to extend the API for a
+ pre-existing driver for the display hardware.
+
+ The 3rd party driver interface provides IMG POWERVR client drivers (e.g. PVR2D)
+ with an API abstraction of the system's underlying display hardware, allowing
+ the client drivers to indirectly control the display hardware and access its
+ associated memory.
+
+ Functions of the API include
+ - query primary surface attributes (width, height, stride, pixel format, CPU
+ physical and virtual address)
+ - swap/flip chain creation and subsequent query of surface attributes
+ - asynchronous display surface flipping, taking account of asynchronous read
+ (flip) and write (render) operations to the display surface
+
+ Note: having queried surface attributes the client drivers are able to map the
+ display memory to any IMG POWERVR Services device by calling
+ PVRSRVMapDeviceClassMemory with the display surface handle.
+
+ This code is intended to be an example of how a pre-existing display driver may
+ be extended to support the 3rd Party Display interface to POWERVR Services
+ - IMG is not providing a display driver implementation.
+ **************************************************************************/
+
+/*
+ * OMAP Linux 3rd party display driver.
+ * This is based on the Generic PVR Linux Framebuffer 3rd party display
+ * driver, with OMAP specific extensions to support flipping.
+ */
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/notifier.h>
+/* IMG services headers */
#include "img_defs.h"
#include "servicesext.h"
#include "kerneldisplay.h"
#include "omaplfb.h"
+#if defined(CONFIG_DSSCOMP)
+
+#if !defined(CONFIG_ION_OMAP)
+#error CONFIG_DSSCOMP support requires CONFIG_ION_OMAP
+#endif
+
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+
+extern struct ion_client *gpsIONClient;
+
+#include <mach/tiler.h>
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+
+#endif /* defined(CONFIG_DSSCOMP) */
+
#define OMAPLFB_COMMAND_COUNT 1
#define OMAPLFB_VSYNC_SETTLE_COUNT 5
//#define OMAPLFB_MAX_NUM_DEVICES FB_MAX
-#define OMAPLFB_MAX_NUM_DEVICES 1
-
+#define OMAPLFB_MAX_NUM_DEVICES 1
#if (OMAPLFB_MAX_NUM_DEVICES > FB_MAX)
#error "OMAPLFB_MAX_NUM_DEVICES must not be greater than FB_MAX"
#endif
static OMAPLFB_DEVINFO *gapsDevInfo[OMAPLFB_MAX_NUM_DEVICES];
+/* Top level 'hook ptr' */
static PFN_DC_GET_PVRJTABLE gpfnGetPVRJTable = NULL;
+/* Round x up to a multiple of y */
static inline unsigned long RoundUpToMultiple(unsigned long x, unsigned long y)
{
unsigned long div = x / y;
return (div + ((rem == 0) ? 0 : 1)) * y;
}
+/* Greatest common divisor of x and y */
static unsigned long GCD(unsigned long x, unsigned long y)
{
while (y != 0)
return x;
}
+/* Least common multiple of x and y */
static unsigned long LCM(unsigned long x, unsigned long y)
{
unsigned long gcd = GCD(x, y);
return OMAPLFB_MAX_NUM_DEVICES;
}
+/* Returns DevInfo pointer for a given device */
OMAPLFB_DEVINFO *OMAPLFBGetDevInfoPtr(unsigned uiFBDevID)
{
WARN_ON(uiFBDevID >= OMAPLFBMaxFBDevIDPlusOne());
return gapsDevInfo[uiFBDevID];
}
+/* Sets the DevInfo pointer for a given device */
static inline void OMAPLFBSetDevInfoPtr(unsigned uiFBDevID, OMAPLFB_DEVINFO *psDevInfo)
{
WARN_ON(uiFBDevID >= OMAPLFB_MAX_NUM_DEVICES);
(psDevInfo->uiSwapChainID != psSwapChain->uiSwapChainID);
}
+/* Don't wait for vertical sync */
static inline OMAPLFB_BOOL DontWaitForVSync(OMAPLFB_DEVINFO *psDevInfo)
{
OMAPLFB_BOOL bDontWait;
return bDontWait;
}
+/*
+ * SetDCState
+ * Called from services.
+ */
static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
{
OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)hDevice;
case DC_STATE_NO_FLUSH_COMMANDS:
OMAPLFBAtomicBoolSet(&psDevInfo->sFlushCommands, OMAPLFB_FALSE);
break;
+ case DC_STATE_FORCE_SWAP_TO_SYSTEM:
+ OMAPLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer);
+ break;
default:
break;
}
}
+/*
+ * OpenDCDevice
+ * Called from services.
+ */
static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 uiPVRDevID,
IMG_HANDLE *phDevice,
PVRSRV_SYNC_DATA* psSystemBufferSyncData)
return PVRSRV_ERROR_INVALID_DEVICE;
}
-
+ /* store the system surface sync data */
psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
eError = OMAPLFBUnblankDisplay(psDevInfo);
return PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED;
}
-
+ /* return handle to the devinfo */
*phDevice = (IMG_HANDLE)psDevInfo;
return PVRSRV_OK;
}
+/*
+ * CloseDCDevice
+ * Called from services.
+ */
static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
{
#if defined(SUPPORT_DRI_DRM)
return PVRSRV_OK;
}
+/*
+ * EnumDCFormats
+ * Called from services.
+ */
static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
IMG_UINT32 *pui32NumFormats,
DISPLAY_FORMAT *psFormat)
return PVRSRV_OK;
}
+/*
+ * EnumDCDims
+ * Called from services.
+ */
static PVRSRV_ERROR EnumDCDims(IMG_HANDLE hDevice,
DISPLAY_FORMAT *psFormat,
IMG_UINT32 *pui32NumDims,
*pui32NumDims = 1;
-
+ /* No need to look at psFormat; there is only one */
if(psDim)
{
psDim[0] = psDevInfo->sDisplayDim;
}
+/*
+ * GetDCSystemBuffer
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE hDevice, IMG_HANDLE *phBuffer)
{
OMAPLFB_DEVINFO *psDevInfo;
}
+/*
+ * GetDCInfo
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCInfo(IMG_HANDLE hDevice, DISPLAY_INFO *psDCInfo)
{
OMAPLFB_DEVINFO *psDevInfo;
return PVRSRV_OK;
}
+/*
+ * GetDCBufferAddr
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE hDevice,
IMG_HANDLE hBuffer,
IMG_SYS_PHYADDR **ppsSysAddr,
if (ppvCpuVAddr)
{
+#if defined(CONFIG_DSSCOMP)
+ *ppvCpuVAddr = psDevInfo->sFBInfo.bIs2D ? NULL : psSystemBuffer->sCPUVAddr;
+#else
*ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
+#endif
}
if (phOSMapInfo)
if (pbIsContiguous)
{
+#if defined(CONFIG_DSSCOMP)
+ *pbIsContiguous = !psDevInfo->sFBInfo.bIs2D;
+#else
*pbIsContiguous = IMG_TRUE;
+#endif
}
+#if defined(CONFIG_DSSCOMP)
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ int i = (psSystemBuffer->sSysAddr.uiAddr - psDevInfo->sFBInfo.psPageList->uiAddr) >> PAGE_SHIFT;
+ *ppsSysAddr = psDevInfo->sFBInfo.psPageList + psDevInfo->sFBInfo.ulHeight * i;
+ }
+#endif
+
return PVRSRV_OK;
}
+/*
+ * CreateDCSwapChain
+ * Called from services.
+ */
static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
IMG_UINT32 ui32Flags,
DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
UNREFERENCED_PARAMETER(ui32OEMFlags);
+ /* Check parameters */
if(!hDevice
|| !psDstSurfAttrib
|| !psSrcSurfAttrib
psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
-
+ /* Do we support swap chains? */
if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
{
return PVRSRV_ERROR_NOT_SUPPORTED;
OMAPLFBCreateSwapChainLock(psDevInfo);
-
+ /* The driver only supports a single swapchain */
if(psDevInfo->psSwapChain != NULL)
{
eError = PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
goto ExitUnLock;
}
-
+ /* Check the buffer count */
if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
{
eError = PVRSRV_ERROR_TOOMANYBUFFERS;
goto ExitUnLock;
}
-
+ /*
+ * We will allocate the swap chain buffers at the back of the frame
+ * buffer area. This preserves the front portion, which may be being
+ * used by other Linux Framebuffer based applications.
+ */
ui32BuffersToSkip = psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers - ui32BufferCount;
-
+ /*
+ * Verify the DST/SRC attributes,
+ * SRC/DST must match the current display mode config
+ */
if(psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat
|| psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride
|| psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width
|| psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height)
{
-
+ /* DST doesn't match the current mode */
eError = PVRSRV_ERROR_INVALID_PARAMS;
goto ExitUnLock;
}
|| psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width
|| psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height)
{
-
+ /* DST doesn't match the SRC */
eError = PVRSRV_ERROR_INVALID_PARAMS;
goto ExitUnLock;
}
-
+ /* check flags if implementation requires them */
UNREFERENCED_PARAMETER(ui32Flags);
#if defined(PVR_OMAPFB3_UPDATE_MODE)
printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set frame buffer update mode %d\n", __FUNCTION__, psDevInfo->uiFBDevID, PVR_OMAPFB3_UPDATE_MODE);
}
#endif
-
+ /* create a swapchain structure */
psSwapChain = (OMAPLFB_SWAPCHAIN*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_SWAPCHAIN));
if(!psSwapChain)
{
psSwapChain->bNotVSynced = OMAPLFB_TRUE;
psSwapChain->uiFBDevID = psDevInfo->uiFBDevID;
-
+ /* Link the buffers */
for(i=0; i<ui32BufferCount-1; i++)
{
psBuffer[i].psNext = &psBuffer[i+1];
}
-
+ /* and link last to first */
psBuffer[i].psNext = &psBuffer[0];
-
+ /* Configure the swapchain buffers */
for(i=0; i<ui32BufferCount; i++)
{
IMG_UINT32 ui32SwapBuffer = i + ui32BuffersToSkip;
IMG_UINT32 ui32BufferOffset = ui32SwapBuffer * (IMG_UINT32)psDevInfo->sFBInfo.ulRoundedBufferSize;
+#if defined(CONFIG_DSSCOMP)
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ ui32BufferOffset = 0;
+ }
+#endif /* defined(CONFIG_DSSCOMP) */
+
psBuffer[i].psSyncData = ppsSyncData[i];
psBuffer[i].sSysAddr.uiAddr = psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
psBuffer[i].ulYOffset = ui32BufferOffset / psDevInfo->sFBInfo.ulByteStride;
psBuffer[i].psDevInfo = psDevInfo;
+#if defined(CONFIG_DSSCOMP)
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ psBuffer[i].sSysAddr.uiAddr += ui32SwapBuffer *
+ ALIGN((IMG_UINT32)psDevInfo->sFBInfo.ulWidth * psDevInfo->sFBInfo.uiBytesPerPixel, PAGE_SIZE);
+ }
+#endif /* defined(CONFIG_DSSCOMP) */
+
OMAPLFBInitBufferForSwap(&psBuffer[i]);
}
return eError;
}
+/*
+ * DestroyDCSwapChain
+ * Called from services.
+ */
static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain)
{
OMAPLFB_SWAPCHAIN *psSwapChain;
OMAPLFB_ERROR eError;
-
+ /* Check parameters */
if(!hDevice || !hSwapChain)
{
return PVRSRV_ERROR_INVALID_PARAMS;
goto ExitUnLock;
}
-
+ /* The swap queue is flushed before being destroyed */
OMAPLFBDestroySwapQueue(psSwapChain);
eError = OMAPLFBDisableLFBEventNotification(psDevInfo);
printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't disable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID);
}
-
+ /* Free resources */
OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
OMAPLFBFreeKernelMem(psSwapChain);
return eError;
}
+/*
+ * SetDCDstRect
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_RECT *psRect)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(psRect);
-
+ /* Only full display swapchains on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * SetDCSrcRect
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_RECT *psRect)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(psRect);
-
+ /* Only full display swapchains on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * SetDCDstColourKey
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_UINT32 ui32CKColour)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(ui32CKColour);
-
+ /* Don't support DST CK on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * SetDCSrcColourKey
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_UINT32 ui32CKColour)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(ui32CKColour);
-
+ /* Don't support SRC CK on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * GetDCBuffers
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_UINT32 *pui32BufferCount,
PVRSRV_ERROR eError;
unsigned i;
-
+ /* Check parameters */
if(!hDevice
|| !hSwapChain
|| !pui32BufferCount
goto Exit;
}
-
+ /* Return the buffer count */
*pui32BufferCount = (IMG_UINT32)psSwapChain->ulBufferCount;
-
+ /* Return the buffers */
for(i=0; i<psSwapChain->ulBufferCount; i++)
{
phBuffer[i] = (IMG_HANDLE)&psSwapChain->psBuffer[i];
return eError;
}
+/*
+ * SwapToDCBuffer
+ * Called from services.
+ */
static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE hDevice,
IMG_HANDLE hBuffer,
IMG_UINT32 ui32SwapInterval,
UNREFERENCED_PARAMETER(ui32ClipRectCount);
UNREFERENCED_PARAMETER(psClipRect);
-
+ /* * Nothing to do since Services common code does the work */
return PVRSRV_OK;
}
-static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE hDevice,
- IMG_HANDLE hSwapChain)
-{
- UNREFERENCED_PARAMETER(hDevice);
- UNREFERENCED_PARAMETER(hSwapChain);
-
-
- return PVRSRV_OK;
-}
-
+/*
+ * Called after the screen has unblanked, or after any other occasion
+ * when we didn't wait for vsync, but now need to. Not doing this after
+ * unblank leads to screen jitter on some screens.
+ * Returns true if the screen has been deemed to have settled.
+ */
static OMAPLFB_BOOL WaitForVSyncSettle(OMAPLFB_DEVINFO *psDevInfo)
{
unsigned i;
return OMAPLFB_TRUE;
}
+/*
+ * Swap handler.
+ * Called from the swap chain work queue handler.
+ * There is no need to take the swap chain creation lock in here, or use
+ * some other method of stopping the swap chain from being destroyed.
+ * This is because the swap chain creation lock is taken when queueing work,
+ * and the work queue is flushed before the swap chain is destroyed.
+ */
void OMAPLFBSwapHandler(OMAPLFB_BUFFER *psBuffer)
{
OMAPLFB_DEVINFO *psDevInfo = psBuffer->psDevInfo;
OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
OMAPLFB_BOOL bPreviouslyNotVSynced;
+
#if defined(SUPPORT_DRI_DRM)
if (!OMAPLFBAtomicBoolRead(&psDevInfo->sLeaveVT))
#endif
break;
}
}
+
psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psBuffer->hCmdComplete, IMG_TRUE);
}
+/* Triggered by PVRSRVSwapToDCBuffer */
+static IMG_BOOL ProcessFlipV1(IMG_HANDLE hCmdCookie,
+ OMAPLFB_DEVINFO *psDevInfo,
+ OMAPLFB_SWAPCHAIN *psSwapChain,
+ OMAPLFB_BUFFER *psBuffer,
+ unsigned long ulSwapInterval)
+{
+ OMAPLFBCreateSwapChainLock(psDevInfo);
+
+ /* The swap chain has been destroyed */
+ if (SwapChainHasChanged(psDevInfo, psSwapChain))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
+ ": %s: Device %u (PVR Device ID %u): The swap chain has been destroyed\n",
+ __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
+ }
+ else
+ {
+ psBuffer->hCmdComplete = (OMAPLFB_HANDLE)hCmdCookie;
+ psBuffer->ulSwapInterval = ulSwapInterval;
+#if defined(CONFIG_DSSCOMP)
+ if (is_tiler_addr(psBuffer->sSysAddr.uiAddr))
+ {
+ IMG_UINT32 w = psBuffer->psDevInfo->sDisplayDim.ui32Width;
+ IMG_UINT32 h = psBuffer->psDevInfo->sDisplayDim.ui32Height;
+ struct dsscomp_setup_dispc_data comp = {
+ .num_mgrs = 1,
+ .mgrs[0].alpha_blending = 1,
+ .num_ovls = 1,
+ .ovls[0].cfg =
+ {
+ .width = w,
+ .win.w = w,
+ .crop.w = w,
+ .height = h,
+ .win.h = h,
+ .crop.h = h,
+ .stride = psBuffer->psDevInfo->sDisplayDim.ui32ByteStride,
+ .color_mode = OMAP_DSS_COLOR_ARGB32,
+ .enabled = 1,
+ .global_alpha = 255,
+ },
+ .mode = DSSCOMP_SETUP_DISPLAY,
+ };
+ struct tiler_pa_info *pas[1] = { NULL };
+ comp.ovls[0].ba = (u32) psBuffer->sSysAddr.uiAddr;
+ dsscomp_gralloc_queue(&comp, pas, true,
+ (void *) psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete,
+ (void *) psBuffer->hCmdComplete);
+ }
+ else
+#endif /* defined(CONFIG_DSSCOMP) */
+ {
+ OMAPLFBQueueBufferForSwap(psSwapChain, psBuffer);
+ }
+ }
+
+ OMAPLFBCreateSwapChainUnLock(psDevInfo);
+
+ return IMG_TRUE;
+}
+
+#if defined(CONFIG_DSSCOMP)
+
+/* Triggered by PVRSRVSwapToDCBuffer2 */
+static IMG_BOOL ProcessFlipV2(IMG_HANDLE hCmdCookie,
+ OMAPLFB_DEVINFO *psDevInfo,
+ PDC_MEM_INFO *ppsMemInfos,
+ IMG_UINT32 ui32NumMemInfos,
+ struct dsscomp_setup_dispc_data *psDssData,
+ IMG_UINT32 ui32DssDataLength)
+{
+ struct tiler_pa_info *apsTilerPAs[5];
+ IMG_UINT32 i, k;
+
+ if(ui32DssDataLength != sizeof(*psDssData))
+ {
+ WARN(1, "invalid size of private data (%d vs %d)",
+ ui32DssDataLength, sizeof(*psDssData));
+ return IMG_FALSE;
+ }
+
+ if(psDssData->num_ovls == 0 || ui32NumMemInfos == 0)
+ {
+ WARN(1, "must have at least one layer");
+ return IMG_FALSE;
+ }
+
+ for(i = k = 0; i < ui32NumMemInfos && k < ARRAY_SIZE(apsTilerPAs); i++, k++)
+ {
+ struct tiler_pa_info *psTilerInfo;
+ IMG_CPU_VIRTADDR virtAddr;
+ IMG_CPU_PHYADDR phyAddr;
+ IMG_UINT32 ui32NumPages;
+ IMG_SIZE_T uByteSize;
+ int j;
+
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetByteSize(ppsMemInfos[i], &uByteSize);
+ ui32NumPages = (uByteSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ apsTilerPAs[k] = NULL;
+
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], 0, &phyAddr);
+
+ /* NV12 buffers are already mapped to tiler */
+ if(psDssData->ovls[k].cfg.color_mode == OMAP_DSS_COLOR_NV12)
+ {
+ psDssData->ovls[k].ba = (u32)phyAddr.uiAddr;
+
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], (uByteSize * 2) / 3, &phyAddr);
+ psDssData->ovls[k].uv = (u32)phyAddr.uiAddr;
+ continue;
+ }
+
+ /* Other kinds of buffer may also already be mapped to tiler */
+ if(is_tiler_addr((u32)phyAddr.uiAddr))
+ {
+ psDssData->ovls[k].ba = (u32)phyAddr.uiAddr;
+ continue;
+ }
+
+ psTilerInfo = kzalloc(sizeof(*psTilerInfo), GFP_KERNEL);
+ if(!psTilerInfo)
+ {
+ continue;
+ }
+
+ psTilerInfo->mem = kzalloc(sizeof(*psTilerInfo->mem) * ui32NumPages, GFP_KERNEL);
+ if(!psTilerInfo->mem)
+ {
+ kfree(psTilerInfo);
+ continue;
+ }
+
+ psTilerInfo->num_pg = ui32NumPages;
+ psTilerInfo->memtype = TILER_MEM_USING;
+
+ for(j = 0; j < ui32NumPages; j++)
+ {
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], j << PAGE_SHIFT, &phyAddr);
+ psTilerInfo->mem[j] = (u32)phyAddr.uiAddr;
+ }
+
+ /* Need base address for in-page offset */
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuVAddr(ppsMemInfos[i], &virtAddr);
+ psDssData->ovls[k].ba = (u32)virtAddr;
+ apsTilerPAs[k] = psTilerInfo;
+ }
+
+ /* Set up cloned layer addresses (but don't duplicate tiler_pas) */
+ for(i = k; i < psDssData->num_ovls && i < ARRAY_SIZE(apsTilerPAs); i++)
+ {
+ unsigned int ix = psDssData->ovls[i].ba;
+ if(ix >= ARRAY_SIZE(apsTilerPAs))
+ {
+ WARN(1, "Invalid clone layer (%u); skipping all cloned layers", ix);
+ psDssData->num_ovls = k;
+ break;
+ }
+ apsTilerPAs[i] = apsTilerPAs[ix];
+ psDssData->ovls[i].ba = psDssData->ovls[ix].ba;
+ psDssData->ovls[i].uv = psDssData->ovls[ix].uv;
+ }
+
+ dsscomp_gralloc_queue(psDssData, apsTilerPAs, false,
+ (void *)psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete,
+ (void *)hCmdCookie);
+
+ for(i = 0; i < k; i++)
+ {
+ tiler_pa_free(apsTilerPAs[i]);
+ }
+
+ return IMG_TRUE;
+}
+
+#endif /* defined(CONFIG_DSSCOMP) */
+
+/* Command processing flip handler function. Called from services. */
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;
-
+ /* Check parameters */
if(!hCmdCookie || !pvData)
{
return IMG_FALSE;
}
-
+ /* Validate data packet */
psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData;
- if (psFlipCmd == IMG_NULL || sizeof(DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
+ if (psFlipCmd == IMG_NULL)
{
return IMG_FALSE;
}
-
psDevInfo = (OMAPLFB_DEVINFO*)psFlipCmd->hExtDevice;
- psBuffer = (OMAPLFB_BUFFER*)psFlipCmd->hExtBuffer;
- psSwapChain = (OMAPLFB_SWAPCHAIN*) psFlipCmd->hExtSwapChain;
- OMAPLFBCreateSwapChainLock(psDevInfo);
-
- if (SwapChainHasChanged(psDevInfo, psSwapChain))
+ if(psFlipCmd->hExtBuffer)
{
-
- DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
- ": %s: Device %u (PVR Device ID %u): The swap chain has been destroyed\n",
- __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
+ return ProcessFlipV1(hCmdCookie,
+ psDevInfo,
+ psFlipCmd->hExtSwapChain,
+ psFlipCmd->hExtBuffer,
+ psFlipCmd->ui32SwapInterval);
}
else
{
- psBuffer->hCmdComplete = (OMAPLFB_HANDLE)hCmdCookie;
- psBuffer->ulSwapInterval = (unsigned long)psFlipCmd->ui32SwapInterval;
-#if defined(NO_HARDWARE)
- psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psBuffer->hCmdComplete, IMG_FALSE);
+#if defined(CONFIG_DSSCOMP)
+ DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd2;
+ psFlipCmd2 = (DISPLAYCLASS_FLIP_COMMAND2 *)pvData;
+ return ProcessFlipV2(hCmdCookie,
+ psDevInfo,
+ psFlipCmd2->ppsMemInfos,
+ psFlipCmd2->ui32NumMemInfos,
+ psFlipCmd2->pvPrivData,
+ psFlipCmd2->ui32PrivDataLength);
#else
- OMAPLFBQueueBufferForSwap(psSwapChain, psBuffer);
+ BUG();
#endif
}
+}
- OMAPLFBCreateSwapChainUnLock(psDevInfo);
+/*!
+******************************************************************************
- return IMG_TRUE;
-}
+ @Function OMAPLFBInitFBDev
+
+ @Description specifies devices in the systems memory map
+
+ @Input psSysData - sys data
+ @Return OMAPLFB_ERROR :
+******************************************************************************/
static OMAPLFB_ERROR OMAPLFBInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
{
struct fb_info *psLINFBInfo;
unsigned long FBSize;
unsigned long ulLCM;
unsigned uiFBDevID = psDevInfo->uiFBDevID;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+
+ OMAPLFB_CONSOLE_LOCK();
psLINFBInfo = registered_fb[uiFBDevID];
if (psLINFBInfo == NULL)
psLINFBInfo->screen_size :
psLINFBInfo->fix.smem_len;
-
+ /*
+ * Try and filter out invalid FB info structures (a problem
+ * seen on some OMAP3 systems).
+ */
if (FBSize == 0 || psLINFBInfo->fix.line_length == 0)
{
eError = OMAPLFB_ERROR_INVALID_DEVICE;
": Device %u: LCM of stride and page size: %lu\n",
psDevInfo->uiFBDevID, ulLCM));
-
+ /* Additional implementation specific information */
+ OMAPLFBPrintInfo(psDevInfo);
+
+#if defined(CONFIG_DSSCOMP)
+ {
+ /* for some reason we need at least 3 buffers in the swap chain */
+ int n = FBSize / RoundUpToMultiple(psLINFBInfo->fix.line_length * psLINFBInfo->var.yres, ulLCM);
+ int res;
+ int i, x, y, w;
+ ion_phys_addr_t phys;
+ size_t size;
+ struct tiler_view_t view;
+
+ struct omap_ion_tiler_alloc_data sAllocData =
+ {
+ /* TILER will align width to 128-bytes */
+ /* however, SGX must have full page width */
+ .w = ALIGN(psLINFBInfo->var.xres, PAGE_SIZE / (psLINFBInfo->var.bits_per_pixel / 8)),
+ .h = psLINFBInfo->var.yres,
+ .fmt = psLINFBInfo->var.bits_per_pixel == 16 ? TILER_PIXEL_FMT_16BIT : TILER_PIXEL_FMT_32BIT,
+ .flags = 0,
+ };
+
+ printk(KERN_DEBUG DRIVER_PREFIX
+ " %s: Device %u: Requesting %d TILER 2D framebuffers\n",
+ __FUNCTION__, uiFBDevID, n);
+
+ /* INTEGRATION_POINT: limit to MAX 3 FBs to save TILER container space */
+ if (n > 3)
+ n = 3;
+
+ sAllocData.w *= n;
+
+ psPVRFBInfo->uiBytesPerPixel = psLINFBInfo->var.bits_per_pixel >> 3;
+ psPVRFBInfo->bIs2D = OMAPLFB_TRUE;
+
+ res = omap_ion_tiler_alloc(gpsIONClient, &sAllocData);
+ psPVRFBInfo->psIONHandle = sAllocData.handle;
+ if (res < 0)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ " %s: Device %u: Could not allocate 2D framebuffer(%d)\n",
+ __FUNCTION__, uiFBDevID, res);
+ goto ErrorModPut;
+ }
+
+ psLINFBInfo->fix.smem_start = ion_phys(gpsIONClient, sAllocData.handle, &phys, &size);
+
+ psPVRFBInfo->sSysAddr.uiAddr = phys;
+ psPVRFBInfo->sCPUVAddr = 0;
+ psPVRFBInfo->ulWidth = psLINFBInfo->var.xres;
+ psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
+
+ psPVRFBInfo->ulByteStride = PAGE_ALIGN(psPVRFBInfo->ulWidth * psPVRFBInfo->uiBytesPerPixel);
+ w = psPVRFBInfo->ulByteStride >> PAGE_SHIFT;
+
+ /* this is an "effective" FB size to get correct number of buffers */
+ psPVRFBInfo->ulFBSize = sAllocData.h * n * psPVRFBInfo->ulByteStride;
+ psPVRFBInfo->psPageList = kzalloc(w * n * psPVRFBInfo->ulHeight * sizeof(*psPVRFBInfo->psPageList), GFP_KERNEL);
+ if (!psPVRFBInfo->psPageList)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Could not allocate page list\n", __FUNCTION__, psDevInfo->uiFBDevID);
+ ion_free(gpsIONClient, sAllocData.handle);
+ goto ErrorModPut;
+ }
+
+ tilview_create(&view, phys, psDevInfo->sFBInfo.ulWidth, psDevInfo->sFBInfo.ulHeight);
+ for(i = 0; i < n; i++)
+ {
+ for(y = 0; y < psDevInfo->sFBInfo.ulHeight; y++)
+ {
+ for(x = 0; x < w; x++)
+ {
+ psPVRFBInfo->psPageList[i * psDevInfo->sFBInfo.ulHeight * w + y * w + x].uiAddr =
+ phys + view.v_inc * y + ((x + i * w) << PAGE_SHIFT);
+ }
+ }
+ }
+ }
+#else /* defined(CONFIG_DSSCOMP) */
+ /* System Surface */
psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
psPVRFBInfo->ulByteStride = psLINFBInfo->fix.line_length;
psPVRFBInfo->ulFBSize = FBSize;
+#endif /* defined(CONFIG_DSSCOMP) */
+
psPVRFBInfo->ulBufferSize = psPVRFBInfo->ulHeight * psPVRFBInfo->ulByteStride;
-
+
+ /* Round the buffer size up to a multiple of the number of pages
+ * and the byte stride.
+ * This is used internally, to ensure buffers start on page
+ * boundaries, for the benefit of PVR Services.
+ */
psPVRFBInfo->ulRoundedBufferSize = RoundUpToMultiple(psPVRFBInfo->ulBufferSize, ulLCM);
if(psLINFBInfo->var.bits_per_pixel == 16)
psDevInfo->sFBInfo.ulPhysicalHeightmm =
((int)psLINFBInfo->var.height > 0) ? psLINFBInfo->var.height : 54;
-
+ /* System Surface */
psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
ErrorModPut:
module_put(psLINFBOwner);
ErrorRelSem:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
return eError;
}
{
struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
struct module *psLINFBOwner;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+
+ OMAPLFB_CONSOLE_LOCK();
+
+#if defined(CONFIG_DSSCOMP)
+ {
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ kfree(psPVRFBInfo->psPageList);
+ if (psPVRFBInfo->psIONHandle)
+ {
+ ion_free(gpsIONClient, psPVRFBInfo->psIONHandle);
+ }
+ }
+#endif /* defined(CONFIG_DSSCOMP) */
psLINFBOwner = psLINFBInfo->fbops->owner;
}
module_put(psLINFBOwner);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+
+ OMAPLFB_CONSOLE_UNLOCK();
}
static OMAPLFB_DEVINFO *OMAPLFBInitDev(unsigned uiFBDevID)
IMG_UINT32 aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
OMAPLFB_DEVINFO *psDevInfo = NULL;
-
+ /* Allocate device info. structure */
psDevInfo = (OMAPLFB_DEVINFO *)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_DEVINFO));
if(psDevInfo == NULL)
goto ErrorExit;
}
-
+ /* Any fields not set will be zero */
memset(psDevInfo, 0, sizeof(OMAPLFB_DEVINFO));
psDevInfo->uiFBDevID = uiFBDevID;
-
+ /* Get the kernel services function table */
if(!(*gpfnGetPVRJTable)(&psDevInfo->sPVRJTable))
{
goto ErrorFreeDevInfo;
}
-#ifdef FBDEV_PRESENT
+ /* Save private fbdev information structure in the dev. info. */
if(OMAPLFBInitFBDev(psDevInfo) != OMAPLFB_OK)
{
-
+ /*
+ * Leave it to OMAPLFBInitFBDev to print an error message, if
+ * required. The function may have failed because
+ * there is no Linux framebuffer device corresponding
+ * to the device ID.
+ */
goto ErrorFreeDevInfo;
}
": Device %u: Maximum number of swap chain buffers: %u\n",
psDevInfo->uiFBDevID, psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
-
+ /* Setup system buffer */
psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
psDevInfo->sSystemBuffer.psDevInfo = psDevInfo;
OMAPLFBInitBufferForSwap(&psDevInfo->sSystemBuffer);
-#else
- psDevInfo->sSystemBuffer.sCPUVAddr = 0x100;
-// psDevInfo->sSystemBuffer.ulBufferSize = 600*3200;
-
- psDevInfo->sDisplayFormat.pixelformat = 20;
- psDevInfo->sFBInfo.ulWidth = 800;
- psDevInfo->sFBInfo.ulHeight = 600;
- psDevInfo->sFBInfo.ulByteStride = 3200;
- psDevInfo->sFBInfo.ulFBSize = 8388608;
- psDevInfo->sFBInfo.ulBufferSize = 600*3200;
-#endif
+ /*
+ Setup the DC Jtable so SRVKM can call into this driver
+ */
psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
- psDevInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem;
psDevInfo->sDCJTable.pfnSetDCState = SetDCState;
-
+ /* Register device with services and retrieve device index */
if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice(
&psDevInfo->sDCJTable,
&psDevInfo->uiPVRDevID) != PVRSRV_OK)
": Device %u: PVR Device ID: %u\n",
psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
-
+ /* Setup private command processing function table ... */
pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
-
- aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
- aui32SyncCountList[DC_FLIP_COMMAND][1] = 2;
-
-
-
-
+ /* ... and associated sync count(s) */
+ aui32SyncCountList[DC_FLIP_COMMAND][0] = 0; /* writes */
+ aui32SyncCountList[DC_FLIP_COMMAND][1] = 10; /* reads */
+ /*
+ Register private command processing functions with
+ the Command Queue Manager and setup the general
+ command complete function in the devinfo.
+ */
if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList(psDevInfo->uiPVRDevID,
&pfnCmdProcList[0],
aui32SyncCountList,
return OMAPLFB_ERROR_INIT_FAILURE;
}
-
+ /*
+ * We search for frame buffer devices backwards, as the last device
+ * registered with PVR Services will be the first device enumerated
+ * by PVR Services.
+ */
for(i = uiMaxFBDevIDPlusOne; i-- != 0;)
{
OMAPLFB_DEVINFO *psDevInfo = OMAPLFBInitDev(i);
if (psDevInfo != NULL)
{
-
+ /* Set the top-level anchor */
OMAPLFBSetDevInfoPtr(psDevInfo->uiFBDevID, psDevInfo);
uiDevicesFound++;
}
return (uiDevicesFound != 0) ? OMAPLFB_OK : OMAPLFB_ERROR_INIT_FAILURE;
}
+/*
+ * OMAPLFBDeInitDev
+ * DeInitialises one device
+ */
static OMAPLFB_BOOL OMAPLFBDeInitDev(OMAPLFB_DEVINFO *psDevInfo)
{
PVRSRV_DC_DISP2SRV_KMJTABLE *psPVRJTable = &psDevInfo->sPVRJTable;
return OMAPLFB_FALSE;
}
-
+ /*
+ * Remove display class device from kernel services device
+ * register.
+ */
if (psPVRJTable->pfnPVRSRVRemoveDCDevice(psDevInfo->uiPVRDevID) != PVRSRV_OK)
{
printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: PVR Device %u: Couldn't remove device from PVR Services\n", __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID);
return OMAPLFB_FALSE;
}
-#ifdef FBDEV_PRESENT
+
OMAPLFBDeInitFBDev(psDevInfo);
-#endif
OMAPLFBSetDevInfoPtr(psDevInfo->uiFBDevID, NULL);
-
+ /* De-allocate data structure */
OMAPLFBFreeKernelMem(psDevInfo);
return OMAPLFB_TRUE;
}
+/*
+ * OMAPLFBDeInit
+ * Deinitialises the display class device component of the FBDev
+ */
OMAPLFB_ERROR OMAPLFBDeInit(void)
{
unsigned uiMaxFBDevIDPlusOne = OMAPLFBMaxFBDevIDPlusOne();
return (bError) ? OMAPLFB_ERROR_INIT_FAILURE : OMAPLFB_OK;
}
+/******************************************************************************
+ End of file (omaplfb_displayclass.c)
+******************************************************************************/
+
-/**********************************************************************
- *
- * Copyright(c) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title OMAP linux display driver components
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
+/**************************************************************************
+ The 3rd party driver is a specification of an API to integrate the IMG POWERVR
+ Services driver with 3rd Party display hardware. It is NOT a specification for
+ a display controller driver, rather a specification to extend the API for a
+ pre-existing driver for the display hardware.
+
+ The 3rd party driver interface provides IMG POWERVR client drivers (e.g. PVR2D)
+ with an API abstraction of the system's underlying display hardware, allowing
+ the client drivers to indirectly control the display hardware and access its
+ associated memory.
+
+ Functions of the API include
+ - query primary surface attributes (width, height, stride, pixel format, CPU
+ physical and virtual address)
+ - swap/flip chain creation and subsequent query of surface attributes
+ - asynchronous display surface flipping, taking account of asynchronous read
+ (flip) and write (render) operations to the display surface
+
+ Note: having queried surface attributes the client drivers are able to map the
+ display memory to any IMG POWERVR Services device by calling
+ PVRSRVMapDeviceClassMemory with the display surface handle.
+
+ This code is intended to be an example of how a pre-existing display driver may
+ be extended to support the 3rd Party Display interface to POWERVR Services
+ - IMG is not providing a display driver implementation.
+ **************************************************************************/
#include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
#ifndef AUTOCONF_INCLUDED
#include <linux/config.h>
#endif
#endif
-
#include <asm/atomic.h>
#if defined(SUPPORT_DRI_DRM)
#include <linux/omapfb.h>
#include <linux/mutex.h>
-//# include <plat/vrfb.h>
+#if defined(PVR_OMAPLFB_DRM_FB)
+#include <plat/display.h>
+#include <linux/omap_gpu.h>
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
+/* OmapZoom.org OMAP3 2.6.29 kernel tree - Needs mach/vrfb.h
+ * OmapZoom.org OMAP3 2.6.32 kernel tree - No additional header required
+ * OmapZoom.org OMAP4 2.6.33 kernel tree - No additional header required
+ * OmapZoom.org OMAP4 2.6.34 kernel tree - Needs plat/vrfb.h
+ * Sholes 2.6.32 kernel tree - Needs plat/vrfb.h
+ */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
#define PVR_OMAPFB3_NEEDS_PLAT_VRFB_H
#endif
#if defined(PVR_OMAPFB3_NEEDS_PLAT_VRFB_H)
-# include <plat/vrfb.h>
+#include <plat/vrfb.h>
#else
-# if defined(PVR_OMAPFB3_NEEDS_MACH_VRFB_H)
-# include <mach/vrfb.h>
-# endif
+#if defined(PVR_OMAPFB3_NEEDS_MACH_VRFB_H)
+#include <mach/vrfb.h>
+#endif
#endif
#if defined(DEBUG)
#define DEBUG PVR_DEBUG
#undef PVR_DEBUG
#endif
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
+
+#if defined(CONFIG_DSSCOMP)
+#include <mach/tiler.h>
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+#endif /* defined(CONFIG_DSSCOMP) */
#include "img_defs.h"
#include "servicesext.h"
MODULE_SUPPORTED_DEVICE(DEVNAME);
+#if !defined(PVR_OMAPLFB_DRM_FB)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
#define OMAP_DSS_DRIVER(drv, dev) struct omap_dss_driver *drv = (dev) != NULL ? (dev)->driver : NULL
#define OMAP_DSS_MANAGER(man, dev) struct omap_overlay_manager *man = (dev) != NULL ? (dev)->manager : NULL
#define OMAP_DSS_MANAGER(man, dev) struct omap_dss_device *man = (dev)
#define WAIT_FOR_VSYNC(man) ((man)->wait_vsync)
#endif
-
+#endif /* !defined(PVR_OMAPLFB_DRM_FB) */
void *OMAPLFBAllocKernelMem(unsigned long ulSize)
{
return (OMAPLFB_ERROR_INVALID_PARAMS);
}
-
+ /* Nothing to do - should be exported from pvrsrv.ko */
*ppfnFuncTable = PVRGetDisplayClassJTable;
return (OMAPLFB_OK);
}
+/* Inset a swap buffer into the swap chain work queue */
void OMAPLFBQueueBufferForSwap(OMAPLFB_SWAPCHAIN *psSwapChain, OMAPLFB_BUFFER *psBuffer)
{
int res = queue_work(psSwapChain->psWorkQueue, &psBuffer->sWork);
}
}
+/* Process an item on a swap chain work queue */
static void WorkQueueHandler(struct work_struct *psWork)
{
OMAPLFB_BUFFER *psBuffer = container_of(psWork, OMAPLFB_BUFFER, sWork);
OMAPLFBSwapHandler(psBuffer);
}
+/* Create a swap chain work queue */
OMAPLFB_ERROR OMAPLFBCreateSwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
{
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34))
- psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
-#else
- psSwapChain->psWorkQueue = create_workqueue(DEVNAME);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ /*
+ * Calling alloc_ordered_workqueue with the WQ_FREEZABLE and
+ * WQ_MEM_RECLAIM flags set, (currently) has the same effect as
+ * calling create_freezable_workqueue. None of the other WQ
+ * flags are valid. Setting WQ_MEM_RECLAIM should allow the
+ * workqueue to continue to service the swap chain in low memory
+ * conditions, preventing the driver from holding on to
+ * resources longer than it needs to.
+ */
+ psSwapChain->psWorkQueue = alloc_ordered_workqueue(DEVNAME, WQ_FREEZEABLE | WQ_MEM_RECLAIM);
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+ psSwapChain->psWorkQueue = create_freezable_workqueue(DEVNAME);
+#else
+ /*
+ * Create a single-threaded, freezable, rt-prio workqueue.
+ * Such workqueues are frozen with user threads when a system
+ * suspends, before driver suspend entry points are called.
+ * This ensures this driver will not call into the Linux
+ * framebuffer driver after the latter is suspended.
+ */
+ psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
+#endif
#endif
if (psSwapChain->psWorkQueue == NULL)
{
- printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: create_singlethreaded_workqueue failed\n", __FUNCTION__, psSwapChain->uiFBDevID);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: Couldn't create workqueue\n", __FUNCTION__, psSwapChain->uiFBDevID);
return (OMAPLFB_ERROR_INIT_FAILURE);
}
return (OMAPLFB_OK);
}
+/* Prepare buffer for insertion into a swap chain work queue */
void OMAPLFBInitBufferForSwap(OMAPLFB_BUFFER *psBuffer)
{
INIT_WORK(&psBuffer->sWork, WorkQueueHandler);
}
+/* Destroy a swap chain work queue */
void OMAPLFBDestroySwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
{
destroy_workqueue(psSwapChain->psWorkQueue);
}
+/* Flip display to given buffer */
void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer)
{
struct fb_var_screeninfo sFBVar;
int res;
unsigned long ulYResVirtual;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+
+ OMAPLFB_CONSOLE_LOCK();
sFBVar = psDevInfo->psLINFBInfo->var;
ulYResVirtual = psBuffer->ulYOffset + sFBVar.yres;
-
+#if defined(CONFIG_DSSCOMP)
+ {
+ /*
+ * If using DSSCOMP, we need to use dsscomp queuing for normal
+ * framebuffer updates, so that previously used overlays get
+ * automatically disabled, and manager gets dirtied. We can
+ * do that because DSSCOMP takes ownership of all pipelines on
+ * a manager.
+ */
+ struct fb_fix_screeninfo sFBFix = psDevInfo->psLINFBInfo->fix;
+ struct dsscomp_setup_dispc_data d =
+ {
+ .num_ovls = 1,
+ .num_mgrs = 1,
+ .mgrs[0].alpha_blending = 1,
+ .ovls[0] =
+ {
+ .cfg =
+ {
+ .win.w = sFBVar.xres,
+ .win.h = sFBVar.yres,
+ .crop.x = sFBVar.xoffset,
+ .crop.y = sFBVar.yoffset,
+ .crop.w = sFBVar.xres,
+ .crop.h = sFBVar.yres,
+ .width = sFBVar.xres_virtual,
+ .height = sFBVar.yres_virtual,
+ .stride = sFBFix.line_length,
+ .enabled = 1,
+ .global_alpha = 255,
+ },
+ },
+ };
+
+ /* do not map buffer into TILER1D as it is contiguous */
+ struct tiler_pa_info *pas[] = { NULL };
+
+ d.ovls[0].ba = sFBFix.smem_start;
+ omapfb_mode_to_dss_mode(&sFBVar, &d.ovls[0].cfg.color_mode);
+
+ res = dsscomp_gralloc_queue(&d, pas, true, NULL, NULL);
+ }
+#else /* defined(CONFIG_DSSCOMP) */
+ /*
+ * PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY should be defined to work
+ * around flipping problems seen with the Taal LCDs on Blaze.
+ * The work around is safe to use with other types of screen on Blaze
+ * (e.g. HDMI) and on other platforms (e.g. Panda board).
+ */
+#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
+ /*
+ * Attempt to change the virtual screen resolution if it is too
+ * small. Note that fb_set_var also pans the display.
+ */
if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
+#endif /* !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) */
{
sFBVar.xres_virtual = sFBVar.xres;
sFBVar.yres_virtual = ulYResVirtual;
res = fb_set_var(psDevInfo->psLINFBInfo, &sFBVar);
if (res != 0)
{
- printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
}
}
+#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
else
{
res = fb_pan_display(psDevInfo->psLINFBInfo, &sFBVar);
if (res != 0)
{
- printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
}
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
+#endif /* !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) */
+#endif /* defined(CONFIG_DSSCOMP) */
+
+ OMAPLFB_CONSOLE_UNLOCK();
+}
+
+#if !defined(PVR_OMAPLFB_DRM_FB) || defined(DEBUG)
+static OMAPLFB_BOOL OMAPLFBValidateDSSUpdateMode(enum omap_dss_update_mode eMode)
+{
+ switch (eMode)
+ {
+ case OMAP_DSS_UPDATE_AUTO:
+ case OMAP_DSS_UPDATE_MANUAL:
+ case OMAP_DSS_UPDATE_DISABLED:
+ return OMAPLFB_TRUE;
+ default:
+ break;
+ }
+
+ return OMAPLFB_FALSE;
+}
+
+static OMAPLFB_UPDATE_MODE OMAPLFBFromDSSUpdateMode(enum omap_dss_update_mode eMode)
+{
+ switch (eMode)
+ {
+ case OMAP_DSS_UPDATE_AUTO:
+ return OMAPLFB_UPDATE_MODE_AUTO;
+ case OMAP_DSS_UPDATE_MANUAL:
+ return OMAPLFB_UPDATE_MODE_MANUAL;
+ case OMAP_DSS_UPDATE_DISABLED:
+ return OMAPLFB_UPDATE_MODE_DISABLED;
+ default:
+ break;
+ }
+
+ return OMAPLFB_UPDATE_MODE_UNDEFINED;
+}
#endif
+
+static OMAPLFB_BOOL OMAPLFBValidateUpdateMode(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return OMAPLFB_TRUE;
+ default:
+ break;
+ }
+
+ return OMAPLFB_FALSE;
+}
+
+static enum omap_dss_update_mode OMAPLFBToDSSUpdateMode(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ return OMAP_DSS_UPDATE_AUTO;
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ return OMAP_DSS_UPDATE_MANUAL;
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return OMAP_DSS_UPDATE_DISABLED;
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+#if defined(DEBUG)
+static const char *OMAPLFBUpdateModeToString(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ return "Auto Update Mode";
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ return "Manual Update Mode";
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return "Update Mode Disabled";
+ case OMAPLFB_UPDATE_MODE_UNDEFINED:
+ return "Update Mode Undefined";
+ default:
+ break;
+ }
+
+ return "Unknown Update Mode";
+}
+
+static const char *OMAPLFBDSSUpdateModeToString(enum omap_dss_update_mode eMode)
+{
+ if (!OMAPLFBValidateDSSUpdateMode(eMode))
+ {
+ return "Unknown Update Mode";
+ }
+
+ return OMAPLFBUpdateModeToString(OMAPLFBFromDSSUpdateMode(eMode));
+}
+
+void OMAPLFBPrintInfo(OMAPLFB_DEVINFO *psDevInfo)
+{
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+ unsigned uConnectors;
+ unsigned uConnector;
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: DRM framebuffer\n", psDevInfo->uiFBDevID));
+
+ for (psConnector = NULL, uConnectors = 0;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ uConnectors++;
+ }
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: Number of screens (DRM connectors): %u\n", psDevInfo->uiFBDevID, uConnectors));
+
+ if (uConnectors == 0)
+ {
+ return;
+ }
+
+ for (psConnector = NULL, uConnector = 0;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL; uConnector++)
+ {
+ enum omap_dss_update_mode eMode = omap_connector_get_update_mode(psConnector);
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: Screen %u: %s (%d)\n", psDevInfo->uiFBDevID, uConnector, OMAPLFBDSSUpdateModeToString(eMode), (int)eMode));
+
+ }
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
+ OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: non-DRM framebuffer\n", psDevInfo->uiFBDevID));
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: %s\n", psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
}
+#endif /* defined(DEBUG) */
+/*
+ * Get display update mode.
+ * If the mode is AUTO, we can wait for VSync, if desired.
+ */
OMAPLFB_UPDATE_MODE OMAPLFBGetUpdateMode(OMAPLFB_DEVINFO *psDevInfo)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+ OMAPLFB_UPDATE_MODE eMode = OMAPLFB_UPDATE_MODE_UNDEFINED;
+
+ /*
+ * There may be multiple displays connected. If at least one
+ * display is manual update mode, report all screens as being
+ * in that mode.
+ */
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ switch(omap_connector_get_update_mode(psConnector))
+ {
+ case OMAP_DSS_UPDATE_MANUAL:
+ eMode = OMAPLFB_UPDATE_MODE_MANUAL;
+ break;
+ case OMAP_DSS_UPDATE_DISABLED:
+ if (eMode == OMAPLFB_UPDATE_MODE_UNDEFINED)
+ {
+ eMode = OMAPLFB_UPDATE_MODE_DISABLED;
+ }
+ break;
+ case OMAP_DSS_UPDATE_AUTO:
+ /* Fall through to default case */
+ default:
+ /* Asssume auto update is possible */
+ if (eMode != OMAPLFB_UPDATE_MODE_MANUAL)
+ {
+ eMode = OMAPLFB_UPDATE_MODE_AUTO;
+ }
+ break;
+ }
+ }
+
+ return eMode;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
- enum omap_dss_update_mode eMode;
OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
- if (psDSSDrv == NULL || psDSSDev == NULL)
- {
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: No DSS device\n", __FUNCTION__, psDevInfo->uiFBDevID));
+
+ enum omap_dss_update_mode eMode;
+
+ if (psDSSDrv == NULL)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No DSS device\n", __FUNCTION__, psDevInfo->uiFBDevID));
return OMAPLFB_UPDATE_MODE_UNDEFINED;
- }
+ }
if (psDSSDrv->get_update_mode == NULL)
{
-// DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Can't get update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
- return OMAPLFB_UPDATE_MODE_AUTO;
+ if (strcmp(psDSSDev->name, "hdmi") == 0)
+ {
+ return OMAPLFB_UPDATE_MODE_AUTO;
+ }
+// DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No get_update_mode function\n", __FUNCTION__, psDevInfo->uiFBDevID));
// return OMAPLFB_UPDATE_MODE_UNDEFINED;
+ return OMAPLFB_UPDATE_MODE_AUTO;
}
eMode = psDSSDrv->get_update_mode(psDSSDev);
- switch(eMode)
+ if (!OMAPLFBValidateDSSUpdateMode(eMode))
{
- case OMAP_DSS_UPDATE_AUTO:
- return OMAPLFB_UPDATE_MODE_AUTO;
- case OMAP_DSS_UPDATE_MANUAL:
- return OMAPLFB_UPDATE_MODE_MANUAL;
- case OMAP_DSS_UPDATE_DISABLED:
- return OMAPLFB_UPDATE_MODE_DISABLED;
- default:
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eMode));
- break;
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
}
- return OMAPLFB_UPDATE_MODE_UNDEFINED;
+ return OMAPLFBFromDSSUpdateMode(eMode);
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
#else
-return OMAPLFB_UPDATE_MODE_AUTO;
+ return OMAPLFB_UPDATE_MODE_AUTO;
#endif
}
+/* Set display update mode */
OMAPLFB_BOOL OMAPLFBSetUpdateMode(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_UPDATE_MODE eMode)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+ enum omap_dss_update_mode eDSSMode;
+ OMAPLFB_BOOL bSuccess = OMAPLFB_FALSE;
+ OMAPLFB_BOOL bFailure = OMAPLFB_FALSE;
+
+ if (!OMAPLFBValidateUpdateMode(eMode))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
+ return OMAPLFB_FALSE;
+ }
+ eDSSMode = OMAPLFBToDSSUpdateMode(eMode);
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ int iRes = omap_connector_set_update_mode(psConnector, eDSSMode);
+ OMAPLFB_BOOL bRes = (iRes == 0);
+
+
+ bSuccess |= bRes;
+ bFailure |= !bRes;
+ }
+
+ if (!bFailure)
+ {
+ if (!bSuccess)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No screens\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ }
+
+ return OMAPLFB_TRUE;
+ }
+
+ if (!bSuccess)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set %s for any screen\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+ return OMAPLFB_FALSE;
+ }
+
+ if (eMode == OMAPLFB_UPDATE_MODE_AUTO)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set %s for all screens\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+ return OMAPLFB_FALSE;
+ }
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: %s set for some screens\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+
+ return OMAPLFB_TRUE;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
enum omap_dss_update_mode eDSSMode;
if (psDSSDrv == NULL || psDSSDrv->set_update_mode == NULL)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Can't set update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Can't set update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
return OMAPLFB_FALSE;
}
- switch(eMode)
+ if (!OMAPLFBValidateUpdateMode(eMode))
{
- case OMAPLFB_UPDATE_MODE_AUTO:
- eDSSMode = OMAP_DSS_UPDATE_AUTO;
- break;
- case OMAPLFB_UPDATE_MODE_MANUAL:
- eDSSMode = OMAP_DSS_UPDATE_MANUAL;
- break;
- case OMAPLFB_UPDATE_MODE_DISABLED:
- eDSSMode = OMAP_DSS_UPDATE_DISABLED;
- break;
- default:
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eMode));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
return OMAPLFB_FALSE;
}
+ eDSSMode = OMAPLFBToDSSUpdateMode(eMode);
res = psDSSDrv->set_update_mode(psDSSDev, eDSSMode);
if (res != 0)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: set_update_mode failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: set_update_mode (%s) failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBDSSUpdateModeToString(eDSSMode), res));
}
return (res == 0);
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
#else
return 1;
#endif
}
+/* Wait for VSync */
OMAPLFB_BOOL OMAPLFBWaitForVSync(OMAPLFB_DEVINFO *psDevInfo)
{
-#ifdef FBDEV_PRESENT
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ (void) omap_encoder_wait_for_vsync(psConnector->encoder);
+ }
+
+ return OMAPLFB_TRUE;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
OMAP_DSS_MANAGER(psDSSMan, psDSSDev);
int res = WAIT_FOR_VSYNC(psDSSMan)(psDSSMan);
if (res != 0)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Wait for vsync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Wait for vsync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res));
return OMAPLFB_FALSE;
}
}
-#endif
+
return OMAPLFB_TRUE;
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
}
+/*
+ * Wait for screen to update. If the screen is in manual or auto update
+ * mode, we can call this function to wait for the screen to update.
+ */
OMAPLFB_BOOL OMAPLFBManualSync(OMAPLFB_DEVINFO *psDevInfo)
{
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL; )
+ {
+ /* Try manual sync first, then try wait for vsync */
+ if (omap_connector_sync(psConnector) != 0)
+ {
+ (void) omap_encoder_wait_for_vsync(psConnector->encoder);
+ }
+ }
+
+ return OMAPLFB_TRUE;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
int res = psDSSDrv->sync(psDSSDev);
if (res != 0)
{
- printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: Sync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: Sync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return OMAPLFB_FALSE;
}
}
+
return OMAPLFB_TRUE;
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
}
+/*
+ * If the screen is manual or auto update mode, wait for the screen to
+ * update.
+ */
OMAPLFB_BOOL OMAPLFBCheckModeAndSync(OMAPLFB_DEVINFO *psDevInfo)
{
OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
return OMAPLFB_TRUE;
}
+/* Linux Framebuffer event notification handler */
static int OMAPLFBFrameBufferEvents(struct notifier_block *psNotif,
unsigned long event, void *data)
{
struct fb_info *psFBInfo = psFBEvent->info;
OMAPLFB_BOOL bBlanked;
-
+ /* Only interested in blanking events */
if (event != FB_EVENT_BLANK)
{
return 0;
return 0;
}
+/* Unblank the screen */
OMAPLFB_ERROR OMAPLFBUnblankDisplay(OMAPLFB_DEVINFO *psDevInfo)
{
-#ifdef FBDEV_PRESENT
int res;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+
+ OMAPLFB_CONSOLE_LOCK();
res = fb_blank(psDevInfo->psLINFBInfo, 0);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
if (res != 0 && res != -EINVAL)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: fb_blank failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return (OMAPLFB_ERROR_GENERIC);
}
-#endif
+
return (OMAPLFB_OK);
}
#ifdef CONFIG_HAS_EARLYSUSPEND
+/* Blank the screen */
static void OMAPLFBBlankDisplay(OMAPLFB_DEVINFO *psDevInfo)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+ OMAPLFB_CONSOLE_LOCK();
fb_blank(psDevInfo->psLINFBInfo, 1);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
}
static void OMAPLFBEarlySuspendHandler(struct early_suspend *h)
}
}
-#endif
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+/* Set up Linux Framebuffer event notification */
OMAPLFB_ERROR OMAPLFBEnableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
{
int res;
OMAPLFB_ERROR eError;
-
+ /* Set up Linux Framebuffer event notification */
memset(&psDevInfo->sLINNotifBlock, 0, sizeof(psDevInfo->sLINNotifBlock));
psDevInfo->sLINNotifBlock.notifier_call = OMAPLFBFrameBufferEvents;
res = fb_register_client(&psDevInfo->sLINNotifBlock);
if (res != 0)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: fb_register_client failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return (OMAPLFB_ERROR_GENERIC);
eError = OMAPLFBUnblankDisplay(psDevInfo);
if (eError != OMAPLFB_OK)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: UnblankDisplay failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eError);
return eError;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
psDevInfo->sEarlySuspend.suspend = OMAPLFBEarlySuspendHandler;
psDevInfo->sEarlySuspend.resume = OMAPLFBEarlyResumeHandler;
- psDevInfo->sEarlySuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
+ psDevInfo->sEarlySuspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1;
register_early_suspend(&psDevInfo->sEarlySuspend);
#endif
return (OMAPLFB_OK);
}
+/* Disable Linux Framebuffer event notification */
OMAPLFB_ERROR OMAPLFBDisableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
{
int res;
unregister_early_suspend(&psDevInfo->sEarlySuspend);
#endif
-
+ /* Unregister for Framebuffer events */
res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
if (res != 0)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: fb_unregister_client failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return (OMAPLFB_ERROR_GENERIC);
}
}
}
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: PVR Device %u: Couldn't find device\n", __FUNCTION__, uiPVRDevID);
return NULL;
}
-int PVR_DRM_MAKENAME(omaplfb, _Ioctl)(struct drm_device unref__ *dev, void *arg, struct drm_file unref__ *pFile)
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(struct drm_device unref__ *dev, void *arg, struct drm_file unref__ *pFile)
{
uint32_t *puiArgs;
uint32_t uiCmd;
pszMode = "(Unknown Mode)";
break;
}
- printk (KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: Display %s\n",
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: Display %s\n",
__FUNCTION__, uiPVRDevID, pszMode);
}
#endif
flush_workqueue(psDevInfo->psSwapChain->psWorkQueue);
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+ OMAPLFB_CONSOLE_LOCK();
ret = fb_blank(psDevInfo->psLINFBInfo, iFBMode);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
OMAPLFBCreateSwapChainUnLock(psDevInfo);
}
#endif
+/* Insert the driver into the kernel */
#if defined(SUPPORT_DRI_DRM)
-int PVR_DRM_MAKENAME(omaplfb, _Init)(struct drm_device unref__ *dev)
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device unref__ *dev)
#else
static int __init OMAPLFB_Init(void)
#endif
{
+
if(OMAPLFBInit() != OMAPLFB_OK)
{
- printk(KERN_WARNING DRIVER_PREFIX ": %s: OMAPLFBInit failed\n", __FUNCTION__);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: OMAPLFBInit failed\n", __FUNCTION__);
return -ENODEV;
}
}
+/* Remove the driver from the kernel */
#if defined(SUPPORT_DRI_DRM)
-void PVR_DRM_MAKENAME(omaplfb, _Cleanup)(struct drm_device unref__ *dev)
+void PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device unref__ *dev)
#else
static void __exit OMAPLFB_Cleanup(void)
#endif
{
if(OMAPLFBDeInit() != OMAPLFB_OK)
{
- printk(KERN_WARNING DRIVER_PREFIX ": %s: OMAPLFBDeInit failed\n", __FUNCTION__);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: OMAPLFBDeInit failed\n", __FUNCTION__);
}
}
#if !defined(SUPPORT_DRI_DRM)
+/*
+ These macro calls define the initialisation and removal functions of the
+ driver. Although they are prefixed `module_', they apply when compiling
+ statically as well; in both cases they define the function the kernel will
+ run to start/stop the driver.
+*/
late_initcall(OMAPLFB_Init);
module_exit(OMAPLFB_Cleanup);
#endif
-/**********************************************************************
- *
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OMAP Linux display driver shared DRM structures
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OMAP Linux display driver DRM structures shared between
+ kernel and user space.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __3RDPARTY_DC_DRM_SHARED_H__
#define __3RDPARTY_DC_DRM_SHARED_H__
#if defined(SUPPORT_DRI_DRM)
#define PVR_DRM_DISP_ARG_DEV 1
#define PVR_DRM_DISP_NUM_ARGS 2
-#endif
-#endif
+#endif /* defined(SUPPORT_DRI_DRM) */
+#endif /* __3RDPARTY_DC_DRM_SHARED_H__ */
+/******************************************************************************
+ End of file (3rdparty_dc_drm_shared.h)
+******************************************************************************/
--- /dev/null
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
+#
+# The contents of this file are subject to the MIT license as set out below.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
+#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+### ###########################################################################
+
+ccflags-y += \
+ -I$(TOP)/services4/3rdparty/dc_omapfb3_linux \
+ -I$(KERNELDIR)/drivers/video/omap2 \
+ -I$(KERNELDIR)/arch/arm/plat-omap/include
+
+omaplfb-y += \
+ services4/3rdparty/dc_omapfb3_linux/omaplfb_displayclass.o \
+ services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.o
--- /dev/null
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
+#
+# The contents of this file are subject to the MIT license as set out below.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
+#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+### ###########################################################################
+
+modules := dc_omapfb3_linux
+
+dc_omapfb3_linux_type := kernel_module
+dc_omapfb3_linux_target := omaplfb.ko
+dc_omapfb3_linux_makefile := $(THIS_DIR)/Kbuild.mk
+++ /dev/null
-#
-# Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
-#
-#
-
-MODULE = $(DISPLAY_CONTROLLER)
-
-INCLUDES =
-
-SOURCES =
-
-SYM_VERS_DEPS = $(EURASIAROOT)/services4/srvkm/env/linux
-
-include $(EURASIAROOT)/services4/$(DISPLAY_CONTROLLER_DIR)/makefile.linux.common
-
-include $(EURASIAROOT)/eurasiacon/build/linux/kbuild/Makefile.kbuild_subdir_common
+++ /dev/null
-#
-# Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
-#
-#
-#
-
-ifeq ($(SUPPORT_DRI_DRM),1)
-DISPLAY_CONTROLLER_SOURCES_ROOT = $(KBUILDROOT)/$(DISPLAY_CONTROLLER_DIR)
-MODULE_CFLAGS += -DPVR_DISPLAY_CONTROLLER_DRM_IOCTL
-else
-DISPLAY_CONTROLLER_SOURCES_ROOT = ..
-endif
-
-INCLUDES += -I$(EURASIAROOT)/include4 \
- -I$(EURASIAROOT)/services4/include \
- -I$(EURASIAROOT)/services4/system/$(PVR_SYSTEM) \
- -I$(EURASIAROOT)/services4/system/include \
- -I$(KERNELDIR)/drivers/video/omap2 \
- -I$(KERNELDIR)/arch/arm/plat-omap/include
-
-SOURCES += $(DISPLAY_CONTROLLER_SOURCES_ROOT)/omaplfb_displayclass.c \
- $(DISPLAY_CONTROLLER_SOURCES_ROOT)/omaplfb_linux.c
-/**********************************************************************
- *
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title OMAP Linux display driver structures and prototypes
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __OMAPLFB_H__
#define __OMAPLFB_H__
#include <linux/earlysuspend.h>
#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+#define OMAPLFB_CONSOLE_LOCK() console_lock()
+#define OMAPLFB_CONSOLE_UNLOCK() console_unlock()
+#else
+#define OMAPLFB_CONSOLE_LOCK() acquire_console_sem()
+#define OMAPLFB_CONSOLE_UNLOCK() release_console_sem()
+#endif
+
#define unref__ __attribute__ ((unused))
typedef void * OMAPLFB_HANDLE;
typedef atomic_t OMAPLFB_ATOMIC_INT;
+/* OMAPLFB buffer structure */
typedef struct OMAPLFB_BUFFER_TAG
{
struct OMAPLFB_BUFFER_TAG *psNext;
struct work_struct sWork;
-
+ /* Position of this buffer in the virtual framebuffer */
unsigned long ulYOffset;
-
-
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
IMG_SYS_PHYADDR sSysAddr;
IMG_CPU_VIRTADDR sCPUVAddr;
PVRSRV_SYNC_DATA *psSyncData;
unsigned long ulSwapInterval;
} OMAPLFB_BUFFER;
+/* OMAPLFB swapchain structure */
typedef struct OMAPLFB_SWAPCHAIN_TAG
{
-
+ /* Swap chain ID */
unsigned int uiSwapChainID;
-
+ /* number of buffers in swapchain */
unsigned long ulBufferCount;
-
+ /* list of buffers in the swapchain */
OMAPLFB_BUFFER *psBuffer;
-
+ /* Swap chain work queue */
struct workqueue_struct *psWorkQueue;
-
+ /*
+ * Set if we didn't manage to wait for VSync on last swap,
+ * or if we think we need to wait for VSync on the next flip.
+ * The flag helps to avoid jitter when the screen is
+ * unblanked, by forcing an extended wait for VSync before
+ * attempting the next flip.
+ */
OMAPLFB_BOOL bNotVSynced;
-
+ /* Previous number of blank events */
int iBlankEvents;
-
+ /* Framebuffer Device ID for messages (e.g. printk) */
unsigned int uiFBDevID;
} OMAPLFB_SWAPCHAIN;
unsigned long ulPhysicalWidthmm;
unsigned long ulPhysicalHeightmm;
-
-
- IMG_SYS_PHYADDR sSysAddr;
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
+ IMG_SYS_PHYADDR sSysAddr;//system physical address
IMG_CPU_VIRTADDR sCPUVAddr;
-
+ /* pixelformat of system/primary surface */
PVRSRV_PIXEL_FORMAT ePixelFormat;
-}OMAPLFB_FBINFO;
+#if defined(CONFIG_DSSCOMP)
+ OMAPLFB_BOOL bIs2D;
+ IMG_SYS_PHYADDR *psPageList;
+ struct ion_handle *psIONHandle;
+ IMG_UINT32 uiBytesPerPixel;
+#endif
+} OMAPLFB_FBINFO;
+
+/* kernel device information structure */
typedef struct OMAPLFB_DEVINFO_TAG
{
-
+ /* Framebuffer Device ID */
unsigned int uiFBDevID;
-
+ /* PVR Device ID */
unsigned int uiPVRDevID;
-
+ /* Swapchain create/destroy mutex */
struct mutex sCreateSwapChainMutex;
-
+ /* system surface info */
OMAPLFB_BUFFER sSystemBuffer;
-
+ /* jump table into PVR services */
PVRSRV_DC_DISP2SRV_KMJTABLE sPVRJTable;
-
+ /* jump table into DC */
PVRSRV_DC_SRV2DISP_KMJTABLE sDCJTable;
-
+ /* fb info structure */
OMAPLFB_FBINFO sFBInfo;
-
+ /* Only one swapchain supported by this device so hang it here */
OMAPLFB_SWAPCHAIN *psSwapChain;
-
+ /* Swap chain ID */
unsigned int uiSwapChainID;
-
+ /* True if PVR Services is flushing its command queues */
OMAPLFB_ATOMIC_BOOL sFlushCommands;
-
+ /* pointer to linux frame buffer information structure */
struct fb_info *psLINFBInfo;
-
+ /* Linux Framebuffer event notification block */
struct notifier_block sLINNotifBlock;
-
-
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
-
+ /* Address of the surface being displayed */
IMG_DEV_VIRTADDR sDisplayDevVAddr;
DISPLAY_INFO sDisplayInfo;
-
+ /* Display format */
DISPLAY_FORMAT sDisplayFormat;
-
+ /* Display dimensions */
DISPLAY_DIMS sDisplayDim;
-
+ /* True if screen is blanked */
OMAPLFB_ATOMIC_BOOL sBlanked;
-
+ /* Number of blank/unblank events */
OMAPLFB_ATOMIC_INT sBlankEvents;
#ifdef CONFIG_HAS_EARLYSUSPEND
-
+ /* Set by early suspend */
OMAPLFB_ATOMIC_BOOL sEarlySuspendFlag;
struct early_suspend sEarlySuspend;
#define OMAPLFB_PAGE_SIZE 4096
-//#define DEBUG
-
+/* DEBUG only printk */
#ifdef DEBUG
#define DEBUG_PRINTK(x) printk x
#else
#define DEVNAME DRVNAME
#define DRIVER_PREFIX DRVNAME
+/*!
+ *****************************************************************************
+ * Error values
+ *****************************************************************************/
typedef enum _OMAPLFB_ERROR_
{
OMAPLFB_OK = 0,
OMAPLFB_ERROR OMAPLFBInit(void);
OMAPLFB_ERROR OMAPLFBDeInit(void);
+/* OS Specific APIs */
OMAPLFB_DEVINFO *OMAPLFBGetDevInfoPtr(unsigned uiFBDevID);
unsigned OMAPLFBMaxFBDevIDPlusOne(void);
void *OMAPLFBAllocKernelMem(unsigned long ulSize);
int OMAPLFBAtomicIntRead(OMAPLFB_ATOMIC_INT *psAtomic);
void OMAPLFBAtomicIntInc(OMAPLFB_ATOMIC_INT *psAtomic);
-#endif
+#if defined(DEBUG)
+void OMAPLFBPrintInfo(OMAPLFB_DEVINFO *psDevInfo);
+#else
+#define OMAPLFBPrintInfo(psDevInfo)
+#endif
+
+#endif /* __OMAPLFB_H__ */
+
+/******************************************************************************
+ End of file (omaplfb.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OMAP common display driver components
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
+/**************************************************************************
+ The 3rd party driver is a specification of an API to integrate the IMG POWERVR
+ Services driver with 3rd Party display hardware. It is NOT a specification for
+ a display controller driver, rather a specification to extend the API for a
+ pre-existing driver for the display hardware.
+
+ The 3rd party driver interface provides IMG POWERVR client drivers (e.g. PVR2D)
+ with an API abstraction of the system's underlying display hardware, allowing
+ the client drivers to indirectly control the display hardware and access its
+ associated memory.
+
+ Functions of the API include
+ - query primary surface attributes (width, height, stride, pixel format, CPU
+ physical and virtual address)
+ - swap/flip chain creation and subsequent query of surface attributes
+ - asynchronous display surface flipping, taking account of asynchronous read
+ (flip) and write (render) operations to the display surface
+
+ Note: having queried surface attributes the client drivers are able to map the
+ display memory to any IMG POWERVR Services device by calling
+ PVRSRVMapDeviceClassMemory with the display surface handle.
+
+ This code is intended to be an example of how a pre-existing display driver may
+ be extended to support the 3rd Party Display interface to POWERVR Services
+ - IMG is not providing a display driver implementation.
+ **************************************************************************/
+
+/*
+ * OMAP Linux 3rd party display driver.
+ * This is based on the Generic PVR Linux Framebuffer 3rd party display
+ * driver, with OMAP specific extensions to support flipping.
+ */
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/notifier.h>
+/* IMG services headers */
#include "img_defs.h"
#include "servicesext.h"
#include "kerneldisplay.h"
#include "omaplfb.h"
+#if defined(CONFIG_DSSCOMP)
+
+#if !defined(CONFIG_ION_OMAP)
+#error CONFIG_DSSCOMP support requires CONFIG_ION_OMAP
+#endif
+
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+
+extern struct ion_client *gpsIONClient;
+
+#include <mach/tiler.h>
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+
+#endif /* defined(CONFIG_DSSCOMP) */
+
#define OMAPLFB_COMMAND_COUNT 1
#define OMAPLFB_VSYNC_SETTLE_COUNT 5
-#define OMAPLFB_MAX_NUM_DEVICES 1 // FB_MAX
+//#define OMAPLFB_MAX_NUM_DEVICES FB_MAX
+#define OMAPLFB_MAX_NUM_DEVICES 1
#if (OMAPLFB_MAX_NUM_DEVICES > FB_MAX)
#error "OMAPLFB_MAX_NUM_DEVICES must not be greater than FB_MAX"
#endif
static OMAPLFB_DEVINFO *gapsDevInfo[OMAPLFB_MAX_NUM_DEVICES];
+/* Top level 'hook ptr' */
static PFN_DC_GET_PVRJTABLE gpfnGetPVRJTable = NULL;
+/* Round x up to a multiple of y */
static inline unsigned long RoundUpToMultiple(unsigned long x, unsigned long y)
{
unsigned long div = x / y;
return (div + ((rem == 0) ? 0 : 1)) * y;
}
+/* Greatest common divisor of x and y */
static unsigned long GCD(unsigned long x, unsigned long y)
{
while (y != 0)
return x;
}
+/* Least common multiple of x and y */
static unsigned long LCM(unsigned long x, unsigned long y)
{
unsigned long gcd = GCD(x, y);
return OMAPLFB_MAX_NUM_DEVICES;
}
+/* Returns DevInfo pointer for a given device */
OMAPLFB_DEVINFO *OMAPLFBGetDevInfoPtr(unsigned uiFBDevID)
{
WARN_ON(uiFBDevID >= OMAPLFBMaxFBDevIDPlusOne());
return gapsDevInfo[uiFBDevID];
}
+/* Sets the DevInfo pointer for a given device */
static inline void OMAPLFBSetDevInfoPtr(unsigned uiFBDevID, OMAPLFB_DEVINFO *psDevInfo)
{
WARN_ON(uiFBDevID >= OMAPLFB_MAX_NUM_DEVICES);
(psDevInfo->uiSwapChainID != psSwapChain->uiSwapChainID);
}
+/* Don't wait for vertical sync */
static inline OMAPLFB_BOOL DontWaitForVSync(OMAPLFB_DEVINFO *psDevInfo)
{
OMAPLFB_BOOL bDontWait;
return bDontWait;
}
+/*
+ * SetDCState
+ * Called from services.
+ */
static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
{
OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)hDevice;
case DC_STATE_NO_FLUSH_COMMANDS:
OMAPLFBAtomicBoolSet(&psDevInfo->sFlushCommands, OMAPLFB_FALSE);
break;
+ case DC_STATE_FORCE_SWAP_TO_SYSTEM:
+ OMAPLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer);
+ break;
default:
break;
}
}
+/*
+ * OpenDCDevice
+ * Called from services.
+ */
static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 uiPVRDevID,
IMG_HANDLE *phDevice,
PVRSRV_SYNC_DATA* psSystemBufferSyncData)
return PVRSRV_ERROR_INVALID_DEVICE;
}
-
+ /* store the system surface sync data */
psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
eError = OMAPLFBUnblankDisplay(psDevInfo);
return PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED;
}
-
+ /* return handle to the devinfo */
*phDevice = (IMG_HANDLE)psDevInfo;
return PVRSRV_OK;
}
+/*
+ * CloseDCDevice
+ * Called from services.
+ */
static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
{
#if defined(SUPPORT_DRI_DRM)
return PVRSRV_OK;
}
+/*
+ * EnumDCFormats
+ * Called from services.
+ */
static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
IMG_UINT32 *pui32NumFormats,
DISPLAY_FORMAT *psFormat)
return PVRSRV_OK;
}
+/*
+ * EnumDCDims
+ * Called from services.
+ */
static PVRSRV_ERROR EnumDCDims(IMG_HANDLE hDevice,
DISPLAY_FORMAT *psFormat,
IMG_UINT32 *pui32NumDims,
*pui32NumDims = 1;
-
+ /* No need to look at psFormat; there is only one */
if(psDim)
{
psDim[0] = psDevInfo->sDisplayDim;
}
+/*
+ * GetDCSystemBuffer
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE hDevice, IMG_HANDLE *phBuffer)
{
OMAPLFB_DEVINFO *psDevInfo;
}
+/*
+ * GetDCInfo
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCInfo(IMG_HANDLE hDevice, DISPLAY_INFO *psDCInfo)
{
OMAPLFB_DEVINFO *psDevInfo;
return PVRSRV_OK;
}
+/*
+ * GetDCBufferAddr
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE hDevice,
IMG_HANDLE hBuffer,
IMG_SYS_PHYADDR **ppsSysAddr,
if (ppvCpuVAddr)
{
+#if defined(CONFIG_DSSCOMP)
+ *ppvCpuVAddr = psDevInfo->sFBInfo.bIs2D ? NULL : psSystemBuffer->sCPUVAddr;
+#else
*ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
+#endif
}
if (phOSMapInfo)
if (pbIsContiguous)
{
+#if defined(CONFIG_DSSCOMP)
+ *pbIsContiguous = !psDevInfo->sFBInfo.bIs2D;
+#else
*pbIsContiguous = IMG_TRUE;
+#endif
}
+#if defined(CONFIG_DSSCOMP)
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ int i = (psSystemBuffer->sSysAddr.uiAddr - psDevInfo->sFBInfo.psPageList->uiAddr) >> PAGE_SHIFT;
+ *ppsSysAddr = psDevInfo->sFBInfo.psPageList + psDevInfo->sFBInfo.ulHeight * i;
+ }
+#endif
+
return PVRSRV_OK;
}
+/*
+ * CreateDCSwapChain
+ * Called from services.
+ */
static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
IMG_UINT32 ui32Flags,
DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
UNREFERENCED_PARAMETER(ui32OEMFlags);
-
+ /* Check parameters */
if(!hDevice
|| !psDstSurfAttrib
|| !psSrcSurfAttrib
psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
-
+ /* Do we support swap chains? */
if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
{
return PVRSRV_ERROR_NOT_SUPPORTED;
OMAPLFBCreateSwapChainLock(psDevInfo);
-
+ /* The driver only supports a single swapchain */
if(psDevInfo->psSwapChain != NULL)
{
eError = PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
goto ExitUnLock;
}
-
+ /* Check the buffer count */
if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
{
eError = PVRSRV_ERROR_TOOMANYBUFFERS;
goto ExitUnLock;
}
-
+ /*
+ * We will allocate the swap chain buffers at the back of the frame
+ * buffer area. This preserves the front portion, which may be being
+ * used by other Linux Framebuffer based applications.
+ */
ui32BuffersToSkip = psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers - ui32BufferCount;
-
+ /*
+ * Verify the DST/SRC attributes,
+ * SRC/DST must match the current display mode config
+ */
if(psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat
|| psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride
|| psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width
|| psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height)
{
-
+ /* DST doesn't match the current mode */
eError = PVRSRV_ERROR_INVALID_PARAMS;
goto ExitUnLock;
}
|| psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width
|| psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height)
{
-
+ /* DST doesn't match the SRC */
eError = PVRSRV_ERROR_INVALID_PARAMS;
goto ExitUnLock;
}
-
+ /* check flags if implementation requires them */
UNREFERENCED_PARAMETER(ui32Flags);
#if defined(PVR_OMAPFB3_UPDATE_MODE)
printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set frame buffer update mode %d\n", __FUNCTION__, psDevInfo->uiFBDevID, PVR_OMAPFB3_UPDATE_MODE);
}
#endif
-
+ /* create a swapchain structure */
psSwapChain = (OMAPLFB_SWAPCHAIN*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_SWAPCHAIN));
if(!psSwapChain)
{
psSwapChain->bNotVSynced = OMAPLFB_TRUE;
psSwapChain->uiFBDevID = psDevInfo->uiFBDevID;
-
+ /* Link the buffers */
for(i=0; i<ui32BufferCount-1; i++)
{
psBuffer[i].psNext = &psBuffer[i+1];
}
-
+ /* and link last to first */
psBuffer[i].psNext = &psBuffer[0];
-
+ /* Configure the swapchain buffers */
for(i=0; i<ui32BufferCount; i++)
{
IMG_UINT32 ui32SwapBuffer = i + ui32BuffersToSkip;
IMG_UINT32 ui32BufferOffset = ui32SwapBuffer * (IMG_UINT32)psDevInfo->sFBInfo.ulRoundedBufferSize;
+#if defined(CONFIG_DSSCOMP)
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ ui32BufferOffset = 0;
+ }
+#endif /* defined(CONFIG_DSSCOMP) */
+
psBuffer[i].psSyncData = ppsSyncData[i];
psBuffer[i].sSysAddr.uiAddr = psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
psBuffer[i].ulYOffset = ui32BufferOffset / psDevInfo->sFBInfo.ulByteStride;
psBuffer[i].psDevInfo = psDevInfo;
+#if defined(CONFIG_DSSCOMP)
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ psBuffer[i].sSysAddr.uiAddr += ui32SwapBuffer *
+ ALIGN((IMG_UINT32)psDevInfo->sFBInfo.ulWidth * psDevInfo->sFBInfo.uiBytesPerPixel, PAGE_SIZE);
+ }
+#endif /* defined(CONFIG_DSSCOMP) */
+
OMAPLFBInitBufferForSwap(&psBuffer[i]);
}
return eError;
}
+/*
+ * DestroyDCSwapChain
+ * Called from services.
+ */
static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain)
{
OMAPLFB_SWAPCHAIN *psSwapChain;
OMAPLFB_ERROR eError;
-
+ /* Check parameters */
if(!hDevice || !hSwapChain)
{
return PVRSRV_ERROR_INVALID_PARAMS;
goto ExitUnLock;
}
-
+ /* The swap queue is flushed before being destroyed */
OMAPLFBDestroySwapQueue(psSwapChain);
eError = OMAPLFBDisableLFBEventNotification(psDevInfo);
printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't disable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID);
}
-
+ /* Free resources */
OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
OMAPLFBFreeKernelMem(psSwapChain);
return eError;
}
+/*
+ * SetDCDstRect
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_RECT *psRect)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(psRect);
-
+ /* Only full display swapchains on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * SetDCSrcRect
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_RECT *psRect)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(psRect);
-
+ /* Only full display swapchains on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * SetDCDstColourKey
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_UINT32 ui32CKColour)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(ui32CKColour);
-
+ /* Don't support DST CK on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * SetDCSrcColourKey
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_UINT32 ui32CKColour)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(ui32CKColour);
-
+ /* Don't support SRC CK on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * GetDCBuffers
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_UINT32 *pui32BufferCount,
PVRSRV_ERROR eError;
unsigned i;
-
+ /* Check parameters */
if(!hDevice
|| !hSwapChain
|| !pui32BufferCount
goto Exit;
}
-
+ /* Return the buffer count */
*pui32BufferCount = (IMG_UINT32)psSwapChain->ulBufferCount;
-
+ /* Return the buffers */
for(i=0; i<psSwapChain->ulBufferCount; i++)
{
phBuffer[i] = (IMG_HANDLE)&psSwapChain->psBuffer[i];
return eError;
}
+/*
+ * SwapToDCBuffer
+ * Called from services.
+ */
static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE hDevice,
IMG_HANDLE hBuffer,
IMG_UINT32 ui32SwapInterval,
UNREFERENCED_PARAMETER(ui32ClipRectCount);
UNREFERENCED_PARAMETER(psClipRect);
-
+ /* * Nothing to do since Services common code does the work */
return PVRSRV_OK;
}
-static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE hDevice,
- IMG_HANDLE hSwapChain)
-{
- UNREFERENCED_PARAMETER(hDevice);
- UNREFERENCED_PARAMETER(hSwapChain);
-
-
- return PVRSRV_OK;
-}
-
+/*
+ * Called after the screen has unblanked, or after any other occasion
+ * when we didn't wait for vsync, but now need to. Not doing this after
+ * unblank leads to screen jitter on some screens.
+ * Returns true if the screen has been deemed to have settled.
+ */
static OMAPLFB_BOOL WaitForVSyncSettle(OMAPLFB_DEVINFO *psDevInfo)
{
unsigned i;
return OMAPLFB_TRUE;
}
+/*
+ * Swap handler.
+ * Called from the swap chain work queue handler.
+ * There is no need to take the swap chain creation lock in here, or use
+ * some other method of stopping the swap chain from being destroyed.
+ * This is because the swap chain creation lock is taken when queueing work,
+ * and the work queue is flushed before the swap chain is destroyed.
+ */
void OMAPLFBSwapHandler(OMAPLFB_BUFFER *psBuffer)
{
OMAPLFB_DEVINFO *psDevInfo = psBuffer->psDevInfo;
OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
OMAPLFB_BOOL bPreviouslyNotVSynced;
-#if 1
+
#if defined(SUPPORT_DRI_DRM)
if (!OMAPLFBAtomicBoolRead(&psDevInfo->sLeaveVT))
#endif
{
OMAPLFBFlip(psDevInfo, psBuffer);
}
-#endif
+
bPreviouslyNotVSynced = psSwapChain->bNotVSynced;
psSwapChain->bNotVSynced = OMAPLFB_TRUE;
}
}
-#if 0
-#if defined(SUPPORT_DRI_DRM)
- if (!OMAPLFBAtomicBoolRead(&psDevInfo->sLeaveVT))
-#endif
- {
- OMAPLFBFlip(psDevInfo, psBuffer);
- }
-#endif
-
psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psBuffer->hCmdComplete, IMG_TRUE);
}
+/* Triggered by PVRSRVSwapToDCBuffer */
+static IMG_BOOL ProcessFlipV1(IMG_HANDLE hCmdCookie,
+ OMAPLFB_DEVINFO *psDevInfo,
+ OMAPLFB_SWAPCHAIN *psSwapChain,
+ OMAPLFB_BUFFER *psBuffer,
+ unsigned long ulSwapInterval)
+{
+ OMAPLFBCreateSwapChainLock(psDevInfo);
+
+ /* The swap chain has been destroyed */
+ if (SwapChainHasChanged(psDevInfo, psSwapChain))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
+ ": %s: Device %u (PVR Device ID %u): The swap chain has been destroyed\n",
+ __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
+ }
+ else
+ {
+ psBuffer->hCmdComplete = (OMAPLFB_HANDLE)hCmdCookie;
+ psBuffer->ulSwapInterval = ulSwapInterval;
+#if defined(CONFIG_DSSCOMP)
+ if (is_tiler_addr(psBuffer->sSysAddr.uiAddr))
+ {
+ IMG_UINT32 w = psBuffer->psDevInfo->sDisplayDim.ui32Width;
+ IMG_UINT32 h = psBuffer->psDevInfo->sDisplayDim.ui32Height;
+ struct dsscomp_setup_dispc_data comp = {
+ .num_mgrs = 1,
+ .mgrs[0].alpha_blending = 1,
+ .num_ovls = 1,
+ .ovls[0].cfg =
+ {
+ .width = w,
+ .win.w = w,
+ .crop.w = w,
+ .height = h,
+ .win.h = h,
+ .crop.h = h,
+ .stride = psBuffer->psDevInfo->sDisplayDim.ui32ByteStride,
+ .color_mode = OMAP_DSS_COLOR_ARGB32,
+ .enabled = 1,
+ .global_alpha = 255,
+ },
+ .mode = DSSCOMP_SETUP_DISPLAY,
+ };
+ struct tiler_pa_info *pas[1] = { NULL };
+ comp.ovls[0].ba = (u32) psBuffer->sSysAddr.uiAddr;
+ dsscomp_gralloc_queue(&comp, pas, true,
+ (void *) psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete,
+ (void *) psBuffer->hCmdComplete);
+ }
+ else
+#endif /* defined(CONFIG_DSSCOMP) */
+ {
+ OMAPLFBQueueBufferForSwap(psSwapChain, psBuffer);
+ }
+ }
+
+ OMAPLFBCreateSwapChainUnLock(psDevInfo);
+
+ return IMG_TRUE;
+}
+
+#if defined(CONFIG_DSSCOMP)
+
+/* Triggered by PVRSRVSwapToDCBuffer2 */
+static IMG_BOOL ProcessFlipV2(IMG_HANDLE hCmdCookie,
+ OMAPLFB_DEVINFO *psDevInfo,
+ PDC_MEM_INFO *ppsMemInfos,
+ IMG_UINT32 ui32NumMemInfos,
+ struct dsscomp_setup_dispc_data *psDssData,
+ IMG_UINT32 ui32DssDataLength)
+{
+ struct tiler_pa_info *apsTilerPAs[5];
+ IMG_UINT32 i, k;
+
+ if(ui32DssDataLength != sizeof(*psDssData))
+ {
+ WARN(1, "invalid size of private data (%d vs %d)",
+ ui32DssDataLength, sizeof(*psDssData));
+ return IMG_FALSE;
+ }
+
+ if(psDssData->num_ovls == 0 || ui32NumMemInfos == 0)
+ {
+ WARN(1, "must have at least one layer");
+ return IMG_FALSE;
+ }
+
+ for(i = k = 0; i < ui32NumMemInfos && k < ARRAY_SIZE(apsTilerPAs); i++, k++)
+ {
+ struct tiler_pa_info *psTilerInfo;
+ IMG_CPU_VIRTADDR virtAddr;
+ IMG_CPU_PHYADDR phyAddr;
+ IMG_UINT32 ui32NumPages;
+ IMG_SIZE_T uByteSize;
+ int j;
+
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetByteSize(ppsMemInfos[i], &uByteSize);
+ ui32NumPages = (uByteSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ apsTilerPAs[k] = NULL;
+
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], 0, &phyAddr);
+
+ /* NV12 buffers are already mapped to tiler */
+ if(psDssData->ovls[k].cfg.color_mode == OMAP_DSS_COLOR_NV12)
+ {
+ psDssData->ovls[k].ba = (u32)phyAddr.uiAddr;
+
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], (uByteSize * 2) / 3, &phyAddr);
+ psDssData->ovls[k].uv = (u32)phyAddr.uiAddr;
+ continue;
+ }
+
+ /* Other kinds of buffer may also already be mapped to tiler */
+ if(is_tiler_addr((u32)phyAddr.uiAddr))
+ {
+ psDssData->ovls[k].ba = (u32)phyAddr.uiAddr;
+ continue;
+ }
+
+ psTilerInfo = kzalloc(sizeof(*psTilerInfo), GFP_KERNEL);
+ if(!psTilerInfo)
+ {
+ continue;
+ }
+
+ psTilerInfo->mem = kzalloc(sizeof(*psTilerInfo->mem) * ui32NumPages, GFP_KERNEL);
+ if(!psTilerInfo->mem)
+ {
+ kfree(psTilerInfo);
+ continue;
+ }
+
+ psTilerInfo->num_pg = ui32NumPages;
+ psTilerInfo->memtype = TILER_MEM_USING;
+
+ for(j = 0; j < ui32NumPages; j++)
+ {
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], j << PAGE_SHIFT, &phyAddr);
+ psTilerInfo->mem[j] = (u32)phyAddr.uiAddr;
+ }
+
+ /* Need base address for in-page offset */
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuVAddr(ppsMemInfos[i], &virtAddr);
+ psDssData->ovls[k].ba = (u32)virtAddr;
+ apsTilerPAs[k] = psTilerInfo;
+ }
+
+ /* Set up cloned layer addresses (but don't duplicate tiler_pas) */
+ for(i = k; i < psDssData->num_ovls && i < ARRAY_SIZE(apsTilerPAs); i++)
+ {
+ unsigned int ix = psDssData->ovls[i].ba;
+ if(ix >= ARRAY_SIZE(apsTilerPAs))
+ {
+ WARN(1, "Invalid clone layer (%u); skipping all cloned layers", ix);
+ psDssData->num_ovls = k;
+ break;
+ }
+ apsTilerPAs[i] = apsTilerPAs[ix];
+ psDssData->ovls[i].ba = psDssData->ovls[ix].ba;
+ psDssData->ovls[i].uv = psDssData->ovls[ix].uv;
+ }
+
+ dsscomp_gralloc_queue(psDssData, apsTilerPAs, false,
+ (void *)psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete,
+ (void *)hCmdCookie);
+
+ for(i = 0; i < k; i++)
+ {
+ tiler_pa_free(apsTilerPAs[i]);
+ }
+
+ return IMG_TRUE;
+}
+
+#endif /* defined(CONFIG_DSSCOMP) */
+
+/* Command processing flip handler function. Called from services. */
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;
-
+ /* Check parameters */
if(!hCmdCookie || !pvData)
{
return IMG_FALSE;
}
-
+ /* Validate data packet */
psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData;
- if (psFlipCmd == IMG_NULL || sizeof(DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
+ if (psFlipCmd == IMG_NULL)
{
return IMG_FALSE;
}
-
psDevInfo = (OMAPLFB_DEVINFO*)psFlipCmd->hExtDevice;
- psBuffer = (OMAPLFB_BUFFER*)psFlipCmd->hExtBuffer;
- psSwapChain = (OMAPLFB_SWAPCHAIN*) psFlipCmd->hExtSwapChain;
-
- OMAPLFBCreateSwapChainLock(psDevInfo);
- if (SwapChainHasChanged(psDevInfo, psSwapChain))
+ if(psFlipCmd->hExtBuffer)
{
-
- DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
- ": %s: Device %u (PVR Device ID %u): The swap chain has been destroyed\n",
- __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
+ return ProcessFlipV1(hCmdCookie,
+ psDevInfo,
+ psFlipCmd->hExtSwapChain,
+ psFlipCmd->hExtBuffer,
+ psFlipCmd->ui32SwapInterval);
}
else
{
- psBuffer->hCmdComplete = (OMAPLFB_HANDLE)hCmdCookie;
- psBuffer->ulSwapInterval = (unsigned long)psFlipCmd->ui32SwapInterval;
-#if defined(NO_HARDWARE)
- psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psBuffer->hCmdComplete, IMG_FALSE);
+#if defined(CONFIG_DSSCOMP)
+ DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd2;
+ psFlipCmd2 = (DISPLAYCLASS_FLIP_COMMAND2 *)pvData;
+ return ProcessFlipV2(hCmdCookie,
+ psDevInfo,
+ psFlipCmd2->ppsMemInfos,
+ psFlipCmd2->ui32NumMemInfos,
+ psFlipCmd2->pvPrivData,
+ psFlipCmd2->ui32PrivDataLength);
#else
- OMAPLFBQueueBufferForSwap(psSwapChain, psBuffer);
+ BUG();
#endif
}
+}
- OMAPLFBCreateSwapChainUnLock(psDevInfo);
+/*!
+******************************************************************************
- return IMG_TRUE;
-}
+ @Function OMAPLFBInitFBDev
+
+ @Description specifies devices in the systems memory map
+
+ @Input psSysData - sys data
+ @Return OMAPLFB_ERROR :
+******************************************************************************/
static OMAPLFB_ERROR OMAPLFBInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
{
struct fb_info *psLINFBInfo;
unsigned long FBSize;
unsigned long ulLCM;
unsigned uiFBDevID = psDevInfo->uiFBDevID;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+
+ OMAPLFB_CONSOLE_LOCK();
psLINFBInfo = registered_fb[uiFBDevID];
if (psLINFBInfo == NULL)
psLINFBInfo->screen_size :
psLINFBInfo->fix.smem_len;
-
+ /*
+ * Try and filter out invalid FB info structures (a problem
+ * seen on some OMAP3 systems).
+ */
if (FBSize == 0 || psLINFBInfo->fix.line_length == 0)
{
eError = OMAPLFB_ERROR_INVALID_DEVICE;
": Device %u: LCM of stride and page size: %lu\n",
psDevInfo->uiFBDevID, ulLCM));
-
+ /* Additional implementation specific information */
+ OMAPLFBPrintInfo(psDevInfo);
+
+#if defined(CONFIG_DSSCOMP)
+ {
+ /* for some reason we need at least 3 buffers in the swap chain */
+ int n = FBSize / RoundUpToMultiple(psLINFBInfo->fix.line_length * psLINFBInfo->var.yres, ulLCM);
+ int res;
+ int i, x, y, w;
+ ion_phys_addr_t phys;
+ size_t size;
+ struct tiler_view_t view;
+
+ struct omap_ion_tiler_alloc_data sAllocData =
+ {
+ /* TILER will align width to 128-bytes */
+ /* however, SGX must have full page width */
+ .w = ALIGN(psLINFBInfo->var.xres, PAGE_SIZE / (psLINFBInfo->var.bits_per_pixel / 8)),
+ .h = psLINFBInfo->var.yres,
+ .fmt = psLINFBInfo->var.bits_per_pixel == 16 ? TILER_PIXEL_FMT_16BIT : TILER_PIXEL_FMT_32BIT,
+ .flags = 0,
+ };
+
+ printk(KERN_DEBUG DRIVER_PREFIX
+ " %s: Device %u: Requesting %d TILER 2D framebuffers\n",
+ __FUNCTION__, uiFBDevID, n);
+
+ /* INTEGRATION_POINT: limit to MAX 3 FBs to save TILER container space */
+ if (n > 3)
+ n = 3;
+
+ sAllocData.w *= n;
+
+ psPVRFBInfo->uiBytesPerPixel = psLINFBInfo->var.bits_per_pixel >> 3;
+ psPVRFBInfo->bIs2D = OMAPLFB_TRUE;
+
+ res = omap_ion_tiler_alloc(gpsIONClient, &sAllocData);
+ psPVRFBInfo->psIONHandle = sAllocData.handle;
+ if (res < 0)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ " %s: Device %u: Could not allocate 2D framebuffer(%d)\n",
+ __FUNCTION__, uiFBDevID, res);
+ goto ErrorModPut;
+ }
+
+ psLINFBInfo->fix.smem_start = ion_phys(gpsIONClient, sAllocData.handle, &phys, &size);
+
+ psPVRFBInfo->sSysAddr.uiAddr = phys;
+ psPVRFBInfo->sCPUVAddr = 0;
+ psPVRFBInfo->ulWidth = psLINFBInfo->var.xres;
+ psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
+
+ psPVRFBInfo->ulByteStride = PAGE_ALIGN(psPVRFBInfo->ulWidth * psPVRFBInfo->uiBytesPerPixel);
+ w = psPVRFBInfo->ulByteStride >> PAGE_SHIFT;
+
+ /* this is an "effective" FB size to get correct number of buffers */
+ psPVRFBInfo->ulFBSize = sAllocData.h * n * psPVRFBInfo->ulByteStride;
+ psPVRFBInfo->psPageList = kzalloc(w * n * psPVRFBInfo->ulHeight * sizeof(*psPVRFBInfo->psPageList), GFP_KERNEL);
+ if (!psPVRFBInfo->psPageList)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Could not allocate page list\n", __FUNCTION__, psDevInfo->uiFBDevID);
+ ion_free(gpsIONClient, sAllocData.handle);
+ goto ErrorModPut;
+ }
+
+ tilview_create(&view, phys, psDevInfo->sFBInfo.ulWidth, psDevInfo->sFBInfo.ulHeight);
+ for(i = 0; i < n; i++)
+ {
+ for(y = 0; y < psDevInfo->sFBInfo.ulHeight; y++)
+ {
+ for(x = 0; x < w; x++)
+ {
+ psPVRFBInfo->psPageList[i * psDevInfo->sFBInfo.ulHeight * w + y * w + x].uiAddr =
+ phys + view.v_inc * y + ((x + i * w) << PAGE_SHIFT);
+ }
+ }
+ }
+ }
+#else /* defined(CONFIG_DSSCOMP) */
+ /* System Surface */
psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
psPVRFBInfo->ulByteStride = psLINFBInfo->fix.line_length;
psPVRFBInfo->ulFBSize = FBSize;
+#endif /* defined(CONFIG_DSSCOMP) */
+
psPVRFBInfo->ulBufferSize = psPVRFBInfo->ulHeight * psPVRFBInfo->ulByteStride;
-
+
+ /* Round the buffer size up to a multiple of the number of pages
+ * and the byte stride.
+ * This is used internally, to ensure buffers start on page
+ * boundaries, for the benefit of PVR Services.
+ */
psPVRFBInfo->ulRoundedBufferSize = RoundUpToMultiple(psPVRFBInfo->ulBufferSize, ulLCM);
if(psLINFBInfo->var.bits_per_pixel == 16)
(psLINFBInfo->var.red.offset == 11) &&
(psLINFBInfo->var.green.offset == 5) &&
(psLINFBInfo->var.blue.offset == 0) &&
- (psLINFBInfo->var.red.msb_right == 0))
+ (psLINFBInfo->var.red.msb_right == 0))
{
psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
}
(psLINFBInfo->var.red.offset == 16) &&
(psLINFBInfo->var.green.offset == 8) &&
(psLINFBInfo->var.blue.offset == 0) &&
- (psLINFBInfo->var.red.msb_right == 0))
+ (psLINFBInfo->var.red.msb_right == 0))
{
psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_ARGB8888;
}
psDevInfo->sFBInfo.ulPhysicalHeightmm =
((int)psLINFBInfo->var.height > 0) ? psLINFBInfo->var.height : 54;
-
+ /* System Surface */
psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
ErrorModPut:
module_put(psLINFBOwner);
ErrorRelSem:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
return eError;
}
struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
struct module *psLINFBOwner;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+ OMAPLFB_CONSOLE_LOCK();
+
+#if defined(CONFIG_DSSCOMP)
+ {
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ kfree(psPVRFBInfo->psPageList);
+ if (psPVRFBInfo->psIONHandle)
+ {
+ ion_free(gpsIONClient, psPVRFBInfo->psIONHandle);
+ }
+ }
+#endif /* defined(CONFIG_DSSCOMP) */
+
psLINFBOwner = psLINFBInfo->fbops->owner;
if (psLINFBInfo->fbops->fb_release != NULL)
}
module_put(psLINFBOwner);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+
+ OMAPLFB_CONSOLE_UNLOCK();
}
static OMAPLFB_DEVINFO *OMAPLFBInitDev(unsigned uiFBDevID)
IMG_UINT32 aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
OMAPLFB_DEVINFO *psDevInfo = NULL;
-
+ /* Allocate device info. structure */
psDevInfo = (OMAPLFB_DEVINFO *)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_DEVINFO));
if(psDevInfo == NULL)
goto ErrorExit;
}
-
+ /* Any fields not set will be zero */
memset(psDevInfo, 0, sizeof(OMAPLFB_DEVINFO));
psDevInfo->uiFBDevID = uiFBDevID;
-
+ /* Get the kernel services function table */
if(!(*gpfnGetPVRJTable)(&psDevInfo->sPVRJTable))
{
goto ErrorFreeDevInfo;
}
#ifdef FBDEV_PRESENT
-
+ /* Save private fbdev information structure in the dev. info. */
if(OMAPLFBInitFBDev(psDevInfo) != OMAPLFB_OK)
{
-
+ /*
+ * Leave it to OMAPLFBInitFBDev to print an error message, if
+ * required. The function may have failed because
+ * there is no Linux framebuffer device corresponding
+ * to the device ID.
+ */
goto ErrorFreeDevInfo;
}
": Device %u: Maximum number of swap chain buffers: %u\n",
psDevInfo->uiFBDevID, psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
-
-
+ /* Setup system buffer */
psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
psDevInfo->sSystemBuffer.psDevInfo = psDevInfo;
OMAPLFBInitBufferForSwap(&psDevInfo->sSystemBuffer);
#else
- psDevInfo->sSystemBuffer.sCPUVAddr = 0x100;
+psDevInfo->sSystemBuffer.sCPUVAddr = 0x100;
// psDevInfo->sSystemBuffer.ulBufferSize = 600*3200;
psDevInfo->sDisplayFormat.pixelformat = 20;
#endif
+ /*
+ Setup the DC Jtable so SRVKM can call into this driver
+ */
psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
- psDevInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem;
psDevInfo->sDCJTable.pfnSetDCState = SetDCState;
-
+ /* Register device with services and retrieve device index */
if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice(
&psDevInfo->sDCJTable,
&psDevInfo->uiPVRDevID) != PVRSRV_OK)
": Device %u: PVR Device ID: %u\n",
psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
-
+ /* Setup private command processing function table ... */
pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
-
- aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
- aui32SyncCountList[DC_FLIP_COMMAND][1] = 2;
-
-
-
-
+ /* ... and associated sync count(s) */
+ aui32SyncCountList[DC_FLIP_COMMAND][0] = 0; /* writes */
+ aui32SyncCountList[DC_FLIP_COMMAND][1] = 10; /* reads */
+ /*
+ Register private command processing functions with
+ the Command Queue Manager and setup the general
+ command complete function in the devinfo.
+ */
if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList(psDevInfo->uiPVRDevID,
&pfnCmdProcList[0],
aui32SyncCountList,
return OMAPLFB_ERROR_INIT_FAILURE;
}
-
+ /*
+ * We search for frame buffer devices backwards, as the last device
+ * registered with PVR Services will be the first device enumerated
+ * by PVR Services.
+ */
for(i = uiMaxFBDevIDPlusOne; i-- != 0;)
{
OMAPLFB_DEVINFO *psDevInfo = OMAPLFBInitDev(i);
if (psDevInfo != NULL)
{
-
+ /* Set the top-level anchor */
OMAPLFBSetDevInfoPtr(psDevInfo->uiFBDevID, psDevInfo);
uiDevicesFound++;
}
return (uiDevicesFound != 0) ? OMAPLFB_OK : OMAPLFB_ERROR_INIT_FAILURE;
}
+/*
+ * OMAPLFBDeInitDev
+ * DeInitialises one device
+ */
static OMAPLFB_BOOL OMAPLFBDeInitDev(OMAPLFB_DEVINFO *psDevInfo)
{
PVRSRV_DC_DISP2SRV_KMJTABLE *psPVRJTable = &psDevInfo->sPVRJTable;
return OMAPLFB_FALSE;
}
-
+ /*
+ * Remove display class device from kernel services device
+ * register.
+ */
if (psPVRJTable->pfnPVRSRVRemoveDCDevice(psDevInfo->uiPVRDevID) != PVRSRV_OK)
{
printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: PVR Device %u: Couldn't remove device from PVR Services\n", __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID);
return OMAPLFB_FALSE;
}
-#ifdef FBDEV_PRESENT
+
OMAPLFBDeInitFBDev(psDevInfo);
-#endif
+
OMAPLFBSetDevInfoPtr(psDevInfo->uiFBDevID, NULL);
-
+ /* De-allocate data structure */
OMAPLFBFreeKernelMem(psDevInfo);
return OMAPLFB_TRUE;
}
+/*
+ * OMAPLFBDeInit
+ * Deinitialises the display class device component of the FBDev
+ */
OMAPLFB_ERROR OMAPLFBDeInit(void)
{
unsigned uiMaxFBDevIDPlusOne = OMAPLFBMaxFBDevIDPlusOne();
return (bError) ? OMAPLFB_ERROR_INIT_FAILURE : OMAPLFB_OK;
}
+/******************************************************************************
+ End of file (omaplfb_displayclass.c)
+******************************************************************************/
+
-/**********************************************************************
- *
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OMAP linux display driver components
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
+/**************************************************************************
+ The 3rd party driver is a specification of an API to integrate the IMG POWERVR
+ Services driver with 3rd Party display hardware. It is NOT a specification for
+ a display controller driver, rather a specification to extend the API for a
+ pre-existing driver for the display hardware.
+
+ The 3rd party driver interface provides IMG POWERVR client drivers (e.g. PVR2D)
+ with an API abstraction of the system's underlying display hardware, allowing
+ the client drivers to indirectly control the display hardware and access its
+ associated memory.
+
+ Functions of the API include
+ - query primary surface attributes (width, height, stride, pixel format, CPU
+ physical and virtual address)
+ - swap/flip chain creation and subsequent query of surface attributes
+ - asynchronous display surface flipping, taking account of asynchronous read
+ (flip) and write (render) operations to the display surface
+
+ Note: having queried surface attributes the client drivers are able to map the
+ display memory to any IMG POWERVR Services device by calling
+ PVRSRVMapDeviceClassMemory with the display surface handle.
+
+ This code is intended to be an example of how a pre-existing display driver may
+ be extended to support the 3rd Party Display interface to POWERVR Services
+ - IMG is not providing a display driver implementation.
+ **************************************************************************/
#include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
#ifndef AUTOCONF_INCLUDED
#include <linux/config.h>
#endif
#endif
-
#include <asm/atomic.h>
#if defined(SUPPORT_DRI_DRM)
#include <linux/module.h>
#endif
-//#include <linux/time.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/hardirq.h>
#include <linux/mutex.h>
#include <video/da8xx-fb.h>
-#include <plat/vrfb.h>
+#if defined(PVR_OMAPLFB_DRM_FB)
+#include <plat/display.h>
+#include <linux/omap_gpu.h>
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
+/* OmapZoom.org OMAP3 2.6.29 kernel tree - Needs mach/vrfb.h
+ * OmapZoom.org OMAP3 2.6.32 kernel tree - No additional header required
+ * OmapZoom.org OMAP4 2.6.33 kernel tree - No additional header required
+ * OmapZoom.org OMAP4 2.6.34 kernel tree - Needs plat/vrfb.h
+ * Sholes 2.6.32 kernel tree - Needs plat/vrfb.h
+ */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
#define PVR_OMAPFB3_NEEDS_PLAT_VRFB_H
#endif
#if defined(PVR_OMAPFB3_NEEDS_PLAT_VRFB_H)
-# include <plat/vrfb.h>
+#include <plat/vrfb.h>
#else
-# if defined(PVR_OMAPFB3_NEEDS_MACH_VRFB_H)
-# include <mach/vrfb.h>
-# endif
+#if defined(PVR_OMAPFB3_NEEDS_MACH_VRFB_H)
+#include <mach/vrfb.h>
+#endif
#endif
#if defined(DEBUG)
#define DEBUG PVR_DEBUG
#undef PVR_DEBUG
#endif
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
+
+#if defined(CONFIG_DSSCOMP)
+#include <mach/tiler.h>
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+#endif /* defined(CONFIG_DSSCOMP) */
#include "img_defs.h"
#include "servicesext.h"
#include "3rdparty_dc_drm_shared.h"
#endif
-#if 0
#if !defined(PVR_LINUX_USING_WORKQUEUES)
#error "PVR_LINUX_USING_WORKQUEUES must be defined"
#endif
-#endif
MODULE_SUPPORTED_DEVICE(DEVNAME);
+#if !defined(PVR_OMAPLFB_DRM_FB)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
#define OMAP_DSS_DRIVER(drv, dev) struct omap_dss_driver *drv = (dev) != NULL ? (dev)->driver : NULL
#define OMAP_DSS_MANAGER(man, dev) struct omap_overlay_manager *man = (dev) != NULL ? (dev)->manager : NULL
#define OMAP_DSS_MANAGER(man, dev) struct omap_dss_device *man = (dev)
#define WAIT_FOR_VSYNC(man) ((man)->wait_vsync)
#endif
+#endif /* !defined(PVR_OMAPLFB_DRM_FB) */
void *OMAPLFBAllocKernelMem(unsigned long ulSize)
{
return (OMAPLFB_ERROR_INVALID_PARAMS);
}
-
+ /* Nothing to do - should be exported from pvrsrv.ko */
*ppfnFuncTable = PVRGetDisplayClassJTable;
return (OMAPLFB_OK);
}
+/* Inset a swap buffer into the swap chain work queue */
void OMAPLFBQueueBufferForSwap(OMAPLFB_SWAPCHAIN *psSwapChain, OMAPLFB_BUFFER *psBuffer)
{
int res = queue_work(psSwapChain->psWorkQueue, &psBuffer->sWork);
}
}
+/* Process an item on a swap chain work queue */
static void WorkQueueHandler(struct work_struct *psWork)
{
OMAPLFB_BUFFER *psBuffer = container_of(psWork, OMAPLFB_BUFFER, sWork);
OMAPLFBSwapHandler(psBuffer);
}
+/* Create a swap chain work queue */
OMAPLFB_ERROR OMAPLFBCreateSwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
{
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34))
- psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
-#else
- psSwapChain->psWorkQueue = create_workqueue(DEVNAME);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ /*
+ * Calling alloc_ordered_workqueue with the WQ_FREEZABLE and
+ * WQ_MEM_RECLAIM flags set, (currently) has the same effect as
+ * calling create_freezable_workqueue. None of the other WQ
+ * flags are valid. Setting WQ_MEM_RECLAIM should allow the
+ * workqueue to continue to service the swap chain in low memory
+ * conditions, preventing the driver from holding on to
+ * resources longer than it needs to.
+ */
+#if (LINUX_VERSION_CODE == KERNEL_VERSION(2,6,37))
+ psSwapChain->psWorkQueue = alloc_ordered_workqueue(DEVNAME, WQ_FREEZEABLE | WQ_MEM_RECLAIM);
+#else
+ psSwapChain->psWorkQueue = alloc_ordered_workqueue(DEVNAME, WQ_FREEZABLE | WQ_MEM_RECLAIM);
+#endif
+
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+ psSwapChain->psWorkQueue = create_freezable_workqueue(DEVNAME);
+#else
+ /*
+ * Create a single-threaded, freezable, rt-prio workqueue.
+ * Such workqueues are frozen with user threads when a system
+ * suspends, before driver suspend entry points are called.
+ * This ensures this driver will not call into the Linux
+ * framebuffer driver after the latter is suspended.
+ */
+ psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
+#endif
#endif
if (psSwapChain->psWorkQueue == NULL)
{
- printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: create_singlethreaded_workqueue failed\n", __FUNCTION__, psSwapChain->uiFBDevID);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: Couldn't create workqueue\n", __FUNCTION__, psSwapChain->uiFBDevID);
return (OMAPLFB_ERROR_INIT_FAILURE);
}
return (OMAPLFB_OK);
}
+/* Prepare buffer for insertion into a swap chain work queue */
void OMAPLFBInitBufferForSwap(OMAPLFB_BUFFER *psBuffer)
{
INIT_WORK(&psBuffer->sWork, WorkQueueHandler);
}
+/* Destroy a swap chain work queue */
void OMAPLFBDestroySwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
{
destroy_workqueue(psSwapChain->psWorkQueue);
}
+/* Flip display to given buffer */
void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer)
{
struct fb_var_screeninfo sFBVar;
int res;
unsigned long ulYResVirtual;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+
+ OMAPLFB_CONSOLE_LOCK();
sFBVar = psDevInfo->psLINFBInfo->var;
sFBVar.yoffset = psBuffer->ulYOffset;
ulYResVirtual = psBuffer->ulYOffset + sFBVar.yres;
-
+
+#if defined(CONFIG_DSSCOMP)
+ {
+ /*
+ * If using DSSCOMP, we need to use dsscomp queuing for normal
+ * framebuffer updates, so that previously used overlays get
+ * automatically disabled, and manager gets dirtied. We can
+ * do that because DSSCOMP takes ownership of all pipelines on
+ * a manager.
+ */
+ struct fb_fix_screeninfo sFBFix = psDevInfo->psLINFBInfo->fix;
+ struct dsscomp_setup_dispc_data d =
+ {
+ .num_ovls = 1,
+ .num_mgrs = 1,
+ .mgrs[0].alpha_blending = 1,
+ .ovls[0] =
+ {
+ .cfg =
+ {
+ .win.w = sFBVar.xres,
+ .win.h = sFBVar.yres,
+ .crop.x = sFBVar.xoffset,
+ .crop.y = sFBVar.yoffset,
+ .crop.w = sFBVar.xres,
+ .crop.h = sFBVar.yres,
+ .width = sFBVar.xres_virtual,
+ .height = sFBVar.yres_virtual,
+ .stride = sFBFix.line_length,
+ .enabled = 1,
+ .global_alpha = 255,
+ },
+ },
+ };
+
+ /* do not map buffer into TILER1D as it is contiguous */
+ struct tiler_pa_info *pas[] = { NULL };
+
+ d.ovls[0].ba = sFBFix.smem_start;
+ omapfb_mode_to_dss_mode(&sFBVar, &d.ovls[0].cfg.color_mode);
+
+ res = dsscomp_gralloc_queue(&d, pas, true, NULL, NULL);
+ }
+#else /* defined(CONFIG_DSSCOMP) */
+ /*
+ * PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY should be defined to work
+ * around flipping problems seen with the Taal LCDs on Blaze.
+ * The work around is safe to use with other types of screen on Blaze
+ * (e.g. HDMI) and on other platforms (e.g. Panda board).
+ */
+#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
+ /*
+ * Attempt to change the virtual screen resolution if it is too
+ * small. Note that fb_set_var also pans the display.
+ */
if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
+#endif /* !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) */
{
sFBVar.xres_virtual = sFBVar.xres;
sFBVar.yres_virtual = ulYResVirtual;
res = fb_set_var(psDevInfo->psLINFBInfo, &sFBVar);
if (res != 0)
{
- printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
}
}
+#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
else
{
res = fb_pan_display(psDevInfo->psLINFBInfo, &sFBVar);
if (res != 0)
{
- printk (" fb_pan api failed \n");
- printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
}
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
+#endif /* !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) */
+#endif /* defined(CONFIG_DSSCOMP) */
+
+ OMAPLFB_CONSOLE_UNLOCK();
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
+#if !defined(PVR_OMAPLFB_DRM_FB) || defined(DEBUG)
+static OMAPLFB_BOOL OMAPLFBValidateDSSUpdateMode(enum omap_dss_update_mode eMode)
+{
+ switch (eMode)
+ {
+ case OMAP_DSS_UPDATE_AUTO:
+ case OMAP_DSS_UPDATE_MANUAL:
+ case OMAP_DSS_UPDATE_DISABLED:
+ return OMAPLFB_TRUE;
+ default:
+ break;
+ }
+
+ return OMAPLFB_FALSE;
+}
+
+static OMAPLFB_UPDATE_MODE OMAPLFBFromDSSUpdateMode(enum omap_dss_update_mode eMode)
+{
+ switch (eMode)
+ {
+ case OMAP_DSS_UPDATE_AUTO:
+ return OMAPLFB_UPDATE_MODE_AUTO;
+ case OMAP_DSS_UPDATE_MANUAL:
+ return OMAPLFB_UPDATE_MODE_MANUAL;
+ case OMAP_DSS_UPDATE_DISABLED:
+ return OMAPLFB_UPDATE_MODE_DISABLED;
+ default:
+ break;
+ }
+
+ return OMAPLFB_UPDATE_MODE_UNDEFINED;
+}
#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
+static OMAPLFB_BOOL OMAPLFBValidateUpdateMode(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return OMAPLFB_TRUE;
+ default:
+ break;
+ }
+
+ return OMAPLFB_FALSE;
+}
+#endif
+#if 0
+static enum omap_dss_update_mode OMAPLFBToDSSUpdateMode(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ return OMAP_DSS_UPDATE_AUTO;
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ return OMAP_DSS_UPDATE_MANUAL;
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return OMAP_DSS_UPDATE_DISABLED;
+ default:
+ break;
+ }
+
+ return -1;
+}
+#endif
+#if defined(DEBUG)
+static const char *OMAPLFBUpdateModeToString(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ return "Auto Update Mode";
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ return "Manual Update Mode";
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return "Update Mode Disabled";
+ case OMAPLFB_UPDATE_MODE_UNDEFINED:
+ return "Update Mode Undefined";
+ default:
+ break;
+ }
+
+ return "Unknown Update Mode";
+}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
+static const char *OMAPLFBDSSUpdateModeToString(enum omap_dss_update_mode eMode)
+{
+
+ if (!OMAPLFBValidateDSSUpdateMode(eMode))
+ {
+ return "Unknown Update Mode";
+ }
+
+ return OMAPLFBUpdateModeToString(OMAPLFBFromDSSUpdateMode(eMode));
+}
+#endif
+void OMAPLFBPrintInfo(OMAPLFB_DEVINFO *psDevInfo)
+{
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+ unsigned uConnectors;
+ unsigned uConnector;
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: DRM framebuffer\n", psDevInfo->uiFBDevID));
+
+ for (psConnector = NULL, uConnectors = 0;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ uConnectors++;
+ }
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: Number of screens (DRM connectors): %u\n", psDevInfo->uiFBDevID, uConnectors));
+
+ if (uConnectors == 0)
+ {
+ return;
+ }
+
+ for (psConnector = NULL, uConnector = 0;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL; uConnector++)
+ {
+ enum omap_dss_update_mode eMode = omap_connector_get_update_mode(psConnector);
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: Screen %u: %s (%d)\n", psDevInfo->uiFBDevID, uConnector, OMAPLFBDSSUpdateModeToString(eMode), (int)eMode));
+
+ }
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
+ OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: non-DRM framebuffer\n", psDevInfo->uiFBDevID));
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: %s\n", psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
}
+#endif /* defined(DEBUG) */
+/*
+ * Get display update mode.
+ * If the mode is AUTO, we can wait for VSync, if desired.
+ */
OMAPLFB_UPDATE_MODE OMAPLFBGetUpdateMode(OMAPLFB_DEVINFO *psDevInfo)
{
#if 0
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+ OMAPLFB_UPDATE_MODE eMode = OMAPLFB_UPDATE_MODE_UNDEFINED;
+
+ /*
+ * There may be multiple displays connected. If at least one
+ * display is manual update mode, report all screens as being
+ * in that mode.
+ */
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ switch(omap_connector_get_update_mode(psConnector))
+ {
+ case OMAP_DSS_UPDATE_MANUAL:
+ eMode = OMAPLFB_UPDATE_MODE_MANUAL;
+ break;
+ case OMAP_DSS_UPDATE_DISABLED:
+ if (eMode == OMAPLFB_UPDATE_MODE_UNDEFINED)
+ {
+ eMode = OMAPLFB_UPDATE_MODE_DISABLED;
+ }
+ break;
+ case OMAP_DSS_UPDATE_AUTO:
+ /* Fall through to default case */
+ default:
+ /* Asssume auto update is possible */
+ if (eMode != OMAPLFB_UPDATE_MODE_MANUAL)
+ {
+ eMode = OMAPLFB_UPDATE_MODE_AUTO;
+ }
+ break;
+ }
+ }
+
+ return eMode;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
+
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
enum omap_dss_update_mode eMode;
- if (psDSSDrv == NULL || psDSSDrv->get_update_mode == NULL)
+ if (psDSSDrv == NULL)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Can't get update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No DSS device\n", __FUNCTION__, psDevInfo->uiFBDevID));
return OMAPLFB_UPDATE_MODE_UNDEFINED;
}
- eMode = psDSSDrv->get_update_mode(psDSSDev);
- switch(eMode)
+ if (psDSSDrv->get_update_mode == NULL)
{
- case OMAP_DSS_UPDATE_AUTO:
+ if (strcmp(psDSSDev->name, "hdmi") == 0)
+ {
+ return OMAPLFB_UPDATE_MODE_AUTO;
+ }
+// DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No get_update_mode function\n", __FUNCTION__, psDevInfo->uiFBDevID));
+// return OMAPLFB_UPDATE_MODE_UNDEFINED;
return OMAPLFB_UPDATE_MODE_AUTO;
- case OMAP_DSS_UPDATE_MANUAL:
- return OMAPLFB_UPDATE_MODE_MANUAL;
- case OMAP_DSS_UPDATE_DISABLED:
- return OMAPLFB_UPDATE_MODE_DISABLED;
- default:
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eMode));
- break;
}
- return OMAPLFB_UPDATE_MODE_UNDEFINED;
+ eMode = psDSSDrv->get_update_mode(psDSSDev);
+ if (!OMAPLFBValidateDSSUpdateMode(eMode))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
+ }
+
+ return OMAPLFBFromDSSUpdateMode(eMode);
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
#endif
- return OMAPLFB_UPDATE_MODE_AUTO;
+return OMAPLFB_UPDATE_MODE_AUTO;
}
+/* Set display update mode */
OMAPLFB_BOOL OMAPLFBSetUpdateMode(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_UPDATE_MODE eMode)
{
#if 0
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+ enum omap_dss_update_mode eDSSMode;
+ OMAPLFB_BOOL bSuccess = OMAPLFB_FALSE;
+ OMAPLFB_BOOL bFailure = OMAPLFB_FALSE;
+
+ if (!OMAPLFBValidateUpdateMode(eMode))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
+ return OMAPLFB_FALSE;
+ }
+ eDSSMode = OMAPLFBToDSSUpdateMode(eMode);
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ int iRes = omap_connector_set_update_mode(psConnector, eDSSMode);
+ OMAPLFB_BOOL bRes = (iRes == 0);
+
+
+ bSuccess |= bRes;
+ bFailure |= !bRes;
+ }
+
+ if (!bFailure)
+ {
+ if (!bSuccess)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No screens\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ }
+
+ return OMAPLFB_TRUE;
+ }
+
+ if (!bSuccess)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set %s for any screen\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+ return OMAPLFB_FALSE;
+ }
+
+ if (eMode == OMAPLFB_UPDATE_MODE_AUTO)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set %s for all screens\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+ return OMAPLFB_FALSE;
+ }
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: %s set for some screens\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+
+ return OMAPLFB_TRUE;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
enum omap_dss_update_mode eDSSMode;
if (psDSSDrv == NULL || psDSSDrv->set_update_mode == NULL)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Can't set update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Can't set update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
return OMAPLFB_FALSE;
}
- switch(eMode)
+ if (!OMAPLFBValidateUpdateMode(eMode))
{
- case OMAPLFB_UPDATE_MODE_AUTO:
- eDSSMode = OMAP_DSS_UPDATE_AUTO;
- break;
- case OMAPLFB_UPDATE_MODE_MANUAL:
- eDSSMode = OMAP_DSS_UPDATE_MANUAL;
- break;
- case OMAPLFB_UPDATE_MODE_DISABLED:
- eDSSMode = OMAP_DSS_UPDATE_DISABLED;
- break;
- default:
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eMode));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
return OMAPLFB_FALSE;
}
+ eDSSMode = OMAPLFBToDSSUpdateMode(eMode);
res = psDSSDrv->set_update_mode(psDSSDev, eDSSMode);
if (res != 0)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: set_update_mode failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: set_update_mode (%s) failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBDSSUpdateModeToString(eDSSMode), res));
}
return (res == 0);
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
#endif
- return 1;
+return 1;
}
+/* Wait for VSync */
OMAPLFB_BOOL OMAPLFBWaitForVSync(OMAPLFB_DEVINFO *psDevInfo)
{
-//struct timeval tv;
-//static time_t curtime,curtime1;
-// struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
-// OMAP_DSS_MANAGER(psDSSMan, psDSSDev);
-// printk("Testing vsync\n");
-/* if (psDSSMan != NULL && WAIT_FOR_VSYNC(psDSSMan) != NULL)
- {
- printk("Vsync call\n");
- do_gettimeofday(&tv);
- curtime=tv.tv_usec;
- printk("The time is %ld\n",curtime);
+#if 0
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ (void) omap_encoder_wait_for_vsync(psConnector->encoder);
+ }
+
+ return OMAPLFB_TRUE;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
+ struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
+ OMAP_DSS_MANAGER(psDSSMan, psDSSDev);
+
+ if (psDSSMan != NULL && WAIT_FOR_VSYNC(psDSSMan) != NULL)
+ {
int res = WAIT_FOR_VSYNC(psDSSMan)(psDSSMan);
- do_gettimeofday(&tv);
- curtime1=tv.tv_usec;
- printk("The time is %ld\n",curtime1);
if (res != 0)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Wait for vsync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Wait for vsync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res));
return OMAPLFB_FALSE;
}
- }*/
-#if 0
- struct vps_grpx_ctrl *gctrl;
- int r;
- gctrl = vps_grpx_get_ctrl(psDevInfo->uiFBDevID);
- printk (" BVSYNC \n");
- r = gctrl->wait_for_vsync(gctrl);
- printk (" AVSYNC: %d\n", vsync_num++);
- return OMAPLFB_TRUE;
+ }
+
+ return OMAPLFB_TRUE;
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
#endif
-// unsigned long timeout = msecs_to_jiffies(500);
#if FBDEV_PRESENT
int r;
void grpx_irq_wait_handler(void *data)
{
complete((struct completion *)data);
-// do_gettimeofday(&tv);
+// do_gettimeofday(&tv);
// curtime=tv.tv_usec;
//printk("The time in handler is %ld\n",curtime);
}
}
#endif
return OMAPLFB_TRUE;
+
}
+/*
+ * Wait for screen to update. If the screen is in manual or auto update
+ * mode, we can call this function to wait for the screen to update.
+ */
OMAPLFB_BOOL OMAPLFBManualSync(OMAPLFB_DEVINFO *psDevInfo)
{
#if 0
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL; )
+ {
+ /* Try manual sync first, then try wait for vsync */
+ if (omap_connector_sync(psConnector) != 0)
+ {
+ (void) omap_encoder_wait_for_vsync(psConnector->encoder);
+ }
+ }
+
+ return OMAPLFB_TRUE;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
int res = psDSSDrv->sync(psDSSDev);
if (res != 0)
{
- printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: Sync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: Sync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return OMAPLFB_FALSE;
}
}
-#endif
return OMAPLFB_TRUE;
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
+#endif
+return OMAPLFB_TRUE;
}
+/*
+ * If the screen is manual or auto update mode, wait for the screen to
+ * update.
+ */
OMAPLFB_BOOL OMAPLFBCheckModeAndSync(OMAPLFB_DEVINFO *psDevInfo)
{
OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
return OMAPLFB_TRUE;
}
+/* Linux Framebuffer event notification handler */
static int OMAPLFBFrameBufferEvents(struct notifier_block *psNotif,
unsigned long event, void *data)
{
struct fb_info *psFBInfo = psFBEvent->info;
OMAPLFB_BOOL bBlanked;
-
+ /* Only interested in blanking events */
if (event != FB_EVENT_BLANK)
{
return 0;
return 0;
}
+/* Unblank the screen */
OMAPLFB_ERROR OMAPLFBUnblankDisplay(OMAPLFB_DEVINFO *psDevInfo)
{
- int res;
#ifdef FBDEV_PRESENT
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+ int res;
+
+ OMAPLFB_CONSOLE_LOCK();
res = fb_blank(psDevInfo->psLINFBInfo, 0);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
if (res != 0 && res != -EINVAL)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: fb_blank failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return (OMAPLFB_ERROR_GENERIC);
}
#endif
-
return (OMAPLFB_OK);
}
#ifdef CONFIG_HAS_EARLYSUSPEND
+/* Blank the screen */
static void OMAPLFBBlankDisplay(OMAPLFB_DEVINFO *psDevInfo)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+ OMAPLFB_CONSOLE_LOCK();
fb_blank(psDevInfo->psLINFBInfo, 1);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
}
static void OMAPLFBEarlySuspendHandler(struct early_suspend *h)
}
}
-#endif
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+/* Set up Linux Framebuffer event notification */
OMAPLFB_ERROR OMAPLFBEnableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
{
int res;
OMAPLFB_ERROR eError;
-
+ /* Set up Linux Framebuffer event notification */
memset(&psDevInfo->sLINNotifBlock, 0, sizeof(psDevInfo->sLINNotifBlock));
psDevInfo->sLINNotifBlock.notifier_call = OMAPLFBFrameBufferEvents;
res = fb_register_client(&psDevInfo->sLINNotifBlock);
if (res != 0)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: fb_register_client failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return (OMAPLFB_ERROR_GENERIC);
eError = OMAPLFBUnblankDisplay(psDevInfo);
if (eError != OMAPLFB_OK)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: UnblankDisplay failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eError);
return eError;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
psDevInfo->sEarlySuspend.suspend = OMAPLFBEarlySuspendHandler;
psDevInfo->sEarlySuspend.resume = OMAPLFBEarlyResumeHandler;
- psDevInfo->sEarlySuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
+ psDevInfo->sEarlySuspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1;
register_early_suspend(&psDevInfo->sEarlySuspend);
#endif
return (OMAPLFB_OK);
}
+/* Disable Linux Framebuffer event notification */
OMAPLFB_ERROR OMAPLFBDisableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
{
int res;
unregister_early_suspend(&psDevInfo->sEarlySuspend);
#endif
-
+ /* Unregister for Framebuffer events */
res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
if (res != 0)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: fb_unregister_client failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return (OMAPLFB_ERROR_GENERIC);
}
}
}
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: PVR Device %u: Couldn't find device\n", __FUNCTION__, uiPVRDevID);
return NULL;
}
-int PVR_DRM_MAKENAME(omaplfb, _Ioctl)(struct drm_device unref__ *dev, void *arg, struct drm_file unref__ *pFile)
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(struct drm_device unref__ *dev, void *arg, struct drm_file unref__ *pFile)
{
uint32_t *puiArgs;
uint32_t uiCmd;
pszMode = "(Unknown Mode)";
break;
}
- printk (KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: Display %s\n",
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: Display %s\n",
__FUNCTION__, uiPVRDevID, pszMode);
}
#endif
{
flush_workqueue(psDevInfo->psSwapChain->psWorkQueue);
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
- ret = fb_blank(psDevInfo->psLINFBInfo, iFBMode);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_LOCK();
+ ret = fb_blank(psDevInfo->psLINFBInfo, iFBMode);
+ OMAPLFB_CONSOLE_UNLOCK();
OMAPLFBCreateSwapChainUnLock(psDevInfo);
}
#endif
+/* Insert the driver into the kernel */
#if defined(SUPPORT_DRI_DRM)
-int PVR_DRM_MAKENAME(omaplfb, _Init)(struct drm_device unref__ *dev)
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device unref__ *dev)
#else
static int __init OMAPLFB_Init(void)
#endif
if(OMAPLFBInit() != OMAPLFB_OK)
{
- printk(KERN_WARNING DRIVER_PREFIX ": %s: OMAPLFBInit failed\n", __FUNCTION__);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: OMAPLFBInit failed\n", __FUNCTION__);
return -ENODEV;
}
}
+/* Remove the driver from the kernel */
#if defined(SUPPORT_DRI_DRM)
-void PVR_DRM_MAKENAME(omaplfb, _Cleanup)(struct drm_device unref__ *dev)
+void PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device unref__ *dev)
#else
static void __exit OMAPLFB_Cleanup(void)
#endif
{
if(OMAPLFBDeInit() != OMAPLFB_OK)
{
- printk(KERN_WARNING DRIVER_PREFIX ": %s: OMAPLFBDeInit failed\n", __FUNCTION__);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: OMAPLFBDeInit failed\n", __FUNCTION__);
}
}
#if !defined(SUPPORT_DRI_DRM)
+/*
+ These macro calls define the initialisation and removal functions of the
+ driver. Although they are prefixed `module_', they apply when compiling
+ statically as well; in both cases they define the function the kernel will
+ run to start/stop the driver.
+*/
late_initcall(OMAPLFB_Init);
module_exit(OMAPLFB_Cleanup);
#endif
-/**********************************************************************
- *
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OMAP Linux display driver shared DRM structures
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OMAP Linux display driver DRM structures shared between
+ kernel and user space.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __3RDPARTY_DC_DRM_SHARED_H__
#define __3RDPARTY_DC_DRM_SHARED_H__
#if defined(SUPPORT_DRI_DRM)
#define PVR_DRM_DISP_ARG_DEV 1
#define PVR_DRM_DISP_NUM_ARGS 2
-#endif
-#endif
+#endif /* defined(SUPPORT_DRI_DRM) */
+#endif /* __3RDPARTY_DC_DRM_SHARED_H__ */
+/******************************************************************************
+ End of file (3rdparty_dc_drm_shared.h)
+******************************************************************************/
-I$(PVR_BUILD_DIR)/include4 \
-I$(PVR_BUILD_DIR)/services4/include \
-I$(PVR_BUILD_DIR)/services4/system/$(PVR_SYSTEM) \
+ -I$(KERNELDIR)/drivers/video/omap2 \
-I$(PVR_BUILD_DIR)/services4/system/include \
$(SYS_CFLAGS.1) \
--- /dev/null
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
+#
+# The contents of this file are subject to the MIT license as set out below.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
+#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+### ###########################################################################
+
+ccflags-y += \
+ -I$(TOP)/services4/3rdparty/dc_omapfb3_linux \
+ -I$(KERNELDIR)/drivers/video/omap2 \
+ -I$(KERNELDIR)/arch/arm/plat-omap/include
+
+omaplfb-y += \
+ services4/3rdparty/dc_omapfb3_linux/omaplfb_displayclass.o \
+ services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.o
--- /dev/null
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
+#
+# The contents of this file are subject to the MIT license as set out below.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
+#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+### ###########################################################################
+
+modules := dc_omapfb3_linux
+
+dc_omapfb3_linux_type := kernel_module
+dc_omapfb3_linux_target := omaplfb.ko
+dc_omapfb3_linux_makefile := $(THIS_DIR)/Kbuild.mk
+++ /dev/null
-#
-# Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
-#
-#
-
-MODULE = $(DISPLAY_CONTROLLER)
-
-INCLUDES =
-
-SOURCES =
-
-SYM_VERS_DEPS = $(EURASIAROOT)/services4/srvkm/env/linux
-
-include $(EURASIAROOT)/services4/$(DISPLAY_CONTROLLER_DIR)/makefile.linux.common
-
-include $(EURASIAROOT)/eurasiacon/build/linux/kbuild/Makefile.kbuild_subdir_common
+++ /dev/null
-#
-# Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
-#
-#
-#
-
-ifeq ($(SUPPORT_DRI_DRM),1)
-DISPLAY_CONTROLLER_SOURCES_ROOT = $(KBUILDROOT)/$(DISPLAY_CONTROLLER_DIR)
-MODULE_CFLAGS += -DPVR_DISPLAY_CONTROLLER_DRM_IOCTL
-else
-DISPLAY_CONTROLLER_SOURCES_ROOT = ..
-endif
-
-INCLUDES += -I$(EURASIAROOT)/include4 \
- -I$(EURASIAROOT)/services4/include \
- -I$(EURASIAROOT)/services4/system/$(PVR_SYSTEM) \
- -I$(EURASIAROOT)/services4/system/include \
- -I$(KERNELDIR)/drivers/video/omap2 \
- -I$(KERNELDIR)/arch/arm/plat-omap/include
-
-SOURCES += $(DISPLAY_CONTROLLER_SOURCES_ROOT)/omaplfb_displayclass.c \
- $(DISPLAY_CONTROLLER_SOURCES_ROOT)/omaplfb_linux.c
-/**********************************************************************
- *
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title OMAP Linux display driver structures and prototypes
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __OMAPLFB_H__
#define __OMAPLFB_H__
#include <linux/earlysuspend.h>
#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+#define OMAPLFB_CONSOLE_LOCK() console_lock()
+#define OMAPLFB_CONSOLE_UNLOCK() console_unlock()
+#else
+#define OMAPLFB_CONSOLE_LOCK() acquire_console_sem()
+#define OMAPLFB_CONSOLE_UNLOCK() release_console_sem()
+#endif
+
#define unref__ __attribute__ ((unused))
typedef void * OMAPLFB_HANDLE;
typedef atomic_t OMAPLFB_ATOMIC_INT;
+/* OMAPLFB buffer structure */
typedef struct OMAPLFB_BUFFER_TAG
{
struct OMAPLFB_BUFFER_TAG *psNext;
struct work_struct sWork;
-
+ /* Position of this buffer in the virtual framebuffer */
unsigned long ulYOffset;
-
-
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
IMG_SYS_PHYADDR sSysAddr;
IMG_CPU_VIRTADDR sCPUVAddr;
PVRSRV_SYNC_DATA *psSyncData;
unsigned long ulSwapInterval;
} OMAPLFB_BUFFER;
+/* OMAPLFB swapchain structure */
typedef struct OMAPLFB_SWAPCHAIN_TAG
{
-
+ /* Swap chain ID */
unsigned int uiSwapChainID;
-
+ /* number of buffers in swapchain */
unsigned long ulBufferCount;
-
+ /* list of buffers in the swapchain */
OMAPLFB_BUFFER *psBuffer;
-
+ /* Swap chain work queue */
struct workqueue_struct *psWorkQueue;
-
+ /*
+ * Set if we didn't manage to wait for VSync on last swap,
+ * or if we think we need to wait for VSync on the next flip.
+ * The flag helps to avoid jitter when the screen is
+ * unblanked, by forcing an extended wait for VSync before
+ * attempting the next flip.
+ */
OMAPLFB_BOOL bNotVSynced;
-
+ /* Previous number of blank events */
int iBlankEvents;
-
+ /* Framebuffer Device ID for messages (e.g. printk) */
unsigned int uiFBDevID;
} OMAPLFB_SWAPCHAIN;
unsigned long ulPhysicalWidthmm;
unsigned long ulPhysicalHeightmm;
-
-
- IMG_SYS_PHYADDR sSysAddr;
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
+ IMG_SYS_PHYADDR sSysAddr;//system physical address
IMG_CPU_VIRTADDR sCPUVAddr;
-
+ /* pixelformat of system/primary surface */
PVRSRV_PIXEL_FORMAT ePixelFormat;
-}OMAPLFB_FBINFO;
+#if defined(CONFIG_DSSCOMP)
+ OMAPLFB_BOOL bIs2D;
+ IMG_SYS_PHYADDR *psPageList;
+ struct ion_handle *psIONHandle;
+ IMG_UINT32 uiBytesPerPixel;
+#endif
+} OMAPLFB_FBINFO;
+
+/* kernel device information structure */
typedef struct OMAPLFB_DEVINFO_TAG
{
-
+ /* Framebuffer Device ID */
unsigned int uiFBDevID;
-
+ /* PVR Device ID */
unsigned int uiPVRDevID;
-
+ /* Swapchain create/destroy mutex */
struct mutex sCreateSwapChainMutex;
-
+ /* system surface info */
OMAPLFB_BUFFER sSystemBuffer;
-
+ /* jump table into PVR services */
PVRSRV_DC_DISP2SRV_KMJTABLE sPVRJTable;
-
+ /* jump table into DC */
PVRSRV_DC_SRV2DISP_KMJTABLE sDCJTable;
-
+ /* fb info structure */
OMAPLFB_FBINFO sFBInfo;
-
+ /* Only one swapchain supported by this device so hang it here */
OMAPLFB_SWAPCHAIN *psSwapChain;
-
+ /* Swap chain ID */
unsigned int uiSwapChainID;
-
+ /* True if PVR Services is flushing its command queues */
OMAPLFB_ATOMIC_BOOL sFlushCommands;
-
+ /* pointer to linux frame buffer information structure */
struct fb_info *psLINFBInfo;
-
+ /* Linux Framebuffer event notification block */
struct notifier_block sLINNotifBlock;
-
-
+ /* IMG structures used, to minimise API function code */
+ /* replace with own structures where necessary */
-
+ /* Address of the surface being displayed */
IMG_DEV_VIRTADDR sDisplayDevVAddr;
DISPLAY_INFO sDisplayInfo;
-
+ /* Display format */
DISPLAY_FORMAT sDisplayFormat;
-
+ /* Display dimensions */
DISPLAY_DIMS sDisplayDim;
-
+ /* True if screen is blanked */
OMAPLFB_ATOMIC_BOOL sBlanked;
-
+ /* Number of blank/unblank events */
OMAPLFB_ATOMIC_INT sBlankEvents;
#ifdef CONFIG_HAS_EARLYSUSPEND
-
+ /* Set by early suspend */
OMAPLFB_ATOMIC_BOOL sEarlySuspendFlag;
struct early_suspend sEarlySuspend;
#define OMAPLFB_PAGE_SIZE 4096
+/* DEBUG only printk */
#ifdef DEBUG
#define DEBUG_PRINTK(x) printk x
#else
#define DEVNAME DRVNAME
#define DRIVER_PREFIX DRVNAME
+/*!
+ *****************************************************************************
+ * Error values
+ *****************************************************************************/
typedef enum _OMAPLFB_ERROR_
{
OMAPLFB_OK = 0,
OMAPLFB_ERROR OMAPLFBInit(void);
OMAPLFB_ERROR OMAPLFBDeInit(void);
+/* OS Specific APIs */
OMAPLFB_DEVINFO *OMAPLFBGetDevInfoPtr(unsigned uiFBDevID);
unsigned OMAPLFBMaxFBDevIDPlusOne(void);
void *OMAPLFBAllocKernelMem(unsigned long ulSize);
int OMAPLFBAtomicIntRead(OMAPLFB_ATOMIC_INT *psAtomic);
void OMAPLFBAtomicIntInc(OMAPLFB_ATOMIC_INT *psAtomic);
-#endif
+#if defined(DEBUG)
+void OMAPLFBPrintInfo(OMAPLFB_DEVINFO *psDevInfo);
+#else
+#define OMAPLFBPrintInfo(psDevInfo)
+#endif
+
+#endif /* __OMAPLFB_H__ */
+
+/******************************************************************************
+ End of file (omaplfb.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OMAP common display driver components
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
+/**************************************************************************
+ The 3rd party driver is a specification of an API to integrate the IMG POWERVR
+ Services driver with 3rd Party display hardware. It is NOT a specification for
+ a display controller driver, rather a specification to extend the API for a
+ pre-existing driver for the display hardware.
+
+ The 3rd party driver interface provides IMG POWERVR client drivers (e.g. PVR2D)
+ with an API abstraction of the system's underlying display hardware, allowing
+ the client drivers to indirectly control the display hardware and access its
+ associated memory.
+
+ Functions of the API include
+ - query primary surface attributes (width, height, stride, pixel format, CPU
+ physical and virtual address)
+ - swap/flip chain creation and subsequent query of surface attributes
+ - asynchronous display surface flipping, taking account of asynchronous read
+ (flip) and write (render) operations to the display surface
+
+ Note: having queried surface attributes the client drivers are able to map the
+ display memory to any IMG POWERVR Services device by calling
+ PVRSRVMapDeviceClassMemory with the display surface handle.
+
+ This code is intended to be an example of how a pre-existing display driver may
+ be extended to support the 3rd Party Display interface to POWERVR Services
+ - IMG is not providing a display driver implementation.
+ **************************************************************************/
+
+/*
+ * OMAP Linux 3rd party display driver.
+ * This is based on the Generic PVR Linux Framebuffer 3rd party display
+ * driver, with OMAP specific extensions to support flipping.
+ */
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/notifier.h>
+/* IMG services headers */
#include "img_defs.h"
#include "servicesext.h"
#include "kerneldisplay.h"
#include "omaplfb.h"
+#if defined(CONFIG_DSSCOMP)
+
+#if !defined(CONFIG_ION_OMAP)
+#error CONFIG_DSSCOMP support requires CONFIG_ION_OMAP
+#endif
+
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+
+extern struct ion_client *gpsIONClient;
+
+#include <mach/tiler.h>
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+
+#endif /* defined(CONFIG_DSSCOMP) */
+
#define OMAPLFB_COMMAND_COUNT 1
#define OMAPLFB_VSYNC_SETTLE_COUNT 5
-#define OMAPLFB_MAX_NUM_DEVICES 1 // FB_MAX
+//#define OMAPLFB_MAX_NUM_DEVICES FB_MAX
+#define OMAPLFB_MAX_NUM_DEVICES 1
#if (OMAPLFB_MAX_NUM_DEVICES > FB_MAX)
#error "OMAPLFB_MAX_NUM_DEVICES must not be greater than FB_MAX"
#endif
static OMAPLFB_DEVINFO *gapsDevInfo[OMAPLFB_MAX_NUM_DEVICES];
+/* Top level 'hook ptr' */
static PFN_DC_GET_PVRJTABLE gpfnGetPVRJTable = NULL;
+/* Round x up to a multiple of y */
static inline unsigned long RoundUpToMultiple(unsigned long x, unsigned long y)
{
unsigned long div = x / y;
return (div + ((rem == 0) ? 0 : 1)) * y;
}
+/* Greatest common divisor of x and y */
static unsigned long GCD(unsigned long x, unsigned long y)
{
while (y != 0)
return x;
}
+/* Least common multiple of x and y */
static unsigned long LCM(unsigned long x, unsigned long y)
{
unsigned long gcd = GCD(x, y);
return OMAPLFB_MAX_NUM_DEVICES;
}
+/* Returns DevInfo pointer for a given device */
OMAPLFB_DEVINFO *OMAPLFBGetDevInfoPtr(unsigned uiFBDevID)
{
WARN_ON(uiFBDevID >= OMAPLFBMaxFBDevIDPlusOne());
return gapsDevInfo[uiFBDevID];
}
+/* Sets the DevInfo pointer for a given device */
static inline void OMAPLFBSetDevInfoPtr(unsigned uiFBDevID, OMAPLFB_DEVINFO *psDevInfo)
{
WARN_ON(uiFBDevID >= OMAPLFB_MAX_NUM_DEVICES);
(psDevInfo->uiSwapChainID != psSwapChain->uiSwapChainID);
}
+/* Don't wait for vertical sync */
static inline OMAPLFB_BOOL DontWaitForVSync(OMAPLFB_DEVINFO *psDevInfo)
{
OMAPLFB_BOOL bDontWait;
return bDontWait;
}
+/*
+ * SetDCState
+ * Called from services.
+ */
static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
{
OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)hDevice;
case DC_STATE_NO_FLUSH_COMMANDS:
OMAPLFBAtomicBoolSet(&psDevInfo->sFlushCommands, OMAPLFB_FALSE);
break;
+ case DC_STATE_FORCE_SWAP_TO_SYSTEM:
+ OMAPLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer);
+ break;
default:
break;
}
}
+/*
+ * OpenDCDevice
+ * Called from services.
+ */
static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 uiPVRDevID,
IMG_HANDLE *phDevice,
PVRSRV_SYNC_DATA* psSystemBufferSyncData)
return PVRSRV_ERROR_INVALID_DEVICE;
}
-
+ /* store the system surface sync data */
psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
eError = OMAPLFBUnblankDisplay(psDevInfo);
return PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED;
}
-
+ /* return handle to the devinfo */
*phDevice = (IMG_HANDLE)psDevInfo;
return PVRSRV_OK;
}
+/*
+ * CloseDCDevice
+ * Called from services.
+ */
static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
{
#if defined(SUPPORT_DRI_DRM)
return PVRSRV_OK;
}
+/*
+ * EnumDCFormats
+ * Called from services.
+ */
static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
IMG_UINT32 *pui32NumFormats,
DISPLAY_FORMAT *psFormat)
return PVRSRV_OK;
}
+/*
+ * EnumDCDims
+ * Called from services.
+ */
static PVRSRV_ERROR EnumDCDims(IMG_HANDLE hDevice,
DISPLAY_FORMAT *psFormat,
IMG_UINT32 *pui32NumDims,
*pui32NumDims = 1;
-
+ /* No need to look at psFormat; there is only one */
if(psDim)
{
psDim[0] = psDevInfo->sDisplayDim;
}
+/*
+ * GetDCSystemBuffer
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE hDevice, IMG_HANDLE *phBuffer)
{
OMAPLFB_DEVINFO *psDevInfo;
}
+/*
+ * GetDCInfo
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCInfo(IMG_HANDLE hDevice, DISPLAY_INFO *psDCInfo)
{
OMAPLFB_DEVINFO *psDevInfo;
return PVRSRV_OK;
}
+/*
+ * GetDCBufferAddr
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE hDevice,
IMG_HANDLE hBuffer,
IMG_SYS_PHYADDR **ppsSysAddr,
if (ppvCpuVAddr)
{
+#if defined(CONFIG_DSSCOMP)
+ *ppvCpuVAddr = psDevInfo->sFBInfo.bIs2D ? NULL : psSystemBuffer->sCPUVAddr;
+#else
*ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
+#endif
}
if (phOSMapInfo)
if (pbIsContiguous)
{
+#if defined(CONFIG_DSSCOMP)
+ *pbIsContiguous = !psDevInfo->sFBInfo.bIs2D;
+#else
*pbIsContiguous = IMG_TRUE;
+#endif
}
+#if defined(CONFIG_DSSCOMP)
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ int i = (psSystemBuffer->sSysAddr.uiAddr - psDevInfo->sFBInfo.psPageList->uiAddr) >> PAGE_SHIFT;
+ *ppsSysAddr = psDevInfo->sFBInfo.psPageList + psDevInfo->sFBInfo.ulHeight * i;
+ }
+#endif
+
return PVRSRV_OK;
}
+/*
+ * CreateDCSwapChain
+ * Called from services.
+ */
static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
IMG_UINT32 ui32Flags,
DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
UNREFERENCED_PARAMETER(ui32OEMFlags);
-
+ /* Check parameters */
if(!hDevice
|| !psDstSurfAttrib
|| !psSrcSurfAttrib
psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
-
+ /* Do we support swap chains? */
if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
{
return PVRSRV_ERROR_NOT_SUPPORTED;
OMAPLFBCreateSwapChainLock(psDevInfo);
-
+ /* The driver only supports a single swapchain */
if(psDevInfo->psSwapChain != NULL)
{
eError = PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
goto ExitUnLock;
}
-
+ /* Check the buffer count */
if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
{
eError = PVRSRV_ERROR_TOOMANYBUFFERS;
goto ExitUnLock;
}
-
+ /*
+ * We will allocate the swap chain buffers at the back of the frame
+ * buffer area. This preserves the front portion, which may be being
+ * used by other Linux Framebuffer based applications.
+ */
ui32BuffersToSkip = psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers - ui32BufferCount;
-
+ /*
+ * Verify the DST/SRC attributes,
+ * SRC/DST must match the current display mode config
+ */
if(psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat
|| psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride
|| psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width
|| psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height)
{
-
+ /* DST doesn't match the current mode */
eError = PVRSRV_ERROR_INVALID_PARAMS;
goto ExitUnLock;
}
|| psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width
|| psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height)
{
-
+ /* DST doesn't match the SRC */
eError = PVRSRV_ERROR_INVALID_PARAMS;
goto ExitUnLock;
}
-
+ /* check flags if implementation requires them */
UNREFERENCED_PARAMETER(ui32Flags);
#if defined(PVR_OMAPFB3_UPDATE_MODE)
printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set frame buffer update mode %d\n", __FUNCTION__, psDevInfo->uiFBDevID, PVR_OMAPFB3_UPDATE_MODE);
}
#endif
-
+ /* create a swapchain structure */
psSwapChain = (OMAPLFB_SWAPCHAIN*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_SWAPCHAIN));
if(!psSwapChain)
{
psSwapChain->bNotVSynced = OMAPLFB_TRUE;
psSwapChain->uiFBDevID = psDevInfo->uiFBDevID;
-
+ /* Link the buffers */
for(i=0; i<ui32BufferCount-1; i++)
{
psBuffer[i].psNext = &psBuffer[i+1];
}
-
+ /* and link last to first */
psBuffer[i].psNext = &psBuffer[0];
-
+ /* Configure the swapchain buffers */
for(i=0; i<ui32BufferCount; i++)
{
IMG_UINT32 ui32SwapBuffer = i + ui32BuffersToSkip;
IMG_UINT32 ui32BufferOffset = ui32SwapBuffer * (IMG_UINT32)psDevInfo->sFBInfo.ulRoundedBufferSize;
+#if defined(CONFIG_DSSCOMP)
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ ui32BufferOffset = 0;
+ }
+#endif /* defined(CONFIG_DSSCOMP) */
+
psBuffer[i].psSyncData = ppsSyncData[i];
psBuffer[i].sSysAddr.uiAddr = psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
psBuffer[i].ulYOffset = ui32BufferOffset / psDevInfo->sFBInfo.ulByteStride;
psBuffer[i].psDevInfo = psDevInfo;
+#if defined(CONFIG_DSSCOMP)
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ psBuffer[i].sSysAddr.uiAddr += ui32SwapBuffer *
+ ALIGN((IMG_UINT32)psDevInfo->sFBInfo.ulWidth * psDevInfo->sFBInfo.uiBytesPerPixel, PAGE_SIZE);
+ }
+#endif /* defined(CONFIG_DSSCOMP) */
+
OMAPLFBInitBufferForSwap(&psBuffer[i]);
}
return eError;
}
+/*
+ * DestroyDCSwapChain
+ * Called from services.
+ */
static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain)
{
OMAPLFB_SWAPCHAIN *psSwapChain;
OMAPLFB_ERROR eError;
-
+ /* Check parameters */
if(!hDevice || !hSwapChain)
{
return PVRSRV_ERROR_INVALID_PARAMS;
goto ExitUnLock;
}
-
+ /* The swap queue is flushed before being destroyed */
OMAPLFBDestroySwapQueue(psSwapChain);
eError = OMAPLFBDisableLFBEventNotification(psDevInfo);
printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't disable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID);
}
-
+ /* Free resources */
OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
OMAPLFBFreeKernelMem(psSwapChain);
return eError;
}
+/*
+ * SetDCDstRect
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_RECT *psRect)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(psRect);
-
+ /* Only full display swapchains on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * SetDCSrcRect
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_RECT *psRect)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(psRect);
-
+ /* Only full display swapchains on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * SetDCDstColourKey
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_UINT32 ui32CKColour)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(ui32CKColour);
-
+ /* Don't support DST CK on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * SetDCSrcColourKey
+ * Called from services.
+ */
static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_UINT32 ui32CKColour)
UNREFERENCED_PARAMETER(hSwapChain);
UNREFERENCED_PARAMETER(ui32CKColour);
-
+ /* Don't support SRC CK on this device */
return PVRSRV_ERROR_NOT_SUPPORTED;
}
+/*
+ * GetDCBuffers
+ * Called from services.
+ */
static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice,
IMG_HANDLE hSwapChain,
IMG_UINT32 *pui32BufferCount,
PVRSRV_ERROR eError;
unsigned i;
-
+ /* Check parameters */
if(!hDevice
|| !hSwapChain
|| !pui32BufferCount
goto Exit;
}
-
+ /* Return the buffer count */
*pui32BufferCount = (IMG_UINT32)psSwapChain->ulBufferCount;
-
+ /* Return the buffers */
for(i=0; i<psSwapChain->ulBufferCount; i++)
{
phBuffer[i] = (IMG_HANDLE)&psSwapChain->psBuffer[i];
return eError;
}
+/*
+ * SwapToDCBuffer
+ * Called from services.
+ */
static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE hDevice,
IMG_HANDLE hBuffer,
IMG_UINT32 ui32SwapInterval,
UNREFERENCED_PARAMETER(ui32ClipRectCount);
UNREFERENCED_PARAMETER(psClipRect);
-
+ /* * Nothing to do since Services common code does the work */
return PVRSRV_OK;
}
-static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE hDevice,
- IMG_HANDLE hSwapChain)
-{
- UNREFERENCED_PARAMETER(hDevice);
- UNREFERENCED_PARAMETER(hSwapChain);
-
-
- return PVRSRV_OK;
-}
-
+/*
+ * Called after the screen has unblanked, or after any other occasion
+ * when we didn't wait for vsync, but now need to. Not doing this after
+ * unblank leads to screen jitter on some screens.
+ * Returns true if the screen has been deemed to have settled.
+ */
static OMAPLFB_BOOL WaitForVSyncSettle(OMAPLFB_DEVINFO *psDevInfo)
{
unsigned i;
return OMAPLFB_TRUE;
}
+/*
+ * Swap handler.
+ * Called from the swap chain work queue handler.
+ * There is no need to take the swap chain creation lock in here, or use
+ * some other method of stopping the swap chain from being destroyed.
+ * This is because the swap chain creation lock is taken when queueing work,
+ * and the work queue is flushed before the swap chain is destroyed.
+ */
void OMAPLFBSwapHandler(OMAPLFB_BUFFER *psBuffer)
{
OMAPLFB_DEVINFO *psDevInfo = psBuffer->psDevInfo;
psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psBuffer->hCmdComplete, IMG_TRUE);
}
+/* Triggered by PVRSRVSwapToDCBuffer */
+static IMG_BOOL ProcessFlipV1(IMG_HANDLE hCmdCookie,
+ OMAPLFB_DEVINFO *psDevInfo,
+ OMAPLFB_SWAPCHAIN *psSwapChain,
+ OMAPLFB_BUFFER *psBuffer,
+ unsigned long ulSwapInterval)
+{
+ OMAPLFBCreateSwapChainLock(psDevInfo);
+
+ /* The swap chain has been destroyed */
+ if (SwapChainHasChanged(psDevInfo, psSwapChain))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
+ ": %s: Device %u (PVR Device ID %u): The swap chain has been destroyed\n",
+ __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
+ }
+ else
+ {
+ psBuffer->hCmdComplete = (OMAPLFB_HANDLE)hCmdCookie;
+ psBuffer->ulSwapInterval = ulSwapInterval;
+#if defined(CONFIG_DSSCOMP)
+ if (is_tiler_addr(psBuffer->sSysAddr.uiAddr))
+ {
+ IMG_UINT32 w = psBuffer->psDevInfo->sDisplayDim.ui32Width;
+ IMG_UINT32 h = psBuffer->psDevInfo->sDisplayDim.ui32Height;
+ struct dsscomp_setup_dispc_data comp = {
+ .num_mgrs = 1,
+ .mgrs[0].alpha_blending = 1,
+ .num_ovls = 1,
+ .ovls[0].cfg =
+ {
+ .width = w,
+ .win.w = w,
+ .crop.w = w,
+ .height = h,
+ .win.h = h,
+ .crop.h = h,
+ .stride = psBuffer->psDevInfo->sDisplayDim.ui32ByteStride,
+ .color_mode = OMAP_DSS_COLOR_ARGB32,
+ .enabled = 1,
+ .global_alpha = 255,
+ },
+ .mode = DSSCOMP_SETUP_DISPLAY,
+ };
+ struct tiler_pa_info *pas[1] = { NULL };
+ comp.ovls[0].ba = (u32) psBuffer->sSysAddr.uiAddr;
+ dsscomp_gralloc_queue(&comp, pas, true,
+ (void *) psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete,
+ (void *) psBuffer->hCmdComplete);
+ }
+ else
+#endif /* defined(CONFIG_DSSCOMP) */
+ {
+ OMAPLFBQueueBufferForSwap(psSwapChain, psBuffer);
+ }
+ }
+
+ OMAPLFBCreateSwapChainUnLock(psDevInfo);
+
+ return IMG_TRUE;
+}
+
+#if defined(CONFIG_DSSCOMP)
+
+/* Triggered by PVRSRVSwapToDCBuffer2 */
+static IMG_BOOL ProcessFlipV2(IMG_HANDLE hCmdCookie,
+ OMAPLFB_DEVINFO *psDevInfo,
+ PDC_MEM_INFO *ppsMemInfos,
+ IMG_UINT32 ui32NumMemInfos,
+ struct dsscomp_setup_dispc_data *psDssData,
+ IMG_UINT32 ui32DssDataLength)
+{
+ struct tiler_pa_info *apsTilerPAs[5];
+ IMG_UINT32 i, k;
+
+ if(ui32DssDataLength != sizeof(*psDssData))
+ {
+ WARN(1, "invalid size of private data (%d vs %d)",
+ ui32DssDataLength, sizeof(*psDssData));
+ return IMG_FALSE;
+ }
+
+ if(psDssData->num_ovls == 0 || ui32NumMemInfos == 0)
+ {
+ WARN(1, "must have at least one layer");
+ return IMG_FALSE;
+ }
+
+ for(i = k = 0; i < ui32NumMemInfos && k < ARRAY_SIZE(apsTilerPAs); i++, k++)
+ {
+ struct tiler_pa_info *psTilerInfo;
+ IMG_CPU_VIRTADDR virtAddr;
+ IMG_CPU_PHYADDR phyAddr;
+ IMG_UINT32 ui32NumPages;
+ IMG_SIZE_T uByteSize;
+ int j;
+
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetByteSize(ppsMemInfos[i], &uByteSize);
+ ui32NumPages = (uByteSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ apsTilerPAs[k] = NULL;
+
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], 0, &phyAddr);
+
+ /* NV12 buffers are already mapped to tiler */
+ if(psDssData->ovls[k].cfg.color_mode == OMAP_DSS_COLOR_NV12)
+ {
+ psDssData->ovls[k].ba = (u32)phyAddr.uiAddr;
+
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], (uByteSize * 2) / 3, &phyAddr);
+ psDssData->ovls[k].uv = (u32)phyAddr.uiAddr;
+ continue;
+ }
+
+ /* Other kinds of buffer may also already be mapped to tiler */
+ if(is_tiler_addr((u32)phyAddr.uiAddr))
+ {
+ psDssData->ovls[k].ba = (u32)phyAddr.uiAddr;
+ continue;
+ }
+
+ psTilerInfo = kzalloc(sizeof(*psTilerInfo), GFP_KERNEL);
+ if(!psTilerInfo)
+ {
+ continue;
+ }
+
+ psTilerInfo->mem = kzalloc(sizeof(*psTilerInfo->mem) * ui32NumPages, GFP_KERNEL);
+ if(!psTilerInfo->mem)
+ {
+ kfree(psTilerInfo);
+ continue;
+ }
+
+ psTilerInfo->num_pg = ui32NumPages;
+ psTilerInfo->memtype = TILER_MEM_USING;
+
+ for(j = 0; j < ui32NumPages; j++)
+ {
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], j << PAGE_SHIFT, &phyAddr);
+ psTilerInfo->mem[j] = (u32)phyAddr.uiAddr;
+ }
+
+ /* Need base address for in-page offset */
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuVAddr(ppsMemInfos[i], &virtAddr);
+ psDssData->ovls[k].ba = (u32)virtAddr;
+ apsTilerPAs[k] = psTilerInfo;
+ }
+
+ /* Set up cloned layer addresses (but don't duplicate tiler_pas) */
+ for(i = k; i < psDssData->num_ovls && i < ARRAY_SIZE(apsTilerPAs); i++)
+ {
+ unsigned int ix = psDssData->ovls[i].ba;
+ if(ix >= ARRAY_SIZE(apsTilerPAs))
+ {
+ WARN(1, "Invalid clone layer (%u); skipping all cloned layers", ix);
+ psDssData->num_ovls = k;
+ break;
+ }
+ apsTilerPAs[i] = apsTilerPAs[ix];
+ psDssData->ovls[i].ba = psDssData->ovls[ix].ba;
+ psDssData->ovls[i].uv = psDssData->ovls[ix].uv;
+ }
+
+ dsscomp_gralloc_queue(psDssData, apsTilerPAs, false,
+ (void *)psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete,
+ (void *)hCmdCookie);
+
+ for(i = 0; i < k; i++)
+ {
+ tiler_pa_free(apsTilerPAs[i]);
+ }
+
+ return IMG_TRUE;
+}
+
+#endif /* defined(CONFIG_DSSCOMP) */
+
+/* Command processing flip handler function. Called from services. */
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;
-
+ /* Check parameters */
if(!hCmdCookie || !pvData)
{
return IMG_FALSE;
}
-
+ /* Validate data packet */
psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData;
- if (psFlipCmd == IMG_NULL || sizeof(DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
+ if (psFlipCmd == IMG_NULL)
{
return IMG_FALSE;
}
-
psDevInfo = (OMAPLFB_DEVINFO*)psFlipCmd->hExtDevice;
- psBuffer = (OMAPLFB_BUFFER*)psFlipCmd->hExtBuffer;
- psSwapChain = (OMAPLFB_SWAPCHAIN*) psFlipCmd->hExtSwapChain;
-
- OMAPLFBCreateSwapChainLock(psDevInfo);
- if (SwapChainHasChanged(psDevInfo, psSwapChain))
+ if(psFlipCmd->hExtBuffer)
{
-
- DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
- ": %s: Device %u (PVR Device ID %u): The swap chain has been destroyed\n",
- __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
+ return ProcessFlipV1(hCmdCookie,
+ psDevInfo,
+ psFlipCmd->hExtSwapChain,
+ psFlipCmd->hExtBuffer,
+ psFlipCmd->ui32SwapInterval);
}
else
{
- psBuffer->hCmdComplete = (OMAPLFB_HANDLE)hCmdCookie;
- psBuffer->ulSwapInterval = (unsigned long)psFlipCmd->ui32SwapInterval;
-
- OMAPLFBQueueBufferForSwap(psSwapChain, psBuffer);
+#if defined(CONFIG_DSSCOMP)
+ DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd2;
+ psFlipCmd2 = (DISPLAYCLASS_FLIP_COMMAND2 *)pvData;
+ return ProcessFlipV2(hCmdCookie,
+ psDevInfo,
+ psFlipCmd2->ppsMemInfos,
+ psFlipCmd2->ui32NumMemInfos,
+ psFlipCmd2->pvPrivData,
+ psFlipCmd2->ui32PrivDataLength);
+#else
+ BUG();
+#endif
}
+}
- OMAPLFBCreateSwapChainUnLock(psDevInfo);
+/*!
+******************************************************************************
- return IMG_TRUE;
-}
+ @Function OMAPLFBInitFBDev
+
+ @Description specifies devices in the systems memory map
+
+ @Input psSysData - sys data
+ @Return OMAPLFB_ERROR :
+******************************************************************************/
static OMAPLFB_ERROR OMAPLFBInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
{
struct fb_info *psLINFBInfo;
unsigned long ulLCM;
unsigned uiFBDevID = psDevInfo->uiFBDevID;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+ OMAPLFB_CONSOLE_LOCK();
psLINFBInfo = registered_fb[uiFBDevID];
if (psLINFBInfo == NULL)
psLINFBInfo->screen_size :
psLINFBInfo->fix.smem_len;
-
+ /*
+ * Try and filter out invalid FB info structures (a problem
+ * seen on some OMAP3 systems).
+ */
if (FBSize == 0 || psLINFBInfo->fix.line_length == 0)
{
eError = OMAPLFB_ERROR_INVALID_DEVICE;
": Device %u: LCM of stride and page size: %lu\n",
psDevInfo->uiFBDevID, ulLCM));
-
+ /* Additional implementation specific information */
+ OMAPLFBPrintInfo(psDevInfo);
+
+#if defined(CONFIG_DSSCOMP)
+ {
+ /* for some reason we need at least 3 buffers in the swap chain */
+ int n = FBSize / RoundUpToMultiple(psLINFBInfo->fix.line_length * psLINFBInfo->var.yres, ulLCM);
+ int res;
+ int i, x, y, w;
+ ion_phys_addr_t phys;
+ size_t size;
+ struct tiler_view_t view;
+
+ struct omap_ion_tiler_alloc_data sAllocData =
+ {
+ /* TILER will align width to 128-bytes */
+ /* however, SGX must have full page width */
+ .w = ALIGN(psLINFBInfo->var.xres, PAGE_SIZE / (psLINFBInfo->var.bits_per_pixel / 8)),
+ .h = psLINFBInfo->var.yres,
+ .fmt = psLINFBInfo->var.bits_per_pixel == 16 ? TILER_PIXEL_FMT_16BIT : TILER_PIXEL_FMT_32BIT,
+ .flags = 0,
+ };
+
+ printk(KERN_DEBUG DRIVER_PREFIX
+ " %s: Device %u: Requesting %d TILER 2D framebuffers\n",
+ __FUNCTION__, uiFBDevID, n);
+
+ /* INTEGRATION_POINT: limit to MAX 3 FBs to save TILER container space */
+ if (n > 3)
+ n = 3;
+
+ sAllocData.w *= n;
+
+ psPVRFBInfo->uiBytesPerPixel = psLINFBInfo->var.bits_per_pixel >> 3;
+ psPVRFBInfo->bIs2D = OMAPLFB_TRUE;
+
+ res = omap_ion_tiler_alloc(gpsIONClient, &sAllocData);
+ psPVRFBInfo->psIONHandle = sAllocData.handle;
+ if (res < 0)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ " %s: Device %u: Could not allocate 2D framebuffer(%d)\n",
+ __FUNCTION__, uiFBDevID, res);
+ goto ErrorModPut;
+ }
+
+ psLINFBInfo->fix.smem_start = ion_phys(gpsIONClient, sAllocData.handle, &phys, &size);
+
+ psPVRFBInfo->sSysAddr.uiAddr = phys;
+ psPVRFBInfo->sCPUVAddr = 0;
+ psPVRFBInfo->ulWidth = psLINFBInfo->var.xres;
+ psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
+
+ psPVRFBInfo->ulByteStride = PAGE_ALIGN(psPVRFBInfo->ulWidth * psPVRFBInfo->uiBytesPerPixel);
+ w = psPVRFBInfo->ulByteStride >> PAGE_SHIFT;
+
+ /* this is an "effective" FB size to get correct number of buffers */
+ psPVRFBInfo->ulFBSize = sAllocData.h * n * psPVRFBInfo->ulByteStride;
+ psPVRFBInfo->psPageList = kzalloc(w * n * psPVRFBInfo->ulHeight * sizeof(*psPVRFBInfo->psPageList), GFP_KERNEL);
+ if (!psPVRFBInfo->psPageList)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Could not allocate page list\n", __FUNCTION__, psDevInfo->uiFBDevID);
+ ion_free(gpsIONClient, sAllocData.handle);
+ goto ErrorModPut;
+ }
+
+ tilview_create(&view, phys, psDevInfo->sFBInfo.ulWidth, psDevInfo->sFBInfo.ulHeight);
+ for(i = 0; i < n; i++)
+ {
+ for(y = 0; y < psDevInfo->sFBInfo.ulHeight; y++)
+ {
+ for(x = 0; x < w; x++)
+ {
+ psPVRFBInfo->psPageList[i * psDevInfo->sFBInfo.ulHeight * w + y * w + x].uiAddr =
+ phys + view.v_inc * y + ((x + i * w) << PAGE_SHIFT);
+ }
+ }
+ }
+ }
+#else /* defined(CONFIG_DSSCOMP) */
+ /* System Surface */
psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
psPVRFBInfo->ulByteStride = psLINFBInfo->fix.line_length;
psPVRFBInfo->ulFBSize = FBSize;
+#endif /* defined(CONFIG_DSSCOMP) */
+
psPVRFBInfo->ulBufferSize = psPVRFBInfo->ulHeight * psPVRFBInfo->ulByteStride;
-
+
+ /* Round the buffer size up to a multiple of the number of pages
+ * and the byte stride.
+ * This is used internally, to ensure buffers start on page
+ * boundaries, for the benefit of PVR Services.
+ */
psPVRFBInfo->ulRoundedBufferSize = RoundUpToMultiple(psPVRFBInfo->ulBufferSize, ulLCM);
if(psLINFBInfo->var.bits_per_pixel == 16)
psDevInfo->sFBInfo.ulPhysicalHeightmm =
((int)psLINFBInfo->var.height > 0) ? psLINFBInfo->var.height : 54;
-
+ /* System Surface */
psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
ErrorModPut:
module_put(psLINFBOwner);
ErrorRelSem:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
+
return eError;
}
struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
struct module *psLINFBOwner;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+ OMAPLFB_CONSOLE_LOCK();
+
+#if defined(CONFIG_DSSCOMP)
+ {
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ kfree(psPVRFBInfo->psPageList);
+ if (psPVRFBInfo->psIONHandle)
+ {
+ ion_free(gpsIONClient, psPVRFBInfo->psIONHandle);
+ }
+ }
+#endif /* defined(CONFIG_DSSCOMP) */
psLINFBOwner = psLINFBInfo->fbops->owner;
}
module_put(psLINFBOwner);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+
+ OMAPLFB_CONSOLE_UNLOCK();
}
static OMAPLFB_DEVINFO *OMAPLFBInitDev(unsigned uiFBDevID)
IMG_UINT32 aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
OMAPLFB_DEVINFO *psDevInfo = NULL;
-
+ /* Allocate device info. structure */
psDevInfo = (OMAPLFB_DEVINFO *)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_DEVINFO));
if(psDevInfo == NULL)
goto ErrorExit;
}
-
+ /* Any fields not set will be zero */
memset(psDevInfo, 0, sizeof(OMAPLFB_DEVINFO));
psDevInfo->uiFBDevID = uiFBDevID;
-
+ /* Get the kernel services function table */
if(!(*gpfnGetPVRJTable)(&psDevInfo->sPVRJTable))
{
goto ErrorFreeDevInfo;
}
#ifdef FBDEV_PRESENT
-
+ /* Save private fbdev information structure in the dev. info. */
if(OMAPLFBInitFBDev(psDevInfo) != OMAPLFB_OK)
{
-
+ /*
+ * Leave it to OMAPLFBInitFBDev to print an error message, if
+ * required. The function may have failed because
+ * there is no Linux framebuffer device corresponding
+ * to the device ID.
+ */
goto ErrorFreeDevInfo;
}
": Device %u: Maximum number of swap chain buffers: %u\n",
psDevInfo->uiFBDevID, psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
-
+ /* Setup system buffer */
psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
psDevInfo->sSystemBuffer.psDevInfo = psDevInfo;
OMAPLFBInitBufferForSwap(&psDevInfo->sSystemBuffer);
#else
- psDevInfo->sSystemBuffer.sCPUVAddr = 0x100;
+psDevInfo->sSystemBuffer.sCPUVAddr = 0x100;
// psDevInfo->sSystemBuffer.ulBufferSize = 600*3200;
psDevInfo->sDisplayFormat.pixelformat = 20;
#endif
+ /*
+ Setup the DC Jtable so SRVKM can call into this driver
+ */
psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
- psDevInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem;
psDevInfo->sDCJTable.pfnSetDCState = SetDCState;
-
+ /* Register device with services and retrieve device index */
if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice(
&psDevInfo->sDCJTable,
&psDevInfo->uiPVRDevID) != PVRSRV_OK)
": Device %u: PVR Device ID: %u\n",
psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
-
+ /* Setup private command processing function table ... */
pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
-
- aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
- aui32SyncCountList[DC_FLIP_COMMAND][1] = 2;
-
-
-
-
+ /* ... and associated sync count(s) */
+ aui32SyncCountList[DC_FLIP_COMMAND][0] = 0; /* writes */
+ aui32SyncCountList[DC_FLIP_COMMAND][1] = 10; /* reads */
+ /*
+ Register private command processing functions with
+ the Command Queue Manager and setup the general
+ command complete function in the devinfo.
+ */
if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList(psDevInfo->uiPVRDevID,
&pfnCmdProcList[0],
aui32SyncCountList,
return OMAPLFB_ERROR_INIT_FAILURE;
}
-
+ /*
+ * We search for frame buffer devices backwards, as the last device
+ * registered with PVR Services will be the first device enumerated
+ * by PVR Services.
+ */
for(i = uiMaxFBDevIDPlusOne; i-- != 0;)
{
OMAPLFB_DEVINFO *psDevInfo = OMAPLFBInitDev(i);
if (psDevInfo != NULL)
{
-
+ /* Set the top-level anchor */
OMAPLFBSetDevInfoPtr(psDevInfo->uiFBDevID, psDevInfo);
uiDevicesFound++;
}
return (uiDevicesFound != 0) ? OMAPLFB_OK : OMAPLFB_ERROR_INIT_FAILURE;
}
+/*
+ * OMAPLFBDeInitDev
+ * DeInitialises one device
+ */
static OMAPLFB_BOOL OMAPLFBDeInitDev(OMAPLFB_DEVINFO *psDevInfo)
{
PVRSRV_DC_DISP2SRV_KMJTABLE *psPVRJTable = &psDevInfo->sPVRJTable;
return OMAPLFB_FALSE;
}
-
+ /*
+ * Remove display class device from kernel services device
+ * register.
+ */
if (psPVRJTable->pfnPVRSRVRemoveDCDevice(psDevInfo->uiPVRDevID) != PVRSRV_OK)
{
printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: PVR Device %u: Couldn't remove device from PVR Services\n", __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID);
return OMAPLFB_FALSE;
}
-#ifdef FBDEV_PRESENT
+
OMAPLFBDeInitFBDev(psDevInfo);
-#endif
+
OMAPLFBSetDevInfoPtr(psDevInfo->uiFBDevID, NULL);
-
+ /* De-allocate data structure */
OMAPLFBFreeKernelMem(psDevInfo);
return OMAPLFB_TRUE;
}
+/*
+ * OMAPLFBDeInit
+ * Deinitialises the display class device component of the FBDev
+ */
OMAPLFB_ERROR OMAPLFBDeInit(void)
{
unsigned uiMaxFBDevIDPlusOne = OMAPLFBMaxFBDevIDPlusOne();
return (bError) ? OMAPLFB_ERROR_INIT_FAILURE : OMAPLFB_OK;
}
+/******************************************************************************
+ End of file (omaplfb_displayclass.c)
+******************************************************************************/
+
-/**********************************************************************
- *
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OMAP linux display driver components
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
+/**************************************************************************
+ The 3rd party driver is a specification of an API to integrate the IMG POWERVR
+ Services driver with 3rd Party display hardware. It is NOT a specification for
+ a display controller driver, rather a specification to extend the API for a
+ pre-existing driver for the display hardware.
+
+ The 3rd party driver interface provides IMG POWERVR client drivers (e.g. PVR2D)
+ with an API abstraction of the system's underlying display hardware, allowing
+ the client drivers to indirectly control the display hardware and access its
+ associated memory.
+
+ Functions of the API include
+ - query primary surface attributes (width, height, stride, pixel format, CPU
+ physical and virtual address)
+ - swap/flip chain creation and subsequent query of surface attributes
+ - asynchronous display surface flipping, taking account of asynchronous read
+ (flip) and write (render) operations to the display surface
+
+ Note: having queried surface attributes the client drivers are able to map the
+ display memory to any IMG POWERVR Services device by calling
+ PVRSRVMapDeviceClassMemory with the display surface handle.
+
+ This code is intended to be an example of how a pre-existing display driver may
+ be extended to support the 3rd Party Display interface to POWERVR Services
+ - IMG is not providing a display driver implementation.
+ **************************************************************************/
#include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
#ifndef AUTOCONF_INCLUDED
#include <linux/config.h>
#endif
#endif
-
#include <asm/atomic.h>
#if defined(SUPPORT_DRI_DRM)
#include <linux/workqueue.h>
#include <linux/fb.h>
#include <linux/console.h>
-// #include <linux/omapfb.h>
+#include <linux/omapfb.h>
#include <linux/mutex.h>
# include <plat/ti81xx-vpss.h>
-# include <plat/vrfb.h>
+#if defined(PVR_OMAPLFB_DRM_FB)
+#include <plat/display.h>
+#include <linux/omap_gpu.h>
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
+/* OmapZoom.org OMAP3 2.6.29 kernel tree - Needs mach/vrfb.h
+ * OmapZoom.org OMAP3 2.6.32 kernel tree - No additional header required
+ * OmapZoom.org OMAP4 2.6.33 kernel tree - No additional header required
+ * OmapZoom.org OMAP4 2.6.34 kernel tree - Needs plat/vrfb.h
+ * Sholes 2.6.32 kernel tree - Needs plat/vrfb.h
+ */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
#define PVR_OMAPFB3_NEEDS_PLAT_VRFB_H
#endif
#if defined(PVR_OMAPFB3_NEEDS_PLAT_VRFB_H)
-# include <plat/vrfb.h>
+#include <plat/vrfb.h>
#else
-# if defined(PVR_OMAPFB3_NEEDS_MACH_VRFB_H)
-# include <mach/vrfb.h>
-# endif
+#if defined(PVR_OMAPFB3_NEEDS_MACH_VRFB_H)
+#include <mach/vrfb.h>
+#endif
#endif
#if defined(DEBUG)
#define PVR_DEBUG DEBUG
#undef DEBUG
#endif
-//#include <omapfb/omapfb.h>
+#include <omapfb/omapfb.h>
#if defined(DEBUG)
#undef DEBUG
#endif
#define DEBUG PVR_DEBUG
#undef PVR_DEBUG
#endif
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
+
+#if defined(CONFIG_DSSCOMP)
+#include <mach/tiler.h>
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+#endif /* defined(CONFIG_DSSCOMP) */
#include "img_defs.h"
#include "servicesext.h"
#include "3rdparty_dc_drm_shared.h"
#endif
-#if 0
#if !defined(PVR_LINUX_USING_WORKQUEUES)
#error "PVR_LINUX_USING_WORKQUEUES must be defined"
#endif
-#endif
MODULE_SUPPORTED_DEVICE(DEVNAME);
-#if 0
+#if !defined(PVR_OMAPLFB_DRM_FB)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
#define OMAP_DSS_DRIVER(drv, dev) struct omap_dss_driver *drv = (dev) != NULL ? (dev)->driver : NULL
#define OMAP_DSS_MANAGER(man, dev) struct omap_overlay_manager *man = (dev) != NULL ? (dev)->manager : NULL
#define OMAP_DSS_MANAGER(man, dev) struct omap_dss_device *man = (dev)
#define WAIT_FOR_VSYNC(man) ((man)->wait_vsync)
#endif
-#endif
+#endif /* !defined(PVR_OMAPLFB_DRM_FB) */
void *OMAPLFBAllocKernelMem(unsigned long ulSize)
{
return (OMAPLFB_ERROR_INVALID_PARAMS);
}
-
+ /* Nothing to do - should be exported from pvrsrv.ko */
*ppfnFuncTable = PVRGetDisplayClassJTable;
return (OMAPLFB_OK);
}
+/* Inset a swap buffer into the swap chain work queue */
void OMAPLFBQueueBufferForSwap(OMAPLFB_SWAPCHAIN *psSwapChain, OMAPLFB_BUFFER *psBuffer)
{
int res = queue_work(psSwapChain->psWorkQueue, &psBuffer->sWork);
}
}
+/* Process an item on a swap chain work queue */
static void WorkQueueHandler(struct work_struct *psWork)
{
OMAPLFB_BUFFER *psBuffer = container_of(psWork, OMAPLFB_BUFFER, sWork);
OMAPLFBSwapHandler(psBuffer);
}
+/* Create a swap chain work queue */
OMAPLFB_ERROR OMAPLFBCreateSwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
{
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34))
- psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
-#else
- psSwapChain->psWorkQueue = create_workqueue(DEVNAME);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ /*
+ * Calling alloc_ordered_workqueue with the WQ_FREEZABLE and
+ * WQ_MEM_RECLAIM flags set, (currently) has the same effect as
+ * calling create_freezable_workqueue. None of the other WQ
+ * flags are valid. Setting WQ_MEM_RECLAIM should allow the
+ * workqueue to continue to service the swap chain in low memory
+ * conditions, preventing the driver from holding on to
+ * resources longer than it needs to.
+ */
+#if (LINUX_VERSION_CODE == KERNEL_VERSION(2,6,37))
+ psSwapChain->psWorkQueue = alloc_ordered_workqueue(DEVNAME, WQ_FREEZEABLE | WQ_MEM_RECLAIM);
+#else
+ psSwapChain->psWorkQueue = alloc_ordered_workqueue(DEVNAME, WQ_FREEZABLE | WQ_MEM_RECLAIM);
+#endif
+
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+ psSwapChain->psWorkQueue = create_freezable_workqueue(DEVNAME);
+#else
+ /*
+ * Create a single-threaded, freezable, rt-prio workqueue.
+ * Such workqueues are frozen with user threads when a system
+ * suspends, before driver suspend entry points are called.
+ * This ensures this driver will not call into the Linux
+ * framebuffer driver after the latter is suspended.
+ */
+ psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
+#endif
#endif
if (psSwapChain->psWorkQueue == NULL)
{
- printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: create_singlethreaded_workqueue failed\n", __FUNCTION__, psSwapChain->uiFBDevID);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: Couldn't create workqueue\n", __FUNCTION__, psSwapChain->uiFBDevID);
return (OMAPLFB_ERROR_INIT_FAILURE);
}
return (OMAPLFB_OK);
}
+/* Prepare buffer for insertion into a swap chain work queue */
void OMAPLFBInitBufferForSwap(OMAPLFB_BUFFER *psBuffer)
{
INIT_WORK(&psBuffer->sWork, WorkQueueHandler);
}
+/* Destroy a swap chain work queue */
void OMAPLFBDestroySwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
{
destroy_workqueue(psSwapChain->psWorkQueue);
}
+/* Flip display to given buffer */
void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer)
{
struct fb_var_screeninfo sFBVar;
int res;
unsigned long ulYResVirtual;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+ OMAPLFB_CONSOLE_LOCK();
sFBVar = psDevInfo->psLINFBInfo->var;
ulYResVirtual = psBuffer->ulYOffset + sFBVar.yres;
-
+#if defined(CONFIG_DSSCOMP)
+ {
+ /*
+ * If using DSSCOMP, we need to use dsscomp queuing for normal
+ * framebuffer updates, so that previously used overlays get
+ * automatically disabled, and manager gets dirtied. We can
+ * do that because DSSCOMP takes ownership of all pipelines on
+ * a manager.
+ */
+ struct fb_fix_screeninfo sFBFix = psDevInfo->psLINFBInfo->fix;
+ struct dsscomp_setup_dispc_data d =
+ {
+ .num_ovls = 1,
+ .num_mgrs = 1,
+ .mgrs[0].alpha_blending = 1,
+ .ovls[0] =
+ {
+ .cfg =
+ {
+ .win.w = sFBVar.xres,
+ .win.h = sFBVar.yres,
+ .crop.x = sFBVar.xoffset,
+ .crop.y = sFBVar.yoffset,
+ .crop.w = sFBVar.xres,
+ .crop.h = sFBVar.yres,
+ .width = sFBVar.xres_virtual,
+ .height = sFBVar.yres_virtual,
+ .stride = sFBFix.line_length,
+ .enabled = 1,
+ .global_alpha = 255,
+ },
+ },
+ };
+
+ /* do not map buffer into TILER1D as it is contiguous */
+ struct tiler_pa_info *pas[] = { NULL };
+
+ d.ovls[0].ba = sFBFix.smem_start;
+ omapfb_mode_to_dss_mode(&sFBVar, &d.ovls[0].cfg.color_mode);
+
+ res = dsscomp_gralloc_queue(&d, pas, true, NULL, NULL);
+ }
+#else /* defined(CONFIG_DSSCOMP) */
+ /*
+ * PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY should be defined to work
+ * around flipping problems seen with the Taal LCDs on Blaze.
+ * The work around is safe to use with other types of screen on Blaze
+ * (e.g. HDMI) and on other platforms (e.g. Panda board).
+ */
+#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
+ /*
+ * Attempt to change the virtual screen resolution if it is too
+ * small. Note that fb_set_var also pans the display.
+ */
if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
+#endif /* !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) */
{
sFBVar.xres_virtual = sFBVar.xres;
sFBVar.yres_virtual = ulYResVirtual;
res = fb_set_var(psDevInfo->psLINFBInfo, &sFBVar);
if (res != 0)
{
- printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
}
}
+#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
else
{
res = fb_pan_display(psDevInfo->psLINFBInfo, &sFBVar);
if (res != 0)
{
- printk (" fb_pan api failed \n");
- printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
}
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
+#endif /* !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) */
+#endif /* defined(CONFIG_DSSCOMP) */
+
+ OMAPLFB_CONSOLE_UNLOCK();
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
+#if !defined(PVR_OMAPLFB_DRM_FB) || defined(DEBUG)
+static OMAPLFB_BOOL OMAPLFBValidateDSSUpdateMode(enum omap_dss_update_mode eMode)
+{
+ switch (eMode)
+ {
+ case OMAP_DSS_UPDATE_AUTO:
+ case OMAP_DSS_UPDATE_MANUAL:
+ case OMAP_DSS_UPDATE_DISABLED:
+ return OMAPLFB_TRUE;
+ default:
+ break;
+ }
+
+ return OMAPLFB_FALSE;
+}
+
+static OMAPLFB_UPDATE_MODE OMAPLFBFromDSSUpdateMode(enum omap_dss_update_mode eMode)
+{
+ switch (eMode)
+ {
+ case OMAP_DSS_UPDATE_AUTO:
+ return OMAPLFB_UPDATE_MODE_AUTO;
+ case OMAP_DSS_UPDATE_MANUAL:
+ return OMAPLFB_UPDATE_MODE_MANUAL;
+ case OMAP_DSS_UPDATE_DISABLED:
+ return OMAPLFB_UPDATE_MODE_DISABLED;
+ default:
+ break;
+ }
+
+ return OMAPLFB_UPDATE_MODE_UNDEFINED;
+}
+#endif
+#endif
+
+static OMAPLFB_BOOL OMAPLFBValidateUpdateMode(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return OMAPLFB_TRUE;
+ default:
+ break;
+ }
+
+ return OMAPLFB_FALSE;
+}
+#if 0
+static enum omap_dss_update_mode OMAPLFBToDSSUpdateMode(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ return OMAP_DSS_UPDATE_AUTO;
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ return OMAP_DSS_UPDATE_MANUAL;
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return OMAP_DSS_UPDATE_DISABLED;
+ default:
+ break;
+ }
+
+ return -1;
+}
#endif
+#if defined(DEBUG)
+static const char *OMAPLFBUpdateModeToString(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ return "Auto Update Mode";
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ return "Manual Update Mode";
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return "Update Mode Disabled";
+ case OMAPLFB_UPDATE_MODE_UNDEFINED:
+ return "Update Mode Undefined";
+ default:
+ break;
+ }
+
+ return "Unknown Update Mode";
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
+static const char *OMAPLFBDSSUpdateModeToString(enum omap_dss_update_mode eMode)
+{
+
+ if (!OMAPLFBValidateDSSUpdateMode(eMode))
+ {
+ return "Unknown Update Mode";
+ }
+
+ return OMAPLFBUpdateModeToString(OMAPLFBFromDSSUpdateMode(eMode));
+}
+#endif
+void OMAPLFBPrintInfo(OMAPLFB_DEVINFO *psDevInfo)
+{
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+ unsigned uConnectors;
+ unsigned uConnector;
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: DRM framebuffer\n", psDevInfo->uiFBDevID));
+ for (psConnector = NULL, uConnectors = 0;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ uConnectors++;
+ }
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: Number of screens (DRM connectors): %u\n", psDevInfo->uiFBDevID, uConnectors));
+
+ if (uConnectors == 0)
+ {
+ return;
+ }
+
+ for (psConnector = NULL, uConnector = 0;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL; uConnector++)
+ {
+ enum omap_dss_update_mode eMode = omap_connector_get_update_mode(psConnector);
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: Screen %u: %s (%d)\n", psDevInfo->uiFBDevID, uConnector, OMAPLFBDSSUpdateModeToString(eMode), (int)eMode));
+
+ }
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
+ OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: non-DRM framebuffer\n", psDevInfo->uiFBDevID));
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: %s\n", psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
+}
+#endif /* defined(DEBUG) */
+
+/*
+ * Get display update mode.
+ * If the mode is AUTO, we can wait for VSync, if desired.
+ */
OMAPLFB_UPDATE_MODE OMAPLFBGetUpdateMode(OMAPLFB_DEVINFO *psDevInfo)
{
#if 0
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+ OMAPLFB_UPDATE_MODE eMode = OMAPLFB_UPDATE_MODE_UNDEFINED;
+
+ /*
+ * There may be multiple displays connected. If at least one
+ * display is manual update mode, report all screens as being
+ * in that mode.
+ */
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ switch(omap_connector_get_update_mode(psConnector))
+ {
+ case OMAP_DSS_UPDATE_MANUAL:
+ eMode = OMAPLFB_UPDATE_MODE_MANUAL;
+ break;
+ case OMAP_DSS_UPDATE_DISABLED:
+ if (eMode == OMAPLFB_UPDATE_MODE_UNDEFINED)
+ {
+ eMode = OMAPLFB_UPDATE_MODE_DISABLED;
+ }
+ break;
+ case OMAP_DSS_UPDATE_AUTO:
+ /* Fall through to default case */
+ default:
+ /* Asssume auto update is possible */
+ if (eMode != OMAPLFB_UPDATE_MODE_MANUAL)
+ {
+ eMode = OMAPLFB_UPDATE_MODE_AUTO;
+ }
+ break;
+ }
+ }
+
+ return eMode;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
+
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
enum omap_dss_update_mode eMode;
- if (psDSSDrv == NULL || psDSSDrv->get_update_mode == NULL)
+ if (psDSSDrv == NULL)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Can't get update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No DSS device\n", __FUNCTION__, psDevInfo->uiFBDevID));
return OMAPLFB_UPDATE_MODE_UNDEFINED;
}
- eMode = psDSSDrv->get_update_mode(psDSSDev);
- switch(eMode)
+ if (psDSSDrv->get_update_mode == NULL)
{
- case OMAP_DSS_UPDATE_AUTO:
+ if (strcmp(psDSSDev->name, "hdmi") == 0)
+ {
+ return OMAPLFB_UPDATE_MODE_AUTO;
+ }
+// DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No get_update_mode function\n", __FUNCTION__, psDevInfo->uiFBDevID));
+// return OMAPLFB_UPDATE_MODE_UNDEFINED;
return OMAPLFB_UPDATE_MODE_AUTO;
- case OMAP_DSS_UPDATE_MANUAL:
- return OMAPLFB_UPDATE_MODE_MANUAL;
- case OMAP_DSS_UPDATE_DISABLED:
- return OMAPLFB_UPDATE_MODE_DISABLED;
- default:
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eMode));
- break;
}
- return OMAPLFB_UPDATE_MODE_UNDEFINED;
+ eMode = psDSSDrv->get_update_mode(psDSSDev);
+ if (!OMAPLFBValidateDSSUpdateMode(eMode))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
+ }
+
+ return OMAPLFBFromDSSUpdateMode(eMode);
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
#endif
- return OMAPLFB_UPDATE_MODE_AUTO;
+return OMAPLFB_UPDATE_MODE_AUTO;
}
+/* Set display update mode */
OMAPLFB_BOOL OMAPLFBSetUpdateMode(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_UPDATE_MODE eMode)
{
#if 0
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+ enum omap_dss_update_mode eDSSMode;
+ OMAPLFB_BOOL bSuccess = OMAPLFB_FALSE;
+ OMAPLFB_BOOL bFailure = OMAPLFB_FALSE;
+
+ if (!OMAPLFBValidateUpdateMode(eMode))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
+ return OMAPLFB_FALSE;
+ }
+ eDSSMode = OMAPLFBToDSSUpdateMode(eMode);
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ int iRes = omap_connector_set_update_mode(psConnector, eDSSMode);
+ OMAPLFB_BOOL bRes = (iRes == 0);
+
+
+ bSuccess |= bRes;
+ bFailure |= !bRes;
+ }
+
+ if (!bFailure)
+ {
+ if (!bSuccess)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No screens\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ }
+
+ return OMAPLFB_TRUE;
+ }
+
+ if (!bSuccess)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set %s for any screen\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+ return OMAPLFB_FALSE;
+ }
+
+ if (eMode == OMAPLFB_UPDATE_MODE_AUTO)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set %s for all screens\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+ return OMAPLFB_FALSE;
+ }
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: %s set for some screens\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+
+ return OMAPLFB_TRUE;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
enum omap_dss_update_mode eDSSMode;
if (psDSSDrv == NULL || psDSSDrv->set_update_mode == NULL)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Can't set update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Can't set update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
return OMAPLFB_FALSE;
}
- switch(eMode)
+ if (!OMAPLFBValidateUpdateMode(eMode))
{
- case OMAPLFB_UPDATE_MODE_AUTO:
- eDSSMode = OMAP_DSS_UPDATE_AUTO;
- break;
- case OMAPLFB_UPDATE_MODE_MANUAL:
- eDSSMode = OMAP_DSS_UPDATE_MANUAL;
- break;
- case OMAPLFB_UPDATE_MODE_DISABLED:
- eDSSMode = OMAP_DSS_UPDATE_DISABLED;
- break;
- default:
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eMode));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
return OMAPLFB_FALSE;
}
+ eDSSMode = OMAPLFBToDSSUpdateMode(eMode);
res = psDSSDrv->set_update_mode(psDSSDev, eDSSMode);
if (res != 0)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: set_update_mode failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: set_update_mode (%s) failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBDSSUpdateModeToString(eDSSMode), res));
}
return (res == 0);
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
#endif
- return 1;
+return 1;
}
+/* Wait for VSync */
OMAPLFB_BOOL OMAPLFBWaitForVSync(OMAPLFB_DEVINFO *psDevInfo)
{
-
#if 0
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ (void) omap_encoder_wait_for_vsync(psConnector->encoder);
+ }
+
+ return OMAPLFB_TRUE;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
OMAP_DSS_MANAGER(psDSSMan, psDSSDev);
int res = WAIT_FOR_VSYNC(psDSSMan)(psDSSMan);
if (res != 0)
{
- DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Wait for vsync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res));
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Wait for vsync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res));
return OMAPLFB_FALSE;
}
}
+
+ return OMAPLFB_TRUE;
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
#endif
-#if 0
- struct vps_grpx_ctrl *gctrl;
- int r;
- gctrl = vps_grpx_get_ctrl(psDevInfo->uiFBDevID);
- printk (" BVSYNC \n");
- r = gctrl->wait_for_vsync(gctrl);
- printk (" AVSYNC: %d\n", vsync_num++);
- return OMAPLFB_TRUE;
-#endif
-// unsigned long timeout = msecs_to_jiffies(500);
#if FBDEV_PRESENT
int r;
return OMAPLFB_FALSE;
}
#endif
+
return OMAPLFB_TRUE;
+
}
+/*
+ * Wait for screen to update. If the screen is in manual or auto update
+ * mode, we can call this function to wait for the screen to update.
+ */
OMAPLFB_BOOL OMAPLFBManualSync(OMAPLFB_DEVINFO *psDevInfo)
{
#if 0
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL; )
+ {
+ /* Try manual sync first, then try wait for vsync */
+ if (omap_connector_sync(psConnector) != 0)
+ {
+ (void) omap_encoder_wait_for_vsync(psConnector->encoder);
+ }
+ }
+
+ return OMAPLFB_TRUE;
+#else /* defined(PVR_OMAPLFB_DRM_FB) */
struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
int res = psDSSDrv->sync(psDSSDev);
if (res != 0)
{
- printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: Sync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: Sync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return OMAPLFB_FALSE;
}
}
-#endif
return OMAPLFB_TRUE;
+#endif /* defined(PVR_OMAPLFB_DRM_FB) */
+#endif
+return OMAPLFB_TRUE;
}
+/*
+ * If the screen is manual or auto update mode, wait for the screen to
+ * update.
+ */
OMAPLFB_BOOL OMAPLFBCheckModeAndSync(OMAPLFB_DEVINFO *psDevInfo)
{
OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
return OMAPLFB_TRUE;
}
+/* Linux Framebuffer event notification handler */
static int OMAPLFBFrameBufferEvents(struct notifier_block *psNotif,
unsigned long event, void *data)
{
struct fb_info *psFBInfo = psFBEvent->info;
OMAPLFB_BOOL bBlanked;
-
+ /* Only interested in blanking events */
if (event != FB_EVENT_BLANK)
{
return 0;
return 0;
}
+/* Unblank the screen */
OMAPLFB_ERROR OMAPLFBUnblankDisplay(OMAPLFB_DEVINFO *psDevInfo)
{
- int res;
#ifdef FBDEV_PRESENT
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+ int res;
+
+ OMAPLFB_CONSOLE_LOCK();
res = fb_blank(psDevInfo->psLINFBInfo, 0);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
if (res != 0 && res != -EINVAL)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: fb_blank failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return (OMAPLFB_ERROR_GENERIC);
}
#endif
-
return (OMAPLFB_OK);
}
#ifdef CONFIG_HAS_EARLYSUSPEND
+/* Blank the screen */
static void OMAPLFBBlankDisplay(OMAPLFB_DEVINFO *psDevInfo)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+ OMAPLFB_CONSOLE_LOCK();
fb_blank(psDevInfo->psLINFBInfo, 1);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
}
static void OMAPLFBEarlySuspendHandler(struct early_suspend *h)
}
}
-#endif
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+/* Set up Linux Framebuffer event notification */
OMAPLFB_ERROR OMAPLFBEnableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
{
int res;
OMAPLFB_ERROR eError;
-
+ /* Set up Linux Framebuffer event notification */
memset(&psDevInfo->sLINNotifBlock, 0, sizeof(psDevInfo->sLINNotifBlock));
psDevInfo->sLINNotifBlock.notifier_call = OMAPLFBFrameBufferEvents;
res = fb_register_client(&psDevInfo->sLINNotifBlock);
if (res != 0)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: fb_register_client failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return (OMAPLFB_ERROR_GENERIC);
eError = OMAPLFBUnblankDisplay(psDevInfo);
if (eError != OMAPLFB_OK)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: UnblankDisplay failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eError);
return eError;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
psDevInfo->sEarlySuspend.suspend = OMAPLFBEarlySuspendHandler;
psDevInfo->sEarlySuspend.resume = OMAPLFBEarlyResumeHandler;
- psDevInfo->sEarlySuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
+ psDevInfo->sEarlySuspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1;
register_early_suspend(&psDevInfo->sEarlySuspend);
#endif
return (OMAPLFB_OK);
}
+/* Disable Linux Framebuffer event notification */
OMAPLFB_ERROR OMAPLFBDisableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
{
int res;
unregister_early_suspend(&psDevInfo->sEarlySuspend);
#endif
-
+ /* Unregister for Framebuffer events */
res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
if (res != 0)
{
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: Device %u: fb_unregister_client failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
return (OMAPLFB_ERROR_GENERIC);
}
}
}
- printk(KERN_WARNING DRIVER_PREFIX
+ printk(KERN_ERR DRIVER_PREFIX
": %s: PVR Device %u: Couldn't find device\n", __FUNCTION__, uiPVRDevID);
return NULL;
}
-int PVR_DRM_MAKENAME(omaplfb, _Ioctl)(struct drm_device unref__ *dev, void *arg, struct drm_file unref__ *pFile)
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(struct drm_device unref__ *dev, void *arg, struct drm_file unref__ *pFile)
{
uint32_t *puiArgs;
uint32_t uiCmd;
pszMode = "(Unknown Mode)";
break;
}
- printk (KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: Display %s\n",
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: Display %s\n",
__FUNCTION__, uiPVRDevID, pszMode);
}
#endif
{
flush_workqueue(psDevInfo->psSwapChain->psWorkQueue);
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_lock();
-#else
- acquire_console_sem();
-#endif
+
+ OMAPLFB_CONSOLE_LOCK();
ret = fb_blank(psDevInfo->psLINFBInfo, iFBMode);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
- console_unlock();
-#else
- release_console_sem();
-#endif
+ OMAPLFB_CONSOLE_UNLOCK();
+
OMAPLFBCreateSwapChainUnLock(psDevInfo);
break;
}
#endif
+/* Insert the driver into the kernel */
#if defined(SUPPORT_DRI_DRM)
-int PVR_DRM_MAKENAME(omaplfb, _Init)(struct drm_device unref__ *dev)
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device unref__ *dev)
#else
static int __init OMAPLFB_Init(void)
#endif
if(OMAPLFBInit() != OMAPLFB_OK)
{
- printk(KERN_WARNING DRIVER_PREFIX ": %s: OMAPLFBInit failed\n", __FUNCTION__);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: OMAPLFBInit failed\n", __FUNCTION__);
return -ENODEV;
}
}
+/* Remove the driver from the kernel */
#if defined(SUPPORT_DRI_DRM)
-void PVR_DRM_MAKENAME(omaplfb, _Cleanup)(struct drm_device unref__ *dev)
+void PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device unref__ *dev)
#else
static void __exit OMAPLFB_Cleanup(void)
#endif
{
if(OMAPLFBDeInit() != OMAPLFB_OK)
{
- printk(KERN_WARNING DRIVER_PREFIX ": %s: OMAPLFBDeInit failed\n", __FUNCTION__);
+ printk(KERN_ERR DRIVER_PREFIX ": %s: OMAPLFBDeInit failed\n", __FUNCTION__);
}
}
#if !defined(SUPPORT_DRI_DRM)
+/*
+ These macro calls define the initialisation and removal functions of the
+ driver. Although they are prefixed `module_', they apply when compiling
+ statically as well; in both cases they define the function the kernel will
+ run to start/stop the driver.
+*/
late_initcall(OMAPLFB_Init);
module_exit(OMAPLFB_Cleanup);
#endif
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
$(call must-be-defined,$(SUPPORT_DRI_DRM))
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
modules := linux_drm
+++ /dev/null
-/**
- * \file ati_pcigart.c
- * ATI PCI GART support
- *
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
- *
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
-
-static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
- struct drm_ati_pcigart_info *gart_info)
-{
- gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size,
- PAGE_SIZE);
- if (gart_info->table_handle == NULL)
- return -ENOMEM;
-
- return 0;
-}
-
-static void drm_ati_free_pcigart_table(struct drm_device *dev,
- struct drm_ati_pcigart_info *gart_info)
-{
- drm_pci_free(dev, gart_info->table_handle);
- gart_info->table_handle = NULL;
-}
-
-int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
-{
- struct drm_sg_mem *entry = dev->sg;
- unsigned long pages;
- int i;
- int max_pages;
-
- /* we need to support large memory configurations */
- if (!entry) {
- DRM_ERROR("no scatter/gather memory!\n");
- return 0;
- }
-
- if (gart_info->bus_addr) {
-
- max_pages = (gart_info->table_size / sizeof(u32));
- pages = (entry->pages <= max_pages)
- ? entry->pages : max_pages;
-
- for (i = 0; i < pages; i++) {
- if (!entry->busaddr[i])
- break;
- pci_unmap_page(dev->pdev, entry->busaddr[i],
- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
- }
-
- if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
- gart_info->bus_addr = 0;
- }
-
- if (gart_info->gart_table_location == DRM_ATI_GART_MAIN &&
- gart_info->table_handle) {
- drm_ati_free_pcigart_table(dev, gart_info);
- }
-
- return 1;
-}
-EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
-
-int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
-{
- struct drm_local_map *map = &gart_info->mapping;
- struct drm_sg_mem *entry = dev->sg;
- void *address = NULL;
- unsigned long pages;
- u32 *pci_gart = NULL, page_base, gart_idx;
- dma_addr_t bus_address = 0;
- int i, j, ret = 0;
- int max_ati_pages, max_real_pages;
-
- if (!entry) {
- DRM_ERROR("no scatter/gather memory!\n");
- goto done;
- }
-
- if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
- DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
-
- if (pci_set_dma_mask(dev->pdev, gart_info->table_mask)) {
- DRM_ERROR("fail to set dma mask to 0x%Lx\n",
- (unsigned long long)gart_info->table_mask);
- ret = 1;
- goto done;
- }
-
- ret = drm_ati_alloc_pcigart_table(dev, gart_info);
- if (ret) {
- DRM_ERROR("cannot allocate PCI GART page!\n");
- goto done;
- }
-
- pci_gart = gart_info->table_handle->vaddr;
- address = gart_info->table_handle->vaddr;
- bus_address = gart_info->table_handle->busaddr;
- } else {
- address = gart_info->addr;
- bus_address = gart_info->bus_addr;
- DRM_DEBUG("PCI: Gart Table: VRAM %08LX mapped at %08lX\n",
- (unsigned long long)bus_address,
- (unsigned long)address);
- }
-
-
- max_ati_pages = (gart_info->table_size / sizeof(u32));
- max_real_pages = max_ati_pages / (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE);
- pages = (entry->pages <= max_real_pages)
- ? entry->pages : max_real_pages;
-
- if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
- memset(pci_gart, 0, max_ati_pages * sizeof(u32));
- } else {
- memset_io((void __iomem *)map->handle, 0, max_ati_pages * sizeof(u32));
- }
-
- gart_idx = 0;
- for (i = 0; i < pages; i++) {
- /* we need to support large memory configurations */
- entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i],
- 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
- if (pci_dma_mapping_error(dev->pdev, entry->busaddr[i])) {
- DRM_ERROR("unable to map PCIGART pages!\n");
- drm_ati_pcigart_cleanup(dev, gart_info);
- address = NULL;
- bus_address = 0;
- goto done;
- }
- page_base = (u32) entry->busaddr[i];
-
- for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
- u32 val;
-
- switch(gart_info->gart_reg_if) {
- case DRM_ATI_GART_IGP:
- val = page_base | 0xc;
- break;
- case DRM_ATI_GART_PCIE:
- val = (page_base >> 8) | 0xc;
- break;
- default:
- case DRM_ATI_GART_PCI:
- val = page_base;
- break;
- }
- if (gart_info->gart_table_location ==
- DRM_ATI_GART_MAIN)
- pci_gart[gart_idx] = cpu_to_le32(val);
- else
- DRM_WRITE32(map, gart_idx * sizeof(u32), val);
- gart_idx++;
- page_base += ATI_PCIGART_PAGE_SIZE;
- }
- }
- ret = 1;
-
-#if defined(__i386__) || defined(__x86_64__)
- wbinvd();
-#else
- mb();
-#endif
-
- done:
- gart_info->addr = address;
- gart_info->bus_addr = bus_address;
- return ret;
-}
-EXPORT_SYMBOL(drm_ati_pcigart_init);
+++ /dev/null
-/**
- * \file drm_agpsupport.c
- * DRM support for AGP/GART backend
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#if __OS_HAS_AGP
-
-#include <asm/agp.h>
-
-/**
- * Get AGP information.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a (output) drm_agp_info structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device has been initialized and acquired and fills in the
- * drm_agp_info structure with the information in drm_agp_head::agp_info.
- */
-int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
-{
- DRM_AGP_KERN *kern;
-
- if (!dev->agp || !dev->agp->acquired)
- return -EINVAL;
-
- kern = &dev->agp->agp_info;
- info->agp_version_major = kern->version.major;
- info->agp_version_minor = kern->version.minor;
- info->mode = kern->mode;
- info->aperture_base = kern->aper_base;
- info->aperture_size = kern->aper_size * 1024 * 1024;
- info->memory_allowed = kern->max_memory << PAGE_SHIFT;
- info->memory_used = kern->current_memory << PAGE_SHIFT;
- info->id_vendor = kern->device->vendor;
- info->id_device = kern->device->device;
-
- return 0;
-}
-
-EXPORT_SYMBOL(drm_agp_info);
-
-int drm_agp_info_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_agp_info *info = data;
- int err;
-
- err = drm_agp_info(dev, info);
- if (err)
- return err;
-
- return 0;
-}
-
-/**
- * Acquire the AGP device.
- *
- * \param dev DRM device that is to acquire AGP.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device hasn't been acquired before and calls
- * \c agp_backend_acquire.
- */
-int drm_agp_acquire(struct drm_device * dev)
-{
- if (!dev->agp)
- return -ENODEV;
- if (dev->agp->acquired)
- return -EBUSY;
- if (!(dev->agp->bridge = agp_backend_acquire(dev->pdev)))
- return -ENODEV;
- dev->agp->acquired = 1;
- return 0;
-}
-
-EXPORT_SYMBOL(drm_agp_acquire);
-
-/**
- * Acquire the AGP device (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device hasn't been acquired before and calls
- * \c agp_backend_acquire.
- */
-int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
-}
-
-/**
- * Release the AGP device.
- *
- * \param dev DRM device that is to release AGP.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device has been acquired and calls \c agp_backend_release.
- */
-int drm_agp_release(struct drm_device * dev)
-{
- if (!dev->agp || !dev->agp->acquired)
- return -EINVAL;
- agp_backend_release(dev->agp->bridge);
- dev->agp->acquired = 0;
- return 0;
-}
-EXPORT_SYMBOL(drm_agp_release);
-
-int drm_agp_release_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- return drm_agp_release(dev);
-}
-
-/**
- * Enable the AGP bus.
- *
- * \param dev DRM device that has previously acquired AGP.
- * \param mode Requested AGP mode.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device has been acquired but not enabled, and calls
- * \c agp_enable.
- */
-int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode)
-{
- if (!dev->agp || !dev->agp->acquired)
- return -EINVAL;
-
- dev->agp->mode = mode.mode;
- agp_enable(dev->agp->bridge, mode.mode);
- dev->agp->enabled = 1;
- return 0;
-}
-
-EXPORT_SYMBOL(drm_agp_enable);
-
-int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_agp_mode *mode = data;
-
- return drm_agp_enable(dev, *mode);
-}
-
-/**
- * Allocate AGP memory.
- *
- * \param inode device inode.
- * \param file_priv file private pointer.
- * \param cmd command.
- * \param arg pointer to a drm_agp_buffer structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device is present and has been acquired, allocates the
- * memory via agp_allocate_memory() and creates a drm_agp_mem entry for it.
- */
-int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
-{
- struct drm_agp_mem *entry;
- DRM_AGP_MEM *memory;
- unsigned long pages;
- u32 type;
-
- if (!dev->agp || !dev->agp->acquired)
- return -EINVAL;
- if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(entry, 0, sizeof(*entry));
-
- pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
- type = (u32) request->type;
- if (!(memory = agp_allocate_memory(dev->agp->bridge, pages, type))) {
- kfree(entry);
- return -ENOMEM;
- }
-
- entry->handle = (unsigned long)memory->key + 1;
- entry->memory = memory;
- entry->bound = 0;
- entry->pages = pages;
- list_add(&entry->head, &dev->agp->memory);
-
- request->handle = entry->handle;
- request->physical = memory->physical;
-
- return 0;
-}
-EXPORT_SYMBOL(drm_agp_alloc);
-
-
-int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_agp_buffer *request = data;
-
- return drm_agp_alloc(dev, request);
-}
-
-/**
- * Search for the AGP memory entry associated with a handle.
- *
- * \param dev DRM device structure.
- * \param handle AGP memory handle.
- * \return pointer to the drm_agp_mem structure associated with \p handle.
- *
- * Walks through drm_agp_head::memory until finding a matching handle.
- */
-static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
- unsigned long handle)
-{
- struct drm_agp_mem *entry;
-
- list_for_each_entry(entry, &dev->agp->memory, head) {
- if (entry->handle == handle)
- return entry;
- }
- return NULL;
-}
-
-/**
- * Unbind AGP memory from the GATT (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_agp_binding structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device is present and acquired, looks-up the AGP memory
- * entry and passes it to the unbind_agp() function.
- */
-int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
-{
- struct drm_agp_mem *entry;
- int ret;
-
- if (!dev->agp || !dev->agp->acquired)
- return -EINVAL;
- if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
- return -EINVAL;
- if (!entry->bound)
- return -EINVAL;
- ret = drm_unbind_agp(entry->memory);
- if (ret == 0)
- entry->bound = 0;
- return ret;
-}
-EXPORT_SYMBOL(drm_agp_unbind);
-
-
-int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_agp_binding *request = data;
-
- return drm_agp_unbind(dev, request);
-}
-
-/**
- * Bind AGP memory into the GATT (ioctl)
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_agp_binding structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device is present and has been acquired and that no memory
- * is currently bound into the GATT. Looks-up the AGP memory entry and passes
- * it to bind_agp() function.
- */
-int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
-{
- struct drm_agp_mem *entry;
- int retcode;
- int page;
-
- if (!dev->agp || !dev->agp->acquired)
- return -EINVAL;
- if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
- return -EINVAL;
- if (entry->bound)
- return -EINVAL;
- page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
- if ((retcode = drm_bind_agp(entry->memory, page)))
- return retcode;
- entry->bound = dev->agp->base + (page << PAGE_SHIFT);
- DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
- dev->agp->base, entry->bound);
- return 0;
-}
-EXPORT_SYMBOL(drm_agp_bind);
-
-
-int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_agp_binding *request = data;
-
- return drm_agp_bind(dev, request);
-}
-
-/**
- * Free AGP memory (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_agp_buffer structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device is present and has been acquired and looks up the
- * AGP memory entry. If the memory it's currently bound, unbind it via
- * unbind_agp(). Frees it via free_agp() as well as the entry itself
- * and unlinks from the doubly linked list it's inserted in.
- */
-int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
-{
- struct drm_agp_mem *entry;
-
- if (!dev->agp || !dev->agp->acquired)
- return -EINVAL;
- if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
- return -EINVAL;
- if (entry->bound)
- drm_unbind_agp(entry->memory);
-
- list_del(&entry->head);
-
- drm_free_agp(entry->memory, entry->pages);
- kfree(entry);
- return 0;
-}
-EXPORT_SYMBOL(drm_agp_free);
-
-
-
-int drm_agp_free_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_agp_buffer *request = data;
-
- return drm_agp_free(dev, request);
-}
-
-/**
- * Initialize the AGP resources.
- *
- * \return pointer to a drm_agp_head structure.
- *
- * Gets the drm_agp_t structure which is made available by the agpgart module
- * via the inter_module_* functions. Creates and initializes a drm_agp_head
- * structure.
- */
-struct drm_agp_head *drm_agp_init(struct drm_device *dev)
-{
- struct drm_agp_head *head = NULL;
-
- if (!(head = kmalloc(sizeof(*head), GFP_KERNEL)))
- return NULL;
- memset((void *)head, 0, sizeof(*head));
- head->bridge = agp_find_bridge(dev->pdev);
- if (!head->bridge) {
- if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
- kfree(head);
- return NULL;
- }
- agp_copy_info(head->bridge, &head->agp_info);
- agp_backend_release(head->bridge);
- } else {
- agp_copy_info(head->bridge, &head->agp_info);
- }
- if (head->agp_info.chipset == NOT_SUPPORTED) {
- kfree(head);
- return NULL;
- }
- INIT_LIST_HEAD(&head->memory);
- head->cant_use_aperture = head->agp_info.cant_use_aperture;
- head->page_mask = head->agp_info.page_mask;
- head->base = head->agp_info.aper_base;
- return head;
-}
-
-/**
- * Binds a collection of pages into AGP memory at the given offset, returning
- * the AGP memory structure containing them.
- *
- * No reference is held on the pages during this time -- it is up to the
- * caller to handle that.
- */
-DRM_AGP_MEM *
-drm_agp_bind_pages(struct drm_device *dev,
- struct page **pages,
- unsigned long num_pages,
- uint32_t gtt_offset,
- u32 type)
-{
- DRM_AGP_MEM *mem;
- int ret, i;
-
- DRM_DEBUG("\n");
-
- mem = agp_allocate_memory(dev->agp->bridge, num_pages,
- type);
- if (mem == NULL) {
- DRM_ERROR("Failed to allocate memory for %ld pages\n",
- num_pages);
- return NULL;
- }
-
- for (i = 0; i < num_pages; i++)
- mem->pages[i] = pages[i];
- mem->page_count = num_pages;
-
- mem->is_flushed = true;
- ret = agp_bind_memory(mem, gtt_offset / PAGE_SIZE);
- if (ret != 0) {
- DRM_ERROR("Failed to bind AGP memory: %d\n", ret);
- agp_free_memory(mem);
- return NULL;
- }
-
- return mem;
-}
-EXPORT_SYMBOL(drm_agp_bind_pages);
-
-void drm_agp_chipset_flush(struct drm_device *dev)
-{
- agp_flush_chipset(dev->agp->bridge);
-}
-EXPORT_SYMBOL(drm_agp_chipset_flush);
-
-#endif /* __OS_HAS_AGP */
+++ /dev/null
-/**
- * \file drm_auth.c
- * IOCTLs for authentication
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-/**
- * Find the file with the given magic number.
- *
- * \param dev DRM device.
- * \param magic magic number.
- *
- * Searches in drm_device::magiclist within all files with the same hash key
- * the one with matching magic number, while holding the drm_device::struct_mutex
- * lock.
- */
-static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic)
-{
- struct drm_file *retval = NULL;
- struct drm_magic_entry *pt;
- struct drm_hash_item *hash;
- struct drm_device *dev = master->minor->dev;
-
- mutex_lock(&dev->struct_mutex);
- if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
- pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
- retval = pt->priv;
- }
- mutex_unlock(&dev->struct_mutex);
- return retval;
-}
-
-/**
- * Adds a magic number.
- *
- * \param dev DRM device.
- * \param priv file private data.
- * \param magic magic number.
- *
- * Creates a drm_magic_entry structure and appends to the linked list
- * associated the magic number hash key in drm_device::magiclist, while holding
- * the drm_device::struct_mutex lock.
- */
-static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
- drm_magic_t magic)
-{
- struct drm_magic_entry *entry;
- struct drm_device *dev = master->minor->dev;
- DRM_DEBUG("%d\n", magic);
-
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry)
- return -ENOMEM;
- entry->priv = priv;
- entry->hash_item.key = (unsigned long)magic;
- mutex_lock(&dev->struct_mutex);
- drm_ht_insert_item(&master->magiclist, &entry->hash_item);
- list_add_tail(&entry->head, &master->magicfree);
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
-/**
- * Remove a magic number.
- *
- * \param dev DRM device.
- * \param magic magic number.
- *
- * Searches and unlinks the entry in drm_device::magiclist with the magic
- * number hash key, while holding the drm_device::struct_mutex lock.
- */
-static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
-{
- struct drm_magic_entry *pt;
- struct drm_hash_item *hash;
- struct drm_device *dev = master->minor->dev;
-
- DRM_DEBUG("%d\n", magic);
-
- mutex_lock(&dev->struct_mutex);
- if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
- }
- pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
- drm_ht_remove_item(&master->magiclist, hash);
- list_del(&pt->head);
- mutex_unlock(&dev->struct_mutex);
-
- kfree(pt);
-
- return 0;
-}
-
-/**
- * Get a unique magic number (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a resulting drm_auth structure.
- * \return zero on success, or a negative number on failure.
- *
- * If there is a magic number in drm_file::magic then use it, otherwise
- * searches an unique non-zero magic number and add it associating it with \p
- * file_priv.
- */
-int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- static drm_magic_t sequence = 0;
- static DEFINE_SPINLOCK(lock);
- struct drm_auth *auth = data;
-
- /* Find unique magic */
- if (file_priv->magic) {
- auth->magic = file_priv->magic;
- } else {
- do {
- spin_lock(&lock);
- if (!sequence)
- ++sequence; /* reserve 0 */
- auth->magic = sequence++;
- spin_unlock(&lock);
- } while (drm_find_file(file_priv->master, auth->magic));
- file_priv->magic = auth->magic;
- drm_add_magic(file_priv->master, file_priv, auth->magic);
- }
-
- DRM_DEBUG("%u\n", auth->magic);
-
- return 0;
-}
-
-/**
- * Authenticate with a magic.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_auth structure.
- * \return zero if authentication successed, or a negative number otherwise.
- *
- * Checks if \p file_priv is associated with the magic number passed in \arg.
- */
-int drm_authmagic(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_auth *auth = data;
- struct drm_file *file;
-
- DRM_DEBUG("%u\n", auth->magic);
- if ((file = drm_find_file(file_priv->master, auth->magic))) {
- file->authenticated = 1;
- drm_remove_magic(file_priv->master, auth->magic);
- return 0;
- }
- return -EINVAL;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2010 Pauli Nieminen.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-/*
- * Multipart buffer for coping data which is larger than the page size.
- *
- * Authors:
- * Pauli Nieminen <suokkos-at-gmail-dot-com>
- */
-
-#include "drm_buffer.h"
-
-/**
- * Allocate the drm buffer object.
- *
- * buf: Pointer to a pointer where the object is stored.
- * size: The number of bytes to allocate.
- */
-int drm_buffer_alloc(struct drm_buffer **buf, int size)
-{
- int nr_pages = size / PAGE_SIZE + 1;
- int idx;
-
- /* Allocating pointer table to end of structure makes drm_buffer
- * variable sized */
- *buf = kzalloc(sizeof(struct drm_buffer) + nr_pages*sizeof(char *),
- GFP_KERNEL);
-
- if (*buf == NULL) {
- DRM_ERROR("Failed to allocate drm buffer object to hold"
- " %d bytes in %d pages.\n",
- size, nr_pages);
- return -ENOMEM;
- }
-
- (*buf)->size = size;
-
- for (idx = 0; idx < nr_pages; ++idx) {
-
- (*buf)->data[idx] =
- kmalloc(min(PAGE_SIZE, size - idx * PAGE_SIZE),
- GFP_KERNEL);
-
-
- if ((*buf)->data[idx] == NULL) {
- DRM_ERROR("Failed to allocate %dth page for drm"
- " buffer with %d bytes and %d pages.\n",
- idx + 1, size, nr_pages);
- goto error_out;
- }
-
- }
-
- return 0;
-
-error_out:
-
- /* Only last element can be null pointer so check for it first. */
- if ((*buf)->data[idx])
- kfree((*buf)->data[idx]);
-
- for (--idx; idx >= 0; --idx)
- kfree((*buf)->data[idx]);
-
- kfree(*buf);
- return -ENOMEM;
-}
-EXPORT_SYMBOL(drm_buffer_alloc);
-
-/**
- * Copy the user data to the begin of the buffer and reset the processing
- * iterator.
- *
- * user_data: A pointer the data that is copied to the buffer.
- * size: The Number of bytes to copy.
- */
-int drm_buffer_copy_from_user(struct drm_buffer *buf,
- void __user *user_data, int size)
-{
- int nr_pages = size / PAGE_SIZE + 1;
- int idx;
-
- if (size > buf->size) {
- DRM_ERROR("Requesting to copy %d bytes to a drm buffer with"
- " %d bytes space\n",
- size, buf->size);
- return -EFAULT;
- }
-
- for (idx = 0; idx < nr_pages; ++idx) {
-
- if (DRM_COPY_FROM_USER(buf->data[idx],
- user_data + idx * PAGE_SIZE,
- min(PAGE_SIZE, size - idx * PAGE_SIZE))) {
- DRM_ERROR("Failed to copy user data (%p) to drm buffer"
- " (%p) %dth page.\n",
- user_data, buf, idx);
- return -EFAULT;
-
- }
- }
- buf->iterator = 0;
- return 0;
-}
-EXPORT_SYMBOL(drm_buffer_copy_from_user);
-
-/**
- * Free the drm buffer object
- */
-void drm_buffer_free(struct drm_buffer *buf)
-{
-
- if (buf != NULL) {
-
- int nr_pages = buf->size / PAGE_SIZE + 1;
- int idx;
- for (idx = 0; idx < nr_pages; ++idx)
- kfree(buf->data[idx]);
-
- kfree(buf);
- }
-}
-EXPORT_SYMBOL(drm_buffer_free);
-
-/**
- * Read an object from buffer that may be split to multiple parts. If object
- * is not split function just returns the pointer to object in buffer. But in
- * case of split object data is copied to given stack object that is suplied
- * by caller.
- *
- * The processing location of the buffer is also advanced to the next byte
- * after the object.
- *
- * objsize: The size of the objet in bytes.
- * stack_obj: A pointer to a memory location where object can be copied.
- */
-void *drm_buffer_read_object(struct drm_buffer *buf,
- int objsize, void *stack_obj)
-{
- int idx = drm_buffer_index(buf);
- int page = drm_buffer_page(buf);
- void *obj = NULL;
-
- if (idx + objsize <= PAGE_SIZE) {
- obj = &buf->data[page][idx];
- } else {
- /* The object is split which forces copy to temporary object.*/
- int beginsz = PAGE_SIZE - idx;
- memcpy(stack_obj, &buf->data[page][idx], beginsz);
-
- memcpy(stack_obj + beginsz, &buf->data[page + 1][0],
- objsize - beginsz);
-
- obj = stack_obj;
- }
-
- drm_buffer_advance(buf, objsize);
- return obj;
-}
-EXPORT_SYMBOL(drm_buffer_read_object);
+++ /dev/null
-/**
- * \file drm_bufs.c
- * Generic buffer template
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/log2.h>
-#include <asm/shmparam.h>
-#include "drmP.h"
-
-static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
- struct drm_local_map *map)
-{
- struct drm_map_list *entry;
- list_for_each_entry(entry, &dev->maplist, head) {
- /*
- * Because the kernel-userspace ABI is fixed at a 32-bit offset
- * while PCI resources may live above that, we ignore the map
- * offset for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS.
- * It is assumed that each driver will have only one resource of
- * each type.
- */
- if (!entry->map ||
- map->type != entry->map->type ||
- entry->master != dev->primary->master)
- continue;
- switch (map->type) {
- case _DRM_SHM:
- if (map->flags != _DRM_CONTAINS_LOCK)
- break;
- case _DRM_REGISTERS:
- case _DRM_FRAME_BUFFER:
- return entry;
- default: /* Make gcc happy */
- ;
- }
- if (entry->map->offset == map->offset)
- return entry;
- }
-
- return NULL;
-}
-
-static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
- unsigned long user_token, int hashed_handle, int shm)
-{
- int use_hashed_handle, shift;
- unsigned long add;
-
-#if (BITS_PER_LONG == 64)
- use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle);
-#elif (BITS_PER_LONG == 32)
- use_hashed_handle = hashed_handle;
-#else
-#error Unsupported long size. Neither 64 nor 32 bits.
-#endif
-
- if (!use_hashed_handle) {
- int ret;
- hash->key = user_token >> PAGE_SHIFT;
- ret = drm_ht_insert_item(&dev->map_hash, hash);
- if (ret != -EINVAL)
- return ret;
- }
-
- shift = 0;
- add = DRM_MAP_HASH_OFFSET >> PAGE_SHIFT;
- if (shm && (SHMLBA > PAGE_SIZE)) {
- int bits = ilog2(SHMLBA >> PAGE_SHIFT) + 1;
-
- /* For shared memory, we have to preserve the SHMLBA
- * bits of the eventual vma->vm_pgoff value during
- * mmap(). Otherwise we run into cache aliasing problems
- * on some platforms. On these platforms, the pgoff of
- * a mmap() request is used to pick a suitable virtual
- * address for the mmap() region such that it will not
- * cause cache aliasing problems.
- *
- * Therefore, make sure the SHMLBA relevant bits of the
- * hash value we use are equal to those in the original
- * kernel virtual address.
- */
- shift = bits;
- add |= ((user_token >> PAGE_SHIFT) & ((1UL << bits) - 1UL));
- }
-
- return drm_ht_just_insert_please(&dev->map_hash, hash,
- user_token, 32 - PAGE_SHIFT - 3,
- shift, add);
-}
-
-/**
- * Core function to create a range of memory available for mapping by a
- * non-root process.
- *
- * Adjusts the memory offset to its absolute value according to the mapping
- * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
- * applicable and if supported by the kernel.
- */
-static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
- unsigned int size, enum drm_map_type type,
- enum drm_map_flags flags,
- struct drm_map_list ** maplist)
-{
- struct drm_local_map *map;
- struct drm_map_list *list;
- drm_dma_handle_t *dmah;
- unsigned long user_token;
- int ret;
-
- map = kmalloc(sizeof(*map), GFP_KERNEL);
- if (!map)
- return -ENOMEM;
-
- map->offset = offset;
- map->size = size;
- map->flags = flags;
- map->type = type;
-
- /* Only allow shared memory to be removable since we only keep enough
- * book keeping information about shared memory to allow for removal
- * when processes fork.
- */
- if ((map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM) {
- kfree(map);
- return -EINVAL;
- }
- DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n",
- (unsigned long long)map->offset, map->size, map->type);
-
- /* page-align _DRM_SHM maps. They are allocated here so there is no security
- * hole created by that and it works around various broken drivers that use
- * a non-aligned quantity to map the SAREA. --BenH
- */
- if (map->type == _DRM_SHM)
- map->size = PAGE_ALIGN(map->size);
-
- if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
- kfree(map);
- return -EINVAL;
- }
- map->mtrr = -1;
- map->handle = NULL;
-
- switch (map->type) {
- case _DRM_REGISTERS:
- case _DRM_FRAME_BUFFER:
-#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__arm__)
- if (map->offset + (map->size-1) < map->offset ||
- map->offset < virt_to_phys(high_memory)) {
- kfree(map);
- return -EINVAL;
- }
-#endif
-#ifdef __alpha__
- map->offset += dev->hose->mem_space->start;
-#endif
- /* Some drivers preinitialize some maps, without the X Server
- * needing to be aware of it. Therefore, we just return success
- * when the server tries to create a duplicate map.
- */
- list = drm_find_matching_map(dev, map);
- if (list != NULL) {
- if (list->map->size != map->size) {
- DRM_DEBUG("Matching maps of type %d with "
- "mismatched sizes, (%ld vs %ld)\n",
- map->type, map->size,
- list->map->size);
- list->map->size = map->size;
- }
-
- kfree(map);
- *maplist = list;
- return 0;
- }
-
- if (drm_core_has_MTRR(dev)) {
- if (map->type == _DRM_FRAME_BUFFER ||
- (map->flags & _DRM_WRITE_COMBINING)) {
- map->mtrr = mtrr_add(map->offset, map->size,
- MTRR_TYPE_WRCOMB, 1);
- }
- }
- if (map->type == _DRM_REGISTERS) {
- map->handle = ioremap(map->offset, map->size);
- if (!map->handle) {
- kfree(map);
- return -ENOMEM;
- }
- }
-
- break;
- case _DRM_SHM:
- list = drm_find_matching_map(dev, map);
- if (list != NULL) {
- if(list->map->size != map->size) {
- DRM_DEBUG("Matching maps of type %d with "
- "mismatched sizes, (%ld vs %ld)\n",
- map->type, map->size, list->map->size);
- list->map->size = map->size;
- }
-
- kfree(map);
- *maplist = list;
- return 0;
- }
- map->handle = vmalloc_user(map->size);
- DRM_DEBUG("%lu %d %p\n",
- map->size, drm_order(map->size), map->handle);
- if (!map->handle) {
- kfree(map);
- return -ENOMEM;
- }
- map->offset = (unsigned long)map->handle;
- if (map->flags & _DRM_CONTAINS_LOCK) {
- /* Prevent a 2nd X Server from creating a 2nd lock */
- if (dev->primary->master->lock.hw_lock != NULL) {
- vfree(map->handle);
- kfree(map);
- return -EBUSY;
- }
- dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle; /* Pointer to lock */
- }
- break;
- case _DRM_AGP: {
- struct drm_agp_mem *entry;
- int valid = 0;
-
- if (!drm_core_has_AGP(dev)) {
- kfree(map);
- return -EINVAL;
- }
-#ifdef __alpha__
- map->offset += dev->hose->mem_space->start;
-#endif
- /* In some cases (i810 driver), user space may have already
- * added the AGP base itself, because dev->agp->base previously
- * only got set during AGP enable. So, only add the base
- * address if the map's offset isn't already within the
- * aperture.
- */
- if (map->offset < dev->agp->base ||
- map->offset > dev->agp->base +
- dev->agp->agp_info.aper_size * 1024 * 1024 - 1) {
- map->offset += dev->agp->base;
- }
- map->mtrr = dev->agp->agp_mtrr; /* for getmap */
-
- /* This assumes the DRM is in total control of AGP space.
- * It's not always the case as AGP can be in the control
- * of user space (i.e. i810 driver). So this loop will get
- * skipped and we double check that dev->agp->memory is
- * actually set as well as being invalid before EPERM'ing
- */
- list_for_each_entry(entry, &dev->agp->memory, head) {
- if ((map->offset >= entry->bound) &&
- (map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) {
- valid = 1;
- break;
- }
- }
- if (!list_empty(&dev->agp->memory) && !valid) {
- kfree(map);
- return -EPERM;
- }
- DRM_DEBUG("AGP offset = 0x%08llx, size = 0x%08lx\n",
- (unsigned long long)map->offset, map->size);
-
- break;
- }
- case _DRM_GEM:
- DRM_ERROR("tried to addmap GEM object\n");
- break;
- case _DRM_SCATTER_GATHER:
- if (!dev->sg) {
- kfree(map);
- return -EINVAL;
- }
- map->offset += (unsigned long)dev->sg->virtual;
- break;
- case _DRM_CONSISTENT:
- /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
- * As we're limiting the address to 2^32-1 (or less),
- * casting it down to 32 bits is no problem, but we
- * need to point to a 64bit variable first. */
- dmah = drm_pci_alloc(dev, map->size, map->size);
- if (!dmah) {
- kfree(map);
- return -ENOMEM;
- }
- map->handle = dmah->vaddr;
- map->offset = (unsigned long)dmah->busaddr;
- kfree(dmah);
- break;
- default:
- kfree(map);
- return -EINVAL;
- }
-
- list = kzalloc(sizeof(*list), GFP_KERNEL);
- if (!list) {
- if (map->type == _DRM_REGISTERS)
- iounmap(map->handle);
- kfree(map);
- return -EINVAL;
- }
- list->map = map;
-
- mutex_lock(&dev->struct_mutex);
- list_add(&list->head, &dev->maplist);
-
- /* Assign a 32-bit handle */
- /* We do it here so that dev->struct_mutex protects the increment */
- user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle :
- map->offset;
- ret = drm_map_handle(dev, &list->hash, user_token, 0,
- (map->type == _DRM_SHM));
- if (ret) {
- if (map->type == _DRM_REGISTERS)
- iounmap(map->handle);
- kfree(map);
- kfree(list);
- mutex_unlock(&dev->struct_mutex);
- return ret;
- }
-
- list->user_token = list->hash.key << PAGE_SHIFT;
- mutex_unlock(&dev->struct_mutex);
-
- if (!(map->flags & _DRM_DRIVER))
- list->master = dev->primary->master;
- *maplist = list;
- return 0;
- }
-
-int drm_addmap(struct drm_device * dev, resource_size_t offset,
- unsigned int size, enum drm_map_type type,
- enum drm_map_flags flags, struct drm_local_map ** map_ptr)
-{
- struct drm_map_list *list;
- int rc;
-
- rc = drm_addmap_core(dev, offset, size, type, flags, &list);
- if (!rc)
- *map_ptr = list->map;
- return rc;
-}
-
-EXPORT_SYMBOL(drm_addmap);
-
-/**
- * Ioctl to specify a range of memory that is available for mapping by a
- * non-root process.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_map structure.
- * \return zero on success or a negative value on error.
- *
- */
-int drm_addmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_map *map = data;
- struct drm_map_list *maplist;
- int err;
-
- if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP || map->type == _DRM_SHM))
- return -EPERM;
-
- err = drm_addmap_core(dev, map->offset, map->size, map->type,
- map->flags, &maplist);
-
- if (err)
- return err;
-
- /* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
- map->handle = (void *)(unsigned long)maplist->user_token;
- return 0;
-}
-
-/**
- * Remove a map private from list and deallocate resources if the mapping
- * isn't in use.
- *
- * Searches the map on drm_device::maplist, removes it from the list, see if
- * its being used, and free any associate resource (such as MTRR's) if it's not
- * being on use.
- *
- * \sa drm_addmap
- */
-int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
-{
- struct drm_map_list *r_list = NULL, *list_t;
- drm_dma_handle_t dmah;
- int found = 0;
- struct drm_master *master;
-
- /* Find the list entry for the map and remove it */
- list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
- if (r_list->map == map) {
- master = r_list->master;
- list_del(&r_list->head);
- drm_ht_remove_key(&dev->map_hash,
- r_list->user_token >> PAGE_SHIFT);
- kfree(r_list);
- found = 1;
- break;
- }
- }
-
- if (!found)
- return -EINVAL;
-
- switch (map->type) {
- case _DRM_REGISTERS:
- iounmap(map->handle);
- /* FALLTHROUGH */
- case _DRM_FRAME_BUFFER:
- if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
- int retcode;
- retcode = mtrr_del(map->mtrr, map->offset, map->size);
- DRM_DEBUG("mtrr_del=%d\n", retcode);
- }
- break;
- case _DRM_SHM:
- vfree(map->handle);
- if (master) {
- if (dev->sigdata.lock == master->lock.hw_lock)
- dev->sigdata.lock = NULL;
- master->lock.hw_lock = NULL; /* SHM removed */
- master->lock.file_priv = NULL;
- wake_up_interruptible_all(&master->lock.lock_queue);
- }
- break;
- case _DRM_AGP:
- case _DRM_SCATTER_GATHER:
- break;
- case _DRM_CONSISTENT:
- dmah.vaddr = map->handle;
- dmah.busaddr = map->offset;
- dmah.size = map->size;
- __drm_pci_free(dev, &dmah);
- break;
- case _DRM_GEM:
- DRM_ERROR("tried to rmmap GEM object\n");
- break;
- }
- kfree(map);
-
- return 0;
-}
-EXPORT_SYMBOL(drm_rmmap_locked);
-
-int drm_rmmap(struct drm_device *dev, struct drm_local_map *map)
-{
- int ret;
-
- mutex_lock(&dev->struct_mutex);
- ret = drm_rmmap_locked(dev, map);
- mutex_unlock(&dev->struct_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(drm_rmmap);
-
-/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on
- * the last close of the device, and this is necessary for cleanup when things
- * exit uncleanly. Therefore, having userland manually remove mappings seems
- * like a pointless exercise since they're going away anyway.
- *
- * One use case might be after addmap is allowed for normal users for SHM and
- * gets used by drivers that the server doesn't need to care about. This seems
- * unlikely.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a struct drm_map structure.
- * \return zero on success or a negative value on error.
- */
-int drm_rmmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_map *request = data;
- struct drm_local_map *map = NULL;
- struct drm_map_list *r_list;
- int ret;
-
- mutex_lock(&dev->struct_mutex);
- list_for_each_entry(r_list, &dev->maplist, head) {
- if (r_list->map &&
- r_list->user_token == (unsigned long)request->handle &&
- r_list->map->flags & _DRM_REMOVABLE) {
- map = r_list->map;
- break;
- }
- }
-
- /* List has wrapped around to the head pointer, or its empty we didn't
- * find anything.
- */
- if (list_empty(&dev->maplist) || !map) {
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
- }
-
- /* Register and framebuffer maps are permanent */
- if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
- mutex_unlock(&dev->struct_mutex);
- return 0;
- }
-
- ret = drm_rmmap_locked(dev, map);
-
- mutex_unlock(&dev->struct_mutex);
-
- return ret;
-}
-
-/**
- * Cleanup after an error on one of the addbufs() functions.
- *
- * \param dev DRM device.
- * \param entry buffer entry where the error occurred.
- *
- * Frees any pages and buffers associated with the given entry.
- */
-static void drm_cleanup_buf_error(struct drm_device * dev,
- struct drm_buf_entry * entry)
-{
- int i;
-
- if (entry->seg_count) {
- for (i = 0; i < entry->seg_count; i++) {
- if (entry->seglist[i]) {
- drm_pci_free(dev, entry->seglist[i]);
- }
- }
- kfree(entry->seglist);
-
- entry->seg_count = 0;
- }
-
- if (entry->buf_count) {
- for (i = 0; i < entry->buf_count; i++) {
- kfree(entry->buflist[i].dev_private);
- }
- kfree(entry->buflist);
-
- entry->buf_count = 0;
- }
-}
-
-#if __OS_HAS_AGP
-/**
- * Add AGP buffers for DMA transfers.
- *
- * \param dev struct drm_device to which the buffers are to be added.
- * \param request pointer to a struct drm_buf_desc describing the request.
- * \return zero on success or a negative number on failure.
- *
- * After some sanity checks creates a drm_buf structure for each buffer and
- * reallocates the buffer list of the same size order to accommodate the new
- * buffers.
- */
-int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
-{
- struct drm_device_dma *dma = dev->dma;
- struct drm_buf_entry *entry;
- struct drm_agp_mem *agp_entry;
- struct drm_buf *buf;
- unsigned long offset;
- unsigned long agp_offset;
- int count;
- int order;
- int size;
- int alignment;
- int page_order;
- int total;
- int byte_count;
- int i, valid;
- struct drm_buf **temp_buflist;
-
- if (!dma)
- return -EINVAL;
-
- count = request->count;
- order = drm_order(request->size);
- size = 1 << order;
-
- alignment = (request->flags & _DRM_PAGE_ALIGN)
- ? PAGE_ALIGN(size) : size;
- page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
- total = PAGE_SIZE << page_order;
-
- byte_count = 0;
- agp_offset = dev->agp->base + request->agp_start;
-
- DRM_DEBUG("count: %d\n", count);
- DRM_DEBUG("order: %d\n", order);
- DRM_DEBUG("size: %d\n", size);
- DRM_DEBUG("agp_offset: %lx\n", agp_offset);
- DRM_DEBUG("alignment: %d\n", alignment);
- DRM_DEBUG("page_order: %d\n", page_order);
- DRM_DEBUG("total: %d\n", total);
-
- if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
- return -EINVAL;
- if (dev->queue_count)
- return -EBUSY; /* Not while in use */
-
- /* Make sure buffers are located in AGP memory that we own */
- valid = 0;
- list_for_each_entry(agp_entry, &dev->agp->memory, head) {
- if ((agp_offset >= agp_entry->bound) &&
- (agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
- valid = 1;
- break;
- }
- }
- if (!list_empty(&dev->agp->memory) && !valid) {
- DRM_DEBUG("zone invalid\n");
- return -EINVAL;
- }
- spin_lock(&dev->count_lock);
- if (dev->buf_use) {
- spin_unlock(&dev->count_lock);
- return -EBUSY;
- }
- atomic_inc(&dev->buf_alloc);
- spin_unlock(&dev->count_lock);
-
- mutex_lock(&dev->struct_mutex);
- entry = &dma->bufs[order];
- if (entry->buf_count) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM; /* May only call once for each order */
- }
-
- if (count < 0 || count > 4096) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -EINVAL;
- }
-
- entry->buflist = kzalloc(count * sizeof(*entry->buflist), GFP_KERNEL);
- if (!entry->buflist) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
-
- entry->buf_size = size;
- entry->page_order = page_order;
-
- offset = 0;
-
- while (entry->buf_count < count) {
- buf = &entry->buflist[entry->buf_count];
- buf->idx = dma->buf_count + entry->buf_count;
- buf->total = alignment;
- buf->order = order;
- buf->used = 0;
-
- buf->offset = (dma->byte_count + offset);
- buf->bus_address = agp_offset + offset;
- buf->address = (void *)(agp_offset + offset);
- buf->next = NULL;
- buf->waiting = 0;
- buf->pending = 0;
- init_waitqueue_head(&buf->dma_wait);
- buf->file_priv = NULL;
-
- buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL);
- if (!buf->dev_private) {
- /* Set count correctly so we free the proper amount. */
- entry->buf_count = count;
- drm_cleanup_buf_error(dev, entry);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
-
- DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
-
- offset += alignment;
- entry->buf_count++;
- byte_count += PAGE_SIZE << page_order;
- }
-
- DRM_DEBUG("byte_count: %d\n", byte_count);
-
- temp_buflist = krealloc(dma->buflist,
- (dma->buf_count + entry->buf_count) *
- sizeof(*dma->buflist), GFP_KERNEL);
- if (!temp_buflist) {
- /* Free the entry because it isn't valid */
- drm_cleanup_buf_error(dev, entry);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
- dma->buflist = temp_buflist;
-
- for (i = 0; i < entry->buf_count; i++) {
- dma->buflist[i + dma->buf_count] = &entry->buflist[i];
- }
-
- dma->buf_count += entry->buf_count;
- dma->seg_count += entry->seg_count;
- dma->page_count += byte_count >> PAGE_SHIFT;
- dma->byte_count += byte_count;
-
- DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
- DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
-
- mutex_unlock(&dev->struct_mutex);
-
- request->count = entry->buf_count;
- request->size = size;
-
- dma->flags = _DRM_DMA_USE_AGP;
-
- atomic_dec(&dev->buf_alloc);
- return 0;
-}
-EXPORT_SYMBOL(drm_addbufs_agp);
-#endif /* __OS_HAS_AGP */
-
-int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
-{
- struct drm_device_dma *dma = dev->dma;
- int count;
- int order;
- int size;
- int total;
- int page_order;
- struct drm_buf_entry *entry;
- drm_dma_handle_t *dmah;
- struct drm_buf *buf;
- int alignment;
- unsigned long offset;
- int i;
- int byte_count;
- int page_count;
- unsigned long *temp_pagelist;
- struct drm_buf **temp_buflist;
-
- if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
- return -EINVAL;
-
- if (!dma)
- return -EINVAL;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- count = request->count;
- order = drm_order(request->size);
- size = 1 << order;
-
- DRM_DEBUG("count=%d, size=%d (%d), order=%d, queue_count=%d\n",
- request->count, request->size, size, order, dev->queue_count);
-
- if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
- return -EINVAL;
- if (dev->queue_count)
- return -EBUSY; /* Not while in use */
-
- alignment = (request->flags & _DRM_PAGE_ALIGN)
- ? PAGE_ALIGN(size) : size;
- page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
- total = PAGE_SIZE << page_order;
-
- spin_lock(&dev->count_lock);
- if (dev->buf_use) {
- spin_unlock(&dev->count_lock);
- return -EBUSY;
- }
- atomic_inc(&dev->buf_alloc);
- spin_unlock(&dev->count_lock);
-
- mutex_lock(&dev->struct_mutex);
- entry = &dma->bufs[order];
- if (entry->buf_count) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM; /* May only call once for each order */
- }
-
- if (count < 0 || count > 4096) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -EINVAL;
- }
-
- entry->buflist = kzalloc(count * sizeof(*entry->buflist), GFP_KERNEL);
- if (!entry->buflist) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
-
- entry->seglist = kzalloc(count * sizeof(*entry->seglist), GFP_KERNEL);
- if (!entry->seglist) {
- kfree(entry->buflist);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
-
- /* Keep the original pagelist until we know all the allocations
- * have succeeded
- */
- temp_pagelist = kmalloc((dma->page_count + (count << page_order)) *
- sizeof(*dma->pagelist), GFP_KERNEL);
- if (!temp_pagelist) {
- kfree(entry->buflist);
- kfree(entry->seglist);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
- memcpy(temp_pagelist,
- dma->pagelist, dma->page_count * sizeof(*dma->pagelist));
- DRM_DEBUG("pagelist: %d entries\n",
- dma->page_count + (count << page_order));
-
- entry->buf_size = size;
- entry->page_order = page_order;
- byte_count = 0;
- page_count = 0;
-
- while (entry->buf_count < count) {
-
- dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000);
-
- if (!dmah) {
- /* Set count correctly so we free the proper amount. */
- entry->buf_count = count;
- entry->seg_count = count;
- drm_cleanup_buf_error(dev, entry);
- kfree(temp_pagelist);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
- entry->seglist[entry->seg_count++] = dmah;
- for (i = 0; i < (1 << page_order); i++) {
- DRM_DEBUG("page %d @ 0x%08lx\n",
- dma->page_count + page_count,
- (unsigned long)dmah->vaddr + PAGE_SIZE * i);
- temp_pagelist[dma->page_count + page_count++]
- = (unsigned long)dmah->vaddr + PAGE_SIZE * i;
- }
- for (offset = 0;
- offset + size <= total && entry->buf_count < count;
- offset += alignment, ++entry->buf_count) {
- buf = &entry->buflist[entry->buf_count];
- buf->idx = dma->buf_count + entry->buf_count;
- buf->total = alignment;
- buf->order = order;
- buf->used = 0;
- buf->offset = (dma->byte_count + byte_count + offset);
- buf->address = (void *)(dmah->vaddr + offset);
- buf->bus_address = dmah->busaddr + offset;
- buf->next = NULL;
- buf->waiting = 0;
- buf->pending = 0;
- init_waitqueue_head(&buf->dma_wait);
- buf->file_priv = NULL;
-
- buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = kzalloc(buf->dev_priv_size,
- GFP_KERNEL);
- if (!buf->dev_private) {
- /* Set count correctly so we free the proper amount. */
- entry->buf_count = count;
- entry->seg_count = count;
- drm_cleanup_buf_error(dev, entry);
- kfree(temp_pagelist);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
-
- DRM_DEBUG("buffer %d @ %p\n",
- entry->buf_count, buf->address);
- }
- byte_count += PAGE_SIZE << page_order;
- }
-
- temp_buflist = krealloc(dma->buflist,
- (dma->buf_count + entry->buf_count) *
- sizeof(*dma->buflist), GFP_KERNEL);
- if (!temp_buflist) {
- /* Free the entry because it isn't valid */
- drm_cleanup_buf_error(dev, entry);
- kfree(temp_pagelist);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
- dma->buflist = temp_buflist;
-
- for (i = 0; i < entry->buf_count; i++) {
- dma->buflist[i + dma->buf_count] = &entry->buflist[i];
- }
-
- /* No allocations failed, so now we can replace the original pagelist
- * with the new one.
- */
- if (dma->page_count) {
- kfree(dma->pagelist);
- }
- dma->pagelist = temp_pagelist;
-
- dma->buf_count += entry->buf_count;
- dma->seg_count += entry->seg_count;
- dma->page_count += entry->seg_count << page_order;
- dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
-
- mutex_unlock(&dev->struct_mutex);
-
- request->count = entry->buf_count;
- request->size = size;
-
- if (request->flags & _DRM_PCI_BUFFER_RO)
- dma->flags = _DRM_DMA_USE_PCI_RO;
-
- atomic_dec(&dev->buf_alloc);
- return 0;
-
-}
-EXPORT_SYMBOL(drm_addbufs_pci);
-
-static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request)
-{
- struct drm_device_dma *dma = dev->dma;
- struct drm_buf_entry *entry;
- struct drm_buf *buf;
- unsigned long offset;
- unsigned long agp_offset;
- int count;
- int order;
- int size;
- int alignment;
- int page_order;
- int total;
- int byte_count;
- int i;
- struct drm_buf **temp_buflist;
-
- if (!drm_core_check_feature(dev, DRIVER_SG))
- return -EINVAL;
-
- if (!dma)
- return -EINVAL;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- count = request->count;
- order = drm_order(request->size);
- size = 1 << order;
-
- alignment = (request->flags & _DRM_PAGE_ALIGN)
- ? PAGE_ALIGN(size) : size;
- page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
- total = PAGE_SIZE << page_order;
-
- byte_count = 0;
- agp_offset = request->agp_start;
-
- DRM_DEBUG("count: %d\n", count);
- DRM_DEBUG("order: %d\n", order);
- DRM_DEBUG("size: %d\n", size);
- DRM_DEBUG("agp_offset: %lu\n", agp_offset);
- DRM_DEBUG("alignment: %d\n", alignment);
- DRM_DEBUG("page_order: %d\n", page_order);
- DRM_DEBUG("total: %d\n", total);
-
- if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
- return -EINVAL;
- if (dev->queue_count)
- return -EBUSY; /* Not while in use */
-
- spin_lock(&dev->count_lock);
- if (dev->buf_use) {
- spin_unlock(&dev->count_lock);
- return -EBUSY;
- }
- atomic_inc(&dev->buf_alloc);
- spin_unlock(&dev->count_lock);
-
- mutex_lock(&dev->struct_mutex);
- entry = &dma->bufs[order];
- if (entry->buf_count) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM; /* May only call once for each order */
- }
-
- if (count < 0 || count > 4096) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -EINVAL;
- }
-
- entry->buflist = kzalloc(count * sizeof(*entry->buflist),
- GFP_KERNEL);
- if (!entry->buflist) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
-
- entry->buf_size = size;
- entry->page_order = page_order;
-
- offset = 0;
-
- while (entry->buf_count < count) {
- buf = &entry->buflist[entry->buf_count];
- buf->idx = dma->buf_count + entry->buf_count;
- buf->total = alignment;
- buf->order = order;
- buf->used = 0;
-
- buf->offset = (dma->byte_count + offset);
- buf->bus_address = agp_offset + offset;
- buf->address = (void *)(agp_offset + offset
- + (unsigned long)dev->sg->virtual);
- buf->next = NULL;
- buf->waiting = 0;
- buf->pending = 0;
- init_waitqueue_head(&buf->dma_wait);
- buf->file_priv = NULL;
-
- buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL);
- if (!buf->dev_private) {
- /* Set count correctly so we free the proper amount. */
- entry->buf_count = count;
- drm_cleanup_buf_error(dev, entry);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
-
- DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
-
- offset += alignment;
- entry->buf_count++;
- byte_count += PAGE_SIZE << page_order;
- }
-
- DRM_DEBUG("byte_count: %d\n", byte_count);
-
- temp_buflist = krealloc(dma->buflist,
- (dma->buf_count + entry->buf_count) *
- sizeof(*dma->buflist), GFP_KERNEL);
- if (!temp_buflist) {
- /* Free the entry because it isn't valid */
- drm_cleanup_buf_error(dev, entry);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
- dma->buflist = temp_buflist;
-
- for (i = 0; i < entry->buf_count; i++) {
- dma->buflist[i + dma->buf_count] = &entry->buflist[i];
- }
-
- dma->buf_count += entry->buf_count;
- dma->seg_count += entry->seg_count;
- dma->page_count += byte_count >> PAGE_SHIFT;
- dma->byte_count += byte_count;
-
- DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
- DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
-
- mutex_unlock(&dev->struct_mutex);
-
- request->count = entry->buf_count;
- request->size = size;
-
- dma->flags = _DRM_DMA_USE_SG;
-
- atomic_dec(&dev->buf_alloc);
- return 0;
-}
-
-static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request)
-{
- struct drm_device_dma *dma = dev->dma;
- struct drm_buf_entry *entry;
- struct drm_buf *buf;
- unsigned long offset;
- unsigned long agp_offset;
- int count;
- int order;
- int size;
- int alignment;
- int page_order;
- int total;
- int byte_count;
- int i;
- struct drm_buf **temp_buflist;
-
- if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
- return -EINVAL;
-
- if (!dma)
- return -EINVAL;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- count = request->count;
- order = drm_order(request->size);
- size = 1 << order;
-
- alignment = (request->flags & _DRM_PAGE_ALIGN)
- ? PAGE_ALIGN(size) : size;
- page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
- total = PAGE_SIZE << page_order;
-
- byte_count = 0;
- agp_offset = request->agp_start;
-
- DRM_DEBUG("count: %d\n", count);
- DRM_DEBUG("order: %d\n", order);
- DRM_DEBUG("size: %d\n", size);
- DRM_DEBUG("agp_offset: %lu\n", agp_offset);
- DRM_DEBUG("alignment: %d\n", alignment);
- DRM_DEBUG("page_order: %d\n", page_order);
- DRM_DEBUG("total: %d\n", total);
-
- if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
- return -EINVAL;
- if (dev->queue_count)
- return -EBUSY; /* Not while in use */
-
- spin_lock(&dev->count_lock);
- if (dev->buf_use) {
- spin_unlock(&dev->count_lock);
- return -EBUSY;
- }
- atomic_inc(&dev->buf_alloc);
- spin_unlock(&dev->count_lock);
-
- mutex_lock(&dev->struct_mutex);
- entry = &dma->bufs[order];
- if (entry->buf_count) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM; /* May only call once for each order */
- }
-
- if (count < 0 || count > 4096) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -EINVAL;
- }
-
- entry->buflist = kzalloc(count * sizeof(*entry->buflist),
- GFP_KERNEL);
- if (!entry->buflist) {
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
-
- entry->buf_size = size;
- entry->page_order = page_order;
-
- offset = 0;
-
- while (entry->buf_count < count) {
- buf = &entry->buflist[entry->buf_count];
- buf->idx = dma->buf_count + entry->buf_count;
- buf->total = alignment;
- buf->order = order;
- buf->used = 0;
-
- buf->offset = (dma->byte_count + offset);
- buf->bus_address = agp_offset + offset;
- buf->address = (void *)(agp_offset + offset);
- buf->next = NULL;
- buf->waiting = 0;
- buf->pending = 0;
- init_waitqueue_head(&buf->dma_wait);
- buf->file_priv = NULL;
-
- buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL);
- if (!buf->dev_private) {
- /* Set count correctly so we free the proper amount. */
- entry->buf_count = count;
- drm_cleanup_buf_error(dev, entry);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
-
- DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
-
- offset += alignment;
- entry->buf_count++;
- byte_count += PAGE_SIZE << page_order;
- }
-
- DRM_DEBUG("byte_count: %d\n", byte_count);
-
- temp_buflist = krealloc(dma->buflist,
- (dma->buf_count + entry->buf_count) *
- sizeof(*dma->buflist), GFP_KERNEL);
- if (!temp_buflist) {
- /* Free the entry because it isn't valid */
- drm_cleanup_buf_error(dev, entry);
- mutex_unlock(&dev->struct_mutex);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
- dma->buflist = temp_buflist;
-
- for (i = 0; i < entry->buf_count; i++) {
- dma->buflist[i + dma->buf_count] = &entry->buflist[i];
- }
-
- dma->buf_count += entry->buf_count;
- dma->seg_count += entry->seg_count;
- dma->page_count += byte_count >> PAGE_SHIFT;
- dma->byte_count += byte_count;
-
- DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
- DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
-
- mutex_unlock(&dev->struct_mutex);
-
- request->count = entry->buf_count;
- request->size = size;
-
- dma->flags = _DRM_DMA_USE_FB;
-
- atomic_dec(&dev->buf_alloc);
- return 0;
-}
-
-
-/**
- * Add buffers for DMA transfers (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a struct drm_buf_desc request.
- * \return zero on success or a negative number on failure.
- *
- * According with the memory type specified in drm_buf_desc::flags and the
- * build options, it dispatches the call either to addbufs_agp(),
- * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
- * PCI memory respectively.
- */
-int drm_addbufs(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_buf_desc *request = data;
- int ret;
-
- if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
- return -EINVAL;
-
-#if __OS_HAS_AGP
- if (request->flags & _DRM_AGP_BUFFER)
- ret = drm_addbufs_agp(dev, request);
- else
-#endif
- if (request->flags & _DRM_SG_BUFFER)
- ret = drm_addbufs_sg(dev, request);
- else if (request->flags & _DRM_FB_BUFFER)
- ret = drm_addbufs_fb(dev, request);
- else
- ret = drm_addbufs_pci(dev, request);
-
- return ret;
-}
-
-/**
- * Get information about the buffer mappings.
- *
- * This was originally mean for debugging purposes, or by a sophisticated
- * client library to determine how best to use the available buffers (e.g.,
- * large buffers can be used for image transfer).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_buf_info structure.
- * \return zero on success or a negative number on failure.
- *
- * Increments drm_device::buf_use while holding the drm_device::count_lock
- * lock, preventing of allocating more buffers after this call. Information
- * about each requested buffer is then copied into user space.
- */
-int drm_infobufs(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_device_dma *dma = dev->dma;
- struct drm_buf_info *request = data;
- int i;
- int count;
-
- if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
- return -EINVAL;
-
- if (!dma)
- return -EINVAL;
-
- spin_lock(&dev->count_lock);
- if (atomic_read(&dev->buf_alloc)) {
- spin_unlock(&dev->count_lock);
- return -EBUSY;
- }
- ++dev->buf_use; /* Can't allocate more after this call */
- spin_unlock(&dev->count_lock);
-
- for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
- if (dma->bufs[i].buf_count)
- ++count;
- }
-
- DRM_DEBUG("count = %d\n", count);
-
- if (request->count >= count) {
- for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
- if (dma->bufs[i].buf_count) {
- struct drm_buf_desc __user *to =
- &request->list[count];
- struct drm_buf_entry *from = &dma->bufs[i];
- struct drm_freelist *list = &dma->bufs[i].freelist;
- if (copy_to_user(&to->count,
- &from->buf_count,
- sizeof(from->buf_count)) ||
- copy_to_user(&to->size,
- &from->buf_size,
- sizeof(from->buf_size)) ||
- copy_to_user(&to->low_mark,
- &list->low_mark,
- sizeof(list->low_mark)) ||
- copy_to_user(&to->high_mark,
- &list->high_mark,
- sizeof(list->high_mark)))
- return -EFAULT;
-
- DRM_DEBUG("%d %d %d %d %d\n",
- i,
- dma->bufs[i].buf_count,
- dma->bufs[i].buf_size,
- dma->bufs[i].freelist.low_mark,
- dma->bufs[i].freelist.high_mark);
- ++count;
- }
- }
- }
- request->count = count;
-
- return 0;
-}
-
-/**
- * Specifies a low and high water mark for buffer allocation
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg a pointer to a drm_buf_desc structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies that the size order is bounded between the admissible orders and
- * updates the respective drm_device_dma::bufs entry low and high water mark.
- *
- * \note This ioctl is deprecated and mostly never used.
- */
-int drm_markbufs(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_device_dma *dma = dev->dma;
- struct drm_buf_desc *request = data;
- int order;
- struct drm_buf_entry *entry;
-
- if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
- return -EINVAL;
-
- if (!dma)
- return -EINVAL;
-
- DRM_DEBUG("%d, %d, %d\n",
- request->size, request->low_mark, request->high_mark);
- order = drm_order(request->size);
- if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
- return -EINVAL;
- entry = &dma->bufs[order];
-
- if (request->low_mark < 0 || request->low_mark > entry->buf_count)
- return -EINVAL;
- if (request->high_mark < 0 || request->high_mark > entry->buf_count)
- return -EINVAL;
-
- entry->freelist.low_mark = request->low_mark;
- entry->freelist.high_mark = request->high_mark;
-
- return 0;
-}
-
-/**
- * Unreserve the buffers in list, previously reserved using drmDMA.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_buf_free structure.
- * \return zero on success or a negative number on failure.
- *
- * Calls free_buffer() for each used buffer.
- * This function is primarily used for debugging.
- */
-int drm_freebufs(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_device_dma *dma = dev->dma;
- struct drm_buf_free *request = data;
- int i;
- int idx;
- struct drm_buf *buf;
-
- if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
- return -EINVAL;
-
- if (!dma)
- return -EINVAL;
-
- DRM_DEBUG("%d\n", request->count);
- for (i = 0; i < request->count; i++) {
- if (copy_from_user(&idx, &request->list[i], sizeof(idx)))
- return -EFAULT;
- if (idx < 0 || idx >= dma->buf_count) {
- DRM_ERROR("Index %d (of %d max)\n",
- idx, dma->buf_count - 1);
- return -EINVAL;
- }
- buf = dma->buflist[idx];
- if (buf->file_priv != file_priv) {
- DRM_ERROR("Process %d freeing buffer not owned\n",
- task_pid_nr(current));
- return -EINVAL;
- }
- drm_free_buffer(dev, buf);
- }
-
- return 0;
-}
-
-/**
- * Maps all of the DMA buffers into client-virtual space (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_buf_map structure.
- * \return zero on success or a negative number on failure.
- *
- * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information
- * about each buffer into user space. For PCI buffers, it calls do_mmap() with
- * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
- * drm_mmap_dma().
- */
-int drm_mapbufs(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_device_dma *dma = dev->dma;
- int retcode = 0;
- const int zero = 0;
- unsigned long virtual;
- unsigned long address;
- struct drm_buf_map *request = data;
- int i;
-
- if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
- return -EINVAL;
-
- if (!dma)
- return -EINVAL;
-
- spin_lock(&dev->count_lock);
- if (atomic_read(&dev->buf_alloc)) {
- spin_unlock(&dev->count_lock);
- return -EBUSY;
- }
- dev->buf_use++; /* Can't allocate more after this call */
- spin_unlock(&dev->count_lock);
-
- if (request->count >= dma->buf_count) {
- if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
- || (drm_core_check_feature(dev, DRIVER_SG)
- && (dma->flags & _DRM_DMA_USE_SG))
- || (drm_core_check_feature(dev, DRIVER_FB_DMA)
- && (dma->flags & _DRM_DMA_USE_FB))) {
- struct drm_local_map *map = dev->agp_buffer_map;
- unsigned long token = dev->agp_buffer_token;
-
- if (!map) {
- retcode = -EINVAL;
- goto done;
- }
- down_write(¤t->mm->mmap_sem);
- virtual = do_mmap(file_priv->filp, 0, map->size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- token);
- up_write(¤t->mm->mmap_sem);
- } else {
- down_write(¤t->mm->mmap_sem);
- virtual = do_mmap(file_priv->filp, 0, dma->byte_count,
- PROT_READ | PROT_WRITE,
- MAP_SHARED, 0);
- up_write(¤t->mm->mmap_sem);
- }
- if (virtual > -1024UL) {
- /* Real error */
- retcode = (signed long)virtual;
- goto done;
- }
- request->virtual = (void __user *)virtual;
-
- for (i = 0; i < dma->buf_count; i++) {
- if (copy_to_user(&request->list[i].idx,
- &dma->buflist[i]->idx,
- sizeof(request->list[0].idx))) {
- retcode = -EFAULT;
- goto done;
- }
- if (copy_to_user(&request->list[i].total,
- &dma->buflist[i]->total,
- sizeof(request->list[0].total))) {
- retcode = -EFAULT;
- goto done;
- }
- if (copy_to_user(&request->list[i].used,
- &zero, sizeof(zero))) {
- retcode = -EFAULT;
- goto done;
- }
- address = virtual + dma->buflist[i]->offset; /* *** */
- if (copy_to_user(&request->list[i].address,
- &address, sizeof(address))) {
- retcode = -EFAULT;
- goto done;
- }
- }
- }
- done:
- request->count = dma->buf_count;
- DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
-
- return retcode;
-}
-
-/**
- * Compute size order. Returns the exponent of the smaller power of two which
- * is greater or equal to given number.
- *
- * \param size size.
- * \return order.
- *
- * \todo Can be made faster.
- */
-int drm_order(unsigned long size)
-{
- int order;
- unsigned long tmp;
-
- for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
-
- if (size & (size - 1))
- ++order;
-
- return order;
-}
-EXPORT_SYMBOL(drm_order);
+++ /dev/null
-/**************************************************************************
- *
- * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-/*
- * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include "drmP.h"
-
-#if defined(CONFIG_X86)
-static void
-drm_clflush_page(struct page *page)
-{
- uint8_t *page_virtual;
- unsigned int i;
-
- if (unlikely(page == NULL))
- return;
-
- page_virtual = kmap_atomic(page, KM_USER0);
- for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
- clflush(page_virtual + i);
- kunmap_atomic(page_virtual, KM_USER0);
-}
-
-static void drm_cache_flush_clflush(struct page *pages[],
- unsigned long num_pages)
-{
- unsigned long i;
-
- mb();
- for (i = 0; i < num_pages; i++)
- drm_clflush_page(*pages++);
- mb();
-}
-
-static void
-drm_clflush_ipi_handler(void *null)
-{
- wbinvd();
-}
-#endif
-
-void
-drm_clflush_pages(struct page *pages[], unsigned long num_pages)
-{
-
-#if defined(CONFIG_X86)
- if (cpu_has_clflush) {
- drm_cache_flush_clflush(pages, num_pages);
- return;
- }
-
- if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0)
- printk(KERN_ERR "Timed out waiting for cache flush.\n");
-
-#elif defined(__powerpc__)
- unsigned long i;
- for (i = 0; i < num_pages; i++) {
- struct page *page = pages[i];
- void *page_virtual;
-
- if (unlikely(page == NULL))
- continue;
-
- page_virtual = kmap_atomic(page, KM_USER0);
- flush_dcache_range((unsigned long)page_virtual,
- (unsigned long)page_virtual + PAGE_SIZE);
- kunmap_atomic(page_virtual, KM_USER0);
- }
-#else
- printk(KERN_ERR "Architecture has no drm_cache.c support\n");
- WARN_ON_ONCE(1);
-#endif
-}
-EXPORT_SYMBOL(drm_clflush_pages);
+++ /dev/null
-/**
- * \file drm_context.c
- * IOCTLs for generic contexts
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * ChangeLog:
- * 2001-11-16 Torsten Duwe <duwe@caldera.de>
- * added context constructor/destructor hooks,
- * needed by SiS driver's memory management.
- */
-
-#include "drmP.h"
-
-/******************************************************************/
-/** \name Context bitmap support */
-/*@{*/
-
-/**
- * Free a handle from the context bitmap.
- *
- * \param dev DRM device.
- * \param ctx_handle context handle.
- *
- * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
- * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
- * lock.
- */
-void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
-{
- mutex_lock(&dev->struct_mutex);
- idr_remove(&dev->ctx_idr, ctx_handle);
- mutex_unlock(&dev->struct_mutex);
-}
-
-/**
- * Context bitmap allocation.
- *
- * \param dev DRM device.
- * \return (non-negative) context handle on success or a negative number on failure.
- *
- * Allocate a new idr from drm_device::ctx_idr while holding the
- * drm_device::struct_mutex lock.
- */
-static int drm_ctxbitmap_next(struct drm_device * dev)
-{
- int new_id;
- int ret;
-
-again:
- if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
- DRM_ERROR("Out of memory expanding drawable idr\n");
- return -ENOMEM;
- }
- mutex_lock(&dev->struct_mutex);
- ret = idr_get_new_above(&dev->ctx_idr, NULL,
- DRM_RESERVED_CONTEXTS, &new_id);
- if (ret == -EAGAIN) {
- mutex_unlock(&dev->struct_mutex);
- goto again;
- }
- mutex_unlock(&dev->struct_mutex);
- return new_id;
-}
-
-/**
- * Context bitmap initialization.
- *
- * \param dev DRM device.
- *
- * Initialise the drm_device::ctx_idr
- */
-int drm_ctxbitmap_init(struct drm_device * dev)
-{
- idr_init(&dev->ctx_idr);
- return 0;
-}
-
-/**
- * Context bitmap cleanup.
- *
- * \param dev DRM device.
- *
- * Free all idr members using drm_ctx_sarea_free helper function
- * while holding the drm_device::struct_mutex lock.
- */
-void drm_ctxbitmap_cleanup(struct drm_device * dev)
-{
- mutex_lock(&dev->struct_mutex);
- idr_remove_all(&dev->ctx_idr);
- mutex_unlock(&dev->struct_mutex);
-}
-
-/*@}*/
-
-/******************************************************************/
-/** \name Per Context SAREA Support */
-/*@{*/
-
-/**
- * Get per-context SAREA.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx_priv_map structure.
- * \return zero on success or a negative number on failure.
- *
- * Gets the map from drm_device::ctx_idr with the handle specified and
- * returns its handle.
- */
-int drm_getsareactx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_ctx_priv_map *request = data;
- struct drm_local_map *map;
- struct drm_map_list *_entry;
-
- mutex_lock(&dev->struct_mutex);
-
- map = idr_find(&dev->ctx_idr, request->ctx_id);
- if (!map) {
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
- }
-
- mutex_unlock(&dev->struct_mutex);
-
- request->handle = NULL;
- list_for_each_entry(_entry, &dev->maplist, head) {
- if (_entry->map == map) {
- request->handle =
- (void *)(unsigned long)_entry->user_token;
- break;
- }
- }
- if (request->handle == NULL)
- return -EINVAL;
-
- return 0;
-}
-
-/**
- * Set per-context SAREA.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx_priv_map structure.
- * \return zero on success or a negative number on failure.
- *
- * Searches the mapping specified in \p arg and update the entry in
- * drm_device::ctx_idr with it.
- */
-int drm_setsareactx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_ctx_priv_map *request = data;
- struct drm_local_map *map = NULL;
- struct drm_map_list *r_list = NULL;
-
- mutex_lock(&dev->struct_mutex);
- list_for_each_entry(r_list, &dev->maplist, head) {
- if (r_list->map
- && r_list->user_token == (unsigned long) request->handle)
- goto found;
- }
- bad:
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
-
- found:
- map = r_list->map;
- if (!map)
- goto bad;
-
- if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id)))
- goto bad;
-
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
-/*@}*/
-
-/******************************************************************/
-/** \name The actual DRM context handling routines */
-/*@{*/
-
-/**
- * Switch context.
- *
- * \param dev DRM device.
- * \param old old context handle.
- * \param new new context handle.
- * \return zero on success or a negative number on failure.
- *
- * Attempt to set drm_device::context_flag.
- */
-static int drm_context_switch(struct drm_device * dev, int old, int new)
-{
- if (test_and_set_bit(0, &dev->context_flag)) {
- DRM_ERROR("Reentering -- FIXME\n");
- return -EBUSY;
- }
-
- DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
- if (new == dev->last_context) {
- clear_bit(0, &dev->context_flag);
- return 0;
- }
-
- return 0;
-}
-
-/**
- * Complete context switch.
- *
- * \param dev DRM device.
- * \param new new context handle.
- * \return zero on success or a negative number on failure.
- *
- * Updates drm_device::last_context and drm_device::last_switch. Verifies the
- * hardware lock is held, clears the drm_device::context_flag and wakes up
- * drm_device::context_wait.
- */
-static int drm_context_switch_complete(struct drm_device *dev,
- struct drm_file *file_priv, int new)
-{
- dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
- dev->last_switch = jiffies;
-
- if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) {
- DRM_ERROR("Lock isn't held after context switch\n");
- }
-
- /* If a context switch is ever initiated
- when the kernel holds the lock, release
- that lock here. */
- clear_bit(0, &dev->context_flag);
- wake_up(&dev->context_wait);
-
- return 0;
-}
-
-/**
- * Reserve contexts.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx_res structure.
- * \return zero on success or a negative number on failure.
- */
-int drm_resctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_ctx_res *res = data;
- struct drm_ctx ctx;
- int i;
-
- if (res->count >= DRM_RESERVED_CONTEXTS) {
- memset(&ctx, 0, sizeof(ctx));
- for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
- ctx.handle = i;
- if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx)))
- return -EFAULT;
- }
- }
- res->count = DRM_RESERVED_CONTEXTS;
-
- return 0;
-}
-
-/**
- * Add context.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx structure.
- * \return zero on success or a negative number on failure.
- *
- * Get a new handle for the context and copy to userspace.
- */
-int drm_addctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_ctx_list *ctx_entry;
- struct drm_ctx *ctx = data;
-
- ctx->handle = drm_ctxbitmap_next(dev);
- if (ctx->handle == DRM_KERNEL_CONTEXT) {
- /* Skip kernel's context and get a new one. */
- ctx->handle = drm_ctxbitmap_next(dev);
- }
- DRM_DEBUG("%d\n", ctx->handle);
- if (ctx->handle == -1) {
- DRM_DEBUG("Not enough free contexts.\n");
- /* Should this return -EBUSY instead? */
- return -ENOMEM;
- }
-
- ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL);
- if (!ctx_entry) {
- DRM_DEBUG("out of memory\n");
- return -ENOMEM;
- }
-
- INIT_LIST_HEAD(&ctx_entry->head);
- ctx_entry->handle = ctx->handle;
- ctx_entry->tag = file_priv;
-
- mutex_lock(&dev->ctxlist_mutex);
- list_add(&ctx_entry->head, &dev->ctxlist);
- ++dev->ctx_count;
- mutex_unlock(&dev->ctxlist_mutex);
-
- return 0;
-}
-
-int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- /* This does nothing */
- return 0;
-}
-
-/**
- * Get context.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx structure.
- * \return zero on success or a negative number on failure.
- */
-int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- struct drm_ctx *ctx = data;
-
- /* This is 0, because we don't handle any context flags */
- ctx->flags = 0;
-
- return 0;
-}
-
-/**
- * Switch context.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx structure.
- * \return zero on success or a negative number on failure.
- *
- * Calls context_switch().
- */
-int drm_switchctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_ctx *ctx = data;
-
- DRM_DEBUG("%d\n", ctx->handle);
- return drm_context_switch(dev, dev->last_context, ctx->handle);
-}
-
-/**
- * New context.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx structure.
- * \return zero on success or a negative number on failure.
- *
- * Calls context_switch_complete().
- */
-int drm_newctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_ctx *ctx = data;
-
- DRM_DEBUG("%d\n", ctx->handle);
- drm_context_switch_complete(dev, file_priv, ctx->handle);
-
- return 0;
-}
-
-/**
- * Remove context.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx structure.
- * \return zero on success or a negative number on failure.
- *
- * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
- */
-int drm_rmctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_ctx *ctx = data;
-
- DRM_DEBUG("%d\n", ctx->handle);
- if (ctx->handle != DRM_KERNEL_CONTEXT) {
- if (dev->driver->context_dtor)
- dev->driver->context_dtor(dev, ctx->handle);
- drm_ctxbitmap_free(dev, ctx->handle);
- }
-
- mutex_lock(&dev->ctxlist_mutex);
- if (!list_empty(&dev->ctxlist)) {
- struct drm_ctx_list *pos, *n;
-
- list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
- if (pos->handle == ctx->handle) {
- list_del(&pos->head);
- kfree(pos);
- --dev->ctx_count;
- }
- }
- }
- mutex_unlock(&dev->ctxlist_mutex);
-
- return 0;
-}
-
-/*@}*/
+++ /dev/null
-/*
- * Copyright (c) 2006-2008 Intel Corporation
- * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
- * Copyright (c) 2008 Red Hat Inc.
- *
- * DRM core CRTC related functions
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- *
- * Authors:
- * Keith Packard
- * Eric Anholt <eric@anholt.net>
- * Dave Airlie <airlied@linux.ie>
- * Jesse Barnes <jesse.barnes@intel.com>
- */
-#include <linux/list.h>
-#include <linux/slab.h>
-#include "drm.h"
-#include "drmP.h"
-#include "drm_crtc.h"
-#include "drm_edid.h"
-
-struct drm_prop_enum_list {
- int type;
- char *name;
-};
-
-/* Avoid boilerplate. I'm tired of typing. */
-#define DRM_ENUM_NAME_FN(fnname, list) \
- char *fnname(int val) \
- { \
- int i; \
- for (i = 0; i < ARRAY_SIZE(list); i++) { \
- if (list[i].type == val) \
- return list[i].name; \
- } \
- return "(unknown)"; \
- }
-
-/*
- * Global properties
- */
-static struct drm_prop_enum_list drm_dpms_enum_list[] =
-{ { DRM_MODE_DPMS_ON, "On" },
- { DRM_MODE_DPMS_STANDBY, "Standby" },
- { DRM_MODE_DPMS_SUSPEND, "Suspend" },
- { DRM_MODE_DPMS_OFF, "Off" }
-};
-
-DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
-
-/*
- * Optional properties
- */
-static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
-{
- { DRM_MODE_SCALE_NONE, "None" },
- { DRM_MODE_SCALE_FULLSCREEN, "Full" },
- { DRM_MODE_SCALE_CENTER, "Center" },
- { DRM_MODE_SCALE_ASPECT, "Full aspect" },
-};
-
-static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
-{
- { DRM_MODE_DITHERING_OFF, "Off" },
- { DRM_MODE_DITHERING_ON, "On" },
- { DRM_MODE_DITHERING_AUTO, "Automatic" },
-};
-
-/*
- * Non-global properties, but "required" for certain connectors.
- */
-static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
-{
- { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
- { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */
- { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */
-};
-
-DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
-
-static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
-{
- { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */
- { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */
- { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */
-};
-
-DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
- drm_dvi_i_subconnector_enum_list)
-
-static struct drm_prop_enum_list drm_tv_select_enum_list[] =
-{
- { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
- { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
- { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */
- { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
- { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */
-};
-
-DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
-
-static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
-{
- { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */
- { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
- { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */
- { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
- { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */
-};
-
-DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
- drm_tv_subconnector_enum_list)
-
-static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
- { DRM_MODE_DIRTY_OFF, "Off" },
- { DRM_MODE_DIRTY_ON, "On" },
- { DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
-};
-
-DRM_ENUM_NAME_FN(drm_get_dirty_info_name,
- drm_dirty_info_enum_list)
-
-struct drm_conn_prop_enum_list {
- int type;
- char *name;
- int count;
-};
-
-/*
- * Connector and encoder types.
- */
-static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
-{ { DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 },
- { DRM_MODE_CONNECTOR_VGA, "VGA", 0 },
- { DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 },
- { DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 },
- { DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 },
- { DRM_MODE_CONNECTOR_Composite, "Composite", 0 },
- { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
- { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
- { DRM_MODE_CONNECTOR_Component, "Component", 0 },
- { DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 },
- { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 },
- { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 },
- { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
- { DRM_MODE_CONNECTOR_TV, "TV", 0 },
- { DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
-};
-
-static struct drm_prop_enum_list drm_encoder_enum_list[] =
-{ { DRM_MODE_ENCODER_NONE, "None" },
- { DRM_MODE_ENCODER_DAC, "DAC" },
- { DRM_MODE_ENCODER_TMDS, "TMDS" },
- { DRM_MODE_ENCODER_LVDS, "LVDS" },
- { DRM_MODE_ENCODER_TVDAC, "TV" },
-};
-
-char *drm_get_encoder_name(struct drm_encoder *encoder)
-{
- static char buf[32];
-
- snprintf(buf, 32, "%s-%d",
- drm_encoder_enum_list[encoder->encoder_type].name,
- encoder->base.id);
- return buf;
-}
-EXPORT_SYMBOL(drm_get_encoder_name);
-
-char *drm_get_connector_name(struct drm_connector *connector)
-{
- static char buf[32];
-
- snprintf(buf, 32, "%s-%d",
- drm_connector_enum_list[connector->connector_type].name,
- connector->connector_type_id);
- return buf;
-}
-EXPORT_SYMBOL(drm_get_connector_name);
-
-char *drm_get_connector_status_name(enum drm_connector_status status)
-{
- if (status == connector_status_connected)
- return "connected";
- else if (status == connector_status_disconnected)
- return "disconnected";
- else
- return "unknown";
-}
-
-/**
- * drm_mode_object_get - allocate a new identifier
- * @dev: DRM device
- * @ptr: object pointer, used to generate unique ID
- * @type: object type
- *
- * LOCKING:
- *
- * Create a unique identifier based on @ptr in @dev's identifier space. Used
- * for tracking modes, CRTCs and connectors.
- *
- * RETURNS:
- * New unique (relative to other objects in @dev) integer identifier for the
- * object.
- */
-static int drm_mode_object_get(struct drm_device *dev,
- struct drm_mode_object *obj, uint32_t obj_type)
-{
- int new_id = 0;
- int ret;
-
-again:
- if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) {
- DRM_ERROR("Ran out memory getting a mode number\n");
- return -EINVAL;
- }
-
- mutex_lock(&dev->mode_config.idr_mutex);
- ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id);
- mutex_unlock(&dev->mode_config.idr_mutex);
- if (ret == -EAGAIN)
- goto again;
-
- obj->id = new_id;
- obj->type = obj_type;
- return 0;
-}
-
-/**
- * drm_mode_object_put - free an identifer
- * @dev: DRM device
- * @id: ID to free
- *
- * LOCKING:
- * Caller must hold DRM mode_config lock.
- *
- * Free @id from @dev's unique identifier pool.
- */
-static void drm_mode_object_put(struct drm_device *dev,
- struct drm_mode_object *object)
-{
- mutex_lock(&dev->mode_config.idr_mutex);
- idr_remove(&dev->mode_config.crtc_idr, object->id);
- mutex_unlock(&dev->mode_config.idr_mutex);
-}
-
-struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
- uint32_t id, uint32_t type)
-{
- struct drm_mode_object *obj = NULL;
-
- mutex_lock(&dev->mode_config.idr_mutex);
- obj = idr_find(&dev->mode_config.crtc_idr, id);
- if (!obj || (obj->type != type) || (obj->id != id))
- obj = NULL;
- mutex_unlock(&dev->mode_config.idr_mutex);
-
- return obj;
-}
-EXPORT_SYMBOL(drm_mode_object_find);
-
-/**
- * drm_framebuffer_init - initialize a framebuffer
- * @dev: DRM device
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Allocates an ID for the framebuffer's parent mode object, sets its mode
- * functions & device file and adds it to the master fd list.
- *
- * RETURNS:
- * Zero on success, error code on failure.
- */
-int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
- const struct drm_framebuffer_funcs *funcs)
-{
- int ret;
-
- ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
- if (ret) {
- return ret;
- }
-
- fb->dev = dev;
- fb->funcs = funcs;
- dev->mode_config.num_fb++;
- list_add(&fb->head, &dev->mode_config.fb_list);
-
- return 0;
-}
-EXPORT_SYMBOL(drm_framebuffer_init);
-
-/**
- * drm_framebuffer_cleanup - remove a framebuffer object
- * @fb: framebuffer to remove
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Scans all the CRTCs in @dev's mode_config. If they're using @fb, removes
- * it, setting it to NULL.
- */
-void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
-{
- struct drm_device *dev = fb->dev;
- struct drm_crtc *crtc;
- struct drm_mode_set set;
- int ret;
-
- /* remove from any CRTC */
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- if (crtc->fb == fb) {
- /* should turn off the crtc */
- memset(&set, 0, sizeof(struct drm_mode_set));
- set.crtc = crtc;
- set.fb = NULL;
- ret = crtc->funcs->set_config(&set);
- if (ret)
- DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
- }
- }
-
- drm_mode_object_put(dev, &fb->base);
- list_del(&fb->head);
- dev->mode_config.num_fb--;
-}
-EXPORT_SYMBOL(drm_framebuffer_cleanup);
-
-/**
- * drm_crtc_init - Initialise a new CRTC object
- * @dev: DRM device
- * @crtc: CRTC object to init
- * @funcs: callbacks for the new CRTC
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Inits a new object created as base part of an driver crtc object.
- */
-void drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
- const struct drm_crtc_funcs *funcs)
-{
- crtc->dev = dev;
- crtc->funcs = funcs;
-
- mutex_lock(&dev->mode_config.mutex);
- drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
-
- list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
- dev->mode_config.num_crtc++;
- mutex_unlock(&dev->mode_config.mutex);
-}
-EXPORT_SYMBOL(drm_crtc_init);
-
-/**
- * drm_crtc_cleanup - Cleans up the core crtc usage.
- * @crtc: CRTC to cleanup
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Cleanup @crtc. Removes from drm modesetting space
- * does NOT free object, caller does that.
- */
-void drm_crtc_cleanup(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
-
- if (crtc->gamma_store) {
- kfree(crtc->gamma_store);
- crtc->gamma_store = NULL;
- }
-
- drm_mode_object_put(dev, &crtc->base);
- list_del(&crtc->head);
- dev->mode_config.num_crtc--;
-}
-EXPORT_SYMBOL(drm_crtc_cleanup);
-
-/**
- * drm_mode_probed_add - add a mode to a connector's probed mode list
- * @connector: connector the new mode
- * @mode: mode data
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Add @mode to @connector's mode list for later use.
- */
-void drm_mode_probed_add(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- list_add(&mode->head, &connector->probed_modes);
-}
-EXPORT_SYMBOL(drm_mode_probed_add);
-
-/**
- * drm_mode_remove - remove and free a mode
- * @connector: connector list to modify
- * @mode: mode to remove
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Remove @mode from @connector's mode list, then free it.
- */
-void drm_mode_remove(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- list_del(&mode->head);
- kfree(mode);
-}
-EXPORT_SYMBOL(drm_mode_remove);
-
-/**
- * drm_connector_init - Init a preallocated connector
- * @dev: DRM device
- * @connector: the connector to init
- * @funcs: callbacks for this connector
- * @name: user visible name of the connector
- *
- * LOCKING:
- * Caller must hold @dev's mode_config lock.
- *
- * Initialises a preallocated connector. Connectors should be
- * subclassed as part of driver connector objects.
- */
-void drm_connector_init(struct drm_device *dev,
- struct drm_connector *connector,
- const struct drm_connector_funcs *funcs,
- int connector_type)
-{
- mutex_lock(&dev->mode_config.mutex);
-
- connector->dev = dev;
- connector->funcs = funcs;
- drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR);
- connector->connector_type = connector_type;
- connector->connector_type_id =
- ++drm_connector_enum_list[connector_type].count; /* TODO */
- INIT_LIST_HEAD(&connector->user_modes);
- INIT_LIST_HEAD(&connector->probed_modes);
- INIT_LIST_HEAD(&connector->modes);
- connector->edid_blob_ptr = NULL;
-
- list_add_tail(&connector->head, &dev->mode_config.connector_list);
- dev->mode_config.num_connector++;
-
- drm_connector_attach_property(connector,
- dev->mode_config.edid_property, 0);
-
- drm_connector_attach_property(connector,
- dev->mode_config.dpms_property, 0);
-
- mutex_unlock(&dev->mode_config.mutex);
-}
-EXPORT_SYMBOL(drm_connector_init);
-
-/**
- * drm_connector_cleanup - cleans up an initialised connector
- * @connector: connector to cleanup
- *
- * LOCKING:
- * Caller must hold @dev's mode_config lock.
- *
- * Cleans up the connector but doesn't free the object.
- */
-void drm_connector_cleanup(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *mode, *t;
-
- list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
- drm_mode_remove(connector, mode);
-
- list_for_each_entry_safe(mode, t, &connector->modes, head)
- drm_mode_remove(connector, mode);
-
- list_for_each_entry_safe(mode, t, &connector->user_modes, head)
- drm_mode_remove(connector, mode);
-
- mutex_lock(&dev->mode_config.mutex);
- drm_mode_object_put(dev, &connector->base);
- list_del(&connector->head);
- mutex_unlock(&dev->mode_config.mutex);
-}
-EXPORT_SYMBOL(drm_connector_cleanup);
-
-void drm_encoder_init(struct drm_device *dev,
- struct drm_encoder *encoder,
- const struct drm_encoder_funcs *funcs,
- int encoder_type)
-{
- mutex_lock(&dev->mode_config.mutex);
-
- encoder->dev = dev;
-
- drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
- encoder->encoder_type = encoder_type;
- encoder->funcs = funcs;
-
- list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
- dev->mode_config.num_encoder++;
-
- mutex_unlock(&dev->mode_config.mutex);
-}
-EXPORT_SYMBOL(drm_encoder_init);
-
-void drm_encoder_cleanup(struct drm_encoder *encoder)
-{
- struct drm_device *dev = encoder->dev;
- mutex_lock(&dev->mode_config.mutex);
- drm_mode_object_put(dev, &encoder->base);
- list_del(&encoder->head);
- mutex_unlock(&dev->mode_config.mutex);
-}
-EXPORT_SYMBOL(drm_encoder_cleanup);
-
-/**
- * drm_mode_create - create a new display mode
- * @dev: DRM device
- *
- * LOCKING:
- * Caller must hold DRM mode_config lock.
- *
- * Create a new drm_display_mode, give it an ID, and return it.
- *
- * RETURNS:
- * Pointer to new mode on success, NULL on error.
- */
-struct drm_display_mode *drm_mode_create(struct drm_device *dev)
-{
- struct drm_display_mode *nmode;
-
- nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
- if (!nmode)
- return NULL;
-
- drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE);
- return nmode;
-}
-EXPORT_SYMBOL(drm_mode_create);
-
-/**
- * drm_mode_destroy - remove a mode
- * @dev: DRM device
- * @mode: mode to remove
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Free @mode's unique identifier, then free it.
- */
-void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
-{
- drm_mode_object_put(dev, &mode->base);
-
- kfree(mode);
-}
-EXPORT_SYMBOL(drm_mode_destroy);
-
-static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
-{
- struct drm_property *edid;
- struct drm_property *dpms;
- int i;
-
- /*
- * Standard properties (apply to all connectors)
- */
- edid = drm_property_create(dev, DRM_MODE_PROP_BLOB |
- DRM_MODE_PROP_IMMUTABLE,
- "EDID", 0);
- dev->mode_config.edid_property = edid;
-
- dpms = drm_property_create(dev, DRM_MODE_PROP_ENUM,
- "DPMS", ARRAY_SIZE(drm_dpms_enum_list));
- for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++)
- drm_property_add_enum(dpms, i, drm_dpms_enum_list[i].type,
- drm_dpms_enum_list[i].name);
- dev->mode_config.dpms_property = dpms;
-
- return 0;
-}
-
-/**
- * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
- * @dev: DRM device
- *
- * Called by a driver the first time a DVI-I connector is made.
- */
-int drm_mode_create_dvi_i_properties(struct drm_device *dev)
-{
- struct drm_property *dvi_i_selector;
- struct drm_property *dvi_i_subconnector;
- int i;
-
- if (dev->mode_config.dvi_i_select_subconnector_property)
- return 0;
-
- dvi_i_selector =
- drm_property_create(dev, DRM_MODE_PROP_ENUM,
- "select subconnector",
- ARRAY_SIZE(drm_dvi_i_select_enum_list));
- for (i = 0; i < ARRAY_SIZE(drm_dvi_i_select_enum_list); i++)
- drm_property_add_enum(dvi_i_selector, i,
- drm_dvi_i_select_enum_list[i].type,
- drm_dvi_i_select_enum_list[i].name);
- dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
-
- dvi_i_subconnector =
- drm_property_create(dev, DRM_MODE_PROP_ENUM |
- DRM_MODE_PROP_IMMUTABLE,
- "subconnector",
- ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
- for (i = 0; i < ARRAY_SIZE(drm_dvi_i_subconnector_enum_list); i++)
- drm_property_add_enum(dvi_i_subconnector, i,
- drm_dvi_i_subconnector_enum_list[i].type,
- drm_dvi_i_subconnector_enum_list[i].name);
- dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
-
- return 0;
-}
-EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
-
-/**
- * drm_create_tv_properties - create TV specific connector properties
- * @dev: DRM device
- * @num_modes: number of different TV formats (modes) supported
- * @modes: array of pointers to strings containing name of each format
- *
- * Called by a driver's TV initialization routine, this function creates
- * the TV specific connector properties for a given device. Caller is
- * responsible for allocating a list of format names and passing them to
- * this routine.
- */
-int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes,
- char *modes[])
-{
- struct drm_property *tv_selector;
- struct drm_property *tv_subconnector;
- int i;
-
- if (dev->mode_config.tv_select_subconnector_property)
- return 0;
-
- /*
- * Basic connector properties
- */
- tv_selector = drm_property_create(dev, DRM_MODE_PROP_ENUM,
- "select subconnector",
- ARRAY_SIZE(drm_tv_select_enum_list));
- for (i = 0; i < ARRAY_SIZE(drm_tv_select_enum_list); i++)
- drm_property_add_enum(tv_selector, i,
- drm_tv_select_enum_list[i].type,
- drm_tv_select_enum_list[i].name);
- dev->mode_config.tv_select_subconnector_property = tv_selector;
-
- tv_subconnector =
- drm_property_create(dev, DRM_MODE_PROP_ENUM |
- DRM_MODE_PROP_IMMUTABLE, "subconnector",
- ARRAY_SIZE(drm_tv_subconnector_enum_list));
- for (i = 0; i < ARRAY_SIZE(drm_tv_subconnector_enum_list); i++)
- drm_property_add_enum(tv_subconnector, i,
- drm_tv_subconnector_enum_list[i].type,
- drm_tv_subconnector_enum_list[i].name);
- dev->mode_config.tv_subconnector_property = tv_subconnector;
-
- /*
- * Other, TV specific properties: margins & TV modes.
- */
- dev->mode_config.tv_left_margin_property =
- drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "left margin", 2);
- dev->mode_config.tv_left_margin_property->values[0] = 0;
- dev->mode_config.tv_left_margin_property->values[1] = 100;
-
- dev->mode_config.tv_right_margin_property =
- drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "right margin", 2);
- dev->mode_config.tv_right_margin_property->values[0] = 0;
- dev->mode_config.tv_right_margin_property->values[1] = 100;
-
- dev->mode_config.tv_top_margin_property =
- drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "top margin", 2);
- dev->mode_config.tv_top_margin_property->values[0] = 0;
- dev->mode_config.tv_top_margin_property->values[1] = 100;
-
- dev->mode_config.tv_bottom_margin_property =
- drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "bottom margin", 2);
- dev->mode_config.tv_bottom_margin_property->values[0] = 0;
- dev->mode_config.tv_bottom_margin_property->values[1] = 100;
-
- dev->mode_config.tv_mode_property =
- drm_property_create(dev, DRM_MODE_PROP_ENUM,
- "mode", num_modes);
- for (i = 0; i < num_modes; i++)
- drm_property_add_enum(dev->mode_config.tv_mode_property, i,
- i, modes[i]);
-
- dev->mode_config.tv_brightness_property =
- drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "brightness", 2);
- dev->mode_config.tv_brightness_property->values[0] = 0;
- dev->mode_config.tv_brightness_property->values[1] = 100;
-
- dev->mode_config.tv_contrast_property =
- drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "contrast", 2);
- dev->mode_config.tv_contrast_property->values[0] = 0;
- dev->mode_config.tv_contrast_property->values[1] = 100;
-
- dev->mode_config.tv_flicker_reduction_property =
- drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "flicker reduction", 2);
- dev->mode_config.tv_flicker_reduction_property->values[0] = 0;
- dev->mode_config.tv_flicker_reduction_property->values[1] = 100;
-
- dev->mode_config.tv_overscan_property =
- drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "overscan", 2);
- dev->mode_config.tv_overscan_property->values[0] = 0;
- dev->mode_config.tv_overscan_property->values[1] = 100;
-
- dev->mode_config.tv_saturation_property =
- drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "saturation", 2);
- dev->mode_config.tv_saturation_property->values[0] = 0;
- dev->mode_config.tv_saturation_property->values[1] = 100;
-
- dev->mode_config.tv_hue_property =
- drm_property_create(dev, DRM_MODE_PROP_RANGE,
- "hue", 2);
- dev->mode_config.tv_hue_property->values[0] = 0;
- dev->mode_config.tv_hue_property->values[1] = 100;
-
- return 0;
-}
-EXPORT_SYMBOL(drm_mode_create_tv_properties);
-
-/**
- * drm_mode_create_scaling_mode_property - create scaling mode property
- * @dev: DRM device
- *
- * Called by a driver the first time it's needed, must be attached to desired
- * connectors.
- */
-int drm_mode_create_scaling_mode_property(struct drm_device *dev)
-{
- struct drm_property *scaling_mode;
- int i;
-
- if (dev->mode_config.scaling_mode_property)
- return 0;
-
- scaling_mode =
- drm_property_create(dev, DRM_MODE_PROP_ENUM, "scaling mode",
- ARRAY_SIZE(drm_scaling_mode_enum_list));
- for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++)
- drm_property_add_enum(scaling_mode, i,
- drm_scaling_mode_enum_list[i].type,
- drm_scaling_mode_enum_list[i].name);
-
- dev->mode_config.scaling_mode_property = scaling_mode;
-
- return 0;
-}
-EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
-
-/**
- * drm_mode_create_dithering_property - create dithering property
- * @dev: DRM device
- *
- * Called by a driver the first time it's needed, must be attached to desired
- * connectors.
- */
-int drm_mode_create_dithering_property(struct drm_device *dev)
-{
- struct drm_property *dithering_mode;
- int i;
-
- if (dev->mode_config.dithering_mode_property)
- return 0;
-
- dithering_mode =
- drm_property_create(dev, DRM_MODE_PROP_ENUM, "dithering",
- ARRAY_SIZE(drm_dithering_mode_enum_list));
- for (i = 0; i < ARRAY_SIZE(drm_dithering_mode_enum_list); i++)
- drm_property_add_enum(dithering_mode, i,
- drm_dithering_mode_enum_list[i].type,
- drm_dithering_mode_enum_list[i].name);
- dev->mode_config.dithering_mode_property = dithering_mode;
-
- return 0;
-}
-EXPORT_SYMBOL(drm_mode_create_dithering_property);
-
-/**
- * drm_mode_create_dirty_property - create dirty property
- * @dev: DRM device
- *
- * Called by a driver the first time it's needed, must be attached to desired
- * connectors.
- */
-int drm_mode_create_dirty_info_property(struct drm_device *dev)
-{
- struct drm_property *dirty_info;
- int i;
-
- if (dev->mode_config.dirty_info_property)
- return 0;
-
- dirty_info =
- drm_property_create(dev, DRM_MODE_PROP_ENUM |
- DRM_MODE_PROP_IMMUTABLE,
- "dirty",
- ARRAY_SIZE(drm_dirty_info_enum_list));
- for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++)
- drm_property_add_enum(dirty_info, i,
- drm_dirty_info_enum_list[i].type,
- drm_dirty_info_enum_list[i].name);
- dev->mode_config.dirty_info_property = dirty_info;
-
- return 0;
-}
-EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
-
-/**
- * drm_mode_config_init - initialize DRM mode_configuration structure
- * @dev: DRM device
- *
- * LOCKING:
- * None, should happen single threaded at init time.
- *
- * Initialize @dev's mode_config structure, used for tracking the graphics
- * configuration of @dev.
- */
-void drm_mode_config_init(struct drm_device *dev)
-{
- mutex_init(&dev->mode_config.mutex);
- mutex_init(&dev->mode_config.idr_mutex);
- INIT_LIST_HEAD(&dev->mode_config.fb_list);
- INIT_LIST_HEAD(&dev->mode_config.crtc_list);
- INIT_LIST_HEAD(&dev->mode_config.connector_list);
- INIT_LIST_HEAD(&dev->mode_config.encoder_list);
- INIT_LIST_HEAD(&dev->mode_config.property_list);
- INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
- idr_init(&dev->mode_config.crtc_idr);
-
- mutex_lock(&dev->mode_config.mutex);
- drm_mode_create_standard_connector_properties(dev);
- mutex_unlock(&dev->mode_config.mutex);
-
- /* Just to be sure */
- dev->mode_config.num_fb = 0;
- dev->mode_config.num_connector = 0;
- dev->mode_config.num_crtc = 0;
- dev->mode_config.num_encoder = 0;
-}
-EXPORT_SYMBOL(drm_mode_config_init);
-
-int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
-{
- uint32_t total_objects = 0;
-
- total_objects += dev->mode_config.num_crtc;
- total_objects += dev->mode_config.num_connector;
- total_objects += dev->mode_config.num_encoder;
-
- if (total_objects == 0)
- return -EINVAL;
-
- group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);
- if (!group->id_list)
- return -ENOMEM;
-
- group->num_crtcs = 0;
- group->num_connectors = 0;
- group->num_encoders = 0;
- return 0;
-}
-
-int drm_mode_group_init_legacy_group(struct drm_device *dev,
- struct drm_mode_group *group)
-{
- struct drm_crtc *crtc;
- struct drm_encoder *encoder;
- struct drm_connector *connector;
- int ret;
-
- if ((ret = drm_mode_group_init(dev, group)))
- return ret;
-
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
- group->id_list[group->num_crtcs++] = crtc->base.id;
-
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
- group->id_list[group->num_crtcs + group->num_encoders++] =
- encoder->base.id;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- group->id_list[group->num_crtcs + group->num_encoders +
- group->num_connectors++] = connector->base.id;
-
- return 0;
-}
-
-/**
- * drm_mode_config_cleanup - free up DRM mode_config info
- * @dev: DRM device
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Free up all the connectors and CRTCs associated with this DRM device, then
- * free up the framebuffers and associated buffer objects.
- *
- * FIXME: cleanup any dangling user buffer objects too
- */
-void drm_mode_config_cleanup(struct drm_device *dev)
-{
- struct drm_connector *connector, *ot;
- struct drm_crtc *crtc, *ct;
- struct drm_encoder *encoder, *enct;
- struct drm_framebuffer *fb, *fbt;
- struct drm_property *property, *pt;
-
- list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
- head) {
- encoder->funcs->destroy(encoder);
- }
-
- list_for_each_entry_safe(connector, ot,
- &dev->mode_config.connector_list, head) {
- connector->funcs->destroy(connector);
- }
-
- list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
- head) {
- drm_property_destroy(dev, property);
- }
-
- list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
- fb->funcs->destroy(fb);
- }
-
- list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
- crtc->funcs->destroy(crtc);
- }
-
-}
-EXPORT_SYMBOL(drm_mode_config_cleanup);
-
-/**
- * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
- * @out: drm_mode_modeinfo struct to return to the user
- * @in: drm_display_mode to use
- *
- * LOCKING:
- * None.
- *
- * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
- * the user.
- */
-void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
- struct drm_display_mode *in)
-{
- out->clock = in->clock;
- out->hdisplay = in->hdisplay;
- out->hsync_start = in->hsync_start;
- out->hsync_end = in->hsync_end;
- out->htotal = in->htotal;
- out->hskew = in->hskew;
- out->vdisplay = in->vdisplay;
- out->vsync_start = in->vsync_start;
- out->vsync_end = in->vsync_end;
- out->vtotal = in->vtotal;
- out->vscan = in->vscan;
- out->vrefresh = in->vrefresh;
- out->flags = in->flags;
- out->type = in->type;
- strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
- out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
-}
-
-/**
- * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
- * @out: drm_display_mode to return to the user
- * @in: drm_mode_modeinfo to use
- *
- * LOCKING:
- * None.
- *
- * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
- * the caller.
- */
-void drm_crtc_convert_umode(struct drm_display_mode *out,
- struct drm_mode_modeinfo *in)
-{
- out->clock = in->clock;
- out->hdisplay = in->hdisplay;
- out->hsync_start = in->hsync_start;
- out->hsync_end = in->hsync_end;
- out->htotal = in->htotal;
- out->hskew = in->hskew;
- out->vdisplay = in->vdisplay;
- out->vsync_start = in->vsync_start;
- out->vsync_end = in->vsync_end;
- out->vtotal = in->vtotal;
- out->vscan = in->vscan;
- out->vrefresh = in->vrefresh;
- out->flags = in->flags;
- out->type = in->type;
- strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
- out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
-}
-
-/**
- * drm_mode_getresources - get graphics configuration
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
- *
- * LOCKING:
- * Takes mode config lock.
- *
- * Construct a set of configuration description structures and return
- * them to the user, including CRTC, connector and framebuffer configuration.
- *
- * Called by the user via ioctl.
- *
- * RETURNS:
- * Zero on success, errno on failure.
- */
-int drm_mode_getresources(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_mode_card_res *card_res = data;
- struct list_head *lh;
- struct drm_framebuffer *fb;
- struct drm_connector *connector;
- struct drm_crtc *crtc;
- struct drm_encoder *encoder;
- int ret = 0;
- int connector_count = 0;
- int crtc_count = 0;
- int fb_count = 0;
- int encoder_count = 0;
- int copied = 0, i;
- uint32_t __user *fb_id;
- uint32_t __user *crtc_id;
- uint32_t __user *connector_id;
- uint32_t __user *encoder_id;
- struct drm_mode_group *mode_group;
-
- mutex_lock(&dev->mode_config.mutex);
-
- /*
- * For the non-control nodes we need to limit the list of resources
- * by IDs in the group list for this node
- */
- list_for_each(lh, &file_priv->fbs)
- fb_count++;
-
- mode_group = &file_priv->master->minor->mode_group;
- if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
-
- list_for_each(lh, &dev->mode_config.crtc_list)
- crtc_count++;
-
- list_for_each(lh, &dev->mode_config.connector_list)
- connector_count++;
-
- list_for_each(lh, &dev->mode_config.encoder_list)
- encoder_count++;
- } else {
-
- crtc_count = mode_group->num_crtcs;
- connector_count = mode_group->num_connectors;
- encoder_count = mode_group->num_encoders;
- }
-
- card_res->max_height = dev->mode_config.max_height;
- card_res->min_height = dev->mode_config.min_height;
- card_res->max_width = dev->mode_config.max_width;
- card_res->min_width = dev->mode_config.min_width;
-
- /* handle this in 4 parts */
- /* FBs */
- if (card_res->count_fbs >= fb_count) {
- copied = 0;
- fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
- list_for_each_entry(fb, &file_priv->fbs, head) {
- if (put_user(fb->base.id, fb_id + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- }
- card_res->count_fbs = fb_count;
-
- /* CRTCs */
- if (card_res->count_crtcs >= crtc_count) {
- copied = 0;
- crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
- if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
- list_for_each_entry(crtc, &dev->mode_config.crtc_list,
- head) {
- DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
- if (put_user(crtc->base.id, crtc_id + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- } else {
- for (i = 0; i < mode_group->num_crtcs; i++) {
- if (put_user(mode_group->id_list[i],
- crtc_id + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- }
- }
- card_res->count_crtcs = crtc_count;
-
- /* Encoders */
- if (card_res->count_encoders >= encoder_count) {
- copied = 0;
- encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
- if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
- list_for_each_entry(encoder,
- &dev->mode_config.encoder_list,
- head) {
- DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
- drm_get_encoder_name(encoder));
- if (put_user(encoder->base.id, encoder_id +
- copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- } else {
- for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) {
- if (put_user(mode_group->id_list[i],
- encoder_id + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
-
- }
- }
- card_res->count_encoders = encoder_count;
-
- /* Connectors */
- if (card_res->count_connectors >= connector_count) {
- copied = 0;
- connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
- if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
- list_for_each_entry(connector,
- &dev->mode_config.connector_list,
- head) {
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
- connector->base.id,
- drm_get_connector_name(connector));
- if (put_user(connector->base.id,
- connector_id + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- } else {
- int start = mode_group->num_crtcs +
- mode_group->num_encoders;
- for (i = start; i < start + mode_group->num_connectors; i++) {
- if (put_user(mode_group->id_list[i],
- connector_id + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- }
- }
- card_res->count_connectors = connector_count;
-
- DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs,
- card_res->count_connectors, card_res->count_encoders);
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-/**
- * drm_mode_getcrtc - get CRTC configuration
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
- *
- * LOCKING:
- * Caller? (FIXME)
- *
- * Construct a CRTC configuration structure to return to the user.
- *
- * Called by the user via ioctl.
- *
- * RETURNS:
- * Zero on success, errno on failure.
- */
-int drm_mode_getcrtc(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_crtc *crtc_resp = data;
- struct drm_crtc *crtc;
- struct drm_mode_object *obj;
- int ret = 0;
-
- mutex_lock(&dev->mode_config.mutex);
-
- obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
- DRM_MODE_OBJECT_CRTC);
- if (!obj) {
- ret = -EINVAL;
- goto out;
- }
- crtc = obj_to_crtc(obj);
-
- crtc_resp->x = crtc->x;
- crtc_resp->y = crtc->y;
- crtc_resp->gamma_size = crtc->gamma_size;
- if (crtc->fb)
- crtc_resp->fb_id = crtc->fb->base.id;
- else
- crtc_resp->fb_id = 0;
-
- if (crtc->enabled) {
-
- drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode);
- crtc_resp->mode_valid = 1;
-
- } else {
- crtc_resp->mode_valid = 0;
- }
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-/**
- * drm_mode_getconnector - get connector configuration
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
- *
- * LOCKING:
- * Caller? (FIXME)
- *
- * Construct a connector configuration structure to return to the user.
- *
- * Called by the user via ioctl.
- *
- * RETURNS:
- * Zero on success, errno on failure.
- */
-int drm_mode_getconnector(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_mode_get_connector *out_resp = data;
- struct drm_mode_object *obj;
- struct drm_connector *connector;
- struct drm_display_mode *mode;
- int mode_count = 0;
- int props_count = 0;
- int encoders_count = 0;
- int ret = 0;
- int copied = 0;
- int i;
- struct drm_mode_modeinfo u_mode;
- struct drm_mode_modeinfo __user *mode_ptr;
- uint32_t __user *prop_ptr;
- uint64_t __user *prop_values;
- uint32_t __user *encoder_ptr;
-
- memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
-
- DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
-
- mutex_lock(&dev->mode_config.mutex);
-
- obj = drm_mode_object_find(dev, out_resp->connector_id,
- DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
- ret = -EINVAL;
- goto out;
- }
- connector = obj_to_connector(obj);
-
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] != 0) {
- props_count++;
- }
- }
-
- for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
- if (connector->encoder_ids[i] != 0) {
- encoders_count++;
- }
- }
-
- if (out_resp->count_modes == 0) {
- connector->funcs->fill_modes(connector,
- dev->mode_config.max_width,
- dev->mode_config.max_height);
- }
-
- /* delayed so we get modes regardless of pre-fill_modes state */
- list_for_each_entry(mode, &connector->modes, head)
- mode_count++;
-
- out_resp->connector_id = connector->base.id;
- out_resp->connector_type = connector->connector_type;
- out_resp->connector_type_id = connector->connector_type_id;
- out_resp->mm_width = connector->display_info.width_mm;
- out_resp->mm_height = connector->display_info.height_mm;
- out_resp->subpixel = connector->display_info.subpixel_order;
- out_resp->connection = connector->status;
- if (connector->encoder)
- out_resp->encoder_id = connector->encoder->base.id;
- else
- out_resp->encoder_id = 0;
-
- /*
- * This ioctl is called twice, once to determine how much space is
- * needed, and the 2nd time to fill it.
- */
- if ((out_resp->count_modes >= mode_count) && mode_count) {
- copied = 0;
- mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr;
- list_for_each_entry(mode, &connector->modes, head) {
- drm_crtc_convert_to_umode(&u_mode, mode);
- if (copy_to_user(mode_ptr + copied,
- &u_mode, sizeof(u_mode))) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- }
- out_resp->count_modes = mode_count;
-
- if ((out_resp->count_props >= props_count) && props_count) {
- copied = 0;
- prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr);
- prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr);
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] != 0) {
- if (put_user(connector->property_ids[i],
- prop_ptr + copied)) {
- ret = -EFAULT;
- goto out;
- }
-
- if (put_user(connector->property_values[i],
- prop_values + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- }
- }
- out_resp->count_props = props_count;
-
- if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
- copied = 0;
- encoder_ptr = (uint32_t *)(unsigned long)(out_resp->encoders_ptr);
- for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
- if (connector->encoder_ids[i] != 0) {
- if (put_user(connector->encoder_ids[i],
- encoder_ptr + copied)) {
- ret = -EFAULT;
- goto out;
- }
- copied++;
- }
- }
- }
- out_resp->count_encoders = encoders_count;
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-int drm_mode_getencoder(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_mode_get_encoder *enc_resp = data;
- struct drm_mode_object *obj;
- struct drm_encoder *encoder;
- int ret = 0;
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, enc_resp->encoder_id,
- DRM_MODE_OBJECT_ENCODER);
- if (!obj) {
- ret = -EINVAL;
- goto out;
- }
- encoder = obj_to_encoder(obj);
-
- if (encoder->crtc)
- enc_resp->crtc_id = encoder->crtc->base.id;
- else
- enc_resp->crtc_id = 0;
- enc_resp->encoder_type = encoder->encoder_type;
- enc_resp->encoder_id = encoder->base.id;
- enc_resp->possible_crtcs = encoder->possible_crtcs;
- enc_resp->possible_clones = encoder->possible_clones;
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-/**
- * drm_mode_setcrtc - set CRTC configuration
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
- *
- * LOCKING:
- * Caller? (FIXME)
- *
- * Build a new CRTC configuration based on user request.
- *
- * Called by the user via ioctl.
- *
- * RETURNS:
- * Zero on success, errno on failure.
- */
-int drm_mode_setcrtc(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_mode_config *config = &dev->mode_config;
- struct drm_mode_crtc *crtc_req = data;
- struct drm_mode_object *obj;
- struct drm_crtc *crtc, *crtcfb;
- struct drm_connector **connector_set = NULL, *connector;
- struct drm_framebuffer *fb = NULL;
- struct drm_display_mode *mode = NULL;
- struct drm_mode_set set;
- uint32_t __user *set_connectors_ptr;
- int ret = 0;
- int i;
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, crtc_req->crtc_id,
- DRM_MODE_OBJECT_CRTC);
- if (!obj) {
- DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
- ret = -EINVAL;
- goto out;
- }
- crtc = obj_to_crtc(obj);
- DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
-
- if (crtc_req->mode_valid) {
- /* If we have a mode we need a framebuffer. */
- /* If we pass -1, set the mode with the currently bound fb */
- if (crtc_req->fb_id == -1) {
- list_for_each_entry(crtcfb,
- &dev->mode_config.crtc_list, head) {
- if (crtcfb == crtc) {
- DRM_DEBUG_KMS("Using current fb for "
- "setmode\n");
- fb = crtc->fb;
- }
- }
- } else {
- obj = drm_mode_object_find(dev, crtc_req->fb_id,
- DRM_MODE_OBJECT_FB);
- if (!obj) {
- DRM_DEBUG_KMS("Unknown FB ID%d\n",
- crtc_req->fb_id);
- ret = -EINVAL;
- goto out;
- }
- fb = obj_to_fb(obj);
- }
-
- mode = drm_mode_create(dev);
- drm_crtc_convert_umode(mode, &crtc_req->mode);
- drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
- }
-
- if (crtc_req->count_connectors == 0 && mode) {
- DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
- ret = -EINVAL;
- goto out;
- }
-
- if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
- DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
- crtc_req->count_connectors);
- ret = -EINVAL;
- goto out;
- }
-
- if (crtc_req->count_connectors > 0) {
- u32 out_id;
-
- /* Avoid unbounded kernel memory allocation */
- if (crtc_req->count_connectors > config->num_connector) {
- ret = -EINVAL;
- goto out;
- }
-
- connector_set = kmalloc(crtc_req->count_connectors *
- sizeof(struct drm_connector *),
- GFP_KERNEL);
- if (!connector_set) {
- ret = -ENOMEM;
- goto out;
- }
-
- for (i = 0; i < crtc_req->count_connectors; i++) {
- set_connectors_ptr = (uint32_t *)(unsigned long)crtc_req->set_connectors_ptr;
- if (get_user(out_id, &set_connectors_ptr[i])) {
- ret = -EFAULT;
- goto out;
- }
-
- obj = drm_mode_object_find(dev, out_id,
- DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
- DRM_DEBUG_KMS("Connector id %d unknown\n",
- out_id);
- ret = -EINVAL;
- goto out;
- }
- connector = obj_to_connector(obj);
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
- connector->base.id,
- drm_get_connector_name(connector));
-
- connector_set[i] = connector;
- }
- }
-
- set.crtc = crtc;
- set.x = crtc_req->x;
- set.y = crtc_req->y;
- set.mode = mode;
- set.connectors = connector_set;
- set.num_connectors = crtc_req->count_connectors;
- set.fb = fb;
- ret = crtc->funcs->set_config(&set);
-
-out:
- kfree(connector_set);
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-int drm_mode_cursor_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_cursor *req = data;
- struct drm_mode_object *obj;
- struct drm_crtc *crtc;
- int ret = 0;
-
- if (!req->flags) {
- DRM_ERROR("no operation set\n");
- return -EINVAL;
- }
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj) {
- DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
- ret = -EINVAL;
- goto out;
- }
- crtc = obj_to_crtc(obj);
-
- if (req->flags & DRM_MODE_CURSOR_BO) {
- if (!crtc->funcs->cursor_set) {
- DRM_ERROR("crtc does not support cursor\n");
- ret = -ENXIO;
- goto out;
- }
- /* Turns off the cursor if handle is 0 */
- ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
- req->width, req->height);
- }
-
- if (req->flags & DRM_MODE_CURSOR_MOVE) {
- if (crtc->funcs->cursor_move) {
- ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
- } else {
- DRM_ERROR("crtc does not support cursor\n");
- ret = -EFAULT;
- goto out;
- }
- }
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-/**
- * drm_mode_addfb - add an FB to the graphics configuration
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
- *
- * LOCKING:
- * Takes mode config lock.
- *
- * Add a new FB to the specified CRTC, given a user request.
- *
- * Called by the user via ioctl.
- *
- * RETURNS:
- * Zero on success, errno on failure.
- */
-int drm_mode_addfb(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_fb_cmd *r = data;
- struct drm_mode_config *config = &dev->mode_config;
- struct drm_framebuffer *fb;
- int ret = 0;
-
- if ((config->min_width > r->width) || (r->width > config->max_width)) {
- DRM_ERROR("mode new framebuffer width not within limits\n");
- return -EINVAL;
- }
- if ((config->min_height > r->height) || (r->height > config->max_height)) {
- DRM_ERROR("mode new framebuffer height not within limits\n");
- return -EINVAL;
- }
-
- mutex_lock(&dev->mode_config.mutex);
-
- /* TODO check buffer is sufficently large */
- /* TODO setup destructor callback */
-
- fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
- if (IS_ERR(fb)) {
- DRM_ERROR("could not create framebuffer\n");
- ret = PTR_ERR(fb);
- goto out;
- }
-
- r->fb_id = fb->base.id;
- list_add(&fb->filp_head, &file_priv->fbs);
- DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-/**
- * drm_mode_rmfb - remove an FB from the configuration
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
- *
- * LOCKING:
- * Takes mode config lock.
- *
- * Remove the FB specified by the user.
- *
- * Called by the user via ioctl.
- *
- * RETURNS:
- * Zero on success, errno on failure.
- */
-int drm_mode_rmfb(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_object *obj;
- struct drm_framebuffer *fb = NULL;
- struct drm_framebuffer *fbl = NULL;
- uint32_t *id = data;
- int ret = 0;
- int found = 0;
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
- /* TODO check that we realy get a framebuffer back. */
- if (!obj) {
- DRM_ERROR("mode invalid framebuffer id\n");
- ret = -EINVAL;
- goto out;
- }
- fb = obj_to_fb(obj);
-
- list_for_each_entry(fbl, &file_priv->fbs, filp_head)
- if (fb == fbl)
- found = 1;
-
- if (!found) {
- DRM_ERROR("tried to remove a fb that we didn't own\n");
- ret = -EINVAL;
- goto out;
- }
-
- /* TODO release all crtc connected to the framebuffer */
- /* TODO unhock the destructor from the buffer object */
-
- list_del(&fb->filp_head);
- fb->funcs->destroy(fb);
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-/**
- * drm_mode_getfb - get FB info
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
- *
- * LOCKING:
- * Caller? (FIXME)
- *
- * Lookup the FB given its ID and return info about it.
- *
- * Called by the user via ioctl.
- *
- * RETURNS:
- * Zero on success, errno on failure.
- */
-int drm_mode_getfb(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_fb_cmd *r = data;
- struct drm_mode_object *obj;
- struct drm_framebuffer *fb;
- int ret = 0;
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
- if (!obj) {
- DRM_ERROR("invalid framebuffer id\n");
- ret = -EINVAL;
- goto out;
- }
- fb = obj_to_fb(obj);
-
- r->height = fb->height;
- r->width = fb->width;
- r->depth = fb->depth;
- r->bpp = fb->bits_per_pixel;
- r->pitch = fb->pitch;
- fb->funcs->create_handle(fb, file_priv, &r->handle);
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_clip_rect __user *clips_ptr;
- struct drm_clip_rect *clips = NULL;
- struct drm_mode_fb_dirty_cmd *r = data;
- struct drm_mode_object *obj;
- struct drm_framebuffer *fb;
- unsigned flags;
- int num_clips;
- int ret = 0;
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
- if (!obj) {
- DRM_ERROR("invalid framebuffer id\n");
- ret = -EINVAL;
- goto out_err1;
- }
- fb = obj_to_fb(obj);
-
- num_clips = r->num_clips;
- clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;
-
- if (!num_clips != !clips_ptr) {
- ret = -EINVAL;
- goto out_err1;
- }
-
- flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
-
- /* If userspace annotates copy, clips must come in pairs */
- if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
- ret = -EINVAL;
- goto out_err1;
- }
-
- if (num_clips && clips_ptr) {
- clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
- if (!clips) {
- ret = -ENOMEM;
- goto out_err1;
- }
-
- ret = copy_from_user(clips, clips_ptr,
- num_clips * sizeof(*clips));
- if (ret) {
- ret = -EFAULT;
- goto out_err2;
- }
- }
-
- if (fb->funcs->dirty) {
- ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
- clips, num_clips);
- } else {
- ret = -ENOSYS;
- goto out_err2;
- }
-
-out_err2:
- kfree(clips);
-out_err1:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-
-/**
- * drm_fb_release - remove and free the FBs on this file
- * @filp: file * from the ioctl
- *
- * LOCKING:
- * Takes mode config lock.
- *
- * Destroy all the FBs associated with @filp.
- *
- * Called by the user via ioctl.
- *
- * RETURNS:
- * Zero on success, errno on failure.
- */
-void drm_fb_release(struct drm_file *priv)
-{
- struct drm_device *dev = priv->minor->dev;
- struct drm_framebuffer *fb, *tfb;
-
- mutex_lock(&dev->mode_config.mutex);
- list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
- list_del(&fb->filp_head);
- fb->funcs->destroy(fb);
- }
- mutex_unlock(&dev->mode_config.mutex);
-}
-
-/**
- * drm_mode_attachmode - add a mode to the user mode list
- * @dev: DRM device
- * @connector: connector to add the mode to
- * @mode: mode to add
- *
- * Add @mode to @connector's user mode list.
- */
-static int drm_mode_attachmode(struct drm_device *dev,
- struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- int ret = 0;
-
- list_add_tail(&mode->head, &connector->user_modes);
- return ret;
-}
-
-int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
- struct drm_display_mode *mode)
-{
- struct drm_connector *connector;
- int ret = 0;
- struct drm_display_mode *dup_mode;
- int need_dup = 0;
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (!connector->encoder)
- break;
- if (connector->encoder->crtc == crtc) {
- if (need_dup)
- dup_mode = drm_mode_duplicate(dev, mode);
- else
- dup_mode = mode;
- ret = drm_mode_attachmode(dev, connector, dup_mode);
- if (ret)
- return ret;
- need_dup = 1;
- }
- }
- return 0;
-}
-EXPORT_SYMBOL(drm_mode_attachmode_crtc);
-
-static int drm_mode_detachmode(struct drm_device *dev,
- struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- int found = 0;
- int ret = 0;
- struct drm_display_mode *match_mode, *t;
-
- list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) {
- if (drm_mode_equal(match_mode, mode)) {
- list_del(&match_mode->head);
- drm_mode_destroy(dev, match_mode);
- found = 1;
- break;
- }
- }
-
- if (!found)
- ret = -EINVAL;
-
- return ret;
-}
-
-int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode)
-{
- struct drm_connector *connector;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- drm_mode_detachmode(dev, connector, mode);
- }
- return 0;
-}
-EXPORT_SYMBOL(drm_mode_detachmode_crtc);
-
-/**
- * drm_fb_attachmode - Attach a user mode to an connector
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
- *
- * This attaches a user specified mode to an connector.
- * Called by the user via ioctl.
- *
- * RETURNS:
- * Zero on success, errno on failure.
- */
-int drm_mode_attachmode_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_mode_cmd *mode_cmd = data;
- struct drm_connector *connector;
- struct drm_display_mode *mode;
- struct drm_mode_object *obj;
- struct drm_mode_modeinfo *umode = &mode_cmd->mode;
- int ret = 0;
-
- mutex_lock(&dev->mode_config.mutex);
-
- obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
- ret = -EINVAL;
- goto out;
- }
- connector = obj_to_connector(obj);
-
- mode = drm_mode_create(dev);
- if (!mode) {
- ret = -ENOMEM;
- goto out;
- }
-
- drm_crtc_convert_umode(mode, umode);
-
- ret = drm_mode_attachmode(dev, connector, mode);
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-
-/**
- * drm_fb_detachmode - Detach a user specified mode from an connector
- * @inode: inode from the ioctl
- * @filp: file * from the ioctl
- * @cmd: cmd from ioctl
- * @arg: arg from ioctl
- *
- * Called by the user via ioctl.
- *
- * RETURNS:
- * Zero on success, errno on failure.
- */
-int drm_mode_detachmode_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_object *obj;
- struct drm_mode_mode_cmd *mode_cmd = data;
- struct drm_connector *connector;
- struct drm_display_mode mode;
- struct drm_mode_modeinfo *umode = &mode_cmd->mode;
- int ret = 0;
-
- mutex_lock(&dev->mode_config.mutex);
-
- obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
- ret = -EINVAL;
- goto out;
- }
- connector = obj_to_connector(obj);
-
- drm_crtc_convert_umode(&mode, umode);
- ret = drm_mode_detachmode(dev, connector, &mode);
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-struct drm_property *drm_property_create(struct drm_device *dev, int flags,
- const char *name, int num_values)
-{
- struct drm_property *property = NULL;
-
- property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
- if (!property)
- return NULL;
-
- if (num_values) {
- property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL);
- if (!property->values)
- goto fail;
- }
-
- drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
- property->flags = flags;
- property->num_values = num_values;
- INIT_LIST_HEAD(&property->enum_blob_list);
-
- if (name)
- strncpy(property->name, name, DRM_PROP_NAME_LEN);
-
- list_add_tail(&property->head, &dev->mode_config.property_list);
- return property;
-fail:
- kfree(property);
- return NULL;
-}
-EXPORT_SYMBOL(drm_property_create);
-
-int drm_property_add_enum(struct drm_property *property, int index,
- uint64_t value, const char *name)
-{
- struct drm_property_enum *prop_enum;
-
- if (!(property->flags & DRM_MODE_PROP_ENUM))
- return -EINVAL;
-
- if (!list_empty(&property->enum_blob_list)) {
- list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
- if (prop_enum->value == value) {
- strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
- prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
- return 0;
- }
- }
- }
-
- prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
- if (!prop_enum)
- return -ENOMEM;
-
- strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
- prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
- prop_enum->value = value;
-
- property->values[index] = value;
- list_add_tail(&prop_enum->head, &property->enum_blob_list);
- return 0;
-}
-EXPORT_SYMBOL(drm_property_add_enum);
-
-void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
-{
- struct drm_property_enum *prop_enum, *pt;
-
- list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) {
- list_del(&prop_enum->head);
- kfree(prop_enum);
- }
-
- if (property->num_values)
- kfree(property->values);
- drm_mode_object_put(dev, &property->base);
- list_del(&property->head);
- kfree(property);
-}
-EXPORT_SYMBOL(drm_property_destroy);
-
-int drm_connector_attach_property(struct drm_connector *connector,
- struct drm_property *property, uint64_t init_val)
-{
- int i;
-
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] == 0) {
- connector->property_ids[i] = property->base.id;
- connector->property_values[i] = init_val;
- break;
- }
- }
-
- if (i == DRM_CONNECTOR_MAX_PROPERTY)
- return -EINVAL;
- return 0;
-}
-EXPORT_SYMBOL(drm_connector_attach_property);
-
-int drm_connector_property_set_value(struct drm_connector *connector,
- struct drm_property *property, uint64_t value)
-{
- int i;
-
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] == property->base.id) {
- connector->property_values[i] = value;
- break;
- }
- }
-
- if (i == DRM_CONNECTOR_MAX_PROPERTY)
- return -EINVAL;
- return 0;
-}
-EXPORT_SYMBOL(drm_connector_property_set_value);
-
-int drm_connector_property_get_value(struct drm_connector *connector,
- struct drm_property *property, uint64_t *val)
-{
- int i;
-
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] == property->base.id) {
- *val = connector->property_values[i];
- break;
- }
- }
-
- if (i == DRM_CONNECTOR_MAX_PROPERTY)
- return -EINVAL;
- return 0;
-}
-EXPORT_SYMBOL(drm_connector_property_get_value);
-
-int drm_mode_getproperty_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_object *obj;
- struct drm_mode_get_property *out_resp = data;
- struct drm_property *property;
- int enum_count = 0;
- int blob_count = 0;
- int value_count = 0;
- int ret = 0, i;
- int copied;
- struct drm_property_enum *prop_enum;
- struct drm_mode_property_enum __user *enum_ptr;
- struct drm_property_blob *prop_blob;
- uint32_t *blob_id_ptr;
- uint64_t __user *values_ptr;
- uint32_t __user *blob_length_ptr;
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
- if (!obj) {
- ret = -EINVAL;
- goto done;
- }
- property = obj_to_property(obj);
-
- if (property->flags & DRM_MODE_PROP_ENUM) {
- list_for_each_entry(prop_enum, &property->enum_blob_list, head)
- enum_count++;
- } else if (property->flags & DRM_MODE_PROP_BLOB) {
- list_for_each_entry(prop_blob, &property->enum_blob_list, head)
- blob_count++;
- }
-
- value_count = property->num_values;
-
- strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
- out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
- out_resp->flags = property->flags;
-
- if ((out_resp->count_values >= value_count) && value_count) {
- values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr;
- for (i = 0; i < value_count; i++) {
- if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
- ret = -EFAULT;
- goto done;
- }
- }
- }
- out_resp->count_values = value_count;
-
- if (property->flags & DRM_MODE_PROP_ENUM) {
- if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
- copied = 0;
- enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr;
- list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
-
- if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
- ret = -EFAULT;
- goto done;
- }
-
- if (copy_to_user(&enum_ptr[copied].name,
- &prop_enum->name, DRM_PROP_NAME_LEN)) {
- ret = -EFAULT;
- goto done;
- }
- copied++;
- }
- }
- out_resp->count_enum_blobs = enum_count;
- }
-
- if (property->flags & DRM_MODE_PROP_BLOB) {
- if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
- copied = 0;
- blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr;
- blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr;
-
- list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
- if (put_user(prop_blob->base.id, blob_id_ptr + copied)) {
- ret = -EFAULT;
- goto done;
- }
-
- if (put_user(prop_blob->length, blob_length_ptr + copied)) {
- ret = -EFAULT;
- goto done;
- }
-
- copied++;
- }
- }
- out_resp->count_enum_blobs = blob_count;
- }
-done:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
- void *data)
-{
- struct drm_property_blob *blob;
-
- if (!length || !data)
- return NULL;
-
- blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
- if (!blob)
- return NULL;
-
- blob->data = (void *)((char *)blob + sizeof(struct drm_property_blob));
- blob->length = length;
-
- memcpy(blob->data, data, length);
-
- drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
-
- list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
- return blob;
-}
-
-static void drm_property_destroy_blob(struct drm_device *dev,
- struct drm_property_blob *blob)
-{
- drm_mode_object_put(dev, &blob->base);
- list_del(&blob->head);
- kfree(blob);
-}
-
-int drm_mode_getblob_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_object *obj;
- struct drm_mode_get_blob *out_resp = data;
- struct drm_property_blob *blob;
- int ret = 0;
- void *blob_ptr;
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
- if (!obj) {
- ret = -EINVAL;
- goto done;
- }
- blob = obj_to_blob(obj);
-
- if (out_resp->length == blob->length) {
- blob_ptr = (void *)(unsigned long)out_resp->data;
- if (copy_to_user(blob_ptr, blob->data, blob->length)){
- ret = -EFAULT;
- goto done;
- }
- }
- out_resp->length = blob->length;
-
-done:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-int drm_mode_connector_update_edid_property(struct drm_connector *connector,
- struct edid *edid)
-{
- struct drm_device *dev = connector->dev;
- int ret = 0, size;
-
- if (connector->edid_blob_ptr)
- drm_property_destroy_blob(dev, connector->edid_blob_ptr);
-
- /* Delete edid, when there is none. */
- if (!edid) {
- connector->edid_blob_ptr = NULL;
- ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0);
- return ret;
- }
-
- size = EDID_LENGTH * (1 + edid->extensions);
- connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
- size, edid);
-
- ret = drm_connector_property_set_value(connector,
- dev->mode_config.edid_property,
- connector->edid_blob_ptr->base.id);
-
- return ret;
-}
-EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
-
-int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_connector_set_property *out_resp = data;
- struct drm_mode_object *obj;
- struct drm_property *property;
- struct drm_connector *connector;
- int ret = -EINVAL;
- int i;
-
- mutex_lock(&dev->mode_config.mutex);
-
- obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
- goto out;
- }
- connector = obj_to_connector(obj);
-
- for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
- if (connector->property_ids[i] == out_resp->prop_id)
- break;
- }
-
- if (i == DRM_CONNECTOR_MAX_PROPERTY) {
- goto out;
- }
-
- obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
- if (!obj) {
- goto out;
- }
- property = obj_to_property(obj);
-
- if (property->flags & DRM_MODE_PROP_IMMUTABLE)
- goto out;
-
- if (property->flags & DRM_MODE_PROP_RANGE) {
- if (out_resp->value < property->values[0])
- goto out;
-
- if (out_resp->value > property->values[1])
- goto out;
- } else {
- int found = 0;
- for (i = 0; i < property->num_values; i++) {
- if (property->values[i] == out_resp->value) {
- found = 1;
- break;
- }
- }
- if (!found) {
- goto out;
- }
- }
-
- /* Do DPMS ourselves */
- if (property == connector->dev->mode_config.dpms_property) {
- if (connector->funcs->dpms)
- (*connector->funcs->dpms)(connector, (int) out_resp->value);
- ret = 0;
- } else if (connector->funcs->set_property)
- ret = connector->funcs->set_property(connector, property, out_resp->value);
-
- /* store the property value if successful */
- if (!ret)
- drm_connector_property_set_value(connector, property, out_resp->value);
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-int drm_mode_connector_attach_encoder(struct drm_connector *connector,
- struct drm_encoder *encoder)
-{
- int i;
-
- for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
- if (connector->encoder_ids[i] == 0) {
- connector->encoder_ids[i] = encoder->base.id;
- return 0;
- }
- }
- return -ENOMEM;
-}
-EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
-
-void drm_mode_connector_detach_encoder(struct drm_connector *connector,
- struct drm_encoder *encoder)
-{
- int i;
- for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
- if (connector->encoder_ids[i] == encoder->base.id) {
- connector->encoder_ids[i] = 0;
- if (connector->encoder == encoder)
- connector->encoder = NULL;
- break;
- }
- }
-}
-EXPORT_SYMBOL(drm_mode_connector_detach_encoder);
-
-bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
- int gamma_size)
-{
- crtc->gamma_size = gamma_size;
-
- crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL);
- if (!crtc->gamma_store) {
- crtc->gamma_size = 0;
- return false;
- }
-
- return true;
-}
-EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
-
-int drm_mode_gamma_set_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_crtc_lut *crtc_lut = data;
- struct drm_mode_object *obj;
- struct drm_crtc *crtc;
- void *r_base, *g_base, *b_base;
- int size;
- int ret = 0;
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj) {
- ret = -EINVAL;
- goto out;
- }
- crtc = obj_to_crtc(obj);
-
- /* memcpy into gamma store */
- if (crtc_lut->gamma_size != crtc->gamma_size) {
- ret = -EINVAL;
- goto out;
- }
-
- size = crtc_lut->gamma_size * (sizeof(uint16_t));
- r_base = crtc->gamma_store;
- if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) {
- ret = -EFAULT;
- goto out;
- }
-
- g_base = r_base + size;
- if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) {
- ret = -EFAULT;
- goto out;
- }
-
- b_base = g_base + size;
- if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) {
- ret = -EFAULT;
- goto out;
- }
-
- crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-
-}
-
-int drm_mode_gamma_get_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_crtc_lut *crtc_lut = data;
- struct drm_mode_object *obj;
- struct drm_crtc *crtc;
- void *r_base, *g_base, *b_base;
- int size;
- int ret = 0;
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj) {
- ret = -EINVAL;
- goto out;
- }
- crtc = obj_to_crtc(obj);
-
- /* memcpy into gamma store */
- if (crtc_lut->gamma_size != crtc->gamma_size) {
- ret = -EINVAL;
- goto out;
- }
-
- size = crtc_lut->gamma_size * (sizeof(uint16_t));
- r_base = crtc->gamma_store;
- if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
- ret = -EFAULT;
- goto out;
- }
-
- g_base = r_base + size;
- if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) {
- ret = -EFAULT;
- goto out;
- }
-
- b_base = g_base + size;
- if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) {
- ret = -EFAULT;
- goto out;
- }
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-
-int drm_mode_page_flip_ioctl(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
-{
- struct drm_mode_crtc_page_flip *page_flip = data;
- struct drm_mode_object *obj;
- struct drm_crtc *crtc;
- struct drm_framebuffer *fb;
- struct drm_pending_vblank_event *e = NULL;
- unsigned long flags;
- int ret = -EINVAL;
-
- if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
- page_flip->reserved != 0)
- return -EINVAL;
-
- mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj)
- goto out;
- crtc = obj_to_crtc(obj);
-
- if (crtc->fb == NULL) {
- /* The framebuffer is currently unbound, presumably
- * due to a hotplug event, that userspace has not
- * yet discovered.
- */
- ret = -EBUSY;
- goto out;
- }
-
- if (crtc->funcs->page_flip == NULL)
- goto out;
-
- obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB);
- if (!obj)
- goto out;
- fb = obj_to_fb(obj);
-
- if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
- ret = -ENOMEM;
- spin_lock_irqsave(&dev->event_lock, flags);
- if (file_priv->event_space < sizeof e->event) {
- spin_unlock_irqrestore(&dev->event_lock, flags);
- goto out;
- }
- file_priv->event_space -= sizeof e->event;
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
- e = kzalloc(sizeof *e, GFP_KERNEL);
- if (e == NULL) {
- spin_lock_irqsave(&dev->event_lock, flags);
- file_priv->event_space += sizeof e->event;
- spin_unlock_irqrestore(&dev->event_lock, flags);
- goto out;
- }
-
- e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
- e->event.base.length = sizeof e->event;
- e->event.user_data = page_flip->user_data;
- e->base.event = &e->event.base;
- e->base.file_priv = file_priv;
- e->base.destroy =
- (void (*) (struct drm_pending_event *)) kfree;
- }
-
- ret = crtc->funcs->page_flip(crtc, fb, e);
- if (ret) {
- spin_lock_irqsave(&dev->event_lock, flags);
- file_priv->event_space += sizeof e->event;
- spin_unlock_irqrestore(&dev->event_lock, flags);
- kfree(e);
- }
-
-out:
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2006-2008 Intel Corporation
- * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
- *
- * DRM core CRTC related functions
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- *
- * Authors:
- * Keith Packard
- * Eric Anholt <eric@anholt.net>
- * Dave Airlie <airlied@linux.ie>
- * Jesse Barnes <jesse.barnes@intel.com>
- */
-
-#include "drmP.h"
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-#include "drm_fb_helper.h"
-
-static bool drm_kms_helper_poll = true;
-module_param_named(poll, drm_kms_helper_poll, bool, 0600);
-
-static void drm_mode_validate_flag(struct drm_connector *connector,
- int flags)
-{
- struct drm_display_mode *mode, *t;
-
- if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE))
- return;
-
- list_for_each_entry_safe(mode, t, &connector->modes, head) {
- if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
- !(flags & DRM_MODE_FLAG_INTERLACE))
- mode->status = MODE_NO_INTERLACE;
- if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
- !(flags & DRM_MODE_FLAG_DBLSCAN))
- mode->status = MODE_NO_DBLESCAN;
- }
-
- return;
-}
-
-/**
- * drm_helper_probe_single_connector_modes - get complete set of display modes
- * @dev: DRM device
- * @maxX: max width for modes
- * @maxY: max height for modes
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Based on @dev's mode_config layout, scan all the connectors and try to detect
- * modes on them. Modes will first be added to the connector's probed_modes
- * list, then culled (based on validity and the @maxX, @maxY parameters) and
- * put into the normal modes list.
- *
- * Intended to be used either at bootup time or when major configuration
- * changes have occurred.
- *
- * FIXME: take into account monitor limits
- *
- * RETURNS:
- * Number of modes found on @connector.
- */
-int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
- uint32_t maxX, uint32_t maxY)
-{
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *mode, *t;
- struct drm_connector_helper_funcs *connector_funcs =
- connector->helper_private;
- int count = 0;
- int mode_flags = 0;
-
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
- drm_get_connector_name(connector));
- /* set all modes to the unverified state */
- list_for_each_entry_safe(mode, t, &connector->modes, head)
- mode->status = MODE_UNVERIFIED;
-
- if (connector->force) {
- if (connector->force == DRM_FORCE_ON)
- connector->status = connector_status_connected;
- else
- connector->status = connector_status_disconnected;
- if (connector->funcs->force)
- connector->funcs->force(connector);
- } else {
- connector->status = connector->funcs->detect(connector, true);
- drm_kms_helper_poll_enable(dev);
- }
-
- if (connector->status == connector_status_disconnected) {
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
- connector->base.id, drm_get_connector_name(connector));
- drm_mode_connector_update_edid_property(connector, NULL);
- goto prune;
- }
-
- count = (*connector_funcs->get_modes)(connector);
- if (count == 0 && connector->status == connector_status_connected)
- count = drm_add_modes_noedid(connector, 1024, 768);
- if (count == 0)
- goto prune;
-
- drm_mode_connector_list_update(connector);
-
- if (maxX && maxY)
- drm_mode_validate_size(dev, &connector->modes, maxX,
- maxY, 0);
-
- if (connector->interlace_allowed)
- mode_flags |= DRM_MODE_FLAG_INTERLACE;
- if (connector->doublescan_allowed)
- mode_flags |= DRM_MODE_FLAG_DBLSCAN;
- drm_mode_validate_flag(connector, mode_flags);
-
- list_for_each_entry_safe(mode, t, &connector->modes, head) {
- if (mode->status == MODE_OK)
- mode->status = connector_funcs->mode_valid(connector,
- mode);
- }
-
-prune:
- drm_mode_prune_invalid(dev, &connector->modes, true);
-
- if (list_empty(&connector->modes))
- return 0;
-
- drm_mode_sort(&connector->modes);
-
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
- drm_get_connector_name(connector));
- list_for_each_entry_safe(mode, t, &connector->modes, head) {
- mode->vrefresh = drm_mode_vrefresh(mode);
-
- drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
- drm_mode_debug_printmodeline(mode);
- }
-
- return count;
-}
-EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
-
-/**
- * drm_helper_encoder_in_use - check if a given encoder is in use
- * @encoder: encoder to check
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Walk @encoders's DRM device's mode_config and see if it's in use.
- *
- * RETURNS:
- * True if @encoder is part of the mode_config, false otherwise.
- */
-bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
-{
- struct drm_connector *connector;
- struct drm_device *dev = encoder->dev;
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- if (connector->encoder == encoder)
- return true;
- return false;
-}
-EXPORT_SYMBOL(drm_helper_encoder_in_use);
-
-/**
- * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
- * @crtc: CRTC to check
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Walk @crtc's DRM device's mode_config and see if it's in use.
- *
- * RETURNS:
- * True if @crtc is part of the mode_config, false otherwise.
- */
-bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
-{
- struct drm_encoder *encoder;
- struct drm_device *dev = crtc->dev;
- /* FIXME: Locking around list access? */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
- if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
- return true;
- return false;
-}
-EXPORT_SYMBOL(drm_helper_crtc_in_use);
-
-static void
-drm_encoder_disable(struct drm_encoder *encoder)
-{
- struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
-
- if (encoder_funcs->disable)
- (*encoder_funcs->disable)(encoder);
- else
- (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
-}
-
-/**
- * drm_helper_disable_unused_functions - disable unused objects
- * @dev: DRM device
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled
- * by calling its dpms function, which should power it off.
- */
-void drm_helper_disable_unused_functions(struct drm_device *dev)
-{
- struct drm_encoder *encoder;
- struct drm_connector *connector;
- struct drm_crtc *crtc;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (!connector->encoder)
- continue;
- if (connector->status == connector_status_disconnected)
- connector->encoder = NULL;
- }
-
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (!drm_helper_encoder_in_use(encoder)) {
- drm_encoder_disable(encoder);
- /* disconnector encoder from any connector */
- encoder->crtc = NULL;
- }
- }
-
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc->enabled = drm_helper_crtc_in_use(crtc);
- if (!crtc->enabled) {
- if (crtc_funcs->disable)
- (*crtc_funcs->disable)(crtc);
- else
- (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
- crtc->fb = NULL;
- }
- }
-}
-EXPORT_SYMBOL(drm_helper_disable_unused_functions);
-
-/**
- * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
- * @encoder: encoder to test
- * @crtc: crtc to test
- *
- * Return false if @encoder can't be driven by @crtc, true otherwise.
- */
-static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
- struct drm_crtc *crtc)
-{
- struct drm_device *dev;
- struct drm_crtc *tmp;
- int crtc_mask = 1;
-
- WARN(!crtc, "checking null crtc?\n");
-
- dev = crtc->dev;
-
- list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
- if (tmp == crtc)
- break;
- crtc_mask <<= 1;
- }
-
- if (encoder->possible_crtcs & crtc_mask)
- return true;
- return false;
-}
-
-/*
- * Check the CRTC we're going to map each output to vs. its current
- * CRTC. If they don't match, we have to disable the output and the CRTC
- * since the driver will have to re-route things.
- */
-static void
-drm_crtc_prepare_encoders(struct drm_device *dev)
-{
- struct drm_encoder_helper_funcs *encoder_funcs;
- struct drm_encoder *encoder;
-
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- encoder_funcs = encoder->helper_private;
- /* Disable unused encoders */
- if (encoder->crtc == NULL)
- drm_encoder_disable(encoder);
- /* Disable encoders whose CRTC is about to change */
- if (encoder_funcs->get_crtc &&
- encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
- drm_encoder_disable(encoder);
- }
-}
-
-/**
- * drm_crtc_set_mode - set a mode
- * @crtc: CRTC to program
- * @mode: mode to use
- * @x: width of mode
- * @y: height of mode
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance
- * to fixup or reject the mode prior to trying to set it.
- *
- * RETURNS:
- * True if the mode was set successfully, or false otherwise.
- */
-bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_display_mode *adjusted_mode, saved_mode;
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- struct drm_encoder_helper_funcs *encoder_funcs;
- int saved_x, saved_y;
- struct drm_encoder *encoder;
- bool ret = true;
-
- adjusted_mode = drm_mode_duplicate(dev, mode);
-
- crtc->enabled = drm_helper_crtc_in_use(crtc);
-
- if (!crtc->enabled)
- return true;
-
- saved_mode = crtc->mode;
- saved_x = crtc->x;
- saved_y = crtc->y;
-
- /* Update crtc values up front so the driver can rely on them for mode
- * setting.
- */
- crtc->mode = *mode;
- crtc->x = x;
- crtc->y = y;
-
- /* Pass our mode to the connectors and the CRTC to give them a chance to
- * adjust it according to limitations or connector properties, and also
- * a chance to reject the mode entirely.
- */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
- if (encoder->crtc != crtc)
- continue;
- encoder_funcs = encoder->helper_private;
- if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
- adjusted_mode))) {
- goto done;
- }
- }
-
- if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
- goto done;
- }
- DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
-
- /* Prepare the encoders and CRTCs before setting the mode. */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
- if (encoder->crtc != crtc)
- continue;
- encoder_funcs = encoder->helper_private;
- /* Disable the encoders as the first thing we do. */
- encoder_funcs->prepare(encoder);
- }
-
- drm_crtc_prepare_encoders(dev);
-
- crtc_funcs->prepare(crtc);
-
- /* Set up the DPLL and any encoders state that needs to adjust or depend
- * on the DPLL.
- */
- ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
- if (!ret)
- goto done;
-
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
- if (encoder->crtc != crtc)
- continue;
-
- DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
- encoder->base.id, drm_get_encoder_name(encoder),
- mode->base.id, mode->name);
- encoder_funcs = encoder->helper_private;
- encoder_funcs->mode_set(encoder, mode, adjusted_mode);
- }
-
- /* Now enable the clocks, plane, pipe, and connectors that we set up. */
- crtc_funcs->commit(crtc);
-
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
- if (encoder->crtc != crtc)
- continue;
-
- encoder_funcs = encoder->helper_private;
- encoder_funcs->commit(encoder);
-
- }
-
- /* XXX free adjustedmode */
- drm_mode_destroy(dev, adjusted_mode);
- /* FIXME: add subpixel order */
-done:
- if (!ret) {
- crtc->mode = saved_mode;
- crtc->x = saved_x;
- crtc->y = saved_y;
- }
-
- return ret;
-}
-EXPORT_SYMBOL(drm_crtc_helper_set_mode);
-
-
-/**
- * drm_crtc_helper_set_config - set a new config from userspace
- * @crtc: CRTC to setup
- * @crtc_info: user provided configuration
- * @new_mode: new mode to set
- * @connector_set: set of connectors for the new config
- * @fb: new framebuffer
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Setup a new configuration, provided by the user in @crtc_info, and enable
- * it.
- *
- * RETURNS:
- * Zero. (FIXME)
- */
-int drm_crtc_helper_set_config(struct drm_mode_set *set)
-{
- struct drm_device *dev;
- struct drm_crtc *save_crtcs, *new_crtc, *crtc;
- struct drm_encoder *save_encoders, *new_encoder, *encoder;
- struct drm_framebuffer *old_fb = NULL;
- bool mode_changed = false; /* if true do a full mode set */
- bool fb_changed = false; /* if true and !mode_changed just do a flip */
- struct drm_connector *save_connectors, *connector;
- int count = 0, ro, fail = 0;
- struct drm_crtc_helper_funcs *crtc_funcs;
- int ret = 0;
- int i;
-
- DRM_DEBUG_KMS("\n");
-
- if (!set)
- return -EINVAL;
-
- if (!set->crtc)
- return -EINVAL;
-
- if (!set->crtc->helper_private)
- return -EINVAL;
-
- crtc_funcs = set->crtc->helper_private;
-
- if (set->fb) {
- DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
- set->crtc->base.id, set->fb->base.id,
- (int)set->num_connectors, set->x, set->y);
- } else {
- DRM_DEBUG_KMS("[CRTC:%d] [NOFB] #connectors=%d (x y) (%i %i)\n",
- set->crtc->base.id, (int)set->num_connectors,
- set->x, set->y);
- }
-
- dev = set->crtc->dev;
-
- /* Allocate space for the backup of all (non-pointer) crtc, encoder and
- * connector data. */
- save_crtcs = kzalloc(dev->mode_config.num_crtc *
- sizeof(struct drm_crtc), GFP_KERNEL);
- if (!save_crtcs)
- return -ENOMEM;
-
- save_encoders = kzalloc(dev->mode_config.num_encoder *
- sizeof(struct drm_encoder), GFP_KERNEL);
- if (!save_encoders) {
- kfree(save_crtcs);
- return -ENOMEM;
- }
-
- save_connectors = kzalloc(dev->mode_config.num_connector *
- sizeof(struct drm_connector), GFP_KERNEL);
- if (!save_connectors) {
- kfree(save_crtcs);
- kfree(save_encoders);
- return -ENOMEM;
- }
-
- /* Copy data. Note that driver private data is not affected.
- * Should anything bad happen only the expected state is
- * restored, not the drivers personal bookkeeping.
- */
- count = 0;
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- save_crtcs[count++] = *crtc;
- }
-
- count = 0;
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- save_encoders[count++] = *encoder;
- }
-
- count = 0;
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- save_connectors[count++] = *connector;
- }
-
- /* We should be able to check here if the fb has the same properties
- * and then just flip_or_move it */
- if (set->crtc->fb != set->fb) {
- /* If we have no fb then treat it as a full mode set */
- if (set->crtc->fb == NULL) {
- DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
- mode_changed = true;
- } else if (set->fb == NULL) {
- mode_changed = true;
- } else
- fb_changed = true;
- }
-
- if (set->x != set->crtc->x || set->y != set->crtc->y)
- fb_changed = true;
-
- if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
- DRM_DEBUG_KMS("modes are different, full mode set\n");
- drm_mode_debug_printmodeline(&set->crtc->mode);
- drm_mode_debug_printmodeline(set->mode);
- mode_changed = true;
- }
-
- /* a) traverse passed in connector list and get encoders for them */
- count = 0;
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- struct drm_connector_helper_funcs *connector_funcs =
- connector->helper_private;
- new_encoder = connector->encoder;
- for (ro = 0; ro < set->num_connectors; ro++) {
- if (set->connectors[ro] == connector) {
- new_encoder = connector_funcs->best_encoder(connector);
- /* if we can't get an encoder for a connector
- we are setting now - then fail */
- if (new_encoder == NULL)
- /* don't break so fail path works correct */
- fail = 1;
- break;
- }
- }
-
- if (new_encoder != connector->encoder) {
- DRM_DEBUG_KMS("encoder changed, full mode switch\n");
- mode_changed = true;
- /* If the encoder is reused for another connector, then
- * the appropriate crtc will be set later.
- */
- if (connector->encoder)
- connector->encoder->crtc = NULL;
- connector->encoder = new_encoder;
- }
- }
-
- if (fail) {
- ret = -EINVAL;
- goto fail;
- }
-
- count = 0;
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (!connector->encoder)
- continue;
-
- if (connector->encoder->crtc == set->crtc)
- new_crtc = NULL;
- else
- new_crtc = connector->encoder->crtc;
-
- for (ro = 0; ro < set->num_connectors; ro++) {
- if (set->connectors[ro] == connector)
- new_crtc = set->crtc;
- }
-
- /* Make sure the new CRTC will work with the encoder */
- if (new_crtc &&
- !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
- ret = -EINVAL;
- goto fail;
- }
- if (new_crtc != connector->encoder->crtc) {
- DRM_DEBUG_KMS("crtc changed, full mode switch\n");
- mode_changed = true;
- connector->encoder->crtc = new_crtc;
- }
- if (new_crtc) {
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
- connector->base.id, drm_get_connector_name(connector),
- new_crtc->base.id);
- } else {
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
- connector->base.id, drm_get_connector_name(connector));
- }
- }
-
- /* mode_set_base is not a required function */
- if (fb_changed && !crtc_funcs->mode_set_base)
- mode_changed = true;
-
- if (mode_changed) {
- set->crtc->enabled = (set->mode != NULL);
- if (set->mode != NULL) {
- DRM_DEBUG_KMS("attempting to set mode from"
- " userspace\n");
- drm_mode_debug_printmodeline(set->mode);
- old_fb = set->crtc->fb;
- set->crtc->fb = set->fb;
- if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
- set->x, set->y,
- old_fb)) {
- DRM_ERROR("failed to set mode on [CRTC:%d]\n",
- set->crtc->base.id);
- ret = -EINVAL;
- goto fail;
- }
- }
- drm_helper_disable_unused_functions(dev);
- } else if (fb_changed) {
- set->crtc->x = set->x;
- set->crtc->y = set->y;
-
- old_fb = set->crtc->fb;
- if (set->crtc->fb != set->fb)
- set->crtc->fb = set->fb;
- ret = crtc_funcs->mode_set_base(set->crtc,
- set->x, set->y, old_fb);
- if (ret != 0)
- goto fail;
- }
- DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
- for (i = 0; i < set->num_connectors; i++) {
- DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
- drm_get_connector_name(set->connectors[i]));
- set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
- }
-
- kfree(save_connectors);
- kfree(save_encoders);
- kfree(save_crtcs);
- return 0;
-
-fail:
- /* Restore all previous data. */
- count = 0;
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- *crtc = save_crtcs[count++];
- }
-
- count = 0;
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- *encoder = save_encoders[count++];
- }
-
- count = 0;
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- *connector = save_connectors[count++];
- }
-
- kfree(save_connectors);
- kfree(save_encoders);
- kfree(save_crtcs);
- return ret;
-}
-EXPORT_SYMBOL(drm_crtc_helper_set_config);
-
-static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
-{
- int dpms = DRM_MODE_DPMS_OFF;
- struct drm_connector *connector;
- struct drm_device *dev = encoder->dev;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- if (connector->encoder == encoder)
- if (connector->dpms < dpms)
- dpms = connector->dpms;
- return dpms;
-}
-
-static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
-{
- int dpms = DRM_MODE_DPMS_OFF;
- struct drm_connector *connector;
- struct drm_device *dev = crtc->dev;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- if (connector->encoder && connector->encoder->crtc == crtc)
- if (connector->dpms < dpms)
- dpms = connector->dpms;
- return dpms;
-}
-
-/**
- * drm_helper_connector_dpms
- * @connector affected connector
- * @mode DPMS mode
- *
- * Calls the low-level connector DPMS function, then
- * calls appropriate encoder and crtc DPMS functions as well
- */
-void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
-{
- struct drm_encoder *encoder = connector->encoder;
- struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
- int old_dpms;
-
- if (mode == connector->dpms)
- return;
-
- old_dpms = connector->dpms;
- connector->dpms = mode;
-
- /* from off to on, do crtc then encoder */
- if (mode < old_dpms) {
- if (crtc) {
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- if (crtc_funcs->dpms)
- (*crtc_funcs->dpms) (crtc,
- drm_helper_choose_crtc_dpms(crtc));
- }
- if (encoder) {
- struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
- if (encoder_funcs->dpms)
- (*encoder_funcs->dpms) (encoder,
- drm_helper_choose_encoder_dpms(encoder));
- }
- }
-
- /* from on to off, do encoder then crtc */
- if (mode > old_dpms) {
- if (encoder) {
- struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
- if (encoder_funcs->dpms)
- (*encoder_funcs->dpms) (encoder,
- drm_helper_choose_encoder_dpms(encoder));
- }
- if (crtc) {
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- if (crtc_funcs->dpms)
- (*crtc_funcs->dpms) (crtc,
- drm_helper_choose_crtc_dpms(crtc));
- }
- }
-
- return;
-}
-EXPORT_SYMBOL(drm_helper_connector_dpms);
-
-int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
- struct drm_mode_fb_cmd *mode_cmd)
-{
- fb->width = mode_cmd->width;
- fb->height = mode_cmd->height;
- fb->pitch = mode_cmd->pitch;
- fb->bits_per_pixel = mode_cmd->bpp;
- fb->depth = mode_cmd->depth;
-
- return 0;
-}
-EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
-
-int drm_helper_resume_force_mode(struct drm_device *dev)
-{
- struct drm_crtc *crtc;
- struct drm_encoder *encoder;
- struct drm_encoder_helper_funcs *encoder_funcs;
- struct drm_crtc_helper_funcs *crtc_funcs;
- int ret;
-
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-
- if (!crtc->enabled)
- continue;
-
- ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
- crtc->x, crtc->y, crtc->fb);
-
- if (ret == false)
- DRM_ERROR("failed to set mode on crtc %p\n", crtc);
-
- /* Turn off outputs that were already powered off */
- if (drm_helper_choose_crtc_dpms(crtc)) {
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
- if(encoder->crtc != crtc)
- continue;
-
- encoder_funcs = encoder->helper_private;
- if (encoder_funcs->dpms)
- (*encoder_funcs->dpms) (encoder,
- drm_helper_choose_encoder_dpms(encoder));
- }
-
- crtc_funcs = crtc->helper_private;
- if (crtc_funcs->dpms)
- (*crtc_funcs->dpms) (crtc,
- drm_helper_choose_crtc_dpms(crtc));
- }
- }
- /* disable the unused connectors while restoring the modesetting */
- drm_helper_disable_unused_functions(dev);
- return 0;
-}
-EXPORT_SYMBOL(drm_helper_resume_force_mode);
-
-#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
-static void output_poll_execute(struct work_struct *work)
-{
- struct delayed_work *delayed_work = to_delayed_work(work);
- struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
- struct drm_connector *connector;
- enum drm_connector_status old_status;
- bool repoll = false, changed = false;
-
- if (!drm_kms_helper_poll)
- return;
-
- mutex_lock(&dev->mode_config.mutex);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-
- /* if this is HPD or polled don't check it -
- TV out for instance */
- if (!connector->polled)
- continue;
-
- else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT))
- repoll = true;
-
- old_status = connector->status;
- /* if we are connected and don't want to poll for disconnect
- skip it */
- if (old_status == connector_status_connected &&
- !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) &&
- !(connector->polled & DRM_CONNECTOR_POLL_HPD))
- continue;
-
- connector->status = connector->funcs->detect(connector, false);
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
- connector->base.id,
- drm_get_connector_name(connector),
- old_status, connector->status);
- if (old_status != connector->status)
- changed = true;
- }
-
- mutex_unlock(&dev->mode_config.mutex);
-
- if (changed) {
- /* send a uevent + call fbdev */
- drm_sysfs_hotplug_event(dev);
- if (dev->mode_config.funcs->output_poll_changed)
- dev->mode_config.funcs->output_poll_changed(dev);
- }
-
- if (repoll)
- queue_delayed_work(system_nrt_wq, delayed_work, DRM_OUTPUT_POLL_PERIOD);
-}
-
-void drm_kms_helper_poll_disable(struct drm_device *dev)
-{
- if (!dev->mode_config.poll_enabled)
- return;
- cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
-}
-EXPORT_SYMBOL(drm_kms_helper_poll_disable);
-
-void drm_kms_helper_poll_enable(struct drm_device *dev)
-{
- bool poll = false;
- struct drm_connector *connector;
-
- if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
- return;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->polled)
- poll = true;
- }
-
- if (poll)
- queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
-}
-EXPORT_SYMBOL(drm_kms_helper_poll_enable);
-
-void drm_kms_helper_poll_init(struct drm_device *dev)
-{
- INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute);
- dev->mode_config.poll_enabled = true;
-
- drm_kms_helper_poll_enable(dev);
-}
-EXPORT_SYMBOL(drm_kms_helper_poll_init);
-
-void drm_kms_helper_poll_fini(struct drm_device *dev)
-{
- drm_kms_helper_poll_disable(dev);
-}
-EXPORT_SYMBOL(drm_kms_helper_poll_fini);
-
-void drm_helper_hpd_irq_event(struct drm_device *dev)
-{
- if (!dev->mode_config.poll_enabled)
- return;
-
- /* kill timer and schedule immediate execution, this doesn't block */
- cancel_delayed_work(&dev->mode_config.output_poll_work);
- if (drm_kms_helper_poll)
- queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0);
-}
-EXPORT_SYMBOL(drm_helper_hpd_irq_event);
+++ /dev/null
-/**
- * \file drm_debugfs.c
- * debugfs support for DRM
- *
- * \author Ben Gamari <bgamari@gmail.com>
- */
-
-/*
- * Created: Sun Dec 21 13:08:50 2008 by bgamari@gmail.com
- *
- * Copyright 2008 Ben Gamari <bgamari@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include "drmP.h"
-
-#if defined(CONFIG_DEBUG_FS)
-
-/***************************************************
- * Initialization, etc.
- **************************************************/
-
-static struct drm_info_list drm_debugfs_list[] = {
- {"name", drm_name_info, 0},
- {"vm", drm_vm_info, 0},
- {"clients", drm_clients_info, 0},
- {"queues", drm_queues_info, 0},
- {"bufs", drm_bufs_info, 0},
- {"gem_names", drm_gem_name_info, DRIVER_GEM},
-#if DRM_DEBUG_CODE
- {"vma", drm_vma_info, 0},
-#endif
-};
-#define DRM_DEBUGFS_ENTRIES ARRAY_SIZE(drm_debugfs_list)
-
-
-static int drm_debugfs_open(struct inode *inode, struct file *file)
-{
- struct drm_info_node *node = inode->i_private;
-
- return single_open(file, node->info_ent->show, node);
-}
-
-
-static const struct file_operations drm_debugfs_fops = {
- .owner = THIS_MODULE,
- .open = drm_debugfs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-
-/**
- * Initialize a given set of debugfs files for a device
- *
- * \param files The array of files to create
- * \param count The number of files given
- * \param root DRI debugfs dir entry.
- * \param minor device minor number
- * \return Zero on success, non-zero on failure
- *
- * Create a given set of debugfs files represented by an array of
- * gdm_debugfs_lists in the given root directory.
- */
-int drm_debugfs_create_files(struct drm_info_list *files, int count,
- struct dentry *root, struct drm_minor *minor)
-{
- struct drm_device *dev = minor->dev;
- struct dentry *ent;
- struct drm_info_node *tmp;
- char name[64];
- int i, ret;
-
- for (i = 0; i < count; i++) {
- u32 features = files[i].driver_features;
-
- if (features != 0 &&
- (dev->driver->driver_features & features) != features)
- continue;
-
- tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
- if (tmp == NULL) {
- ret = -1;
- goto fail;
- }
- ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
- root, tmp, &drm_debugfs_fops);
- if (!ent) {
- DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/%s\n",
- name, files[i].name);
- kfree(tmp);
- ret = -1;
- goto fail;
- }
-
- tmp->minor = minor;
- tmp->dent = ent;
- tmp->info_ent = &files[i];
- list_add(&(tmp->list), &(minor->debugfs_nodes.list));
- }
- return 0;
-
-fail:
- drm_debugfs_remove_files(files, count, minor);
- return ret;
-}
-EXPORT_SYMBOL(drm_debugfs_create_files);
-
-/**
- * Initialize the DRI debugfs filesystem for a device
- *
- * \param dev DRM device
- * \param minor device minor number
- * \param root DRI debugfs dir entry.
- *
- * Create the DRI debugfs root entry "/sys/kernel/debug/dri", the device debugfs root entry
- * "/sys/kernel/debug/dri/%minor%/", and each entry in debugfs_list as
- * "/sys/kernel/debug/dri/%minor%/%name%".
- */
-int drm_debugfs_init(struct drm_minor *minor, int minor_id,
- struct dentry *root)
-{
- struct drm_device *dev = minor->dev;
- char name[64];
- int ret;
-
- INIT_LIST_HEAD(&minor->debugfs_nodes.list);
- sprintf(name, "%d", minor_id);
- minor->debugfs_root = debugfs_create_dir(name, root);
- if (!minor->debugfs_root) {
- DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s\n", name);
- return -1;
- }
-
- ret = drm_debugfs_create_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES,
- minor->debugfs_root, minor);
- if (ret) {
- debugfs_remove(minor->debugfs_root);
- minor->debugfs_root = NULL;
- DRM_ERROR("Failed to create core drm debugfs files\n");
- return ret;
- }
-
- if (dev->driver->debugfs_init) {
- ret = dev->driver->debugfs_init(minor);
- if (ret) {
- DRM_ERROR("DRM: Driver failed to initialize "
- "/sys/kernel/debug/dri.\n");
- return ret;
- }
- }
- return 0;
-}
-
-
-/**
- * Remove a list of debugfs files
- *
- * \param files The list of files
- * \param count The number of files
- * \param minor The minor of which we should remove the files
- * \return always zero.
- *
- * Remove all debugfs entries created by debugfs_init().
- */
-int drm_debugfs_remove_files(struct drm_info_list *files, int count,
- struct drm_minor *minor)
-{
- struct list_head *pos, *q;
- struct drm_info_node *tmp;
- int i;
-
- for (i = 0; i < count; i++) {
- list_for_each_safe(pos, q, &minor->debugfs_nodes.list) {
- tmp = list_entry(pos, struct drm_info_node, list);
- if (tmp->info_ent == &files[i]) {
- debugfs_remove(tmp->dent);
- list_del(pos);
- kfree(tmp);
- }
- }
- }
- return 0;
-}
-EXPORT_SYMBOL(drm_debugfs_remove_files);
-
-/**
- * Cleanup the debugfs filesystem resources.
- *
- * \param minor device minor number.
- * \return always zero.
- *
- * Remove all debugfs entries created by debugfs_init().
- */
-int drm_debugfs_cleanup(struct drm_minor *minor)
-{
- struct drm_device *dev = minor->dev;
-
- if (!minor->debugfs_root)
- return 0;
-
- if (dev->driver->debugfs_cleanup)
- dev->driver->debugfs_cleanup(minor);
-
- drm_debugfs_remove_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES, minor);
-
- debugfs_remove(minor->debugfs_root);
- minor->debugfs_root = NULL;
-
- return 0;
-}
-
-#endif /* CONFIG_DEBUG_FS */
-
+++ /dev/null
-/**
- * \file drm_dma.c
- * DMA IOCTL and function support
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-/**
- * Initialize the DMA data.
- *
- * \param dev DRM device.
- * \return zero on success or a negative value on failure.
- *
- * Allocate and initialize a drm_device_dma structure.
- */
-int drm_dma_setup(struct drm_device *dev)
-{
- int i;
-
- dev->dma = kzalloc(sizeof(*dev->dma), GFP_KERNEL);
- if (!dev->dma)
- return -ENOMEM;
-
- for (i = 0; i <= DRM_MAX_ORDER; i++)
- memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
-
- return 0;
-}
-
-/**
- * Cleanup the DMA resources.
- *
- * \param dev DRM device.
- *
- * Free all pages associated with DMA buffers, the buffers and pages lists, and
- * finally the drm_device::dma structure itself.
- */
-void drm_dma_takedown(struct drm_device *dev)
-{
- struct drm_device_dma *dma = dev->dma;
- int i, j;
-
- if (!dma)
- return;
-
- /* Clear dma buffers */
- for (i = 0; i <= DRM_MAX_ORDER; i++) {
- if (dma->bufs[i].seg_count) {
- DRM_DEBUG("order %d: buf_count = %d,"
- " seg_count = %d\n",
- i,
- dma->bufs[i].buf_count,
- dma->bufs[i].seg_count);
- for (j = 0; j < dma->bufs[i].seg_count; j++) {
- if (dma->bufs[i].seglist[j]) {
- drm_pci_free(dev, dma->bufs[i].seglist[j]);
- }
- }
- kfree(dma->bufs[i].seglist);
- }
- if (dma->bufs[i].buf_count) {
- for (j = 0; j < dma->bufs[i].buf_count; j++) {
- kfree(dma->bufs[i].buflist[j].dev_private);
- }
- kfree(dma->bufs[i].buflist);
- }
- }
-
- kfree(dma->buflist);
- kfree(dma->pagelist);
- kfree(dev->dma);
- dev->dma = NULL;
-}
-
-/**
- * Free a buffer.
- *
- * \param dev DRM device.
- * \param buf buffer to free.
- *
- * Resets the fields of \p buf.
- */
-void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf)
-{
- if (!buf)
- return;
-
- buf->waiting = 0;
- buf->pending = 0;
- buf->file_priv = NULL;
- buf->used = 0;
-
- if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)
- && waitqueue_active(&buf->dma_wait)) {
- wake_up_interruptible(&buf->dma_wait);
- }
-}
-
-/**
- * Reclaim the buffers.
- *
- * \param file_priv DRM file private.
- *
- * Frees each buffer associated with \p file_priv not already on the hardware.
- */
-void drm_core_reclaim_buffers(struct drm_device *dev,
- struct drm_file *file_priv)
-{
- struct drm_device_dma *dma = dev->dma;
- int i;
-
- if (!dma)
- return;
- for (i = 0; i < dma->buf_count; i++) {
- if (dma->buflist[i]->file_priv == file_priv) {
- switch (dma->buflist[i]->list) {
- case DRM_LIST_NONE:
- drm_free_buffer(dev, dma->buflist[i]);
- break;
- case DRM_LIST_WAIT:
- dma->buflist[i]->list = DRM_LIST_RECLAIM;
- break;
- default:
- /* Buffer already on hardware. */
- break;
- }
- }
- }
-}
-
-EXPORT_SYMBOL(drm_core_reclaim_buffers);
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/i2c.h>
-#include "drm_dp_helper.h"
-#include "drmP.h"
-
-/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
-static int
-i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
- uint8_t write_byte, uint8_t *read_byte)
-{
- struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
- int ret;
-
- ret = (*algo_data->aux_ch)(adapter, mode,
- write_byte, read_byte);
- return ret;
-}
-
-/*
- * I2C over AUX CH
- */
-
-/*
- * Send the address. If the I2C link is running, this 'restarts'
- * the connection with the new address, this is used for doing
- * a write followed by a read (as needed for DDC)
- */
-static int
-i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
-{
- struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
- int mode = MODE_I2C_START;
- int ret;
-
- if (reading)
- mode |= MODE_I2C_READ;
- else
- mode |= MODE_I2C_WRITE;
- algo_data->address = address;
- algo_data->running = true;
- ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
- return ret;
-}
-
-/*
- * Stop the I2C transaction. This closes out the link, sending
- * a bare address packet with the MOT bit turned off
- */
-static void
-i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
-{
- struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
- int mode = MODE_I2C_STOP;
-
- if (reading)
- mode |= MODE_I2C_READ;
- else
- mode |= MODE_I2C_WRITE;
- if (algo_data->running) {
- (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
- algo_data->running = false;
- }
-}
-
-/*
- * Write a single byte to the current I2C address, the
- * the I2C link must be running or this returns -EIO
- */
-static int
-i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
-{
- struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
- int ret;
-
- if (!algo_data->running)
- return -EIO;
-
- ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
- return ret;
-}
-
-/*
- * Read a single byte from the current I2C address, the
- * I2C link must be running or this returns -EIO
- */
-static int
-i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
-{
- struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
- int ret;
-
- if (!algo_data->running)
- return -EIO;
-
- ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
- return ret;
-}
-
-static int
-i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
- struct i2c_msg *msgs,
- int num)
-{
- int ret = 0;
- bool reading = false;
- int m;
- int b;
-
- for (m = 0; m < num; m++) {
- u16 len = msgs[m].len;
- u8 *buf = msgs[m].buf;
- reading = (msgs[m].flags & I2C_M_RD) != 0;
- ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
- if (ret < 0)
- break;
- if (reading) {
- for (b = 0; b < len; b++) {
- ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
- if (ret < 0)
- break;
- }
- } else {
- for (b = 0; b < len; b++) {
- ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
- if (ret < 0)
- break;
- }
- }
- if (ret < 0)
- break;
- }
- if (ret >= 0)
- ret = num;
- i2c_algo_dp_aux_stop(adapter, reading);
- DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
- return ret;
-}
-
-static u32
-i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
- I2C_FUNC_SMBUS_READ_BLOCK_DATA |
- I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
- I2C_FUNC_10BIT_ADDR;
-}
-
-static const struct i2c_algorithm i2c_dp_aux_algo = {
- .master_xfer = i2c_algo_dp_aux_xfer,
- .functionality = i2c_algo_dp_aux_functionality,
-};
-
-static void
-i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
-{
- (void) i2c_algo_dp_aux_address(adapter, 0, false);
- (void) i2c_algo_dp_aux_stop(adapter, false);
-
-}
-
-static int
-i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
-{
- adapter->algo = &i2c_dp_aux_algo;
- adapter->retries = 3;
- i2c_dp_aux_reset_bus(adapter);
- return 0;
-}
-
-int
-i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
-{
- int error;
-
- error = i2c_dp_aux_prepare_bus(adapter);
- if (error)
- return error;
- error = i2c_add_adapter(adapter);
- return error;
-}
-EXPORT_SYMBOL(i2c_dp_aux_add_bus);
+++ /dev/null
-/**
- * \file drm_drv.c
- * Generic driver template
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- *
- * To use this template, you must at least define the following (samples
- * given for the MGA driver):
- *
- * \code
- * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
- *
- * #define DRIVER_NAME "mga"
- * #define DRIVER_DESC "Matrox G200/G400"
- * #define DRIVER_DATE "20001127"
- *
- * #define drm_x mga_##x
- * \endcode
- */
-
-/*
- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-#include "drmP.h"
-#include "drm_core.h"
-
-
-static int drm_version(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
- [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0}
-
-/** Ioctl table */
-static struct drm_ioctl_desc drm_ioctls[] = {
- DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
-
- DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
-
- DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
-
- DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
- DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
- /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
- DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
-#if __OS_HAS_AGP
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-#endif
-
- DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
- DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
-
- DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
-
- DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
- DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
-
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
-};
-
-#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
-
-/**
- * Take down the DRM device.
- *
- * \param dev DRM device structure.
- *
- * Frees every resource in \p dev.
- *
- * \sa drm_device
- */
-int drm_lastclose(struct drm_device * dev)
-{
- struct drm_vma_entry *vma, *vma_temp;
- int i;
-
- DRM_DEBUG("\n");
-
- if (dev->driver->lastclose)
- dev->driver->lastclose(dev);
- DRM_DEBUG("driver lastclose completed\n");
-
- if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
- drm_irq_uninstall(dev);
-
- mutex_lock(&dev->struct_mutex);
-
- /* Clear AGP information */
- if (drm_core_has_AGP(dev) && dev->agp &&
- !drm_core_check_feature(dev, DRIVER_MODESET)) {
- struct drm_agp_mem *entry, *tempe;
-
- /* Remove AGP resources, but leave dev->agp
- intact until drv_cleanup is called. */
- list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
- if (entry->bound)
- drm_unbind_agp(entry->memory);
- drm_free_agp(entry->memory, entry->pages);
- kfree(entry);
- }
- INIT_LIST_HEAD(&dev->agp->memory);
-
- if (dev->agp->acquired)
- drm_agp_release(dev);
-
- dev->agp->acquired = 0;
- dev->agp->enabled = 0;
- }
- if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg &&
- !drm_core_check_feature(dev, DRIVER_MODESET)) {
- drm_sg_cleanup(dev->sg);
- dev->sg = NULL;
- }
-
- /* Clear vma list (only built for debugging) */
- list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
- list_del(&vma->head);
- kfree(vma);
- }
-
- if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
- for (i = 0; i < dev->queue_count; i++) {
- kfree(dev->queuelist[i]);
- dev->queuelist[i] = NULL;
- }
- kfree(dev->queuelist);
- dev->queuelist = NULL;
- }
- dev->queue_count = 0;
-
- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
- !drm_core_check_feature(dev, DRIVER_MODESET))
- drm_dma_takedown(dev);
-
- dev->dev_mapping = NULL;
- mutex_unlock(&dev->struct_mutex);
-
- DRM_DEBUG("lastclose completed\n");
- return 0;
-}
-
-/**
- * Module initialization. Called via init_module at module load time, or via
- * linux/init/main.c (this is not currently supported).
- *
- * \return zero on success or a negative number on failure.
- *
- * Initializes an array of drm_device structures, and attempts to
- * initialize all available devices, using consecutive minors, registering the
- * stubs and initializing the device.
- *
- * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
- * after the initialization for driver customization.
- */
-int drm_init(struct drm_driver *driver)
-{
- DRM_DEBUG("\n");
- INIT_LIST_HEAD(&driver->device_list);
-
- if (driver->driver_features & DRIVER_USE_PLATFORM_DEVICE)
- return drm_platform_init(driver);
- else
- return drm_pci_init(driver);
-}
-
-EXPORT_SYMBOL(drm_init);
-
-void drm_exit(struct drm_driver *driver)
-{
- struct drm_device *dev, *tmp;
- DRM_DEBUG("\n");
-
- if (driver->driver_features & DRIVER_MODESET) {
- pci_unregister_driver(&driver->pci_driver);
- } else {
- list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
- drm_put_dev(dev);
- }
-
- DRM_INFO("Module unloaded\n");
-}
-
-EXPORT_SYMBOL(drm_exit);
-
-/** File operations structure */
-static const struct file_operations drm_stub_fops = {
- .owner = THIS_MODULE,
- .open = drm_stub_open,
- .llseek = noop_llseek,
-};
-
-static int __init drm_core_init(void)
-{
- int ret = -ENOMEM;
-
- drm_global_init();
- idr_init(&drm_minors_idr);
-
- if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
- goto err_p1;
-
- drm_class = drm_sysfs_create(THIS_MODULE, "drm");
- if (IS_ERR(drm_class)) {
- printk(KERN_ERR "DRM: Error creating drm class.\n");
- ret = PTR_ERR(drm_class);
- goto err_p2;
- }
-
- drm_proc_root = proc_mkdir("dri", NULL);
- if (!drm_proc_root) {
- DRM_ERROR("Cannot create /proc/dri\n");
- ret = -1;
- goto err_p3;
- }
-
- drm_debugfs_root = debugfs_create_dir("dri", NULL);
- if (!drm_debugfs_root) {
- DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
- ret = -1;
- goto err_p3;
- }
-
- DRM_INFO("Initialized %s %d.%d.%d %s\n",
- CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
- return 0;
-err_p3:
- drm_sysfs_destroy();
-err_p2:
- unregister_chrdev(DRM_MAJOR, "drm");
-
- idr_destroy(&drm_minors_idr);
-err_p1:
- return ret;
-}
-
-static void __exit drm_core_exit(void)
-{
- remove_proc_entry("dri", NULL);
- debugfs_remove(drm_debugfs_root);
- drm_sysfs_destroy();
-
- unregister_chrdev(DRM_MAJOR, "drm");
-
- idr_remove_all(&drm_minors_idr);
- idr_destroy(&drm_minors_idr);
-}
-
-module_init(drm_core_init);
-module_exit(drm_core_exit);
-
-/**
- * Copy and IOCTL return string to user space
- */
-static int drm_copy_field(char *buf, size_t *buf_len, const char *value)
-{
- int len;
-
- /* don't overflow userbuf */
- len = strlen(value);
- if (len > *buf_len)
- len = *buf_len;
-
- /* let userspace know exact length of driver value (which could be
- * larger than the userspace-supplied buffer) */
- *buf_len = strlen(value);
-
- /* finally, try filling in the userbuf */
- if (len && buf)
- if (copy_to_user(buf, value, len))
- return -EFAULT;
- return 0;
-}
-
-/**
- * Get version information
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_version structure.
- * \return zero on success or negative number on failure.
- *
- * Fills in the version information in \p arg.
- */
-static int drm_version(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_version *version = data;
- int err;
-
- version->version_major = dev->driver->major;
- version->version_minor = dev->driver->minor;
- version->version_patchlevel = dev->driver->patchlevel;
- err = drm_copy_field(version->name, &version->name_len,
- dev->driver->name);
- if (!err)
- err = drm_copy_field(version->date, &version->date_len,
- dev->driver->date);
- if (!err)
- err = drm_copy_field(version->desc, &version->desc_len,
- dev->driver->desc);
-
- return err;
-}
-
-/**
- * Called whenever a process performs an ioctl on /dev/drm.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
- *
- * Looks up the ioctl function in the ::ioctls table, checking for root
- * previleges if so required, and dispatches to the respective function.
- */
-long drm_ioctl(struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- struct drm_file *file_priv = filp->private_data;
- struct drm_device *dev;
- struct drm_ioctl_desc *ioctl;
- drm_ioctl_t *func;
- unsigned int nr = DRM_IOCTL_NR(cmd);
- int retcode = -EINVAL;
- char stack_kdata[128];
- char *kdata = NULL;
- unsigned int usize, asize;
-
- dev = file_priv->minor->dev;
- atomic_inc(&dev->ioctl_count);
- atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
- ++file_priv->ioctl_count;
-
- DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
- task_pid_nr(current), cmd, nr,
- (long)old_encode_dev(file_priv->minor->device),
- file_priv->authenticated);
-
- if ((nr >= DRM_CORE_IOCTL_COUNT) &&
- ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
- goto err_i1;
- if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
- (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
- u32 drv_size;
- ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
- drv_size = _IOC_SIZE(ioctl->cmd_drv);
- usize = asize = _IOC_SIZE(cmd);
- if (drv_size > asize)
- asize = drv_size;
- }
- else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
- ioctl = &drm_ioctls[nr];
- cmd = ioctl->cmd;
- usize = asize = _IOC_SIZE(cmd);
- } else
- goto err_i1;
-
- /* Do not trust userspace, use our own definition */
- func = ioctl->func;
- /* is there a local override? */
- if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
- func = dev->driver->dma_ioctl;
-
- if (!func) {
- DRM_DEBUG("no function\n");
- retcode = -EINVAL;
- } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
- ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
- ((ioctl->flags & DRM_MASTER) && !file_priv->is_master) ||
- (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL))) {
- retcode = -EACCES;
- } else {
- if (cmd & (IOC_IN | IOC_OUT)) {
- if (asize <= sizeof(stack_kdata)) {
- kdata = stack_kdata;
- } else {
- kdata = kmalloc(asize, GFP_KERNEL);
- if (!kdata) {
- retcode = -ENOMEM;
- goto err_i1;
- }
- }
- }
-
- if (cmd & IOC_IN) {
- if (copy_from_user(kdata, (void __user *)arg,
- usize) != 0) {
- retcode = -EFAULT;
- goto err_i1;
- }
- } else
- memset(kdata, 0, usize);
-
- if (ioctl->flags & DRM_UNLOCKED)
- retcode = func(dev, kdata, file_priv);
- else {
- mutex_lock(&drm_global_mutex);
- retcode = func(dev, kdata, file_priv);
- mutex_unlock(&drm_global_mutex);
- }
-
- if (cmd & IOC_OUT) {
- if (copy_to_user((void __user *)arg, kdata,
- usize) != 0)
- retcode = -EFAULT;
- }
- }
-
- err_i1:
- if (kdata != stack_kdata)
- kfree(kdata);
- atomic_dec(&dev->ioctl_count);
- if (retcode)
- DRM_DEBUG("ret = %x\n", retcode);
- return retcode;
-}
-
-EXPORT_SYMBOL(drm_ioctl);
-
-struct drm_local_map *drm_getsarea(struct drm_device *dev)
-{
- struct drm_map_list *entry;
-
- list_for_each_entry(entry, &dev->maplist, head) {
- if (entry->map && entry->map->type == _DRM_SHM &&
- (entry->map->flags & _DRM_CONTAINS_LOCK)) {
- return entry->map;
- }
- }
- return NULL;
-}
-EXPORT_SYMBOL(drm_getsarea);
+++ /dev/null
-/*
- * Copyright (c) 2006 Luc Verhaegen (quirks list)
- * Copyright (c) 2007-2008 Intel Corporation
- * Jesse Barnes <jesse.barnes@intel.com>
- * Copyright 2010 Red Hat, Inc.
- *
- * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from
- * FB layer.
- * Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include "drmP.h"
-#include "drm_edid.h"
-#include "drm_edid_modes.h"
-
-#define version_greater(edid, maj, min) \
- (((edid)->version > (maj)) || \
- ((edid)->version == (maj) && (edid)->revision > (min)))
-
-#define EDID_EST_TIMINGS 16
-#define EDID_STD_TIMINGS 8
-#define EDID_DETAILED_TIMINGS 4
-
-/*
- * EDID blocks out in the wild have a variety of bugs, try to collect
- * them here (note that userspace may work around broken monitors first,
- * but fixes should make their way here so that the kernel "just works"
- * on as many displays as possible).
- */
-
-/* First detailed mode wrong, use largest 60Hz mode */
-#define EDID_QUIRK_PREFER_LARGE_60 (1 << 0)
-/* Reported 135MHz pixel clock is too high, needs adjustment */
-#define EDID_QUIRK_135_CLOCK_TOO_HIGH (1 << 1)
-/* Prefer the largest mode at 75 Hz */
-#define EDID_QUIRK_PREFER_LARGE_75 (1 << 2)
-/* Detail timing is in cm not mm */
-#define EDID_QUIRK_DETAILED_IN_CM (1 << 3)
-/* Detailed timing descriptors have bogus size values, so just take the
- * maximum size and use that.
- */
-#define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4)
-/* Monitor forgot to set the first detailed is preferred bit. */
-#define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5)
-/* use +hsync +vsync for detailed mode */
-#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
-
-struct detailed_mode_closure {
- struct drm_connector *connector;
- struct edid *edid;
- bool preferred;
- u32 quirks;
- int modes;
-};
-
-#define LEVEL_DMT 0
-#define LEVEL_GTF 1
-#define LEVEL_GTF2 2
-#define LEVEL_CVT 3
-
-static struct edid_quirk {
- char *vendor;
- int product_id;
- u32 quirks;
-} edid_quirk_list[] = {
- /* Acer AL1706 */
- { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 },
- /* Acer F51 */
- { "API", 0x7602, EDID_QUIRK_PREFER_LARGE_60 },
- /* Unknown Acer */
- { "ACR", 2423, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
-
- /* Belinea 10 15 55 */
- { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 },
- { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
-
- /* Envision Peripherals, Inc. EN-7100e */
- { "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH },
- /* Envision EN2028 */
- { "EPI", 8232, EDID_QUIRK_PREFER_LARGE_60 },
-
- /* Funai Electronics PM36B */
- { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 |
- EDID_QUIRK_DETAILED_IN_CM },
-
- /* LG Philips LCD LP154W01-A5 */
- { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
- { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
-
- /* Philips 107p5 CRT */
- { "PHL", 57364, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
-
- /* Proview AY765C */
- { "PTS", 765, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
-
- /* Samsung SyncMaster 205BW. Note: irony */
- { "SAM", 541, EDID_QUIRK_DETAILED_SYNC_PP },
- /* Samsung SyncMaster 22[5-6]BW */
- { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 },
- { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 },
-};
-
-/*** DDC fetch and block validation ***/
-
-static const u8 edid_header[] = {
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
-};
-
-/*
- * Sanity check the EDID block (base or extension). Return 0 if the block
- * doesn't check out, or 1 if it's valid.
- */
-static bool
-drm_edid_block_valid(u8 *raw_edid)
-{
- int i;
- u8 csum = 0;
- struct edid *edid = (struct edid *)raw_edid;
-
- if (raw_edid[0] == 0x00) {
- int score = 0;
-
- for (i = 0; i < sizeof(edid_header); i++)
- if (raw_edid[i] == edid_header[i])
- score++;
-
- if (score == 8) ;
- else if (score >= 6) {
- DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
- memcpy(raw_edid, edid_header, sizeof(edid_header));
- } else {
- goto bad;
- }
- }
-
- for (i = 0; i < EDID_LENGTH; i++)
- csum += raw_edid[i];
- if (csum) {
- DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum);
-
- /* allow CEA to slide through, switches mangle this */
- if (raw_edid[0] != 0x02)
- goto bad;
- }
-
- /* per-block-type checks */
- switch (raw_edid[0]) {
- case 0: /* base */
- if (edid->version != 1) {
- DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
- goto bad;
- }
-
- if (edid->revision > 4)
- DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
- break;
-
- default:
- break;
- }
-
- return 1;
-
-bad:
- if (raw_edid) {
- DRM_ERROR("Raw EDID:\n");
- print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH);
- printk("\n");
- }
- return 0;
-}
-
-/**
- * drm_edid_is_valid - sanity check EDID data
- * @edid: EDID data
- *
- * Sanity-check an entire EDID record (including extensions)
- */
-bool drm_edid_is_valid(struct edid *edid)
-{
- int i;
- u8 *raw = (u8 *)edid;
-
- if (!edid)
- return false;
-
- for (i = 0; i <= edid->extensions; i++)
- if (!drm_edid_block_valid(raw + i * EDID_LENGTH))
- return false;
-
- return true;
-}
-EXPORT_SYMBOL(drm_edid_is_valid);
-
-#define DDC_ADDR 0x50
-#define DDC_SEGMENT_ADDR 0x30
-/**
- * Get EDID information via I2C.
- *
- * \param adapter : i2c device adaptor
- * \param buf : EDID data buffer to be filled
- * \param len : EDID data buffer length
- * \return 0 on success or -1 on failure.
- *
- * Try to fetch EDID information by calling i2c driver function.
- */
-static int
-drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
- int block, int len)
-{
- unsigned char start = block * EDID_LENGTH;
- struct i2c_msg msgs[] = {
- {
- .addr = DDC_ADDR,
- .flags = 0,
- .len = 1,
- .buf = &start,
- }, {
- .addr = DDC_ADDR,
- .flags = I2C_M_RD,
- .len = len,
- .buf = buf,
- }
- };
-
- if (i2c_transfer(adapter, msgs, 2) == 2)
- return 0;
-
- return -1;
-}
-
-static u8 *
-drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
-{
- int i, j = 0, valid_extensions = 0;
- u8 *block, *new;
-
- if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
- return NULL;
-
- /* base block fetch */
- for (i = 0; i < 4; i++) {
- if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH))
- goto out;
- if (drm_edid_block_valid(block))
- break;
- }
- if (i == 4)
- goto carp;
-
- /* if there's no extensions, we're done */
- if (block[0x7e] == 0)
- return block;
-
- new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
- if (!new)
- goto out;
- block = new;
-
- for (j = 1; j <= block[0x7e]; j++) {
- for (i = 0; i < 4; i++) {
- if (drm_do_probe_ddc_edid(adapter,
- block + (valid_extensions + 1) * EDID_LENGTH,
- j, EDID_LENGTH))
- goto out;
- if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH)) {
- valid_extensions++;
- break;
- }
- }
- if (i == 4)
- dev_warn(connector->dev->dev,
- "%s: Ignoring invalid EDID block %d.\n",
- drm_get_connector_name(connector), j);
- }
-
- if (valid_extensions != block[0x7e]) {
- block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
- block[0x7e] = valid_extensions;
- new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
- if (!new)
- goto out;
- block = new;
- }
-
- return block;
-
-carp:
- dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
- drm_get_connector_name(connector), j);
-
-out:
- kfree(block);
- return NULL;
-}
-
-/**
- * Probe DDC presence.
- *
- * \param adapter : i2c device adaptor
- * \return 1 on success
- */
-static bool
-drm_probe_ddc(struct i2c_adapter *adapter)
-{
- unsigned char out;
-
- return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0);
-}
-
-/**
- * drm_get_edid - get EDID data, if available
- * @connector: connector we're probing
- * @adapter: i2c adapter to use for DDC
- *
- * Poke the given i2c channel to grab EDID data if possible. If found,
- * attach it to the connector.
- *
- * Return edid data or NULL if we couldn't find any.
- */
-struct edid *drm_get_edid(struct drm_connector *connector,
- struct i2c_adapter *adapter)
-{
- struct edid *edid = NULL;
-
- if (drm_probe_ddc(adapter))
- edid = (struct edid *)drm_do_get_edid(connector, adapter);
-
- connector->display_info.raw_edid = (char *)edid;
-
- return edid;
-
-}
-EXPORT_SYMBOL(drm_get_edid);
-
-/*** EDID parsing ***/
-
-/**
- * edid_vendor - match a string against EDID's obfuscated vendor field
- * @edid: EDID to match
- * @vendor: vendor string
- *
- * Returns true if @vendor is in @edid, false otherwise
- */
-static bool edid_vendor(struct edid *edid, char *vendor)
-{
- char edid_vendor[3];
-
- edid_vendor[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@';
- edid_vendor[1] = (((edid->mfg_id[0] & 0x3) << 3) |
- ((edid->mfg_id[1] & 0xe0) >> 5)) + '@';
- edid_vendor[2] = (edid->mfg_id[1] & 0x1f) + '@';
-
- return !strncmp(edid_vendor, vendor, 3);
-}
-
-/**
- * edid_get_quirks - return quirk flags for a given EDID
- * @edid: EDID to process
- *
- * This tells subsequent routines what fixes they need to apply.
- */
-static u32 edid_get_quirks(struct edid *edid)
-{
- struct edid_quirk *quirk;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
- quirk = &edid_quirk_list[i];
-
- if (edid_vendor(edid, quirk->vendor) &&
- (EDID_PRODUCT_ID(edid) == quirk->product_id))
- return quirk->quirks;
- }
-
- return 0;
-}
-
-#define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay)
-#define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh))
-
-/**
- * edid_fixup_preferred - set preferred modes based on quirk list
- * @connector: has mode list to fix up
- * @quirks: quirks list
- *
- * Walk the mode list for @connector, clearing the preferred status
- * on existing modes and setting it anew for the right mode ala @quirks.
- */
-static void edid_fixup_preferred(struct drm_connector *connector,
- u32 quirks)
-{
- struct drm_display_mode *t, *cur_mode, *preferred_mode;
- int target_refresh = 0;
-
- if (list_empty(&connector->probed_modes))
- return;
-
- if (quirks & EDID_QUIRK_PREFER_LARGE_60)
- target_refresh = 60;
- if (quirks & EDID_QUIRK_PREFER_LARGE_75)
- target_refresh = 75;
-
- preferred_mode = list_first_entry(&connector->probed_modes,
- struct drm_display_mode, head);
-
- list_for_each_entry_safe(cur_mode, t, &connector->probed_modes, head) {
- cur_mode->type &= ~DRM_MODE_TYPE_PREFERRED;
-
- if (cur_mode == preferred_mode)
- continue;
-
- /* Largest mode is preferred */
- if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode))
- preferred_mode = cur_mode;
-
- /* At a given size, try to get closest to target refresh */
- if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) &&
- MODE_REFRESH_DIFF(cur_mode, target_refresh) <
- MODE_REFRESH_DIFF(preferred_mode, target_refresh)) {
- preferred_mode = cur_mode;
- }
- }
-
- preferred_mode->type |= DRM_MODE_TYPE_PREFERRED;
-}
-
-struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
- int hsize, int vsize, int fresh)
-{
- int i;
- struct drm_display_mode *ptr, *mode;
-
- mode = NULL;
- for (i = 0; i < drm_num_dmt_modes; i++) {
- ptr = &drm_dmt_modes[i];
- if (hsize == ptr->hdisplay &&
- vsize == ptr->vdisplay &&
- fresh == drm_mode_vrefresh(ptr)) {
- /* get the expected default mode */
- mode = drm_mode_duplicate(dev, ptr);
- break;
- }
- }
- return mode;
-}
-EXPORT_SYMBOL(drm_mode_find_dmt);
-
-typedef void detailed_cb(struct detailed_timing *timing, void *closure);
-
-static void
-cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
-{
- int i, n = 0;
- u8 rev = ext[0x01], d = ext[0x02];
- u8 *det_base = ext + d;
-
- switch (rev) {
- case 0:
- /* can't happen */
- return;
- case 1:
- /* have to infer how many blocks we have, check pixel clock */
- for (i = 0; i < 6; i++)
- if (det_base[18*i] || det_base[18*i+1])
- n++;
- break;
- default:
- /* explicit count */
- n = min(ext[0x03] & 0x0f, 6);
- break;
- }
-
- for (i = 0; i < n; i++)
- cb((struct detailed_timing *)(det_base + 18 * i), closure);
-}
-
-static void
-vtb_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
-{
- unsigned int i, n = min((int)ext[0x02], 6);
- u8 *det_base = ext + 5;
-
- if (ext[0x01] != 1)
- return; /* unknown version */
-
- for (i = 0; i < n; i++)
- cb((struct detailed_timing *)(det_base + 18 * i), closure);
-}
-
-static void
-drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure)
-{
- int i;
- struct edid *edid = (struct edid *)raw_edid;
-
- if (edid == NULL)
- return;
-
- for (i = 0; i < EDID_DETAILED_TIMINGS; i++)
- cb(&(edid->detailed_timings[i]), closure);
-
- for (i = 1; i <= raw_edid[0x7e]; i++) {
- u8 *ext = raw_edid + (i * EDID_LENGTH);
- switch (*ext) {
- case CEA_EXT:
- cea_for_each_detailed_block(ext, cb, closure);
- break;
- case VTB_EXT:
- vtb_for_each_detailed_block(ext, cb, closure);
- break;
- default:
- break;
- }
- }
-}
-
-static void
-is_rb(struct detailed_timing *t, void *data)
-{
- u8 *r = (u8 *)t;
- if (r[3] == EDID_DETAIL_MONITOR_RANGE)
- if (r[15] & 0x10)
- *(bool *)data = true;
-}
-
-/* EDID 1.4 defines this explicitly. For EDID 1.3, we guess, badly. */
-static bool
-drm_monitor_supports_rb(struct edid *edid)
-{
- if (edid->revision >= 4) {
- bool ret;
- drm_for_each_detailed_block((u8 *)edid, is_rb, &ret);
- return ret;
- }
-
- return ((edid->input & DRM_EDID_INPUT_DIGITAL) != 0);
-}
-
-static void
-find_gtf2(struct detailed_timing *t, void *data)
-{
- u8 *r = (u8 *)t;
- if (r[3] == EDID_DETAIL_MONITOR_RANGE && r[10] == 0x02)
- *(u8 **)data = r;
-}
-
-/* Secondary GTF curve kicks in above some break frequency */
-static int
-drm_gtf2_hbreak(struct edid *edid)
-{
- u8 *r = NULL;
- drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
- return r ? (r[12] * 2) : 0;
-}
-
-static int
-drm_gtf2_2c(struct edid *edid)
-{
- u8 *r = NULL;
- drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
- return r ? r[13] : 0;
-}
-
-static int
-drm_gtf2_m(struct edid *edid)
-{
- u8 *r = NULL;
- drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
- return r ? (r[15] << 8) + r[14] : 0;
-}
-
-static int
-drm_gtf2_k(struct edid *edid)
-{
- u8 *r = NULL;
- drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
- return r ? r[16] : 0;
-}
-
-static int
-drm_gtf2_2j(struct edid *edid)
-{
- u8 *r = NULL;
- drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
- return r ? r[17] : 0;
-}
-
-/**
- * standard_timing_level - get std. timing level(CVT/GTF/DMT)
- * @edid: EDID block to scan
- */
-static int standard_timing_level(struct edid *edid)
-{
- if (edid->revision >= 2) {
- if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF))
- return LEVEL_CVT;
- if (drm_gtf2_hbreak(edid))
- return LEVEL_GTF2;
- return LEVEL_GTF;
- }
- return LEVEL_DMT;
-}
-
-/*
- * 0 is reserved. The spec says 0x01 fill for unused timings. Some old
- * monitors fill with ascii space (0x20) instead.
- */
-static int
-bad_std_timing(u8 a, u8 b)
-{
- return (a == 0x00 && b == 0x00) ||
- (a == 0x01 && b == 0x01) ||
- (a == 0x20 && b == 0x20);
-}
-
-/**
- * drm_mode_std - convert standard mode info (width, height, refresh) into mode
- * @t: standard timing params
- * @timing_level: standard timing level
- *
- * Take the standard timing params (in this case width, aspect, and refresh)
- * and convert them into a real mode using CVT/GTF/DMT.
- */
-static struct drm_display_mode *
-drm_mode_std(struct drm_connector *connector, struct edid *edid,
- struct std_timing *t, int revision)
-{
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *m, *mode = NULL;
- int hsize, vsize;
- int vrefresh_rate;
- unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK)
- >> EDID_TIMING_ASPECT_SHIFT;
- unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK)
- >> EDID_TIMING_VFREQ_SHIFT;
- int timing_level = standard_timing_level(edid);
-
- if (bad_std_timing(t->hsize, t->vfreq_aspect))
- return NULL;
-
- /* According to the EDID spec, the hdisplay = hsize * 8 + 248 */
- hsize = t->hsize * 8 + 248;
- /* vrefresh_rate = vfreq + 60 */
- vrefresh_rate = vfreq + 60;
- /* the vdisplay is calculated based on the aspect ratio */
- if (aspect_ratio == 0) {
- if (revision < 3)
- vsize = hsize;
- else
- vsize = (hsize * 10) / 16;
- } else if (aspect_ratio == 1)
- vsize = (hsize * 3) / 4;
- else if (aspect_ratio == 2)
- vsize = (hsize * 4) / 5;
- else
- vsize = (hsize * 9) / 16;
-
- /* HDTV hack, part 1 */
- if (vrefresh_rate == 60 &&
- ((hsize == 1360 && vsize == 765) ||
- (hsize == 1368 && vsize == 769))) {
- hsize = 1366;
- vsize = 768;
- }
-
- /*
- * If this connector already has a mode for this size and refresh
- * rate (because it came from detailed or CVT info), use that
- * instead. This way we don't have to guess at interlace or
- * reduced blanking.
- */
- list_for_each_entry(m, &connector->probed_modes, head)
- if (m->hdisplay == hsize && m->vdisplay == vsize &&
- drm_mode_vrefresh(m) == vrefresh_rate)
- return NULL;
-
- /* HDTV hack, part 2 */
- if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) {
- mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0,
- false);
- mode->hdisplay = 1366;
- mode->hsync_start = mode->hsync_start - 1;
- mode->hsync_end = mode->hsync_end - 1;
- return mode;
- }
-
- /* check whether it can be found in default mode table */
- mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate);
- if (mode)
- return mode;
-
- switch (timing_level) {
- case LEVEL_DMT:
- break;
- case LEVEL_GTF:
- mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
- break;
- case LEVEL_GTF2:
- /*
- * This is potentially wrong if there's ever a monitor with
- * more than one ranges section, each claiming a different
- * secondary GTF curve. Please don't do that.
- */
- mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
- if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) {
- kfree(mode);
- mode = drm_gtf_mode_complex(dev, hsize, vsize,
- vrefresh_rate, 0, 0,
- drm_gtf2_m(edid),
- drm_gtf2_2c(edid),
- drm_gtf2_k(edid),
- drm_gtf2_2j(edid));
- }
- break;
- case LEVEL_CVT:
- mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
- false);
- break;
- }
- return mode;
-}
-
-/*
- * EDID is delightfully ambiguous about how interlaced modes are to be
- * encoded. Our internal representation is of frame height, but some
- * HDTV detailed timings are encoded as field height.
- *
- * The format list here is from CEA, in frame size. Technically we
- * should be checking refresh rate too. Whatever.
- */
-static void
-drm_mode_do_interlace_quirk(struct drm_display_mode *mode,
- struct detailed_pixel_timing *pt)
-{
- int i;
- static const struct {
- int w, h;
- } cea_interlaced[] = {
- { 1920, 1080 },
- { 720, 480 },
- { 1440, 480 },
- { 2880, 480 },
- { 720, 576 },
- { 1440, 576 },
- { 2880, 576 },
- };
-
- if (!(pt->misc & DRM_EDID_PT_INTERLACED))
- return;
-
- for (i = 0; i < ARRAY_SIZE(cea_interlaced); i++) {
- if ((mode->hdisplay == cea_interlaced[i].w) &&
- (mode->vdisplay == cea_interlaced[i].h / 2)) {
- mode->vdisplay *= 2;
- mode->vsync_start *= 2;
- mode->vsync_end *= 2;
- mode->vtotal *= 2;
- mode->vtotal |= 1;
- }
- }
-
- mode->flags |= DRM_MODE_FLAG_INTERLACE;
-}
-
-/**
- * drm_mode_detailed - create a new mode from an EDID detailed timing section
- * @dev: DRM device (needed to create new mode)
- * @edid: EDID block
- * @timing: EDID detailed timing info
- * @quirks: quirks to apply
- *
- * An EDID detailed timing block contains enough info for us to create and
- * return a new struct drm_display_mode.
- */
-static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
- struct edid *edid,
- struct detailed_timing *timing,
- u32 quirks)
-{
- struct drm_display_mode *mode;
- struct detailed_pixel_timing *pt = &timing->data.pixel_data;
- unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
- unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
- unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo;
- unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
- unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
- unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
- unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
- unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
-
- /* ignore tiny modes */
- if (hactive < 64 || vactive < 64)
- return NULL;
-
- if (pt->misc & DRM_EDID_PT_STEREO) {
- printk(KERN_WARNING "stereo mode not supported\n");
- return NULL;
- }
- if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
- printk(KERN_WARNING "composite sync not supported\n");
- }
-
- /* it is incorrect if hsync/vsync width is zero */
- if (!hsync_pulse_width || !vsync_pulse_width) {
- DRM_DEBUG_KMS("Incorrect Detailed timing. "
- "Wrong Hsync/Vsync pulse width\n");
- return NULL;
- }
- mode = drm_mode_create(dev);
- if (!mode)
- return NULL;
-
- mode->type = DRM_MODE_TYPE_DRIVER;
-
- if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
- timing->pixel_clock = cpu_to_le16(1088);
-
- mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
-
- mode->hdisplay = hactive;
- mode->hsync_start = mode->hdisplay + hsync_offset;
- mode->hsync_end = mode->hsync_start + hsync_pulse_width;
- mode->htotal = mode->hdisplay + hblank;
-
- mode->vdisplay = vactive;
- mode->vsync_start = mode->vdisplay + vsync_offset;
- mode->vsync_end = mode->vsync_start + vsync_pulse_width;
- mode->vtotal = mode->vdisplay + vblank;
-
- /* Some EDIDs have bogus h/vtotal values */
- if (mode->hsync_end > mode->htotal)
- mode->htotal = mode->hsync_end + 1;
- if (mode->vsync_end > mode->vtotal)
- mode->vtotal = mode->vsync_end + 1;
-
- drm_mode_do_interlace_quirk(mode, pt);
-
- drm_mode_set_name(mode);
-
- if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
- pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
- }
-
- mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
- DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
- mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
- DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
-
- mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
- mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
-
- if (quirks & EDID_QUIRK_DETAILED_IN_CM) {
- mode->width_mm *= 10;
- mode->height_mm *= 10;
- }
-
- if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
- mode->width_mm = edid->width_cm * 10;
- mode->height_mm = edid->height_cm * 10;
- }
-
- return mode;
-}
-
-static bool
-mode_is_rb(struct drm_display_mode *mode)
-{
- return (mode->htotal - mode->hdisplay == 160) &&
- (mode->hsync_end - mode->hdisplay == 80) &&
- (mode->hsync_end - mode->hsync_start == 32) &&
- (mode->vsync_start - mode->vdisplay == 3);
-}
-
-static bool
-mode_in_hsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t)
-{
- int hsync, hmin, hmax;
-
- hmin = t[7];
- if (edid->revision >= 4)
- hmin += ((t[4] & 0x04) ? 255 : 0);
- hmax = t[8];
- if (edid->revision >= 4)
- hmax += ((t[4] & 0x08) ? 255 : 0);
- hsync = drm_mode_hsync(mode);
-
- return (hsync <= hmax && hsync >= hmin);
-}
-
-static bool
-mode_in_vsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t)
-{
- int vsync, vmin, vmax;
-
- vmin = t[5];
- if (edid->revision >= 4)
- vmin += ((t[4] & 0x01) ? 255 : 0);
- vmax = t[6];
- if (edid->revision >= 4)
- vmax += ((t[4] & 0x02) ? 255 : 0);
- vsync = drm_mode_vrefresh(mode);
-
- return (vsync <= vmax && vsync >= vmin);
-}
-
-static u32
-range_pixel_clock(struct edid *edid, u8 *t)
-{
- /* unspecified */
- if (t[9] == 0 || t[9] == 255)
- return 0;
-
- /* 1.4 with CVT support gives us real precision, yay */
- if (edid->revision >= 4 && t[10] == 0x04)
- return (t[9] * 10000) - ((t[12] >> 2) * 250);
-
- /* 1.3 is pathetic, so fuzz up a bit */
- return t[9] * 10000 + 5001;
-}
-
-static bool
-mode_in_range(struct drm_display_mode *mode, struct edid *edid,
- struct detailed_timing *timing)
-{
- u32 max_clock;
- u8 *t = (u8 *)timing;
-
- if (!mode_in_hsync_range(mode, edid, t))
- return false;
-
- if (!mode_in_vsync_range(mode, edid, t))
- return false;
-
- if ((max_clock = range_pixel_clock(edid, t)))
- if (mode->clock > max_clock)
- return false;
-
- /* 1.4 max horizontal check */
- if (edid->revision >= 4 && t[10] == 0x04)
- if (t[13] && mode->hdisplay > 8 * (t[13] + (256 * (t[12]&0x3))))
- return false;
-
- if (mode_is_rb(mode) && !drm_monitor_supports_rb(edid))
- return false;
-
- return true;
-}
-
-/*
- * XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will
- * need to account for them.
- */
-static int
-drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
- struct detailed_timing *timing)
-{
- int i, modes = 0;
- struct drm_display_mode *newmode;
- struct drm_device *dev = connector->dev;
-
- for (i = 0; i < drm_num_dmt_modes; i++) {
- if (mode_in_range(drm_dmt_modes + i, edid, timing)) {
- newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]);
- if (newmode) {
- drm_mode_probed_add(connector, newmode);
- modes++;
- }
- }
- }
-
- return modes;
-}
-
-static void
-do_inferred_modes(struct detailed_timing *timing, void *c)
-{
- struct detailed_mode_closure *closure = c;
- struct detailed_non_pixel *data = &timing->data.other_data;
- int gtf = (closure->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF);
-
- if (gtf && data->type == EDID_DETAIL_MONITOR_RANGE)
- closure->modes += drm_gtf_modes_for_range(closure->connector,
- closure->edid,
- timing);
-}
-
-static int
-add_inferred_modes(struct drm_connector *connector, struct edid *edid)
-{
- struct detailed_mode_closure closure = {
- connector, edid, 0, 0, 0
- };
-
- if (version_greater(edid, 1, 0))
- drm_for_each_detailed_block((u8 *)edid, do_inferred_modes,
- &closure);
-
- return closure.modes;
-}
-
-static int
-drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing)
-{
- int i, j, m, modes = 0;
- struct drm_display_mode *mode;
- u8 *est = ((u8 *)timing) + 5;
-
- for (i = 0; i < 6; i++) {
- for (j = 7; j > 0; j--) {
- m = (i * 8) + (7 - j);
- if (m >= ARRAY_SIZE(est3_modes))
- break;
- if (est[i] & (1 << j)) {
- mode = drm_mode_find_dmt(connector->dev,
- est3_modes[m].w,
- est3_modes[m].h,
- est3_modes[m].r
- /*, est3_modes[m].rb */);
- if (mode) {
- drm_mode_probed_add(connector, mode);
- modes++;
- }
- }
- }
- }
-
- return modes;
-}
-
-static void
-do_established_modes(struct detailed_timing *timing, void *c)
-{
- struct detailed_mode_closure *closure = c;
- struct detailed_non_pixel *data = &timing->data.other_data;
-
- if (data->type == EDID_DETAIL_EST_TIMINGS)
- closure->modes += drm_est3_modes(closure->connector, timing);
-}
-
-/**
- * add_established_modes - get est. modes from EDID and add them
- * @edid: EDID block to scan
- *
- * Each EDID block contains a bitmap of the supported "established modes" list
- * (defined above). Tease them out and add them to the global modes list.
- */
-static int
-add_established_modes(struct drm_connector *connector, struct edid *edid)
-{
- struct drm_device *dev = connector->dev;
- unsigned long est_bits = edid->established_timings.t1 |
- (edid->established_timings.t2 << 8) |
- ((edid->established_timings.mfg_rsvd & 0x80) << 9);
- int i, modes = 0;
- struct detailed_mode_closure closure = {
- connector, edid, 0, 0, 0
- };
-
- for (i = 0; i <= EDID_EST_TIMINGS; i++) {
- if (est_bits & (1<<i)) {
- struct drm_display_mode *newmode;
- newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
- if (newmode) {
- drm_mode_probed_add(connector, newmode);
- modes++;
- }
- }
- }
-
- if (version_greater(edid, 1, 0))
- drm_for_each_detailed_block((u8 *)edid,
- do_established_modes, &closure);
-
- return modes + closure.modes;
-}
-
-static void
-do_standard_modes(struct detailed_timing *timing, void *c)
-{
- struct detailed_mode_closure *closure = c;
- struct detailed_non_pixel *data = &timing->data.other_data;
- struct drm_connector *connector = closure->connector;
- struct edid *edid = closure->edid;
-
- if (data->type == EDID_DETAIL_STD_MODES) {
- int i;
- for (i = 0; i < 6; i++) {
- struct std_timing *std;
- struct drm_display_mode *newmode;
-
- std = &data->data.timings[i];
- newmode = drm_mode_std(connector, edid, std,
- edid->revision);
- if (newmode) {
- drm_mode_probed_add(connector, newmode);
- closure->modes++;
- }
- }
- }
-}
-
-/**
- * add_standard_modes - get std. modes from EDID and add them
- * @edid: EDID block to scan
- *
- * Standard modes can be calculated using the appropriate standard (DMT,
- * GTF or CVT. Grab them from @edid and add them to the list.
- */
-static int
-add_standard_modes(struct drm_connector *connector, struct edid *edid)
-{
- int i, modes = 0;
- struct detailed_mode_closure closure = {
- connector, edid, 0, 0, 0
- };
-
- for (i = 0; i < EDID_STD_TIMINGS; i++) {
- struct drm_display_mode *newmode;
-
- newmode = drm_mode_std(connector, edid,
- &edid->standard_timings[i],
- edid->revision);
- if (newmode) {
- drm_mode_probed_add(connector, newmode);
- modes++;
- }
- }
-
- if (version_greater(edid, 1, 0))
- drm_for_each_detailed_block((u8 *)edid, do_standard_modes,
- &closure);
-
- /* XXX should also look for standard codes in VTB blocks */
-
- return modes + closure.modes;
-}
-
-static int drm_cvt_modes(struct drm_connector *connector,
- struct detailed_timing *timing)
-{
- int i, j, modes = 0;
- struct drm_display_mode *newmode;
- struct drm_device *dev = connector->dev;
- struct cvt_timing *cvt;
- const int rates[] = { 60, 85, 75, 60, 50 };
- const u8 empty[3] = { 0, 0, 0 };
-
- for (i = 0; i < 4; i++) {
- int uninitialized_var(width), height;
- cvt = &(timing->data.other_data.data.cvt[i]);
-
- if (!memcmp(cvt->code, empty, 3))
- continue;
-
- height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2;
- switch (cvt->code[1] & 0x0c) {
- case 0x00:
- width = height * 4 / 3;
- break;
- case 0x04:
- width = height * 16 / 9;
- break;
- case 0x08:
- width = height * 16 / 10;
- break;
- case 0x0c:
- width = height * 15 / 9;
- break;
- }
-
- for (j = 1; j < 5; j++) {
- if (cvt->code[2] & (1 << j)) {
- newmode = drm_cvt_mode(dev, width, height,
- rates[j], j == 0,
- false, false);
- if (newmode) {
- drm_mode_probed_add(connector, newmode);
- modes++;
- }
- }
- }
- }
-
- return modes;
-}
-
-static void
-do_cvt_mode(struct detailed_timing *timing, void *c)
-{
- struct detailed_mode_closure *closure = c;
- struct detailed_non_pixel *data = &timing->data.other_data;
-
- if (data->type == EDID_DETAIL_CVT_3BYTE)
- closure->modes += drm_cvt_modes(closure->connector, timing);
-}
-
-static int
-add_cvt_modes(struct drm_connector *connector, struct edid *edid)
-{
- struct detailed_mode_closure closure = {
- connector, edid, 0, 0, 0
- };
-
- if (version_greater(edid, 1, 2))
- drm_for_each_detailed_block((u8 *)edid, do_cvt_mode, &closure);
-
- /* XXX should also look for CVT codes in VTB blocks */
-
- return closure.modes;
-}
-
-static void
-do_detailed_mode(struct detailed_timing *timing, void *c)
-{
- struct detailed_mode_closure *closure = c;
- struct drm_display_mode *newmode;
-
- if (timing->pixel_clock) {
- newmode = drm_mode_detailed(closure->connector->dev,
- closure->edid, timing,
- closure->quirks);
- if (!newmode)
- return;
-
- if (closure->preferred)
- newmode->type |= DRM_MODE_TYPE_PREFERRED;
-
- drm_mode_probed_add(closure->connector, newmode);
- closure->modes++;
- closure->preferred = 0;
- }
-}
-
-/*
- * add_detailed_modes - Add modes from detailed timings
- * @connector: attached connector
- * @edid: EDID block to scan
- * @quirks: quirks to apply
- */
-static int
-add_detailed_modes(struct drm_connector *connector, struct edid *edid,
- u32 quirks)
-{
- struct detailed_mode_closure closure = {
- connector,
- edid,
- 1,
- quirks,
- 0
- };
-
- if (closure.preferred && !version_greater(edid, 1, 3))
- closure.preferred =
- (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
-
- drm_for_each_detailed_block((u8 *)edid, do_detailed_mode, &closure);
-
- return closure.modes;
-}
-
-#define HDMI_IDENTIFIER 0x000C03
-#define AUDIO_BLOCK 0x01
-#define VENDOR_BLOCK 0x03
-#define EDID_BASIC_AUDIO (1 << 6)
-
-/**
- * Search EDID for CEA extension block.
- */
-static u8 *drm_find_cea_extension(struct edid *edid)
-{
- u8 *edid_ext = NULL;
- int i;
-
- /* No EDID or EDID extensions */
- if (edid == NULL || edid->extensions == 0)
- return NULL;
-
- /* Find CEA extension */
- for (i = 0; i < edid->extensions; i++) {
- edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
- if (edid_ext[0] == CEA_EXT)
- break;
- }
-
- if (i == edid->extensions)
- return NULL;
-
- return edid_ext;
-}
-
-/**
- * drm_detect_hdmi_monitor - detect whether monitor is hdmi.
- * @edid: monitor EDID information
- *
- * Parse the CEA extension according to CEA-861-B.
- * Return true if HDMI, false if not or unknown.
- */
-bool drm_detect_hdmi_monitor(struct edid *edid)
-{
- u8 *edid_ext;
- int i, hdmi_id;
- int start_offset, end_offset;
- bool is_hdmi = false;
-
- edid_ext = drm_find_cea_extension(edid);
- if (!edid_ext)
- goto end;
-
- /* Data block offset in CEA extension block */
- start_offset = 4;
- end_offset = edid_ext[2];
-
- /*
- * Because HDMI identifier is in Vendor Specific Block,
- * search it from all data blocks of CEA extension.
- */
- for (i = start_offset; i < end_offset;
- /* Increased by data block len */
- i += ((edid_ext[i] & 0x1f) + 1)) {
- /* Find vendor specific block */
- if ((edid_ext[i] >> 5) == VENDOR_BLOCK) {
- hdmi_id = edid_ext[i + 1] | (edid_ext[i + 2] << 8) |
- edid_ext[i + 3] << 16;
- /* Find HDMI identifier */
- if (hdmi_id == HDMI_IDENTIFIER)
- is_hdmi = true;
- break;
- }
- }
-
-end:
- return is_hdmi;
-}
-EXPORT_SYMBOL(drm_detect_hdmi_monitor);
-
-/**
- * drm_detect_monitor_audio - check monitor audio capability
- *
- * Monitor should have CEA extension block.
- * If monitor has 'basic audio', but no CEA audio blocks, it's 'basic
- * audio' only. If there is any audio extension block and supported
- * audio format, assume at least 'basic audio' support, even if 'basic
- * audio' is not defined in EDID.
- *
- */
-bool drm_detect_monitor_audio(struct edid *edid)
-{
- u8 *edid_ext;
- int i, j;
- bool has_audio = false;
- int start_offset, end_offset;
-
- edid_ext = drm_find_cea_extension(edid);
- if (!edid_ext)
- goto end;
-
- has_audio = ((edid_ext[3] & EDID_BASIC_AUDIO) != 0);
-
- if (has_audio) {
- DRM_DEBUG_KMS("Monitor has basic audio support\n");
- goto end;
- }
-
- /* Data block offset in CEA extension block */
- start_offset = 4;
- end_offset = edid_ext[2];
-
- for (i = start_offset; i < end_offset;
- i += ((edid_ext[i] & 0x1f) + 1)) {
- if ((edid_ext[i] >> 5) == AUDIO_BLOCK) {
- has_audio = true;
- for (j = 1; j < (edid_ext[i] & 0x1f); j += 3)
- DRM_DEBUG_KMS("CEA audio format %d\n",
- (edid_ext[i + j] >> 3) & 0xf);
- goto end;
- }
- }
-end:
- return has_audio;
-}
-EXPORT_SYMBOL(drm_detect_monitor_audio);
-
-/**
- * drm_add_edid_modes - add modes from EDID data, if available
- * @connector: connector we're probing
- * @edid: edid data
- *
- * Add the specified modes to the connector's mode list.
- *
- * Return number of modes added or 0 if we couldn't find any.
- */
-int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
-{
- int num_modes = 0;
- u32 quirks;
-
- if (edid == NULL) {
- return 0;
- }
- if (!drm_edid_is_valid(edid)) {
- dev_warn(connector->dev->dev, "%s: EDID invalid.\n",
- drm_get_connector_name(connector));
- return 0;
- }
-
- quirks = edid_get_quirks(edid);
-
- /*
- * EDID spec says modes should be preferred in this order:
- * - preferred detailed mode
- * - other detailed modes from base block
- * - detailed modes from extension blocks
- * - CVT 3-byte code modes
- * - standard timing codes
- * - established timing codes
- * - modes inferred from GTF or CVT range information
- *
- * We get this pretty much right.
- *
- * XXX order for additional mode types in extension blocks?
- */
- num_modes += add_detailed_modes(connector, edid, quirks);
- num_modes += add_cvt_modes(connector, edid);
- num_modes += add_standard_modes(connector, edid);
- num_modes += add_established_modes(connector, edid);
- num_modes += add_inferred_modes(connector, edid);
-
- if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
- edid_fixup_preferred(connector, quirks);
-
- connector->display_info.width_mm = edid->width_cm * 10;
- connector->display_info.height_mm = edid->height_cm * 10;
-
- return num_modes;
-}
-EXPORT_SYMBOL(drm_add_edid_modes);
-
-/**
- * drm_add_modes_noedid - add modes for the connectors without EDID
- * @connector: connector we're probing
- * @hdisplay: the horizontal display limit
- * @vdisplay: the vertical display limit
- *
- * Add the specified modes to the connector's mode list. Only when the
- * hdisplay/vdisplay is not beyond the given limit, it will be added.
- *
- * Return number of modes added or 0 if we couldn't find any.
- */
-int drm_add_modes_noedid(struct drm_connector *connector,
- int hdisplay, int vdisplay)
-{
- int i, count, num_modes = 0;
- struct drm_display_mode *mode, *ptr;
- struct drm_device *dev = connector->dev;
-
- count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
- if (hdisplay < 0)
- hdisplay = 0;
- if (vdisplay < 0)
- vdisplay = 0;
-
- for (i = 0; i < count; i++) {
- ptr = &drm_dmt_modes[i];
- if (hdisplay && vdisplay) {
- /*
- * Only when two are valid, they will be used to check
- * whether the mode should be added to the mode list of
- * the connector.
- */
- if (ptr->hdisplay > hdisplay ||
- ptr->vdisplay > vdisplay)
- continue;
- }
- if (drm_mode_vrefresh(ptr) > 61)
- continue;
- mode = drm_mode_duplicate(dev, ptr);
- if (mode) {
- drm_mode_probed_add(connector, mode);
- num_modes++;
- }
- }
- return num_modes;
-}
-EXPORT_SYMBOL(drm_add_modes_noedid);
+++ /dev/null
-/*
- * Copyright (C) 2009 Francisco Jerez.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "drm_encoder_slave.h"
-
-/**
- * drm_i2c_encoder_init - Initialize an I2C slave encoder
- * @dev: DRM device.
- * @encoder: Encoder to be attached to the I2C device. You aren't
- * required to have called drm_encoder_init() before.
- * @adap: I2C adapter that will be used to communicate with
- * the device.
- * @info: Information that will be used to create the I2C device.
- * Required fields are @addr and @type.
- *
- * Create an I2C device on the specified bus (the module containing its
- * driver is transparently loaded) and attach it to the specified
- * &drm_encoder_slave. The @slave_funcs field will be initialized with
- * the hooks provided by the slave driver.
- *
- * If @info->platform_data is non-NULL it will be used as the initial
- * slave config.
- *
- * Returns 0 on success or a negative errno on failure, in particular,
- * -ENODEV is returned when no matching driver is found.
- */
-int drm_i2c_encoder_init(struct drm_device *dev,
- struct drm_encoder_slave *encoder,
- struct i2c_adapter *adap,
- const struct i2c_board_info *info)
-{
- char modalias[sizeof(I2C_MODULE_PREFIX)
- + I2C_NAME_SIZE];
- struct module *module = NULL;
- struct i2c_client *client;
- struct drm_i2c_encoder_driver *encoder_drv;
- int err = 0;
-
- snprintf(modalias, sizeof(modalias),
- "%s%s", I2C_MODULE_PREFIX, info->type);
- request_module(modalias);
-
- client = i2c_new_device(adap, info);
- if (!client) {
- err = -ENOMEM;
- goto fail;
- }
-
- if (!client->driver) {
- err = -ENODEV;
- goto fail_unregister;
- }
-
- module = client->driver->driver.owner;
- if (!try_module_get(module)) {
- err = -ENODEV;
- goto fail_unregister;
- }
-
- encoder->bus_priv = client;
-
- encoder_drv = to_drm_i2c_encoder_driver(client->driver);
-
- err = encoder_drv->encoder_init(client, dev, encoder);
- if (err)
- goto fail_unregister;
-
- if (info->platform_data)
- encoder->slave_funcs->set_config(&encoder->base,
- info->platform_data);
-
- return 0;
-
-fail_unregister:
- i2c_unregister_device(client);
- module_put(module);
-fail:
- return err;
-}
-EXPORT_SYMBOL(drm_i2c_encoder_init);
-
-/**
- * drm_i2c_encoder_destroy - Unregister the I2C device backing an encoder
- * @drm_encoder: Encoder to be unregistered.
- *
- * This should be called from the @destroy method of an I2C slave
- * encoder driver once I2C access is no longer needed.
- */
-void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
-{
- struct drm_encoder_slave *encoder = to_encoder_slave(drm_encoder);
- struct i2c_client *client = drm_i2c_encoder_get_client(drm_encoder);
- struct module *module = client->driver->driver.owner;
-
- i2c_unregister_device(client);
- encoder->bus_priv = NULL;
-
- module_put(module);
-}
-EXPORT_SYMBOL(drm_i2c_encoder_destroy);
+++ /dev/null
-/*
- * Copyright (c) 2006-2009 Red Hat Inc.
- * Copyright (c) 2006-2008 Intel Corporation
- * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
- *
- * DRM framebuffer helper functions
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- *
- * Authors:
- * Dave Airlie <airlied@linux.ie>
- * Jesse Barnes <jesse.barnes@intel.com>
- */
-#include <linux/kernel.h>
-#include <linux/sysrq.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include "drmP.h"
-#include "drm_crtc.h"
-#include "drm_fb_helper.h"
-#include "drm_crtc_helper.h"
-
-MODULE_AUTHOR("David Airlie, Jesse Barnes");
-MODULE_DESCRIPTION("DRM KMS helper");
-MODULE_LICENSE("GPL and additional rights");
-
-static LIST_HEAD(kernel_fb_helper_list);
-
-/* simple single crtc case helper function */
-int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
-{
- struct drm_device *dev = fb_helper->dev;
- struct drm_connector *connector;
- int i;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- struct drm_fb_helper_connector *fb_helper_connector;
-
- fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
- if (!fb_helper_connector)
- goto fail;
-
- fb_helper_connector->connector = connector;
- fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
- }
- return 0;
-fail:
- for (i = 0; i < fb_helper->connector_count; i++) {
- kfree(fb_helper->connector_info[i]);
- fb_helper->connector_info[i] = NULL;
- }
- fb_helper->connector_count = 0;
- return -ENOMEM;
-}
-EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
-
-/**
- * drm_fb_helper_connector_parse_command_line - parse command line for connector
- * @connector - connector to parse line for
- * @mode_option - per connector mode option
- *
- * This parses the connector specific then generic command lines for
- * modes and options to configure the connector.
- *
- * This uses the same parameters as the fb modedb.c, except for extra
- * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
- *
- * enable/enable Digital/disable bit at the end
- */
-static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_connector *fb_helper_conn,
- const char *mode_option)
-{
- const char *name;
- unsigned int namelen;
- int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
- unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
- int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
- int i;
- enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
- struct drm_fb_helper_cmdline_mode *cmdline_mode;
- struct drm_connector *connector;
-
- if (!fb_helper_conn)
- return false;
- connector = fb_helper_conn->connector;
-
- cmdline_mode = &fb_helper_conn->cmdline_mode;
- if (!mode_option)
- mode_option = fb_mode_option;
-
- if (!mode_option) {
- cmdline_mode->specified = false;
- return false;
- }
-
- name = mode_option;
- namelen = strlen(name);
- for (i = namelen-1; i >= 0; i--) {
- switch (name[i]) {
- case '@':
- namelen = i;
- if (!refresh_specified && !bpp_specified &&
- !yres_specified) {
- refresh = simple_strtol(&name[i+1], NULL, 10);
- refresh_specified = 1;
- if (cvt || rb)
- cvt = 0;
- } else
- goto done;
- break;
- case '-':
- namelen = i;
- if (!bpp_specified && !yres_specified) {
- bpp = simple_strtol(&name[i+1], NULL, 10);
- bpp_specified = 1;
- if (cvt || rb)
- cvt = 0;
- } else
- goto done;
- break;
- case 'x':
- if (!yres_specified) {
- yres = simple_strtol(&name[i+1], NULL, 10);
- yres_specified = 1;
- } else
- goto done;
- case '0' ... '9':
- break;
- case 'M':
- if (!yres_specified)
- cvt = 1;
- break;
- case 'R':
- if (cvt)
- rb = 1;
- break;
- case 'm':
- if (!cvt)
- margins = 1;
- break;
- case 'i':
- if (!cvt)
- interlace = 1;
- break;
- case 'e':
- force = DRM_FORCE_ON;
- break;
- case 'D':
- if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
- (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
- force = DRM_FORCE_ON;
- else
- force = DRM_FORCE_ON_DIGITAL;
- break;
- case 'd':
- force = DRM_FORCE_OFF;
- break;
- default:
- goto done;
- }
- }
- if (i < 0 && yres_specified) {
- xres = simple_strtol(name, NULL, 10);
- res_specified = 1;
- }
-done:
-
- DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
- drm_get_connector_name(connector), xres, yres,
- (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
- "", (margins) ? " with margins" : "", (interlace) ?
- " interlaced" : "");
-
- if (force) {
- const char *s;
- switch (force) {
- case DRM_FORCE_OFF: s = "OFF"; break;
- case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break;
- default:
- case DRM_FORCE_ON: s = "ON"; break;
- }
-
- DRM_INFO("forcing %s connector %s\n",
- drm_get_connector_name(connector), s);
- connector->force = force;
- }
-
- if (res_specified) {
- cmdline_mode->specified = true;
- cmdline_mode->xres = xres;
- cmdline_mode->yres = yres;
- }
-
- if (refresh_specified) {
- cmdline_mode->refresh_specified = true;
- cmdline_mode->refresh = refresh;
- }
-
- if (bpp_specified) {
- cmdline_mode->bpp_specified = true;
- cmdline_mode->bpp = bpp;
- }
- cmdline_mode->rb = rb ? true : false;
- cmdline_mode->cvt = cvt ? true : false;
- cmdline_mode->interlace = interlace ? true : false;
-
- return true;
-}
-
-static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
-{
- struct drm_fb_helper_connector *fb_helper_conn;
- int i;
-
- for (i = 0; i < fb_helper->connector_count; i++) {
- char *option = NULL;
-
- fb_helper_conn = fb_helper->connector_info[i];
-
- /* do something on return - turn off connector maybe */
- if (fb_get_options(drm_get_connector_name(fb_helper_conn->connector), &option))
- continue;
-
- drm_fb_helper_connector_parse_command_line(fb_helper_conn, option);
- }
- return 0;
-}
-
-static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
-{
- uint16_t *r_base, *g_base, *b_base;
- int i;
-
- r_base = crtc->gamma_store;
- g_base = r_base + crtc->gamma_size;
- b_base = g_base + crtc->gamma_size;
-
- for (i = 0; i < crtc->gamma_size; i++)
- helper->funcs->gamma_get(crtc, &r_base[i], &g_base[i], &b_base[i], i);
-}
-
-static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
-{
- uint16_t *r_base, *g_base, *b_base;
-
- r_base = crtc->gamma_store;
- g_base = r_base + crtc->gamma_size;
- b_base = g_base + crtc->gamma_size;
-
- crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
-}
-
-int drm_fb_helper_debug_enter(struct fb_info *info)
-{
- struct drm_fb_helper *helper = info->par;
- struct drm_crtc_helper_funcs *funcs;
- int i;
-
- if (list_empty(&kernel_fb_helper_list))
- return false;
-
- list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
- for (i = 0; i < helper->crtc_count; i++) {
- struct drm_mode_set *mode_set =
- &helper->crtc_info[i].mode_set;
-
- if (!mode_set->crtc->enabled)
- continue;
-
- funcs = mode_set->crtc->helper_private;
- drm_fb_helper_save_lut_atomic(mode_set->crtc, helper);
- funcs->mode_set_base_atomic(mode_set->crtc,
- mode_set->fb,
- mode_set->x,
- mode_set->y,
- ENTER_ATOMIC_MODE_SET);
- }
- }
-
- return 0;
-}
-EXPORT_SYMBOL(drm_fb_helper_debug_enter);
-
-/* Find the real fb for a given fb helper CRTC */
-static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_crtc *c;
-
- list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
- if (crtc->base.id == c->base.id)
- return c->fb;
- }
-
- return NULL;
-}
-
-int drm_fb_helper_debug_leave(struct fb_info *info)
-{
- struct drm_fb_helper *helper = info->par;
- struct drm_crtc *crtc;
- struct drm_crtc_helper_funcs *funcs;
- struct drm_framebuffer *fb;
- int i;
-
- for (i = 0; i < helper->crtc_count; i++) {
- struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
- crtc = mode_set->crtc;
- funcs = crtc->helper_private;
- fb = drm_mode_config_fb(crtc);
-
- if (!crtc->enabled)
- continue;
-
- if (!fb) {
- DRM_ERROR("no fb to restore??\n");
- continue;
- }
-
- drm_fb_helper_restore_lut_atomic(mode_set->crtc);
- funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
- crtc->y, LEAVE_ATOMIC_MODE_SET);
- }
-
- return 0;
-}
-EXPORT_SYMBOL(drm_fb_helper_debug_leave);
-
-bool drm_fb_helper_force_kernel_mode(void)
-{
- int i = 0;
- bool ret, error = false;
- struct drm_fb_helper *helper;
-
- if (list_empty(&kernel_fb_helper_list))
- return false;
-
- list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
- for (i = 0; i < helper->crtc_count; i++) {
- struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
- ret = drm_crtc_helper_set_config(mode_set);
- if (ret)
- error = true;
- }
- }
- return error;
-}
-
-int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
- void *panic_str)
-{
- printk(KERN_ERR "panic occurred, switching back to text console\n");
- return drm_fb_helper_force_kernel_mode();
- return 0;
-}
-EXPORT_SYMBOL(drm_fb_helper_panic);
-
-static struct notifier_block paniced = {
- .notifier_call = drm_fb_helper_panic,
-};
-
-/**
- * drm_fb_helper_restore - restore the framebuffer console (kernel) config
- *
- * Restore's the kernel's fbcon mode, used for lastclose & panic paths.
- */
-void drm_fb_helper_restore(void)
-{
- bool ret;
- ret = drm_fb_helper_force_kernel_mode();
- if (ret == true)
- DRM_ERROR("Failed to restore crtc configuration\n");
-}
-EXPORT_SYMBOL(drm_fb_helper_restore);
-
-#ifdef CONFIG_MAGIC_SYSRQ
-static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
-{
- drm_fb_helper_restore();
-}
-static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
-
-static void drm_fb_helper_sysrq(int dummy1)
-{
- schedule_work(&drm_fb_helper_restore_work);
-}
-
-static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
- .handler = drm_fb_helper_sysrq,
- .help_msg = "force-fb(V)",
- .action_msg = "Restore framebuffer console",
-};
-#else
-static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
-#endif
-
-static void drm_fb_helper_on(struct fb_info *info)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct drm_device *dev = fb_helper->dev;
- struct drm_crtc *crtc;
- struct drm_crtc_helper_funcs *crtc_funcs;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
- int i, j;
-
- /*
- * For each CRTC in this fb, turn the crtc on then,
- * find all associated encoders and turn them on.
- */
- mutex_lock(&dev->mode_config.mutex);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
- crtc_funcs = crtc->helper_private;
-
- if (!crtc->enabled)
- continue;
-
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-
- /* Walk the connectors & encoders on this fb turning them on */
- for (j = 0; j < fb_helper->connector_count; j++) {
- connector = fb_helper->connector_info[j]->connector;
- connector->dpms = DRM_MODE_DPMS_ON;
- drm_connector_property_set_value(connector,
- dev->mode_config.dpms_property,
- DRM_MODE_DPMS_ON);
- }
- /* Found a CRTC on this fb, now find encoders */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- struct drm_encoder_helper_funcs *encoder_funcs;
-
- encoder_funcs = encoder->helper_private;
- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
- }
- }
- }
- mutex_unlock(&dev->mode_config.mutex);
-}
-
-static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct drm_device *dev = fb_helper->dev;
- struct drm_crtc *crtc;
- struct drm_crtc_helper_funcs *crtc_funcs;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
- int i, j;
-
- /*
- * For each CRTC in this fb, find all associated encoders
- * and turn them off, then turn off the CRTC.
- */
- mutex_lock(&dev->mode_config.mutex);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
- crtc_funcs = crtc->helper_private;
-
- if (!crtc->enabled)
- continue;
-
- /* Walk the connectors on this fb and mark them off */
- for (j = 0; j < fb_helper->connector_count; j++) {
- connector = fb_helper->connector_info[j]->connector;
- connector->dpms = dpms_mode;
- drm_connector_property_set_value(connector,
- dev->mode_config.dpms_property,
- dpms_mode);
- }
- /* Found a CRTC on this fb, now find encoders */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- struct drm_encoder_helper_funcs *encoder_funcs;
-
- encoder_funcs = encoder->helper_private;
- encoder_funcs->dpms(encoder, dpms_mode);
- }
- }
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
- }
- mutex_unlock(&dev->mode_config.mutex);
-}
-
-int drm_fb_helper_blank(int blank, struct fb_info *info)
-{
- switch (blank) {
- /* Display: On; HSync: On, VSync: On */
- case FB_BLANK_UNBLANK:
- drm_fb_helper_on(info);
- break;
- /* Display: Off; HSync: On, VSync: On */
- case FB_BLANK_NORMAL:
- drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
- break;
- /* Display: Off; HSync: Off, VSync: On */
- case FB_BLANK_HSYNC_SUSPEND:
- drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
- break;
- /* Display: Off; HSync: On, VSync: Off */
- case FB_BLANK_VSYNC_SUSPEND:
- drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
- break;
- /* Display: Off; HSync: Off, VSync: Off */
- case FB_BLANK_POWERDOWN:
- drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
- break;
- }
- return 0;
-}
-EXPORT_SYMBOL(drm_fb_helper_blank);
-
-static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
-{
- int i;
-
- for (i = 0; i < helper->connector_count; i++)
- kfree(helper->connector_info[i]);
- kfree(helper->connector_info);
- for (i = 0; i < helper->crtc_count; i++)
- kfree(helper->crtc_info[i].mode_set.connectors);
- kfree(helper->crtc_info);
-}
-
-int drm_fb_helper_init(struct drm_device *dev,
- struct drm_fb_helper *fb_helper,
- int crtc_count, int max_conn_count)
-{
- struct drm_crtc *crtc;
- int ret = 0;
- int i;
-
- fb_helper->dev = dev;
-
- INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
-
- fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
- if (!fb_helper->crtc_info)
- return -ENOMEM;
-
- fb_helper->crtc_count = crtc_count;
- fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
- if (!fb_helper->connector_info) {
- kfree(fb_helper->crtc_info);
- return -ENOMEM;
- }
- fb_helper->connector_count = 0;
-
- for (i = 0; i < crtc_count; i++) {
- fb_helper->crtc_info[i].mode_set.connectors =
- kcalloc(max_conn_count,
- sizeof(struct drm_connector *),
- GFP_KERNEL);
-
- if (!fb_helper->crtc_info[i].mode_set.connectors) {
- ret = -ENOMEM;
- goto out_free;
- }
- fb_helper->crtc_info[i].mode_set.num_connectors = 0;
- }
-
- i = 0;
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- fb_helper->crtc_info[i].crtc_id = crtc->base.id;
- fb_helper->crtc_info[i].mode_set.crtc = crtc;
- i++;
- }
- fb_helper->conn_limit = max_conn_count;
- return 0;
-out_free:
- drm_fb_helper_crtc_free(fb_helper);
- return -ENOMEM;
-}
-EXPORT_SYMBOL(drm_fb_helper_init);
-
-void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
-{
- if (!list_empty(&fb_helper->kernel_fb_list)) {
- list_del(&fb_helper->kernel_fb_list);
- if (list_empty(&kernel_fb_helper_list)) {
- printk(KERN_INFO "drm: unregistered panic notifier\n");
- atomic_notifier_chain_unregister(&panic_notifier_list,
- &paniced);
- unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
- }
- }
-
- drm_fb_helper_crtc_free(fb_helper);
-
-}
-EXPORT_SYMBOL(drm_fb_helper_fini);
-
-static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
- u16 blue, u16 regno, struct fb_info *info)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct drm_framebuffer *fb = fb_helper->fb;
- int pindex;
-
- if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
- u32 *palette;
- u32 value;
- /* place color in psuedopalette */
- if (regno > 16)
- return -EINVAL;
- palette = (u32 *)info->pseudo_palette;
- red >>= (16 - info->var.red.length);
- green >>= (16 - info->var.green.length);
- blue >>= (16 - info->var.blue.length);
- value = (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset);
- palette[regno] = value;
- return 0;
- }
-
- pindex = regno;
-
- if (fb->bits_per_pixel == 16) {
- pindex = regno << 3;
-
- if (fb->depth == 16 && regno > 63)
- return -EINVAL;
- if (fb->depth == 15 && regno > 31)
- return -EINVAL;
-
- if (fb->depth == 16) {
- u16 r, g, b;
- int i;
- if (regno < 32) {
- for (i = 0; i < 8; i++)
- fb_helper->funcs->gamma_set(crtc, red,
- green, blue, pindex + i);
- }
-
- fb_helper->funcs->gamma_get(crtc, &r,
- &g, &b,
- pindex >> 1);
-
- for (i = 0; i < 4; i++)
- fb_helper->funcs->gamma_set(crtc, r,
- green, b,
- (pindex >> 1) + i);
- }
- }
-
- if (fb->depth != 16)
- fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
- return 0;
-}
-
-int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct drm_crtc_helper_funcs *crtc_funcs;
- u16 *red, *green, *blue, *transp;
- struct drm_crtc *crtc;
- int i, rc = 0;
- int start;
-
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
- crtc_funcs = crtc->helper_private;
-
- red = cmap->red;
- green = cmap->green;
- blue = cmap->blue;
- transp = cmap->transp;
- start = cmap->start;
-
- for (i = 0; i < cmap->len; i++) {
- u16 hred, hgreen, hblue, htransp = 0xffff;
-
- hred = *red++;
- hgreen = *green++;
- hblue = *blue++;
-
- if (transp)
- htransp = *transp++;
-
- rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
- if (rc)
- return rc;
- }
- crtc_funcs->load_lut(crtc);
- }
- return rc;
-}
-EXPORT_SYMBOL(drm_fb_helper_setcmap);
-
-int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct drm_framebuffer *fb = fb_helper->fb;
- int depth;
-
- if (var->pixclock != 0 || in_dbg_master())
- return -EINVAL;
-
- /* Need to resize the fb object !!! */
- if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) {
- DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
- "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel,
- fb->width, fb->height, fb->bits_per_pixel);
- return -EINVAL;
- }
-
- switch (var->bits_per_pixel) {
- case 16:
- depth = (var->green.length == 6) ? 16 : 15;
- break;
- case 32:
- depth = (var->transp.length > 0) ? 32 : 24;
- break;
- default:
- depth = var->bits_per_pixel;
- break;
- }
-
- switch (depth) {
- case 8:
- var->red.offset = 0;
- var->green.offset = 0;
- var->blue.offset = 0;
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- var->transp.length = 0;
- var->transp.offset = 0;
- break;
- case 15:
- var->red.offset = 10;
- var->green.offset = 5;
- var->blue.offset = 0;
- var->red.length = 5;
- var->green.length = 5;
- var->blue.length = 5;
- var->transp.length = 1;
- var->transp.offset = 15;
- break;
- case 16:
- var->red.offset = 11;
- var->green.offset = 5;
- var->blue.offset = 0;
- var->red.length = 5;
- var->green.length = 6;
- var->blue.length = 5;
- var->transp.length = 0;
- var->transp.offset = 0;
- break;
- case 24:
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- var->transp.length = 0;
- var->transp.offset = 0;
- break;
- case 32:
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- var->transp.length = 8;
- var->transp.offset = 24;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-EXPORT_SYMBOL(drm_fb_helper_check_var);
-
-/* this will let fbcon do the mode init */
-int drm_fb_helper_set_par(struct fb_info *info)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct drm_device *dev = fb_helper->dev;
- struct fb_var_screeninfo *var = &info->var;
- struct drm_crtc *crtc;
- int ret;
- int i;
-
- if (var->pixclock != 0) {
- DRM_ERROR("PIXEL CLOCK SET\n");
- return -EINVAL;
- }
-
- mutex_lock(&dev->mode_config.mutex);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
- ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
- if (ret) {
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
- }
- }
- mutex_unlock(&dev->mode_config.mutex);
-
- if (fb_helper->delayed_hotplug) {
- fb_helper->delayed_hotplug = false;
- drm_fb_helper_hotplug_event(fb_helper);
- }
- return 0;
-}
-EXPORT_SYMBOL(drm_fb_helper_set_par);
-
-int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct drm_device *dev = fb_helper->dev;
- struct drm_mode_set *modeset;
- struct drm_crtc *crtc;
- int ret = 0;
- int i;
-
- mutex_lock(&dev->mode_config.mutex);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
-
- modeset = &fb_helper->crtc_info[i].mode_set;
-
- modeset->x = var->xoffset;
- modeset->y = var->yoffset;
-
- if (modeset->num_connectors) {
- ret = crtc->funcs->set_config(modeset);
- if (!ret) {
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
- }
- }
- }
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
-}
-EXPORT_SYMBOL(drm_fb_helper_pan_display);
-
-int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
- int preferred_bpp)
-{
- int new_fb = 0;
- int crtc_count = 0;
- int i;
- struct fb_info *info;
- struct drm_fb_helper_surface_size sizes;
- int gamma_size = 0;
-
- memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
- sizes.surface_depth = 24;
- sizes.surface_bpp = 32;
- sizes.fb_width = (unsigned)-1;
- sizes.fb_height = (unsigned)-1;
-
- /* if driver picks 8 or 16 by default use that
- for both depth/bpp */
- if (preferred_bpp != sizes.surface_bpp) {
- sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
- }
- /* first up get a count of crtcs now in use and new min/maxes width/heights */
- for (i = 0; i < fb_helper->connector_count; i++) {
- struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
- struct drm_fb_helper_cmdline_mode *cmdline_mode;
-
- cmdline_mode = &fb_helper_conn->cmdline_mode;
-
- if (cmdline_mode->bpp_specified) {
- switch (cmdline_mode->bpp) {
- case 8:
- sizes.surface_depth = sizes.surface_bpp = 8;
- break;
- case 15:
- sizes.surface_depth = 15;
- sizes.surface_bpp = 16;
- break;
- case 16:
- sizes.surface_depth = sizes.surface_bpp = 16;
- break;
- case 24:
- sizes.surface_depth = sizes.surface_bpp = 24;
- break;
- case 32:
- sizes.surface_depth = 24;
- sizes.surface_bpp = 32;
- break;
- }
- break;
- }
- }
-
- crtc_count = 0;
- for (i = 0; i < fb_helper->crtc_count; i++) {
- struct drm_display_mode *desired_mode;
- desired_mode = fb_helper->crtc_info[i].desired_mode;
-
- if (desired_mode) {
- if (gamma_size == 0)
- gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
- if (desired_mode->hdisplay < sizes.fb_width)
- sizes.fb_width = desired_mode->hdisplay;
- if (desired_mode->vdisplay < sizes.fb_height)
- sizes.fb_height = desired_mode->vdisplay;
- if (desired_mode->hdisplay > sizes.surface_width)
- sizes.surface_width = desired_mode->hdisplay;
- if (desired_mode->vdisplay > sizes.surface_height)
- sizes.surface_height = desired_mode->vdisplay;
- crtc_count++;
- }
- }
-
- if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
- /* hmm everyone went away - assume VGA cable just fell out
- and will come back later. */
- DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n");
- sizes.fb_width = sizes.surface_width = 1024;
- sizes.fb_height = sizes.surface_height = 768;
- }
-
- /* push down into drivers */
- new_fb = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
- if (new_fb < 0)
- return new_fb;
-
- info = fb_helper->fbdev;
-
- /* set the fb pointer */
- for (i = 0; i < fb_helper->crtc_count; i++) {
- fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
- }
-
- if (new_fb) {
- info->var.pixclock = 0;
- if (register_framebuffer(info) < 0) {
- return -EINVAL;
- }
-
- printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
- info->fix.id);
-
- } else {
- drm_fb_helper_set_par(info);
- }
-
- /* Switch back to kernel console on panic */
- /* multi card linked list maybe */
- if (list_empty(&kernel_fb_helper_list)) {
- printk(KERN_INFO "drm: registered panic notifier\n");
- atomic_notifier_chain_register(&panic_notifier_list,
- &paniced);
- register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
- }
- if (new_fb)
- list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
-
- return 0;
-}
-EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
-
-void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
- uint32_t depth)
-{
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
- FB_VISUAL_TRUECOLOR;
- info->fix.type_aux = 0;
- info->fix.xpanstep = 1; /* doing it in hw */
- info->fix.ypanstep = 1; /* doing it in hw */
- info->fix.ywrapstep = 0;
- info->fix.accel = FB_ACCEL_NONE;
- info->fix.type_aux = 0;
-
- info->fix.line_length = pitch;
- return;
-}
-EXPORT_SYMBOL(drm_fb_helper_fill_fix);
-
-void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
- uint32_t fb_width, uint32_t fb_height)
-{
- struct drm_framebuffer *fb = fb_helper->fb;
- info->pseudo_palette = fb_helper->pseudo_palette;
- info->var.xres_virtual = fb->width;
- info->var.yres_virtual = fb->height;
- info->var.bits_per_pixel = fb->bits_per_pixel;
- info->var.xoffset = 0;
- info->var.yoffset = 0;
- info->var.activate = FB_ACTIVATE_NOW;
- info->var.height = -1;
- info->var.width = -1;
-
- switch (fb->depth) {
- case 8:
- info->var.red.offset = 0;
- info->var.green.offset = 0;
- info->var.blue.offset = 0;
- info->var.red.length = 8; /* 8bit DAC */
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 0;
- info->var.transp.length = 0;
- break;
- case 15:
- info->var.red.offset = 10;
- info->var.green.offset = 5;
- info->var.blue.offset = 0;
- info->var.red.length = 5;
- info->var.green.length = 5;
- info->var.blue.length = 5;
- info->var.transp.offset = 15;
- info->var.transp.length = 1;
- break;
- case 16:
- info->var.red.offset = 11;
- info->var.green.offset = 5;
- info->var.blue.offset = 0;
- info->var.red.length = 5;
- info->var.green.length = 6;
- info->var.blue.length = 5;
- info->var.transp.offset = 0;
- break;
- case 24:
- info->var.red.offset = 16;
- info->var.green.offset = 8;
- info->var.blue.offset = 0;
- info->var.red.length = 8;
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 0;
- info->var.transp.length = 0;
- break;
- case 32:
- info->var.red.offset = 16;
- info->var.green.offset = 8;
- info->var.blue.offset = 0;
- info->var.red.length = 8;
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 24;
- info->var.transp.length = 8;
- break;
- default:
- break;
- }
-
- info->var.xres = fb_width;
- info->var.yres = fb_height;
-}
-EXPORT_SYMBOL(drm_fb_helper_fill_var);
-
-static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
- uint32_t maxX,
- uint32_t maxY)
-{
- struct drm_connector *connector;
- int count = 0;
- int i;
-
- for (i = 0; i < fb_helper->connector_count; i++) {
- connector = fb_helper->connector_info[i]->connector;
- count += connector->funcs->fill_modes(connector, maxX, maxY);
- }
-
- return count;
-}
-
-static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
-{
- struct drm_display_mode *mode;
-
- list_for_each_entry(mode, &fb_connector->connector->modes, head) {
- if (drm_mode_width(mode) > width ||
- drm_mode_height(mode) > height)
- continue;
- if (mode->type & DRM_MODE_TYPE_PREFERRED)
- return mode;
- }
- return NULL;
-}
-
-static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
-{
- struct drm_fb_helper_cmdline_mode *cmdline_mode;
- cmdline_mode = &fb_connector->cmdline_mode;
- return cmdline_mode->specified;
-}
-
-static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
- int width, int height)
-{
- struct drm_fb_helper_cmdline_mode *cmdline_mode;
- struct drm_display_mode *mode = NULL;
-
- cmdline_mode = &fb_helper_conn->cmdline_mode;
- if (cmdline_mode->specified == false)
- return mode;
-
- /* attempt to find a matching mode in the list of modes
- * we have gotten so far, if not add a CVT mode that conforms
- */
- if (cmdline_mode->rb || cmdline_mode->margins)
- goto create_mode;
-
- list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
- /* check width/height */
- if (mode->hdisplay != cmdline_mode->xres ||
- mode->vdisplay != cmdline_mode->yres)
- continue;
-
- if (cmdline_mode->refresh_specified) {
- if (mode->vrefresh != cmdline_mode->refresh)
- continue;
- }
-
- if (cmdline_mode->interlace) {
- if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
- continue;
- }
- return mode;
- }
-
-create_mode:
- if (cmdline_mode->cvt)
- mode = drm_cvt_mode(fb_helper_conn->connector->dev,
- cmdline_mode->xres, cmdline_mode->yres,
- cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
- cmdline_mode->rb, cmdline_mode->interlace,
- cmdline_mode->margins);
- else
- mode = drm_gtf_mode(fb_helper_conn->connector->dev,
- cmdline_mode->xres, cmdline_mode->yres,
- cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
- cmdline_mode->interlace,
- cmdline_mode->margins);
- drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
- list_add(&mode->head, &fb_helper_conn->connector->modes);
- return mode;
-}
-
-static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
-{
- bool enable;
-
- if (strict) {
- enable = connector->status == connector_status_connected;
- } else {
- enable = connector->status != connector_status_disconnected;
- }
- return enable;
-}
-
-static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
- bool *enabled)
-{
- bool any_enabled = false;
- struct drm_connector *connector;
- int i = 0;
-
- for (i = 0; i < fb_helper->connector_count; i++) {
- connector = fb_helper->connector_info[i]->connector;
- enabled[i] = drm_connector_enabled(connector, true);
- DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
- enabled[i] ? "yes" : "no");
- any_enabled |= enabled[i];
- }
-
- if (any_enabled)
- return;
-
- for (i = 0; i < fb_helper->connector_count; i++) {
- connector = fb_helper->connector_info[i]->connector;
- enabled[i] = drm_connector_enabled(connector, false);
- }
-}
-
-static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
- struct drm_display_mode **modes,
- bool *enabled, int width, int height)
-{
- int count, i, j;
- bool can_clone = false;
- struct drm_fb_helper_connector *fb_helper_conn;
- struct drm_display_mode *dmt_mode, *mode;
-
- /* only contemplate cloning in the single crtc case */
- if (fb_helper->crtc_count > 1)
- return false;
-
- count = 0;
- for (i = 0; i < fb_helper->connector_count; i++) {
- if (enabled[i])
- count++;
- }
-
- /* only contemplate cloning if more than one connector is enabled */
- if (count <= 1)
- return false;
-
- /* check the command line or if nothing common pick 1024x768 */
- can_clone = true;
- for (i = 0; i < fb_helper->connector_count; i++) {
- if (!enabled[i])
- continue;
- fb_helper_conn = fb_helper->connector_info[i];
- modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height);
- if (!modes[i]) {
- can_clone = false;
- break;
- }
- for (j = 0; j < i; j++) {
- if (!enabled[j])
- continue;
- if (!drm_mode_equal(modes[j], modes[i]))
- can_clone = false;
- }
- }
-
- if (can_clone) {
- DRM_DEBUG_KMS("can clone using command line\n");
- return true;
- }
-
- /* try and find a 1024x768 mode on each connector */
- can_clone = true;
- dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60);
-
- for (i = 0; i < fb_helper->connector_count; i++) {
-
- if (!enabled[i])
- continue;
-
- fb_helper_conn = fb_helper->connector_info[i];
- list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
- if (drm_mode_equal(mode, dmt_mode))
- modes[i] = mode;
- }
- if (!modes[i])
- can_clone = false;
- }
-
- if (can_clone) {
- DRM_DEBUG_KMS("can clone using 1024x768\n");
- return true;
- }
- DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
- return false;
-}
-
-static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
- struct drm_display_mode **modes,
- bool *enabled, int width, int height)
-{
- struct drm_fb_helper_connector *fb_helper_conn;
- int i;
-
- for (i = 0; i < fb_helper->connector_count; i++) {
- fb_helper_conn = fb_helper->connector_info[i];
-
- if (enabled[i] == false)
- continue;
-
- DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
- fb_helper_conn->connector->base.id);
-
- /* got for command line mode first */
- modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height);
- if (!modes[i]) {
- DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
- fb_helper_conn->connector->base.id);
- modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height);
- }
- /* No preferred modes, pick one off the list */
- if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) {
- list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head)
- break;
- }
- DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
- "none");
- }
- return true;
-}
-
-static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
- struct drm_fb_helper_crtc **best_crtcs,
- struct drm_display_mode **modes,
- int n, int width, int height)
-{
- int c, o;
- struct drm_device *dev = fb_helper->dev;
- struct drm_connector *connector;
- struct drm_connector_helper_funcs *connector_funcs;
- struct drm_encoder *encoder;
- struct drm_fb_helper_crtc *best_crtc;
- int my_score, best_score, score;
- struct drm_fb_helper_crtc **crtcs, *crtc;
- struct drm_fb_helper_connector *fb_helper_conn;
-
- if (n == fb_helper->connector_count)
- return 0;
-
- fb_helper_conn = fb_helper->connector_info[n];
- connector = fb_helper_conn->connector;
-
- best_crtcs[n] = NULL;
- best_crtc = NULL;
- best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height);
- if (modes[n] == NULL)
- return best_score;
-
- crtcs = kzalloc(dev->mode_config.num_connector *
- sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
- if (!crtcs)
- return best_score;
-
- my_score = 1;
- if (connector->status == connector_status_connected)
- my_score++;
- if (drm_has_cmdline_mode(fb_helper_conn))
- my_score++;
- if (drm_has_preferred_mode(fb_helper_conn, width, height))
- my_score++;
-
- connector_funcs = connector->helper_private;
- encoder = connector_funcs->best_encoder(connector);
- if (!encoder)
- goto out;
-
- /* select a crtc for this connector and then attempt to configure
- remaining connectors */
- for (c = 0; c < fb_helper->crtc_count; c++) {
- crtc = &fb_helper->crtc_info[c];
-
- if ((encoder->possible_crtcs & (1 << c)) == 0) {
- continue;
- }
-
- for (o = 0; o < n; o++)
- if (best_crtcs[o] == crtc)
- break;
-
- if (o < n) {
- /* ignore cloning unless only a single crtc */
- if (fb_helper->crtc_count > 1)
- continue;
-
- if (!drm_mode_equal(modes[o], modes[n]))
- continue;
- }
-
- crtcs[n] = crtc;
- memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *));
- score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1,
- width, height);
- if (score > best_score) {
- best_crtc = crtc;
- best_score = score;
- memcpy(best_crtcs, crtcs,
- dev->mode_config.num_connector *
- sizeof(struct drm_fb_helper_crtc *));
- }
- }
-out:
- kfree(crtcs);
- return best_score;
-}
-
-static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
-{
- struct drm_device *dev = fb_helper->dev;
- struct drm_fb_helper_crtc **crtcs;
- struct drm_display_mode **modes;
- struct drm_encoder *encoder;
- struct drm_mode_set *modeset;
- bool *enabled;
- int width, height;
- int i, ret;
-
- DRM_DEBUG_KMS("\n");
-
- width = dev->mode_config.max_width;
- height = dev->mode_config.max_height;
-
- /* clean out all the encoder/crtc combos */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- encoder->crtc = NULL;
- }
-
- crtcs = kcalloc(dev->mode_config.num_connector,
- sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
- modes = kcalloc(dev->mode_config.num_connector,
- sizeof(struct drm_display_mode *), GFP_KERNEL);
- enabled = kcalloc(dev->mode_config.num_connector,
- sizeof(bool), GFP_KERNEL);
-
- drm_enable_connectors(fb_helper, enabled);
-
- ret = drm_target_cloned(fb_helper, modes, enabled, width, height);
- if (!ret) {
- ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
- if (!ret)
- DRM_ERROR("Unable to find initial modes\n");
- }
-
- DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height);
-
- drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
-
- /* need to set the modesets up here for use later */
- /* fill out the connector<->crtc mappings into the modesets */
- for (i = 0; i < fb_helper->crtc_count; i++) {
- modeset = &fb_helper->crtc_info[i].mode_set;
- modeset->num_connectors = 0;
- }
-
- for (i = 0; i < fb_helper->connector_count; i++) {
- struct drm_display_mode *mode = modes[i];
- struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
- modeset = &fb_crtc->mode_set;
-
- if (mode && fb_crtc) {
- DRM_DEBUG_KMS("desired mode %s set on crtc %d\n",
- mode->name, fb_crtc->mode_set.crtc->base.id);
- fb_crtc->desired_mode = mode;
- if (modeset->mode)
- drm_mode_destroy(dev, modeset->mode);
- modeset->mode = drm_mode_duplicate(dev,
- fb_crtc->desired_mode);
- modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
- }
- }
-
- kfree(crtcs);
- kfree(modes);
- kfree(enabled);
-}
-
-/**
- * drm_helper_initial_config - setup a sane initial connector configuration
- * @dev: DRM device
- *
- * LOCKING:
- * Called at init time, must take mode config lock.
- *
- * Scan the CRTCs and connectors and try to put together an initial setup.
- * At the moment, this is a cloned configuration across all heads with
- * a new framebuffer object as the backing store.
- *
- * RETURNS:
- * Zero if everything went ok, nonzero otherwise.
- */
-bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
-{
- struct drm_device *dev = fb_helper->dev;
- int count = 0;
-
- /* disable all the possible outputs/crtcs before entering KMS mode */
- drm_helper_disable_unused_functions(fb_helper->dev);
-
- drm_fb_helper_parse_command_line(fb_helper);
-
- count = drm_fb_helper_probe_connector_modes(fb_helper,
- dev->mode_config.max_width,
- dev->mode_config.max_height);
- /*
- * we shouldn't end up with no modes here.
- */
- if (count == 0) {
- printk(KERN_INFO "No connectors reported connected with modes\n");
- }
- drm_setup_crtcs(fb_helper);
-
- return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
-}
-EXPORT_SYMBOL(drm_fb_helper_initial_config);
-
-bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
-{
- int count = 0;
- u32 max_width, max_height, bpp_sel;
- bool bound = false, crtcs_bound = false;
- struct drm_crtc *crtc;
-
- if (!fb_helper->fb)
- return false;
-
- list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) {
- if (crtc->fb)
- crtcs_bound = true;
- if (crtc->fb == fb_helper->fb)
- bound = true;
- }
-
- if (!bound && crtcs_bound) {
- fb_helper->delayed_hotplug = true;
- return false;
- }
- DRM_DEBUG_KMS("\n");
-
- max_width = fb_helper->fb->width;
- max_height = fb_helper->fb->height;
- bpp_sel = fb_helper->fb->bits_per_pixel;
-
- count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
- max_height);
- drm_setup_crtcs(fb_helper);
-
- return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
-}
-EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
-
+++ /dev/null
-/**
- * \file drm_fops.c
- * File operations for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Daryll Strauss <daryll@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include <linux/poll.h>
-#include <linux/slab.h>
-
-/* from BKL pushdown: note that nothing else serializes idr_find() */
-DEFINE_MUTEX(drm_global_mutex);
-EXPORT_SYMBOL(drm_global_mutex);
-
-static int drm_open_helper(struct inode *inode, struct file *filp,
- struct drm_device * dev);
-
-static int drm_setup(struct drm_device * dev)
-{
- int i;
- int ret;
-
- if (dev->driver->firstopen) {
- ret = dev->driver->firstopen(dev);
- if (ret != 0)
- return ret;
- }
-
- atomic_set(&dev->ioctl_count, 0);
- atomic_set(&dev->vma_count, 0);
-
- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
- !drm_core_check_feature(dev, DRIVER_MODESET)) {
- dev->buf_use = 0;
- atomic_set(&dev->buf_alloc, 0);
-
- i = drm_dma_setup(dev);
- if (i < 0)
- return i;
- }
-
- for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
- atomic_set(&dev->counts[i], 0);
-
- dev->sigdata.lock = NULL;
-
- dev->queue_count = 0;
- dev->queue_reserved = 0;
- dev->queue_slots = 0;
- dev->queuelist = NULL;
- dev->context_flag = 0;
- dev->interrupt_flag = 0;
- dev->dma_flag = 0;
- dev->last_context = 0;
- dev->last_switch = 0;
- dev->last_checked = 0;
- init_waitqueue_head(&dev->context_wait);
- dev->if_version = 0;
-
- dev->ctx_start = 0;
- dev->lck_start = 0;
-
- dev->buf_async = NULL;
- init_waitqueue_head(&dev->buf_readers);
- init_waitqueue_head(&dev->buf_writers);
-
- DRM_DEBUG("\n");
-
- /*
- * The kernel's context could be created here, but is now created
- * in drm_dma_enqueue. This is more resource-efficient for
- * hardware that does not do DMA, but may mean that
- * drm_select_queue fails between the time the interrupt is
- * initialized and the time the queues are initialized.
- */
-
- return 0;
-}
-
-/**
- * Open file.
- *
- * \param inode device inode
- * \param filp file pointer.
- * \return zero on success or a negative number on failure.
- *
- * Searches the DRM device with the same minor number, calls open_helper(), and
- * increments the device open count. If the open count was previous at zero,
- * i.e., it's the first that the device is open, then calls setup().
- */
-int drm_open(struct inode *inode, struct file *filp)
-{
- struct drm_device *dev = NULL;
- int minor_id = iminor(inode);
- struct drm_minor *minor;
- int retcode = 0;
-
- minor = idr_find(&drm_minors_idr, minor_id);
- if (!minor)
- return -ENODEV;
-
- if (!(dev = minor->dev))
- return -ENODEV;
-
- retcode = drm_open_helper(inode, filp, dev);
- if (!retcode) {
- atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
- if (!dev->open_count++)
- retcode = drm_setup(dev);
- }
- if (!retcode) {
- mutex_lock(&dev->struct_mutex);
- if (minor->type == DRM_MINOR_LEGACY) {
- if (dev->dev_mapping == NULL)
- dev->dev_mapping = inode->i_mapping;
- else if (dev->dev_mapping != inode->i_mapping)
- retcode = -ENODEV;
- }
- mutex_unlock(&dev->struct_mutex);
- }
-
- return retcode;
-}
-EXPORT_SYMBOL(drm_open);
-
-/**
- * File \c open operation.
- *
- * \param inode device inode.
- * \param filp file pointer.
- *
- * Puts the dev->fops corresponding to the device minor number into
- * \p filp, call the \c open method, and restore the file operations.
- */
-int drm_stub_open(struct inode *inode, struct file *filp)
-{
- struct drm_device *dev = NULL;
- struct drm_minor *minor;
- int minor_id = iminor(inode);
- int err = -ENODEV;
- const struct file_operations *old_fops;
-
- DRM_DEBUG("\n");
-
- mutex_lock(&drm_global_mutex);
- minor = idr_find(&drm_minors_idr, minor_id);
- if (!minor)
- goto out;
-
- if (!(dev = minor->dev))
- goto out;
-
- old_fops = filp->f_op;
- filp->f_op = fops_get(&dev->driver->fops);
- if (filp->f_op == NULL) {
- filp->f_op = old_fops;
- goto out;
- }
- if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
- fops_put(filp->f_op);
- filp->f_op = fops_get(old_fops);
- }
- fops_put(old_fops);
-
-out:
- mutex_unlock(&drm_global_mutex);
- return err;
-}
-
-/**
- * Check whether DRI will run on this CPU.
- *
- * \return non-zero if the DRI will run on this CPU, or zero otherwise.
- */
-static int drm_cpu_valid(void)
-{
-#if defined(__i386__)
- if (boot_cpu_data.x86 == 3)
- return 0; /* No cmpxchg on a 386 */
-#endif
-#if defined(__sparc__) && !defined(__sparc_v9__)
- return 0; /* No cmpxchg before v9 sparc. */
-#endif
- return 1;
-}
-
-/**
- * Called whenever a process opens /dev/drm.
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param dev device.
- * \return zero on success or a negative number on failure.
- *
- * Creates and initializes a drm_file structure for the file private data in \p
- * filp and add it into the double linked list in \p dev.
- */
-static int drm_open_helper(struct inode *inode, struct file *filp,
- struct drm_device * dev)
-{
- int minor_id = iminor(inode);
- struct drm_file *priv;
- int ret;
-
- if (filp->f_flags & O_EXCL)
- return -EBUSY; /* No exclusive opens */
- if (!drm_cpu_valid())
- return -EINVAL;
-
- DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- filp->private_data = priv;
- priv->filp = filp;
- priv->uid = current_euid();
- priv->pid = task_pid_nr(current);
- priv->minor = idr_find(&drm_minors_idr, minor_id);
- priv->ioctl_count = 0;
- /* for compatibility root is always authenticated */
- priv->authenticated = capable(CAP_SYS_ADMIN);
- priv->lock_count = 0;
-
- INIT_LIST_HEAD(&priv->lhead);
- INIT_LIST_HEAD(&priv->fbs);
- INIT_LIST_HEAD(&priv->event_list);
- init_waitqueue_head(&priv->event_wait);
- priv->event_space = 4096; /* set aside 4k for event buffer */
-
- if (dev->driver->driver_features & DRIVER_GEM)
- drm_gem_open(dev, priv);
-
- if (dev->driver->open) {
- ret = dev->driver->open(dev, priv);
- if (ret < 0)
- goto out_free;
- }
-
-
- /* if there is no current master make this fd it */
- mutex_lock(&dev->struct_mutex);
- if (!priv->minor->master) {
- /* create a new master */
- priv->minor->master = drm_master_create(priv->minor);
- if (!priv->minor->master) {
- mutex_unlock(&dev->struct_mutex);
- ret = -ENOMEM;
- goto out_free;
- }
-
- priv->is_master = 1;
- /* take another reference for the copy in the local file priv */
- priv->master = drm_master_get(priv->minor->master);
-
- priv->authenticated = 1;
-
- mutex_unlock(&dev->struct_mutex);
- if (dev->driver->master_create) {
- ret = dev->driver->master_create(dev, priv->master);
- if (ret) {
- mutex_lock(&dev->struct_mutex);
- /* drop both references if this fails */
- drm_master_put(&priv->minor->master);
- drm_master_put(&priv->master);
- mutex_unlock(&dev->struct_mutex);
- goto out_free;
- }
- }
- mutex_lock(&dev->struct_mutex);
- if (dev->driver->master_set) {
- ret = dev->driver->master_set(dev, priv, true);
- if (ret) {
- /* drop both references if this fails */
- drm_master_put(&priv->minor->master);
- drm_master_put(&priv->master);
- mutex_unlock(&dev->struct_mutex);
- goto out_free;
- }
- }
- mutex_unlock(&dev->struct_mutex);
- } else {
- /* get a reference to the master */
- priv->master = drm_master_get(priv->minor->master);
- mutex_unlock(&dev->struct_mutex);
- }
-
- mutex_lock(&dev->struct_mutex);
- list_add(&priv->lhead, &dev->filelist);
- mutex_unlock(&dev->struct_mutex);
-
-#ifdef __alpha__
- /*
- * Default the hose
- */
- if (!dev->hose) {
- struct pci_dev *pci_dev;
- pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
- if (pci_dev) {
- dev->hose = pci_dev->sysdata;
- pci_dev_put(pci_dev);
- }
- if (!dev->hose) {
- struct pci_bus *b = pci_bus_b(pci_root_buses.next);
- if (b)
- dev->hose = b->sysdata;
- }
- }
-#endif
-
- return 0;
- out_free:
- kfree(priv);
- filp->private_data = NULL;
- return ret;
-}
-
-/** No-op. */
-int drm_fasync(int fd, struct file *filp, int on)
-{
- struct drm_file *priv = filp->private_data;
- struct drm_device *dev = priv->minor->dev;
-
- DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
- (long)old_encode_dev(priv->minor->device));
- return fasync_helper(fd, filp, on, &dev->buf_async);
-}
-EXPORT_SYMBOL(drm_fasync);
-
-/*
- * Reclaim locked buffers; note that this may be a bad idea if the current
- * context doesn't have the hw lock...
- */
-static void drm_reclaim_locked_buffers(struct drm_device *dev, struct file *f)
-{
- struct drm_file *file_priv = f->private_data;
-
- if (drm_i_have_hw_lock(dev, file_priv)) {
- dev->driver->reclaim_buffers_locked(dev, file_priv);
- } else {
- unsigned long _end = jiffies + 3 * DRM_HZ;
- int locked = 0;
-
- drm_idlelock_take(&file_priv->master->lock);
-
- /*
- * Wait for a while.
- */
- do {
- spin_lock_bh(&file_priv->master->lock.spinlock);
- locked = file_priv->master->lock.idle_has_lock;
- spin_unlock_bh(&file_priv->master->lock.spinlock);
- if (locked)
- break;
- schedule();
- } while (!time_after_eq(jiffies, _end));
-
- if (!locked) {
- DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n"
- "\tdriver to use reclaim_buffers_idlelocked() instead.\n"
- "\tI will go on reclaiming the buffers anyway.\n");
- }
-
- dev->driver->reclaim_buffers_locked(dev, file_priv);
- drm_idlelock_release(&file_priv->master->lock);
- }
-}
-
-static void drm_master_release(struct drm_device *dev, struct file *filp)
-{
- struct drm_file *file_priv = filp->private_data;
-
- if (dev->driver->reclaim_buffers_locked &&
- file_priv->master->lock.hw_lock)
- drm_reclaim_locked_buffers(dev, filp);
-
- if (dev->driver->reclaim_buffers_idlelocked &&
- file_priv->master->lock.hw_lock) {
- drm_idlelock_take(&file_priv->master->lock);
- dev->driver->reclaim_buffers_idlelocked(dev, file_priv);
- drm_idlelock_release(&file_priv->master->lock);
- }
-
-
- if (drm_i_have_hw_lock(dev, file_priv)) {
- DRM_DEBUG("File %p released, freeing lock for context %d\n",
- filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
- drm_lock_free(&file_priv->master->lock,
- _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
- }
-
- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
- !dev->driver->reclaim_buffers_locked) {
- dev->driver->reclaim_buffers(dev, file_priv);
- }
-}
-
-static void drm_events_release(struct drm_file *file_priv)
-{
- struct drm_device *dev = file_priv->minor->dev;
- struct drm_pending_event *e, *et;
- struct drm_pending_vblank_event *v, *vt;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->event_lock, flags);
-
- /* Remove pending flips */
- list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link)
- if (v->base.file_priv == file_priv) {
- list_del(&v->base.link);
- drm_vblank_put(dev, v->pipe);
- v->base.destroy(&v->base);
- }
-
- /* Remove unconsumed events */
- list_for_each_entry_safe(e, et, &file_priv->event_list, link)
- e->destroy(e);
-
- spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
-/**
- * Release file.
- *
- * \param inode device inode
- * \param file_priv DRM file private.
- * \return zero on success or a negative number on failure.
- *
- * If the hardware lock is held then free it, and take it again for the kernel
- * context since it's necessary to reclaim buffers. Unlink the file private
- * data from its list and free it. Decreases the open count and if it reaches
- * zero calls drm_lastclose().
- */
-int drm_release(struct inode *inode, struct file *filp)
-{
- struct drm_file *file_priv = filp->private_data;
- struct drm_device *dev = file_priv->minor->dev;
- int retcode = 0;
-
- mutex_lock(&drm_global_mutex);
-
- DRM_DEBUG("open_count = %d\n", dev->open_count);
-
- if (dev->driver->preclose)
- dev->driver->preclose(dev, file_priv);
-
- /* ========================================================
- * Begin inline drm_release
- */
-
- DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
- task_pid_nr(current),
- (long)old_encode_dev(file_priv->minor->device),
- dev->open_count);
-
- /* if the master has gone away we can't do anything with the lock */
- if (file_priv->minor->master)
- drm_master_release(dev, filp);
-
- drm_events_release(file_priv);
-
- if (dev->driver->driver_features & DRIVER_GEM)
- drm_gem_release(dev, file_priv);
-
- if (dev->driver->driver_features & DRIVER_MODESET)
- drm_fb_release(file_priv);
-
- mutex_lock(&dev->ctxlist_mutex);
- if (!list_empty(&dev->ctxlist)) {
- struct drm_ctx_list *pos, *n;
-
- list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
- if (pos->tag == file_priv &&
- pos->handle != DRM_KERNEL_CONTEXT) {
- if (dev->driver->context_dtor)
- dev->driver->context_dtor(dev,
- pos->handle);
-
- drm_ctxbitmap_free(dev, pos->handle);
-
- list_del(&pos->head);
- kfree(pos);
- --dev->ctx_count;
- }
- }
- }
- mutex_unlock(&dev->ctxlist_mutex);
-
- mutex_lock(&dev->struct_mutex);
-
- if (file_priv->is_master) {
- struct drm_master *master = file_priv->master;
- struct drm_file *temp;
- list_for_each_entry(temp, &dev->filelist, lhead) {
- if ((temp->master == file_priv->master) &&
- (temp != file_priv))
- temp->authenticated = 0;
- }
-
- /**
- * Since the master is disappearing, so is the
- * possibility to lock.
- */
-
- if (master->lock.hw_lock) {
- if (dev->sigdata.lock == master->lock.hw_lock)
- dev->sigdata.lock = NULL;
- master->lock.hw_lock = NULL;
- master->lock.file_priv = NULL;
- wake_up_interruptible_all(&master->lock.lock_queue);
- }
-
- if (file_priv->minor->master == file_priv->master) {
- /* drop the reference held my the minor */
- if (dev->driver->master_drop)
- dev->driver->master_drop(dev, file_priv, true);
- drm_master_put(&file_priv->minor->master);
- }
- }
-
- /* drop the reference held my the file priv */
- drm_master_put(&file_priv->master);
- file_priv->is_master = 0;
- list_del(&file_priv->lhead);
- mutex_unlock(&dev->struct_mutex);
-
- if (dev->driver->postclose)
- dev->driver->postclose(dev, file_priv);
- kfree(file_priv);
-
- /* ========================================================
- * End inline drm_release
- */
-
- atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
- if (!--dev->open_count) {
- if (atomic_read(&dev->ioctl_count)) {
- DRM_ERROR("Device busy: %d\n",
- atomic_read(&dev->ioctl_count));
- retcode = -EBUSY;
- } else
- retcode = drm_lastclose(dev);
- }
- mutex_unlock(&drm_global_mutex);
-
- return retcode;
-}
-EXPORT_SYMBOL(drm_release);
-
-static bool
-drm_dequeue_event(struct drm_file *file_priv,
- size_t total, size_t max, struct drm_pending_event **out)
-{
- struct drm_device *dev = file_priv->minor->dev;
- struct drm_pending_event *e;
- unsigned long flags;
- bool ret = false;
-
- spin_lock_irqsave(&dev->event_lock, flags);
-
- *out = NULL;
- if (list_empty(&file_priv->event_list))
- goto out;
- e = list_first_entry(&file_priv->event_list,
- struct drm_pending_event, link);
- if (e->event->length + total > max)
- goto out;
-
- file_priv->event_space += e->event->length;
- list_del(&e->link);
- *out = e;
- ret = true;
-
-out:
- spin_unlock_irqrestore(&dev->event_lock, flags);
- return ret;
-}
-
-ssize_t drm_read(struct file *filp, char __user *buffer,
- size_t count, loff_t *offset)
-{
- struct drm_file *file_priv = filp->private_data;
- struct drm_pending_event *e;
- size_t total;
- ssize_t ret;
-
- ret = wait_event_interruptible(file_priv->event_wait,
- !list_empty(&file_priv->event_list));
- if (ret < 0)
- return ret;
-
- total = 0;
- while (drm_dequeue_event(file_priv, total, count, &e)) {
- if (copy_to_user(buffer + total,
- e->event, e->event->length)) {
- total = -EFAULT;
- break;
- }
-
- total += e->event->length;
- e->destroy(e);
- }
-
- return total;
-}
-EXPORT_SYMBOL(drm_read);
-
-unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
-{
- struct drm_file *file_priv = filp->private_data;
- unsigned int mask = 0;
-
- poll_wait(filp, &file_priv->event_wait, wait);
-
- if (!list_empty(&file_priv->event_list))
- mask |= POLLIN | POLLRDNORM;
-
- return mask;
-}
-EXPORT_SYMBOL(drm_poll);
+++ /dev/null
-/*
- * Copyright © 2008 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- *
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/uaccess.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/module.h>
-#include <linux/mman.h>
-#include <linux/pagemap.h>
-#include "drmP.h"
-
-/** @file drm_gem.c
- *
- * This file provides some of the base ioctls and library routines for
- * the graphics memory manager implemented by each device driver.
- *
- * Because various devices have different requirements in terms of
- * synchronization and migration strategies, implementing that is left up to
- * the driver, and all that the general API provides should be generic --
- * allocating objects, reading/writing data with the cpu, freeing objects.
- * Even there, platform-dependent optimizations for reading/writing data with
- * the CPU mean we'll likely hook those out to driver-specific calls. However,
- * the DRI2 implementation wants to have at least allocate/mmap be generic.
- *
- * The goal was to have swap-backed object allocation managed through
- * struct file. However, file descriptors as handles to a struct file have
- * two major failings:
- * - Process limits prevent more than 1024 or so being used at a time by
- * default.
- * - Inability to allocate high fds will aggravate the X Server's select()
- * handling, and likely that of many GL client applications as well.
- *
- * This led to a plan of using our own integer IDs (called handles, following
- * DRM terminology) to mimic fds, and implement the fd syscalls we need as
- * ioctls. The objects themselves will still include the struct file so
- * that we can transition to fds if the required kernel infrastructure shows
- * up at a later date, and as our interface with shmfs for memory allocation.
- */
-
-/*
- * We make up offsets for buffer objects so we can recognize them at
- * mmap time.
- */
-
-/* pgoff in mmap is an unsigned long, so we need to make sure that
- * the faked up offset will fit
- */
-
-#if BITS_PER_LONG == 64
-#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1)
-#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16)
-#else
-#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFUL >> PAGE_SHIFT) + 1)
-#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16)
-#endif
-
-/**
- * Initialize the GEM device fields
- */
-
-int
-drm_gem_init(struct drm_device *dev)
-{
- struct drm_gem_mm *mm;
-
- spin_lock_init(&dev->object_name_lock);
- idr_init(&dev->object_name_idr);
-
- mm = kzalloc(sizeof(struct drm_gem_mm), GFP_KERNEL);
- if (!mm) {
- DRM_ERROR("out of memory\n");
- return -ENOMEM;
- }
-
- dev->mm_private = mm;
-
- if (drm_ht_create(&mm->offset_hash, 19)) {
- kfree(mm);
- return -ENOMEM;
- }
-
- if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
- DRM_FILE_PAGE_OFFSET_SIZE)) {
- drm_ht_remove(&mm->offset_hash);
- kfree(mm);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-void
-drm_gem_destroy(struct drm_device *dev)
-{
- struct drm_gem_mm *mm = dev->mm_private;
-
- drm_mm_takedown(&mm->offset_manager);
- drm_ht_remove(&mm->offset_hash);
- kfree(mm);
- dev->mm_private = NULL;
-}
-
-/**
- * Initialize an already allocate GEM object of the specified size with
- * shmfs backing store.
- */
-int drm_gem_object_init(struct drm_device *dev,
- struct drm_gem_object *obj, size_t size)
-{
- BUG_ON((size & (PAGE_SIZE - 1)) != 0);
-
- obj->dev = dev;
- obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
- if (IS_ERR(obj->filp))
- return -ENOMEM;
-
- kref_init(&obj->refcount);
- atomic_set(&obj->handle_count, 0);
- obj->size = size;
-
- return 0;
-}
-EXPORT_SYMBOL(drm_gem_object_init);
-
-/**
- * Allocate a GEM object of the specified size with shmfs backing store
- */
-struct drm_gem_object *
-drm_gem_object_alloc(struct drm_device *dev, size_t size)
-{
- struct drm_gem_object *obj;
-
- obj = kzalloc(sizeof(*obj), GFP_KERNEL);
- if (!obj)
- goto free;
-
- if (drm_gem_object_init(dev, obj, size) != 0)
- goto free;
-
- if (dev->driver->gem_init_object != NULL &&
- dev->driver->gem_init_object(obj) != 0) {
- goto fput;
- }
- return obj;
-fput:
- /* Object_init mangles the global counters - readjust them. */
- fput(obj->filp);
-free:
- kfree(obj);
- return NULL;
-}
-EXPORT_SYMBOL(drm_gem_object_alloc);
-
-/**
- * Removes the mapping from handle to filp for this object.
- */
-static int
-drm_gem_handle_delete(struct drm_file *filp, u32 handle)
-{
- struct drm_device *dev;
- struct drm_gem_object *obj;
-
- /* This is gross. The idr system doesn't let us try a delete and
- * return an error code. It just spews if you fail at deleting.
- * So, we have to grab a lock around finding the object and then
- * doing the delete on it and dropping the refcount, or the user
- * could race us to double-decrement the refcount and cause a
- * use-after-free later. Given the frequency of our handle lookups,
- * we may want to use ida for number allocation and a hash table
- * for the pointers, anyway.
- */
- spin_lock(&filp->table_lock);
-
- /* Check if we currently have a reference on the object */
- obj = idr_find(&filp->object_idr, handle);
- if (obj == NULL) {
- spin_unlock(&filp->table_lock);
- return -EINVAL;
- }
- dev = obj->dev;
-
- /* Release reference and decrement refcount. */
- idr_remove(&filp->object_idr, handle);
- spin_unlock(&filp->table_lock);
-
- drm_gem_object_handle_unreference_unlocked(obj);
-
- return 0;
-}
-
-/**
- * Create a handle for this object. This adds a handle reference
- * to the object, which includes a regular reference count. Callers
- * will likely want to dereference the object afterwards.
- */
-int
-drm_gem_handle_create(struct drm_file *file_priv,
- struct drm_gem_object *obj,
- u32 *handlep)
-{
- int ret;
-
- /*
- * Get the user-visible handle using idr.
- */
-again:
- /* ensure there is space available to allocate a handle */
- if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0)
- return -ENOMEM;
-
- /* do the allocation under our spinlock */
- spin_lock(&file_priv->table_lock);
- ret = idr_get_new_above(&file_priv->object_idr, obj, 1, (int *)handlep);
- spin_unlock(&file_priv->table_lock);
- if (ret == -EAGAIN)
- goto again;
-
- if (ret != 0)
- return ret;
-
- drm_gem_object_handle_reference(obj);
- return 0;
-}
-EXPORT_SYMBOL(drm_gem_handle_create);
-
-/** Returns a reference to the object named by the handle. */
-struct drm_gem_object *
-drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
- u32 handle)
-{
- struct drm_gem_object *obj;
-
- spin_lock(&filp->table_lock);
-
- /* Check if we currently have a reference on the object */
- obj = idr_find(&filp->object_idr, handle);
- if (obj == NULL) {
- spin_unlock(&filp->table_lock);
- return NULL;
- }
-
- drm_gem_object_reference(obj);
-
- spin_unlock(&filp->table_lock);
-
- return obj;
-}
-EXPORT_SYMBOL(drm_gem_object_lookup);
-
-/**
- * Releases the handle to an mm object.
- */
-int
-drm_gem_close_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_close *args = data;
- int ret;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- ret = drm_gem_handle_delete(file_priv, args->handle);
-
- return ret;
-}
-
-/**
- * Create a global name for an object, returning the name.
- *
- * Note that the name does not hold a reference; when the object
- * is freed, the name goes away.
- */
-int
-drm_gem_flink_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_flink *args = data;
- struct drm_gem_object *obj;
- int ret;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (obj == NULL)
- return -ENOENT;
-
-again:
- if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) {
- ret = -ENOMEM;
- goto err;
- }
-
- spin_lock(&dev->object_name_lock);
- if (!obj->name) {
- ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
- &obj->name);
- args->name = (uint64_t) obj->name;
- spin_unlock(&dev->object_name_lock);
-
- if (ret == -EAGAIN)
- goto again;
-
- if (ret != 0)
- goto err;
-
- /* Allocate a reference for the name table. */
- drm_gem_object_reference(obj);
- } else {
- args->name = (uint64_t) obj->name;
- spin_unlock(&dev->object_name_lock);
- ret = 0;
- }
-
-err:
- drm_gem_object_unreference_unlocked(obj);
- return ret;
-}
-
-/**
- * Open an object using the global name, returning a handle and the size.
- *
- * This handle (of course) holds a reference to the object, so the object
- * will not go away until the handle is deleted.
- */
-int
-drm_gem_open_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_open *args = data;
- struct drm_gem_object *obj;
- int ret;
- u32 handle;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- spin_lock(&dev->object_name_lock);
- obj = idr_find(&dev->object_name_idr, (int) args->name);
- if (obj)
- drm_gem_object_reference(obj);
- spin_unlock(&dev->object_name_lock);
- if (!obj)
- return -ENOENT;
-
- ret = drm_gem_handle_create(file_priv, obj, &handle);
- drm_gem_object_unreference_unlocked(obj);
- if (ret)
- return ret;
-
- args->handle = handle;
- args->size = obj->size;
-
- return 0;
-}
-
-/**
- * Called at device open time, sets up the structure for handling refcounting
- * of mm objects.
- */
-void
-drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
-{
- idr_init(&file_private->object_idr);
- spin_lock_init(&file_private->table_lock);
-}
-
-/**
- * Called at device close to release the file's
- * handle references on objects.
- */
-static int
-drm_gem_object_release_handle(int id, void *ptr, void *data)
-{
- struct drm_gem_object *obj = ptr;
-
- drm_gem_object_handle_unreference_unlocked(obj);
-
- return 0;
-}
-
-/**
- * Called at close time when the filp is going away.
- *
- * Releases any remaining references on objects by this filp.
- */
-void
-drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
-{
- idr_for_each(&file_private->object_idr,
- &drm_gem_object_release_handle, NULL);
-
- idr_remove_all(&file_private->object_idr);
- idr_destroy(&file_private->object_idr);
-}
-
-void
-drm_gem_object_release(struct drm_gem_object *obj)
-{
- fput(obj->filp);
-}
-EXPORT_SYMBOL(drm_gem_object_release);
-
-/**
- * Called after the last reference to the object has been lost.
- * Must be called holding struct_ mutex
- *
- * Frees the object
- */
-void
-drm_gem_object_free(struct kref *kref)
-{
- struct drm_gem_object *obj = (struct drm_gem_object *) kref;
- struct drm_device *dev = obj->dev;
-
- BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-
- if (dev->driver->gem_free_object != NULL)
- dev->driver->gem_free_object(obj);
-}
-EXPORT_SYMBOL(drm_gem_object_free);
-
-static void drm_gem_object_ref_bug(struct kref *list_kref)
-{
- BUG();
-}
-
-/**
- * Called after the last handle to the object has been closed
- *
- * Removes any name for the object. Note that this must be
- * called before drm_gem_object_free or we'll be touching
- * freed memory
- */
-void drm_gem_object_handle_free(struct drm_gem_object *obj)
-{
- struct drm_device *dev = obj->dev;
-
- /* Remove any name for this object */
- spin_lock(&dev->object_name_lock);
- if (obj->name) {
- idr_remove(&dev->object_name_idr, obj->name);
- obj->name = 0;
- spin_unlock(&dev->object_name_lock);
- /*
- * The object name held a reference to this object, drop
- * that now.
- *
- * This cannot be the last reference, since the handle holds one too.
- */
- kref_put(&obj->refcount, drm_gem_object_ref_bug);
- } else
- spin_unlock(&dev->object_name_lock);
-
-}
-EXPORT_SYMBOL(drm_gem_object_handle_free);
-
-void drm_gem_vm_open(struct vm_area_struct *vma)
-{
- struct drm_gem_object *obj = vma->vm_private_data;
-
- drm_gem_object_reference(obj);
-
- mutex_lock(&obj->dev->struct_mutex);
- drm_vm_open_locked(vma);
- mutex_unlock(&obj->dev->struct_mutex);
-}
-EXPORT_SYMBOL(drm_gem_vm_open);
-
-void drm_gem_vm_close(struct vm_area_struct *vma)
-{
- struct drm_gem_object *obj = vma->vm_private_data;
-
- mutex_lock(&obj->dev->struct_mutex);
- drm_vm_close_locked(vma);
- drm_gem_object_unreference(obj);
- mutex_unlock(&obj->dev->struct_mutex);
-}
-EXPORT_SYMBOL(drm_gem_vm_close);
-
-
-/**
- * drm_gem_mmap - memory map routine for GEM objects
- * @filp: DRM file pointer
- * @vma: VMA for the area to be mapped
- *
- * If a driver supports GEM object mapping, mmap calls on the DRM file
- * descriptor will end up here.
- *
- * If we find the object based on the offset passed in (vma->vm_pgoff will
- * contain the fake offset we created when the GTT map ioctl was called on
- * the object), we set up the driver fault handler so that any accesses
- * to the object can be trapped, to perform migration, GTT binding, surface
- * register allocation, or performance monitoring.
- */
-int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct drm_file *priv = filp->private_data;
- struct drm_device *dev = priv->minor->dev;
- struct drm_gem_mm *mm = dev->mm_private;
- struct drm_local_map *map = NULL;
- struct drm_gem_object *obj;
- struct drm_hash_item *hash;
- int ret = 0;
-
- mutex_lock(&dev->struct_mutex);
-
- if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) {
- mutex_unlock(&dev->struct_mutex);
- return drm_mmap(filp, vma);
- }
-
- map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
- if (!map ||
- ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) {
- ret = -EPERM;
- goto out_unlock;
- }
-
- /* Check for valid size. */
- if (map->size < vma->vm_end - vma->vm_start) {
- ret = -EINVAL;
- goto out_unlock;
- }
-
- obj = map->handle;
- if (!obj->dev->driver->gem_vm_ops) {
- ret = -EINVAL;
- goto out_unlock;
- }
-
- vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND;
- vma->vm_ops = obj->dev->driver->gem_vm_ops;
- vma->vm_private_data = map->handle;
- vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
-
- /* Take a ref for this mapping of the object, so that the fault
- * handler can dereference the mmap offset's pointer to the object.
- * This reference is cleaned up by the corresponding vm_close
- * (which should happen whether the vma was created by this call, or
- * by a vm_open due to mremap or partial unmap or whatever).
- */
- drm_gem_object_reference(obj);
-
- vma->vm_file = filp; /* Needed for drm_vm_open() */
- drm_vm_open_locked(vma);
-
-out_unlock:
- mutex_unlock(&dev->struct_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(drm_gem_mmap);
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2008-2009 VMware, Inc., Palo Alto, CA., USA
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-/*
- * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
- */
-
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include "drm_global.h"
-
-struct drm_global_item {
- struct mutex mutex;
- void *object;
- int refcount;
-};
-
-static struct drm_global_item glob[DRM_GLOBAL_NUM];
-
-void drm_global_init(void)
-{
- int i;
-
- for (i = 0; i < DRM_GLOBAL_NUM; ++i) {
- struct drm_global_item *item = &glob[i];
- mutex_init(&item->mutex);
- item->object = NULL;
- item->refcount = 0;
- }
-}
-
-void drm_global_release(void)
-{
- int i;
- for (i = 0; i < DRM_GLOBAL_NUM; ++i) {
- struct drm_global_item *item = &glob[i];
- BUG_ON(item->object != NULL);
- BUG_ON(item->refcount != 0);
- }
-}
-
-int drm_global_item_ref(struct drm_global_reference *ref)
-{
- int ret;
- struct drm_global_item *item = &glob[ref->global_type];
- void *object;
-
- mutex_lock(&item->mutex);
- if (item->refcount == 0) {
- item->object = kzalloc(ref->size, GFP_KERNEL);
- if (unlikely(item->object == NULL)) {
- ret = -ENOMEM;
- goto out_err;
- }
-
- ref->object = item->object;
- ret = ref->init(ref);
- if (unlikely(ret != 0))
- goto out_err;
-
- }
- ++item->refcount;
- ref->object = item->object;
- object = item->object;
- mutex_unlock(&item->mutex);
- return 0;
-out_err:
- mutex_unlock(&item->mutex);
- item->object = NULL;
- return ret;
-}
-EXPORT_SYMBOL(drm_global_item_ref);
-
-void drm_global_item_unref(struct drm_global_reference *ref)
-{
- struct drm_global_item *item = &glob[ref->global_type];
-
- mutex_lock(&item->mutex);
- BUG_ON(item->refcount == 0);
- BUG_ON(ref->object != item->object);
- if (--item->refcount == 0) {
- ref->release(ref);
- item->object = NULL;
- }
- mutex_unlock(&item->mutex);
-}
-EXPORT_SYMBOL(drm_global_item_unref);
-
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-/*
- * Simple open hash tab implementation.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include "drmP.h"
-#include "drm_hashtab.h"
-#include <linux/hash.h>
-#include <linux/slab.h>
-
-int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
-{
- unsigned int i;
-
- ht->size = 1 << order;
- ht->order = order;
- ht->fill = 0;
- ht->table = NULL;
- ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE);
- if (!ht->use_vmalloc) {
- ht->table = kcalloc(ht->size, sizeof(*ht->table), GFP_KERNEL);
- }
- if (!ht->table) {
- ht->use_vmalloc = 1;
- ht->table = vmalloc(ht->size*sizeof(*ht->table));
- }
- if (!ht->table) {
- DRM_ERROR("Out of memory for hash table\n");
- return -ENOMEM;
- }
- for (i=0; i< ht->size; ++i) {
- INIT_HLIST_HEAD(&ht->table[i]);
- }
- return 0;
-}
-EXPORT_SYMBOL(drm_ht_create);
-
-void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
-{
- struct drm_hash_item *entry;
- struct hlist_head *h_list;
- struct hlist_node *list;
- unsigned int hashed_key;
- int count = 0;
-
- hashed_key = hash_long(key, ht->order);
- DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
- h_list = &ht->table[hashed_key];
- hlist_for_each(list, h_list) {
- entry = hlist_entry(list, struct drm_hash_item, head);
- DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
- }
-}
-
-static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
- unsigned long key)
-{
- struct drm_hash_item *entry;
- struct hlist_head *h_list;
- struct hlist_node *list;
- unsigned int hashed_key;
-
- hashed_key = hash_long(key, ht->order);
- h_list = &ht->table[hashed_key];
- hlist_for_each(list, h_list) {
- entry = hlist_entry(list, struct drm_hash_item, head);
- if (entry->key == key)
- return list;
- if (entry->key > key)
- break;
- }
- return NULL;
-}
-
-
-int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
-{
- struct drm_hash_item *entry;
- struct hlist_head *h_list;
- struct hlist_node *list, *parent;
- unsigned int hashed_key;
- unsigned long key = item->key;
-
- hashed_key = hash_long(key, ht->order);
- h_list = &ht->table[hashed_key];
- parent = NULL;
- hlist_for_each(list, h_list) {
- entry = hlist_entry(list, struct drm_hash_item, head);
- if (entry->key == key)
- return -EINVAL;
- if (entry->key > key)
- break;
- parent = list;
- }
- if (parent) {
- hlist_add_after(parent, &item->head);
- } else {
- hlist_add_head(&item->head, h_list);
- }
- return 0;
-}
-EXPORT_SYMBOL(drm_ht_insert_item);
-
-/*
- * Just insert an item and return any "bits" bit key that hasn't been
- * used before.
- */
-int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
- unsigned long seed, int bits, int shift,
- unsigned long add)
-{
- int ret;
- unsigned long mask = (1 << bits) - 1;
- unsigned long first, unshifted_key;
-
- unshifted_key = hash_long(seed, bits);
- first = unshifted_key;
- do {
- item->key = (unshifted_key << shift) + add;
- ret = drm_ht_insert_item(ht, item);
- if (ret)
- unshifted_key = (unshifted_key + 1) & mask;
- } while(ret && (unshifted_key != first));
-
- if (ret) {
- DRM_ERROR("Available key bit space exhausted\n");
- return -EINVAL;
- }
- return 0;
-}
-EXPORT_SYMBOL(drm_ht_just_insert_please);
-
-int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
- struct drm_hash_item **item)
-{
- struct hlist_node *list;
-
- list = drm_ht_find_key(ht, key);
- if (!list)
- return -EINVAL;
-
- *item = hlist_entry(list, struct drm_hash_item, head);
- return 0;
-}
-EXPORT_SYMBOL(drm_ht_find_item);
-
-int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
-{
- struct hlist_node *list;
-
- list = drm_ht_find_key(ht, key);
- if (list) {
- hlist_del_init(list);
- ht->fill--;
- return 0;
- }
- return -EINVAL;
-}
-
-int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
-{
- hlist_del_init(&item->head);
- ht->fill--;
- return 0;
-}
-EXPORT_SYMBOL(drm_ht_remove_item);
-
-void drm_ht_remove(struct drm_open_hash *ht)
-{
- if (ht->table) {
- if (ht->use_vmalloc)
- vfree(ht->table);
- else
- kfree(ht->table);
- ht->table = NULL;
- }
-}
-EXPORT_SYMBOL(drm_ht_remove);
+++ /dev/null
-/**
- * \file drm_info.c
- * DRM info file implementations
- *
- * \author Ben Gamari <bgamari@gmail.com>
- */
-
-/*
- * Created: Sun Dec 21 13:09:50 2008 by bgamari@gmail.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * Copyright 2008 Ben Gamari <bgamari@gmail.com>
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/seq_file.h>
-#include "drmP.h"
-
-/**
- * Called when "/proc/dri/.../name" is read.
- *
- * Prints the device name together with the bus id if available.
- */
-int drm_name_info(struct seq_file *m, void *data)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_minor *minor = node->minor;
- struct drm_device *dev = minor->dev;
- struct drm_master *master = minor->master;
-
- if (!master)
- return 0;
-
- if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
- if (master->unique) {
- seq_printf(m, "%s %s %s\n",
- dev->driver->platform_device->name,
- dev_name(dev->dev), master->unique);
- } else {
- seq_printf(m, "%s\n",
- dev->driver->platform_device->name);
- }
- } else {
- if (master->unique) {
- seq_printf(m, "%s %s %s\n",
- dev->driver->pci_driver.name,
- dev_name(dev->dev), master->unique);
- } else {
- seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
- dev_name(dev->dev));
- }
- }
-
- return 0;
-}
-
-/**
- * Called when "/proc/dri/.../vm" is read.
- *
- * Prints information about all mappings in drm_device::maplist.
- */
-int drm_vm_info(struct seq_file *m, void *data)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
- struct drm_local_map *map;
- struct drm_map_list *r_list;
-
- /* Hardcoded from _DRM_FRAME_BUFFER,
- _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
- _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
- const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
- const char *type;
- int i;
-
- mutex_lock(&dev->struct_mutex);
- seq_printf(m, "slot offset size type flags address mtrr\n\n");
- i = 0;
- list_for_each_entry(r_list, &dev->maplist, head) {
- map = r_list->map;
- if (!map)
- continue;
- if (map->type < 0 || map->type > 5)
- type = "??";
- else
- type = types[map->type];
-
- seq_printf(m, "%4d 0x%016llx 0x%08lx %4.4s 0x%02x 0x%08lx ",
- i,
- (unsigned long long)map->offset,
- map->size, type, map->flags,
- (unsigned long) r_list->user_token);
- if (map->mtrr < 0)
- seq_printf(m, "none\n");
- else
- seq_printf(m, "%4d\n", map->mtrr);
- i++;
- }
- mutex_unlock(&dev->struct_mutex);
- return 0;
-}
-
-/**
- * Called when "/proc/dri/.../queues" is read.
- */
-int drm_queues_info(struct seq_file *m, void *data)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
- int i;
- struct drm_queue *q;
-
- mutex_lock(&dev->struct_mutex);
- seq_printf(m, " ctx/flags use fin"
- " blk/rw/rwf wait flushed queued"
- " locks\n\n");
- for (i = 0; i < dev->queue_count; i++) {
- q = dev->queuelist[i];
- atomic_inc(&q->use_count);
- seq_printf(m, "%5d/0x%03x %5d %5d"
- " %5d/%c%c/%c%c%c %5Zd\n",
- i,
- q->flags,
- atomic_read(&q->use_count),
- atomic_read(&q->finalization),
- atomic_read(&q->block_count),
- atomic_read(&q->block_read) ? 'r' : '-',
- atomic_read(&q->block_write) ? 'w' : '-',
- waitqueue_active(&q->read_queue) ? 'r' : '-',
- waitqueue_active(&q->write_queue) ? 'w' : '-',
- waitqueue_active(&q->flush_queue) ? 'f' : '-',
- DRM_BUFCOUNT(&q->waitlist));
- atomic_dec(&q->use_count);
- }
- mutex_unlock(&dev->struct_mutex);
- return 0;
-}
-
-/**
- * Called when "/proc/dri/.../bufs" is read.
- */
-int drm_bufs_info(struct seq_file *m, void *data)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
- struct drm_device_dma *dma;
- int i, seg_pages;
-
- mutex_lock(&dev->struct_mutex);
- dma = dev->dma;
- if (!dma) {
- mutex_unlock(&dev->struct_mutex);
- return 0;
- }
-
- seq_printf(m, " o size count free segs pages kB\n\n");
- for (i = 0; i <= DRM_MAX_ORDER; i++) {
- if (dma->bufs[i].buf_count) {
- seg_pages = dma->bufs[i].seg_count * (1 << dma->bufs[i].page_order);
- seq_printf(m, "%2d %8d %5d %5d %5d %5d %5ld\n",
- i,
- dma->bufs[i].buf_size,
- dma->bufs[i].buf_count,
- atomic_read(&dma->bufs[i].freelist.count),
- dma->bufs[i].seg_count,
- seg_pages,
- seg_pages * PAGE_SIZE / 1024);
- }
- }
- seq_printf(m, "\n");
- for (i = 0; i < dma->buf_count; i++) {
- if (i && !(i % 32))
- seq_printf(m, "\n");
- seq_printf(m, " %d", dma->buflist[i]->list);
- }
- seq_printf(m, "\n");
- mutex_unlock(&dev->struct_mutex);
- return 0;
-}
-
-/**
- * Called when "/proc/dri/.../vblank" is read.
- */
-int drm_vblank_info(struct seq_file *m, void *data)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
- int crtc;
-
- mutex_lock(&dev->struct_mutex);
- for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
- seq_printf(m, "CRTC %d enable: %d\n",
- crtc, atomic_read(&dev->vblank_refcount[crtc]));
- seq_printf(m, "CRTC %d counter: %d\n",
- crtc, drm_vblank_count(dev, crtc));
- seq_printf(m, "CRTC %d last wait: %d\n",
- crtc, dev->last_vblank_wait[crtc]);
- seq_printf(m, "CRTC %d in modeset: %d\n",
- crtc, dev->vblank_inmodeset[crtc]);
- }
- mutex_unlock(&dev->struct_mutex);
- return 0;
-}
-
-/**
- * Called when "/proc/dri/.../clients" is read.
- *
- */
-int drm_clients_info(struct seq_file *m, void *data)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
- struct drm_file *priv;
-
- mutex_lock(&dev->struct_mutex);
- seq_printf(m, "a dev pid uid magic ioctls\n\n");
- list_for_each_entry(priv, &dev->filelist, lhead) {
- seq_printf(m, "%c %3d %5d %5d %10u %10lu\n",
- priv->authenticated ? 'y' : 'n',
- priv->minor->index,
- priv->pid,
- priv->uid, priv->magic, priv->ioctl_count);
- }
- mutex_unlock(&dev->struct_mutex);
- return 0;
-}
-
-
-int drm_gem_one_name_info(int id, void *ptr, void *data)
-{
- struct drm_gem_object *obj = ptr;
- struct seq_file *m = data;
-
- seq_printf(m, "name %d size %zd\n", obj->name, obj->size);
-
- seq_printf(m, "%6d %8zd %7d %8d\n",
- obj->name, obj->size,
- atomic_read(&obj->handle_count),
- atomic_read(&obj->refcount.refcount));
- return 0;
-}
-
-int drm_gem_name_info(struct seq_file *m, void *data)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
-
- seq_printf(m, " name size handles refcount\n");
- idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m);
- return 0;
-}
-
-#if DRM_DEBUG_CODE
-
-int drm_vma_info(struct seq_file *m, void *data)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
- struct drm_vma_entry *pt;
- struct vm_area_struct *vma;
-#if defined(__i386__)
- unsigned int pgprot;
-#endif
-
- mutex_lock(&dev->struct_mutex);
- seq_printf(m, "vma use count: %d, high_memory = %p, 0x%08llx\n",
- atomic_read(&dev->vma_count),
- high_memory, (u64)virt_to_phys(high_memory));
-
- list_for_each_entry(pt, &dev->vmalist, head) {
- vma = pt->vma;
- if (!vma)
- continue;
- seq_printf(m,
- "\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
- pt->pid, vma->vm_start, vma->vm_end,
- vma->vm_flags & VM_READ ? 'r' : '-',
- vma->vm_flags & VM_WRITE ? 'w' : '-',
- vma->vm_flags & VM_EXEC ? 'x' : '-',
- vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
- vma->vm_flags & VM_LOCKED ? 'l' : '-',
- vma->vm_flags & VM_IO ? 'i' : '-',
- vma->vm_pgoff);
-
-#if defined(__i386__)
- pgprot = pgprot_val(vma->vm_page_prot);
- seq_printf(m, " %c%c%c%c%c%c%c%c%c",
- pgprot & _PAGE_PRESENT ? 'p' : '-',
- pgprot & _PAGE_RW ? 'w' : 'r',
- pgprot & _PAGE_USER ? 'u' : 's',
- pgprot & _PAGE_PWT ? 't' : 'b',
- pgprot & _PAGE_PCD ? 'u' : 'c',
- pgprot & _PAGE_ACCESSED ? 'a' : '-',
- pgprot & _PAGE_DIRTY ? 'd' : '-',
- pgprot & _PAGE_PSE ? 'm' : 'k',
- pgprot & _PAGE_GLOBAL ? 'g' : 'l');
-#endif
- seq_printf(m, "\n");
- }
- mutex_unlock(&dev->struct_mutex);
- return 0;
-}
-
-#endif
-
+++ /dev/null
-/**
- * \file drm_ioc32.c
- *
- * 32-bit ioctl compatibility routines for the DRM.
- *
- * \author Paul Mackerras <paulus@samba.org>
- *
- * Copyright (C) Paul Mackerras 2005.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <linux/compat.h>
-
-#include "drmP.h"
-#include "drm_core.h"
-
-#define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t)
-#define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t)
-#define DRM_IOCTL_GET_MAP32 DRM_IOWR(0x04, drm_map32_t)
-#define DRM_IOCTL_GET_CLIENT32 DRM_IOWR(0x05, drm_client32_t)
-#define DRM_IOCTL_GET_STATS32 DRM_IOR( 0x06, drm_stats32_t)
-
-#define DRM_IOCTL_SET_UNIQUE32 DRM_IOW( 0x10, drm_unique32_t)
-#define DRM_IOCTL_ADD_MAP32 DRM_IOWR(0x15, drm_map32_t)
-#define DRM_IOCTL_ADD_BUFS32 DRM_IOWR(0x16, drm_buf_desc32_t)
-#define DRM_IOCTL_MARK_BUFS32 DRM_IOW( 0x17, drm_buf_desc32_t)
-#define DRM_IOCTL_INFO_BUFS32 DRM_IOWR(0x18, drm_buf_info32_t)
-#define DRM_IOCTL_MAP_BUFS32 DRM_IOWR(0x19, drm_buf_map32_t)
-#define DRM_IOCTL_FREE_BUFS32 DRM_IOW( 0x1a, drm_buf_free32_t)
-
-#define DRM_IOCTL_RM_MAP32 DRM_IOW( 0x1b, drm_map32_t)
-
-#define DRM_IOCTL_SET_SAREA_CTX32 DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
-#define DRM_IOCTL_GET_SAREA_CTX32 DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
-
-#define DRM_IOCTL_RES_CTX32 DRM_IOWR(0x26, drm_ctx_res32_t)
-#define DRM_IOCTL_DMA32 DRM_IOWR(0x29, drm_dma32_t)
-
-#define DRM_IOCTL_AGP_ENABLE32 DRM_IOW( 0x32, drm_agp_mode32_t)
-#define DRM_IOCTL_AGP_INFO32 DRM_IOR( 0x33, drm_agp_info32_t)
-#define DRM_IOCTL_AGP_ALLOC32 DRM_IOWR(0x34, drm_agp_buffer32_t)
-#define DRM_IOCTL_AGP_FREE32 DRM_IOW( 0x35, drm_agp_buffer32_t)
-#define DRM_IOCTL_AGP_BIND32 DRM_IOW( 0x36, drm_agp_binding32_t)
-#define DRM_IOCTL_AGP_UNBIND32 DRM_IOW( 0x37, drm_agp_binding32_t)
-
-#define DRM_IOCTL_SG_ALLOC32 DRM_IOW( 0x38, drm_scatter_gather32_t)
-#define DRM_IOCTL_SG_FREE32 DRM_IOW( 0x39, drm_scatter_gather32_t)
-
-#define DRM_IOCTL_UPDATE_DRAW32 DRM_IOW( 0x3f, drm_update_draw32_t)
-
-#define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t)
-
-typedef struct drm_version_32 {
- int version_major; /**< Major version */
- int version_minor; /**< Minor version */
- int version_patchlevel; /**< Patch level */
- u32 name_len; /**< Length of name buffer */
- u32 name; /**< Name of driver */
- u32 date_len; /**< Length of date buffer */
- u32 date; /**< User-space buffer to hold date */
- u32 desc_len; /**< Length of desc buffer */
- u32 desc; /**< User-space buffer to hold desc */
-} drm_version32_t;
-
-static int compat_drm_version(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_version32_t v32;
- struct drm_version __user *version;
- int err;
-
- if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
- return -EFAULT;
-
- version = compat_alloc_user_space(sizeof(*version));
- if (!access_ok(VERIFY_WRITE, version, sizeof(*version)))
- return -EFAULT;
- if (__put_user(v32.name_len, &version->name_len)
- || __put_user((void __user *)(unsigned long)v32.name,
- &version->name)
- || __put_user(v32.date_len, &version->date_len)
- || __put_user((void __user *)(unsigned long)v32.date,
- &version->date)
- || __put_user(v32.desc_len, &version->desc_len)
- || __put_user((void __user *)(unsigned long)v32.desc,
- &version->desc))
- return -EFAULT;
-
- err = drm_ioctl(file,
- DRM_IOCTL_VERSION, (unsigned long)version);
- if (err)
- return err;
-
- if (__get_user(v32.version_major, &version->version_major)
- || __get_user(v32.version_minor, &version->version_minor)
- || __get_user(v32.version_patchlevel, &version->version_patchlevel)
- || __get_user(v32.name_len, &version->name_len)
- || __get_user(v32.date_len, &version->date_len)
- || __get_user(v32.desc_len, &version->desc_len))
- return -EFAULT;
-
- if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
- return -EFAULT;
- return 0;
-}
-
-typedef struct drm_unique32 {
- u32 unique_len; /**< Length of unique */
- u32 unique; /**< Unique name for driver instantiation */
-} drm_unique32_t;
-
-static int compat_drm_getunique(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_unique32_t uq32;
- struct drm_unique __user *u;
- int err;
-
- if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
- return -EFAULT;
-
- u = compat_alloc_user_space(sizeof(*u));
- if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
- return -EFAULT;
- if (__put_user(uq32.unique_len, &u->unique_len)
- || __put_user((void __user *)(unsigned long)uq32.unique,
- &u->unique))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
- if (err)
- return err;
-
- if (__get_user(uq32.unique_len, &u->unique_len))
- return -EFAULT;
- if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
- return -EFAULT;
- return 0;
-}
-
-static int compat_drm_setunique(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_unique32_t uq32;
- struct drm_unique __user *u;
-
- if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
- return -EFAULT;
-
- u = compat_alloc_user_space(sizeof(*u));
- if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
- return -EFAULT;
- if (__put_user(uq32.unique_len, &u->unique_len)
- || __put_user((void __user *)(unsigned long)uq32.unique,
- &u->unique))
- return -EFAULT;
-
- return drm_ioctl(file, DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
-}
-
-typedef struct drm_map32 {
- u32 offset; /**< Requested physical address (0 for SAREA)*/
- u32 size; /**< Requested physical size (bytes) */
- enum drm_map_type type; /**< Type of memory to map */
- enum drm_map_flags flags; /**< Flags */
- u32 handle; /**< User-space: "Handle" to pass to mmap() */
- int mtrr; /**< MTRR slot used */
-} drm_map32_t;
-
-static int compat_drm_getmap(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_map32_t __user *argp = (void __user *)arg;
- drm_map32_t m32;
- struct drm_map __user *map;
- int idx, err;
- void *handle;
-
- if (get_user(idx, &argp->offset))
- return -EFAULT;
-
- map = compat_alloc_user_space(sizeof(*map));
- if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
- return -EFAULT;
- if (__put_user(idx, &map->offset))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_GET_MAP, (unsigned long)map);
- if (err)
- return err;
-
- if (__get_user(m32.offset, &map->offset)
- || __get_user(m32.size, &map->size)
- || __get_user(m32.type, &map->type)
- || __get_user(m32.flags, &map->flags)
- || __get_user(handle, &map->handle)
- || __get_user(m32.mtrr, &map->mtrr))
- return -EFAULT;
-
- m32.handle = (unsigned long)handle;
- if (copy_to_user(argp, &m32, sizeof(m32)))
- return -EFAULT;
- return 0;
-
-}
-
-static int compat_drm_addmap(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_map32_t __user *argp = (void __user *)arg;
- drm_map32_t m32;
- struct drm_map __user *map;
- int err;
- void *handle;
-
- if (copy_from_user(&m32, argp, sizeof(m32)))
- return -EFAULT;
-
- map = compat_alloc_user_space(sizeof(*map));
- if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
- return -EFAULT;
- if (__put_user(m32.offset, &map->offset)
- || __put_user(m32.size, &map->size)
- || __put_user(m32.type, &map->type)
- || __put_user(m32.flags, &map->flags))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_ADD_MAP, (unsigned long)map);
- if (err)
- return err;
-
- if (__get_user(m32.offset, &map->offset)
- || __get_user(m32.mtrr, &map->mtrr)
- || __get_user(handle, &map->handle))
- return -EFAULT;
-
- m32.handle = (unsigned long)handle;
- if (m32.handle != (unsigned long)handle && printk_ratelimit())
- printk(KERN_ERR "compat_drm_addmap truncated handle"
- " %p for type %d offset %x\n",
- handle, m32.type, m32.offset);
-
- if (copy_to_user(argp, &m32, sizeof(m32)))
- return -EFAULT;
-
- return 0;
-}
-
-static int compat_drm_rmmap(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_map32_t __user *argp = (void __user *)arg;
- struct drm_map __user *map;
- u32 handle;
-
- if (get_user(handle, &argp->handle))
- return -EFAULT;
-
- map = compat_alloc_user_space(sizeof(*map));
- if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
- return -EFAULT;
- if (__put_user((void *)(unsigned long)handle, &map->handle))
- return -EFAULT;
-
- return drm_ioctl(file, DRM_IOCTL_RM_MAP, (unsigned long)map);
-}
-
-typedef struct drm_client32 {
- int idx; /**< Which client desired? */
- int auth; /**< Is client authenticated? */
- u32 pid; /**< Process ID */
- u32 uid; /**< User ID */
- u32 magic; /**< Magic */
- u32 iocs; /**< Ioctl count */
-} drm_client32_t;
-
-static int compat_drm_getclient(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_client32_t c32;
- drm_client32_t __user *argp = (void __user *)arg;
- struct drm_client __user *client;
- int idx, err;
-
- if (get_user(idx, &argp->idx))
- return -EFAULT;
-
- client = compat_alloc_user_space(sizeof(*client));
- if (!access_ok(VERIFY_WRITE, client, sizeof(*client)))
- return -EFAULT;
- if (__put_user(idx, &client->idx))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, (unsigned long)client);
- if (err)
- return err;
-
- if (__get_user(c32.auth, &client->auth)
- || __get_user(c32.pid, &client->pid)
- || __get_user(c32.uid, &client->uid)
- || __get_user(c32.magic, &client->magic)
- || __get_user(c32.iocs, &client->iocs))
- return -EFAULT;
-
- if (copy_to_user(argp, &c32, sizeof(c32)))
- return -EFAULT;
- return 0;
-}
-
-typedef struct drm_stats32 {
- u32 count;
- struct {
- u32 value;
- enum drm_stat_type type;
- } data[15];
-} drm_stats32_t;
-
-static int compat_drm_getstats(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_stats32_t s32;
- drm_stats32_t __user *argp = (void __user *)arg;
- struct drm_stats __user *stats;
- int i, err;
-
- stats = compat_alloc_user_space(sizeof(*stats));
- if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_GET_STATS, (unsigned long)stats);
- if (err)
- return err;
-
- if (__get_user(s32.count, &stats->count))
- return -EFAULT;
- for (i = 0; i < 15; ++i)
- if (__get_user(s32.data[i].value, &stats->data[i].value)
- || __get_user(s32.data[i].type, &stats->data[i].type))
- return -EFAULT;
-
- if (copy_to_user(argp, &s32, sizeof(s32)))
- return -EFAULT;
- return 0;
-}
-
-typedef struct drm_buf_desc32 {
- int count; /**< Number of buffers of this size */
- int size; /**< Size in bytes */
- int low_mark; /**< Low water mark */
- int high_mark; /**< High water mark */
- int flags;
- u32 agp_start; /**< Start address in the AGP aperture */
-} drm_buf_desc32_t;
-
-static int compat_drm_addbufs(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_buf_desc32_t __user *argp = (void __user *)arg;
- struct drm_buf_desc __user *buf;
- int err;
- unsigned long agp_start;
-
- buf = compat_alloc_user_space(sizeof(*buf));
- if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf))
- || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)))
- return -EFAULT;
-
- if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start))
- || __get_user(agp_start, &argp->agp_start)
- || __put_user(agp_start, &buf->agp_start))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
- if (err)
- return err;
-
- if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start))
- || __get_user(agp_start, &buf->agp_start)
- || __put_user(agp_start, &argp->agp_start))
- return -EFAULT;
-
- return 0;
-}
-
-static int compat_drm_markbufs(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_buf_desc32_t b32;
- drm_buf_desc32_t __user *argp = (void __user *)arg;
- struct drm_buf_desc __user *buf;
-
- if (copy_from_user(&b32, argp, sizeof(b32)))
- return -EFAULT;
-
- buf = compat_alloc_user_space(sizeof(*buf));
- if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)))
- return -EFAULT;
-
- if (__put_user(b32.size, &buf->size)
- || __put_user(b32.low_mark, &buf->low_mark)
- || __put_user(b32.high_mark, &buf->high_mark))
- return -EFAULT;
-
- return drm_ioctl(file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
-}
-
-typedef struct drm_buf_info32 {
- int count; /**< Entries in list */
- u32 list;
-} drm_buf_info32_t;
-
-static int compat_drm_infobufs(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_buf_info32_t req32;
- drm_buf_info32_t __user *argp = (void __user *)arg;
- drm_buf_desc32_t __user *to;
- struct drm_buf_info __user *request;
- struct drm_buf_desc __user *list;
- size_t nbytes;
- int i, err;
- int count, actual;
-
- if (copy_from_user(&req32, argp, sizeof(req32)))
- return -EFAULT;
-
- count = req32.count;
- to = (drm_buf_desc32_t __user *) (unsigned long)req32.list;
- if (count < 0)
- count = 0;
- if (count > 0
- && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
- return -EFAULT;
-
- nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
- request = compat_alloc_user_space(nbytes);
- if (!access_ok(VERIFY_WRITE, request, nbytes))
- return -EFAULT;
- list = (struct drm_buf_desc *) (request + 1);
-
- if (__put_user(count, &request->count)
- || __put_user(list, &request->list))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_INFO_BUFS, (unsigned long)request);
- if (err)
- return err;
-
- if (__get_user(actual, &request->count))
- return -EFAULT;
- if (count >= actual)
- for (i = 0; i < actual; ++i)
- if (__copy_in_user(&to[i], &list[i],
- offsetof(struct drm_buf_desc, flags)))
- return -EFAULT;
-
- if (__put_user(actual, &argp->count))
- return -EFAULT;
-
- return 0;
-}
-
-typedef struct drm_buf_pub32 {
- int idx; /**< Index into the master buffer list */
- int total; /**< Buffer size */
- int used; /**< Amount of buffer in use (for DMA) */
- u32 address; /**< Address of buffer */
-} drm_buf_pub32_t;
-
-typedef struct drm_buf_map32 {
- int count; /**< Length of the buffer list */
- u32 virtual; /**< Mmap'd area in user-virtual */
- u32 list; /**< Buffer information */
-} drm_buf_map32_t;
-
-static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_buf_map32_t __user *argp = (void __user *)arg;
- drm_buf_map32_t req32;
- drm_buf_pub32_t __user *list32;
- struct drm_buf_map __user *request;
- struct drm_buf_pub __user *list;
- int i, err;
- int count, actual;
- size_t nbytes;
- void __user *addr;
-
- if (copy_from_user(&req32, argp, sizeof(req32)))
- return -EFAULT;
- count = req32.count;
- list32 = (void __user *)(unsigned long)req32.list;
-
- if (count < 0)
- return -EINVAL;
- nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
- request = compat_alloc_user_space(nbytes);
- if (!access_ok(VERIFY_WRITE, request, nbytes))
- return -EFAULT;
- list = (struct drm_buf_pub *) (request + 1);
-
- if (__put_user(count, &request->count)
- || __put_user(list, &request->list))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_MAP_BUFS, (unsigned long)request);
- if (err)
- return err;
-
- if (__get_user(actual, &request->count))
- return -EFAULT;
- if (count >= actual)
- for (i = 0; i < actual; ++i)
- if (__copy_in_user(&list32[i], &list[i],
- offsetof(struct drm_buf_pub, address))
- || __get_user(addr, &list[i].address)
- || __put_user((unsigned long)addr,
- &list32[i].address))
- return -EFAULT;
-
- if (__put_user(actual, &argp->count)
- || __get_user(addr, &request->virtual)
- || __put_user((unsigned long)addr, &argp->virtual))
- return -EFAULT;
-
- return 0;
-}
-
-typedef struct drm_buf_free32 {
- int count;
- u32 list;
-} drm_buf_free32_t;
-
-static int compat_drm_freebufs(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_buf_free32_t req32;
- struct drm_buf_free __user *request;
- drm_buf_free32_t __user *argp = (void __user *)arg;
-
- if (copy_from_user(&req32, argp, sizeof(req32)))
- return -EFAULT;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
- return -EFAULT;
- if (__put_user(req32.count, &request->count)
- || __put_user((int __user *)(unsigned long)req32.list,
- &request->list))
- return -EFAULT;
-
- return drm_ioctl(file, DRM_IOCTL_FREE_BUFS, (unsigned long)request);
-}
-
-typedef struct drm_ctx_priv_map32 {
- unsigned int ctx_id; /**< Context requesting private mapping */
- u32 handle; /**< Handle of map */
-} drm_ctx_priv_map32_t;
-
-static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_ctx_priv_map32_t req32;
- struct drm_ctx_priv_map __user *request;
- drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
-
- if (copy_from_user(&req32, argp, sizeof(req32)))
- return -EFAULT;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
- return -EFAULT;
- if (__put_user(req32.ctx_id, &request->ctx_id)
- || __put_user((void *)(unsigned long)req32.handle,
- &request->handle))
- return -EFAULT;
-
- return drm_ioctl(file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
-}
-
-static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct drm_ctx_priv_map __user *request;
- drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
- int err;
- unsigned int ctx_id;
- void *handle;
-
- if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp))
- || __get_user(ctx_id, &argp->ctx_id))
- return -EFAULT;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
- return -EFAULT;
- if (__put_user(ctx_id, &request->ctx_id))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
- if (err)
- return err;
-
- if (__get_user(handle, &request->handle)
- || __put_user((unsigned long)handle, &argp->handle))
- return -EFAULT;
-
- return 0;
-}
-
-typedef struct drm_ctx_res32 {
- int count;
- u32 contexts;
-} drm_ctx_res32_t;
-
-static int compat_drm_resctx(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_ctx_res32_t __user *argp = (void __user *)arg;
- drm_ctx_res32_t res32;
- struct drm_ctx_res __user *res;
- int err;
-
- if (copy_from_user(&res32, argp, sizeof(res32)))
- return -EFAULT;
-
- res = compat_alloc_user_space(sizeof(*res));
- if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
- return -EFAULT;
- if (__put_user(res32.count, &res->count)
- || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts,
- &res->contexts))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_RES_CTX, (unsigned long)res);
- if (err)
- return err;
-
- if (__get_user(res32.count, &res->count)
- || __put_user(res32.count, &argp->count))
- return -EFAULT;
-
- return 0;
-}
-
-typedef struct drm_dma32 {
- int context; /**< Context handle */
- int send_count; /**< Number of buffers to send */
- u32 send_indices; /**< List of handles to buffers */
- u32 send_sizes; /**< Lengths of data to send */
- enum drm_dma_flags flags; /**< Flags */
- int request_count; /**< Number of buffers requested */
- int request_size; /**< Desired size for buffers */
- u32 request_indices; /**< Buffer information */
- u32 request_sizes;
- int granted_count; /**< Number of buffers granted */
-} drm_dma32_t;
-
-static int compat_drm_dma(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_dma32_t d32;
- drm_dma32_t __user *argp = (void __user *)arg;
- struct drm_dma __user *d;
- int err;
-
- if (copy_from_user(&d32, argp, sizeof(d32)))
- return -EFAULT;
-
- d = compat_alloc_user_space(sizeof(*d));
- if (!access_ok(VERIFY_WRITE, d, sizeof(*d)))
- return -EFAULT;
-
- if (__put_user(d32.context, &d->context)
- || __put_user(d32.send_count, &d->send_count)
- || __put_user((int __user *)(unsigned long)d32.send_indices,
- &d->send_indices)
- || __put_user((int __user *)(unsigned long)d32.send_sizes,
- &d->send_sizes)
- || __put_user(d32.flags, &d->flags)
- || __put_user(d32.request_count, &d->request_count)
- || __put_user((int __user *)(unsigned long)d32.request_indices,
- &d->request_indices)
- || __put_user((int __user *)(unsigned long)d32.request_sizes,
- &d->request_sizes))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_DMA, (unsigned long)d);
- if (err)
- return err;
-
- if (__get_user(d32.request_size, &d->request_size)
- || __get_user(d32.granted_count, &d->granted_count)
- || __put_user(d32.request_size, &argp->request_size)
- || __put_user(d32.granted_count, &argp->granted_count))
- return -EFAULT;
-
- return 0;
-}
-
-#if __OS_HAS_AGP
-typedef struct drm_agp_mode32 {
- u32 mode; /**< AGP mode */
-} drm_agp_mode32_t;
-
-static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_agp_mode32_t __user *argp = (void __user *)arg;
- drm_agp_mode32_t m32;
- struct drm_agp_mode __user *mode;
-
- if (get_user(m32.mode, &argp->mode))
- return -EFAULT;
-
- mode = compat_alloc_user_space(sizeof(*mode));
- if (put_user(m32.mode, &mode->mode))
- return -EFAULT;
-
- return drm_ioctl(file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
-}
-
-typedef struct drm_agp_info32 {
- int agp_version_major;
- int agp_version_minor;
- u32 mode;
- u32 aperture_base; /* physical address */
- u32 aperture_size; /* bytes */
- u32 memory_allowed; /* bytes */
- u32 memory_used;
-
- /* PCI information */
- unsigned short id_vendor;
- unsigned short id_device;
-} drm_agp_info32_t;
-
-static int compat_drm_agp_info(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_agp_info32_t __user *argp = (void __user *)arg;
- drm_agp_info32_t i32;
- struct drm_agp_info __user *info;
- int err;
-
- info = compat_alloc_user_space(sizeof(*info));
- if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_AGP_INFO, (unsigned long)info);
- if (err)
- return err;
-
- if (__get_user(i32.agp_version_major, &info->agp_version_major)
- || __get_user(i32.agp_version_minor, &info->agp_version_minor)
- || __get_user(i32.mode, &info->mode)
- || __get_user(i32.aperture_base, &info->aperture_base)
- || __get_user(i32.aperture_size, &info->aperture_size)
- || __get_user(i32.memory_allowed, &info->memory_allowed)
- || __get_user(i32.memory_used, &info->memory_used)
- || __get_user(i32.id_vendor, &info->id_vendor)
- || __get_user(i32.id_device, &info->id_device))
- return -EFAULT;
-
- if (copy_to_user(argp, &i32, sizeof(i32)))
- return -EFAULT;
-
- return 0;
-}
-
-typedef struct drm_agp_buffer32 {
- u32 size; /**< In bytes -- will round to page boundary */
- u32 handle; /**< Used for binding / unbinding */
- u32 type; /**< Type of memory to allocate */
- u32 physical; /**< Physical used by i810 */
-} drm_agp_buffer32_t;
-
-static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_agp_buffer32_t __user *argp = (void __user *)arg;
- drm_agp_buffer32_t req32;
- struct drm_agp_buffer __user *request;
- int err;
-
- if (copy_from_user(&req32, argp, sizeof(req32)))
- return -EFAULT;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
- || __put_user(req32.size, &request->size)
- || __put_user(req32.type, &request->type))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
- if (err)
- return err;
-
- if (__get_user(req32.handle, &request->handle)
- || __get_user(req32.physical, &request->physical)
- || copy_to_user(argp, &req32, sizeof(req32))) {
- drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int compat_drm_agp_free(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_agp_buffer32_t __user *argp = (void __user *)arg;
- struct drm_agp_buffer __user *request;
- u32 handle;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
- || get_user(handle, &argp->handle)
- || __put_user(handle, &request->handle))
- return -EFAULT;
-
- return drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
-}
-
-typedef struct drm_agp_binding32 {
- u32 handle; /**< From drm_agp_buffer */
- u32 offset; /**< In bytes -- will round to page boundary */
-} drm_agp_binding32_t;
-
-static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_agp_binding32_t __user *argp = (void __user *)arg;
- drm_agp_binding32_t req32;
- struct drm_agp_binding __user *request;
-
- if (copy_from_user(&req32, argp, sizeof(req32)))
- return -EFAULT;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
- || __put_user(req32.handle, &request->handle)
- || __put_user(req32.offset, &request->offset))
- return -EFAULT;
-
- return drm_ioctl(file, DRM_IOCTL_AGP_BIND, (unsigned long)request);
-}
-
-static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_agp_binding32_t __user *argp = (void __user *)arg;
- struct drm_agp_binding __user *request;
- u32 handle;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
- || get_user(handle, &argp->handle)
- || __put_user(handle, &request->handle))
- return -EFAULT;
-
- return drm_ioctl(file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
-}
-#endif /* __OS_HAS_AGP */
-
-typedef struct drm_scatter_gather32 {
- u32 size; /**< In bytes -- will round to page boundary */
- u32 handle; /**< Used for mapping / unmapping */
-} drm_scatter_gather32_t;
-
-static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_scatter_gather32_t __user *argp = (void __user *)arg;
- struct drm_scatter_gather __user *request;
- int err;
- unsigned long x;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
- || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
- || __get_user(x, &argp->size)
- || __put_user(x, &request->size))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_SG_ALLOC, (unsigned long)request);
- if (err)
- return err;
-
- /* XXX not sure about the handle conversion here... */
- if (__get_user(x, &request->handle)
- || __put_user(x >> PAGE_SHIFT, &argp->handle))
- return -EFAULT;
-
- return 0;
-}
-
-static int compat_drm_sg_free(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_scatter_gather32_t __user *argp = (void __user *)arg;
- struct drm_scatter_gather __user *request;
- unsigned long x;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
- || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
- || __get_user(x, &argp->handle)
- || __put_user(x << PAGE_SHIFT, &request->handle))
- return -EFAULT;
-
- return drm_ioctl(file, DRM_IOCTL_SG_FREE, (unsigned long)request);
-}
-
-#if defined(CONFIG_X86) || defined(CONFIG_IA64)
-typedef struct drm_update_draw32 {
- drm_drawable_t handle;
- unsigned int type;
- unsigned int num;
- /* 64-bit version has a 32-bit pad here */
- u64 data; /**< Pointer */
-} __attribute__((packed)) drm_update_draw32_t;
-
-static int compat_drm_update_draw(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_update_draw32_t update32;
- struct drm_update_draw __user *request;
- int err;
-
- if (copy_from_user(&update32, (void __user *)arg, sizeof(update32)))
- return -EFAULT;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) ||
- __put_user(update32.handle, &request->handle) ||
- __put_user(update32.type, &request->type) ||
- __put_user(update32.num, &request->num) ||
- __put_user(update32.data, &request->data))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_UPDATE_DRAW, (unsigned long)request);
- return err;
-}
-#endif
-
-struct drm_wait_vblank_request32 {
- enum drm_vblank_seq_type type;
- unsigned int sequence;
- u32 signal;
-};
-
-struct drm_wait_vblank_reply32 {
- enum drm_vblank_seq_type type;
- unsigned int sequence;
- s32 tval_sec;
- s32 tval_usec;
-};
-
-typedef union drm_wait_vblank32 {
- struct drm_wait_vblank_request32 request;
- struct drm_wait_vblank_reply32 reply;
-} drm_wait_vblank32_t;
-
-static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- drm_wait_vblank32_t __user *argp = (void __user *)arg;
- drm_wait_vblank32_t req32;
- union drm_wait_vblank __user *request;
- int err;
-
- if (copy_from_user(&req32, argp, sizeof(req32)))
- return -EFAULT;
-
- request = compat_alloc_user_space(sizeof(*request));
- if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
- || __put_user(req32.request.type, &request->request.type)
- || __put_user(req32.request.sequence, &request->request.sequence)
- || __put_user(req32.request.signal, &request->request.signal))
- return -EFAULT;
-
- err = drm_ioctl(file, DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
- if (err)
- return err;
-
- if (__get_user(req32.reply.type, &request->reply.type)
- || __get_user(req32.reply.sequence, &request->reply.sequence)
- || __get_user(req32.reply.tval_sec, &request->reply.tval_sec)
- || __get_user(req32.reply.tval_usec, &request->reply.tval_usec))
- return -EFAULT;
-
- if (copy_to_user(argp, &req32, sizeof(req32)))
- return -EFAULT;
-
- return 0;
-}
-
-drm_ioctl_compat_t *drm_compat_ioctls[] = {
- [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
- [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
- [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap,
- [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient,
- [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats,
- [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique,
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap,
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs,
- [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs,
- [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs,
- [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs,
- [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs,
- [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap,
- [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx,
- [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx,
- [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx,
- [DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma,
-#if __OS_HAS_AGP
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable,
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info,
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc,
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free,
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind,
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind,
-#endif
- [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
- [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
-#if defined(CONFIG_X86) || defined(CONFIG_IA64)
- [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw,
-#endif
- [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
-};
-
-/**
- * Called whenever a 32-bit process running under a 64-bit kernel
- * performs an ioctl on /dev/drm.
- *
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
- */
-long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- unsigned int nr = DRM_IOCTL_NR(cmd);
- drm_ioctl_compat_t *fn;
- int ret;
-
- /* Assume that ioctls without an explicit compat routine will just
- * work. This may not always be a good assumption, but it's better
- * than always failing.
- */
- if (nr >= ARRAY_SIZE(drm_compat_ioctls))
- return drm_ioctl(filp, cmd, arg);
-
- fn = drm_compat_ioctls[nr];
-
- if (fn != NULL)
- ret = (*fn) (filp, cmd, arg);
- else
- ret = drm_ioctl(filp, cmd, arg);
-
- return ret;
-}
-
-EXPORT_SYMBOL(drm_compat_ioctl);
+++ /dev/null
-/**
- * \file drm_ioctl.c
- * IOCTL processing for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm_core.h"
-
-#include "linux/pci.h"
-
-/**
- * Get the bus id.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_unique structure.
- * \return zero on success or a negative number on failure.
- *
- * Copies the bus id from drm_device::unique into user space.
- */
-int drm_getunique(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_unique *u = data;
- struct drm_master *master = file_priv->master;
-
- if (u->unique_len >= master->unique_len) {
- if (copy_to_user(u->unique, master->unique, master->unique_len))
- return -EFAULT;
- }
- u->unique_len = master->unique_len;
-
- return 0;
-}
-
-static void
-drm_unset_busid(struct drm_device *dev,
- struct drm_master *master)
-{
- kfree(dev->devname);
- dev->devname = NULL;
-
- kfree(master->unique);
- master->unique = NULL;
- master->unique_len = 0;
- master->unique_size = 0;
-}
-
-/**
- * Set the bus id.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_unique structure.
- * \return zero on success or a negative number on failure.
- *
- * Copies the bus id from userspace into drm_device::unique, and verifies that
- * it matches the device this DRM is attached to (EINVAL otherwise). Deprecated
- * in interface version 1.1 and will return EBUSY when setversion has requested
- * version 1.1 or greater.
- */
-int drm_setunique(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_unique *u = data;
- struct drm_master *master = file_priv->master;
- int domain, bus, slot, func, ret;
-
- if (master->unique_len || master->unique)
- return -EBUSY;
-
- if (!u->unique_len || u->unique_len > 1024)
- return -EINVAL;
-
- master->unique_len = u->unique_len;
- master->unique_size = u->unique_len + 1;
- master->unique = kmalloc(master->unique_size, GFP_KERNEL);
- if (!master->unique) {
- ret = -ENOMEM;
- goto err;
- }
-
- if (copy_from_user(master->unique, u->unique, master->unique_len)) {
- ret = -EFAULT;
- goto err;
- }
-
- master->unique[master->unique_len] = '\0';
-
- dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
- strlen(master->unique) + 2, GFP_KERNEL);
- if (!dev->devname) {
- ret = -ENOMEM;
- goto err;
- }
-
- sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
- master->unique);
-
- /* Return error if the busid submitted doesn't match the device's actual
- * busid.
- */
- ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
- if (ret != 3) {
- ret = -EINVAL;
- goto err;
- }
-
- domain = bus >> 8;
- bus &= 0xff;
-
- if ((domain != drm_get_pci_domain(dev)) ||
- (bus != dev->pdev->bus->number) ||
- (slot != PCI_SLOT(dev->pdev->devfn)) ||
- (func != PCI_FUNC(dev->pdev->devfn))) {
- ret = -EINVAL;
- goto err;
- }
-
- return 0;
-
-err:
- drm_unset_busid(dev, master);
- return ret;
-}
-
-static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
-{
- struct drm_master *master = file_priv->master;
- int len, ret;
-
- if (master->unique != NULL)
- drm_unset_busid(dev, master);
-
- if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
- master->unique_len = 10 + strlen(dev->platformdev->name);
- master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
-
- if (master->unique == NULL)
- return -ENOMEM;
-
- len = snprintf(master->unique, master->unique_len,
- "platform:%s", dev->platformdev->name);
-
- if (len > master->unique_len) {
- DRM_ERROR("Unique buffer overflowed\n");
- ret = -EINVAL;
- goto err;
- }
-
- dev->devname =
- kmalloc(strlen(dev->platformdev->name) +
- master->unique_len + 2, GFP_KERNEL);
-
- if (dev->devname == NULL) {
- ret = -ENOMEM;
- goto err;
- }
-
- sprintf(dev->devname, "%s@%s", dev->platformdev->name,
- master->unique);
-
- } else {
- master->unique_len = 40;
- master->unique_size = master->unique_len;
- master->unique = kmalloc(master->unique_size, GFP_KERNEL);
- if (master->unique == NULL)
- return -ENOMEM;
-
- len = snprintf(master->unique, master->unique_len,
- "pci:%04x:%02x:%02x.%d",
- drm_get_pci_domain(dev),
- dev->pdev->bus->number,
- PCI_SLOT(dev->pdev->devfn),
- PCI_FUNC(dev->pdev->devfn));
- if (len >= master->unique_len) {
- DRM_ERROR("buffer overflow");
- ret = -EINVAL;
- goto err;
- } else
- master->unique_len = len;
-
- dev->devname =
- kmalloc(strlen(dev->driver->pci_driver.name) +
- master->unique_len + 2, GFP_KERNEL);
-
- if (dev->devname == NULL) {
- ret = -ENOMEM;
- goto err;
- }
-
- sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
- master->unique);
- }
-
- return 0;
-
-err:
- drm_unset_busid(dev, master);
- return ret;
-}
-
-/**
- * Get a mapping information.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_map structure.
- *
- * \return zero on success or a negative number on failure.
- *
- * Searches for the mapping with the specified offset and copies its information
- * into userspace
- */
-int drm_getmap(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_map *map = data;
- struct drm_map_list *r_list = NULL;
- struct list_head *list;
- int idx;
- int i;
-
- idx = map->offset;
-
- mutex_lock(&dev->struct_mutex);
- if (idx < 0) {
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
- }
-
- i = 0;
- list_for_each(list, &dev->maplist) {
- if (i == idx) {
- r_list = list_entry(list, struct drm_map_list, head);
- break;
- }
- i++;
- }
- if (!r_list || !r_list->map) {
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
- }
-
- map->offset = r_list->map->offset;
- map->size = r_list->map->size;
- map->type = r_list->map->type;
- map->flags = r_list->map->flags;
- map->handle = (void *)(unsigned long) r_list->user_token;
- map->mtrr = r_list->map->mtrr;
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
-/**
- * Get client information.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_client structure.
- *
- * \return zero on success or a negative number on failure.
- *
- * Searches for the client with the specified index and copies its information
- * into userspace
- */
-int drm_getclient(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_client *client = data;
- struct drm_file *pt;
- int idx;
- int i;
-
- idx = client->idx;
- mutex_lock(&dev->struct_mutex);
-
- i = 0;
- list_for_each_entry(pt, &dev->filelist, lhead) {
- if (i++ >= idx) {
- client->auth = pt->authenticated;
- client->pid = pt->pid;
- client->uid = pt->uid;
- client->magic = pt->magic;
- client->iocs = pt->ioctl_count;
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
- }
- }
- mutex_unlock(&dev->struct_mutex);
-
- return -EINVAL;
-}
-
-/**
- * Get statistics information.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_stats structure.
- *
- * \return zero on success or a negative number on failure.
- */
-int drm_getstats(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_stats *stats = data;
- int i;
-
- memset(stats, 0, sizeof(*stats));
-
- mutex_lock(&dev->struct_mutex);
-
- for (i = 0; i < dev->counters; i++) {
- if (dev->types[i] == _DRM_STAT_LOCK)
- stats->data[i].value =
- (file_priv->master->lock.hw_lock ? file_priv->master->lock.hw_lock->lock : 0);
- else
- stats->data[i].value = atomic_read(&dev->counts[i]);
- stats->data[i].type = dev->types[i];
- }
-
- stats->count = dev->counters;
-
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
-/**
- * Setversion ioctl.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_lock structure.
- * \return zero on success or negative number on failure.
- *
- * Sets the requested interface version
- */
-int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- struct drm_set_version *sv = data;
- int if_version, retcode = 0;
-
- if (sv->drm_di_major != -1) {
- if (sv->drm_di_major != DRM_IF_MAJOR ||
- sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) {
- retcode = -EINVAL;
- goto done;
- }
- if_version = DRM_IF_VERSION(sv->drm_di_major,
- sv->drm_di_minor);
- dev->if_version = max(if_version, dev->if_version);
- if (sv->drm_di_minor >= 1) {
- /*
- * Version 1.1 includes tying of DRM to specific device
- * Version 1.4 has proper PCI domain support
- */
- retcode = drm_set_busid(dev, file_priv);
- if (retcode)
- goto done;
- }
- }
-
- if (sv->drm_dd_major != -1) {
- if (sv->drm_dd_major != dev->driver->major ||
- sv->drm_dd_minor < 0 || sv->drm_dd_minor >
- dev->driver->minor) {
- retcode = -EINVAL;
- goto done;
- }
-
- if (dev->driver->set_version)
- dev->driver->set_version(dev, sv);
- }
-
-done:
- sv->drm_di_major = DRM_IF_MAJOR;
- sv->drm_di_minor = DRM_IF_MINOR;
- sv->drm_dd_major = dev->driver->major;
- sv->drm_dd_minor = dev->driver->minor;
-
- return retcode;
-}
-
-/** No-op ioctl. */
-int drm_noop(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- DRM_DEBUG("\n");
- return 0;
-}
+++ /dev/null
-/**
- * \file drm_irq.c
- * IRQ support
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm_trace.h"
-
-#include <linux/interrupt.h> /* For task queue support */
-#include <linux/slab.h>
-
-#include <linux/vgaarb.h>
-/**
- * Get interrupt from bus id.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_irq_busid structure.
- * \return zero on success or a negative number on failure.
- *
- * Finds the PCI device with the specified bus id and gets its IRQ number.
- * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
- * to that of the device that this DRM instance attached to.
- */
-int drm_irq_by_busid(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_irq_busid *p = data;
-
- if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
- return -EINVAL;
-
- if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
- return -EINVAL;
-
- if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
- (p->busnum & 0xff) != dev->pdev->bus->number ||
- p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
- return -EINVAL;
-
- p->irq = dev->pdev->irq;
-
- DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
- p->irq);
-
- return 0;
-}
-
-static void vblank_disable_fn(unsigned long arg)
-{
- struct drm_device *dev = (struct drm_device *)arg;
- unsigned long irqflags;
- int i;
-
- if (!dev->vblank_disable_allowed)
- return;
-
- for (i = 0; i < dev->num_crtcs; i++) {
- spin_lock_irqsave(&dev->vbl_lock, irqflags);
- if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
- dev->vblank_enabled[i]) {
- DRM_DEBUG("disabling vblank on crtc %d\n", i);
- dev->last_vblank[i] =
- dev->driver->get_vblank_counter(dev, i);
- dev->driver->disable_vblank(dev, i);
- dev->vblank_enabled[i] = 0;
- }
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
- }
-}
-
-void drm_vblank_cleanup(struct drm_device *dev)
-{
- /* Bail if the driver didn't call drm_vblank_init() */
- if (dev->num_crtcs == 0)
- return;
-
- del_timer(&dev->vblank_disable_timer);
-
- vblank_disable_fn((unsigned long)dev);
-
- kfree(dev->vbl_queue);
- kfree(dev->_vblank_count);
- kfree(dev->vblank_refcount);
- kfree(dev->vblank_enabled);
- kfree(dev->last_vblank);
- kfree(dev->last_vblank_wait);
- kfree(dev->vblank_inmodeset);
-
- dev->num_crtcs = 0;
-}
-EXPORT_SYMBOL(drm_vblank_cleanup);
-
-int drm_vblank_init(struct drm_device *dev, int num_crtcs)
-{
- int i, ret = -ENOMEM;
-
- setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
- (unsigned long)dev);
- spin_lock_init(&dev->vbl_lock);
- dev->num_crtcs = num_crtcs;
-
- dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs,
- GFP_KERNEL);
- if (!dev->vbl_queue)
- goto err;
-
- dev->_vblank_count = kmalloc(sizeof(atomic_t) * num_crtcs, GFP_KERNEL);
- if (!dev->_vblank_count)
- goto err;
-
- dev->vblank_refcount = kmalloc(sizeof(atomic_t) * num_crtcs,
- GFP_KERNEL);
- if (!dev->vblank_refcount)
- goto err;
-
- dev->vblank_enabled = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL);
- if (!dev->vblank_enabled)
- goto err;
-
- dev->last_vblank = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL);
- if (!dev->last_vblank)
- goto err;
-
- dev->last_vblank_wait = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL);
- if (!dev->last_vblank_wait)
- goto err;
-
- dev->vblank_inmodeset = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL);
- if (!dev->vblank_inmodeset)
- goto err;
-
- /* Zero per-crtc vblank stuff */
- for (i = 0; i < num_crtcs; i++) {
- init_waitqueue_head(&dev->vbl_queue[i]);
- atomic_set(&dev->_vblank_count[i], 0);
- atomic_set(&dev->vblank_refcount[i], 0);
- }
-
- dev->vblank_disable_allowed = 0;
- return 0;
-
-err:
- drm_vblank_cleanup(dev);
- return ret;
-}
-EXPORT_SYMBOL(drm_vblank_init);
-
-static void drm_irq_vgaarb_nokms(void *cookie, bool state)
-{
- struct drm_device *dev = cookie;
-
- if (dev->driver->vgaarb_irq) {
- dev->driver->vgaarb_irq(dev, state);
- return;
- }
-
- if (!dev->irq_enabled)
- return;
-
- if (state)
- dev->driver->irq_uninstall(dev);
- else {
- dev->driver->irq_preinstall(dev);
- dev->driver->irq_postinstall(dev);
- }
-}
-
-/**
- * Install IRQ handler.
- *
- * \param dev DRM device.
- *
- * Initializes the IRQ related data. Installs the handler, calling the driver
- * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
- * before and after the installation.
- */
-int drm_irq_install(struct drm_device *dev)
-{
- int ret = 0;
- unsigned long sh_flags = 0;
- char *irqname;
-
- if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
- return -EINVAL;
-
- if (drm_dev_to_irq(dev) == 0)
- return -EINVAL;
-
- mutex_lock(&dev->struct_mutex);
-
- /* Driver must have been initialized */
- if (!dev->dev_private) {
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
- }
-
- if (dev->irq_enabled) {
- mutex_unlock(&dev->struct_mutex);
- return -EBUSY;
- }
- dev->irq_enabled = 1;
- mutex_unlock(&dev->struct_mutex);
-
- DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
-
- /* Before installing handler */
- dev->driver->irq_preinstall(dev);
-
- /* Install handler */
- if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
- sh_flags = IRQF_SHARED;
-
- if (dev->devname)
- irqname = dev->devname;
- else
- irqname = dev->driver->name;
-
- ret = request_irq(drm_dev_to_irq(dev), dev->driver->irq_handler,
- sh_flags, irqname, dev);
-
- if (ret < 0) {
- mutex_lock(&dev->struct_mutex);
- dev->irq_enabled = 0;
- mutex_unlock(&dev->struct_mutex);
- return ret;
- }
-
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- vga_client_register(dev->pdev, (void *)dev, drm_irq_vgaarb_nokms, NULL);
-
- /* After installing handler */
- ret = dev->driver->irq_postinstall(dev);
- if (ret < 0) {
- mutex_lock(&dev->struct_mutex);
- dev->irq_enabled = 0;
- mutex_unlock(&dev->struct_mutex);
- }
-
- return ret;
-}
-EXPORT_SYMBOL(drm_irq_install);
-
-/**
- * Uninstall the IRQ handler.
- *
- * \param dev DRM device.
- *
- * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
- */
-int drm_irq_uninstall(struct drm_device * dev)
-{
- unsigned long irqflags;
- int irq_enabled, i;
-
- if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
- return -EINVAL;
-
- mutex_lock(&dev->struct_mutex);
- irq_enabled = dev->irq_enabled;
- dev->irq_enabled = 0;
- mutex_unlock(&dev->struct_mutex);
-
- /*
- * Wake up any waiters so they don't hang.
- */
- spin_lock_irqsave(&dev->vbl_lock, irqflags);
- for (i = 0; i < dev->num_crtcs; i++) {
- DRM_WAKEUP(&dev->vbl_queue[i]);
- dev->vblank_enabled[i] = 0;
- dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i);
- }
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-
- if (!irq_enabled)
- return -EINVAL;
-
- DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
-
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- vga_client_register(dev->pdev, NULL, NULL, NULL);
-
- dev->driver->irq_uninstall(dev);
-
- free_irq(drm_dev_to_irq(dev), dev);
-
- return 0;
-}
-EXPORT_SYMBOL(drm_irq_uninstall);
-
-/**
- * IRQ control ioctl.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_control structure.
- * \return zero on success or a negative number on failure.
- *
- * Calls irq_install() or irq_uninstall() according to \p arg.
- */
-int drm_control(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_control *ctl = data;
-
- /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
-
-
- switch (ctl->func) {
- case DRM_INST_HANDLER:
- if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
- return 0;
- if (drm_core_check_feature(dev, DRIVER_MODESET))
- return 0;
- if (dev->if_version < DRM_IF_VERSION(1, 2) &&
- ctl->irq != drm_dev_to_irq(dev))
- return -EINVAL;
- return drm_irq_install(dev);
- case DRM_UNINST_HANDLER:
- if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
- return 0;
- if (drm_core_check_feature(dev, DRIVER_MODESET))
- return 0;
- return drm_irq_uninstall(dev);
- default:
- return -EINVAL;
- }
-}
-
-/**
- * drm_vblank_count - retrieve "cooked" vblank counter value
- * @dev: DRM device
- * @crtc: which counter to retrieve
- *
- * Fetches the "cooked" vblank count value that represents the number of
- * vblank events since the system was booted, including lost events due to
- * modesetting activity.
- */
-u32 drm_vblank_count(struct drm_device *dev, int crtc)
-{
- return atomic_read(&dev->_vblank_count[crtc]);
-}
-EXPORT_SYMBOL(drm_vblank_count);
-
-/**
- * drm_update_vblank_count - update the master vblank counter
- * @dev: DRM device
- * @crtc: counter to update
- *
- * Call back into the driver to update the appropriate vblank counter
- * (specified by @crtc). Deal with wraparound, if it occurred, and
- * update the last read value so we can deal with wraparound on the next
- * call if necessary.
- *
- * Only necessary when going from off->on, to account for frames we
- * didn't get an interrupt for.
- *
- * Note: caller must hold dev->vbl_lock since this reads & writes
- * device vblank fields.
- */
-static void drm_update_vblank_count(struct drm_device *dev, int crtc)
-{
- u32 cur_vblank, diff;
-
- /*
- * Interrupts were disabled prior to this call, so deal with counter
- * wrap if needed.
- * NOTE! It's possible we lost a full dev->max_vblank_count events
- * here if the register is small or we had vblank interrupts off for
- * a long time.
- */
- cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
- diff = cur_vblank - dev->last_vblank[crtc];
- if (cur_vblank < dev->last_vblank[crtc]) {
- diff += dev->max_vblank_count;
-
- DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
- crtc, dev->last_vblank[crtc], cur_vblank, diff);
- }
-
- DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
- crtc, diff);
-
- atomic_add(diff, &dev->_vblank_count[crtc]);
-}
-
-/**
- * drm_vblank_get - get a reference count on vblank events
- * @dev: DRM device
- * @crtc: which CRTC to own
- *
- * Acquire a reference count on vblank events to avoid having them disabled
- * while in use.
- *
- * RETURNS
- * Zero on success, nonzero on failure.
- */
-int drm_vblank_get(struct drm_device *dev, int crtc)
-{
- unsigned long irqflags;
- int ret = 0;
-
- spin_lock_irqsave(&dev->vbl_lock, irqflags);
- /* Going from 0->1 means we have to enable interrupts again */
- if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
- if (!dev->vblank_enabled[crtc]) {
- ret = dev->driver->enable_vblank(dev, crtc);
- DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
- if (ret)
- atomic_dec(&dev->vblank_refcount[crtc]);
- else {
- dev->vblank_enabled[crtc] = 1;
- drm_update_vblank_count(dev, crtc);
- }
- }
- } else {
- if (!dev->vblank_enabled[crtc]) {
- atomic_dec(&dev->vblank_refcount[crtc]);
- ret = -EINVAL;
- }
- }
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-
- return ret;
-}
-EXPORT_SYMBOL(drm_vblank_get);
-
-/**
- * drm_vblank_put - give up ownership of vblank events
- * @dev: DRM device
- * @crtc: which counter to give up
- *
- * Release ownership of a given vblank counter, turning off interrupts
- * if possible.
- */
-void drm_vblank_put(struct drm_device *dev, int crtc)
-{
- BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0);
-
- /* Last user schedules interrupt disable */
- if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
- mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
-}
-EXPORT_SYMBOL(drm_vblank_put);
-
-void drm_vblank_off(struct drm_device *dev, int crtc)
-{
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev->vbl_lock, irqflags);
- dev->driver->disable_vblank(dev, crtc);
- DRM_WAKEUP(&dev->vbl_queue[crtc]);
- dev->vblank_enabled[crtc] = 0;
- dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-}
-EXPORT_SYMBOL(drm_vblank_off);
-
-/**
- * drm_vblank_pre_modeset - account for vblanks across mode sets
- * @dev: DRM device
- * @crtc: CRTC in question
- * @post: post or pre mode set?
- *
- * Account for vblank events across mode setting events, which will likely
- * reset the hardware frame counter.
- */
-void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
-{
- /* vblank is not initialized (IRQ not installed ?) */
- if (!dev->num_crtcs)
- return;
- /*
- * To avoid all the problems that might happen if interrupts
- * were enabled/disabled around or between these calls, we just
- * have the kernel take a reference on the CRTC (just once though
- * to avoid corrupting the count if multiple, mismatch calls occur),
- * so that interrupts remain enabled in the interim.
- */
- if (!dev->vblank_inmodeset[crtc]) {
- dev->vblank_inmodeset[crtc] = 0x1;
- if (drm_vblank_get(dev, crtc) == 0)
- dev->vblank_inmodeset[crtc] |= 0x2;
- }
-}
-EXPORT_SYMBOL(drm_vblank_pre_modeset);
-
-void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
-{
- unsigned long irqflags;
-
- if (dev->vblank_inmodeset[crtc]) {
- spin_lock_irqsave(&dev->vbl_lock, irqflags);
- dev->vblank_disable_allowed = 1;
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-
- if (dev->vblank_inmodeset[crtc] & 0x2)
- drm_vblank_put(dev, crtc);
-
- dev->vblank_inmodeset[crtc] = 0;
- }
-}
-EXPORT_SYMBOL(drm_vblank_post_modeset);
-
-/**
- * drm_modeset_ctl - handle vblank event counter changes across mode switch
- * @DRM_IOCTL_ARGS: standard ioctl arguments
- *
- * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
- * ioctls around modesetting so that any lost vblank events are accounted for.
- *
- * Generally the counter will reset across mode sets. If interrupts are
- * enabled around this call, we don't have to do anything since the counter
- * will have already been incremented.
- */
-int drm_modeset_ctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_modeset_ctl *modeset = data;
- int crtc, ret = 0;
-
- /* If drm_vblank_init() hasn't been called yet, just no-op */
- if (!dev->num_crtcs)
- goto out;
-
- crtc = modeset->crtc;
- if (crtc >= dev->num_crtcs) {
- ret = -EINVAL;
- goto out;
- }
-
- switch (modeset->cmd) {
- case _DRM_PRE_MODESET:
- drm_vblank_pre_modeset(dev, crtc);
- break;
- case _DRM_POST_MODESET:
- drm_vblank_post_modeset(dev, crtc);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
-out:
- return ret;
-}
-
-static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
- union drm_wait_vblank *vblwait,
- struct drm_file *file_priv)
-{
- struct drm_pending_vblank_event *e;
- struct timeval now;
- unsigned long flags;
- unsigned int seq;
- int ret;
-
- e = kzalloc(sizeof *e, GFP_KERNEL);
- if (e == NULL) {
- ret = -ENOMEM;
- goto err_put;
- }
-
- e->pipe = pipe;
- e->base.pid = current->pid;
- e->event.base.type = DRM_EVENT_VBLANK;
- e->event.base.length = sizeof e->event;
- e->event.user_data = vblwait->request.signal;
- e->base.event = &e->event.base;
- e->base.file_priv = file_priv;
- e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
-
- do_gettimeofday(&now);
- spin_lock_irqsave(&dev->event_lock, flags);
-
- if (file_priv->event_space < sizeof e->event) {
- ret = -EBUSY;
- goto err_unlock;
- }
-
- file_priv->event_space -= sizeof e->event;
- seq = drm_vblank_count(dev, pipe);
- if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&
- (seq - vblwait->request.sequence) <= (1 << 23)) {
- vblwait->request.sequence = seq + 1;
- vblwait->reply.sequence = vblwait->request.sequence;
- }
-
- DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
- vblwait->request.sequence, seq, pipe);
-
- trace_drm_vblank_event_queued(current->pid, pipe,
- vblwait->request.sequence);
-
- e->event.sequence = vblwait->request.sequence;
- if ((seq - vblwait->request.sequence) <= (1 << 23)) {
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
- drm_vblank_put(dev, pipe);
- list_add_tail(&e->base.link, &e->base.file_priv->event_list);
- wake_up_interruptible(&e->base.file_priv->event_wait);
- trace_drm_vblank_event_delivered(current->pid, pipe,
- vblwait->request.sequence);
- } else {
- list_add_tail(&e->base.link, &dev->vblank_event_list);
- }
-
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
- return 0;
-
-err_unlock:
- spin_unlock_irqrestore(&dev->event_lock, flags);
- kfree(e);
-err_put:
- drm_vblank_put(dev, pipe);
- return ret;
-}
-
-/**
- * Wait for VBLANK.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param data user argument, pointing to a drm_wait_vblank structure.
- * \return zero on success or a negative number on failure.
- *
- * This function enables the vblank interrupt on the pipe requested, then
- * sleeps waiting for the requested sequence number to occur, and drops
- * the vblank interrupt refcount afterwards. (vblank irq disable follows that
- * after a timeout with no further vblank waits scheduled).
- */
-int drm_wait_vblank(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- union drm_wait_vblank *vblwait = data;
- int ret = 0;
- unsigned int flags, seq, crtc;
-
- if ((!drm_dev_to_irq(dev)) || (!dev->irq_enabled))
- return -EINVAL;
-
- if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
- return -EINVAL;
-
- if (vblwait->request.type &
- ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
- DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
- vblwait->request.type,
- (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
- return -EINVAL;
- }
-
- flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
- crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
-
- if (crtc >= dev->num_crtcs)
- return -EINVAL;
-
- ret = drm_vblank_get(dev, crtc);
- if (ret) {
- DRM_DEBUG("failed to acquire vblank counter, %d\n", ret);
- return ret;
- }
- seq = drm_vblank_count(dev, crtc);
-
- switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
- case _DRM_VBLANK_RELATIVE:
- vblwait->request.sequence += seq;
- vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
- case _DRM_VBLANK_ABSOLUTE:
- break;
- default:
- ret = -EINVAL;
- goto done;
- }
-
- if (flags & _DRM_VBLANK_EVENT)
- return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
-
- if ((flags & _DRM_VBLANK_NEXTONMISS) &&
- (seq - vblwait->request.sequence) <= (1<<23)) {
- vblwait->request.sequence = seq + 1;
- }
-
- DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
- vblwait->request.sequence, crtc);
- dev->last_vblank_wait[crtc] = vblwait->request.sequence;
- DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
- (((drm_vblank_count(dev, crtc) -
- vblwait->request.sequence) <= (1 << 23)) ||
- !dev->irq_enabled));
-
- if (ret != -EINTR) {
- struct timeval now;
-
- do_gettimeofday(&now);
-
- vblwait->reply.tval_sec = now.tv_sec;
- vblwait->reply.tval_usec = now.tv_usec;
- vblwait->reply.sequence = drm_vblank_count(dev, crtc);
- DRM_DEBUG("returning %d to client\n",
- vblwait->reply.sequence);
- } else {
- DRM_DEBUG("vblank wait interrupted by signal\n");
- }
-
-done:
- drm_vblank_put(dev, crtc);
- return ret;
-}
-
-void drm_handle_vblank_events(struct drm_device *dev, int crtc)
-{
- struct drm_pending_vblank_event *e, *t;
- struct timeval now;
- unsigned long flags;
- unsigned int seq;
-
- do_gettimeofday(&now);
- seq = drm_vblank_count(dev, crtc);
-
- spin_lock_irqsave(&dev->event_lock, flags);
-
- list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
- if (e->pipe != crtc)
- continue;
- if ((seq - e->event.sequence) > (1<<23))
- continue;
-
- DRM_DEBUG("vblank event on %d, current %d\n",
- e->event.sequence, seq);
-
- e->event.sequence = seq;
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
- drm_vblank_put(dev, e->pipe);
- list_move_tail(&e->base.link, &e->base.file_priv->event_list);
- wake_up_interruptible(&e->base.file_priv->event_wait);
- trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
- e->event.sequence);
- }
-
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
- trace_drm_vblank_event(crtc, seq);
-}
-
-/**
- * drm_handle_vblank - handle a vblank event
- * @dev: DRM device
- * @crtc: where this event occurred
- *
- * Drivers should call this routine in their vblank interrupt handlers to
- * update the vblank counter and send any signals that may be pending.
- */
-void drm_handle_vblank(struct drm_device *dev, int crtc)
-{
- if (!dev->num_crtcs)
- return;
-
- atomic_inc(&dev->_vblank_count[crtc]);
- DRM_WAKEUP(&dev->vbl_queue[crtc]);
- drm_handle_vblank_events(dev, crtc);
-}
-EXPORT_SYMBOL(drm_handle_vblank);
+++ /dev/null
-/**
- * \file drm_lock.c
- * IOCTLs for locking
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-static int drm_notifier(void *priv);
-
-static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
-
-/**
- * Lock ioctl.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_lock structure.
- * \return zero on success or negative number on failure.
- *
- * Add the current task to the lock wait queue, and attempt to take to lock.
- */
-int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- DECLARE_WAITQUEUE(entry, current);
- struct drm_lock *lock = data;
- struct drm_master *master = file_priv->master;
- int ret = 0;
-
- ++file_priv->lock_count;
-
- if (lock->context == DRM_KERNEL_CONTEXT) {
- DRM_ERROR("Process %d using kernel context %d\n",
- task_pid_nr(current), lock->context);
- return -EINVAL;
- }
-
- DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
- lock->context, task_pid_nr(current),
- master->lock.hw_lock->lock, lock->flags);
-
- if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
- if (lock->context < 0)
- return -EINVAL;
-
- add_wait_queue(&master->lock.lock_queue, &entry);
- spin_lock_bh(&master->lock.spinlock);
- master->lock.user_waiters++;
- spin_unlock_bh(&master->lock.spinlock);
-
- for (;;) {
- __set_current_state(TASK_INTERRUPTIBLE);
- if (!master->lock.hw_lock) {
- /* Device has been unregistered */
- send_sig(SIGTERM, current, 0);
- ret = -EINTR;
- break;
- }
- if (drm_lock_take(&master->lock, lock->context)) {
- master->lock.file_priv = file_priv;
- master->lock.lock_time = jiffies;
- atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
- break; /* Got lock */
- }
-
- /* Contention */
- mutex_unlock(&drm_global_mutex);
- schedule();
- mutex_lock(&drm_global_mutex);
- if (signal_pending(current)) {
- ret = -EINTR;
- break;
- }
- }
- spin_lock_bh(&master->lock.spinlock);
- master->lock.user_waiters--;
- spin_unlock_bh(&master->lock.spinlock);
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&master->lock.lock_queue, &entry);
-
- DRM_DEBUG("%d %s\n", lock->context,
- ret ? "interrupted" : "has lock");
- if (ret) return ret;
-
- /* don't set the block all signals on the master process for now
- * really probably not the correct answer but lets us debug xkb
- * xserver for now */
- if (!file_priv->is_master) {
- sigemptyset(&dev->sigmask);
- sigaddset(&dev->sigmask, SIGSTOP);
- sigaddset(&dev->sigmask, SIGTSTP);
- sigaddset(&dev->sigmask, SIGTTIN);
- sigaddset(&dev->sigmask, SIGTTOU);
- dev->sigdata.context = lock->context;
- dev->sigdata.lock = master->lock.hw_lock;
- block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
- }
-
- if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT))
- {
- if (dev->driver->dma_quiescent(dev)) {
- DRM_DEBUG("%d waiting for DMA quiescent\n",
- lock->context);
- return -EBUSY;
- }
- }
-
- return 0;
-}
-
-/**
- * Unlock ioctl.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_lock structure.
- * \return zero on success or negative number on failure.
- *
- * Transfer and free the lock.
- */
-int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- struct drm_lock *lock = data;
- struct drm_master *master = file_priv->master;
-
- if (lock->context == DRM_KERNEL_CONTEXT) {
- DRM_ERROR("Process %d using kernel context %d\n",
- task_pid_nr(current), lock->context);
- return -EINVAL;
- }
-
- atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
-
- if (drm_lock_free(&master->lock, lock->context)) {
- /* FIXME: Should really bail out here. */
- }
-
- unblock_all_signals();
- return 0;
-}
-
-/**
- * Take the heavyweight lock.
- *
- * \param lock lock pointer.
- * \param context locking context.
- * \return one if the lock is held, or zero otherwise.
- *
- * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
- */
-static
-int drm_lock_take(struct drm_lock_data *lock_data,
- unsigned int context)
-{
- unsigned int old, new, prev;
- volatile unsigned int *lock = &lock_data->hw_lock->lock;
-
- spin_lock_bh(&lock_data->spinlock);
- do {
- old = *lock;
- if (old & _DRM_LOCK_HELD)
- new = old | _DRM_LOCK_CONT;
- else {
- new = context | _DRM_LOCK_HELD |
- ((lock_data->user_waiters + lock_data->kernel_waiters > 1) ?
- _DRM_LOCK_CONT : 0);
- }
- prev = cmpxchg(lock, old, new);
- } while (prev != old);
- spin_unlock_bh(&lock_data->spinlock);
-
- if (_DRM_LOCKING_CONTEXT(old) == context) {
- if (old & _DRM_LOCK_HELD) {
- if (context != DRM_KERNEL_CONTEXT) {
- DRM_ERROR("%d holds heavyweight lock\n",
- context);
- }
- return 0;
- }
- }
-
- if ((_DRM_LOCKING_CONTEXT(new)) == context && (new & _DRM_LOCK_HELD)) {
- /* Have lock */
- return 1;
- }
- return 0;
-}
-
-/**
- * This takes a lock forcibly and hands it to context. Should ONLY be used
- * inside *_unlock to give lock to kernel before calling *_dma_schedule.
- *
- * \param dev DRM device.
- * \param lock lock pointer.
- * \param context locking context.
- * \return always one.
- *
- * Resets the lock file pointer.
- * Marks the lock as held by the given context, via the \p cmpxchg instruction.
- */
-static int drm_lock_transfer(struct drm_lock_data *lock_data,
- unsigned int context)
-{
- unsigned int old, new, prev;
- volatile unsigned int *lock = &lock_data->hw_lock->lock;
-
- lock_data->file_priv = NULL;
- do {
- old = *lock;
- new = context | _DRM_LOCK_HELD;
- prev = cmpxchg(lock, old, new);
- } while (prev != old);
- return 1;
-}
-
-/**
- * Free lock.
- *
- * \param dev DRM device.
- * \param lock lock.
- * \param context context.
- *
- * Resets the lock file pointer.
- * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
- * waiting on the lock queue.
- */
-int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
-{
- unsigned int old, new, prev;
- volatile unsigned int *lock = &lock_data->hw_lock->lock;
-
- spin_lock_bh(&lock_data->spinlock);
- if (lock_data->kernel_waiters != 0) {
- drm_lock_transfer(lock_data, 0);
- lock_data->idle_has_lock = 1;
- spin_unlock_bh(&lock_data->spinlock);
- return 1;
- }
- spin_unlock_bh(&lock_data->spinlock);
-
- do {
- old = *lock;
- new = _DRM_LOCKING_CONTEXT(old);
- prev = cmpxchg(lock, old, new);
- } while (prev != old);
-
- if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
- DRM_ERROR("%d freed heavyweight lock held by %d\n",
- context, _DRM_LOCKING_CONTEXT(old));
- return 1;
- }
- wake_up_interruptible(&lock_data->lock_queue);
- return 0;
-}
-
-/**
- * If we get here, it means that the process has called DRM_IOCTL_LOCK
- * without calling DRM_IOCTL_UNLOCK.
- *
- * If the lock is not held, then let the signal proceed as usual. If the lock
- * is held, then set the contended flag and keep the signal blocked.
- *
- * \param priv pointer to a drm_sigdata structure.
- * \return one if the signal should be delivered normally, or zero if the
- * signal should be blocked.
- */
-static int drm_notifier(void *priv)
-{
- struct drm_sigdata *s = (struct drm_sigdata *) priv;
- unsigned int old, new, prev;
-
- /* Allow signal delivery if lock isn't held */
- if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
- || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context)
- return 1;
-
- /* Otherwise, set flag to force call to
- drmUnlock */
- do {
- old = s->lock->lock;
- new = old | _DRM_LOCK_CONT;
- prev = cmpxchg(&s->lock->lock, old, new);
- } while (prev != old);
- return 0;
-}
-
-/**
- * This function returns immediately and takes the hw lock
- * with the kernel context if it is free, otherwise it gets the highest priority when and if
- * it is eventually released.
- *
- * This guarantees that the kernel will _eventually_ have the lock _unless_ it is held
- * by a blocked process. (In the latter case an explicit wait for the hardware lock would cause
- * a deadlock, which is why the "idlelock" was invented).
- *
- * This should be sufficient to wait for GPU idle without
- * having to worry about starvation.
- */
-
-void drm_idlelock_take(struct drm_lock_data *lock_data)
-{
- int ret = 0;
-
- spin_lock_bh(&lock_data->spinlock);
- lock_data->kernel_waiters++;
- if (!lock_data->idle_has_lock) {
-
- spin_unlock_bh(&lock_data->spinlock);
- ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
- spin_lock_bh(&lock_data->spinlock);
-
- if (ret == 1)
- lock_data->idle_has_lock = 1;
- }
- spin_unlock_bh(&lock_data->spinlock);
-}
-
-void drm_idlelock_release(struct drm_lock_data *lock_data)
-{
- unsigned int old, prev;
- volatile unsigned int *lock = &lock_data->hw_lock->lock;
-
- spin_lock_bh(&lock_data->spinlock);
- if (--lock_data->kernel_waiters == 0) {
- if (lock_data->idle_has_lock) {
- do {
- old = *lock;
- prev = cmpxchg(lock, old, DRM_KERNEL_CONTEXT);
- } while (prev != old);
- wake_up_interruptible(&lock_data->lock_queue);
- lock_data->idle_has_lock = 0;
- }
- }
- spin_unlock_bh(&lock_data->spinlock);
-}
-
-int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv)
-{
- struct drm_master *master = file_priv->master;
- return (file_priv->lock_count && master->lock.hw_lock &&
- _DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) &&
- master->lock.file_priv == file_priv);
-}
+++ /dev/null
-/**
- * \file drm_memory.c
- * Memory management wrappers for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/highmem.h>
-#include "drmP.h"
-
-/**
- * Called when "/proc/dri/%dev%/mem" is read.
- *
- * \param buf output buffer.
- * \param start start of output data.
- * \param offset requested start offset.
- * \param len requested number of bytes.
- * \param eof whether there is no more data to return.
- * \param data private data.
- * \return number of written bytes.
- *
- * No-op.
- */
-int drm_mem_info(char *buf, char **start, off_t offset,
- int len, int *eof, void *data)
-{
- return 0;
-}
-
-#if __OS_HAS_AGP
-static void *agp_remap(unsigned long offset, unsigned long size,
- struct drm_device * dev)
-{
- unsigned long i, num_pages =
- PAGE_ALIGN(size) / PAGE_SIZE;
- struct drm_agp_mem *agpmem;
- struct page **page_map;
- struct page **phys_page_map;
- void *addr;
-
- size = PAGE_ALIGN(size);
-
-#ifdef __alpha__
- offset -= dev->hose->mem_space->start;
-#endif
-
- list_for_each_entry(agpmem, &dev->agp->memory, head)
- if (agpmem->bound <= offset
- && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
- (offset + size))
- break;
- if (&agpmem->head == &dev->agp->memory)
- return NULL;
-
- /*
- * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
- * the CPU do not get remapped by the GART. We fix this by using the kernel's
- * page-table instead (that's probably faster anyhow...).
- */
- /* note: use vmalloc() because num_pages could be large... */
- page_map = vmalloc(num_pages * sizeof(struct page *));
- if (!page_map)
- return NULL;
-
- phys_page_map = (agpmem->memory->pages + (offset - agpmem->bound) / PAGE_SIZE);
- for (i = 0; i < num_pages; ++i)
- page_map[i] = phys_page_map[i];
- addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
- vfree(page_map);
-
- return addr;
-}
-
-/** Wrapper around agp_free_memory() */
-void drm_free_agp(DRM_AGP_MEM * handle, int pages)
-{
- agp_free_memory(handle);
-}
-EXPORT_SYMBOL(drm_free_agp);
-
-/** Wrapper around agp_bind_memory() */
-int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
-{
- return agp_bind_memory(handle, start);
-}
-
-/** Wrapper around agp_unbind_memory() */
-int drm_unbind_agp(DRM_AGP_MEM * handle)
-{
- return agp_unbind_memory(handle);
-}
-EXPORT_SYMBOL(drm_unbind_agp);
-
-#else /* __OS_HAS_AGP */
-static inline void *agp_remap(unsigned long offset, unsigned long size,
- struct drm_device * dev)
-{
- return NULL;
-}
-
-#endif /* agp */
-
-void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
-{
- if (drm_core_has_AGP(dev) &&
- dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
- map->handle = agp_remap(map->offset, map->size, dev);
- else
- map->handle = ioremap(map->offset, map->size);
-}
-EXPORT_SYMBOL(drm_core_ioremap);
-
-void drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev)
-{
- if (drm_core_has_AGP(dev) &&
- dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
- map->handle = agp_remap(map->offset, map->size, dev);
- else
- map->handle = ioremap_wc(map->offset, map->size);
-}
-EXPORT_SYMBOL(drm_core_ioremap_wc);
-
-void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev)
-{
- if (!map->handle || !map->size)
- return;
-
- if (drm_core_has_AGP(dev) &&
- dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
- vunmap(map->handle);
- else
- iounmap(map->handle);
-}
-EXPORT_SYMBOL(drm_core_ioremapfree);
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-
-/*
- * Generic simple memory manager implementation. Intended to be used as a base
- * class implementation for more advanced memory managers.
- *
- * Note that the algorithm used is quite simple and there might be substantial
- * performance gains if a smarter free list is implemented. Currently it is just an
- * unordered stack of free regions. This could easily be improved if an RB-tree
- * is used instead. At least if we expect heavy fragmentation.
- *
- * Aligned allocations can also see improvement.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include "drmP.h"
-#include "drm_mm.h"
-#include <linux/slab.h>
-#include <linux/seq_file.h>
-
-#define MM_UNUSED_TARGET 4
-
-static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
-{
- struct drm_mm_node *child;
-
- if (atomic)
- child = kzalloc(sizeof(*child), GFP_ATOMIC);
- else
- child = kzalloc(sizeof(*child), GFP_KERNEL);
-
- if (unlikely(child == NULL)) {
- spin_lock(&mm->unused_lock);
- if (list_empty(&mm->unused_nodes))
- child = NULL;
- else {
- child =
- list_entry(mm->unused_nodes.next,
- struct drm_mm_node, free_stack);
- list_del(&child->free_stack);
- --mm->num_unused;
- }
- spin_unlock(&mm->unused_lock);
- }
- return child;
-}
-
-/* drm_mm_pre_get() - pre allocate drm_mm_node structure
- * drm_mm: memory manager struct we are pre-allocating for
- *
- * Returns 0 on success or -ENOMEM if allocation fails.
- */
-int drm_mm_pre_get(struct drm_mm *mm)
-{
- struct drm_mm_node *node;
-
- spin_lock(&mm->unused_lock);
- while (mm->num_unused < MM_UNUSED_TARGET) {
- spin_unlock(&mm->unused_lock);
- node = kzalloc(sizeof(*node), GFP_KERNEL);
- spin_lock(&mm->unused_lock);
-
- if (unlikely(node == NULL)) {
- int ret = (mm->num_unused < 2) ? -ENOMEM : 0;
- spin_unlock(&mm->unused_lock);
- return ret;
- }
- ++mm->num_unused;
- list_add_tail(&node->free_stack, &mm->unused_nodes);
- }
- spin_unlock(&mm->unused_lock);
- return 0;
-}
-EXPORT_SYMBOL(drm_mm_pre_get);
-
-static int drm_mm_create_tail_node(struct drm_mm *mm,
- unsigned long start,
- unsigned long size, int atomic)
-{
- struct drm_mm_node *child;
-
- child = drm_mm_kmalloc(mm, atomic);
- if (unlikely(child == NULL))
- return -ENOMEM;
-
- child->free = 1;
- child->size = size;
- child->start = start;
- child->mm = mm;
-
- list_add_tail(&child->node_list, &mm->node_list);
- list_add_tail(&child->free_stack, &mm->free_stack);
-
- return 0;
-}
-
-static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
- unsigned long size,
- int atomic)
-{
- struct drm_mm_node *child;
-
- child = drm_mm_kmalloc(parent->mm, atomic);
- if (unlikely(child == NULL))
- return NULL;
-
- INIT_LIST_HEAD(&child->free_stack);
-
- child->size = size;
- child->start = parent->start;
- child->mm = parent->mm;
-
- list_add_tail(&child->node_list, &parent->node_list);
- INIT_LIST_HEAD(&child->free_stack);
-
- parent->size -= size;
- parent->start += size;
- return child;
-}
-
-
-struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
- unsigned long size,
- unsigned alignment,
- int atomic)
-{
-
- struct drm_mm_node *align_splitoff = NULL;
- unsigned tmp = 0;
-
- if (alignment)
- tmp = node->start % alignment;
-
- if (tmp) {
- align_splitoff =
- drm_mm_split_at_start(node, alignment - tmp, atomic);
- if (unlikely(align_splitoff == NULL))
- return NULL;
- }
-
- if (node->size == size) {
- list_del_init(&node->free_stack);
- node->free = 0;
- } else {
- node = drm_mm_split_at_start(node, size, atomic);
- }
-
- if (align_splitoff)
- drm_mm_put_block(align_splitoff);
-
- return node;
-}
-EXPORT_SYMBOL(drm_mm_get_block_generic);
-
-struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node,
- unsigned long size,
- unsigned alignment,
- unsigned long start,
- unsigned long end,
- int atomic)
-{
- struct drm_mm_node *align_splitoff = NULL;
- unsigned tmp = 0;
- unsigned wasted = 0;
-
- if (node->start < start)
- wasted += start - node->start;
- if (alignment)
- tmp = ((node->start + wasted) % alignment);
-
- if (tmp)
- wasted += alignment - tmp;
- if (wasted) {
- align_splitoff = drm_mm_split_at_start(node, wasted, atomic);
- if (unlikely(align_splitoff == NULL))
- return NULL;
- }
-
- if (node->size == size) {
- list_del_init(&node->free_stack);
- node->free = 0;
- } else {
- node = drm_mm_split_at_start(node, size, atomic);
- }
-
- if (align_splitoff)
- drm_mm_put_block(align_splitoff);
-
- return node;
-}
-EXPORT_SYMBOL(drm_mm_get_block_range_generic);
-
-/*
- * Put a block. Merge with the previous and / or next block if they are free.
- * Otherwise add to the free stack.
- */
-
-void drm_mm_put_block(struct drm_mm_node *cur)
-{
-
- struct drm_mm *mm = cur->mm;
- struct list_head *cur_head = &cur->node_list;
- struct list_head *root_head = &mm->node_list;
- struct drm_mm_node *prev_node = NULL;
- struct drm_mm_node *next_node;
-
- int merged = 0;
-
- BUG_ON(cur->scanned_block || cur->scanned_prev_free
- || cur->scanned_next_free);
-
- if (cur_head->prev != root_head) {
- prev_node =
- list_entry(cur_head->prev, struct drm_mm_node, node_list);
- if (prev_node->free) {
- prev_node->size += cur->size;
- merged = 1;
- }
- }
- if (cur_head->next != root_head) {
- next_node =
- list_entry(cur_head->next, struct drm_mm_node, node_list);
- if (next_node->free) {
- if (merged) {
- prev_node->size += next_node->size;
- list_del(&next_node->node_list);
- list_del(&next_node->free_stack);
- spin_lock(&mm->unused_lock);
- if (mm->num_unused < MM_UNUSED_TARGET) {
- list_add(&next_node->free_stack,
- &mm->unused_nodes);
- ++mm->num_unused;
- } else
- kfree(next_node);
- spin_unlock(&mm->unused_lock);
- } else {
- next_node->size += cur->size;
- next_node->start = cur->start;
- merged = 1;
- }
- }
- }
- if (!merged) {
- cur->free = 1;
- list_add(&cur->free_stack, &mm->free_stack);
- } else {
- list_del(&cur->node_list);
- spin_lock(&mm->unused_lock);
- if (mm->num_unused < MM_UNUSED_TARGET) {
- list_add(&cur->free_stack, &mm->unused_nodes);
- ++mm->num_unused;
- } else
- kfree(cur);
- spin_unlock(&mm->unused_lock);
- }
-}
-
-EXPORT_SYMBOL(drm_mm_put_block);
-
-static int check_free_hole(unsigned long start, unsigned long end,
- unsigned long size, unsigned alignment)
-{
- unsigned wasted = 0;
-
- if (end - start < size)
- return 0;
-
- if (alignment) {
- unsigned tmp = start % alignment;
- if (tmp)
- wasted = alignment - tmp;
- }
-
- if (end >= start + size + wasted) {
- return 1;
- }
-
- return 0;
-}
-
-struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
- unsigned long size,
- unsigned alignment, int best_match)
-{
- struct drm_mm_node *entry;
- struct drm_mm_node *best;
- unsigned long best_size;
-
- BUG_ON(mm->scanned_blocks);
-
- best = NULL;
- best_size = ~0UL;
-
- list_for_each_entry(entry, &mm->free_stack, free_stack) {
- if (!check_free_hole(entry->start, entry->start + entry->size,
- size, alignment))
- continue;
-
- if (!best_match)
- return entry;
-
- if (entry->size < best_size) {
- best = entry;
- best_size = entry->size;
- }
- }
-
- return best;
-}
-EXPORT_SYMBOL(drm_mm_search_free);
-
-struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
- unsigned long size,
- unsigned alignment,
- unsigned long start,
- unsigned long end,
- int best_match)
-{
- struct drm_mm_node *entry;
- struct drm_mm_node *best;
- unsigned long best_size;
-
- BUG_ON(mm->scanned_blocks);
-
- best = NULL;
- best_size = ~0UL;
-
- list_for_each_entry(entry, &mm->free_stack, free_stack) {
- unsigned long adj_start = entry->start < start ?
- start : entry->start;
- unsigned long adj_end = entry->start + entry->size > end ?
- end : entry->start + entry->size;
-
- if (!check_free_hole(adj_start, adj_end, size, alignment))
- continue;
-
- if (!best_match)
- return entry;
-
- if (entry->size < best_size) {
- best = entry;
- best_size = entry->size;
- }
- }
-
- return best;
-}
-EXPORT_SYMBOL(drm_mm_search_free_in_range);
-
-/**
- * Initializa lru scanning.
- *
- * This simply sets up the scanning routines with the parameters for the desired
- * hole.
- *
- * Warning: As long as the scan list is non-empty, no other operations than
- * adding/removing nodes to/from the scan list are allowed.
- */
-void drm_mm_init_scan(struct drm_mm *mm, unsigned long size,
- unsigned alignment)
-{
- mm->scan_alignment = alignment;
- mm->scan_size = size;
- mm->scanned_blocks = 0;
- mm->scan_hit_start = 0;
- mm->scan_hit_size = 0;
-}
-EXPORT_SYMBOL(drm_mm_init_scan);
-
-/**
- * Add a node to the scan list that might be freed to make space for the desired
- * hole.
- *
- * Returns non-zero, if a hole has been found, zero otherwise.
- */
-int drm_mm_scan_add_block(struct drm_mm_node *node)
-{
- struct drm_mm *mm = node->mm;
- struct list_head *prev_free, *next_free;
- struct drm_mm_node *prev_node, *next_node;
-
- mm->scanned_blocks++;
-
- prev_free = next_free = NULL;
-
- BUG_ON(node->free);
- node->scanned_block = 1;
- node->free = 1;
-
- if (node->node_list.prev != &mm->node_list) {
- prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
- node_list);
-
- if (prev_node->free) {
- list_del(&prev_node->node_list);
-
- node->start = prev_node->start;
- node->size += prev_node->size;
-
- prev_node->scanned_prev_free = 1;
-
- prev_free = &prev_node->free_stack;
- }
- }
-
- if (node->node_list.next != &mm->node_list) {
- next_node = list_entry(node->node_list.next, struct drm_mm_node,
- node_list);
-
- if (next_node->free) {
- list_del(&next_node->node_list);
-
- node->size += next_node->size;
-
- next_node->scanned_next_free = 1;
-
- next_free = &next_node->free_stack;
- }
- }
-
- /* The free_stack list is not used for allocated objects, so these two
- * pointers can be abused (as long as no allocations in this memory
- * manager happens). */
- node->free_stack.prev = prev_free;
- node->free_stack.next = next_free;
-
- if (check_free_hole(node->start, node->start + node->size,
- mm->scan_size, mm->scan_alignment)) {
- mm->scan_hit_start = node->start;
- mm->scan_hit_size = node->size;
-
- return 1;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(drm_mm_scan_add_block);
-
-/**
- * Remove a node from the scan list.
- *
- * Nodes _must_ be removed in the exact same order from the scan list as they
- * have been added, otherwise the internal state of the memory manager will be
- * corrupted.
- *
- * When the scan list is empty, the selected memory nodes can be freed. An
- * immediatly following drm_mm_search_free with best_match = 0 will then return
- * the just freed block (because its at the top of the free_stack list).
- *
- * Returns one if this block should be evicted, zero otherwise. Will always
- * return zero when no hole has been found.
- */
-int drm_mm_scan_remove_block(struct drm_mm_node *node)
-{
- struct drm_mm *mm = node->mm;
- struct drm_mm_node *prev_node, *next_node;
-
- mm->scanned_blocks--;
-
- BUG_ON(!node->scanned_block);
- node->scanned_block = 0;
- node->free = 0;
-
- prev_node = list_entry(node->free_stack.prev, struct drm_mm_node,
- free_stack);
- next_node = list_entry(node->free_stack.next, struct drm_mm_node,
- free_stack);
-
- if (prev_node) {
- BUG_ON(!prev_node->scanned_prev_free);
- prev_node->scanned_prev_free = 0;
-
- list_add_tail(&prev_node->node_list, &node->node_list);
-
- node->start = prev_node->start + prev_node->size;
- node->size -= prev_node->size;
- }
-
- if (next_node) {
- BUG_ON(!next_node->scanned_next_free);
- next_node->scanned_next_free = 0;
-
- list_add(&next_node->node_list, &node->node_list);
-
- node->size -= next_node->size;
- }
-
- INIT_LIST_HEAD(&node->free_stack);
-
- /* Only need to check for containement because start&size for the
- * complete resulting free block (not just the desired part) is
- * stored. */
- if (node->start >= mm->scan_hit_start &&
- node->start + node->size
- <= mm->scan_hit_start + mm->scan_hit_size) {
- return 1;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(drm_mm_scan_remove_block);
-
-int drm_mm_clean(struct drm_mm * mm)
-{
- struct list_head *head = &mm->node_list;
-
- return (head->next->next == head);
-}
-EXPORT_SYMBOL(drm_mm_clean);
-
-int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
-{
- INIT_LIST_HEAD(&mm->node_list);
- INIT_LIST_HEAD(&mm->free_stack);
- INIT_LIST_HEAD(&mm->unused_nodes);
- mm->num_unused = 0;
- mm->scanned_blocks = 0;
- spin_lock_init(&mm->unused_lock);
-
- return drm_mm_create_tail_node(mm, start, size, 0);
-}
-EXPORT_SYMBOL(drm_mm_init);
-
-void drm_mm_takedown(struct drm_mm * mm)
-{
- struct list_head *bnode = mm->free_stack.next;
- struct drm_mm_node *entry;
- struct drm_mm_node *next;
-
- entry = list_entry(bnode, struct drm_mm_node, free_stack);
-
- if (entry->node_list.next != &mm->node_list ||
- entry->free_stack.next != &mm->free_stack) {
- DRM_ERROR("Memory manager not clean. Delaying takedown\n");
- return;
- }
-
- list_del(&entry->free_stack);
- list_del(&entry->node_list);
- kfree(entry);
-
- spin_lock(&mm->unused_lock);
- list_for_each_entry_safe(entry, next, &mm->unused_nodes, free_stack) {
- list_del(&entry->free_stack);
- kfree(entry);
- --mm->num_unused;
- }
- spin_unlock(&mm->unused_lock);
-
- BUG_ON(mm->num_unused != 0);
-}
-EXPORT_SYMBOL(drm_mm_takedown);
-
-void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
-{
- struct drm_mm_node *entry;
- int total_used = 0, total_free = 0, total = 0;
-
- list_for_each_entry(entry, &mm->node_list, node_list) {
- printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
- prefix, entry->start, entry->start + entry->size,
- entry->size, entry->free ? "free" : "used");
- total += entry->size;
- if (entry->free)
- total_free += entry->size;
- else
- total_used += entry->size;
- }
- printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total,
- total_used, total_free);
-}
-EXPORT_SYMBOL(drm_mm_debug_table);
-
-#if defined(CONFIG_DEBUG_FS)
-int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
-{
- struct drm_mm_node *entry;
- int total_used = 0, total_free = 0, total = 0;
-
- list_for_each_entry(entry, &mm->node_list, node_list) {
- seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: %s\n", entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used");
- total += entry->size;
- if (entry->free)
- total_free += entry->size;
- else
- total_used += entry->size;
- }
- seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free);
- return 0;
-}
-EXPORT_SYMBOL(drm_mm_dump_table);
-#endif
+++ /dev/null
-/*
- * Copyright © 1997-2003 by The XFree86 Project, Inc.
- * Copyright © 2007 Dave Airlie
- * Copyright © 2007-2008 Intel Corporation
- * Jesse Barnes <jesse.barnes@intel.com>
- * Copyright 2005-2006 Luc Verhaegen
- * Copyright (c) 2001, Andy Ritger aritger@nvidia.com
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-#include <linux/list.h>
-#include <linux/list_sort.h>
-#include "drmP.h"
-#include "drm.h"
-#include "drm_crtc.h"
-
-/**
- * drm_mode_debug_printmodeline - debug print a mode
- * @dev: DRM device
- * @mode: mode to print
- *
- * LOCKING:
- * None.
- *
- * Describe @mode using DRM_DEBUG.
- */
-void drm_mode_debug_printmodeline(struct drm_display_mode *mode)
-{
- DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d "
- "0x%x 0x%x\n",
- mode->base.id, mode->name, mode->vrefresh, mode->clock,
- mode->hdisplay, mode->hsync_start,
- mode->hsync_end, mode->htotal,
- mode->vdisplay, mode->vsync_start,
- mode->vsync_end, mode->vtotal, mode->type, mode->flags);
-}
-EXPORT_SYMBOL(drm_mode_debug_printmodeline);
-
-/**
- * drm_cvt_mode -create a modeline based on CVT algorithm
- * @dev: DRM device
- * @hdisplay: hdisplay size
- * @vdisplay: vdisplay size
- * @vrefresh : vrefresh rate
- * @reduced : Whether the GTF calculation is simplified
- * @interlaced:Whether the interlace is supported
- *
- * LOCKING:
- * none.
- *
- * return the modeline based on CVT algorithm
- *
- * This function is called to generate the modeline based on CVT algorithm
- * according to the hdisplay, vdisplay, vrefresh.
- * It is based from the VESA(TM) Coordinated Video Timing Generator by
- * Graham Loveridge April 9, 2003 available at
- * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
- *
- * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c.
- * What I have done is to translate it by using integer calculation.
- */
-#define HV_FACTOR 1000
-struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
- int vdisplay, int vrefresh,
- bool reduced, bool interlaced, bool margins)
-{
- /* 1) top/bottom margin size (% of height) - default: 1.8, */
-#define CVT_MARGIN_PERCENTAGE 18
- /* 2) character cell horizontal granularity (pixels) - default 8 */
-#define CVT_H_GRANULARITY 8
- /* 3) Minimum vertical porch (lines) - default 3 */
-#define CVT_MIN_V_PORCH 3
- /* 4) Minimum number of vertical back porch lines - default 6 */
-#define CVT_MIN_V_BPORCH 6
- /* Pixel Clock step (kHz) */
-#define CVT_CLOCK_STEP 250
- struct drm_display_mode *drm_mode;
- unsigned int vfieldrate, hperiod;
- int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync;
- int interlace;
-
- /* allocate the drm_display_mode structure. If failure, we will
- * return directly
- */
- drm_mode = drm_mode_create(dev);
- if (!drm_mode)
- return NULL;
-
- /* the CVT default refresh rate is 60Hz */
- if (!vrefresh)
- vrefresh = 60;
-
- /* the required field fresh rate */
- if (interlaced)
- vfieldrate = vrefresh * 2;
- else
- vfieldrate = vrefresh;
-
- /* horizontal pixels */
- hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY);
-
- /* determine the left&right borders */
- hmargin = 0;
- if (margins) {
- hmargin = hdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
- hmargin -= hmargin % CVT_H_GRANULARITY;
- }
- /* find the total active pixels */
- drm_mode->hdisplay = hdisplay_rnd + 2 * hmargin;
-
- /* find the number of lines per field */
- if (interlaced)
- vdisplay_rnd = vdisplay / 2;
- else
- vdisplay_rnd = vdisplay;
-
- /* find the top & bottom borders */
- vmargin = 0;
- if (margins)
- vmargin = vdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
-
- drm_mode->vdisplay = vdisplay + 2 * vmargin;
-
- /* Interlaced */
- if (interlaced)
- interlace = 1;
- else
- interlace = 0;
-
- /* Determine VSync Width from aspect ratio */
- if (!(vdisplay % 3) && ((vdisplay * 4 / 3) == hdisplay))
- vsync = 4;
- else if (!(vdisplay % 9) && ((vdisplay * 16 / 9) == hdisplay))
- vsync = 5;
- else if (!(vdisplay % 10) && ((vdisplay * 16 / 10) == hdisplay))
- vsync = 6;
- else if (!(vdisplay % 4) && ((vdisplay * 5 / 4) == hdisplay))
- vsync = 7;
- else if (!(vdisplay % 9) && ((vdisplay * 15 / 9) == hdisplay))
- vsync = 7;
- else /* custom */
- vsync = 10;
-
- if (!reduced) {
- /* simplify the GTF calculation */
- /* 4) Minimum time of vertical sync + back porch interval (µs)
- * default 550.0
- */
- int tmp1, tmp2;
-#define CVT_MIN_VSYNC_BP 550
- /* 3) Nominal HSync width (% of line period) - default 8 */
-#define CVT_HSYNC_PERCENTAGE 8
- unsigned int hblank_percentage;
- int vsyncandback_porch, vback_porch, hblank;
-
- /* estimated the horizontal period */
- tmp1 = HV_FACTOR * 1000000 -
- CVT_MIN_VSYNC_BP * HV_FACTOR * vfieldrate;
- tmp2 = (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH) * 2 +
- interlace;
- hperiod = tmp1 * 2 / (tmp2 * vfieldrate);
-
- tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / hperiod + 1;
- /* 9. Find number of lines in sync + backporch */
- if (tmp1 < (vsync + CVT_MIN_V_PORCH))
- vsyncandback_porch = vsync + CVT_MIN_V_PORCH;
- else
- vsyncandback_porch = tmp1;
- /* 10. Find number of lines in back porch */
- vback_porch = vsyncandback_porch - vsync;
- drm_mode->vtotal = vdisplay_rnd + 2 * vmargin +
- vsyncandback_porch + CVT_MIN_V_PORCH;
- /* 5) Definition of Horizontal blanking time limitation */
- /* Gradient (%/kHz) - default 600 */
-#define CVT_M_FACTOR 600
- /* Offset (%) - default 40 */
-#define CVT_C_FACTOR 40
- /* Blanking time scaling factor - default 128 */
-#define CVT_K_FACTOR 128
- /* Scaling factor weighting - default 20 */
-#define CVT_J_FACTOR 20
-#define CVT_M_PRIME (CVT_M_FACTOR * CVT_K_FACTOR / 256)
-#define CVT_C_PRIME ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
- CVT_J_FACTOR)
- /* 12. Find ideal blanking duty cycle from formula */
- hblank_percentage = CVT_C_PRIME * HV_FACTOR - CVT_M_PRIME *
- hperiod / 1000;
- /* 13. Blanking time */
- if (hblank_percentage < 20 * HV_FACTOR)
- hblank_percentage = 20 * HV_FACTOR;
- hblank = drm_mode->hdisplay * hblank_percentage /
- (100 * HV_FACTOR - hblank_percentage);
- hblank -= hblank % (2 * CVT_H_GRANULARITY);
- /* 14. find the total pixes per line */
- drm_mode->htotal = drm_mode->hdisplay + hblank;
- drm_mode->hsync_end = drm_mode->hdisplay + hblank / 2;
- drm_mode->hsync_start = drm_mode->hsync_end -
- (drm_mode->htotal * CVT_HSYNC_PERCENTAGE) / 100;
- drm_mode->hsync_start += CVT_H_GRANULARITY -
- drm_mode->hsync_start % CVT_H_GRANULARITY;
- /* fill the Vsync values */
- drm_mode->vsync_start = drm_mode->vdisplay + CVT_MIN_V_PORCH;
- drm_mode->vsync_end = drm_mode->vsync_start + vsync;
- } else {
- /* Reduced blanking */
- /* Minimum vertical blanking interval time (µs)- default 460 */
-#define CVT_RB_MIN_VBLANK 460
- /* Fixed number of clocks for horizontal sync */
-#define CVT_RB_H_SYNC 32
- /* Fixed number of clocks for horizontal blanking */
-#define CVT_RB_H_BLANK 160
- /* Fixed number of lines for vertical front porch - default 3*/
-#define CVT_RB_VFPORCH 3
- int vbilines;
- int tmp1, tmp2;
- /* 8. Estimate Horizontal period. */
- tmp1 = HV_FACTOR * 1000000 -
- CVT_RB_MIN_VBLANK * HV_FACTOR * vfieldrate;
- tmp2 = vdisplay_rnd + 2 * vmargin;
- hperiod = tmp1 / (tmp2 * vfieldrate);
- /* 9. Find number of lines in vertical blanking */
- vbilines = CVT_RB_MIN_VBLANK * HV_FACTOR / hperiod + 1;
- /* 10. Check if vertical blanking is sufficient */
- if (vbilines < (CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH))
- vbilines = CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH;
- /* 11. Find total number of lines in vertical field */
- drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vbilines;
- /* 12. Find total number of pixels in a line */
- drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK;
- /* Fill in HSync values */
- drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2;
- drm_mode->hsync_start = drm_mode->hsync_end - CVT_RB_H_SYNC;
- /* Fill in VSync values */
- drm_mode->vsync_start = drm_mode->vdisplay + CVT_RB_VFPORCH;
- drm_mode->vsync_end = drm_mode->vsync_start + vsync;
- }
- /* 15/13. Find pixel clock frequency (kHz for xf86) */
- drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod;
- drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP;
- /* 18/16. Find actual vertical frame frequency */
- /* ignore - just set the mode flag for interlaced */
- if (interlaced) {
- drm_mode->vtotal *= 2;
- drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
- }
- /* Fill the mode line name */
- drm_mode_set_name(drm_mode);
- if (reduced)
- drm_mode->flags |= (DRM_MODE_FLAG_PHSYNC |
- DRM_MODE_FLAG_NVSYNC);
- else
- drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC |
- DRM_MODE_FLAG_NHSYNC);
-
- return drm_mode;
-}
-EXPORT_SYMBOL(drm_cvt_mode);
-
-/**
- * drm_gtf_mode_complex - create the modeline based on full GTF algorithm
- *
- * @dev :drm device
- * @hdisplay :hdisplay size
- * @vdisplay :vdisplay size
- * @vrefresh :vrefresh rate.
- * @interlaced :whether the interlace is supported
- * @margins :desired margin size
- * @GTF_[MCKJ] :extended GTF formula parameters
- *
- * LOCKING.
- * none.
- *
- * return the modeline based on full GTF algorithm.
- *
- * GTF feature blocks specify C and J in multiples of 0.5, so we pass them
- * in here multiplied by two. For a C of 40, pass in 80.
- */
-struct drm_display_mode *
-drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay,
- int vrefresh, bool interlaced, int margins,
- int GTF_M, int GTF_2C, int GTF_K, int GTF_2J)
-{ /* 1) top/bottom margin size (% of height) - default: 1.8, */
-#define GTF_MARGIN_PERCENTAGE 18
- /* 2) character cell horizontal granularity (pixels) - default 8 */
-#define GTF_CELL_GRAN 8
- /* 3) Minimum vertical porch (lines) - default 3 */
-#define GTF_MIN_V_PORCH 1
- /* width of vsync in lines */
-#define V_SYNC_RQD 3
- /* width of hsync as % of total line */
-#define H_SYNC_PERCENT 8
- /* min time of vsync + back porch (microsec) */
-#define MIN_VSYNC_PLUS_BP 550
- /* C' and M' are part of the Blanking Duty Cycle computation */
-#define GTF_C_PRIME ((((GTF_2C - GTF_2J) * GTF_K / 256) + GTF_2J) / 2)
-#define GTF_M_PRIME (GTF_K * GTF_M / 256)
- struct drm_display_mode *drm_mode;
- unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd;
- int top_margin, bottom_margin;
- int interlace;
- unsigned int hfreq_est;
- int vsync_plus_bp, vback_porch;
- unsigned int vtotal_lines, vfieldrate_est, hperiod;
- unsigned int vfield_rate, vframe_rate;
- int left_margin, right_margin;
- unsigned int total_active_pixels, ideal_duty_cycle;
- unsigned int hblank, total_pixels, pixel_freq;
- int hsync, hfront_porch, vodd_front_porch_lines;
- unsigned int tmp1, tmp2;
-
- drm_mode = drm_mode_create(dev);
- if (!drm_mode)
- return NULL;
-
- /* 1. In order to give correct results, the number of horizontal
- * pixels requested is first processed to ensure that it is divisible
- * by the character size, by rounding it to the nearest character
- * cell boundary:
- */
- hdisplay_rnd = (hdisplay + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
- hdisplay_rnd = hdisplay_rnd * GTF_CELL_GRAN;
-
- /* 2. If interlace is requested, the number of vertical lines assumed
- * by the calculation must be halved, as the computation calculates
- * the number of vertical lines per field.
- */
- if (interlaced)
- vdisplay_rnd = vdisplay / 2;
- else
- vdisplay_rnd = vdisplay;
-
- /* 3. Find the frame rate required: */
- if (interlaced)
- vfieldrate_rqd = vrefresh * 2;
- else
- vfieldrate_rqd = vrefresh;
-
- /* 4. Find number of lines in Top margin: */
- top_margin = 0;
- if (margins)
- top_margin = (vdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
- 1000;
- /* 5. Find number of lines in bottom margin: */
- bottom_margin = top_margin;
-
- /* 6. If interlace is required, then set variable interlace: */
- if (interlaced)
- interlace = 1;
- else
- interlace = 0;
-
- /* 7. Estimate the Horizontal frequency */
- {
- tmp1 = (1000000 - MIN_VSYNC_PLUS_BP * vfieldrate_rqd) / 500;
- tmp2 = (vdisplay_rnd + 2 * top_margin + GTF_MIN_V_PORCH) *
- 2 + interlace;
- hfreq_est = (tmp2 * 1000 * vfieldrate_rqd) / tmp1;
- }
-
- /* 8. Find the number of lines in V sync + back porch */
- /* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */
- vsync_plus_bp = MIN_VSYNC_PLUS_BP * hfreq_est / 1000;
- vsync_plus_bp = (vsync_plus_bp + 500) / 1000;
- /* 9. Find the number of lines in V back porch alone: */
- vback_porch = vsync_plus_bp - V_SYNC_RQD;
- /* 10. Find the total number of lines in Vertical field period: */
- vtotal_lines = vdisplay_rnd + top_margin + bottom_margin +
- vsync_plus_bp + GTF_MIN_V_PORCH;
- /* 11. Estimate the Vertical field frequency: */
- vfieldrate_est = hfreq_est / vtotal_lines;
- /* 12. Find the actual horizontal period: */
- hperiod = 1000000 / (vfieldrate_rqd * vtotal_lines);
-
- /* 13. Find the actual Vertical field frequency: */
- vfield_rate = hfreq_est / vtotal_lines;
- /* 14. Find the Vertical frame frequency: */
- if (interlaced)
- vframe_rate = vfield_rate / 2;
- else
- vframe_rate = vfield_rate;
- /* 15. Find number of pixels in left margin: */
- if (margins)
- left_margin = (hdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
- 1000;
- else
- left_margin = 0;
-
- /* 16.Find number of pixels in right margin: */
- right_margin = left_margin;
- /* 17.Find total number of active pixels in image and left and right */
- total_active_pixels = hdisplay_rnd + left_margin + right_margin;
- /* 18.Find the ideal blanking duty cycle from blanking duty cycle */
- ideal_duty_cycle = GTF_C_PRIME * 1000 -
- (GTF_M_PRIME * 1000000 / hfreq_est);
- /* 19.Find the number of pixels in the blanking time to the nearest
- * double character cell: */
- hblank = total_active_pixels * ideal_duty_cycle /
- (100000 - ideal_duty_cycle);
- hblank = (hblank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN);
- hblank = hblank * 2 * GTF_CELL_GRAN;
- /* 20.Find total number of pixels: */
- total_pixels = total_active_pixels + hblank;
- /* 21.Find pixel clock frequency: */
- pixel_freq = total_pixels * hfreq_est / 1000;
- /* Stage 1 computations are now complete; I should really pass
- * the results to another function and do the Stage 2 computations,
- * but I only need a few more values so I'll just append the
- * computations here for now */
- /* 17. Find the number of pixels in the horizontal sync period: */
- hsync = H_SYNC_PERCENT * total_pixels / 100;
- hsync = (hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
- hsync = hsync * GTF_CELL_GRAN;
- /* 18. Find the number of pixels in horizontal front porch period */
- hfront_porch = hblank / 2 - hsync;
- /* 36. Find the number of lines in the odd front porch period: */
- vodd_front_porch_lines = GTF_MIN_V_PORCH ;
-
- /* finally, pack the results in the mode struct */
- drm_mode->hdisplay = hdisplay_rnd;
- drm_mode->hsync_start = hdisplay_rnd + hfront_porch;
- drm_mode->hsync_end = drm_mode->hsync_start + hsync;
- drm_mode->htotal = total_pixels;
- drm_mode->vdisplay = vdisplay_rnd;
- drm_mode->vsync_start = vdisplay_rnd + vodd_front_porch_lines;
- drm_mode->vsync_end = drm_mode->vsync_start + V_SYNC_RQD;
- drm_mode->vtotal = vtotal_lines;
-
- drm_mode->clock = pixel_freq;
-
- if (interlaced) {
- drm_mode->vtotal *= 2;
- drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
- }
-
- drm_mode_set_name(drm_mode);
- if (GTF_M == 600 && GTF_2C == 80 && GTF_K == 128 && GTF_2J == 40)
- drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC;
- else
- drm_mode->flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC;
-
- return drm_mode;
-}
-EXPORT_SYMBOL(drm_gtf_mode_complex);
-
-/**
- * drm_gtf_mode - create the modeline based on GTF algorithm
- *
- * @dev :drm device
- * @hdisplay :hdisplay size
- * @vdisplay :vdisplay size
- * @vrefresh :vrefresh rate.
- * @interlaced :whether the interlace is supported
- * @margins :whether the margin is supported
- *
- * LOCKING.
- * none.
- *
- * return the modeline based on GTF algorithm
- *
- * This function is to create the modeline based on the GTF algorithm.
- * Generalized Timing Formula is derived from:
- * GTF Spreadsheet by Andy Morrish (1/5/97)
- * available at http://www.vesa.org
- *
- * And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c.
- * What I have done is to translate it by using integer calculation.
- * I also refer to the function of fb_get_mode in the file of
- * drivers/video/fbmon.c
- *
- * Standard GTF parameters:
- * M = 600
- * C = 40
- * K = 128
- * J = 20
- */
-struct drm_display_mode *
-drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
- bool lace, int margins)
-{
- return drm_gtf_mode_complex(dev, hdisplay, vdisplay, vrefresh, lace,
- margins, 600, 40 * 2, 128, 20 * 2);
-}
-EXPORT_SYMBOL(drm_gtf_mode);
-
-/**
- * drm_mode_set_name - set the name on a mode
- * @mode: name will be set in this mode
- *
- * LOCKING:
- * None.
- *
- * Set the name of @mode to a standard format.
- */
-void drm_mode_set_name(struct drm_display_mode *mode)
-{
- bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
-
- snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s",
- mode->hdisplay, mode->vdisplay,
- interlaced ? "i" : "");
-}
-EXPORT_SYMBOL(drm_mode_set_name);
-
-/**
- * drm_mode_list_concat - move modes from one list to another
- * @head: source list
- * @new: dst list
- *
- * LOCKING:
- * Caller must ensure both lists are locked.
- *
- * Move all the modes from @head to @new.
- */
-void drm_mode_list_concat(struct list_head *head, struct list_head *new)
-{
-
- struct list_head *entry, *tmp;
-
- list_for_each_safe(entry, tmp, head) {
- list_move_tail(entry, new);
- }
-}
-EXPORT_SYMBOL(drm_mode_list_concat);
-
-/**
- * drm_mode_width - get the width of a mode
- * @mode: mode
- *
- * LOCKING:
- * None.
- *
- * Return @mode's width (hdisplay) value.
- *
- * FIXME: is this needed?
- *
- * RETURNS:
- * @mode->hdisplay
- */
-int drm_mode_width(struct drm_display_mode *mode)
-{
- return mode->hdisplay;
-
-}
-EXPORT_SYMBOL(drm_mode_width);
-
-/**
- * drm_mode_height - get the height of a mode
- * @mode: mode
- *
- * LOCKING:
- * None.
- *
- * Return @mode's height (vdisplay) value.
- *
- * FIXME: is this needed?
- *
- * RETURNS:
- * @mode->vdisplay
- */
-int drm_mode_height(struct drm_display_mode *mode)
-{
- return mode->vdisplay;
-}
-EXPORT_SYMBOL(drm_mode_height);
-
-/** drm_mode_hsync - get the hsync of a mode
- * @mode: mode
- *
- * LOCKING:
- * None.
- *
- * Return @modes's hsync rate in kHz, rounded to the nearest int.
- */
-int drm_mode_hsync(struct drm_display_mode *mode)
-{
- unsigned int calc_val;
-
- if (mode->hsync)
- return mode->hsync;
-
- if (mode->htotal < 0)
- return 0;
-
- calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
- calc_val += 500; /* round to 1000Hz */
- calc_val /= 1000; /* truncate to kHz */
-
- return calc_val;
-}
-EXPORT_SYMBOL(drm_mode_hsync);
-
-/**
- * drm_mode_vrefresh - get the vrefresh of a mode
- * @mode: mode
- *
- * LOCKING:
- * None.
- *
- * Return @mode's vrefresh rate in Hz or calculate it if necessary.
- *
- * FIXME: why is this needed? shouldn't vrefresh be set already?
- *
- * RETURNS:
- * Vertical refresh rate. It will be the result of actual value plus 0.5.
- * If it is 70.288, it will return 70Hz.
- * If it is 59.6, it will return 60Hz.
- */
-int drm_mode_vrefresh(struct drm_display_mode *mode)
-{
- int refresh = 0;
- unsigned int calc_val;
-
- if (mode->vrefresh > 0)
- refresh = mode->vrefresh;
- else if (mode->htotal > 0 && mode->vtotal > 0) {
- int vtotal;
- vtotal = mode->vtotal;
- /* work out vrefresh the value will be x1000 */
- calc_val = (mode->clock * 1000);
- calc_val /= mode->htotal;
- refresh = (calc_val + vtotal / 2) / vtotal;
-
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- refresh *= 2;
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- refresh /= 2;
- if (mode->vscan > 1)
- refresh /= mode->vscan;
- }
- return refresh;
-}
-EXPORT_SYMBOL(drm_mode_vrefresh);
-
-/**
- * drm_mode_set_crtcinfo - set CRTC modesetting parameters
- * @p: mode
- * @adjust_flags: unused? (FIXME)
- *
- * LOCKING:
- * None.
- *
- * Setup the CRTC modesetting parameters for @p, adjusting if necessary.
- */
-void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
-{
- if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN))
- return;
-
- p->crtc_hdisplay = p->hdisplay;
- p->crtc_hsync_start = p->hsync_start;
- p->crtc_hsync_end = p->hsync_end;
- p->crtc_htotal = p->htotal;
- p->crtc_hskew = p->hskew;
- p->crtc_vdisplay = p->vdisplay;
- p->crtc_vsync_start = p->vsync_start;
- p->crtc_vsync_end = p->vsync_end;
- p->crtc_vtotal = p->vtotal;
-
- if (p->flags & DRM_MODE_FLAG_INTERLACE) {
- if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
- p->crtc_vdisplay /= 2;
- p->crtc_vsync_start /= 2;
- p->crtc_vsync_end /= 2;
- p->crtc_vtotal /= 2;
- }
-
- p->crtc_vtotal |= 1;
- }
-
- if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
- p->crtc_vdisplay *= 2;
- p->crtc_vsync_start *= 2;
- p->crtc_vsync_end *= 2;
- p->crtc_vtotal *= 2;
- }
-
- if (p->vscan > 1) {
- p->crtc_vdisplay *= p->vscan;
- p->crtc_vsync_start *= p->vscan;
- p->crtc_vsync_end *= p->vscan;
- p->crtc_vtotal *= p->vscan;
- }
-
- p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
- p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
- p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
- p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
-
- p->crtc_hadjusted = false;
- p->crtc_vadjusted = false;
-}
-EXPORT_SYMBOL(drm_mode_set_crtcinfo);
-
-
-/**
- * drm_mode_duplicate - allocate and duplicate an existing mode
- * @m: mode to duplicate
- *
- * LOCKING:
- * None.
- *
- * Just allocate a new mode, copy the existing mode into it, and return
- * a pointer to it. Used to create new instances of established modes.
- */
-struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
- struct drm_display_mode *mode)
-{
- struct drm_display_mode *nmode;
- int new_id;
-
- nmode = drm_mode_create(dev);
- if (!nmode)
- return NULL;
-
- new_id = nmode->base.id;
- *nmode = *mode;
- nmode->base.id = new_id;
- INIT_LIST_HEAD(&nmode->head);
- return nmode;
-}
-EXPORT_SYMBOL(drm_mode_duplicate);
-
-/**
- * drm_mode_equal - test modes for equality
- * @mode1: first mode
- * @mode2: second mode
- *
- * LOCKING:
- * None.
- *
- * Check to see if @mode1 and @mode2 are equivalent.
- *
- * RETURNS:
- * True if the modes are equal, false otherwise.
- */
-bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2)
-{
- /* do clock check convert to PICOS so fb modes get matched
- * the same */
- if (mode1->clock && mode2->clock) {
- if (KHZ2PICOS(mode1->clock) != KHZ2PICOS(mode2->clock))
- return false;
- } else if (mode1->clock != mode2->clock)
- return false;
-
- if (mode1->hdisplay == mode2->hdisplay &&
- mode1->hsync_start == mode2->hsync_start &&
- mode1->hsync_end == mode2->hsync_end &&
- mode1->htotal == mode2->htotal &&
- mode1->hskew == mode2->hskew &&
- mode1->vdisplay == mode2->vdisplay &&
- mode1->vsync_start == mode2->vsync_start &&
- mode1->vsync_end == mode2->vsync_end &&
- mode1->vtotal == mode2->vtotal &&
- mode1->vscan == mode2->vscan &&
- mode1->flags == mode2->flags)
- return true;
-
- return false;
-}
-EXPORT_SYMBOL(drm_mode_equal);
-
-/**
- * drm_mode_validate_size - make sure modes adhere to size constraints
- * @dev: DRM device
- * @mode_list: list of modes to check
- * @maxX: maximum width
- * @maxY: maximum height
- * @maxPitch: max pitch
- *
- * LOCKING:
- * Caller must hold a lock protecting @mode_list.
- *
- * The DRM device (@dev) has size and pitch limits. Here we validate the
- * modes we probed for @dev against those limits and set their status as
- * necessary.
- */
-void drm_mode_validate_size(struct drm_device *dev,
- struct list_head *mode_list,
- int maxX, int maxY, int maxPitch)
-{
- struct drm_display_mode *mode;
-
- list_for_each_entry(mode, mode_list, head) {
- if (maxPitch > 0 && mode->hdisplay > maxPitch)
- mode->status = MODE_BAD_WIDTH;
-
- if (maxX > 0 && mode->hdisplay > maxX)
- mode->status = MODE_VIRTUAL_X;
-
- if (maxY > 0 && mode->vdisplay > maxY)
- mode->status = MODE_VIRTUAL_Y;
- }
-}
-EXPORT_SYMBOL(drm_mode_validate_size);
-
-/**
- * drm_mode_validate_clocks - validate modes against clock limits
- * @dev: DRM device
- * @mode_list: list of modes to check
- * @min: minimum clock rate array
- * @max: maximum clock rate array
- * @n_ranges: number of clock ranges (size of arrays)
- *
- * LOCKING:
- * Caller must hold a lock protecting @mode_list.
- *
- * Some code may need to check a mode list against the clock limits of the
- * device in question. This function walks the mode list, testing to make
- * sure each mode falls within a given range (defined by @min and @max
- * arrays) and sets @mode->status as needed.
- */
-void drm_mode_validate_clocks(struct drm_device *dev,
- struct list_head *mode_list,
- int *min, int *max, int n_ranges)
-{
- struct drm_display_mode *mode;
- int i;
-
- list_for_each_entry(mode, mode_list, head) {
- bool good = false;
- for (i = 0; i < n_ranges; i++) {
- if (mode->clock >= min[i] && mode->clock <= max[i]) {
- good = true;
- break;
- }
- }
- if (!good)
- mode->status = MODE_CLOCK_RANGE;
- }
-}
-EXPORT_SYMBOL(drm_mode_validate_clocks);
-
-/**
- * drm_mode_prune_invalid - remove invalid modes from mode list
- * @dev: DRM device
- * @mode_list: list of modes to check
- * @verbose: be verbose about it
- *
- * LOCKING:
- * Caller must hold a lock protecting @mode_list.
- *
- * Once mode list generation is complete, a caller can use this routine to
- * remove invalid modes from a mode list. If any of the modes have a
- * status other than %MODE_OK, they are removed from @mode_list and freed.
- */
-void drm_mode_prune_invalid(struct drm_device *dev,
- struct list_head *mode_list, bool verbose)
-{
- struct drm_display_mode *mode, *t;
-
- list_for_each_entry_safe(mode, t, mode_list, head) {
- if (mode->status != MODE_OK) {
- list_del(&mode->head);
- if (verbose) {
- drm_mode_debug_printmodeline(mode);
- DRM_DEBUG_KMS("Not using %s mode %d\n",
- mode->name, mode->status);
- }
- drm_mode_destroy(dev, mode);
- }
- }
-}
-EXPORT_SYMBOL(drm_mode_prune_invalid);
-
-/**
- * drm_mode_compare - compare modes for favorability
- * @priv: unused
- * @lh_a: list_head for first mode
- * @lh_b: list_head for second mode
- *
- * LOCKING:
- * None.
- *
- * Compare two modes, given by @lh_a and @lh_b, returning a value indicating
- * which is better.
- *
- * RETURNS:
- * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or
- * positive if @lh_b is better than @lh_a.
- */
-static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head *lh_b)
-{
- struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head);
- struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head);
- int diff;
-
- diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) -
- ((a->type & DRM_MODE_TYPE_PREFERRED) != 0);
- if (diff)
- return diff;
- diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
- if (diff)
- return diff;
- diff = b->clock - a->clock;
- return diff;
-}
-
-/**
- * drm_mode_sort - sort mode list
- * @mode_list: list to sort
- *
- * LOCKING:
- * Caller must hold a lock protecting @mode_list.
- *
- * Sort @mode_list by favorability, putting good modes first.
- */
-void drm_mode_sort(struct list_head *mode_list)
-{
- list_sort(NULL, mode_list, drm_mode_compare);
-}
-EXPORT_SYMBOL(drm_mode_sort);
-
-/**
- * drm_mode_connector_list_update - update the mode list for the connector
- * @connector: the connector to update
- *
- * LOCKING:
- * Caller must hold a lock protecting @mode_list.
- *
- * This moves the modes from the @connector probed_modes list
- * to the actual mode list. It compares the probed mode against the current
- * list and only adds different modes. All modes unverified after this point
- * will be removed by the prune invalid modes.
- */
-void drm_mode_connector_list_update(struct drm_connector *connector)
-{
- struct drm_display_mode *mode;
- struct drm_display_mode *pmode, *pt;
- int found_it;
-
- list_for_each_entry_safe(pmode, pt, &connector->probed_modes,
- head) {
- found_it = 0;
- /* go through current modes checking for the new probed mode */
- list_for_each_entry(mode, &connector->modes, head) {
- if (drm_mode_equal(pmode, mode)) {
- found_it = 1;
- /* if equal delete the probed mode */
- mode->status = pmode->status;
- /* Merge type bits together */
- mode->type |= pmode->type;
- list_del(&pmode->head);
- drm_mode_destroy(connector->dev, pmode);
- break;
- }
- }
-
- if (!found_it) {
- list_move_tail(&pmode->head, &connector->modes);
- }
- }
-}
-EXPORT_SYMBOL(drm_mode_connector_list_update);
+++ /dev/null
-/* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */
-/**
- * \file drm_pci.c
- * \brief Functions and ioctls to manage PCI memory
- *
- * \warning These interfaces aren't stable yet.
- *
- * \todo Implement the remaining ioctl's for the PCI pools.
- * \todo The wrappers here are so thin that they would be better off inlined..
- *
- * \author José Fonseca <jrfonseca@tungstengraphics.com>
- * \author Leif Delgass <ldelgass@retinalburn.net>
- */
-
-/*
- * Copyright 2003 José Fonseca.
- * Copyright 2003 Leif Delgass.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include "drmP.h"
-
-/**********************************************************************/
-/** \name PCI memory */
-/*@{*/
-
-/**
- * \brief Allocate a PCI consistent memory block, for DMA.
- */
-drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align)
-{
- drm_dma_handle_t *dmah;
-#if 1
- unsigned long addr;
- size_t sz;
-#endif
-
- /* pci_alloc_consistent only guarantees alignment to the smallest
- * PAGE_SIZE order which is greater than or equal to the requested size.
- * Return NULL here for now to make sure nobody tries for larger alignment
- */
- if (align > size)
- return NULL;
-
- dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
- if (!dmah)
- return NULL;
-
- dmah->size = size;
- dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP);
-
- if (dmah->vaddr == NULL) {
- kfree(dmah);
- return NULL;
- }
-
- memset(dmah->vaddr, 0, size);
-
- /* XXX - Is virt_to_page() legal for consistent mem? */
- /* Reserve */
- for (addr = (unsigned long)dmah->vaddr, sz = size;
- sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
- SetPageReserved(virt_to_page(addr));
- }
-
- return dmah;
-}
-
-EXPORT_SYMBOL(drm_pci_alloc);
-
-/**
- * \brief Free a PCI consistent memory block without freeing its descriptor.
- *
- * This function is for internal use in the Linux-specific DRM core code.
- */
-void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
-{
-#if 1
- unsigned long addr;
- size_t sz;
-#endif
-
- if (dmah->vaddr) {
- /* XXX - Is virt_to_page() legal for consistent mem? */
- /* Unreserve */
- for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
- sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
- ClearPageReserved(virt_to_page(addr));
- }
- dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
- dmah->busaddr);
- }
-}
-
-/**
- * \brief Free a PCI consistent memory block
- */
-void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
-{
- __drm_pci_free(dev, dmah);
- kfree(dmah);
-}
-
-EXPORT_SYMBOL(drm_pci_free);
-
-#ifdef CONFIG_PCI
-/**
- * Register.
- *
- * \param pdev - PCI device structure
- * \param ent entry from the PCI ID table with device type flags
- * \return zero on success or a negative number on failure.
- *
- * Attempt to gets inter module "drm" information. If we are first
- * then register the character device and inter module information.
- * Try and register, if we fail to register, backout previous work.
- */
-int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
- struct drm_driver *driver)
-{
- struct drm_device *dev;
- int ret;
-
- DRM_DEBUG("\n");
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
-
- ret = pci_enable_device(pdev);
- if (ret)
- goto err_g1;
-
- pci_set_master(pdev);
-
- dev->pdev = pdev;
- dev->dev = &pdev->dev;
-
- dev->pci_device = pdev->device;
- dev->pci_vendor = pdev->vendor;
-
-#ifdef __alpha__
- dev->hose = pdev->sysdata;
-#endif
-
- mutex_lock(&drm_global_mutex);
-
- if ((ret = drm_fill_in_dev(dev, ent, driver))) {
- printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
- goto err_g2;
- }
-
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- pci_set_drvdata(pdev, dev);
- ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
- if (ret)
- goto err_g2;
- }
-
- if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
- goto err_g3;
-
- if (dev->driver->load) {
- ret = dev->driver->load(dev, ent->driver_data);
- if (ret)
- goto err_g4;
- }
-
- /* setup the grouping for the legacy output */
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- ret = drm_mode_group_init_legacy_group(dev,
- &dev->primary->mode_group);
- if (ret)
- goto err_g4;
- }
-
- list_add_tail(&dev->driver_item, &driver->device_list);
-
- DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
- driver->name, driver->major, driver->minor, driver->patchlevel,
- driver->date, pci_name(pdev), dev->primary->index);
-
- mutex_unlock(&drm_global_mutex);
- return 0;
-
-err_g4:
- drm_put_minor(&dev->primary);
-err_g3:
- if (drm_core_check_feature(dev, DRIVER_MODESET))
- drm_put_minor(&dev->control);
-err_g2:
- pci_disable_device(pdev);
-err_g1:
- kfree(dev);
- mutex_unlock(&drm_global_mutex);
- return ret;
-}
-EXPORT_SYMBOL(drm_get_pci_dev);
-
-/**
- * PCI device initialization. Called via drm_init at module load time,
- *
- * \return zero on success or a negative number on failure.
- *
- * Initializes a drm_device structures,registering the
- * stubs and initializing the AGP device.
- *
- * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
- * after the initialization for driver customization.
- */
-int drm_pci_init(struct drm_driver *driver)
-{
- struct pci_dev *pdev = NULL;
- const struct pci_device_id *pid;
- int i;
-
- if (driver->driver_features & DRIVER_MODESET)
- return pci_register_driver(&driver->pci_driver);
-
- /* If not using KMS, fall back to stealth mode manual scanning. */
- for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
- pid = &driver->pci_driver.id_table[i];
-
- /* Loop around setting up a DRM device for each PCI device
- * matching our ID and device class. If we had the internal
- * function that pci_get_subsys and pci_get_class used, we'd
- * be able to just pass pid in instead of doing a two-stage
- * thing.
- */
- pdev = NULL;
- while ((pdev =
- pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
- pid->subdevice, pdev)) != NULL) {
- if ((pdev->class & pid->class_mask) != pid->class)
- continue;
-
- /* stealth mode requires a manual probe */
- pci_dev_get(pdev);
- drm_get_pci_dev(pdev, pid, driver);
- }
- }
- return 0;
-}
-
-#else
-
-int drm_pci_init(struct drm_driver *driver)
-{
- return -1;
-}
-
-#endif
-/*@}*/
+++ /dev/null
-/*
- * Derived from drm_pci.c
- *
- * Copyright 2003 José Fonseca.
- * Copyright 2003 Leif Delgass.
- * Copyright (c) 2009, Code Aurora Forum.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-/**
- * Register.
- *
- * \param platdev - Platform device struture
- * \return zero on success or a negative number on failure.
- *
- * Attempt to gets inter module "drm" information. If we are first
- * then register the character device and inter module information.
- * Try and register, if we fail to register, backout previous work.
- */
-
-int drm_get_platform_dev(struct platform_device *platdev,
- struct drm_driver *driver)
-{
- struct drm_device *dev;
- int ret;
-
- DRM_DEBUG("\n");
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
-
- dev->platformdev = platdev;
- dev->dev = &platdev->dev;
-
- mutex_lock(&drm_global_mutex);
-
- ret = drm_fill_in_dev(dev, NULL, driver);
-
- if (ret) {
- printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
- goto err_g1;
- }
-
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- dev_set_drvdata(&platdev->dev, dev);
- ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
- if (ret)
- goto err_g1;
- }
-
- ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY);
- if (ret)
- goto err_g2;
-
- if (dev->driver->load) {
- ret = dev->driver->load(dev, 0);
- if (ret)
- goto err_g3;
- }
-
- /* setup the grouping for the legacy output */
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- ret = drm_mode_group_init_legacy_group(dev,
- &dev->primary->mode_group);
- if (ret)
- goto err_g3;
- }
-
- list_add_tail(&dev->driver_item, &driver->device_list);
-
- mutex_unlock(&drm_global_mutex);
-
- DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
- driver->name, driver->major, driver->minor, driver->patchlevel,
- driver->date, dev->primary->index);
-
- return 0;
-
-err_g3:
- drm_put_minor(&dev->primary);
-err_g2:
- if (drm_core_check_feature(dev, DRIVER_MODESET))
- drm_put_minor(&dev->control);
-err_g1:
- kfree(dev);
- mutex_unlock(&drm_global_mutex);
- return ret;
-}
-EXPORT_SYMBOL(drm_get_platform_dev);
-
-/**
- * Platform device initialization. Called via drm_init at module load time,
- *
- * \return zero on success or a negative number on failure.
- *
- * Initializes a drm_device structures,registering the
- * stubs
- *
- * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
- * after the initialization for driver customization.
- */
-
-int drm_platform_init(struct drm_driver *driver)
-{
- return drm_get_platform_dev(driver->platform_device, driver);
-}
+++ /dev/null
-/**
- * \file drm_proc.c
- * /proc support for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- *
- * \par Acknowledgements:
- * Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix
- * the problem with the proc files not outputting all their information.
- */
-
-/*
- * Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include "drmP.h"
-
-/***************************************************
- * Initialization, etc.
- **************************************************/
-
-/**
- * Proc file list.
- */
-static struct drm_info_list drm_proc_list[] = {
- {"name", drm_name_info, 0},
- {"vm", drm_vm_info, 0},
- {"clients", drm_clients_info, 0},
- {"queues", drm_queues_info, 0},
- {"bufs", drm_bufs_info, 0},
- {"gem_names", drm_gem_name_info, DRIVER_GEM},
-#if DRM_DEBUG_CODE
- {"vma", drm_vma_info, 0},
-#endif
-};
-#define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)
-
-static int drm_proc_open(struct inode *inode, struct file *file)
-{
- struct drm_info_node* node = PDE(inode)->data;
-
- return single_open(file, node->info_ent->show, node);
-}
-
-static const struct file_operations drm_proc_fops = {
- .owner = THIS_MODULE,
- .open = drm_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-
-/**
- * Initialize a given set of proc files for a device
- *
- * \param files The array of files to create
- * \param count The number of files given
- * \param root DRI proc dir entry.
- * \param minor device minor number
- * \return Zero on success, non-zero on failure
- *
- * Create a given set of proc files represented by an array of
- * gdm_proc_lists in the given root directory.
- */
-int drm_proc_create_files(struct drm_info_list *files, int count,
- struct proc_dir_entry *root, struct drm_minor *minor)
-{
- struct drm_device *dev = minor->dev;
- struct proc_dir_entry *ent;
- struct drm_info_node *tmp;
- char name[64];
- int i, ret;
-
- for (i = 0; i < count; i++) {
- u32 features = files[i].driver_features;
-
- if (features != 0 &&
- (dev->driver->driver_features & features) != features)
- continue;
-
- tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
- if (tmp == NULL) {
- ret = -1;
- goto fail;
- }
- tmp->minor = minor;
- tmp->info_ent = &files[i];
- list_add(&tmp->list, &minor->proc_nodes.list);
-
- ent = proc_create_data(files[i].name, S_IRUGO, root,
- &drm_proc_fops, tmp);
- if (!ent) {
- DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
- name, files[i].name);
- list_del(&tmp->list);
- kfree(tmp);
- ret = -1;
- goto fail;
- }
-
- }
- return 0;
-
-fail:
- for (i = 0; i < count; i++)
- remove_proc_entry(drm_proc_list[i].name, minor->proc_root);
- return ret;
-}
-
-/**
- * Initialize the DRI proc filesystem for a device
- *
- * \param dev DRM device
- * \param minor device minor number
- * \param root DRI proc dir entry.
- * \param dev_root resulting DRI device proc dir entry.
- * \return root entry pointer on success, or NULL on failure.
- *
- * Create the DRI proc root entry "/proc/dri", the device proc root entry
- * "/proc/dri/%minor%/", and each entry in proc_list as
- * "/proc/dri/%minor%/%name%".
- */
-int drm_proc_init(struct drm_minor *minor, int minor_id,
- struct proc_dir_entry *root)
-{
- char name[64];
- int ret;
-
- INIT_LIST_HEAD(&minor->proc_nodes.list);
- sprintf(name, "%d", minor_id);
- minor->proc_root = proc_mkdir(name, root);
- if (!minor->proc_root) {
- DRM_ERROR("Cannot create /proc/dri/%s\n", name);
- return -1;
- }
-
- ret = drm_proc_create_files(drm_proc_list, DRM_PROC_ENTRIES,
- minor->proc_root, minor);
- if (ret) {
- remove_proc_entry(name, root);
- minor->proc_root = NULL;
- DRM_ERROR("Failed to create core drm proc files\n");
- return ret;
- }
-
- return 0;
-}
-
-int drm_proc_remove_files(struct drm_info_list *files, int count,
- struct drm_minor *minor)
-{
- struct list_head *pos, *q;
- struct drm_info_node *tmp;
- int i;
-
- for (i = 0; i < count; i++) {
- list_for_each_safe(pos, q, &minor->proc_nodes.list) {
- tmp = list_entry(pos, struct drm_info_node, list);
- if (tmp->info_ent == &files[i]) {
- remove_proc_entry(files[i].name,
- minor->proc_root);
- list_del(pos);
- kfree(tmp);
- }
- }
- }
- return 0;
-}
-
-/**
- * Cleanup the proc filesystem resources.
- *
- * \param minor device minor number.
- * \param root DRI proc dir entry.
- * \param dev_root DRI device proc dir entry.
- * \return always zero.
- *
- * Remove all proc entries created by proc_init().
- */
-int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
-{
- char name[64];
-
- if (!root || !minor->proc_root)
- return 0;
-
- drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor);
-
- sprintf(name, "%d", minor->index);
- remove_proc_entry(name, root);
-
- return 0;
-}
-
+++ /dev/null
-/**
- * \file drm_scatter.c
- * IOCTLs to manage scatter/gather memory
- *
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
- *
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include "drmP.h"
-
-#define DEBUG_SCATTER 0
-
-static inline void *drm_vmalloc_dma(unsigned long size)
-{
-#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
- return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL | _PAGE_NO_CACHE);
-#else
- return vmalloc_32(size);
-#endif
-}
-
-void drm_sg_cleanup(struct drm_sg_mem * entry)
-{
- struct page *page;
- int i;
-
- for (i = 0; i < entry->pages; i++) {
- page = entry->pagelist[i];
- if (page)
- ClearPageReserved(page);
- }
-
- vfree(entry->virtual);
-
- kfree(entry->busaddr);
- kfree(entry->pagelist);
- kfree(entry);
-}
-
-#ifdef _LP64
-# define ScatterHandle(x) (unsigned int)((x >> 32) + (x & ((1L << 32) - 1)))
-#else
-# define ScatterHandle(x) (unsigned int)(x)
-#endif
-
-int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
-{
- struct drm_sg_mem *entry;
- unsigned long pages, i, j;
-
- DRM_DEBUG("\n");
-
- if (!drm_core_check_feature(dev, DRIVER_SG))
- return -EINVAL;
-
- if (dev->sg)
- return -EINVAL;
-
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry)
- return -ENOMEM;
-
- memset(entry, 0, sizeof(*entry));
- pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
- DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages);
-
- entry->pages = pages;
- entry->pagelist = kmalloc(pages * sizeof(*entry->pagelist), GFP_KERNEL);
- if (!entry->pagelist) {
- kfree(entry);
- return -ENOMEM;
- }
-
- memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
-
- entry->busaddr = kmalloc(pages * sizeof(*entry->busaddr), GFP_KERNEL);
- if (!entry->busaddr) {
- kfree(entry->pagelist);
- kfree(entry);
- return -ENOMEM;
- }
- memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
-
- entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT);
- if (!entry->virtual) {
- kfree(entry->busaddr);
- kfree(entry->pagelist);
- kfree(entry);
- return -ENOMEM;
- }
-
- /* This also forces the mapping of COW pages, so our page list
- * will be valid. Please don't remove it...
- */
- memset(entry->virtual, 0, pages << PAGE_SHIFT);
-
- entry->handle = ScatterHandle((unsigned long)entry->virtual);
-
- DRM_DEBUG("handle = %08lx\n", entry->handle);
- DRM_DEBUG("virtual = %p\n", entry->virtual);
-
- for (i = (unsigned long)entry->virtual, j = 0; j < pages;
- i += PAGE_SIZE, j++) {
- entry->pagelist[j] = vmalloc_to_page((void *)i);
- if (!entry->pagelist[j])
- goto failed;
- SetPageReserved(entry->pagelist[j]);
- }
-
- request->handle = entry->handle;
-
- dev->sg = entry;
-
-#if DEBUG_SCATTER
- /* Verify that each page points to its virtual address, and vice
- * versa.
- */
- {
- int error = 0;
-
- for (i = 0; i < pages; i++) {
- unsigned long *tmp;
-
- tmp = page_address(entry->pagelist[i]);
- for (j = 0;
- j < PAGE_SIZE / sizeof(unsigned long);
- j++, tmp++) {
- *tmp = 0xcafebabe;
- }
- tmp = (unsigned long *)((u8 *) entry->virtual +
- (PAGE_SIZE * i));
- for (j = 0;
- j < PAGE_SIZE / sizeof(unsigned long);
- j++, tmp++) {
- if (*tmp != 0xcafebabe && error == 0) {
- error = 1;
- DRM_ERROR("Scatter allocation error, "
- "pagelist does not match "
- "virtual mapping\n");
- }
- }
- tmp = page_address(entry->pagelist[i]);
- for (j = 0;
- j < PAGE_SIZE / sizeof(unsigned long);
- j++, tmp++) {
- *tmp = 0;
- }
- }
- if (error == 0)
- DRM_ERROR("Scatter allocation matches pagelist\n");
- }
-#endif
-
- return 0;
-
- failed:
- drm_sg_cleanup(entry);
- return -ENOMEM;
-}
-
-int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_scatter_gather *request = data;
-
- return drm_sg_alloc(dev, request);
-
-}
-
-int drm_sg_free(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_scatter_gather *request = data;
- struct drm_sg_mem *entry;
-
- if (!drm_core_check_feature(dev, DRIVER_SG))
- return -EINVAL;
-
- entry = dev->sg;
- dev->sg = NULL;
-
- if (!entry || entry->handle != request->handle)
- return -EINVAL;
-
- DRM_DEBUG("virtual = %p\n", entry->virtual);
-
- drm_sg_cleanup(entry);
-
- return 0;
-}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck., ND., USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- *
- **************************************************************************/
-/*
- * Simple memory manager interface that keeps track on allocate regions on a
- * per "owner" basis. All regions associated with an "owner" can be released
- * with a simple call. Typically if the "owner" exists. The owner is any
- * "unsigned long" identifier. Can typically be a pointer to a file private
- * struct or a context identifier.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include "drm_sman.h"
-
-struct drm_owner_item {
- struct drm_hash_item owner_hash;
- struct list_head sman_list;
- struct list_head mem_blocks;
-};
-
-void drm_sman_takedown(struct drm_sman * sman)
-{
- drm_ht_remove(&sman->user_hash_tab);
- drm_ht_remove(&sman->owner_hash_tab);
- kfree(sman->mm);
-}
-
-EXPORT_SYMBOL(drm_sman_takedown);
-
-int
-drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
- unsigned int user_order, unsigned int owner_order)
-{
- int ret = 0;
-
- sman->mm = (struct drm_sman_mm *) kcalloc(num_managers,
- sizeof(*sman->mm),
- GFP_KERNEL);
- if (!sman->mm) {
- ret = -ENOMEM;
- goto out;
- }
- sman->num_managers = num_managers;
- INIT_LIST_HEAD(&sman->owner_items);
- ret = drm_ht_create(&sman->owner_hash_tab, owner_order);
- if (ret)
- goto out1;
- ret = drm_ht_create(&sman->user_hash_tab, user_order);
- if (!ret)
- goto out;
-
- drm_ht_remove(&sman->owner_hash_tab);
-out1:
- kfree(sman->mm);
-out:
- return ret;
-}
-
-EXPORT_SYMBOL(drm_sman_init);
-
-static void *drm_sman_mm_allocate(void *private, unsigned long size,
- unsigned alignment)
-{
- struct drm_mm *mm = (struct drm_mm *) private;
- struct drm_mm_node *tmp;
-
- tmp = drm_mm_search_free(mm, size, alignment, 1);
- if (!tmp) {
- return NULL;
- }
- tmp = drm_mm_get_block(tmp, size, alignment);
- return tmp;
-}
-
-static void drm_sman_mm_free(void *private, void *ref)
-{
- struct drm_mm_node *node = (struct drm_mm_node *) ref;
-
- drm_mm_put_block(node);
-}
-
-static void drm_sman_mm_destroy(void *private)
-{
- struct drm_mm *mm = (struct drm_mm *) private;
- drm_mm_takedown(mm);
- kfree(mm);
-}
-
-static unsigned long drm_sman_mm_offset(void *private, void *ref)
-{
- struct drm_mm_node *node = (struct drm_mm_node *) ref;
- return node->start;
-}
-
-int
-drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
- unsigned long start, unsigned long size)
-{
- struct drm_sman_mm *sman_mm;
- struct drm_mm *mm;
- int ret;
-
- BUG_ON(manager >= sman->num_managers);
-
- sman_mm = &sman->mm[manager];
- mm = kzalloc(sizeof(*mm), GFP_KERNEL);
- if (!mm) {
- return -ENOMEM;
- }
- sman_mm->private = mm;
- ret = drm_mm_init(mm, start, size);
-
- if (ret) {
- kfree(mm);
- return ret;
- }
-
- sman_mm->allocate = drm_sman_mm_allocate;
- sman_mm->free = drm_sman_mm_free;
- sman_mm->destroy = drm_sman_mm_destroy;
- sman_mm->offset = drm_sman_mm_offset;
-
- return 0;
-}
-
-EXPORT_SYMBOL(drm_sman_set_range);
-
-int
-drm_sman_set_manager(struct drm_sman * sman, unsigned int manager,
- struct drm_sman_mm * allocator)
-{
- BUG_ON(manager >= sman->num_managers);
- sman->mm[manager] = *allocator;
-
- return 0;
-}
-EXPORT_SYMBOL(drm_sman_set_manager);
-
-static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
- unsigned long owner)
-{
- int ret;
- struct drm_hash_item *owner_hash_item;
- struct drm_owner_item *owner_item;
-
- ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
- if (!ret) {
- return drm_hash_entry(owner_hash_item, struct drm_owner_item,
- owner_hash);
- }
-
- owner_item = kzalloc(sizeof(*owner_item), GFP_KERNEL);
- if (!owner_item)
- goto out;
-
- INIT_LIST_HEAD(&owner_item->mem_blocks);
- owner_item->owner_hash.key = owner;
- if (drm_ht_insert_item(&sman->owner_hash_tab, &owner_item->owner_hash))
- goto out1;
-
- list_add_tail(&owner_item->sman_list, &sman->owner_items);
- return owner_item;
-
-out1:
- kfree(owner_item);
-out:
- return NULL;
-}
-
-struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager,
- unsigned long size, unsigned alignment,
- unsigned long owner)
-{
- void *tmp;
- struct drm_sman_mm *sman_mm;
- struct drm_owner_item *owner_item;
- struct drm_memblock_item *memblock;
-
- BUG_ON(manager >= sman->num_managers);
-
- sman_mm = &sman->mm[manager];
- tmp = sman_mm->allocate(sman_mm->private, size, alignment);
-
- if (!tmp) {
- return NULL;
- }
-
- memblock = kzalloc(sizeof(*memblock), GFP_KERNEL);
-
- if (!memblock)
- goto out;
-
- memblock->mm_info = tmp;
- memblock->mm = sman_mm;
- memblock->sman = sman;
-
- if (drm_ht_just_insert_please
- (&sman->user_hash_tab, &memblock->user_hash,
- (unsigned long)memblock, 32, 0, 0))
- goto out1;
-
- owner_item = drm_sman_get_owner_item(sman, owner);
- if (!owner_item)
- goto out2;
-
- list_add_tail(&memblock->owner_list, &owner_item->mem_blocks);
-
- return memblock;
-
-out2:
- drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash);
-out1:
- kfree(memblock);
-out:
- sman_mm->free(sman_mm->private, tmp);
-
- return NULL;
-}
-
-EXPORT_SYMBOL(drm_sman_alloc);
-
-static void drm_sman_free(struct drm_memblock_item *item)
-{
- struct drm_sman *sman = item->sman;
-
- list_del(&item->owner_list);
- drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
- item->mm->free(item->mm->private, item->mm_info);
- kfree(item);
-}
-
-int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
-{
- struct drm_hash_item *hash_item;
- struct drm_memblock_item *memblock_item;
-
- if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
- return -EINVAL;
-
- memblock_item = drm_hash_entry(hash_item, struct drm_memblock_item,
- user_hash);
- drm_sman_free(memblock_item);
- return 0;
-}
-
-EXPORT_SYMBOL(drm_sman_free_key);
-
-static void drm_sman_remove_owner(struct drm_sman *sman,
- struct drm_owner_item *owner_item)
-{
- list_del(&owner_item->sman_list);
- drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
- kfree(owner_item);
-}
-
-int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
-{
-
- struct drm_hash_item *hash_item;
- struct drm_owner_item *owner_item;
-
- if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
- return -1;
- }
-
- owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
- if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
- drm_sman_remove_owner(sman, owner_item);
- return -1;
- }
-
- return 0;
-}
-
-EXPORT_SYMBOL(drm_sman_owner_clean);
-
-static void drm_sman_do_owner_cleanup(struct drm_sman *sman,
- struct drm_owner_item *owner_item)
-{
- struct drm_memblock_item *entry, *next;
-
- list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
- owner_list) {
- drm_sman_free(entry);
- }
- drm_sman_remove_owner(sman, owner_item);
-}
-
-void drm_sman_owner_cleanup(struct drm_sman *sman, unsigned long owner)
-{
-
- struct drm_hash_item *hash_item;
- struct drm_owner_item *owner_item;
-
- if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
-
- return;
- }
-
- owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
- drm_sman_do_owner_cleanup(sman, owner_item);
-}
-
-EXPORT_SYMBOL(drm_sman_owner_cleanup);
-
-void drm_sman_cleanup(struct drm_sman *sman)
-{
- struct drm_owner_item *entry, *next;
- unsigned int i;
- struct drm_sman_mm *sman_mm;
-
- list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
- drm_sman_do_owner_cleanup(sman, entry);
- }
- if (sman->mm) {
- for (i = 0; i < sman->num_managers; ++i) {
- sman_mm = &sman->mm[i];
- if (sman_mm->private) {
- sman_mm->destroy(sman_mm->private);
- sman_mm->private = NULL;
- }
- }
- }
-}
-
-EXPORT_SYMBOL(drm_sman_cleanup);
+++ /dev/null
-/**
- * \file drm_stub.h
- * Stub support
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- */
-
-/*
- * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
- *
- * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-#include "drmP.h"
-#include "drm_core.h"
-
-unsigned int drm_debug = 0; /* 1 to enable debug output */
-EXPORT_SYMBOL(drm_debug);
-
-MODULE_AUTHOR(CORE_AUTHOR);
-MODULE_DESCRIPTION(CORE_DESC);
-MODULE_LICENSE("GPL and additional rights");
-MODULE_PARM_DESC(debug, "Enable debug output");
-
-module_param_named(debug, drm_debug, int, 0600);
-
-struct idr drm_minors_idr;
-
-struct class *drm_class;
-struct proc_dir_entry *drm_proc_root;
-struct dentry *drm_debugfs_root;
-void drm_ut_debug_printk(unsigned int request_level,
- const char *prefix,
- const char *function_name,
- const char *format, ...)
-{
- va_list args;
-
- if (drm_debug & request_level) {
- if (function_name)
- printk(KERN_DEBUG "[%s:%s], ", prefix, function_name);
- va_start(args, format);
- vprintk(format, args);
- va_end(args);
- }
-}
-EXPORT_SYMBOL(drm_ut_debug_printk);
-static int drm_minor_get_id(struct drm_device *dev, int type)
-{
- int new_id;
- int ret;
- int base = 0, limit = 63;
-
- if (type == DRM_MINOR_CONTROL) {
- base += 64;
- limit = base + 127;
- } else if (type == DRM_MINOR_RENDER) {
- base += 128;
- limit = base + 255;
- }
-
-again:
- if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
- DRM_ERROR("Out of memory expanding drawable idr\n");
- return -ENOMEM;
- }
- mutex_lock(&dev->struct_mutex);
- ret = idr_get_new_above(&drm_minors_idr, NULL,
- base, &new_id);
- mutex_unlock(&dev->struct_mutex);
- if (ret == -EAGAIN) {
- goto again;
- } else if (ret) {
- return ret;
- }
-
- if (new_id >= limit) {
- idr_remove(&drm_minors_idr, new_id);
- return -EINVAL;
- }
- return new_id;
-}
-
-struct drm_master *drm_master_create(struct drm_minor *minor)
-{
- struct drm_master *master;
-
- master = kzalloc(sizeof(*master), GFP_KERNEL);
- if (!master)
- return NULL;
-
- kref_init(&master->refcount);
- spin_lock_init(&master->lock.spinlock);
- init_waitqueue_head(&master->lock.lock_queue);
- drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
- INIT_LIST_HEAD(&master->magicfree);
- master->minor = minor;
-
- list_add_tail(&master->head, &minor->master_list);
-
- return master;
-}
-
-struct drm_master *drm_master_get(struct drm_master *master)
-{
- kref_get(&master->refcount);
- return master;
-}
-EXPORT_SYMBOL(drm_master_get);
-
-static void drm_master_destroy(struct kref *kref)
-{
- struct drm_master *master = container_of(kref, struct drm_master, refcount);
- struct drm_magic_entry *pt, *next;
- struct drm_device *dev = master->minor->dev;
- struct drm_map_list *r_list, *list_temp;
-
- list_del(&master->head);
-
- if (dev->driver->master_destroy)
- dev->driver->master_destroy(dev, master);
-
- list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
- if (r_list->master == master) {
- drm_rmmap_locked(dev, r_list->map);
- r_list = NULL;
- }
- }
-
- if (master->unique) {
- kfree(master->unique);
- master->unique = NULL;
- master->unique_len = 0;
- }
-
- kfree(dev->devname);
- dev->devname = NULL;
-
- list_for_each_entry_safe(pt, next, &master->magicfree, head) {
- list_del(&pt->head);
- drm_ht_remove_item(&master->magiclist, &pt->hash_item);
- kfree(pt);
- }
-
- drm_ht_remove(&master->magiclist);
-
- kfree(master);
-}
-
-void drm_master_put(struct drm_master **master)
-{
- kref_put(&(*master)->refcount, drm_master_destroy);
- *master = NULL;
-}
-EXPORT_SYMBOL(drm_master_put);
-
-int drm_setmaster_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- int ret = 0;
-
- if (file_priv->is_master)
- return 0;
-
- if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
- return -EINVAL;
-
- if (!file_priv->master)
- return -EINVAL;
-
- if (!file_priv->minor->master &&
- file_priv->minor->master != file_priv->master) {
- mutex_lock(&dev->struct_mutex);
- file_priv->minor->master = drm_master_get(file_priv->master);
- file_priv->is_master = 1;
- if (dev->driver->master_set) {
- ret = dev->driver->master_set(dev, file_priv, false);
- if (unlikely(ret != 0)) {
- file_priv->is_master = 0;
- drm_master_put(&file_priv->minor->master);
- }
- }
- mutex_unlock(&dev->struct_mutex);
- }
-
- return 0;
-}
-
-int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- if (!file_priv->is_master)
- return -EINVAL;
-
- if (!file_priv->minor->master)
- return -EINVAL;
-
- mutex_lock(&dev->struct_mutex);
- if (dev->driver->master_drop)
- dev->driver->master_drop(dev, file_priv, false);
- drm_master_put(&file_priv->minor->master);
- file_priv->is_master = 0;
- mutex_unlock(&dev->struct_mutex);
- return 0;
-}
-
-int drm_fill_in_dev(struct drm_device *dev,
- const struct pci_device_id *ent,
- struct drm_driver *driver)
-{
- int retcode;
-
- INIT_LIST_HEAD(&dev->filelist);
- INIT_LIST_HEAD(&dev->ctxlist);
- INIT_LIST_HEAD(&dev->vmalist);
- INIT_LIST_HEAD(&dev->maplist);
- INIT_LIST_HEAD(&dev->vblank_event_list);
-
- spin_lock_init(&dev->count_lock);
- spin_lock_init(&dev->event_lock);
- mutex_init(&dev->struct_mutex);
- mutex_init(&dev->ctxlist_mutex);
-
- if (drm_ht_create(&dev->map_hash, 12)) {
- return -ENOMEM;
- }
-
- /* the DRM has 6 basic counters */
- dev->counters = 6;
- dev->types[0] = _DRM_STAT_LOCK;
- dev->types[1] = _DRM_STAT_OPENS;
- dev->types[2] = _DRM_STAT_CLOSES;
- dev->types[3] = _DRM_STAT_IOCTLS;
- dev->types[4] = _DRM_STAT_LOCKS;
- dev->types[5] = _DRM_STAT_UNLOCKS;
-
- dev->driver = driver;
-
- if (drm_core_has_AGP(dev)) {
- if (drm_device_is_agp(dev))
- dev->agp = drm_agp_init(dev);
- if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
- && (dev->agp == NULL)) {
- DRM_ERROR("Cannot initialize the agpgart module.\n");
- retcode = -EINVAL;
- goto error_out_unreg;
- }
- if (drm_core_has_MTRR(dev)) {
- if (dev->agp)
- dev->agp->agp_mtrr =
- mtrr_add(dev->agp->agp_info.aper_base,
- dev->agp->agp_info.aper_size *
- 1024 * 1024, MTRR_TYPE_WRCOMB, 1);
- }
- }
-
-
- retcode = drm_ctxbitmap_init(dev);
- if (retcode) {
- DRM_ERROR("Cannot allocate memory for context bitmap.\n");
- goto error_out_unreg;
- }
-
- if (driver->driver_features & DRIVER_GEM) {
- retcode = drm_gem_init(dev);
- if (retcode) {
- DRM_ERROR("Cannot initialize graphics execution "
- "manager (GEM)\n");
- goto error_out_unreg;
- }
- }
-
- return 0;
-
- error_out_unreg:
- drm_lastclose(dev);
- return retcode;
-}
-
-
-/**
- * Get a secondary minor number.
- *
- * \param dev device data structure
- * \param sec-minor structure to hold the assigned minor
- * \return negative number on failure.
- *
- * Search an empty entry and initialize it to the given parameters, and
- * create the proc init entry via proc_init(). This routines assigns
- * minor numbers to secondary heads of multi-headed cards
- */
-int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
-{
- struct drm_minor *new_minor;
- int ret;
- int minor_id;
-
- DRM_DEBUG("\n");
-
- minor_id = drm_minor_get_id(dev, type);
- if (minor_id < 0)
- return minor_id;
-
- new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
- if (!new_minor) {
- ret = -ENOMEM;
- goto err_idr;
- }
-
- new_minor->type = type;
- new_minor->device = MKDEV(DRM_MAJOR, minor_id);
- new_minor->dev = dev;
- new_minor->index = minor_id;
- INIT_LIST_HEAD(&new_minor->master_list);
-
- idr_replace(&drm_minors_idr, new_minor, minor_id);
-
- if (type == DRM_MINOR_LEGACY) {
- ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
- if (ret) {
- DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
- goto err_mem;
- }
- } else
- new_minor->proc_root = NULL;
-
-#if defined(CONFIG_DEBUG_FS)
- ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
- if (ret) {
- DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
- goto err_g2;
- }
-#endif
-
- ret = drm_sysfs_device_add(new_minor);
- if (ret) {
- printk(KERN_ERR
- "DRM: Error sysfs_device_add.\n");
- goto err_g2;
- }
- *minor = new_minor;
-
- DRM_DEBUG("new minor assigned %d\n", minor_id);
- return 0;
-
-
-err_g2:
- if (new_minor->type == DRM_MINOR_LEGACY)
- drm_proc_cleanup(new_minor, drm_proc_root);
-err_mem:
- kfree(new_minor);
-err_idr:
- idr_remove(&drm_minors_idr, minor_id);
- *minor = NULL;
- return ret;
-}
-
-/**
- * Put a secondary minor number.
- *
- * \param sec_minor - structure to be released
- * \return always zero
- *
- * Cleans up the proc resources. Not legal for this to be the
- * last minor released.
- *
- */
-int drm_put_minor(struct drm_minor **minor_p)
-{
- struct drm_minor *minor = *minor_p;
-
- DRM_DEBUG("release secondary minor %d\n", minor->index);
-
- if (minor->type == DRM_MINOR_LEGACY)
- drm_proc_cleanup(minor, drm_proc_root);
-#if defined(CONFIG_DEBUG_FS)
- drm_debugfs_cleanup(minor);
-#endif
-
- drm_sysfs_device_remove(minor);
-
- idr_remove(&drm_minors_idr, minor->index);
-
- kfree(minor);
- *minor_p = NULL;
- return 0;
-}
-
-/**
- * Called via drm_exit() at module unload time or when pci device is
- * unplugged.
- *
- * Cleans up all DRM device, calling drm_lastclose().
- *
- * \sa drm_init
- */
-void drm_put_dev(struct drm_device *dev)
-{
- struct drm_driver *driver;
- struct drm_map_list *r_list, *list_temp;
-
- DRM_DEBUG("\n");
-
- if (!dev) {
- DRM_ERROR("cleanup called no dev\n");
- return;
- }
- driver = dev->driver;
-
- drm_lastclose(dev);
-
- if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
- dev->agp && dev->agp->agp_mtrr >= 0) {
- int retval;
- retval = mtrr_del(dev->agp->agp_mtrr,
- dev->agp->agp_info.aper_base,
- dev->agp->agp_info.aper_size * 1024 * 1024);
- DRM_DEBUG("mtrr_del=%d\n", retval);
- }
-
- if (dev->driver->unload)
- dev->driver->unload(dev);
-
- if (drm_core_has_AGP(dev) && dev->agp) {
- kfree(dev->agp);
- dev->agp = NULL;
- }
-
- drm_vblank_cleanup(dev);
-
- list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
- drm_rmmap(dev, r_list->map);
- drm_ht_remove(&dev->map_hash);
-
- drm_ctxbitmap_cleanup(dev);
-
- if (drm_core_check_feature(dev, DRIVER_MODESET))
- drm_put_minor(&dev->control);
-
- if (driver->driver_features & DRIVER_GEM)
- drm_gem_destroy(dev);
-
- drm_put_minor(&dev->primary);
-
- if (dev->devname) {
- kfree(dev->devname);
- dev->devname = NULL;
- }
- kfree(dev);
-}
-EXPORT_SYMBOL(drm_put_dev);
+++ /dev/null
-
-/*
- * drm_sysfs.c - Modifications to drm_sysfs_class.c to support
- * extra sysfs attribute from DRM. Normal drm_sysfs_class
- * does not allow adding attributes.
- *
- * Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com>
- * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (c) 2003-2004 IBM Corp.
- *
- * This file is released under the GPLv2
- *
- */
-
-#include <linux/device.h>
-#include <linux/kdev_t.h>
-#include <linux/gfp.h>
-#include <linux/err.h>
-
-#include "drm_sysfs.h"
-#include "drm_core.h"
-#include "drmP.h"
-
-#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
-#define to_drm_connector(d) container_of(d, struct drm_connector, kdev)
-
-static struct device_type drm_sysfs_device_minor = {
- .name = "drm_minor"
-};
-
-/**
- * drm_class_suspend - DRM class suspend hook
- * @dev: Linux device to suspend
- * @state: power state to enter
- *
- * Just figures out what the actual struct drm_device associated with
- * @dev is and calls its suspend hook, if present.
- */
-static int drm_class_suspend(struct device *dev, pm_message_t state)
-{
- if (dev->type == &drm_sysfs_device_minor) {
- struct drm_minor *drm_minor = to_drm_minor(dev);
- struct drm_device *drm_dev = drm_minor->dev;
-
- if (drm_minor->type == DRM_MINOR_LEGACY &&
- !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
- drm_dev->driver->suspend)
- return drm_dev->driver->suspend(drm_dev, state);
- }
- return 0;
-}
-
-/**
- * drm_class_resume - DRM class resume hook
- * @dev: Linux device to resume
- *
- * Just figures out what the actual struct drm_device associated with
- * @dev is and calls its resume hook, if present.
- */
-static int drm_class_resume(struct device *dev)
-{
- if (dev->type == &drm_sysfs_device_minor) {
- struct drm_minor *drm_minor = to_drm_minor(dev);
- struct drm_device *drm_dev = drm_minor->dev;
-
- if (drm_minor->type == DRM_MINOR_LEGACY &&
- !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
- drm_dev->driver->resume)
- return drm_dev->driver->resume(drm_dev);
- }
- return 0;
-}
-
-static char *drm_devnode(struct device *dev, mode_t *mode)
-{
- return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
-}
-
-static CLASS_ATTR_STRING(version, S_IRUGO,
- CORE_NAME " "
- __stringify(CORE_MAJOR) "."
- __stringify(CORE_MINOR) "."
- __stringify(CORE_PATCHLEVEL) " "
- CORE_DATE);
-
-/**
- * drm_sysfs_create - create a struct drm_sysfs_class structure
- * @owner: pointer to the module that is to "own" this struct drm_sysfs_class
- * @name: pointer to a string for the name of this class.
- *
- * This is used to create DRM class pointer that can then be used
- * in calls to drm_sysfs_device_add().
- *
- * Note, the pointer created here is to be destroyed when finished by making a
- * call to drm_sysfs_destroy().
- */
-struct class *drm_sysfs_create(struct module *owner, char *name)
-{
- struct class *class;
- int err;
-
- class = class_create(owner, name);
- if (IS_ERR(class)) {
- err = PTR_ERR(class);
- goto err_out;
- }
-
- class->suspend = drm_class_suspend;
- class->resume = drm_class_resume;
-
- err = class_create_file(class, &class_attr_version.attr);
- if (err)
- goto err_out_class;
-
- class->devnode = drm_devnode;
-
- return class;
-
-err_out_class:
- class_destroy(class);
-err_out:
- return ERR_PTR(err);
-}
-
-/**
- * drm_sysfs_destroy - destroys DRM class
- *
- * Destroy the DRM device class.
- */
-void drm_sysfs_destroy(void)
-{
- if ((drm_class == NULL) || (IS_ERR(drm_class)))
- return;
- class_remove_file(drm_class, &class_attr_version.attr);
- class_destroy(drm_class);
-}
-
-/**
- * drm_sysfs_device_release - do nothing
- * @dev: Linux device
- *
- * Normally, this would free the DRM device associated with @dev, along
- * with cleaning up any other stuff. But we do that in the DRM core, so
- * this function can just return and hope that the core does its job.
- */
-static void drm_sysfs_device_release(struct device *dev)
-{
- memset(dev, 0, sizeof(struct device));
- return;
-}
-
-/*
- * Connector properties
- */
-static ssize_t status_show(struct device *device,
- struct device_attribute *attr,
- char *buf)
-{
- struct drm_connector *connector = to_drm_connector(device);
- enum drm_connector_status status;
-
- status = connector->funcs->detect(connector, true);
- return snprintf(buf, PAGE_SIZE, "%s\n",
- drm_get_connector_status_name(status));
-}
-
-static ssize_t dpms_show(struct device *device,
- struct device_attribute *attr,
- char *buf)
-{
- struct drm_connector *connector = to_drm_connector(device);
- struct drm_device *dev = connector->dev;
- uint64_t dpms_status;
- int ret;
-
- ret = drm_connector_property_get_value(connector,
- dev->mode_config.dpms_property,
- &dpms_status);
- if (ret)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%s\n",
- drm_get_dpms_name((int)dpms_status));
-}
-
-static ssize_t enabled_show(struct device *device,
- struct device_attribute *attr,
- char *buf)
-{
- struct drm_connector *connector = to_drm_connector(device);
-
- return snprintf(buf, PAGE_SIZE, "%s\n", connector->encoder ? "enabled" :
- "disabled");
-}
-
-static ssize_t edid_show(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t off,
- size_t count)
-{
- struct device *connector_dev = container_of(kobj, struct device, kobj);
- struct drm_connector *connector = to_drm_connector(connector_dev);
- unsigned char *edid;
- size_t size;
-
- if (!connector->edid_blob_ptr)
- return 0;
-
- edid = connector->edid_blob_ptr->data;
- size = connector->edid_blob_ptr->length;
- if (!edid)
- return 0;
-
- if (off >= size)
- return 0;
-
- if (off + count > size)
- count = size - off;
- memcpy(buf, edid + off, count);
-
- return count;
-}
-
-static ssize_t modes_show(struct device *device,
- struct device_attribute *attr,
- char *buf)
-{
- struct drm_connector *connector = to_drm_connector(device);
- struct drm_display_mode *mode;
- int written = 0;
-
- list_for_each_entry(mode, &connector->modes, head) {
- written += snprintf(buf + written, PAGE_SIZE - written, "%s\n",
- mode->name);
- }
-
- return written;
-}
-
-static ssize_t subconnector_show(struct device *device,
- struct device_attribute *attr,
- char *buf)
-{
- struct drm_connector *connector = to_drm_connector(device);
- struct drm_device *dev = connector->dev;
- struct drm_property *prop = NULL;
- uint64_t subconnector;
- int is_tv = 0;
- int ret;
-
- switch (connector->connector_type) {
- case DRM_MODE_CONNECTOR_DVII:
- prop = dev->mode_config.dvi_i_subconnector_property;
- break;
- case DRM_MODE_CONNECTOR_Composite:
- case DRM_MODE_CONNECTOR_SVIDEO:
- case DRM_MODE_CONNECTOR_Component:
- case DRM_MODE_CONNECTOR_TV:
- prop = dev->mode_config.tv_subconnector_property;
- is_tv = 1;
- break;
- default:
- DRM_ERROR("Wrong connector type for this property\n");
- return 0;
- }
-
- if (!prop) {
- DRM_ERROR("Unable to find subconnector property\n");
- return 0;
- }
-
- ret = drm_connector_property_get_value(connector, prop, &subconnector);
- if (ret)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%s", is_tv ?
- drm_get_tv_subconnector_name((int)subconnector) :
- drm_get_dvi_i_subconnector_name((int)subconnector));
-}
-
-static ssize_t select_subconnector_show(struct device *device,
- struct device_attribute *attr,
- char *buf)
-{
- struct drm_connector *connector = to_drm_connector(device);
- struct drm_device *dev = connector->dev;
- struct drm_property *prop = NULL;
- uint64_t subconnector;
- int is_tv = 0;
- int ret;
-
- switch (connector->connector_type) {
- case DRM_MODE_CONNECTOR_DVII:
- prop = dev->mode_config.dvi_i_select_subconnector_property;
- break;
- case DRM_MODE_CONNECTOR_Composite:
- case DRM_MODE_CONNECTOR_SVIDEO:
- case DRM_MODE_CONNECTOR_Component:
- case DRM_MODE_CONNECTOR_TV:
- prop = dev->mode_config.tv_select_subconnector_property;
- is_tv = 1;
- break;
- default:
- DRM_ERROR("Wrong connector type for this property\n");
- return 0;
- }
-
- if (!prop) {
- DRM_ERROR("Unable to find select subconnector property\n");
- return 0;
- }
-
- ret = drm_connector_property_get_value(connector, prop, &subconnector);
- if (ret)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%s", is_tv ?
- drm_get_tv_select_name((int)subconnector) :
- drm_get_dvi_i_select_name((int)subconnector));
-}
-
-static struct device_attribute connector_attrs[] = {
- __ATTR_RO(status),
- __ATTR_RO(enabled),
- __ATTR_RO(dpms),
- __ATTR_RO(modes),
-};
-
-/* These attributes are for both DVI-I connectors and all types of tv-out. */
-static struct device_attribute connector_attrs_opt1[] = {
- __ATTR_RO(subconnector),
- __ATTR_RO(select_subconnector),
-};
-
-static struct bin_attribute edid_attr = {
- .attr.name = "edid",
- .attr.mode = 0444,
- .size = 0,
- .read = edid_show,
-};
-
-/**
- * drm_sysfs_connector_add - add an connector to sysfs
- * @connector: connector to add
- *
- * Create an connector device in sysfs, along with its associated connector
- * properties (so far, connection status, dpms, mode list & edid) and
- * generate a hotplug event so userspace knows there's a new connector
- * available.
- *
- * Note:
- * This routine should only be called *once* for each DRM minor registered.
- * A second call for an already registered device will trigger the BUG_ON
- * below.
- */
-int drm_sysfs_connector_add(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- int attr_cnt = 0;
- int opt_cnt = 0;
- int i;
- int ret = 0;
-
- /* We shouldn't get called more than once for the same connector */
- BUG_ON(device_is_registered(&connector->kdev));
-
- connector->kdev.parent = &dev->primary->kdev;
- connector->kdev.class = drm_class;
- connector->kdev.release = drm_sysfs_device_release;
-
- DRM_DEBUG("adding \"%s\" to sysfs\n",
- drm_get_connector_name(connector));
-
- dev_set_name(&connector->kdev, "card%d-%s",
- dev->primary->index, drm_get_connector_name(connector));
- ret = device_register(&connector->kdev);
-
- if (ret) {
- DRM_ERROR("failed to register connector device: %d\n", ret);
- goto out;
- }
-
- /* Standard attributes */
-
- for (attr_cnt = 0; attr_cnt < ARRAY_SIZE(connector_attrs); attr_cnt++) {
- ret = device_create_file(&connector->kdev, &connector_attrs[attr_cnt]);
- if (ret)
- goto err_out_files;
- }
-
- /* Optional attributes */
- /*
- * In the long run it maybe a good idea to make one set of
- * optionals per connector type.
- */
- switch (connector->connector_type) {
- case DRM_MODE_CONNECTOR_DVII:
- case DRM_MODE_CONNECTOR_Composite:
- case DRM_MODE_CONNECTOR_SVIDEO:
- case DRM_MODE_CONNECTOR_Component:
- case DRM_MODE_CONNECTOR_TV:
- for (opt_cnt = 0; opt_cnt < ARRAY_SIZE(connector_attrs_opt1); opt_cnt++) {
- ret = device_create_file(&connector->kdev, &connector_attrs_opt1[opt_cnt]);
- if (ret)
- goto err_out_files;
- }
- break;
- default:
- break;
- }
-
- ret = sysfs_create_bin_file(&connector->kdev.kobj, &edid_attr);
- if (ret)
- goto err_out_files;
-
- /* Let userspace know we have a new connector */
- drm_sysfs_hotplug_event(dev);
-
- return 0;
-
-err_out_files:
- for (i = 0; i < opt_cnt; i++)
- device_remove_file(&connector->kdev, &connector_attrs_opt1[i]);
- for (i = 0; i < attr_cnt; i++)
- device_remove_file(&connector->kdev, &connector_attrs[i]);
- device_unregister(&connector->kdev);
-
-out:
- return ret;
-}
-EXPORT_SYMBOL(drm_sysfs_connector_add);
-
-/**
- * drm_sysfs_connector_remove - remove an connector device from sysfs
- * @connector: connector to remove
- *
- * Remove @connector and its associated attributes from sysfs. Note that
- * the device model core will take care of sending the "remove" uevent
- * at this time, so we don't need to do it.
- *
- * Note:
- * This routine should only be called if the connector was previously
- * successfully registered. If @connector hasn't been registered yet,
- * you'll likely see a panic somewhere deep in sysfs code when called.
- */
-void drm_sysfs_connector_remove(struct drm_connector *connector)
-{
- int i;
-
- DRM_DEBUG("removing \"%s\" from sysfs\n",
- drm_get_connector_name(connector));
-
- for (i = 0; i < ARRAY_SIZE(connector_attrs); i++)
- device_remove_file(&connector->kdev, &connector_attrs[i]);
- sysfs_remove_bin_file(&connector->kdev.kobj, &edid_attr);
- device_unregister(&connector->kdev);
-}
-EXPORT_SYMBOL(drm_sysfs_connector_remove);
-
-/**
- * drm_sysfs_hotplug_event - generate a DRM uevent
- * @dev: DRM device
- *
- * Send a uevent for the DRM device specified by @dev. Currently we only
- * set HOTPLUG=1 in the uevent environment, but this could be expanded to
- * deal with other types of events.
- */
-void drm_sysfs_hotplug_event(struct drm_device *dev)
-{
- char *event_string = "HOTPLUG=1";
- char *envp[] = { event_string, NULL };
-
- DRM_DEBUG("generating hotplug event\n");
-
- kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, envp);
-}
-EXPORT_SYMBOL(drm_sysfs_hotplug_event);
-
-/**
- * drm_sysfs_device_add - adds a class device to sysfs for a character driver
- * @dev: DRM device to be added
- * @head: DRM head in question
- *
- * Add a DRM device to the DRM's device model class. We use @dev's PCI device
- * as the parent for the Linux device, and make sure it has a file containing
- * the driver we're using (for userspace compatibility).
- */
-int drm_sysfs_device_add(struct drm_minor *minor)
-{
- int err;
- char *minor_str;
-
- minor->kdev.parent = minor->dev->dev;
-
- minor->kdev.class = drm_class;
- minor->kdev.release = drm_sysfs_device_release;
- minor->kdev.devt = minor->device;
- minor->kdev.type = &drm_sysfs_device_minor;
- if (minor->type == DRM_MINOR_CONTROL)
- minor_str = "controlD%d";
- else if (minor->type == DRM_MINOR_RENDER)
- minor_str = "renderD%d";
- else
- minor_str = "card%d";
-
- dev_set_name(&minor->kdev, minor_str, minor->index);
-
- err = device_register(&minor->kdev);
- if (err) {
- DRM_ERROR("device add failed: %d\n", err);
- goto err_out;
- }
-
- return 0;
-
-err_out:
- return err;
-}
-
-/**
- * drm_sysfs_device_remove - remove DRM device
- * @dev: DRM device to remove
- *
- * This call unregisters and cleans up a class device that was created with a
- * call to drm_sysfs_device_add()
- */
-void drm_sysfs_device_remove(struct drm_minor *minor)
-{
- device_unregister(&minor->kdev);
-}
-
-
-/**
- * drm_class_device_register - Register a struct device in the drm class.
- *
- * @dev: pointer to struct device to register.
- *
- * @dev should have all relevant members pre-filled with the exception
- * of the class member. In particular, the device_type member must
- * be set.
- */
-
-int drm_class_device_register(struct device *dev)
-{
- dev->class = drm_class;
- return device_register(dev);
-}
-EXPORT_SYMBOL_GPL(drm_class_device_register);
-
-void drm_class_device_unregister(struct device *dev)
-{
- return device_unregister(dev);
-}
-EXPORT_SYMBOL_GPL(drm_class_device_unregister);
+++ /dev/null
-#include "drmP.h"
-
-#define CREATE_TRACE_POINTS
-#include "drm_trace.h"
+++ /dev/null
-/**
- * \file drm_vm.c
- * Memory mapping for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#if defined(__ia64__)
-#include <linux/efi.h>
-#include <linux/slab.h>
-#endif
-
-static void drm_vm_open(struct vm_area_struct *vma);
-static void drm_vm_close(struct vm_area_struct *vma);
-
-static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
-{
- pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
-
-#if defined(__i386__) || defined(__x86_64__)
- if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) {
- pgprot_val(tmp) |= _PAGE_PCD;
- pgprot_val(tmp) &= ~_PAGE_PWT;
- }
-#elif defined(__powerpc__)
- pgprot_val(tmp) |= _PAGE_NO_CACHE;
- if (map_type == _DRM_REGISTERS)
- pgprot_val(tmp) |= _PAGE_GUARDED;
-#elif defined(__ia64__)
- if (efi_range_is_wc(vma->vm_start, vma->vm_end -
- vma->vm_start))
- tmp = pgprot_writecombine(tmp);
- else
- tmp = pgprot_noncached(tmp);
-#elif defined(__sparc__) || defined(__arm__)
- tmp = pgprot_noncached(tmp);
-#endif
- return tmp;
-}
-
-static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
-{
- pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
-
-#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
- tmp |= _PAGE_NO_CACHE;
-#endif
- return tmp;
-}
-
-/**
- * \c fault method for AGP virtual memory.
- *
- * \param vma virtual memory area.
- * \param address access address.
- * \return pointer to the page structure.
- *
- * Find the right map and if it's AGP memory find the real physical page to
- * map, get the page, increment the use count and return it.
- */
-#if __OS_HAS_AGP
-static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct drm_file *priv = vma->vm_file->private_data;
- struct drm_device *dev = priv->minor->dev;
- struct drm_local_map *map = NULL;
- struct drm_map_list *r_list;
- struct drm_hash_item *hash;
-
- /*
- * Find the right map
- */
- if (!drm_core_has_AGP(dev))
- goto vm_fault_error;
-
- if (!dev->agp || !dev->agp->cant_use_aperture)
- goto vm_fault_error;
-
- if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash))
- goto vm_fault_error;
-
- r_list = drm_hash_entry(hash, struct drm_map_list, hash);
- map = r_list->map;
-
- if (map && map->type == _DRM_AGP) {
- /*
- * Using vm_pgoff as a selector forces us to use this unusual
- * addressing scheme.
- */
- resource_size_t offset = (unsigned long)vmf->virtual_address -
- vma->vm_start;
- resource_size_t baddr = map->offset + offset;
- struct drm_agp_mem *agpmem;
- struct page *page;
-
-#ifdef __alpha__
- /*
- * Adjust to a bus-relative address
- */
- baddr -= dev->hose->mem_space->start;
-#endif
-
- /*
- * It's AGP memory - find the real physical page to map
- */
- list_for_each_entry(agpmem, &dev->agp->memory, head) {
- if (agpmem->bound <= baddr &&
- agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
- break;
- }
-
- if (&agpmem->head == &dev->agp->memory)
- goto vm_fault_error;
-
- /*
- * Get the page, inc the use count, and return it
- */
- offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
- page = agpmem->memory->pages[offset];
- get_page(page);
- vmf->page = page;
-
- DRM_DEBUG
- ("baddr = 0x%llx page = 0x%p, offset = 0x%llx, count=%d\n",
- (unsigned long long)baddr,
- agpmem->memory->pages[offset],
- (unsigned long long)offset,
- page_count(page));
- return 0;
- }
-vm_fault_error:
- return VM_FAULT_SIGBUS; /* Disallow mremap */
-}
-#else /* __OS_HAS_AGP */
-static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- return VM_FAULT_SIGBUS;
-}
-#endif /* __OS_HAS_AGP */
-
-/**
- * \c nopage method for shared virtual memory.
- *
- * \param vma virtual memory area.
- * \param address access address.
- * \return pointer to the page structure.
- *
- * Get the mapping, find the real physical page to map, get the page, and
- * return it.
- */
-static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct drm_local_map *map = vma->vm_private_data;
- unsigned long offset;
- unsigned long i;
- struct page *page;
-
- if (!map)
- return VM_FAULT_SIGBUS; /* Nothing allocated */
-
- offset = (unsigned long)vmf->virtual_address - vma->vm_start;
- i = (unsigned long)map->handle + offset;
- page = vmalloc_to_page((void *)i);
- if (!page)
- return VM_FAULT_SIGBUS;
- get_page(page);
- vmf->page = page;
-
- DRM_DEBUG("shm_fault 0x%lx\n", offset);
- return 0;
-}
-
-/**
- * \c close method for shared virtual memory.
- *
- * \param vma virtual memory area.
- *
- * Deletes map information if we are the last
- * person to close a mapping and it's not in the global maplist.
- */
-static void drm_vm_shm_close(struct vm_area_struct *vma)
-{
- struct drm_file *priv = vma->vm_file->private_data;
- struct drm_device *dev = priv->minor->dev;
- struct drm_vma_entry *pt, *temp;
- struct drm_local_map *map;
- struct drm_map_list *r_list;
- int found_maps = 0;
-
- DRM_DEBUG("0x%08lx,0x%08lx\n",
- vma->vm_start, vma->vm_end - vma->vm_start);
- atomic_dec(&dev->vma_count);
-
- map = vma->vm_private_data;
-
- mutex_lock(&dev->struct_mutex);
- list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
- if (pt->vma->vm_private_data == map)
- found_maps++;
- if (pt->vma == vma) {
- list_del(&pt->head);
- kfree(pt);
- }
- }
-
- /* We were the only map that was found */
- if (found_maps == 1 && map->flags & _DRM_REMOVABLE) {
- /* Check to see if we are in the maplist, if we are not, then
- * we delete this mappings information.
- */
- found_maps = 0;
- list_for_each_entry(r_list, &dev->maplist, head) {
- if (r_list->map == map)
- found_maps++;
- }
-
- if (!found_maps) {
- drm_dma_handle_t dmah;
-
- switch (map->type) {
- case _DRM_REGISTERS:
- case _DRM_FRAME_BUFFER:
- if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
- int retcode;
- retcode = mtrr_del(map->mtrr,
- map->offset,
- map->size);
- DRM_DEBUG("mtrr_del = %d\n", retcode);
- }
- iounmap(map->handle);
- break;
- case _DRM_SHM:
- vfree(map->handle);
- break;
- case _DRM_AGP:
- case _DRM_SCATTER_GATHER:
- break;
- case _DRM_CONSISTENT:
- dmah.vaddr = map->handle;
- dmah.busaddr = map->offset;
- dmah.size = map->size;
- __drm_pci_free(dev, &dmah);
- break;
- case _DRM_GEM:
- DRM_ERROR("tried to rmmap GEM object\n");
- break;
- }
- kfree(map);
- }
- }
- mutex_unlock(&dev->struct_mutex);
-}
-
-/**
- * \c fault method for DMA virtual memory.
- *
- * \param vma virtual memory area.
- * \param address access address.
- * \return pointer to the page structure.
- *
- * Determine the page number from the page offset and get it from drm_device_dma::pagelist.
- */
-static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct drm_file *priv = vma->vm_file->private_data;
- struct drm_device *dev = priv->minor->dev;
- struct drm_device_dma *dma = dev->dma;
- unsigned long offset;
- unsigned long page_nr;
- struct page *page;
-
- if (!dma)
- return VM_FAULT_SIGBUS; /* Error */
- if (!dma->pagelist)
- return VM_FAULT_SIGBUS; /* Nothing allocated */
-
- offset = (unsigned long)vmf->virtual_address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
- page_nr = offset >> PAGE_SHIFT; /* page_nr could just be vmf->pgoff */
- page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK))));
-
- get_page(page);
- vmf->page = page;
-
- DRM_DEBUG("dma_fault 0x%lx (page %lu)\n", offset, page_nr);
- return 0;
-}
-
-/**
- * \c fault method for scatter-gather virtual memory.
- *
- * \param vma virtual memory area.
- * \param address access address.
- * \return pointer to the page structure.
- *
- * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
- */
-static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct drm_local_map *map = vma->vm_private_data;
- struct drm_file *priv = vma->vm_file->private_data;
- struct drm_device *dev = priv->minor->dev;
- struct drm_sg_mem *entry = dev->sg;
- unsigned long offset;
- unsigned long map_offset;
- unsigned long page_offset;
- struct page *page;
-
- if (!entry)
- return VM_FAULT_SIGBUS; /* Error */
- if (!entry->pagelist)
- return VM_FAULT_SIGBUS; /* Nothing allocated */
-
- offset = (unsigned long)vmf->virtual_address - vma->vm_start;
- map_offset = map->offset - (unsigned long)dev->sg->virtual;
- page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
- page = entry->pagelist[page_offset];
- get_page(page);
- vmf->page = page;
-
- return 0;
-}
-
-static int drm_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- return drm_do_vm_fault(vma, vmf);
-}
-
-static int drm_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- return drm_do_vm_shm_fault(vma, vmf);
-}
-
-static int drm_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- return drm_do_vm_dma_fault(vma, vmf);
-}
-
-static int drm_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- return drm_do_vm_sg_fault(vma, vmf);
-}
-
-/** AGP virtual memory operations */
-static const struct vm_operations_struct drm_vm_ops = {
- .fault = drm_vm_fault,
- .open = drm_vm_open,
- .close = drm_vm_close,
-};
-
-/** Shared virtual memory operations */
-static const struct vm_operations_struct drm_vm_shm_ops = {
- .fault = drm_vm_shm_fault,
- .open = drm_vm_open,
- .close = drm_vm_shm_close,
-};
-
-/** DMA virtual memory operations */
-static const struct vm_operations_struct drm_vm_dma_ops = {
- .fault = drm_vm_dma_fault,
- .open = drm_vm_open,
- .close = drm_vm_close,
-};
-
-/** Scatter-gather virtual memory operations */
-static const struct vm_operations_struct drm_vm_sg_ops = {
- .fault = drm_vm_sg_fault,
- .open = drm_vm_open,
- .close = drm_vm_close,
-};
-
-/**
- * \c open method for shared virtual memory.
- *
- * \param vma virtual memory area.
- *
- * Create a new drm_vma_entry structure as the \p vma private data entry and
- * add it to drm_device::vmalist.
- */
-void drm_vm_open_locked(struct vm_area_struct *vma)
-{
- struct drm_file *priv = vma->vm_file->private_data;
- struct drm_device *dev = priv->minor->dev;
- struct drm_vma_entry *vma_entry;
-
- DRM_DEBUG("0x%08lx,0x%08lx\n",
- vma->vm_start, vma->vm_end - vma->vm_start);
- atomic_inc(&dev->vma_count);
-
- vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL);
- if (vma_entry) {
- vma_entry->vma = vma;
- vma_entry->pid = current->pid;
- list_add(&vma_entry->head, &dev->vmalist);
- }
-}
-
-static void drm_vm_open(struct vm_area_struct *vma)
-{
- struct drm_file *priv = vma->vm_file->private_data;
- struct drm_device *dev = priv->minor->dev;
-
- mutex_lock(&dev->struct_mutex);
- drm_vm_open_locked(vma);
- mutex_unlock(&dev->struct_mutex);
-}
-
-void drm_vm_close_locked(struct vm_area_struct *vma)
-{
- struct drm_file *priv = vma->vm_file->private_data;
- struct drm_device *dev = priv->minor->dev;
- struct drm_vma_entry *pt, *temp;
-
- DRM_DEBUG("0x%08lx,0x%08lx\n",
- vma->vm_start, vma->vm_end - vma->vm_start);
- atomic_dec(&dev->vma_count);
-
- list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
- if (pt->vma == vma) {
- list_del(&pt->head);
- kfree(pt);
- break;
- }
- }
-}
-
-/**
- * \c close method for all virtual memory types.
- *
- * \param vma virtual memory area.
- *
- * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
- * free it.
- */
-static void drm_vm_close(struct vm_area_struct *vma)
-{
- struct drm_file *priv = vma->vm_file->private_data;
- struct drm_device *dev = priv->minor->dev;
-
- mutex_lock(&dev->struct_mutex);
- drm_vm_close_locked(vma);
- mutex_unlock(&dev->struct_mutex);
-}
-
-/**
- * mmap DMA memory.
- *
- * \param file_priv DRM file private.
- * \param vma virtual memory area.
- * \return zero on success or a negative number on failure.
- *
- * Sets the virtual memory area operations structure to vm_dma_ops, the file
- * pointer, and calls vm_open().
- */
-static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
-{
- struct drm_file *priv = filp->private_data;
- struct drm_device *dev;
- struct drm_device_dma *dma;
- unsigned long length = vma->vm_end - vma->vm_start;
-
- dev = priv->minor->dev;
- dma = dev->dma;
- DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
- vma->vm_start, vma->vm_end, vma->vm_pgoff);
-
- /* Length must match exact page count */
- if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
- return -EINVAL;
- }
-
- if (!capable(CAP_SYS_ADMIN) &&
- (dma->flags & _DRM_DMA_USE_PCI_RO)) {
- vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
-#if defined(__i386__) || defined(__x86_64__)
- pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
-#else
- /* Ye gads this is ugly. With more thought
- we could move this up higher and use
- `protection_map' instead. */
- vma->vm_page_prot =
- __pgprot(pte_val
- (pte_wrprotect
- (__pte(pgprot_val(vma->vm_page_prot)))));
-#endif
- }
-
- vma->vm_ops = &drm_vm_dma_ops;
-
- vma->vm_flags |= VM_RESERVED; /* Don't swap */
- vma->vm_flags |= VM_DONTEXPAND;
-
- vma->vm_file = filp; /* Needed for drm_vm_open() */
- drm_vm_open_locked(vma);
- return 0;
-}
-
-static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev)
-{
-#ifdef __alpha__
- return dev->hose->dense_mem_base - dev->hose->mem_space->start;
-#else
- return 0;
-#endif
-}
-
-/**
- * mmap DMA memory.
- *
- * \param file_priv DRM file private.
- * \param vma virtual memory area.
- * \return zero on success or a negative number on failure.
- *
- * If the virtual memory area has no offset associated with it then it's a DMA
- * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist,
- * checks that the restricted flag is not set, sets the virtual memory operations
- * according to the mapping type and remaps the pages. Finally sets the file
- * pointer and calls vm_open().
- */
-int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
-{
- struct drm_file *priv = filp->private_data;
- struct drm_device *dev = priv->minor->dev;
- struct drm_local_map *map = NULL;
- resource_size_t offset = 0;
- struct drm_hash_item *hash;
-
- DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
- vma->vm_start, vma->vm_end, vma->vm_pgoff);
-
- if (!priv->authenticated)
- return -EACCES;
-
- /* We check for "dma". On Apple's UniNorth, it's valid to have
- * the AGP mapped at physical address 0
- * --BenH.
- */
- if (!vma->vm_pgoff
-#if __OS_HAS_AGP
- && (!dev->agp
- || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
-#endif
- )
- return drm_mmap_dma(filp, vma);
-
- if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) {
- DRM_ERROR("Could not find map\n");
- return -EINVAL;
- }
-
- map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
- if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
- return -EPERM;
-
- /* Check for valid size. */
- if (map->size < vma->vm_end - vma->vm_start)
- return -EINVAL;
-
- if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
- vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
-#if defined(__i386__) || defined(__x86_64__)
- pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
-#else
- /* Ye gads this is ugly. With more thought
- we could move this up higher and use
- `protection_map' instead. */
- vma->vm_page_prot =
- __pgprot(pte_val
- (pte_wrprotect
- (__pte(pgprot_val(vma->vm_page_prot)))));
-#endif
- }
-
- switch (map->type) {
-#if !defined(__arm__)
- case _DRM_AGP:
- if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
- /*
- * On some platforms we can't talk to bus dma address from the CPU, so for
- * memory of type DRM_AGP, we'll deal with sorting out the real physical
- * pages and mappings in fault()
- */
-#if defined(__powerpc__)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-#endif
- vma->vm_ops = &drm_vm_ops;
- break;
- }
- /* fall through to _DRM_FRAME_BUFFER... */
-#endif
- case _DRM_FRAME_BUFFER:
- case _DRM_REGISTERS:
- offset = drm_core_get_reg_ofs(dev);
- vma->vm_flags |= VM_IO; /* not in core dump */
- vma->vm_page_prot = drm_io_prot(map->type, vma);
-#if !defined(__arm__)
- if (io_remap_pfn_range(vma, vma->vm_start,
- (map->offset + offset) >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-#else
- if (remap_pfn_range(vma, vma->vm_start,
- (map->offset + offset) >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-#endif
-
- DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
- " offset = 0x%llx\n",
- map->type,
- vma->vm_start, vma->vm_end, (unsigned long long)(map->offset + offset));
-
- vma->vm_ops = &drm_vm_ops;
- break;
- case _DRM_CONSISTENT:
- /* Consistent memory is really like shared memory. But
- * it's allocated in a different way, so avoid fault */
- if (remap_pfn_range(vma, vma->vm_start,
- page_to_pfn(virt_to_page(map->handle)),
- vma->vm_end - vma->vm_start, vma->vm_page_prot))
- return -EAGAIN;
- vma->vm_page_prot = drm_dma_prot(map->type, vma);
- /* fall through to _DRM_SHM */
- case _DRM_SHM:
- vma->vm_ops = &drm_vm_shm_ops;
- vma->vm_private_data = (void *)map;
- /* Don't let this area swap. Change when
- DRM_KERNEL advisory is supported. */
- vma->vm_flags |= VM_RESERVED;
- break;
- case _DRM_SCATTER_GATHER:
- vma->vm_ops = &drm_vm_sg_ops;
- vma->vm_private_data = (void *)map;
- vma->vm_flags |= VM_RESERVED;
- vma->vm_page_prot = drm_dma_prot(map->type, vma);
- break;
- default:
- return -EINVAL; /* This should never happen. */
- }
- vma->vm_flags |= VM_RESERVED; /* Don't swap */
- vma->vm_flags |= VM_DONTEXPAND;
-
- vma->vm_file = filp; /* Needed for drm_vm_open() */
- drm_vm_open_locked(vma);
- return 0;
-}
-
-int drm_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct drm_file *priv = filp->private_data;
- struct drm_device *dev = priv->minor->dev;
- int ret;
-
- mutex_lock(&dev->struct_mutex);
- ret = drm_mmap_locked(filp, vma);
- mutex_unlock(&dev->struct_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(drm_mmap);
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title DRM stub functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __PVR_DRM_MOD_H__
#define __PVR_DRM_MOD_H__
void drm_pvr_dev_remove(void);
-#endif
+#endif /* __PVR_DRM_MOD_H__ */
-/**********************************************************************
- *
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title DRM stub functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/*
+ * Emulate enough of the PCI layer to allow the Linux DRM module to be used
+ * with a non-PCI device.
+ * Only one device is supported at present.
+ */
#include <linux/version.h>
#include <linux/kernel.h>
-#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/pci.h>
#include <asm/system.h>
#include "pvr_drm_mod.h"
#define CLEAR_STRUCT(x) memset(&(x), 0, sizeof(x))
+/*
+ * Don't specify any initialisers for pvr_pci_bus and pvr_pci_dev, as they
+ * will be cleared to zero on unregister. This has to be done for
+ * pvr_pci_dev to prevent a warning from the kernel if the device is
+ * re-registered without unloading the DRM module.
+ */
static struct pci_bus pvr_pci_bus;
static struct pci_dev pvr_pci_dev;
return 0;
}
-
+ /* Set the device ID */
pvr_pci_dev.vendor = SGX_VENDOR_ID;
pvr_pci_dev.device = SGX_DEVICE_ID;
pvr_pci_dev.subsystem_vendor = SGX_SUB_VENDOR_ID;
pvr_pci_dev.subsystem_device = SGX_SUB_DEVICE_ID;
-
+ /* drm_set_busid needs the bus number */
pvr_pci_dev.bus = &pvr_pci_bus;
dev_set_name(&pvr_pci_dev.dev, "%s", "SGX");
device_unregister(&pvr_pci_dev.dev);
bDeviceIsRegistered = false;
-
+ /* Prevent kernel warnings on re-register */
CLEAR_STRUCT(pvr_pci_dev);
CLEAR_STRUCT(pvr_pci_bus);
}
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PowerVR drm driver shared definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined(__PVR_DRM_SHARED_H__)
#define __PVR_DRM_SHARED_H__
#if defined(SUPPORT_DRI_DRM)
+/* DRM command numbers, relative to DRM_COMMAND_BASE */
#if defined(SUPPORT_DRI_DRM_EXT)
-#define PVR_DRM_SRVKM_CMD DRM_PVR_RESERVED1
-#define PVR_DRM_DISP_CMD DRM_PVR_RESERVED2
-#define PVR_DRM_BC_CMD DRM_PVR_RESERVED3
-#define PVR_DRM_IS_MASTER_CMD DRM_PVR_RESERVED4
-#define PVR_DRM_UNPRIV_CMD DRM_PVR_RESERVED5
-#define PVR_DRM_DBGDRV_CMD DRM_PVR_RESERVED6
-#else
-#define PVR_DRM_SRVKM_CMD 0
-#define PVR_DRM_DISP_CMD 1
-#define PVR_DRM_BC_CMD 2
-#define PVR_DRM_IS_MASTER_CMD 3
-#define PVR_DRM_UNPRIV_CMD 4
-#define PVR_DRM_DBGDRV_CMD 5
-#endif
-
-#define PVR_DRM_UNPRIV_INIT_SUCCESFUL 0
+#define PVR_DRM_SRVKM_CMD DRM_PVR_RESERVED1 /* Used for PVR Services ioctls */
+#define PVR_DRM_DISP_CMD DRM_PVR_RESERVED2 /* Reserved for display class driver */
+#define PVR_DRM_BC_CMD DRM_PVR_RESERVED3 /* Reserved for buffer class driver */
+#define PVR_DRM_IS_MASTER_CMD DRM_PVR_RESERVED4 /* Are we the DRM master? */
+#define PVR_DRM_UNPRIV_CMD DRM_PVR_RESERVED5 /* PVR driver unprivileged ioctls */
+#define PVR_DRM_DBGDRV_CMD DRM_PVR_RESERVED6 /* Debug driver (PDUMP) ioctls */
+#else /* defined(SUPPORT_DRI_DRM_EXT) */
+#define PVR_DRM_SRVKM_CMD 0 /* Used for PVR Services ioctls */
+#define PVR_DRM_DISP_CMD 1 /* Reserved for display class driver */
+#define PVR_DRM_BC_CMD 2 /* Reserved for buffer class driver */
+#define PVR_DRM_IS_MASTER_CMD 3 /* Are we the DRM master? */
+#define PVR_DRM_UNPRIV_CMD 4 /* PVR driver unprivileged ioctls */
+#define PVR_DRM_DBGDRV_CMD 5 /* Debug driver (PDUMP) ioctls */
+#endif /* defined(SUPPORT_DRI_DRM_EXT) */
+
+/* Subcommands of PVR_DRM_UNPRIV_CMD */
+#define PVR_DRM_UNPRIV_INIT_SUCCESFUL 0 /* PVR Services init succesful */
#endif
-#endif
+#endif /* defined(__PVR_DRM_SHARED_H__) */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title buffer device class API structures and prototypes
+ for kernel services to kernel 3rd party buffer device driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description provides display device class API structures and prototypes
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined (__KERNELBUFFER_H__)
#define __KERNELBUFFER_H__
extern "C" {
#endif
+/*
+ Function table and pointers for SRVKM->BUFFER
+*/
typedef PVRSRV_ERROR (*PFN_OPEN_BC_DEVICE)(IMG_UINT32, IMG_HANDLE*);
typedef PVRSRV_ERROR (*PFN_CLOSE_BC_DEVICE)(IMG_UINT32, IMG_HANDLE);
typedef PVRSRV_ERROR (*PFN_GET_BC_INFO)(IMG_HANDLE, BUFFER_INFO*);
} PVRSRV_BC_SRV2BUFFER_KMJTABLE;
+/*
+ Function table and pointers for BUFFER->SRVKM
+*/
typedef PVRSRV_ERROR (*PFN_BC_REGISTER_BUFFER_DEV)(PVRSRV_BC_SRV2BUFFER_KMJTABLE*, IMG_UINT32*);
typedef IMG_VOID (*PFN_BC_SCHEDULE_DEVICES)(IMG_VOID);
typedef PVRSRV_ERROR (*PFN_BC_REMOVE_BUFFER_DEV)(IMG_UINT32);
} PVRSRV_BC_BUFFER2SRV_KMJTABLE, *PPVRSRV_BC_BUFFER2SRV_KMJTABLE;
+/* function to retrieve kernel services function table from kernel services */
typedef IMG_BOOL (*PFN_BC_GET_PVRJTABLE) (PPVRSRV_BC_BUFFER2SRV_KMJTABLE);
+/* Prototype for platforms that access the JTable via linkage */
IMG_IMPORT IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
#if defined (__cplusplus)
}
#endif
-#endif
+#endif/* #if !defined (__KERNELBUFFER_H__) */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Display device class API structures and prototypes
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides display device class API structures and prototypes
+ for kernel services to kernel 3rd party display.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined (__KERNELDISPLAY_H__)
#define __KERNELDISPLAY_H__
IMG_HANDLE,
IMG_UINT32,
IMG_RECT*);
-typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_SYSTEM)(IMG_HANDLE, IMG_HANDLE);
typedef IMG_VOID (*PFN_QUERY_SWAP_COMMAND_ID)(IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_UINT16*, IMG_BOOL*);
typedef IMG_VOID (*PFN_SET_DC_STATE)(IMG_HANDLE, IMG_UINT32);
+/*
+ Function table for SRVKM->DISPLAY
+*/
typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG
{
IMG_UINT32 ui32TableSize;
PFN_SET_DC_SRCCK pfnSetDCSrcColourKey;
PFN_GET_DC_BUFFERS pfnGetDCBuffers;
PFN_SWAP_TO_DC_BUFFER pfnSwapToDCBuffer;
- PFN_SWAP_TO_DC_SYSTEM pfnSwapToDCSystem;
PFN_SET_DC_STATE pfnSetDCState;
PFN_QUERY_SWAP_COMMAND_ID pfnQuerySwapCommandID;
} PVRSRV_DC_SRV2DISP_KMJTABLE;
+/* ISR callback pfn prototype */
typedef IMG_BOOL (*PFN_ISR_HANDLER)(IMG_VOID*);
+/*
+ functions exported by kernel services for use by 3rd party kernel display class device driver
+*/
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);
PFN_PRE_CLOCKSPEED_CHANGE, PFN_POST_CLOCKSPEED_CHANGE,
IMG_HANDLE, PVRSRV_DEV_POWER_STATE, PVRSRV_DEV_POWER_STATE);
+typedef struct _PVRSRV_KERNEL_MEM_INFO_* PDC_MEM_INFO;
+
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_CPU_VADDR)(PDC_MEM_INFO, IMG_CPU_VIRTADDR *pVAddr);
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_CPU_PADDR)(PDC_MEM_INFO, IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr);
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_BYTE_SIZE)(PDC_MEM_INFO, IMG_SIZE_T *uByteSize);
+typedef IMG_BOOL (*PFN_DC_MEMINFO_IS_PHYS_CONTIG)(PDC_MEM_INFO);
+
+/*
+ Function table for DISPLAY->SRVKM
+*/
typedef struct PVRSRV_DC_DISP2SRV_KMJTABLE_TAG
{
IMG_UINT32 ui32TableSize;
PFN_DC_REGISTER_SYS_ISR pfnPVRSRVRegisterSystemISRHandler;
PFN_DC_REGISTER_POWER pfnPVRSRVRegisterPowerDevice;
PFN_DC_CMD_COMPLETE pfnPVRSRVFreeCmdCompletePacket;
+ PFN_DC_MEMINFO_GET_CPU_VADDR pfnPVRSRVDCMemInfoGetCpuVAddr;
+ PFN_DC_MEMINFO_GET_CPU_PADDR pfnPVRSRVDCMemInfoGetCpuPAddr;
+ PFN_DC_MEMINFO_GET_BYTE_SIZE pfnPVRSRVDCMemInfoGetByteSize;
+ PFN_DC_MEMINFO_IS_PHYS_CONTIG pfnPVRSRVDCMemInfoIsPhysContig;
+
} PVRSRV_DC_DISP2SRV_KMJTABLE, *PPVRSRV_DC_DISP2SRV_KMJTABLE;
typedef struct DISPLAYCLASS_FLIP_COMMAND_TAG
{
-
+ /* Ext Device Handle */
IMG_HANDLE hExtDevice;
-
+ /* Ext SwapChain Handle */
IMG_HANDLE hExtSwapChain;
-
+ /* Ext Buffer Handle (Buffer to Flip to) */
IMG_HANDLE hExtBuffer;
-
+ /* private tag */
IMG_HANDLE hPrivateTag;
-
+ /* number of clip rects */
IMG_UINT32 ui32ClipRectCount;
-
+ /* clip rects */
IMG_RECT *psClipRect;
-
+ /* number of vsync intervals between successive flips */
IMG_UINT32 ui32SwapInterval;
} DISPLAYCLASS_FLIP_COMMAND;
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND2_TAG
+{
+ /* Ext Device Handle */
+ IMG_HANDLE hExtDevice;
+
+ /* Ext SwapChain Handle */
+ IMG_HANDLE hExtSwapChain;
+
+ /* Unused field, padding for compatibility with above structure */
+ IMG_HANDLE hUnused;
+
+ /* number of vsync intervals between successive flips */
+ IMG_UINT32 ui32SwapInterval;
+
+ /* private data from userspace */
+ IMG_PVOID pvPrivData;
+
+ /* length of private data in bytes */
+ IMG_UINT32 ui32PrivDataLength;
+
+ /* meminfos */
+ PDC_MEM_INFO *ppsMemInfos;
+
+ /* number of meminfos */
+ IMG_UINT32 ui32NumMemInfos;
+
+} DISPLAYCLASS_FLIP_COMMAND2;
+
+/* start command IDs from 0 */
#define DC_FLIP_COMMAND 0
+/* States used in PFN_SET_DC_STATE */
#define DC_STATE_NO_FLUSH_COMMANDS 0
#define DC_STATE_FLUSH_COMMANDS 1
+#define DC_STATE_FORCE_SWAP_TO_SYSTEM 2
-
+/* function to retrieve kernel services function table from kernel services */
typedef IMG_BOOL (*PFN_DC_GET_PVRJTABLE)(PPVRSRV_DC_DISP2SRV_KMJTABLE);
+/* Prototype for platforms that access the JTable via linkage */
IMG_IMPORT IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
}
#endif
-#endif
+#endif/* #if !defined (__KERNELDISPLAY_H__) */
+/******************************************************************************
+ End of file (kerneldisplay.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PDUMP flags definitions.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _SERVICES_PDUMP_H_
#define _SERVICES_PDUMP_H_
#define PDUMP_FLAGS_CONTINUOUS 0x40000000U
#define PDUMP_FLAGS_PERSISTENT 0x80000000U
-#endif
+#endif /* _SERVICES_PDUMP_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the PVR Bridge code
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __PVR_BRIDGE_H__
#define __PVR_BRIDGE_H__
#include "servicesint.h"
+/*
+ * Bridge Cmd Ids
+ */
+
+
#ifdef __linux__
#include <linux/ioctl.h>
-
+ /*!< Nov 2006: according to ioctl-number.txt 'g' wasn't in use. */
#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
+#else /* __linux__ */
- #if defined(__QNXNTO__)
+ #if defined(__QNXNTO__)
#define PVRSRV_IOC_GID (0x0UL)
#else
#error Unknown platform: Cannot define ioctls
#define PVRSRV_IOWR(INDEX) (PVRSRV_IOC_GID + (INDEX))
#define PVRSRV_BRIDGE_BASE PVRSRV_IOC_GID
-#endif
+#endif /* __linux__ */
+/*
+ * Note *REMEMBER* to update PVRSRV_BRIDGE_LAST_CMD (below) if you add any new
+ * bridge commands!
+ */
+
#define PVRSRV_BRIDGE_CORE_CMD_FIRST 0UL
-#define PVRSRV_BRIDGE_ENUM_DEVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+0)
-#define PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+1)
-#define PVRSRV_BRIDGE_RELEASE_DEVICEINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+2)
-#define PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+3)
-#define PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+4)
-#define PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+5)
-#define PVRSRV_BRIDGE_ALLOC_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+6)
-#define PVRSRV_BRIDGE_FREE_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+7)
-#define PVRSRV_BRIDGE_GETFREE_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+8)
-#define PVRSRV_BRIDGE_CREATE_COMMANDQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+9)
-#define PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+10)
-#define PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+11)
-#define PVRSRV_BRIDGE_CONNECT_SERVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+12)
-#define PVRSRV_BRIDGE_DISCONNECT_SERVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+13)
-#define PVRSRV_BRIDGE_WRAP_DEVICE_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+14)
-#define PVRSRV_BRIDGE_GET_DEVICEMEMINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_ENUM_DEVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+0) /*!< enumerate device bridge index */
+#define PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+1) /*!< acquire device data bridge index */
+#define PVRSRV_BRIDGE_RELEASE_DEVICEINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+2) /*!< release device data bridge index */
+#define PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+3) /*!< create device addressable memory context */
+#define PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+4) /*!< destroy device addressable memory context */
+#define PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+5) /*!< get device memory heap info */
+#define PVRSRV_BRIDGE_ALLOC_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+6) /*!< alloc device memory bridge index */
+#define PVRSRV_BRIDGE_FREE_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+7) /*!< free device memory bridge index */
+#define PVRSRV_BRIDGE_GETFREE_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+8) /*!< get free device memory bridge index */
+#define PVRSRV_BRIDGE_CREATE_COMMANDQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+9) /*!< create Cmd Q bridge index */
+#define PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+10) /*!< destroy Cmd Q bridge index */
+#define PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+11) /*!< generate mmap data from a memory handle */
+#define PVRSRV_BRIDGE_CONNECT_SERVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+12) /*!< services connect bridge index */
+#define PVRSRV_BRIDGE_DISCONNECT_SERVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+13) /*!< services disconnect bridge index */
+#define PVRSRV_BRIDGE_WRAP_DEVICE_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+14) /*!< wrap device memory bridge index */
+#define PVRSRV_BRIDGE_GET_DEVICEMEMINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+15) /*!< read the kernel meminfo record */
#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_CHG_DEV_MEM_ATTRIBS PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+28)
#define PVRSRV_BRIDGE_MAP_DEV_MEMORY_2 PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+29)
#define PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2 PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+30)
+#if defined (SUPPORT_ION)
+#define PVRSRV_BRIDGE_MAP_ION_HANDLE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+31)
+#define PVRSRV_BRIDGE_UNMAP_ION_HANDLE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+32)
+#define PVRSRV_BRIDGE_CORE_CMD_LAST (PVRSRV_BRIDGE_CORE_CMD_FIRST+32)
+#else
#define PVRSRV_BRIDGE_CORE_CMD_LAST (PVRSRV_BRIDGE_CORE_CMD_FIRST+30)
-
+#endif
+/* SIM */
#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_PROCESS_SIMISR_EVENT PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+0) /*!< RTSIM pseudo ISR */
+#define PVRSRV_BRIDGE_REGISTER_SIM_PROCESS PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+1) /*!< Register RTSIM process thread */
+#define PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+2) /*!< Unregister RTSIM process thread */
#define PVRSRV_BRIDGE_SIM_CMD_LAST (PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+/* User Mapping */
#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_MAPPHYSTOUSERSPACE PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+0) /*!< map CPU phys to user space */
+#define PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+1) /*!< unmap CPU phys to user space */
+#define PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2) /*!< get user copy of Phys to Lin loopup table */
#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_GET_FB_STATS PVRSRV_IOWR(PVRSRV_BRIDGE_STATS_CMD_FIRST+0) /*!< Get FB memory stats */
#define PVRSRV_BRIDGE_STATS_CMD_LAST (PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+/* API to retrieve misc. info. from services */
#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_GET_MISC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+0) /*!< misc. info. */
+#define PVRSRV_BRIDGE_RELEASE_MISC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+1) /*!< misc. info. */
#define PVRSRV_BRIDGE_MISC_CMD_LAST (PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+/* Overlay ioctls */
+
#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
#define PVRSRV_BRIDGE_OVERLAY_CMD_FIRST (PVRSRV_BRIDGE_MISC_CMD_LAST+1)
-#define PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+0)
-#define PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+0) /*!< 3D Overlay rotate blit init */
+#define PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1) /*!< 3D Overlay rotate blit deinit */
#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST (PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
#else
#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST PVRSRV_BRIDGE_MISC_CMD_LAST
#endif
+/* PDUMP */
#if defined(PDUMP)
#define PVRSRV_BRIDGE_PDUMP_CMD_FIRST (PVRSRV_BRIDGE_OVERLAY_CMD_LAST+1)
-#define PVRSRV_BRIDGE_PDUMP_INIT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0)
-#define PVRSRV_BRIDGE_PDUMP_MEMPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1)
-#define PVRSRV_BRIDGE_PDUMP_DUMPMEM PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2)
-#define PVRSRV_BRIDGE_PDUMP_REG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3)
-#define PVRSRV_BRIDGE_PDUMP_REGPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4)
-#define PVRSRV_BRIDGE_PDUMP_COMMENT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+5)
-#define PVRSRV_BRIDGE_PDUMP_SETFRAME PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+6)
-#define PVRSRV_BRIDGE_PDUMP_ISCAPTURING PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7)
-#define PVRSRV_BRIDGE_PDUMP_DUMPBITMAP PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+8)
-#define PVRSRV_BRIDGE_PDUMP_DUMPREADREG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+9)
-#define PVRSRV_BRIDGE_PDUMP_SYNCPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+10)
-#define PVRSRV_BRIDGE_PDUMP_DUMPSYNC PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+11)
-#define PVRSRV_BRIDGE_PDUMP_MEMPAGES PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+12)
-#define PVRSRV_BRIDGE_PDUMP_DRIVERINFO PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+13)
-#define PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_PDUMP_INIT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_MEMPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DUMPMEM PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_REG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_REGPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_COMMENT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+5) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_SETFRAME PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+6) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_ISCAPTURING PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DUMPBITMAP PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+8) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DUMPREADREG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+9) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_SYNCPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+10) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DUMPSYNC PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+11) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_MEMPAGES PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+12) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DRIVERINFO PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+13) /*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+15) /*!< pdump command structure */
#define PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+16)
#define PVRSRV_BRIDGE_PDUMP_STARTINITPHASE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+17)
#define PVRSRV_BRIDGE_PDUMP_STOPINITPHASE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
#define PVRSRV_BRIDGE_PDUMP_CMD_LAST (PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
#else
+/* Note we are carefull here not to leave a large gap in the ioctl numbers.
+ * (Some ports may use these values to index into an array where large gaps can
+ * waste memory) */
#define PVRSRV_BRIDGE_PDUMP_CMD_LAST PVRSRV_BRIDGE_OVERLAY_CMD_LAST
#endif
+/* DisplayClass APIs */
#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_GET_OEMJTABLE PVRSRV_IOWR(PVRSRV_BRIDGE_OEM_CMD_FIRST+0) /*!< Get OEM Jtable */
#define PVRSRV_BRIDGE_OEM_CMD_LAST (PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+/* device class enum */
#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)
+/* display class API */
#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_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_SWAP_DISPCLASS_TO_BUFFER2 PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_LAST (PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+15)
+/* buffer class API */
#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_BUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
#define PVRSRV_BRIDGE_BUFCLASS_CMD_LAST (PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+/* Wrap/Unwrap external memory */
#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)
+/* Shared memory */
#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_UNMAP_MEMINFO_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
#define PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST (PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+/* Intialisation Service support */
#define PVRSRV_BRIDGE_INITSRV_CMD_FIRST (PVRSRV_BRIDGE_SHAREDMEM_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)
+/* Event Objects */
#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)
+/* Sync ops */
#define PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST+1)
#define PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+0)
#define PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+1)
#define PVRSRV_BRIDGE_FREE_SYNC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+9)
#define PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST (PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+9)
+/* For sgx_bridge.h (msvdx_bridge.h should probably use these defines too) */
#define PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD (PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST+1)
+/******************************************************************************
+ * Bridge flags
+ *****************************************************************************/
#define PVRSRV_KERNEL_MODE_CLIENT 1
+/******************************************************************************
+ * Generic bridge structures
+ *****************************************************************************/
+
+/******************************************************************************
+ * bridge return structure
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_RETURN_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_RETURN;
+/******************************************************************************
+ * bridge packaging structure
+ *****************************************************************************/
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_UINT32 ui32BridgeID; /*!< ioctl/drvesc index */
+ IMG_UINT32 ui32Size; /*!< size of structure */
+ IMG_VOID *pvParamIn; /*!< input data buffer */
+ IMG_UINT32 ui32InBufferSize; /*!< size of input data buffer */
+ IMG_VOID *pvParamOut; /*!< output data buffer */
+ IMG_UINT32 ui32OutBufferSize; /*!< size of output data buffer */
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hKernelServices;
+ IMG_SID hKernelServices; /*!< kernel servcies handle */
#else
- IMG_HANDLE hKernelServices;
+ IMG_HANDLE hKernelServices; /*!< kernel servcies handle */
#endif
}PVRSRV_BRIDGE_PACKAGE;
+/******************************************************************************
+ * Input structures for IOCTL/DRVESC
+ *****************************************************************************/
+
+
+/******************************************************************************
+ * 'bridge in' connect to services
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_CONNECT_SERVICES_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_UINT32 ui32Flags;
} PVRSRV_BRIDGE_IN_CONNECT_SERVICES;
+/******************************************************************************
+ * 'bridge in' acquire device info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_UINT32 uiDevIndex;
PVRSRV_DEVICE_TYPE eDeviceType;
} PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO;
+/******************************************************************************
+ * 'bridge in' enum class
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_ENUMCLASS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
PVRSRV_DEVICE_CLASS sDeviceClass;
} PVRSRV_BRIDGE_IN_ENUMCLASS;
+/******************************************************************************
+ * 'bridge in' close display class device
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
#else
} PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE;
+/******************************************************************************
+ * 'bridge in' enum display class formats
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
#else
} PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS;
+/******************************************************************************
+ * 'bridge in' get display class sysbuffer
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
#else
} PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER;
+/******************************************************************************
+ * 'bridge in' display class info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
#else
} PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO;
+/******************************************************************************
+ * 'bridge in' close buffer class device
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
#else
} PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE;
+/******************************************************************************
+ * 'bridge in' close buffer class device
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
#else
} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO;
+/******************************************************************************
+ * 'bridge out' acquire device info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
} PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO;
+/******************************************************************************
+ * 'bridge in' free class devices info.
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
PVRSRV_DEVICE_CLASS DeviceClass;
IMG_VOID* pvDevInfo;
}PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO;
+/******************************************************************************
+ * 'bridge in' get device memory heap info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hDevMemContext;
}PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO;
+/******************************************************************************
+ * 'bridge in' create device memory context
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
}PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT;
+/******************************************************************************
+ * 'bridge in' destroy device memory context
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hDevMemContext;
}PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT;
+/******************************************************************************
+ * 'bridge in' alloc device memory
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hDevMemHeap;
IMG_UINT32 ui32Attribs;
IMG_SIZE_T ui32Size;
IMG_SIZE_T ui32Alignment;
+ IMG_PVOID pvPrivData;
+ IMG_UINT32 ui32PrivDataLength;
+ IMG_UINT32 ui32ChunkSize;
+ IMG_UINT32 ui32NumVirtChunks;
+ IMG_UINT32 ui32NumPhysChunks;
+ IMG_BOOL *pabMapChunk;
}PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM;
+/******************************************************************************
+ * 'bridge in' map meminfo to user mode
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
}PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER;
+/******************************************************************************
+ * 'bridge in' unmap meminfo from user mode
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
}PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER;
+/******************************************************************************
+ * 'bridge in' free device memory
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hKernelMemInfo;
}PVRSRV_BRIDGE_IN_FREEDEVICEMEM;
+/******************************************************************************
+ * 'bridge in' export device memory
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hKernelMemInfo;
}PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM;
+/******************************************************************************
+ * 'bridge in' map ion handle
+ *****************************************************************************/
+typedef struct _PVRSRV_BRIDGE_IN_MAP_ION_HANDLE_
+{
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
+ IMG_HANDLE handle;
+ IMG_UINT32 ui32Attribs;
+ IMG_SIZE_T ui32Size;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hDevMemContext;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+#endif
+} PVRSRV_BRIDGE_IN_MAP_ION_HANDLE;
+
+/******************************************************************************
+ * 'bridge in' unmap ion handle
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_ION_HANDLE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+}PVRSRV_BRIDGE_IN_UNMAP_ION_HANDLE;
+
+/******************************************************************************
+ * 'bridge in' get free device memory
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_UINT32 ui32Flags;
} PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM;
+/******************************************************************************
+ * 'bridge in' create Cmd Q
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
}PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE;
+/******************************************************************************
+ * 'bridge in' destroy Cmd Q
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
}PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE;
+/******************************************************************************
+ * 'bridge in' get full map data
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hMHandle;
+ IMG_SID hMHandle; /* Handle associated with the memory that needs to be mapped */
#else
- IMG_HANDLE hMHandle;
+ IMG_HANDLE hMHandle; /* Handle associated with the memory that needs to be mapped */
#endif
} PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA;
+/******************************************************************************
+ * 'bridge in' get full map data
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hMHandle;
+ IMG_SID hMHandle; /* Handle associated with the memory that needs to be mapped */
#else
- IMG_HANDLE hMHandle;
+ IMG_HANDLE hMHandle; /* Handle associated with the memory that needs to be mapped */
#endif
} PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA;
+/******************************************************************************
+ * 'bridge in' reserve vm
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevMemHeap;
#else
}PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM;
+/******************************************************************************
+ * 'bridge out' connect to services
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_CONNECT_SERVICES_TAG
{
PVRSRV_ERROR eError;
#endif
}PVRSRV_BRIDGE_OUT_CONNECT_SERVICES;
+/******************************************************************************
+ * 'bridge out' reserve vm
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM;
+/******************************************************************************
+ * 'bridge in' free vm
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
}PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM;
+/******************************************************************************
+ * 'bridge in' map dev memory allocation to another heap
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
IMG_SID hDstDevMemHeap;
}PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY;
+/******************************************************************************
+ * 'bridge out' map dev memory allocation to another heap
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY;
+/******************************************************************************
+ * 'bridge in' unmap dev memory allocation
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
}PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY;
+/******************************************************************************
+ * 'bridge in' map pages
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
}PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY;
+/******************************************************************************
+ * 'bridge in' unmap pages
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
IMG_UINT32 ui32Flags;
}PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY;
+/******************************************************************************
+ * 'bridge in' map device class buffer pages
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceClassBuffer;
IMG_SID hDevMemContext;
}PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY;
+/******************************************************************************
+ * 'bridge out' map device class buffer pages
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY;
+/******************************************************************************
+ * 'bridge in' unmap device class buffer pages
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
}PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY;
+/******************************************************************************
+ * 'bridge in' pdump memory poll
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPOL_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
}PVRSRV_BRIDGE_IN_PDUMP_MEMPOL;
+/******************************************************************************
+ * 'bridge in' pdump sync poll
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelSyncInfo;
#else
}PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL;
+/******************************************************************************
+ * 'bridge in' pdump dump memory
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_PVOID pvLinAddr;
IMG_PVOID pvAltLinAddr;
#if defined (SUPPORT_SID_INTERFACE)
}PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM;
+/******************************************************************************
+ * 'bridge in' pdump dump sync
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_PVOID pvAltLinAddr;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelSyncInfo;
}PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC;
+/******************************************************************************
+ * 'bridge in' pdump dump reg
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPREG_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
}PVRSRV_BRIDGE_IN_PDUMP_DUMPREG;
+/******************************************************************************
+ * 'bridge in' pdump dump reg
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_REGPOL_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
IMG_CHAR szRegRegion[32];
}PVRSRV_BRIDGE_IN_PDUMP_REGPOL;
+/******************************************************************************
+ * 'bridge in' pdump dump PD reg
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
PVRSRV_HWREG sHWReg;
IMG_UINT32 ui32Flags;
}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG;
+/******************************************************************************
+ * 'bridge in' pdump dump mem pages
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hKernelMemInfo;
}PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES;
+/******************************************************************************
+ * 'bridge in' pdump dump comment
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_COMMENT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_CHAR szComment[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
IMG_UINT32 ui32Flags;
}PVRSRV_BRIDGE_IN_PDUMP_COMMENT;
+/******************************************************************************
+ * 'bridge in' pdump set frame
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_SETFRAME_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_UINT32 ui32Frame;
}PVRSRV_BRIDGE_IN_PDUMP_SETFRAME;
+/******************************************************************************
+ * 'bridge in' pdump dump bitmap
+ *****************************************************************************/
+
typedef struct PVRSRV_BRIDGE_IN_PDUMP_BITMAP_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
}PVRSRV_BRIDGE_IN_PDUMP_BITMAP;
+/******************************************************************************
+ * 'bridge in' pdump dump read reg
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_READREG_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
}PVRSRV_BRIDGE_IN_PDUMP_READREG;
+/******************************************************************************
+ * 'bridge in' pdump dump driver-info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_CHAR szString[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
IMG_BOOL bContinuous;
typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
IMG_DEV_PHYADDR sPDDevPAddr;
}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR;
+/******************************************************************************
+ * 'bridge in' pdump cycle count register read
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_PDUM_IN_CYCLE_COUNT_REG_READ_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
IMG_BOOL bLastFrame;
}PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ;
+/*****************************************************************************
+ * Output structures for BRIDGEs
+ ****************************************************************************/
+
+/******************************************************************************
+ * 'bridge out' enum. devices
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_ENUMDEVICE_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_ENUMDEVICE;
+/******************************************************************************
+ * 'bridge out' acquire device info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO_TAG
{
} PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO;
+/******************************************************************************
+ * 'bridge out' enum. class devices
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_ENUMCLASS_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_ENUMCLASS;
+/******************************************************************************
+ * 'bridge in' open display class devices
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_UINT32 ui32DeviceID;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
}PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE;
+/******************************************************************************
+ * 'bridge out' open display class devices
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE;
+/******************************************************************************
+ * 'bridge in' wrap pages
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hDevMemContext;
}PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY;
+/******************************************************************************
+ * 'bridge out' wrap pages
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY;
+/******************************************************************************
+ * 'bridge in' unwrap pages
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
#define PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS 4
#define PVRSRV_MAX_DC_CLIP_RECTS 32
+/******************************************************************************
+ * 'bridge out' enum display class formats
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS;
+/******************************************************************************
+ * 'bridge in' enum display class dims
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
#else
}PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS;
+/******************************************************************************
+ * 'bridge out' enum display class dims
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS;
+/******************************************************************************
+ * 'bridge out' enum display class dims
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO;
+/******************************************************************************
+ * 'bridge out' get display class system buffer
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER;
+/******************************************************************************
+ * 'bridge in' create swap chain
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
#else
} PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN;
+/******************************************************************************
+ * 'bridge out' create swap chain
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN;
+/******************************************************************************
+ * 'bridge in' destroy swap chain
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
IMG_SID hSwapChain;
} PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN;
+/******************************************************************************
+ * 'bridge in' set DST/SRC rect
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
IMG_SID hSwapChain;
} PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT;
+/******************************************************************************
+ * 'bridge in' set DST/SRC colourkey
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
IMG_SID hSwapChain;
} PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY;
+/******************************************************************************
+ * 'bridge in' get buffers (from swapchain)
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
IMG_SID hSwapChain;
} PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS;
+/******************************************************************************
+ * 'bridge out' get buffers (from swapchain)
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS_TAG
{
PVRSRV_ERROR eError;
#else
IMG_HANDLE ahBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
#endif
-
+ IMG_SYS_PHYADDR asPhyAddr[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
} PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS;
+/******************************************************************************
+ * 'bridge in' swap to buffer
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
IMG_SID hBuffer;
} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER;
+/******************************************************************************
+ * 'bridge in' swap to buffer
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER2_TAG
+{
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+ IMG_SID hSwapChain;
+#else
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+#endif
+ IMG_UINT32 ui32SwapInterval;
+
+ IMG_UINT32 ui32NumMemInfos;
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos;
+ PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfos;
+
+ IMG_UINT32 ui32PrivDataLength;
+ IMG_PVOID pvPrivData;
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER2;
+
+/******************************************************************************
+ * 'bridge in' swap to system buffer (primary)
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
IMG_SID hSwapChain;
} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM;
+/******************************************************************************
+ * 'bridge in' open buffer class device
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_UINT32 ui32DeviceID;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
} PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE;
+/******************************************************************************
+ * 'bridge out' open buffer class device
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE;
+/******************************************************************************
+ * 'bridge out' get buffer class info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO;
+/******************************************************************************
+ * 'bridge in' get buffer class buffer
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDeviceKM;
#else
} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER;
+/******************************************************************************
+ * 'bridge out' get buffer class buffer
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER;
+/******************************************************************************
+ * 'bridge out' get heap info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO;
+/******************************************************************************
+ * 'bridge out' create device memory context
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT;
+/******************************************************************************
+ * 'bridge out' create device memory context
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP;
+/******************************************************************************
+ * 'bridge out' alloc device memory
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM;
+/******************************************************************************
+ * 'bridge out' export device memory
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM;
+/******************************************************************************
+ * 'bridge out' map ion handle
+ *****************************************************************************/
+typedef struct _PVRSRV_BRIDGE_OUT_MAP_ION_HANDLE_
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+} PVRSRV_BRIDGE_OUT_MAP_ION_HANDLE;
+
+
+/******************************************************************************
+ * 'bridge out' map meminfo to user mode
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER;
+/******************************************************************************
+ * 'bridge out' get free device memory
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM;
+//#ifdef LINUX
+/******************************************************************************
+ * 'bridge out' get full map data
+ *****************************************************************************/
#include "pvrmmap.h"
typedef struct PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA_TAG
{
PVRSRV_ERROR eError;
-
+ /* This is a the offset you should pass to mmap(2) so that
+ * the driver can look up the full details for the mapping
+ * request. */
IMG_UINT32 ui32MMapOffset;
-
+ /* This is the byte offset you should add to the mapping you
+ * get from mmap */
IMG_UINT32 ui32ByteOffset;
-
+ /* This is the real size of the mapping that will be created
+ * which should be passed to mmap _and_ munmap. */
IMG_UINT32 ui32RealByteSize;
-
+ /* User mode address associated with mapping */
IMG_UINT32 ui32UserVAddr;
} PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA;
{
PVRSRV_ERROR eError;
-
+ /* Flag that indicates whether the mapping should be destroyed */
IMG_BOOL bMUnmap;
-
+ /* User mode address associated with mapping */
IMG_UINT32 ui32UserVAddr;
-
+ /* Size of mapping */
IMG_UINT32 ui32RealByteSize;
} PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA;
+//#endif
+
+
+/******************************************************************************
+ * 'bridge in' get misc info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GET_MISC_INFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
PVRSRV_MISC_INFO sMiscInfo;
}PVRSRV_BRIDGE_IN_GET_MISC_INFO;
+/******************************************************************************
+ * 'bridge out' get misc info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GET_MISC_INFO_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_GET_MISC_INFO;
+/******************************************************************************
+ * 'bridge in' get misc info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
PVRSRV_MISC_INFO sMiscInfo;
}PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO;
+/******************************************************************************
+ * 'bridge out' get misc info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO;
+/******************************************************************************
+ * 'bridge out' PDUMP is capturing
+ *****************************************************************************/
+
typedef struct PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING_TAG
{
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING;
+/******************************************************************************
+ * 'bridge in' get FB mem stats
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GET_FB_STATS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_SIZE_T ui32Total;
IMG_SIZE_T ui32Available;
} PVRSRV_BRIDGE_IN_GET_FB_STATS;
+/******************************************************************************
+ * 'bridge in' Map CPU Physical to User Space
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
} PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE;
+/******************************************************************************
+ * 'bridge out' Map CPU Physical to User Space
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE_TAG
{
IMG_PVOID pvUserAddr;
} PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE;
+/******************************************************************************
+ * 'bridge in' Unmap CPU Physical to User Space
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
} PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE;
+/******************************************************************************
+ * 'bridge out' Get user space pointer to Phys to Lin lookup table
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP_TAG
{
IMG_PVOID *ppvTbl;
#if !defined (SUPPORT_SID_INTERFACE)
+/******************************************************************************
+ * 'bridge in' Register RTSIM process thread
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_HANDLE hDevCookie;
IMG_PVOID pvProcess;
} PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS;
+/******************************************************************************
+ * 'bridge out' Register RTSIM process thread
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS_TAG
{
- IMG_SYS_PHYADDR sRegsPhysBase;
- IMG_VOID *pvRegsBase;
+ IMG_SYS_PHYADDR sRegsPhysBase; /*!< Physical address of current device register */
+ IMG_VOID *pvRegsBase; /*!< User mode linear address of SGX device registers */
IMG_PVOID pvProcess;
IMG_UINT32 ulNoOfEntries;
IMG_PVOID pvTblLinAddr;
} PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS;
+/******************************************************************************
+ * 'bridge in' Unregister RTSIM process thread
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_HANDLE hDevCookie;
IMG_PVOID pvProcess;
- IMG_VOID *pvRegsBase;
+ IMG_VOID *pvRegsBase; /*!< User mode linear address of SGX device registers */
} PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS;
+/******************************************************************************
+ * 'bridge in' process simulator ISR event
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_HANDLE hDevCookie;
IMG_UINT32 ui32StatusAndMask;
PVRSRV_ERROR eError;
} PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT;
-#endif
+#endif /* #if !defined (SUPPORT_SID_INTERFACE) */
+/******************************************************************************
+ * 'bridge in' initialisation server disconnect
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_BOOL bInitSuccesful;
} PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT;
typedef struct PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_UINT32 ui32Flags;
IMG_SIZE_T ui32Size;
}PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM;
IMG_SID hKernelMemInfo;
IMG_SID hMappingInfo;
#else
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
#endif
PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
typedef struct PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
typedef struct PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
}PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM;
typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAI_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hOSEventKM;
#else
typedef struct PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelSyncInfoModObj;
#else
typedef struct PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelSyncInfoModObj;
IMG_SID hKernelSyncInfo;
typedef struct PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelSyncInfoModObj;
#else
{
PVRSRV_ERROR eError;
-
+ /* The following variable are used to return the PRE-INCREMENTED op vals */
IMG_UINT32 ui32ReadOpsPending;
IMG_UINT32 ui32WriteOpsPending;
+ IMG_UINT32 ui32ReadOps2Pending;
} PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS;
typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_TAKE_TOKEN_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelSyncInfo;
#else
IMG_UINT32 ui32ReadOpsPending;
IMG_UINT32 ui32WriteOpsPending;
+ IMG_UINT32 ui32ReadOps2Pending;
} PVRSRV_BRIDGE_OUT_SYNC_OPS_TAKE_TOKEN;
typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_TOKEN_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelSyncInfo;
#else
#endif
IMG_UINT32 ui32ReadOpsPendingSnapshot;
IMG_UINT32 ui32WriteOpsPendingSnapshot;
+ IMG_UINT32 ui32ReadOps2PendingSnapshot;
} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_TOKEN;
typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelSyncInfoModObj;
#else
typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelSyncInfo;
#else
typedef struct PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
typedef struct PVRSRV_BRIDGE_IN_FREE_SYNC_INFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelSyncInfo;
}
#endif
-#endif
+#endif /* __PVR_BRIDGE_H__ */
+
+/******************************************************************************
+ End of file (pvr_bridge.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the PVR Bridge code
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __PVR_BRIDGE_KM_H_
#define __PVR_BRIDGE_KM_H_
#include "pvr_bridge.h"
#include "perproc.h"
+/******************************************************************************
+ * Function prototypes
+ *****************************************************************************/
#if defined(__linux__)
PVRSRV_ERROR LinuxBridgeInit(IMG_VOID);
IMG_VOID LinuxBridgeDeInit(IMG_VOID);
IMG_UINT32 ui32Flags,
IMG_SIZE_T ui32Size,
IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
- #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo, logStr) \
+ #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, \
+ chunksize, numvirtchunks, numphyschunks, mapchunk, memInfo, logStr) \
(PVR_TRACE(("PVRSRVAllocDeviceMemKM(" #devCookie ", " #perProc ", " #devMemHeap ", " #flags ", " #size \
", " #alignment "," #memInfo "): " logStr " (size = 0x%x)", size)),\
- _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo))
+ _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, \
+ chunksize, numvirtchunks, numphyschunks, mapchunk, memInfo))
#else
- #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo, logStr) \
- _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo)
+ #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, \
+ chunksize, numvirtchunks, numphyschunks, mapchunk, memInfo, logStr) \
+ _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, \
+ chunksize, numvirtchunks, numphyschunks, mapchunk, memInfo)
#endif
PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+#if defined(SUPPORT_ION)
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVMapIonHandleKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hIon,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapIonHandleKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+#endif /* SUPPORT_ION */
+
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie,
PVRSRV_KERNEL_MEM_INFO *psMemInfo);
IMG_HANDLE *phDeviceKM);
IMG_IMPORT
-PVRSRV_ERROR PVRSRVCloseDCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM(IMG_HANDLE hDeviceKM);
IMG_IMPORT
PVRSRV_ERROR PVRSRVEnumDCFormatsKM(IMG_HANDLE hDeviceKM,
PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
IMG_HANDLE hSwapChain,
IMG_UINT32 *pui32BufferCount,
- IMG_HANDLE *phBuffer);
+ IMG_HANDLE *phBuffer,
+ IMG_SYS_PHYADDR *psPhyAddr);
IMG_IMPORT
PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
IMG_HANDLE hBuffer,
IMG_UINT32 ui32ClipRectCount,
IMG_RECT *psClipRect);
IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfos,
+ PVRSRV_KERNEL_SYNC_INFO **ppsSyncInfos,
+ IMG_UINT32 ui32NumMemSyncInfos,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength);
+IMG_IMPORT
PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
IMG_HANDLE hSwapChain);
IMG_HANDLE hDevCookie,
IMG_HANDLE *phDeviceKM);
IMG_IMPORT
-PVRSRV_ERROR PVRSRVCloseBCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM(IMG_HANDLE hDeviceKM);
IMG_IMPORT
PVRSRV_ERROR PVRSRVGetBCInfoKM(IMG_HANDLE hDeviceKM,
IMG_HANDLE hDevMemContext,
PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo);
IMG_IMPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo);
+IMG_VOID IMG_CALLCONV PVRSRVAcquireSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo);
+IMG_IMPORT
+IMG_VOID IMG_CALLCONV PVRSRVReleaseSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo);
IMG_IMPORT
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo);
#endif
+/*!
+ * *****************************************************************************
+ * @brief Allocates memory on behalf of a userspace process that is addressable
+ * by ther kernel. The memory is suitable for mapping into
+ * user space and it is possible to entirely dissociate the memory
+ * from the userspace process via PVRSRVDissociateSharedSysMemoryKM.
+ *
+ * @param psPerProc
+ * @param ui32Flags
+ * @param ui32Size
+ * @param ppsKernelMemInfo
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR
PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_UINT32 ui32Flags,
IMG_SIZE_T ui32Size,
PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo);
+/*!
+ * *****************************************************************************
+ * @brief Frees memory allocated via PVRSRVAllocSharedSysMemoryKM (Note you must
+ * be sure any additional kernel references you created have been
+ * removed before freeing the memory)
+ *
+ * @param psKernelMemInfo
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR
PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+/*!
+******************************************************************************
+
+ @brief Dissociates memory from the process that allocates it. Intended for
+ transfering the ownership of system memory from a particular process
+ to the kernel. Unlike PVRSRVDissociateDeviceMemKM, ownership is not
+ transfered to the kernel context, so the Resource Manager will not
+ automatically clean up such memory.
+
+ @param psKernelMemInfo:
+
+ @return PVRSRV_ERROR:
+******************************************************************************/
IMG_IMPORT PVRSRV_ERROR
PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
}
#endif
-#endif
+#endif /* __PVR_BRIDGE_KM_H_ */
+/******************************************************************************
+ End of file (pvr_bridge_km.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Main include file for PVRMMAP library.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __PVRMMAP_H__
#define __PVRMMAP_H__
+/*!
+ **************************************************************************
+ @brief map kernel memory into user memory.
+
+ @param hModule - a handle to the device supplying the kernel memory
+ @param ppvLinAddr - pointer to where the user mode address should be placed
+ @param pvLinAddrKM - the base of kernel address range to map
+ @param phMappingInfo - pointer to mapping information handle
+ @param hMHandle - handle associated with memory to be mapped
+
+ @return PVRSRV_OK, or error code.
+ ***************************************************************************/
+
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRPMapKMem(IMG_HANDLE hModule, IMG_VOID **ppvLinAddr, IMG_VOID *pvLinAddrKM, IMG_SID *phMappingInfo, IMG_SID hMHandle);
#else
#endif
+/*!
+ **************************************************************************
+ @brief Removes a kernel to userspace memory mapping.
+
+ @param hModule - a handle to the device supplying the kernel memory
+ @param hMappingInfo - mapping information handle
+ @param hMHandle - handle associated with memory to be mapped
+
+ @return IMG_BOOL indicating success or otherwise.
+ ***************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
IMG_BOOL PVRUnMapKMem(IMG_HANDLE hModule, IMG_SID hMappingInfo, IMG_SID hMHandle);
#else
IMG_BOOL PVRUnMapKMem(IMG_HANDLE hModule, IMG_HANDLE hMappingInfo, IMG_HANDLE hMHandle);
#endif
-#endif
+#endif /* _PVRMMAP_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title error code to string translation utility
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description error code to string translation utility
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined (__PVRSRV_ERRORS_H__)
#define __PVRSRV_ERRORS_H__
extern "C" {
#endif
+/*
+ NOTE: TO BE INCLUDED ONLY ONCE IN THE UM AND KM SERVICES MODULES
+ PROVIDES IMPLEMENTATIONS OF
+
+ MUST BE KEPT IN SYNC WITH SERVICESEXT.H
+
+ PVRSRVGetErrorString
+ PVRSRVGetErrorStringKM
+ Specifically, we have
+
+ resources.c:
+ IMG_EXPORT
+ const IMG_CHAR *PVRSRVGetErrorString(PVRSRV_ERROR eError)
+ {
+ #include "pvrsrv_errors.h"
+ }
+
+ pvrsrv.c:
+ IMG_EXPORT
+ const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
+ {
+ #include "pvrsrv_errors.h"
+ }
+*/
switch (eError)
{
case PVRSRV_OK: return "No Errors";
case PVRSRV_ERROR_UNKNOWN_SGL_ERROR: return "PVRSRV_ERROR_UNKNOWN_SGL_ERROR";
case PVRSRV_ERROR_BAD_SYNC_STATE: return "PVRSRV_ERROR_BAD_SYNC_STATE";
+ case PVRSRV_ERROR_CACHE_INVALIDATE_FAILED: return "PVRSRV_ERROR_CACHE_INVALIDATE_FAILED";
+
case PVRSRV_ERROR_FORCE_I32: return "PVRSRV_ERROR_FORCE_I32";
default:
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* __PVRSRV_ERRORS_H__ */
+/*****************************************************************************
+ End of file (pvrsrv_errors.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Services Internal Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description services internal details
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined (__SERVICESINT_H__)
#define __SERVICESINT_H__
#include "services.h"
#include "sysinfo.h"
+#include "sysconfig.h"
#define HWREC_DEFAULT_TIMEOUT (500)
#define DRIVERNAME_MAXLENGTH (100)
+/*
+ helper macros:
+*/
#define ALIGNSIZE(size, alignshift) (((size) + ((1UL << (alignshift))-1)) & ~((1UL << (alignshift))-1))
#ifndef MAX
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
+/*
+ Note:
+ MAX_CLEANUP_TRYS is set to try and be around the frame rate
+ as for every try we will kick the uKernel which we want to avoid
+ doing too often (as we risk flooding the uKernel trace buffer
+ with requests and losing important information from before the
+ cleanup requests started).
+*/
+#define MAX_CLEANUP_TIME_US (MAX_HW_TIME_US * 4)
+#define MAX_CLEANUP_TRYS 100
+#define MAX_CLEANUP_TIME_WAIT_US (MAX_CLEANUP_TIME_US/MAX_CLEANUP_TRYS)
+
typedef enum _PVRSRV_MEMTYPE_
{
PVRSRV_MEMTYPE_UNKNOWN = 0,
PVRSRV_MEMTYPE_DEVICECLASS = 2,
PVRSRV_MEMTYPE_WRAPPED = 3,
PVRSRV_MEMTYPE_MAPPED = 4,
+ PVRSRV_MEMTYPE_ION = 5,
} PVRSRV_MEMTYPE;
+/*
+ Kernel Memory Information structure
+*/
typedef struct _PVRSRV_KERNEL_MEM_INFO_
{
-
+ /* Kernel Mode CPU Virtual address */
IMG_PVOID pvLinAddrKM;
-
+ /* Device Virtual Address */
IMG_DEV_VIRTADDR sDevVAddr;
-
+ /* allocation flags */
IMG_UINT32 ui32Flags;
-
+ /* Size of the allocated buffer in bytes */
IMG_SIZE_T uAllocSize;
-
+ /* Internal implementation details. Do not use outside services code. */
PVRSRV_MEMBLK sMemBlk;
-
+ /* Address of the backup buffer used in a save/restore of the surface */
IMG_PVOID pvSysBackupBuffer;
-
+ /* refcount for allocation, wrapping and mapping */
IMG_UINT32 ui32RefCount;
-
+ /* Set when free call ocured and a mapping was still open */
IMG_BOOL bPendingFree;
#if defined(SUPPORT_MEMINFO_IDS)
#if !defined(USE_CODE)
-
+ /* Globally unique "stamp" for allocation (not re-used until wrap) */
IMG_UINT64 ui64Stamp;
- #else
+ #else /* !defined(USE_CODE) */
IMG_UINT32 dummy1;
IMG_UINT32 dummy2;
- #endif
-#endif
+ #endif /* !defined(USE_CODE) */
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
-
+ /* ptr to associated kernel sync info - NULL if no sync */
struct _PVRSRV_KERNEL_SYNC_INFO_ *psKernelSyncInfo;
PVRSRV_MEMTYPE memType;
-
-
-
-
-
-
-
+ /*
+ To activate the "share mem workaround", add PVRSRV_MEM_XPROC to
+ the flags for the allocation. This will cause the "map" API to
+ call use Alloc Device Mem but will share the underlying memory
+ block and sync data. Note that this is a workaround for a bug
+ exposed by a specific use-case on a particular platform. Do not
+ use this functionality generally.
+ */
struct {
-
-
+ /* Record whether the workaround is active for this
+ allocation. The rest of the fields in this struct are
+ undefined unless this is true */
IMG_BOOL bInUse;
-
+ /* Store the device cookie handle from the original
+ allocation, as it is not present on the "Map" API. */
IMG_HANDLE hDevCookieInt;
-
+ /* This is an index into a static array which store
+ information about the underlying allocation */
IMG_UINT32 ui32ShareIndex;
-
-
+ /* Original arguments as supplied to original
+ "PVRSRVAllocDeviceMem" call, such that a new call to this
+ function can be later constructed */
IMG_UINT32 ui32OrigReqAttribs;
IMG_UINT32 ui32OrigReqSize;
IMG_UINT32 ui32OrigReqAlignment;
} PVRSRV_KERNEL_MEM_INFO;
+/*
+ Kernel Sync Info structure
+*/
typedef struct _PVRSRV_KERNEL_SYNC_INFO_
{
-
+ /* kernel sync data */
PVRSRV_SYNC_DATA *psSyncData;
-
+ /* Device accessible WriteOp Info */
IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
-
+ /* Device accessible ReadOp Info */
IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
-
+ /* Device accessible ReadOp Info */
+ IMG_DEV_VIRTADDR sReadOps2CompleteDevVAddr;
+
+ /* meminfo for sync data */
PVRSRV_KERNEL_MEM_INFO *psSyncDataMemInfoKM;
-
-
- IMG_UINT32 ui32RefCount;
+ /* Reference count for deferring destruction of syncinfo when it is shared */
+ /* NB: This is only done for devicemem.c (alloc/map/wrap etc), and
+ not (presently) for deviceclass memory */
+ IMG_PVOID pvRefCount;
-
+ /* Resman cleanup, for those created with explicit API */
IMG_HANDLE hResItem;
-
+ /* Unique ID of the sync object */
IMG_UINT32 ui32UID;
} PVRSRV_KERNEL_SYNC_INFO;
+/*!
+ *****************************************************************************
+ * This is a device addressable version of a pvrsrv_sync_oject
+ * - any hw cmd may have an unlimited number of these
+ ****************************************************************************/
typedef struct _PVRSRV_DEVICE_SYNC_OBJECT_
{
-
+ /* KEEP THESE 6 VARIABLES TOGETHER FOR UKERNEL BLOCK LOAD */
IMG_UINT32 ui32ReadOpsPendingVal;
IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
IMG_UINT32 ui32WriteOpsPendingVal;
IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui32ReadOps2PendingVal;
+ IMG_DEV_VIRTADDR sReadOps2CompleteDevVAddr;
} PVRSRV_DEVICE_SYNC_OBJECT;
+/*!
+ *****************************************************************************
+ * encapsulates a single sync object
+ * - any cmd may have an unlimited number of these
+ ****************************************************************************/
typedef struct _PVRSRV_SYNC_OBJECT
{
PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfoKM;
IMG_UINT32 ui32WriteOpsPending;
IMG_UINT32 ui32ReadOpsPending;
+ IMG_UINT32 ui32ReadOps2Pending;
}PVRSRV_SYNC_OBJECT, *PPVRSRV_SYNC_OBJECT;
+/*!
+ *****************************************************************************
+ * The `one size fits all' generic command.
+ ****************************************************************************/
typedef struct _PVRSRV_COMMAND
{
- IMG_SIZE_T uCmdSize;
- IMG_UINT32 ui32DevIndex;
- IMG_UINT32 CommandType;
- IMG_UINT32 ui32DstSyncCount;
- IMG_UINT32 ui32SrcSyncCount;
- PVRSRV_SYNC_OBJECT *psDstSync;
- PVRSRV_SYNC_OBJECT *psSrcSync;
- IMG_SIZE_T uDataSize;
- IMG_UINT32 ui32ProcessID;
- IMG_VOID *pvData;
+ IMG_SIZE_T uCmdSize; /*!< total size of command */
+ IMG_UINT32 ui32DevIndex; /*!< device type - 16bit enum (exported by system) */
+ IMG_UINT32 CommandType; /*!< command type */
+ IMG_UINT32 ui32DstSyncCount; /*!< number of dst sync objects */
+ IMG_UINT32 ui32SrcSyncCount; /*!< number of src sync objects */
+ PVRSRV_SYNC_OBJECT *psDstSync; /*!< dst sync ptr list, allocated on
+ back of this structure, i.e. is resident in Q */
+ PVRSRV_SYNC_OBJECT *psSrcSync; /*!< src sync ptr list, allocated on
+ back of this structure, i.e. is resident in Q */
+ IMG_SIZE_T uDataSize; /*!< Size of Cmd Data Packet
+ - only required in terms of allocating Q space */
+ IMG_UINT32 ui32ProcessID; /*!< Process ID for debugging */
+ IMG_VOID *pvData; /*!< data to be passed to Cmd Handler function,
+ allocated on back of this structure, i.e. is resident in Q */
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete; /*!< Command complete callback */
+ IMG_HANDLE hCallbackData; /*!< Command complete callback data */
}PVRSRV_COMMAND, *PPVRSRV_COMMAND;
+/*!
+ *****************************************************************************
+ * Circular command buffer structure forming the queue of pending commands.
+ *
+ * Queues are implemented as circular comamnd buffers (CCBs).
+ * The buffer is allocated as a specified size, plus the size of the largest supported command.
+ * The extra size allows commands to be added without worrying about wrapping around at the end.
+ *
+ * Commands are added to the CCB by client processes and consumed within
+ * kernel mode code running from within an L/MISR typically.
+ *
+ * The process of adding a command to a queue is as follows:-
+ * - A `lock' is acquired to prevent other processes from adding commands to a queue
+ * - Data representing the command to be executed, along with it's PVRSRV_SYNC_INFO
+ * dependencies is written to the buffer representing the queue at the queues
+ * current WriteOffset.
+ * - The PVRSRV_SYNC_INFO that the command depends on are updated to reflect
+ * the addition of the new command.
+ * - The WriteOffset is incremented by the size of the command added.
+ * - If the WriteOffset now lies beyound the declared buffer size, it is
+ * reset to zero.
+ * - The semaphore is released.
+ *
+ *****************************************************************************/
typedef struct _PVRSRV_QUEUE_INFO_
{
- IMG_VOID *pvLinQueueKM;
- IMG_VOID *pvLinQueueUM;
- volatile IMG_SIZE_T ui32ReadOffset;
- volatile IMG_SIZE_T ui32WriteOffset;
- IMG_UINT32 *pui32KickerAddrKM;
- IMG_UINT32 *pui32KickerAddrUM;
- IMG_SIZE_T ui32QueueSize;
+ IMG_VOID *pvLinQueueKM; /*!< Pointer to the command buffer in the kernel's
+ address space */
+
+ IMG_VOID *pvLinQueueUM; /*!< Pointer to the command buffer in the user's
+ address space */
+
+ volatile IMG_SIZE_T ui32ReadOffset; /*!< Index into the buffer at which commands are being
+ consumed */
- IMG_UINT32 ui32ProcessID;
+ volatile IMG_SIZE_T ui32WriteOffset; /*!< Index into the buffer at which commands are being
+ added */
+
+ IMG_UINT32 *pui32KickerAddrKM; /*!< kicker address in the kernel's
+ address space*/
+
+ IMG_UINT32 *pui32KickerAddrUM; /*!< kicker address in the user's
+ address space */
+
+ IMG_SIZE_T ui32QueueSize; /*!< Size in bytes of the buffer - excluding the safety allocation */
+
+ IMG_UINT32 ui32ProcessID; /*!< Process ID required by resource locking */
IMG_HANDLE hMemBlock[2];
- struct _PVRSRV_QUEUE_INFO_ *psNextKM;
+ struct _PVRSRV_QUEUE_INFO_ *psNextKM; /*!< The next queue in the system */
}PVRSRV_QUEUE_INFO;
}PVRSRV_HEAP_INFO_KM;
+/*
+ Event Object information structure
+*/
typedef struct _PVRSRV_EVENTOBJECT_KM_
{
-
+ /* globally unique name of the event object */
IMG_CHAR szName[EVENTOBJNAME_MAXLENGTH];
-
+ /* kernel specific handle for the event object */
IMG_HANDLE hOSEventKM;
} PVRSRV_EVENTOBJECT_KM;
+/*!
+ ******************************************************************************
+ * Structure to retrieve misc. information from services
+ *****************************************************************************/
typedef struct _PVRSRV_MISC_INFO_KM_
{
- IMG_UINT32 ui32StateRequest;
- IMG_UINT32 ui32StatePresent;
+ IMG_UINT32 ui32StateRequest; /*!< requested State Flags */
+ IMG_UINT32 ui32StatePresent; /*!< Present/Valid State Flags */
-
+ /*!< SOC Timer register */
IMG_VOID *pvSOCTimerRegisterKM;
IMG_VOID *pvSOCTimerRegisterUM;
IMG_HANDLE hSOCTimerRegisterOSMemHandle;
IMG_HANDLE hSOCTimerRegisterMappingInfo;
-
+ /*!< SOC Clock Gating registers */
IMG_VOID *pvSOCClockGateRegs;
IMG_UINT32 ui32SOCClockGateRegsSize;
-
+ /* Memory Stats/DDK version string depending on ui32StateRequest flags */
IMG_CHAR *pszMemoryStr;
IMG_UINT32 ui32MemoryStrLen;
-
- PVRSRV_EVENTOBJECT_KM sGlobalEventObject;
+ /* global event object */
+ PVRSRV_EVENTOBJECT_KM sGlobalEventObject;//FIXME: should be private to services
IMG_HANDLE hOSGlobalEvent;
-
+ /* Note: add misc. items as required */
IMG_UINT32 aui32DDKVersion[4];
-
+ /*!< CPU cache flush controls: */
struct
{
-
+ /*!< Defer the CPU cache op to the next HW op to be submitted (else flush now) */
IMG_BOOL bDeferOp;
-
+ /*!< Type of cache operation to perform */
PVRSRV_MISC_INFO_CPUCACHEOP_TYPE eCacheOpType;
+ /*!< Meminfo (or meminfo handle) to flush */
PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
-
+ /*!< Offset in MemInfo to start cache op */
IMG_VOID *pvBaseVAddr;
-
+ /*!< Length of range to perform cache op */
IMG_UINT32 ui32Length;
} sCacheOpCtl;
+
+ /*!< Meminfo refcount controls: */
+ struct
+ {
+ /*!< Meminfo (or meminfo handle) to get refcount for */
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ /*!< Resulting refcount */
+ IMG_UINT32 ui32RefCount;
+ } sGetRefCountCtl;
} PVRSRV_MISC_INFO_KM;
+/* insert command function pointer */
typedef PVRSRV_ERROR (*PFN_INSERT_CMD) (PVRSRV_QUEUE_INFO*,
PVRSRV_COMMAND**,
IMG_UINT32,
IMG_UINT32,
PVRSRV_KERNEL_SYNC_INFO*[],
IMG_UINT32);
+/* submit command function pointer */
typedef PVRSRV_ERROR (*PFN_SUBMIT_CMD) (PVRSRV_QUEUE_INFO*, PVRSRV_COMMAND*, IMG_BOOL);
+/***********************************************************************
+ Device Class Structures
+***********************************************************************/
+
+/*
+ Generic Device Class Buffer
+ - details common between DC and BC
+*/
typedef struct PVRSRV_DEVICECLASS_BUFFER_TAG
{
PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
} PVRSRV_DEVICECLASS_BUFFER;
+/*
+ Common Device Class client services information structure
+*/
typedef struct PVRSRV_CLIENT_DEVICECLASS_INFO_TAG
{
#if defined (SUPPORT_SID_INTERFACE)
} 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)
+typedef enum
{
- IMG_UINT32 ui32WriteOpsPending;
-
- if(bIsReadOp)
- {
- ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
- }
- else
- {
-
-
-
- ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending++;
- }
-
- return ui32WriteOpsPending;
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR,
+ PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER,
+ PVRSRV_FREE_CALLBACK_ORIGIN_EXTERNAL,
}
+PVRSRV_FREE_CALLBACK_ORIGIN;
-#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;
- }
+IMG_IMPORT
+PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin);
- return ui32ReadOpsPending;
-}
IMG_IMPORT
PVRSRV_ERROR PVRSRVQueueCommand(IMG_HANDLE hQueueInfo,
PVRSRV_COMMAND *psCommand);
+/*!
+ * *****************************************************************************
+ * @Description Allocates system memory on behalf of a userspace process that is
+ * addressable by the kernel; suitable for mapping into the current
+ * user space process; suitable for mapping into other userspace
+ * processes and it is possible to entirely disassociate the system
+ * memory from the current userspace process via a call to
+ * PVRSRVDissociateSharedSysMemoryKM.
+ *
+ * @Input psConnection
+ * @Input ui32Flags
+ * @Input ui32Size
+ * @Output ppsClientMemInfo
+ *
+ * @Return PVRSRV_ERROR
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
PVRSRVAllocSharedSysMem(const PVRSRV_CONNECTION *psConnection,
IMG_UINT32 ui32Flags,
IMG_SIZE_T ui32Size,
PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+/*!
+ * *****************************************************************************
+ * @Description Frees memory allocated via PVRSRVAllocSharedMemory (Note you must
+ * be sure any additional kernel references you created have been
+ * removed before freeing the memory)
+ *
+ * @Input psConnection
+ * @Input psClientMemInfo
+ *
+ * @Return PVRSRV_ERROR
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
PVRSRVFreeSharedSysMem(const PVRSRV_CONNECTION *psConnection,
PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+/*!
+ * *****************************************************************************
+ * @Description Removes any userspace reference to the shared system memory, except
+ * that the memory will remain registered with the services resource
+ * manager so if the process dies/exits the actuall shared memory will
+ * still be freed.
+ * If you need to move ownership of shared memory from userspace
+ * to kernel space then before unrefing a shared piece of memory you can
+ * take a copy of psClientMemInfo->hKernelMemInfo; call
+ * PVRSRVUnrefSharedSysMem; then use some mechanism (specialised bridge
+ * function) to request that the kernel remove any resource manager
+ * reference to the shared memory and assume responsaility for the meminfo
+ * in one atomic operation. (Note to aid with such a kernel space bridge
+ * function see PVRSRVDissociateSharedSysMemoryKM)
+ *
+ * @Input psConnection
+ * @Input psClientMemInfo
+ *
+ * @Return PVRSRV_ERROR
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR
PVRSRVUnrefSharedSysMem(const PVRSRV_CONNECTION *psConnection,
PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+/*!
+ * *****************************************************************************
+ * @Description For shared system or device memory that is owned by the kernel, you can
+ * use this function to map the underlying memory into a client using a
+ * handle for the KernelMemInfo.
+ *
+ * @Input psConnection
+ * @Input hKernelMemInfo
+ * @Output ppsClientMemInfo
+ *
+ * @Return PVRSRV_ERROR
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
PVRSRVMapMemInfoMem(const PVRSRV_CONNECTION *psConnection,
#if defined (SUPPORT_SID_INTERFACE)
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* __SERVICESINT_H__ */
+/*****************************************************************************
+ End of file (servicesint.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the sgx Brdige code
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined(__SGX_BRIDGE_H__)
#define __SGX_BRIDGE_H__
#endif
+/*
+ * Bridge Cmd Ids
+ */
+
+/* *REMEMBER* to update PVRSRV_BRIDGE_LAST_SGX_CMD if you add/remove a command!
+ * Also you need to ensure all PVRSRV_BRIDGE_SGX_CMD_BASE+ offsets are sequential!
+ */
+
#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)
+/* *REMEMBER* to update PVRSRV_BRIDGE_LAST_SGX_CMD if you add/remove a command!
+ * You need to ensure all PVRSRV_BRIDGE_SGX_CMD_BASE+ offsets are sequential!
+ */
#define PVRSRV_BRIDGE_LAST_SGX_CMD (PVRSRV_BRIDGE_SGX_CMD_BASE+37)
-
+/*****************************************************************************
+ * Input structures for IOCTL/DRVESC
+ *****************************************************************************/
+
+/*!
+ *****************************************************************************
+ * `bridge in' SGX Get Phys Page Addr
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_HANDLE hDevMemHeap;
IMG_DEV_VIRTADDR sDevVAddr;
}PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR;
-
+/*!
+ *****************************************************************************
+ * `bridge out' SGX Get Phys Page Addr
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR
{
PVRSRV_ERROR eError;
IMG_CPU_PHYADDR CpuPAddr;
}PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR;
-
+/*!
+ *****************************************************************************
+ * `bridge in' set transfer context priority
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SGX_SET_TRANSFER_CONTEXT_PRIORITY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hHWTransferContext;
IMG_UINT32 ui32OffsetOfPriorityField;
}PVRSRV_BRIDGE_IN_SGX_SET_TRANSFER_CONTEXT_PRIORITY;
-
+/*!
+ *****************************************************************************
+ * `bridge in' set render context priority
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SGX_SET_RENDER_CONTEXT_PRIORITY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hHWRenderContext;
IMG_UINT32 ui32OffsetOfPriorityField;
}PVRSRV_BRIDGE_IN_SGX_SET_RENDER_CONTEXT_PRIORITY;
-
+/*!
+ *****************************************************************************
+ * `bridge in' Get Client Info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GETCLIENTINFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
#endif
}PVRSRV_BRIDGE_IN_GETCLIENTINFO;
-
+/*!
+ *****************************************************************************
+ * `bridge out' Get internal device info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO_TAG
{
SGX_INTERNAL_DEVINFO sSGXInternalDevInfo;
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO;
-
+/*!
+ *****************************************************************************
+ * `bridge in' Get internal device info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
#endif
}PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO;
-
+/*!
+ *****************************************************************************
+ * `bridge out' Get Client Info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_GETCLIENTINFO_TAG
{
SGX_CLIENT_INFO sClientInfo;
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_GETCLIENTINFO;
-
+/*!
+ *****************************************************************************
+ * `bridge in' Release Client Info
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
SGX_CLIENT_INFO sClientInfo;
}PVRSRV_BRIDGE_IN_RELEASECLIENTINFO;
-
+/*!
+ *****************************************************************************
+ * `bridge in' Pdump ISP mem Pol
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_ISPBREAKPOLL_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
#endif
}PVRSRV_BRIDGE_IN_ISPBREAKPOLL;
-
+/*!
+ *****************************************************************************
+ * `bridge in' KickTA
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_DOKICK_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
SGX_CCB_KICK sCCBKick;
}PVRSRV_BRIDGE_IN_DOKICK;
-
+/*!
+ *****************************************************************************
+ * `bridge in' SGXScheduleProcessQueues
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
#if defined(TRANSFER_QUEUE)
-
+/*!
+ *****************************************************************************
+ * `bridge in' SubmitTransfer
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SUBMITTRANSFER_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
}PVRSRV_BRIDGE_IN_SUBMITTRANSFER;
#if defined(SGX_FEATURE_2D_HARDWARE)
-
+/*!
+ *****************************************************************************
+ * `bridge in' Submit2D
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SUBMIT2D_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
#endif
#endif
-
+/*!
+ *****************************************************************************
+ * `bridge in' ReadRegistryString
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_READREGDWORD_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
IMG_PCHAR pszValue;
}PVRSRV_BRIDGE_IN_READREGDWORD;
-
+/*!
+ *****************************************************************************
+ * `bridge out' ReadRegistryString
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_READREGDWORD_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_READREGDWORD;
+/*!
+ *****************************************************************************
+ * `bridge in' SGXGetMiscInfo
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SGXGETMISCINFO_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
SGX_MISC_INFO *psMiscInfo;
}PVRSRV_BRIDGE_IN_SGXGETMISCINFO;
+/*!
+ *****************************************************************************
+ * `bridge in' SGXGetInfoForSrvInit
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
#endif
}PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT;
+/*!
+ *****************************************************************************
+ * `bridge out' SGXGetInfoForSrvInit
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT_TAG
{
PVRSRV_ERROR eError;
SGX_BRIDGE_INFO_FOR_SRVINIT sInitInfo;
}PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT;
+/*!
+ *****************************************************************************
+ * `bridge in' SGXDevInitPart2
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
SGX_BRIDGE_INIT_INFO sInitInfo;
}PVRSRV_BRIDGE_IN_SGXDEVINITPART2;
+/*!
+ *****************************************************************************
+ * `bridge out' SGXDevInitPart2
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_SGXDEVINITPART2_TAG
{
PVRSRV_ERROR eError;
}PVRSRV_BRIDGE_OUT_SGXDEVINITPART2;
-
+/*!
+ *****************************************************************************
+ * `bridge in' 2D query blits complete
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hKernSyncInfo;
typedef struct PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
typedef struct PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hSharedPBDesc;
#else
typedef struct PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_UINT32 ui32TotalPBSize;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#ifdef PDUMP
typedef struct PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
SGX_KICKTA_DUMP_BUFFER *psBufferArray;
IMG_UINT32 ui32BufferArrayLength;
IMG_BOOL bDumpPolls;
typedef struct PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hDevMemContext;
typedef struct PVRSRV_BRIDGE_IN_PDUMPCOUNTER_REGISTERS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
typedef struct PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
typedef struct PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hDevMemContext;
typedef struct PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
IMG_SID hDevMemContext;
typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_BOOL bForceCleanup;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_BOOL bForceCleanup;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
typedef struct PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr;
}PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET;
-
+/*!
+ *****************************************************************************
+ * SGX 2D specific defines
+ *****************************************************************************/
#if defined(SGX_FEATURE_2D_HARDWARE)
typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
IMG_BOOL bForceCleanup;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#endif
}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT;
-#define SGX2D_MAX_BLT_CMD_SIZ 256
-#endif
+#define SGX2D_MAX_BLT_CMD_SIZ 256 /* Maximum size of a blit command, in bytes */
+#endif /* SGX_FEATURE_2D_HARDWARE */
+/*!
+ *****************************************************************************
+ * `bridge in' SGXReadHWPerfCB
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB_TAG
{
- IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hDevCookie;
#else
PVRSRV_SGX_HWPERF_CB_ENTRY *psHWPerfCBData;
} PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB;
+/*!
+ *****************************************************************************
+ * `bridge out' SGXReadHWPerfCB
+ *****************************************************************************/
typedef struct PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB_TAG
{
PVRSRV_ERROR eError;
}
#endif
-#endif
+#endif /* __SGX_BRIDGE_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX microkernel interface structures used by srvkm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description SGX microkernel interface structures used by srvkm
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined (__SGX_MKIF_KM_H__)
#define __SGX_MKIF_KM_H__
#if !defined (SGX_MP_CORE_SELECT)
+/* MP register control macros */
#if defined(SGX_FEATURE_MP)
#define SGX_REG_BANK_SHIFT (14)
#define SGX_REG_BANK_SIZE (1 << SGX_REG_BANK_SHIFT)
#define SGX_MP_MASTER_SELECT(x) (x + (SGX_REG_BANK_MASTER_INDEX * SGX_REG_BANK_SIZE))
#else
#define SGX_MP_CORE_SELECT(x,i) (x)
-#endif
+#endif /* SGX_FEATURE_MP */
#endif
+/*!
+ ******************************************************************************
+ * CCB command structure for SGX
+ *****************************************************************************/
typedef struct _SGXMKIF_COMMAND_
{
- IMG_UINT32 ui32ServiceAddress;
- IMG_UINT32 ui32CacheControl;
- IMG_UINT32 ui32Data[6];
+ IMG_UINT32 ui32ServiceAddress; /*!< address of the USE command handler */
+ IMG_UINT32 ui32CacheControl; /*!< See SGXMKIF_CC_INVAL_* */
+ IMG_UINT32 ui32Data[6]; /*!< array of other command control words */
} SGXMKIF_COMMAND;
+/*!
+ ******************************************************************************
+ * CCB array of commands for SGX
+ *****************************************************************************/
typedef struct _PVRSRV_SGX_KERNEL_CCB_
{
- SGXMKIF_COMMAND asCommands[256];
+ SGXMKIF_COMMAND asCommands[256]; /*!< array of commands */
} PVRSRV_SGX_KERNEL_CCB;
+/*!
+ ******************************************************************************
+ * CCB control for SGX
+ *****************************************************************************/
typedef struct _PVRSRV_SGX_CCB_CTL_
{
- IMG_UINT32 ui32WriteOffset;
- IMG_UINT32 ui32ReadOffset;
+ IMG_UINT32 ui32WriteOffset; /*!< write offset into array of commands (MUST be alligned to 16 bytes!) */
+ IMG_UINT32 ui32ReadOffset; /*!< read offset into array of commands */
} PVRSRV_SGX_CCB_CTL;
+/*!
+ *****************************************************************************
+ * Control data for SGX
+ *****************************************************************************/
typedef struct _SGXMKIF_HOST_CTL_
{
#if defined(PVRSRV_USSE_EDM_BREAKPOINTS)
IMG_UINT32 ui32Continue;
#endif
- volatile IMG_UINT32 ui32InitStatus;
- volatile IMG_UINT32 ui32PowerStatus;
- volatile IMG_UINT32 ui32CleanupStatus;
+ volatile IMG_UINT32 ui32InitStatus; /*!< Microkernel Initialisation status */
+ volatile IMG_UINT32 ui32PowerStatus; /*!< Microkernel Power Management status */
+ volatile IMG_UINT32 ui32CleanupStatus; /*!< Microkernel Resource Management status */
#if defined(FIX_HW_BRN_28889)
- volatile IMG_UINT32 ui32InvalStatus;
+ volatile IMG_UINT32 ui32InvalStatus; /*!< Microkernel BIF Cache Invalidate status */
#endif
#if defined(SUPPORT_HW_RECOVERY)
- IMG_UINT32 ui32uKernelDetectedLockups;
- IMG_UINT32 ui32HostDetectedLockups;
- IMG_UINT32 ui32HWRecoverySampleRate;
-#endif
- IMG_UINT32 ui32uKernelTimerClock;
- IMG_UINT32 ui32ActivePowManSampleRate;
- IMG_UINT32 ui32InterruptFlags;
- IMG_UINT32 ui32InterruptClearFlags;
- IMG_UINT32 ui32BPSetClearSignal;
-
- IMG_UINT32 ui32NumActivePowerEvents;
-
- IMG_UINT32 ui32TimeWraps;
- IMG_UINT32 ui32HostClock;
- IMG_UINT32 ui32AssertFail;
+ IMG_UINT32 ui32uKernelDetectedLockups; /*!< counter relating to the number of lockups the uKernel has detected */
+ IMG_UINT32 ui32HostDetectedLockups; /*!< counter relating to the number of lockups the host has detected */
+ IMG_UINT32 ui32HWRecoverySampleRate; /*!< SGX lockup detection rate (in multiples of the timer period) */
+#endif /* SUPPORT_HW_RECOVERY*/
+ IMG_UINT32 ui32uKernelTimerClock; /*!< SGX ukernel timer period (in clocks) */
+ IMG_UINT32 ui32ActivePowManSampleRate; /*!< SGX Active Power latency period (in multiples of the timer period) */
+ IMG_UINT32 ui32InterruptFlags; /*!< Interrupt flags - PVRSRV_USSE_EDM_INTERRUPT_xxx */
+ IMG_UINT32 ui32InterruptClearFlags; /*!< Interrupt clear flags - PVRSRV_USSE_EDM_INTERRUPT_xxx */
+ IMG_UINT32 ui32BPSetClearSignal; /*!< Breakpoint set/cear signal */
+
+ IMG_UINT32 ui32NumActivePowerEvents; /*!< counter for the number of active power events */
+
+ IMG_UINT32 ui32TimeWraps; /*!< to count time wraps in the Timer task*/
+ IMG_UINT32 ui32HostClock; /*!< Host clock value at microkernel power-up time */
+ IMG_UINT32 ui32AssertFail; /*!< Microkernel assert failure code */
#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
- IMG_UINT32 aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
- IMG_UINT32 aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+ IMG_UINT32 aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS]; /*!< Specifies the HW's active group selectors */
+ IMG_UINT32 aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS]; /*!< Specifies the HW's active bit selectors */
+ IMG_UINT32 ui32PerfCounterBitSelect; /*!< Specifies the HW's counter bit selectors */
+ IMG_UINT32 ui32PerfSumMux; /*!< Specifies the HW's sum_mux selectors */
#else
- IMG_UINT32 ui32PerfGroup;
-#endif
+ IMG_UINT32 ui32PerfGroup; /*!< Specifies the HW's active group */
+#endif /* SGX_FEATURE_EXTENDED_PERF_COUNTERS */
#if defined(FIX_HW_BRN_31939)
IMG_UINT32 ui32BRN31939Mem;
#endif
- IMG_UINT32 ui32OpenCLDelayCount;
+ IMG_UINT32 ui32OpenCLDelayCount; /* Counter to keep track OpenCL task completion time in units of regular task time out events */
} SGXMKIF_HOST_CTL;
+/*
+ * TA queue Kick flags
+ */
+/* Set in DoKickKM to indicate the command is ready to be processed */
#define SGXMKIF_CMDTA_CTRLFLAGS_READY 0x00000001
+/*!
+ ******************************************************************************
+ * Shared TA command structure.
+ * This structure is part of the TA command structure proper (SGXMKIF_CMDTA),
+ * and is accessed from the kernel part of the driver and the microkernel.
+ * There shouldn't be a need to access it from user space.
+ *****************************************************************************/
typedef struct _SGXMKIF_CMDTA_SHARED_
{
IMG_UINT32 ui32CtrlFlags;
IMG_UINT32 ui32NumTAStatusVals;
IMG_UINT32 ui32Num3DStatusVals;
-
+ /* KEEP THESE 4 VARIABLES TOGETHER FOR UKERNEL BLOCK LOAD */
IMG_UINT32 ui32TATQSyncWriteOpsPendingVal;
IMG_DEV_VIRTADDR sTATQSyncWriteOpsCompleteDevVAddr;
IMG_UINT32 ui32TATQSyncReadOpsPendingVal;
IMG_DEV_VIRTADDR sTATQSyncReadOpsCompleteDevVAddr;
-
+ /* KEEP THESE 4 VARIABLES TOGETHER FOR UKERNEL BLOCK LOAD */
IMG_UINT32 ui323DTQSyncWriteOpsPendingVal;
IMG_DEV_VIRTADDR s3DTQSyncWriteOpsCompleteDevVAddr;
IMG_UINT32 ui323DTQSyncReadOpsPendingVal;
IMG_DEV_VIRTADDR s3DTQSyncReadOpsCompleteDevVAddr;
+ /* sync criteria used for TA/3D dependency synchronisation */
+ PVRSRV_DEVICE_SYNC_OBJECT sTA3DDependency;
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
-
+ /* SRC and DST syncs */
IMG_UINT32 ui32NumTASrcSyncs;
PVRSRV_DEVICE_SYNC_OBJECT asTASrcSyncs[SGX_MAX_TA_SRC_SYNCS];
IMG_UINT32 ui32NumTADstSyncs;
IMG_UINT32 ui32Num3DSrcSyncs;
PVRSRV_DEVICE_SYNC_OBJECT as3DSrcSyncs[SGX_MAX_3D_SRC_SYNCS];
#else
-
+ /* source dependency details */
IMG_UINT32 ui32NumSrcSyncs;
- PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS];
+ PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS_TA];
#endif
-
- PVRSRV_DEVICE_SYNC_OBJECT sTA3DDependency;
-
CTL_STATUS sCtlTAStatusInfo[SGX_MAX_TA_STATUS_VALS];
CTL_STATUS sCtl3DStatusInfo[SGX_MAX_3D_STATUS_VALS];
} SGXMKIF_CMDTA_SHARED;
+/*
+ * Services internal TQ limits
+ */
#define SGXTQ_MAX_STATUS SGX_MAX_TRANSFER_STATUS_VALS + 2
+/*
+ * Transfer queue Kick flags
+ */
+/* if set the uKernel won't update the sync objects on completion*/
#define SGXMKIF_TQFLAGS_NOSYNCUPDATE 0x00000001
+/* if set the kernel won't advance the pending values*/
#define SGXMKIF_TQFLAGS_KEEPPENDING 0x00000002
+/* in services equivalent for the same client flags*/
#define SGXMKIF_TQFLAGS_TATQ_SYNC 0x00000004
#define SGXMKIF_TQFLAGS_3DTQ_SYNC 0x00000008
#if defined(SGX_FEATURE_FAST_RENDER_CONTEXT_SWITCH)
#define SGXMKIF_TQFLAGS_CTXSWITCH 0x00000010
#endif
+/* if set uKernel only updates syncobjects / status values*/
#define SGXMKIF_TQFLAGS_DUMMYTRANSFER 0x00000020
+/*!
+ ******************************************************************************
+ * Shared Transfer Queue command structure.
+ * This structure is placed at the start of the TQ command structure proper
+ * (SGXMKIF_TRANSFERCMD), and is accessed from the kernel part of the driver
+ * and the microkernel.
+ *****************************************************************************/
typedef struct _SGXMKIF_TRANSFERCMD_SHARED_
{
-
+ /* need to be able to check read and write ops on src, and update reads */
IMG_UINT32 ui32NumSrcSyncs;
- PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS];
-
+ PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS_TQ];
+ /* need to be able to check reads and writes on dest, and update writes */
IMG_UINT32 ui32NumDstSyncs;
- PVRSRV_DEVICE_SYNC_OBJECT asDstSyncs[SGX_MAX_DST_SYNCS];
-
+ PVRSRV_DEVICE_SYNC_OBJECT asDstSyncs[SGX_MAX_DST_SYNCS_TQ];
+ /* KEEP THESE 4 VARIABLES TOGETHER FOR UKERNEL BLOCK LOAD */
IMG_UINT32 ui32TASyncWriteOpsPendingVal;
IMG_DEV_VIRTADDR sTASyncWriteOpsCompleteDevVAddr;
IMG_UINT32 ui32TASyncReadOpsPendingVal;
IMG_DEV_VIRTADDR sTASyncReadOpsCompleteDevVAddr;
-
+ /* KEEP THESE 4 VARIABLES TOGETHER FOR UKERNEL BLOCK LOAD */
IMG_UINT32 ui323DSyncWriteOpsPendingVal;
IMG_DEV_VIRTADDR s3DSyncWriteOpsCompleteDevVAddr;
IMG_UINT32 ui323DSyncReadOpsPendingVal;
#if defined(SGX_FEATURE_2D_HARDWARE)
typedef struct _SGXMKIF_2DCMD_SHARED_ {
-
+ /* need to be able to check read and write ops on src, and update reads */
IMG_UINT32 ui32NumSrcSync;
PVRSRV_DEVICE_SYNC_OBJECT sSrcSyncData[SGX_MAX_2D_SRC_SYNC_OPS];
-
+ /* need to be able to check reads and writes on dest, and update writes */
PVRSRV_DEVICE_SYNC_OBJECT sDstSyncData;
-
+ /* need to be able to check reads and writes on TA ops, and update writes */
PVRSRV_DEVICE_SYNC_OBJECT sTASyncData;
-
+ /* need to be able to check reads and writes on 2D ops, and update writes */
PVRSRV_DEVICE_SYNC_OBJECT s3DSyncData;
} SGXMKIF_2DCMD_SHARED, *PSGXMKIF_2DCMD_SHARED;
-#endif
+#endif /* SGX_FEATURE_2D_HARDWARE */
typedef struct _SGXMKIF_HWDEVICE_SYNC_LIST_
{
IMG_DEV_VIRTADDR sAccessDevAddr;
IMG_UINT32 ui32NumSyncObjects;
-
+ /* Must be the last variable in the structure */
PVRSRV_DEVICE_SYNC_OBJECT asSyncData[1];
} SGXMKIF_HWDEVICE_SYNC_LIST, *PSGXMKIF_HWDEVICE_SYNC_LIST;
-#define PVRSRV_USSE_EDM_INIT_COMPLETE (1UL << 0)
-
-#define PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE (1UL << 2)
-#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE (1UL << 3)
-#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE (1UL << 4)
-#define PVRSRV_USSE_EDM_POWMAN_NO_WORK (1UL << 5)
-
-#define PVRSRV_USSE_EDM_INTERRUPT_HWR (1UL << 0)
-#define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER (1UL << 1)
-
-#define PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE (1UL << 0)
+/*!
+ *****************************************************************************
+ * Microkernel initialisation status
+ *****************************************************************************/
+#define PVRSRV_USSE_EDM_INIT_COMPLETE (1UL << 0) /*!< ukernel initialisation complete */
+
+/*!
+ *****************************************************************************
+ * Microkernel power status definitions
+ *****************************************************************************/
+#define PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE (1UL << 2) /*!< Signal from ukernel->Host indicating SGX is idle */
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE (1UL << 3) /*!< Signal from ukernel->Host indicating SGX can be powered down */
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE (1UL << 4) /*!< Signal from ukernel->Host indicating there is work to do immediately */
+#define PVRSRV_USSE_EDM_POWMAN_NO_WORK (1UL << 5) /*!< Signal from ukernel->Host indicating no work to do */
+
+/*!
+ *****************************************************************************
+ * EDM interrupt defines
+ *****************************************************************************/
+#define PVRSRV_USSE_EDM_INTERRUPT_HWR (1UL << 0) /*!< EDM requesting hardware recovery */
+#define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER (1UL << 1) /*!< EDM requesting to be powered down */
+#define PVRSRV_USSE_EDM_INTERRUPT_IDLE (1UL << 2) /*!< EDM indicating SGX idle */
+
+/*!
+ *****************************************************************************
+ * EDM Resource management defines
+ *****************************************************************************/
+#define PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE (1UL << 0) /*!< Signal from EDM->Host indicating clean-up request completion */
+#define PVRSRV_USSE_EDM_CLEANUPCMD_BUSY (1UL << 1) /*!< Signal from EDM->Host indicating clean-up is blocked as the resource is busy */
+#define PVRSRV_USSE_EDM_CLEANUPCMD_DONE (1UL << 2) /*!< Signal from EDM->Host indicating clean-up has been done */
#if defined(FIX_HW_BRN_28889)
-#define PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE (1UL << 0)
+/*!
+ *****************************************************************************
+ * EDM BIF Cache Invalidate defines
+ *****************************************************************************/
+#define PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE (1UL << 0) /*!< Signal from EDM->Host indicating the BIF invalidate has started */
#endif
+/*!
+ ****************************************************************************
+ * EDM / uKernel Get misc info defines
+ ****************************************************************************
+ */
#define PVRSRV_USSE_MISCINFO_READY 0x1UL
-#define PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES 0x2UL
+#define PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES 0x2UL /*!< If set, getmiscinfo ukernel func returns structure sizes */
#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
-#define PVRSRV_USSE_MISCINFO_MEMREAD 0x4UL
-#define PVRSRV_USSE_MISCINFO_MEMWRITE 0x8UL
+#define PVRSRV_USSE_MISCINFO_MEMREAD 0x4UL /*!< If set, getmiscinfo ukernel func reads arbitrary device mem */
+#define PVRSRV_USSE_MISCINFO_MEMWRITE 0x8UL /*!< If set, getmiscinfo ukernel func writes arbitrary device mem */
#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
-#define PVRSRV_USSE_MISCINFO_MEMREAD_FAIL 0x1UL << 31
+#define PVRSRV_USSE_MISCINFO_MEMREAD_FAIL 0x1UL << 31 /* If set, ukernel was unable to read from the mem context */
#endif
#endif
+/* Cleanup command control word */
#define PVRSRV_CLEANUPCMD_RT 0x1U
#define PVRSRV_CLEANUPCMD_RC 0x2U
#define PVRSRV_CLEANUPCMD_TC 0x3U
#define PVRSRV_CLEANUPCMD_2DC 0x4U
#define PVRSRV_CLEANUPCMD_PB 0x5U
+/* Power command control word */
#define PVRSRV_POWERCMD_POWEROFF 0x1U
#define PVRSRV_POWERCMD_IDLE 0x2U
#define PVRSRV_POWERCMD_RESUME 0x3U
+/* Context suspend command control word */
#define PVRSRV_CTXSUSPCMD_SUSPEND 0x1U
#define PVRSRV_CTXSUSPCMD_RESUME 0x2U
#define SGX_BIF_DIR_LIST_INDEX_EDM (0)
#endif
+/*!
+ ******************************************************************************
+ * microkernel cache control requests
+ ******************************************************************************/
#define SGXMKIF_CC_INVAL_BIF_PT 0x1
#define SGXMKIF_CC_INVAL_BIF_PD 0x2
#define SGXMKIF_CC_INVAL_BIF_SL 0x4
#define SGXMKIF_CC_INVAL_DATA 0x8
+/*!
+ ******************************************************************************
+ * SGX microkernel interface structure sizes
+ ******************************************************************************/
typedef struct _SGX_MISCINFO_STRUCT_SIZES_
{
#if defined (SGX_FEATURE_2D_HARDWARE)
#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+/*!
+ *****************************************************************************
+ * SGX misc info for accessing device memory from ukernel
+ *****************************************************************************
+ */
typedef struct _PVRSRV_SGX_MISCINFO_MEMACCESS
{
- IMG_DEV_VIRTADDR sDevVAddr;
- IMG_DEV_PHYADDR sPDDevPAddr;
+ IMG_DEV_VIRTADDR sDevVAddr; /*!< dev virtual addr for mem access */
+ IMG_DEV_PHYADDR sPDDevPAddr; /*!< device physical addr of PD for the mem heap */
} PVRSRV_SGX_MISCINFO_MEMACCESS;
#endif
+/*!
+ *****************************************************************************
+ * SGX Misc Info structure used in the microkernel
+ * PVRSRV_SGX_MISCINFO_FEATURES is defined in sgxapi_km.h
+ ****************************************************************************/
typedef struct _PVRSRV_SGX_MISCINFO_INFO
{
IMG_UINT32 ui32MiscInfoFlags;
- PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures;
- SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+ PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures; /*!< external info for client */
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes; /*!< internal info: microkernel structure sizes */
#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
- PVRSRV_SGX_MISCINFO_MEMACCESS sSGXMemAccessSrc;
- PVRSRV_SGX_MISCINFO_MEMACCESS sSGXMemAccessDest;
+ PVRSRV_SGX_MISCINFO_MEMACCESS sSGXMemAccessSrc; /*!< internal info: for reading dev memory */
+ PVRSRV_SGX_MISCINFO_MEMACCESS sSGXMemAccessDest; /*!< internal info: for writing dev memory */
#endif
} PVRSRV_SGX_MISCINFO_INFO;
#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+/*!
+ *****************************************************************************
+ * Number of entries in the microkernel status buffer
+ *****************************************************************************/
#define SGXMK_TRACE_BUFFER_SIZE 512
-#endif
+#endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */
-#define SGXMKIF_HWPERF_CB_SIZE 0x100
+#define SGXMKIF_HWPERF_CB_SIZE 0x100 /* must be 2^n*/
+/*!
+ *****************************************************************************
+ * One entry in the HWPerf Circular Buffer.
+ *****************************************************************************/
typedef struct _SGXMKIF_HWPERF_CB_ENTRY_
{
IMG_UINT32 ui32FrameNo;
IMG_UINT32 ui32Info;
IMG_UINT32 ui32TimeWraps;
IMG_UINT32 ui32Time;
-
+ /* NOTE: There should always be at least as many 3D cores as TA cores. */
IMG_UINT32 ui32Counters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_COUNTERS];
IMG_UINT32 ui32MiscCounters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS];
} SGXMKIF_HWPERF_CB_ENTRY;
+/*!
+ *****************************************************************************
+ * The HWPerf Circular Buffer.
+ *****************************************************************************/
typedef struct _SGXMKIF_HWPERF_CB_
{
IMG_UINT32 ui32Woff;
} SGXMKIF_HWPERF_CB;
-#endif
+#endif /* __SGX_MKIF_KM_H__ */
+
+/******************************************************************************
+ End of file (sgx_mkif_km.h)
+******************************************************************************/
+
--- /dev/null
+/*************************************************************************/ /*!
+@File sgx_ukernel_status_codes.h
+@Title SGX microkernel debug status codes
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description SGX microkernel debug status codes
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __SGX_UKERNEL_STATUS_CODES_H__
+#define __SGX_UKERNEL_STATUS_CODES_H__
+
+/*
+ NOTE: Do not add any conditional macros to this file! There must be
+ no use of #if defined(). This file is included in srvkm to print
+ stringified ukernel status codes, it must build identically to
+ srvinit.
+*/
+
+/*
+ Users of this header might define this macro to do something
+ clever; the primary use right now is to generate a switch/case
+ LUT for debugging in srvkm. If you add a new code, make sure it
+ has a corresponding MKTC_ST.
+*/
+#ifndef MKTC_ST
+#define MKTC_ST(x)
+#endif
+
+/*
+ It would be nice to put these definitions into an enumeration, but USEASM
+ only has access to the C preprocessor so macros are required.
+*/
+
+/*
+ Bits 24-31 of these codes (0xAD) are a magic number used to help
+ distinguish between them and other debug information which can be
+ optionally dumped into the status buffer, e.g. sync object values.
+*/
+
+/*
+ Microkernel trace codes
+*/
+#define MKTC_EHEVENT_3DMEMFREE 0xAD000001
+MKTC_ST(MKTC_EHEVENT_3DMEMFREE)
+#define MKTC_EHEVENT_PIXELENDRENDER 0xAD000002
+MKTC_ST(MKTC_EHEVENT_PIXELENDRENDER)
+#define MKTC_EHEVENT_ISPBREAKPOINT 0xAD000004
+MKTC_ST(MKTC_EHEVENT_ISPBREAKPOINT)
+#define MKTC_EHEVENT_TAFINISHED 0xAD000005
+MKTC_ST(MKTC_EHEVENT_TAFINISHED)
+#define MKTC_EHEVENT_OUTOFMEM 0xAD000007
+MKTC_ST(MKTC_EHEVENT_OUTOFMEM)
+#define MKTC_EHEVENT_TATERMINATE 0xAD000008
+MKTC_ST(MKTC_EHEVENT_TATERMINATE)
+#define MKTC_EHEVENT_TIMER 0xAD000009
+MKTC_ST(MKTC_EHEVENT_TIMER)
+#define MKTC_EHEVENT_SWEVENT 0xAD00000A
+MKTC_ST(MKTC_EHEVENT_SWEVENT)
+#define MKTC_EHEVENT_2DCOMPLETE 0xAD00000B
+MKTC_ST(MKTC_EHEVENT_2DCOMPLETE)
+
+#define MKTC_3DEVENT_3DMEMFREE 0xAD000100
+MKTC_ST(MKTC_3DEVENT_3DMEMFREE)
+#define MKTC_3DEVENT_PIXELENDRENDER 0xAD000101
+MKTC_ST(MKTC_3DEVENT_PIXELENDRENDER)
+#define MKTC_3DEVENT_ISPBREAKPOINT 0xAD000102
+MKTC_ST(MKTC_3DEVENT_ISPBREAKPOINT)
+#define MKTC_3DEVENT_END 0xAD000104
+MKTC_ST(MKTC_3DEVENT_END)
+#define MKTC_3DLB_3DMEMFREE 0xAD000180
+MKTC_ST(MKTC_3DLB_3DMEMFREE)
+#define MKTC_3DLB_PIXELENDRENDER 0xAD000181
+MKTC_ST(MKTC_3DLB_PIXELENDRENDER)
+#define MKTC_3DLB_ISPBREAKPOINT 0xAD000182
+MKTC_ST(MKTC_3DLB_ISPBREAKPOINT)
+#define MKTC_3DLB_FIND3D 0xAD000183
+MKTC_ST(MKTC_3DLB_FIND3D)
+#define MKTC_3DLB_END 0xAD000184
+MKTC_ST(MKTC_3DLB_END)
+
+#define MKTC_TAEVENT_TAFINISHED 0xAD000200
+MKTC_ST(MKTC_TAEVENT_TAFINISHED)
+#define MKTC_TAEVENT_END 0xAD000202
+MKTC_ST(MKTC_TAEVENT_END)
+#define MKTC_TALB_TAFINISHED 0xAD000280
+MKTC_ST(MKTC_TALB_TAFINISHED)
+#define MKTC_TALB_FINDTA 0xAD000281
+MKTC_ST(MKTC_TALB_FINDTA)
+#define MKTC_TALB_END 0xAD000282
+MKTC_ST(MKTC_TALB_END)
+
+#define MKTC_CRRL_WRITEOPSBLOCKED 0xAD000300
+MKTC_ST(MKTC_CRRL_WRITEOPSBLOCKED)
+#define MKTC_CRRL_READOPSBLOCKED 0xAD000301
+MKTC_ST(MKTC_CRRL_READOPSBLOCKED)
+#define MKTC_CRRL_FOUNDRENDER 0xAD000302
+MKTC_ST(MKTC_CRRL_FOUNDRENDER)
+#define MKTC_CRRL_NORENDER 0xAD000303
+MKTC_ST(MKTC_CRRL_NORENDER)
+#define MKTC_CRRL_TARC_DIFFERENT 0xAD000304
+MKTC_ST(MKTC_CRRL_TARC_DIFFERENT)
+#define MKTC_CRRL_BLOCKEDRC 0xAD000309
+MKTC_ST(MKTC_CRRL_BLOCKEDRC)
+#define MKTC_CRRL_BLOCKEDRTDATA 0xAD00030A
+MKTC_ST(MKTC_CRRL_BLOCKEDRTDATA)
+#define MKTC_CRRL_CONTEXT_SUSPENDED 0xAD00030B
+MKTC_ST(MKTC_CRRL_CONTEXT_SUSPENDED)
+#define MKTC_CRRL_TAWAITINGFORMEM 0xAD00030C
+MKTC_ST(MKTC_CRRL_TAWAITINGFORMEM)
+#define MKTC_CRRL_TAOOMBUTPRIOINV 0xAD00030D
+MKTC_ST(MKTC_CRRL_TAOOMBUTPRIOINV)
+#define MKTC_CRRL_READOPS2BLOCKED 0xAD00030E
+MKTC_ST(MKTC_CRRL_READOPS2BLOCKED)
+#define MKTC_CRRL_SRC_WRITEOPSBLOCKED 0xAD00030F
+MKTC_ST(MKTC_CRRL_SRC_WRITEOPSBLOCKED)
+#define MKTC_CRRL_SRC_READOPSBLOCKED 0xAD000310
+MKTC_ST(MKTC_CRRL_SRC_READOPSBLOCKED)
+#define MKTC_CRRL_TQ_WRITEOPSBLOCKED 0xAD000311
+MKTC_ST(MKTC_CRRL_TQ_WRITEOPSBLOCKED)
+#define MKTC_CRRL_TQ_READOPSBLOCKED 0xAD000312
+MKTC_ST(MKTC_CRRL_TQ_READOPSBLOCKED)
+
+#define MKTC_KICKRENDER_START 0xAD000400
+MKTC_ST(MKTC_KICKRENDER_START)
+#define MKTC_KICKRENDER_OVERLAP 0xAD000401
+MKTC_ST(MKTC_KICKRENDER_OVERLAP)
+#define MKTC_KICKRENDER_ISP_START 0xAD000402
+MKTC_ST(MKTC_KICKRENDER_ISP_START)
+#define MKTC_KICKRENDER_RESUME 0xAD000403
+MKTC_ST(MKTC_KICKRENDER_RESUME)
+#define MKTC_KICKRENDER_CONFIG_REGION_HDRS 0xAD000404
+MKTC_ST(MKTC_KICKRENDER_CONFIG_REGION_HDRS)
+#define MKTC_KICKRENDER_END 0xAD000408
+MKTC_ST(MKTC_KICKRENDER_END)
+#define MKTC_KICKRENDER_RENDERCONTEXT 0xAD000409
+MKTC_ST(MKTC_KICKRENDER_RENDERCONTEXT)
+#define MKTC_KICKRENDER_RTDATA 0xAD00040A
+MKTC_ST(MKTC_KICKRENDER_RTDATA)
+#define MKTC_KICKRENDER_PID 0xAD00040B
+MKTC_ST(MKTC_KICKRENDER_PID)
+
+#define MKTC_RENDERFINISHED_START 0xAD000500
+MKTC_ST(MKTC_RENDERFINISHED_START)
+#define MKTC_RF_START_NEXT_MT 0xAD000501
+MKTC_ST(MKTC_RF_START_NEXT_MT)
+#define MKTC_RF_ALL_MTS_DONE 0xAD000502
+MKTC_ST(MKTC_RF_ALL_MTS_DONE)
+#define MKTC_RENDERFINISHED_END 0xAD000503
+MKTC_ST(MKTC_RENDERFINISHED_END)
+#define MKTC_VISQUERY_START 0xAD000504
+MKTC_ST(MKTC_VISQUERY_START)
+#define MKTC_VISQUERY_END 0xAD000505
+MKTC_ST(MKTC_VISQUERY_END)
+#define MKTC_TRANSFERRENDERFINISHED_START 0xAD000508
+MKTC_ST(MKTC_TRANSFERRENDERFINISHED_START)
+#define MKTC_TRANSFERRENDERFINISHED_END 0xAD000509
+MKTC_ST(MKTC_TRANSFERRENDERFINISHED_END)
+#define MKTC_TRF_UPDATESTATUSVALS 0xAD00050A
+MKTC_ST(MKTC_TRF_UPDATESTATUSVALS)
+#define MKTC_TRF_UPDATESTATUSVALS_DONE 0xAD00050B
+MKTC_ST(MKTC_TRF_UPDATESTATUSVALS_DONE)
+
+#define MKTC_PIXELENDRENDER_START 0xAD000600
+MKTC_ST(MKTC_PIXELENDRENDER_START)
+#define MKTC_PIXELENDRENDER_AFTERLOCK 0xAD000601
+MKTC_ST(MKTC_PIXELENDRENDER_AFTERLOCK)
+#define MKTC_PIXELENDRENDER_END 0xAD000602
+MKTC_ST(MKTC_PIXELENDRENDER_END)
+#define MKTC_PIXELENDRENDER_TLQEND 0xAD000603
+MKTC_ST(MKTC_PIXELENDRENDER_TLQEND)
+
+#define MKTC_3DMEMFREE_START 0xAD000700
+MKTC_ST(MKTC_3DMEMFREE_START)
+#define MKTC_3DMEMFREE_AFTERLOCK 0xAD000701
+MKTC_ST(MKTC_3DMEMFREE_AFTERLOCK)
+#define MKTC_3DMEMFREE_TESTEOR 0xAD000702
+MKTC_ST(MKTC_3DMEMFREE_TESTEOR)
+#define MKTC_3DMEMFREE_END 0xAD000703
+MKTC_ST(MKTC_3DMEMFREE_END)
+
+#define MKTC_KICKTA_START 0xAD000800
+MKTC_ST(MKTC_KICKTA_START)
+#define MKTC_KICKTA_OVERLAP 0xAD000801
+MKTC_ST(MKTC_KICKTA_OVERLAP)
+#define MKTC_KICKTA_RESETCONTEXT 0xAD000802
+MKTC_ST(MKTC_KICKTA_RESETCONTEXT)
+#define MKTC_KICKTA_VDM_START 0xAD000803
+MKTC_ST(MKTC_KICKTA_VDM_START)
+#define MKTC_KICKTA_END 0xAD000804
+MKTC_ST(MKTC_KICKTA_END)
+#define MKTC_KICKTA_RENDERCONTEXT 0xAD000805
+MKTC_ST(MKTC_KICKTA_RENDERCONTEXT)
+#define MKTC_KICKTA_RTDATA 0xAD000806
+MKTC_ST(MKTC_KICKTA_RTDATA)
+#define MKTC_KICKTA_RESET_VDMCSSTATUS 0xAD000807
+MKTC_ST(MKTC_KICKTA_RESET_VDMCSSTATUS)
+#define MKTC_KICKTA_RESET_BUFFERS 0xAD000808
+MKTC_ST(MKTC_KICKTA_RESET_BUFFERS)
+#define MKTC_KICKTA_PID 0xAD000809
+MKTC_ST(MKTC_KICKTA_PID)
+#define MKTC_KICKTA_TACMD_DEBUG 0xAD00080A
+MKTC_ST(MKTC_KICKTA_TACMD_DEBUG)
+#define MKTC_KICKTA_FREECONTEXT 0xAD00080B
+MKTC_ST(MKTC_KICKTA_FREECONTEXT)
+#define MKTC_KICKTA_PIM_PATCHING 0xAD00080C
+MKTC_ST(MKTC_KICKTA_PIM_PATCHING)
+
+#define MKTC_KICKTA_CHKPT_START_DUMMY_CS 0xAD0008A1
+MKTC_ST(MKTC_KICKTA_CHKPT_START_DUMMY_CS)
+#define MKTC_KICKTA_CHKPT_START_DUMMY_TAK 0xAD0008A2
+MKTC_ST(MKTC_KICKTA_CHKPT_START_DUMMY_TAK)
+#define MKTC_KICKTA_CHKPT_WAIT_FOR_DUMMY_KICK 0xAD0008A3
+MKTC_ST(MKTC_KICKTA_CHKPT_WAIT_FOR_DUMMY_KICK)
+#define MKTC_KICKTA_CHKPT_WAIT_NEXT_CORE 0xAD0008A4
+MKTC_ST(MKTC_KICKTA_CHKPT_WAIT_NEXT_CORE)
+#define MKTC_KICKTA_CHKPT_RESET_COMPLETE 0xAD0008A5
+MKTC_ST(MKTC_KICKTA_CHKPT_RESET_COMPLETE)
+#define MKTC_KICKTA_CHKPT_CHECK_SWITCH 0xAD0008A6
+MKTC_ST(MKTC_KICKTA_CHKPT_CHECK_SWITCH)
+
+#define MKTC_HOSTKICK_START 0xAD000900
+MKTC_ST(MKTC_HOSTKICK_START)
+#define MKTC_HOSTKICK_END 0xAD000901
+MKTC_ST(MKTC_HOSTKICK_END)
+#define MKTC_HOSTKICK_PROCESS_QUEUES_END 0xAD000902
+MKTC_ST(MKTC_HOSTKICK_PROCESS_QUEUES_END)
+#define MKTC_HOSTKICK_2D 0xAD000903
+MKTC_ST(MKTC_HOSTKICK_2D)
+#define MKTC_HOSTKICK_TRANSFER 0xAD000904
+MKTC_ST(MKTC_HOSTKICK_TRANSFER)
+#define MKTC_HOSTKICK_TA 0xAD000905
+MKTC_ST(MKTC_HOSTKICK_TA)
+#define MKTC_HOSTKICK_PROCESS_QUEUES 0xAD000906
+MKTC_ST(MKTC_HOSTKICK_PROCESS_QUEUES)
+#define MKTC_HOSTKICK_RESUME 0xAD000908
+MKTC_ST(MKTC_HOSTKICK_RESUME)
+#define MKTC_HOSTKICK_POWEROFF 0xAD000909
+MKTC_ST(MKTC_HOSTKICK_POWEROFF)
+#define MKTC_HOSTKICK_IDLE 0xAD00090A
+MKTC_ST(MKTC_HOSTKICK_IDLE)
+#define MKTC_HOSTKICK_CTXSUSPEND 0xAD00090B
+MKTC_ST(MKTC_HOSTKICK_CTXSUSPEND)
+#define MKTC_HOSTKICK_CTXRESUME 0xAD00090C
+MKTC_ST(MKTC_HOSTKICK_CTXRESUME)
+
+#define MKTC_TIMER_POTENTIAL_TA_LOCKUP 0xAD000A00
+MKTC_ST(MKTC_TIMER_POTENTIAL_TA_LOCKUP)
+#define MKTC_TIMER_POTENTIAL_3D_LOCKUP 0xAD000A01
+MKTC_ST(MKTC_TIMER_POTENTIAL_3D_LOCKUP)
+#define MKTC_TIMER_CTAL_START 0xAD000A02
+MKTC_ST(MKTC_TIMER_CTAL_START)
+#define MKTC_TIMER_CTAL_END 0xAD000A03
+MKTC_ST(MKTC_TIMER_CTAL_END)
+#define MKTC_TIMER_C3DL_START 0xAD000A04
+MKTC_ST(MKTC_TIMER_C3DL_START)
+#define MKTC_TIMER_C3DL_END 0xAD000A05
+MKTC_ST(MKTC_TIMER_C3DL_END)
+#define MKTC_TIMER_LOCKUP 0xAD000A0A
+MKTC_ST(MKTC_TIMER_LOCKUP)
+#define MKTC_TIMER_NOT_TA_LOCKUP 0xAD000A0B
+MKTC_ST(MKTC_TIMER_NOT_TA_LOCKUP)
+#define MKTC_TIMER_NOT_3D_LOCKUP 0xAD000A0C
+MKTC_ST(MKTC_TIMER_NOT_3D_LOCKUP)
+#define MKTC_TIMER_2D_LOCKUP 0xAD000A0D
+MKTC_ST(MKTC_TIMER_2D_LOCKUP)
+#define MKTC_TIMER_POTENTIAL_2D_LOCKUP 0xAD000A10
+MKTC_ST(MKTC_TIMER_POTENTIAL_2D_LOCKUP)
+#define MKTC_TIMER_C2DL_START 0xAD000A11
+MKTC_ST(MKTC_TIMER_C2DL_START)
+#define MKTC_TIMER_C2DL_END 0xAD000A12
+MKTC_ST(MKTC_TIMER_C2DL_END)
+#define MKTC_TIMER_NOT_2D_LOCKUP 0xAD000A13
+MKTC_ST(MKTC_TIMER_NOT_2D_LOCKUP)
+#define MKTC_TIMER_ABORTALL 0xAD000A0E
+MKTC_ST(MKTC_TIMER_ABORTALL)
+#define MKTC_TIMER_END 0xAD000A0F
+MKTC_ST(MKTC_TIMER_END)
+
+#define MKTC_HWR_START 0xAD000B00
+MKTC_ST(MKTC_HWR_START)
+#define MKTC_HWR_END 0xAD000B01
+MKTC_ST(MKTC_HWR_END)
+#define MKTC_HWR_HKS 0xAD000B02
+MKTC_ST(MKTC_HWR_HKS)
+#define MKTC_HWR_PRL 0xAD000B03
+MKTC_ST(MKTC_HWR_PRL)
+#define MKTC_HWR_PRL_DP 0xAD000B04
+MKTC_ST(MKTC_HWR_PRL_DP)
+#define MKTC_HWR_CRL 0xAD000B05
+MKTC_ST(MKTC_HWR_CRL)
+#define MKTC_HWR_CRL_DP 0xAD000B06
+MKTC_ST(MKTC_HWR_CRL_DP)
+#define MKTC_HWR_TRL 0xAD000B07
+MKTC_ST(MKTC_HWR_TRL)
+#define MKTC_HWR_TRL_DP 0xAD000B08
+MKTC_ST(MKTC_HWR_TRL_DP)
+#define MKTC_HWR_ISC 0xAD000B09
+MKTC_ST(MKTC_HWR_ISC)
+#define MKTC_HWR_2DL 0xAD000B0A
+MKTC_ST(MKTC_HWR_2DL)
+#define MKTC_HWR_CLEANUP 0xAD000B0B
+MKTC_ST(MKTC_HWR_CLEANUP)
+
+#define MKTC_URSV_START 0xAD000C00
+MKTC_ST(MKTC_URSV_START)
+#define MKTC_URSV_UPDATEWRITEOPS 0xAD000C01
+MKTC_ST(MKTC_URSV_UPDATEWRITEOPS)
+#define MKTC_URSV_UPDATESTATUSVALS 0xAD000C03
+MKTC_ST(MKTC_URSV_UPDATESTATUSVALS)
+#define MKTC_URSV_UPDATESTATUSVALS_DONE 0xAD000C04
+MKTC_ST(MKTC_URSV_UPDATESTATUSVALS_DONE)
+#define MKTC_URSV_END 0xAD000C05
+MKTC_ST(MKTC_URSV_END)
+
+#define MKTC_STORETACONTEXT_START 0xAD000D00
+MKTC_ST(MKTC_STORETACONTEXT_START)
+#define MKTC_STORETACONTEXT_END 0xAD000D01
+MKTC_ST(MKTC_STORETACONTEXT_END)
+#define MKTC_LOADTACONTEXT_START 0xAD000D02
+MKTC_ST(MKTC_LOADTACONTEXT_START)
+#define MKTC_LOADTACONTEXT_END 0xAD000D03
+MKTC_ST(MKTC_LOADTACONTEXT_END)
+#define MKTC_STORE3DCONTEXT_START 0xAD000D04
+MKTC_ST(MKTC_STORE3DCONTEXT_START)
+#define MKTC_STORE3DCONTEXT_END 0xAD000D05
+MKTC_ST(MKTC_STORE3DCONTEXT_END)
+#define MKTC_LOAD3DCONTEXT_START 0xAD000D06
+MKTC_ST(MKTC_LOAD3DCONTEXT_START)
+#define MKTC_LOAD3DCONTEXT_END 0xAD000D07
+MKTC_ST(MKTC_LOAD3DCONTEXT_END)
+
+#define MKTC_FINDTA_POWERREQUEST 0xAD000E00
+MKTC_ST(MKTC_FINDTA_POWERREQUEST)
+#define MKTC_FINDTA_TA3D_OVERLAP_BLOCKED 0xAD000E01
+MKTC_ST(MKTC_FINDTA_TA3D_OVERLAP_BLOCKED)
+#define MKTC_FINDTA_RTDATA_RENDERING 0xAD000E02
+MKTC_ST(MKTC_FINDTA_RTDATA_RENDERING)
+#define MKTC_FINDTA_3DRC_DIFFERENT 0xAD000E03
+MKTC_ST(MKTC_FINDTA_3DRC_DIFFERENT)
+#define MKTC_FINDTA_WRITEOPSBLOCKED 0xAD000E04
+MKTC_ST(MKTC_FINDTA_WRITEOPSBLOCKED)
+#define MKTC_FINDTA_READOPSBLOCKED 0xAD000E05
+MKTC_ST(MKTC_FINDTA_READOPSBLOCKED)
+#define MKTC_FINDTA_RESIZE_PB 0xAD000E06
+MKTC_ST(MKTC_FINDTA_RESIZE_PB)
+#define MKTC_FINDTA_RESIZE_PB_BLOCKED 0xAD000E07
+MKTC_ST(MKTC_FINDTA_RESIZE_PB_BLOCKED)
+#define MKTC_FINDTA_SHRINK_PB 0xAD000E08
+MKTC_ST(MKTC_FINDTA_SHRINK_PB)
+#define MKTC_FINDTA_TAPB_DIFFERENT 0xAD000E09
+MKTC_ST(MKTC_FINDTA_TAPB_DIFFERENT)
+#define MKTC_FINDTA_TACONTEXT_DIFFERENT 0xAD000E0A
+MKTC_ST(MKTC_FINDTA_TACONTEXT_DIFFERENT)
+#define MKTC_FINDTA_TA2D_OVERLAP_BLOCKED 0xAD000E0B
+MKTC_ST(MKTC_FINDTA_TA2D_OVERLAP_BLOCKED)
+#define MKTC_FINDTA_CONTEXT_SUSPENDED 0xAD000E0C
+MKTC_ST(MKTC_FINDTA_CONTEXT_SUSPENDED)
+#define MKTC_FINDTA_SRC_READOPSBLOCKED 0xAD000E0D
+MKTC_ST(MKTC_FINDTA_SRC_READOPSBLOCKED)
+#define MKTC_FINDTA_SRC_WRITEOPSBLOCKED 0xAD000E0E
+MKTC_ST(MKTC_FINDTA_SRC_WRITEOPSBLOCKED)
+#define MKTC_FINDTA_READOPS2BLOCKED 0xAD000E0F
+MKTC_ST(MKTC_FINDTA_READOPS2BLOCKED)
+
+#define MKTC_CTRL_SRCREADOPSBLOCKED 0xAD000F00
+MKTC_ST(MKTC_CTRL_SRCREADOPSBLOCKED)
+#define MKTC_CTRL_SRCWRITEOPSBLOCKED 0xAD000F01
+MKTC_ST(MKTC_CTRL_SRCWRITEOPSBLOCKED)
+#define MKTC_CTRL_DSTREADOPSBLOCKED 0xAD000F02
+MKTC_ST(MKTC_CTRL_DSTREADOPSBLOCKED)
+#define MKTC_CTRL_DSTWRITEOPSBLOCKED 0xAD000F03
+MKTC_ST(MKTC_CTRL_DSTWRITEOPSBLOCKED)
+#define MKTC_CTRL_TARC_DIFFERENT 0xAD000F04
+MKTC_ST(MKTC_CTRL_TARC_DIFFERENT)
+#define MKTC_CTRL_CONTEXT_SUSPENDED 0xAD000F05
+MKTC_ST(MKTC_CTRL_CONTEXT_SUSPENDED)
+#define MKTC_CTRL_SRCREADOPS2BLOCKED 0xAD000F06
+MKTC_ST(MKTC_CTRL_SRCREADOPS2BLOCKED)
+#define MKTC_CTRL_3D_WRITEOPSBLOCKED 0xAD000F07
+MKTC_ST(MKTC_CTRL_3D_WRITEOPSBLOCKED)
+#define MKTC_CTRL_3D_READOPSBLOCKED 0xAD000F08
+MKTC_ST(MKTC_CTRL_3D_READOPSBLOCKED)
+
+#define MKTC_DPTA_START 0xAD001000
+MKTC_ST(MKTC_DPTA_START)
+#define MKTC_DPTA_UPDATESTATUSVALS 0xAD001001
+MKTC_ST(MKTC_DPTA_UPDATESTATUSVALS)
+#define MKTC_DPTA_UPDATESTATUSVALS_DONE 0xAD001002
+MKTC_ST(MKTC_DPTA_UPDATESTATUSVALS_DONE)
+#define MKTC_DPTA_NORENDER 0xAD001003
+MKTC_ST(MKTC_DPTA_NORENDER)
+#define MKTC_DPTA_MEMFREE 0xAD001004
+MKTC_ST(MKTC_DPTA_MEMFREE)
+#define MKTC_DPTA_INC_COMPLETECOUNT 0xAD001005
+MKTC_ST(MKTC_DPTA_INC_COMPLETECOUNT)
+
+#define MKTC_INVALDC 0xAD001100
+MKTC_ST(MKTC_INVALDC)
+#define MKTC_INVALPT 0xAD001101
+MKTC_ST(MKTC_INVALPT)
+#define MKTC_INVALSLC 0xAD001102
+MKTC_ST(MKTC_INVALSLC)
+#define MKTC_INVALDATA 0xAD001103
+MKTC_ST(MKTC_INVALDATA)
+
+#define MKTC_RESTARTTA 0xAD001200
+MKTC_ST(MKTC_RESTARTTA)
+#define MKTC_CSABORTNONGBL 0xAD001201
+MKTC_ST(MKTC_CSABORTNONGBL)
+#define MKTC_CSABORTALL 0xAD001202
+MKTC_ST(MKTC_CSABORTALL)
+#define MKTC_CSRENDERINPROGRESS 0xAD001203
+MKTC_ST(MKTC_CSRENDERINPROGRESS)
+#define MKTC_TATERMRENDERINPROGRESS 0xAD001204
+MKTC_ST(MKTC_TATERMRENDERINPROGRESS)
+#define MKTC_RESTARTTANORENDER 0xAD001205
+MKTC_ST(MKTC_RESTARTTANORENDER)
+#define MKTC_SPM_KICKRENDER 0xAD001206
+MKTC_ST(MKTC_SPM_KICKRENDER)
+#define MKTC_SPM_RESUME_ABORTCOMPLETE 0xAD001208
+MKTC_ST(MKTC_SPM_RESUME_ABORTCOMPLETE)
+#define MKTC_RESUMEVDM 0xAD001209
+MKTC_ST(MKTC_RESUMEVDM)
+#define MKTC_REMOVE_RESERVE_MEM 0xAD00120A
+MKTC_ST(MKTC_REMOVE_RESERVE_MEM)
+#define MKTC_INCREASEZLSTHRESHOLD 0xAD00120B
+MKTC_ST(MKTC_INCREASEZLSTHRESHOLD)
+#define MKTC_CSFORCEABORTALL 0xAD00120C
+MKTC_ST(MKTC_CSFORCEABORTALL)
+
+#define MKTC_DUMMY_DEPTH 0xAD00120D
+MKTC_ST(MKTC_DUMMY_DEPTH)
+#define MKTC_DUMMY_DEPTH_CS 0xAD00120E
+MKTC_ST(MKTC_DUMMY_DEPTH_CS)
+
+#define MKTC_MTETE_OOM 0xAD00120F
+MKTC_ST(MKTC_MTETE_OOM)
+#define MKTC_MTETE_OOM_FIRST_STORE_REF 0xAD001210
+MKTC_ST(MKTC_MTETE_OOM_FIRST_STORE_REF)
+#define MKTC_MERGE_STATE_TABLES 0xAD001211
+MKTC_ST(MKTC_MERGE_STATE_TABLES)
+#define MKTC_NO_PAGES_LEFT_FOR_23055 0xAD001212
+MKTC_ST(MKTC_NO_PAGES_LEFT_FOR_23055)
+#define MKTC_NO_STATE_MODS 0xAD001213
+MKTC_ST(MKTC_NO_STATE_MODS)
+#define MKTC_FIND_MTE_PAGE_IN_STATE 0xAD001214
+MKTC_ST(MKTC_FIND_MTE_PAGE_IN_STATE)
+#define MKTC_MTE_PAGE_FOUND 0xAD001215
+MKTC_ST(MKTC_MTE_PAGE_FOUND)
+#define MKTC_MOVE_MTE_PAGE_TO_TA_STATE 0xAD001216
+MKTC_ST(MKTC_MOVE_MTE_PAGE_TO_TA_STATE)
+#define MKTC_MOVE_MTE_PAGE_TO_TA_STATE_END 0xAD001217
+MKTC_ST(MKTC_MOVE_MTE_PAGE_TO_TA_STATE_END)
+#define MKTC_ZERO_ZLS_THRESHOLD 0xAD001218
+MKTC_ST(MKTC_ZERO_ZLS_THRESHOLD)
+#define MKTC_RESTORE_ZLS_THRESHOLD 0xAD001219
+MKTC_ST(MKTC_RESTORE_ZLS_THRESHOLD)
+#define MKTC_FIND_MTE_PAGE_IN_CSM 0xAD00121A
+MKTC_ST(MKTC_FIND_MTE_PAGE_IN_CSM)
+#define MKTC_REISSUE_MTE_PAGE 0xAD00121B
+MKTC_ST(MKTC_REISSUE_MTE_PAGE)
+#define MKTC_REISSUE_MTE_PAGE_REQUIRED 0xAD00121C
+MKTC_ST(MKTC_REISSUE_MTE_PAGE_REQUIRED)
+#define MKTC_REISSUE_MTE_PAGE_END 0xAD00121D
+MKTC_ST(MKTC_REISSUE_MTE_PAGE_END)
+#define MKTC_RESET_TE_PSG 0xAD00121E
+MKTC_ST(MKTC_RESET_TE_PSG)
+
+#define MKTC_OOM_WRITEOPSBLOCKED 0xAD00121F
+MKTC_ST(MKTC_OOM_WRITEOPSBLOCKED)
+#define MKTC_OOM_READOPSBLOCKED 0xAD001220
+MKTC_ST(MKTC_OOM_READOPSBLOCKED)
+#define MKTC_OOM_SRC_WRITEOPSBLOCKED 0xAD001221
+MKTC_ST(MKTC_OOM_SRC_WRITEOPSBLOCKED)
+#define MKTC_OOM_SRC_READOPSBLOCKED 0xAD001222
+MKTC_ST(MKTC_OOM_SRC_READOPSBLOCKED)
+#define MKTC_OOM_SPM_DEADLOCK 0xAD001223
+MKTC_ST(MKTC_OOM_SPM_DEADLOCK)
+#define MKTC_OOM_SPM_DEADLOCK_MEM_ADDED 0xAD001224
+MKTC_ST(MKTC_OOM_SPM_DEADLOCK_MEM_ADDED)
+#define MKTC_RESET 0xAD001225
+MKTC_ST(MKTC_RESET)
+#define MKTC_SPM_INVALID_ZLSCONFIG 0xAD001226
+MKTC_ST(MKTC_SPM_INVALID_ZLSCONFIG)
+
+#define MKTC_OOM_TYPE_MT 0xAD00122A
+MKTC_ST(MKTC_OOM_TYPE_MT)
+#define MKTC_OOM_TYPE_GLOBAL 0xAD001230
+MKTC_ST(MKTC_OOM_TYPE_GLOBAL)
+#define MKTC_OOM_CAUSE_GBL_OOM 0xAD001231
+MKTC_ST(MKTC_OOM_CAUSE_GBL_OOM)
+#define MKTC_OOM_RESTORE_LIST_SIZE 0xAD001232
+MKTC_ST(MKTC_OOM_RESTORE_LIST_SIZE)
+
+#define MKTC_CHECK_MTE_PAGE_REISSUE 0xAD001240
+MKTC_ST(MKTC_CHECK_MTE_PAGE_REISSUE)
+#define MKTC_CPRI_VALID_ENTRIES 0xAD001241
+MKTC_ST(MKTC_CPRI_VALID_ENTRIES)
+#define MKTC_CPRI_STORE_DPLIST 0xAD001242
+MKTC_ST(MKTC_CPRI_STORE_DPLIST)
+#define MKTC_CPRI_STORE_OTPM_CSM 0xAD001243
+MKTC_ST(MKTC_CPRI_STORE_OTPM_CSM)
+#define MKTC_CPRI_ABORT_MT_IDX 0xAD001244
+MKTC_ST(MKTC_CPRI_ABORT_MT_IDX)
+#define MKTC_CPRI_ABORT_CORE_IDX 0xAD001245
+MKTC_ST(MKTC_CPRI_ABORT_CORE_IDX)
+#define MKTC_CPRI_CSM_TABLE_DATA 0xAD001246
+MKTC_ST(MKTC_CPRI_CSM_TABLE_DATA)
+#define MKTC_CPRI_PIM_DATA 0xAD001247
+MKTC_ST(MKTC_CPRI_PIM_DATA)
+#define MKTC_CPRI_DO_CIRCULAR_TEST 0xAD001248
+MKTC_ST(MKTC_CPRI_DO_CIRCULAR_TEST)
+#define MKTC_CPRI_WRITE_ENTRIES 0xAD001249
+MKTC_ST(MKTC_CPRI_WRITE_ENTRIES)
+
+#define MKTC_MTE_ENTRY_NOT_IN_ANY_LIST 0xAD001250
+MKTC_ST(MKTC_MTE_ENTRY_NOT_IN_ANY_LIST)
+
+#define MKTC_SPMAC_IGNORE_TERMINATE 0xAD001251
+MKTC_ST(MKTC_SPMAC_IGNORE_TERMINATE)
+
+#define MKTC_SPMAC_REQUEST_3D_TIMEOUT 0xAD001252
+MKTC_ST(MKTC_SPMAC_REQUEST_3D_TIMEOUT)
+#define MKTC_SPMAC_3D_TIMEOUT_COMPLETE 0xAD001253
+MKTC_ST(MKTC_SPMAC_3D_TIMEOUT_COMPLETE)
+#define MKTC_OOM_READOPS2BLOCKED 0xAD001254
+MKTC_ST(MKTC_OOM_READOPS2BLOCKED)
+
+/* PB Load/store status */
+#define MKTC_LOADTAPB_START 0xAD001300
+MKTC_ST(MKTC_LOADTAPB_START)
+#define MKTC_LOADTAPB_END 0xAD001301
+MKTC_ST(MKTC_LOADTAPB_END)
+#define MKTC_STORETAPB_START 0xAD001302
+MKTC_ST(MKTC_STORETAPB_START)
+#define MKTC_STORETAPB_END 0xAD001303
+MKTC_ST(MKTC_STORETAPB_END)
+#define MKTC_LOAD3DPB_START 0xAD001304
+MKTC_ST(MKTC_LOAD3DPB_START)
+#define MKTC_LOAD3DPB_END 0xAD001305
+MKTC_ST(MKTC_LOAD3DPB_END)
+#define MKTC_STORE3DPB_START 0xAD001306
+MKTC_ST(MKTC_STORE3DPB_START)
+#define MKTC_STORE3DPB_END 0xAD001307
+MKTC_ST(MKTC_STORE3DPB_END)
+#define MKTC_LOADTAPB_PAGETABLE_DONE 0xAD001308
+MKTC_ST(MKTC_LOADTAPB_PAGETABLE_DONE)
+#define MKTC_LOAD3DPB_PAGETABLE_DONE 0xAD001309
+MKTC_ST(MKTC_LOAD3DPB_PAGETABLE_DONE)
+
+#define MKTC_TIMER_RC_CLEANUP 0xAD001400
+MKTC_ST(MKTC_TIMER_RC_CLEANUP)
+#define MKTC_TIMER_RC_CLEANUP_DONE 0xAD001401
+MKTC_ST(MKTC_TIMER_RC_CLEANUP_DONE)
+#define MKTC_TIMER_RC_CLEANUP_BUSY 0xAD001402
+MKTC_ST(MKTC_TIMER_RC_CLEANUP_BUSY)
+#define MKTC_TIMER_RT_CLEANUP 0xAD001410
+MKTC_ST(MKTC_TIMER_RT_CLEANUP)
+#define MKTC_TIMER_RT_CLEANUP_DONE 0xAD001411
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_DONE)
+#define MKTC_TIMER_RT_CLEANUP_PENDING 0xAD001412
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_PENDING)
+#define MKTC_TIMER_RT_CLEANUP_TIDYPARTIALLIST 0xAD001413
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_TIDYPARTIALLIST)
+#define MKTC_TIMER_RT_CLEANUP_BUSY 0xAD001414
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_BUSY)
+#define MKTC_TIMER_TC_CLEANUP 0xAD001420
+MKTC_ST(MKTC_TIMER_TC_CLEANUP)
+#define MKTC_TIMER_TC_CLEANUP_DONE 0xAD001421
+MKTC_ST(MKTC_TIMER_TC_CLEANUP_DONE)
+#define MKTC_TIMER_TC_CLEANUP_BUSY 0xAD001422
+MKTC_ST(MKTC_TIMER_TC_CLEANUP_BUSY)
+#define MKTC_TIMER_2DC_CLEANUP 0xAD001430
+MKTC_ST(MKTC_TIMER_2DC_CLEANUP)
+#define MKTC_TIMER_2DC_CLEANUP_DONE 0xAD001431
+MKTC_ST(MKTC_TIMER_2DC_CLEANUP_DONE)
+#define MKTC_TIMER_2DC_CLEANUP_BUSY 0xAD001432
+MKTC_ST(MKTC_TIMER_2DC_CLEANUP_BUSY)
+#define MKTC_TIMER_SHAREDPBDESC_CLEANUP 0xAD001440
+MKTC_ST(MKTC_TIMER_SHAREDPBDESC_CLEANUP)
+
+
+#define MKTC_TIMER_ISP_SWITCH_POTENTIAL_LOCKUP 0xAD001450
+MKTC_ST(MKTC_TIMER_ISP_SWITCH_POTENTIAL_LOCKUP)
+#define MKTC_TIMER_ISP_SWITCH_FORCE_SWITCH 0xAD001451
+MKTC_ST(MKTC_TIMER_ISP_SWITCH_FORCE_SWITCH)
+
+#define MKTC_UTSO_UPDATEREADOPS 0xAD001600
+MKTC_ST(MKTC_UTSO_UPDATEREADOPS)
+#define MKTC_UTSO_UPDATEWRITEOPS 0xAD001601
+MKTC_ST(MKTC_UTSO_UPDATEWRITEOPS)
+
+#define MKTC_TAFINISHED_UPDATESTATUSVALS 0xAD001700
+MKTC_ST(MKTC_TAFINISHED_UPDATESTATUSVALS)
+#define MKTC_TAFINISHED_UPDATESTATUSVALS_DONE 0xAD001701
+MKTC_ST(MKTC_TAFINISHED_UPDATESTATUSVALS_DONE)
+#define MKTC_TAFINISHED_NORENDER 0xAD001702
+MKTC_ST(MKTC_TAFINISHED_NORENDER)
+#define MKTC_TAFINISHED_LASTKICK 0xAD001703
+MKTC_ST(MKTC_TAFINISHED_LASTKICK)
+#define MKTC_TAFINISHED_FINDRENDER 0xAD001704
+MKTC_ST(MKTC_TAFINISHED_FINDRENDER)
+#define MKTC_TAFINISHED_FINDTA 0xAD001705
+MKTC_ST(MKTC_TAFINISHED_FINDTA)
+#define MKTC_TAFINISHED_END 0xAD001706
+MKTC_ST(MKTC_TAFINISHED_END)
+#define MKTC_TAF_SPM_DEADLOCK_MEM_REMOVED 0xAD001707
+MKTC_ST(MKTC_TAF_SPM_DEADLOCK_MEM_REMOVED)
+#define MKTC_TAF_RESERVE_MEM 0xAD001708
+MKTC_ST(MKTC_TAF_RESERVE_MEM)
+#define MKTC_TAF_RESERVE_MEM_REQUEST_RENDER 0xAD001709
+MKTC_ST(MKTC_TAF_RESERVE_MEM_REQUEST_RENDER)
+#define MKTC_TAF_RESERVE_FREE_RENDER_FINISHED 0xAD00170A
+MKTC_ST(MKTC_TAF_RESERVE_FREE_RENDER_FINISHED)
+#define MKTC_TAF_RESERVE_FREE_DUMMY_RENDER 0xAD00170B
+MKTC_ST(MKTC_TAF_RESERVE_FREE_DUMMY_RENDER)
+#define MKTC_TAF_DEBUG_SAS 0xAD00170C
+MKTC_ST(MKTC_TAF_DEBUG_SAS)
+#define MKTC_TAFINISHED_NOCONTEXTSWITCH 0xAD00170D
+MKTC_ST(MKTC_TAFINISHED_NOCONTEXTSWITCH)
+
+#define MKTC_TAFINISHED_TERM_COMPLETE_START 0xAD001710
+MKTC_ST(MKTC_TAFINISHED_TERM_COMPLETE_START)
+#define MKTC_TAFINISHED_TERM_COMPLETE_END 0xAD001711
+MKTC_ST(MKTC_TAFINISHED_TERM_COMPLETE_END)
+
+#define MKTC_TAFINISHED_DPMPAGERECYCLING 0xAD001720
+MKTC_ST(MKTC_TAFINISHED_DPMPAGERECYCLING)
+
+#define MKTC_2DEVENT_2DCOMPLETE 0xAD001800
+MKTC_ST(MKTC_2DEVENT_2DCOMPLETE)
+#define MKTC_2DEVENT_END 0xAD001801
+MKTC_ST(MKTC_2DEVENT_END)
+#define MKTC_2DLB_2DCOMPLETE 0xAD001802
+MKTC_ST(MKTC_2DLB_2DCOMPLETE)
+#define MKTC_2DLB_FIND2D 0xAD001803
+MKTC_ST(MKTC_2DLB_FIND2D)
+#define MKTC_2DLB_END 0xAD001804
+MKTC_ST(MKTC_2DLB_END)
+#define MKTC_2DCOMPLETE_START 0xAD001805
+MKTC_ST(MKTC_2DCOMPLETE_START)
+#define MKTC_2DCOMPLETE_END 0xAD001806
+MKTC_ST(MKTC_2DCOMPLETE_END)
+#define MKTC_KICK2D_START 0xAD001807
+MKTC_ST(MKTC_KICK2D_START)
+#define MKTC_KICK2D_END 0xAD001808
+MKTC_ST(MKTC_KICK2D_END)
+#define MKTC_DUMMYPROC2D 0xAD001809
+MKTC_ST(MKTC_DUMMYPROC2D)
+#define MKTC_FTD_SRCREADOPSBLOCKED 0xAD00180A
+MKTC_ST(MKTC_FTD_SRCREADOPSBLOCKED)
+#define MKTC_FTD_SRCWRITEOPSBLOCKED 0xAD00180B
+MKTC_ST(MKTC_FTD_SRCWRITEOPSBLOCKED)
+#define MKTC_FTD_DSTREADOPSBLOCKED 0xAD00180C
+MKTC_ST(MKTC_FTD_DSTREADOPSBLOCKED)
+#define MKTC_FTD_DSTWRITEOPSBLOCKED 0xAD00180D
+MKTC_ST(MKTC_FTD_DSTWRITEOPSBLOCKED)
+#define MKTC_FTD_TA2D_OVERLAP_BLOCKED 0xAD00180E
+MKTC_ST(MKTC_FTD_TA2D_OVERLAP_BLOCKED)
+#define MKTC_U2DSO_UPDATEREADOPS 0xAD00180F
+MKTC_ST(MKTC_U2DSO_UPDATEREADOPS)
+#define MKTC_U2DSO_UPDATEWRITEOPS 0xAD001810
+MKTC_ST(MKTC_U2DSO_UPDATEWRITEOPS)
+#define MKTC_FTD_TAOPSBLOCKED 0xAD001811
+MKTC_ST(MKTC_FTD_TAOPSBLOCKED)
+#define MKTC_KICK2D_2DSLAVEPORT 0xAD001812
+MKTC_ST(MKTC_KICK2D_2DSLAVEPORT)
+#define MKTC_KICK2D_2DSLAVEPORT_DONE 0xAD001813
+MKTC_ST(MKTC_KICK2D_2DSLAVEPORT_DONE)
+#define MKTC_FTD_CONTEXT_SUSPENDED 0xAD001814
+MKTC_ST(MKTC_FTD_CONTEXT_SUSPENDED)
+#define MKTC_KICK2D_PID 0xAD001815
+MKTC_ST(MKTC_KICK2D_PID)
+#define MKTC_FIND2D_ADDR_SPACE_DIFFERENT 0xAD001816
+MKTC_ST(MKTC_FIND2D_ADDR_SPACE_DIFFERENT)
+#define MKTC_FTD_3DOPSBLOCKED 0xAD001817
+MKTC_ST(MKTC_FTD_3DOPSBLOCKED)
+#define MKTC_FTD_DSTREADOPS2BLOCKED 0xAD001818
+MKTC_ST(MKTC_FTD_DSTREADOPS2BLOCKED)
+
+#define MKTC_FCM_START 0xAD001900
+MKTC_ST(MKTC_FCM_START)
+#define MKTC_FCM_END 0xAD001901
+MKTC_ST(MKTC_FCM_END)
+
+#define MKTC_TIMER_ACTIVE_POWER 0xAD001A00
+MKTC_ST(MKTC_TIMER_ACTIVE_POWER)
+#define MKTC_TIMER_POWER_3D_ACTIVE 0xAD001A01
+MKTC_ST(MKTC_TIMER_POWER_3D_ACTIVE)
+#define MKTC_TIMER_POWER_TA_ACTIVE 0xAD001A02
+MKTC_ST(MKTC_TIMER_POWER_TA_ACTIVE)
+#define MKTC_TIMER_POWER_2D_ACTIVE 0xAD001A03
+MKTC_ST(MKTC_TIMER_POWER_2D_ACTIVE)
+#define MKTC_TIMER_POWER_PENDING_EVENTS 0xAD001A04
+MKTC_ST(MKTC_TIMER_POWER_PENDING_EVENTS)
+#define MKTC_TIMER_POWER_IDLE 0xAD001A05
+MKTC_ST(MKTC_TIMER_POWER_IDLE)
+#define MKTC_TIMER_POWER_OFF 0xAD001A06
+MKTC_ST(MKTC_TIMER_POWER_OFF)
+#define MKTC_TIMER_POWER_CCB_ERROR 0xAD001A07
+MKTC_ST(MKTC_TIMER_POWER_CCB_ERROR)
+#define MKTC_TIMER_POWER_RESTART_IMMEDIATE 0xAD001A08
+MKTC_ST(MKTC_TIMER_POWER_RESTART_IMMEDIATE)
+
+#define MKTC_3DCONTEXT_SWITCH 0xAD001B00
+MKTC_ST(MKTC_3DCONTEXT_SWITCH)
+#define MKTC_3DCONTEXT_SWITCH_END 0xAD001B01
+MKTC_ST(MKTC_3DCONTEXT_SWITCH_END)
+
+#define MKTC_TACONTEXT_SWITCH 0xAD001C00
+MKTC_ST(MKTC_TACONTEXT_SWITCH)
+#define MKTC_TACONTEXT_SWITCH_END 0xAD001C02
+MKTC_ST(MKTC_TACONTEXT_SWITCH_END)
+
+#define MKTC_GETMISCINFO_MEMREAD_START 0xAD001D00
+MKTC_ST(MKTC_GETMISCINFO_MEMREAD_START)
+#define MKTC_GETMISCINFO_MEMREAD_END 0xAD001D01
+MKTC_ST(MKTC_GETMISCINFO_MEMREAD_END)
+#define MKTC_GETMISCINFO_MEMWRITE_START 0xAD001D02
+MKTC_ST(MKTC_GETMISCINFO_MEMWRITE_START)
+#define MKTC_GETMISCINFO_MEMWRITE_END 0xAD001D03
+MKTC_ST(MKTC_GETMISCINFO_MEMWRITE_END)
+
+#define MKTC_HALTTA 0xAD001E00
+MKTC_ST(MKTC_HALTTA)
+#define MKTC_HTA_SET_FLAG 0xAD001E01
+MKTC_ST(MKTC_HTA_SET_FLAG)
+#define MKTC_HTA_SAVE_COMPLEX_PTR 0xAD001E02
+MKTC_ST(MKTC_HTA_SAVE_COMPLEX_PTR)
+#define MKTC_HALTTA_END 0xAD001E03
+MKTC_ST(MKTC_HALTTA_END)
+
+#define MKTC_RESUMETA 0xAD001F00
+MKTC_ST(MKTC_RESUMETA)
+#define MKTC_RTA_CONTEXT_LOADED 0xAD001F01
+MKTC_ST(MKTC_RTA_CONTEXT_LOADED)
+#define MKTC_RTA_MTE_STATE_KICKED 0xAD001F02
+MKTC_ST(MKTC_RTA_MTE_STATE_KICKED)
+#define MKTC_RTA_CMPLX_GEOM_PRESENT 0xAD001F03
+MKTC_ST(MKTC_RTA_CMPLX_GEOM_PRESENT)
+#define MKTC_RTA_CMPLX_STATE_KICKED 0xAD001F04
+MKTC_ST(MKTC_RTA_CMPLX_STATE_KICKED)
+#define MKTC_RTA_CHECK_NEXT_SA_PROG 0xAD001F05
+MKTC_ST(MKTC_RTA_CHECK_NEXT_SA_PROG)
+#define MKTC_RTA_CORE_COMPLETED 0xAD001F06
+MKTC_ST(MKTC_RTA_CORE_COMPLETED)
+#define MKTC_RTA_DEBUG_SAS 0xAD001F07
+MKTC_ST(MKTC_RTA_DEBUG_SAS)
+#define MKTC_RESUMETA_END 0xAD001F0F
+MKTC_ST(MKTC_RESUMETA_END)
+
+#define MKTC_RENDERHALT 0xAD002000
+MKTC_ST(MKTC_RENDERHALT)
+#define MKTC_RH_CLEARFLAGS 0xAD002001
+MKTC_ST(MKTC_RH_CLEARFLAGS)
+#define MKTC_RH_CTRL_ADDR 0xAD002002
+MKTC_ST(MKTC_RH_CTRL_ADDR)
+#define MKTC_RH_RGN_ADDR 0xAD002003
+MKTC_ST(MKTC_RH_RGN_ADDR)
+#define MKTC_RH_EMPTY_TILE 0xAD002004
+MKTC_ST(MKTC_RH_EMPTY_TILE)
+#define MKTC_RH_EMPTY_LAST_TILE 0xAD002005
+MKTC_ST(MKTC_RH_EMPTY_LAST_TILE)
+#define MKTC_RH_3D_TIMEOUT 0xAD002006
+MKTC_ST(MKTC_RH_3D_TIMEOUT)
+#define MKTC_RH_NOT_EMPTY 0xAD002007
+MKTC_ST(MKTC_RH_NOT_EMPTY)
+#define MKTC_RH_OBJECT_COMPLETE 0xAD002008
+MKTC_ST(MKTC_RH_OBJECT_COMPLETE)
+#define MKTC_RH_STREAM_LINK 0xAD002009
+MKTC_ST(MKTC_RH_STREAM_LINK)
+#define MKTC_RH_OBJECT_INCOMPLETE 0xAD00200A
+MKTC_ST(MKTC_RH_OBJECT_INCOMPLETE)
+#define MKTC_RH_PRIM_MASK_PRESENT 0xAD00200B
+MKTC_ST(MKTC_RH_PRIM_MASK_PRESENT)
+#define MKTC_RH_BYTE_MASK_PRESENT 0xAD00200C
+MKTC_ST(MKTC_RH_BYTE_MASK_PRESENT)
+#define MKTC_RH_BYTE_MASK_ZERO 0xAD00200D
+MKTC_ST(MKTC_RH_BYTE_MASK_ZERO)
+#define MKTC_RH_PRIM_MASK_ZERO 0xAD00200E
+MKTC_ST(MKTC_RH_PRIM_MASK_ZERO)
+#define MKTC_RH_INVALIDATE_OBJECTS 0xAD00200F
+MKTC_ST(MKTC_RH_INVALIDATE_OBJECTS)
+#define MKTC_RH_OBJECTS_INVALIDATED 0xAD002010
+MKTC_ST(MKTC_RH_OBJECTS_INVALIDATED)
+#define MKTC_RH_DPM_RGN_PARSER_IDLE 0xAD002011
+MKTC_ST(MKTC_RH_DPM_RGN_PARSER_IDLE)
+#define MKTC_RH_NEXT_RGN_BASE 0xAD002012
+MKTC_ST(MKTC_RH_NEXT_RGN_BASE)
+#define MKTC_RH_OCC_EXIT 0xAD002013
+MKTC_ST(MKTC_RH_OCC_EXIT)
+#define MKTC_RH_STILL_RUNNING 0xAD002020
+MKTC_ST(MKTC_RH_STILL_RUNNING)
+#define MKTC_RH_CLEARMCI 0xAD002021
+MKTC_ST(MKTC_RH_CLEARMCI)
+#define MKTC_RH_EOR 0xAD002022
+MKTC_ST(MKTC_RH_EOR)
+#define MKTC_RENDERHALT_END 0xAD002030
+MKTC_ST(MKTC_RENDERHALT_END)
+
+#define MKTC_FIND3D_POWERREQUEST 0xAD002100
+MKTC_ST(MKTC_FIND3D_POWERREQUEST)
+
+#define MKTC_FIND2D_POWERREQUEST 0xAD002200
+MKTC_ST(MKTC_FIND2D_POWERREQUEST)
+
+#define MKTC_UKERNEL_INIT 0xAD002300
+MKTC_ST(MKTC_UKERNEL_INIT)
+#define MKTC_UKERNEL_INIT_DCS_COMPLETE 0xAD002301
+MKTC_ST(MKTC_UKERNEL_INIT_DCS_COMPLETE)
+#define MKTC_UKERNEL_INIT_VDMKICK_COMPLETE 0xAD002303
+MKTC_ST(MKTC_UKERNEL_INIT_VDMKICK_COMPLETE)
+
+#define MKTC_KICKTRANSFERRENDER_START 0xAD002400
+MKTC_ST(MKTC_KICKTRANSFERRENDER_START)
+#define MKTC_KICKTRANSFERRENDER_ISP_START 0xAD002401
+MKTC_ST(MKTC_KICKTRANSFERRENDER_ISP_START)
+#define MKTC_KICKTRANSFERRENDER_END 0xAD002402
+MKTC_ST(MKTC_KICKTRANSFERRENDER_END)
+#define MKTC_DUMMYPROCTRANSFER 0xAD002403
+MKTC_ST(MKTC_DUMMYPROCTRANSFER)
+#define MKTC_KTR_TQFENCE 0xAD002404
+MKTC_ST(MKTC_KTR_TQFENCE)
+#define MKTC_KICKTRANSFERRENDER_PID 0xAD002405
+MKTC_ST(MKTC_KICKTRANSFERRENDER_PID)
+
+#define MKTC_HOSTKICK_CLEANUP_RT 0xAD002500
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_RT)
+#define MKTC_HOSTKICK_CLEANUP_RC 0xAD002501
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_RC)
+#define MKTC_HOSTKICK_CLEANUP_TC 0xAD002502
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_TC)
+#define MKTC_HOSTKICK_CLEANUP_2DC 0xAD002503
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_2DC)
+#define MKTC_HOSTKICK_CLEANUP_PB 0xAD002504
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_PB)
+#define MKTC_HOSTKICK_GETMISCINFO 0xAD002505
+MKTC_ST(MKTC_HOSTKICK_GETMISCINFO)
+#define MKTC_HOSTKICK_DATABREAKPOINT 0xAD002506
+MKTC_ST(MKTC_HOSTKICK_DATABREAKPOINT)
+#define MKTC_HOSTKICK_SETHWPERFSTATUS 0xAD002507
+MKTC_ST(MKTC_HOSTKICK_SETHWPERFSTATUS)
+
+#define MKTC_ZEROPC 0xAD002600
+MKTC_ST(MKTC_ZEROPC)
+
+#define MKTC_ASSERT_FAIL 0xAD002700
+MKTC_ST(MKTC_ASSERT_FAIL)
+
+#define MKTC_SDLB_ILLEGAL 0xAD002800
+MKTC_ST(MKTC_SDLB_ILLEGAL)
+
+#define MKTC_SPMEVENT_OUTOFMEM 0xAD002901
+MKTC_ST(MKTC_SPMEVENT_OUTOFMEM)
+#define MKTC_SPMEVENT_TATERMINATE 0xAD002902
+MKTC_ST(MKTC_SPMEVENT_TATERMINATE)
+#define MKTC_SPMEVENT_END 0xAD002904
+MKTC_ST(MKTC_SPMEVENT_END)
+
+#define MKTC_SPMLB_OUTOFMEM 0xAD002981
+MKTC_ST(MKTC_SPMLB_OUTOFMEM)
+#define MKTC_SPMLB_TATERMINATE 0xAD002982
+MKTC_ST(MKTC_SPMLB_TATERMINATE)
+#define MKTC_SPMLB_SPMRENDERFINSHED 0xAD002983
+MKTC_ST(MKTC_SPMLB_SPMRENDERFINSHED)
+#define MKTC_SPMLB_END 0xAD002985
+MKTC_ST(MKTC_SPMLB_END)
+
+#define MKTC_SPM_CHECK_MT_DEADLOCK 0xAD002991
+MKTC_ST(MKTC_SPM_CHECK_MT_DEADLOCK)
+#define MKTC_SPM_CHECK_GLOBAL_DEADLOCK 0xAD002992
+MKTC_ST(MKTC_SPM_CHECK_GLOBAL_DEADLOCK)
+#define MKTC_SPM_RESERVE_ADDED 0xAD002993
+MKTC_ST(MKTC_SPM_RESERVE_ADDED)
+#define MKTC_SPM_FORCE_GLOBAL_OOM_FAILED 0xAD00299E
+MKTC_ST(MKTC_SPM_FORCE_GLOBAL_OOM_FAILED)
+#define MKTC_SPM_DEADLOCK_MEM_FAILED 0xAD00299F
+MKTC_ST(MKTC_SPM_DEADLOCK_MEM_FAILED)
+
+#define MKTC_IBC_ILLEGAL 0xAD002A00
+MKTC_ST(MKTC_IBC_ILLEGAL)
+
+#define MKTC_HWP_CLEARCOUNTERS 0xAD002B00
+MKTC_ST(MKTC_HWP_CLEARCOUNTERS)
+
+#define MKTC_TA_FRAMENUM 0xAD002C00
+MKTC_ST(MKTC_TA_FRAMENUM)
+#define MKTC_3D_FRAMENUM 0xAD002C01
+MKTC_ST(MKTC_3D_FRAMENUM)
+#define MKTC_SPM3D_FRAMENUM 0xAD002C02
+MKTC_ST(MKTC_SPM3D_FRAMENUM)
+
+#define MKTC_HKTA_RENDERCONTEXT 0xAD002D00
+MKTC_ST(MKTC_HKTA_RENDERCONTEXT)
+#define MKTC_IDLECORE_REFCOUNT_FAIL 0xAD002E00
+MKTC_ST(MKTC_IDLECORE_REFCOUNT_FAIL)
+
+#define MKTC_MCISTATE_NOT_CLEARED 0xAD002F00
+MKTC_ST(MKTC_MCISTATE_NOT_CLEARED)
+
+#define MKTC_LOWERED_TO_PDS_THRESHOLD 0xAD003000
+MKTC_ST(MKTC_LOWERED_TO_PDS_THRESHOLD)
+#define MKTC_REDUCE_MAX_VTX_PARTITIONS 0xAD003001
+MKTC_ST(MKTC_REDUCE_MAX_VTX_PARTITIONS)
+#define MKTC_KTAOVERRIDE_MAX_VTX_PARTITIONS 0xAD003002
+MKTC_ST(MKTC_KTAOVERRIDE_MAX_VTX_PARTITIONS)
+#define MKTC_KTANOOVERRIDE_MAX_VTX_PARTITIONS 0xAD003003
+MKTC_ST(MKTC_KTANOOVERRIDE_MAX_VTX_PARTITIONS)
+
+#define MKTC_IPRB_NORENDERDETAILS 0xAD003010
+MKTC_ST(MKTC_IPRB_NORENDERDETAILS)
+#define MKTC_IPRB_HAVERENDERDETAILS 0xAD003011
+MKTC_ST(MKTC_IPRB_HAVERENDERDETAILS)
+
+#define MKTC_RENDER_OUT_OF_ORDER 0xAD003020
+MKTC_ST(MKTC_RENDER_OUT_OF_ORDER)
+#define MKTC_RENDER_NOT_OUT_OF_ORDER 0xAD003021
+MKTC_ST(MKTC_RENDER_NOT_OUT_OF_ORDER)
+
+#define MKTC_ZLS_IDLE_BEGIN 0xAD003030
+MKTC_ST(MKTC_ZLS_IDLE_BEGIN)
+#define MKTC_ZLS_ISP_CLK_GATING_EN 0xAD003031
+MKTC_ST(MKTC_ZLS_ISP_CLK_GATING_EN)
+#define MKTC_ZLS_IDLE_END 0xAD003032
+MKTC_ST(MKTC_ZLS_IDLE_END)
+
+#endif /* __SGX_UKERNEL_STATUS_CODES_H__ */
+
+/******************************************************************************
+ End of file (sgx_ukernel_status_codes.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title sgx services structures/functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description inline functions/structures shared across UM and KM services components
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined (__SGXINFO_H__)
#define __SGXINFO_H__
#endif
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
IMG_HANDLE hKernelVDMSnapShotBufferMemInfo;
IMG_HANDLE hKernelVDMCtrlStreamBufferMemInfo;
#endif
IMG_UINT32 ui32MasterClkGateStatusMask;
IMG_UINT32 ui32MasterClkGateStatus2Reg;
IMG_UINT32 ui32MasterClkGateStatus2Mask;
-#endif
+#endif /* SGX_FEATURE_MP */
IMG_UINT32 ui32CacheControl;
struct _SGX_DEVICE_SYNC_LIST_ *psNext;
-
+ /* Must be the last variable in the structure */
IMG_UINT32 ui32NumSyncObjects;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID ahSyncHandles[1];
IMG_HANDLE hKernelHWSyncListMemInfo;
#endif
-
+ /* DST syncs */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID *pahDstSyncHandles;
#else
#endif
IMG_BOOL bFirstKickOrResume;
-#if (defined(NO_HARDWARE) || defined(PDUMP))
+#if defined(NO_HARDWARE) || defined(PDUMP)
IMG_BOOL bTerminateOrAbort;
#endif
IMG_BOOL bLastInScene;
-
+ /* CCB offset of data structure associated with this kick */
IMG_UINT32 ui32CCBOffset;
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
-
+ /* SRC and DST syncs */
IMG_UINT32 ui32NumTASrcSyncs;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID ahTASrcKernelSyncInfo[SGX_MAX_TA_SRC_SYNCS];
IMG_HANDLE ah3DSrcKernelSyncInfo[SGX_MAX_3D_SRC_SYNCS];
#endif
#else
-
+ /* SRC syncs */
IMG_UINT32 ui32NumSrcSyncs;
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS];
+ IMG_SID ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS_TA];
#else
- IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS];
+ IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS_TA];
#endif
#endif
-
+ /* TA/3D dependency data */
IMG_BOOL bTADependency;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hTA3DSyncInfo;
} SGX_CCB_KICK;
+/*!
+ ******************************************************************************
+ * shared client/kernel device information structure for SGX
+ *****************************************************************************/
#define SGX_KERNEL_USE_CODE_BASE_INDEX 15
+/*!
+ ******************************************************************************
+ * Client device information structure for SGX
+ *****************************************************************************/
typedef struct _SGX_CLIENT_INFO_
{
- IMG_UINT32 ui32ProcessID;
- IMG_VOID *pvProcess;
- PVRSRV_MISC_INFO sMiscInfo;
+ IMG_UINT32 ui32ProcessID; /*!< ID of process controlling SGX device */
+ IMG_VOID *pvProcess; /*!< pointer to OS specific 'process' structure */
+ PVRSRV_MISC_INFO sMiscInfo; /*!< Misc. Information, inc. SOC specifics */
IMG_UINT32 asDevData[SGX_MAX_DEV_DATA];
} SGX_CLIENT_INFO;
+/*!
+ ******************************************************************************
+ * Internal device information structure for SGX
+ *****************************************************************************/
typedef struct _SGX_INTERNAL_DEVINFO_
{
IMG_UINT32 ui32Flags;
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
-
+ /* need to be able to check reads and writes on dest, and update writes */
IMG_SID hDstSyncInfo;
-
+ /* need to be able to check reads and writes on TA ops, and update writes */
IMG_SID hTASyncInfo;
-
+ /* need to be able to check reads and writes on 2D ops, and update writes */
IMG_SID h3DSyncInfo;
#else
IMG_HANDLE ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
-
+ /* need to be able to check reads and writes on dest, and update writes */
IMG_HANDLE hDstSyncInfo;
-
+ /* need to be able to check reads and writes on TA ops, and update writes */
IMG_HANDLE hTASyncInfo;
-
+ /* need to be able to check reads and writes on 2D ops, and update writes */
IMG_HANDLE h3DSyncInfo;
#endif
#endif
IMG_HANDLE hDevMemContext;
} PVRSRV_2D_SGX_KICK, *PPVRSRV_2D_SGX_KICK;
-#endif
-#endif
+#endif /* defined(SGX_FEATURE_2D_HARDWARE) */
+#endif /* defined(TRANSFER_QUEUE) */
-#endif
+#endif /* __SGXINFO_H__ */
+/******************************************************************************
+ End of file (sgxinfo.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Common Bridge Module (kernel side)
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Receives calls from the user portion of services and
+ despatches them to functions in the kernel portion.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "perproc.h"
#include "device.h"
#include "buffer_manager.h"
+#include "refcount.h"
#include "pdump_km.h"
#include "syscommon.h"
#include "srvkm.h"
+/* FIXME: we should include an OS specific header here to allow configuration of
+ * which functions should be excluded (like the shared srvclient bridge code)
+ * so that ports may choose to override certain things. */
+
+/* For the purpose of maintainability, it is intended that this file should not
+ * contain large amounts of OS specific #ifdefs. Headers are fine, and perhaps
+ * a few one liners, but for anything more, please find a way to add e.g.
+ * an osfunc.c abstraction or override the entire function in question within
+ * env,*,pvr_bridge_k.c
+ */
+
+
PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
#if defined(DEBUG_BRIDGE_KM)
return 0;
}
-
+ /*
+ * Handle is not allocated in batch mode, as there is no resource
+ * allocation to undo if the handle allocation fails.
+ */
psAcquireDevInfoOUT->eError =
PVRSRVAllocHandle(psPerProc->psHandleBase,
&psAcquireDevInfoOUT->hDevCookie,
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT);
-
+ /*
+ * We potentially need one handle for the device memory context,
+ * and one handle for each client heap.
+ */
NEW_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS + 1)
psCreateDevMemContextOUT->eError =
return 0;
}
-
+ /*
+ * Only allocate a handle if the device memory context was created.
+ * If an existing context was returned, lookup the existing
+ * handle.
+ */
if(bCreated)
{
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
if(abSharedDeviceMemHeap[i])
#endif
{
-
+ /*
+ * Heaps shared by everybody. These heaps are not
+ * created as part of the device memory context
+ * creation, and exist for the lifetime of the
+ * driver, hence, we use shared handles for these
+ * heaps.
+ */
#if defined (SUPPORT_SID_INTERFACE)
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&hDevMemHeapExt,
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
else
{
-
+ /*
+ * Heaps belonging to this context. The handles for
+ * these are made subhandles of the memory context
+ * handle, so that they are automatically deallocated
+ * when the memory context handle is deallocated.
+ */
if(bCreated)
{
#if defined (SUPPORT_SID_INTERFACE)
if(abSharedDeviceMemHeap[i])
#endif
{
-
+ /*
+ * Heaps shared by everybody. These heaps are not
+ * created as part of the device memory context
+ * creation, and exist for the lifetime of the
+ * driver, hence, we use shared handles for these
+ * heaps.
+ */
#if defined (SUPPORT_SID_INTERFACE)
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&hDevMemHeapExt,
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
else
{
-
+ /*
+ * Heaps belonging to this context. The handles for
+ * these are made subhandles of the memory context
+ * handle, so that they are automatically deallocated
+ * when the memory context handle is deallocated.
+ */
psGetDevMemHeapInfoOUT->eError =
PVRSRVFindHandle(psPerProc->psHandleBase,
&hDevMemHeapExt,
#if defined(OS_PVRSRV_ALLOC_DEVICE_MEM_BW)
+/* customised version */
IMG_INT
PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
IMG_HANDLE hDevMemHeapInt;
IMG_UINT32 ui32ShareIndex;
IMG_BOOL bUseShareMemWorkaround;
+ IMG_BOOL *pabMapChunk = IMG_NULL;
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_DEVICEMEM);
NEW_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc, 2)
+ /* Do same sanity checking */
+ if (psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_SPARSE)
+ {
+ if (psAllocDeviceMemIN->ui32NumPhysChunks > psAllocDeviceMemIN->ui32NumVirtChunks)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: more physical chunks then virtual space"));
+ psAllocDeviceMemOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ if (psAllocDeviceMemIN->pabMapChunk == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: Called in sparse mapping mode but without MapChunk array"));
+ psAllocDeviceMemOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ }
+
psAllocDeviceMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
psAllocDeviceMemIN->hDevCookie,
return 0;
}
-
+ /* Memory sharing workaround, version 2 */
bUseShareMemWorkaround = ((psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_XPROC) != 0) ? IMG_TRUE : IMG_FALSE;
- ui32ShareIndex = 7654321;
+ ui32ShareIndex = 7654321; /* stops MSVC compiler warning */
if (bUseShareMemWorkaround)
{
-
-
+ /* allocate a shared-surface ID, prior to the call to AllocDeviceMem */
+ /* We could plumb in an extra argument, but for now, we'll keep the
+ shared-surface ID as a piece of global state, and rely upon the
+ bridge mutex to make it safe for us */
psAllocDeviceMemOUT->eError =
BM_XProcWorkaroundFindNewBufferAndSetShareIndex(&ui32ShareIndex);
}
}
+ /* Check access to private data, if provided */
+ if(psAllocDeviceMemIN->pvPrivData)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psAllocDeviceMemIN->pvPrivData,
+ psAllocDeviceMemIN->ui32PrivDataLength))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: Access check failed for pvPrivData"));
+ return -EFAULT;
+ }
+ }
+
+ if (psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_SPARSE)
+ {
+ /* Check access to the sparse mapping table, if provided */
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psAllocDeviceMemIN->pabMapChunk,
+ psAllocDeviceMemIN->ui32NumVirtChunks))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: Access check failed for pabMapChunk"));
+ return -EFAULT;
+ }
+
+ psAllocDeviceMemOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_BOOL) * psAllocDeviceMemIN->ui32NumVirtChunks,
+ (IMG_VOID **) &pabMapChunk,
+ 0,
+ "MapChunk kernel copy");
+ if (psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psAllocDeviceMemOUT->eError = OSCopyFromUser(psPerProc,
+ pabMapChunk,
+ psAllocDeviceMemIN->pabMapChunk,
+ sizeof(IMG_BOOL) * psAllocDeviceMemIN->ui32NumVirtChunks);
+ if (psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_BOOL) * psAllocDeviceMemIN->ui32NumVirtChunks,
+ pabMapChunk,
+ 0);
+ return 0;
+ }
+ }
+
+
psAllocDeviceMemOUT->eError =
PVRSRVAllocDeviceMemKM(hDevCookieInt,
psPerProc,
psAllocDeviceMemIN->ui32Attribs,
psAllocDeviceMemIN->ui32Size,
psAllocDeviceMemIN->ui32Alignment,
+ psAllocDeviceMemIN->pvPrivData,
+ psAllocDeviceMemIN->ui32PrivDataLength,
+ psAllocDeviceMemIN->ui32ChunkSize,
+ psAllocDeviceMemIN->ui32NumVirtChunks,
+ psAllocDeviceMemIN->ui32NumPhysChunks,
+ pabMapChunk,
&psMemInfo,
- "" );
+ "" /*FIXME: add something meaningful*/);
if (bUseShareMemWorkaround)
{
psAllocDeviceMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
psAllocDeviceMemOUT->sClientMemInfo.uAllocSize = psMemInfo->uAllocSize;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* see below */
#else
psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
#endif
if(psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
{
-
+ /* signal no syncinfo */
OSMemSet(&psAllocDeviceMemOUT->sClientSyncInfo,
0,
sizeof (PVRSRV_CLIENT_SYNC_INFO));
}
else
{
-
+ /* and setup the sync info */
#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
psAllocDeviceMemOUT->sClientSyncInfo.psSyncData =
psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
psAllocDeviceMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psAllocDeviceMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
#if defined (SUPPORT_SID_INTERFACE)
if (psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo =
&psAllocDeviceMemOUT->sClientSyncInfo;
-
}
COMMIT_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc)
return 0;
}
-#endif
+#endif /* OS_PVRSRV_ALLOC_DEVICE_MEM_BW */
static IMG_INT
PVRSRVFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
IMG_HANDLE hDevCookieInt;
IMG_VOID *pvKernelMemInfo;
-
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_DEVICEMEM);
psRetOUT->eError =
ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2));
PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
-
+ /* find the device cookie */
psExportDeviceMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevCookieInt,
return 0;
}
-
+ /* find the kernel meminfo from the process handle list */
psExportDeviceMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
(IMG_PVOID *)&psKernelMemInfo,
return 0;
}
-
+ /* see if it's already exported */
psExportDeviceMemOUT->eError =
PVRSRVFindHandle(KERNEL_HANDLE_BASE,
&psExportDeviceMemOUT->hMemInfo,
PVRSRV_HANDLE_TYPE_MEM_INFO);
if(psExportDeviceMemOUT->eError == PVRSRV_OK)
{
-
+ /* it's already exported */
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVExportDeviceMemBW: allocation is already exported"));
return 0;
}
-
+ /* export the allocation */
psExportDeviceMemOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
&psExportDeviceMemOUT->hMemInfo,
psKernelMemInfo,
return 0;
}
-
+ /* mark the meminfo as 'exported' */
psKernelMemInfo->ui32Flags |= PVRSRV_MEM_EXPORTED;
return 0;
NEW_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc, 2)
-
+ /* lookup srcmeminfo handle */
psMapDevMemOUT->eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
(IMG_VOID**)&psSrcKernelMemInfo,
psMapDevMemIN->hKernelMemInfo,
return 0;
}
-
+ /* lookup dev mem heap handle */
psMapDevMemOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDstDevMemHeap,
psMapDevMemIN->hDstDevMemHeap,
return 0;
}
-
+ /* check for workaround */
if (psSrcKernelMemInfo->sShareMemWorkaround.bInUse)
{
PVR_DPF((PVR_DBG_MESSAGE, "using the mem wrap workaround."));
-
-
-
-
-
-
-
-
+ /* Ensure we get the same ID for this allocation, such that it
+ inherits the same physical block. Rather than add a lot of
+ plumbing to several APIs, we call into buffer manager directly
+ to set "global" state. This works only if we make
+ this allocation while holding the bridge mutex and don't
+ make any other allocations (because the state persists and
+ would affect other device memory allocations too). It is
+ important that we bracket the PVRSRVAllocDeviceMemKM() call
+ with this Set/Unset pair. */
psMapDevMemOUT->eError = BM_XProcWorkaroundSetShareIndex(psSrcKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
if(psMapDevMemOUT->eError != PVRSRV_OK)
{
psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqAttribs | PVRSRV_MEM_NO_SYNCOBJ,
psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqSize,
psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqAlignment,
+ IMG_NULL,
+ 0,
+ /* FIXME: Do we need to be able to export sparse memory? */
+ 0,0,0,IMG_NULL, /* No sparse mapping data */
&psDstKernelMemInfo,
- "" );
-
-
+ "" /*FIXME: add something meaningful*/);
+ /* counterpart of the above "SetShareIndex". NB: this must be
+ done in both the success and failure paths of the
+ AllocDeviceMemKM() call */
BM_XProcWorkaroundUnsetShareIndex(psSrcKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
if(psMapDevMemOUT->eError != PVRSRV_OK)
{
- PVR_DPF((PVR_DBG_ERROR, "lakjgfgewjlrgebhe"));
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryBW: Failed to create allocation for cross-process memory map"));
return 0;
}
if(psSrcKernelMemInfo->psKernelSyncInfo)
{
- psSrcKernelMemInfo->psKernelSyncInfo->ui32RefCount++;
+ PVRSRVKernelSyncInfoIncRef(psSrcKernelMemInfo->psKernelSyncInfo, psSrcKernelMemInfo);
}
psDstKernelMemInfo->psKernelSyncInfo = psSrcKernelMemInfo->psKernelSyncInfo;
}
else
{
-
+ /* map the meminfo to the target heap and memory context */
psMapDevMemOUT->eError = PVRSRVMapDeviceMemoryKM(psPerProc,
psSrcKernelMemInfo,
hDstDevMemHeap,
}
}
-
+ /* copy the workaround info */
psDstKernelMemInfo->sShareMemWorkaround = psSrcKernelMemInfo->sShareMemWorkaround;
OSMemSet(&psMapDevMemOUT->sDstClientMemInfo,
psMapDevMemOUT->sDstClientMemInfo.ui32Flags = psDstKernelMemInfo->ui32Flags;
psMapDevMemOUT->sDstClientMemInfo.uAllocSize = psDstKernelMemInfo->uAllocSize;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* see below */
#else
psMapDevMemOUT->sDstClientMemInfo.hMappingInfo = psDstKernelMemInfo->sMemBlk.hOSMemHandle;
#endif
-
+ /* allocate handle to the DST kernel meminfo */
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo,
psDstKernelMemInfo,
psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo = IMG_NULL;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* alloc subhandle for the mapping info */
if (psDstKernelMemInfo->sMemBlk.hOSMemHandle != IMG_NULL)
{
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
}
#endif
-
+ /* and setup the sync info */
if(psDstKernelMemInfo->psKernelSyncInfo)
{
#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
psDstKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
psMapDevMemOUT->sDstClientSyncInfo.sReadOpsCompleteDevVAddr =
psDstKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapDevMemOUT->sDstClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* alloc subhandle for the mapping info */
if (psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
{
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
#endif
psMapDevMemOUT->sDstClientMemInfo.psClientSyncInfo = &psMapDevMemOUT->sDstClientSyncInfo;
-
+ /*
+ * The sync info is associated with the device buffer,
+ * and not allocated here. It isn't exported when created,
+ * hence the handle allocation rather than a lookup.
+ */
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo,
psDstKernelMemInfo->psKernelSyncInfo,
NEW_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc, 2)
-
+ /*
+ * The buffer to be mapped can belong to a 3rd party display or
+ * buffer driver, and we don't know which type we have at this
+ * point.
+ */
psMapDevClassMemOUT->eError =
PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
&hDeviceClassBufferInt,
return 0;
}
-
+ /* get the device memory context */
psMapDevClassMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevMemContextInt,
return 0;
}
-
+ /* Having looked up the handle, now check its type */
switch(eHandleType)
{
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo = IMG_NULL;
-
+ /* and setup the sync info */
if(psMemInfo->psKernelSyncInfo)
{
#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
psMapDevClassMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapDevClassMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
#if defined (SUPPORT_SID_INTERFACE)
if (psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != 0)
#endif
psMapDevClassMemOUT->sClientMemInfo.psClientSyncInfo = &psMapDevClassMemOUT->sClientSyncInfo;
-
+ /*
+ * The sync info is associated with the device buffer,
+ * and not allocated here. It isn't exported when
+ * created, hence the handle allocation rather than a
+ * lookup.
+ */
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo,
psMemInfo->psKernelSyncInfo,
PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
PVRSRV_PER_PROCESS_DATA *psPerProc);
-#else
+#else /* OS_PVRSRV_WRAP_EXT_MEM_BW */
static IMG_INT
PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
NEW_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc, 2)
-
+ /*
+ * FIXME: This needs reworking - don't use the user supplied page
+ * table list, get the list from the OS.
+ */
psWrapExtMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
psWrapExtMemIN->hDevCookie,
return 0;
}
-
+ /* get the device memory context */
psWrapExtMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
psWrapExtMemIN->hDevMemContext,
ui32PageTableSize) != PVRSRV_OK)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageTableSize, (IMG_VOID *)psSysPAddr, 0);
-
+ /*not nulling pointer, out of scope*/
return -EFAULT;
}
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
ui32PageTableSize,
(IMG_VOID *)psSysPAddr, 0);
-
+ /*not nulling pointer, out of scope*/
}
if(psWrapExtMemOUT->eError != PVRSRV_OK)
psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM =
psMemInfo->pvLinAddrKM;
-
+ /* setup the mem info */
psWrapExtMemOUT->sClientMemInfo.pvLinAddr = 0;
psWrapExtMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
psWrapExtMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
psWrapExtMemOUT->sClientMemInfo.uAllocSize = psMemInfo->uAllocSize;
#if defined (SUPPORT_SID_INTERFACE)
+/* see below */
#else
psWrapExtMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
#endif
PVRSRV_HANDLE_ALLOC_FLAG_NONE);
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* alloc subhandle for the mapping info */
if (psMemInfo->sMemBlk.hOSMemHandle != IMG_NULL)
{
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
}
#endif
-
+ /* setup the sync info */
#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
psWrapExtMemOUT->sClientSyncInfo.psSyncData =
psMemInfo->psKernelSyncInfo->psSyncData;
psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
psWrapExtMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psWrapExtMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* alloc subhandle for the mapping info */
if (psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
{
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
return 0;
}
-#endif
+#endif /* OS_PVRSRV_WRAP_EXT_MEM_BW */
static IMG_INT
PVRSRVUnwrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
return 0;
}
+#if defined(SUPPORT_ION)
+static IMG_INT
+PVRSRVMapIonHandleBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_ION_HANDLE *psMapIonIN,
+ PVRSRV_BRIDGE_OUT_MAP_ION_HANDLE *psMapIonOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ psMapIonOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psMapIonIN->hDevCookie,
+ psMapIonIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if (psMapIonOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to lookup device node handle", __FUNCTION__));
+ return 0;
+ }
+
+ psMapIonOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psMapIonIN->hDevMemContext,
+ psMapIonIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if (psMapIonOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to lookup memory context handle", __FUNCTION__));
+ return 0;
+ }
+
+ psMapIonOUT->eError = PVRSRVMapIonHandleKM(psPerProc,
+ psMapIonIN->hDevCookie,
+ psMapIonIN->hDevMemContext,
+ psMapIonIN->handle,
+ psMapIonIN->ui32Attribs,
+ psMapIonIN->ui32Size,
+ &psKernelMemInfo);
+ if (psMapIonOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map ion handle", __FUNCTION__));
+ return 0;
+ }
+
+ OSMemSet(&psMapIonOUT->sClientMemInfo,
+ 0,
+ sizeof(psMapIonOUT->sClientMemInfo));
+
+ psMapIonOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psMapIonOUT->sClientMemInfo.pvLinAddr = 0;
+ psMapIonOUT->sClientMemInfo.sDevVAddr = psKernelMemInfo->sDevVAddr;
+ psMapIonOUT->sClientMemInfo.ui32Flags = psKernelMemInfo->ui32Flags;
+ psMapIonOUT->sClientMemInfo.uAllocSize = psKernelMemInfo->uAllocSize;
+
+ /* No mapping info, we map through ion */
+ psMapIonOUT->sClientMemInfo.hMappingInfo = IMG_NULL;
+
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psMapIonOUT->sClientMemInfo.hKernelMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ if(psMapIonIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+ /* signal no syncinfo */
+ OSMemSet(&psMapIonOUT->sClientSyncInfo,
+ 0,
+ sizeof (PVRSRV_CLIENT_SYNC_INFO));
+ psMapIonOUT->sClientMemInfo.psClientSyncInfo = IMG_NULL;
+ }
+ else
+ {
+ /* and setup the sync info */
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+ psMapIonOUT->sClientSyncInfo.psSyncData =
+ psKernelMemInfo->psKernelSyncInfo->psSyncData;
+ psMapIonOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapIonOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapIonOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapIonOUT->sClientSyncInfo.hMappingInfo,
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapIonOUT->sClientMemInfo.hKernelMemInfo);
+ }
+ else
+ {
+ psMapIonOUT->sClientSyncInfo.hMappingInfo = 0;
+ }
+#else
+ psMapIonOUT->sClientSyncInfo.hMappingInfo =
+ psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+#endif
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapIonOUT->sClientSyncInfo.hKernelSyncInfo,
+ psKernelMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapIonOUT->sClientMemInfo.hKernelMemInfo);
+
+ psMapIonOUT->sClientMemInfo.psClientSyncInfo =
+ &psMapIonOUT->sClientSyncInfo;
+ }
+ return 0;
+}
+
+static IMG_INT
+PVRSRVUnmapIonHandleBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNMAP_ION_HANDLE *psUnmapIonIN,
+ PVRSRV_BRIDGE_RETURN *psUnmapIonOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_ION_HANDLE);
+
+ psUnmapIonOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvKernelMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psUnmapIonIN->hKernelMemInfo,
+#else
+ psUnmapIonIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psUnmapIonOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psUnmapIonOUT->eError = PVRSRVUnmapIonHandleKM(pvKernelMemInfo);
+
+ if(psUnmapIonOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psUnmapIonOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ psUnmapIonIN->hKernelMemInfo,
+#else
+ psUnmapIonIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+#endif /* SUPPORT_ION */
+
static IMG_INT
PVRSRVGetFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM *psGetFreeDeviceMemIN,
{
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA);
-#if defined (__linux__) || defined(__QNXNTO__)
+#if defined (__linux__) || defined (__QNXNTO__)
psMMapDataOUT->eError =
PVRMMapOSMemHandleToMMapData(psPerProc,
psMMapDataIN->hMHandle,
{
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RELEASE_MMAP_DATA);
-#if defined (__linux__) || defined(__QNXNTO__)
+#if defined (__linux__) || defined (__QNXNTO__)
psMMapDataOUT->eError =
PVRMMapReleaseMMapData(psPerProc,
psMMapDataIN->hMHandle,
ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
}
-
+ /* FIXME: Move this code to somewhere outside of the bridge */
if (psPDumpSyncPolIN->bUseLastOpDumpVal)
{
if(psPDumpSyncPolIN->bIsRead)
return 0;
}
-#endif
+#endif /* PDUMP */
static IMG_INT
PVRSRV_ERROR eError;
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_MISC_INFO);
+
#if defined (SUPPORT_SID_INTERFACE)
sMiscInfo.ui32StateRequest = psGetMiscInfoIN->sMiscInfo.ui32StateRequest;
sMiscInfo.ui32StatePresent = psGetMiscInfoIN->sMiscInfo.ui32StatePresent;
OSMemCopy(&sMiscInfo.sCacheOpCtl,
&psGetMiscInfoIN->sMiscInfo.sCacheOpCtl,
sizeof(sMiscInfo.sCacheOpCtl));
+ OSMemCopy(&sMiscInfo.sGetRefCountCtl,
+ &psGetMiscInfoIN->sMiscInfo.sGetRefCountCtl,
+ sizeof(sMiscInfo.sGetRefCountCtl));
#else
-
OSMemCopy(&psGetMiscInfoOUT->sMiscInfo,
&psGetMiscInfoIN->sMiscInfo,
sizeof(PVRSRV_MISC_INFO));
((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) &&
((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
{
-
+ /* Client must choose which of memstats and DDK version will be written to
+ * kernel side buffer */
psGetMiscInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
}
((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) ||
((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
{
-
+ /* Alloc kernel side buffer to write into */
#if defined (SUPPORT_SID_INTERFACE)
ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
"Output string buffer"));
psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&sMiscInfo);
-
+ /* Copy result to user */
eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
sMiscInfo.pszMemoryStr,
psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
-
+ /* Copy result to user */
eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
psGetMiscInfoOUT->sMiscInfo.pszMemoryStr,
psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen);
#endif
-
+ /* Free kernel side buffer again */
#if defined (SUPPORT_SID_INTERFACE)
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
sMiscInfo.ui32MemoryStrLen,
(IMG_VOID *)psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0);
#endif
-
+ /* Replace output buffer pointer with input pointer, as both are expected
+ * to point to the same userspace memory.
+ */
psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = psGetMiscInfoIN->sMiscInfo.pszMemoryStr;
if(eError != PVRSRV_OK)
{
-
+ /* Do error check at the end as we always have to free and reset the
+ * pointer.
+ */
PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoBW Error copy to user"));
return -EFAULT;
}
#endif
}
-
+ /* Return on error so exit status of PVRSRVGetMiscInfoKM is propagated to client.
+ * Don't alloc handles for event object or timer; if error exit status is returned
+ * the handles should not be used (even if not null) */
if (psGetMiscInfoOUT->eError != PVRSRV_OK)
{
return 0;
}
-
+ /*
+ * The handles are not allocated in batch mode as they are shared
+ * (a shared handle is allocated at most once), and there is no
+ * resource allocation to undo if the handle allocation fails.
+ */
#if defined (SUPPORT_SID_INTERFACE)
if (sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT)
#else
OSMemCopy(&psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.szName,
sMiscInfo.sGlobalEventObject.szName,
EVENTOBJNAME_MAXLENGTH);
-
#endif
}
if (psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle)
#endif
{
-
+ /* Allocate handle for SOC OSMemHandle */
psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
&psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
#if defined (SUPPORT_SID_INTERFACE)
psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle = 0;
}
-
+ /* copy data from local sMiscInfo to OUT */
psGetMiscInfoOUT->sMiscInfo.ui32StateRequest = sMiscInfo.ui32StateRequest;
psGetMiscInfoOUT->sMiscInfo.ui32StatePresent = sMiscInfo.ui32StatePresent;
OSMemCopy(&psGetMiscInfoOUT->sMiscInfo.sCacheOpCtl,
&sMiscInfo.sCacheOpCtl,
sizeof(psGetMiscInfoOUT->sMiscInfo.sCacheOpCtl));
+ OSMemCopy(&psGetMiscInfoOUT->sMiscInfo.sGetRefCountCtl,
+ &sMiscInfo.sGetRefCountCtl,
+ sizeof(psGetMiscInfoOUT->sMiscInfo.sGetRefCountCtl));
#endif
return 0;
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
#if defined(PDUMP)
-
+ /* Store the per process connection info.
+ * The Xserver initially connects via PVR2D which sets the persistent flag.
+ * But, later the Xserver may connect via SGL which doesn't carry the flag (in
+ * general SGL clients aren't persistent). So we OR in the flag so if it was set
+ * before it remains set.
+ */
if ((psConnectServicesIN->ui32Flags & SRV_FLAGS_PERSIST) != 0)
{
psPerProc->bPDumpPersistent = IMG_TRUE;
}
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* Select whether this client is our 'active' target for pdumping in a
+ * multi-process environment.
+ * NOTE: only 1 active target is supported at present.
+ */
if ((psConnectServicesIN->ui32Flags & SRV_FLAGS_PDUMP_ACTIVE) != 0)
{
psPerProc->bPDumpActive = IMG_TRUE;
}
-#endif
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
#else
PVR_UNREFERENCED_PARAMETER(psConnectServicesIN);
#endif
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DISCONNECT_SERVICES);
-
+ /* just return OK, per-process data is cleaned up by resmgr */
psRetOUT->eError = PVRSRV_OK;
return 0;
return 0;
}
- psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt, IMG_FALSE);
+ psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt);
if(psRetOUT->eError != PVRSRV_OK)
{
return 0;
return 0;
}
+#if defined(SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER)
static IMG_INT
PVRSRVGetDCSystemBufferBW(IMG_UINT32 ui32BridgeID,
- PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN, //IMG_HANDLE *phGetDispClassSysBufferIN,
PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferOUT,
PVRSRV_PER_PROCESS_DATA *psPerProc)
{
return 0;
}
-
+ /* PRQA S 1461 6 */ /* ignore warning about enum type being converted */
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&psGetDispClassSysBufferOUT->hBuffer,
hBufferInt,
return 0;
}
+#endif
static IMG_INT
PVRSRVGetDCInfoBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* Get ui32SwapChainID from input */
ui32SwapChainID = psCreateDispClassSwapChainIN->ui32SwapChainID;
psCreateDispClassSwapChainOUT->eError =
return 0;
}
-
+ /* Pass ui32SwapChainID to output */
psCreateDispClassSwapChainOUT->ui32SwapChainID = ui32SwapChainID;
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
pvSwapChain,
&psGetDispClassBuffersOUT->ui32BufferCount,
#if defined (SUPPORT_SID_INTERFACE)
- pahBuffer);
+ pahBuffer,
#else
- psGetDispClassBuffersOUT->ahBuffer);
+ psGetDispClassBuffersOUT->ahBuffer,
#endif
+ psGetDispClassBuffersOUT->asPhyAddr);
if (psGetDispClassBuffersOUT->eError != PVRSRV_OK)
{
return 0;
IMG_HANDLE hBufferExt;
#endif
-
+ /* PRQA S 1461 15 */ /* ignore warning about enum type being converted */
#if defined (SUPPORT_SID_INTERFACE)
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&hBufferExt,
}
#endif
-
psRetOUT->eError =
PVRSRVSwapToDCBufferKM(pvDispClassInfo,
pvSwapChainBuf,
return 0;
}
+static IMG_INT
+PVRSRVSwapToDCBuffer2BW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER2 *psSwapDispClassBufferIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvPrivData = IMG_NULL;
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up DISP_INFO handle"));
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSwapDispClassBufferIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ psSwapDispClassBufferIN->hDeviceKM);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up DISP_BUFFER handle"));
+ return 0;
+ }
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psSwapDispClassBufferIN->ppsKernelMemInfos,
+ sizeof(IMG_HANDLE) * psSwapDispClassBufferIN->ui32NumMemInfos))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Access check failed for ppsKernelMemInfos"));
+ return -EFAULT;
+ }
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psSwapDispClassBufferIN->ppsKernelSyncInfos,
+ sizeof(IMG_HANDLE) * psSwapDispClassBufferIN->ui32NumMemInfos))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Access check failed for ppsKernelSyncInfos"));
+ return -EFAULT;
+ }
+
+ for (i = 0; i < psSwapDispClassBufferIN->ui32NumMemInfos; i++)
+ {
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psSwapDispClassBufferIN->ppsKernelMemInfos[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up MEM_INFO handle"));
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelSyncInfo,
+ psSwapDispClassBufferIN->ppsKernelSyncInfos[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up SYNC_INFO handle"));
+ return 0;
+ }
+
+ psSwapDispClassBufferIN->ppsKernelMemInfos[i] = psKernelMemInfo;
+ psSwapDispClassBufferIN->ppsKernelSyncInfos[i] = psKernelSyncInfo;
+ }
+
+ if(psSwapDispClassBufferIN->ui32PrivDataLength > 0)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSwapDispClassBufferIN->ui32PrivDataLength,
+ (IMG_VOID **)&pvPrivData, IMG_NULL,
+ "Swap Command Private Data") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2BW: Failed to allocate private data space"));
+ return -ENOMEM;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pvPrivData,
+ psSwapDispClassBufferIN->pvPrivData,
+ psSwapDispClassBufferIN->ui32PrivDataLength) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to copy private data"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSwapDispClassBufferIN->ui32PrivDataLength,
+ pvPrivData, IMG_NULL);
+ return -EFAULT;
+ }
+ }
+
+ psRetOUT->eError =
+ PVRSRVSwapToDCBuffer2KM(pvDispClassInfo,
+ pvSwapChain,
+ psSwapDispClassBufferIN->ui32SwapInterval,
+ psSwapDispClassBufferIN->ppsKernelMemInfos,
+ psSwapDispClassBufferIN->ppsKernelSyncInfos,
+ psSwapDispClassBufferIN->ui32NumMemInfos,
+ pvPrivData,
+ psSwapDispClassBufferIN->ui32PrivDataLength);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSwapDispClassBufferIN->ui32PrivDataLength,
+ pvPrivData, IMG_NULL);
+ }
+
+ return 0;
+}
+
+
+
static IMG_INT
PVRSRVSwapToDCSystemBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM *psSwapDispClassSystemIN,
}
psRetOUT->eError =
- PVRSRVCloseBCDeviceKM(pvBufClassInfo, IMG_FALSE);
+ PVRSRVCloseBCDeviceKM(pvBufClassInfo);
if(psRetOUT->eError != PVRSRV_OK)
{
return 0;
}
-
+ /* PRQA S 1461 6 */ /* ignore warning about enum type being converted */
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&psGetBufferClassBufferOUT->hBuffer,
hBufferInt,
return 0;
}
-
+ /*
+ * To prevent the building up of deep chains of subhandles, parent
+ * the new meminfo off the parent of the input meminfo, if it has
+ * a parent.
+ */
psMapMemInfoMemOUT->eError =
PVRSRVGetParentHandle(psPerProc->psHandleBase,
&hParent,
if(psKernelMemInfo->ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
{
-
+ /* signal no syncinfo */
OSMemSet(&psMapMemInfoMemOUT->sClientSyncInfo,
0,
sizeof (PVRSRV_CLIENT_SYNC_INFO));
}
else
{
-
+ /* and setup the sync info */
#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
psMapMemInfoMemOUT->sClientSyncInfo.psSyncData =
psKernelMemInfo->psKernelSyncInfo->psSyncData;
psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
psMapMemInfoMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapMemInfoMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
#if defined (SUPPORT_SID_INTERFACE)
if (psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
}
+/*!
+ * *****************************************************************************
+ * @brief A wrapper for filling in the g_BridgeDispatchTable array that does
+ * error checking.
+ *
+ * @param ui32Index
+ * @param pszIOCName
+ * @param pfFunction
+ * @param pszFunctionName
+ *
+ * @return
+ ********************************************************************************/
IMG_VOID
_SetDispatchTableEntry(IMG_UINT32 ui32Index,
const IMG_CHAR *pszIOCName,
BridgeWrapperFunction pfFunction,
const IMG_CHAR *pszFunctionName)
{
- static IMG_UINT32 ui32PrevIndex = ~0UL;
+ static IMG_UINT32 ui32PrevIndex = ~0UL; /* -1 */
#if !defined(DEBUG)
PVR_UNREFERENCED_PARAMETER(pszIOCName);
#endif
#endif
#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
-
+ /* INTEGRATION_POINT: Enable this to dump out the dispatch table entries */
PVR_DPF((PVR_DBG_WARNING, "%s: %d %s %s", __FUNCTION__, ui32Index, pszIOCName, pszFunctionName));
#endif
-
+ /* We should never be over-writing a previous entry.
+ * If we are, tell the world about it.
+ * NOTE: This shouldn't be debug only since switching from debug->release
+ * etc is likly to modify the available ioctls and thus be a point where
+ * mistakes are exposed. This isn't run at at a performance critical time.
+ */
if(g_BridgeDispatchTable[ui32Index].pfFunction)
{
#if defined(DEBUG_BRIDGE_KM)
PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
}
-
+ /* Any gaps are sub-optimal in-terms of memory usage, but we are mainly
+ * interested in spotting any large gap of wasted memory that could be
+ * accidentally introduced.
+ *
+ * This will currently flag up any gaps > 5 entries.
+ *
+ * NOTE: This shouldn't be debug only since switching from debug->release
+ * etc is likly to modify the available ioctls and thus be a point where
+ * mistakes are exposed. This isn't run at at a performance critical time.
+ */
+// if((ui32PrevIndex != (IMG_UINT32)-1) &&
if((ui32PrevIndex != ~0UL) &&
((ui32Index >= ui32PrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
(ui32Index <= ui32PrevIndex)))
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_CONNECT);
PVR_UNREFERENCED_PARAMETER(psBridgeIn);
-
+ /* PRQA S 3415 1 */ /* side effects needed - if any step fails */
if((OSProcHasPrivSrvInit() == IMG_FALSE) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
{
psRetOUT->eError = PVRSRV_ERROR_SRV_CONNECT_FAILED;
return 0;
}
-#if defined (__linux__) || defined(__QNXNTO__)
+#if defined (__linux__) || defined (__QNXNTO__)
PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
#endif
psPerProc->bInitProcess = IMG_TRUE;
psPerProc->bInitProcess = IMG_FALSE;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ psPerProc->bPDumpActive = IMG_FALSE;
+#endif
+
PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_FALSE);
PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, IMG_TRUE);
}
#if defined (SUPPORT_SID_INTERFACE)
+/* Windows7, WinXP and Vista already use an Index type handle which the client glue uses directly */
+/* Linux requires a SID handle */
#if !defined (WINXP) && !defined(SUPPORT_VISTA)
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&psEventObjectOpenOUT->hOSEvent,
&psEventObjectCloseIN->sEventObject.szName,
EVENTOBJNAME_MAXLENGTH) != PVRSRV_OK)
{
-
+ /*not nulling pointer, out of scope*/
return -EFAULT;
}
IMG_UINT32 ui32ModifyFlags;
IMG_UINT32 ui32ReadOpsPendingSnapShot;
IMG_UINT32 ui32WriteOpsPendingSnapShot;
+ IMG_UINT32 ui32ReadOps2PendingSnapShot;
} MODIFY_SYNC_OP_INFO;
static PVRSRV_ERROR DoQuerySyncOpsSatisfied(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
IMG_UINT32 ui32ReadOpsPendingSnapShot,
- IMG_UINT32 ui32WriteOpsPendingSnapShot)
+ IMG_UINT32 ui32WriteOpsPendingSnapShot,
+ IMG_UINT32 ui32ReadOps2PendingSnapShot)
{
IMG_UINT32 ui32WriteOpsPending;
IMG_UINT32 ui32ReadOpsPending;
+ IMG_UINT32 ui32ReadOps2Pending;
+
+ /*
+ *
+ * We wait until the complete count reaches _or_moves_past_ the
+ * snapshot value.
+ *
+ */
-
if (!psKernelSyncInfo)
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
-
-
-
-
-
-
+ /*
+ let p be the pending ops count
+ let c be the complete ops count
+ let p' be the previously taken snapshot
+ if p exceeds c by an amount greater than that by which
+ p exceeds p', then the condition is not yet satisfied.
+ Note that (p - c) can never be negative, and neither can (p - p')
+ so we can do the comparison using unsigned arithmetic
+ */
ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
if((ui32WriteOpsPending - ui32WriteOpsPendingSnapShot >=
ui32WriteOpsPending - psKernelSyncInfo->psSyncData->ui32WriteOpsComplete) &&
(ui32ReadOpsPending - ui32ReadOpsPendingSnapShot >=
- ui32ReadOpsPending - psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
+ ui32ReadOpsPending - psKernelSyncInfo->psSyncData->ui32ReadOpsComplete) &&
+ (ui32ReadOps2Pending - ui32ReadOps2PendingSnapShot >=
+ ui32ReadOps2Pending - psKernelSyncInfo->psSyncData->ui32ReadOps2Complete))
{
#if defined(PDUMP) && !defined(SUPPORT_VGX)
-
+ /* pdump the sync pol: reads */
PDumpComment("Poll for read ops complete to reach value (pdump: %u, actual snapshot: %u)",
psKernelSyncInfo->psSyncData->ui32LastReadOpDumpVal,
ui32ReadOpsPendingSnapShot);
offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
psKernelSyncInfo->psSyncData->ui32LastReadOpDumpVal,
0xFFFFFFFF,
- PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_POLL_OPERATOR_EQUAL, /* * see "NB" below */
0,
MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
-
+ /* pdump the sync pol: writes */
PDumpComment("Poll for write ops complete to reach value (pdump: %u, actual snapshot: %u)",
psKernelSyncInfo->psSyncData->ui32LastOpDumpVal,
ui32WriteOpsPendingSnapShot);
offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
psKernelSyncInfo->psSyncData->ui32LastOpDumpVal,
0xFFFFFFFF,
- PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_POLL_OPERATOR_EQUAL, /* * see "NB" below */
0,
MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
-
-
+ /* NB: FIXME -- really need to POL on an expression to
+ accurately reflect the condition we need to check. How to
+ do this in PDUMP? */
#endif
return PVRSRV_OK;
}
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* If user has used the API correctly, we will always have reached the pending snapshot.
+ We should catch this error on the client side of the bridge and report it in an obvious way */
if((psModSyncOpInfo->ui32WriteOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
|| (psModSyncOpInfo->ui32ReadOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
{
return PVRSRV_ERROR_BAD_SYNC_STATE;
}
-
+ /* update the WOpComplete */
if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
{
psKernelSyncInfo->psSyncData->ui32WriteOpsComplete++;
}
-
+ /* update the ROpComplete */
if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
{
psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
if (psModSyncOpInfo->psKernelSyncInfo)
{
-
LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
{
if (DoQuerySyncOpsSatisfied(psModSyncOpInfo->psKernelSyncInfo,
psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
- psModSyncOpInfo->ui32WriteOpsPendingSnapShot) == PVRSRV_OK)
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot) == PVRSRV_OK)
{
goto OpFlushedComplete;
}
PVR_DPF((PVR_DBG_ERROR, " Write ops pending snapshot = %d, write ops complete = %d",
psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32WriteOpsComplete));
- PVR_DPF((PVR_DBG_ERROR, " Read ops pending snapshot = %d, write ops complete = %d",
+ PVR_DPF((PVR_DBG_ERROR, " Read ops pending snapshot = %d, read ops complete = %d",
psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32ReadOpsComplete));
-
+ PVR_DPF((PVR_DBG_ERROR, " Read ops pending snapshot = %d, read ops2 complete = %d",
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot,
+ psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32ReadOps2Complete));
return PVRSRV_ERROR_TIMEOUT;
OpFlushedComplete:
-
DoModifyCompleteSyncOps(psModSyncOpInfo);
+ PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MODIFY_SYNC_OP_INFO), (IMG_VOID *)psModSyncOpInfo, 0);
-
-
+ /* re-kick all services managed devices */
PVRSRVScheduleDeviceCallbacks();
return PVRSRV_OK;
(IMG_VOID **)&psModSyncOpInfo, 0,
"ModSyncOpInfo (MODIFY_SYNC_OP_INFO)"));
- psModSyncOpInfo->psKernelSyncInfo = IMG_NULL;
+ psModSyncOpInfo->psKernelSyncInfo = IMG_NULL; /* mark it as empty */
psCreateSyncInfoModObjOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
&psCreateSyncInfoModObjOUT->hKernelSyncInfoModObj,
if(psModSyncOpInfo->psKernelSyncInfo != IMG_NULL)
{
-
+ /* Not empty */
psDestroySyncInfoModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
}
+ PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
+
psDestroySyncInfoModObjOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
psDestroySyncInfoModObjIN->hKernelSyncInfoModObj,
PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
if(psModSyncOpInfo->psKernelSyncInfo)
{
-
+ /* SyncInfoModification is not empty */
psModifySyncOpsOUT->eError = PVRSRV_ERROR_RETRY;
PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVModifyPendingSyncOpsBW: SyncInfo Modification object is not empty"));
return 0;
}
-
+ /* Should never happen, but check to be sure */
+ if (psKernelSyncInfo == IMG_NULL)
+ {
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVModifyPendingSyncOpsBW: SyncInfo bad handle"));
+ return 0;
+ }
+
+ PVRSRVKernelSyncInfoIncRef(psKernelSyncInfo, IMG_NULL);
+ /* setup info to store in resman */
psModSyncOpInfo->psKernelSyncInfo = psKernelSyncInfo;
psModSyncOpInfo->ui32ModifyFlags = psModifySyncOpsIN->ui32ModifyFlags;
psModSyncOpInfo->ui32ReadOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
psModSyncOpInfo->ui32WriteOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
-
+ /* We return PRE-INCREMENTED versions of all sync Op Values */
psModifySyncOpsOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
psModifySyncOpsOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+ psModifySyncOpsOUT->ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
{
psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
}
-
+ /* pull the resman item to the front of the list */
psModifySyncOpsOUT->eError = ResManDissociateRes(psModSyncOpInfo->hResItem,
psPerProc->hResManContext);
if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
{
-
+ /* Empty */
psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
}
return 0;
}
+ PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
psModSyncOpInfo->psKernelSyncInfo = IMG_NULL;
-
+ /* re-kick all services managed devices */
PVRSRVScheduleDeviceCallbacks();
return 0;
return 0;
}
-
+ /* We return PRE-INCREMENTED versions of all sync Op Values */
psSyncOpsTakeTokenOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
psSyncOpsTakeTokenOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSyncOpsTakeTokenOUT->ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
return 0;
}
PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
IMG_UINT32 ui32ReadOpsPendingSnapshot;
IMG_UINT32 ui32WriteOpsPendingSnapshot;
+ IMG_UINT32 ui32ReadOps2PendingSnapshot;
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_TOKEN);
ui32ReadOpsPendingSnapshot = psSyncOpsFlushToTokenIN->ui32ReadOpsPendingSnapshot;
ui32WriteOpsPendingSnapshot = psSyncOpsFlushToTokenIN->ui32WriteOpsPendingSnapshot;
+ ui32ReadOps2PendingSnapshot = psSyncOpsFlushToTokenIN->ui32ReadOps2PendingSnapshot;
psSyncOpsFlushToTokenOUT->eError = DoQuerySyncOpsSatisfied(psKernelSyncInfo,
ui32ReadOpsPendingSnapshot,
- ui32WriteOpsPendingSnapshot);
+ ui32WriteOpsPendingSnapshot,
+ ui32ReadOps2PendingSnapshot);
if (psSyncOpsFlushToTokenOUT->eError != PVRSRV_OK && psSyncOpsFlushToTokenOUT->eError != PVRSRV_ERROR_RETRY)
{
if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
{
-
+ /* Empty */
psSyncOpsFlushToModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
}
psSyncOpsFlushToModObjOUT->eError = DoQuerySyncOpsSatisfied(psModSyncOpInfo->psKernelSyncInfo,
psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
- psModSyncOpInfo->ui32WriteOpsPendingSnapShot);
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot);
if (psSyncOpsFlushToModObjOUT->eError != PVRSRV_OK && psSyncOpsFlushToModObjOUT->eError != PVRSRV_ERROR_RETRY)
{
return 0;
}
-
+ /* FIXME: there's logic here in the bridge-wrapper - this needs to be moved to
+ a better place */
+
ui32DeltaRead = psSyncInfo->psSyncData->ui32ReadOpsPending - psSyncInfo->psSyncData->ui32ReadOpsComplete;
ui32DeltaWrite = psSyncInfo->psSyncData->ui32WriteOpsPending - psSyncInfo->psSyncData->ui32WriteOpsComplete;
if (ui32DeltaRead <= psSyncOpsFlushToDeltaIN->ui32Delta && ui32DeltaWrite <= psSyncOpsFlushToDeltaIN->ui32Delta)
{
#if defined(PDUMP) && !defined(SUPPORT_VGX)
-
+ /* pdump the sync pol: reads */
PDumpComment("Poll for read ops complete to delta (%u)",
psSyncOpsFlushToDeltaIN->ui32Delta);
psSyncOpsFlushToDeltaOUT->eError =
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /* pdump the sync pol: writes */
PDumpComment("Poll for write ops complete to delta (%u)",
psSyncOpsFlushToDeltaIN->ui32Delta);
psSyncOpsFlushToDeltaOUT->eError =
IMG_BOOL bDummy)
{
PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
- PVRSRV_ERROR eError;
PVR_UNREFERENCED_PARAMETER(ui32Param);
PVR_UNREFERENCED_PARAMETER(bDummy);
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)pvParam;
- eError = PVRSRVFreeSyncInfoKM(psSyncInfo);
- if (eError != PVRSRV_OK)
- {
- return eError;
- }
+ PVRSRVKernelSyncInfoDecRef(psSyncInfo, IMG_NULL);
return PVRSRV_OK;
}
RESMAN_TYPE_SYNC_INFO,
psSyncInfo,
0,
- FreeSyncInfoCallback);
+ &FreeSyncInfoCallback);
-
+ /* Success */
goto allocsyncinfo_commit;
-
+ /* Error handling */
allocsyncinfo_errorexit_freesyncinfo:
- PVRSRVFreeSyncInfoKM(psSyncInfo);
+ PVRSRVKernelSyncInfoDecRef(psSyncInfo, IMG_NULL);
allocsyncinfo_errorexit:
-
+ /* Common exit */
allocsyncinfo_commit:
psAllocSyncInfoOUT->eError = eError;
COMMIT_HANDLE_BATCH_OR_ERROR(eError, psPerProc);
SetDispatchTableEntry(PVRSRV_BRIDGE_CHG_DEV_MEM_ATTRIBS, PVRSRVChangeDeviceMemoryAttributesBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEV_MEMORY_2, PVRSRVMapDeviceMemoryBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2, PVRSRVExportDeviceMemBW);
+#if defined(SUPPORT_ION)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_ION_HANDLE, PVRSRVMapIonHandleBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_ION_HANDLE, PVRSRVUnmapIonHandleBW);
+#endif
-
+ /* SIM */
SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS, DummyBW);
-
+ /* User Mapping */
SetDispatchTableEntry(PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_FB_STATS, DummyBW);
-
+ /* API to retrieve misc. info. from services */
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_MISC_INFO, PVRSRVGetMiscInfoBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MISC_INFO, DummyBW);
-
+ /* Overlay ioctls */
#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
-
+ /* PDUMP */
#if defined(PDUMP)
SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_INIT, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_MEMPOL, PDumpMemPolBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ, PDumpCycleCountRegReadBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STARTINITPHASE, PDumpStartInitPhaseBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STOPINITPHASE, PDumpStopInitPhaseBW);
-#endif
+#endif /* defined(PDUMP) */
-
+ /* DisplayClass APIs */
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_OEMJTABLE, DummyBW);
-
+ /* device class enum */
SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_CLASS, PVRSRVEnumerateDCBW);
-
+ /* display class API */
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);
+#if defined(SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER)
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, PVRSRVGetDCSystemBufferBW);
+#else
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, DummyBW);
+#endif
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_SRCCOLOURKEY, PVRSRVSetDCSrcColourKeyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS, PVRSRVGetDCBuffersBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER, PVRSRVSwapToDCBufferBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2, PVRSRVSwapToDCBuffer2BW);
SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM, PVRSRVSwapToDCSystemBW);
-
+ /* buffer class API */
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);
-
+ /* Wrap/Unwrap external memory */
SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_EXT_MEMORY, PVRSRVWrapExtMemoryBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY, PVRSRVUnwrapExtMemoryBW);
-
+ /* Shared memory */
SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM, PVRSRVAllocSharedSysMemoryBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM, PVRSRVFreeSharedSysMemoryBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEMINFO_MEM, PVRSRVMapMemInfoMemBW);
-
+ /* Intialisation Service support */
SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_CONNECT, &PVRSRVInitSrvConnectBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_DISCONNECT, &PVRSRVInitSrvDisconnectBW);
-
+ /* Event Object */
SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_WAIT, &PVRSRVEventObjectWaitBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_OPEN, &PVRSRVEventObjectOpenBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE, &PVRSRVEventObjectCloseBW);
SetMSVDXDispatchTableEntry();
#endif
-
-
-
+ /* A safety net to help ensure there won't be any un-initialised dispatch
+ * table entries... */
+ /* Note: This is specifically done _after_ setting all the dispatch entries
+ * so that SetDispatchTableEntry can detect mistakes where entries
+ * overlap */
for(i=0;i<BRIDGE_DISPATCH_TABLE_ENTRY_COUNT;i++)
{
if(!g_BridgeDispatchTable[i].pfFunction)
IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM)
{
-
IMG_VOID * psBridgeIn;
IMG_VOID * psBridgeOut;
BridgeWrapperFunction pfBridgeHandler;
}
else
{
-
+ /* Only certain operations are allowed */
switch(ui32BridgeID)
{
case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES):
}
}
-
-
#if defined(__linux__)
{
-
+ /* This should be moved into the linux specific code */
SYS_DATA *psSysData;
SysAcquireData(&psSysData);
-
+ /* We have already set up some static buffers to store our ioctl data... */
psBridgeIn = ((ENV_DATA *)psSysData->pvEnvSpecificData)->pvBridgeData;
psBridgeOut = (IMG_PVOID)((IMG_PBYTE)psBridgeIn + PVRSRV_MAX_BRIDGE_IN_SIZE);
-
+ /* check we are not using a bigger bridge than allocated */
if((psBridgePackageKM->ui32InBufferSize > PVRSRV_MAX_BRIDGE_IN_SIZE) ||
(psBridgePackageKM->ui32OutBufferSize > PVRSRV_MAX_BRIDGE_OUT_SIZE))
{
goto return_fault;
}
-
#if defined(__linux__)
-
+ /* This should be moved into the linux specific code */
if(CopyToUserWrapper(psPerProc,
ui32BridgeID,
psBridgePackageKM->pvParamOut,
return err;
}
+/******************************************************************************
+ End of file (bridged_pvr_bridge.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the PVR Bridge code
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __BRIDGED_PVR_BRIDGE_H__
#define __BRIDGED_PVR_BRIDGE_H__
PVRSRVReleaseHandleBatch(psPerProc->psHandleBase);
}
}
-#else
+#else /* defined(PVR_SECURE_HANDLES) */
#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)
#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc)
#define ReleaseHandleBatch(psPerProc)
-#endif
+#endif /* defined(PVR_SECURE_HANDLES) */
IMG_INT
DummyBW(IMG_UINT32 ui32BridgeID,
typedef struct _PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
{
- BridgeWrapperFunction pfFunction;
+ BridgeWrapperFunction pfFunction; /*!< The wrapper function that validates the ioctl
+ arguments before calling into srvkm proper */
#if defined(DEBUG_BRIDGE_KM)
- const IMG_CHAR *pszIOCName;
- const IMG_CHAR *pszFunctionName;
- IMG_UINT32 ui32CallCount;
- IMG_UINT32 ui32CopyFromUserTotalBytes;
- IMG_UINT32 ui32CopyToUserTotalBytes;
+ const IMG_CHAR *pszIOCName; /*!< Name of the ioctl: e.g. "PVRSRV_BRIDGE_CONNECT_SERVICES" */
+ const IMG_CHAR *pszFunctionName; /*!< Name of the wrapper function: e.g. "PVRSRVConnectBW" */
+ IMG_UINT32 ui32CallCount; /*!< The total number of times the ioctl has been called */
+ IMG_UINT32 ui32CopyFromUserTotalBytes; /*!< The total number of bytes copied from
+ userspace within this ioctl */
+ IMG_UINT32 ui32CopyToUserTotalBytes; /*!< The total number of bytes copied from
+ userspace within this ioctl */
#endif
}PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
const IMG_CHAR *pszFunctionName);
-
+/* PRQA S 0884,3410 2*/ /* macro relies on the lack of brackets */
#define SetDispatchTableEntry(ui32Index, pfFunction) \
_SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32Index), #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction)
IMG_UINT32 ui32TotalCopyToUserBytes;
}PVRSRV_BRIDGE_GLOBAL_STATS;
+/* OS specific code way want to report the stats held here and within the
+ * BRIDGE_DISPATCH_TABLE_ENTRYs (E.g. on Linux we report these via a
+ * proc entry /proc/pvr/bridge_stats. Ref printLinuxBridgeStats()) */
extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
#endif
}
#endif
-#endif
+#endif /* __BRIDGED_PVR_BRIDGE_H__ */
+/******************************************************************************
+ End of file (bridged_pvr_bridge.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Bridge Support Functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description User/kernel mode bridge support. The functions in here
+ may be used beyond the bridge code proper (e.g. Linux
+ mmap interface).
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "img_defs.h"
#include "servicesint.h"
#include "bridged_support.h"
+/*
+ * Derive the internal OS specific memory handle from a secure
+ * handle.
+ */
PVRSRV_ERROR
#if defined (SUPPORT_SID_INTERFACE)
PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHandle, IMG_SID hMHandle)
PVRSRV_HANDLE_TYPE eHandleType;
PVRSRV_ERROR eError;
-
+ /*
+ * We don't know the type of the handle at this point, so we use
+ * PVRSRVLookupHandleAnyType to look it up.
+ */
eError = PVRSRVLookupHandleAnyType(psHandleBase, &hMHandleInt,
&eHandleType,
hMHandle);
return PVRSRV_OK;
}
+/******************************************************************************
+ End of file (bridged_support.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Bridge Support
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description User/kernel mode bridge support. The functions in here
+ may be used beyond the bridge code proper (e.g. Linux
+ mmap interface).
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __BRIDGED_SUPPORT_H__
#define __BRIDGED_SUPPORT_H__
extern "C" {
#endif
+/*
+ * Derive the internal OS specific memory handle from a secure
+ * handle.
+ */
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phOSMemHandle, IMG_SID hMHandle);
#else
}
#endif
-#endif
+#endif /* __BRIDGED_SUPPORT_H__ */
+/******************************************************************************
+ End of file (bridged_support.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX Common Bridge Module (kernel side)
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Receives calls from the user portion of services and
+ despatches them to functions in the kernel portion.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0);
-
+ /*
+ * psDevInfo->ui32ClientRefCount can be zero if an error occurred before SGXGetClientInfo is called
+ */
if (psDevInfo->ui32ClientRefCount > 0)
{
psDevInfo->ui32ClientRefCount--;
&psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo);
#endif
-
+ /*
+ * Handle is not allocated in batch mode, as there is no resource
+ * allocation to undo if the handle allocation fails.
+ */
psSGXGetInternalDevInfoOUT->eError =
PVRSRVAllocHandle(psPerProc->psHandleBase,
&psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
}
#if defined(FIX_HW_BRN_31620)
-
+ /* We need to lookup the mem context and pass it through */
psRetOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
&psDoKickIN->sCCBKick.hDevMemContext,
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
-
+ /* SRC and DST sync details */
if (psDoKickIN->sCCBKick.ui32NumTASrcSyncs > SGX_MAX_TA_SRC_SYNCS)
{
psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
}
}
-#else
-
- if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS)
+#else/* #if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS) */
+ /* texture dependency details */
+ if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS_TA)
{
psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
return 0;
}
}
-#endif
+#endif/* #if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS) */
if (psDoKickIN->sCCBKick.ui32NumTAStatusVals > SGX_MAX_TA_STATUS_VALS)
{
goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
}
-
+ /* Set sCCBKick.pahDstSyncHandles to point to the local memory */
psDoKickIN->sCCBKick.pahDstSyncHandles = phKernelSyncInfoHandles;
#endif
sCCBKickKM.ui32CCBOffset = psDoKickIN->sCCBKick.ui32CCBOffset;
sCCBKickKM.bTADependency = psDoKickIN->sCCBKick.bTADependency;
-#if (defined(NO_HARDWARE) || defined(PDUMP))
+#if defined(NO_HARDWARE) || defined(PDUMP)
sCCBKickKM.bTerminateOrAbort = psDoKickIN->sCCBKick.bTerminateOrAbort;
#endif
#if defined(PDUMP)
#if defined(NO_HARDWARE)
sCCBKickKM.ui32WriteOpsPendingVal = psDoKickIN->sCCBKick.ui32WriteOpsPendingVal;
#endif
-#endif
+#endif /* #if defined (SUPPORT_SID_INTERFACE) */
psRetOUT->eError =
SGXDoKickKM(hDevCookieInt,
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT:
+//#if (!defined(_UITRON_) && !defined(UNDER_VISTA)) || defined (SUPPORT_SID_INTERFACE)
if(phKernelSyncInfoHandles)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
ui32NumDstSyncs * sizeof(IMG_HANDLE),
(IMG_VOID *)phKernelSyncInfoHandles,
0);
-
+ /*not nulling pointer, out of scope*/
}
return ret;
}
psKick = &psSubmitTransferIN->sKick;
#if defined(FIX_HW_BRN_31620)
-
+ /* We need to lookup the mem context and pass it through */
psRetOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
&psKick->hDevMemContext,
psKick = &psSubmit2DIN->sKick;
#if defined(FIX_HW_BRN_31620)
-
+ /* We need to lookup the mem context and pass it through */
psRetOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
&psKick->hDevMemContext,
sKickKM.hDstSyncInfo = IMG_NULL;
}
-
+ /* copy common members across */
sKickKM.ui32SharedCmdCCBOffset = psKick->ui32SharedCmdCCBOffset;
sKickKM.ui32NumSrcSync = psKick->ui32NumSrcSync;
sKickKM.ui32PDumpFlags = psKick->ui32PDumpFlags;
return 0;
}
-#endif
-#endif
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE) */
+#endif /* #if defined(TRANSFER_QUEUE) */
static IMG_INT
}
#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
-
+ /* Lookup handle for dev mem context */
if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMREAD)
{
psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
}
}
#endif
-
+ /* device node is required for scheduling a CCB command */
psDeviceNode = hDevCookieInt;
PVR_ASSERT(psDeviceNode != IMG_NULL);
if (psDeviceNode == IMG_NULL)
psDevInfo = psDeviceNode->pvDevice;
-
+ /* Copy psMiscInfo to kernel space */
psRetOUT->eError = CopyFromUserWrapper(psPerProc,
ui32BridgeID,
&sMiscInfo,
}
}
-
+ /* Copy back misc info to user address space */
psRetOUT->eError = CopyToUserWrapper(psPerProc,
ui32BridgeID,
psSGXGetMiscInfoIN->psMiscInfo,
ui32AllocatedSize,
psAllocated,
hAllocatedHandle);
-
+ /*not nulling pointer, out of scope*/
return 0;
}
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DEVINITPART2);
-
+ /* Report the kernel-side build options to UM */
psSGXDevInitPart2OUT->ui32KMBuildOptions = SGX_BUILD_OPTIONS;
if(!psPerProc->bInitProcess)
return 0;
}
-
+ /* Check all the meminfo handles */
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDummy,
psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
PVRSRV_HANDLE_TYPE_MEM_INFO);
if (eError != PVRSRV_OK)
{
+ PVR_DPF((PVR_DBG_ERROR, "SGXDevInitPart2BW: Failed to look up HWPerf meminfo (possibly due to SUPPORT_SGX_HWPERF option mismatch)"));
bLookupFailed = IMG_TRUE;
}
#endif
}
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDummy,
psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo,
if (bLookupFailed)
{
- PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle lookup failed"));
+ PVR_DPF((PVR_DBG_ERROR, "SGXDevInitPart2BW: A handle lookup failed"));
psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
return 0;
}
-
+ /* Lookup and release the device memory handles */
eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
#if defined (SUPPORT_SID_INTERFACE)
&asInitInfoKM.hKernelCCBMemInfo,
bReleaseFailed = IMG_TRUE;
}
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
&psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo,
psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo,
if (bReleaseFailed)
{
- PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle release failed"));
+ PVR_DPF((PVR_DBG_ERROR, "SGXDevInitPart2BW: A handle release failed"));
psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
-
+ /*
+ * Given that we checked the handles before release, a release
+ * failure is unexpected.
+ */
PVR_DBG_BREAK;
return 0;
}
-
+ /* Dissociate device memory from caller */
#if defined (SUPPORT_SID_INTERFACE)
eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelCCBMemInfo);
#else
}
#endif
-
+ /* Dissociate SGX MiscInfo buffer from user space */
#if defined (SUPPORT_SID_INTERFACE)
eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelSGXMiscMemInfo);
#else
#endif
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo);
bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
}
}
-
+ /* If any dissociations failed, free all the device memory passed in */
if(bDissociateFailed)
{
#if defined (SUPPORT_SID_INTERFACE)
}
- PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A dissociate failed"));
+ PVR_DPF((PVR_DBG_ERROR, "SGXDevInitPart2BW: A dissociate failed"));
psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
-
+ /* A dissociation failure is unexpected */
PVR_DBG_BREAK;
return 0;
}
PVRSRV_PER_PROCESS_DATA *psPerProc)
{
IMG_HANDLE hDevCookieInt;
+// PVRSRV_SGXDEV_INFO *psDevInfo;
IMG_HANDLE hHWRenderContextInt;
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT);
return 0;
}
-#endif
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE) */
static IMG_INT
SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID,
PVRSRV_PER_PROCESS_DATA *psPerProc)
{
IMG_HANDLE hDevCookieInt;
+// PVRSRV_SGXDEV_INFO *psDevInfo;
+
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET);
psRetOUT->eError =
return 0;
}
+// psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
psRetOUT->eError = SGXFlushHWRenderTargetKM(hDevCookieInt, psSGXFlushHWRenderTargetIN->sHWRTDataSetDevVAddr, IMG_FALSE);
return 0;
if(hSharedPBDesc == IMG_NULL)
{
psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle = 0;
-
+ /* It's not an error if we don't find a buffer,
+ * we just return NULL */
goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
}
PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
PVRSRV_HANDLE_ALLOC_FLAG_NONE);
-
+ /*
+ * We allocate handles of type PVRSRV_HANDLE_TYPE_MEM_INFO_REF here,
+ * as the process doesn't own the underlying memory, and so should
+ * only be allowed a restricted set of operations on it, such as
+ * mapping it into its address space.
+ */
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle,
psSharedPBDescKernelMemInfo,
}
}
-
-
+ /*
+ * Release all the handles we've just looked up, as none
+ * of the associated resources will be valid for access via
+ * those handles once we return from SGXAddSharedPBDesc.
+ */
+ /* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
PVR_ASSERT(eError == PVRSRV_OK);
-
+ /* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
PVRSRV_HANDLE_TYPE_MEM_INFO);
PVR_ASSERT(eError == PVRSRV_OK);
-
+ /* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
PVR_ASSERT(eError == PVRSRV_OK);
-
+ /* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
PVRSRV_HANDLE_TYPE_MEM_INFO);
for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
{
-
+ /* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
phKernelMemInfoHandles[i],
PVRSRV_HANDLE_TYPE_MEM_INFO);
if ((asHeapInfo[i].ui32HeapID != (IMG_UINT32)SGX_UNDEFINED_HEAP_ID) &&
(asHeapInfo[i].hDevMemHeap != IMG_NULL))
{
-
+ /* Allocate heap handle */
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&psHeapInfo->hDevMemHeap,
asHeapInfo[i].hDevMemHeap,
if (psHeapInfo->hDevMemHeap != IMG_NULL)
{
-
+ /* Allocate heap handle */
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&hDevMemHeapExt,
psHeapInfo->hDevMemHeap,
}
#if defined(PDUMP)
+// PRQA S 5120++
+/*****************************************************************************
+ FUNCTION : DumpBufferArray
+ PURPOSE : PDUMP information in stored buffer array
+ PARAMETERS :
+ RETURNS :
+*****************************************************************************/
static IMG_VOID
DumpBufferArray(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined (SUPPORT_SID_INTERFACE)
}
else
{
-
+ /*
+ Range of data wraps the end of the buffer so it needs to be dumped in two sections
+ */
if (bDumpPolls)
{
SGX_KICKTA_DUMP_BUFFER *psUMPtr;
SGX_KICKTA_DUMP_BUFFER_KM *psKickTADumpBufferKM, *psKMPtr;
#else
+#if defined(__QNXNTO__)
+ const IMG_UINT32 NAME_BUFFER_SIZE = 30;
+ IMG_PCHAR pszNameBuffer, pszName;
+ IMG_UINT32 ui32NameBufferArraySize, ui32NameLength;
+#endif
SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
#endif
IMG_UINT32 ui32BufferArrayLength =
ui32BufferArrayLength * sizeof(SGX_KICKTA_DUMP_BUFFER);
PVRSRV_ERROR eError = PVRSRV_ERROR_TOO_FEW_BUFFERS;
-#if defined (__QNXNTO__)
- const IMG_UINT32 MAX_BUFFER_NAME_SIZE = 30;
- IMG_PCHAR pszNamesBuffer, pszName;
- IMG_UINT32 ui32NameBufferArraySize;
-#endif
-
PVR_UNREFERENCED_PARAMETER(psBridgeOut);
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY);
ui32BufferArraySize) != PVRSRV_OK)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
-
+ /*not nulling pointer, out of scope*/
return -EFAULT;
}
-#endif
#if defined (__QNXNTO__)
- ui32NameBufferArraySize = ui32BufferArrayLength * MAX_BUFFER_NAME_SIZE;
+ ui32NameBufferArraySize = ui32BufferArrayLength * NAME_BUFFER_SIZE;
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, ui32NameBufferArraySize,
- (IMG_PVOID *)&pszNamesBuffer, 0,
+ (IMG_PVOID *)&pszNameBuffer, 0,
"Kick Tile Accelerator Dump Buffer names") != PVRSRV_OK)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
return -ENOMEM;
}
- pszName = pszNamesBuffer;
+ pszName = pszNameBuffer;
+
for (i=0; i<ui32BufferArrayLength; i++)
{
- if (CopyFromUserWrapper(psPerProc, ui32BridgeID,
- pszName, psKickTADumpBuffer[i].pszName,
- MAX_BUFFER_NAME_SIZE) != PVRSRV_OK)
+ if (psKickTADumpBuffer[i].pszName)
{
- PVR_DPF((PVR_DBG_WARNING, "Failed to read pdump buffer name"));
- psKickTADumpBuffer[i].pszName = 0;
+ ui32NameLength = psKickTADumpBuffer[i].ui32NameLength;
+ if (ui32NameLength >= NAME_BUFFER_SIZE)
+ {
+ ui32NameLength = NAME_BUFFER_SIZE - 1;
+ }
+
+ if (ui32NameLength &&
+ (CopyFromUserWrapper(psPerProc, ui32BridgeID, pszName,
+ psKickTADumpBuffer[i].pszName, ui32NameLength + 1) == PVRSRV_OK))
+ {
+ pszName[NAME_BUFFER_SIZE - 1] = 0;
+ psKickTADumpBuffer[i].pszName = pszName;
+ pszName += NAME_BUFFER_SIZE;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Failed to read PDUMP buffer name"));
+ psKickTADumpBuffer[i].pszName = 0;
+ }
}
- else
- {
- pszName[MAX_BUFFER_NAME_SIZE-1] = 0;
- psKickTADumpBuffer[i].pszName = pszName;
- }
- pszName += MAX_BUFFER_NAME_SIZE;
}
+#endif
#endif
for(i = 0; i < ui32BufferArrayLength; i++)
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBufferKM, 0);
#else
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
-#endif
-
-
#if defined (__QNXNTO__)
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32NameBufferArraySize, pszNamesBuffer, 0);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32NameBufferArraySize, pszNameBuffer, 0);
#endif
+#endif
+ /*not nulling pointer, out of scope*/
return 0;
}
psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
-
+ /* Enable all cores available */
ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
#if defined(PDUMP)
return 0;
}
-
- PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL)
+ /* look up the MMU context ID */
+ PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL);
ui32MMUContextID = psDeviceNode->pfnMMUGetContextID((IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext);
PDumpSignatureBuffer(&psDeviceNode->sDevId,
psDevInfo->psKernelTASigBufferMemInfo->sDevVAddr,
(IMG_UINT32)psDevInfo->psKernelTASigBufferMemInfo->uAllocSize,
ui32MMUContextID,
- 0 );
+ 0 /*ui32PDumpFlags*/);
PDumpSignatureBuffer(&psDeviceNode->sDevId,
"out.3dsig", "3D", 0,
psDevInfo->psKernel3DSigBufferMemInfo->sDevVAddr,
(IMG_UINT32)psDevInfo->psKernel3DSigBufferMemInfo->uAllocSize,
ui32MMUContextID,
- 0 );
+ 0 /*ui32PDumpFlags*/);
ExitNoError:
psRetOUT->eError = PVRSRV_OK;
psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
-
+ /* Enable all cores available */
ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
#if defined(PDUMP)
return ret;
}
+//PRQA S 5120--
+
+
static IMG_INT
SGXPDumpHWPerfCBBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB *psPDumpHWPerfCBIN,
return 0;
}
-
- PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL)
+ /* look up the MMU context ID */
+ PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL);
ui32MMUContextID = psDeviceNode->pfnMMUGetContextID(hDevMemContextInt);
PDumpHWPerfCBKM(&psDeviceNode->sDevId,
PVR_UNREFERENCED_PARAMETER(psRetOUT);
PVR_UNREFERENCED_PARAMETER(psPerProc);
return 0;
-#endif
+#endif /* defined(LINUX) || defined(UNDER_XP) */
#else
PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
PVR_UNREFERENCED_PARAMETER(psRetOUT);
PVR_UNREFERENCED_PARAMETER(psPerProc);
return -EFAULT;
-#endif
+#endif /* defined(SUPPORT_SGX_HWPERF) */
}
return 0;
}
-
- PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL)
+ /* look up the MMU context ID */
+ PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL);
ui32MMUContextID = psDeviceNode->pfnMMUGetContextID(hDevMemContextInt);
PDumpSaveMemKM(&psDeviceNode->sDevId,
return 0;
}
-#endif
+#endif /* PDUMP */
-
+/* PRQA S 0313,3635 END_SET_SGX */ /* function macro required this format */
IMG_VOID SetSGXDispatchTableEntry(IMG_VOID)
{
SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM, SGXPDumpSaveMemBW);
#endif
}
-
+/* PRQA L:END_SET_SGX */ /* end of setup overrides */
-#endif
+#endif /* SUPPORT_SGX */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the PVR Bridge code
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __BRIDGED_SGX_BRIDGE_H__
#define __BRIDGED_SGX_BRIDGE_H__
}
#endif
-#endif
+#endif /* __BRIDGED_SGX_BRIDGE_H__ */
+/******************************************************************************
+ End of file (bridged_sgx_bridge.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Buffer management functions for Linux
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Manages buffers mapped into two memory spaces - cpu and device,
+ either of which can be virtual or physical.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
BM_FreeMemory (IMG_VOID *pH, IMG_UINTPTR_T base, BM_MAPPING *psMapping);
static IMG_BOOL
BM_ImportMemory(IMG_VOID *pH, IMG_SIZE_T uSize,
- IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping,
- IMG_UINT32 uFlags, IMG_UINTPTR_T *pBase);
+ IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags, IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength, IMG_UINTPTR_T *pBase);
static IMG_BOOL
DevMemoryAlloc (BM_CONTEXT *pBMContext,
static IMG_VOID
DevMemoryFree (BM_MAPPING *pMapping);
+/*!
+******************************************************************************
+
+ @Function AllocMemory
+
+ @Description Allocate a buffer mapped into both cpu and device virtual
+ address spaces. This is now quite simple:
+
+ 1. Choose whence to get the memory;
+ 2. Obtain memory from that source;
+ 3. Work out the actual buffer addresses in other spaces.
+
+ In choosing whence to get the memory we work like this:
+
+ 1. If an import arena exists, use unless BP_CONTIGUOUS is set;
+ 2. Use a contiguous pool.
+
+ @Input pBMContext - BM context
+ @Input psBMHeap - BM heap
+ @Input psDevVAddr - device virtual address (optional)
+ @Input uSize - requested buffer size in bytes.
+ @Input uFlags - property flags for the buffer.
+ @Input uDevVAddrAlignment - required device virtual address
+ alignment, or 0.
+ @Input pvPrivData - opaque private data passed through to allocator
+ @Input ui32PrivDataLength - length of opaque private data
+
+ @Output pBuf - receives a pointer to a descriptor of the allocated
+ buffer.
+ @Return IMG_TRUE - Success
+ IMG_FALSE - Failed.
+
+ *****************************************************************************/
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)
+AllocMemory (BM_CONTEXT *pBMContext,
+ BM_HEAP *psBMHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ BM_BUF *pBuf)
{
BM_MAPPING *pMapping;
IMG_UINTPTR_T uOffset;
"AllocMemory (uSize=0x%x, uFlags=0x%x, align=0x%x)",
uSize, uFlags, uDevVAddrAlignment));
-
-
-
+ /*
+ what to do depends on combination of DevVaddr generation
+ and backing RAM requirement
+ */
if(uFlags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
{
if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
{
-
+ /* user supplied DevVAddr, RAM backing */
PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported"));
return IMG_FALSE;
}
-
+ /* BM supplied DevVAddr, RAM Backing */
-
+ /* check heap attributes */
if(psBMHeap->ui32Attribs
& (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
{
-
+ /* specify arena (VM+RAM)*/
pArena = psBMHeap->pImportArena;
PVR_ASSERT(psBMHeap->sDevArena.psDeviceMemoryHeapInfo->ui32Attribs & PVRSRV_MEM_RAM_BACKED_ALLOCATION);
}
return IMG_FALSE;
}
+ /* Now allocate from the arena we chose above. */
+ if (uFlags & PVRSRV_MEM_SPARSE)
+ {
+ IMG_BOOL bSuccess;
+ IMG_SIZE_T puiActualSize;
+
+ /* Allocate physcial memory */
+ bSuccess = BM_ImportMemory(psBMHeap,
+ ui32ChunkSize * ui32NumPhysChunks,
+ &puiActualSize,
+ &pMapping,
+ uFlags,
+ pvPrivData,
+ ui32PrivDataLength,
+ IMG_NULL); /* We allocate VM space */
+
+ if (puiActualSize != ui32ChunkSize * ui32NumPhysChunks)
+ {
+ /*
+ Most likley the chunksize was not host page multiple so
+ return with an error
+ */
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: Failed to allocate memory for sparse allocation"));
+ BM_FreeMemory(pArena, IMG_NULL, pMapping);
+ return IMG_FALSE;
+ }
+
+ pMapping->uSizeVM = ui32ChunkSize * ui32NumVirtChunks;
+ uSize = pMapping->uSizeVM;
+ pMapping->ui32ChunkSize = ui32ChunkSize;
+ pMapping->ui32NumVirtChunks = ui32NumVirtChunks;
+ pMapping->ui32NumPhysChunks = ui32NumPhysChunks;
+ pMapping->pabMapChunk = pabMapChunk;
+
+ /* Allocate VA space and map in the physical memory */
+ bSuccess = DevMemoryAlloc (pBMContext,
+ pMapping,
+ IMG_NULL,
+ uFlags,
+ (IMG_UINT32)uDevVAddrAlignment,
+ &pMapping->DevVAddr);
+ if (!bSuccess)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocMemory: Failed to allocate device memory"));
+ BM_FreeMemory(pArena, IMG_NULL, pMapping);
+ return IMG_FALSE;
+ }
- if (!RA_Alloc(pArena,
- uSize,
- IMG_NULL,
- (IMG_VOID*) &pMapping,
- uFlags,
- uDevVAddrAlignment,
- 0,
- (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
- {
- PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%x) FAILED", uSize));
- return IMG_FALSE;
+ /* uDevVAddrAlignment is currently set to zero so QAC generates warning which we override */
+ /* PRQA S 3356,3358 1 */
+ PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+ pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr;
+ }
+ else
+ {
+ if (!RA_Alloc(pArena,
+ uSize,
+ IMG_NULL,
+ (IMG_VOID*) &pMapping,
+ uFlags,
+ uDevVAddrAlignment,
+ 0,
+ pvPrivData,
+ ui32PrivDataLength,
+ (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;
pBuf->CpuVAddr = IMG_NULL;
}
- if(uSize == pMapping->uSize)
+ if(uSize == pMapping->uSizeVM)
{
pBuf->hOSMemHandle = pMapping->hOSMemHandle;
}
}
}
-
+ /* for hm_contiguous and hm_wrapped memory, the pMapping
+ * will have a physical address, else 0 */
pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
if(uFlags & PVRSRV_MEM_ZERO)
{
if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
{
-
+ /* user supplied DevVAddr, no RAM backing */
PVR_ASSERT(psDevVAddr != IMG_NULL);
if (psDevVAddr == IMG_NULL)
return IMG_FALSE;
}
-
+ /* just make space in the pagetables */
pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
uSize,
IMG_NULL,
uDevVAddrAlignment,
psDevVAddr);
-
+ /* setup buf */
pBuf->DevVAddr = *psDevVAddr;
}
else
{
-
+ IMG_BOOL bResult;
+ /* BM supplied DevVAddr, no RAM Backing */
-
- pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+ /* just make space in the pagetables */
+ bResult = pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
uSize,
IMG_NULL,
0,
uDevVAddrAlignment,
&pBuf->DevVAddr);
+
+ if(!bResult)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: MMUAlloc failed"));
+ return IMG_FALSE;
+ }
}
-
+ /* allocate a mocked-up mapping */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof (struct _BM_MAPPING_),
(IMG_PVOID *)&pMapping, IMG_NULL,
return IMG_FALSE;
}
-
+ /* setup buf */
pBuf->CpuVAddr = IMG_NULL;
pBuf->hOSMemHandle = 0;
pBuf->CpuPAddr.uiAddr = 0;
-
+ /* setup mapping */
pMapping->CpuVAddr = IMG_NULL;
pMapping->CpuPAddr.uiAddr = 0;
pMapping->DevVAddr = pBuf->DevVAddr;
pMapping->hOSMemHandle = 0;
}
-
+ /* Record the arena pointer in the mapping. */
pMapping->pArena = pArena;
-
+ /* record the heap */
pMapping->pBMHeap = psBMHeap;
pBuf->pMapping = pMapping;
-
+ /* output some stats */
PVR_DPF ((PVR_DBG_MESSAGE,
"AllocMemory: pMapping=%08x: DevV=%08X CpuV=%08x CpuP=%08X uSize=0x%x",
(IMG_UINTPTR_T)pMapping,
pBuf->CpuPAddr.uiAddr,
uSize));
-
+ /* Verify virtual device address alignment */
PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);
return IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function WrapMemory
+
+ @Description Allocate a buffer mapped into both cpu and device virtual
+ address spaces.
+
+ @Input psBMHeap - BM heap
+ @Input uSize - requested buffer size in bytes.
+ @Input ui32BaseOffset - Offset from page of wrap.
+ @Input bPhysContig - Is the wrap physically contiguous.
+ @Input psAddr - List of pages to wrap.
+ @Input pvCPUVAddr - Optional CPU Kernel virtual address (page aligned) of memory to wrap
+ @Input uFlags - property flags for the buffer.
+ @Output Buf - receives a pointer to a descriptor of the allocated
+ buffer.
+ @Return IMG_TRUE - Success
+ IMG_FALSE - Failed.
+
+ *****************************************************************************/
static IMG_BOOL
WrapMemory (BM_HEAP *psBMHeap,
IMG_SIZE_T uSize,
(IMG_UINTPTR_T)psBMHeap, uSize, ui32BaseOffset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags));
PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);
-
+ /* Only need lower 12 bits of the cpu addr - don't care what size a void* is */
PVR_ASSERT(((IMG_UINTPTR_T)pvCPUVAddr & (ui32PageSize - 1)) == 0);
uSize += ui32BaseOffset;
uSize = HOST_PAGEALIGN (uSize);
-
+ /* allocate a mocked-up mapping */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*pMapping),
(IMG_PVOID *)&pMapping, IMG_NULL,
OSMemSet(pMapping, 0, sizeof (*pMapping));
pMapping->uSize = uSize;
+ pMapping->uSizeVM = uSize;
pMapping->pBMHeap = psBMHeap;
if(pvCPUVAddr)
if(OSReservePhys(pMapping->CpuPAddr,
pMapping->uSize,
uFlags,
+ IMG_NULL,
&pMapping->CpuVAddr,
&pMapping->hOSMemHandle) != PVRSRV_OK)
{
}
}
-
+ /*
+ * Allocate device memory for this buffer. Map wrapped pages as read/write
+ */
bResult = DevMemoryAlloc(psBMHeap->pBMContext,
pMapping,
IMG_NULL,
goto fail_cleanup;
}
-
+ /*
+ * Determine the offset of this allocation within the underlying
+ * dual mapped chunk of memory, we can assume that all three
+ * addresses associated with this allocation are placed at the same
+ * offset within the underlying chunk.
+ */
pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + ui32BaseOffset;
if(!ui32BaseOffset)
{
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return IMG_FALSE;
}
IMG_SIZE_T ui32CurrentOffset = 0;
IMG_CPU_PHYADDR CpuPAddr;
-
+ /* Walk through the pBuf one page at a time and use
+ * transient mappings to zero the memory */
+
PVR_ASSERT(pBuf->hOSMemHandle);
while(ui32BytesRemaining > 0)
{
IMG_SIZE_T ui32BlockBytes = MIN(ui32BytesRemaining, HOST_PAGESIZE());
CpuPAddr = OSMemHandleToCpuPAddr(pBuf->hOSMemHandle, ui32CurrentOffset);
-
+ /* If the CpuPAddr isn't page aligned then start by writing up to the next page
+ * boundary (or ui32BytesRemaining if less), so that subsequent iterations can
+ * copy full physical pages. */
if(CpuPAddr.uiAddr & (HOST_PAGESIZE() -1))
{
ui32BlockBytes =
return IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function FreeBuf
+
+ @Description Free a buffer previously allocated with BM_Alloc() or unwrap
+ one previous wrapped with BM_Wrap().
+ The buffer is identified by the buffer descriptor pBuf
+ returned at allocation. Note the double indirection when
+ passing the buffer.
+
+
+ @Input pBuf - buffer descriptor to free.
+ @Input ui32Flags - flags
+ @Input bFromAllocator - Is this being called by the
+ allocator?
+
+ @Return None.
+
+ *****************************************************************************/
static IMG_VOID
FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
{
(IMG_UINTPTR_T)pBuf, pBuf->DevVAddr.uiAddr,
(IMG_UINTPTR_T)pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr));
-
+ /* record mapping */
pMapping = pBuf->pMapping;
psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
{
-
+ /* Submemhandle is required by exported mappings */
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
-
+ /* user supplied Device Virtual Address */
if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
{
-
+ /* RAM backed allocation */
PVR_DPF ((PVR_DBG_ERROR, "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported"));
}
else
{
-
+ /* free the mocked-up mapping */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
- pBuf->pMapping = IMG_NULL;
+ pBuf->pMapping = IMG_NULL; /*nulling pointer alias*/
}
}
}
else
{
-
+ /* BM supplied Device Virtual Address */
if(pBuf->hOSMemHandle != pMapping->hOSMemHandle)
{
-
+ /* Submemhandle is required by exported mappings */
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
-
OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags);
}
}
if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
{
-
-
+ /* Submemhandle is required by exported mappings */
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
-
-
-
- PVR_ASSERT(pBuf->ui32ExportCount == 0)
- RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE);
+ /*
+ RAM backed allocation
+ Note: currently no need to distinguish between hm_env and hm_contiguous
+ */
+ PVR_ASSERT(pBuf->ui32ExportCount == 0);
+ if (pBuf->pMapping->ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ IMG_UINT32 ui32FreeSize = sizeof(IMG_BOOL) * pBuf->pMapping->ui32NumVirtChunks;
+ IMG_PVOID pvFreePtr = pBuf->pMapping->pabMapChunk;
+
+ /* With sparse allocations we don't go through the sub-alloc RA */
+ BM_FreeMemory(pBuf->pMapping->pBMHeap, pBuf->DevVAddr.uiAddr, pBuf->pMapping);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32FreeSize,
+ pvFreePtr,
+ IMG_NULL);
+ }
+ else
+ {
+ RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE);
+ }
}
}
else
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
-
+ /* free the mocked-up mapping */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
- pBuf->pMapping = IMG_NULL;
+ pBuf->pMapping = IMG_NULL; /*nulling pointer alias*/
}
}
}
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
}
+/*!
+******************************************************************************
+
+ @Function BM_DestroyContext_AnyCb
+
+ @Description Destroy a buffer manager heap.
+
+ @Input psBMHeap
+
+ @Return PVRSRV_ERROR
+
+ *****************************************************************************/
static PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP *psBMHeap)
{
if(psBMHeap->ui32Attribs
}
+/*!
+******************************************************************************
+
+ @Function BM_DestroyContext
+
+ @Description Destroy a buffer manager context. All allocated buffers must be
+ free'd before calling this function. This function is called
+ also to perform cleanup during aborted initialisations so it's
+ fairly careful not to assume any given resource has really been
+ created/allocated.
+
+ @Return PVRSRV_ERROR
+
+ *****************************************************************************/
PVRSRV_ERROR
BM_DestroyContext(IMG_HANDLE hBMContext,
IMG_BOOL *pbDestroyed)
*pbDestroyed = IMG_FALSE;
}
-
-
+ /*
+ Exit straight away if it's an invalid context handle
+ */
if (pBMContext == IMG_NULL)
{
PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle"));
if (pBMContext->ui32RefCount > 0)
{
-
+ /* Just return if there are more references to this context */
return PVRSRV_OK;
}
-
-
-
+ /*
+ Check whether there is a bug in the client which brought it here before
+ all the allocations have been freed.
+ */
eError = List_BM_HEAP_PVRSRV_ERROR_Any(pBMContext->psBMHeap, &BM_DestroyContext_AnyCb);
if(eError != PVRSRV_OK)
{
PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: List_BM_HEAP_PVRSRV_ERROR_Any failed"));
-#if 0
-
-
-
-
- PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Cleaning up with ResManFreeSpecial"));
- if(ResManFreeSpecial() != PVRSRV_OK)
- {
- PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeSpecial failed %d",eError));
- }
-
-#endif
return eError;
}
else
{
-
+ /* free the device memory context */
eError = ResManFreeResByPtr(pBMContext->hResItem, CLEANUP_WITH_POLL);
if(eError != PVRSRV_OK)
{
return eError;
}
-
+ /* mark context as destroyed */
if (pbDestroyed != IMG_NULL)
{
*pbDestroyed = IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function BM_DestroyContextCallBack_AnyVaCb
+
+ @Description Destroy Device memory context
+
+ @Input psBMHeap - heap to be freed.
+ @Input va - list of variable arguments with the following contents:
+ - psDeviceNode
+ @Return PVRSRV_ERROR
+
+ *****************************************************************************/
static PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
{
PVRSRV_DEVICE_NODE *psDeviceNode;
psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
-
+ /* Free up the import arenas */
if(psBMHeap->ui32Attribs
& (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
return PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE;
}
-
+ /* Free up the MMU Heaps */
psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
-
+ /* Free Heap memory */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function BM_DestroyContextCallBack
+
+ @Description Destroy Device memory context
+
+ @Input pvParam - opaque void ptr param
+ @Input ui32Param - opaque unsigned long param
+
+ @Return PVRSRV_ERROR
+
+ *****************************************************************************/
static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam,
IMG_UINT32 ui32Param,
IMG_BOOL bDummy)
BM_CONTEXT *pBMContext = pvParam;
PVRSRV_DEVICE_NODE *psDeviceNode;
PVRSRV_ERROR eError;
+/* BM_CONTEXT **ppBMContext;
+ BM_HEAP *psBMHeap, *psTmpBMHeap;*/
+
PVR_UNREFERENCED_PARAMETER(ui32Param);
PVR_UNREFERENCED_PARAMETER(bDummy);
-
-
+ /*
+ Get DeviceNode from BMcontext
+ */
psDeviceNode = pBMContext->psDeviceNode;
-
-
+ /*
+ Free the import arenas and heaps
+ */
eError = List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap,
&BM_DestroyContextCallBack_AnyVaCb,
psDeviceNode);
{
return eError;
}
-
-
+ /*
+ 'Finalise' the MMU
+ */
if (pBMContext->psMMUContext)
{
psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
}
-
-
+ /*
+ Free up generic, useful resources - if they were allocated.
+ */
if (pBMContext->pBufferHash)
{
HASH_Delete(pBMContext->pBufferHash);
if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext)
{
-
+ /* Freeing the kernel context */
psDeviceNode->sDevMemoryInfo.pBMKernelContext = IMG_NULL;
}
else
{
if (pBMContext->ppsThis != IMG_NULL)
{
-
+ /*
+ * Remove context from the linked list
+ */
List_BM_CONTEXT_Remove(pBMContext);
}
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
hResManContext = va_arg(va, PRESMAN_CONTEXT);
if(ResManFindResourceByPtr(hResManContext, pBMContext->hResItem) == PVRSRV_OK)
{
-
+ /* just increment the refcount and return the memory context found for this process */
pBMContext->ui32RefCount++;
return pBMContext;
}
case DEVICE_MEMORY_HEAP_SHARED:
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
{
-
+ /* insert the heap into the device's MMU page directory/table */
psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext, psBMHeap->pMMUHeap);
break;
}
}
}
+/*!
+******************************************************************************
+
+ @Function BM_CreateContext
+
+ @Description Creates and initialises a buffer manager context. This function must be called
+ before any other buffer manager functions.
+
+ @Return valid BM context handle - Success
+ IMG_NULL - Failed
+
+ *****************************************************************************/
IMG_HANDLE
BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_DEV_PHYADDR *psPDDevPAddr,
IMG_BOOL *pbCreated)
{
BM_CONTEXT *pBMContext;
+/* BM_HEAP *psBMHeap;*/
DEVICE_MEMORY_INFO *psDevMemoryInfo;
IMG_BOOL bKernelContext;
PRESMAN_CONTEXT hResManContext;
*pbCreated = IMG_FALSE;
}
-
+ /* setup the device memory info. */
psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
if (bKernelContext == IMG_FALSE)
}
}
-
+ /* allocate a BM context */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof (struct _BM_CONTEXT_),
(IMG_PVOID *)&pBMContext, IMG_NULL,
}
OSMemSet(pBMContext, 0, sizeof (BM_CONTEXT));
-
+ /* store the associated devicenode */
pBMContext->psDeviceNode = psDeviceNode;
-
-
+ /* This hash table is used to store BM_Wraps in a global way */
+ /* INTEGRATION_POINT: 32 is an abitrary limit on the number of hashed BM_wraps */
pBMContext->pBufferHash = HASH_Create(32);
if (pBMContext->pBufferHash==IMG_NULL)
{
if(bKernelContext)
{
-
+ /* just save the kernel context */
PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == IMG_NULL);
psDevMemoryInfo->pBMKernelContext = pBMContext;
}
else
{
-
-
-
-
-
+ /*
+ On the creation of each new context we must
+ insert the kernel context's 'shared' and 'shared_exported'
+ heaps into the new context
+ - check the kernel context and heaps exist
+ */
PVR_ASSERT(psDevMemoryInfo->pBMKernelContext);
if (psDevMemoryInfo->pBMKernelContext == IMG_NULL)
PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap);
-
-
-
-
+ /*
+ insert the kernel heaps structures into the new context's shared heap list
+ Note. this will include the kernel only heaps but these will not actually
+ be imported into the context nor returned to the client
+ */
pBMContext->psBMSharedHeap = psDevMemoryInfo->pBMKernelContext->psBMHeap;
-
-
-
+ /*
+ insert the shared heaps into the MMU page directory/table
+ for the new context
+ */
List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap,
&BM_CreateContext_InsertHeap_ForEachVaCb,
psDeviceNode,
pBMContext);
-
+ /* Finally, insert the new context into the list of BM contexts */
List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext, pBMContext);
}
-
+ /* Increment the refcount, as creation is successful */
pBMContext->ui32RefCount++;
-
+ /* register with resman */
pBMContext->hResItem = ResManRegisterRes(hResManContext,
RESMAN_TYPE_DEVICEMEM_CONTEXT,
pBMContext,
psDevMemHeapInfo = va_arg(va, DEVICE_MEMORY_HEAP_INFO*);
if (psBMHeap->sDevArena.ui32HeapID == psDevMemHeapInfo->ui32HeapID)
{
-
+ /* Match - just return already created heap */
return psBMHeap;
}
else
}
}
+/*!
+******************************************************************************
+
+ @Function BM_CreateHeap
+
+ @Description Creates and initialises a BM heap for a given BM context.
+
+ @Return
+ valid heap handle - success
+ IMG_NULL - failure
+
+
+ *****************************************************************************/
IMG_HANDLE
BM_CreateHeap (IMG_HANDLE hBMContext,
DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo)
psDeviceNode = pBMContext->psDeviceNode;
-
-
+ /*
+ * Ensure that the heap size is a multiple of the data page size.
+ */
PVR_ASSERT((psDevMemHeapInfo->ui32HeapSize & (psDevMemHeapInfo->ui32DataPageSize - 1)) == 0);
PVR_ASSERT(psDevMemHeapInfo->ui32HeapSize > 0);
-
-
-
-
-
+ /*
+ We may be being asked to create a heap in a context which already has one.
+ Test for refcount > 0 because PVRSRVGetDeviceMemHeapInfoKM doesn't increment the refcount.
+ This does mean that the first call to PVRSRVCreateDeviceMemContextKM will first try to find
+ heaps that we already know don't exist
+ */
if(pBMContext->ui32RefCount > 0)
{
psBMHeap = (BM_HEAP*)List_BM_HEAP_Any_va(pBMContext->psBMHeap,
psBMHeap->sDevArena.ui32DataPageSize = psDevMemHeapInfo->ui32DataPageSize;
psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo;
psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs;
+#if defined(SUPPORT_MEMORY_TILING)
+ psBMHeap->ui32XTileStride = psDevMemHeapInfo->ui32XTileStride;
+#endif
-
+ /* tie the heap to the context */
psBMHeap->pBMContext = pBMContext;
psBMHeap->pMMUHeap = psDeviceNode->pfnMMUCreate (pBMContext->psMMUContext,
goto ErrorExit;
}
-
+ /* memory is allocated from the OS as required */
psBMHeap->pImportArena = RA_Create (psDevMemHeapInfo->pszBSName,
0, 0, IMG_NULL,
MAX(HOST_PAGESIZE(), psBMHeap->sDevArena.ui32DataPageSize),
if(psBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
{
-
-
-
-
+ /*
+ memory comes from a device memory contiguous allocator (ra)
+ Note: these arenas are shared across the system so don't delete
+ as part of heap destroy
+ */
psBMHeap->pLocalDevMemArena = psDevMemHeapInfo->psLocalDevMemArena;
if(psBMHeap->pLocalDevMemArena == IMG_NULL)
{
}
}
-
+ /* insert heap into head of the heap list */
List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap);
return (IMG_HANDLE)psBMHeap;
-
+ /* handle error case */
ErrorExit:
-
+ /* Free up the MMU if we created one */
if (psBMHeap->pMMUHeap != IMG_NULL)
{
psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
-
+ /* don't finalise psMMUContext as we don't own it */
}
-
+ /* Free the Heap memory */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return IMG_NULL;
}
+/*!
+******************************************************************************
+
+ @Function BM_DestroyHeap
+
+ @Description Destroys a BM heap
+
+ @Return
+ valid heap handle - success
+ IMG_NULL - failure
+
+
+ *****************************************************************************/
IMG_VOID
BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
{
if(psBMHeap)
{
-
+ /* Free up the import arenas */
if(psBMHeap->ui32Attribs
& (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
return;
}
-
+ /* Free up the MMU Heap */
psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
-
+ /* remove from the heap list */
List_BM_HEAP_Remove(psBMHeap);
-
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
-
}
else
{
}
+/*!
+******************************************************************************
+
+ @Function BM_Reinitialise
+
+ @Description Reinitialise the buffer manager after a power down event.
+
+ @Return IMG_TRUE - Success
+ IMG_FALSE - Failed
+
+ *****************************************************************************/
IMG_BOOL
BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise"));
PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+ /* FIXME: Need to reenable all contexts
+ List_BM_CONTEXT_ForEach(psDeviceNode->sDevMemoryInfo.pBMContext, MMU_Enable);
+ */
return IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function BM_Alloc
+
+ @Description Allocate a buffer mapped into both cpu and device virtual
+ memory maps.
+
+ @Input hDevMemHeap
+ @Input psDevVAddr - device virtual address specified by caller (optional)
+ @Input uSize - require size in bytes of the buffer.
+ @Input pui32Flags - bit mask of buffer property flags.
+ @Input uDevVAddrAlignment - required alignment in bytes, or 0.
+ @Input pvPrivData - opaque private data passed through to allocator
+ @Input ui32PrivDataLength - length of opaque private data
+
+ @Output phBuf - receives buffer handle
+ @Output pui32Flags - bit mask of heap property flags.
+
+ @Return IMG_TRUE - Success
+ IMG_FALSE - Failure
+
+ *****************************************************************************/
IMG_BOOL
BM_Alloc ( IMG_HANDLE hDevMemHeap,
IMG_DEV_VIRTADDR *psDevVAddr,
IMG_SIZE_T uSize,
IMG_UINT32 *pui32Flags,
IMG_UINT32 uDevVAddrAlignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
BM_HANDLE *phBuf)
{
BM_BUF *pBuf;
uDevVAddrAlignment = 1;
}
-
+ /*
+ * Allocate something in which to record the allocation's details.
+ */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof (BM_BUF),
(IMG_PVOID *)&pBuf, IMG_NULL,
}
OSMemSet(pBuf, 0, sizeof (BM_BUF));
-
+ /*
+ * Allocate the memory itself now.
+ */
if (AllocMemory(pBMContext,
psBMHeap,
psDevVAddr,
uSize,
uFlags,
uDevVAddrAlignment,
+ pvPrivData,
+ ui32PrivDataLength,
+ ui32ChunkSize,
+ ui32NumVirtChunks,
+ ui32NumPhysChunks,
+ pabMapChunk,
pBuf) != IMG_TRUE)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
-
+ /* not nulling pointer, out of scope */
PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED"));
return IMG_FALSE;
}
"BM_Alloc (uSize=0x%x, uFlags=0x%x)",
uSize, uFlags));
-
+ /*
+ * Assign the handle and return.
+ */
pBuf->ui32RefCount = 1;
*phBuf = (BM_HANDLE)pBuf;
*pui32Flags = uFlags | psBMHeap->ui32Attribs;
-
+ /*
+ * If the user has specified heap CACHETYPE flags themselves,
+ * override any CACHETYPE flags inherited from the heap.
+ */
if(uFlags & PVRSRV_HAP_CACHETYPE_MASK)
{
*pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK;
#if defined(PVR_LMA)
+/*!
+******************************************************************************
+
+ @Function ValidSysPAddrArrayForDev
+
+ @Description Verify the array of system address is accessible
+ by the given device.
+
+ @Input psDeviceNode
+ @Input psSysPAddr - system address array
+ @Input ui32PageSize - size of address array
+
+ @Return IMG_BOOL
+
+ *****************************************************************************/
static IMG_BOOL
ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR *psSysPAddr, IMG_UINT32 ui32PageCount, IMG_SIZE_T ui32PageSize)
{
return IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function ValidSysPAddrRangeForDev
+
+ @Description Verify a system address range is accessible
+ by the given device.
+
+ @Input psDeviceNode
+ @Input sStartSysPAddr - starting system address
+ @Input ui32Range - length of address range
+
+ @Return IMG_BOOL
+
+ *****************************************************************************/
static IMG_BOOL
ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR sStartSysPAddr, IMG_SIZE_T ui32Range)
{
#endif
+/*!
+******************************************************************************
+
+ @Function BM_Wrap
+
+ @Description Create a buffer which wraps user provided system physical
+ memory.
+ The wrapped memory must be page aligned. BM_Wrap will
+ roundup the size to a multiple of cpu pages.
+
+ @Input ui32Size - size of memory to wrap.
+ @Input ui32Offset - Offset into page of memory to wrap.
+ @Input bPhysContig - Is the wrap physically contiguous.
+ @Input psSysAddr - list of system physical page addresses of memory to wrap.
+ @Input pvCPUVAddr - optional CPU kernel virtual address (Page aligned) of memory to wrap.
+ @Input uFlags - bit mask of buffer property flags.
+ @output phBuf - receives the buffer handle.
+
+ @Return IMG_TRUE - Success.
+ IMG_FALSE - Failed
+
+ *****************************************************************************/
IMG_BOOL
BM_Wrap ( IMG_HANDLE hDevMemHeap,
IMG_SIZE_T ui32Size,
}
}
#endif
-
+ /*
+ * Insert the System Physical Address of the first page into the hash so we can optimise multiple wraps of the
+ * same memory.
+ */
sHashAddress = psSysAddr[0];
-
+ /* Add the in-page offset to ensure a unique hash */
sHashAddress.uiAddr += ui32Offset;
-
+ /* See if this address has already been wrapped */
pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, sHashAddress.uiAddr);
if(pBuf)
{
IMG_SIZE_T ui32MappingSize = HOST_PAGEALIGN (ui32Size + ui32Offset);
-
+ /* Check base address, size and contiguity type match */
if(pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped ||
pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr))
{
"BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)",
ui32Size, ui32Offset, sHashAddress.uiAddr));
- pBuf->ui32RefCount++;
+ PVRSRVBMBufIncRef(pBuf);
*phBuf = (BM_HANDLE)pBuf;
if(pui32Flags)
*pui32Flags = uFlags;
}
else
{
-
+ /* Otherwise removed that item from the hash table
+ (a workaround for buffer device class) */
HASH_Remove(psBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddress.uiAddr);
}
}
-
+ /*
+ * Allocate something in which to record the allocation's details.
+ */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof (BM_BUF),
(IMG_PVOID *)&pBuf, IMG_NULL,
}
OSMemSet(pBuf, 0, sizeof (BM_BUF));
-
+ /*
+ * Actually perform the memory wrap.
+ */
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);
-
+ /*not nulling pointer, out of scope*/
return IMG_FALSE;
}
-
+ /* Only insert the buffer in the hash table if it is contiguous - allows for optimisation of multiple wraps
+ * of the same contiguous buffer.
+ */
if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
{
-
+ /* Have we calculated the right Hash key ? */
PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr);
if (!HASH_Insert (psBMContext->pBufferHash, sHashAddress.uiAddr, (IMG_UINTPTR_T)pBuf))
"BM_Wrap (uSize=0x%x, uFlags=0x%x, devVAddr=%08X)",
ui32Size, uFlags, pBuf->DevVAddr.uiAddr));
-
+ /*
+ * Assign the handle and return.
+ */
pBuf->ui32RefCount = 1;
*phBuf = (BM_HANDLE)pBuf;
if(pui32Flags)
{
-
+ /* need to override the heap attributes SINGLE PROC to MULT_PROC. */
*pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS;
}
return IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function BM_Export
+
+ @Description Export a buffer previously allocated via BM_Alloc.
+
+ @Input hBuf - buffer handle.
+ @Input ui32Flags - flags
+
+ @Return None.
+
+ *****************************************************************************/
+
IMG_VOID
BM_Export (BM_HANDLE hBuf)
{
BM_BUF *pBuf = (BM_BUF *)hBuf;
- pBuf->ui32ExportCount++;
+ PVRSRVBMBufIncExport(pBuf);
}
+/*!
+******************************************************************************
+ @Function BM_Export
+
+ @Description Export a buffer previously allocated via BM_Alloc.
+
+ @Input hBuf - buffer handle.
+
+ @Return None.
+**************************************************************************/
IMG_VOID
BM_FreeExport(BM_HANDLE hBuf,
IMG_UINT32 ui32Flags)
{
BM_BUF *pBuf = (BM_BUF *)hBuf;
- pBuf->ui32ExportCount--;
+ PVRSRVBMBufDecExport(pBuf);
FreeBuf (pBuf, ui32Flags, IMG_FALSE);
}
+/*!
+******************************************************************************
+ @Function BM_FreeExport
+
+ @Description Free a buffer previously exported via BM_Export.
+
+ @Input hBuf - buffer handle.
+ @Input ui32Flags - flags
+
+ @Return None.
+**************************************************************************/
IMG_VOID
BM_Free (BM_HANDLE hBuf,
IMG_UINT32 ui32Flags)
SysAcquireData(&psSysData);
- pBuf->ui32RefCount--;
-
+ PVRSRVBMBufDecRef(pBuf);
if(pBuf->ui32RefCount == 0)
{
if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
}
+/*!
+******************************************************************************
+
+ @Function BM_HandleToCpuVaddr
+
+ @Description Retreive the cpu virtual address associated with a buffer.
+
+ @Input buffer handle.
+
+ @Return buffers cpu virtual address, or NULL if none exists
+
+ *****************************************************************************/
IMG_CPU_VIRTADDR
BM_HandleToCpuVaddr (BM_HANDLE hBuf)
{
}
+/*!
+******************************************************************************
+
+ @Function BM_HandleToDevVaddr
+
+ @Description Retreive the device virtual address associated with a buffer.
+
+ @Input hBuf - buffer handle.
+
+ @Return buffers device virtual address.
+
+ *****************************************************************************/
IMG_DEV_VIRTADDR
BM_HandleToDevVaddr (BM_HANDLE hBuf)
{
}
+/*!
+******************************************************************************
+
+ @Function BM_HandleToSysPaddr
+
+ @Description Retreive the system physical address associated with a buffer.
+
+ @Input hBuf - buffer handle.
+
+ @Return buffers device virtual address.
+
+ *****************************************************************************/
IMG_SYS_PHYADDR
BM_HandleToSysPaddr (BM_HANDLE hBuf)
{
return SysCpuPAddrToSysPAddr (pBuf->CpuPAddr);
}
+/*!
+******************************************************************************
+
+ @Function BM_HandleToMemOSHandle
+
+ @Description Retreive the underlying memory handle associated with a buffer.
+
+ @Input hBuf - buffer handle.
+
+ @Return OS Specific memory handle.
+
+ *****************************************************************************/
IMG_HANDLE
BM_HandleToOSMemHandle(BM_HANDLE hBuf)
{
return pBuf->hOSMemHandle;
}
+/*!
+******************************************************************************
+
+ @Function DevMemoryAlloc
+
+ @Description Allocate device memory for a given physical/virtual memory
+ mapping. We handle the main cases where device MMU mappings
+ are required - these are the dynamic cases: all wrappings of
+ host OS memory and host OS imports for SYS_MMU_NORMAL mode.
+
+ If no MMU support is required then we simply map device virtual
+ space as device physical space.
+
+ @Input pBMContext - the pager to allocate from.
+ @Output pMapping - the mapping descriptor to be filled in for this
+ allocation.
+ @Output pActualSize - the actual size of the block allocated in
+ bytes.
+ @Input uFlags - allocation flags
+ @Input dev_vaddr_alignment - required device virtual address
+ alignment, or 0.
+ @Output pDevVAddr - receives the device virtual base address of the
+ allocated block.
+ @Return IMG_TRUE - Success
+ IMG_FALSE - Failed.
+
+ *****************************************************************************/
static IMG_BOOL
DevMemoryAlloc (BM_CONTEXT *pBMContext,
BM_MAPPING *pMapping,
if(uFlags & PVRSRV_MEM_INTERLEAVED)
{
-
+ /* double the size */
pMapping->uSize *= 2;
}
#ifdef PDUMP
if(uFlags & PVRSRV_MEM_DUMMY)
{
-
+ /* only one page behind a dummy allocation */
ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
}
#endif
-
+ /* Check we haven't fall through a gap */
+ PVR_ASSERT(pMapping->uSizeVM != 0);
+ /* allocate device linear space */
if (!psDeviceNode->pfnMMUAlloc (pMapping->pBMHeap->pMMUHeap,
- pMapping->uSize,
+ pMapping->uSizeVM,
pActualSize,
0,
dev_vaddr_alignment,
#endif
#if defined(PDUMP)
-
+ /* pdump the memory allocate */
PDUMPMALLOCPAGES(&psDeviceNode->sDevId,
pMapping->DevVAddr.uiAddr,
pMapping->CpuVAddr,
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
psDeviceNode->pfnMMUIsHeapShared(pMapping->pBMHeap->pMMUHeap),
#else
- IMG_FALSE,
-#endif
+ IMG_FALSE, // unused
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
(IMG_HANDLE)pMapping);
#endif
case hm_wrapped_virtaddr:
case hm_contiguous:
{
- psDeviceNode->pfnMMUMapPages ( pMapping->pBMHeap->pMMUHeap,
- pMapping->DevVAddr,
- SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
- pMapping->uSize,
- uFlags,
- (IMG_HANDLE)pMapping);
-
+ if (uFlags & PVRSRV_MEM_SPARSE)
+ {
+ /* Check if this device supports sparse mappings */
+ PVR_ASSERT(psDeviceNode->pfnMMUMapPagesSparse != IMG_NULL);
+ psDeviceNode->pfnMMUMapPagesSparse(pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
+ pMapping->ui32ChunkSize,
+ pMapping->ui32NumVirtChunks,
+ pMapping->ui32NumPhysChunks,
+ pMapping->pabMapChunk,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+ }
+ else
+ {
+ 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);
+ if (uFlags & PVRSRV_MEM_SPARSE)
+ {
+ /* Check if this device supports sparse mappings */
+ PVR_ASSERT(psDeviceNode->pfnMMUMapShadowSparse != IMG_NULL);
+ psDeviceNode->pfnMMUMapShadowSparse(pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->ui32ChunkSize,
+ pMapping->ui32NumVirtChunks,
+ pMapping->ui32NumPhysChunks,
+ pMapping->pabMapChunk,
+ pMapping->CpuVAddr,
+ pMapping->hOSMemHandle,
+ pDevVAddr,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+ }
+ else
+ {
+ psDeviceNode->pfnMMUMapShadow ( pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->uSize,
+ pMapping->CpuVAddr,
+ pMapping->hOSMemHandle,
+ pDevVAddr,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+ }
break;
}
case hm_wrapped_scatter:
if (sDevPAddr.uiAddr != 0)
{
#ifdef PDUMP
-
+ /* pdump the memory free */
if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
{
-
+ /* physical memory size differs in the case of Dummy allocations */
ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
}
else
ui32PSize,
pMapping->pBMHeap->sDevArena.ui32DataPageSize,
(IMG_HANDLE)pMapping,
- (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE);
+ (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE,
+ (pMapping->ui32Flags & PVRSRV_MEM_SPARSE) ? IMG_TRUE : IMG_FALSE);
#endif
}
- psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize));
+ PVR_ASSERT(pMapping->uSizeVM != 0);
+ psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSizeVM));
}
+/* If this array grows larger, it might be preferable to use a hashtable rather than an array. */
#ifndef XPROC_WORKAROUND_NUM_SHAREABLES
#define XPROC_WORKAROUND_NUM_SHAREABLES 200
#endif
#define XPROC_WORKAROUND_BAD_SHAREINDEX 0773407734
+#define XPROC_WORKAROUND_UNKNOWN 0
+#define XPROC_WORKAROUND_ALLOC 1
+#define XPROC_WORKAROUND_MAP 2
+
static IMG_UINT32 gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX;
+static IMG_UINT32 gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN;
-
-static struct {
- IMG_UINT32 ui32RefCount;
- IMG_UINT32 ui32AllocFlags;
- IMG_UINT32 ui32Size;
- IMG_UINT32 ui32PageSize;
- RA_ARENA *psArena;
- IMG_SYS_PHYADDR sSysPAddr;
- IMG_VOID *pvCpuVAddr;
- IMG_HANDLE hOSMemHandle;
-} gXProcWorkaroundShareData[XPROC_WORKAROUND_NUM_SHAREABLES] = {{0}};
+/* PRQA S 0686 10 */ /* force compiler to init structure */
+XPROC_DATA gXProcWorkaroundShareData[XPROC_WORKAROUND_NUM_SHAREABLES] = {{0}};
PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index)
{
-
-
-
+ /* if you fail this assertion - did you acquire the mutex?
+ did you call "set" exactly once?
+ did you call "unset" exactly once per set?
+ */
if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX)
{
PVR_DPF((PVR_DBG_ERROR, "No, it's already set!"));
}
gXProcWorkaroundShareIndex = ui32Index;
+ gXProcWorkaroundState = XPROC_WORKAROUND_MAP;
return PVRSRV_OK;
}
PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index)
{
-
-
-
+ /* if you fail this assertion - did you acquire the mutex?
+ did you call "set" exactly once?
+ did you call "unset" exactly once per set?
+ */
if (gXProcWorkaroundShareIndex == XPROC_WORKAROUND_BAD_SHAREINDEX)
{
PVR_DPF((PVR_DBG_ERROR, "huh? how can it be bad??"));
}
gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX;
+ gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN;
return PVRSRV_OK;
}
PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32Index)
{
-
-
-
+ /* if you fail this assertion - did you acquire the mutex?
+ did you call "set" exactly once?
+ did you call "unset" exactly once per set?
+ */
if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX)
{
return PVRSRV_ERROR_INVALID_PARAMS;
if (gXProcWorkaroundShareData[*pui32Index].ui32RefCount == 0)
{
gXProcWorkaroundShareIndex = *pui32Index;
+ gXProcWorkaroundState = XPROC_WORKAROUND_ALLOC;
return PVRSRV_OK;
}
}
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-IMG_UINT32 BM_XProcWorkaroundGetRefCount(IMG_UINT32 ui32Index)
-{
- return gXProcWorkaroundShareData[ui32Index].ui32RefCount;
-}
-
static PVRSRV_ERROR
XProcWorkaroundAllocShareable(RA_ARENA *psArena,
IMG_UINT32 ui32AllocFlags,
IMG_UINT32 ui32Size,
IMG_UINT32 ui32PageSize,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_VOID **ppvCpuVAddr,
IMG_HANDLE *phOSMemHandle)
{
*ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr;
*phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle;
- gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount ++;
+ BM_XProcIndexAcquire(gXProcWorkaroundShareIndex);
return PVRSRV_OK;
}
else
{
+ if (gXProcWorkaroundState != XPROC_WORKAROUND_ALLOC)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "XPROC workaround in bad state! About to allocate memory from non-alloc state! (%d)",
+ gXProcWorkaroundState));
+ }
+ PVR_ASSERT(gXProcWorkaroundState == XPROC_WORKAROUND_ALLOC);
+
if (psArena != IMG_NULL)
{
IMG_CPU_PHYADDR sCpuPAddr;
0,
ui32PageSize,
0,
+ pvPrivData,
+ ui32PrivDataLength,
(IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
{
PVR_DPF((PVR_DBG_ERROR, "XProcWorkaroundAllocShareable: RA_Alloc(0x%x) FAILED", ui32Size));
if(OSReservePhys(sCpuPAddr,
ui32Size,
ui32AllocFlags,
+ IMG_NULL,
(IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr,
&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK)
{
ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK;
ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS;
-
+ /* allocate pages from the OS RAM */
if (OSAllocPages(ui32AllocFlags,
ui32Size,
ui32PageSize,
+ pvPrivData,
+ ui32PrivDataLength,
+ IMG_NULL, /* FIXME: to support cross process sparse allocations */
(IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr,
&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK)
{
*ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr;
*phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle;
- gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount ++;
+ BM_XProcIndexAcquire(gXProcWorkaroundShareIndex);
return PVRSRV_OK;
}
static PVRSRV_ERROR XProcWorkaroundHandleToSI(IMG_HANDLE hOSMemHandle, IMG_UINT32 *pui32SI)
{
-
IMG_UINT32 ui32SI;
IMG_BOOL bFound;
IMG_BOOL bErrorDups;
return PVRSRV_OK;
}
-static IMG_VOID XProcWorkaroundFreeShareable(IMG_HANDLE hOSMemHandle)
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexAcquireDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+#else
+IMG_VOID _BM_XProcIndexAcquire(IMG_UINT32 ui32Index)
+#endif
{
- IMG_UINT32 ui32SI = (IMG_UINT32)((IMG_UINTPTR_T)hOSMemHandle & 0xffffU);
- PVRSRV_ERROR eError;
-
- eError = XProcWorkaroundHandleToSI(hOSMemHandle, &ui32SI);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "bad handle"));
- return;
- }
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+ PVRSRVBMXProcIncRef2(pszFile, iLine, ui32Index);
+#else
+ PVRSRVBMXProcIncRef(ui32Index);
+#endif
+}
- gXProcWorkaroundShareData[ui32SI].ui32RefCount --;
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexReleaseDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+#else
+IMG_VOID _BM_XProcIndexRelease(IMG_UINT32 ui32Index)
+#endif
+{
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+ PVRSRVBMXProcDecRef2(pszFile, iLine, ui32Index);
+#else
+ PVRSRVBMXProcDecRef(ui32Index);
+#endif
PVR_DPF((PVR_DBG_VERBOSE, "Reduced refcount of SI[%d] from %d to %d",
- ui32SI, gXProcWorkaroundShareData[ui32SI].ui32RefCount+1, gXProcWorkaroundShareData[ui32SI].ui32RefCount));
+ ui32Index, gXProcWorkaroundShareData[ui32Index].ui32RefCount+1, gXProcWorkaroundShareData[ui32Index].ui32RefCount));
- if (gXProcWorkaroundShareData[ui32SI].ui32RefCount == 0)
+ if (gXProcWorkaroundShareData[ui32Index].ui32RefCount == 0)
{
- if (gXProcWorkaroundShareData[ui32SI].psArena != IMG_NULL)
+ if (gXProcWorkaroundShareData[ui32Index].psArena != IMG_NULL)
{
IMG_SYS_PHYADDR sSysPAddr;
- if (gXProcWorkaroundShareData[ui32SI].pvCpuVAddr != IMG_NULL)
+ if (gXProcWorkaroundShareData[ui32Index].pvCpuVAddr != IMG_NULL)
{
- OSUnReservePhys(gXProcWorkaroundShareData[ui32SI].pvCpuVAddr,
- gXProcWorkaroundShareData[ui32SI].ui32Size,
- gXProcWorkaroundShareData[ui32SI].ui32AllocFlags,
- gXProcWorkaroundShareData[ui32SI].hOSMemHandle);
+ OSUnReservePhys(gXProcWorkaroundShareData[ui32Index].pvCpuVAddr,
+ gXProcWorkaroundShareData[ui32Index].ui32Size,
+ gXProcWorkaroundShareData[ui32Index].ui32AllocFlags,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle);
}
- sSysPAddr = gXProcWorkaroundShareData[ui32SI].sSysPAddr;
- RA_Free (gXProcWorkaroundShareData[ui32SI].psArena,
+ sSysPAddr = gXProcWorkaroundShareData[ui32Index].sSysPAddr;
+ RA_Free (gXProcWorkaroundShareData[ui32Index].psArena,
sSysPAddr.uiAddr,
IMG_FALSE);
}
else
{
PVR_DPF((PVR_DBG_VERBOSE, "freeing OS memory"));
- OSFreePages(gXProcWorkaroundShareData[ui32SI].ui32AllocFlags,
- gXProcWorkaroundShareData[ui32SI].ui32PageSize,
- gXProcWorkaroundShareData[ui32SI].pvCpuVAddr,
- gXProcWorkaroundShareData[ui32SI].hOSMemHandle);
+ OSFreePages(gXProcWorkaroundShareData[ui32Index].ui32AllocFlags,
+ gXProcWorkaroundShareData[ui32Index].ui32PageSize,
+ gXProcWorkaroundShareData[ui32Index].pvCpuVAddr,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle);
}
}
}
+static IMG_VOID XProcWorkaroundFreeShareable(IMG_HANDLE hOSMemHandle)
+{
+ IMG_UINT32 ui32SI = (IMG_UINT32)((IMG_UINTPTR_T)hOSMemHandle & 0xffffU);
+ PVRSRV_ERROR eError;
+ eError = XProcWorkaroundHandleToSI(hOSMemHandle, &ui32SI);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "bad handle"));
+ return;
+ }
+
+ BM_XProcIndexRelease(ui32SI);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function BM_ImportMemory
+
+ @Description Provide a resource allocator with a source of pages of memory
+ from the Host OS's own allocation. Allocates a block of pages
+ larger than requested, allowing the resource allocator to
+ operate a small cache of pre allocated pages.
+
+ @Input pH - buffer manager handle, not the void type is dictated
+ by the generic nature of the resource allocator interface.
+ @Input uRequestSize - requested size in bytes
+ @Output pActualSize - receives the actual size allocated in bytes
+ which may be >= requested size
+ @Output ppsMapping - receives the arbitrary user reference
+ associated with the underlying storage.
+ @Input uFlags - bit mask of allocation flags
+ @Input pvPrivData - opaque private data passed through to allocator
+ @Input ui32PrivDataLength - length of opaque private data
+ @Output pBase - receives a pointer to the allocated storage.
+
+ @Return IMG_TRUE - success
+ IMG_FALSE - failed
+
+ *****************************************************************************/
static IMG_BOOL
BM_ImportMemory (IMG_VOID *pH,
IMG_SIZE_T uRequestSize,
IMG_SIZE_T *pActualSize,
BM_MAPPING **ppsMapping,
IMG_UINT32 uFlags,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_UINTPTR_T *pBase)
{
BM_MAPPING *pMapping;
IMG_BOOL bResult;
IMG_SIZE_T uSize;
IMG_SIZE_T uPSize;
- IMG_SIZE_T uDevVAddrAlignment = 0;
+ IMG_SIZE_T uDevVAddrAlignment = 0; /* ? */
PVR_DPF ((PVR_DBG_MESSAGE,
"BM_ImportMemory (pBMContext=0x%x, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)",
pMapping->DevVAddr.uiAddr = 0;
pMapping->CpuPAddr.uiAddr = 0;
pMapping->uSize = uSize;
+ if ((uFlags & PVRSRV_MEM_SPARSE) == 0)
+ {
+ pMapping->uSizeVM = uSize;
+ }
pMapping->pBMHeap = pBMHeap;
pMapping->ui32Flags = uFlags;
-
+ /*
+ * If anyone want's to know, pass back the actual size of our allocation.
+ * There could be up to an extra page's worth of memory which will be marked
+ * as free in the RA.
+ */
if (pActualSize)
{
*pActualSize = uSize;
}
-
+ /* if it's a dummy allocation only use one physical page */
if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
{
uPSize = pBMHeap->sDevArena.ui32DataPageSize;
IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs | PVRSRV_MEM_XPROC;
IMG_BOOL bBadBackingStoreType;
- bBadBackingStoreType = IMG_TRUE;
+ if(uFlags & PVRSRV_MEM_ION)
+ {
+ ui32Attribs |= PVRSRV_MEM_ION;
+ }
+
+ bBadBackingStoreType = IMG_TRUE;
- if ((ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) != 0)
+ if ((ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) != 0)
{
-#ifndef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
uDevVAddrAlignment = MAX(pBMHeap->sDevArena.ui32DataPageSize, HOST_PAGESIZE());
PVR_DPF((PVR_DBG_ERROR, "Cannot use use this memory sharing workaround with allocations that might be suballocated"));
goto fail_mapping_alloc;
}
- uDevVAddrAlignment = 0;
+ uDevVAddrAlignment = 0; /* FIXME: find out why it doesn't work if alignment is specified */
-
+ /* If the user has specified heap CACHETYPE flags, use them to
+ * override the flags inherited from the heap.
+ */
if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
{
ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
}
-
+ /* allocate "shared" pages. */
if (XProcWorkaroundAllocShareable(IMG_NULL,
ui32Attribs,
- (IMG_UINT32)uPSize,
+ (IMG_UINT32)uPSize,
pBMHeap->sDevArena.ui32DataPageSize,
+ pvPrivData,
+ ui32PrivDataLength,
(IMG_VOID **)&pMapping->CpuVAddr,
&pMapping->hOSMemHandle) != PVRSRV_OK)
{
goto fail_mapping_alloc;
}
-
-
-
+ /* specify how page addresses are derived */
+ /* it works just like "env" now - no need to record
+ it as shareable, as we use the actual hOSMemHandle
+ and only divert to our wrapper layer based on Attribs */
pMapping->eCpuMemoryOrigin = hm_env;
- bBadBackingStoreType = IMG_FALSE;
+ bBadBackingStoreType = IMG_FALSE;
}
- if ((ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) != 0)
+ if ((ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) != 0)
{
- uDevVAddrAlignment = pBMHeap->sDevArena.ui32DataPageSize;
+ uDevVAddrAlignment = pBMHeap->sDevArena.ui32DataPageSize;
if (uPSize % uDevVAddrAlignment != 0)
{
PVR_DPF((PVR_DBG_ERROR, "Cannot use use this memory sharing workaround with allocations that might be suballocated"));
goto fail_mapping_alloc;
}
- uDevVAddrAlignment = 0;
+ uDevVAddrAlignment = 0; /* FIXME: find out why it doesn't work if alignment is specified */
-
+ /* If the user has specified heap CACHETYPE flags, use them to
+ * override the flags inherited from the heap.
+ */
if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
{
ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
}
-
+ /* allocate "shared" pages. */
if (XProcWorkaroundAllocShareable(pBMHeap->pLocalDevMemArena,
ui32Attribs,
(IMG_UINT32)uPSize,
pBMHeap->sDevArena.ui32DataPageSize,
+ pvPrivData,
+ ui32PrivDataLength,
(IMG_VOID **)&pMapping->CpuVAddr,
&pMapping->hOSMemHandle) != PVRSRV_OK)
{
goto fail_mapping_alloc;
}
-
-
-
+ /* specify how page addresses are derived */
+ /* it works just like "env" now - no need to record
+ it as shareable, as we use the actual hOSMemHandle
+ and only divert to our wrapper layer based on Attribs */
pMapping->eCpuMemoryOrigin = hm_env;
bBadBackingStoreType = IMG_FALSE;
}
}
else
-
-
+ /*
+ What type of backing store do we have?
+ */
if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
{
IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
-
+ /* The allocation code needs to know this is a sparse mapping */
+ if (pMapping->ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ ui32Attribs |= PVRSRV_MEM_SPARSE;
+ }
+
+ /* If the user has specified heap CACHETYPE flags, use them to
+ * override the flags inherited from the heap.
+ */
if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
{
ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
}
-
+ if (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM)
+ {
+ ui32Attribs &= ~PVRSRV_MEM_ALLOCATENONCACHEDMEM;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM);
+ }
+
+ /* allocate pages from the OS RAM */
if (OSAllocPages(ui32Attribs,
uPSize,
pBMHeap->sDevArena.ui32DataPageSize,
+ pvPrivData,
+ ui32PrivDataLength,
+ pMapping,
(IMG_VOID **)&pMapping->CpuVAddr,
&pMapping->hOSMemHandle) != PVRSRV_OK)
{
goto fail_mapping_alloc;
}
-
+ /* specify how page addresses are derived */
pMapping->eCpuMemoryOrigin = hm_env;
}
else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
IMG_SYS_PHYADDR sSysPAddr;
IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
-
+ /* The allocation code needs to know this is a sparse mapping */
+ if (pMapping->ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ ui32Attribs |= PVRSRV_MEM_SPARSE;
+ }
+
+ /* allocate pages from the local device memory allocator */
PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL);
-
+ /* If the user has specified heap CACHETYPE flags, use them to
+ * override the flags inherited from the heap.
+ */
if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
{
ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
0,
pBMHeap->sDevArena.ui32DataPageSize,
0,
+ pvPrivData,
+ ui32PrivDataLength,
(IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
{
PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: RA_Alloc(0x%x) FAILED", uPSize));
goto fail_mapping_alloc;
}
-
+ /* derive the CPU virtual address */
pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
if(OSReservePhys(pMapping->CpuPAddr,
uPSize,
ui32Attribs,
+ pMapping,
&pMapping->CpuVAddr,
&pMapping->hOSMemHandle) != PVRSRV_OK)
{
goto fail_dev_mem_alloc;
}
-
+ /* specify how page addresses are derived */
pMapping->eCpuMemoryOrigin = hm_contiguous;
}
else
goto fail_mapping_alloc;
}
-
- bResult = DevMemoryAlloc (pBMContext,
- pMapping,
- IMG_NULL,
- uFlags,
- (IMG_UINT32)uDevVAddrAlignment,
- &pMapping->DevVAddr);
- if (!bResult)
+ /*
+ * Allocate some device memory for what we just allocated.
+ */
+ if ((uFlags & PVRSRV_MEM_SPARSE) == 0)
{
- PVR_DPF((PVR_DBG_ERROR,
- "BM_ImportMemory: DevMemoryAlloc(0x%x) failed",
- pMapping->uSize));
- goto fail_dev_mem_alloc;
- }
-
-
+ bResult = DevMemoryAlloc (pBMContext,
+ pMapping,
+ IMG_NULL,
+ uFlags,
+ (IMG_UINT32)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);
+ /* uDevVAddrAlignment is currently set to zero so QAC generates warning which we override */
+ /* PRQA S 3356,3358 1 */
+ PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+ PVR_ASSERT(pBase);
+ *pBase = pMapping->DevVAddr.uiAddr;
+ }
- *pBase = pMapping->DevVAddr.uiAddr;
*ppsMapping = pMapping;
PVR_DPF ((PVR_DBG_MESSAGE, "BM_ImportMemory: IMG_TRUE"));
fail_dev_mem_alloc:
if (pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
{
-
+ /* the size is double the actual size for interleaved allocations */
if(pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED)
{
pMapping->uSize /= 2;
}
fail_mapping_alloc:
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
fail_exit:
return IMG_FALSE;
}
+/*!
+******************************************************************************
+
+ @Function BM_FreeMemory
+
+ @Description Free a block of pages previously allocated via
+ BM_ImportMemory.
+
+ @Input h - buffer manager handle, not the void type as dictated by
+ the generic nature of the resource allocator interface.
+ @Input _base - base address of blocks to free.
+ @Input psMapping - arbitrary user reference associated with the
+ underlying storage provided by BM_ImportMemory
+ @Return None
+
+ *****************************************************************************/
static IMG_VOID
BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
{
return;
}
- DevMemoryFree (psMapping);
+ /*
+ Only free the virtual memory if we got as far a allocating it.
+ This NULL check should be safe as we always have a guard page
+ at virtual address 0x00000000
+ */
+ if (psMapping->DevVAddr.uiAddr)
+ {
+ DevMemoryFree (psMapping);
+ }
-
+ /* the size is double the actual for interleaved */
if((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0)
{
psMapping->uSize /= 2;
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), psMapping, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
PVR_DPF((PVR_DBG_MESSAGE,
"..BM_FreeMemory (h=0x%x, base=0x%x)",
(IMG_UINTPTR_T)h, _base));
}
+/*!
+******************************************************************************
+
+ @Function BM_GetPhysPageAddr
+
+ @Description
+
+ @Input psMemInfo
+
+ @Input sDevVPageAddr
+
+ @Output psDevPAddr
+
+ @Return IMG_VOID
+
+******************************************************************************/
+
IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
IMG_DEV_VIRTADDR sDevVPageAddr,
IMG_DEV_PHYADDR *psDevPAddr)
PVR_DPF((PVR_DBG_MESSAGE, "BM_GetPhysPageAddr"));
- PVR_ASSERT (psMemInfo && psDevPAddr)
+ PVR_ASSERT(psMemInfo && psDevPAddr);
-
+ /* check it's a page address */
PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
-
+ /* PRQA S 0505 4 */ /* PVR_ASSERT should catch NULL ptrs */
psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode;
*psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap,
}
+/*!
+******************************************************************************
+ @Function BM_GetMMUContext
+
+ @Description utility function to return the MMU context
+
+ @Input hDevMemHeap - the Dev mem heap handle
+
+ @Return MMU context, else NULL
+**************************************************************************/
MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap)
{
BM_HEAP *pBMHeap = (BM_HEAP*)hDevMemHeap;
return pBMHeap->pBMContext->psMMUContext;
}
+/*!
+******************************************************************************
+ @Function BM_GetMMUContextFromMemContext
+
+ @Description utility function to return the MMU context
+
+ @Input hDevMemContext - the Dev mem context handle
+
+ @Return MMU context, else NULL
+**************************************************************************/
MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext)
{
BM_CONTEXT *pBMContext = (BM_CONTEXT*)hDevMemContext;
return pBMContext->psMMUContext;
}
+/*!
+******************************************************************************
+ @Function BM_GetMMUHeap
+
+ @Description utility function to return the MMU heap handle
+
+ @Input hDevMemHeap - the Dev mem heap handle
+
+ @Return MMU heap handle, else NULL
+**************************************************************************/
IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap)
{
PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap"));
}
+/*!
+******************************************************************************
+ @Function BM_GetDeviceNode
+
+ @Description utility function to return the devicenode from the BM Context
+
+ @Input hDevMemContext - the Dev Mem Context
+
+ @Return MMU heap handle, else NULL
+**************************************************************************/
PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext)
{
PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode"));
}
+/*!
+******************************************************************************
+ @Function BM_GetMappingHandle
+
+ @Description utility function to return the mapping handle from a meminfo
+
+ @Input psMemInfo - kernel meminfo
+
+ @Return mapping handle, else NULL
+**************************************************************************/
IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
{
PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle"));
return ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle;
}
+/*!
+******************************************************************************
+ @Function BM_MappingHandleFromBuffer
+
+ @Description utility function to get the BM mapping handle from a BM buffer
+
+ @Input hBuffer - Handle to BM buffer
+
+ @Return BM mapping handle
+**************************************************************************/
+IMG_HANDLE BM_MappingHandleFromBuffer(IMG_HANDLE hBuffer)
+{
+ BM_BUF *psBuffer;
+
+ PVR_ASSERT(hBuffer != IMG_NULL);
+ psBuffer = hBuffer;
+ return psBuffer->pMapping;
+}
+
+/*!
+******************************************************************************
+ @Function BM_GetVirtualSize
+
+ @Description utility function to get the VM size of a BM mapping
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Return VM size of mapping
+**************************************************************************/
+IMG_UINT32 BM_GetVirtualSize(IMG_HANDLE hBMHandle)
+{
+ BM_MAPPING *psMapping;
+
+ PVR_ASSERT(hBMHandle != IMG_NULL);
+ psMapping = hBMHandle;
+ return psMapping->ui32ChunkSize * psMapping->ui32NumVirtChunks;
+}
+
+/*!
+******************************************************************************
+ @Function BM_MapPageAtOffset
+
+ @Description utility function check if the specificed offset in a BM mapping
+ is a page that needs tp be mapped
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Input ui32Offset - Offset into allocation
+
+ @Return IMG_TRUE if the page should be mapped
+**************************************************************************/
+IMG_BOOL BM_MapPageAtOffset(IMG_HANDLE hBMHandle, IMG_UINT32 ui32Offset)
+{
+ BM_MAPPING *psMapping;
+ IMG_UINT32 ui32ChunkIndex;
+
+ PVR_ASSERT(hBMHandle != IMG_NULL);
+ psMapping = hBMHandle;
+
+ ui32ChunkIndex = ui32Offset / psMapping->ui32ChunkSize;
+ /* Check for overrun */
+ PVR_ASSERT(ui32ChunkIndex <= psMapping->ui32NumVirtChunks);
+ return psMapping->pabMapChunk[ui32ChunkIndex];
+}
+
+/*!
+******************************************************************************
+ @Function BM_VirtOffsetToPhyscial
+
+ @Description utility function find of physical offset of a sparse allocation
+ from it's virtual offset.
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Input ui32VirtOffset - Virtual offset into allocation
+
+ @Output pui32PhysOffset - Physical offset
+
+ @Return IMG_TRUE if the virtual offset is physically backed
+**************************************************************************/
+IMG_BOOL BM_VirtOffsetToPhysical(IMG_HANDLE hBMHandle,
+ IMG_UINT32 ui32VirtOffset,
+ IMG_UINT32 *pui32PhysOffset)
+{
+ BM_MAPPING *psMapping;
+ IMG_UINT32 ui32ChunkOffset;
+ IMG_UINT32 ui32PhysOffset = 0;
+ IMG_UINT32 i;
+
+ PVR_ASSERT(hBMHandle != IMG_NULL);
+ psMapping = hBMHandle;
+
+ ui32ChunkOffset = ui32VirtOffset / psMapping->ui32ChunkSize;
+ if (!psMapping->pabMapChunk[ui32ChunkOffset])
+ {
+ return IMG_FALSE;
+ }
+
+ for (i=0;i<ui32ChunkOffset;i++)
+ {
+ if (psMapping->pabMapChunk[i])
+ {
+ ui32PhysOffset += psMapping->ui32ChunkSize;
+ }
+ }
+ *pui32PhysOffset = ui32PhysOffset;
+
+ return IMG_TRUE;
+}
+/******************************************************************************
+ End of file (buffer_manager.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device class services functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Kernel services functions for device class devices
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
#include "buffer_manager.h"
IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
IMG_BOOL bScheduleMISR);
#endif
+/***********************************************************************
+ Local Display Class Structures
+************************************************************************/
typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE;
+/*
+ Display Class Buffer Info
+*/
typedef struct PVRSRV_DC_BUFFER_TAG
{
-
+ /* BC/DC common details - THIS MUST BE THE FIRST MEMBER */
PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
} PVRSRV_DC_BUFFER;
+/*
+ Display Device Class kernel swapchain information structure
+*/
typedef struct PVRSRV_DC_SWAPCHAIN_TAG
{
IMG_HANDLE hExtSwapChain;
PVRSRV_DC_BUFFER *psLastFlipBuffer;
IMG_UINT32 ui32MinSwapInterval;
IMG_UINT32 ui32MaxSwapInterval;
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ PVRSRV_KERNEL_SYNC_INFO **ppsLastSyncInfos;
+ IMG_UINT32 ui32LastNumSyncInfos;
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
struct PVRSRV_DC_SWAPCHAIN_TAG *psNext;
} PVRSRV_DC_SWAPCHAIN;
+/*
+ Display Device Class kernel swapchain referecne structure
+*/
typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG
{
struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
} PVRSRV_DC_SWAPCHAIN_REF;
+/*
+ Display Device Class kernel services information structure
+*/
typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG
{
IMG_UINT32 ui32RefCount;
} PVRSRV_DISPLAYCLASS_INFO;
+/*
+ Per-context Display Device Class kernel services information structure
+*/
typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG
{
PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
} PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO;
+/***********************************************************************
+ Local Buffer Class Structures
+************************************************************************/
typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE;
+/*
+ Buffer Class Buffer Info
+*/
typedef struct PVRSRV_BC_BUFFER_TAG
{
-
+ /* BC/DC common details - THIS MUST BE THE FIRST MEMBER */
PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo;
} PVRSRV_BC_BUFFER;
+/*
+ Buffer Device Class kernel services information structure
+*/
typedef struct PVRSRV_BUFFERCLASS_INFO_TAG
{
IMG_UINT32 ui32RefCount;
IMG_HANDLE hExtDevice;
PPVRSRV_BC_SRV2BUFFER_KMJTABLE psFuncTable;
IMG_HANDLE hDevMemContext;
-
+ /* buffer info returned from 3rd party driver */
IMG_UINT32 ui32BufferCount;
PVRSRV_BC_BUFFER *psBuffer;
} PVRSRV_BUFFERCLASS_INFO;
+/*
+ Per-context Buffer Device Class kernel services information structure
+*/
typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG
{
PVRSRV_BUFFERCLASS_INFO *psBCInfo;
} PVRSRV_BUFFERCLASS_PERCONTEXT_INFO;
+/*!
+******************************************************************************
+ @Function DCDeviceHandleToDCInfo
+
+ @Description
+
+ Convert a client-visible 3rd party device class handle to an internal
+ PVRSRV_DISPLAYCLASS_INFO pointer.
+
+ @Input hDeviceKM - handle to display class device, returned from OpenDCDevice
+
+ @Return
+ success: pointer to PVRSRV_DISPLAYCLASS_INFO
+ failure: IMG_NULL
+******************************************************************************/
static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM)
{
PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
}
+/*!
+******************************************************************************
+ @Function BCDeviceHandleToBCInfo
+
+ @Description
+
+ Convert a client-visible 3rd party buffer class handle to an internal
+ PVRSRV_BUFFERCLASS_INFO pointer.
+
+ @Input hDeviceKM - handle to buffer class device, returned from OpenBCDevice
+
+ @Return
+ success: pointer to PVRSRV_BUFFERCLASS_INFO
+ failure: IMG_NULL
+******************************************************************************/
static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM)
{
PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
return psBCPerContextInfo->psBCInfo;
}
+/*!
+******************************************************************************
+ @Function PVRSRVEnumerateDCKM_ForEachVaCb
+
+ @Description
+
+ Enumerates the device node (if is of the same class as given).
+
+ @Input psDeviceNode - The device node to be enumerated
+ va - variable arguments list, with:
+ pui32DevCount - The device count pointer (to be increased)
+ ppui32DevID - The pointer to the device IDs pointer (to be updated and increased)
+ peDeviceClass - The pointer to the device class of the psDeviceNode's to be enumerated.
+******************************************************************************/
static IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
{
IMG_UINT *pui32DevCount;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnumerateDCKM
+
+ @Description
+
+ Enumerates devices available in a given class.
+ On first call, pass valid ptr for pui32DevCount and IMG_NULL for pui32DevID,
+ On second call, pass same ptr for pui32DevCount and client allocated ptr
+ for pui32DevID device id list
+
+ @Input hServices - handle for services connection
+ @Input ui32DevClass - device class identifier
+ @Output pui32DevCount - number of devices available in class
+ @Output pui32DevID - list of device ids in the device class
+
+ @Return
+ success: handle to matching display class device
+ failure: IMG_NULL
+
+******************************************************************************/
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;
SysAcquireData(&psSysData);
-
+ /* search devonode list for devices in specified class and return the device ids */
List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
&PVRSRVEnumerateDCKM_ForEachVaCb,
&ui32DevCount,
}
-static
-PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
- IMG_UINT32 *pui32DeviceID)
-{
- PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL;
- PVRSRV_DEVICE_NODE *psDeviceNode;
- SYS_DATA *psSysData;
-
-
-
-
+/*!
+******************************************************************************
+ @Function PVRSRVRegisterDCDeviceKM
+ @Description
+ registers an external device with the system
+ @Input psFuncTable : device function table
+ @Output pui32DeviceID : unique device key (for case of multiple identical devices)
+ @Return PVRSRV_ERROR :
+******************************************************************************/
+static
+PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
+ IMG_UINT32 *pui32DeviceID)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ /*
+ IN:
+ - name of client side ext. device driver library for subsequent loading
+ - predefined list of callbacks into kernel ext. device driver (based on class type)
+ FUNCTION TASKS:
+ - allocate display device class info structure
+ - hang ext.device kernel callbacks on this structure (pfnKSwapToSystem)
+ OUT:
+ - DEVICE_ID
+ - pass back devinfo? no
+ Q&A:
+ - DEVICE_ID passed in or allocated - assume allocate
+ */
SysAcquireData(&psSysData);
-
-
+ /*
+ If we got this far we're doing dynamic enumeration
+ or first time static registration
+ */
-
+ /* Allocate device control block */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*psDCInfo),
(IMG_VOID **)&psDCInfo, IMG_NULL,
}
OSMemSet (psDCInfo, 0, sizeof(*psDCInfo));
-
+ /* setup the display device information structure */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
(IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL,
}
OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE));
-
+ /* copy the jump table */
*psDCInfo->psFuncTable = *psFuncTable;
-
+ /* Allocate device node */
if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_DEVICE_NODE),
(IMG_VOID **)&psDeviceNode, IMG_NULL,
psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
psDeviceNode->psSysData = psSysData;
-
+ /* allocate a unique device id */
if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
*pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
}
-
+ /* Register the device with the system */
SysRegisterExternalDevice(psDeviceNode);
-
+ /* and finally insert the device into the dev-list */
List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
return PVRSRV_OK;
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRemoveDCDeviceKM
+
+ @Description
+
+ Removes external device from services system record
+
+ @Input ui32DeviceIndex : unique device key (for case of multiple identical devices)
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
{
SYS_DATA *psSysData;
SysAcquireData(&psSysData);
-
+ /*search the node matching the devindex and display class*/
psDeviceNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
PVRSRV_DEVICE_CLASS_DISPLAY);
if (!psDeviceNode)
{
-
+ /*device not found*/
PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex));
return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
}
-
+ /* setup DCInfo ptr */
psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
-
-
-
+ /*
+ The device can only be removed if there are
+ no open connections in the Services interface
+ */
if(psDCInfo->ui32RefCount == 0)
{
-
-
+ /*
+ Remove from the device list.
+ */
List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
-
+ /* Unregister the device with the system */
SysRemoveExternalDevice(psDeviceNode);
-
-
-
+ /*
+ OK found a device with a matching devindex
+ remove registration information
+ */
PVR_ASSERT(psDCInfo->ui32RefCount == 0);
(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
psDCInfo->psFuncTable = IMG_NULL;
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
-
+ /*not nulling original pointer, overwritten*/
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
}
else
{
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterBCDeviceKM
+
+ @Description
+
+ registers an external device with the system
+
+ @Input psFuncTable : device function table
+ @Input ui32DeviceIndex : unique device key (for case of multiple identical devices)
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static
PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
IMG_UINT32 *pui32DeviceID)
PVRSRV_BUFFERCLASS_INFO *psBCInfo = IMG_NULL;
PVRSRV_DEVICE_NODE *psDeviceNode;
SYS_DATA *psSysData;
-
-
-
-
-
-
-
-
-
-
+ /*
+ IN:
+ - name of client side ext. device driver library for subsequent loading
+ - predefined list of callbacks into kernel ext. device driver (based on class type)
+ FUNCTION TASKS:
+ - allocate buffer device class info structure
+ OUT:
+ - DEVICE_ID
+ - pass back devinfo? no
+ Q&A:
+ - DEVICE_ID passed in or allocated - assume allcoate
+ */
SysAcquireData(&psSysData);
-
-
+ /*
+ If we got this far we're doing dynamic enumeration
+ or first time static registration
+ */
-
+ /* Allocate device control block */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*psBCInfo),
(IMG_VOID **)&psBCInfo, IMG_NULL,
}
OSMemSet (psBCInfo, 0, sizeof(*psBCInfo));
-
+ /* setup the buffer device information structure */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
(IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL,
}
OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE));
-
+ /* copy the jump table */
*psBCInfo->psFuncTable = *psFuncTable;
-
+ /* Allocate device node */
if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_DEVICE_NODE),
(IMG_VOID **)&psDeviceNode, IMG_NULL,
psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
psDeviceNode->psSysData = psSysData;
-
+ /* allocate a unique device id */
if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
*pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
}
-
+ /* and finally insert the device into the dev-list */
List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
return PVRSRV_OK;
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
-
+ /*not nulling shared pointer, wasn't allocated to this point*/
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRemoveBCDeviceKM
+
+ @Description
+
+ Removes external device from services system record
+
+ @Input ui32DeviceIndex : unique device key (for case of multiple identical devices)
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
{
SYS_DATA *psSysData;
SysAcquireData(&psSysData);
-
+ /*search the device node with the devindex and buffer class*/
psDevNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
}
-
-
+ /* set-up devnode ptr */
+/* psDevNode = *(ppsDevNode); */
+ /* setup BCInfo ptr */
psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice;
-
-
-
+ /*
+ The device can only be removed if there are
+ no open connections in the Services interface
+ */
if(psBCInfo->ui32RefCount == 0)
{
-
-
+ /*
+ Remove from the device list.
+ */
List_PVRSRV_DEVICE_NODE_Remove(psDevNode);
-
-
-
+ /*
+ OK found a device with a matching devindex
+ remove registration information
+ */
(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
-
-
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
psBCInfo->psFuncTable = IMG_NULL;
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
}
else
{
+/*!
+******************************************************************************
+
+ @Function PVRSRVCloseDCDeviceKM
+
+ @Description
+
+ Closes a connection to the Display Class device
+
+ @Input hDeviceKM : device handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
-PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM,
- IMG_BOOL bResManCallback)
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM)
{
PVRSRV_ERROR eError;
PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
- PVR_UNREFERENCED_PARAMETER(bResManCallback);
-
psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
-
+ /* Remove the item from the resman list and trigger the callback. */
eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem, CLEANUP_WITH_POLL);
return eError;
if(psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount != 0)
{
- PVR_DPF((PVR_DBG_ERROR,"CloseDCDeviceCallBack: system buffer (0x%p) still mapped (refcount = %d)",
+ PVR_DPF((PVR_DBG_MESSAGE,"CloseDCDeviceCallBack: system buffer (0x%p) still mapped (refcount = %d)",
&psDCInfo->sSystemBuffer.sDeviceClassBuffer,
psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount));
-
-#if 0
-
- return PVRSRV_ERROR_STILL_MAPPED;
-#endif
}
psDCInfo->ui32RefCount--;
if(psDCInfo->ui32RefCount == 0)
{
-
+ /* close the external device */
psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
- if (--psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
- {
- PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
psDCInfo->hDevMemContext = IMG_NULL;
psDCInfo->hExtDevice = IMG_NULL;
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVOpenDCDeviceKM
+
+ @Description
+
+ Opens a connection to the Display Class device, associating the connection
+ with a Device Memory Context for a services managed device
+
+ @Input psPerProc : Per-process data
+ @Input ui32DeviceID : unique device index
+ @Input hDevCookie : devcookie used to derive the Device Memory
+ Context into BC surfaces will be mapped into
+ @Outut phDeviceKM : handle to the DC device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_UINT32 ui32DeviceID,
SysAcquireData(&psSysData);
-
+ /* find the matching devicenode */
psDeviceNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
}
psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
-
-
-
+ /*
+ Allocate the per-context DC Info before calling the external device,
+ to make error handling easier.
+ */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*psDCPerContextInfo),
(IMG_VOID **)&psDCPerContextInfo, IMG_NULL,
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
-
+ /* store the device kernel context to map into */
psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
-
+ /* create a syncinfo for the device's system surface */
eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
(IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext,
&psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
return eError;
}
-
+ /* open the external device */
eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID,
&psDCInfo->hExtDevice,
(PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM);
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device"));
psDCInfo->ui32RefCount--;
- PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+ PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
return eError;
}
- psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+ psDCPerContextInfo->psDCInfo = psDCInfo;
+ eError = PVRSRVGetDCSystemBufferKM(psDCPerContextInfo, IMG_NULL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to get system buffer"));
+ psDCInfo->ui32RefCount--;
+ PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+ return eError;
+ }
psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount = 0;
}
+ else
+ {
+ psDCPerContextInfo->psDCInfo = psDCInfo;
+ }
- psDCPerContextInfo->psDCInfo = psDCInfo;
psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DISPLAYCLASS_DEVICE,
psDCPerContextInfo,
0,
&CloseDCDeviceCallBack);
-
+ /* return a reference to the DCPerContextInfo */
*phDeviceKM = (IMG_HANDLE)psDCPerContextInfo;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnumDCFormatsKM
+
+ @Description
+
+ Enumerates the devices pixel formats
+
+ @Input hDeviceKM : device handle
+ @Output pui32Count : number of pixel formats
+ @Output psFormat : format list
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM,
IMG_UINT32 *pui32Count,
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
-
+ /* call into the display device driver to get info */
return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnumDCDimsKM
+
+ @Description
+
+ Enumerates the devices mode dimensions for a given pixel format
+
+ @Input hDeviceKM : device handle
+ @Input psFormat : pixel format
+ @Output pui32Count : number of dimensions
+ @Output psDim : dimensions list
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
DISPLAY_FORMAT *psFormat,
{
PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
- if(!hDeviceKM || !pui32Count || !psFormat)
+ if(!hDeviceKM || !pui32Count || !psFormat) // psDim==NULL to query number of dims
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters"));
return PVRSRV_ERROR_INVALID_PARAMS;
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
-
+ /* call into the display device driver to get info */
return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetDCSystemBufferKM
+
+ @Description
+
+ Get the primary surface and optionally return its buffer handle
+
+ @Input hDeviceKM : device handle
+ @Output phBuffer : Optional buffer handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
IMG_HANDLE *phBuffer)
PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
IMG_HANDLE hExtBuffer;
- if(!hDeviceKM || !phBuffer)
+ if(!hDeviceKM)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters"));
return PVRSRV_ERROR_INVALID_PARAMS;
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
-
+ /* call into the display device driver to get info */
eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer);
if(eError != PVRSRV_OK)
{
return eError;
}
-
+ /* save the new info */
psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
-
- *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
+ /* return handle */
+ if (phBuffer)
+ {
+ *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
+ }
return PVRSRV_OK;
}
+/******************************************************************************
+
+ @Function PVRSRVGetDCInfoKM
+
+ @Description
+
+ Gets Display Class device Info
+
+ @Input hDeviceKM : device handle
+ @Output psDisplayInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM,
DISPLAY_INFO *psDisplayInfo)
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
-
+ /* call into the display device driver to get info */
eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo);
if (eError != PVRSRV_OK)
{
PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo;
IMG_UINT32 i;
-
+ /* Update shared swapchains list */
if( psDCInfo->psDCSwapChainShared )
{
if( psDCInfo->psDCSwapChainShared == psSwapChain )
}
}
-
+ /* Destroy command queue before swapchain - it may use the swapchain when commands are flushed. */
PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
-
+ /* call into the display device driver to destroy a swapchain */
eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
psSwapChain->hExtSwapChain);
return eError;
}
-
+ /* free the resources */
for(i=0; i<psSwapChain->ui32BufferCount; i++)
{
if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
{
- if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
- {
- PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
}
}
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ if (psSwapChain->ppsLastSyncInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos,
+ psSwapChain->ppsLastSyncInfos, IMG_NULL);
+ }
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
+
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return eError;
}
PVR_DPF((PVR_DBG_ERROR, "DestroyDCSwapChainRefCallBack: swapchain (0x%p) still mapped (ui32MemMapRefCount = %d)",
&psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer,
psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount));
-#if 0
-
- return PVRSRV_ERROR_STILL_MAPPED;
-#endif
}
}
{
PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
-
+ /* Allocate swapchain reference structre*/
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_DC_SWAPCHAIN_REF),
(IMG_VOID **)&psSwapChainRef, IMG_NULL,
}
OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF));
-
+ /* Bump refcount */
psSwapChain->ui32RefCount++;
-
+ /* Create reference resource */
psSwapChainRef->psSwapChain = psSwapChain;
psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY )
{
-
+ /* Query - use pui32SwapChainID as input */
psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID );
if( psSwapChain )
{
-
+ /* Create new reference */
eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
psSwapChain,
&psSwapChainRef);
return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
}
-
+ /* Allocate swapchain control structure for srvkm */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_DC_SWAPCHAIN),
(IMG_VOID **)&psSwapChain, IMG_NULL,
}
OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN));
-
+ /* Create a command queue for the swapchain */
eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
if(eError != PVRSRV_OK)
{
goto ErrorExit;
}
-
+ /* store the Queue */
psSwapChain->psQueue = psQueue;
-
+ /* Create a Sync Object for each surface in the swapchain */
for(i=0; i<ui32BufferCount; i++)
{
eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
goto ErrorExit;
}
- psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
-
-
+ /* setup common device class info */
psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
-
+ /* save off useful ptrs */
psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
-
+ /* syncinfos must be passed as array of syncdata ptrs to the 3rd party driver */
apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
}
psSwapChain->ui32MinSwapInterval = sDisplayInfo.ui32MinSwapInterval;
psSwapChain->ui32MaxSwapInterval = sDisplayInfo.ui32MaxSwapInterval;
-
+ /* call into the display device driver to create a swapchain */
eError = psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
ui32Flags,
psDstSurfAttrib,
goto ErrorExit;
}
-
+ /* Create new reference */
eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
psSwapChain,
&psSwapChainRef);
psSwapChain->ui32RefCount = 1;
psSwapChain->ui32Flags = ui32Flags;
-
+ /* Save pointer in DC structure if ti's shared struct */
if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED )
{
if(! psDCInfo->psDCSwapChainShared )
}
}
-
+ /* We create swapchain - pui32SwapChainID is output */
*pui32SwapChainID = psSwapChain->ui32SwapChainID;
-
+ /* return the swapchain reference handle */
*phSwapChainRef= (IMG_HANDLE)psSwapChainRef;
return eError;
{
if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
{
- if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
- {
- PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
}
}
if(psSwapChain)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
}
return eError;
PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
IMG_HANDLE hSwapChainRef,
IMG_UINT32 *pui32BufferCount,
- IMG_HANDLE *phBuffer)
+ IMG_HANDLE *phBuffer,
+ IMG_SYS_PHYADDR *psPhyAddr)
{
PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
PVRSRV_DC_SWAPCHAIN *psSwapChain;
PVRSRV_ERROR eError;
IMG_UINT32 i;
- if(!hDeviceKM || !hSwapChainRef || !phBuffer)
+ if(!hDeviceKM || !hSwapChainRef || !phBuffer || !psPhyAddr)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters"));
return PVRSRV_ERROR_INVALID_PARAMS;
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
-
+ /* call into the display device driver to get info */
eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
psSwapChain->hExtSwapChain,
pui32BufferCount,
PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
-
-
-
+ /*
+ populate the srvkm's buffer structure with the 3rd party buffer handles
+ and return the services buffer handles
+ */
for(i=0; i<*pui32BufferCount; i++)
{
psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i];
phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i];
}
+#if defined(SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS)
+ for(i = 0; i < *pui32BufferCount; i++)
+ {
+ IMG_UINT32 ui32ByteSize, ui32TilingStride;
+ IMG_SYS_PHYADDR *pPhyAddr;
+ IMG_BOOL bIsContiguous;
+ IMG_HANDLE hOSMapInfo;
+ IMG_VOID *pvVAddr;
+
+ eError = psDCInfo->psFuncTable->pfnGetBufferAddr(psDCInfo->hExtDevice,
+ ahExtBuffer[i],
+ &pPhyAddr,
+ &ui32ByteSize,
+ &pvVAddr,
+ &hOSMapInfo,
+ &bIsContiguous,
+ &ui32TilingStride);
+ if(eError != PVRSRV_OK)
+ {
+ break;
+ }
+
+ psPhyAddr[i] = *pPhyAddr;
+ }
+#endif /* defined(SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS) */
+
return eError;
}
psBuffer = (PVRSRV_DC_BUFFER*)hBuffer;
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
-
+ /* Validate swap interval against limits */
if(ui32SwapInterval < psBuffer->psSwapChain->ui32MinSwapInterval ||
ui32SwapInterval > psBuffer->psSwapChain->ui32MaxSwapInterval)
{
#endif
-
+ /* get the queue from the buffer structure */
psQueue = psBuffer->psSwapChain->psQueue;
-
+ /* specify the syncs */
apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
-
-
-
if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer &&
psBuffer != psBuffer->psSwapChain->psLastFlipBuffer)
{
apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
-
-
-
ui32NumSrcSyncs++;
}
-
+ /* insert the command (header) */
eError = PVRSRVInsertCommandKM (psQueue,
&psCommand,
psDCInfo->ui32DeviceID,
IMG_NULL,
ui32NumSrcSyncs,
apsSrcSync,
- sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount));
+ sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount),
+ IMG_NULL,
+ IMG_NULL);
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue"));
goto Exit;
}
-
+ /* setup the flip command */
psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
-
+ /* Ext Device Handle */
psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
-
+ /* Ext SwapChain Handle */
psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
-
+ /* Ext Buffer Handle (Buffer to Flip to) */
psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
-
+ /* private tag */
psFlipCmd->hPrivateTag = hPrivateTag;
-
+ /* setup the clip rects */
psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
-
- psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND));
-
+ /* cliprect memory appends the command structure */
+ psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND)); // PRQA S 3305
+ /* copy the clip rects */
for(i=0; i<ui32ClipRectCount; i++)
{
psFlipCmd->psClipRect[i] = psClipRect[i];
}
-
+ /* number of vsyncs between successive flips */
psFlipCmd->ui32SwapInterval = ui32SwapInterval;
-
- eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command"));
- goto Exit;
+ SysAcquireData(&psSysData);
+
+ /* Because we might be composing just software surfaces, without
+ * any SGX renders since the last frame, we won't necessarily
+ * have cleaned/flushed the CPU caches before the buffers need
+ * to be displayed.
+ *
+ * Doing so now is safe because InsertCommand bumped ROP2 on the
+ * affected buffers (preventing more SW renders starting) but the
+ * display won't start to process the buffers until SubmitCommand.
+ */
+ {
+ if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+ {
+ OSFlushCPUCacheKM();
+ }
+ else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+ {
+ OSCleanCPUCacheKM();
+ }
+
+ psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
}
-
+ /* submit the command */
+ eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command"));
+ goto Exit;
+ }
- SysAcquireData(&psSysData);
+ /*
+ Schedule an MISR to process it
+ */
eError = OSScheduleMISR(psSysData);
if (eError != PVRSRV_OK)
goto Exit;
}
-
+ /* update the last flip buffer */
psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
Exit:
return eError;
}
+typedef struct _CALLBACK_DATA_
+{
+ IMG_PVOID pvPrivData;
+ IMG_UINT32 ui32PrivDataLength;
+ IMG_PVOID ppvMemInfos;
+ IMG_UINT32 ui32NumMemInfos;
+} CALLBACK_DATA;
+
+static IMG_VOID FreePrivateData(IMG_HANDLE hCallbackData)
+{
+ CALLBACK_DATA *psCallbackData = hCallbackData;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psCallbackData->ui32PrivDataLength,
+ psCallbackData->pvPrivData, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos,
+ psCallbackData->ppvMemInfos, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), hCallbackData, IMG_NULL);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32SwapInterval,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfos,
+ PVRSRV_KERNEL_SYNC_INFO **ppsSyncInfos,
+ IMG_UINT32 ui32NumMemSyncInfos,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength)
+{
+ PVRSRV_KERNEL_SYNC_INFO **ppsCompiledSyncInfos;
+ IMG_UINT32 i, ui32NumCompiledSyncInfos;
+ DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ CALLBACK_DATA *psCallbackData;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_COMMAND *psCommand;
+ IMG_PVOID *ppvMemInfos;
+ SYS_DATA *psSysData;
+
+ if(!hDeviceKM || !hSwapChain || !ppsMemInfos || !ppsSyncInfos || ui32NumMemSyncInfos < 1)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChain)->psSwapChain;
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ /* Validate swap interval against limits */
+ if(ui32SwapInterval < psSwapChain->ui32MinSwapInterval ||
+ ui32SwapInterval > psSwapChain->ui32MaxSwapInterval)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid swap interval. Requested %u, Allowed range %u-%u",
+ ui32SwapInterval, psSwapChain->ui32MinSwapInterval, psSwapChain->ui32MaxSwapInterval));
+ return PVRSRV_ERROR_INVALID_SWAPINTERVAL;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(CALLBACK_DATA),
+ (IMG_VOID **)&psCallbackData, IMG_NULL,
+ "PVRSRVSwapToDCBuffer2KM callback data");
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ psCallbackData->pvPrivData = pvPrivData;
+ psCallbackData->ui32PrivDataLength = ui32PrivDataLength;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_VOID *) * ui32NumMemSyncInfos,
+ (IMG_VOID **)&ppvMemInfos, IMG_NULL,
+ "Swap Command Meminfos") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+ psCallbackData->ppvMemInfos = IMG_NULL;
+ goto Exit;
+ }
+
+ for(i = 0; i < ui32NumMemSyncInfos; i++)
+ {
+ ppvMemInfos[i] = ppsMemInfos[i];
+ }
+
+ psCallbackData->ppvMemInfos = ppvMemInfos;
+ psCallbackData->ui32NumMemInfos = ui32NumMemSyncInfos;
+
+ /* get the queue from the buffer structure */
+ psQueue = psSwapChain->psQueue;
+
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ if(psSwapChain->ppsLastSyncInfos)
+ {
+ IMG_UINT32 ui32NumUniqueSyncInfos = psSwapChain->ui32LastNumSyncInfos;
+ IMG_UINT32 j;
+
+ for(j = 0; j < psSwapChain->ui32LastNumSyncInfos; j++)
+ {
+ for(i = 0; i < ui32NumMemSyncInfos; i++)
+ {
+ if(psSwapChain->ppsLastSyncInfos[j] == ppsSyncInfos[i])
+ {
+ psSwapChain->ppsLastSyncInfos[j] = IMG_NULL;
+ ui32NumUniqueSyncInfos--;
+ }
+ }
+ }
+
+ ui32NumCompiledSyncInfos = ui32NumMemSyncInfos + ui32NumUniqueSyncInfos;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
+ (IMG_VOID **)&ppsCompiledSyncInfos, IMG_NULL,
+ "Compiled syncinfos") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+ goto Exit;
+ }
+
+ OSMemCopy(ppsCompiledSyncInfos, ppsSyncInfos, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos);
+ for(j = 0, i = ui32NumMemSyncInfos; j < psSwapChain->ui32LastNumSyncInfos; j++)
+ {
+ if(psSwapChain->ppsLastSyncInfos[j])
+ {
+ ppsCompiledSyncInfos[i] = psSwapChain->ppsLastSyncInfos[j];
+ i++;
+ }
+ }
+ }
+ else
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
+ {
+ ppsCompiledSyncInfos = ppsSyncInfos;
+ ui32NumCompiledSyncInfos = ui32NumMemSyncInfos;
+ }
+
+ /* insert the command (header) */
+ eError = PVRSRVInsertCommandKM (psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ DC_FLIP_COMMAND,
+ 0,
+ IMG_NULL,
+ ui32NumCompiledSyncInfos,
+ ppsCompiledSyncInfos,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND2),
+ FreePrivateData,
+ psCallbackData);
+
+ if (ppsCompiledSyncInfos != ppsSyncInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
+ (IMG_VOID *)ppsCompiledSyncInfos,
+ IMG_NULL);
+ }
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+ /* setup the flip command */
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND2*)psCommand->pvData;
+
+ /* Ext Device Handle */
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+ /* Ext SwapChain Handle */
+ psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+ /* number of vsyncs between successive flips */
+ psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+ /* Opaque private data, if supplied */
+ psFlipCmd->pvPrivData = pvPrivData;
+ psFlipCmd->ui32PrivDataLength = ui32PrivDataLength;
+
+ psFlipCmd->ppsMemInfos = (PDC_MEM_INFO *)ppvMemInfos;
+ psFlipCmd->ui32NumMemInfos = ui32NumMemSyncInfos;
+
+ /* Even though this is "unused", we have to initialize it,
+ * as the display controller might NULL-test it.
+ */
+ psFlipCmd->hUnused = IMG_NULL;
+
+ SysAcquireData(&psSysData);
+
+ /* Because we might be composing just software surfaces, without
+ * any SGX renders since the last frame, we won't necessarily
+ * have cleaned/flushed the CPU caches before the buffers need
+ * to be displayed.
+ *
+ * Doing so now is safe because InsertCommand bumped ROP2 on the
+ * affected buffers (preventing more SW renders starting) but the
+ * display won't start to process the buffers until SubmitCommand.
+ */
+ {
+ if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+ {
+ OSFlushCPUCacheKM();
+ }
+ else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+ {
+ OSCleanCPUCacheKM();
+ }
+
+ psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+ }
+
+ /* submit the command */
+ eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to submit command"));
+ goto Exit;
+ }
+
+ /* The command has been submitted and so psCallbackData will be freed by the callback */
+ psCallbackData = IMG_NULL;
+
+ /*
+ Schedule an MISR to process it
+ */
+ eError = OSScheduleMISR(psSysData);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to schedule MISR"));
+ goto Exit;
+ }
+
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ /* Reallocate the syncinfo list if it was too small */
+ if (psSwapChain->ui32LastNumSyncInfos < ui32NumMemSyncInfos)
+ {
+ if (psSwapChain->ppsLastSyncInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos,
+ psSwapChain->ppsLastSyncInfos, IMG_NULL);
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos,
+ (IMG_VOID **)&psSwapChain->ppsLastSyncInfos, IMG_NULL,
+ "Last syncinfos") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+ goto Exit;
+ }
+ }
+
+ psSwapChain->ui32LastNumSyncInfos = ui32NumMemSyncInfos;
+
+ for(i = 0; i < ui32NumMemSyncInfos; i++)
+ {
+ psSwapChain->ppsLastSyncInfos[i] = ppsSyncInfos[i];
+ }
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
+
+Exit:
+ if (psCallbackData)
+ {
+ if(psCallbackData->ppvMemInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos,
+ psCallbackData->ppvMemInfos, IMG_NULL);
+ }
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), psCallbackData, IMG_NULL);
+ }
+ if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return eError;
+}
+
IMG_EXPORT
PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef;
psSwapChain = psSwapChainRef->psSwapChain;
-
+ /* get the queue from the buffer structure */
psQueue = psSwapChain->psQueue;
#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
#endif
-
+ /* specify the syncs */
apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
-
-
-
if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer)
{
-
+ /* Make sure we don't make a double dependency on the same server */
if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo)
{
apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
-
-
-
ui32NumSrcSyncs++;
}
}
-
+ /* insert the command (header) */
eError = PVRSRVInsertCommandKM (psQueue,
&psCommand,
psDCInfo->ui32DeviceID,
IMG_NULL,
ui32NumSrcSyncs,
apsSrcSync,
- sizeof(DISPLAYCLASS_FLIP_COMMAND));
+ sizeof(DISPLAYCLASS_FLIP_COMMAND),
+ IMG_NULL,
+ IMG_NULL);
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue"));
goto Exit;
}
-
+ /* setup the flip command */
psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
-
+ /* Ext Device Handle */
psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
-
+ /* Ext SwapChain Handle */
psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
-
+ /* Ext Buffer Handle (Buffer to Flip to) */
psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
-
+ /* private tag */
psFlipCmd->hPrivateTag = IMG_NULL;
-
+ /* setup the clip rects */
psFlipCmd->ui32ClipRectCount = 0;
psFlipCmd->ui32SwapInterval = 1;
-
+ /* submit the command */
eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
if (eError != PVRSRV_OK)
{
goto Exit;
}
-
+ /* Schedule an MISR to process it */
SysAcquireData(&psSysData);
eError = OSScheduleMISR(psSysData);
goto Exit;
}
-
+ /* update the last flip buffer */
psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
eError = PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterSystemISRHandler
+
+ @Description
+
+ registers an external ISR to be called of the back of a system ISR
+
+ @Input ppfnISRHandler : ISR pointer
+
+ @Input hISRHandlerData : Callback data
+
+ @Input ui32ISRSourceMask : ISR Mask
+
+ @Input ui32DeviceID : unique device key
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static
PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER pfnISRHandler,
IMG_VOID *pvISRHandlerData,
SysAcquireData(&psSysData);
-
+ /* Find Dev Node (just using the device id, ignore the class) */
psDevNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
}
-
+ /* set up data before enabling the ISR */
psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData;
-
+ /* enable the ISR */
psDevNode->pfnDeviceISR = pfnISRHandler;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetDCState_ForEachVaCb
+
+ @Description
+
+ If the device node is a display, calls its set state function.
+
+ @Input psDeviceNode - the device node
+ va - variable argument list with:
+ ui32State - the state to be set.
+
+******************************************************************************/
static
IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
{
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetDCState
+
+ @Description
+
+ Calls the display driver(s) to put them into the specified state.
+
+ @Input ui32State: new DC state - one of DC_STATE_*
+
+******************************************************************************/
IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
{
+/* PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode; */
SYS_DATA *psSysData;
SysAcquireData(&psSysData);
ui32State);
}
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetCpuVAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+ IMG_CPU_VIRTADDR *pVAddr)
+{
+ *pVAddr = psKernelMemInfo->pvLinAddrKM;
+ return PVRSRV_OK;
+}
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetCpuPAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+ IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr)
+{
+ *pPAddr = OSMemHandleToCpuPAddr(psKernelMemInfo->sMemBlk.hOSMemHandle, uByteOffset);
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetByteSize(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+ IMG_SIZE_T *uByteSize)
+{
+ *uByteSize = psKernelMemInfo->uAllocSize;
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL
+PVRSRVDCMemInfoIsPhysContig(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ return OSMemHandleIsPhysContig(psKernelMemInfo->sMemBlk.hOSMemHandle);
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRGetDisplayClassJTable
+
+ @Description
+
+ Sets up function table for 3rd party Display Class Device to call through
+
+ @Input psJTable : pointer to function pointer table memory
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
{
#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM;
#endif
-
+ psJTable->pfnPVRSRVDCMemInfoGetCpuVAddr = &PVRSRVDCMemInfoGetCpuVAddr;
+ psJTable->pfnPVRSRVDCMemInfoGetCpuPAddr = &PVRSRVDCMemInfoGetCpuPAddr;
+ psJTable->pfnPVRSRVDCMemInfoGetByteSize = &PVRSRVDCMemInfoGetByteSize;
+ psJTable->pfnPVRSRVDCMemInfoIsPhysContig = &PVRSRVDCMemInfoIsPhysContig;
return IMG_TRUE;
}
+/******************************************************************************
+
+ @Function PVRSRVCloseBCDeviceKM
+
+ @Description
+
+ Closes a connection to the Buffer Class device
+
+ @Input hDeviceKM : device handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
-PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM,
- IMG_BOOL bResManCallback)
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM)
{
PVRSRV_ERROR eError;
PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
- PVR_UNREFERENCED_PARAMETER(bResManCallback);
-
psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
-
+ /* Remove the item from the resman list and trigger the callback. */
eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem, CLEANUP_WITH_POLL);
return eError;
psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)pvParam;
psBCInfo = psBCPerContextInfo->psBCInfo;
-#if 0
+
for (i = 0; i < psBCInfo->ui32BufferCount; i++)
{
if (psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0)
return PVRSRV_ERROR_STILL_MAPPED;
}
}
-#endif
+
psBCInfo->ui32RefCount--;
if(psBCInfo->ui32RefCount == 0)
{
- for (i = 0; i < psBCInfo->ui32BufferCount; i++)
- {
- if (psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0)
- {
- PVR_DPF((PVR_DBG_ERROR, "CloseBCDeviceCallBack: buffer %d (0x%p) still mapped (ui32MemMapRefCount = %d)",
- i,
- &psBCInfo->psBuffer[i].sDeviceClassBuffer,
- psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount));
- return PVRSRV_ERROR_STILL_MAPPED;
- }
- }
-
+ /* close the external device */
psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice);
-
+ /* free syncinfos */
for(i=0; i<psBCInfo->ui32BufferCount; i++)
{
if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
{
- if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
- {
- PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
}
}
-
+ /* free buffers */
if(psBCInfo->psBuffer)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * psBCInfo->ui32BufferCount, psBCInfo->psBuffer, IMG_NULL);
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVOpenBCDeviceKM
+
+ @Description
+
+ Opens a connection to the Buffer Class device, associating the connection
+ with a Device Memory Context for a services managed device
+
+ @Input psPerProc : Per-process data
+ @Input ui32DeviceID : unique device index
+ @Input hDevCookie : devcookie used to derive the Device Memory
+ Context into BC surfaces will be mapped into
+ @Outut phDeviceKM : handle to the DC device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_UINT32 ui32DeviceID,
SysAcquireData(&psSysData);
-
+ /* find the matching devicenode */
psDeviceNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
}
psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice;
-
-
-
+/*
+FoundDevice:
+*/
+ /*
+ Allocate the per-context BC Info before calling the external device,
+ to make error handling easier.
+ */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*psBCPerContextInfo),
(IMG_VOID **)&psBCPerContextInfo, IMG_NULL,
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
-
+ /* store the device kernel context to map into */
psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
-
+ /* open the external device */
eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice);
if(eError != PVRSRV_OK)
{
return eError;
}
-
+ /* get information about the buffers */
eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo);
if(eError != PVRSRV_OK)
{
return eError;
}
-
+ /* interpret and store info */
psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
-
-
+ /* allocate BC buffers */
eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount,
(IMG_VOID **)&psBCInfo->psBuffer,
for(i=0; i<psBCInfo->ui32BufferCount; i++)
{
-
+ /* create a syncinfo for the device's system surface */
eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
psBCInfo->hDevMemContext,
&psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc"));
goto ErrorExit;
}
-
- psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
-
-
-
+ /*
+ get the buffers from the buffer class
+ drivers by index, passing-in the syncdata objects
+ */
eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice,
i,
psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData,
goto ErrorExit;
}
-
+ /* setup common device class info */
psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr;
psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext;
psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice;
0,
&CloseBCDeviceCallBack);
-
+ /* return a reference to the BCPerContextInfo */
*phDeviceKM = (IMG_HANDLE)psBCPerContextInfo;
return PVRSRV_OK;
ErrorExit:
-
+ /* free syncinfos */
for(i=0; i<psBCInfo->ui32BufferCount; i++)
{
if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
{
- if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
- {
- PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
}
}
-
+ /* free buffers */
if(psBCInfo->psBuffer)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
+/******************************************************************************
+
+ @Function PVRSRVGetBCInfoKM
+
+ @Description
+
+ Gets Buffer Class device Info
+
+ @Input hDeviceKM : device handle
+ @Output psBufferInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM,
BUFFER_INFO *psBufferInfo)
}
+/******************************************************************************
+
+ @Function PVRSRVGetBCBufferKM
+
+ @Description
+
+ Gets Buffer Class Buffer Handle
+
+ @Input hDeviceKM : device handle
+ @Output psBufferInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM,
IMG_UINT32 ui32BufferIndex,
}
+/*!
+******************************************************************************
+
+ @Function PVRGetBufferClassJTable
+
+ @Description
+
+ Sets up function table for 3rd party Buffer Class Device to call through
+
+ @Input psJTable : pointer to function pointer table memory
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
{
return IMG_TRUE;
}
+/******************************************************************************
+ End of file (deviceclass.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device ID helpers
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __DEVICEID_H__
#define __DEVICEID_H__
PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
-#endif
+#endif /* __DEVICEID_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device addressable memory functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Device addressable memory APIs
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <stddef.h>
#include "pvr_bridge_km.h"
#include "osfunc.h"
-static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
- IMG_HANDLE hDevMemHeap,
- IMG_UINT32 ui32Flags,
- IMG_SIZE_T ui32Size,
- IMG_SIZE_T ui32Alignment,
- PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+#if defined(SUPPORT_ION)
+#include "ion.h"
+#include "env_perproc.h"
+#endif
+/* local function prototypes */
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+/* local structures */
+
+/*
+ structure stored in resman to store references
+ to the SRC and DST meminfo
+*/
typedef struct _RESMAN_MAP_DEVICE_MEM_DATA_
{
-
+ /* the DST meminfo created by the map */
PVRSRV_KERNEL_MEM_INFO *psMemInfo;
-
+ /* SRC meminfo */
PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo;
} RESMAN_MAP_DEVICE_MEM_DATA;
+/*
+ map device class resman memory storage structure
+*/
typedef struct _PVRSRV_DC_MAPINFO_
{
PVRSRV_KERNEL_MEM_INFO *psMemInfo;
static IMG_UINT32 g_ui32SyncUID = 0;
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetDeviceMemHeapsKM
+
+ @Description
+
+ Gets the device shared memory heaps
+
+ @Input hDevCookie :
+ @Output phDevMemContext : ptr to handle to memory context
+ @Output psHeapInfo : ptr to array of heap info
+
+ @Return PVRSRV_DEVICE_NODE, valid devnode or IMG_NULL
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
#if defined (SUPPORT_SID_INTERFACE)
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
-
+ /* Setup useful pointers */
ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
-
+ /* check we don't exceed the max number of heaps */
PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
-
+ /* retrieve heap information */
for(i=0; i<ui32HeapCount; i++)
{
-
+ /* return information about the heap */
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;
+ /* (XTileStride > 0) denotes a tiled heap */
+ psHeapInfo[i].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
}
for(; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVCreateDeviceMemContextKM
+
+ @Description
+
+ Creates a device memory context
+
+ @Input hDevCookie :
+ @Input psPerProc : Per-process data
+ @Output phDevMemContext : ptr to handle to memory context
+ @Output pui32ClientHeapCount : ptr to heap count
+ @Output psHeapInfo : ptr to array of heap info
+
+ @Return PVRSRV_DEVICE_NODE, valid devnode or IMG_NULL
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCookie,
PVRSRV_PER_PROCESS_DATA *psPerProc,
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
-
-
+ /*
+ Setup useful pointers
+ */
ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
-
-
+ /*
+ check we don't exceed the max number of heaps
+ */
PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
-
-
+ /*
+ Create a memory context for the caller
+ */
hDevMemContext = BM_CreateContext(psDeviceNode,
&sPDDevPAddr,
psPerProc,
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* create the per context heaps */
for(i=0; i<ui32HeapCount; i++)
{
switch(psDeviceMemoryHeap[i].DevMemHeapType)
{
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
{
-
+ /* return information about the heap */
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(SUPPORT_MEMORY_TILING)
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+ #else
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = 0;
+ #endif
+
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
pbShared[ui32ClientHeapCount] = IMG_TRUE;
#endif
hDevMemHeap = IMG_NULL;
}
-
+ /* return information about the heap */
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(SUPPORT_MEMORY_TILING)
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+ #else
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = 0;
+ #endif
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
pbShared[ui32ClientHeapCount] = IMG_FALSE;
#endif
}
}
-
+ /* return shared_exported and per context heap information to the caller */
*pui32ClientHeapCount = ui32ClientHeapCount;
*phDevMemContext = hDevMemContext;
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetDeviceMemHeapInfoKM
+
+ @Description
+
+ gets heap info
+
+ @Input hDevCookie :
+ @Input hDevMemContext : ptr to handle to memory context
+ @Output pui32ClientHeapCount : ptr to heap count
+ @Output psHeapInfo : ptr to array of heap info
+
+ @Return
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie,
IMG_HANDLE hDevMemContext,
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
-
-
+ /*
+ Setup useful pointers
+ */
ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
-
-
+ /*
+ check we don't exceed the max number of heaps
+ */
PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
-
+ /* create the per context heaps */
for(i=0; i<ui32HeapCount; i++)
{
switch(psDeviceMemoryHeap[i].DevMemHeapType)
{
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
{
-
+ /* return information about the heap */
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;
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
pbShared[ui32ClientHeapCount] = IMG_TRUE;
#endif
hDevMemHeap = IMG_NULL;
}
-
+ /* return information about the heap */
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;
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
pbShared[ui32ClientHeapCount] = IMG_FALSE;
#endif
}
}
-
+ /* return shared_exported and per context heap information to the caller */
*pui32ClientHeapCount = ui32ClientHeapCount;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function AllocDeviceMem
+
+ @Description
+
+ Allocates device memory
+
+ @Input hDevCookie :
+
+ @Input hDevMemHeap
+
+ @Input ui32Flags : Some combination of PVRSRV_MEM_ flags
+
+ @Input ui32Size : Number of bytes to allocate
+
+ @Input ui32Alignment : Alignment of allocation
+
+ @Input pvPrivData : Opaque private data passed through to allocator
+
+ @Input ui32PrivDataLength : Length of opaque private data
+
+ @Output **ppsMemInfo : On success, receives a pointer to the created MEM_INFO structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
- IMG_HANDLE hDevMemHeap,
- IMG_UINT32 ui32Flags,
- IMG_SIZE_T ui32Size,
- IMG_SIZE_T ui32Alignment,
- PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
{
PVRSRV_KERNEL_MEM_INFO *psMemInfo;
BM_HANDLE hBuffer;
-
+ /* Pointer to implementation details within the mem_info */
PVRSRV_MEMBLK *psMemBlock;
IMG_BOOL bBMError;
psMemBlock = &(psMemInfo->sMemBlk);
-
+ /* BM supplied Device Virtual Address with physical backing RAM */
psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
bBMError = BM_Alloc (hDevMemHeap,
ui32Size,
&psMemInfo->ui32Flags,
IMG_CAST_TO_DEVVADDR_UINT(ui32Alignment),
+ pvPrivData,
+ ui32PrivDataLength,
+ ui32ChunkSize,
+ ui32NumVirtChunks,
+ ui32NumPhysChunks,
+ pabMapChunk,
&hBuffer);
if (!bBMError)
{
PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: BM_Alloc Failed"));
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* Fill in "Implementation dependant" section of mem info */
psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
-
+ /* Convert from BM_HANDLE to external IMG_HANDLE */
psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
-
+ /* Fill in the public fields of the MEM_INFO structure */
psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
- psMemInfo->uAllocSize = ui32Size;
+ if (ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ psMemInfo->uAllocSize = ui32ChunkSize * ui32NumVirtChunks;
+ }
+ else
+ {
+ psMemInfo->uAllocSize = ui32Size;
+ }
-
+ /* Clear the Backup buffer pointer as we do not have one at this point. We only allocate this as we are going up/down */
psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
+ /*
+ * Setup the output.
+ */
*ppsMemInfo = psMemInfo;
-
+ /*
+ * And I think we're done for now....
+ */
return (PVRSRV_OK);
}
-static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, IMG_BOOL bFromAllocator)
+static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin)
{
BM_HANDLE hBuffer;
hBuffer = psMemInfo->sMemBlk.hBuffer;
-
- if (bFromAllocator)
- BM_Free(hBuffer, psMemInfo->ui32Flags);
- else
- BM_FreeExport(hBuffer, psMemInfo->ui32Flags);
+ switch(eCallbackOrigin)
+ {
+ case PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR:
+ BM_Free(hBuffer, psMemInfo->ui32Flags);
+ break;
+ case PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER:
+ BM_FreeExport(hBuffer, psMemInfo->ui32Flags);
+ break;
+ default:
+ break;
+ }
-
- if ((psMemInfo->pvSysBackupBuffer) && bFromAllocator)
+ if (psMemInfo->pvSysBackupBuffer &&
+ eCallbackOrigin == PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR)
{
-
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->uAllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
psMemInfo->pvSysBackupBuffer = IMG_NULL;
}
if (psMemInfo->ui32RefCount == 0)
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
-
return(PVRSRV_OK);
}
hBuffer = psMemInfo->sMemBlk.hBuffer;
-
BM_Free(hBuffer, psMemInfo->ui32Flags);
if(psMemInfo->pvSysBackupBuffer)
{
-
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->uAllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
psMemInfo->pvSysBackupBuffer = IMG_NULL;
}
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
-
return(PVRSRV_OK);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocSyncInfoKM
+
+ @Description
+
+ Allocates a sync info
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
IMG_HANDLE hDevMemContext,
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
- psKernelSyncInfo->ui32RefCount = 0;
-
+ eError = OSAtomicAlloc(&psKernelSyncInfo->pvRefCount);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to allocate atomic"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Get the devnode from the devheap */
pBMContext = (BM_CONTEXT*)hDevMemContext;
psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
-
+ /* and choose a heap for the syncinfo */
hSyncDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->ui32SyncHeapID].hDevMemHeap;
-
-
-
+ /*
+ Cache consistent flag would be unnecessary if the heap attributes were
+ changed to specify it.
+ */
eError = AllocDeviceMem(hDevCookie,
hSyncDevMemHeap,
PVRSRV_MEM_CACHE_CONSISTENT,
sizeof(PVRSRV_SYNC_DATA),
sizeof(IMG_UINT32),
+ IMG_NULL,
+ 0,
+ 0, 0, 0, IMG_NULL, /* Sparse mapping args, not required */
&psKernelSyncInfo->psSyncDataMemInfoKM);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+ OSAtomicFree(psKernelSyncInfo->pvRefCount);
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* init sync data */
psKernelSyncInfo->psSyncData = psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
psSyncData = psKernelSyncInfo->psSyncData;
psSyncData->ui32WriteOpsComplete = 0;
psSyncData->ui32ReadOpsPending = 0;
psSyncData->ui32ReadOpsComplete = 0;
+ psSyncData->ui32ReadOps2Pending = 0;
+ psSyncData->ui32ReadOps2Complete = 0;
psSyncData->ui32LastOpDumpVal = 0;
psSyncData->ui32LastReadOpDumpVal = 0;
+ psSyncData->ui64LastWrite = 0;
#if defined(PDUMP)
PDUMPCOMMENT("Allocating kernel sync object");
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->sReadOps2CompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOps2Complete);
psKernelSyncInfo->ui32UID = g_ui32SyncUID++;
-
+ /* syncinfo meminfo has no syncinfo! */
psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = IMG_NULL;
-
+ OSAtomicInc(psKernelSyncInfo->pvRefCount);
+
+ /* return result */
*ppsKernelSyncInfo = psKernelSyncInfo;
return PVRSRV_OK;
}
-
IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+IMG_VOID PVRSRVAcquireSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
{
- PVRSRV_ERROR eError;
+ OSAtomicInc(psKernelSyncInfo->pvRefCount);
+}
- if (psKernelSyncInfo->ui32RefCount != 0)
- {
- PVR_DPF((PVR_DBG_ERROR, "oops: sync info ref count not zero at destruction"));
-
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
+/*!
+******************************************************************************
- eError = FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
- (IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
-
+ @Function PVRSRVFreeSyncInfoKM
- return eError;
-}
+ @Description
-static IMG_VOID freeWrapped(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
-{
- IMG_HANDLE hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+ Frees a sync info
-
- if(psMemInfo->sMemBlk.psIntSysPAddr)
- {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
- psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
- }
+ @Return PVRSRV_ERROR :
- if(hOSWrapMem)
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVReleaseSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+ if (OSAtomicDecAndTest(psKernelSyncInfo->pvRefCount))
{
- OSReleasePhysPageAddr(hOSWrapMem);
+ FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+
+ /* Catch anyone who is trying to access the freed structure */
+ psKernelSyncInfo->psSyncDataMemInfoKM = IMG_NULL;
+ psKernelSyncInfo->psSyncData = IMG_NULL;
+ OSAtomicFree(psKernelSyncInfo->pvRefCount);
+ (IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+ /*not nulling pointer, copy on stack*/
}
}
+/*!
+******************************************************************************
-#if defined (PVRSRV_FLUSH_KERNEL_OPS_LAST_ONLY)
-static
-PVRSRV_ERROR _PollUntilAtLeast(volatile IMG_UINT32* pui32WatchedValue,
- IMG_UINT32 ui32MinimumValue,
- IMG_UINT32 ui32Waitus,
- IMG_UINT32 ui32Tries)
-{
- PVRSRV_ERROR eError;
- IMG_INT32 iDiff;
+ @Function freeExternal
- for(;;)
- {
- SYS_DATA *psSysData = SysAcquireDataNoCheck();
- iDiff = *pui32WatchedValue - ui32MinimumValue;
+ @Description
- if (iDiff >= 0)
- {
- eError = PVRSRV_OK;
- break;
- }
+ Code for freeing meminfo elements that are specific to external types memory
- if(!ui32Tries)
- {
- eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
- break;
- }
+ @Input psMemInfo : Kernel meminfo
- ui32Tries--;
+ @Return PVRSRV_ERROR :
-
- if (psSysData->psGlobalEventObject)
- {
- IMG_HANDLE hOSEventKM;
- if(psSysData->psGlobalEventObject)
- {
- eError = OSEventObjectOpenKM(psSysData->psGlobalEventObject, &hOSEventKM);
- if (eError |= PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,
- "_PollUntilAtLeast: OSEventObjectOpen failed"));
- goto Exit;
- }
- eError = OSEventObjectWaitKM(hOSEventKM);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,
- "_PollUntilAtLeast: PVRSRVEventObjectWait failed"));
- goto Exit;
- }
- eError = OSEventObjectCloseKM(psSysData->psGlobalEventObject, hOSEventKM);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,
- "_PollUntilAtLeast: OSEventObjectClose failed"));
- }
- }
- }
- }
-Exit:
- return eError;
-}
+******************************************************************************/
-static PVRSRV_ERROR FlushKernelOps(PVRSRV_SYNC_DATA *psSyncData)
+static IMG_VOID freeExternal(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
{
- PVRSRV_ERROR eError;
+ IMG_HANDLE hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
- if(!psSyncData)
+ /* free the page addr array if req'd */
+ if(psMemInfo->sMemBlk.psIntSysPAddr)
{
- PVR_DPF((PVR_DBG_ERROR, "FlushKernelOps: invalid psSyncData"));
- return PVRSRV_ERROR_INVALID_PARAMS;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+ psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
}
-
-
-
-
-
+ /* Mem type dependent stuff */
+ if (psMemInfo->memType == PVRSRV_MEMTYPE_WRAPPED)
+ {
+ if(hOSWrapMem)
+ {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ }
+ }
+#if defined(SUPPORT_ION)
+ else if (psMemInfo->memType == PVRSRV_MEMTYPE_ION)
+ {
+ if (hOSWrapMem)
+ {
+ IonUnimportBufferAndReleasePhysAddr(hOSWrapMem);
+ }
+ }
+#endif
+}
+/*!
+******************************************************************************
+ @Function FreeMemCallBackCommon
+ @Description
- eError = _PollUntilAtLeast(&psSyncData->ui32ReadOpsComplete,
- psSyncData->ui32ReadOpsPending,
- MAX_HW_TIME_US/WAIT_TRY_COUNT,
- WAIT_TRY_COUNT);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "FlushClientOps: Read ops pending timeout"));
- PVR_DBG_BREAK;
- return eError;
- }
+ Common code for freeing device mem (called for freeing, unwrapping and unmapping)
- eError = _PollUntilAtLeast(&psSyncData->ui32WriteOpsComplete,
- psSyncData->ui32WriteOpsPending,
- MAX_HW_TIME_US/WAIT_TRY_COUNT,
- WAIT_TRY_COUNT);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "FlushClientOps: Write ops pending timeout"));
- PVR_DBG_BREAK;
- }
+ @Input psMemInfo : Kernel meminfo
+ @Input ui32Param : packet size
+ @Input uibFromAllocatorParam : Are we being called by the original allocator?
- return eError;
-}
-#endif
+ @Return PVRSRV_ERROR :
-static PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
- IMG_UINT32 ui32Param,
- IMG_BOOL bFromAllocator)
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin)
{
PVRSRV_ERROR eError = PVRSRV_OK;
PVR_UNREFERENCED_PARAMETER(ui32Param);
-
- psMemInfo->ui32RefCount--;
+ /* decrement the refcount */
+ PVRSRVKernelMemInfoDecRef(psMemInfo);
-
- if(((psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED) != 0) && (bFromAllocator == IMG_TRUE))
+ /* check no other processes has this meminfo mapped */
+ if (psMemInfo->ui32RefCount == 0)
{
+ if((psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED) != 0)
+ {
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hMemInfo = 0;
+ IMG_SID hMemInfo = 0;
#else
- IMG_HANDLE hMemInfo = IMG_NULL;
+ IMG_HANDLE hMemInfo = IMG_NULL;
#endif
-
- eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
- &hMemInfo,
- psMemInfo,
- PVRSRV_HANDLE_TYPE_MEM_INFO);
- if(eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: can't find exported meminfo in the global handle list"));
- return eError;
- }
-
-
- eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
- hMemInfo,
- PVRSRV_HANDLE_TYPE_MEM_INFO);
- if(eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: PVRSRVReleaseHandle failed for exported meminfo"));
- return eError;
- }
- }
-
-
- if (psMemInfo->ui32RefCount == 0)
- {
-#if defined (PVRSRV_FLUSH_KERNEL_OPS_LAST_ONLY)
- if (psMemInfo->psKernelSyncInfo)
- {
- if (psMemInfo->sShareMemWorkaround.bInUse)
+ /* find the handle */
+ eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &hMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
{
-
- if (BM_XProcWorkaroundGetRefCount(psMemInfo->sShareMemWorkaround.ui32ShareIndex)
- == 1)
- {
- FlushKernelOps(psMemInfo->psKernelSyncInfo->psSyncData);
- }
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: can't find exported meminfo in the global handle list"));
+ return eError;
}
- else
- {
-
-
-
-
-
-
-
- FlushKernelOps(psMemInfo->psKernelSyncInfo->psSyncData);
+ /* release the handle */
+ eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ hMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: PVRSRVReleaseHandle failed for exported meminfo"));
+ return eError;
}
}
-#endif
+
switch(psMemInfo->memType)
{
-
+ /* Fall through: Free only what we should for each memory type */
case PVRSRV_MEMTYPE_WRAPPED:
- freeWrapped(psMemInfo);
+ case PVRSRV_MEMTYPE_ION:
+ freeExternal(psMemInfo);
case PVRSRV_MEMTYPE_DEVICE:
+ case PVRSRV_MEMTYPE_DEVICECLASS:
if (psMemInfo->psKernelSyncInfo)
{
- psMemInfo->psKernelSyncInfo->ui32RefCount--;
-
- if (psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
- {
- eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
}
- case PVRSRV_MEMTYPE_DEVICECLASS:
break;
default:
PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: Unknown memType"));
}
}
-
+ /*
+ * FreeDeviceMem2 will do the right thing, freeing
+ * the virtual memory info when the allocator calls
+ * but only releaseing the physical pages when everyone
+ * is done.
+ */
+
if (eError == PVRSRV_OK)
{
- eError = FreeDeviceMem2(psMemInfo, bFromAllocator);
+ eError = FreeDeviceMem2(psMemInfo, eCallbackOrigin);
}
return eError;
}
+/*!
+******************************************************************************
+
+ @Function FreeDeviceMemCallBack
+
+ @Description
+
+ ResMan call back to free device memory
+
+ @Input pvParam : data packet
+ @Input ui32Param : packet size
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static PVRSRV_ERROR FreeDeviceMemCallBack(IMG_PVOID pvParam,
IMG_UINT32 ui32Param,
IMG_BOOL bDummy)
PVR_UNREFERENCED_PARAMETER(bDummy);
- return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+ return FreeMemCallBackCommon(psMemInfo, ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVFreeDeviceMemKM
+
+ @Description
+
+ Frees memory allocated with PVRAllocDeviceMem, including the mem_info structure
+
+ @Input psMemInfo :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
PVRSRV_KERNEL_MEM_INFO *psMemInfo)
}
else
{
-
+ /* PVRSRV_MEM_NO_RESMAN */
eError = FreeDeviceMemCallBack(psMemInfo, 0, CLEANUP_WITH_POLL);
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocDeviceMemKM
+
+ @Description
+
+ Allocates device memory
+
+ @Input hDevCookie :
+ @Input psPerProc : Per-process data
+ @Input hDevMemHeap
+ @Input ui32Flags : Some combination of PVRSRV_MEM_ flags
+ @Input ui32Size : Number of bytes to allocate
+ @Input ui32Alignment :
+ @Output **ppsMemInfo : On success, receives a pointer to the created MEM_INFO structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
- PVRSRV_PER_PROCESS_DATA *psPerProc,
- IMG_HANDLE hDevMemHeap,
- IMG_UINT32 ui32Flags,
- IMG_SIZE_T ui32Size,
- IMG_SIZE_T ui32Alignment,
- PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
{
PVRSRV_KERNEL_MEM_INFO *psMemInfo;
PVRSRV_ERROR eError;
IMG_HANDLE hDevMemContext;
if (!hDevMemHeap ||
- (ui32Size == 0))
+ ((ui32Size == 0) && ((ui32Flags & PVRSRV_MEM_SPARSE) == 0)) ||
+ (((ui32ChunkSize == 0) || (ui32NumVirtChunks == 0) || (ui32NumPhysChunks == 0) ||
+ (pabMapChunk == IMG_NULL )) && (ui32Flags & PVRSRV_MEM_SPARSE)))
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* Sprase alloc input validation */
+ if (ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ IMG_UINT32 i;
+ IMG_UINT32 ui32Check = 0;
+
+ if (ui32NumVirtChunks < ui32NumPhysChunks)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ for (i=0;i<ui32NumVirtChunks;i++)
+ {
+ if (pabMapChunk[i])
+ {
+ ui32Check++;
+ }
+ }
+ if (ui32NumPhysChunks != ui32Check)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ /* FIXME: At the moment we force CACHETYPE override allocations to
+ * be multiples of PAGE_SIZE and page aligned. If the RA/BM
+ * is fixed, this limitation can be removed.
+ *
+ * INTEGRATION_POINT: HOST_PAGESIZE() is not correct, should be device-specific.
+ */
if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
{
-
+ /* PRQA S 3415 1 */ /* order of evaluation is not important */
if (((ui32Size % HOST_PAGESIZE()) != 0) ||
((ui32Alignment % HOST_PAGESIZE()) != 0))
{
ui32Flags,
ui32Size,
ui32Alignment,
+ pvPrivData,
+ ui32PrivDataLength,
+ ui32ChunkSize,
+ ui32NumVirtChunks,
+ ui32NumPhysChunks,
+ pabMapChunk,
&psMemInfo);
if (eError != PVRSRV_OK)
}
else
{
-
-
-
+ /*
+ allocate a syncinfo but don't register with resman
+ because the holding devicemem will handle the syncinfo
+ */
psBMHeap = (BM_HEAP*)hDevMemHeap;
hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
eError = PVRSRVAllocSyncInfoKM(hDevCookie,
{
goto free_mainalloc;
}
- psMemInfo->psKernelSyncInfo->ui32RefCount++;
}
-
+ /*
+ * Setup the output.
+ */
*ppsMemInfo = psMemInfo;
if (ui32Flags & PVRSRV_MEM_NO_RESMAN)
}
else
{
-
+ /* register with the resman */
psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICEMEM_ALLOCATION,
psMemInfo,
&FreeDeviceMemCallBack);
if (psMemInfo->sMemBlk.hResItem == IMG_NULL)
{
-
eError = PVRSRV_ERROR_OUT_OF_MEMORY;
goto free_mainalloc;
}
}
-
- psMemInfo->ui32RefCount++;
+ /* increment the refcount */
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE;
-
+ /*
+ * And I think we're done for now....
+ */
return (PVRSRV_OK);
free_mainalloc:
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
FreeDeviceMem(psMemInfo);
return eError;
}
+#if defined(SUPPORT_ION)
+static PVRSRV_ERROR IonUnmapCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ return FreeMemCallBackCommon(psMemInfo, ui32Param, PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVMapIonHandleKM
+
+ @Description
+
+ Map an ION buffer into the specified device memory context
+
+ @Input psPerProc : PerProcess data
+ @Input hDevCookie : Device node cookie
+ @Input hDevMemContext : Device memory context cookie
+ @Input hIon : Handle to ION buffer
+ @Input ui32Flags : Mapping flags
+ @Input ui32Size : Mapping size
+ @Output ppsKernelMemInfo: Output kernel meminfo if successful
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVMapIonHandleKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hIon,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProcEnv = PVRSRVProcessPrivateData(psPerProc);
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_KERNEL_MEM_INFO *psNewKernelMemInfo;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_SYS_PHYADDR *pasSysPhysAddr;
+ PVRSRV_MEMBLK *psMemBlock;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDevMemHeap = IMG_NULL;
+ IMG_HANDLE hPriv;
+ BM_HANDLE hBuffer;
+ IMG_UINT32 ui32HeapCount;
+ IMG_UINT32 ui32PageCount;
+ IMG_UINT32 i;
+ IMG_BOOL bAllocSync = (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)?IMG_FALSE:IMG_TRUE;
+
+ if ((hDevCookie == IMG_NULL) || (ui32Size == 0)
+ || (hDevMemContext == IMG_NULL) || (ppsKernelMemInfo == IMG_NULL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid params", __FUNCTION__));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psNewKernelMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Failed to alloc memory for block", __FUNCTION__));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psNewKernelMemInfo, 0, sizeof(PVRSRV_KERNEL_MEM_INFO));
+
+ /* Choose the heap to map to */
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+ for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32IonHeapID)
+ {
+ if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+ {
+ if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+ }
+ else
+ {
+ hDevMemHeap = IMG_NULL;
+ }
+ }
+ else
+ {
+ hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+ }
+ break;
+ }
+ }
+
+ if (hDevMemHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get ION heap", __FUNCTION__));
+ eError = PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO;
+ goto exitFailedHeap;
+ }
+
+ /* Import the ION buffer into our ion_client and DMA map it */
+ eError = IonImportBufferAndAquirePhysAddr(psPerProcEnv->psIONClient,
+ hIon,
+ &ui32PageCount,
+ &pasSysPhysAddr,
+ &psNewKernelMemInfo->pvLinAddrKM,
+ &hPriv);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get ion buffer/buffer phys addr", __FUNCTION__));
+ goto exitFailedHeap;
+ }
+
+ /* Wrap the returned addresses into our memory context */
+ if (!BM_Wrap(hDevMemHeap,
+ ui32Size,
+ 0,
+ IMG_FALSE,
+ pasSysPhysAddr,
+ IMG_NULL,
+ &ui32Flags, /* This function clobbers our bits in ui32Flags */
+ &hBuffer))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to wrap ion buffer", __FUNCTION__));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto exitFailedWrap;
+ }
+
+ /* Fill in "Implementation dependant" section of mem info */
+ psMemBlock = &psNewKernelMemInfo->sMemBlk;
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+ psMemBlock->hBuffer = (IMG_HANDLE) hBuffer;
+ psMemBlock->hOSWrapMem = hPriv; /* Saves creating a new element as we know hOSWrapMem will not be used */
+ psMemBlock->psIntSysPAddr = pasSysPhysAddr;
+
+ psNewKernelMemInfo->ui32Flags = ui32Flags;
+ psNewKernelMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psNewKernelMemInfo->uAllocSize = ui32Size;
+ psNewKernelMemInfo->memType = PVRSRV_MEMTYPE_ION;
+ PVRSRVKernelMemInfoIncRef(psNewKernelMemInfo);
+
+ /* Clear the Backup buffer pointer as we do not have one at this point. We only allocate this as we are going up/down */
+ psNewKernelMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+ if (!bAllocSync)
+ {
+ psNewKernelMemInfo->psKernelSyncInfo = IMG_NULL;
+ }
+ else
+ {
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psNewKernelMemInfo->psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ goto exitFailedSync;
+ }
+ }
+
+ /* register with the resman */
+ psNewKernelMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_ION,
+ psNewKernelMemInfo,
+ 0,
+ &IonUnmapCallback);
+ if (psNewKernelMemInfo->sMemBlk.hResItem == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto exitFailedResman;
+ }
+
+ psNewKernelMemInfo->memType = PVRSRV_MEMTYPE_ION;
+
+ *ppsKernelMemInfo = psNewKernelMemInfo;
+ return PVRSRV_OK;
+
+exitFailedResman:
+ if (psNewKernelMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psNewKernelMemInfo->psKernelSyncInfo, psNewKernelMemInfo);
+ }
+exitFailedSync:
+ BM_Free(hBuffer, ui32Flags);
+exitFailedWrap:
+ IonUnimportBufferAndReleasePhysAddr(hPriv);
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(IMG_SYS_PHYADDR) * ui32PageCount,
+ pasSysPhysAddr,
+ IMG_NULL);
+exitFailedHeap:
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psNewKernelMemInfo,
+ IMG_NULL);
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVUnmapIonHandleKM
+
+ @Description
+
+ Frees an ion buffer mapped with PVRSRVMapIonHandleKM, including the mem_info structure
+
+ @Input psMemInfo :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapIonHandleKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+}
+#endif /* SUPPORT_ION */
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDissociateDeviceMemKM
+ @Description
+
+ Dissociates memory from the process that allocates it. Intended for
+ transfering the ownership of device memory from a particular process
+ to the kernel.
+
+ @Input psMemInfo :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie,
PVRSRV_KERNEL_MEM_INFO *psMemInfo)
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetFreeDeviceMemKM
+
+ @Description
+
+ Determines how much memory remains available in the system with the specified
+ capabilities.
+
+ @Input ui32Flags :
+
+ @Output pui32Total :
+
+ @Output pui32Free :
+
+ @Output pui32LargestBlock :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
IMG_SIZE_T *pui32Total,
IMG_SIZE_T *pui32Free,
IMG_SIZE_T *pui32LargestBlock)
{
-
+ /* TO BE IMPLEMENTED */
PVR_UNREFERENCED_PARAMETER(ui32Flags);
PVR_UNREFERENCED_PARAMETER(pui32Total);
+/*!
+******************************************************************************
+ @Function PVRSRVUnwrapExtMemoryKM
+
+ @Description On last unwrap of a given meminfo, unmaps physical pages from a
+ wrapped allocation, and frees the associated device address space.
+ Note: this can only unmap memory mapped by PVRSRVWrapExtMemory
+
+ @Input psMemInfo - mem info describing the wrapped allocation
+ @Return None
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
{
}
+/*!
+******************************************************************************
+ @Function UnwrapExtMemoryCallBack
+
+ @Description Resman callback to unwrap memory
+
+ @Input pvParam - opaque void ptr param
+ @Input ui32Param - opaque unsigned long param
+ @Return PVRSRV_ERROR
+******************************************************************************/
static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID pvParam,
IMG_UINT32 ui32Param,
IMG_BOOL bDummy)
PVR_UNREFERENCED_PARAMETER(bDummy);
- return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+ return FreeMemCallBackCommon(psMemInfo, ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
}
+/*!
+******************************************************************************
+ @Function PVRSRVWrapExtMemoryKM
+
+ @Description Allocates a Device Virtual Address in the shared mapping heap
+ and maps physical pages into that allocation. Note, if the pages are
+ already mapped into the heap, the existing allocation is returned.
+
+ @Input hDevCookie - Device cookie
+ @Input psPerProc - Per-process data
+ @Input hDevMemContext - device memory context
+ @Input uByteSize - Size of allocation
+ @Input uPageOffset - Offset into the first page of the memory to be wrapped
+ @Input bPhysContig - whether the underlying memory is physically contiguous
+ @Input psExtSysPAddr - The list of Device Physical page addresses
+ @Input pvLinAddr - ptr to buffer to wrap
+ @Output ppsMemInfo - mem info describing the wrapped allocation
+ @Return None
+******************************************************************************/
+
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
PVRSRV_PER_PROCESS_DATA *psPerProc,
if(pvLinAddr)
{
-
+ /* derive the page offset from the cpu ptr (in case it's not supplied) */
uPageOffset = (IMG_UINTPTR_T)pvLinAddr & (ui32HostPageSize - 1);
-
+ /* get the pagecount and the page aligned base ptr */
uPageCount = HOST_PAGEALIGN(uByteSize + uPageOffset) / ui32HostPageSize;
pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvLinAddr - uPageOffset);
-
+ /* allocate array of SysPAddr to hold page addresses */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
uPageCount * sizeof(IMG_SYS_PHYADDR),
(IMG_VOID **)&psIntSysPAddr, IMG_NULL,
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
- eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;//FIXME: need better error code
goto ErrorExitPhase1;
}
-
+ /* replace the supplied page address list */
psExtSysPAddr = psIntSysPAddr;
-
-
+ /* assume memory is not physically contiguous;
+ we shouldn't trust what the user says here
+ */
bPhysContig = IMG_FALSE;
}
- else
- {
-
- }
-
+ /* Choose the heap to map to */
psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo;
psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
{
if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
{
-
if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
{
hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
goto ErrorExitPhase3;
}
-
+ /* Fill in "Implementation dependant" section of mem info */
psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
psMemBlock->hOSWrapMem = hOSWrapMem;
psMemBlock->psIntSysPAddr = psIntSysPAddr;
-
+ /* Convert from BM_HANDLE to external IMG_HANDLE */
psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
-
+ /* Fill in the public fields of the MEM_INFO structure */
psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
psMemInfo->uAllocSize = uByteSize;
-
-
+ /* Clear the Backup buffer pointer as we do not have one at this point.
+ We only allocate this as we are going up/down
+ */
psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
-
-
+ /*
+ allocate a syncinfo but don't register with resman
+ because the holding devicemem will handle the syncinfo
+ */
psBMHeap = (BM_HEAP*)hDevMemHeap;
hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
eError = PVRSRVAllocSyncInfoKM(hDevCookie,
goto ErrorExitPhase4;
}
- psMemInfo->psKernelSyncInfo->ui32RefCount++;
-
-
- psMemInfo->ui32RefCount++;
+ /* increment the refcount */
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED;
-
+ /* Register Resource */
psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICEMEM_WRAP,
psMemInfo,
0,
&UnwrapExtMemoryCallBack);
-
+ /* return the meminfo */
*ppsMemInfo = psMemInfo;
return PVRSRV_OK;
-
+ /* error handling: */
ErrorExitPhase4:
if(psMemInfo)
{
FreeDeviceMem(psMemInfo);
-
-
-
+ /*
+ FreeDeviceMem will free the meminfo so set
+ it to NULL to avoid double free below
+ */
psMemInfo = IMG_NULL;
}
if(psMemInfo)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
}
ErrorExitPhase2:
if(psIntSysPAddr)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, uPageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL);
-
+ /*not nulling shared pointer, uninitialized to this point*/
}
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVUnmapDeviceMemoryKM
+
+ @Description
+ Unmaps an existing allocation previously mapped by PVRSRVMapDeviceMemory
+
+ @Input psMemInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
{
}
+/*!
+******************************************************************************
+ @Function UnmapDeviceMemoryCallBack
+
+ @Description Resman callback to unmap memory memory previously mapped
+ from one allocation to another
+
+ @Input pvParam - opaque void ptr param
+ @Input ui32Param - opaque unsigned long param
+ @Return PVRSRV_ERROR
+******************************************************************************/
static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam,
IMG_UINT32 ui32Param,
IMG_BOOL bDummy)
if( psMapData->psMemInfo->psKernelSyncInfo )
{
- psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount--;
- if (psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
- {
- eError = PVRSRVFreeSyncInfoKM(psMapData->psMemInfo->psKernelSyncInfo);
- if(eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free sync info"));
- return eError;
- }
- }
+ PVRSRVKernelSyncInfoDecRef(psMapData->psMemInfo->psKernelSyncInfo, psMapData->psMemInfo);
}
eError = FreeDeviceMem(psMapData->psMemInfo);
return eError;
}
-
- eError = FreeMemCallBackCommon(psMapData->psSrcMemInfo, 0, IMG_FALSE);
+ /* This will only free the src psMemInfo if we hold the last reference */
+ eError = FreeMemCallBackCommon(psMapData->psSrcMemInfo, 0,
+ PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVMapDeviceMemoryKM
+
+ @Description
+ Maps an existing allocation to a specific device address space and heap
+ Note: it's valid to map from one physical device to another
+
+ @Input psPerProc : Per-process data
+ @Input psSrcMemInfo
+ @Input hDstDevMemHeap
+ @Input ppsDstMemInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
IMG_VOID *pvPageAlignedCPUVAddr;
RESMAN_MAP_DEVICE_MEM_DATA *psMapData = IMG_NULL;
-
+ /* check params */
if(!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters"));
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* initialise the Dst Meminfo to NULL*/
*ppsDstMemInfo = IMG_NULL;
uPageOffset = psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1);
uPageCount = HOST_PAGEALIGN(psSrcMemInfo->uAllocSize + uPageOffset) / ui32HostPageSize;
pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psSrcMemInfo->pvLinAddrKM - uPageOffset);
-
-
-
-
+ /*
+ allocate array of SysPAddr to hold SRC allocation page addresses
+ */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
uPageCount*sizeof(IMG_SYS_PHYADDR),
(IMG_VOID **)&psSysPAddr, IMG_NULL,
psBuf = psSrcMemInfo->sMemBlk.hBuffer;
-
+ /* get the device node */
psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode;
-
+ /* build a list of physical page addresses */
sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - IMG_CAST_TO_DEVVADDR_UINT(uPageOffset);
for(i=0; i<uPageCount; i++)
{
BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
-
+ /* save the address */
psSysPAddr[i] = SysDevPAddrToSysPAddr (psDeviceNode->sDevId.eDeviceType, sDevPAddr);
-
+ /* advance the DevVaddr one page */
sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize);
}
-
+ /* allocate the resman map data */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(RESMAN_MAP_DEVICE_MEM_DATA),
(IMG_VOID **)&psMapData, IMG_NULL,
goto ErrorExit;
}
-
+ /* Fill in "Implementation dependant" section of mem info */
psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
-
+ /* Convert from BM_HANDLE to external IMG_HANDLE */
psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
-
+ /* Store page list */
psMemBlock->psIntSysPAddr = psSysPAddr;
-
+ /* patch up the CPU VAddr into the meminfo */
psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM;
-
+ /* Fill in the public fields of the MEM_INFO structure */
psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
psMemInfo->uAllocSize = psSrcMemInfo->uAllocSize;
psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo;
-
+ /* reference the same ksi that the original meminfo referenced */
if(psMemInfo->psKernelSyncInfo)
{
- psMemInfo->psKernelSyncInfo->ui32RefCount++;
+ PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo);
}
-
-
+ /* Clear the Backup buffer pointer as we do not have one at this point.
+ We only allocate this as we are going up/down
+ */
psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
- psMemInfo->ui32RefCount++;
+ /* increment our refcount */
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
-
- psSrcMemInfo->ui32RefCount++;
+ /* increment the src refcount */
+ PVRSRVKernelMemInfoIncRef(psSrcMemInfo);
-
+ /* Tell the buffer manager about the export */
BM_Export(psSrcMemInfo->sMemBlk.hBuffer);
psMemInfo->memType = PVRSRV_MEMTYPE_MAPPED;
-
+ /* setup the resman map data */
psMapData->psMemInfo = psMemInfo;
psMapData->psSrcMemInfo = psSrcMemInfo;
-
+ /* Register Resource */
psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICEMEM_MAPPING,
psMapData,
return PVRSRV_OK;
-
+ /* error handling: */
ErrorExit:
if(psSysPAddr)
{
-
+ /* Free the page address list */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psSysPAddr, IMG_NULL);
-
+ /*not nulling shared pointer, holding structure could be not initialized*/
}
if(psMemInfo)
{
-
+ /* Free the page address list */
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
-
+ /*not nulling shared pointer, holding structure could be not initialized*/
}
if(psMapData)
{
-
+ /* Free the resman map data */
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
}
return eError;
}
+/*!
+******************************************************************************
+ @Function PVRSRVUnmapDeviceClassMemoryKM
+
+ @Description unmaps physical pages from devices address space at a specified
+ Device Virtual Address.
+ Note: this can only unmap memory mapped by
+ PVRSRVMapDeviceClassMemoryKM
+
+ @Input psMemInfo - mem info describing the device virtual address
+ to unmap RAM from
+ @Return None
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
{
}
+/*!
+******************************************************************************
+ @Function UnmapDeviceClassMemoryCallBack
+
+ @Description Resman callback to unmap device class memory
+
+ @Input pvParam - opaque void ptr param
+ @Input ui32Param - opaque unsigned long param
+ @Return PVRSRV_ERROR
+******************************************************************************/
static PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(IMG_PVOID pvParam,
IMG_UINT32 ui32Param,
IMG_BOOL bDummy)
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_MAPINFO), psDCMapInfo, IMG_NULL);
- return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+ return FreeMemCallBackCommon(psMemInfo, ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
}
+/*!
+******************************************************************************
+ @Function PVRSRVMapDeviceClassMemoryKM
+
+ @Description maps physical pages for DeviceClass buffers into a devices
+ address space at a specified and pre-allocated Device
+ Virtual Address
+
+ @Input psPerProc - Per-process data
+ @Input hDevMemContext - Device memory context
+ @Input hDeviceClassBuffer - Device Class Buffer (Surface) handle
+ @Input hDevMemContext - device memory context to which mapping
+ is made
+ @Output ppsMemInfo - mem info describing the mapped memory
+ @Output phOSMapInfo - OS specific mapping information
+ @Return None
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevMemContext,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* allocate resman storage structure */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_DC_MAPINFO),
(IMG_VOID **)&psDCMapInfo, IMG_NULL,
psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ /*
+ call into external driver to get info so we can map a meminfo
+ Notes:
+ It's expected that third party displays will only support
+ physically contiguous display surfaces. However, it's possible
+ a given display may have an MMU and therefore support non-contig'
+ display surfaces.
+
+ If surfaces are contiguous, ext driver should return:
+ - a CPU virtual address, or IMG_NULL where the surface is not mapped to CPU
+ - (optional) an OS Mapping handle for KM->UM surface mapping
+ - the size in bytes
+ - a single system physical address
+
+ If surfaces are non-contiguous, ext driver should return:
+ - a CPU virtual address
+ - (optional) an OS Mapping handle for KM->UM surface mapping
+ - the size in bytes (must be multiple of 4kB)
+ - a list of system physical addresses (at 4kB intervals)
+ */
eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice,
psDeviceClassBuffer->hExtBuffer,
&psSysPAddr,
goto ErrorExitPhase1;
}
-
+ /* Choose the heap to map to */
psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext;
psDeviceNode = psBMContext->psDeviceNode;
psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
{
if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
{
-
if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
{
hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
goto ErrorExitPhase1;
}
-
+ /* Only need lower 12 bits of the cpu addr - don't care what size a void* is */
ui32Offset = ((IMG_UINTPTR_T)pvCPUVAddr) & (ui32PageSize - 1);
pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - ui32Offset);
if (!bBMError)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed"));
-
+ /*not nulling pointer, out of scope*/
eError = PVRSRV_ERROR_BAD_MAPPING;
goto ErrorExitPhase2;
}
-
+ /* Fill in "Implementation dependant" section of mem info */
psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
-
+ /* Convert from BM_HANDLE to external IMG_HANDLE */
psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
-
-
+ /* patch up the CPU VAddr into the meminfo - use the address from the BM, not the one from the deviceclass
+ api, to ensure user mode mapping is possible
+ */
psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
-
+ /* Fill in the public fields of the MEM_INFO structure */
psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
psMemInfo->uAllocSize = uByteSize;
psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
-
+ PVR_ASSERT(psMemInfo->psKernelSyncInfo != IMG_NULL);
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
+ /* Clear the Backup buffer pointer as we do not have one at this point.
+ We only allocate this as we are going up/down
+ */
psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
+ /* setup DCMapInfo */
psDCMapInfo->psMemInfo = psMemInfo;
psDCMapInfo->psDeviceClassBuffer = psDeviceClassBuffer;
if(psDCMapInfo->ui32TilingStride > 0)
{
-
+ /* try to acquire a tiling range on this device */
eError = psDeviceNode->pfnAllocMemTilingRange(psDeviceNode,
psMemInfo,
psDCMapInfo->ui32TilingStride,
}
#endif
-
+ /* Register Resource */
psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
psDCMapInfo,
&UnmapDeviceClassMemoryCallBack);
(psDeviceClassBuffer->ui32MemMapRefCount)++;
- psMemInfo->ui32RefCount++;
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS;
-
+ /* return the meminfo */
*ppsMemInfo = psMemInfo;
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
- PDUMPCOMMENT("Dump display surface");
- PDUMPMEM(IMG_NULL, psMemInfo, ui32Offset, psMemInfo->uAllocSize, PDUMP_FLAGS_CONTINUOUS, ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping);
+ /* If the 3PDD supplies a kernel virtual address, we can PDUMP it */
+ if(psMemInfo->pvLinAddrKM)
+ {
+ /* FIXME:
+ * Initialise the display surface here when it is mapped into Services.
+ * Otherwise there is a risk that pdump toolchain will assign previously
+ * used physical pages, leading to visual artefacts on the unrendered surface
+ * (e.g. during LLS rendering).
+ *
+ * A better method is to pdump the allocation from the DC driver, so the
+ * BM_Wrap pdumps only the virtual memory which better represents the driver
+ * behaviour.
+ */
+ PDUMPCOMMENT("Dump display surface");
+ PDUMPMEM(IMG_NULL, psMemInfo, ui32Offset, psMemInfo->uAllocSize, PDUMP_FLAGS_CONTINUOUS, ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping);
+ }
#endif
return PVRSRV_OK;
ErrorExitPhase3:
if(psMemInfo)
{
- FreeDeviceMem(psMemInfo);
-
-
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
+ FreeDeviceMem(psMemInfo);
+ /*
+ FreeDeviceMem will free the meminfo so set
+ it to NULL to avoid double free below
+ */
psMemInfo = IMG_NULL;
}
#endif
}
+/******************************************************************************
+ End of file (devicemem.c)
+******************************************************************************/
+
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Resource Handle Manager
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource handle management
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+/* See handle.h for a description of the handle API. */
+
+/*
+ * There is no locking here. It is assumed the code is used in a single
+ * threaded environment. In particular, it is assumed that the code will
+ * never be called from an interrupt handler.
+ *
+ * The implmentation supports movable handle structures, allowing the address
+ * of a handle structure to change without having to fix up pointers in
+ * any of the handle structures. For example, the linked list mechanism
+ * used to link subhandles together uses handle array indices rather than
+ * pointers to the structures themselves.
+ */
+
#include <stddef.h>
#include "services_headers.h"
#define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+/* Valid handles are never NULL, but handle array indices are based from 0 */
#if defined (SUPPORT_SID_INTERFACE)
#define INDEX_TO_HANDLE(i) ((IMG_SID)((i) + 1))
#define HANDLE_TO_INDEX(h) ((IMG_UINT32)(h) - 1)
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+/*
+ * Linked list structure. Used for both the list head and list items.
+ * Array indices, rather than pointers, are used to point to the next and
+ * previous items on the list.
+ */
struct sHandleList
{
IMG_UINT32 ui32Prev;
INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
};
+/* Handle structure */
struct sHandle
{
-
+ /* Handle type */
PVRSRV_HANDLE_TYPE eType;
-
+ /* Pointer to the data that the handle represents */
IMG_VOID *pvData;
-
+ /*
+ * When handles are on the free list, the value of the "next index
+ * plus one field" has the following meaning:
+ * zero - next handle is the one that follows this one,
+ * nonzero - the index of the next handle is the value minus one.
+ * This scheme means handle space can be initialised to all zeros.
+ *
+ * When this field is used to link together handles on a list
+ * other than the free list, zero indicates the end of the
+ * list, with nonzero the same as above.
+ */
IMG_UINT32 ui32NextIndexPlusOne;
-
+ /* Internal flags */
enum ePVRSRVInternalHandleFlag eInternalFlag;
-
+ /* Flags specified when the handle was allocated */
PVRSRV_HANDLE_ALLOC_FLAG eFlag;
-
+ /* Index of this handle in the handle array */
IMG_UINT32 ui32Index;
-
+ /* List head for subhandles of this handle */
struct sHandleList sChildren;
-
+ /* List entry for sibling subhandles */
struct sHandleList sSiblings;
};
+/* Handle array index structure.
+ * The handle array is an array of index structures, reallocated as the number of
+ * handles increases.
+ * NOTE: There is one index structure per block of handles.
+ */
struct sHandleIndex
{
-
+ /* Pointer to first handle structure in the block */
struct sHandle *psHandle;
-
+ /* Block allocation cookie returned from OSAllocMem for the block of handles */
IMG_HANDLE hBlockAlloc;
-
+ /* Number of free handles in block */
IMG_UINT32 ui32FreeHandBlockCount;
};
struct _PVRSRV_HANDLE_BASE_
{
-
+ /* Handle returned from OSAllocMem for handle base allocation */
IMG_HANDLE hBaseBlockAlloc;
-
+ /* Handle returned from OSAllocMem for handle array allocation */
IMG_HANDLE hArrayBlockAlloc;
-
+ /* Pointer to array of pointers to handle structures */
struct sHandleIndex *psHandleArray;
-
+ /*
+ * Pointer to handle hash table.
+ * The hash table is used to do reverse lookups, converting data
+ * pointers to handles.
+ */
HASH_TABLE *psHashTab;
-
+ /* Number of free handles */
IMG_UINT32 ui32FreeHandCount;
-
+ /*
+ * If purging is not enabled, this is the array index of first free
+ * handle.
+ * If purging is enabled, this is the index to start searching for
+ * a free handle from. In this case it is usually zero, unless
+ * the handle array size has been increased due to lack of
+ * handles.
+ */
IMG_UINT32 ui32FirstFreeIndex;
-
+ /* Maximum handle index, plus one */
IMG_UINT32 ui32MaxIndexPlusOne;
-
+ /* Total number of handles, free and allocated */
IMG_UINT32 ui32TotalHandCount;
-
+ /*
+ * Index of the last free index, plus one. Not used if purging
+ * is enabled.
+ */
IMG_UINT32 ui32LastFreeIndexPlusOne;
-
+ /* Size of current handle batch, or zero if batching not enabled */
IMG_UINT32 ui32HandBatchSize;
-
+ /* Number of handles prior to start of current batch */
IMG_UINT32 ui32TotalHandCountPreBatch;
-
+ /* Index of first handle in batch, plus one */
IMG_UINT32 ui32FirstBatchIndexPlusOne;
-
+ /* Number of handle allocation failures in batch */
IMG_UINT32 ui32BatchHandAllocFailures;
-
+ /* Purging enabled.
+ * If purging is enabled, the size of the table can be reduced
+ * by removing free space at the end of the table. To make
+ * purging more likely to succeed, handles are allocated as
+ * far to the front of the table as possible. The first free
+ * handle is found by a linear search from the start of the table,
+ * and so no free handle list management is done.
+ */
IMG_BOOL bPurgingEnabled;
};
+/*
+ * The key for the handle hash table is an array of three elements, the
+ * pointer to the resource, the resource type, and the process ID. The
+ * eHandKey enumeration gives the array indices of the elements making
+ * up the key.
+ */
enum eHandKey {
HAND_KEY_DATA = 0,
HAND_KEY_TYPE,
HAND_KEY_PARENT,
- HAND_KEY_LEN
+ HAND_KEY_LEN /* Must be last item in list */
};
+/*
+ * Kernel handle base structure. For handles that are not allocated on
+ * behalf of a particular process
+ */
PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
+/* HAND_KEY is the type of the hash table key */
typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
+/*!
+******************************************************************************
+
+ @Function HandleListInit
+
+ @Description Initialise a linked list structure embedded in a handle
+ structure.
+
+ @Input ui32Index - index of handle in the handle array
+ psList - pointer to linked list structure
+ hParent - parent handle, or IMG_NULL
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(HandleListInit)
#endif
psList->hParent = hParent;
}
+/*!
+******************************************************************************
+
+ @Function InitParentList
+
+ @Description Initialise the children list head in a handle structure.
+ The children are the subhandles of this handle.
+
+ @Input psHandle - pointer to handle structure
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(InitParentList)
#endif
HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(ui32Parent));
}
+/*!
+******************************************************************************
+
+ @Function InitChildEntry
+
+ @Description Initialise the child list entry in a handle structure.
+ The list entry is used to link together subhandles of
+ a given handle.
+
+ @Input psHandle - pointer to handle structure
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(InitChildEntry)
#endif
HandleListInit(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, IMG_NULL);
}
+/*!
+******************************************************************************
+
+ @Function HandleListIsEmpty
+
+ @Description Determine whether a given linked list is empty.
+
+ @Input ui32Index - index of the handle containing the list head
+ psList - pointer to the list head
+
+ @Return IMG_TRUE if the list is empty, IMG_FALSE if it isn't.
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(HandleListIsEmpty)
#endif
IMG_BOOL bIsEmpty2;
bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
- PVR_ASSERT(bIsEmpty == bIsEmpty2)
+ PVR_ASSERT(bIsEmpty == bIsEmpty2);
}
#endif
}
#ifdef DEBUG
+/*!
+******************************************************************************
+
+ @Function NoChildren
+
+ @Description Determine whether a handle has any subhandles
+
+ @Input psHandle - pointer to handle structure
+
+ @Return IMG_TRUE if the handle has no subhandles, IMG_FALSE if it does.
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(NoChildren)
#endif
static INLINE
IMG_BOOL NoChildren(struct sHandle *psHandle)
{
- PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle))
+ PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle));
return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sChildren);
}
+/*!
+******************************************************************************
+
+ @Function NoParent
+
+ @Description Determine whether a handle is a subhandle
+
+ @Input psHandle - pointer to handle structure
+
+ @Return IMG_TRUE if the handle is not a subhandle, IMG_FALSE if it is.
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(NoParent)
#endif
{
if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings))
{
- PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL)
+ PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL);
return IMG_TRUE;
}
else
{
- PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL)
+ PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL);
}
return IMG_FALSE;
}
-#endif
+#endif /*DEBUG*/
+/*!
+******************************************************************************
+
+ @Function ParentHandle
+
+ @Description Determine the parent of a handle
+
+ @Input psHandle - pointer to handle structure
+
+ @Return Parent handle, or IMG_NULL if the handle is not a subhandle.
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(ParentHandle)
#endif
return psHandle->sSiblings.hParent;
}
+/*
+ * The LIST_PTR_FROM_INDEX_AND_OFFSET macro is used to generate either a
+ * pointer to the subhandle list head, or a pointer to the linked list
+ * structure of an item on a subhandle list.
+ * The list head is itself on the list, but is at a different offset
+ * in the handle structure to the linked list structure for items on
+ * the list. The two linked list structures are differentiated by
+ * the third parameter, containing the parent index. The parent field
+ * in the list head structure references the handle structure that contains
+ * it. For items on the list, the parent field in the linked list structure
+ * references the parent handle, which will be different from the handle
+ * containing the linked list structure.
+ */
#define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_STRUCT_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
+/*!
+******************************************************************************
+
+ @Function HandleListInsertBefore
+
+ @Description Insert a handle before a handle currently on the list.
+
+ @Input ui32InsIndex - index of handle to be inserted after
+ psIns - pointer to handle structure to be inserted after
+ uiParentOffset - offset to list head struct in handle structure
+ ui32EntryIndex - index of handle to be inserted
+ psEntry - pointer to handle structure of item to be inserted
+ uiEntryOffset - offset of list item struct in handle structure
+
+******************************************************************************/
#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)
{
-
+ /* PRQA S 3305 7 */ /*override stricter alignment warning */
struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
- PVR_ASSERT(psEntry->hParent == IMG_NULL)
- PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next)
- PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex))
+ PVR_ASSERT(psEntry->hParent == IMG_NULL);
+ PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
+ PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex));
psEntry->ui32Prev = psIns->ui32Prev;
psIns->ui32Prev = ui32EntryIndex;
psEntry->hParent = INDEX_TO_HANDLE(ui32ParentIndex);
}
+/*!
+******************************************************************************
+
+ @Function AdoptChild
+
+ @Description Assign a subhandle to a handle
+
+ @Input psParent - pointer to handle structure of parent handle
+ psChild - pointer to handle structure of child subhandle
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(AdoptChild)
#endif
{
IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psParent->sChildren.hParent);
- PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent))
+ PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent));
HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
}
+/*!
+******************************************************************************
+
+ @Function HandleListRemove
+
+ @Description Remove a handle from a list
+
+ @Input ui32EntryIndex - index of handle to be removed
+ psEntry - pointer to handle structure of item to be removed
+ uiEntryOffset - offset of list item struct in handle structure
+ uiParentOffset - offset to list head struct in handle structure
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(HandleListRemove)
#endif
{
if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
{
-
+ /* PRQA S 3305 3 */ /*override stricter alignment warning */
struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
-
- PVR_ASSERT(psEntry->hParent != IMG_NULL)
+ /*
+ * The list head is on the list, and we don't want to
+ * remove it.
+ */
+ PVR_ASSERT(psEntry->hParent != IMG_NULL);
psPrev->ui32Next = psEntry->ui32Next;
psNext->ui32Prev = psEntry->ui32Prev;
}
}
+/*!
+******************************************************************************
+
+ @Function UnlinkFromParent
+
+ @Description Remove a subhandle from its parents list
+
+ @Input psHandle - pointer to handle structure of child subhandle
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(UnlinkFromParent)
#endif
HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
}
+/*!
+******************************************************************************
+
+ @Function HandleListIterate
+
+ @Description Iterate over the items in a list
+
+ @Input psHead - pointer to list head
+ uiParentOffset - offset to list head struct in handle structure
+ uiEntryOffset - offset of list item struct in handle structure
+ pfnIterFunc - function to be called for each handle in the list
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(HandleListIterate)
#endif
IMG_UINT32 ui32Index;
IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psHead->hParent);
- PVR_ASSERT(psHead->hParent != IMG_NULL)
+ PVR_ASSERT(psHead->hParent != IMG_NULL);
-
+ /*
+ * Follow the next chain from the list head until we reach
+ * the list head again, which signifies the end of the list.
+ */
for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
{
struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
-
+ /* PRQA S 3305 2 */ /*override stricter alignment warning */
struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
PVRSRV_ERROR eError;
- PVR_ASSERT(psEntry->hParent == psHead->hParent)
-
+ PVR_ASSERT(psEntry->hParent == psHead->hParent);
+ /*
+ * Get the next index now, in case the list item is
+ * modified by the iteration function.
+ */
ui32Index = psEntry->ui32Next;
eError = (*pfnIterFunc)(psBase, psHandle);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function IterateOverChildren
+
+ @Description Iterate over the subhandles of a parent handle
+
+ @Input psParent - pointer to parent handle structure
+ pfnIterFunc - function to be called for each subhandle
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(IterateOverChildren)
#endif
return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
}
+/*!
+******************************************************************************
+
+ @Function GetHandleStructure
+
+ @Description Get the handle structure for a given handle
+
+ @Input psBase - pointer to handle base structure
+ ppsHandle - location to return pointer to handle structure
+ hHandle - handle from client
+ eType - handle type or PVRSRV_HANDLE_TYPE_NONE if the
+ handle type is not to be checked.
+
+ @Output ppsHandle - points to a pointer to the handle structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(GetHandleStructure)
#endif
IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle);
struct sHandle *psHandle;
-
+ /* Check handle index is in range */
if (!INDEX_IS_VALID(psBase, ui32Index))
{
PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED;
}
-
+ /*
+ * Unless PVRSRV_HANDLE_TYPE_NONE was passed in to this function,
+ * check handle is of the correct type.
+ */
if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
{
PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH;
}
-
+ /* Return the handle structure */
*ppsHandle = psHandle;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function ParentIfPrivate
+
+ @Description Return the parent handle if the handle was allocated
+ with PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE, else return
+ IMG_NULL
+
+ @Input psHandle - pointer to handle
+
+ @Return Parent handle, or IMG_NULL
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(ParentIfPrivate)
#endif
ParentHandle(psHandle) : IMG_NULL;
}
+/*!
+******************************************************************************
+
+ @Function InitKey
+
+ @Description Initialise a hash table key for the current process
+
+ @Input psBase - pointer to handle base structure
+ aKey - pointer to key
+ pvData - pointer to the resource the handle represents
+ eType - type of resource
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(InitKey)
#endif
aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
}
+/*!
+******************************************************************************
+
+ @Function ReallocHandleArray
+
+ @Description Reallocate the handle array
+
+ @Input psBase - handle base.
+ phBlockAlloc - pointer to block allocation handle.
+ ui32NewCount - new handle count
+ ui32OldCount - old handle count
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
static
PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount)
{
if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) ||
((ui32NewCount % HANDLE_BLOCK_SIZE) != 0))
{
- PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0)
- PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0)
+ PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0);
+ PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0);
return PVRSRV_ERROR_INVALID_PARAMS;
}
if (ui32NewCount != 0)
{
-
+ /* Allocate new handle array */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
(IMG_VOID **)&psNewArray,
}
}
-
+ /*
+ * If the new handle array is smaller than the old one, free
+ * unused handle structures
+ */
for(ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE)
{
struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psOldArray, ui32Index);
}
}
-
+ /*
+ * If the new handle array is bigger than the old one, allocate
+ * new handle structures
+ */
for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
{
-
+ /* PRQA S 0505 1 */ /* psNewArray is never NULL, see assert earlier */
struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
}
#ifdef DEBUG_MAX_HANDLE_COUNT
-
+ /* Force handle failure to test error exit code */
if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT)
{
PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Max handle count (%u) reached", DEBUG_MAX_HANDLE_COUNT));
if (psOldArray != IMG_NULL)
{
-
+ /* Free old handle array */
eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
HANDLE_ARRAY_SIZE(ui32OldCount) * sizeof(struct sHandleIndex),
psOldArray,
if (ui32NewCount > ui32OldCount)
{
-
- PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount)
+ /* Check for wraparound */
+ PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount);
-
+ /* PRQA S 3382 1 */ /* ui32NewCount always > ui32OldCount */
psBase->ui32FreeHandCount += (ui32NewCount - ui32OldCount);
-
+ /*
+ * If purging is enabled, there is no free handle list
+ * management, but as an optimization, when allocating
+ * new handles, we use ui32FirstFreeIndex to point to
+ * the first handle in a newly allocated block.
+ */
if (psBase->ui32FirstFreeIndex == 0)
{
- PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
psBase->ui32FirstFreeIndex = ui32OldCount;
}
{
if (!psBase->bPurgingEnabled)
{
- PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
- PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+ PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1;
}
}
else
{
- PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled)
- PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount)
- PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount)
+ PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled);
+ PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount);
+ PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount);
-
+ /* PRQA S 3382 1 */ /* ui32OldCount always >= ui32NewCount */
psBase->ui32FreeHandCount -= (ui32OldCount - ui32NewCount);
if (ui32NewCount == 0)
}
}
- PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount)
+ PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount);
return PVRSRV_OK;
error:
- PVR_ASSERT(eReturn != PVRSRV_OK)
+ PVR_ASSERT(eReturn != PVRSRV_OK);
if (psNewArray != IMG_NULL)
{
-
+ /* Free any new handle structures that were allocated */
for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
{
struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
}
}
-
+ /* Free new handle array */
eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
psNewArray,
return eReturn;
}
+/*!
+******************************************************************************
+
+ @Function FreeHandleArray
+
+ @Description Frees the handle array.
+ The memory containing the array of handle structure
+ pointers is deallocated.
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
{
return ReallocHandleArray(psBase, 0);
}
+/*!
+******************************************************************************
+
+ @Function FreeHandle
+
+ @Description Free a handle structure.
+
+ @Input psBase - pointer to handle base structure
+ psHandle - pointer to handle structure
+
+ @Return PVRSRV_OK or PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
{
HAND_KEY aKey;
IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psHandle);
PVRSRV_ERROR eError;
-
+ /*
+ * If a handle allocated in batch mode is freed whilst still
+ * in batch mode, the type is set to PVRSRV_HANDLE_TYPE_NONE further
+ * down, to indicate the handle will not be used, but not actually
+ * freed. The Free is completed when this function is called a
+ * second time as part of the batch commit or release.
+ */
+
InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
#endif
- PVR_ASSERT(hHandle != IMG_NULL)
- PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index))
+ PVR_ASSERT(hHandle != IMG_NULL);
+ PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index));
PVR_UNREFERENCED_PARAMETER(hHandle);
}
-
+ /* Unlink handle from parent */
UnlinkFromParent(psBase, psHandle);
-
+ /* Free children */
eError = IterateOverChildren(psBase, psHandle, FreeHandle);
if (eError != PVRSRV_OK)
{
return eError;
}
-
+ /*
+ * Clear the type here, so that a handle can no longer be looked
+ * up if it is only partially freed.
+ */
psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
{
-
+ /* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */
SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
-
+ /*
+ * If the handle was allocated in batch mode, delay the free
+ * until the batch commit or release.
+ */
return PVRSRV_OK;
}
-
+ /* No free list management if purging is enabled */
if (!psBase->bPurgingEnabled)
{
if (psBase->ui32FreeHandCount == 0)
{
- PVR_ASSERT(psBase->ui32FirstFreeIndex == 0)
- PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
psBase->ui32FirstFreeIndex = ui32Index;
}
else
{
-
- PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
- PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
+ /*
+ * Put the handle pointer on the end of the the free
+ * handle pointer linked list.
+ */
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+ PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1;
}
- PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0)
+ PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
-
+ /* Update the end of the free handle linked list */
psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
}
psBase->ui32FreeHandCount++;
INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)++;
- PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE)
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE);
#ifdef DEBUG
{
ui32FreeHandCount += INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32BlockedIndex);
}
- PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount)
+ PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount);
}
#endif
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function FreeAllHandles
+
+ @Description Free all handles for a given handle base
+
+ @Input psBase - pointer to handle base structure
+
+ @Return PVRSRV_OK or PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
{
IMG_UINT32 i;
break;
}
-
+ /* Break out of loop if all the handles free */
if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
{
break;
return eError;
}
+/*!
+******************************************************************************
+
+ @Function FreeHandleBase
+
+ @Description Free a handle base.
+
+ @Input psHandleBase - pointer to handle base
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
{
PVRSRV_ERROR eError;
PVRSRVReleaseHandleBatch(psBase);
}
-
+ /* Free the handle array */
eError = FreeAllHandles(psBase);
if (eError != PVRSRV_OK)
{
return eError;
}
-
+ /* Free the handle array */
eError = FreeHandleArray(psBase);
if (eError != PVRSRV_OK)
{
if (psBase->psHashTab != IMG_NULL)
{
-
+ /* Free the hash table */
HASH_Delete(psBase->psHashTab);
}
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function FindHandle
+
+ @Description Find handle corresponding to a resource pointer
+
+ @Input psBase - pointer to handle base structure
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+
+ @Return the handle, or IMG_NULL if not found
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(FindHandle)
#endif
{
HAND_KEY aKey;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
InitKey(aKey, psBase, pvData, eType, hParent);
#endif
}
+/*!
+******************************************************************************
+
+ @Function IncreaseHandleArraySize
+
+ @Description Allocate some more free handles
+
+ @Input psBase - pointer to handle base structure
+ ui32Delta - number of new handles required
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
{
PVRSRV_ERROR eError;
IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(ui32Delta);
IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
-;
- PVR_ASSERT(ui32Delta != 0)
+ PVR_ASSERT(ui32Delta != 0);
-
+ /*
+ * Check new count against max handle index, and check for wrap around.
+ */
if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
{
ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
}
}
- PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta)
+ PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
-
+ /* Realloc handle pointer array */
eError = ReallocHandleArray(psBase, ui32NewTotalHandCount);
if (eError != PVRSRV_OK)
{
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function EnsureFreeHandles
+
+ @Description Ensure there are enough free handles
+
+ @Input psBase - pointer to handle base structure
+ ui32Free - number of free handles required
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
{
PVRSRV_ERROR eError;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function AllocHandle
+
+ @Description Allocate a new handle
+
+ @Input phHandle - location for new handle
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+ hParent - parent handle or IMG_NULL
+
+ @Output phHandle - points to new handle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent)
#else
HAND_KEY aKey;
PVRSRV_ERROR eError;
-
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
- PVR_ASSERT(psBase != IMG_NULL)
- PVR_ASSERT(psBase->psHashTab != IMG_NULL)
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(psBase != IMG_NULL);
+ PVR_ASSERT(psBase->psHashTab != IMG_NULL);
if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
{
-
- PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL)
+ /* Handle must not already exist */
+ 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));
}
-
+ /* Ensure there is a free handle */
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)
+ PVR_ASSERT(psBase->ui32FreeHandCount != 0);
if (!psBase->bPurgingEnabled)
{
-
+ /* Array index of first free handle */
ui32NewIndex = psBase->ui32FirstFreeIndex;
-
+ /* Get handle array entry */
psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
}
else
{
IMG_UINT32 ui32BlockedIndex;
-
-
- PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0)
+ /*
+ * If purging is enabled, we always try to allocate handles
+ * at the front of the array, to increase the chances that
+ * the size of the handle array can be reduced by a purge.
+ * No linked list of free handles is kept; we search for
+ * free handles as required.
+ */
+
+ /*
+ * ui32FirstFreeIndex should only be set when a new batch of
+ * handle structures is allocated, and should always be a
+ * multiple of the block size.
+ */
+ PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0);
for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
{
}
}
psBase->ui32FirstFreeIndex = 0;
- PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount)
+ PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
}
- PVR_ASSERT(psNewHandle != IMG_NULL)
+ PVR_ASSERT(psNewHandle != IMG_NULL);
-
+ /* Handle to be returned to client */
hHandle = INDEX_TO_HANDLE(ui32NewIndex);
-
+ /*
+ * If a data pointer can be associated with multiple handles, we
+ * don't put the handle in the hash table, as the data pointer
+ * may not map to a unique handle
+ */
if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
{
-
+ /* Initialise hash key */
InitKey(aKey, psBase, pvData, eType, hParent);
-
+ /* Put the new handle in the hash table */
if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
{
PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
psBase->ui32FreeHandCount--;
- PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE)
- PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0)
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE);
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0);
INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex)--;
-
+ /* No free list management if purging is enabled */
if (!psBase->bPurgingEnabled)
{
-
+ /* Check whether the last free handle has been allocated */
if (psBase->ui32FreeHandCount == 0)
{
- PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex)
- PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1))
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));
psBase->ui32LastFreeIndexPlusOne = 0;
psBase->ui32FirstFreeIndex = 0;
}
else
{
-
+ /*
+ * Update the first free handle index.
+ * If the "next free index plus one" field in the new
+ * handle structure is zero, the next free index is
+ * the index of the new handle plus one. This
+ * convention has been adopted to simplify the
+ * initialisation of freshly allocated handle
+ * space.
+ */
psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
ui32NewIndex + 1 :
psNewHandle->ui32NextIndexPlusOne - 1;
}
}
-
- PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex)
+ /* Initialise the newly allocated handle */
+ PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex);
-
+ /* PRQA S 0505 1 */ /* psNewHandle is never NULL, see assert earlier */
psNewHandle->eType = eType;
psNewHandle->pvData = pvData;
psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
InitParentList(psNewHandle);
#if defined(DEBUG)
- PVR_ASSERT(NoChildren(psNewHandle))
+ PVR_ASSERT(NoChildren(psNewHandle));
#endif
InitChildEntry(psNewHandle);
#if defined(DEBUG)
- PVR_ASSERT(NoParent(psNewHandle))
+ PVR_ASSERT(NoParent(psNewHandle));
#endif
if (HANDLES_BATCHED(psBase))
{
-
+ /* Add handle to batch list */
psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
-
+ /* PRQA S 1474 1 */ /* ignore warnings about enum types being modified */
SET_BATCHED_HANDLE(psNewHandle);
}
else
psNewHandle->ui32NextIndexPlusOne = 0;
}
-
+ /* Return the new handle to the client */
*phHandle = hHandle;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocHandle
+
+ @Description Allocate a handle
+
+ @Input phHandle - location for new handle
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+
+ @Output phHandle - points to new handle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
#else
if (HANDLES_BATCHED(psBase))
{
-
+ /*
+ * Increment the counter in case of failure. It will be
+ * decremented on success.
+ */
psBase->ui32BatchHandAllocFailures++;
}
-
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
{
-
+ /* See if there is already a handle for this data pointer */
hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
#if defined (SUPPORT_SID_INTERFACE)
if (hHandle != 0)
return eError;
}
-
+ /*
+ * If the client is willing to share a handle, and the
+ * existing handle is marked as shareable, return the
+ * existing handle.
+ */
if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
{
*phHandle = hHandle;
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocSubHandle
+
+ @Description Allocate a subhandle
+
+ @Input phHandle - location for new subhandle
+ pvData - pointer to resource to be associated with the subhandle
+ eType - the type of resource
+ hParent - parent handle
+
+ @Output phHandle - points to new subhandle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent)
#else
if (HANDLES_BATCHED(psBase))
{
-
+ /*
+ * Increment the counter in case of failure. It will be
+ * decremented on success.
+ */
psBase->ui32BatchHandAllocFailures++;
}
-
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
hParent : IMG_NULL;
-
+ /* Lookup the parent handle */
eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
if (eError != PVRSRV_OK)
{
if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
{
-
+ /* See if there is already a handle for this data pointer */
hHandle = FindHandle(psBase, pvData, eType, hParentKey);
#if defined (SUPPORT_SID_INTERFACE)
if (hHandle != 0)
return eErr;
}
- PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
+ PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent);
-
+ /*
+ * If the client is willing to share a handle, the
+ * existing handle is marked as shareable, and the
+ * existing handle has the same parent, return the
+ * existing handle.
+ */
if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
{
*phHandle = hHandle;
return eError;
}
-
+ /*
+ * Get the parent handle structure again, in case the handle
+ * structure has moved (depending on the implementation
+ * of AllocHandle).
+ */
psPHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hParent);
psCHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVFindHandle
+
+ @Description Find handle corresponding to a resource pointer
+
+ @Input phHandle - location for returned handle
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+
+ @Output phHandle - points to handle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
#else
IMG_HANDLE hHandle;
#endif
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
-
+ /* See if there is a handle for this data pointer */
#if defined (SUPPORT_SID_INTERFACE)
hHandle = (IMG_SID) FindHandle(psBase, pvData, eType, IMG_NULL);
#else
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupHandleAnyType
+
+ @Description Lookup the data pointer and type corresponding to a handle
+
+ @Input ppvData - location to return data pointer
+ peType - location to return handle type
+ hHandle - handle from client
+
+ @Output ppvData - points to the data pointer
+ peType - points to handle type
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_SID hHandle)
#else
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupHandle
+
+ @Description Lookup the data pointer corresponding to a handle
+
+ @Input ppvData - location to return data pointer
+ hHandle - handle from client
+ eType - handle type
+
+ @Output ppvData - points to the data pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
#else
struct sHandle *psHandle;
PVRSRV_ERROR eError;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
#if defined (SUPPORT_SID_INTERFACE)
- PVR_ASSERT(hHandle != 0)
+ PVR_ASSERT(hHandle != 0);
#endif
eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupSubHandle
+
+ @Description Lookup the data pointer corresponding to a subhandle
+
+ @Input ppvData - location to return data pointer
+ hHandle - handle from client
+ eType - handle type
+ hAncestor - ancestor handle
+
+ @Output ppvData - points to the data pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType, IMG_SID hAncestor)
#else
struct sHandle *psCHand;
PVRSRV_ERROR eError;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
#if defined (SUPPORT_SID_INTERFACE)
- PVR_ASSERT(hHandle != 0)
+ PVR_ASSERT(hHandle != 0);
#endif
eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
return eError;
}
-
+ /* Look for hAncestor among the handle's ancestors */
for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
{
eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetParentHandle
+
+ @Description Lookup the parent of a handle
+
+ @Input phParent - location for returning parent handle
+ hHandle - handle for which the parent handle is required
+ eType - handle type
+ hParent - parent handle
+
+ @Output *phParent - parent handle, or IMG_NULL if there is no parent
+
+ @Return Error code or PVRSRV_OK. Note that not having a parent is
+ not regarded as an error.
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phParent, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
#else
struct sHandle *psHandle;
PVRSRV_ERROR eError;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
if (eError != PVRSRV_OK)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupAndReleaseHandle
+
+ @Description Lookup the data pointer corresponding to a handle
+
+ @Input ppvData - location to return data pointer
+ hHandle - handle from client
+ eType - handle type
+ eFlag - lookup flags
+
+ @Output ppvData - points to the data pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
#else
struct sHandle *psHandle;
PVRSRV_ERROR eError;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
if (eError != PVRSRV_OK)
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVReleaseHandle
+
+ @Description Release a handle that is no longer needed
+
+ @Input hHandle - handle from client
+ eType - handle type
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
#else
struct sHandle *psHandle;
PVRSRV_ERROR eError;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
if (eError != PVRSRV_OK)
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVNewHandleBatch
+
+ @Description Start a new handle batch
+
+ @Input psBase - handle base
+ @Input ui32BatchSize - handle batch size
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
{
PVRSRV_ERROR eError;
psBase->ui32HandBatchSize = ui32BatchSize;
-
+ /* Record current number of handles */
psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
- PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0)
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
- PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0)
+ PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
- PVR_ASSERT(HANDLES_BATCHED(psBase))
+ PVR_ASSERT(HANDLES_BATCHED(psBase));
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVHandleBatchCommitOrRelease
+
+ @Description Release a handle batch
+
+ @Input psBase - handle base
+ bCommit - commit handles
+
+ @Return none
+
+******************************************************************************/
static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
{
}
bCommitBatch = IMG_FALSE;
}
-
- PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit)
+ /*
+ * The whole point of batched handles is to avoid handle allocation
+ * failures.
+ */
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
while(ui32IndexPlusOne != 0)
{
struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32IndexPlusOne - 1);
IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
- PVR_ASSERT(BATCHED_HANDLE(psHandle))
+ PVR_ASSERT(BATCHED_HANDLE(psHandle));
psHandle->ui32NextIndexPlusOne = 0;
{
PVRSRV_ERROR eError;
-
+ /*
+ * We need a complete free here. If the handle
+ * is not partially free, set the handle as
+ * unbatched to avoid a partial free.
+ */
if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
{
-
- SET_UNBATCHED_HANDLE(psHandle);
+ /* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */
+ SET_UNBATCHED_HANDLE(psHandle); /* PRQA S 4130 */ /* mis-use of enums FIXME*/
}
eError = FreeHandle(psBase, psHandle);
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
}
- PVR_ASSERT(eError == PVRSRV_OK)
+ PVR_ASSERT(eError == PVRSRV_OK);
}
else
{
-
+ /* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */
SET_UNBATCHED_HANDLE(psHandle);
}
{
IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
- PVR_ASSERT(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));
if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
{
- PVR_ASSERT(!bCommitBatch)
+ PVR_ASSERT(!bCommitBatch);
return PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE;
}
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVCommitHandleBatch
+
+ @Description Commit a handle batch
+
+ @Input psBase - handle base
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
{
return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRReleaseHandleBatch
+
+ @Description Release a handle batch
+
+ @Input psBase - handle base
+
+ @Return none
+
+******************************************************************************/
IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
{
(IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetMaxHandle
+
+ @Description Set maximum handle number for given handle base
+
+ @Input psBase - pointer to handle base structure
+ ui32MaxHandle - Maximum handle number
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
{
IMG_UINT32 ui32MaxHandleRounded;
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* Validate the limit */
if (ui32MaxHandle == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE)
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* The limit can only be set if no handles have been allocated */
if (psBase->ui32TotalHandCount != 0)
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set because handles have already been allocated"));
ui32MaxHandleRounded = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(ui32MaxHandle);
-
+ /*
+ * Allow the maximum number of handles to be reduced, but never to
+ * zero.
+ */
if (ui32MaxHandleRounded != 0 && ui32MaxHandleRounded < psBase->ui32MaxIndexPlusOne)
{
psBase->ui32MaxIndexPlusOne = ui32MaxHandleRounded;
}
- PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0)
- PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE)
- PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0)
+ PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0);
+ PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE);
+ PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetMaxHandle
+
+ @Description Get maximum handle number for given handle base
+
+ @Input psBase - pointer to handle base structure
+
+ @Output Maximum handle number, or 0 if handle limits not
+ supported.
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
{
return psBase->ui32MaxIndexPlusOne;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnableHandlePurging
+
+ @Description Enable purging for a given handle base
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
{
if (psBase->bPurgingEnabled)
return PVRSRV_OK;
}
-
+ /* Purging can only be enabled if no handles have been allocated */
if (psBase->ui32TotalHandCount != 0)
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPurgeHandles
+
+ @Description Purge handles for a given handle base
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
{
IMG_UINT32 ui32BlockIndex;
return PVRSRV_ERROR_INVALID_PARAMS;
}
- PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0)
+ PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0);
for (ui32BlockIndex = INDEX_TO_BLOCK_INDEX(psBase->ui32TotalHandCount); ui32BlockIndex != 0; ui32BlockIndex--)
{
}
ui32NewHandCount = BLOCK_INDEX_TO_INDEX(ui32BlockIndex);
-
+ /*
+ * Check for a suitable decrease in the handle count.
+ */
if (ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
{
PVRSRV_ERROR eError;
-
+ // PVR_TRACE((" PVRSRVPurgeHandles: reducing number of handles from %u to %u", psBase->ui32TotalHandCount, ui32NewHandCount));
eError = ReallocHandleArray(psBase, ui32NewHandCount);
if (eError != PVRSRV_OK)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocHandleBase
+
+ @Description Allocate a handle base structure for a process
+
+ @Input ppsBase - pointer to handle base structure pointer
+
+ @Output ppsBase - points to handle base structure pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
{
PVRSRV_HANDLE_BASE *psBase;
}
OSMemSet(psBase, 0, sizeof(*psBase));
-
+ /* Create hash table */
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)
{
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVFreeHandleBase
+
+ @Description Free a handle base structure
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
{
PVRSRV_ERROR eError;
- PVR_ASSERT(psBase != gpsKernelHandleBase)
+ PVR_ASSERT(psBase != gpsKernelHandleBase);
eError = FreeHandleBase(psBase);
if (eError != PVRSRV_OK)
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVHandleInit
+
+ @Description Initialise handle management
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
{
PVRSRV_ERROR eError;
- PVR_ASSERT(gpsKernelHandleBase == IMG_NULL)
+ PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
if (eError != PVRSRV_OK)
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVHandleDeInit
+
+ @Description De-initialise handle management
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
{
PVRSRV_ERROR eError = PVRSRV_OK;
return eError;
}
#else
-#endif
+/* disable warning about empty module */
+#endif /* #if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE) */
+/******************************************************************************
+ End of file (handle.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Self scaling hash tables.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description
+ Implements simple self scaling hash tables. Hash collisions are
+ handled by chaining entries together. Hash tables are increased in
+ size when they become more than (50%?) full and decreased in size
+ when less than (25%?) full. Hash tables are never decreased below
+ their initial size.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "pvr_debug.h"
#include "img_defs.h"
#define KEY_COMPARE(pHash, pKey1, pKey2) \
((pHash)->pfnKeyComp((pHash)->uKeySize, (pKey1), (pKey2)))
+/* Each entry in a hash table is placed into a bucket */
struct _BUCKET_
{
-
+ /* the next bucket on the same chain */
struct _BUCKET_ *pNext;
-
+ /* entry value */
IMG_UINTPTR_T v;
-
- IMG_UINTPTR_T k[];
+ /* entry key */
+ IMG_UINTPTR_T k[]; /* PRQA S 0642 */ /* override dynamic array declaration warning */
};
typedef struct _BUCKET_ BUCKET;
struct _HASH_TABLE_
{
-
+ /* the hash table array */
BUCKET **ppBucketTable;
-
+ /* current size of the hash table */
IMG_UINT32 uSize;
-
+ /* number of entries currently in the hash table */
IMG_UINT32 uCount;
-
+ /* the minimum size that the hash table should be re-sized to */
IMG_UINT32 uMinimumSize;
-
+ /* size of key in bytes */
IMG_UINT32 uKeySize;
-
+ /* hash function */
HASH_FUNC *pfnHashFunc;
-
+ /* key comparison function */
HASH_KEY_COMP *pfnKeyComp;
};
+/*!
+******************************************************************************
+ @Function HASH_Func_Default
+
+ @Description Hash function intended for hashing keys composed of
+ IMG_UINTPTR_T arrays.
+
+ @Input uKeySize - the size of the hash key, in bytes.
+ @Input pKey - a pointer to the key to hash.
+ @Input uHashTabLen - the length of the hash table.
+
+ @Return the hash value.
+******************************************************************************/
IMG_UINT32
HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen)
{
return uHashKey;
}
+/*!
+******************************************************************************
+ @Function HASH_Key_Comp_Default
+
+ @Description Compares keys composed of IMG_UINTPTR_T arrays.
+
+ @Input uKeySize - the size of the hash key, in bytes.
+ @Input pKey1 - pointer to first hash key to compare.
+ @Input pKey2 - pointer to second hash key to compare.
+ @Return IMG_TRUE - the keys match.
+ IMG_FALSE - the keys don't match.
+******************************************************************************/
IMG_BOOL
HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2)
{
return IMG_TRUE;
}
+/*!
+******************************************************************************
+ @Function _ChainInsert
+
+ @Description Insert a bucket into the appropriate hash table chain.
+
+ @Input pBucket - the bucket
+ @Input ppBucketTable - the hash table
+ @Input uSize - the size of the hash table
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
static PVRSRV_ERROR
_ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UINT32 uSize)
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
- uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize);
+ uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize); /* PRQA S 0432,0541 */ /* ignore dynamic array warning */
pBucket->pNext = ppBucketTable[uIndex];
ppBucketTable[uIndex] = pBucket;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ @Function _Rehash
+
+ @Description Iterate over every entry in an old hash table and
+ rehash into the new table.
+
+ @Input ppOldTable - the old hash table
+ @Input uOldSize - the size of the old hash table
+ @Input ppNewTable - the new hash table
+ @Input uNewSize - the size of the new hash table
+
+ @Return None
+******************************************************************************/
static PVRSRV_ERROR
_Rehash (HASH_TABLE *pHash,
BUCKET **ppOldTable, IMG_UINT32 uOldSize,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ @Function _Resize
+
+ @Description Attempt to resize a hash table, failure to allocate a
+ new larger hash table is not considered a hard failure.
+ We simply continue and allow the table to fill up, the
+ effect is to allow hash chains to become longer.
+
+ @Input pHash - Hash table to resize.
+ @Input uNewSize - Required table size.
+ @Return IMG_TRUE Success
+ IMG_FALSE Failed
+******************************************************************************/
static IMG_BOOL
_Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
{
}
OSFreeMem (PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
-
+ /*not nulling pointer, being reassigned just below*/
pHash->ppBucketTable = ppNewTable;
pHash->uSize = uNewSize;
}
}
+/*!
+******************************************************************************
+ @Function HASH_Create_Extended
+
+ @Description Create a self scaling hash table, using the supplied
+ key size, and the supplied hash and key comparsion
+ functions.
+
+ @Input uInitialLen - initial and minimum length of the
+ hash table, where the length refers to the number
+ of entries in the hash table, not its size in
+ bytes.
+ @Input uKeySize - the size of the key, in bytes.
+ @Input pfnHashFunc - pointer to hash function.
+ @Input pfnKeyComp - pointer to key comparsion function.
+ @Return IMG_NULL or hash table handle.
+******************************************************************************/
HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp)
{
HASH_TABLE *pHash;
if (pHash->ppBucketTable == IMG_NULL)
{
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return IMG_NULL;
}
return pHash;
}
+/*!
+******************************************************************************
+ @Function HASH_Create
+
+ @Description Create a self scaling hash table with a key
+ consisting of a single IMG_UINTPTR_T, and using
+ the default hash and key comparison functions.
+
+ @Input uInitialLen - initial and minimum length of the
+ hash table, where the length refers to the
+ number of entries in the hash table, not its size
+ in bytes.
+ @Return IMG_NULL or hash table handle.
+******************************************************************************/
HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen)
{
return HASH_Create_Extended(uInitialLen, sizeof(IMG_UINTPTR_T),
&HASH_Func_Default, &HASH_Key_Comp_Default);
}
+/*!
+******************************************************************************
+ @Function HASH_Delete
+
+ @Description Delete a hash table created by HASH_Create_Extended or
+ HASH_Create. All entries in the table must have been
+ removed before calling this function.
+
+ @Input pHash - hash table
+
+ @Return None
+******************************************************************************/
IMG_VOID
HASH_Delete (HASH_TABLE *pHash)
{
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
pHash->ppBucketTable = IMG_NULL;
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
}
+/*!
+******************************************************************************
+ @Function HASH_Insert_Extended
+
+ @Description Insert a key value pair into a hash table created
+ with HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to the key.
+ @Input v - the value associated with the key.
+
+ @Return IMG_TRUE - success
+ IMG_FALSE - failure
+******************************************************************************/
IMG_BOOL
HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
{
}
pBucket->v = v;
-
+ /* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k (linux)*/
OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
if (_ChainInsert (pHash, pBucket, pHash->ppBucketTable, pHash->uSize) != PVRSRV_OK)
{
pHash->uCount++;
-
+ /* check if we need to think about re-balencing */
if (pHash->uCount << 1 > pHash->uSize)
{
-
-
+ /* Ignore the return code from _Resize because the hash table is
+ still in a valid state and although not ideally sized, it is still
+ functional */
_Resize (pHash, pHash->uSize << 1);
}
return IMG_TRUE;
}
+/*!
+******************************************************************************
+ @Function HASH_Insert
+
+ @Description Insert a key value pair into a hash table created with
+ HASH_Create.
+
+ @Input pHash - the hash table.
+ @Input k - the key value.
+ @Input v - the value associated with the key.
+
+ @Return IMG_TRUE - success.
+ IMG_FALSE - failure.
+******************************************************************************/
IMG_BOOL
HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v)
{
return HASH_Insert_Extended(pHash, &k, v);
}
+/*!
+******************************************************************************
+ @Function HASH_Remove_Extended
+
+ @Description Remove a key from a hash table created with
+ HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to key.
+
+ @Return 0 if the key is missing, or the value associated
+ with the key.
+******************************************************************************/
IMG_UINTPTR_T
HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
{
for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
{
-
+ /* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k */
if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
{
BUCKET *pBucket = *ppBucket;
(*ppBucket) = pBucket->pNext;
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET) + pHash->uKeySize, pBucket, IMG_NULL);
-
+ /*not nulling original pointer, already overwritten*/
pHash->uCount--;
-
+ /* check if we need to think about re-balencing */
if (pHash->uSize > (pHash->uCount << 2) &&
pHash->uSize > pHash->uMinimumSize)
{
-
-
+ /* Ignore the return code from _Resize because the
+ hash table is still in a valid state and although
+ not ideally sized, it is still functional */
_Resize (pHash,
PRIVATE_MAX (pHash->uSize >> 1,
pHash->uMinimumSize));
return 0;
}
+/*!
+******************************************************************************
+ @Function HASH_Remove
+
+ @Description Remove a key value pair from a hash table created
+ with HASH_Create.
+
+ @Input pHash - the hash table
+ @Input k - the key
+
+ @Return 0 if the key is missing, or the value associated
+ with the key.
+******************************************************************************/
IMG_UINTPTR_T
HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k)
{
return HASH_Remove_Extended(pHash, &k);
}
+/*!
+******************************************************************************
+ @Function HASH_Retrieve_Extended
+
+ @Description Retrieve a value from a hash table created with
+ HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to the key.
+
+ @Return 0 if the key is missing, or the value associated with
+ the key.
+******************************************************************************/
IMG_UINTPTR_T
HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
{
for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
{
-
+ /* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k */
if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
{
BUCKET *pBucket = *ppBucket;
return 0;
}
+/*!
+******************************************************************************
+ @Function HASH_Retrieve
+
+ @Description Retrieve a value from a hash table created with
+ HASH_Create.
+
+ @Input pHash - the hash table
+ @Input k - the key
+ @Return 0 if the key is missing, or the value associated with
+ the key.
+******************************************************************************/
IMG_UINTPTR_T
HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k)
{
return HASH_Retrieve_Extended(pHash, &k);
}
+/*!
+******************************************************************************
+ @Function HASH_Iterate
+
+ @Description Iterate over every entry in the hash table
+
+ @Input pHash - the old hash table
+ @Input pfnCallback - the size of the old hash table
+
+ @Return Callback error if any, otherwise PVRSRV_OK
+******************************************************************************/
PVRSRV_ERROR
HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback)
{
eError = pfnCallback((IMG_UINTPTR_T) ((IMG_VOID *) *(pBucket->k)), (IMG_UINTPTR_T) pBucket->v);
-
+ /* The callback might want us to break out early */
if (eError != PVRSRV_OK)
return eError;
}
#ifdef HASH_TRACE
+/*!
+******************************************************************************
+ @Function HASH_Dump
+
+ @Description To dump the contents of a hash table in human readable
+ form.
+
+ @Input pHash - the hash table
+
+ @Return None
+******************************************************************************/
IMG_VOID
HASH_Dump (HASH_TABLE *pHash)
{
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linked list shared functions implementation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implementation of the list iterators for types shared among
+ more than one file in the services code.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "lists.h"
#include "services_headers.h"
+/*===================================================================
+ LIST ITERATOR FUNCTIONS USED IN MORE THAN ONE FILE (those used just
+ once are implemented locally).
+ ===================================================================*/
+
IMPLEMENT_LIST_ANY_VA(BM_HEAP)
IMPLEMENT_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
IMPLEMENT_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
+/*===================================================================
+ BELOW ARE IMPLEMENTED SOME COMMON CALLBACKS USED IN DIFFERENT FILES
+ ===================================================================*/
+
+
+/*!
+******************************************************************************
+ @Function MatchDeviceKM_AnyVaCb
+ @Description Matchs a device node with an id and optionally a class.
+
+ @Input psDeviceNode - Pointer to the device node.
+ @Input va - Variable argument list, with te following values:
+ # ui32DevIndex - Index of de device to match.
+ # bIgnoreClass - Flag indicating if there's
+ no need to check the device class.
+ # eDevClass - Device class, ONLY present if
+ bIgnoreClass was IMG_FALSE.
+
+ @Return The pointer to the device node if it matchs, IMG_NULL
+ otherwise.
+******************************************************************************/
IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
{
IMG_UINT32 ui32DevIndex;
}
else
{
-
-
+ /*this value will never be used, since the short circuit evaluation
+ of the first clause will stop because bIgnoreClass is true, but the
+ compiler complains if it's not initialized.*/
eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
}
return IMG_NULL;
}
+/*!
+******************************************************************************
+
+ @Function MatchPowerDeviceIndex_AnyVaCb
+
+ @Description
+ Matches a power device with its device index.
+
+ @Input va : variable argument list with:
+ ui32DeviceIndex : device index
+
+ @Return the pointer to the device it matched, IMG_NULL otherwise.
+
+******************************************************************************/
IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va)
{
IMG_UINT32 ui32DeviceIndex;
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title System memory functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description System memory allocation APIs
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
#include "pvr_bridge_km.h"
sizeof(PVRSRV_KERNEL_MEM_INFO),
psKernelMemInfo,
IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
if(OSAllocPages(psKernelMemInfo->ui32Flags,
psKernelMemInfo->uAllocSize,
(IMG_UINT32)HOST_PAGESIZE(),
+ IMG_NULL,
+ 0,
+ IMG_NULL,
&psKernelMemInfo->pvLinAddrKM,
&psKernelMemInfo->sMemBlk.hOSMemHandle)
!= PVRSRV_OK)
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* register with the resman */
psKernelMemInfo->sMemBlk.hResItem =
ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_SHARED_MEM_INFO,
return eError;
}
+/******************************************************************************
+ End of file (mem.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Memory debugging routines.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Adds extra memory to the allocations to trace the memory bounds
+ and other runtime information.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef MEM_DEBUG_C
#define MEM_DEBUG_C
#define STOP_ON_ERROR 0
-
-
-
-
-
-
-
+ /*
+ Allocated Memory Layout:
+
+ --------- \
+ Status [OSMEM_DEBUG_INFO] |- TEST_BUFFER_PADDING_STATUS
+ --------- <
+ [0xBB]* [raw bytes] |- ui32Size
+ --------- <
+ [0xB2]* [raw bytes] |- TEST_BUFFER_PADDING_AFTER
+ --------- /
+ */
IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize)
{
return IMG_TRUE;
}
-
-
+ /*
+ This function expects the pointer to the user data, not the debug data.
+ */
IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine)
{
OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
-
+ /* invalid pointer */
if (pvCpuVAddr == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : null pointer"
while (STOP_ON_ERROR);
}
-
+ /* align */
if (((IMG_UINT32)pvCpuVAddr&3) != 0)
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : invalid alignment"
while (STOP_ON_ERROR);
}
-
+ /*check guard region before*/
if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)))
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region before overwritten"
while (STOP_ON_ERROR);
}
-
+ /*check size*/
if (uSize != psInfo->uSize)
{
PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : supplied size was different to stored size (0x%X != 0x%X)"
while (STOP_ON_ERROR);
}
-
+ /*check size parity*/
if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize)
{
PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : stored size parity error (0x%X != 0x%X)"
}
else
{
-
+ /*the stored size is ok, so we use it instead the supplied uSize*/
uSize = psInfo->uSize;
}
-
+ /*check padding after*/
if (uSize)
{
if (!MemCheck((IMG_VOID*)((IMG_UINT32)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER))
}
}
-
+ /* allocated... */
if (psInfo->eValid != isAllocated)
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : not allocated (freed? %d)"
{
IMG_SIZE_T i = 0;
- for (; i < 128; i++)
+ for (; i < 128; i++) /*changed to 128 to match the filename array size*/
{
*pDest = *pSrc;
if (*pSrc == '\0') break;
return eError;
}
-
OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size);
OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER);
-
+ /*fill the dbg info struct*/
psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr);
OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore));
psInfo->uSize = ui32Size;
psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size;
-
+ /*point to the user data section*/
*ppvCpuVAddr = (IMG_PVOID) ((IMG_UINT32)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS;
#ifdef PVRSRV_LOG_MEMORY_ALLOCS
-
+ /*this is here to simplify the surounding logging macro, that is a expression
+ maybe the macro should be an expression */
PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line));
#endif
{
OSMEM_DEBUG_INFO *psInfo;
-
+ /*check dbginfo (arg pointing to user memory)*/
OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line);
-
- OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
+ /*mark memory as freed*/
+ OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
-
+ /*point to the starting address of the total allocated memory*/
psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
-
+ /*update dbg info struct*/
psInfo->uSize = 0;
psInfo->uSizeParityCheck = 0;
psInfo->eValid = isFree;
}
#endif
-#endif
+#endif /* PVRSRV_DEBUG_OS_MEMORY */
-#endif
+#endif /* MEM_DEBUG_C */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Time measuring functions.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
#include "metrics.h"
+/* VGX: */
#if defined(SUPPORT_VGX)
#include "vgxapi_km.h"
#endif
+/* SGX: */
#if defined(SUPPORT_SGX)
#include "sgxapi_km.h"
#endif
Temporal_Data asTimers[PVRSRV_NUM_TIMERS];
+/***********************************************************************************
+ Function Name : PVRSRVTimeNow
+ Inputs : None
+ Outputs : None
+ Returns : Current timer register value
+ Description : Returns the current timer register value
+************************************************************************************/
IMG_UINT32 PVRSRVTimeNow(IMG_VOID)
{
if (!pui32TimerRegister)
return (0xffffffff-*pui32TimerRegister);
-#else
+#else /* defined(__sh__) */
return 0;
-#endif
+#endif /* defined(__sh__) */
}
+/***********************************************************************************
+ Function Name : PVRSRVGetCPUFreq
+ Inputs : None
+ Outputs : None
+ Returns : CPU timer frequency
+ Description : Returns the CPU timer frequency
+************************************************************************************/
static IMG_UINT32 PVRSRVGetCPUFreq(IMG_VOID)
{
IMG_UINT32 ui32Time1, ui32Time2;
}
+/***********************************************************************************
+ Function Name : PVRSRVSetupMetricTimers
+ Inputs : pvDevInfo
+ Outputs : None
+ Returns : None
+ Description : Resets metric timers and sets up the timer register
+************************************************************************************/
IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo)
{
IMG_UINT32 ui32Loop;
asTimers[ui32Loop].ui32Count = 0;
}
-
#if defined(__sh__)
-
-
-
-
+ /* timer control register */
+ // clock / 1024 when TIMER_DIVISOR = 4
+ // underflow int disabled
+ // we get approx 38 uS per timer tick
*TCR_2 = TIMER_DIVISOR;
-
+ /* reset the timer counter to 0 */
*TCOR_2 = *TCNT_2 = (IMG_UINT)0xffffffff;
-
+ /* start timer 2 */
*TST_REG |= (IMG_UINT8)0x04;
pui32TimerRegister = (IMG_UINT32 *)TCNT_2;
- #else
+ #else /* defined(__sh__) */
pui32TimerRegister = 0;
- #endif
-
+ #endif /* defined(__sh__) */
}
+/***********************************************************************************
+ Function Name : PVRSRVOutputMetricTotals
+ Inputs : None
+ Outputs : None
+ Returns : None
+ Description : Displays final metric data
+************************************************************************************/
IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID)
{
IMG_UINT32 ui32TicksPerMS, ui32Loop;
}
}
#if 0
-
+ /*
+ ** EXAMPLE TIMER OUTPUT
+ */
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
+#endif /* defined(DEBUG) || defined(TIMING) */
+
+/******************************************************************************
+ End of file (metrics.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Wrapper layer for osfunc routines that have common code.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Adds extra memory to the allocations to trace the memory bounds
+ and other runtime information.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "img_types.h"
#include "services_headers.h"
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Common PDump functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if defined(PDUMP)
#include <stdarg.h>
#include "services_headers.h"
#include "perproc.h"
+/* pdump headers */
#include "pdump_km.h"
#include "pdump_int.h"
+/* Allow temporary buffer size override */
#if !defined(PDUMP_TEMP_BUFFER_SIZE)
#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024U)
#endif
+/* DEBUG */
#if 1
#define PDUMP_DBG(a) PDumpOSDebugPrintf (a)
#else
static IMG_UINT16 gui16MMUContextUsage = 0;
#if defined(PDUMP_DEBUG_OUTFILES)
+/* counter increments each time debug write is called */
IMG_UINT32 g_ui32EveryLineCounter = 1U;
#endif
if(psPerProc == IMG_NULL)
{
-
+ /* only occurs early in driver init, and init phase is already persistent */
return IMG_FALSE;
}
return psPerProc->bPDumpPersistent;
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc == IMG_NULL)
{
-
+ /* FIXME: kernel process logs some comments when kernel module is
+ * loaded, want to keep those.
+ */
return IMG_TRUE;
}
return psPerProc->bPDumpActive;
}
-#endif
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
#if defined(PDUMP_DEBUG_OUTFILES)
static INLINE
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc == IMG_NULL)
{
-
+ /* Kernel PID */
return 0;
}
return psPerProc->ui32PID;
}
-#endif
-
+#endif /* PDUMP_DEBUG_OUTFILES */
+
+/**************************************************************************
+ * Function Name : GetTempBuffer
+ * Inputs : None
+ * Outputs : None
+ * Returns : Temporary buffer address, or IMG_NULL
+ * Description : Get temporary buffer address.
+**************************************************************************/
static IMG_VOID *GetTempBuffer(IMG_VOID)
{
-
+ /*
+ * Allocate the temporary buffer, it it hasn't been allocated already.
+ * Return the address of the temporary buffer, or IMG_NULL if it
+ * couldn't be allocated.
+ * It is expected that the buffer will be allocated once, at driver
+ * load time, and left in place until the driver unloads.
+ */
+
if (gpvTempBuffer == IMG_NULL)
{
PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
IMG_VOID PDumpInitCommon(IMG_VOID)
{
-
+ /* Allocate temporary buffer for copying from user space */
(IMG_VOID) GetTempBuffer();
-
+ /* Call environment specific PDump initialisation */
PDumpInit();
}
IMG_VOID PDumpDeInitCommon(IMG_VOID)
{
-
+ /* Free temporary buffer */
FreeTempBuffer();
-
+ /* Call environment specific PDump Deinitialisation */
PDumpDeInit();
}
#endif
}
+/**************************************************************************
+ * Function Name : PDumpRegWithFlagsKM
+ * Inputs : pszPDumpDevName, Register offset, and value to write
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Create a PDUMP string, which represents a register write
+**************************************************************************/
PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
IMG_UINT32 ui32Reg,
IMG_UINT32 ui32Data,
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpRegKM
+ * Inputs : Register offset, and value to write
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Create a PDUMP string, which represents a register write
+**************************************************************************/
PVRSRV_ERROR PDumpRegKM(IMG_CHAR *pszPDumpRegName,
IMG_UINT32 ui32Reg,
IMG_UINT32 ui32Data)
return PDumpRegWithFlagsKM(pszPDumpRegName, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS);
}
+/**************************************************************************
+ * Function Name : PDumpRegPolWithFlagsKM
+ * Inputs : Description of what this register read is trying to do
+ * pszPDumpDevName
+ * Register offset
+ * expected value
+ * mask for that value
+ * Outputs : None
+ * Returns : None
+ * Description : Create a PDUMP string which represents a register read
+ * with the expected value
+**************************************************************************/
PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
IMG_UINT32 ui32RegAddr,
IMG_UINT32 ui32RegValue,
IMG_UINT32 ui32Flags,
PDUMP_POLL_OPERATOR eOperator)
{
-
+ /* Timings correct for linux and XP */
#define POLL_DELAY 1000U
#define POLL_COUNT_LONG (2000000000U / POLL_DELAY)
#define POLL_COUNT_SHORT (1000000U / POLL_DELAY)
PDUMP_DBG(("PDumpRegPolWithFlagsKM"));
if ( _PDumpIsPersistent() )
{
-
+ /* Don't pdump-poll if the process is persistent */
return PVRSRV_OK;
}
-#if 0
- if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
- (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_TA_FINISHED_MASK) != 0) ||
- ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
- (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK) != 0) ||
- ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
- (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK) != 0))
- {
- ui32PollCount = POLL_COUNT_LONG;
- }
- else
-#endif
- {
- ui32PollCount = POLL_COUNT_LONG;
- }
+ ui32PollCount = POLL_COUNT_LONG;
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "POL :%s:0x%08X 0x%08X 0x%08X %d %u %d\r\n",
pszPDumpRegName, ui32RegAddr, ui32RegValue,
}
+/**************************************************************************
+ * Function Name : PDumpRegPol
+ * Inputs : Description of what this register read is trying to do
+ * pszPDumpDevName
+ Register offset
+ * expected value
+ * mask for that value
+ * Outputs : None
+ * Returns : None
+ * Description : Create a PDUMP string which represents a register read
+ * with the expected value
+**************************************************************************/
PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue, IMG_UINT32 ui32Mask, PDUMP_POLL_OPERATOR eOperator)
{
return PDumpRegPolWithFlagsKM(pszPDumpRegName, ui32RegAddr, ui32RegValue, ui32Mask, PDUMP_FLAGS_CONTINUOUS, eOperator);
}
+/**************************************************************************
+ * Function Name : PDumpMallocPages
+ * Inputs : psDevID, ui32DevVAddr, pvLinAddr, ui32NumBytes, hOSMemHandle
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : None
+ * Description : Malloc memory pages
+
+FIXME: This function assumes pvLinAddr is the address of the start of the
+block for this hOSMemHandle.
+If this isn't true, the call to PDumpOSCPUVAddrToDevPAddr below will be
+incorrect. (Consider using OSMemHandleToCPUPAddr() instead?)
+The only caller at the moment is in buffer_manager.c, which does the right
+thing.
+**************************************************************************/
PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER *psDevID,
IMG_UINT32 ui32DevVAddr,
IMG_CPU_VIRTADDR pvLinAddr,
PDUMP_GET_SCRIPT_STRING();
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* Always dump physical pages backing a shared allocation */
ui32Flags |= ( _PDumpIsPersistent() || bShared ) ? PDUMP_FLAGS_PERSISTENT : 0;
#else
PVR_UNREFERENCED_PARAMETER(bShared);
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
#endif
-
+ /* However, lin addr is only required in non-linux OSes */
#if !defined(LINUX)
PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & HOST_PAGEMASK) == 0);
#endif
PVR_ASSERT(((IMG_UINT32) ui32DevVAddr & HOST_PAGEMASK) == 0);
PVR_ASSERT(((IMG_UINT32) ui32NumBytes & HOST_PAGEMASK) == 0);
-
-
+ /*
+ Write a comment to the PDump2 script streams indicating the memory allocation
+ */
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- MALLOC :%s:VA_%08X 0x%08X %u\r\n",
psDevID->pszPDumpDevName, ui32DevVAddr, ui32NumBytes, ui32PageSize);
if(eErr != PVRSRV_OK)
}
PDumpOSWriteString2(hScript, ui32Flags);
-
-
+ /*
+ Write to the MMU script stream indicating the memory allocation
+ */
pui8LinAddr = (IMG_PUINT8) pvLinAddr;
ui32Offset = 0;
ui32NumPages = ui32NumBytes / ui32PageSize;
{
ui32NumPages--;
-
-
-
-
-
-
-
-
-
-
+ /* See FIXME in function header.
+ * Currently: linux pdump uses OSMemHandle and Offset
+ * other OSes use the LinAddr.
+ */
+ /* Calculate the device physical address for this page */
PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
hOSMemHandle,
ui32Offset,
ui32PageSize,
&sDevPAddr);
ui32Page = (IMG_UINT32)(sDevPAddr.uiAddr / ui32PageSize);
-
+ /* increment kernel virtual address */
pui8LinAddr += ui32PageSize;
ui32Offset += ui32PageSize;
}
+/**************************************************************************
+ * Function Name : PDumpMallocPageTable
+ * Inputs : psDevId, pvLinAddr, ui32NumBytes, hUniqueTag
+ * Outputs : None
+ * Returns : None
+ * Description : Malloc memory page table
+**************************************************************************/
PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
-
+ /*
+ Write a comment to the PDump2 script streams indicating the memory allocation
+ */
eErr = PDumpOSBufprintf(hScript,
ui32MaxLen,
"-- MALLOC :%s:PAGE_TABLE 0x%08X %u\r\n",
}
PDumpOSWriteString2(hScript, ui32Flags);
-
-
-
-
-
-
+ /*
+ Write to the MMU script stream indicating the memory allocation
+ */
+ // FIXME: we'll never need more than a 4k page for a pagetable
+ // fixing to 1 page for now.
+ // note: when the mmu code supports packed pagetables the PTs
+ // will be as small as 16bytes
PDumpOSCPUVAddrToDevPAddr(psDevId->eDeviceType,
- hOSMemHandle,
+ hOSMemHandle, /* um - does this mean the pvLinAddr would be ignored? Is that safe? */
ui32Offset,
(IMG_PUINT8) pvLinAddr,
ui32PTSize,
psDevId->pszPDumpDevName,
(IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
sDevPAddr.uiAddr,
- ui32PTSize,
- ui32PTSize,
+ ui32PTSize,//size
+ ui32PTSize,//alignment
sDevPAddr.uiAddr);
if(eErr != PVRSRV_OK)
{
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpFreePages
+ * Inputs : psBMHeap, sDevVAddr, ui32NumBytes, hUniqueTag,
+ bInterLeaved
+ * Outputs : None
+ * Returns : None
+ * Description : Free memory pages
+**************************************************************************/
PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
IMG_DEV_VIRTADDR sDevVAddr,
IMG_UINT32 ui32NumBytes,
IMG_UINT32 ui32PageSize,
IMG_HANDLE hUniqueTag,
- IMG_BOOL bInterleaved)
+ IMG_BOOL bInterleaved,
+ IMG_BOOL bSparse)
{
PVRSRV_ERROR eErr;
IMG_UINT32 ui32NumPages, ui32PageCounter;
psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
-
+ /*
+ Write a comment to the PDUMP2 script streams indicating the memory free
+ */
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:VA_%08X\r\n",
psDeviceNode->sDevId.pszPDumpDevName, sDevVAddr.uiAddr);
if(eErr != PVRSRV_OK)
}
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* if we're dumping a shared heap, need to ensure phys allocation
+ * is freed even if this app isn't the one marked for pdumping
+ */
{
PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
#endif
PDumpOSWriteString2(hScript, ui32Flags);
-
-
+ /*
+ Write to the MMU script stream indicating the memory free
+ */
ui32NumPages = ui32NumBytes / ui32PageSize;
for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages; ui32PageCounter++)
{
{
sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->pMMUHeap, sDevVAddr);
- PVR_ASSERT(sDevPAddr.uiAddr != 0)
+ /* With sparse mappings we expect spaces */
+ if (bSparse && (sDevPAddr.uiAddr == 0))
+ {
+ continue;
+ }
+
+ PVR_ASSERT(sDevPAddr.uiAddr != 0);
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:PA_%08X%08X\r\n",
psDeviceNode->sDevId.pszPDumpDevName, (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag, sDevPAddr.uiAddr);
}
else
{
-
+ /* Gap pages in an interleaved allocation should be ignored. */
}
sDevVAddr.uiAddr += ui32PageSize;
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpFreePageTable
+ * Inputs : psDevID, pvLinAddr, ui32NumBytes, hUniqueTag
+ * Outputs : None
+ * Returns : None
+ * Description : Free memory page table
+**************************************************************************/
PVRSRV_ERROR PDumpFreePageTable (PVRSRV_DEVICE_IDENTIFIER *psDevID,
IMG_HANDLE hOSMemHandle,
IMG_CPU_VIRTADDR pvLinAddr,
ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
- PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize-1UL)) == 0);
-
-
+ /* override QAC warning about wrap around */
+ PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize-1UL)) == 0); /* PRQA S 3382 */
+ /*
+ Write a comment to the PDUMP2 script streams indicating the memory free
+ */
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:PAGE_TABLE\r\n", psDevID->pszPDumpDevName);
if(eErr != PVRSRV_OK)
{
}
PDumpOSWriteString2(hScript, ui32Flags);
-
-
-
-
-
-
+ /*
+ Write to the MMU script stream indicating the memory free
+ */
+ // FIXME: we'll never need more than a 4k page for a pagetable
+ // fixing to 1 page for now.
+ // note: when the mmu code supports packed pagetables the PTs
+ // will be as small as 16bytes
PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
- hOSMemHandle,
+ hOSMemHandle, /* um - does this mean the pvLinAddr would be ignored? Is that safe? */
0,
(IMG_PUINT8) pvLinAddr,
ui32PTSize,
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpPDRegWithFlags
+ * Inputs : psMMUAttrib
+ * : ui32Reg
+ * : ui32Data
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : None
+ * Description : Kernel Services internal pdump memory API
+ * Used for registers specifying physical addresses
+ e.g. MMU page directory register
+**************************************************************************/
PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_UINT32 ui32Reg,
IMG_UINT32 ui32Data,
pszRegString = psMMUAttrib->sDevId.pszPDumpRegName;
}
-
-
+ /*
+ Write to the MMU script stream indicating the physical page directory
+ */
#if defined(SGX_FEATURE_36BIT_MMU)
eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
"WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpPDReg
+ * Inputs : psMMUAttrib
+ : ui32Reg
+ * : ui32Data
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Kernel Services internal pdump memory API
+ * Used for registers specifying physical addresses
+ e.g. MMU page directory register
+**************************************************************************/
PVRSRV_ERROR PDumpPDReg (PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_UINT32 ui32Reg,
IMG_UINT32 ui32Data,
return PDumpPDRegWithFlags(psMMUAttrib, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
}
+/**************************************************************************
+ * Function Name : PDumpMemPolKM
+ * Inputs : psMemInfo
+ * : ui32Offset
+ * : ui32Value
+ * : ui32Mask
+ * : eOperator
+ * : ui32Flags
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Implements Client pdump memory poll API
+**************************************************************************/
PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
IMG_UINT32 ui32Offset,
IMG_UINT32 ui32Value,
if ( _PDumpIsPersistent() )
{
-
+ /* Don't pdump-poll if the process is persistent */
return PVRSRV_OK;
}
-
+ /* Check the offset and size don't exceed the bounds of the allocation */
PVR_ASSERT((ui32Offset + sizeof(IMG_UINT32)) <= psMemInfo->uAllocSize);
psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
-
-
+ /*
+ Write a comment to the PDump2 script streams indicating the virtual memory pol
+ */
eErr = PDumpOSBufprintf(hScript,
ui32MaxLen,
"-- POL :%s:VA_%08X 0x%08X 0x%08X %d %d %d\r\n",
pui8LinAddr = psMemInfo->pvLinAddrKM;
-
+ /* Advance address by offset */
pui8LinAddr += ui32Offset;
-
-
-
+ /*
+ query the buffer manager for the physical pages that back the
+ virtual address
+ */
PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
ui32Offset,
pui8LinAddr,
psMMUAttrib->ui32DataPageMask,
&ui32PageOffset);
-
+ /* calculate the DevV page address */
sDevVPageAddr.uiAddr = psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
-
+ /* get the physical page address based on the device virtual address */
BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
-
+ /* convert DevP page address to byte address */
sDevPAddr.uiAddr += ui32PageOffset;
eErr = PDumpOSBufprintf(hScript,
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)
+/**************************************************************************
+ * Function Name : _PDumpMemIntKM
+ * Inputs : psMemInfo
+ * : ui32Offset
+ * : ui32Bytes
+ * : ui32Flags
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Implements Client pdump mem API
+**************************************************************************/
+static PVRSRV_ERROR _PDumpMemIntKM(IMG_PVOID pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
{
PVRSRV_ERROR eErr;
IMG_UINT32 ui32NumPages;
PDUMP_GET_SCRIPT_AND_FILE_STRING();
-
+ /* PRQA S 3415 1 */ /* side effects desired */
if (ui32Bytes == 0 || PDumpOSIsSuspended())
{
return PVRSRV_OK;
psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
-
-
+ /*
+ check the offset and size don't exceed the bounds of the allocation
+ */
PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->uAllocSize);
if (!PDumpOSJTInitialised())
}
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* if we're dumping a shared heap, need to ensure phys allocation
+ * is initialised even if this app isn't the one marked for pdumping
+ */
{
BM_HEAP *pHeap = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap;
PVRSRV_DEVICE_NODE *psDeviceNode = pHeap->pBMContext->psDeviceNode;
}
#endif
-
+ /* setup memory addresses */
if(pvAltLinAddr)
{
pui8DataLinAddr = pvAltLinAddr;
pui8LinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM;
sDevVAddr = psMemInfo->sDevVAddr;
-
+ /* advance address by offset */
sDevVAddr.uiAddr += ui32Offset;
pui8LinAddr += ui32Offset;
ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
-
-
+ /*
+ write the binary data up-front.
+ */
if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
pui8DataLinAddr,
ui32Bytes,
return eErr;
}
-
-
+ /*
+ Write a comment to the PDump2 script streams indicating the virtual memory load
+ */
eErr = PDumpOSBufprintf(hScript,
ui32MaxLenScript,
"-- LDB :%s:VA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
}
PDumpOSWriteString2(hScript, ui32Flags);
-
-
-
+ /*
+ query the buffer manager for the physical pages that back the
+ virtual address
+ */
PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
ui32Offset,
pui8LinAddr,
{
ui32NumPages--;
-
+ /* calculate the DevV page address */
sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
if (ui32DataPageSize <= PDUMP_TEMP_BUFFER_SIZE)
{
-
+ /* if a page fits within temp buffer, we should dump in page-aligned chunks. */
PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
}
-
+ /* get the physical page address based on the device virtual address */
BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
-
+ /* convert DevP page address to byte address */
sDevPAddr.uiAddr += ui32PageByteOffset;
-
+ /* how many bytes to dump from this page */
if (ui32PageByteOffset + ui32Bytes > ui32DataPageSize)
{
-
+ /* dump up to the page boundary */
ui32BlockBytes = ui32DataPageSize - ui32PageByteOffset;
}
else
{
-
+ /* dump what's left */
ui32BlockBytes = ui32Bytes;
}
}
PDumpOSWriteString2(hScript, ui32Flags);
-
+ /* update details for next page */
#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
-
+ /* page may be larger than pdump temporary buffer */
ui32PageByteOffset = (ui32PageByteOffset + ui32BlockBytes) % ui32DataPageSize;
#else
-
+ /* page offset 0 after first page dump */
ui32PageByteOffset = 0;
#endif
-
- ui32Bytes -= ui32BlockBytes;
-
+ /* bytes left over */
+ ui32Bytes -= ui32BlockBytes; /* PRQA S 3382 */ /* QAC missed MIN test */
+ /* advance devVaddr */
sDevVAddr.uiAddr += ui32BlockBytes;
-
+ /* advance the cpuVaddr */
pui8LinAddr += ui32BlockBytes;
-
+ /* update the file write offset */
ui32ParamOutPos += ui32BlockBytes;
}
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpMemKM
+ * Inputs : psMemInfo
+ * : ui32Offset
+ * : ui32Bytes
+ * : ui32Flags
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Implements Client pdump mem API
+**************************************************************************/
+PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ /*
+ For now we don't support dumping sparse allocations that
+ are from within the kernel, or are from UM but without a
+ alternative linear address
+ */
+ PVR_ASSERT((psMemInfo->ui32Flags & PVRSRV_MEM_SPARSE) == 0);
+
+ if (psMemInfo->ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ else
+ {
+ return _PDumpMemIntKM(pvAltLinAddr,
+ psMemInfo,
+ ui32Offset,
+ ui32Bytes,
+ ui32Flags,
+ hUniqueTag);
+ }
+}
+
PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_HANDLE hOSMemHandle,
IMG_CPU_VIRTADDR pvLinAddr,
{
PDUMP_MMU_ATTRIB sMMUAttrib;
-
+ /* Override the (variable) PT size since PDs are always 4K in size */
sMMUAttrib = *psMMUAttrib;
sMMUAttrib.ui32PTSize = (IMG_UINT32)HOST_PAGESIZE();
return PDumpMemPTEntriesKM( &sMMUAttrib,
hUniqueTag2);
}
+/**************************************************************************
+ * Function Name : PDumpMemPTEntriesKM
+ * Inputs : psMMUAttrib - MMU attributes for pdump
+ * : pvLinAddr - CPU address of PT base
+ * : ui32Bytes - size
+ * : ui32Flags - pdump flags
+ * : bInitialisePages - whether to initialise pages from file
+ * : hUniqueTag1 - ID for PT physical page
+ * : hUniqueTag2 - ID for target physical page (if !bInitialisePages)
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Kernel Services internal pdump memory API
+ * Used for memory without DevVAddress mappings
+ e.g. MMU page tables
+ FIXME: This function doesn't support non-4k data pages,
+ e.g. dummy data page
+**************************************************************************/
PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_HANDLE hOSMemHandle,
IMG_CPU_VIRTADDR pvLinAddr,
IMG_CPU_PHYADDR sCpuPAddr;
IMG_UINT32 ui32Offset;
IMG_UINT32 ui32ParamOutPos;
- IMG_UINT32 ui32PageMask;
+ IMG_UINT32 ui32PageMask; /* mask for the physical page backing the PT */
PDUMP_GET_SCRIPT_AND_FILE_STRING();
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
if (bInitialisePages)
{
-
-
-
+ /*
+ write the binary data up-front
+ Use the 'continuous' memory stream
+ */
if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
pvLinAddr,
ui32Bytes,
}
}
-
-
-
-
-
+ /*
+ Mask for the physical page address backing the PT
+ The PT size can be less than 4k with variable page size support
+ The PD size is always 4k
+ FIXME: This won't work for dumping the dummy data page
+ */
ui32PageMask = psMMUAttrib->ui32PTSize - 1;
-
-
-
+ /*
+ Write to the MMU script stream indicating the physical page table entries
+ */
+ /* physical pages that back the virtual address */
ui32PageOffset = (IMG_UINT32)((IMG_UINTPTR_T)pvLinAddr & (psMMUAttrib->ui32PTSize - 1));
ui32NumPages = (ui32PageOffset + ui32Bytes + psMMUAttrib->ui32PTSize - 1) / psMMUAttrib->ui32PTSize;
pui8LinAddr = (IMG_UINT8*) pvLinAddr;
while (ui32NumPages)
{
ui32NumPages--;
-
-
-
-
-
-
+ /* FIXME: if we used OSMemHandleToCPUPAddr() here, we might be
+ able to lose the lin addr arg. At least one thing that
+ would need to be done here is to pass in an offset, as the
+ calling function doesn't necessarily give us the lin addr
+ of the start of the mem area. Probably best to keep the
+ lin addr arg for now - but would be nice to remove the
+ redundancy */
sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
sDevPAddr = SysCpuPAddrToDevPAddr(psMMUAttrib->sDevId.eDeviceType, sCpuPAddr);
-
+ /* how many bytes to dump from this page */
if (ui32PageOffset + ui32Bytes > psMMUAttrib->ui32PTSize)
{
-
+ /* dump up to the page boundary */
ui32BlockBytes = psMMUAttrib->ui32PTSize - ui32PageOffset;
}
else
{
-
+ /* dump what's left */
ui32BlockBytes = ui32Bytes;
}
-
-
+ /*
+ Write a comment to the MMU script stream indicating the page table load
+ */
if (bInitialisePages)
{
{
for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(IMG_UINT32))
{
- IMG_UINT32 ui32PTE = *((IMG_UINT32 *)(IMG_UINTPTR_T)(pui8LinAddr + ui32Offset));
+ IMG_UINT32 ui32PTE = *((IMG_UINT32 *)(IMG_UINTPTR_T)(pui8LinAddr + ui32Offset)); /* PRQA S 3305 */ /* strict pointer */
if ((ui32PTE & psMMUAttrib->ui32PDEMask) != 0)
{
-
+ /* PT entry points to non-null page */
#if defined(SGX_FEATURE_36BIT_MMU)
eErr = PDumpOSBufprintf(hScript,
ui32MaxLenScript,
}
}
-
+ /* update details for next page */
-
+ /* page offset 0 after first page dump */
ui32PageOffset = 0;
-
+ /* bytes left over */
ui32Bytes -= ui32BlockBytes;
-
+ /* advance the cpuVaddr */
pui8LinAddr += ui32BlockBytes;
-
+ /* update the file write offset */
ui32ParamOutPos += ui32BlockBytes;
}
IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
IMG_UINT32 ui32ParamOutPos;
PDUMP_MMU_ATTRIB *psMMUAttrib;
- IMG_UINT32 ui32PageMask;
+ IMG_UINT32 ui32PageMask; /* mask for the physical page backing the PT */
PDUMP_GET_SCRIPT_AND_FILE_STRING();
ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
-
+ /* Write the PD phys addr to the param stream up front */
if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
(IMG_UINT8 *)&sPDDevPAddr,
sizeof(IMG_DEV_PHYADDR),
return eErr;
}
-
+ /* Write a comment indicating the PD phys addr write, so that the offsets
+ * into the param stream increase in correspondence with the number of bytes
+ * written. */
eErr = PDumpOSBufprintf(hScript,
ui32MaxLenScript,
"-- LDB :%s:PA_0x%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
}
PDumpOSWriteString2(hScript, ui32Flags);
-
sDevVAddr = psMemInfo->sDevVAddr;
ui32PageByteOffset = sDevVAddr.uiAddr & ui32PageMask;
return PVRSRV_OK;
}
-
-
-
+/**************************************************************************
+ * Function Name : PDumpCommentKM
+ * Inputs : pszComment, ui32Flags
+ * Outputs : None
+ * Returns : None
+ * Description : Dumps a comment
+**************************************************************************/
PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
{
PVRSRV_ERROR eErr;
- IMG_CHAR pszCommentPrefix[] = "-- ";
+ IMG_CHAR pszCommentPrefix[] = "-- "; /* prefix for comments */
#if defined(PDUMP_DEBUG_OUTFILES)
IMG_CHAR pszTemp[256];
#endif
PDUMP_GET_SCRIPT_STRING();
PDUMP_DBG(("PDumpCommentKM"));
#if defined(PDUMP_DEBUG_OUTFILES)
-
+ /* include comments in the "extended" init phase.
+ * default is to ignore them.
+ */
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
#endif
-
+ /* Put \r \n sequence at the end if it isn't already there */
PDumpOSVerifyLineEnding(pszComment, ui32MaxLen);
-
+ /* Length of string excluding terminating NULL character */
ui32LenCommentPrefix = PDumpOSBuflen(pszCommentPrefix, sizeof(pszCommentPrefix));
-
-
+ /* Ensure output file is available for writing */
+ /* FIXME: is this necessary? */
if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_SCRIPT2),
(IMG_UINT8*)pszCommentPrefix,
ui32LenCommentPrefix,
}
#if defined(PDUMP_DEBUG_OUTFILES)
-
+ /* Prefix comment with PID and line number */
eErr = PDumpOSSprintf(pszTemp, 256, "%d-%d %s",
_PDumpGetPID(),
g_ui32EveryLineCounter,
pszComment);
-
+ /* Append the comment to the script stream */
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "%s",
pszTemp);
#else
return PVRSRV_OK;
}
-
+/**************************************************************************
+ * Function Name : PDumpCommentWithFlags
+ * Inputs : psPDev - PDev for PDump device
+ * : pszFormat - format string for comment
+ * : ... - args for format string
+ * Outputs : None
+ * Returns : None
+ * Description : PDumps a comments
+**************************************************************************/
PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
{
PVRSRV_ERROR eErr;
PDUMP_va_list ap;
PDUMP_GET_MSG_STRING();
-
+ /* Construct the string */
PDUMP_va_start(ap, pszFormat);
eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
PDUMP_va_end(ap);
return PDumpCommentKM(pszMsg, ui32Flags);
}
+/**************************************************************************
+ * Function Name : PDumpComment
+ * Inputs : psPDev - PDev for PDump device
+ * : pszFormat - format string for comment
+ * : ... - args for format string
+ * Outputs : None
+ * Returns : None
+ * Description : PDumps a comments
+**************************************************************************/
PVRSRV_ERROR PDumpComment(IMG_CHAR *pszFormat, ...)
{
PVRSRV_ERROR eErr;
PDUMP_va_list ap;
PDUMP_GET_MSG_STRING();
-
+ /* Construct the string */
PDUMP_va_start(ap, pszFormat);
eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
PDUMP_va_end(ap);
return PDumpCommentKM(pszMsg, PDUMP_FLAGS_CONTINUOUS);
}
+/**************************************************************************
+ * Function Name : PDumpDriverInfoKM
+ * Inputs : pszString, ui32Flags
+ * Outputs : None
+ * Returns : None
+ * Description : Dumps a comment
+**************************************************************************/
PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags)
{
PVRSRV_ERROR eErr;
IMG_UINT32 ui32MsgLen;
PDUMP_GET_MSG_STRING();
-
+ /* Construct the string */
eErr = PDumpOSSprintf(pszMsg, ui32MaxLen, "%s", pszString);
if(eErr != PVRSRV_OK)
{
return eErr;
}
-
+ /* Put \r \n sequence at the end if it isn't already there */
PDumpOSVerifyLineEnding(pszMsg, ui32MaxLen);
ui32MsgLen = PDumpOSBuflen(pszMsg, ui32MaxLen);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PDumpBitmapKM
+
+ @Description
+
+ Dumps a bitmap from device memory to a file
+
+ @Input psDevId
+ @Input pszFileName
+ @Input ui32FileOffset
+ @Input ui32Width
+ @Input ui32Height
+ @Input ui32StrideInBytes
+ @Input sDevBaseAddr
+ @Input ui32Size
+ @Input ePixelFormat
+ @Input eMemFormat
+ @Input ui32PDumpFlags
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR PDumpBitmapKM( PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump bitmap of render\r\n");
-
+ /* find MMU context ID */
ui32MMUContextID = psDeviceNode->pfnMMUGetContextID( hDevMemContext );
eErr = PDumpOSBufprintf(hScript,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PDumpReadRegKM
+
+ @Description
+
+ Dumps a read from a device register to a file
+
+ @Input psConnection : connection info
+ @Input pszFileName
+ @Input ui32FileOffset
+ @Input ui32Address
+ @Input ui32Size
+ @Input ui32PDumpFlags
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR PDumpReadRegKM ( IMG_CHAR *pszPDumpRegName,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpTestNextFrame
+ @brief Tests whether the next frame will be pdumped
+ @param ui32CurrentFrame
+ @return bFrameDumped
+*****************************************************************************/
IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame)
{
IMG_BOOL bFrameDumped;
-
-
+ /*
+ Try dumping a string
+ */
(IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame + 1);
bFrameDumped = PDumpIsCaptureFrameKM();
(IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame);
return bFrameDumped;
}
+/*****************************************************************************
+ @name PDumpSignatureRegister
+ @brief Dumps a single signature register
+ @param psDevId - device ID
+ @param ui32Address - The register address
+ @param ui32Size - The amount of data to be dumped in bytes
+ @param pui32FileOffset - Offset of dump in output file
+ @param ui32Flags - Flags
+ @return none
+*****************************************************************************/
static PVRSRV_ERROR PDumpSignatureRegister (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32Address,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpRegisterRange
+ @brief Dumps a list of signature registers to a file
+ @param psDevId - device ID
+ @param pszFileName - target filename for dump
+ @param pui32Registers - register list
+ @param ui32NumRegisters - number of regs to dump
+ @param pui32FileOffset - file offset
+ @param ui32Size - size of write in bytes
+ @param ui32Flags - pdump flags
+ @return none
+ *****************************************************************************/
static IMG_VOID PDumpRegisterRange(PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_CHAR *pszFileName,
IMG_UINT32 *pui32Registers,
}
}
+/*****************************************************************************
+ @name PDump3DSignatureRegisters
+ @brief Dumps the signature registers for 3D modules...
+ @param psDevId - device ID info
+ @param pui32Registers - register list
+ @param ui32NumRegisters - number of regs to dump
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_UINT32 ui32DumpFrameNum,
IMG_BOOL bLastFrame,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpTASignatureRegisters
+ @brief Dumps the TA signature registers
+ @param psDevId - device id info
+ @param ui32DumpFrameNum - frame number
+ @param ui32TAKickCount - TA kick counter
+ @param bLastFrame
+ @param pui32Registers - register list
+ @param ui32NumRegisters - number of regs to dump
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDumpTASignatureRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_UINT32 ui32DumpFrameNum,
IMG_UINT32 ui32TAKickCount,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpCounterRegisters
+ @brief Dumps the performance counters
+ @param psDevId - device id info
+ @param ui32DumpFrameNum - frame number
+ @param bLastFrame
+ @param pui32Registers - register list
+ @param ui32NumRegisters - number of regs to dump
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDumpCounterRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_UINT32 ui32DumpFrameNum,
IMG_BOOL bLastFrame,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpRegRead
+ @brief Dump signature register read to script
+ @param pszPDumpDevName - pdump device name
+ @param ui32RegOffset - register offset
+ @param ui32Flags - pdump flags
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
const IMG_UINT32 ui32RegOffset,
IMG_UINT32 ui32Flags)
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpSaveMemKM
+ @brief Save device memory to a file
+ @param psDevId
+ @param pszFileName
+ @param ui32FileOffset
+ @param sDevBaseAddr
+ @param ui32Size
+ @param ui32PDumpFlags
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpCycleCountRegRead
+ @brief Dump counter register read to script
+ @param ui32RegOffset - register offset
+ @param bLastFrame
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
const IMG_UINT32 ui32RegOffset,
IMG_BOOL bLastFrame)
}
+/*!
+******************************************************************************
+
+ @Function PDumpSignatureBuffer
+
+ @Description
+
+ Dumps a signature registers buffer
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR PDumpSignatureBuffer (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_CHAR *pszFileName,
IMG_CHAR *pszBufferType,
}
+/*!
+******************************************************************************
+
+ @Function PDumpHWPerfCBKM
+
+ @Description
+
+ Dumps the HW Perf Circular Buffer
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR PDumpHWPerfCBKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
}
+/*****************************************************************************
+ FUNCTION : PDumpCBP
+
+ PURPOSE : Dump CBP command to script
+
+ PARAMETERS :
+
+ RETURNS : None
+*****************************************************************************/
PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
IMG_UINT32 ui32ROffOffset,
IMG_UINT32 ui32WPosVal,
IMG_DEV_VIRTADDR sDevVAddr;
IMG_DEV_PHYADDR sDevPAddr;
IMG_DEV_VIRTADDR sDevVPageAddr;
-
+ //IMG_CPU_PHYADDR CpuPAddr;
PDUMP_MMU_ATTRIB *psMMUAttrib;
PDUMP_GET_SCRIPT_STRING();
psMMUAttrib = ((BM_BUF*)psROffMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
-
+ /* Check the offset and size don't exceed the bounds of the allocation */
PVR_ASSERT((ui32ROffOffset + sizeof(IMG_UINT32)) <= psROffMemInfo->uAllocSize);
pui8LinAddr = psROffMemInfo->pvLinAddrKM;
sDevVAddr = psROffMemInfo->sDevVAddr;
-
+ /* Advance addresses by offset */
pui8LinAddr += ui32ROffOffset;
sDevVAddr.uiAddr += ui32ROffOffset;
-
-
-
+ /*
+ query the buffer manager for the physical pages that back the
+ virtual address
+ */
PDumpOSCPUVAddrToPhysPages(psROffMemInfo->sMemBlk.hOSMemHandle,
ui32ROffOffset,
pui8LinAddr,
psMMUAttrib->ui32DataPageMask,
&ui32PageOffset);
-
+ /* calculate the DevV page address */
sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
-
+ /* get the physical page address based on the device virtual address */
BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
-
+ /* convert DevP page address to byte address */
sDevPAddr.uiAddr += ui32PageOffset;
eErr = PDumpOSBufprintf(hScript,
}
+/**************************************************************************
+ * Function Name : PDumpIDLWithFlags
+ * Inputs : Idle time in clocks
+ * Outputs : None
+ * Returns : Error
+ * Description : Dump IDL command to script
+**************************************************************************/
PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
{
PVRSRV_ERROR eErr;
}
+/**************************************************************************
+ * Function Name : PDumpIDL
+ * Inputs : Idle time in clocks
+ * Outputs : None
+ * Returns : Error
+ * Description : Dump IDL command to script
+**************************************************************************/
PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
{
return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
}
+/**************************************************************************
+ * Function Name : PDumpMemUM
+ * Inputs : pvAltLinAddrUM
+ * : pvLinAddrUM
+ * : psMemInfo
+ * : ui32Offset
+ * : ui32Bytes
+ * : ui32Flags
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Dump user mode memory
+**************************************************************************/
PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_PVOID pvAltLinAddrUM,
IMG_PVOID pvLinAddrUM,
{
IMG_VOID *pvAddrUM;
IMG_VOID *pvAddrKM;
- IMG_UINT32 ui32BytesDumped;
- IMG_UINT32 ui32CurrentOffset;
+ PVRSRV_ERROR eError;
if (psMemInfo->pvLinAddrKM != IMG_NULL && pvAltLinAddrUM == IMG_NULL)
{
-
+ /*
+ * There is a kernel virtual address for the memory that is
+ * being dumped, and no alternate user mode linear address.
+ */
return PDumpMemKM(IMG_NULL,
psMemInfo,
ui32Offset,
pvAddrKM = GetTempBuffer();
-
+ /*
+ * The memory to be dumped needs to be copied in from
+ * the client. Dump the memory, a buffer at a time.
+ */
PVR_ASSERT(pvAddrUM != IMG_NULL && pvAddrKM != IMG_NULL);
if (pvAddrUM == IMG_NULL || pvAddrKM == IMG_NULL)
{
PDumpCommentWithFlags(ui32Flags, "Dumping 0x%08x bytes of memory, in blocks of 0x%08x bytes", ui32Bytes, (IMG_UINT32)PDUMP_TEMP_BUFFER_SIZE);
}
- ui32CurrentOffset = ui32Offset;
- for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;)
+ if (psMemInfo->ui32Flags & PVRSRV_MEM_SPARSE)
{
- PVRSRV_ERROR eError;
- IMG_UINT32 ui32BytesToDump = MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+ /*
+ In case of sparse mappings we can't just copy the full range as not
+ all pages are valid, instead we walk a page at a time only dumping
+ if the a page exists at that address
+ */
+ IMG_UINT32 ui32BytesRemain = ui32Bytes;
+ IMG_UINT32 ui32InPageStart = ui32Offset & (~HOST_PAGEMASK);
+ IMG_UINT32 ui32PageOffset = ui32Offset & (HOST_PAGEMASK);
+ IMG_UINT32 ui32BytesToCopy = MIN(HOST_PAGESIZE() - ui32InPageStart, ui32BytesRemain);
- eError = OSCopyFromUser(psPerProc,
- pvAddrKM,
- pvAddrUM,
- ui32BytesToDump);
- if (eError != PVRSRV_OK)
+ do
{
- PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
- return eError;
- }
+ if (BM_MapPageAtOffset(BM_MappingHandleFromBuffer(psMemInfo->sMemBlk.hBuffer), ui32PageOffset))
+ {
+ eError = OSCopyFromUser(psPerProc,
+ pvAddrKM,
+ pvAddrUM,
+ ui32BytesToCopy);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
+ return eError;
+ }
- eError = PDumpMemKM(pvAddrKM,
- psMemInfo,
- ui32CurrentOffset,
- ui32BytesToDump,
- ui32Flags,
- hUniqueTag);
+ /*
+ At this point we know we're dumping a valid page so call
+ the internal function
+ */
+ eError = _PDumpMemIntKM(pvAddrKM,
+ psMemInfo,
+ ui32PageOffset + ui32InPageStart,
+ ui32BytesToCopy,
+ ui32Flags,
+ hUniqueTag);
+
+ if (eError != PVRSRV_OK)
+ {
+ /*
+ * If writing fails part way through, then some
+ * investigation is needed.
+ */
+ if (ui32BytesToCopy != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+ }
+ PVR_ASSERT(ui32BytesToCopy == 0);
+ return eError;
+ }
+ }
- if (eError != PVRSRV_OK)
+ VPTR_INC(pvAddrUM, ui32BytesToCopy);
+ ui32BytesRemain -= ui32BytesToCopy;
+ ui32InPageStart = 0;
+ ui32PageOffset += HOST_PAGESIZE();
+ } while(ui32BytesRemain);
+ }
+ else
+ {
+ IMG_UINT32 ui32CurrentOffset = ui32Offset;
+ IMG_UINT32 ui32BytesDumped;
+
+ for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;)
{
-
- if (ui32BytesDumped != 0)
+ IMG_UINT32 ui32BytesToDump = MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+
+ eError = OSCopyFromUser(psPerProc,
+ pvAddrKM,
+ pvAddrUM,
+ ui32BytesToDump);
+ if (eError != PVRSRV_OK)
{
- PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
+ return eError;
}
- PVR_ASSERT(ui32BytesDumped == 0);
- return eError;
+
+ eError = PDumpMemKM(pvAddrKM,
+ psMemInfo,
+ ui32CurrentOffset,
+ ui32BytesToDump,
+ ui32Flags,
+ hUniqueTag);
+
+ if (eError != PVRSRV_OK)
+ {
+ /*
+ * If writing fails part way through, then some
+ * investigation is needed.
+ */
+ if (ui32BytesDumped != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+ }
+ PVR_ASSERT(ui32BytesDumped == 0);
+ return eError;
+ }
+
+ VPTR_INC(pvAddrUM, ui32BytesToDump);
+ ui32CurrentOffset += ui32BytesToDump;
+ ui32BytesDumped += ui32BytesToDump;
}
-
- VPTR_INC(pvAddrUM, ui32BytesToDump);
- ui32CurrentOffset += ui32BytesToDump;
- ui32BytesDumped += ui32BytesToDump;
}
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : _PdumpAllocMMUContext
+ * Inputs : pui32MMUContextID
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : pdump util to allocate MMU contexts
+**************************************************************************/
static PVRSRV_ERROR _PdumpAllocMMUContext(IMG_UINT32 *pui32MMUContextID)
{
IMG_UINT32 i;
-
+ /* there are MAX_PDUMP_MMU_CONTEXTS contexts available, find one */
for(i=0; i<MAX_PDUMP_MMU_CONTEXTS; i++)
{
if((gui16MMUContextUsage & (1U << i)) == 0)
{
-
+ /* mark in use */
gui16MMUContextUsage |= 1U << i;
*pui32MMUContextID = i;
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : _PdumpFreeMMUContext
+ * Inputs : ui32MMUContextID
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : pdump util to free MMU contexts
+**************************************************************************/
static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
{
if(ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS)
{
-
+ /* free the id */
gui16MMUContextUsage &= ~(1U << ui32MMUContextID);
return PVRSRV_OK;
}
}
+/**************************************************************************
+ * Function Name : PDumpSetMMUContext
+ * Inputs :
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Set MMU Context
+**************************************************************************/
PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_CHAR *pszMemSpace,
IMG_UINT32 *pui32MMUContextID,
return eErr;
}
-
-
+ /* derive the DevPAddr */
+ /* FIXME: if we used OSMemHandleToCPUPAddr() here, we could lose the lin addr arg */
sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
-
+ /* and round to 4k page */
sDevPAddr.uiAddr &= ~((PVRSRV_4K_PAGE_SIZE) -1);
eErr = PDumpOSBufprintf(hScript,
}
PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
-
+ /* return the MMU Context ID */
*pui32MMUContextID = ui32MMUContextID;
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpClearMMUContext
+ * Inputs :
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Clear MMU Context
+**************************************************************************/
PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_CHAR *pszMemSpace,
IMG_UINT32 ui32MMUContextID,
PVR_UNREFERENCED_PARAMETER(eDeviceType);
PVR_UNREFERENCED_PARAMETER(ui32MMUType);
-
+ /* FIXME: Propagate error from PDumpComment once it's supported on
+ * all OSes and platforms
+ */
PDumpComment("Clear MMU Context for memory space %s\r\n", pszMemSpace);
eErr = PDumpOSBufprintf(hScript,
ui32MaxLen,
return PVRSRV_OK;
}
+/*****************************************************************************
+ FUNCTION : PDumpStoreMemToFile
+
+ PURPOSE : Dumps a given addr:size to a file
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
PDUMP_GET_SCRIPT_STRING();
-
-
-
+ /*
+ query the buffer manager for the physical pages that back the
+ virtual address
+ */
ui32PageOffset = (IMG_UINT32)((IMG_UINTPTR_T)psMemInfo->pvLinAddrKM & psMMUAttrib->ui32DataPageMask);
-
+ /* calculate the DevV page address */
sDevVPageAddr.uiAddr = uiAddr - ui32PageOffset;
-
+ /* get the physical page address based on the device virtual address */
BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
-
+ /* convert DevP page address to byte address */
sDevPAddr.uiAddr += ui32PageOffset;
PDumpOSBufprintf(hScript,
return PVRSRV_OK;
}
+/*****************************************************************************
+ FUNCTION : PDumpRegBasedCBP
+
+ PURPOSE : Dump CBP command to script
+
+ PARAMETERS :
+
+ RETURNS : None
+*****************************************************************************/
PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR *pszPDumpRegName,
IMG_UINT32 ui32RegOffset,
IMG_UINT32 ui32WPosVal,
}
-
+/****************************************************
+ * Non-uitron code here.
+ * For example, code communicating with dbg driver.
+ ***************************************************/
+/* PRQA S 5087 1 */ /* include file needed here */
#include "syscommon.h"
+/**************************************************************************
+ * Function Name : PDumpConnectionNotify
+ * Description : Called by the debugdrv to tell Services that pdump has
+ * connected
+ * NOTE: No debugdrv on uitron.
+ **************************************************************************/
IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID)
{
SYS_DATA *psSysData;
PVRSRV_DEVICE_NODE *psThis;
PVR_DPF((PVR_DBG_WARNING, "PDump has connected."));
-
+ /* Loop over all known devices */
SysAcquireData(&psSysData);
psThis = psSysData->psDeviceNodeList;
{
if (psThis->pfnPDumpInitDevice)
{
-
+ /* Reset pdump according to connected device */
psThis->pfnPDumpInitDevice(psThis);
}
psThis = psThis->psNext;
}
}
+/*****************************************************************************
+ * Function Name : DbgWrite
+ * Inputs : psStream - debug stream to write to
+ pui8Data - buffer
+ ui32BCount - buffer length
+ ui32Flags - flags, e.g. continuous, LF
+ * Outputs : None
+ * Returns : Bytes written
+ * Description : Write a block of data to a debug stream
+ * NOTE: No debugdrv on uitron.
+ *****************************************************************************/
IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
{
IMG_UINT32 ui32BytesWritten = 0;
IMG_UINT32 ui32Off = 0;
PDBG_STREAM_CONTROL psCtrl = psStream->psCtrl;
-
+ /* Return immediately if marked as "never" */
if ((ui32Flags & PDUMP_FLAGS_NEVER) != 0)
{
return ui32BCount;
}
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* Return if process is not marked for pdumping, unless it's persistent.
+ */
if ( (_PDumpIsProcessActive() == IMG_FALSE ) &&
((ui32Flags & PDUMP_FLAGS_PERSISTENT) == 0) )
{
}
#endif
-
+ /* Send persistent data first ...
+ * If we're still initialising the params will be captured to the
+ * init stream in the call to pfnDBGDrivWrite2 below.
+ */
if ( ((ui32Flags & PDUMP_FLAGS_PERSISTENT) != 0) && (psCtrl->bInitPhaseComplete) )
{
while (ui32BCount > 0)
{
-
-
-
+ /*
+ Params marked as persistent should be appended to the init phase.
+ For example window system mem mapping of the primary surface.
+ */
ui32BytesWritten = PDumpOSDebugDriverWrite( psStream,
PDUMP_WRITE_MODE_PERSISTENT,
&pui8Data[ui32Off], ui32BCount, 1, 0);
PVR_DPF((PVR_DBG_ERROR, "DbgWrite: Failed to send persistent data"));
if( (psCtrl->ui32Flags & DEBUG_FLAGS_READONLY) != 0)
{
-
+ /* suspend pdump to prevent flooding kernel log buffer */
PDumpSuspendKM();
}
return 0xFFFFFFFFU;
}
}
-
+ /* reset buffer counters */
ui32BCount = ui32Off; ui32Off = 0; ui32BytesWritten = 0;
}
{
if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0)
{
-
-
+ /*
+ If pdump client (or its equivalent) isn't running then throw continuous data away.
+ */
if (((psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
(psCtrl->ui32Start == 0xFFFFFFFFU) &&
(psCtrl->ui32End == 0xFFFFFFFFU) &&
}
}
-
-
-
+ /*
+ If the debug driver's buffers are full so no data could be written then yield
+ execution so pdump can run and empty them.
+ */
if (ui32BytesWritten == 0)
{
PDumpOSReleaseExecution();
ui32BCount -= ui32BytesWritten;
}
-
+ /* loop exits when i) all data is written, or ii) an unrecoverable error occurs */
}
-
-
return ui32BytesWritten;
}
-#else
-#endif
+#else /* defined(PDUMP) */
+/* disable warning about empty module */
+#endif /* defined(PDUMP) */
+/*****************************************************************************
+ End of file (pdump_common.c)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Per-process storage
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Manage per-process storage
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
#include "resman.h"
static HASH_TABLE *psHashTab = IMG_NULL;
+/*!
+******************************************************************************
+
+ @Function FreePerProcData
+
+ @Description Free a per-process data area
+
+ @Input psPerProc - pointer to per-process data area
+
+ @Return Error code, or PVRSRV_OK
+
+******************************************************************************/
static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
{
PVRSRV_ERROR eError;
if (uiPerProc == 0)
{
PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table"));
-
+ /*
+ * We must have failed early in the per-process data area
+ * creation, before the process ID was set.
+ */
PVR_ASSERT(psPerProc->ui32PID == 0);
}
else
PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID);
}
-
+ /* Free handle base for this process */
if (psPerProc->psHandleBase != IMG_NULL)
{
eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
}
}
-
+ /* Release handle for per-process data area */
if (psPerProc->hPerProcData != IMG_NULL)
{
eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA);
}
}
-
+ /* Call environment specific per process deinit function */
eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
if (eError != PVRSRV_OK)
{
sizeof(*psPerProc),
psPerProc,
psPerProc->hBlockAlloc);
-
+ /*not nulling pointer, copy on stack*/
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError));
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPerProcessData
+
+ @Description Return per-process data area
+
+ @Input ui32PID - process ID
+
+ @Return Pointer to per-process data area, or IMG_NULL on error.
+
+******************************************************************************/
PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID)
{
PVRSRV_PER_PROCESS_DATA *psPerProc;
PVR_ASSERT(psHashTab != IMG_NULL);
-
+ /* Look for existing per-process data area */
psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
return psPerProc;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPerProcessDataConnect
+
+ @Description Allocate per-process data area, or increment refcount if one
+ already exists for this PID.
+
+ @Input ui32PID - process ID
+ ppsPerProc - Pointer to per-process data area
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags)
{
PVRSRV_PER_PROCESS_DATA *psPerProc;
return PVRSRV_ERROR_INIT_FAILURE;
}
-
+ /* Look for existing per-process data area */
psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
if (psPerProc == IMG_NULL)
{
-
+ /* Allocate per-process data area */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(*psPerProc),
(IMG_PVOID *)&psPerProc,
PVR_UNREFERENCED_PARAMETER(ui32Flags);
#endif
-
+ /* Call environment specific per process init function */
eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
if (eError != PVRSRV_OK)
{
goto failure;
}
-
+ /* Allocate a handle for the per-process data area */
eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
&psPerProc->hPerProcData,
psPerProc,
goto failure;
}
-
+ /* Allocate handle base for this process */
eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
if (eError != PVRSRV_OK)
{
goto failure;
}
-
+ /* Set per-process handle options */
eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
if (eError != PVRSRV_OK)
{
goto failure;
}
-
+ /* Create a resource manager context for the process */
eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
if (eError != PVRSRV_OK)
{
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPerProcessDataDisconnect
+
+ @Description Decrement refcount for per-process data area,
+ and free the resources if necessary.
+
+ @Input ui32PID - process ID
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID)
{
PVRSRV_ERROR eError;
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataDisconnect: "
"Last close from process 0x%x received", ui32PID));
+ /* Close the Resource Manager connection */
+ PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE);
+
#if defined (TTRACE)
PVRSRVTimeTraceBufferDestroy(ui32PID);
#endif
-
- PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE);
-
-
+ /* Free the per-process data */
eError = FreePerProcessData(psPerProc);
if (eError != PVRSRV_OK)
{
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPerProcessDataInit
+
+ @Description Initialise per-process data management
+
+ @Return Error code, or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID)
{
PVR_ASSERT(psHashTab == IMG_NULL);
-
+ /* Create hash table */
psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
if (psHashTab == IMG_NULL)
{
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPerProcessDataDeInit
+
+ @Description De-initialise per-process data management
+
+ @Return Error code, or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
{
-
+ /* Destroy per-process data area hash table */
if (psHashTab != IMG_NULL)
{
-
+ /* Free the hash table */
HASH_Delete(psHashTab);
psHashTab = IMG_NULL;
}
return PVRSRV_OK;
}
+/******************************************************************************
+ End of file (perproc.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Power management functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for power management functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
#include "pdump_km.h"
static IMG_BOOL gbInitServerRan = IMG_FALSE;
static IMG_BOOL gbInitSuccessful = IMG_FALSE;
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetInitServerState
+
+ @Description Sets given services init state.
+
+ @Input eInitServerState : a services init state
+ @Input bState : a state to set
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState)
{
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetInitServerState
+
+ @Description Tests whether a given services init state was run.
+
+ @Input eInitServerState : a services init state
+
+ @Return IMG_BOOL
+
+******************************************************************************/
IMG_EXPORT
IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
{
return bReturnVal;
}
+/*!
+******************************************************************************
+
+ @Function _IsSystemStatePowered
+
+ @Description Tests whether a given system state represents powered-up.
+
+ @Input eSystemPowerState : a system power state
+
+ @Return IMG_BOOL
+
+******************************************************************************/
static IMG_BOOL _IsSystemStatePowered(PVRSRV_SYS_POWER_STATE eSystemPowerState)
{
return (IMG_BOOL)(eSystemPowerState < PVRSRV_SYS_POWER_STATE_D2);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPowerLock
+
+ @Description Obtain the mutex for power transitions
+
+ @Input ui32CallerID : KERNEL_ID or ISR_ID
+ @Input bSystemPowerEvent : Only pass IMG_TRUE if the lock is for a
+ system power state change
+
+ @Return PVRSRV_ERROR IMG_CALLCONV
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
IMG_BOOL bSystemPowerEvent)
}
else if (bTryLock)
{
-
-
+ /*
+ ISR failed to acquire lock so it must be held by a kernel thread.
+ */
eError = PVRSRV_ERROR_RETRY;
break;
}
OSPowerLockUnwrap();
}
-
+ /* PRQA S 3415 3 */ /* side effects desired */
if ((eError == PVRSRV_OK) &&
!bSystemPowerEvent &&
!_IsSystemStatePowered(psSysData->eCurrentPowerState))
{
-
+ /* Reject device power state change due to system power state. */
PVRSRVPowerUnlock(ui32CallerID);
eError = PVRSRV_ERROR_RETRY;
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPowerUnlock
+
+ @Description Release the mutex for power transitions
+
+ @Input ui32CallerID : KERNEL_ID or ISR_ID
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID)
{
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePrePowerStateKM_AnyVaCb
+
+ @Description
+
+ Perform device-specific processing required before a power transition
+
+ @Input psPowerDevice : the device
+ @Input va : variable argument list with:
+ bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ ui32DeviceIndex : device index
+ eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
{
PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
PVRSRV_ERROR eError;
-
+ /*Variable Argument variables*/
IMG_BOOL bAllDevices;
IMG_UINT32 ui32DeviceIndex;
PVRSRV_DEV_POWER_STATE eNewPowerState;
-
+ /* WARNING: if types were not aligned to 4 bytes, this could be dangerous. */
bAllDevices = va_arg(va, IMG_BOOL);
ui32DeviceIndex = va_arg(va, IMG_UINT32);
eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
{
if (psPowerDevice->pfnPrePower != IMG_NULL)
{
-
+ /* Call the device's power callback. */
eError = psPowerDevice->pfnPrePower(psPowerDevice->hDevCookie,
eNewDevicePowerState,
psPowerDevice->eCurrentPowerState);
}
}
-
+ /* Do any required system-layer processing. */
eError = SysDevicePrePowerState(psPowerDevice->ui32DeviceIndex,
eNewDevicePowerState,
psPowerDevice->eCurrentPowerState);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePrePowerStateKM
+
+ @Description
+
+ Perform device-specific processing required before a power transition
+
+ @Input bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ @Input ui32DeviceIndex : device index
+ @Input eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static
PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
IMG_UINT32 ui32DeviceIndex,
SysAcquireData(&psSysData);
-
+ /* Loop through the power devices. */
eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
&PVRSRVDevicePrePowerStateKM_AnyVaCb,
bAllDevices,
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePostPowerStateKM_AnyVaCb
+
+ @Description
+
+ Perform device-specific processing required after a power transition
+
+ @Input psPowerDevice : the device
+ @Input va : variable argument list with:
+ bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ ui32DeviceIndex : device index
+ eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
{
PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
PVRSRV_ERROR eError;
-
+ /*Variable Argument variables*/
IMG_BOOL bAllDevices;
IMG_UINT32 ui32DeviceIndex;
PVRSRV_DEV_POWER_STATE eNewPowerState;
-
+ /* WARNING: if types were not aligned to 4 bytes, this could be dangerous. */
bAllDevices = va_arg(va, IMG_BOOL);
ui32DeviceIndex = va_arg(va, IMG_UINT32);
eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
{
-
+ /* Do any required system-layer processing. */
eError = SysDevicePostPowerState(psPowerDevice->ui32DeviceIndex,
eNewDevicePowerState,
psPowerDevice->eCurrentPowerState);
if (psPowerDevice->pfnPostPower != IMG_NULL)
{
-
+ /* Call the device's power callback. */
eError = psPowerDevice->pfnPostPower(psPowerDevice->hDevCookie,
eNewDevicePowerState,
psPowerDevice->eCurrentPowerState);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePostPowerStateKM
+
+ @Description
+
+ Perform device-specific processing required after a power transition
+
+ @Input bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ @Input ui32DeviceIndex : device index
+ @Input eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static
PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
IMG_UINT32 ui32DeviceIndex,
SysAcquireData(&psSysData);
-
+ /* Loop through the power devices. */
eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
&PVRSRVDevicePostPowerStateKM_AnyVaCb,
bAllDevices,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetDevicePowerStateKM
+
+ @Description Set the Device into a new state
+
+ @Input ui32DeviceIndex : device index
+ @Input eNewPowerState : New power state
+ @Input ui32CallerID : KERNEL_ID or ISR_ID
+ @Input bRetainMutex : If true, the power mutex is retained on exit
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
- PVRSRV_DEV_POWER_STATE eNewPowerState,
- IMG_UINT32 ui32CallerID,
- IMG_BOOL bRetainMutex)
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
{
PVRSRV_ERROR eError;
SYS_DATA *psSysData;
SysAcquireData(&psSysData);
- eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
- if(eError != PVRSRV_OK)
- {
- return eError;
- }
-
#if defined(PDUMP)
if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
{
-
-
-
-
+ /*
+ Pdump a power-up regardless of the default state.
+ Then disable pdump and transition to the default power state.
+ This ensures that a power-up is always present in the pdump when necessary.
+ */
eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
if(eError != PVRSRV_OK)
{
PDUMPSUSPEND();
}
- #endif
+ #endif /* PDUMP */
eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
if(eError != PVRSRV_OK)
"PVRSRVSetDevicePowerStateKM : Transition to %d FAILED 0x%x", eNewPowerState, eError));
}
- if (!bRetainMutex || (eError != PVRSRV_OK))
- {
- PVRSRVPowerUnlock(ui32CallerID);
- }
-
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSystemPrePowerStateKM
+
+ @Description Perform processing required before a system power transition
+
+ @Input eNewSysPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
{
SysAcquireData(&psSysData);
-
+ /* This mutex is unlocked in PVRSRVSystemPostPowerStateKM() */
eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE);
if(eError != PVRSRV_OK)
{
{
if (_IsSystemStatePowered(eNewSysPowerState))
{
-
+ /* Return device back to its default state. */
eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
}
else
eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
}
-
+ /* Perform device-specific transitions. */
eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
if (eError != PVRSRV_OK)
{
if (eNewSysPowerState != psSysData->eCurrentPowerState)
{
-
+ /* Perform system-specific power transitions. */
eError = SysSystemPrePowerState(eNewSysPowerState);
if (eError != PVRSRV_OK)
{
"PVRSRVSystemPrePowerStateKM: Transition from %d to %d FAILED 0x%x",
psSysData->eCurrentPowerState, eNewSysPowerState, eError));
-
+ /* save the power state for the re-attempt */
psSysData->eFailedPowerState = eNewSysPowerState;
PVRSRVPowerUnlock(KERNEL_ID);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSystemPostPowerStateKM
+
+ @Description Perform processing required after a system power transition
+
+ @Input eNewSysPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
{
if (eNewSysPowerState != psSysData->eCurrentPowerState)
{
-
+ /* Perform system-specific power transitions. */
eError = SysSystemPostPowerState(eNewSysPowerState);
if (eError != PVRSRV_OK)
{
{
if (_IsSystemStatePowered(eNewSysPowerState))
{
-
+ /* Return device back to its default state. */
eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
}
else
eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
}
-
+ /* Perform device-specific power transitions. */
eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
if (eError != PVRSRV_OK)
{
PVRSRVPowerUnlock(KERNEL_ID);
-
+ /* PRQA S 3415 2 */ /* side effects desired */
if (_IsSystemStatePowered(eNewSysPowerState) &&
PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
{
-
-
-
+ /*
+ Reprocess the devices' queues in case commands were blocked during
+ the power transition.
+ */
PVRSRVScheduleDeviceCallbacks();
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetPowerStateKM
+
+ @Description Set the system into a new state
+
+ @Input eNewPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
{
goto ErrorExit;
}
-
+ /* save new power state */
psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
return PVRSRV_OK;
"PVRSRVSetPowerStateKM: Transition from %d to %d FAILED 0x%x",
psSysData->eCurrentPowerState, eNewSysPowerState, eError));
-
+ /* save the power state for the re-attempt */
psSysData->eFailedPowerState = eNewSysPowerState;
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterPowerDevice
+
+ @Description
+
+ Registers a device with the power manager. Passes Pre/Post Power handlers
+ and private device handle to be passed to power handlers
+
+ @Input ui32DeviceIndex : device index
+ @Input pfnPrePower : Pre power transition handler
+ @Input pfnPostPower : Post power transition handler
+ @Input pfnPreClockSpeedChange : Pre clock speed transition handler (if required)
+ @Input pfnPostClockSpeedChange : Post clock speed transition handler (if required)
+ @Input hDevCookie : Dev cookie for dev power handlers
+ @Input eCurrentPowerState : Current power state of the device
+ @Input eDefaultPowerState : Default power state of the device
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
PFN_PRE_POWER pfnPrePower,
PFN_POST_POWER pfnPostPower,
return eError;
}
-
+ /* setup device for power manager */
psPowerDevice->pfnPrePower = pfnPrePower;
psPowerDevice->pfnPostPower = pfnPostPower;
psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange;
psPowerDevice->eCurrentPowerState = eCurrentPowerState;
psPowerDevice->eDefaultPowerState = eDefaultPowerState;
-
+ /* insert into power device list */
List_PVRSRV_POWER_DEV_Insert(&(psSysData->psPowerDeviceList), psPowerDevice);
return (PVRSRV_OK);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRemovePowerDevice
+
+ @Description
+
+ Removes device from power management register. Device is located by Device Index
+
+ @Input ui32DeviceIndex : device index
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
{
SYS_DATA *psSysData;
SysAcquireData(&psSysData);
-
+ /* find device in list and remove it */
psPowerDev = (PVRSRV_POWER_DEV*)
List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
&MatchPowerDeviceIndex_AnyVaCb,
{
List_PVRSRV_POWER_DEV_Remove(psPowerDev);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_POWER_DEV), psPowerDev, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
return (PVRSRV_OK);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVIsDevicePowered
+
+ @Description
+
+ Whether the device is powered, for the purposes of lockup detection.
+
+ @Input ui32DeviceIndex : device index
+
+ @Return IMG_BOOL
+
+******************************************************************************/
IMG_EXPORT
IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
{
SysAcquireData(&psSysData);
-
+ /* PRQA S 3415 2 */ /* order not important */
if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID) ||
OSIsResourceLocked(&psSysData->sPowerStateChangeResource, ISR_ID))
{
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePreClockSpeedChange
+
+ @Description
+
+ Notification from system layer that a device clock speed change is about to happen.
+
+ @Input ui32DeviceIndex : device index
+ @Input bIdleDevice : whether the device should be idled
+ @Input pvInfo
+
+ @Return IMG_VOID
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
IMG_BOOL bIdleDevice,
IMG_VOID *pvInfo)
if (bIdleDevice)
{
-
+ /* This mutex is released in PVRSRVDevicePostClockSpeedChange. */
eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
if (eError != PVRSRV_OK)
{
}
}
-
+ /*search the device and then do the pre clock speed change*/
psPowerDevice = (PVRSRV_POWER_DEV*)
List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
&MatchPowerDeviceIndex_AnyVaCb,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePostClockSpeedChange
+
+ @Description
+
+ Notification from system layer that a device clock speed change has just happened.
+
+ @Input ui32DeviceIndex : device index
+ @Input bIdleDevice : whether the device had been idled
+ @Input pvInfo
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
IMG_BOOL bIdleDevice,
IMG_VOID *pvInfo)
SysAcquireData(&psSysData);
-
+ /*search the device and then do the post clock speed change*/
psPowerDevice = (PVRSRV_POWER_DEV*)
List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
&MatchPowerDeviceIndex_AnyVaCb,
if (bIdleDevice)
{
-
+ /* This mutex was acquired in PVRSRVDevicePreClockSpeedChange. */
PVRSRVPowerUnlock(KERNEL_ID);
}
}
+/******************************************************************************
+ End of file (power.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title core services functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for core services functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
#include "buffer_manager.h"
#if defined(TTRACE)
#include "ttrace.h"
#endif
+#include "perfkm.h"
#include "pvrversion.h"
IMG_UINT32 g_ui32InitFlags;
+/* mark which parts of Services were initialised */
#define INIT_DATA_ENABLE_PDUMPINIT 0x1U
#define INIT_DATA_ENABLE_TTARCE 0x2U
+/*!
+******************************************************************************
+
+ @Function AllocateDeviceID
+
+ @Description
+
+ allocates a device id from the pool of valid ids
+
+ @input psSysData : system data
+
+ @input pui32DevID : device id to return
+
+ @Return device id
+
+******************************************************************************/
PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
{
SYS_DEVICE_ID* psDeviceWalker;
psDeviceWalker = &psSysData->sDeviceID[0];
psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
-
+ /* find a free ID */
while (psDeviceWalker < psDeviceEnd)
{
if (!psDeviceWalker->bInUse)
PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
-
+ /* Should never get here: sDeviceID[] may have been setup too small */
PVR_ASSERT(psDeviceWalker < psDeviceEnd);
return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE;
}
+/*!
+******************************************************************************
+
+ @Function FreeDeviceID
+
+ @Description
+
+ frees a device id from the pool of valid ids
+
+ @input psSysData : system data
+
+ @input ui32DevID : device id to free
+
+ @Return device id
+
+******************************************************************************/
PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
{
SYS_DEVICE_ID* psDeviceWalker;
psDeviceWalker = &psSysData->sDeviceID[0];
psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
-
+ /* find the ID to free */
while (psDeviceWalker < psDeviceEnd)
{
-
+ /* if matching id and in use, free */
if (
(psDeviceWalker->uiID == ui32DevID) &&
(psDeviceWalker->bInUse)
PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
-
+ /* should never get here */
PVR_ASSERT(psDeviceWalker < psDeviceEnd);
return PVRSRV_ERROR_INVALID_DEVICEID;
}
+/*!
+******************************************************************************
+
+ @Function ReadHWReg
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Offset : byte offset from register base
+
+ @Return register value
+
+******************************************************************************/
#ifndef ReadHWReg
IMG_EXPORT
IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
#endif
+/*!
+******************************************************************************
+
+ @Function WriteHWReg
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Offset : byte offset from register base
+
+ @input ui32Value : value to write to register
+
+ @Return register value : original reg. value
+
+******************************************************************************/
#ifndef WriteHWReg
IMG_EXPORT
IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
#endif
+/*!
+******************************************************************************
+
+ @Function WriteHWRegs
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Count : register count
+
+ @input psHWRegs : address/value register list
+
+ @Return none
+
+******************************************************************************/
#ifndef WriteHWRegs
IMG_EXPORT
IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs)
}
#endif
+/*!
+******************************************************************************
+ @Function PVRSRVEnumerateDCKM_ForEachVaCb
+
+ @Description
+
+ Enumerates the device node (if is of the same class as given).
+
+ @Input psDeviceNode - The device node to be enumerated
+ va - variable arguments list, with:
+ pui32DevCount - The device count pointer (to be increased)
+ ppui32DevID - The pointer to the device IDs pointer (to be updated and increased)
+******************************************************************************/
static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
{
IMG_UINT *pui32DevCount;
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnumerateDevicesKM
+
+ @Description
+ This function will enumerate all the devices supported by the
+ PowerVR services within the target system.
+ The function returns a list of the device ID strcutres stored either in
+ the services or constructed in the user mode glue component in certain
+ environments. The number of devices in the list is also returned.
+
+ In a binary layered component which does not support dynamic runtime selection,
+ the glue code should compile to return the supported devices statically,
+ e.g. multiple instances of the same device if multiple devices are supported,
+ or the target combination of MBX and display device.
+
+ In the case of an environment (for instance) where one MBX1 may connect to two
+ display devices this code would enumerate all three devices and even
+ non-dynamic MBX1 selection code should retain the facility to parse the list
+ to find the index of the MBX device
+
+ @output pui32NumDevices : On success, contains the number of devices present
+ in the system
+
+ @output psDevIdList : Pointer to called supplied buffer to receive the
+ list of PVRSRV_DEVICE_IDENTIFIER
+
+ @return PVRSRV_ERROR : PVRSRV_NO_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
{
SYS_DATA *psSysData;
+/* PVRSRV_DEVICE_NODE *psDeviceNode; */
IMG_UINT32 i;
if (!pui32NumDevices || !psDevIdList)
SysAcquireData(&psSysData);
-
-
+ /*
+ setup input buffer to be `empty'
+ */
for (i=0; i<PVRSRV_MAX_DEVICES; i++)
{
psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
}
-
+ /* and zero device count */
*pui32NumDevices = 0;
-
-
-
-
+ /*
+ Search through the device list for services managed devices
+ return id info for each device and the number of devices
+ available
+ */
List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
&PVRSRVEnumerateDevicesKM_ForEachVaCb,
pui32NumDevices,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVInit
+
+ @Description Initialise services
+
+ @Input psSysData : sysdata structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
{
PVRSRV_ERROR eError;
-
+ /* Initialise Resource Manager */
eError = ResManInit();
if (eError != PVRSRV_OK)
{
goto Error;
}
-
+ /* Initialise handles */
eError = PVRSRVHandleInit();
if(eError != PVRSRV_OK)
{
goto Error;
}
-
+ /* Initialise Power Manager Lock */
eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
if (eError != PVRSRV_OK)
{
goto Error;
}
-
+ /* Initialise system power state */
psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
-
+ /* Create an event object */
if(OSAllocMem( PVRSRV_PAGEABLE_SELECT,
sizeof(PVRSRV_EVENTOBJECT) ,
(IMG_VOID **)&psSysData->psGlobalEventObject, 0,
goto Error;
}
-
+ /* Store OS high res timer fallbacks, the system is free to overide these */
psSysData->pfnHighResTimerCreate = OSFuncHighResTimerCreate;
psSysData->pfnHighResTimerGetus = OSFuncHighResTimerGetus;
psSysData->pfnHighResTimerDestroy = OSFuncHighResTimerDestroy;
g_ui32InitFlags |= INIT_DATA_ENABLE_TTARCE;
#endif
-
+ /* Initialise pdump */
PDUMPINIT();
g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
+ PERFINIT();
return eError;
Error:
+/*!
+******************************************************************************
+
+ @Function PVRSRVDeInit
+
+ @Description De-Initialise services
+
+ @Input psSysData : sysdata structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
{
PVRSRV_ERROR eError;
PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
return;
}
+
+ PERFDEINIT();
+
#if defined(TTRACE)
-
+ /* deinitialise ttrace */
if ((g_ui32InitFlags & INIT_DATA_ENABLE_TTARCE) > 0)
{
PVRSRVTimeTraceDeinit();
}
#endif
-
+ /* deinitialise pdump */
if( (g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0)
{
PDUMPDEINIT();
}
-
+ /* destroy event object */
if(psSysData->psGlobalEventObject)
{
OSEventObjectDestroyKM(psSysData->psGlobalEventObject);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterDevice
+
+ @Description
+
+ registers a device with the system
+
+ @Input psSysData : sysdata structure
+
+ @Input pfnRegisterDevice : device registration function
+
+ @Input ui32SOCInterruptBit : SoC interrupt bit for this device
+
+ @Output pui32DeviceIndex : unique device key (for case of multiple identical devices)
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
IMG_UINT32 ui32SOCInterruptBit,
PVRSRV_ERROR eError;
PVRSRV_DEVICE_NODE *psDeviceNode;
-
+ /* Allocate device node */
if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_DEVICE_NODE),
(IMG_VOID **)&psDeviceNode, IMG_NULL,
{
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
}
-
-
-
-
-
+ /*
+ make the refcount 1 and test on this to initialise device
+ at acquiredevinfo. On release if refcount is 1, deinitialise
+ and when refcount is 0 (sysdata de-alloc) deallocate the device
+ structures
+ */
psDeviceNode->ui32RefCount = 1;
psDeviceNode->psSysData = psSysData;
psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
-
+ /* all devices need a unique identifier */
AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
-
+ /* and finally insert the device into the dev-list */
List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
-
+ /* and copy back index */
*pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVInitialiseDevice
+
+ @Description
+
+ initialises device by index
+
+ @Input ui32DevIndex : Index to the required device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
{
PVRSRV_DEVICE_NODE *psDeviceNode;
SysAcquireData(&psSysData);
-
+ /* Find device in the list */
psDeviceNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
IMG_TRUE);
if(!psDeviceNode)
{
-
+ /* Devinfo not in the list */
PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present"));
return PVRSRV_ERROR_INIT_FAILURE;
}
- PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+/*
+FoundDevice:
+*/
-
+ PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+ /*
+ Create the device's resource manager context.
+ */
eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext);
if (eError != PVRSRV_OK)
{
return eError;
}
-
+ /* Initialise the device */
if(psDeviceNode->pfnInitDevice != IMG_NULL)
{
eError = psDeviceNode->pfnInitDevice(psDeviceNode);
static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVRSRV_ERROR eError;
+
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVPowerLock call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+ return eError;
+ }
+
eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
- PVRSRV_DEV_POWER_STATE_DEFAULT,
- KERNEL_ID, IMG_FALSE);
+ PVRSRV_DEV_POWER_STATE_DEFAULT);
+ PVRSRVPowerUnlock(KERNEL_ID);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
return eError;
}
+/*wraps the PVRSRVDevInitCompatCheck call and prints a debugging message if failed*/
static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVRSRV_ERROR eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVFinaliseSystem
+
+ @Description
+
+ Final part of system initialisation.
+
+ @Input ui32DevIndex : Index to the required device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
{
+/* PVRSRV_DEVICE_NODE *psDeviceNode;*/
SYS_DATA *psSysData;
PVRSRV_ERROR eError;
return eError;
}
-
+ /* Place all devices into their default power state. */
eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
&PVRSRVFinaliseSystem_SetPowerState_AnyCb);
if (eError != PVRSRV_OK)
return eError;
}
-
+ /* Verify microkernel compatibility for devices */
eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
&PVRSRVFinaliseSystem_CompatCheck_AnyCb);
if (eError != PVRSRV_OK)
}
}
-
-
-
-
-#if !defined(__QNXNTO__)
+ /* Some platforms call this too early in the boot phase. */
PDUMPENDINITPHASE();
-#endif
return PVRSRV_OK;
}
PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
{
-
+ /* Only check devices which specify a compatibility check callback */
if (psDeviceNode->pfnInitDeviceCompatCheck)
return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
else
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAcquireDeviceDataKM
+
+ @Description
+
+ Matchs a device given a device type and a device index.
+
+ @input psDeviceNode :The device node to be matched.
+
+ @Input va : Variable argument list with:
+ eDeviceType : Required device type. If type is unknown use ui32DevIndex
+ to locate device data
+
+ ui32DevIndex : Index to the required device obtained from the
+ PVRSRVEnumerateDevice function
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
{
PVRSRV_DEVICE_TYPE eDeviceType;
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAcquireDeviceDataKM
+
+ @Description
+
+ Returns device information
+
+ @Input ui32DevIndex : Index to the required device obtained from the
+ PVRSRVEnumerateDevice function
+
+ @Input eDeviceType : Required device type. If type is unknown use ui32DevIndex
+ to locate device data
+
+ @Output *phDevCookie : Dev Cookie
+
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
PVRSRV_DEVICE_TYPE eDeviceType,
SysAcquireData(&psSysData);
-
+ /* Find device in the list */
psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
eDeviceType,
if (!psDeviceNode)
{
-
+ /* device can't be found in the list so it isn't in the system */
PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
return PVRSRV_ERROR_INIT_FAILURE;
}
+/*FoundDevice:*/
+
PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
-
+ /* return the dev cookie? */
if (phDevCookie)
{
*phDevCookie = (IMG_HANDLE)psDeviceNode;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDeinitialiseDevice
+
+ @Description
+
+ This De-inits device
+
+ @Input ui32DevIndex : Index to the required device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
{
PVRSRV_DEVICE_NODE *psDeviceNode;
return PVRSRV_ERROR_DEVICEID_NOT_FOUND;
}
-
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVPowerLock call"));
+ return eError;
+ }
+ /*
+ Power down the device if necessary.
+ */
eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
- PVRSRV_DEV_POWER_STATE_OFF,
- KERNEL_ID,
- IMG_FALSE);
+ PVRSRV_DEV_POWER_STATE_OFF);
+ PVRSRVPowerUnlock(KERNEL_ID);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
return eError;
}
-
-
+ /*
+ Free the dissociated device memory.
+ */
eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
RESMAN_CRITERIA_RESTYPE,
RESMAN_TYPE_DEVICEMEM_ALLOCATION,
return eError;
}
-
-
+ /*
+ De-init the device.
+ */
if(psDeviceNode->pfnDeInitDevice != IMG_NULL)
{
eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
}
}
-
-
+ /*
+ Close the device's resource manager context.
+ */
PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
psDeviceNode->hResManContext = IMG_NULL;
-
+ /* remove node from list */
List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
-
+ /* deallocate id and memory */
(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return (PVRSRV_OK);
}
PVR_UNREFERENCED_PARAMETER(ui32PollPeriodus);
#endif
-
-
+ /* For the Emulator we want the system to stop when a lock-up is detected so the state can be analysed.
+ * Also the Emulator is much slower than real silicon so timeouts are not valid.
+ */
do
{
if((*pui32LinMemAddr & ui32Mask) == ui32Value)
OSReleaseThreadQuanta();
#endif
- } while (ui32Timeoutus);
+ } while (ui32Timeoutus); /* Endless loop only for the Emulator */
}
#else
{
- IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU;
+ IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU; /* Initialiser only required to prevent incorrect warning */
if (bAllowPreemption)
{
PVR_ASSERT(ui32PollPeriodus >= 1000);
}
-
+ /* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */
LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
{
ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).",
ui32Value, ui32ActualValue, ui32Mask));
}
-#endif
+#endif /* #if defined (EMULATOR) */
return PVRSRV_ERROR_TIMEOUT;
}
+/*Level 3 of the loop nesting*/
static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
{
IMG_CHAR **ppszStr;
pui32StrLen = va_arg(va, IMG_UINT32*);
ui32Mode = va_arg(va, IMG_UINT32);
-
+ /* Would be better to pass fn pointer in the variable args list
+ * but MS C compiler complains with error C2066: In ANSI C,
+ * it is not legal to cast between a function pointer and a data pointer.
+ */
switch(ui32Mode)
{
case PVRSRV_MISC_INFO_MEMSTATS_PRESENT:
}
}
+/*Level 2 of the loop nesting*/
static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va)
{
}
+/*level 1 of the loop nesting*/
static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
{
IMG_UINT32 *pui32StrLen;
*pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType);
UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
-
+ /* kernel context: */
if(psDeviceNode->sDevMemoryInfo.pBMKernelContext)
{
CHECK_SPACE(*pui32StrLen);
ui32Mode);
}
-
+ /* double loop app contexts:heaps */
return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext,
&PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
pui32StrLen,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetMiscInfoKM
+
+ @Description
+ Retrieves misc. info.
+
+ @Output PVRSRV_MISC_INFO
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO_KM *psMiscInfo)
psMiscInfo->ui32StatePresent = 0;
-
+ /* do a basic check for uninitialised request flag */
if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
|PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
|PVRSRV_MISC_INFO_MEMSTATS_PRESENT
|PVRSRV_MISC_INFO_DDKVERSION_PRESENT
|PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT
|PVRSRV_MISC_INFO_RESET_PRESENT
- |PVRSRV_MISC_INFO_FREEMEM_PRESENT))
+ |PVRSRV_MISC_INFO_FREEMEM_PRESENT
+ |PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT
+ |PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT
+ |PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT))
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
return PVRSRV_ERROR_INVALID_PARAMS;
SysAcquireData(&psSysData);
-
+ /* return SOC Timer registers */
if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
(psSysData->pvSOCTimerRegisterKM != IMG_NULL))
{
psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
}
-
+ /* return SOC Clock Gating registers */
if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
(psSysData->pvSOCClockGateRegsBase != IMG_NULL))
{
psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
}
-
+ /* memory stats */
if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
(psMiscInfo->pszMemoryStr != IMG_NULL))
{
RA_ARENA **ppArena;
+/* BM_HEAP *psBMHeap;
+ BM_CONTEXT *psBMContext;
+ PVRSRV_DEVICE_NODE *psDeviceNode;*/
IMG_CHAR *pszStr;
IMG_UINT32 ui32StrLen;
IMG_INT32 i32Count;
psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
-
+ /* Local backing stores */
ppArena = &psSysData->apsLocalDevMemArena[0];
while(*ppArena)
{
RA_GetStats(*ppArena,
&pszStr,
&ui32StrLen);
-
+ /* advance through the array */
ppArena++;
}
-
-
+ /* per device */
+/* psDeviceNode = psSysData->psDeviceNodeList;*/
+
+ /*triple loop; devices:contexts:heaps*/
List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
&PVRSRVGetMiscInfoKM_Device_AnyVaCb,
&ui32StrLen,
&pszStr,
PVRSRV_MISC_INFO_MEMSTATS_PRESENT);
-
+ /* attach a new line and string terminate */
i32Count = OSSNPrintf(pszStr, 100, "\n");
UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
}
-
+ /* Lean version of mem stats: only show free mem on each RA */
if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0)
&& psMiscInfo->pszMemoryStr)
{
psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT;
-
+ /* triple loop over devices:contexts:heaps */
List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
&PVRSRVGetMiscInfoKM_Device_AnyVaCb,
&ui32StrLen,
psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
}
-
+ /* DDK version and memstats not supported in same call to GetMiscInfo */
if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
&& ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
{
IMG_CHAR *pszStr;
IMG_UINT32 ui32StrLen;
- IMG_UINT32 ui32LenStrPerNum = 12;
+ IMG_UINT32 ui32LenStrPerNum = 12; /* string length per UI32: 10 digits + '.' + '\0' = 12 bytes */
IMG_INT32 i32Count;
IMG_INT i;
psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
-
+ /* construct DDK string */
psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
- psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH;
- psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD;
+ psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BUILD_HI;
+ psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD_LO;
pszStr = psMiscInfo->pszMemoryStr;
ui32StrLen = psMiscInfo->ui32MemoryStrLen;
if(psMiscInfo->sCacheOpCtl.bDeferOp)
{
-
+ /* For now, assume deferred ops are "full" cache ops,
+ * and we don't need (or expect) a meminfo.
+ */
psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType;
}
else
#if defined (SUPPORT_SID_INTERFACE)
PVR_DBG_BREAK
#else
-
psPerProc = PVRSRVFindPerProcessData();
if(PVRSRVLookupHandle(psPerProc->psHandleBase,
if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
{
if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+ 0,
psMiscInfo->sCacheOpCtl.pvBaseVAddr,
psMiscInfo->sCacheOpCtl.ui32Length))
{
else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
{
if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+ 0,
psMiscInfo->sCacheOpCtl.pvBaseVAddr,
psMiscInfo->sCacheOpCtl.ui32Length))
{
}
}
+ if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL)
+ {
+#if !defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+#endif
+
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#else
+ psPerProc = PVRSRVFindPerProcessData();
+
+ if(PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psMiscInfo->sGetRefCountCtl.u.psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
+ "Can't find kernel meminfo"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psMiscInfo->sGetRefCountCtl.ui32RefCount = psKernelMemInfo->ui32RefCount;
+#endif
+ }
+
+ if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT) != 0UL)
+ {
+ psMiscInfo->ui32PageSize = HOST_PAGESIZE();
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT;
+ }
+
#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
{
PVR_LOG(("User requested OS reset"));
OSPanic();
}
-#endif
+#endif /* #if defined(PVRSRV_RESET_ON_HWTIMEOUT) */
+
+ if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT) != 0UL)
+ {
+ PVRSRVSetDCState(DC_STATE_FORCE_SWAP_TO_SYSTEM);
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT;
+ }
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDeviceLISR
+
+ @Description
+ OS-independent Device Low-level Interrupt Service Routine
+
+ @Input psDeviceNode
+
+ @Return IMG_BOOL : Whether any interrupts were serviced
+
+******************************************************************************/
IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
{
SYS_DATA *psSysData;
}
psSysData = psDeviceNode->psSysData;
-
+ /* query the SOC/system to see whether this device was the source of the interrupt */
ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
{
{
if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData))
{
-
+ /* Record if serviced any interrupts. */
*pbStatus = IMG_TRUE;
}
-
+ /* Combine the SOC clear bits. */
*pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit;
}
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSystemLISR
+
+ @Description
+ OS-independent System Low-level Interrupt Service Routine
+
+ @Input pvSysData
+
+ @Return IMG_BOOL : Whether any interrupts were serviced
+
+******************************************************************************/
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; */
}
else
{
-
+ /* query SOC for source of interrupts */
ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
-
+ /* only proceed if PVR interrupts */
if(ui32InterruptSource)
{
-
+ /* traverse the devices' ISR handlers */
List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
&PVRSRVSystemLISR_ForEachVaCb,
&bStatus,
SysClearInterrupts(psSysData, ui32ClearInterrupts);
}
+/*out:*/
}
return bStatus;
}
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVMISR
+
+ @Input pvSysData
+
+ @Description
+ OS-independent Medium-level Interrupt Service Routine
+
+******************************************************************************/
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;
}
-
+ /* Traverse the devices' MISR handlers. */
List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
&PVRSRVMISR_ForEachCb);
-
+ /* Process the queues. */
if (PVRSRVProcessQueues(IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED)
{
PVRSRVProcessQueues(IMG_FALSE);
}
-
+ /* signal global event object */
if (psSysData->psGlobalEventObject)
{
IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVProcessConnect
+
+ @Description Inform services that a process has connected.
+
+ @Input ui32PID - process ID
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags)
{
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVProcessDisconnect
+
+ @Description Inform services that a process has disconnected.
+
+ @Input ui32PID - process ID
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_EXPORT
IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID)
{
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSaveRestoreLiveSegments
+
+ @Input pArena - the arena the segment was originally allocated from.
+ pbyBuffer - the system memory buffer set to null to get the size needed.
+ puiBufSize - size of system memory buffer.
+ bSave - IMG_TRUE if a save is required
+
+ @Description
+ Function to save or restore Resources Live segments
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer,
IMG_SIZE_T *puiBufSize, IMG_BOOL bSave)
{
sSegDetails.sCpuPhyAddr.uiAddr = 0;
sSegDetails.hSegment = 0;
-
+ /* walk the arena segments and write live one to the buffer */
while (RA_GetNextLiveSegment(hArena, &sSegDetails))
{
if (pbyBuffer == IMG_NULL)
{
-
+ /* calc buffer required */
uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
}
else
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x", sSegDetails.sCpuPhyAddr.uiAddr, sSegDetails.uiSize));
-
+ /* Map the device's local memory area onto the host. */
pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
sSegDetails.uiSize,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
if (bSave)
{
-
+ /* write segment size then segment data */
OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize));
pbyBuffer += sizeof(sSegDetails.uiSize);
else
{
IMG_UINT32 uiSize;
-
+ /* reag segment size and validate */
OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize));
if (uiSize != sSegDetails.uiSize)
}
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVGetErrorStringKM
+
+ @Description Returns a text string relating to the PVRSRV_ERROR enum.
+
+ @Note case statement used rather than an indexed arrary to ensure text is
+ synchronised with the correct enum
+
+ @Input eError : PVRSRV_ERROR enum
+
+ @Return const IMG_CHAR * : Text string
+
+ @Note Must be kept in sync with servicesext.h
+
+******************************************************************************/
+
IMG_EXPORT
const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
{
-
+/* PRQA S 5087 1 */ /* include file required here */
#include "pvrsrv_errors.h"
}
{
if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
{
-
+ /* Call the device's callback function. */
(*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVScheduleDeviceCallbacks
+
+ @Description Schedule all device callbacks
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID)
{
SYS_DATA *psSysData;
+/* PVRSRV_DEVICE_NODE *psDeviceNode;*/
+
SysAcquireData(&psSysData);
-
+ /*for all the device, invoke the callback function*/
List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
&PVRSRVCommandCompleteCallbacks_ForEachCb);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVScheduleDevices
+
+ @Description Schedules all Services-Managed Devices to check their pending
+ command queues. The intention is that ScheduleDevices be called by the
+ 3rd party BC driver after it has finished writing new data to its output
+ texture.
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_EXPORT
IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID)
{
PVRSRVScheduleDeviceCallbacks();
}
+/*****************************************************************************
+ End of file (pvrsrv.c)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Kernel side command queue functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
+#include "pvr_bridge_km.h"
#include "lists.h"
#include "ttrace.h"
+/*
+ * The number of commands of each type which can be in flight at once.
+ */
+#if defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+#define DC_NUM_COMMANDS_PER_TYPE 2
+#else
#define DC_NUM_COMMANDS_PER_TYPE 1
-
+#endif
+
+/*
+ * List of private command processing function pointer tables and command
+ * complete tables for a device in the system.
+ * Each table is allocated when the device registers its private command
+ * processing functions.
+ */
typedef struct _DEVICE_COMMAND_DATA_
{
PFN_CMD_PROC pfnCmdProc;
PCOMMAND_COMPLETE_DATA apsCmdCompleteData[DC_NUM_COMMANDS_PER_TYPE];
IMG_UINT32 ui32CCBOffset;
+ IMG_UINT32 ui32MaxDstSyncCount; /*!< Maximum number of dest syncs */
+ IMG_UINT32 ui32MaxSrcSyncCount; /*!< Maximum number of source syncs */
} DEVICE_COMMAND_DATA;
#include "proc.h"
+/*****************************************************************************
+ FUNCTION : ProcSeqShowQueue
+
+ PURPOSE : Print the content of queue element to /proc file
+ (See env/linux/proc.c:CreateProcReadEntrySeq)
+
+ PARAMETERS : sfile - /proc seq_file
+ el - Element to print
+*****************************************************************************/
void ProcSeqShowQueue(struct seq_file *sfile,void* el)
{
PVRSRV_QUEUE_INFO *psQueue = (PVRSRV_QUEUE_INFO*)el;
PVRSRV_SYNC_DATA *psSyncData = psCmd->psSrcSync[i].psKernelSyncInfoKM->psSyncData;
seq_printf(sfile, " Sync %u: ROP/ROC: 0x%x/0x%x WOP/WOC: 0x%x/0x%x ROC-VA: 0x%x WOC-VA: 0x%x\n",
i,
- psCmd->psSrcSync[i].ui32ReadOpsPending,
- psSyncData->ui32ReadOpsComplete,
+ psCmd->psSrcSync[i].ui32ReadOps2Pending,
+ psSyncData->ui32ReadOps2Complete,
psCmd->psSrcSync[i].ui32WriteOpsPending,
psSyncData->ui32WriteOpsComplete,
- psCmd->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCmd->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCmd->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr);
}
}
-
+ /* taken from UPDATE_QUEUE_ROFF in queue.h */
ui32ReadOffset += psCmd->uCmdSize;
ui32ReadOffset &= psQueue->ui32QueueSize - 1;
cmds++;
}
}
+/*****************************************************************************
+ FUNCTION : ProcSeqOff2ElementQueue
+
+ PURPOSE : Transale offset to element (/proc stuff)
+
+ PARAMETERS : sfile - /proc seq_file
+ off - the offset into the buffer
+
+ RETURNS : element to print
+*****************************************************************************/
void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off)
{
PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
return psQueue;
}
-#endif
+#endif /* __linux__ && __KERNEL__ */
+/*!
+ * Macro to return space in given command queue
+ */
#define GET_SPACE_IN_CMDQ(psQueue) \
((((psQueue)->ui32ReadOffset - (psQueue)->ui32WriteOffset) \
+ ((psQueue)->ui32QueueSize - 1)) & ((psQueue)->ui32QueueSize - 1))
+/*!
+ * Macro to Write Offset in given command queue
+ */
#define UPDATE_QUEUE_WOFF(psQueue, ui32Size) \
(psQueue)->ui32WriteOffset = ((psQueue)->ui32WriteOffset + (ui32Size)) \
& ((psQueue)->ui32QueueSize - 1);
+/*!
+ * Check if an ops complete value has gone past the pending value.
+ * This can happen when dummy processing multiple operations, e.g. hardware recovery.
+ */
#define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending) \
((ui32OpsComplete) >= (ui32OpsPending))
+/*!
+****************************************************************************
+ @Function : PVRSRVGetWriteOpsPending
+
+ @Description : Gets the next operation to wait for in a sync object
+
+ @Input : psSyncInfo - pointer to sync information struct
+ @Input : bIsReadOp - Is this a read or write op
+
+ @Return : Next op value
+*****************************************************************************/
+#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
+ {
+ /*
+ Note: This needs to be atomic and is provided the
+ kernel driver is single threaded (non-rentrant)
+ */
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ return ui32WriteOpsPending;
+}
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVGetReadOpsPending
+
+ @Description : Gets the number of pending read ops
+
+ @Input : psSyncInfo - pointer to sync information struct
+ @Input : bIsReadOp - Is this a read or write op
+
+ @Return : Next op value
+*****************************************************************************/
+#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->ui32ReadOps2Pending++;
+ }
+ else
+ {
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+ }
+
+ return ui32ReadOpsPending;
+}
static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData,
IMG_UINT32 i,
{
PVR_LOG(("\t%s %u: ROC DevVAddr:0x%X ROP:0x%x ROC:0x%x, WOC DevVAddr:0x%X WOP:0x%x WOC:0x%x",
bIsSrc ? "SRC" : "DEST", i,
- psSyncObject[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
- psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsPending,
- psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete,
+ psSyncObject[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Pending,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Complete,
psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending,
psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete))
}
+/*****************************************************************************
+ Kernel-side functions of User->Kernel transitions
+******************************************************************************/
+
static IMG_SIZE_T NearestPower2(IMG_SIZE_T ui32Value)
{
IMG_SIZE_T ui32Temp, ui32Result = 1;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVCreateCommandQueueKM
+
+ @Description
+ Creates a new command queue into which render/blt commands etc can be
+ inserted.
+
+ @Input ui32QueueSize :
+
+ @Output ppsQueueInfo :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
PVRSRV_QUEUE_INFO **ppsQueueInfo)
SysAcquireData(&psSysData);
-
+ /* allocate an internal queue info structure */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_QUEUE_INFO),
(IMG_VOID **)&psQueueInfo, &hMemBlock,
psQueueInfo->hMemBlock[0] = hMemBlock;
psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
-
+ /* allocate the command queue buffer - allow for overrun */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
&psQueueInfo->pvLinQueueKM, &hMemBlock,
psQueueInfo->hMemBlock[1] = hMemBlock;
psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
-
+ /* Sanity check: Should be zeroed by OSMemSet */
PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0);
PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0);
psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
-
+ /* if this is the first q, create a lock resource for the q list */
if (psSysData->psQueueList == IMG_NULL)
{
eError = OSCreateResource(&psSysData->sQProcessResource);
}
}
-
+ /* Ensure we don't corrupt queue list, by blocking access */
eError = OSLockResource(&psSysData->sQProcessResource,
KERNEL_ID);
if (eError != PVRSRV_OK)
sizeof(PVRSRV_QUEUE_INFO),
psQueueInfo,
psQueueInfo->hMemBlock[0]);
-
+ /*not nulling pointer, out of scope*/
}
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDestroyCommandQueueKM
+
+ @Description Destroys a command queue
+
+ @Input psQueueInfo :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo)
{
psQueue = psSysData->psQueueList;
-
+ /* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */
LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
{
if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
if (bTimeout)
{
-
+ /* The command queue could not be flushed within the timeout period.
+ Allow the queue to be destroyed before returning the error code. */
PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
goto ErrorExit;
}
-
+ /* Ensure we don't corrupt queue list, by blocking access */
eError = OSLockResource(&psSysData->sQProcessResource,
KERNEL_ID);
if (eError != PVRSRV_OK)
sizeof(PVRSRV_QUEUE_INFO),
psQueueInfo,
psQueueInfo->hMemBlock[0]);
-
- psQueueInfo = IMG_NULL;
+ /* PRQA S 3199 1 */ /* see note */
+ psQueueInfo = IMG_NULL; /*it's a copy on stack, but null it because the function doesn't end right here*/
}
else
{
sizeof(PVRSRV_QUEUE_INFO),
psQueueInfo,
psQueueInfo->hMemBlock[0]);
-
- psQueueInfo = IMG_NULL;
+ /* PRQA S 3199 1 */ /* see note */
+ psQueueInfo = IMG_NULL; /*it's a copy on stack, but null it because the function doesn't end right here*/
break;
}
psQueue = psQueue->psNextKM;
}
}
-
+ /* unlock the Q list lock resource */
eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
if (eError != PVRSRV_OK)
{
goto ErrorExit;
}
-
+ /* if the Q list is now empty, destroy the Q list lock resource */
if (psSysData->psQueueList == IMG_NULL)
{
eError = OSDestroyResource(&psSysData->sQProcessResource);
}
+/*!
+*****************************************************************************
+
+ @Function : PVRSRVGetQueueSpaceKM
+
+ @Description : Waits for queue access rights and checks for available space in
+ queue for task param structure
+
+ @Input : psQueue - pointer to queue information struct
+ @Input : ui32ParamSize - size of task data structure
+ @Output : ppvSpace
+
+ @Return : PVRSRV_ERROR
+*****************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
IMG_SIZE_T ui32ParamSize,
{
IMG_BOOL bTimeout = IMG_TRUE;
-
+ /* round to 4byte units */
ui32ParamSize = (ui32ParamSize+3) & 0xFFFFFFFC;
if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE)
return PVRSRV_ERROR_CMD_TOO_BIG;
}
-
+ /* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */
LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
{
if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize)
}
+/*!
+*****************************************************************************
+ @Function PVRSRVInsertCommandKM
+
+ @Description :
+ command insertion utility
+ - waits for space in the queue for a new command
+ - fills in generic command information
+ - returns a pointer to the caller who's expected to then fill
+ in the private data.
+ The caller should follow PVRSRVInsertCommand with PVRSRVSubmitCommand
+ which will update the queue's write offset so the command can be
+ executed.
+
+ @Input psQueue : pointer to queue information struct
+
+ @Output ppvCmdData : holds pointer to space in queue for private cmd data
+
+ @Return PVRSRV_ERROR
+*****************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
PVRSRV_COMMAND **ppsCommand,
PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
IMG_UINT32 ui32SrcSyncCount,
PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
- IMG_SIZE_T ui32DataByteSize )
+ IMG_SIZE_T ui32DataByteSize,
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete,
+ IMG_HANDLE hCallbackData)
{
PVRSRV_ERROR eError;
PVRSRV_COMMAND *psCommand;
IMG_SIZE_T ui32CommandSize;
IMG_UINT32 i;
+ SYS_DATA *psSysData;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
-
+ /* Check that we've got enough space in our command complete data for this command */
+ SysAcquireData(&psSysData);
+ psDeviceCommandData = psSysData->apsDeviceCommandData[ui32DevIndex];
+
+ if ((psDeviceCommandData[CommandType].ui32MaxDstSyncCount < ui32DstSyncCount) ||
+ (psDeviceCommandData[CommandType].ui32MaxSrcSyncCount < ui32SrcSyncCount))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVInsertCommandKM: Too many syncs"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Round up to nearest 32 bit size so pointer arithmetic works */
ui32DataByteSize = (ui32DataByteSize + 3UL) & ~3UL;
-
+ /* calc. command size */
ui32CommandSize = sizeof(PVRSRV_COMMAND)
+ ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT))
+ ui32DataByteSize;
-
+ /* wait for space in queue */
eError = PVRSRVGetQueueSpaceKM (psQueue, ui32CommandSize, (IMG_VOID**)&psCommand);
if(eError != PVRSRV_OK)
{
psCommand->ui32ProcessID = OSGetCurrentProcessIDKM();
-
- psCommand->uCmdSize = ui32CommandSize;
+ /* setup the command */
+ psCommand->uCmdSize = ui32CommandSize; /* this may change if cmd shrinks */
psCommand->ui32DevIndex = ui32DevIndex;
psCommand->CommandType = CommandType;
psCommand->ui32DstSyncCount = ui32DstSyncCount;
psCommand->ui32SrcSyncCount = ui32SrcSyncCount;
-
-
+ /* override QAC warning about stricter pointers */
+ /* PRQA S 3305 END_PTR_ASSIGNMENTS */
psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand) + sizeof(PVRSRV_COMMAND));
psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psSrcSync)
+ (ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
- psCommand->uDataSize = ui32DataByteSize;
+/* PRQA L:END_PTR_ASSIGNMENTS */
+
+ psCommand->uDataSize = ui32DataByteSize;/* this may change if cmd shrinks */
+
+ psCommand->pfnCommandComplete = pfnCommandComplete;
+ psCommand->hCallbackData = hCallbackData;
PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_START, QUEUE_TOKEN_INSERTKM);
PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_NONE,
QUEUE_TOKEN_COMMAND_TYPE, CommandType);
-
+ /* setup dst sync objects and their sync dependencies */
for (i=0; i<ui32DstSyncCount; i++)
{
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_DST_SYNC,
psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE);
- psCommand->psDstSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+ psCommand->psDstSync[i].ui32ReadOps2Pending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+
+ PVRSRVKernelSyncInfoIncRef(apsDstSync[i], IMG_NULL);
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
- i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCommand->psDstSync[i].ui32ReadOpsPending,
+ psCommand->psDstSync[i].ui32ReadOps2Pending,
psCommand->psDstSync[i].ui32WriteOpsPending));
}
-
+ /* setup src sync objects and their sync dependencies */
for (i=0; i<ui32SrcSyncCount; i++)
{
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_DST_SYNC,
psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
- psCommand->psSrcSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+ psCommand->psSrcSync[i].ui32ReadOps2Pending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+
+ PVRSRVKernelSyncInfoIncRef(apsSrcSync[i], IMG_NULL);
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
- i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCommand->psSrcSync[i].ui32ReadOpsPending,
+ psCommand->psSrcSync[i].ui32ReadOps2Pending,
psCommand->psSrcSync[i].ui32WriteOpsPending));
}
PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_END, QUEUE_TOKEN_INSERTKM);
-
+ /* return pointer to caller to fill out private data */
*ppsCommand = psCommand;
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+ @Function : PVRSRVSubmitCommandKM
+
+ @Description :
+ updates the queue's write offset so the command can be executed.
+
+ @Input : psQueue - queue command is in
+ @Input : psCommand
+
+ @Return : PVRSRV_ERROR
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
PVRSRV_COMMAND *psCommand)
{
-
-
-
+ /* override QAC warnings about stricter pointers */
+ /* PRQA S 3305 END_PTR_ASSIGNMENTS2 */
+ /* patch pointers in the command to be kernel pointers */
if (psCommand->ui32DstSyncCount > 0)
{
psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+ (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))
+ (psCommand->ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
-
+/* PRQA L:END_PTR_ASSIGNMENTS2 */
+
+ /* update write offset before releasing access lock */
UPDATE_QUEUE_WOFF(psQueue, psCommand->uCmdSize);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ @Function CheckIfSyncIsQueued
+ @Description Check if the specificed sync object is already queued and
+ can safely be given to the display controller.
+ This check is required as a 3rd party displayclass device can
+ have several flips "in flight" and we need to ensure that we
+ keep their pipeline full and don't deadlock waiting for them
+ to complete an operation on a surface.
+
+ @Input psSysData : system data
+ @Input psCmdData : COMMAND_COMPLETE_DATA structure
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+static
+PVRSRV_ERROR CheckIfSyncIsQueued(PVRSRV_SYNC_OBJECT *psSync, COMMAND_COMPLETE_DATA *psCmdData)
+{
+ IMG_UINT32 k;
+
+ if (psCmdData->bInUse)
+ {
+ for (k=0;k<psCmdData->ui32SrcSyncCount;k++)
+ {
+ if (psSync->psKernelSyncInfoKM == psCmdData->psSrcSync[k].psKernelSyncInfoKM)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psSync->psKernelSyncInfoKM->psSyncData;
+ IMG_UINT32 ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+
+ /*
+ We still need to ensure that we don't we don't give a command
+ to the display controller if writes are outstanding on it
+ */
+ if (ui32WriteOpsComplete == psSync->ui32WriteOpsPending)
+ {
+ return PVRSRV_OK;
+ }
+ else
+ {
+ if (SYNCOPS_STALE(ui32WriteOpsComplete, psSync->ui32WriteOpsPending))
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "CheckIfSyncIsQueued: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+ (IMG_UINTPTR_T)psSyncData, ui32WriteOpsComplete, psSync->ui32WriteOpsPending));
+ return PVRSRV_OK;
+ }
+ }
+ }
+ }
+ }
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVProcessCommand
+
+ @Description Tries to process a command
+
+ @Input psSysData : system data
+ @Input psCommand : PVRSRV_COMMAND structure
+ @Input bFlush : Check for stale dependencies (only used for HW recovery)
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static
PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
PVRSRV_COMMAND *psCommand,
DEVICE_COMMAND_DATA *psDeviceCommandData;
IMG_UINT32 ui32CCBOffset;
-
+ /* satisfy sync dependencies on the DST(s) */
psWalkerObj = psCommand->psDstSync;
psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
while (psWalkerObj < psEndObj)
PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
- ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
-
+ ui32ReadOpsComplete = psSyncData->ui32ReadOps2Complete;
+ /* fail if reads or writes are not up to date */
if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
- || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOps2Pending))
{
if (!bFlush ||
!SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
- !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
{
return PVRSRV_ERROR_FAILED_DEPENDENCIES;
}
psWalkerObj++;
}
-
+ /* satisfy sync dependencies on the SRC(s) */
psWalkerObj = psCommand->psSrcSync;
psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
while (psWalkerObj < psEndObj)
{
PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
- ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+ ui32ReadOpsComplete = psSyncData->ui32ReadOps2Complete;
ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
-
+ /* fail if writes are not up to date */
if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
- || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOps2Pending))
{
if (!bFlush &&
SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) &&
- SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
{
PVR_DPF((PVR_DBG_WARNING,
"PVRSRVProcessCommand: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
if (!bFlush ||
!SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
- !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
{
- return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ IMG_UINT32 j;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bFound = IMG_FALSE;
+
+ psDeviceCommandData = psSysData->apsDeviceCommandData[psCommand->ui32DevIndex];
+ for (j=0;j<DC_NUM_COMMANDS_PER_TYPE;j++)
+ {
+ eError = CheckIfSyncIsQueued(psWalkerObj, psDeviceCommandData[psCommand->CommandType].apsCmdCompleteData[j]);
+
+ if (eError == PVRSRV_OK)
+ {
+ bFound = IMG_TRUE;
+ }
+ }
+ if (!bFound)
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
}
}
psWalkerObj++;
}
-
+ /* validate device type */
if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT)
{
PVR_DPF((PVR_DBG_ERROR,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* fish out the appropriate storage structure for the duration of the command */
psDeviceCommandData = psSysData->apsDeviceCommandData[psCommand->ui32DevIndex];
ui32CCBOffset = psDeviceCommandData[psCommand->CommandType].ui32CCBOffset;
psCmdCompleteData = psDeviceCommandData[psCommand->CommandType].apsCmdCompleteData[ui32CCBOffset];
if (psCmdCompleteData->bInUse)
{
-
+ /* can use this to protect against concurrent execution of same command */
return PVRSRV_ERROR_FAILED_DEPENDENCIES;
}
-
+ /* mark the structure as in use */
psCmdCompleteData->bInUse = IMG_TRUE;
-
+ /* copy src updates over */
psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
for (i=0; i<psCommand->ui32DstSyncCount; i++)
{
psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
- i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psDstSync[i].ui32ReadOps2Pending,
psCmdCompleteData->psDstSync[i].ui32WriteOpsPending,
ui32CCBOffset));
}
+ psCmdCompleteData->pfnCommandComplete = psCommand->pfnCommandComplete;
+ psCmdCompleteData->hCallbackData = psCommand->hCallbackData;
-
+ /* copy dst updates over */
psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
for (i=0; i<psCommand->ui32SrcSyncCount; i++)
{
psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
- i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOps2Pending,
psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending,
ui32CCBOffset));
}
-
-
-
-
-
-
-
-
-
-
+ /*
+ call the cmd specific handler:
+ it should:
+ - check the cmd specific dependencies
+ - setup private cmd complete structure
+ - execute cmd on HW
+ - store psCmdCompleteData `cookie' and later pass as
+ argument to Generic Command Complete Callback
+
+ n.b. ui32DataSize (packet size) is useful for packet validation
+ */
if (psDeviceCommandData[psCommand->CommandType].pfnCmdProc((IMG_HANDLE)psCmdCompleteData,
(IMG_UINT32)psCommand->uDataSize,
psCommand->pvData) == IMG_FALSE)
{
-
-
-
+ /*
+ clean-up:
+ free cmd complete structure
+ */
psCmdCompleteData->bInUse = IMG_FALSE;
eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
}
-
+ /* Increment the CCB offset */
psDeviceCommandData[psCommand->CommandType].ui32CCBOffset = (ui32CCBOffset + 1) % DC_NUM_COMMANDS_PER_TYPE;
return eError;
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVProcessQueues
+
+ @Description Tries to process a command from each Q
+
+ @input ui32CallerID - used to distinguish between async ISR/DPC type calls
+ the synchronous services driver
+ @input bFlush - flush commands with stale dependencies (only used for HW recovery)
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+
IMG_EXPORT
PVRSRV_ERROR PVRSRVProcessQueues(IMG_BOOL bFlush)
{
PVRSRV_QUEUE_INFO *psQueue;
SYS_DATA *psSysData;
PVRSRV_COMMAND *psCommand;
- SysAcquireData(&psSysData);
+/* PVRSRV_DEVICE_NODE *psDeviceNode;*/
-
+ SysAcquireData(&psSysData);
+ /* Ensure we don't corrupt queue list, by blocking access. This is required for OSs where
+ multiple ISR threads may exist simultaneously (eg WinXP DPC routines)
+ */
while (OSLockResource(&psSysData->sQProcessResource, ISR_ID) != PVRSRV_OK)
{
- OSSleepms(1);
+ OSWaitus(1);
};
psQueue = psSysData->psQueueList;
if (PVRSRVProcessCommand(psSysData, psCommand, bFlush) == PVRSRV_OK)
{
-
+ /* processed cmd so update queue */
UPDATE_QUEUE_ROFF(psQueue, psCommand->uCmdSize)
continue;
}
PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
}
-
+ /* Re-process command complete handlers if necessary. */
List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
&PVRSRVProcessQueues_ForEachCb);
}
#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+/*!
+******************************************************************************
+
+ @Function PVRSRVCommandCompleteKM
+
+ @Description Updates non-private command complete sync objects
+
+ @Input hCmdCookie : command cookie
+ @Input bScheduleMISR : obsolete parameter
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_INTERNAL
IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
IMG_BOOL bScheduleMISR)
COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
SYS_DATA *psSysData;
+ PVR_UNREFERENCED_PARAMETER(bScheduleMISR);
+
SysAcquireData(&psSysData);
-
+ /* free command complete storage */
psCmdCompleteData->bInUse = IMG_FALSE;
-
+ /* FIXME: This may cause unrelated devices to be woken up. */
PVRSRVScheduleDeviceCallbacks();
- if(bScheduleMISR)
- {
- OSScheduleMISR(psSysData);
- }
+ /* the MISR is always scheduled, regardless of bScheduleMISR */
+ OSScheduleMISR(psSysData);
}
-#endif
+#endif /* (SUPPORT_CUSTOM_SWAP_OPERATIONS) */
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVCommandCompleteKM
+
+ @Description Updates non-private command complete sync objects
+ @Input hCmdCookie : command cookie
+ @Input bScheduleMISR : boolean to schedule MISR
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie,
IMG_BOOL bScheduleMISR)
PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_COMP_START,
QUEUE_TOKEN_COMMAND_COMPLETE);
-
+ /* update DST(s) syncs */
for (i=0; i<psCmdCompleteData->ui32DstSyncCount; i++)
{
psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++;
+ PVRSRVKernelSyncInfoDecRef(psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM, IMG_NULL);
+
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_UPDATE_DST,
psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM,
PVRSRV_SYNCOP_COMPLETE);
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
- i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psDstSync[i].ui32ReadOps2Pending,
psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
}
-
+ /* update SRC(s) syncs */
for (i=0; i<psCmdCompleteData->ui32SrcSyncCount; i++)
{
- psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete++;
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Complete++;
+
+ PVRSRVKernelSyncInfoDecRef(psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM, IMG_NULL);
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_UPDATE_SRC,
psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM,
PVRSRV_SYNCOP_COMPLETE);
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
- i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOps2Pending,
psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
}
PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_COMP_END,
QUEUE_TOKEN_COMMAND_COMPLETE);
-
+ if (psCmdCompleteData->pfnCommandComplete)
+ {
+ psCmdCompleteData->pfnCommandComplete(psCmdCompleteData->hCallbackData);
+ }
+
+ /* free command complete storage */
psCmdCompleteData->bInUse = IMG_FALSE;
-
+ /* FIXME: This may cause unrelated devices to be woken up. */
PVRSRVScheduleDeviceCallbacks();
if(bScheduleMISR)
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterCmdProcListKM
+
+ @Description
+
+ registers a list of private command processing functions with the Command
+ Queue Manager
+
+ @Input ui32DevIndex : device index
+
+ @Input ppfnCmdProcList : function ptr table of private command processors
+
+ @Input ui32MaxSyncsPerCmd : max number of syncobjects used by command
+
+ @Input ui32CmdCount : number of entries in function ptr table
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
PFN_CMD_PROC *ppfnCmdProcList,
DEVICE_COMMAND_DATA *psDeviceCommandData;
COMMAND_COMPLETE_DATA *psCmdCompleteData;
-
+ /* validate device type */
if(ui32DevIndex >= SYS_DEVICE_COUNT)
{
PVR_DPF((PVR_DBG_ERROR,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* acquire system data structure */
SysAcquireData(&psSysData);
-
+ /* array of pointers for each command store */
ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
ui32AllocSize,
{
psDeviceCommandData[ui32CmdTypeCounter].pfnCmdProc = ppfnCmdProcList[ui32CmdTypeCounter];
psDeviceCommandData[ui32CmdTypeCounter].ui32CCBOffset = 0;
-
+ psDeviceCommandData[ui32CmdTypeCounter].ui32MaxDstSyncCount = ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0];
+ psDeviceCommandData[ui32CmdTypeCounter].ui32MaxSrcSyncCount = ui32MaxSyncsPerCmd[ui32CmdTypeCounter][1];
for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
{
-
-
- ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+ /*
+ allocate storage for the sync update on command complete
+ */
+ ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA) /* space for one GENERIC_CMD_COMPLETE */
+ ((ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0]
+ ui32MaxSyncsPerCmd[ui32CmdTypeCounter][1])
- * sizeof(PVRSRV_SYNC_OBJECT));
+ * sizeof(PVRSRV_SYNC_OBJECT)); /* space for max sync objects */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
ui32AllocSize,
psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = psCmdCompleteData;
-
+ /* clear memory */
OSMemSet(psCmdCompleteData, 0x00, ui32AllocSize);
-
+ /* setup sync pointers */
psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT*)
(((IMG_UINTPTR_T)psCmdCompleteData)
+ sizeof(COMMAND_COMPLETE_DATA));
ErrorExit:
-
+ /* clean-up if things went wrong */
if (PVRSRVRemoveCmdProcListKM(ui32DevIndex, ui32CmdCount) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRemoveCmdProcListKM
+
+ @Description
+
+ removes a list of private command processing functions and data from the
+ Queue Manager
+
+ @Input ui32DevIndex : device index
+
+ @Input ui32CmdCount : number of entries in function ptr table
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
IMG_UINT32 ui32CmdCount)
COMMAND_COMPLETE_DATA *psCmdCompleteData;
IMG_SIZE_T ui32AllocSize;
-
+ /* validate device type */
if(ui32DevIndex >= SYS_DEVICE_COUNT)
{
PVR_DPF((PVR_DBG_ERROR,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* acquire system data structure */
SysAcquireData(&psSysData);
psDeviceCommandData = psSysData->apsDeviceCommandData[ui32DevIndex];
{
psCmdCompleteData = psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter];
-
+ /* free the cmd complete structure array entries */
if (psCmdCompleteData != IMG_NULL)
{
+ PVR_ASSERT(psCmdCompleteData->bInUse == IMG_FALSE);
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, psCmdCompleteData->ui32AllocSize,
psCmdCompleteData, IMG_NULL);
psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = IMG_NULL;
}
}
-
+ /* free the cmd complete structure array for the device */
ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psDeviceCommandData, IMG_NULL);
psSysData->apsDeviceCommandData[ui32DevIndex] = IMG_NULL;
return PVRSRV_OK;
}
+/******************************************************************************
+ End of file (queue.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Resource Allocator
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description
+ Implements generic resource allocation. The resource
+ allocator was originally intended to manage address spaces in
+ practice the resource allocator is generic and can manages arbitrary
+ sets of integers.
+
+ Resources are allocated from arenas. Arena's can be created with an
+ initial span of resources. Further resources spans can be added to
+ arenas. A call back mechanism allows an arena to request further
+ resource spans on demand.
+
+ Each arena maintains an ordered list of resource segments each
+ described by a boundary tag. Each boundary tag describes a segment
+ of resources which are either 'free', available for allocation, or
+ 'busy' currently allocated. Adjacent 'free' segments are always
+ coallesced to avoid fragmentation.
+
+ For allocation, all 'free' segments are kept on lists of 'free'
+ segments in a table index by pvr_log2(segment size). ie Each table index
+ n holds 'free' segments in the size range 2**(n-1) -> 2**n.
+
+ Allocation policy is based on an *almost* best fit
+ stratedy. Choosing any segment from the appropriate table entry
+ guarantees that we choose a segment which is with a power of 2 of
+ the size we are allocating.
+
+ Allocated segments are inserted into a self scaling hash table which
+ maps the base resource of the span to the relevant boundary
+ tag. This allows the code to get back to the bounary tag without
+ exporting explicit boundary tag references through the API.
+
+ Each arena has an associated quantum size, all allocations from the
+ arena are made in multiples of the basic quantum.
+
+ On resource exhaustion in an arena, a callback if provided will be
+ used to request further resources. Resouces spans allocated by the
+ callback mechanism are delimited by special boundary tag markers of
+ zero span, 'span' markers. Span markers are never coallesced. Span
+ markers are used to detect when an imported span is completely free
+ and can be deallocated by the callback mechanism.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/* Issues:
+ * - flags, flags are passed into the resource allocator but are not currently used.
+ * - determination, of import size, is currently braindead.
+ * - debug code should be moved out to own module and #ifdef'd
+ */
#include "services_headers.h"
#include "hash.h"
#include "buffer_manager.h"
#include "osfunc.h"
-#ifdef __linux__
+#if defined(__linux__) && defined(__KERNEL__)
#include <linux/kernel.h>
#include "proc.h"
#endif
#include <stdio.h>
#endif
+/* The initial, and minimum size of the live address -> boundary tag
+ structure hash table. The value 64 is a fairly arbitrary
+ choice. The hash table resizes on demand so the value choosen is
+ not critical. */
#define MINIMUM_HASH_SIZE (64)
#if defined(VALIDATE_ARENA_TEST)
+/* This test validates the doubly linked ordered list of boundary tags, by
+checking that adjacent members of the list have compatible eResourceSpan
+and eResourceType values. */
+
typedef enum RESOURCE_DESCRIPTOR_TAG {
RESOURCE_SPAN_LIVE = 10,
IMG_UINT32 ValidateArena(RA_ARENA *pArena);
#endif
+/* boundary tags, used to describe a resource segment */
struct _BT_
{
enum bt_type
{
- btt_span,
- btt_free,
- btt_live
+ btt_span, /* span markers */
+ btt_free, /* free resource segment */
+ btt_live /* allocated resource segment */
} type;
-
+ /* The base resource and extent of this segment */
IMG_UINTPTR_T base;
IMG_SIZE_T uSize;
-
+ /* doubly linked ordered list of all segments within the arena */
struct _BT_ *pNextSegment;
struct _BT_ *pPrevSegment;
-
+ /* doubly linked un-ordered list of free segments. */
struct _BT_ *pNextFree;
struct _BT_ *pPrevFree;
-
+ /* a user reference associated with this span, user references are
+ * currently only provided in the callback mechanism */
BM_MAPPING *psMapping;
#if defined(VALIDATE_ARENA_TEST)
RESOURCE_DESCRIPTOR eResourceSpan;
RESOURCE_TYPE eResourceType;
-
+ /* This variable provides a reference (used in debug messages) to incompatible
+ boundary tags within the doubly linked ordered list. */
IMG_UINT32 ui32BoundaryTagID;
#endif
typedef struct _BT_ BT;
+/* resource allocation arena */
struct _RA_ARENA_
{
-
+ /* arena name for diagnostics output */
IMG_CHAR *name;
-
+ /* allocations within this arena are quantum sized */
IMG_SIZE_T uQuantum;
-
+ /* import interface, if provided */
IMG_BOOL (*pImportAlloc)(IMG_VOID *,
IMG_SIZE_T uSize,
IMG_SIZE_T *pActualSize,
BM_MAPPING **ppsMapping,
IMG_UINT32 uFlags,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_UINTPTR_T *pBase);
IMG_VOID (*pImportFree) (IMG_VOID *,
IMG_UINTPTR_T,
BM_MAPPING *psMapping);
IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE);
-
+ /* arbitrary handle provided by arena owner to be passed into the
+ * import alloc and free hooks */
IMG_VOID *pImportHandle;
-
+ /* head of list of free boundary tags for indexed by pvr_log2 of the
+ boundary tag size */
#define FREE_TABLE_LIMIT 32
-
+ /* power-of-two table of free lists */
BT *aHeadFree [FREE_TABLE_LIMIT];
-
+ /* resource ordered segment list */
BT *pHeadSegment;
BT *pTailSegment;
-
+ /* segment address to boundary tag hash table */
HASH_TABLE *pSegmentHash;
#ifdef RA_STATS
IMG_BOOL bInitProcEntry;
#endif
};
+/* #define ENABLE_RA_DUMP 1 */
#if defined(ENABLE_RA_DUMP)
IMG_VOID RA_Dump (RA_ARENA *pArena);
#endif
static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el);
static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off);
-#endif
+#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
#ifdef USE_BM_FREESPACE_CHECK
IMG_VOID CheckBMFreespace(IMG_VOID);
}
#endif
+/*!
+******************************************************************************
+ @Function _RequestAllocFail
+
+ @Description Default callback allocator used if no callback is
+ specified, always fails to allocate further resources to the
+ arena.
+
+ @Input _h - callback handle
+ @Input _uSize - requested allocation size
+ @Output _pActualSize - actual allocation size
+ @Input _pRef - user reference
+ @Input _uflags - allocation flags
+ @Input _pvPrivData - private data
+ @Input _ui32PrivDataLength - private data length
+ @Input _pBase - receives allocated base
+
+ @Return IMG_FALSE, this function always fails to allocate.
+******************************************************************************/
static IMG_BOOL
_RequestAllocFail (IMG_VOID *_h,
IMG_SIZE_T _uSize,
IMG_SIZE_T *_pActualSize,
BM_MAPPING **_ppsMapping,
IMG_UINT32 _uFlags,
+ IMG_PVOID _pvPrivData,
+ IMG_UINT32 _ui32PrivDataLength,
IMG_UINTPTR_T *_pBase)
{
PVR_UNREFERENCED_PARAMETER (_h);
PVR_UNREFERENCED_PARAMETER (_ppsMapping);
PVR_UNREFERENCED_PARAMETER (_uFlags);
PVR_UNREFERENCED_PARAMETER (_pBase);
+ PVR_UNREFERENCED_PARAMETER (_pvPrivData);
+ PVR_UNREFERENCED_PARAMETER (_ui32PrivDataLength);
return IMG_FALSE;
}
+/*!
+******************************************************************************
+ @Function pvr_log2
+
+ @Description Computes the floor of the log base 2 of a unsigned integer
+
+ @Input n - unsigned integer
+
+ @Return Floor(Log2(n))
+******************************************************************************/
static IMG_UINT32
pvr_log2 (IMG_SIZE_T n)
{
return l;
}
+/*!
+******************************************************************************
+ @Function _SegmentListInsertAfter
+
+ @Description Insert a boundary tag into an arena segment list after a
+ specified boundary tag.
+
+ @Input pArena - the arena.
+ @Input pInsertionPoint - the insertion point.
+ @Input pBT - the boundary tag to insert.
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
static PVRSRV_ERROR
_SegmentListInsertAfter (RA_ARENA *pArena,
BT *pInsertionPoint,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ @Function _SegmentListInsert
+
+ @Description Insert a boundary tag into an arena segment list at the
+ appropriate point.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag to insert.
+
+ @Return None
+******************************************************************************/
static PVRSRV_ERROR
_SegmentListInsert (RA_ARENA *pArena, BT *pBT)
{
PVRSRV_ERROR eError = PVRSRV_OK;
-
+ /* insert into the segment chain */
if (pArena->pHeadSegment == IMG_NULL)
{
pArena->pHeadSegment = pArena->pTailSegment = pBT;
if (pBT->base < pArena->pHeadSegment->base)
{
-
+ /* The base address of pBT is less than the base address of the boundary tag
+ at the head of the list - so insert this boundary tag at the head. */
pBT->pNextSegment = pArena->pHeadSegment;
pArena->pHeadSegment->pPrevSegment = pBT;
pArena->pHeadSegment = pBT;
else
{
-
-
-
+ /* The base address of pBT is greater than or equal to that of the boundary tag
+ at the head of the list. Search for the insertion point: pBT must be inserted
+ before the first boundary tag with a greater base value - or at the end of the list.
+ */
pBTScan = pArena->pHeadSegment;
while ((pBTScan->pNextSegment != IMG_NULL) && (pBT->base >= pBTScan->pNextSegment->base))
return eError;
}
+/*!
+******************************************************************************
+ @Function _SegmentListRemove
+
+ @Description Remove a boundary tag from an arena segment list.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag to remove.
+
+ @Return None
+******************************************************************************/
static IMG_VOID
_SegmentListRemove (RA_ARENA *pArena, BT *pBT)
{
pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
}
+/*!
+******************************************************************************
+ @Function _SegmentSplit
+
+ @Description Split a segment into two, maintain the arena segment list. The
+ boundary tag should not be in the free table. Neither the
+ original or the new neighbour bounary tag will be in the free
+ table.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag to split.
+ @Input uSize - the required segment size of boundary tag after
+ splitting.
+
+ @Return New neighbour boundary tag.
+
+******************************************************************************/
static BT *
_SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize)
{
return pNeighbour;
}
+/*!
+******************************************************************************
+ @Function _FreeListInsert
+
+ @Description Insert a boundary tag into an arena free table.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag.
+
+ @Return None
+
+******************************************************************************/
static IMG_VOID
_FreeListInsert (RA_ARENA *pArena, BT *pBT)
{
pArena->aHeadFree [uIndex] = pBT;
}
+/*!
+******************************************************************************
+ @Function _FreeListRemove
+
+ @Description Remove a boundary tag from an arena free table.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag.
+
+ @Return None
+
+******************************************************************************/
static IMG_VOID
_FreeListRemove (RA_ARENA *pArena, BT *pBT)
{
pBT->pPrevFree->pNextFree = pBT->pNextFree;
}
+/*!
+******************************************************************************
+ @Function _BuildSpanMarker
+
+ @Description Construct a span marker boundary tag.
+
+ @Input pArena - arena to contain span marker
+ @Input base - the base of the bounary tag.
+
+ @Return span marker boundary tag
+
+******************************************************************************/
static BT *
_BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
return pBT;
}
+/*!
+******************************************************************************
+ @Function _BuildBT
+
+ @Description Construct a boundary tag for a free segment.
+
+ @Input base - the base of the resource segment.
+ @Input uSize - the extent of the resouce segment.
+
+ @Return boundary tag
+
+******************************************************************************/
static BT *
_BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
return pBT;
}
+/*!
+******************************************************************************
+ @Function _InsertResource
+
+ @Description Add a free resource segment to an arena.
+
+ @Input pArena - the arena.
+ @Input base - the base of the resource segment.
+ @Input uSize - the extent of the resource segment.
+
+ @Return New bucket pointer
+ IMG_NULL failure
+
+******************************************************************************/
static BT *
_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
return pBT;
}
+/*!
+******************************************************************************
+ @Function _InsertResourceSpan
+
+ @Description Add a free resource span to an arena, complete with span markers.
+
+ @Input pArena - the arena.
+ @Input base - the base of the resource segment.
+ @Input uSize - the extent of the resource segment.
+
+ @Return the boundary tag representing the free resource segment,
+ or IMG_NULL on failure.
+******************************************************************************/
static BT *
_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
#ifdef RA_STATS
pArena->sStatistics.uTotalResourceCount+=uSize;
+/* pArena->sStatistics.uFreeResourceCount+=uSize;
+ This has got to be wrong as uFreeResourceCount ends
+ up larger than uTotalResourceCount by uTotalResourceCount
+ - allocated memory
+*/
#endif
return pBT;
fail_SegListInsert:
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
fail_bt:
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
fail_end:
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
fail_start:
return IMG_NULL;
}
+/*!
+******************************************************************************
+ @Function _FreeBT
+
+ @Description Free a boundary tag taking care of the segment list and the
+ boundary tag free table.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag to free.
+ @Input bFreeBackingStore - Should backing for the memory be freed
+ as well.
+ @Return None
+******************************************************************************/
static IMG_VOID
_FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
{
uOrigBase = pBT->base;
uOrigSize = pBT->uSize;
-
+ /* try and coalesce with left neighbour */
pNeighbour = pBT->pPrevSegment;
if (pNeighbour!=IMG_NULL
&& pNeighbour->type == btt_free
pBT->base = pNeighbour->base;
pBT->uSize += pNeighbour->uSize;
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
-
+ /*not nulling original pointer, already overwritten*/
#ifdef RA_STATS
pArena->sStatistics.uFreeSegmentCount--;
#endif
}
-
+ /* try to coalesce with right neighbour */
pNeighbour = pBT->pNextSegment;
if (pNeighbour!=IMG_NULL
&& pNeighbour->type == btt_free
_SegmentListRemove (pArena, pNeighbour);
pBT->uSize += pNeighbour->uSize;
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
-
+ /*not nulling original pointer, already overwritten*/
#ifdef RA_STATS
pArena->sStatistics.uFreeSegmentCount--;
#endif
}
-
+ /* try to free backing store memory. */
if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore)
{
IMG_UINTPTR_T uRoundedStart, uRoundedEnd;
-
+ /* Work out the first address we might be able to free. */
uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
-
+ /* If a span is still using that address then leave it. */
if (uRoundedStart < pBT->base)
{
uRoundedStart += pArena->uQuantum;
}
-
+ /* Work out the last address we might be able to free. */
uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum;
-
+ /* If a span is still using that addres then leave it. */
if (uRoundedEnd > (pBT->base + pBT->uSize))
{
uRoundedEnd -= pArena->uQuantum;
pArena->sStatistics.uTotalResourceCount-=pBT->uSize;
#endif
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL);
-
+ /*not nulling original pointer, already overwritten*/
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL);
-
+ /*not nulling original pointer, already overwritten*/
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
else
_FreeListInsert (pArena, pBT);
}
+/*!
+******************************************************************************
+ @Function _AttemptAllocAligned
+
+ @Description Attempt an allocation from an arena.
+
+ @Input pArena - the arena.
+ @Input uSize - the requested allocation size.
+ @Output ppsMapping - the user references associated with
+ the allocated segment.
+ @Input flags - allocation flags
+ @Input uAlignment - required uAlignment, or 0
+ @Input uAlignmentOffset
+ @Output base - allocated resource base
+
+ @Return IMG_FALSE failure
+ IMG_TRUE success
+******************************************************************************/
static IMG_BOOL
_AttemptAllocAligned (RA_ARENA *pArena,
IMG_SIZE_T uSize,
if (uAlignment>1)
uAlignmentOffset %= uAlignment;
-
-
+ /* search for a near fit free boundary tag, start looking at the
+ pvr_log2 free table for our required size and work on up the
+ table. */
uIndex = pvr_log2 (uSize);
-#if 0
-
- if (1u<<uIndex < uSize)
- uIndex++;
-#endif
-
while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL)
uIndex++;
{
if (pArena->aHeadFree[uIndex]!=IMG_NULL)
{
-
+ /* we have a cached free boundary tag */
BT *pBT;
pBT = pArena->aHeadFree [uIndex];
pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
#endif
-
+ /* with uAlignment we might need to discard the front of this segment */
if (aligned_base > pBT->base)
{
BT *pNeighbour;
pNeighbour = _SegmentSplit (pArena, pBT, (IMG_SIZE_T)(aligned_base - pBT->base));
-
+ /* partition the buffer, create a new boundary tag */
if (pNeighbour==IMG_NULL)
{
PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed"));
-
+ /* Put pBT back in the list */
_FreeListInsert (pArena, pBT);
return IMG_FALSE;
}
pBT = pNeighbour;
}
-
+ /* the segment might be too big, if so, discard the back of the segment */
if (pBT->uSize > uSize)
{
BT *pNeighbour;
pNeighbour = _SegmentSplit (pArena, pBT, uSize);
-
+ /* partition the buffer, create a new boundary tag */
if (pNeighbour==IMG_NULL)
{
PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed"));
-
+ /* Put pBT back in the list */
_FreeListInsert (pArena, pBT);
return IMG_FALSE;
}
+/*!
+******************************************************************************
+ @Function RA_Create
+
+ @Description To create a resource arena.
+
+ @Input name - the name of the arena for diagnostic purposes.
+ @Input base - the base of an initial resource span or 0.
+ @Input uSize - the size of an initial resource span or 0.
+ @Input uQuantum - the arena allocation quantum.
+ @Input alloc - a resource allocation callback or 0.
+ @Input free - a resource de-allocation callback or 0.
+ @Input backingstore_free - a callback to free resources for spans or 0.
+ @Input pImportHandle - handle passed to alloc and free or 0.
+
+ @Return arena handle, or IMG_NULL.
+******************************************************************************/
RA_ARENA *
RA_Create (IMG_CHAR *name,
IMG_UINTPTR_T base,
BM_MAPPING *psMapping,
IMG_SIZE_T uQuantum,
IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize,
- BM_MAPPING **ppsMapping, IMG_UINT32 _flags, IMG_UINTPTR_T *pBase),
+ BM_MAPPING **ppsMapping, IMG_UINT32 _flags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength,
+ IMG_UINTPTR_T *pBase),
IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *),
IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE),
IMG_VOID *pImportHandle)
pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
-
+ /* Don't put shared heap info into a per process /proc subdirectory */
pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq;
ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name);
PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
}
}
-#endif
+#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE);
if (pArena->pSegmentHash==IMG_NULL)
HASH_Delete (pArena->pSegmentHash);
hash_fail:
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
arena_fail:
return IMG_NULL;
}
+/*!
+******************************************************************************
+ @Function RA_Delete
+
+ @Description To delete a resource arena. All resources allocated from
+ the arena must be freed before deleting the arena.
+
+ @Input pArena - the arena to delete.
+
+ @Return None
+******************************************************************************/
IMG_VOID
RA_Delete (RA_ARENA *pArena)
{
_SegmentListRemove (pArena, pBT);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
-
+ /*not nulling original pointer, it has changed*/
#ifdef RA_STATS
pArena->sStatistics.uSpanCount--;
#endif
#endif
HASH_Delete (pArena->pSegmentHash);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
+/*!
+******************************************************************************
+ @Function RA_TestDelete
+
+ @Description To test whether it is safe to delete a resource arena. If any
+ allocations have not been freed, the RA must not be deleted.
+
+ @Input pArena - the arena to test.
+
+ @Return IMG_BOOL - IMG_TRUE if is safe to go on and call RA_Delete.
+******************************************************************************/
IMG_BOOL
RA_TestDelete (RA_ARENA *pArena)
{
return IMG_TRUE;
}
+/*!
+******************************************************************************
+ @Function RA_Add
+
+ @Description To add a resource span to an arena. The span must not
+ overlapp with any span previously added to the arena.
+
+ @Input pArena - the arena to add a span into.
+ @Input base - the base of the span.
+ @Input uSize - the extent of the span.
+
+ @Return IMG_TRUE - Success
+ IMG_FALSE - failure
+******************************************************************************/
IMG_BOOL
RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL));
}
+/*!
+******************************************************************************
+ @Function RA_Alloc
+
+ @Description To allocate resource from an arena.
+
+ @Input pArena - the arena
+ @Input uRequestSize - the size of resource segment requested.
+ @Output pActualSize - the actual size of resource segment
+ allocated, typcially rounded up by quantum.
+ @Output ppsMapping - the user reference associated with allocated resource span.
+ @Input uFlags - flags influencing allocation policy.
+ @Input uAlignment - the uAlignment constraint required for the
+ allocated segment, use 0 if uAlignment not required.
+ @Input uAlignmentOffset
+ @Input pvPrivData - opaque private data passed through to allocator
+ @Input ui32PrivDataLength - length of opaque private data
+
+ @Output base - allocated base resource
+
+ @Return IMG_TRUE - success
+ IMG_FALSE - failure
+******************************************************************************/
IMG_BOOL
RA_Alloc (RA_ARENA *pArena,
IMG_SIZE_T uRequestSize,
IMG_UINT32 uFlags,
IMG_UINT32 uAlignment,
IMG_UINT32 uAlignmentOffset,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_UINTPTR_T *base)
{
IMG_BOOL bResult;
"RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x",
pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset));
-
-
+ /* if allocation failed then we might have an import source which
+ can provide more resource, else we will have to fail the
+ allocation to the caller. */
bResult = _AttemptAllocAligned (pArena, uSize, ppsMapping, uFlags,
uAlignment, uAlignmentOffset, base);
if (!bResult)
IMG_UINTPTR_T import_base;
IMG_SIZE_T uImportSize = uSize;
-
-
-
+ /*
+ Ensure that we allocate sufficient space to meet the uAlignment
+ constraint
+ */
if (uAlignment > pArena->uQuantum)
{
uImportSize += (uAlignment - 1);
}
-
+ /* ensure that we import according to the quanta of this arena */
uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum;
bResult =
pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize,
- &psImportMapping, uFlags, &import_base);
+ &psImportMapping, uFlags,
+ pvPrivData, ui32PrivDataLength, &import_base);
if (bResult)
{
BT *pBT;
pBT = _InsertResourceSpan (pArena, import_base, uImportSize);
-
+ /* successfully import more resource, create a span to
+ represent it and retry the allocation attempt */
if (pBT == IMG_NULL)
{
-
+ /* insufficient resources to insert the newly acquired span,
+ so free it back again */
pArena->pImportFree(pArena->pImportHandle, import_base,
psImportMapping);
PVR_DPF ((PVR_DBG_MESSAGE,
"RA_Alloc: name='%s', size=0x%x failed!",
pArena->name, uSize));
-
+ /* RA_Dump (arena); */
return IMG_FALSE;
}
pBT->psMapping = psImportMapping;
"RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
pArena->name, uSize, *base, bResult));
-
+ /* RA_Dump (pArena);
+ ra_stats (pArena);
+ */
#if defined(VALIDATE_ARENA_TEST)
ValidateArena(pArena);
#if defined(VALIDATE_ARENA_TEST)
+/*!
+******************************************************************************
+ @Function ValidateArena
+
+ @Description Validate an arena by checking that adjacent members of the
+ double linked ordered list are compatible. PVR_DBG_BREAK and
+ PVR_DPF messages are used when an error is detected.
+ NOTE: A DEBUG build is required for PVR_DBG_BREAK and PVR_DPF
+ to operate.
+
+ @Input pArena - the arena
+
+ @Return 0
+******************************************************************************/
IMG_UINT32 ValidateArena(RA_ARENA *pArena)
{
BT* pSegment;
(eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
(eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
{
-
+ /* error - next span must be live, free or end */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
(eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
{
-
+ /* error - next span must be live or end */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
(eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
(eNextSpan == IMPORTED_RESOURCE_SPAN_END))
{
-
+ /* error - next span cannot be live, free or end */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
(eNextSpan == IMPORTED_RESOURCE_SPAN_FREE)))
{
-
+ /* error - next span must be live or free */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
(eNextSpan == RESOURCE_SPAN_LIVE)))
{
-
+ /* error - next span must be free or live */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
(eNextSpan == RESOURCE_SPAN_LIVE)))
{
-
+ /* error - next span must be free or live */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
#endif
+/*!
+******************************************************************************
+ @Function RA_Free
+
+ @Description To free a resource segment.
+
+ @Input pArena - the arena the segment was originally allocated from.
+ @Input base - the base of the resource span to free.
+ @Input bFreeBackingStore - Should backing store memory be freed.
+
+ @Return None
+******************************************************************************/
IMG_VOID
RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
{
}
+/*!
+******************************************************************************
+ @Function RA_GetNextLiveSegment
+
+ @Description Returns details of the next live resource segments
+
+ @Input pArena - the arena the segment was originally allocated from.
+ @InOut psSegDetails - rtn details of segments
+
+ @Return IMG_TRUE if operation succeeded
+******************************************************************************/
IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails)
{
BT *pBT;
pBT = pArena->pHeadSegment;
}
-
+ /* walk the arena segments and write live one to the buffer */
while (pBT != IMG_NULL)
{
if (pBT->type == btt_live)
}
return "junk";
}
-#endif
+#endif /*defined(CONFIG_PROC_FS) && defined(DEBUG)*/
#if defined(ENABLE_RA_DUMP)
+/*!
+******************************************************************************
+ @Function RA_Dump
+
+ @Description To dump a readable description of an arena. Diagnostic only.
+
+ @Input pArena - the arena to dump.
+
+ @Return None
+******************************************************************************/
IMG_VOID
RA_Dump (RA_ARENA *pArena)
{
for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
{
- PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s ref=%08X",
- (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type),
- pBT->pRef));
+ PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s",
+ (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type)));
}
#ifdef HASH_TRACE
HASH_Dump (pArena->pSegmentHash);
#endif
}
-#endif
+#endif /* #if defined(ENABLE_RA_DUMP) */
#if defined(CONFIG_PROC_FS) && defined(DEBUG)
return (void*)pBT;
}
-#endif
+#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
#ifdef RA_STATS
+/*!
+******************************************************************************
+ @Function RA_GetStats
+
+ @Description Gets the arena stats and places in client buffer
+
+ @Input pArena - the arena to print statistics for.
+ @Input ppszStr - caller string to fill
+ @Input pui32StrLen - length of caller string
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
IMG_CHAR **ppszStr,
IMG_UINT32 *pui32StrLen)
}
#endif
+/******************************************************************************
+ End of file (ra.c)
+******************************************************************************/
+
+
+
+
--- /dev/null
+/*************************************************************************/ /*!
+@Title Services reference count debugging
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+
+#include "services_headers.h"
+
+#ifndef __linux__
+#warning Reference count debugging is not thread-safe on this platform
+#define PVRSRV_LOCK_CCB()
+#define PVRSRV_UNLOCK_CCB()
+#else /* __linux__ */
+#include <linux/spinlock.h>
+static DEFINE_SPINLOCK(gsCCBLock);
+#define PVRSRV_LOCK_CCB() \
+ { \
+ unsigned long flags; \
+ spin_lock_irqsave(&gsCCBLock, flags);
+#define PVRSRV_UNLOCK_CCB() \
+ spin_unlock_irqrestore(&gsCCBLock, flags); \
+ }
+#endif /* __linux__ */
+
+#define PVRSRV_REFCOUNT_CCB_MAX 512
+#define PVRSRV_REFCOUNT_CCB_MESG_MAX 80
+
+#define PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO (1U << 0)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO (1U << 1)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF (1U << 2)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2 (1U << 3)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC (1U << 4)
+
+#if defined(__linux__)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP (1U << 16)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2 (1U << 17)
+#else
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP 0
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2 0
+#endif
+
+#define PVRSRV_REFCOUNT_CCB_DEBUG_ALL ~0U
+
+/*static const IMG_UINT guiDebugMask = PVRSRV_REFCOUNT_CCB_DEBUG_ALL;*/
+static const IMG_UINT guiDebugMask =
+ PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO |
+ PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2;
+
+typedef struct
+{
+ const IMG_CHAR *pszFile;
+ IMG_INT iLine;
+ IMG_UINT32 ui32PID;
+ IMG_CHAR pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX];
+}
+PVRSRV_REFCOUNT_CCB;
+
+static PVRSRV_REFCOUNT_CCB gsRefCountCCB[PVRSRV_REFCOUNT_CCB_MAX];
+static IMG_UINT giOffset;
+
+static const IMG_CHAR gszHeader[] =
+ /* 10 20 30 40 50 60 70
+ * 345678901234567890123456789012345678901234567890123456789012345678901
+ */
+ "TYPE SYNCINFO MEMINFO MEMHANDLE OTHER REF REF' SIZE PID";
+ /* NCINFO deadbeef deadbeef deadbeef deadbeef 1234 1234 deadbeef */
+
+#define PVRSRV_REFCOUNT_CCB_FMT_STRING "%8.8s %8p %8p %8p %8p %.4d %.4d %.8x"
+
+IMG_INTERNAL
+void PVRSRVDumpRefCountCCB(void)
+{
+ int i;
+
+ PVRSRV_LOCK_CCB();
+
+ PVR_LOG(("%s", gszHeader));
+
+ for(i = 0; i < PVRSRV_REFCOUNT_CCB_MAX; i++)
+ {
+ PVRSRV_REFCOUNT_CCB *psRefCountCCBEntry =
+ &gsRefCountCCB[(giOffset + i) % PVRSRV_REFCOUNT_CCB_MAX];
+
+ /* Early on, we won't have MAX_REFCOUNT_CCB_SIZE messages */
+ if(!psRefCountCCBEntry->pszFile)
+ break;
+
+ PVR_LOG(("%s %d %s:%d", psRefCountCCBEntry->pcMesg,
+ psRefCountCCBEntry->ui32PID,
+ psRefCountCCBEntry->pszFile,
+ psRefCountCCBEntry->iLine));
+ }
+
+ PVRSRV_UNLOCK_CCB();
+}
+
+IMG_INTERNAL
+void PVRSRVKernelSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ IMG_UINT32 ui32RefValue = OSAtomicRead(psKernelSyncInfo->pvRefCount);
+
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "SYNCINFO",
+ psKernelSyncInfo,
+ psKernelMemInfo,
+ NULL,
+ (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL,
+ ui32RefValue,
+ ui32RefValue + 1,
+ (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ PVRSRVAcquireSyncInfoKM(psKernelSyncInfo);
+}
+
+IMG_INTERNAL
+void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ IMG_UINT32 ui32RefValue = OSAtomicRead(psKernelSyncInfo->pvRefCount);
+
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "SYNCINFO",
+ psKernelSyncInfo,
+ psKernelMemInfo,
+ (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL,
+ NULL,
+ ui32RefValue,
+ ui32RefValue - 1,
+ (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ PVRSRVReleaseSyncInfoKM(psKernelSyncInfo);
+}
+
+IMG_INTERNAL
+void PVRSRVKernelMemInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MEMINFO",
+ psKernelMemInfo->psKernelSyncInfo,
+ psKernelMemInfo,
+ psKernelMemInfo->sMemBlk.hOSMemHandle,
+ NULL,
+ psKernelMemInfo->ui32RefCount,
+ psKernelMemInfo->ui32RefCount + 1,
+ psKernelMemInfo->uAllocSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psKernelMemInfo->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MEMINFO",
+ psKernelMemInfo->psKernelSyncInfo,
+ psKernelMemInfo,
+ psKernelMemInfo->sMemBlk.hOSMemHandle,
+ NULL,
+ psKernelMemInfo->ui32RefCount,
+ psKernelMemInfo->ui32RefCount - 1,
+ psKernelMemInfo->uAllocSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psKernelMemInfo->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32RefCount,
+ pBuf->ui32RefCount + 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32RefCount,
+ pBuf->ui32RefCount - 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufIncExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF2",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32ExportCount,
+ pBuf->ui32ExportCount + 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32ExportCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF2",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32ExportCount,
+ pBuf->ui32ExportCount - 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32ExportCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMXProcIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_XPROC",
+ NULL,
+ NULL,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle,
+ (IMG_VOID *) ui32Index,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount + 1,
+ gXProcWorkaroundShareData[ui32Index].ui32Size);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMXProcDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_XPROC",
+ NULL,
+ NULL,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle,
+ (IMG_VOID *) ui32Index,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount - 1,
+ gXProcWorkaroundShareData[ui32Index].ui32Size);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount--;
+}
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+
+IMG_INTERNAL
+void PVRSRVOffsetStructIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32RefCount,
+ psOffsetStruct->ui32RefCount + 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32RefCount,
+ psOffsetStruct->ui32RefCount - 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructIncMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP2",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32Mapped,
+ psOffsetStruct->ui32Mapped + 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32Mapped++;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP2",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32Mapped,
+ psOffsetStruct->ui32Mapped - 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32Mapped--;
+}
+
+#endif /* defined(__linux__) */
+
+#endif /* defined(PVRSRV_REFCOUNT_DEBUG) */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Resource Manager
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource management
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
#include "resman.h"
#define RESMAN_SIGNATURE 0x12345678
+/******************************************************************************
+ * resman structures
+ *****************************************************************************/
+
+/* resman item structure */
typedef struct _RESMAN_ITEM_
{
#ifdef DEBUG
IMG_UINT32 ui32Signature;
#endif
- struct _RESMAN_ITEM_ **ppsThis;
- struct _RESMAN_ITEM_ *psNext;
+ struct _RESMAN_ITEM_ **ppsThis; /*!< list navigation */
+ struct _RESMAN_ITEM_ *psNext; /*!< list navigation */
- IMG_UINT32 ui32Flags;
- IMG_UINT32 ui32ResType;
+ IMG_UINT32 ui32Flags; /*!< flags */
+ IMG_UINT32 ui32ResType;/*!< res type */
- IMG_PVOID pvParam;
- IMG_UINT32 ui32Param;
+ IMG_PVOID pvParam; /*!< param1 for callback */
+ IMG_UINT32 ui32Param; /*!< param2 for callback */
- RESMAN_FREE_FN pfnFreeResource;
+ RESMAN_FREE_FN pfnFreeResource;/*!< resman item free callback */
} RESMAN_ITEM;
+/* resman context structure */
typedef struct _RESMAN_CONTEXT_
{
#ifdef DEBUG
IMG_UINT32 ui32Signature;
#endif
- struct _RESMAN_CONTEXT_ **ppsThis;
- struct _RESMAN_CONTEXT_ *psNext;
+ struct _RESMAN_CONTEXT_ **ppsThis;/*!< list navigation */
+ struct _RESMAN_CONTEXT_ *psNext;/*!< list navigation */
- PVRSRV_PER_PROCESS_DATA *psPerProc;
+ PVRSRV_PER_PROCESS_DATA *psPerProc; /* owner of resources */
- RESMAN_ITEM *psResItemList;
+ RESMAN_ITEM *psResItemList;/*!< res item list for context */
} RESMAN_CONTEXT;
+/* resman list structure */
typedef struct
{
- RESMAN_CONTEXT *psContextList;
+ RESMAN_CONTEXT *psContextList; /*!< resman context list */
-} RESMAN_LIST, *PRESMAN_LIST;
+} RESMAN_LIST, *PRESMAN_LIST; /* PRQA S 3205 */
PRESMAN_LIST gpsResList = IMG_NULL;
-#include "lists.h"
+#include "lists.h" /* PRQA S 5087 */ /* include lists.h required here */
static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
#define PRINT_RESLIST(x, y, z)
+/******************************************************** Forword references */
+
static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem, IMG_BOOL bExecuteCallback, IMG_BOOL bForceCleanup);
static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psContext,
+/*!
+******************************************************************************
+
+ @Function ResManInit
+
+ @Description initialises the resman
+
+ @Return none
+
+******************************************************************************/
PVRSRV_ERROR ResManInit(IMG_VOID)
{
if (gpsResList == IMG_NULL)
{
-
+ /* If not already initialised */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*gpsResList),
(IMG_VOID **)&gpsResList, IMG_NULL,
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* Init list, the linked list has dummy entries at both ends */
gpsResList->psContextList = IMG_NULL;
-
+ /* Check resource list */
VALIDATERESLIST();
}
}
+/*!
+******************************************************************************
+
+ @Function ResManDeInit
+
+ @Description de-initialises the resman
+
+ @Return none
+
+******************************************************************************/
IMG_VOID ResManDeInit(IMG_VOID)
{
if (gpsResList != IMG_NULL)
{
-
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList), gpsResList, IMG_NULL);
gpsResList = IMG_NULL;
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManConnect
+
+ @Description Opens a connection to the Resource Manager
+
+ @input hPerProc - Per-process data (if applicable)
+ @output phResManContext - Resman context
+
+ @Return error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
PRESMAN_CONTEXT *phResManContext)
{
PVRSRV_ERROR eError;
PRESMAN_CONTEXT psResManContext;
-
+ /*Acquire resource list sync object*/
ACQUIRE_SYNC_OBJ;
-
+ /*Check resource list*/
VALIDATERESLIST();
-
+ /* Allocate memory for the new context. */
eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
(IMG_VOID **)&psResManContext, IMG_NULL,
"Resource Manager Context");
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
return eError;
#ifdef DEBUG
psResManContext->ui32Signature = RESMAN_SIGNATURE;
-#endif
+#endif /* DEBUG */
psResManContext->psResItemList = IMG_NULL;
psResManContext->psPerProc = hPerProc;
-
+ /* Insert new context struct after the dummy first entry */
List_RESMAN_CONTEXT_Insert(&gpsResList->psContextList, psResManContext);
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
*phResManContext = psResManContext;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManDisconnect
+
+ @Description Closes a Resource Manager connection and frees all resources
+
+ @input hResManContext - Resman context
+ @input bKernelContext - IMG_TRUE for kernel contexts
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
IMG_BOOL bKernelContext)
{
-
+ /* Acquire resource list sync object */
ACQUIRE_SYNC_OBJ;
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Print and validate resource list */
PRINT_RESLIST(gpsResList, psResManContext, IMG_TRUE);
-
+ /* Free all auto-freed resources in order */
if (!bKernelContext)
{
-
+ /* OS specific User-mode Mappings: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_OS_USERMODE_MAPPING, 0, 0, IMG_TRUE);
-
+ /* VGX types: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DMA_CLIENT_FIFO_DATA, 0, 0, IMG_TRUE);
-
+ /* Event Object */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_EVENT_OBJECT, 0, 0, IMG_TRUE);
-
-
+ /* syncobject state (Read/Write Complete values) */
+ /* Must be FIFO, so we reverse the list, twice */
List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_MODIFY_SYNC_OPS, 0, 0, IMG_TRUE);
- List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
+ List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList); // (could survive without this - all following items would be cleared up "fifo" too)
-
+ /* SGX types: */
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_SHARED_PB_DESC_CREATE_LOCK, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC, 0, 0, IMG_TRUE);
-
-
-
+ /* COMMON types: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SYNC_INFO, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_WRAP, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_CONTEXT, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_MEM_INFO, 0, 0, IMG_TRUE);
-
-
+#if defined(SUPPORT_ION)
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ION, 0, 0, IMG_TRUE);
+#endif
+ /* DISPLAY CLASS types: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_DEVICE, 0, 0, IMG_TRUE);
-
+ /* BUFFER CLASS types: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_BUFFERCLASS_DEVICE, 0, 0, IMG_TRUE);
}
-
+ /* Ensure that there are no resources left */
PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
-
+ /* Remove the context struct from the list */
List_RESMAN_CONTEXT_Remove(psResManContext);
-
+ /* Free the context struct */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), psResManContext, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Print and validate resource list */
PRINT_RESLIST(gpsResList, psResManContext, IMG_FALSE);
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
}
+/*!
+******************************************************************************
+ @Function ResManRegisterRes
+
+ @Description : Inform the resource manager that the given resource has
+ been alloacted and freeing of it will be the responsibility
+ of the resource manager
+
+ @input psResManContext - resman context
+ @input ui32ResType - identify what kind of resource it is
+ @input pvParam - address of resource
+ @input ui32Param - size of resource
+ @input pfnFreeResource - pointer to function that frees this resource
+
+ @Return On success a pointer to an opaque data structure that represents
+ the allocated resource, else NULL
+
+**************************************************************************/
PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
IMG_UINT32 ui32ResType,
IMG_PVOID pvParam,
return (PRESMAN_ITEM) IMG_NULL;
}
-
+ /* Acquire resource list sync object */
ACQUIRE_SYNC_OBJ;
-
+ /* Check resource list */
VALIDATERESLIST();
PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
ui32Param,
(IMG_UINTPTR_T)pfnFreeResource));
-
+ /* Allocate memory for the new resource structure */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(RESMAN_ITEM), (IMG_VOID **)&psNewResItem,
IMG_NULL,
PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
"ERROR allocating new resource item"));
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
return((PRESMAN_ITEM)IMG_NULL);
}
-
+ /* Fill in details about this resource */
#ifdef DEBUG
psNewResItem->ui32Signature = RESMAN_SIGNATURE;
-#endif
+#endif /* DEBUG */
psNewResItem->ui32ResType = ui32ResType;
psNewResItem->pvParam = pvParam;
psNewResItem->ui32Param = ui32Param;
psNewResItem->pfnFreeResource = pfnFreeResource;
psNewResItem->ui32Flags = 0;
-
+ /* Insert new structure after dummy first entry */
List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
return(psNewResItem);
}
+/*!
+******************************************************************************
+ @Function ResManFreeResByPtr
+
+ @Description frees a resource by matching on pointer type
+
+ @inputs psResItem - pointer to resource item to free
+ bForceCleanup - ignored uKernel re-sync
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM *psResItem, IMG_BOOL bForceCleanup)
{
PVRSRV_ERROR eError;
PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %08X",
(IMG_UINTPTR_T)psResItem));
-
+ /*Acquire resource list sync object*/
ACQUIRE_SYNC_OBJ;
-
+ /*Check resource list*/
VALIDATERESLIST();
-
+ /*Free resource*/
eError = FreeResourceByPtr(psResItem, IMG_TRUE, bForceCleanup);
-
+ /*Check resource list*/
VALIDATERESLIST();
-
+ /*Release resource list sync object*/
RELEASE_SYNC_OBJ;
return(eError);
}
+/*!
+******************************************************************************
+ @Function ResManFreeResByCriteria
+
+ @Description frees a resource by matching on criteria
+
+ @inputs hResManContext - handle for resman context
+ @inputs ui32SearchCriteria - indicates which parameters should be
+ used in search for resources to free
+ @inputs ui32ResType - identify what kind of resource to free
+ @inputs pvParam - address of resource to be free
+ @inputs ui32Param - size of resource to be free
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT psResManContext,
IMG_UINT32 ui32SearchCriteria,
IMG_UINT32 ui32ResType,
PVR_ASSERT(psResManContext != IMG_NULL);
-
+ /* Acquire resource list sync object */
ACQUIRE_SYNC_OBJ;
-
+ /* Check resource list */
VALIDATERESLIST();
PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
(IMG_UINTPTR_T)psResManContext, ui32SearchCriteria, ui32ResType,
(IMG_UINTPTR_T)pvParam, ui32Param));
-
+ /* Free resources by criteria for this context */
eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
ui32ResType, pvParam, ui32Param,
IMG_TRUE);
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
return eError;
}
+/*!
+******************************************************************************
+ @Function ResManDissociateRes
+
+ @Description Moves a resource from one context to another.
+
+ @inputs psResItem - pointer to resource item to dissociate
+ @inputs psNewResManContext - new resman context for the resource
+
+ @Return IMG_VOID
+**************************************************************************/
PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM *psResItem,
PRESMAN_CONTEXT psNewResManContext)
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
-#ifdef DEBUG
+#ifdef DEBUG /* QAC fix */
PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
#endif
if (psNewResManContext != IMG_NULL)
{
-
+ /* Remove this item from its old resource list */
List_RESMAN_ITEM_Remove(psResItem);
-
+ /* Re-insert into new list */
List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
}
return eError;
}
+/*!
+******************************************************************************
+ @Function ResManFindResourceByPtr_AnyVaCb
+
+ @Description
+ Compares the resman item with a given pointer.
+
+ @inputs psCurItem - theThe item to check
+ @inputs va - Variable argument list with:
+ psItem - pointer to resource item to find
+
+ @Return IMG_BOOL
+**************************************************************************/
static IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
{
RESMAN_ITEM *psItem;
}
+/*!
+******************************************************************************
+ @Function ResManFindResourceByPtr
+
+ @Description
+ Attempts to find a resource in the list for this context
+
+ @inputs hResManContext - handle for resman context
+ @inputs psItem - pointer to resource item to find
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContext,
RESMAN_ITEM *psItem)
{
+/* RESMAN_ITEM *psCurItem;*/
+
PVRSRV_ERROR eResult;
PVR_ASSERT(psResManContext != IMG_NULL);
return PVRSRV_ERROR_INVALID_PARAMS;
}
-#ifdef DEBUG
+#ifdef DEBUG /* QAC fix */
PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
#endif
-
+ /* Acquire resource list sync object */
ACQUIRE_SYNC_OBJ;
PVR_DPF((PVR_DBG_MESSAGE,
(IMG_UINTPTR_T)psItem->pfnFreeResource,
psItem->ui32Flags));
-
+ /* Search resource items starting at after the first dummy item */
if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
&ResManFindResourceByPtr_AnyVaCb,
psItem))
eResult = PVRSRV_ERROR_NOT_OWNER;
}
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
+/* return PVRSRV_ERROR_NOT_OWNER;*/
return eResult;
}
+/*!
+******************************************************************************
+ @Function FreeResourceByPtr
+
+ @Description
+ Frees a resource and move it from the list
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @inputs psItem - pointer to resource item to free
+ bExecuteCallback - execute callback?
+ bForceCleanup - skips uKernel re-sync
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem,
IMG_BOOL bExecuteCallback,
IMG_BOOL bForceCleanup)
return PVRSRV_ERROR_INVALID_PARAMS;
}
-#ifdef DEBUG
+#ifdef DEBUG /* QAC fix */
PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
#endif
(IMG_UINTPTR_T)psItem->pvParam, psItem->ui32Param,
(IMG_UINTPTR_T)psItem->pfnFreeResource, psItem->ui32Flags));
-
- List_RESMAN_ITEM_Remove(psItem);
-
-
-
+ /* Release resource list sync object just in case the free routine calls the resource manager */
RELEASE_SYNC_OBJ;
-
+ /* Call the freeing routine */
if (bExecuteCallback)
{
eError = psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param, bForceCleanup);
- if (eError != PVRSRV_OK)
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
{
PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function"));
}
}
-
+ /* Acquire resource list sync object */
ACQUIRE_SYNC_OBJ;
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL);
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Remove this item from the resource list */
+ List_RESMAN_ITEM_Remove(psItem);
+
+ /* Free memory for the resource item */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL);
+ }
return(eError);
}
+/*!
+******************************************************************************
+ @Function FreeResourceByCriteria_AnyVaCb
+
+ @Description
+ Matches a resource manager item with a given criteria.
+
+ @inputs psCuItem - the item to be matched
+ @inputs va - a variable argument list with:.
+ ui32SearchCriteria - indicates which parameters should be used
+ search for resources to free
+ ui32ResType - identify what kind of resource to free
+ pvParam - address of resource to be free
+ ui32Param - size of resource to be free
+
+
+ @Return psCurItem if matched, IMG_NULL otherwise.
+**************************************************************************/
static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
{
IMG_UINT32 ui32SearchCriteria;
pvParam = va_arg(va, IMG_PVOID);
ui32Param = va_arg(va, IMG_UINT32);
-
+ /*check that for all conditions are either disabled or eval to true*/
if(
-
+ /* Check resource type */
(((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
(psCurItem->ui32ResType == ui32ResType))
&&
-
+ /* Check address */
(((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
(psCurItem->pvParam == pvParam))
&&
-
+ /* Check size */
(((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
(psCurItem->ui32Param == ui32Param))
)
}
}
+/*!
+******************************************************************************
+ @Function FreeResourceByCriteria
+
+ @Description
+ Frees all resources that match the given criteria for the
+ context.
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @inputs psResManContext - pointer to resman context
+ @inputs ui32SearchCriteria - indicates which parameters should be used
+ @inputs search for resources to free
+ @inputs ui32ResType - identify what kind of resource to free
+ @inputs pvParam - address of resource to be free
+ @inputs ui32Param - size of resource to be free
+ @inputs ui32AutoFreeLev - auto free level to free
+ @inputs bExecuteCallback - execute callback?
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
IMG_UINT32 ui32SearchCriteria,
IMG_UINT32 ui32ResType,
PRESMAN_ITEM psCurItem;
PVRSRV_ERROR eError = PVRSRV_OK;
-
-
+ /* Search resource items starting at after the first dummy item */
+ /*while we get a match and not an error*/
while((psCurItem = (PRESMAN_ITEM)
List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
&FreeResourceByCriteria_AnyVaCb,
ui32Param)) != IMG_NULL
&& eError == PVRSRV_OK)
{
- eError = FreeResourceByPtr(psCurItem, bExecuteCallback, CLEANUP_WITH_POLL);
+ do
+ {
+ eError = FreeResourceByPtr(psCurItem, bExecuteCallback, CLEANUP_WITH_POLL);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ RELEASE_SYNC_OBJ;
+ OSReleaseBridgeLock();
+ /* Give a chance for other threads to come in and SGX to do more work */
+ OSSleepms(MAX_CLEANUP_TIME_WAIT_US/1000);
+ OSReacquireBridgeLock();
+ ACQUIRE_SYNC_OBJ;
+ }
+ } while (eError == PVRSRV_ERROR_RETRY);
}
return eError;
#ifdef DEBUG
+/*!
+******************************************************************************
+ @Function ValidateResList
+
+ @Description
+ Walks the resource list check the pointers
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @Return none
+**************************************************************************/
static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
{
PRESMAN_ITEM psCurItem, *ppsThisItem;
PRESMAN_CONTEXT psCurContext, *ppsThisContext;
-
+ /* check we're initialised */
if (psResList == IMG_NULL)
{
PVR_DPF((PVR_DBG_MESSAGE, "ValidateResList: resman not initialised yet"));
psCurContext = psResList->psContextList;
ppsThisContext = &psResList->psContextList;
-
+ /* Walk the context list */
while(psCurContext != IMG_NULL)
{
-
+ /* Check current item */
PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
if (psCurContext->ppsThis != ppsThisContext)
{
PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
}
-
+ /* Walk the list for this context */
psCurItem = psCurContext->psResItemList;
ppsThisItem = &psCurContext->psResItemList;
while(psCurItem != IMG_NULL)
{
-
+ /* Check current item */
PVR_ASSERT(psCurItem->ui32Signature == RESMAN_SIGNATURE);
if (psCurItem->ppsThis != ppsThisItem)
{
PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
}
-
+ /* Move to next item */
ppsThisItem = &psCurItem->psNext;
psCurItem = psCurItem->psNext;
}
-
+ /* Move to next context */
ppsThisContext = &psCurContext->psNext;
psCurContext = psCurContext->psNext;
}
}
-#endif
+#endif /* DEBUG */
+/******************************************************************************
+ End of file (resman.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title MMU Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements basic low level control of MMU.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "sgxdefs.h"
#include "sgxmmu.h"
#define UINT32_MAX_VALUE 0xFFFFFFFFUL
+/*
+ MMU performs device virtual to physical translation.
+ terminology:
+ page directory (PD)
+ pagetable (PT)
+ data page (DP)
+
+ Incoming 32bit Device Virtual Addresses are deconstructed into 3 fields:
+ ---------------------------------------------------------
+ | PD Index/tag: | PT Index: | DP offset: |
+ | bits 31:22 | bits 21:n | bits (n-1):0 |
+ ---------------------------------------------------------
+ where typically n=12 for a standard 4k DP
+ but n=16 for a 64k DP
+
+ MMU page directory (PD), pagetable (PT) and data page (DP) config:
+ PD:
+ - always one page per address space
+ - up to 4k in size to span 4Gb (32bit)
+ - contains up to 1024 32bit entries
+ - entries are indexed by the top 12 bits of an incoming 32bit device virtual address
+ - the PD entry selected contains the physical address of the PT to
+ perform the next stage of the V to P translation
+
+ PT:
+ - size depends on the DP size, e.g. 4k DPs have 4k PTs but 16k DPs have 1k PTs
+ - each PT always spans 4Mb of device virtual address space irrespective of DP size
+ - number of entries in a PT depend on DP size and ranges from 1024 to 4 entries
+ - entries are indexed by the PT Index field of the device virtual address (21:n)
+ - the PT entry selected contains the physical address of the DP to access
+
+ DP:
+ - size varies from 4k to 4M in multiple of 4 steppings
+ - DP offset field of the device virtual address ((n-1):0) is used as a byte offset
+ to address into the DP itself
+*/
+
#define SGX_MAX_PD_ENTRIES (1<<(SGX_FEATURE_ADDRESS_SPACE_SIZE - SGX_MMU_PT_SHIFT - SGX_MMU_PAGE_SHIFT))
#if defined(FIX_HW_BRN_31620)
-#define SGX_MMU_PDE_DUMMY_PAGE (0)
-#define SGX_MMU_PTE_DUMMY_PAGE (0)
+/* Sim doesn't use the address mask */
+#define SGX_MMU_PDE_DUMMY_PAGE (0)//(0x00000020U)
+#define SGX_MMU_PTE_DUMMY_PAGE (0)//(0x00000020U)
+/* 4MB adress range per page table */
#define BRN31620_PT_ADDRESS_RANGE_SHIFT 22
#define BRN31620_PT_ADDRESS_RANGE_SIZE (1 << BRN31620_PT_ADDRESS_RANGE_SHIFT)
+/* 64MB address range per PDE cache line */
#define BRN31620_PDE_CACHE_FILL_SHIFT 26
#define BRN31620_PDE_CACHE_FILL_SIZE (1 << BRN31620_PDE_CACHE_FILL_SHIFT)
#define BRN31620_PDE_CACHE_FILL_MASK (BRN31620_PDE_CACHE_FILL_SIZE - 1)
+/* Page Directory Enteries per cache line */
#define BRN31620_PDES_PER_CACHE_LINE_SHIFT (BRN31620_PDE_CACHE_FILL_SHIFT - BRN31620_PT_ADDRESS_RANGE_SHIFT)
#define BRN31620_PDES_PER_CACHE_LINE_SIZE (1 << BRN31620_PDES_PER_CACHE_LINE_SHIFT)
#define BRN31620_PDES_PER_CACHE_LINE_MASK (BRN31620_PDES_PER_CACHE_LINE_SIZE - 1)
+/* Macros for working out offset for dummy pages */
#define BRN31620_DUMMY_PAGE_OFFSET (1 * SGX_MMU_PAGE_SIZE)
#define BRN31620_DUMMY_PDE_INDEX (BRN31620_DUMMY_PAGE_OFFSET / BRN31620_PT_ADDRESS_RANGE_SIZE)
#define BRN31620_DUMMY_PTE_INDEX ((BRN31620_DUMMY_PAGE_OFFSET - (BRN31620_DUMMY_PDE_INDEX * BRN31620_PT_ADDRESS_RANGE_SIZE))/SGX_MMU_PAGE_SIZE)
+/* Cache number of cache lines */
#define BRN31620_CACHE_FLUSH_SHIFT (32 - BRN31620_PDE_CACHE_FILL_SHIFT)
#define BRN31620_CACHE_FLUSH_SIZE (1 << BRN31620_CACHE_FLUSH_SHIFT)
+/* Cache line bits in a UINT32 */
#define BRN31620_CACHE_FLUSH_BITS_SHIFT 5
#define BRN31620_CACHE_FLUSH_BITS_SIZE (1 << BRN31620_CACHE_FLUSH_BITS_SHIFT)
#define BRN31620_CACHE_FLUSH_BITS_MASK (BRN31620_CACHE_FLUSH_BITS_SIZE - 1)
+/* Cache line index in array */
#define BRN31620_CACHE_FLUSH_INDEX_BITS (BRN31620_CACHE_FLUSH_SHIFT - BRN31620_CACHE_FLUSH_BITS_SHIFT)
#define BRN31620_CACHE_FLUSH_INDEX_SIZE (1 << BRN31620_CACHE_FLUSH_INDEX_BITS)
typedef struct _MMU_PT_INFO_
{
-
+ /* note: may need a union here to accommodate a PT page address for local memory */
IMG_VOID *hPTPageOSMemHandle;
IMG_CPU_VIRTADDR PTPageCpuVAddr;
-
-
+ /* Map of reserved PTEs.
+ * Reserved PTEs are like "valid" PTEs in that they (and the DevVAddrs they represent)
+ * cannot be assigned to another allocation but their "reserved" status persists through
+ * any amount of mapping and unmapping, until the allocation is finally destroyed.
+ *
+ * Reserved and Valid are independent.
+ * When a PTE is first reserved, it will have Reserved=1 and Valid=0.
+ * When the PTE is actually mapped, it will have Reserved=1 and Valid=1.
+ * When the PTE is unmapped, it will have Reserved=1 and Valid=0.
+ * At this point, the PT will can not be destroyed because although there is
+ * not an active mapping on the PT, it is known a PTE is reserved for use.
+ *
+ * The above sequence of mapping and unmapping may repeat any number of times
+ * until the allocation is unmapped and destroyed which causes the PTE to have
+ * Valid=0 and Reserved=0.
+ */
+ /* Number of PTEs set up.
+ * i.e. have a valid SGX Phys Addr and the "VALID" PTE bit == 1
+ */
IMG_UINT32 ui32ValidPTECount;
} MMU_PT_INFO;
+#define MMU_CONTEXT_NAME_SIZE 50
struct _MMU_CONTEXT_
{
-
+ /* the device node */
PVRSRV_DEVICE_NODE *psDeviceNode;
-
+ /* Page Directory CPUVirt and DevPhys Addresses */
IMG_CPU_VIRTADDR pvPDCpuVAddr;
IMG_DEV_PHYADDR sPDDevPAddr;
IMG_VOID *hPDOSMemHandle;
-
+ /* information about dynamically allocated pagetables */
MMU_PT_INFO *apsPTInfoList[SGX_MAX_PD_ENTRIES];
PVRSRV_SGXDEV_INFO *psDevInfo;
#endif
#endif
+ IMG_UINT32 ui32PID;
+ IMG_CHAR szName[MMU_CONTEXT_NAME_SIZE];
+
#if defined (FIX_HW_BRN_31620)
IMG_UINT32 ui32PDChangeMask[BRN31620_CACHE_FLUSH_INDEX_SIZE];
IMG_UINT32 ui32PDCacheRangeRefCount[BRN31620_CACHE_FLUSH_SIZE];
struct _MMU_HEAP_
{
-
+ /* MMU context */
MMU_CONTEXT *psMMUContext;
-
-
-
+ /*
+ heap specific details:
+ */
+ /* the Base PD index for the heap */
IMG_UINT32 ui32PDBaseIndex;
-
+ /* number of pagetables in this heap */
IMG_UINT32 ui32PageTableCount;
-
+ /* total number of pagetable entries in this heap which may be mapped to data pages */
IMG_UINT32 ui32PTETotalUsable;
-
+ /* PD entry DP size control field */
IMG_UINT32 ui32PDEPageSizeCtrl;
-
-
-
+ /*
+ Data Page (DP) Details:
+ */
+ /* size in bytes of a data page */
IMG_UINT32 ui32DataPageSize;
-
+ /* bit width of the data page offset addressing field */
IMG_UINT32 ui32DataPageBitWidth;
-
+ /* bit mask of the data page offset addressing field */
IMG_UINT32 ui32DataPageMask;
-
-
-
+ /*
+ PageTable (PT) Details:
+ */
+ /* bit shift to base of PT addressing field */
IMG_UINT32 ui32PTShift;
-
+ /* bit width of the PT addressing field */
IMG_UINT32 ui32PTBitWidth;
-
+ /* bit mask of the PT addressing field */
IMG_UINT32 ui32PTMask;
-
+ /* size in bytes of a pagetable */
IMG_UINT32 ui32PTSize;
-
+ /* Allocated PT Entries per PT */
IMG_UINT32 ui32PTNumEntriesAllocated;
-
+ /* Usable PT Entries per PT (may be different to num allocated for 4MB data page) */
IMG_UINT32 ui32PTNumEntriesUsable;
-
-
-
+ /*
+ PageDirectory Details:
+ */
+ /* bit shift to base of PD addressing field */
IMG_UINT32 ui32PDShift;
-
+ /* bit width of the PD addressing field */
IMG_UINT32 ui32PDBitWidth;
-
+ /* bit mask of the PT addressing field */
IMG_UINT32 ui32PDMask;
-
-
+ /*
+ Arena Info:
+ */
RA_ARENA *psVMArena;
DEV_ARENA_DESCRIPTOR *psDevArena;
+
+ /* If we have sparse mappings then we can't do PT level sanity checks */
+ IMG_BOOL bHasSparseMappings;
#if defined(PDUMP)
PDUMP_MMU_ATTRIB sMMUAttrib;
#endif
#define DUMMY_DATA_PAGE_SIGNATURE 0xDEADBEEF
#endif
+/* local prototypes: */
static IMG_VOID
_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT);
IMG_SIZE_T uSize,
IMG_BOOL bForUnmap,
IMG_HANDLE hUniqueTag);
-#endif
+#endif /* #if defined(PDUMP) */
+/* This option tests page table memory, for use during device bring-up. */
#define PAGE_TEST 0
#if PAGE_TEST
static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr);
#endif
+/* This option dumps out the PT if an assert fails */
+#define PT_DUMP 1
+
+/* This option sanity checks page table PTE valid count matches active PTEs */
#define PT_DEBUG 0
-#if PT_DEBUG
+#if (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF)
static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
{
IMG_UINT32 *p = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
IMG_UINT32 i;
-
+ /* 1024 entries in a 4K page table */
for(i = 0; i < 1024; i += 8)
{
- PVR_DPF((PVR_DBG_WARNING,
+ PVR_DPF((PVR_DBG_ERROR,
"%08X %08X %08X %08X %08X %08X %08X %08X\n",
p[i + 0], p[i + 1], p[i + 2], p[i + 3],
p[i + 4], p[i + 5], p[i + 6], p[i + 7]));
}
}
+#else /* (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF) */
+static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+ PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+#endif /* (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF) */
+#if PT_DEBUG
static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
{
IMG_UINT32 *p = (IMG_UINT32*) psPTInfoList->PTPageCpuVAddr;
IMG_UINT32 i, ui32Count = 0;
-
+ /* 1024 entries in a 4K page table */
for(i = 0; i < 1024; i++)
if(p[i] & SGX_MMU_PTE_VALID)
ui32Count++;
if(psPTInfoList->ui32ValidPTECount != ui32Count)
{
- PVR_DPF((PVR_DBG_WARNING, "ui32ValidPTECount: %u ui32Count: %u\n",
+ PVR_DPF((PVR_DBG_ERROR, "ui32ValidPTECount: %u ui32Count: %u\n",
psPTInfoList->ui32ValidPTECount, ui32Count));
DumpPT(psPTInfoList);
BUG();
}
}
-#else
-static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+#else /* PT_DEBUG */
+static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
{
PVR_UNREFERENCED_PARAMETER(psPTInfoList);
}
+#endif /* PT_DEBUG */
-static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+/*
+ Debug functionality that allows us to make the CPU
+ mapping of pagetable memory readonly and only make
+ it read/write when we alter it. This allows us
+ to check that our memory isn't being overwritten
+*/
+#if defined(PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND)
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#else
+#include <generated/autoconf.h>
+#endif
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/highmem.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+static IMG_VOID MakeKernelPageReadWrite(IMG_PVOID ulCPUVAddr)
{
- PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ pte_t ptent;
+ IMG_UINT32 ui32CPUVAddr = (IMG_UINT32) ulCPUVAddr;
+
+ psPGD = pgd_offset_k(ui32CPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPUD = pud_offset(psPGD, ui32CPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPMD = pmd_offset(psPUD, ui32CPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ {
+ PVR_ASSERT(0);
+ }
+ psPTE = (pte_t *)pte_offset_kernel(psPMD, ui32CPUVAddr);
+
+ ptent = ptep_modify_prot_start(&init_mm, ui32CPUVAddr, psPTE);
+ ptent = pte_mkwrite(ptent);
+ ptep_modify_prot_commit(&init_mm, ui32CPUVAddr, psPTE, ptent);
+
+ flush_tlb_all();
+}
+
+static IMG_VOID MakeKernelPageReadOnly(IMG_PVOID ulCPUVAddr)
+{
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ pte_t ptent;
+ IMG_UINT32 ui32CPUVAddr = (IMG_UINT32) ulCPUVAddr;
+
+ OSWriteMemoryBarrier();
+
+ psPGD = pgd_offset_k(ui32CPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPUD = pud_offset(psPGD, ui32CPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPMD = pmd_offset(psPUD, ui32CPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPTE = (pte_t *)pte_offset_kernel(psPMD, ui32CPUVAddr);
+
+ ptent = ptep_modify_prot_start(&init_mm, ui32CPUVAddr, psPTE);
+ ptent = pte_wrprotect(ptent);
+ ptep_modify_prot_commit(&init_mm, ui32CPUVAddr, psPTE, ptent);
+
+ flush_tlb_all();
+
+}
+
+#else /* defined(PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND) */
+
+static INLINE IMG_VOID MakeKernelPageReadWrite(IMG_PVOID ulCPUVAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(ulCPUVAddr);
+}
+
+static INLINE IMG_VOID MakeKernelPageReadOnly(IMG_PVOID ulCPUVAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(ulCPUVAddr);
}
-#endif
+#endif /* defined(PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND) */
+
+/*___________________________________________________________________________
+
+ Information for SUPPORT_PDUMP_MULTI_PROCESS feature.
+
+ The client marked for pdumping will set the bPDumpActive flag in
+ the MMU Context (see MMU_Initialise).
+
+ Shared heap allocations should be persistent so all apps which
+ are pdumped will see the allocation. Persistent flag over-rides
+ the bPDumpActive flag (see pdump_common.c/DbgWrite function).
+
+ The idea is to dump PT,DP for shared heap allocations, but only
+ dump the PDE if the allocation is mapped into the kernel or active
+ client context. This ensures if a background app allocates on a
+ shared heap then all clients can access it in the pdump toolchain.
+
+
+
+ PD PT DP
+ +-+
+ | |---> +-+
+ +-+ | |---> +-+
+ +-+ + +
+ +-+
+
+ PD allocation/free: pdump flags are 0 (only need PD for active apps)
+ PT allocation/free: pdump flags are 0
+ unless PT is for a shared heap, in which case persistent is set
+ PD entries (MMU init/insert shared heap):
+ only pdump if PDE is on the active MMU context, flags are 0
+ PD entries (PT alloc):
+ pdump flags are 0 if kernel heap
+ pdump flags are 0 if shared heap and PDE is on active MMU context
+ otherwise ignore.
+ PT entries pdump flags are 0
+ unless PTE is for a shared heap, in which case persistent is set
+
+ NOTE: PDump common code:-
+ PDumpMallocPages and PDumpMemKM also set the persistent flag for
+ shared heap allocations.
+
+ ___________________________________________________________________________
+*/
+
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_IsHeapShared
+ PURPOSE: Is this heap shared?
+ PARAMETERS: In: pMMU_Heap
+ RETURNS: true if heap is shared
+******************************************************************************/
IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMUHeap)
{
switch(pMMUHeap->psDevArena->DevMemHeapType)
}
#ifdef SUPPORT_SGX_MMU_BYPASS
+/*!
+******************************************************************************
+ FUNCTION: EnableHostAccess
+
+ PURPOSE: Enables Host accesses to device memory, by passing the device
+ MMU address translation
+
+ PARAMETERS: In: psMMUContext
+ RETURNS: None
+******************************************************************************/
IMG_VOID
EnableHostAccess (MMU_CONTEXT *psMMUContext)
{
IMG_UINT32 ui32RegVal;
IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
-
-
-
+ /*
+ bypass the MMU for the host port requestor,
+ conserving bypass state of other requestors
+ */
ui32RegVal = OSReadHWReg(pvRegsBaseKM, EUR_CR_BIF_CTRL);
OSWriteHWReg(pvRegsBaseKM,
EUR_CR_BIF_CTRL,
ui32RegVal | EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
-
+ /* assume we're not wiping-out any other bits */
PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
}
+/*!
+******************************************************************************
+ FUNCTION: DisableHostAccess
+
+ PURPOSE: Disables Host accesses to device memory, by passing the device
+ MMU address translation
+
+ PARAMETERS: In: psMMUContext
+ RETURNS: None
+******************************************************************************/
IMG_VOID
DisableHostAccess (MMU_CONTEXT *psMMUContext)
{
IMG_UINT32 ui32RegVal;
IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
-
-
-
-
+ /*
+ disable MMU-bypass for the host port requestor,
+ conserving bypass state of other requestors
+ and flushing all caches/tlbs
+ */
OSWriteHWReg(pvRegsBaseKM,
EUR_CR_BIF_CTRL,
ui32RegVal & ~EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
-
+ /* assume we're not wiping-out any other bits */
PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, 0);
}
#endif
#if defined(SGX_FEATURE_SYSTEM_CACHE)
+/*!
+******************************************************************************
+ FUNCTION: MMU_InvalidateSystemLevelCache
+
+ PURPOSE: Invalidates the System Level Cache to purge stale PDEs and PTEs
+
+ PARAMETERS: In: psDevInfo
+ RETURNS: None
+
+******************************************************************************/
static IMG_VOID MMU_InvalidateSystemLevelCache(PVRSRV_SGXDEV_INFO *psDevInfo)
{
#if defined(SGX_FEATURE_MP)
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
#else
-
+ /* The MMU always bypasses the SLC */
PVR_UNREFERENCED_PARAMETER(psDevInfo);
- #endif
+ #endif /* SGX_FEATURE_MP */
}
-#endif
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_InvalidateDirectoryCache
+ PURPOSE: Invalidates the page directory cache + page table cache + requestor TLBs
+
+ PARAMETERS: In: psDevInfo
+ RETURNS: None
+
+******************************************************************************/
IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo)
{
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
#if defined(SGX_FEATURE_SYSTEM_CACHE)
MMU_InvalidateSystemLevelCache(psDevInfo);
- #endif
+ #endif /* SGX_FEATURE_SYSTEM_CACHE */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_InvalidatePageTableCache
+
+ PURPOSE: Invalidates the page table cache + requestor TLBs
+
+ PARAMETERS: In: psDevInfo
+ RETURNS: None
+
+******************************************************************************/
static IMG_VOID MMU_InvalidatePageTableCache(PVRSRV_SGXDEV_INFO *psDevInfo)
{
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PT;
#if defined(SGX_FEATURE_SYSTEM_CACHE)
MMU_InvalidateSystemLevelCache(psDevInfo);
- #endif
+ #endif /* SGX_FEATURE_SYSTEM_CACHE */
}
#if defined(FIX_HW_BRN_31620)
+/*!
+******************************************************************************
+ FUNCTION: BRN31620InvalidatePageTableEntry
+
+ PURPOSE: Frees page tables in PDE cache line chunks re-wiring the
+ dummy page when required
+
+ PARAMETERS: In: psMMUContext, ui32PDIndex, ui32PTIndex
+ RETURNS: None
+
+******************************************************************************/
static IMG_VOID BRN31620InvalidatePageTableEntry(MMU_CONTEXT *psMMUContext, IMG_UINT32 ui32PDIndex, IMG_UINT32 ui32PTIndex, IMG_UINT32 *pui32PTE)
{
PVRSRV_SGXDEV_INFO *psDevInfo = psMMUContext->psDevInfo;
-
+ /*
+ * Note: We can't tell at this stage if this PT will be freed before
+ * the end of the function so we always wire up the dummy page to
+ * to the PT.
+ */
if (((ui32PDIndex % (BRN31620_PDE_CACHE_FILL_SIZE/BRN31620_PT_ADDRESS_RANGE_SIZE)) == BRN31620_DUMMY_PDE_INDEX)
&& (ui32PTIndex == BRN31620_DUMMY_PTE_INDEX))
{
}
}
+/*!
+******************************************************************************
+ FUNCTION: BRN31620FreePageTable
+
+ PURPOSE: Frees page tables in PDE cache line chunks re-wiring the
+ dummy page when required
+
+ PARAMETERS: In: psMMUContext, ui32PDIndex
+ RETURNS: IMG_TRUE if we freed any PT's
+
+******************************************************************************/
static IMG_BOOL BRN31620FreePageTable(MMU_HEAP *psMMUHeap, IMG_UINT32 ui32PDIndex)
{
MMU_CONTEXT *psMMUContext = psMMUHeap->psMMUContext;
PVR_ASSERT(psMMUHeap != IMG_NULL);
-
+ /*
+ * Clear the PT info for this PD index so even if we don't
+ * free the memory here apsPTInfoList[PDIndex] will trigger
+ * an "allocation" in _DeferredAllocPagetables which
+ * bumps up the refcount.
+ */
PVR_ASSERT(psMMUContext->apsPTInfoListSave[ui32PDIndex] == IMG_NULL);
psMMUContext->apsPTInfoListSave[ui32PDIndex] = psMMUContext->apsPTInfoList[ui32PDIndex];
psMMUContext->apsPTInfoList[ui32PDIndex] = IMG_NULL;
-
+ /* Check if this was the last PT in the cache line */
if (--psMMUContext->ui32PDCacheRangeRefCount[ui32PDCacheLine] == 0)
{
IMG_UINT32 i;
IMG_UINT32 ui32PDIndexEnd = ui32PDIndexStart + BRN31620_PDES_PER_CACHE_LINE_SIZE;
IMG_UINT32 ui32PDBitMaskIndex, ui32PDBitMaskShift;
-
+ /* Free all PT's in cache line */
for (i=ui32PDIndexStart;i<ui32PDIndexEnd;i++)
{
-
+ /* This PT is _really_ being freed now */
psMMUContext->apsPTInfoList[i] = psMMUContext->apsPTInfoListSave[i];
psMMUContext->apsPTInfoListSave[i] = IMG_NULL;
_DeferredFreePageTable(psMMUHeap, i - psMMUHeap->ui32PDBaseIndex, IMG_TRUE);
ui32PDBitMaskIndex = ui32PDCacheLine >> BRN31620_CACHE_FLUSH_BITS_SHIFT;
ui32PDBitMaskShift = ui32PDCacheLine & BRN31620_CACHE_FLUSH_BITS_MASK;
-
+ /* Check if this is a shared heap */
if (MMU_IsHeapShared(psMMUHeap))
{
-
+ /* Mark the remove of the Page Table from all memory contexts */
MMU_CONTEXT *psMMUContextWalker = (MMU_CONTEXT*) psMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
while(psMMUContextWalker)
{
psMMUContextWalker->ui32PDChangeMask[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
-
+ /*
+ * We've just cleared a cache line's worth of PDE's so we need
+ * to wire up the dummy PT
+ */
+ MakeKernelPageReadWrite(psMMUContextWalker->pvPDCpuVAddr);
pui32Tmp = (IMG_UINT32 *) psMMUContextWalker->pvPDCpuVAddr;
pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_DUMMY_PAGE
| SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(psMMUContextWalker->pvPDCpuVAddr);
PDUMPCOMMENT("BRN31620 Re-wire dummy PT due to releasing PT allocation block");
PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContextWalker->hPDOSMemHandle, (IMG_VOID*)&pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
{
psMMUContext->ui32PDChangeMask[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
-
+ /*
+ * We've just cleared a cache line's worth of PDE's so we need
+ * to wire up the dummy PT
+ */
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
pui32Tmp = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr;
pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_DUMMY_PAGE
| SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
PDUMPCOMMENT("BRN31620 Re-wire dummy PT due to releasing PT allocation block");
PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
-
+ /* We've freed a cachline's worth of PDE's so trigger a PD cache flush */
bFreePTs = IMG_TRUE;
}
}
#endif
+/*!
+******************************************************************************
+ FUNCTION: _AllocPageTableMemory
+
+ PURPOSE: Allocate physical memory for a page table
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ In: psPTInfoList - PT info
+ Out: psDevPAddr - device physical address for new PT
+ RETURNS: IMG_TRUE - Success
+ IMG_FALSE - Failed
+******************************************************************************/
static IMG_BOOL
_AllocPageTableMemory (MMU_HEAP *pMMUHeap,
MMU_PT_INFO *psPTInfoList,
IMG_DEV_PHYADDR sDevPAddr;
IMG_CPU_PHYADDR sCpuPAddr;
-
-
-
+ /*
+ depending on the specific system, pagetables are allocated from system memory
+ or device local memory. For now, just look for at least a valid local heap/arena
+ */
if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
{
-
+ //FIXME: replace with an RA, this allocator only handles 4k allocs
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- pMMUHeap->ui32PTSize,
- SGX_MMU_PAGE_SIZE,
- (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr,
- &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK)
+ pMMUHeap->ui32PTSize,
+ SGX_MMU_PAGE_SIZE,//FIXME: assume 4K page size for now (wastes memory for smaller pagetables
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr,
+ &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to OSAllocPages failed"));
return IMG_FALSE;
}
-
+ /*
+ Force the page to read only, we will make it read/write as
+ and when we need to
+ */
+ MakeKernelPageReadOnly(psPTInfoList->PTPageCpuVAddr);
+
+ /* translate address to device physical */
if(psPTInfoList->PTPageCpuVAddr)
{
sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle,
}
else
{
-
+ /* This isn't used in all cases since not all ports currently support
+ * OSMemHandleToCpuPAddr() */
sCpuPAddr = OSMemHandleToCpuPAddr(psPTInfoList->hPTPageOSMemHandle, 0);
}
{
IMG_SYS_PHYADDR sSysPAddr;
-
-
-
-
+ /*
+ just allocate from the first local memory arena
+ (unlikely to be more than one local mem area(?))
+ */
+ //FIXME: just allocate a 4K page for each PT for now
if(RA_Alloc(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena,
- SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,//pMMUHeap->ui32PTSize,
IMG_NULL,
IMG_NULL,
0,
- SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,//pMMUHeap->ui32PTSize,
+ 0,
+ IMG_NULL,
0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
return IMG_FALSE;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
-
+ /* note: actual ammount is pMMUHeap->ui32PTSize but must be a multiple of 4k pages */
psPTInfoList->PTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
return IMG_FALSE;
}
-
+ /* translate address to device physical */
sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
#if PAGE_TEST
#endif
}
+ MakeKernelPageReadWrite(psPTInfoList->PTPageCpuVAddr);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
{
IMG_UINT32 *pui32Tmp;
IMG_UINT32 i;
pui32Tmp = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
-
+ /* point the new PT entries to the dummy data page */
for(i=0; i<pMMUHeap->ui32PTNumEntriesUsable; i++)
{
pui32Tmp[i] = (pMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
}
-
+ /* zero the remaining allocated entries, if any */
for(; i<pMMUHeap->ui32PTNumEntriesAllocated; i++)
{
pui32Tmp[i] = 0;
}
}
#else
-
+ /* Zero the page table. */
OSMemSet(psPTInfoList->PTPageCpuVAddr, 0, pMMUHeap->ui32PTSize);
#endif
+ MakeKernelPageReadOnly(psPTInfoList->PTPageCpuVAddr);
#if defined(PDUMP)
{
IMG_UINT32 ui32Flags = 0;
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* make sure shared heap PT allocs are always pdumped */
ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
#endif
-
+ /* pdump the PT malloc */
PDUMPMALLOCPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, psPTInfoList->hPTPageOSMemHandle, 0, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG);
-
+ /* pdump the PT Pages */
PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfoList->hPTPageOSMemHandle, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
#endif
-
-
+
+ /* return the DevPAddr */
*psDevPAddr = sDevPAddr;
return IMG_TRUE;
}
+/*!
+******************************************************************************
+ FUNCTION: _FreePageTableMemory
+
+ PURPOSE: Free physical memory for a page table
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ In: psPTInfoList - PT info to free
+ RETURNS: NONE
+******************************************************************************/
static IMG_VOID
_FreePageTableMemory (MMU_HEAP *pMMUHeap, MMU_PT_INFO *psPTInfoList)
{
-
-
-
-
+ /*
+ free the PT page:
+ depending on the specific system, pagetables are allocated from system memory
+ or device local memory. For now, just look for at least a valid local heap/arena
+ */
if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
{
-
+ /* Force the page to read write before we free it*/
+ MakeKernelPageReadWrite(psPTInfoList->PTPageCpuVAddr);
+
+ //FIXME: replace with an RA, this allocator only handles 4k allocs
OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
pMMUHeap->ui32PTSize,
psPTInfoList->PTPageCpuVAddr,
IMG_SYS_PHYADDR sSysPAddr;
IMG_CPU_PHYADDR sCpuPAddr;
-
+ /* derive the system physical address */
sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle,
psPTInfoList->PTPageCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr (sCpuPAddr);
-
-
+ /* unmap the CPU mapping */
+ /* note: actual ammount is pMMUHeap->ui32PTSize but must be a multiple of 4k pages */
OSUnMapPhysToLin(psPTInfoList->PTPageCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psPTInfoList->hPTPageOSMemHandle);
-
-
-
+ /*
+ just free from the first local memory arena
+ (unlikely to be more than one local mem area(?))
+ */
RA_Free (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
}
}
+/*!
+******************************************************************************
+ FUNCTION: _DeferredFreePageTable
+
+ PURPOSE: Free one page table associated with an MMU.
+
+ PARAMETERS: In: pMMUHeap - the mmu heap
+ In: ui32PTIndex - index of the page table to free relative
+ to the base of heap.
+ RETURNS: None
+******************************************************************************/
static IMG_VOID
_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT)
{
SysAcquireData(&psSysData);
-
+ /* find the index/offset in PD entries */
ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* set the base PT info */
ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
{
if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount > 0)
{
DumpPT(ppsPTInfoList[ui32PTIndex]);
-
+ /* Fall-through, will fail assert */
}
#endif
-
+ /* Assert that all mappings have gone */
PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == IMG_NULL || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount == 0);
}
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
#endif
-
+ /* pdump the PT free */
PDUMPCOMMENT("Free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr)
{
case DEVICE_MEMORY_HEAP_SHARED :
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
{
-
+ /* Remove Page Table from all memory contexts */
MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
while(psMMUContext)
{
-
+ /* get the PD CPUVAddr base and advance to the first entry */
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
pui32PDEntry += ui32PDIndex;
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* point the PD entry to the dummy PT */
pui32PDEntry[ui32PTIndex] = (psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_VALID;
#else
-
+ /* free the entry */
if(bOSFreePT)
{
pui32PDEntry[ui32PTIndex] = 0;
}
#endif
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
#if defined(PDUMP)
-
+ /* pdump the PD Page modifications */
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
if(psMMUContext->bPDumpActive)
#endif
PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
#endif
-
+ /* advance to next context */
psMMUContext = psMMUContext->psNext;
}
break;
case DEVICE_MEMORY_HEAP_PERCONTEXT :
case DEVICE_MEMORY_HEAP_KERNEL :
{
-
+ MakeKernelPageReadWrite(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+ /* Remove Page Table from this memory context only */
pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
pui32PDEntry += ui32PDIndex;
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* point the PD entry to the dummy PT */
pui32PDEntry[ui32PTIndex] = (pMMUHeap->psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_VALID;
#else
-
+ /* free the entry */
if(bOSFreePT)
{
pui32PDEntry[ui32PTIndex] = 0;
}
#endif
+ MakeKernelPageReadOnly(pMMUHeap->psMMUContext->pvPDCpuVAddr);
-
+ /* pdump the PD Page modifications */
PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
break;
}
}
}
-
+ /* clear the PT entries in each PT page */
if(ppsPTInfoList[ui32PTIndex] != IMG_NULL)
{
if(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != IMG_NULL)
{
IMG_PUINT32 pui32Tmp;
+ MakeKernelPageReadWrite(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr);
pui32Tmp = (IMG_UINT32*)ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr;
-
+ /* clear the entries */
for(i=0;
(i<pMMUHeap->ui32PTETotalUsable) && (i<pMMUHeap->ui32PTNumEntriesUsable);
i++)
{
-
+ /* over-allocated PT entries for 4MB data page case should never be non-zero */
pui32Tmp[i] = 0;
}
+ MakeKernelPageReadOnly(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr);
-
-
+ /*
+ free the pagetable memory
+ */
if(bOSFreePT)
{
_FreePageTableMemory(pMMUHeap, ppsPTInfoList[ui32PTIndex]);
}
-
-
-
+ /*
+ decrement the PT Entry Count by the number
+ of entries we've cleared in this pass
+ */
pMMUHeap->ui32PTETotalUsable -= i;
}
else
{
-
+ /* decrement the PT Entry Count by a page's worth of entries */
pMMUHeap->ui32PTETotalUsable -= pMMUHeap->ui32PTNumEntriesUsable;
}
if(bOSFreePT)
{
-
+ /* free the pt info */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(MMU_PT_INFO),
ppsPTInfoList[ui32PTIndex],
}
else
{
-
+ /* decrement the PT Entry Count by a page's worth of usable entries */
pMMUHeap->ui32PTETotalUsable -= pMMUHeap->ui32PTNumEntriesUsable;
}
PDUMPCOMMENT("Finished free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
}
+/*!
+******************************************************************************
+ FUNCTION: _DeferredFreePageTables
+
+ PURPOSE: Free the page tables associated with an MMU.
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ RETURNS: None
+******************************************************************************/
static IMG_VOID
_DeferredFreePageTables (MMU_HEAP *pMMUHeap)
{
{
if (psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
{
-
+ /*
+ * We have to do this to setup the dummy page as
+ * not all heaps are PD cache size or aligned
+ */
for (j=0;j<SGX_MMU_PT_SIZE;j++)
{
pui32Tmp = (IMG_UINT32 *) psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
BRN31620InvalidatePageTableEntry(psMMUContext, ui32PDIndex, j, &pui32Tmp[j]);
}
}
-
+ /* Free the PT and NULL's out the PTInfo */
if (BRN31620FreePageTable(pMMUHeap, ui32PDIndex) == IMG_TRUE)
{
bInvalidateDirectoryCache = IMG_TRUE;
}
}
-
+ /*
+ * Due to freeing PT's in chunks we might need to flush the PT cache
+ * rather then the directory cache
+ */
if (bInvalidateDirectoryCache)
{
MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
}
+/*!
+******************************************************************************
+ FUNCTION: _DeferredAllocPagetables
+
+ PURPOSE: allocates page tables at time of allocation
+
+ PARAMETERS: In: pMMUHeap - the mmu heap
+ DevVAddr - devVAddr of allocation
+ ui32Size - size of allocation
+ RETURNS: IMG_TRUE - Success
+ IMG_FALSE - Failed
+******************************************************************************/
static IMG_BOOL
_DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
{
IMG_UINT32 ui32ModifiedCachelines[BRN31620_CACHE_FLUSH_INDEX_SIZE];
#endif
-
+ /* Check device linear address */
#if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32
PVR_ASSERT(DevVAddr.uiAddr < (1<<SGX_FEATURE_ADDRESS_SPACE_SIZE));
#endif
-
+ /* get the sysdata */
SysAcquireData(&psSysData);
-
+ /* find the index/offset in PD entries */
ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
-
+ /* how many PDs does the allocation occupy? */
+ /* first check for overflows */
if((UINT32_MAX_VALUE - DevVAddr.uiAddr)
< (ui32Size + pMMUHeap->ui32DataPageMask + pMMUHeap->ui32PTMask))
{
-
+ /* detected overflow, clamp to highest address */
sHighDevVAddr.uiAddr = UINT32_MAX_VALUE;
}
else
ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* Fix allocation of last 4MB */
if (ui32PageTableCount == 0)
ui32PageTableCount = 1024;
ui32ModifiedCachelines[i] = 0;
}
-
-
-
+ /*****************************************************************/
+ /* Save off requested data and round allocation to PD cache line */
+ /*****************************************************************/
sDevVAddrRequestStart = DevVAddr;
ui32PDRequestStart = ui32PDIndex;
sDevVAddrRequestEnd = sHighDevVAddr;
ui32PDRequestEnd = ui32PageTableCount - 1;
-
+ /* Round allocations down to the PD cacheline */
DevVAddr.uiAddr = DevVAddr.uiAddr & (~BRN31620_PDE_CACHE_FILL_MASK);
-
+ /* Round the end address of the PD allocation to cacheline */
sHighDevVAddr.uiAddr = ((sHighDevVAddr.uiAddr + (BRN31620_PDE_CACHE_FILL_SIZE - 1)) & (~BRN31620_PDE_CACHE_FILL_MASK));
ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* Fix allocation of last 4MB */
if (ui32PageTableCount == 0)
ui32PageTableCount = 1024;
#endif
ui32PageTableCount -= ui32PDIndex;
-
+ /* get the PD CPUVAddr base and advance to the first entry */
pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
pui32PDEntry += ui32PDIndex;
-
+ /* and advance to the first PT info list */
ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
#if defined(PDUMP)
{
IMG_UINT32 ui32Flags = 0;
-
+ /* pdump the PD Page modifications */
if( MMU_IsHeapShared(pMMUHeap) )
{
ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
PDUMPCOMMENTWITHFLAGS(ui32Flags, "Page directory mods (page count == %08X)", ui32PageTableCount);
}
#endif
-
+ /* walk the psPTInfoList to see what needs allocating: */
for(i=0; i<ui32PageTableCount; i++)
{
if(ppsPTInfoList[i] == IMG_NULL)
{
#if defined(FIX_HW_BRN_31620)
-
+ /* Check if we have a saved PT (i.e. this PDE cache line is still live) */
if (pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i])
{
-
+ /* Only make this PTInfo "live" if it's requested */
if (((ui32PDIndex + i) >= ui32PDRequestStart) && ((ui32PDIndex + i) <= ui32PDRequestEnd))
{
IMG_UINT32 ui32PDCacheLine = (ui32PDIndex + i) >> BRN31620_PDES_PER_CACHE_LINE_SHIFT;
#endif
}
#if defined(FIX_HW_BRN_31620)
-
+ /* Only try to allocate if ppsPTInfoList[i] is valid */
if (ppsPTInfoList[i])
{
#endif
IMG_UINT32 j;
#else
#if !defined(FIX_HW_BRN_31620)
-
+ /* no page table has been allocated so allocate one */
PVR_ASSERT(pui32PDEntry[i] == 0);
#endif
#endif
}
#if defined(FIX_HW_BRN_31620)
bFlushSystemCache = IMG_TRUE;
-
+ /* Bump up the page table count if required */
{
IMG_UINT32 ui32PD;
IMG_UINT32 ui32PDCacheLine;
ui32PDBitMaskShift = ui32PDCacheLine & BRN31620_CACHE_FLUSH_BITS_MASK;
ui32ModifiedCachelines[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
-
+ /* Add 1 to ui32PD as we want the count, not a range */
if ((pMMUHeap->ui32PDBaseIndex + pMMUHeap->ui32PageTableCount) < (ui32PD + 1))
{
pMMUHeap->ui32PageTableCount = (ui32PD + 1) - pMMUHeap->ui32PDBaseIndex;
case DEVICE_MEMORY_HEAP_SHARED :
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
{
-
+ /* insert Page Table into all memory contexts */
MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
while(psMMUContext)
{
-
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+ /* get the PD CPUVAddr base and advance to the first entry */
pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
pui32PDEntry += ui32PDIndex;
-
+ /* insert the page, specify the data page size and make the pde valid */
pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| pMMUHeap->ui32PDEPageSizeCtrl
| SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
#if defined(PDUMP)
-
+ /* pdump the PD Page modifications */
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
if(psMMUContext->bPDumpActive)
#endif
{
-
+ //PDUMPCOMMENT("_DeferredAllocPTs: Dumping shared PDEs on context %d (%s)", psMMUContext->ui32PDumpMMUContextID, (psMMUContext->bPDumpActive) ? "active" : "");
PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
- #endif
-
+ #endif /* PDUMP */
+ /* advance to next context */
psMMUContext = psMMUContext->psNext;
}
#if defined(FIX_HW_BRN_31620)
case DEVICE_MEMORY_HEAP_PERCONTEXT :
case DEVICE_MEMORY_HEAP_KERNEL :
{
-
+ MakeKernelPageReadWrite(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+ /* insert Page Table into only this memory context */
pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| pMMUHeap->ui32PDEPageSizeCtrl
| SGX_MMU_PDE_VALID;
-
-
-
+ MakeKernelPageReadOnly(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+ /* pdump the PD Page modifications */
+ //PDUMPCOMMENT("_DeferredAllocPTs: Dumping kernel PDEs on context %d (%s)", pMMUHeap->psMMUContext->ui32PDumpMMUContextID, (pMMUHeap->psMMUContext->bPDumpActive) ? "active" : "");
PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
break;
}
}
#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
-
-
-
-
+ /* This is actually not to do with multiple mem contexts, but to do with the directory cache.
+ In the 1 context implementation of the MMU, the directory "cache" is actually a copy of the
+ page directory memory, and requires updating whenever the page directory changes, even if there
+ was no previous value in a particular entry
+ */
MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
#endif
#if defined(FIX_HW_BRN_31620)
-
+ /* If this PT is not in the requested range then save it and null out the main PTInfo */
if (((ui32PDIndex + i) < ui32PDRequestStart) || ((ui32PDIndex + i) > ui32PDRequestEnd))
{
pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i] = ppsPTInfoList[i];
else
{
#if !defined(FIX_HW_BRN_31620)
-
+ /* already have an allocated PT */
PVR_ASSERT(pui32PDEntry[i] != 0);
#endif
}
#if defined(SGX_FEATURE_SYSTEM_CACHE)
#if defined(FIX_HW_BRN_31620)
-
+ /* This function might not allocate any new PT's so check before flushing */
if (bFlushSystemCache)
{
#endif
MMU_InvalidateSystemLevelCache(pMMUHeap->psMMUContext->psDevInfo);
- #endif
+ #endif /* SGX_FEATURE_SYSTEM_CACHE */
#if defined(FIX_HW_BRN_31620)
}
-
+ /* Handle the last 4MB roll over */
sHighDevVAddr.uiAddr = sHighDevVAddr.uiAddr - 1;
-
+ /* Update our PD flush mask if required */
if (bFlushSystemCache)
{
MMU_CONTEXT *psMMUContext;
psMMUContext->ui32PDChangeMask[i] |= ui32ModifiedCachelines[i];
}
-
+ /* advance to next context */
psMMUContext = psMMUContext->psNext;
}
}
}
}
-
+ /*
+ * Always hook up the dummy page when we allocate a new range of PTs.
+ * It might be this is overwritten before the SGX access the dummy page
+ * but we don't care, it's a lot simpler to add this logic here.
+ */
psMMUContext = pMMUHeap->psMMUContext;
for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
{
ui32PDIndex = (((i * BRN31620_CACHE_FLUSH_BITS_SIZE) + j) * BRN31620_PDES_PER_CACHE_LINE_SIZE) + BRN31620_DUMMY_PDE_INDEX;
-
+ /* The PT for the dummy page might not be "live". If not get it from the saved pointer */
if (psMMUContext->apsPTInfoList[ui32PDIndex])
{
psTempPTInfo = psMMUContext->apsPTInfoList[ui32PDIndex];
PVR_ASSERT(psTempPTInfo != IMG_NULL);
+ MakeKernelPageReadWrite(psTempPTInfo->PTPageCpuVAddr);
pui32Tmp = (IMG_UINT32 *) psTempPTInfo->PTPageCpuVAddr;
PVR_ASSERT(pui32Tmp != IMG_NULL);
pui32Tmp[BRN31620_DUMMY_PTE_INDEX] = (psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_DUMMY_PAGE
| SGX_MMU_PTE_READONLY
| SGX_MMU_PTE_VALID;
-
+ MakeKernelPageReadOnly(psTempPTInfo->PTPageCpuVAddr);
PDUMPCOMMENT("BRN31620 Dump PTE for dummy page after wireing up new PT");
PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psTempPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32Tmp[BRN31620_DUMMY_PTE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
#if defined(PDUMP)
+/*!
+ * FUNCTION: MMU_GetPDumpContextID
+ *
+ * RETURNS: pdump MMU context ID
+ */
IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext)
{
BM_CONTEXT *pBMContext = hDevMemContext;
PVR_ASSERT(pBMContext);
-
+ /* PRQA S 0505 1 */ /* PVR_ASSERT should catch NULL ptr */
return pBMContext->psMMUContext->ui32PDumpMMUContextID;
}
+/*!
+ * FUNCTION: MMU_SetPDumpAttribs
+ *
+ * PURPOSE: Called from MMU_Initialise and MMU_Create.
+ * Sets up device-specific attributes for pdumping.
+ * FIXME: breaks variable size PTs. Really need separate per context
+ * and per heap attribs.
+ *
+ * INPUT: psDeviceNode - used to access deviceID
+ * INPUT: ui32DataPageMask - data page mask
+ * INPUT: ui32PTSize - PT size
+ *
+ * OUTPUT: psMMUAttrib - pdump MMU attributes
+ *
+ * RETURNS: none
+ */
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+# error "FIXME: breaks variable size pagetables"
+#endif
static IMG_VOID MMU_SetPDumpAttribs(PDUMP_MMU_ATTRIB *psMMUAttrib,
PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_UINT32 ui32DataPageMask,
IMG_UINT32 ui32PTSize)
{
-
+ /* Sets up device ID, contains pdump memspace name */
psMMUAttrib->sDevId = psDeviceNode->sDevId;
psMMUAttrib->pszPDRegRegion = IMG_NULL;
psMMUAttrib->ui32PDEMask = SGX_MMU_PDE_ADDR_MASK;
psMMUAttrib->ui32PDEAlignShift = SGX_MMU_PDE_ADDR_ALIGNSHIFT;
}
-#endif
+#endif /* PDUMP */
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_Initialise
+ PURPOSE: Called from BM_CreateContext.
+ Allocates the top level Page Directory 4k Page for the new context.
+
+ PARAMETERS: None
+ RETURNS: PVRSRV_ERROR
+******************************************************************************/
PVRSRV_ERROR
MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr)
{
SysAcquireData(&psSysData);
#if defined(PDUMP)
-
-
+ /* Note: these attribs are on the stack, used only to pdump the MMU context
+ * creation. */
MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
SGX_MMU_PAGE_MASK,
SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
}
OSMemSet (psMMUContext, 0, sizeof(MMU_CONTEXT));
-
+ /* stick the devinfo in the context for subsequent use */
psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
psMMUContext->psDevInfo = psDevInfo;
-
+ /* record device node for subsequent use */
psMMUContext->psDeviceNode = psDeviceNode;
-
+ /* allocate 4k page directory page for the new context */
if(psDeviceNode->psLocalDevMemArena == IMG_NULL)
{
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- &pvPDCpuVAddr,
- &hPDOSMemHandle) != PVRSRV_OK)
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ &pvPDCpuVAddr,
+ &hPDOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
}
else
{
-
+ /* This is not used in all cases, since not all ports currently
+ * support OSMemHandleToCpuPAddr */
sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0);
}
sPDDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
#endif
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* Allocate dummy PT and Data pages for the first context to be created */
if(!psDevInfo->pvMMUContextList)
{
-
+ /* Dummy PT page */
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- &psDevInfo->pvDummyPTPageCpuVAddr,
- &psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK)
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ &psDevInfo->pvDummyPTPageCpuVAddr,
+ &psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
}
else
{
-
+ /* This is not used in all cases, since not all ports currently
+ * support OSMemHandleToCpuPAddr */
sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyPTPageOSMemHandle, 0);
}
psDevInfo->sDummyPTDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
-
+ /* Dummy Data page */
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- &psDevInfo->pvDummyDataPageCpuVAddr,
- &psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK)
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ &psDevInfo->pvDummyDataPageCpuVAddr,
+ &psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
}
psDevInfo->sDummyDataDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
}
-#endif
+#endif /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
#if defined(FIX_HW_BRN_31620)
-
+ /* Allocate dummy Data pages for the first context to be created */
if(!psDevInfo->pvMMUContextList)
{
IMG_UINT32 j;
-
+ /* Allocate dummy page */
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- &psDevInfo->pvBRN31620DummyPageCpuVAddr,
- &psDevInfo->hBRN31620DummyPageOSMemHandle) != PVRSRV_OK)
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ &psDevInfo->pvBRN31620DummyPageCpuVAddr,
+ &psDevInfo->hBRN31620DummyPageOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
}
-
+ /* Get a physical address */
if(psDevInfo->pvBRN31620DummyPageCpuVAddr)
{
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPageOSMemHandle,
psDevInfo->sBRN31620DummyPageDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, 0, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
-
+ /* Allocate dummy PT */
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- &psDevInfo->pvBRN31620DummyPTCpuVAddr,
- &psDevInfo->hBRN31620DummyPTOSMemHandle) != PVRSRV_OK)
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ &psDevInfo->pvBRN31620DummyPTCpuVAddr,
+ &psDevInfo->hBRN31620DummyPTOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
}
-
+ /* Get a physical address */
if(psDevInfo->pvBRN31620DummyPTCpuVAddr)
{
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPTOSMemHandle,
{
IMG_SYS_PHYADDR sSysPAddr;
-
+ /* allocate from the device's local memory arena */
if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
SGX_MMU_PAGE_SIZE,
IMG_NULL,
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
pvPDCpuVAddr = OSMapPhysToLin(sCpuPAddr,
#endif
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* Allocate dummy PT and Data pages for the first context to be created */
if(!psDevInfo->pvMMUContextList)
{
-
+ /* Dummy PT page */
if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
SGX_MMU_PAGE_SIZE,
IMG_NULL,
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
psDevInfo->sDummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
psDevInfo->pvDummyPTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
}
-
+ /* Dummy Data page */
if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
SGX_MMU_PAGE_SIZE,
IMG_NULL,
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
psDevInfo->sDummyDataDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
psDevInfo->pvDummyDataPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
}
}
-#endif
+#endif /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
#if defined(FIX_HW_BRN_31620)
-
+ /* Allocate dummy PT and Data pages for the first context to be created */
if(!psDevInfo->pvMMUContextList)
{
IMG_UINT32 j;
-
+ /* Allocate dummy page */
if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
SGX_MMU_PAGE_SIZE,
IMG_NULL,
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
psDevInfo->sBRN31620DummyPageDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
psDevInfo->pvBRN31620DummyPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
}
+ MakeKernelPageReadWrite(psDevInfo->pvBRN31620DummyPageCpuVAddr);
pui32Tmp = (IMG_UINT32 *)psDevInfo->pvBRN31620DummyPageCpuVAddr;
for(j=0; j<(SGX_MMU_PAGE_SIZE/4); j++)
{
pui32Tmp[j] = BRN31620_DUMMY_PAGE_SIGNATURE;
}
+ MakeKernelPageReadOnly(psDevInfo->pvBRN31620DummyPageCpuVAddr);
PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, 0, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
-
+ /* Allocate dummy PT */
if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
SGX_MMU_PAGE_SIZE,
IMG_NULL,
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
psDevInfo->sBRN31620DummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
psDevInfo->pvBRN31620DummyPTCpuVAddr = OSMapPhysToLin(sCpuPAddr,
OSMemSet(psDevInfo->pvBRN31620DummyPTCpuVAddr,0,SGX_MMU_PAGE_SIZE);
PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, 0, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
}
-#endif
+#endif /* #if defined(FIX_HW_BRN_31620) */
}
#if defined(FIX_HW_BRN_31620)
if (!psDevInfo->pvMMUContextList)
{
-
+ /* Save the kernel MMU context which is always the 1st to be created */
psDevInfo->hKernelMMUContext = psMMUContext;
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: saving kernel mmu context: %p", psMMUContext));
}
#if defined(PDUMP)
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* Find out if this context is for the active pdump client.
+ * If it is, need to ensure PD entries are pdumped whenever another
+ * process allocates from a shared heap. */
{
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc == IMG_NULL)
{
-
+ /* changes to the kernel context PD/PTs should be pdumped */
psMMUContext->bPDumpActive = IMG_TRUE;
}
else
psMMUContext->bPDumpActive = psPerProc->bPDumpActive;
}
}
-#endif
-
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
+ /* pdump the PD malloc */
#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
PDUMPCOMMENT("Alloc page directory for new MMU context (PDDevPAddr == 0x%08x)",
sPDDevPAddr.uiAddr);
sPDDevPAddr.uiHighAddr, sPDDevPAddr.uiAddr);
#endif
PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDOSMemHandle, 0, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
-#endif
+#endif /* PDUMP */
#ifdef SUPPORT_SGX_MMU_BYPASS
EnableHostAccess(psMMUContext);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ MakeKernelPageReadWrite(pvPDCpuVAddr);
+ /* wire-up the new PD to the dummy PT */
for(i=0; i<SGX_MMU_PD_SIZE; i++)
{
pui32Tmp[i] = (psDevInfo->sDummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_VALID;
}
+ MakeKernelPageReadOnly(pvPDCpuVAddr);
if(!psDevInfo->pvMMUContextList)
{
-
-
-
+ /*
+ if we've just allocated the dummy pages
+ wire up the dummy PT to the dummy data page
+ */
+ MakeKernelPageReadWrite(psDevInfo->pvDummyPTPageCpuVAddr);
pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyPTPageCpuVAddr;
for(i=0; i<SGX_MMU_PT_SIZE; i++)
{
pui32Tmp[i] = (psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
}
-
+ MakeKernelPageReadOnly(psDevInfo->pvDummyPTPageCpuVAddr);
+ /* pdump the Dummy PT Page */
PDUMPCOMMENT("Dummy Page table contents");
PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hDummyPTOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
-
-
+ /*
+ write a signature to the dummy data page
+ */
+ MakeKernelPageReadWrite(psDevInfo->pvDummyDataPageCpuVAddr);
pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyDataPageCpuVAddr;
for(i=0; i<(SGX_MMU_PAGE_SIZE/4); i++)
{
pui32Tmp[i] = DUMMY_DATA_PAGE_SIGNATURE;
}
-
+ MakeKernelPageReadOnly(psDevInfo->pvDummyDataPageCpuVAddr);
+ /* pdump the Dummy Data Page */
PDUMPCOMMENT("Dummy Data Page contents");
PDUMPMEMPTENTRIES(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
-#else
-
+#else /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
+ /* initialise the PD to invalid address state */
+ MakeKernelPageReadWrite(pvPDCpuVAddr);
for(i=0; i<SGX_MMU_PD_SIZE; i++)
{
-
+ /* invalid, no read, no write, no cache consistency */
pui32Tmp[i] = 0;
}
-#endif
+ MakeKernelPageReadOnly(pvPDCpuVAddr);
+#endif /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
#if defined(PDUMP)
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
if(psMMUContext->bPDumpActive)
-#endif
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
{
-
+ /* pdump the PD Page */
PDUMPCOMMENT("Page directory contents");
PDUMPPDENTRIES(&sMMUAttrib, hPDOSMemHandle, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
PDUMPCOMMENT("BRN31620 Set up dummy PT");
+ MakeKernelPageReadWrite(psDevInfo->pvBRN31620DummyPTCpuVAddr);
pui32PT = (IMG_UINT32 *) psDevInfo->pvBRN31620DummyPTCpuVAddr;
pui32PT[BRN31620_DUMMY_PTE_INDEX] = (psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_DUMMY_PAGE
| SGX_MMU_PTE_READONLY
| SGX_MMU_PTE_VALID;
-
+ MakeKernelPageReadOnly(psDevInfo->pvBRN31620DummyPTCpuVAddr);
#if defined(PDUMP)
-
+ /* Dump initial contents */
PDUMPCOMMENT("BRN31620 Dump dummy PT contents");
PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPTOSMemHandle, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
PDUMPCOMMENT("BRN31620 Dump dummy page contents");
PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
-
+ /* Dump the wiring */
for(i=0;i<SGX_MMU_PT_SIZE;i++)
{
PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPTOSMemHandle, &pui32PT[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
#endif
PDUMPCOMMENT("BRN31620 Dump PDE wire up");
-
+ /* Walk the PD wireing up the PT's */
for(i=0;i<SGX_MMU_PD_SIZE;i++)
{
pui32Tmp[i] = 0;
if (ui32PDCount == BRN31620_DUMMY_PDE_INDEX)
{
+ MakeKernelPageReadWrite(pvPDCpuVAddr);
pui32Tmp[i] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_DUMMY_PAGE
| SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(pvPDCpuVAddr);
}
PDUMPMEMPTENTRIES(&sMMUAttrib, hPDOSMemHandle, (IMG_VOID *) &pui32Tmp[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
ui32PDCount++;
if (ui32PDCount == BRN31620_PDES_PER_CACHE_LINE_SIZE)
{
-
+ /* Reset PT count */
ui32PDCount = 0;
}
}
-
+ /* pdump the Dummy PT Page */
PDUMPCOMMENT("BRN31620 dummy Page table contents");
PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
#endif
#if defined(PDUMP)
-
+ /* pdump set MMU context */
{
PVRSRV_ERROR eError;
-
+ /* default MMU type is 1, 4k page */
IMG_UINT32 ui32MMUType = 1;
#if defined(SGX_FEATURE_36BIT_MMU)
}
}
-
+ /* PDump the context ID */
PDUMPCOMMENT("Set MMU context complete (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
#endif
psMMUContext->apsPTInfoListSave[i] = IMG_NULL;
}
#endif
-
+ /* store PD info in the MMU context */
psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr;
psMMUContext->sPDDevPAddr = sPDDevPAddr;
psMMUContext->hPDOSMemHandle = hPDOSMemHandle;
-
+ /* Get some process information to aid debug */
+ psMMUContext->ui32PID = OSGetCurrentProcessIDKM();
+ psMMUContext->szName[0] = '\0';
+ OSGetCurrentProcessNameKM(psMMUContext->szName, MMU_CONTEXT_NAME_SIZE);
+
+ /* return context */
*ppsMMUContext = psMMUContext;
-
+ /* return the PD DevVAddr */
*psPDDevPAddr = sPDDevPAddr;
-
+
+ /* add the new MMU context onto the list of MMU contexts */
psMMUContext->psNext = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
psDevInfo->pvMMUContextList = (IMG_VOID*)psMMUContext;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Finalise
+
+ PURPOSE: Finalise the mmu module, deallocate all resources.
+
+ PARAMETERS: In: psMMUContext - MMU context to deallocate
+ RETURNS: None.
+******************************************************************************/
IMG_VOID
MMU_Finalise (MMU_CONTEXT *psMMUContext)
{
SysAcquireData(&psSysData);
#if defined(PDUMP)
-
+ /* pdump the MMU context clear */
PDUMPCOMMENT("Clear MMU context (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
PDUMPCLEARMMUCONTEXT(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->psDeviceNode->sDevId.pszPDumpDevName, psMMUContext->ui32PDumpMMUContextID, 2);
-
+ /* pdump the PD free */
#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
PDUMPCOMMENT("Free page directory (PDDevPAddr == 0x%08x)",
psMMUContext->sPDDevPAddr.uiAddr);
PDUMPCOMMENT("Free page directory, 64-bit arch detected (PDDevPAddr == 0x%08x%08x)",
psMMUContext->sPDDevPAddr.uiHighAddr, psMMUContext->sPDDevPAddr.uiAddr);
#endif
-#endif
+#endif /* PDUMP */
PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psMMUContext->hPDOSMemHandle, psMMUContext->pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
pui32Tmp = (IMG_UINT32 *)psMMUContext->pvPDCpuVAddr;
-
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+ /* initialise the PD to invalid address state */
for(i=0; i<SGX_MMU_PD_SIZE; i++)
{
-
+ /* invalid, no read, no write, no cache consistency */
pui32Tmp[i] = 0;
}
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
-
-
-
-
+ /*
+ free the PD:
+ depending on the specific system, the PD is allocated from system memory
+ or device local memory. For now, just look for at least a valid local heap/arena
+ */
if(psMMUContext->psDeviceNode->psLocalDevMemArena == IMG_NULL)
{
#if defined(FIX_HW_BRN_31620)
PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo;
#endif
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
SGX_MMU_PAGE_SIZE,
psMMUContext->pvPDCpuVAddr,
psMMUContext->hPDOSMemHandle);
#if defined(FIX_HW_BRN_31620)
-
+ /* If this is the _last_ MMU context it must be the uKernel */
if (!psMMUContextList->psNext)
{
PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
}
#endif
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* if this is the last context free the dummy pages too */
if(!psMMUContextList->psNext)
{
OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
IMG_SYS_PHYADDR sSysPAddr;
IMG_CPU_PHYADDR sCpuPAddr;
-
+ /* derive the system physical address */
sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->hPDOSMemHandle,
psMMUContext->pvPDCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
-
+ /* unmap the CPU mapping */
OSUnMapPhysToLin(psMMUContext->pvPDCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psMMUContext->hPDOSMemHandle);
-
+ /* and free the memory */
RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* if this is the last context free the dummy pages too */
if(!psMMUContextList->psNext)
{
-
+ /* free the Dummy PT Page */
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
psDevInfo->pvDummyPTPageCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
-
+ /* unmap the CPU mapping */
OSUnMapPhysToLin(psDevInfo->pvDummyPTPageCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psDevInfo->hDummyPTPageOSMemHandle);
-
+ /* and free the memory */
RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
-
+ /* free the Dummy Data Page */
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyDataPageOSMemHandle,
psDevInfo->pvDummyDataPageCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
-
+ /* unmap the CPU mapping */
OSUnMapPhysToLin(psDevInfo->pvDummyDataPageCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psDevInfo->hDummyDataPageOSMemHandle);
-
+ /* and free the memory */
RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
}
#endif
#if defined(FIX_HW_BRN_31620)
-
+ /* if this is the last context free the dummy pages too */
if(!psMMUContextList->psNext)
{
-
+ /* free the Page */
PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPageOSMemHandle,
psDevInfo->pvBRN31620DummyPageCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
-
+ /* unmap the CPU mapping */
OSUnMapPhysToLin(psDevInfo->pvBRN31620DummyPageCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psDevInfo->hBRN31620DummyPageOSMemHandle);
-
+ /* and free the memory */
RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
-
+ /* free the Dummy PT */
PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPTOSMemHandle,
psDevInfo->pvBRN31620DummyPTCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
-
+ /* unmap the CPU mapping */
OSUnMapPhysToLin(psDevInfo->pvBRN31620DummyPTCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psDevInfo->hBRN31620DummyPTOSMemHandle);
-
+ /* and free the memory */
RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
}
#endif
PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Finalise"));
-
+ /* remove the MMU context from the list of MMU contexts */
ppsMMUContext = (MMU_CONTEXT**)&psMMUContext->psDevInfo->pvMMUContextList;
while(*ppsMMUContext)
{
if(*ppsMMUContext == psMMUContext)
{
-
+ /* remove item from the list */
*ppsMMUContext = psMMUContext->psNext;
break;
}
-
+ /* advance to next next */
ppsMMUContext = &((*ppsMMUContext)->psNext);
}
-
+ /* free the context itself. */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_CONTEXT), psMMUContext, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_InsertHeap
+
+ PURPOSE: Copies PDEs from shared/exported heap into current MMU context.
+
+ PARAMETERS: In: psMMUContext - the mmu
+ In: psMMUHeap - a shared/exported heap
+
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
{
IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
#endif
-
+ /* advance to the first entry */
pui32PDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
pui32KernelPDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
-
-
-
+ /*
+ update the PD range relating to the heap's
+ device virtual address range
+ */
#if defined(PDUMP)
PDUMPCOMMENT("Page directory shared heap range copy");
PDUMPCOMMENT(" (Source heap MMU Context ID == %u, PT count == 0x%x)",
psMMUHeap->psMMUContext->ui32PDumpMMUContextID,
psMMUHeap->ui32PageTableCount);
PDUMPCOMMENT(" (Destination MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
-#endif
+#endif /* PDUMP */
#ifdef SUPPORT_SGX_MMU_BYPASS
EnableHostAccess(psMMUContext);
#endif
for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PageTableCount; ui32PDEntry++)
{
#if (!defined(SUPPORT_SGX_MMU_DUMMY_PAGE)) && (!defined(FIX_HW_BRN_31620))
-
+ /* check we have invalidated target PDEs */
PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0);
#endif
-
-
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+ /* copy over the PDEs */
pui32PDCpuVAddr[ui32PDEntry] = pui32KernelPDCpuVAddr[ui32PDEntry];
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
if (pui32PDCpuVAddr[ui32PDEntry])
{
-
+ /* Ensure the shared heap allocation is mapped into the context/PD
+ * for the active pdump process/app. The PTs and backing physical
+ * should also be pdumped (elsewhere).
+ * MALLOC (PT)
+ * LDB (init PT)
+ * MALLOC (data page)
+ * WRW (PTE->data page)
+ * LDB (init data page) -- could be useful to ensure page is initialised
+ */
#if defined(PDUMP)
-
+ //PDUMPCOMMENT("MMU_InsertHeap: Mapping shared heap to new context %d (%s)", psMMUContext->ui32PDumpMMUContextID, (psMMUContext->bPDumpActive) ? "active" : "");
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
if(psMMUContext->bPDumpActive)
- #endif
+ #endif /* SUPPORT_PDUMP_MULTI_PROCESS */
{
PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID *) &pui32PDCpuVAddr[ui32PDEntry], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
if (bInvalidateDirectoryCache)
{
-
-
-
-
+ /* This is actually not to do with multiple mem contexts, but to do with the directory cache.
+ In the 1 context implementation of the MMU, the directory "cache" is actually a copy of the
+ page directory memory, and requires updating whenever the page directory changes, even if there
+ was no previous value in a particular entry
+ */
MMU_InvalidateDirectoryCache(psMMUContext->psDevInfo);
}
#endif
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_UnmapPagesAndFreePTs
+
+ PURPOSE: unmap pages, invalidate virtual address and try to free the PTs
+
+ PARAMETERS: In: psMMUHeap - the mmu.
+ In: sDevVAddr - the device virtual address.
+ In: ui32PageCount - page count
+ In: hUniqueTag - A unique ID for use as a tag identifier
+
+ RETURNS: None
+******************************************************************************/
static IMG_VOID
MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
IMG_DEV_VIRTADDR sDevVAddr,
#if !defined (PDUMP)
PVR_UNREFERENCED_PARAMETER(hUniqueTag);
#endif
-
+ /* setup tmp devvaddr to base of allocation */
sTmpDevVAddr = sDevVAddr;
for(i=0; i<ui32PageCount; i++)
{
MMU_PT_INFO **ppsPTInfoList;
-
+ /* find the index/offset in PD entries */
ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
-
+ /* and advance to the first PT info list */
ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
{
-
+ /* find the index/offset of the first PT in the first PT page */
ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
-
+ /* Is the PT page valid? */
if (!ppsPTInfoList[0])
{
- PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ /*
+ With sparse mappings we expect that the PT could be freed
+ before we reach the end of it as the unmapped pages don't
+ bump ui32ValidPTECount so it can reach zero before we reach
+ the end of the PT.
+ */
+ if (!psMMUHeap->bHasSparseMappings)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ }
-
+ /* advance the sTmpDevVAddr by one page */
sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
-
+ /* Try to unmap the remaining allocation pages */
continue;
}
-
+ /* setup pointer to the first entry in the PT page */
pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
-
+ /* Is PTPageCpuVAddr valid ? */
if (!pui32Tmp)
{
continue;
CheckPT(ppsPTInfoList[0]);
-
+ /* Decrement the valid page count only if the current page is valid*/
if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
{
ppsPTInfoList[0]->ui32ValidPTECount--;
}
else
{
- PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ if (!psMMUHeap->bHasSparseMappings)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ }
}
-
+ /* The page table count should not go below zero */
PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
-
+ MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* point the PT entry to the dummy data page */
pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
#else
-
+ /* invalidate entry */
#if defined(FIX_HW_BRN_31620)
BRN31620InvalidatePageTableEntry(psMMUHeap->psMMUContext, ui32PDIndex, ui32PTIndex, &pui32Tmp[ui32PTIndex]);
#else
pui32Tmp[ui32PTIndex] = 0;
#endif
#endif
-
+ MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
CheckPT(ppsPTInfoList[0]);
}
-
-
+ /*
+ Free a page table if we can.
+ */
if (ppsPTInfoList[0] && (ppsPTInfoList[0]->ui32ValidPTECount == 0)
)
{
#endif
}
-
+ /* advance the sTmpDevVAddr by one page */
sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
}
psMMUHeap->ui32DataPageSize * ui32PageCount,
IMG_TRUE,
hUniqueTag);
-#endif
+#endif /* #if defined(PDUMP) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_FreePageTables
+
+ PURPOSE: Call back from RA_Free to zero page table entries used by freed
+ spans.
+
+ PARAMETERS: In: pvMMUHeap
+ In: ui32Start
+ In: ui32End
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS:
+******************************************************************************/
static IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap,
IMG_SIZE_T ui32Start,
IMG_SIZE_T ui32End,
MMU_UnmapPagesAndFreePTs(pMMUHeap, Start, (IMG_UINT32)((ui32End - ui32Start) >> pMMUHeap->ui32PTShift), hUniqueTag);
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Create
+
+ PURPOSE: Create an mmu device virtual heap.
+
+ PARAMETERS: In: psMMUContext - MMU context
+ In: psDevArena - device memory resource arena
+ Out: ppsVMArena - virtual mapping arena
+ RETURNS: MMU_HEAP
+ RETURNS:
+******************************************************************************/
MMU_HEAP *
MMU_Create (MMU_CONTEXT *psMMUContext,
DEV_ARENA_DESCRIPTOR *psDevArena,
pMMUHeap->psMMUContext = psMMUContext;
pMMUHeap->psDevArena = psDevArena;
-
-
-
+ /*
+ generate page table and data page mask and shift values
+ based on the data page size
+ */
switch(pMMUHeap->psDevArena->ui32DataPageSize)
{
case 0x1000:
ui32ScaleSize = 10;
pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4M;
break;
-#endif
+#endif /* #if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE) */
default:
PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid data page size"));
goto ErrorFreeHeap;
}
-
+ /* number of bits of address offset into the data page */
pMMUHeap->ui32DataPageSize = psDevArena->ui32DataPageSize;
pMMUHeap->ui32DataPageBitWidth = SGX_MMU_PAGE_SHIFT + ui32ScaleSize;
pMMUHeap->ui32DataPageMask = pMMUHeap->ui32DataPageSize - 1;
-
+ /* number of bits of address indexing into a pagetable */
pMMUHeap->ui32PTShift = pMMUHeap->ui32DataPageBitWidth;
pMMUHeap->ui32PTBitWidth = SGX_MMU_PT_SHIFT - ui32ScaleSize;
pMMUHeap->ui32PTMask = SGX_MMU_PT_MASK & (SGX_MMU_PT_MASK<<ui32ScaleSize);
pMMUHeap->ui32PTSize = (IMG_UINT32)(1UL<<pMMUHeap->ui32PTBitWidth) * sizeof(IMG_UINT32);
-
+ /* note: PT size must be at least 4 entries, even for 4Mb data page size */
if(pMMUHeap->ui32PTSize < 4 * sizeof(IMG_UINT32))
{
pMMUHeap->ui32PTSize = 4 * sizeof(IMG_UINT32);
}
pMMUHeap->ui32PTNumEntriesAllocated = pMMUHeap->ui32PTSize >> 2;
-
+ /* find the number of actual PT entries per PD entry range. For 4MB data
+ * pages we only use the first entry although the PT has 16 byte allocation/alignment
+ * (due to 4 LSbits of the PDE are reserved for control) */
pMMUHeap->ui32PTNumEntriesUsable = (IMG_UINT32)(1UL << pMMUHeap->ui32PTBitWidth);
-
+ /* number of bits of address indexing into a page directory */
pMMUHeap->ui32PDShift = pMMUHeap->ui32PTBitWidth + pMMUHeap->ui32PTShift;
pMMUHeap->ui32PDBitWidth = SGX_FEATURE_ADDRESS_SPACE_SIZE - pMMUHeap->ui32PTBitWidth - pMMUHeap->ui32DataPageBitWidth;
pMMUHeap->ui32PDMask = SGX_MMU_PD_MASK & (SGX_MMU_PD_MASK>>(32-SGX_FEATURE_ADDRESS_SPACE_SIZE));
-
+ /* External system cache violates this rule */
#if !defined (SUPPORT_EXTERNAL_SYSTEM_CACHE)
-
-
-
-
+ /*
+ The heap must start on a PT boundary to avoid PT sharing across heaps
+ The only exception is the first heap which can start at any address
+ from 0 to the end of the first PT boundary
+ */
if(psDevArena->BaseDevVAddr.uiAddr > (pMMUHeap->ui32DataPageMask | pMMUHeap->ui32PTMask))
{
-
-
-
+ /*
+ if for some reason the first heap starts after the end of the first PT boundary
+ but is not aligned to a PT boundary then the assert will trigger unncessarily
+ */
PVR_ASSERT ((psDevArena->BaseDevVAddr.uiAddr
& (pMMUHeap->ui32DataPageMask
| pMMUHeap->ui32PTMask)) == 0);
}
#endif
-
+ /* how many PT entries do we need? */
pMMUHeap->ui32PTETotalUsable = pMMUHeap->psDevArena->ui32Size >> pMMUHeap->ui32PTShift;
-
+ /* calculate the PD Base index for the Heap (required for page mapping) */
pMMUHeap->ui32PDBaseIndex = (pMMUHeap->psDevArena->BaseDevVAddr.uiAddr & pMMUHeap->ui32PDMask) >> pMMUHeap->ui32PDShift;
-
-
-
+ /*
+ how many page tables?
+ round up to nearest entries to the nearest page table sized block
+ */
pMMUHeap->ui32PageTableCount = (pMMUHeap->ui32PTETotalUsable + pMMUHeap->ui32PTNumEntriesUsable - 1)
>> pMMUHeap->ui32PTBitWidth;
PVR_ASSERT(pMMUHeap->ui32PageTableCount > 0);
-
+ /* Create the arena */
pMMUHeap->psVMArena = RA_Create(psDevArena->pszName,
psDevArena->BaseDevVAddr.uiAddr,
psDevArena->ui32Size,
}
#if defined(PDUMP)
-
+ /* setup per-heap PDUMP MMU attributes */
MMU_SetPDumpAttribs(&pMMUHeap->sMMUAttrib,
psMMUContext->psDeviceNode,
pMMUHeap->ui32DataPageMask,
psDevArena->ui32Size,
pMMUHeap->ui32DataPageSize,
psDevArena->BaseDevVAddr.uiAddr);
-#endif
-
-#if 0
-
- if(psDevArena->ui32HeapID == SGX_TILED_HEAP_ID)
- {
- IMG_UINT32 ui32RegVal;
- IMG_UINT32 ui32XTileStride;
-
-
-
-
-
-
- ui32XTileStride = 2;
-
- ui32RegVal = (EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK
- & ((psDevArena->BaseDevVAddr.uiAddr>>20)
- << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT))
- |(EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK
- & (((psDevArena->BaseDevVAddr.uiAddr+psDevArena->ui32Size)>>20)
- << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT))
- |(EUR_CR_BIF_TILE0_CFG_MASK
- & (((ui32XTileStride<<1)|8) << EUR_CR_BIF_TILE0_CFG_SHIFT));
- PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_TILE0, ui32RegVal);
- }
-#endif
-
-
+#endif /* PDUMP */
+ /*
+ And return the RA for VM arena management
+ */
*ppsVMArena = pMMUHeap->psVMArena;
return pMMUHeap;
-
+ /* drop into here if errors */
ErrorFreePagetables:
_DeferredFreePageTables (pMMUHeap);
ErrorFreeHeap:
OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return IMG_NULL;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Delete
+
+ PURPOSE: Delete an MMU device virtual heap.
+
+ PARAMETERS: In: pMMUHeap - The MMU heap to delete.
+ RETURNS:
+******************************************************************************/
IMG_VOID
MMU_Delete (MMU_HEAP *pMMUHeap)
{
pMMUHeap->psDevArena->pszName,
pMMUHeap->psDevArena->BaseDevVAddr.uiAddr,
pMMUHeap->ui32PageTableCount);
-#endif
+#endif /* PDUMP */
#ifdef SUPPORT_SGX_MMU_BYPASS
EnableHostAccess(pMMUHeap->psMMUContext);
#endif
OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Alloc
+ PURPOSE: Allocate space in an mmu's virtual address space.
+ PARAMETERS: In: pMMUHeap - MMU to allocate on.
+ In: uSize - Size in bytes to allocate.
+ Out: pActualSize - If non null receives actual size allocated.
+ In: uFlags - Allocation flags.
+ In: uDevVAddrAlignment - Required alignment.
+ Out: DevVAddr - Receives base address of allocation.
+ RETURNS: IMG_TRUE - Success
+ IMG_FALSE - Failure
+******************************************************************************/
IMG_BOOL
MMU_Alloc (MMU_HEAP *pMMUHeap,
IMG_SIZE_T uSize,
"MMU_Alloc: uSize=0x%x, flags=0x%x, align=0x%x",
uSize, uFlags, uDevVAddrAlignment));
-
-
+ /*
+ Only allocate a VM address if the caller did not supply one
+ */
if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
{
IMG_UINTPTR_T uiAddr;
0,
uDevVAddrAlignment,
0,
+ IMG_NULL,
+ 0,
&uiAddr);
if(!bStatus)
{
EnableHostAccess(pMMUHeap->psMMUContext);
#endif
-
+ /* allocate page tables to cover allocation as required */
bStatus = _DeferredAllocPagetables(pMMUHeap, *psDevVAddr, (IMG_UINT32)uSize);
#ifdef SUPPORT_SGX_MMU_BYPASS
pMMUHeap->psDevArena->ui32HeapID));
if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
{
-
+ /* free the VM address */
RA_Free (pMMUHeap->psVMArena, psDevVAddr->uiAddr, IMG_FALSE);
}
}
return bStatus;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Free
+ PURPOSE: Free space in an mmu's virtual address space.
+ PARAMETERS: In: pMMUHeap - MMU to deallocate on.
+ In: DevVAddr - Base address to deallocate.
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
{
pMMUHeap->psDevArena->ui32HeapID));
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Enable
+
+ PURPOSE: Enable an mmu. Establishes pages tables and takes the mmu out
+ of bypass and waits for the mmu to acknowledge enabled.
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_Enable (MMU_HEAP *pMMUHeap)
{
PVR_UNREFERENCED_PARAMETER(pMMUHeap);
-
+ /* SGX mmu is always enabled (stub function) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Disable
+
+ PURPOSE: Disable an mmu, takes the mmu into bypass.
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_Disable (MMU_HEAP *pMMUHeap)
{
PVR_UNREFERENCED_PARAMETER(pMMUHeap);
-
+ /* SGX mmu is always enabled (stub function) */
}
#if defined(FIX_HW_BRN_31620)
+/*!
+******************************************************************************
+ FUNCTION: MMU_GetCacheFlushRange
+
+ PURPOSE: Gets device physical address of the mmu context.
+
+ PARAMETERS: In: pMMUContext - the mmu context
+ Out: pui32RangeMask - Bit mask showing which PD cache
+ lines have changed
+ RETURNS: None
+******************************************************************************/
+
IMG_VOID MMU_GetCacheFlushRange(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask)
{
IMG_UINT32 i;
{
pui32RangeMask[i] = pMMUContext->ui32PDChangeMask[i];
-
+ /* Clear bit mask for the next set of allocations */
pMMUContext->ui32PDChangeMask[i] = 0;
}
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_GetPDPhysAddr
+
+ PURPOSE: Gets device physical address of the mmu contexts PD.
+
+ PARAMETERS: In: pMMUContext - the mmu context
+ Out: psDevPAddr - Address of PD
+ RETURNS: None
+******************************************************************************/
+
IMG_VOID MMU_GetPDPhysAddr(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr)
{
*psDevPAddr = pMMUContext->sPDDevPAddr;
#endif
#if defined(PDUMP)
+/*!
+******************************************************************************
+ FUNCTION: MMU_PDumpPageTables
+
+ PURPOSE: PDump the linear mapping for a range of pages at a specified
+ virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: uSize - size of memory range in bytes
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
static IMG_VOID
MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
IMG_UINT32 ui32PDIndex;
IMG_UINT32 ui32PTDumpCount;
-
+#if defined(FIX_HW_BRN_31620)
+ PVRSRV_SGXDEV_INFO *psDevInfo = pMMUHeap->psMMUContext->psDevInfo;
+#endif
+ /* find number of PT entries to dump */
ui32NumPTEntries = (IMG_UINT32)((uSize + pMMUHeap->ui32DataPageMask) >> pMMUHeap->ui32PTShift);
-
+ /* find the index/offset in PD entries */
ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* set the base PT info */
ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
-
+ /* find the index/offset of the first PT entry in the first PT page */
ui32PTIndex = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
-
+ /* pdump the PT Page modification */
PDUMPCOMMENT("Page table mods (num entries == %08X) %s", ui32NumPTEntries, bForUnmap ? "(for unmap)" : "");
-
+ /* walk the PT pages, dumping as we go */
while(ui32NumPTEntries > 0)
{
MMU_PT_INFO* psPTInfo = *ppsPTInfoList++;
if (psPTInfo)
{
+#if defined(FIX_HW_BRN_31620)
+ IMG_UINT32 i;
+#endif
IMG_UINT32 ui32Flags = 0;
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
#endif
pui32PTEntry = (IMG_UINT32*)psPTInfo->PTPageCpuVAddr;
- PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+#if defined(FIX_HW_BRN_31620)
+ if ((ui32PDIndex % (BRN31620_PDE_CACHE_FILL_SIZE/BRN31620_PT_ADDRESS_RANGE_SIZE)) == BRN31620_DUMMY_PDE_INDEX)
+ {
+ for (i=ui32PTIndex;i<(ui32PTIndex + ui32PTDumpCount);i++)
+ {
+ if (pui32PTEntry[i] == ((psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_DUMMY_PAGE
+ | SGX_MMU_PTE_READONLY
+ | SGX_MMU_PTE_VALID))
+ {
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[i], sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+ }
+ else
+ {
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[i], sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+ }
+ }
+ }
+ else
+#endif
+ {
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+ }
}
-
+ /* decrement PT entries left */
ui32NumPTEntries -= ui32PTDumpCount;
-
+ /* reset offset in page */
ui32PTIndex = 0;
+
+#if defined(FIX_HW_BRN_31620)
+ /* For 31620 we need to know which PD index we're working on */
+ ui32PDIndex++;
+#endif
}
PDUMPCOMMENT("Finished page table mods %s", bForUnmap ? "(for unmap)" : "");
}
-#endif
+#endif /* #if defined(PDUMP) */
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapPage
+ PURPOSE: Create a mapping for one page at a specified virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: DevPAddr - the device physical address of the page to map.
+ In: ui32MemFlags - BM r/w/cache flags
+ RETURNS: None
+******************************************************************************/
static IMG_VOID
MMU_MapPage (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
IMG_UINT32 ui32MMUFlags = 0;
MMU_PT_INFO **ppsPTInfoList;
-
+ /* check the physical alignment of the memory to map */
PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
-
-
+ /*
+ unravel the read/write/cache flags
+ */
if(((PVRSRV_MEM_READ|PVRSRV_MEM_WRITE) & ui32MemFlags) == (PVRSRV_MEM_READ|PVRSRV_MEM_WRITE))
{
-
+ /* read/write */
ui32MMUFlags = 0;
}
else if(PVRSRV_MEM_READ & ui32MemFlags)
{
-
+ /* read only */
ui32MMUFlags |= SGX_MMU_PTE_READONLY;
}
else if(PVRSRV_MEM_WRITE & ui32MemFlags)
{
-
+ /* write only */
ui32MMUFlags |= SGX_MMU_PTE_WRITEONLY;
}
-
+ /* cache coherency */
if(PVRSRV_MEM_CACHE_CONSISTENT & ui32MemFlags)
{
ui32MMUFlags |= SGX_MMU_PTE_CACHECONSISTENT;
}
#if !defined(FIX_HW_BRN_25503)
-
+ /* EDM protection */
if(PVRSRV_MEM_EDM_PROTECT & ui32MemFlags)
{
ui32MMUFlags |= SGX_MMU_PTE_EDMPROTECT;
}
#endif
-
-
+ /*
+ we receive a device physical address for the page that is to be mapped
+ and a device virtual address representing where it should be mapped to
+ */
-
+ /* find the index/offset in PD entries */
ui32Index = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* and advance to the first PT info list */
ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
CheckPT(ppsPTInfoList[0]);
-
+ /* find the index/offset of the first PT in the first PT page */
ui32Index = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
-
+ /* setup pointer to the first entry in the PT page */
pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
{
IMG_UINT32 uTmp = pui32Tmp[ui32Index];
-
+ /* Is the current page already valid? (should not be unless it was allocated and not deallocated) */
#if defined(FIX_HW_BRN_31620)
if ((uTmp & SGX_MMU_PTE_VALID) && ((DevVAddr.uiAddr & BRN31620_PDE_CACHE_FILL_MASK) != BRN31620_DUMMY_PAGE_OFFSET))
#else
ui32Index ));
PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page table entry value: 0x%08X", uTmp));
PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Physical page to map: 0x%08X", DevPAddr.uiAddr));
+#if PT_DUMP
+ DumpPT(ppsPTInfoList[0]);
+#endif
}
#if !defined(FIX_HW_BRN_31620)
PVR_ASSERT((uTmp & SGX_MMU_PTE_VALID) == 0);
}
#endif
-
+ /* One more valid entry in the page table. */
ppsPTInfoList[0]->ui32ValidPTECount++;
-
+ MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
+ /* map in the physical page */
pui32Tmp[ui32Index] = ((DevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
& ((~pMMUHeap->ui32DataPageMask)>>SGX_MMU_PTE_ADDR_ALIGNSHIFT))
| SGX_MMU_PTE_VALID
| ui32MMUFlags;
-
+ MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
CheckPT(ppsPTInfoList[0]);
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapScatter
+
+ PURPOSE: Create a linear mapping for a range of pages at a specified
+ virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: psSysAddr - the device physical address of the page to
+ map.
+ In: uSize - size of memory range in bytes
+ In: ui32MemFlags - page table flags.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapScatter (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
{
#if defined(PDUMP)
IMG_DEV_VIRTADDR MapBaseDevVAddr;
-#endif
+#endif /*PDUMP*/
IMG_UINT32 uCount, i;
IMG_DEV_PHYADDR DevPAddr;
MapBaseDevVAddr = DevVAddr;
#else
PVR_UNREFERENCED_PARAMETER(hUniqueTag);
-#endif
+#endif /*PDUMP*/
for (i=0, uCount=0; uCount<uSize; i++, uCount+=pMMUHeap->ui32DataPageSize)
{
sSysAddr = psSysAddr[i];
-
+ /* check the physical alignment of the memory to map */
PVR_ASSERT((sSysAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr);
#if defined(PDUMP)
MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
-#endif
+#endif /* #if defined(PDUMP) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapPages
+
+ PURPOSE: Create a linear mapping for a ranege of pages at a specified
+ virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: SysPAddr - the system physical address of the page to
+ map.
+ In: uSize - size of memory range in bytes
+ In: ui32MemFlags - page table flags.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapPages (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
IMG_DEV_PHYADDR DevPAddr;
#if defined(PDUMP)
IMG_DEV_VIRTADDR MapBaseDevVAddr;
-#endif
+#endif /*PDUMP*/
IMG_UINT32 uCount;
IMG_UINT32 ui32VAdvance;
IMG_UINT32 ui32PAdvance;
SysPAddr.uiAddr,
uSize));
-
+ /* set the virtual and physical advance */
ui32VAdvance = pMMUHeap->ui32DataPageSize;
ui32PAdvance = pMMUHeap->ui32DataPageSize;
MapBaseDevVAddr = DevVAddr;
#else
PVR_UNREFERENCED_PARAMETER(hUniqueTag);
-#endif
+#endif /*PDUMP*/
DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
-
+ /* check the physical alignment of the memory to map */
PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
-#if defined(FIX_HW_BRN_23281)
- if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+ /*
+ for dummy allocations there is only one physical
+ page backing the virtual range
+ */
+ if(ui32MemFlags & PVRSRV_MEM_DUMMY)
{
- ui32VAdvance *= 2;
+ 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 /* #if defined(PDUMP) */
+}
+
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapPagesSparse
+
+ PURPOSE: Create a linear mapping for a ranege of pages at a specified
+ virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: SysPAddr - the system physical address of the page to
+ map.
+ In: ui32ChunkSize - Size of the chunk (must be page multiple)
+ In: ui32NumVirtChunks - Number of virtual chunks
+ In: ui32NumPhysChunks - Number of physical chunks
+ In: pabMapChunk - Mapping array
+ In: ui32MemFlags - page table flags.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
+IMG_VOID
+MMU_MapPagesSparse (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+#if defined(PDUMP)
+ IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif /*PDUMP*/
+ IMG_UINT32 uCount;
+ IMG_UINT32 ui32VAdvance;
+ IMG_UINT32 ui32PAdvance;
+ IMG_SIZE_T uSizeVM = ui32ChunkSize * ui32NumVirtChunks;
+#if !defined(PVRSRV_NEED_PVR_DPF)
+ PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
#endif
-
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_MapPagesSparse: heap:%s, heap_id:%d devVAddr=%08X, SysPAddr=%08X, VM space=0x%x, PHYS space=0x%x",
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID,
+ DevVAddr.uiAddr,
+ SysPAddr.uiAddr,
+ uSizeVM,
+ ui32ChunkSize * ui32NumPhysChunks));
+ /* set the virtual and physical advance */
+ ui32VAdvance = pMMUHeap->ui32DataPageSize;
+ ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+#if defined(PDUMP)
+ MapBaseDevVAddr = DevVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif /*PDUMP*/
+
+ DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+ /* check the physical alignment of the memory to map */
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+ /*
+ for dummy allocations there is only one physical
+ page backing the virtual range
+ */
if(ui32MemFlags & PVRSRV_MEM_DUMMY)
{
ui32PAdvance = 0;
}
- for (uCount=0; uCount<uSize; uCount+=ui32VAdvance)
+ for (uCount=0; uCount<uSizeVM; uCount+=ui32VAdvance)
{
- MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ if (pabMapChunk[uCount/ui32ChunkSize])
+ {
+ MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevPAddr.uiAddr += ui32PAdvance;
+ }
DevVAddr.uiAddr += ui32VAdvance;
- DevPAddr.uiAddr += ui32PAdvance;
}
+ pMMUHeap->bHasSparseMappings = IMG_TRUE;
#if defined(PDUMP)
- MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
-#endif
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSizeVM, IMG_FALSE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapShadow
+
+ PURPOSE: Create a mapping for a range of pages from either a CPU
+ virtual adddress, (or if NULL a hOSMemHandle) to a specified
+ device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: MapBaseDevVAddr - A page aligned device virtual address
+ to start mapping from.
+ In: uByteSize - A page aligned mapping length in bytes.
+ In: CpuVAddr - A page aligned CPU virtual address.
+ In: hOSMemHandle - An alternative OS specific memory handle
+ for mapping RAM without a CPU virtual
+ address
+ Out: pDevVAddr - deprecated - It used to return a byte aligned
+ device virtual address corresponding to the
+ cpu virtual address (When CpuVAddr wasn't
+ constrained to be page aligned.) Now it just
+ returns MapBaseDevVAddr. Unaligned semantics
+ can easily be handled above this API if required.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ In: ui32MemFlags - page table flags.
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapShadow (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR MapBaseDevVAddr,
uByteSize,
(IMG_UINTPTR_T)CpuVAddr));
-
+ /* set the virtual and physical advance */
ui32VAdvance = pMMUHeap->ui32DataPageSize;
ui32PAdvance = pMMUHeap->ui32DataPageSize;
-
+ /* note: can't do useful check on the CPU Addr other than it being at least 4k alignment */
PVR_ASSERT(((IMG_UINTPTR_T)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
PVR_ASSERT(((IMG_UINT32)uByteSize & pMMUHeap->ui32DataPageMask) == 0);
pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
-#if defined(FIX_HW_BRN_23281)
- if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
- {
- ui32VAdvance *= 2;
- }
-#endif
-
-
-
-
+ /*
+ for dummy allocations there is only one physical
+ page backing the virtual range
+ */
if(ui32MemFlags & PVRSRV_MEM_DUMMY)
{
ui32PAdvance = 0;
}
-
+ /* Loop through cpu memory and map page by page */
MapDevVAddr = MapBaseDevVAddr;
for (i=0; i<uByteSize; i+=ui32VAdvance)
{
}
DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
-
+ /* check the physical alignment of the memory to map */
PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
PVR_DPF ((PVR_DBG_MESSAGE,
MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
-
+ /* loop update */
MapDevVAddr.uiAddr += ui32VAdvance;
uOffset += ui32PAdvance;
}
#if defined(PDUMP)
MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uByteSize, IMG_FALSE, hUniqueTag);
-#endif
+#endif /* #if defined(PDUMP) */
+}
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapShadowSparse
+
+ PURPOSE: Create a mapping for a range of pages from either a CPU
+ virtual adddress, (or if NULL a hOSMemHandle) to a specified
+ device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: MapBaseDevVAddr - A page aligned device virtual address
+ to start mapping from.
+ In: ui32ChunkSize - Size of the chunk (must be page multiple)
+ In: ui32NumVirtChunks - Number of virtual chunks
+ In: ui32NumPhysChunks - Number of physical chunks
+ In: pabMapChunk - Mapping array
+ In: CpuVAddr - A page aligned CPU virtual address.
+ In: hOSMemHandle - An alternative OS specific memory handle
+ for mapping RAM without a CPU virtual
+ address
+ Out: pDevVAddr - deprecated - It used to return a byte aligned
+ device virtual address corresponding to the
+ cpu virtual address (When CpuVAddr wasn't
+ constrained to be page aligned.) Now it just
+ returns MapBaseDevVAddr. Unaligned semantics
+ can easily be handled above this API if required.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ In: ui32MemFlags - page table flags.
+ RETURNS: None
+******************************************************************************/
+IMG_VOID
+MMU_MapShadowSparse (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR *pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 i;
+ IMG_UINT32 uOffset = 0;
+ IMG_DEV_VIRTADDR MapDevVAddr;
+ IMG_UINT32 ui32VAdvance;
+ IMG_UINT32 ui32PAdvance;
+ IMG_SIZE_T uiSizeVM = ui32ChunkSize * ui32NumVirtChunks;
+ IMG_UINT32 ui32ChunkIndex = 0;
+ IMG_UINT32 ui32ChunkOffset = 0;
+#if !defined(PVRSRV_NEED_PVR_DPF)
+ PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
+#endif
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_MapShadowSparse: DevVAddr:%08X, VM space:0x%x, CPUVAddr:%08X PHYS space:0x%x",
+ MapBaseDevVAddr.uiAddr,
+ uiSizeVM,
+ (IMG_UINTPTR_T)CpuVAddr,
+ ui32ChunkSize * ui32NumPhysChunks));
+
+ /* set the virtual and physical advance */
+ ui32VAdvance = pMMUHeap->ui32DataPageSize;
+ ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+ /* note: can't do useful check on the CPU Addr other than it being at least 4k alignment */
+ PVR_ASSERT(((IMG_UINTPTR_T)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+ PVR_ASSERT(((IMG_UINT32)uiSizeVM & pMMUHeap->ui32DataPageMask) == 0);
+ pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
+
+ /* Shouldn't come through the sparse interface */
+ PVR_ASSERT((ui32MemFlags & PVRSRV_MEM_DUMMY) == 0);
+
+ /* Loop through cpu memory and map page by page */
+ MapDevVAddr = MapBaseDevVAddr;
+ for (i=0; i<uiSizeVM; i+=ui32VAdvance)
+ {
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_PHYADDR DevPAddr;
+
+ if (pabMapChunk[i/ui32ChunkSize])
+ /*if (pabMapChunk[ui32ChunkIndex])*/
+ {
+ if(CpuVAddr)
+ {
+ CpuPAddr = OSMapLinToCPUPhys (hOSMemHandle,
+ (IMG_VOID *)((IMG_UINTPTR_T)CpuVAddr + uOffset));
+ }
+ else
+ {
+ CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+ }
+ DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+
+ /* check the physical alignment of the memory to map */
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "Offset=0x%x: CpuVAddr=%08X, CpuPAddr=%08X, DevVAddr=%08X, DevPAddr=%08X",
+ uOffset,
+ (IMG_UINTPTR_T)CpuVAddr + uOffset,
+ CpuPAddr.uiAddr,
+ MapDevVAddr.uiAddr,
+ DevPAddr.uiAddr));
+
+ MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
+ uOffset += ui32PAdvance;
+ }
+
+ /* loop update */
+ MapDevVAddr.uiAddr += ui32VAdvance;
+
+ if (ui32ChunkOffset == ui32ChunkSize)
+ {
+ ui32ChunkIndex++;
+ ui32ChunkOffset = 0;
+ }
+ }
+
+ pMMUHeap->bHasSparseMappings = IMG_TRUE;
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uiSizeVM, IMG_FALSE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_UnmapPages
+
+ PURPOSE: unmap pages and invalidate virtual address
+ PARAMETERS: In: psMMUHeap - the mmu.
+ In: sDevVAddr - the device virtual address.
+ In: ui32PageCount - page count
+ In: hUniqueTag - A unique ID for use as a tag identifier
+
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_UnmapPages (MMU_HEAP *psMMUHeap,
IMG_DEV_VIRTADDR sDevVAddr,
PVR_UNREFERENCED_PARAMETER(hUniqueTag);
#endif
-
+ /* setup tmp devvaddr to base of allocation */
sTmpDevVAddr = sDevVAddr;
for(i=0; i<ui32PageCount; i++)
{
MMU_PT_INFO **ppsPTInfoList;
-
+ /* find the index/offset in PD entries */
ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
-
+ /* and advance to the first PT info list */
ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
-
+ /* find the index/offset of the first PT in the first PT page */
ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
-
- if (!ppsPTInfoList[0])
+ /* Is the PT page valid? */
+ if ((!ppsPTInfoList[0]) && (!psMMUHeap->bHasSparseMappings))
{
PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: ERROR Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",
sTmpDevVAddr.uiAddr,
ui32PDIndex,
ui32PTIndex));
-
+ /* advance the sTmpDevVAddr by one page */
sTmpDevVAddr.uiAddr += uPageSize;
-
+ /* Try to unmap the remaining allocation pages */
continue;
}
CheckPT(ppsPTInfoList[0]);
-
+ /* setup pointer to the first entry in the PT page */
pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
-
+ /* Decrement the valid page count only if the current page is valid*/
if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
{
ppsPTInfoList[0]->ui32ValidPTECount--;
PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page table entry value: 0x%08X", pui32Tmp[ui32PTIndex]));
}
-
+ /* The page table count should not go below zero */
PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+ MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* point the PT entry to the dummy data page */
pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
#else
-
+ /* invalidate entry */
#if defined(FIX_HW_BRN_31620)
BRN31620InvalidatePageTableEntry(psMMUHeap->psMMUContext, ui32PDIndex, ui32PTIndex, &pui32Tmp[ui32PTIndex]);
#else
pui32Tmp[ui32PTIndex] = 0;
#endif
#endif
+ MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
CheckPT(ppsPTInfoList[0]);
-
+ /* advance the sTmpDevVAddr by one page */
sTmpDevVAddr.uiAddr += uPageSize;
}
#if defined(PDUMP)
MMU_PDumpPageTables (psMMUHeap, sDevVAddr, uPageSize*ui32PageCount, IMG_TRUE, hUniqueTag);
-#endif
+#endif /* #if defined(PDUMP) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_GetPhysPageAddr
+
+ PURPOSE: extracts physical address from MMU page tables
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ PARAMETERS: In: sDevVPageAddr - the virtual address to extract physical
+ page mapping from
+ RETURNS: None
+******************************************************************************/
IMG_DEV_PHYADDR
MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr)
{
IMG_DEV_PHYADDR sDevPAddr;
MMU_PT_INFO **ppsPTInfoList;
-
+ /* find the index/offset in PD entries */
ui32Index = sDevVPageAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* and advance to the first PT info list */
ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
if (!ppsPTInfoList[0])
{
- PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr));
+ /* Heaps with sparse mappings are allowed invalid pages */
+ if (!pMMUHeap->bHasSparseMappings)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr));
+ }
sDevPAddr.uiAddr = 0;
return sDevPAddr;
}
-
+ /* find the index/offset of the first PT in the first PT page */
ui32Index = (sDevVPageAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
-
+ /* setup pointer to the first entry in the PT page */
pui32PageTable = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
-
+ /* read back physical page */
sDevPAddr.uiAddr = pui32PageTable[ui32Index];
-
+ /* Mask off non-address bits */
sDevPAddr.uiAddr &= ~(pMMUHeap->ui32DataPageMask>>SGX_MMU_PTE_ADDR_ALIGNSHIFT);
-
+ /* and align the address */
sDevPAddr.uiAddr <<= SGX_MMU_PTE_ADDR_ALIGNSHIFT;
return sDevPAddr;
}
+/*!
+******************************************************************************
+ FUNCTION: SGXGetPhysPageAddr
+
+ PURPOSE: Gets DEV and CPU physical address of sDevVAddr
+
+ PARAMETERS: In: hDevMemHeap - device mem heap handle
+ PARAMETERS: In: sDevVAddr - the base virtual address to unmap from
+ PARAMETERS: Out: pDevPAddr - DEV physical address
+ PARAMETERS: Out: pCpuPAddr - CPU physical address
+ RETURNS: None
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR SGXGetPhysPageAddrKM (IMG_HANDLE hDevMemHeap,
IMG_DEV_VIRTADDR sDevVAddr,
MMU_HEAP *pMMUHeap;
IMG_DEV_PHYADDR DevPAddr;
-
-
+ /*
+ Get MMU Heap From hDevMemHeap
+ */
pMMUHeap = (MMU_HEAP*)BM_GetMMUHeap(hDevMemHeap);
DevPAddr = MMU_GetPhysPageAddr(pMMUHeap, sDevVAddr);
- pCpuPAddr->uiAddr = DevPAddr.uiAddr;
+ pCpuPAddr->uiAddr = DevPAddr.uiAddr; /* SysDevPAddrToCPUPAddr(DevPAddr) */
pDevPAddr->uiAddr = DevPAddr.uiAddr;
return (pDevPAddr->uiAddr != 0) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_PARAMS;
}
+/*!
+******************************************************************************
+ FUNCTION: SGXGetMMUPDAddrKM
+
+ PURPOSE: Gets PD device physical address of hDevMemContext
+
+ PARAMETERS: In: hDevCookie - device cookie
+ PARAMETERS: In: hDevMemContext - memory context
+ PARAMETERS: Out: psPDDevPAddr - MMU PD address
+ RETURNS: None
+******************************************************************************/
PVRSRV_ERROR SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie,
IMG_HANDLE hDevMemContext,
IMG_DEV_PHYADDR *psPDDevPAddr)
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* return the address */
*psPDDevPAddr = ((BM_CONTEXT*)hDevMemContext)->psMMUContext->sPDDevPAddr;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_BIFResetPDAlloc
+
+ PURPOSE: Allocate a dummy Page Directory, Page Table and Page which can
+ be used for dynamic dummy page mapping during SGX reset.
+ Note: since this is only used for hardware recovery, no
+ pdumping is performed.
+
+ PARAMETERS: In: psDevInfo - device info
+ RETURNS: PVRSRV_OK or error
+******************************************************************************/
PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
{
PVRSRV_ERROR eError;
psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
-
+ /* allocate 3 pages - for the PD, PT and dummy page */
if(psLocalDevMemArena == IMG_NULL)
{
-
+ /* UMA system */
eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
3 * SGX_MMU_PAGE_SIZE,
SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
(IMG_VOID **)&pui8MemBlock,
&hOSMemHandle);
if (eError != PVRSRV_OK)
return eError;
}
-
+ /* translate address to device physical */
if(pui8MemBlock)
{
sMemBlockCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle,
}
else
{
-
+ /* This isn't used in all cases since not all ports currently support
+ * OSMemHandleToCpuPAddr() */
sMemBlockCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, 0);
}
}
else
{
-
+ /* non-UMA system */
if(RA_Alloc(psLocalDevMemArena,
3 * SGX_MMU_PAGE_SIZE,
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sMemBlockSysPAddr.uiAddr)) != IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* derive the CPU virtual address */
sMemBlockCpuPAddr = SysSysPAddrToCpuPAddr(sMemBlockSysPAddr);
pui8MemBlock = OSMapPhysToLin(sMemBlockCpuPAddr,
SGX_MMU_PAGE_SIZE * 3,
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;
-
-
+ /* override pointer cast warnings */
+ /* PRQA S 3305,509 2 */
psDevInfo->pui32BIFResetPD = (IMG_UINT32 *)pui8MemBlock;
psDevInfo->pui32BIFResetPT = (IMG_UINT32 *)(pui8MemBlock + SGX_MMU_PAGE_SIZE);
-
+ /* Invalidate entire PD and PT. */
OSMemSet(psDevInfo->pui32BIFResetPD, 0, SGX_MMU_PAGE_SIZE);
OSMemSet(psDevInfo->pui32BIFResetPT, 0, SGX_MMU_PAGE_SIZE);
-
+ /* Fill dummy page with markers. */
OSMemSet(pui8MemBlock + (2 * SGX_MMU_PAGE_SIZE), 0xDB, SGX_MMU_PAGE_SIZE);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_BIFResetPDFree
+
+ PURPOSE: Free resources allocated in MMU_BIFResetPDAlloc.
+
+ PARAMETERS: In: psDevInfo - device info
+ RETURNS:
+******************************************************************************/
IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo)
{
SYS_DATA *psSysData;
psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
-
+ /* free the page directory */
if(psLocalDevMemArena == IMG_NULL)
{
OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
}
}
-
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
-PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE *psDeviceNode)
+IMG_VOID MMU_CheckFaultAddr(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32PDDevPAddr, IMG_UINT32 ui32FaultAddr)
{
- PVRSRV_ERROR eError;
- SYS_DATA *psSysData;
- RA_ARENA *psLocalDevMemArena;
- IMG_HANDLE hPTPageOSMemHandle = IMG_NULL;
- IMG_HANDLE hPDPageOSMemHandle = IMG_NULL;
- IMG_UINT32 *pui32PD = IMG_NULL;
- IMG_UINT32 *pui32PT = IMG_NULL;
- IMG_CPU_PHYADDR sCpuPAddr;
- IMG_DEV_PHYADDR sPTDevPAddr;
- IMG_DEV_PHYADDR sPDDevPAddr;
- PVRSRV_SGXDEV_INFO *psDevInfo;
- IMG_UINT32 ui32PDOffset;
- IMG_UINT32 ui32PTOffset;
-
- psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
-
- SysAcquireData(&psSysData);
-
- psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+ MMU_CONTEXT *psMMUContext = psDevInfo->pvMMUContextList;
-
- if(psLocalDevMemArena == IMG_NULL)
+ while (psMMUContext && (psMMUContext->sPDDevPAddr.uiAddr != ui32PDDevPAddr))
{
-
- eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- (IMG_VOID **)&pui32PT,
- &hPTPageOSMemHandle);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
- return eError;
- }
- ui32PTOffset = 0;
-
- eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- (IMG_VOID **)&pui32PD,
- &hPDPageOSMemHandle);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
- return eError;
- }
- ui32PDOffset = 0;
-
-
- if(pui32PT)
- {
- sCpuPAddr = OSMapLinToCPUPhys(hPTPageOSMemHandle,
- pui32PT);
- }
- else
- {
-
- sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0);
- }
- sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
-
- if(pui32PD)
- {
- sCpuPAddr = OSMapLinToCPUPhys(hPDPageOSMemHandle,
- pui32PD);
- }
- else
- {
-
- sCpuPAddr = OSMemHandleToCpuPAddr(hPDPageOSMemHandle, 0);
- }
- sPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
-
- }
- else
- {
-
-
- if(RA_Alloc(psLocalDevMemArena,
- SGX_MMU_PAGE_SIZE * 2,
- IMG_NULL,
- IMG_NULL,
- 0,
- SGX_MMU_PAGE_SIZE,
- 0,
- &(psDevInfo->sBRN22997SysPAddr.uiAddr))!= IMG_TRUE)
- {
- PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to RA_Alloc failed"));
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
-
-
- sCpuPAddr = SysSysPAddrToCpuPAddr(psDevInfo->sBRN22997SysPAddr);
- pui32PT = OSMapPhysToLin(sCpuPAddr,
- SGX_MMU_PAGE_SIZE * 2,
- PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
- &hPTPageOSMemHandle);
- if(!pui32PT)
- {
- PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR failed to map page tables"));
- return PVRSRV_ERROR_BAD_MAPPING;
- }
- ui32PTOffset = 0;
-
-
- sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
-
- pui32PD = pui32PT + SGX_MMU_PAGE_SIZE/sizeof(IMG_UINT32);
- ui32PDOffset = SGX_MMU_PAGE_SIZE;
- hPDPageOSMemHandle = hPTPageOSMemHandle;
- sPDDevPAddr.uiAddr = sPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+ psMMUContext = psMMUContext->psNext;
}
- OSMemSet(pui32PD, 0, SGX_MMU_PAGE_SIZE);
- OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE);
-
-
- PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDPageOSMemHandle, ui32PDOffset, pui32PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
- PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPTPageOSMemHandle, ui32PTOffset, pui32PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
-
- psDevInfo->hBRN22997PTPageOSMemHandle = hPTPageOSMemHandle;
- psDevInfo->hBRN22997PDPageOSMemHandle = hPDPageOSMemHandle;
- psDevInfo->sBRN22997PTDevPAddr = sPTDevPAddr;
- psDevInfo->sBRN22997PDDevPAddr = sPDDevPAddr;
- psDevInfo->pui32BRN22997PD = pui32PD;
- psDevInfo->pui32BRN22997PT = pui32PT;
-
- return PVRSRV_OK;
-}
-
-
-IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo)
-{
- IMG_UINT32 *pui32PD = psDevInfo->pui32BRN22997PD;
- IMG_UINT32 *pui32PT = psDevInfo->pui32BRN22997PT;
- IMG_UINT32 ui32PDIndex;
- IMG_UINT32 ui32PTIndex;
- IMG_DEV_VIRTADDR sDevVAddr;
- volatile IMG_UINT32 *pui32HostPort;
- IMG_UINT32 ui32BIFCtrl;
-
-
-
-
- pui32HostPort = (volatile IMG_UINT32*)(((IMG_UINT8*)psDevInfo->pvHostPortBaseKM) + SYS_SGX_HOSTPORT_BRN23030_OFFSET);
-
-
- sDevVAddr.uiAddr = SYS_SGX_HOSTPORT_BASE_DEVVADDR + SYS_SGX_HOSTPORT_BRN23030_OFFSET;
-
- ui32PDIndex = (sDevVAddr.uiAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
- ui32PTIndex = (sDevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
-
-
- pui32PD[ui32PDIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
- | SGX_MMU_PDE_VALID;
-
- pui32PT[ui32PTIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
- | SGX_MMU_PTE_VALID;
-
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
-
-
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0,
- psDevInfo->sBRN22997PDDevPAddr.uiAddr);
- PDUMPPDREG(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sBRN22997PDDevPAddr.uiAddr, PDUMP_PD_UNIQUETAG);
-
-
- ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
- PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
- PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl);
-
-
- if (pui32HostPort)
+ if (psMMUContext)
{
-
- IMG_UINT32 ui32Tmp;
- ui32Tmp = *pui32HostPort;
- }
- else
- {
- PVR_DPF((PVR_DBG_ERROR,"Host Port not present for BRN22997 workaround"));
- }
-
-
-
-
-
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 ui32PDIndex;
-
- PDUMPCOMMENT("RDW :SGXMEM:v4:%08X\r\n", sDevVAddr.uiAddr);
-
- PDUMPCOMMENT("SAB :SGXMEM:v4:%08X 4 0 hostport.bin", sDevVAddr.uiAddr);
-
-
- pui32PD[ui32PDIndex] = 0;
- pui32PT[ui32PTIndex] = 0;
-
-
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+ PVR_LOG(("Found MMU context for page fault 0x%08x", ui32FaultAddr));
+ PVR_LOG(("GPU memory context is for PID=%d (%s)", psMMUContext->ui32PID, psMMUContext->szName));
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
- PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
- PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl);
-}
+ ui32PTIndex = (ui32FaultAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+ ui32PDIndex = (ui32FaultAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PT_SHIFT + SGX_MMU_PAGE_SHIFT);
-
-IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode)
-{
- SYS_DATA *psSysData;
- RA_ARENA *psLocalDevMemArena;
- PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
-
-
- SysAcquireData(&psSysData);
-
- psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
-
- PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PDPageOSMemHandle, psDevInfo->pui32BRN22997PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
- PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PTPageOSMemHandle, psDevInfo->pui32BRN22997PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
-
-
- if(psLocalDevMemArena == IMG_NULL)
- {
- if (psDevInfo->pui32BRN22997PD != IMG_NULL)
+ if (psMMUContext->apsPTInfoList[ui32PDIndex])
{
- OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- psDevInfo->pui32BRN22997PD,
- psDevInfo->hBRN22997PDPageOSMemHandle);
- }
+ if (psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
+ {
+ IMG_UINT32 *pui32Ptr = psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+ IMG_UINT32 ui32PTE = pui32Ptr[ui32PTIndex];
- if (psDevInfo->pui32BRN22997PT != IMG_NULL)
- {
- OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- psDevInfo->pui32BRN22997PT,
- psDevInfo->hBRN22997PTPageOSMemHandle);
+ PVR_LOG(("PDE valid: PTE = 0x%08x (PhysAddr = 0x%08x, %s)",
+ ui32PTE,
+ ui32PTE & SGX_MMU_PTE_ADDR_MASK,
+ ui32PTE & SGX_MMU_PTE_VALID?"valid":"Invalid"));
+ }
+ else
+ {
+ PVR_LOG(("Found PT info but no CPU address"));
+ }
}
- }
- else
- {
- if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+ else
{
- OSUnMapPhysToLin(psDevInfo->pui32BRN22997PT,
- SGX_MMU_PAGE_SIZE * 2,
- PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
- psDevInfo->hBRN22997PTPageOSMemHandle);
-
-
- RA_Free(psLocalDevMemArena, psDevInfo->sBRN22997SysPAddr.uiAddr, IMG_FALSE);
+ PVR_LOG(("No PDE found"));
}
}
}
-#endif
-
#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapExtSystemCacheRegs
+
+ PURPOSE: maps external system cache control registers into SGX MMU
+
+ PARAMETERS: In: psDeviceNode - device node
+ RETURNS:
+******************************************************************************/
PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
{
IMG_UINT32 *pui32PT;
pui32PT = (IMG_UINT32 *) psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
-
+ MakeKernelPageReadWrite(pui32PT);
+ /* map the PT to the registers */
pui32PT[ui32PTIndex] = (psDevInfo->sExtSysCacheRegsDevPBase.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
-
+ MakeKernelPageReadOnly(pui32PT);
#if defined(PDUMP)
-
+ /* Add the entery to the PT */
{
IMG_DEV_PHYADDR sDevPAddr;
IMG_CPU_PHYADDR sCpuPAddr;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_UnmapExtSystemCacheRegs
+
+ PURPOSE: unmaps external system cache control registers
+
+ PARAMETERS: In: psDeviceNode - device node
+ RETURNS:
+******************************************************************************/
PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
{
SYS_DATA *psSysData;
psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
-
+ /* unmap the MMU page table from the PD */
ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
-
+ /* Only unmap it if the PT hasn't already been freed */
if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex])
{
if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
}
}
+ MakeKernelPageReadWrite(pui32PT);
pui32PT[ui32PTIndex] = 0;
+ MakeKernelPageReadOnly(pui32PT);
PDUMPMEMPTENTRIES(&sMMUAttrib, psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->hPDOSMemHandle, &pui32PT[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
#if PAGE_TEST
+/*!
+******************************************************************************
+ FUNCTION: PageTest
+
+ PURPOSE: Tests page table memory, for use during device bring-up.
+
+ PARAMETERS: In: void* pMem - page address (CPU mapped)
+ PARAMETERS: In: IMG_DEV_PHYADDR sDevPAddr - page device phys address
+ RETURNS: None, provides debug output and breaks if an error is detected.
+******************************************************************************/
static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
{
volatile IMG_UINT32 ui32WriteData;
if (ui32WriteData != ui32ReadData)
{
-
+ // Mem fault
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 (ui32WriteData != ui32ReadData)
{
-
+ // Mem fault
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;
}
#endif
+/******************************************************************************
+ End of file (mmu.c)
+******************************************************************************/
+
+
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title MMU Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements basic low level control of MMU.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _MMU_H_
#define _MMU_H_
#include "sgxinfokm.h"
+/*
+******************************************************************************
+ FUNCTION: MMU_Initialise
+
+ PURPOSE: Initialise the mmu module.
+
+ PARAMETERS: None
+ RETURNS: PVRSRV_ERROR
+******************************************************************************/
PVRSRV_ERROR
MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr);
+/*
+******************************************************************************
+ FUNCTION: MMU_Finalise
+
+ PURPOSE: Finalise the mmu module, deallocate all resources.
+
+ PARAMETERS: None.
+ RETURNS: None.
+******************************************************************************/
IMG_VOID
MMU_Finalise (MMU_CONTEXT *psMMUContext);
+/*
+******************************************************************************
+ FUNCTION: MMU_InsertHeap
+
+ PURPOSE: Inserts shared heap into the specified context
+ from the kernel context
+
+ PARAMETERS: None.
+ RETURNS: None.
+******************************************************************************/
IMG_VOID
MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap);
+/*
+******************************************************************************
+ FUNCTION: MMU_Create
+
+ PURPOSE: Create an mmu device.
+
+ PARAMETERS: In: psMMUContext -
+ In: psDevArena -
+ Out: ppsVMArena
+ RETURNS: MMU_HEAP
+******************************************************************************/
MMU_HEAP *
MMU_Create (MMU_CONTEXT *psMMUContext,
DEV_ARENA_DESCRIPTOR *psDevArena,
RA_ARENA **ppsVMArena,
PDUMP_MMU_ATTRIB **ppsMMUAttrib);
+/*
+******************************************************************************
+ FUNCTION: MMU_Delete
+
+ PURPOSE: Delete an mmu device.
+
+ PARAMETERS: In: pMMUHeap - The mmu to delete.
+ RETURNS:
+******************************************************************************/
IMG_VOID
MMU_Delete (MMU_HEAP *pMMUHeap);
+/*
+******************************************************************************
+ FUNCTION: MMU_Alloc
+ PURPOSE: Allocate space in an mmu's virtual address space.
+ PARAMETERS: In: pMMUHeap - MMU to allocate on.
+ In: uSize - Size in bytes to allocate.
+ Out: pActualSize - If non null receives actual size allocated.
+ In: uFlags - Allocation flags.
+ In: uDevVAddrAlignment - Required alignment.
+ Out: pDevVAddr - Receives base address of allocation.
+ RETURNS: IMG_TRUE - Success
+ IMG_FALSE - Failure
+******************************************************************************/
IMG_BOOL
MMU_Alloc (MMU_HEAP *pMMUHeap,
IMG_SIZE_T uSize,
IMG_UINT32 uDevVAddrAlignment,
IMG_DEV_VIRTADDR *pDevVAddr);
+/*
+******************************************************************************
+ FUNCTION: MMU_Free
+ PURPOSE: Frees space in an mmu's virtual address space.
+ PARAMETERS: In: pMMUHeap - MMU to free on.
+ In: DevVAddr - Base address of allocation.
+ RETURNS: IMG_TRUE - Success
+ IMG_FALSE - Failure
+******************************************************************************/
IMG_VOID
MMU_Free (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
IMG_UINT32 ui32Size);
+/*
+******************************************************************************
+ FUNCTION: MMU_Enable
+
+ PURPOSE: Enable an mmu. Establishes pages tables and takes the mmu out
+ of bypass and waits for the mmu to acknowledge enabled.
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_Enable (MMU_HEAP *pMMUHeap);
+/*
+******************************************************************************
+ FUNCTION: MMU_Disable
+
+ PURPOSE: Disable an mmu, takes the mmu into bypass.
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_Disable (MMU_HEAP *pMMUHeap);
+/*
+******************************************************************************
+ FUNCTION: MMU_MapPages
+
+ PURPOSE: Create a mapping for a range of pages from a device physical
+ adddress to a specified device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: SysPAddr - the system physical address of the page to map.
+ In: uSize - size of memory range in bytes
+ In: ui32MemFlags - page table flags.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapPages (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
IMG_UINT32 ui32MemFlags,
IMG_HANDLE hUniqueTag);
+/*
+******************************************************************************
+ FUNCTION: MMU_MapPagesSparse
+
+ PURPOSE: Create a mapping for a range of pages from a device physical
+ adddress to a specified device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: SysPAddr - the system physical address of the page to map.
+ In: ui32ChunkSize - Size of the chunk (must be page multiple)
+ In: ui32NumVirtChunks - Number of virtual chunks
+ In: ui32NumPhysChunks - Number of physical chunks
+ In: pabMapChunk - Mapping array
+ In: ui32MemFlags - page table flags.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
+IMG_VOID
+MMU_MapPagesSparse (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+/*
+******************************************************************************
+ FUNCTION: MMU_MapShadow
+
+ PURPOSE: Create a mapping for a range of pages from a CPU virtual
+ adddress to a specified device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: MapBaseDevVAddr - A page aligned device virtual address
+ to start mapping from.
+ In: uByteSize - A page aligned mapping length in bytes.
+ In: CpuVAddr - A page aligned CPU virtual address.
+ In: hOSMemHandle - An alternative OS specific memory handle
+ for mapping RAM without a CPU virtual
+ address
+ Out: pDevVAddr - deprecated
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ In: ui32MemFlags - page table flags.
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapShadow (MMU_HEAP * pMMUHeap,
IMG_DEV_VIRTADDR MapBaseDevVAddr,
- IMG_SIZE_T uByteSize,
+ IMG_SIZE_T uByteSize,
IMG_CPU_VIRTADDR CpuVAddr,
IMG_HANDLE hOSMemHandle,
IMG_DEV_VIRTADDR * pDevVAddr,
IMG_UINT32 ui32MemFlags,
IMG_HANDLE hUniqueTag);
+/*
+******************************************************************************
+ FUNCTION: MMU_MapShadowSparse
+
+ PURPOSE: Create a mapping for a range of pages from a CPU virtual
+ adddress to a specified device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: MapBaseDevVAddr - A page aligned device virtual address
+ to start mapping from.
+ In: ui32ChunkSize - Size of the chunk (must be page multiple)
+ In: ui32NumVirtChunks - Number of virtual chunks
+ In: ui32NumPhysChunks - Number of physical chunks
+ In: pabMapChunk - Mapping array
+ In: CpuVAddr - A page aligned CPU virtual address.
+ In: hOSMemHandle - An alternative OS specific memory handle
+ for mapping RAM without a CPU virtual
+ address
+ Out: pDevVAddr - deprecated
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ In: ui32MemFlags - page table flags.
+ RETURNS: None
+******************************************************************************/
+IMG_VOID
+MMU_MapShadowSparse (MMU_HEAP * pMMUHeap,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL * pabMapChunk,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR * pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+/*
+******************************************************************************
+ FUNCTION: MMU_UnmapPages
+
+ PURPOSE: unmaps pages and invalidates virtual address.
+
+ PARAMETERS: In: psMMUHeap - the mmu.
+ In: sDevVAddr - the device virtual address.
+ In: ui32PageCount - page count.
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_UnmapPages (MMU_HEAP *psMMUHeap,
IMG_DEV_VIRTADDR sDevVAddr,
IMG_UINT32 ui32PageCount,
IMG_HANDLE hUniqueTag);
+/*
+******************************************************************************
+ FUNCTION: MMU_MapScatter
+
+ PURPOSE: Create a mapping for a list of pages to a specified device
+ virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: psSysAddr - the list of physical addresses of the pages to
+ map.
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapScatter (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
IMG_HANDLE hUniqueTag);
+/*
+******************************************************************************
+ FUNCTION: MMU_GetPhysPageAddr
+
+ PURPOSE: extracts physical address from MMU page tables
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ PARAMETERS: In: sDevVPageAddr - the virtual address to extract physical
+ page mapping from
+ RETURNS: IMG_DEV_PHYADDR
+******************************************************************************/
IMG_DEV_PHYADDR
MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+/*
+******************************************************************************
+ FUNCTION: MMU_GetPDDevPAddr
+
+ PURPOSE: returns PD given the MMU context (SGX to MMU API)
+
+ PARAMETERS: In: pMMUContext - the mmu
+ RETURNS: IMG_DEV_PHYADDR
+******************************************************************************/
IMG_DEV_PHYADDR
MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext);
#ifdef SUPPORT_SGX_MMU_BYPASS
+/*
+******************************************************************************
+ FUNCTION: EnableHostAccess
+
+ PURPOSE: Enables Host accesses to device memory, by passing the device
+ MMU address translation
+
+ PARAMETERS: In: psMMUContext
+ RETURNS: None
+******************************************************************************/
IMG_VOID
EnableHostAccess (MMU_CONTEXT *psMMUContext);
+/*
+******************************************************************************
+ FUNCTION: DisableHostAccess
+
+ PURPOSE: Disables Host accesses to device memory, by passing the device
+ MMU address translation
+
+ PARAMETERS: In: psMMUContext
+ RETURNS: None
+******************************************************************************/
IMG_VOID
DisableHostAccess (MMU_CONTEXT *psMMUContext);
#endif
+/*
+******************************************************************************
+ FUNCTION: MMU_InvalidateDirectoryCache
+
+ PURPOSE: Invalidates the page directory cache
+
+ PARAMETERS: In: psDevInfo
+ RETURNS: None
+******************************************************************************/
IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo);
-PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo);
+/*
+******************************************************************************
+ FUNCTION: MMU_BIFResetPDAlloc
-IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo);
+ PURPOSE: Allocate a dummy Page Directory which causes all virtual
+ addresses to page fault.
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
-PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE *psDeviceNode);
+ PARAMETERS: In: psDevInfo - device info
+ RETURNS: PVRSRV_OK or error
+******************************************************************************/
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo);
-IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo);
+/*
+******************************************************************************
+ FUNCTION: MMU_BIFResetPDFree
-IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode);
-#endif
+ PURPOSE: Free resources allocated in MMU_BIFResetPDAlloc.
+
+ PARAMETERS: In: psDevInfo - device info
+ RETURNS:
+******************************************************************************/
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo);
#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+/*
+******************************************************************************
+ FUNCTION: MMU_MapExtSystemCacheRegs
+
+ PURPOSE: maps external system cache control registers into SGX MMU
+
+ PARAMETERS: In: psDeviceNode - device node
+ RETURNS:
+******************************************************************************/
PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
-PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
-#endif
+/*
+******************************************************************************
+ FUNCTION: MMU_UnmapExtSystemCacheRegs
+ PURPOSE: unmaps external system cache control registers
+
+ PARAMETERS: In: psDeviceNode - device node
+ RETURNS:
+******************************************************************************/
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif /* #if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE) */
+
+/*
+******************************************************************************
+ FUNCTION: MMU_IsHeapShared
+
+ PURPOSE: Is this heap shared?
+ PARAMETERS: In: pMMU_Heap
+ RETURNS: true if heap is shared
+******************************************************************************/
IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMU_Heap);
#if defined(FIX_HW_BRN_31620)
+/*
+******************************************************************************
+ FUNCTION: MMU_GetCacheFlushRange
+
+ PURPOSE: Gets device physical address of the mmu context.
+
+ PARAMETERS: In: pMMUContext - the mmu context
+ Out: pui32RangeMask - Bit mask showing which PD cache
+ lines have changed
+ RETURNS: None
+******************************************************************************/
IMG_VOID MMU_GetCacheFlushRange(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask);
+/*
+******************************************************************************
+ FUNCTION: MMU_GetPDPhysAddr
+
+ PURPOSE: Gets device physical address of the mmu contexts PD.
+
+ PARAMETERS: In: pMMUContext - the mmu context
+ Out: psDevPAddr - Address of PD
+ RETURNS: None
+******************************************************************************/
IMG_VOID MMU_GetPDPhysAddr(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr);
#endif
+IMG_VOID MMU_CheckFaultAddr(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32PDDevPAddr, IMG_UINT32 ui32RegVal);
+
#if defined(PDUMP)
+/*
+******************************************************************************
+ FUNCTION: MMU_GetPDumpContextID
+
+ PURPOSE: translates device mem context to unique pdump identifier
+
+ PARAMETERS: In: hDevMemContext - device memory per-process context
+ RETURNS: context identifier used internally in pdump
+******************************************************************************/
IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext);
-#endif
+#endif /* #ifdef PDUMP */
-#endif
+#endif /* #ifndef _MMU_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Parameter Buffer management functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <stddef.h>
#include "pdump_km.h"
#include "sgxutils.h"
-#ifndef __linux__
-#pragma message("TODO: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
+#if !defined(__linux__) && !defined(__QNXNTO__)
+#pragma message("FIXME: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
#endif
#include "lists.h"
static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy);
static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy);
+/* override level pointer indirection */
+/* PRQA S 5102 12 */
IMG_EXPORT PVRSRV_ERROR
SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevCookie,
sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount,
ppsSharedPBDescSubKernelMemInfos,
0);
-
+ /*not nulling pointer, out of scope*/
PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
static PVRSRV_ERROR
SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
{
-
+ /*PVRSRV_STUB_PBDESC **ppsStubPBDesc;*/
IMG_UINT32 i;
PVRSRV_DEVICE_NODE *psDeviceNode;
psDeviceNode = (PVRSRV_DEVICE_NODE*)psStubPBDescIn->hDevCookie;
-
-
-
psStubPBDescIn->ui32RefCount--;
if (psStubPBDescIn->ui32RefCount == 0)
{
List_PVRSRV_STUB_PBDESC_Remove(psStubPBDescIn);
for(i=0 ; i<psStubPBDescIn->ui32SubKernelMemInfosCount; i++)
{
-
PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie,
psStubPBDescIn->ppsSubKernelMemInfos[i]);
}
sizeof(PVRSRV_STUB_PBDESC),
psStubPBDescIn,
0);
-
+ /*not nulling pointer, copy on stack*/
-
+ /* signal the microkernel to clear its sTAHWPBDesc and s3DHWPBDesc values in sTA3DCtl */
SGXCleanupRequest(psDeviceNode,
&sHWPBDescDevVAddr,
PVRSRV_CLEANUPCMD_PB,
CLEANUP_WITH_POLL);
}
return PVRSRV_OK;
-
+ /*return PVRSRV_ERROR_INVALID_PARAMS;*/
}
static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy)
PVRSRV_SGXDEV_INFO *psSGXDevInfo;
PRESMAN_ITEM psResItem;
-
+ /*
+ * The caller must have previously called SGXFindSharedPBDesc with
+ * bLockOnFailure set, and not managed to find a suitable shared PB.
+ */
if (psPerProcCreateSharedPB != psPerProc)
{
goto NoAdd;
}
-
+ /*
+ * We make the caller think the add was successful,
+ * but return the existing shared PB desc rather than
+ * a new one.
+ */
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_SHARED_PB_DESC,
psStubPBDesc,
goto NoAddKeepPB;
}
-
+ /*
+ * The caller will unreference the PB desc after
+ * a successful add, so up the reference count.
+ */
psStubPBDesc->ui32RefCount++;
*phSharedPBDesc = (IMG_HANDLE)psResItem;
}
psStubPBDesc->hDevCookie = hDevCookie;
-
+ /* Finally everything was prepared successfully so link the new
+ * PB in to place. */
List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM),
psStubPBDesc);
sizeof(PVRSRV_STUB_PBDESC),
psStubPBDesc,
0);
-
+ /*not nulling pointer, out of scope*/
}
NoAddKeepPB:
return eRet;
}
+/******************************************************************************
+ End of file (pb.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the SGX Bridge code
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined(__SGX_BRIDGE_KM_H__)
#define __SGX_BRIDGE_KM_H__
SGX_BRIDGE_INIT_INFO *psInitInfo);
#endif
+/*!
+ * *****************************************************************************
+ * @brief Looks for a parameter buffer description that corresponds to
+ * a buffer of size ui32TotalPBSize, optionally taking the lock
+ * needed for SharedPBCreation on failure.
+ *
+ * Note if a PB Desc is found then its internal reference counter
+ * is automatically incremented. It is your responsability to call
+ * SGXUnrefSharedPBDesc to decrement this reference and free associated
+ * resources when you are done.
+ *
+ * If bLockOnFailure is set, and a suitable shared PB isn't found,
+ * an internal flag is set, allowing this process to create a
+ * shared PB. Any other process calling this function with
+ * bLockOnFailure set, will receive the return code
+ * PVRSRV_ERROR_PROCESSING_BLOCKED, indicating that it needs
+ * to retry the function call. The internal flag is cleared
+ * when this process creates a shared PB.
+ *
+ * Note: You are responsible for freeing the list returned in
+ * pppsSharedPBDescSubKernelMemInfos
+ * via OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ * sizeof(PVRSRV_KERNEL_MEM_INFO *)
+ * * ui32SharedPBDescSubKernelMemInfosCount,
+ * ppsSharedPBDescSubKernelMemInfos,
+ * NULL);
+ *
+ * @param[in] psPerProc
+ * @param[in] hDevCookie
+ * @param[in] bLockOnError
+ * @param[in] ui32TotalPBSize
+ * @param[in] phSharedPBDesc
+ * @param[out] ppsSharedPBDescKernelMemInfo
+ * @param[out] ppsHWPBDescKernelMemInfo
+ * @param[out] pppsSharedPBDescSubKernelMemInfos A list of integral sub meminfos.
+ * @param[out] ui32SharedPBDescSubKernelMemInfosCount
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
+/* disable QAC pointer level check for over 2 */
+/* PRQA S 5102++ */
IMG_IMPORT PVRSRV_ERROR
SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevCookie,
PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount);
+/*!
+ * *****************************************************************************
+ * @brief Decrements the reference counter and frees all userspace resources
+ * associated with a SharedPBDesc.
+ *
+ * @param hSharedPBDesc
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR
SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc);
+/*!
+ * *****************************************************************************
+ * @brief Links a new SharedPBDesc into a kernel managed list that can
+ * then be queried by other clients.
+ *
+ * As a side affect this function also dissociates the SharedPBDesc
+ * from the calling process so that the memory won't be freed if the
+ * process dies/exits. (The kernel assumes responsability over the
+ * memory at the same time)
+ *
+ * As well as the psSharedPBDescKernelMemInfo you must also pass
+ * a complete list of other meminfos that are integral to the
+ * shared PB description. (Although the kernel doesn't have direct
+ * access to the shared PB desc it still needs to be able to
+ * clean up all the associated resources when it is no longer
+ * in use.)
+ *
+ * If the dissociation fails then all the memory associated with
+ * the psSharedPBDescKernelMemInfo and all entries in psKernelMemInfos
+ * will be freed by kernel services! Because of this, you are
+ * responsible for freeing the corresponding client meminfos _before_
+ * calling SGXAddSharedPBDescKM.
+ *
+ * This function will return an error unless a succesful call to
+ * SGXFindSharedPBDesc, with bLockOnFailure set, has been made.
+ *
+ * @param psPerProc
+ * @param hDevCookie
+ * @param psSharedPBDescKernelMemInfo
+ * @param psHWPBDescKernelMemInfo
+ * @param psBlockKernelMemInfo
+ * @param ui32TotalPBSize The size of the associated parameter buffer
+ * @param ppsSharedPBDescSubKernelMemInfos A list of other meminfos integral to
+ * the shared PB description.
+ * @param ui32SharedPBDescSubKernelMemInfosCount The number of entires in
+ * psKernelMemInfos
+ * @param sHWPBDescDevVAddr The device virtual address of the HWPBDesc
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR
SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevCookie,
IMG_DEV_VIRTADDR sHWPBDescDevVAddr);
+/*!
+ * *****************************************************************************
+ * @brief Gets device information that is not intended to be passed
+ on beyond the srvclient libs.
+ *
+ * @param[in] hDevCookie
+ * @param[out] psSGXInternalDevInfo
+ *
+ * @return
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR
SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
#if defined (SUPPORT_SID_INTERFACE)
}
#endif
-#endif
+#endif /* __SGX_BRIDGE_KM_H__ */
+/******************************************************************************
+ End of file (sgx_bridge_km.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title device configuration
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __SGXCONFIG_H__
#define __SGXCONFIG_H__
#define SGX_KERNEL_DATA_HEAP_OFFSET 0x00000000
#endif
+#if !defined(ION_HEAP_SIZE) && defined(SUPPORT_ION)
+ /* Default the Ion heap to 16MB */
+ #define ION_HEAP_SIZE 0x01000000
+#else
+ #define ION_HEAP_SIZE 0
+#endif
+
+
#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32
#if defined(FIX_HW_BRN_31620)
#if defined(SGX_FEATURE_2D_HARDWARE)
#define SGX_GENERAL_HEAP_BASE 0x08000000
#define SGX_GENERAL_HEAP_SIZE (0xB8000000-0x00001000)
-
+ /*
+ * For hybrid PB we have to split virtual PB range between the shared
+ * PB and percontext PB due to the fact we only have one heap config
+ * per device.
+ * If hybrid PB is enabled we split the space acording to HYBRID_SHARED_PB_SIZE.
+ * i.e. HYBRID_SHARED_PB_SIZE defines the size of the shared PB and the
+ * remainder is the size of the percontext PB.
+ * If hybrid PB is not enabled then we still create both heaps (helps keep
+ * the code clean) and define the size of the unused one to 0
+ */
+
#define SGX_3DPARAMETERS_HEAP_SIZE 0x10000000
-
+ /* By default we split the PB 50/50 */
#if !defined(HYBRID_SHARED_PB_SIZE)
#define HYBRID_SHARED_PB_SIZE (SGX_3DPARAMETERS_HEAP_SIZE >> 1)
#endif
#endif
#define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0xC0000000
-
+ /* Size is defiend above */
#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
-
+ /* Size is defiend above */
#define SGX_TADATA_HEAP_BASE 0xD0000000
#define SGX_TADATA_HEAP_SIZE (0x0D000000-0x00001000)
#define SGX_KERNEL_DATA_HEAP_BASE (0xF0000000+SGX_KERNEL_DATA_HEAP_OFFSET)
#define SGX_KERNEL_DATA_HEAP_SIZE (0x03000000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
-
+ /* Actual Pixel and Vertex shared heaps sizes may be reduced by
+ * override - see SGX_USE_CODE_SEGMENT_RANGE_BITS.*/
#define SGX_PIXELSHADER_HEAP_BASE 0xF4000000
#define SGX_PIXELSHADER_HEAP_SIZE (0x05000000-0x00001000)
#define SGX_VERTEXSHADER_HEAP_BASE 0xFC000000
#define SGX_VERTEXSHADER_HEAP_SIZE (0x02000000-0x00001000)
-#else
+#else /* FIX_HW_BRN_31620 */
#if defined(SGX_FEATURE_2D_HARDWARE)
#define SGX_2D_HEAP_BASE 0x00100000
#define SGX_2D_HEAP_SIZE (0x08000000-0x00100000-0x00001000)
- #else
- #if defined(FIX_HW_BRN_26915)
- #define SGX_CGBUFFER_HEAP_BASE 0x00100000
- #define SGX_CGBUFFER_HEAP_SIZE (0x08000000-0x00100000-0x00001000)
- #endif
#endif
#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
#define SGX_GENERAL_MAPPING_HEAP_SIZE (0x08000000-0x00001000)
#endif
- #define SGX_GENERAL_HEAP_BASE 0x10000000
- #define SGX_GENERAL_HEAP_SIZE (0xC2000000-0x00001000)
+ #if !defined(SUPPORT_MEMORY_TILING)
+ #if defined (SUPPORT_ION)
+ #define SGX_GENERAL_HEAP_BASE 0x10000000
+ #define SGX_GENERAL_HEAP_SIZE (0xC2000000-ION_HEAP_SIZE-0x00001000)
+
+ #define SGX_ION_HEAP_BASE (SGX_GENERAL_HEAP_BASE+SGX_GENERAL_HEAP_SIZE+0x00001000)
+ #define SGX_ION_HEAP_SIZE (ION_HEAP_SIZE-0x00001000)
+ #else
+ #define SGX_GENERAL_HEAP_BASE 0x10000000
+ #define SGX_GENERAL_HEAP_SIZE (0xC2000000-0x00001000)
+ #endif
+ #else
+ #include <sgx_msvdx_defs.h>
+ /* Create heaps with memory tiling enabled.
+ * SGX HW limit is 10 heaps.
+ */
+ /* Tiled heap space is taken from general heap */
+ #define SGX_GENERAL_HEAP_BASE 0x10000000
+ #define SGX_GENERAL_HEAP_SIZE (0xB5000000-0x00001000)
+
+ #define SGX_VPB_TILED_HEAP_STRIDE TILING_TILE_STRIDE_2K
+ #define SGX_VPB_TILED_HEAP_BASE 0xC5000000
+ #define SGX_VPB_TILED_HEAP_SIZE (0x0D000000-0x00001000)
+
+ /* Check tiled heap base alignment */
+ #if((SGX_VPB_TILED_HEAP_BASE & SGX_BIF_TILING_ADDR_INV_MASK) != 0)
+ #error "sgxconfig.h: SGX_VPB_TILED_HEAP has insufficient alignment"
+ #endif
+
+ #endif /* SUPPORT_MEMORY_TILING */
+
+ /*
+ * For hybrid PB we have to split virtual PB range between the shared
+ * PB and percontext PB due to the fact we only have one heap config
+ * per device.
+ * If hybrid PB is enabled we split the space acording to HYBRID_SHARED_PB_SIZE.
+ * i.e. HYBRID_SHARED_PB_SIZE defines the size of the shared PB and the
+ * remainder is the size of the percontext PB.
+ * If hybrid PB is not enabled then we still create both heaps (helps keep
+ * the code clean) and define the size of the unused one to 0
+ */
-
#define SGX_3DPARAMETERS_HEAP_SIZE 0x10000000
-
+ /* By default we split the PB 50/50 */
#if !defined(HYBRID_SHARED_PB_SIZE)
#define HYBRID_SHARED_PB_SIZE (SGX_3DPARAMETERS_HEAP_SIZE >> 1)
#endif
#endif
#define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0xD2000000
-
+ /* Size is defiend above */
#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
-
+ /* Size is defiend above */
#define SGX_TADATA_HEAP_BASE 0xE2000000
#define SGX_TADATA_HEAP_SIZE (0x0D000000-0x00001000)
#define SGX_KERNEL_DATA_HEAP_BASE (0xF4000000+SGX_KERNEL_DATA_HEAP_OFFSET)
#define SGX_KERNEL_DATA_HEAP_SIZE (0x05000000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
-
+ /* Actual Pixel and Vertex shared heaps sizes may be reduced by
+ * override - see SGX_USE_CODE_SEGMENT_RANGE_BITS.*/
#define SGX_PIXELSHADER_HEAP_BASE 0xF9000000
#define SGX_PIXELSHADER_HEAP_SIZE (0x05000000-0x00001000)
#define SGX_VERTEXSHADER_HEAP_BASE 0xFE000000
#define SGX_VERTEXSHADER_HEAP_SIZE (0x02000000-0x00001000)
-#endif
-
+#endif /* FIX_HW_BRN_31620 */
+ /* signal we've identified the core by the build */
#define SGX_CORE_IDENTIFIED
-#endif
+#endif /* SGX_FEATURE_ADDRESS_SPACE_SIZE == 32 */
#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
#define SGX_GENERAL_MAPPING_HEAP_SIZE (0x01800000-0x00001000-0x00001000)
#define SGX_GENERAL_HEAP_BASE 0x01800000
- #define SGX_GENERAL_HEAP_SIZE (0x07000000-0x00001000)
+ #define SGX_GENERAL_HEAP_SIZE (0x07000000-ION_HEAP_SIZE-0x00001000)
#else
#define SGX_GENERAL_HEAP_BASE 0x00001000
- #define SGX_GENERAL_HEAP_SIZE (0x08800000-0x00001000-0x00001000)
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
+ #define SGX_GENERAL_HEAP_SIZE (0x0B800000-ION_HEAP_SIZE-0x00001000-0x00001000)
+#else
+ #define SGX_GENERAL_HEAP_SIZE (0x08800000-ION_HEAP_SIZE-0x00001000-0x00001000)
#endif
-
+#endif
+
+#if defined(SUPPORT_ION)
+ #define SGX_ION_HEAP_BASE (SGX_GENERAL_HEAP_BASE+SGX_GENERAL_HEAP_SIZE+0x00001000)
+ #define SGX_ION_HEAP_SIZE (ION_HEAP_SIZE-0x00001000)
+#endif
+ /*
+ * For hybrid PB we have to split virtual PB range between the shared
+ * PB and percontext PB due to the fact we only have one heap config
+ * per device.
+ * If hybrid PB is enabled we split the space acording to HYBRID_SHARED_PB_SIZE.
+ * i.e. HYBRID_SHARED_PB_SIZE defines the size of the shared PB and the
+ * remainder is the size of the percontext PB.
+ * If hybrid PB is not enabled then we still create both heaps (helps keep
+ * the code clean) and define the size of the unused one to 0
+ */
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
+ #define SGX_3DPARAMETERS_HEAP_SIZE 0x01000000
+#else
#define SGX_3DPARAMETERS_HEAP_SIZE 0x04000000
+#endif
-
+ /* By default we split the PB 50/50 */
#if !defined(HYBRID_SHARED_PB_SIZE)
#define HYBRID_SHARED_PB_SIZE (SGX_3DPARAMETERS_HEAP_SIZE >> 1)
#endif
#endif
#endif
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
+ #define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0x0B800000
+#else
#define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0x08800000
-
+#endif
+
+ /* Size is defined above */
#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
-
+ /* Size is defined above */
#define SGX_TADATA_HEAP_BASE 0x0C800000
#define SGX_TADATA_HEAP_SIZE (0x01000000-0x00001000)
#define SGX_VERTEXSHADER_HEAP_BASE 0x0FC00000
#define SGX_VERTEXSHADER_HEAP_SIZE (0x00200000-0x00001000)
-
+ /* signal we've identified the core by the build */
#define SGX_CORE_IDENTIFIED
-#endif
+#endif /* SGX_FEATURE_ADDRESS_SPACE_SIZE == 28 */
#if !defined(SGX_CORE_IDENTIFIED)
#error "sgxconfig.h: ERROR: unspecified SGX Core version"
#endif
+/*********************************************************************************
+ *
+ * SGX_PDSPIXEL_CODEDATA_HEAP_BASE + 64MB range must include PDSVERTEX_CODEDATA and KERNEL_CODE heaps
+ *
+ ********************************************************************************/
#if !defined (SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE)
#if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) > 0x4000000)
#error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
#endif
#endif
+/*********************************************************************************
+ *
+ * The General Mapping heap must be within the 2D requestor range of the 2D heap base
+ *
+ ********************************************************************************/
#if defined(SGX_FEATURE_2D_HARDWARE) && defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
#if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE - SGX_2D_HEAP_BASE) >= EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK)
#error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP inaccessable by 2D requestor"
#endif
#endif
+/*********************************************************************************
+ *
+ * The kernel code heap base must be aligned to a USSE code page
+ *
+ ********************************************************************************/
#if defined (EURASIA_USE_CODE_PAGE_SIZE)
#if ((SGX_KERNEL_CODE_HEAP_BASE & (EURASIA_USE_CODE_PAGE_SIZE - 1)) != 0)
#error "sgxconfig.h: ERROR: Kernel code heap base misalignment"
#endif
#endif
+/*********************************************************************************
+ *
+ * Heap overlap check
+ *
+ ********************************************************************************/
#if defined(SGX_FEATURE_2D_HARDWARE)
#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
#if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
#error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_HEAP_BASE"
#endif
#endif
-#else
- #if defined(FIX_HW_BRN_26915)
- #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
- #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
- #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_MAPPING_HEAP"
- #endif
- #else
- #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
- #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_HEAP_BASE"
- #endif
- #endif
- #endif
#endif
#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
#endif
#endif
-#if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
- #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+#if defined(SUPPORT_MEMORY_TILING)
+ #if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_VPB_TILED_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_VPB_TILED_HEAP"
+ #endif
+ #if ((SGX_VPB_TILED_HEAP_BASE + SGX_VPB_TILED_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_VPB_TILED_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+ #endif
+#else
+ #if defined(SUPPORT_ION)
+ #if ((SGX_ION_HEAP_BASE + SGX_ION_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_ION_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+ #endif
+ #endif
+ #if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+ #endif
#endif
#if (((SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE + SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE) >= SGX_TADATA_HEAP_BASE) && (SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE > 0))
#error "sgxconfig.h: ERROR: SGX_VERTEXSHADER_HEAP_BASE size cause wraparound"
#endif
-#endif
+#endif /* __SGXCONFIG_H__ */
+/*****************************************************************************
+ End of file (sgxconfig.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title SGX kernel services structues/functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Structures and inline functions for KM services component
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __SGXINFOKM_H__
#define __SGXINFOKM_H__
extern "C" {
#endif
+/****************************************************************************/
+/* kernel only defines: */
+/****************************************************************************/
+/* SGXDeviceMap Flag defines */
#define SGX_HOSTPORT_PRESENT 0x00000001UL
+/*
+ SGX PDUMP register bank name (prefix)
+*/
#define SGX_PDUMPREG_NAME "SGXREG"
+/****************************************************************************/
+/* kernel only structures: */
+/****************************************************************************/
+
+/*Forward declaration*/
typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
IMG_UINT32 ui32CoreConfig;
IMG_UINT32 ui32CoreFlags;
-
+ /* Kernel mode linear address of device registers */
IMG_PVOID pvRegsBaseKM;
#if defined(SGX_FEATURE_HOST_PORT)
-
+ /* Kernel mode linear address of host port */
IMG_PVOID pvHostPortBaseKM;
-
+ /* HP size */
IMG_UINT32 ui32HPSize;
-
+ /* HP syspaddr */
IMG_SYS_PHYADDR sHPSysPAddr;
#endif
-
+ /* FIXME: The alloc for this should go through OSAllocMem in future */
IMG_HANDLE hRegMapping;
-
+ /* System physical address of device registers*/
IMG_SYS_PHYADDR sRegsPhysBase;
-
+ /* Register region size in bytes */
IMG_UINT32 ui32RegSize;
#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
-
+ /* external system cache register region size in bytes */
IMG_UINT32 ui32ExtSysCacheRegsSize;
-
+ /* external system cache register device relative physical address */
IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase;
-
+ /* ptr to page table */
IMG_UINT32 *pui32ExtSystemCacheRegsPT;
-
+ /* handle to page table alloc/mapping */
IMG_HANDLE hExtSystemCacheRegsPTPageOSMemHandle;
-
+ /* sys phys addr of PT */
IMG_SYS_PHYADDR sExtSystemCacheRegsPTSysPAddr;
#endif
-
+ /* SGX clock speed */
IMG_UINT32 ui32CoreClockSpeed;
IMG_UINT32 ui32uKernelTimerClock;
+ IMG_BOOL bSGXIdle;
PVRSRV_STUB_PBDESC *psStubPBDescListKM;
-
+ /* kernel memory context info */
IMG_DEV_PHYADDR sKernelPDDevPAddr;
+ IMG_UINT32 ui32HeapCount; /*!< heap count */
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;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBMemInfo; /*!< meminfo for CCB in device accessible memory */
+ PVRSRV_SGX_KERNEL_CCB *psKernelCCB; /*!< kernel mode linear address of CCB in device accessible memory */
+ PPVRSRV_SGX_CCB_INFO psKernelCCBInfo; /*!< CCB information structure */
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBCtlMemInfo; /*!< meminfo for CCB control in device accessible memory */
+ PVRSRV_SGX_CCB_CTL *psKernelCCBCtl; /*!< kernel mode linear address of CCB control in device accessible memory */
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBEventKickerMemInfo; /*!< meminfo for kernel CCB event kicker */
+ IMG_UINT32 *pui32KernelCCBEventKicker; /*!< kernel mode linear address of kernel CCB event kicker */
#if defined(PDUMP)
- IMG_UINT32 ui32KernelCCBEventKickerDumpVal;
-#endif
- PVRSRV_KERNEL_MEM_INFO *psKernelSGXMiscMemInfo;
- IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX];
+ IMG_UINT32 ui32KernelCCBEventKickerDumpVal; /*!< pdump copy of the kernel CCB event kicker */
+#endif /* PDUMP */
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXMiscMemInfo; /*!< kernel mode linear address of SGX misc info buffer */
+ IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX]; /*!< ukernel host kick offests */
#if defined(SGX_SUPPORT_HWPROFILING)
PPVRSRV_KERNEL_MEM_INFO psKernelHWProfilingMemInfo;
#endif
- PPVRSRV_KERNEL_MEM_INFO psKernelHWPerfCBMemInfo;
- PPVRSRV_KERNEL_MEM_INFO psKernelTASigBufferMemInfo;
- PPVRSRV_KERNEL_MEM_INFO psKernel3DSigBufferMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelHWPerfCBMemInfo; /*!< Meminfo for hardware performace circular buffer */
+ PPVRSRV_KERNEL_MEM_INFO psKernelTASigBufferMemInfo; /*!< Meminfo for TA signature buffer */
+ PPVRSRV_KERNEL_MEM_INFO psKernel3DSigBufferMemInfo; /*!< Meminfo for 3D signature buffer */
#if defined(FIX_HW_BRN_29702)
- PPVRSRV_KERNEL_MEM_INFO psKernelCFIMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCFIMemInfo; /*!< Meminfo for cfi */
#endif
#if defined(FIX_HW_BRN_29823)
- PPVRSRV_KERNEL_MEM_INFO psKernelDummyTermStreamMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelDummyTermStreamMemInfo; /*!< Meminfo for dummy terminate stream */
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
- PPVRSRV_KERNEL_MEM_INFO psKernelVDMSnapShotBufferMemInfo;
- PPVRSRV_KERNEL_MEM_INFO psKernelVDMCtrlStreamBufferMemInfo;
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
+ PPVRSRV_KERNEL_MEM_INFO psKernelVDMSnapShotBufferMemInfo; /*!< Meminfo for dummy snapshot buffer */
+ PPVRSRV_KERNEL_MEM_INFO psKernelVDMCtrlStreamBufferMemInfo; /*!< Meminfo for dummy control stream */
#endif
#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
- PPVRSRV_KERNEL_MEM_INFO psKernelVDMStateUpdateBufferMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelVDMStateUpdateBufferMemInfo; /*!< Meminfo for state update buffer */
#endif
#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
- PPVRSRV_KERNEL_MEM_INFO psKernelEDMStatusBufferMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelEDMStatusBufferMemInfo; /*!< Meminfo for EDM status buffer */
#endif
-
+ /* Client reference count */
IMG_UINT32 ui32ClientRefCount;
-
+ /* cache control word for micro kernel cache flush/invalidates */
IMG_UINT32 ui32CacheControl;
-
+ /* client-side build options */
IMG_UINT32 ui32ClientBuildOptions;
-
+ /* client-side microkernel structure sizes */
SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
-
-
-
+ /*
+ if we don't preallocate the pagetables we must
+ insert newly allocated page tables dynamically
+ */
IMG_VOID *pvMMUContextList;
-
+ /* Copy of registry ForcePTOff entry */
IMG_BOOL bForcePTOff;
IMG_UINT32 ui32EDMTaskReg0;
IMG_UINT32 ui32MasterClkGateStatusMask;
IMG_UINT32 ui32MasterClkGateStatus2Reg;
IMG_UINT32 ui32MasterClkGateStatus2Mask;
-#endif
+#endif /* SGX_FEATURE_MP */
SGX_INIT_SCRIPTS sScripts;
-
+ /* Members associated with dummy PD needed for BIF reset */
IMG_HANDLE hBIFResetPDOSMemHandle;
IMG_DEV_PHYADDR sBIFResetPDDevPAddr;
IMG_DEV_PHYADDR sBIFResetPTDevPAddr;
IMG_UINT32 *pui32BIFResetPD;
IMG_UINT32 *pui32BIFResetPT;
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
-
- IMG_HANDLE hBRN22997PTPageOSMemHandle;
- IMG_HANDLE hBRN22997PDPageOSMemHandle;
- IMG_DEV_PHYADDR sBRN22997PTDevPAddr;
- IMG_DEV_PHYADDR sBRN22997PDDevPAddr;
- IMG_UINT32 *pui32BRN22997PT;
- IMG_UINT32 *pui32BRN22997PD;
- IMG_SYS_PHYADDR sBRN22997SysPAddr;
-#endif
#if defined(SUPPORT_HW_RECOVERY)
-
+ /* Timeout callback handle */
IMG_HANDLE hTimer;
-
+ /* HW recovery Time stamp */
IMG_UINT32 ui32TimeStamp;
#endif
-
+ /* Number of SGX resets */
IMG_UINT32 ui32NumResets;
-
+ /* host control */
PVRSRV_KERNEL_MEM_INFO *psKernelSGXHostCtlMemInfo;
SGXMKIF_HOST_CTL *psSGXHostCtl;
-
+ /* TA/3D control */
PVRSRV_KERNEL_MEM_INFO *psKernelSGXTA3DCtlMemInfo;
#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
IMG_UINT32 ui32Flags;
-
+ /* memory tiling range usage */
IMG_UINT32 ui32MemTilingUsage;
#if defined(PDUMP)
#endif
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* SGX MMU dummy page details */
IMG_VOID *pvDummyPTPageCpuVAddr;
IMG_DEV_PHYADDR sDummyPTDevPAddr;
IMG_HANDLE hDummyPTPageOSMemHandle;
IMG_UINT32 asSGXDevData[SGX_MAX_DEV_DATA];
#if defined(FIX_HW_BRN_31620)
-
+ /* Dummy page refs */
IMG_VOID *pvBRN31620DummyPageCpuVAddr;
IMG_HANDLE hBRN31620DummyPageOSMemHandle;
IMG_DEV_PHYADDR sBRN31620DummyPageDevPAddr;
-
+ /* Dummy PT refs */
IMG_VOID *pvBRN31620DummyPTCpuVAddr;
IMG_HANDLE hBRN31620DummyPTOSMemHandle;
IMG_DEV_PHYADDR sBRN31620DummyPTDevPAddr;
IMG_UINT32 ui32uKernelFreq;
} SGX_TIMING_INFORMATION;
+/* FIXME Rename this structure to sg more generalised as it's been extended*/
+/* SGX device map */
typedef struct _SGX_DEVICE_MAP_
{
IMG_UINT32 ui32Flags;
-
+ /* Registers */
IMG_SYS_PHYADDR sRegsSysPBase;
IMG_CPU_PHYADDR sRegsCpuPBase;
IMG_CPU_VIRTADDR pvRegsCpuVBase;
IMG_UINT32 ui32HPSize;
#endif
-
+ /* Local Device Memory Region: (if present) */
IMG_SYS_PHYADDR sLocalMemSysPBase;
IMG_DEV_PHYADDR sLocalMemDevPBase;
IMG_CPU_PHYADDR sLocalMemCpuPBase;
IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase;
#endif
-
+ /* device interrupt IRQ */
IMG_UINT32 ui32IRQ;
#if !defined(SGX_DYNAMIC_TIMING_INFO)
-
+ /* timing information*/
SGX_TIMING_INFORMATION sTimingInfo;
#endif
#if defined(PDUMP)
-
+ /* pdump memory region name */
IMG_CHAR *pszPDumpDevName;
#endif
} SGX_DEVICE_MAP;
PVRSRV_STUB_PBDESC **ppsThis;
};
+/*!
+ ******************************************************************************
+ * CCB control structure for SGX
+ *****************************************************************************/
typedef struct _PVRSRV_SGX_CCB_INFO_
{
- PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo;
- PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo;
- SGXMKIF_COMMAND *psCommands;
- IMG_UINT32 *pui32WriteOffset;
- volatile IMG_UINT32 *pui32ReadOffset;
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo; /*!< meminfo for CCB in device accessible memory */
+ PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo; /*!< meminfo for CCB control in device accessible memory */
+ SGXMKIF_COMMAND *psCommands; /*!< linear address of the array of commands */
+ IMG_UINT32 *pui32WriteOffset; /*!< linear address of the write offset into array of commands */
+ volatile IMG_UINT32 *pui32ReadOffset; /*!< linear address of the read offset into array of commands */
#if defined(PDUMP)
- IMG_UINT32 ui32CCBDumpWOff;
+ IMG_UINT32 ui32CCBDumpWOff; /*!< for pdumping */
#endif
} PVRSRV_SGX_CCB_INFO;
IMG_UINT32 ui32ClkGateStatusReg;
IMG_UINT32 ui32ClkGateStatusMask;
#if defined(SGX_FEATURE_MP)
-#endif
+// IMG_UINT32 ui32MasterClkGateStatusReg;
+// IMG_UINT32 ui32MasterClkGateStatusMask;
+// IMG_UINT32 ui32MasterClkGateStatus2Reg;
+// IMG_UINT32 ui32MasterClkGateStatus2Mask;
+#endif /* SGX_FEATURE_MP */
IMG_UINT32 ui32CacheControl;
IMG_UINT32 ui32NumDstSyncObjects;
IMG_HANDLE hKernelHWSyncListMemInfo;
-
+ /* DST syncs */
IMG_HANDLE *pahDstSyncHandles;
IMG_UINT32 ui32NumTAStatusVals;
#endif
IMG_BOOL bFirstKickOrResume;
-#if (defined(NO_HARDWARE) || defined(PDUMP))
+#if defined(NO_HARDWARE) || defined(PDUMP)
IMG_BOOL bTerminateOrAbort;
#endif
-
+ /* CCB offset of data structure associated with this kick */
IMG_UINT32 ui32CCBOffset;
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
-
+ /* SRC and DST syncs */
IMG_UINT32 ui32NumTASrcSyncs;
IMG_HANDLE ahTASrcKernelSyncInfo[SGX_MAX_TA_SRC_SYNCS];
IMG_UINT32 ui32NumTADstSyncs;
IMG_UINT32 ui32Num3DSrcSyncs;
IMG_HANDLE ah3DSrcKernelSyncInfo[SGX_MAX_3D_SRC_SYNCS];
#else
-
+ /* SRC syncs */
IMG_UINT32 ui32NumSrcSyncs;
- IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS];
+ IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS_TA];
#endif
-
+ /* TA/3D dependency data */
IMG_BOOL bTADependency;
IMG_HANDLE hTA3DSyncInfo;
IMG_UINT32 ui32NumSrcSync;
IMG_HANDLE ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
-
+ /* need to be able to check reads and writes on dest, and update writes */
IMG_HANDLE hDstSyncInfo;
-
+ /* need to be able to check reads and writes on TA ops, and update writes */
IMG_HANDLE hTASyncInfo;
-
+ /* need to be able to check reads and writes on 2D ops, and update writes */
IMG_HANDLE h3DSyncInfo;
IMG_UINT32 ui32PDumpFlags;
IMG_UINT32 ui32CCBDumpWOff;
#endif
} PVRSRV_2D_SGX_KICK_KM, *PPVRSRV_2D_SGX_KICK_KM;
-#endif
-#endif
+#endif /* defined(SGX_FEATURE_2D_HARDWARE) */
+#endif /* #if defined(TRANSFER_QUEUE) */
+/****************************************************************************/
+/* kernel only functions prototypes */
+/****************************************************************************/
PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode);
IMG_VOID SGXOSTimer(IMG_VOID *pvData);
IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo);
+IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bDumpSGXRegs);
+
PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
#if defined(SGX_DYNAMIC_TIMING_INFO)
IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psSGXTimingInfo);
#endif
+/****************************************************************************/
+/* kernel only functions: */
+/****************************************************************************/
#if defined(NO_HARDWARE)
static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32StatusRegister,
}
#endif
-#endif
+#endif /* __SGXINFOKM_H__ */
+/*****************************************************************************
+ End of file (sgxinfokm.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific initialisation routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <stddef.h>
#include "lists.h"
#include "srvkm.h"
#include "ttrace.h"
-#define VAR(x) #x
-
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+
+static const IMG_CHAR *SGXUKernelStatusString(IMG_UINT32 code)
+{
+ switch(code)
+ {
+#define MKTC_ST(x) \
+ case x: \
+ return #x;
+#include "sgx_ukernel_status_codes.h"
+ default:
+ return "(Unknown)";
+ }
+}
+
+#endif /* defined(PVRSRV_USSE_EDM_STATUS_DEBUG) */
+
+#define VAR(x) #x
+/* PRQA S 0881 11 */ /* ignore 'order of evaluation' warning */
#define CHECK_SIZE(NAME) \
{ \
if (psSGXStructSizes->ui32Sizeof_##NAME != psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME) \
PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_HANDLE hDevMemContext);
-static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
- IMG_BOOL bDumpSGXRegs);
-
#if defined(PDUMP)
static
PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode);
#endif
+/*!
+*******************************************************************************
+
+ @Function SGXCommandComplete
+
+ @Description
+
+ SGX command complete handler
+
+ @Input psDeviceNode - SGX device node
+
+ @Return none
+
+******************************************************************************/
static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode)
{
#if defined(OS_SUPPORTS_IN_LISR)
if (OSInLISR(psDeviceNode->psSysData))
{
-
+ /*
+ * We shouldn't call SGXScheduleProcessQueuesKM in an
+ * LISR, as it may attempt to power up SGX.
+ * We assume that the LISR will schedule the MISR, which
+ * will test the following flag, and call
+ * SGXScheduleProcessQueuesKM if the flag is set.
+ */
psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
}
else
#endif
}
+/*!
+*******************************************************************************
+
+ @Function DeinitDevInfo
+
+ @Description
+
+ Deinits DevInfo
+
+ @Input none
+
+ @Return none
+
+******************************************************************************/
static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO *psDevInfo)
{
if (psDevInfo->psKernelCCBInfo != IMG_NULL)
{
-
-
+ /*
+ Free CCB info.
+ */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO), psDevInfo->psKernelCCBInfo, IMG_NULL);
}
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+
+ @Function InitDevInfo
+
+ @Description
+
+ Loads DevInfo
+
+ @Input psDeviceNode
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
PVRSRV_DEVICE_NODE *psDeviceNode,
#if defined (SUPPORT_SID_INTERFACE)
#if defined(FIX_HW_BRN_29823)
psDevInfo->psKernelDummyTermStreamMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelDummyTermStreamMemInfo;
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
psDevInfo->psKernelVDMSnapShotBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMSnapShotBufferMemInfo;
psDevInfo->psKernelVDMCtrlStreamBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMCtrlStreamBufferMemInfo;
#endif
#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
psDevInfo->psKernelEDMStatusBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelEDMStatusBufferMemInfo;
#endif
-#if defined(SGX_FEATURE_SPM_MODE_0)
- psDevInfo->psKernelTmpDPMStateMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpDPMStateMemInfo;
-#endif
-
+ /*
+ * Assign client-side build options for later verification
+ */
psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions;
-
+ /*
+ * Assign microkernel IF structure sizes for later verification
+ */
psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes;
-
-
+ /*
+ Setup the kernel version of the CCB control
+ */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_SGX_CCB_INFO),
(IMG_VOID **)&psKernelCCBInfo, 0,
psKernelCCBInfo->pui32ReadOffset = &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
-
-
+ /*
+ Copy the USE code addresses for the host kick.
+ */
OSMemCopy(psDevInfo->aui32HostKickAddr, psInitInfo->aui32HostKickAddr,
SGXMKIF_CMD_MAX * sizeof(psDevInfo->aui32HostKickAddr[0]));
psDevInfo->ui32MasterClkGateStatusMask = psInitInfo->ui32MasterClkGateStatusMask;
psDevInfo->ui32MasterClkGateStatus2Reg = psInitInfo->ui32MasterClkGateStatus2Reg;
psDevInfo->ui32MasterClkGateStatus2Mask = psInitInfo->ui32MasterClkGateStatus2Mask;
-#endif
+#endif /* SGX_FEATURE_MP */
-
+ /* Initialise Dev Data */
OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData, sizeof(psDevInfo->asSGXDevData));
return PVRSRV_OK;
PDUMPREG(SGX_PDUMPREG_NAME, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
break;
}
+ case SGX_INIT_OP_READ_HW_REG:
+ {
+ OSReadHWReg(psDevInfo->pvRegsBaseKM, psComm->sReadHWReg.ui32Offset);
+#if defined(PDUMP)
+ PDUMPCOMMENT("SGXRunScript: Read HW reg operation");
+ PDumpRegRead(SGX_PDUMPREG_NAME, psComm->sReadHWReg.ui32Offset, PDUMP_FLAGS_CONTINUOUS);
+#endif
+ break;
+ }
#if defined(PDUMP)
case SGX_INIT_OP_PDUMP_HW_REG:
{
return PVRSRV_OK;
}
case SGX_INIT_OP_ILLEGAL:
-
+ /* FALLTHROUGH */
default:
{
PVR_DPF((PVR_DBG_ERROR,"SGXRunScript: PC %d: Illegal command: %d", ui32PC, psComm->eOp));
return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
}
+#if defined(SUPPORT_MEMORY_TILING)
+static PVRSRV_ERROR SGX_AllocMemTilingRangeInt(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32End,
+ IMG_UINT32 ui32TilingStride,
+ IMG_UINT32 *pui32RangeIndex)
+{
+ IMG_UINT32 i;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Val;
+
+ /* HW supports 10 ranges */
+ for(i=0; i < SGX_BIF_NUM_TILING_RANGES; i++)
+ {
+ if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0)
+ {
+ /* mark in use */
+ psDevInfo->ui32MemTilingUsage |= 1U << i;
+ /* output range index if the caller wants it */
+ if(pui32RangeIndex != IMG_NULL)
+ {
+ *pui32RangeIndex = i;
+ }
+ goto RangeAllocated;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: all tiling ranges in use"));
+ return PVRSRV_ERROR_EXCEEDED_HW_LIMITS;
+
+RangeAllocated:
+
+ /* An improperly aligned range could cause BIF not to tile some memory which is intended to be tiled,
+ * or cause BIF to tile some memory which is not intended to be.
+ */
+ if(ui32Start & ~SGX_BIF_TILING_ADDR_MASK)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"SGX_AllocMemTilingRangeInt: Tiling range start (0x%08X) fails"
+ "alignment test", ui32Start));
+ }
+ if((ui32End + 0x00001000) & ~SGX_BIF_TILING_ADDR_MASK)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"SGX_AllocMemTilingRangeInt: Tiling range end (0x%08X) fails"
+ "alignment test", ui32End));
+ }
+
+ ui32Offset = EUR_CR_BIF_TILE0 + (i<<2);
+
+ ui32Val = ((ui32TilingStride << EUR_CR_BIF_TILE0_CFG_SHIFT) & EUR_CR_BIF_TILE0_CFG_MASK)
+ | (((ui32End>>SGX_BIF_TILING_ADDR_LSB) << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK)
+ | (((ui32Start>>SGX_BIF_TILING_ADDR_LSB) << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK)
+ | (EUR_CR_BIF_TILE0_ENABLE << EUR_CR_BIF_TILE0_CFG_SHIFT);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+ PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+ ui32Offset = EUR_CR_BIF_TILE0_ADDR_EXT + (i<<2);
+
+ ui32Val = (((ui32End>>SGX_BIF_TILING_EXT_ADDR_LSB) << EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK)
+ | (((ui32Start>>SGX_BIF_TILING_EXT_ADDR_LSB) << EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MIN_MASK);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+ PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+#endif /* SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS */
+
+ return PVRSRV_OK;
+}
+
+#endif /* SUPPORT_MEMORY_TILING */
+
+/*!
+*******************************************************************************
+
+ @Function SGXInitialise
+
+ @Description
+
+ (client invoked) chip-reset and initialisation
+
+ @Input pvDeviceNode - device info. structure
+ @Input bHardwareRecovery - true if recovering powered hardware,
+ false if powering up
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_BOOL bHardwareRecovery)
{
static IMG_BOOL bFirstTime = IMG_TRUE;
#if defined(PDUMP)
IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended();
-#endif
+#endif /* PDUMP */
#if defined(SGX_FEATURE_MP)
-
+ /* Slave core clocks must be enabled during reset */
#else
SGXInitClocks(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
-#endif
+#endif /* SGX_FEATURE_MP */
-
-
+ /*
+ Part 1 of the initialisation script runs before resetting SGX.
+ */
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 1\n");
eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1, SGX_MAX_INIT_COMMANDS);
if (eError != PVRSRV_OK)
}
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 1\n");
-
+ /* Reset the chip */
psDevInfo->ui32NumResets++;
- SGXReset(psDevInfo, bFirstTime || bHardwareRecovery, PDUMP_FLAGS_CONTINUOUS);
+
+#if !defined(SGX_FEATURE_MP)
+ bHardwareRecovery |= bFirstTime;
+#endif /* SGX_FEATURE_MP */
+
+ SGXReset(psDevInfo, bHardwareRecovery, PDUMP_FLAGS_CONTINUOUS);
#if defined(EUR_CR_POWER)
#if defined(SGX531)
-
-
-
-
-
+ /*
+ Disable half the pipes.
+ 531 has 2 pipes within a 4 pipe framework, so
+ the 2 redundant pipes must be disabled even
+ though they do not exist.
+ */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1);
PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 1);
#else
-
+ /* set the default pipe count (all fully enabled) */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0);
PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 0);
#endif
#endif
-
+ /* Initialise the kernel CCB event kicker value */
*psDevInfo->pui32KernelCCBEventKicker = 0;
#if defined(PDUMP)
if (!bPDumpIsSuspended)
sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
}
-#endif
+#endif /* PDUMP */
-
+#if defined(SUPPORT_MEMORY_TILING)
+ {
+ /* Initialise EUR_CR_BIF_TILE registers for any tiling heaps */
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDevInfo->pvDeviceMemoryHeap;
+ IMG_UINT32 i;
+ psDevInfo->ui32MemTilingUsage = 0;
+
+ for(i=0; i<psDevInfo->ui32HeapCount; i++)
+ {
+ if(psDeviceMemoryHeap[i].ui32XTileStride > 0)
+ {
+ /* Set up the HW control registers */
+ eError = SGX_AllocMemTilingRangeInt(
+ psDevInfo,
+ psDeviceMemoryHeap[i].sDevVAddrBase.uiAddr,
+ psDeviceMemoryHeap[i].sDevVAddrBase.uiAddr
+ + psDeviceMemoryHeap[i].ui32HeapSize,
+ psDeviceMemoryHeap[i].ui32XTileStride,
+ NULL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Unable to allocate SGX BIF tiling range for heap: %s",
+ psDeviceMemoryHeap[i].pszName));
+ break;
+ }
+ }
+ }
+ }
+#endif
+
+ /*
+ Part 2 of the initialisation script runs after resetting SGX.
+ */
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 2\n");
eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2, SGX_MAX_INIT_COMMANDS);
if (eError != PVRSRV_OK)
return eError;
}
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 2\n");
-
if(!(cpu_is_omap3530() || cpu_is_omap3517()))
{
OSWriteHWReg(psDevInfo->pvRegsBaseKM, 0xFF08, 0x80000000);//OCP Bypass mode
}
-
+
+ /* Record the system timestamp for the microkernel */
psSGXHostCtl->ui32HostClock = OSClockus();
psSGXHostCtl->ui32InitStatus = 0;
MAKEUNIQUETAG(psSGXHostCtlMemInfo));
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
"Initialise the microkernel\n");
-#endif
+#endif /* PDUMP */
#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
OSWriteMemoryBarrier();
OSWriteHWReg(psDevInfo->pvRegsBaseKM,
SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
EUR_CR_EVENT_KICK_NOW_MASK);
-#endif
+#endif /* SGX_FEATURE_MULTI_EVENT_KICK */
OSMemoryBarrier();
#if defined(PDUMP)
-
-
+ /*
+ Dump the host kick.
+ */
if (!bPDumpIsSuspended)
{
#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK);
-#endif
+#endif /* SGX_FEATURE_MULTI_EVENT_KICK */
}
-#endif
+#endif /* PDUMP */
#if !defined(NO_HARDWARE)
-
-
+ /*
+ Wait for the microkernel to finish initialising.
+ */
if (PollForValueKM(&psSGXHostCtl->ui32InitStatus,
PVRSRV_USSE_EDM_INIT_COMPLETE,
PVRSRV_USSE_EDM_INIT_COMPLETE,
IMG_FALSE) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed"));
- #if !defined(FIX_HW_BRN_23281)
+
SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
PVR_DBG_BREAK;
- #endif
+
return PVRSRV_ERROR_RETRY;
}
-#endif
+#endif /* NO_HARDWARE */
#if defined(PDUMP)
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
PDUMP_POLL_OPERATOR_EQUAL,
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psSGXHostCtlMemInfo));
-#endif
-
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
-
-
-
- WorkaroundBRN22997ReadHostPort(psDevInfo);
-#endif
+#endif /* PDUMP */
PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset == psDevInfo->psKernelCCBCtl->ui32WriteOffset);
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+
+ @Function SGXDeinitialise
+
+ @Description
+
+ (client invoked) chip-reset and deinitialisation
+
+ @Input hDevCookie - device info. handle
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
{
PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie;
PVRSRV_ERROR eError;
-
+ /* Did SGXInitialise map the SGX registers in? */
if (psDevInfo->pvRegsBaseKM == IMG_NULL)
{
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+
+ @Function DevInitSGXPart1
+
+ @Description
+
+ Reset and initialise Chip
+
+ @Input pvDeviceNode - device info. structure
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
{
IMG_HANDLE hDevMemHeap = IMG_NULL;
DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
PVRSRV_ERROR eError;
-
+ /* pdump info about the core */
PDUMPCOMMENT("SGX Core Version Information: %s", SGX_CORE_FRIENDLY_NAME);
#if defined(SGX_FEATURE_MP)
#else
PDUMPCOMMENT("SGX Multi-processor: %d TA cores, %d 3D cores", SGX_FEATURE_MP_CORE_COUNT_TA, SGX_FEATURE_MP_CORE_COUNT_3D);
#endif
- #endif
+ #endif /* SGX_FEATURE_MP */
#if (SGX_CORE_REV == 0)
PDUMPCOMMENT("SGX Core Revision Information: head RTL");
PDUMPCOMMENT("SGX System Level Cache is present\r\n");
#if defined(SGX_BYPASS_SYSTEM_CACHE)
PDUMPCOMMENT("SGX System Level Cache is bypassed\r\n");
- #endif
- #endif
+ #endif /* SGX_BYPASS_SYSTEM_CACHE */
+ #endif /* SGX_FEATURE_SYSTEM_CACHE */
PDUMPCOMMENT("SGX Initialisation Part 1");
-
+ /* Allocate device control block */
if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_SGXDEV_INFO),
(IMG_VOID **)&psDevInfo, IMG_NULL,
}
OSMemSet (psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO));
-
+ /* setup info from jdisplayconfig.h (variations controlled by build) */
psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
-
+ /* Store the devinfo as its needed by dynamically enumerated systems called from BM */
psDeviceNode->pvDevice = (IMG_PVOID)psDevInfo;
-
+ /* get heap info from the devnode */
+ psDevInfo->ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
psDevInfo->pvDeviceMemoryHeap = (IMG_VOID*)psDeviceMemoryHeap;
-
+ /* create the kernel memory context */
hKernelDevMemContext = BM_CreateContext(psDeviceNode,
&sPDDevPAddr,
IMG_NULL,
psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
-
+ /* create the kernel, shared and shared_exported heaps */
for(i=0; i<psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++)
{
switch(psDeviceMemoryHeap[i].DevMemHeapType)
case DEVICE_MEMORY_HEAP_SHARED:
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
{
-
+ /* Shared PB heap could be zero size */
if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
{
hDevMemHeap = BM_CreateHeap (hKernelDevMemContext,
&psDeviceMemoryHeap[i]);
-
-
-
+ /*
+ in the case of kernel context heaps just store
+ the heap handle in the heap info structure
+ */
psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
}
break;
#if defined(PDUMP)
if(hDevMemHeap)
{
-
+ /* set up the MMU pdump info */
psDevInfo->sMMUAttrib = *((BM_HEAP*)hDevMemHeap)->psMMUAttrib;
}
#endif
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+
+ @Function SGXGetInfoForSrvinitKM
+
+ @Description
+
+ Get SGX related information necessary for initilisation server
+
+ @Input hDevHandle - device handle
+ psInitInfo - pointer to structure for returned information
+
+ @Output psInitInfo - pointer to structure containing returned information
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, PVRSRV_HEAP_INFO_KM *pasHeapInfo, IMG_DEV_PHYADDR *psPDDevPAddr)
return eError;
}
+/*!
+*******************************************************************************
+
+ @Function DevInitSGXPart2KM
+
+ @Description
+
+ Reset and initialise Chip
+
+ @Input pvDeviceNode - device info. structure
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevHandle,
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
-
-
+ /*
+ Init devinfo
+ */
eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
if (eError != PVRSRV_OK)
{
return PVRSRV_ERROR_INIT_FAILURE;
}
-
+ /* Registers already mapped? */
if (psSGXDeviceMap->pvRegsCpuVBase)
{
psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
}
else
{
-
+ /* Map Regs */
psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
psSGXDeviceMap->ui32RegsSize,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
#if defined(SGX_FEATURE_HOST_PORT)
if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
{
-
+ /* Map Host Port */
psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(psSGXDeviceMap->sHPCpuPBase,
psSGXDeviceMap->ui32HPSize,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
psDevInfo->ui32HPSize = psSGXDeviceMap->ui32HPSize;
psDevInfo->sHPSysPAddr = psSGXDeviceMap->sHPSysPBase;
}
-#endif
+#endif/* #ifdef SGX_FEATURE_HOST_PORT */
#if defined (SYS_USING_INTERRUPTS)
-
+ /* Set up ISR callback information. */
psDeviceNode->pvISRData = psDeviceNode;
-
+ /* ISR handler address was set up earlier */
PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
-#endif
+#endif /* SYS_USING_INTERRUPTS */
-
+ /* Prevent the microkernel being woken up before there is something to do. */
psDevInfo->psSGXHostCtl->ui32PowerStatus |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
-
+ /* Register the device with the power manager. */
eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
&SGXPrePowerState, &SGXPostPowerState,
&SGXPreClockSpeedChange, &SGXPostClockSpeedChange,
return eError;
}
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
- eError = WorkaroundBRN22997Alloc(psDeviceNode);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to alloc memory for BRN22997 workaround"));
- return eError;
- }
-#endif
-
#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
-
+ /* map the external system cache control registers into the SGX MMU */
psDevInfo->ui32ExtSysCacheRegsSize = psSGXDeviceMap->ui32ExtSysCacheRegsSize;
psDevInfo->sExtSysCacheRegsDevPBase = psSGXDeviceMap->sExtSysCacheRegsDevPBase;
eError = MMU_MapExtSystemCacheRegs(psDeviceNode);
PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to map external system cache registers"));
return eError;
}
-#endif
-
-
+#endif /* SUPPORT_EXTERNAL_SYSTEM_CACHE */
+ /*
+ Initialise the Kernel CCB
+ */
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));
return eError;
}
+/*!
+*******************************************************************************
+
+ @Function DevDeInitSGX
+
+ @Description
+
+ Reset and deinitialise Chip
+
+ @Input pvDeviceNode - device info. structure
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
{
PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
if (!psDevInfo)
{
-
+ /* Can happen if DevInitSGX failed */
PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Null DevInfo"));
return PVRSRV_OK;
}
}
psDevInfo->hTimer = IMG_NULL;
}
-#endif
+#endif /* SUPPORT_HW_RECOVERY */
#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
-
+ /* unmap the external system cache control registers */
eError = MMU_UnmapExtSystemCacheRegs(psDeviceNode);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to unmap ext system cache registers"));
return eError;
}
-#endif
-
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
- WorkaroundBRN22997Free(psDeviceNode);
-#endif
+#endif /* SUPPORT_EXTERNAL_SYSTEM_CACHE */
MMU_BIFResetPDFree(psDevInfo);
-
-
+ /*
+ DeinitDevInfo the DevInfo
+ */
DeinitDevInfo(psDevInfo);
-
+ /* Destroy heaps. */
psDeviceMemoryHeap = (DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
for(ui32Heap=0; ui32Heap<psDeviceNode->sDevMemoryInfo.ui32HeapCount; ui32Heap++)
{
}
}
-
+ /* Destroy the kernel context. */
eError = BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext, IMG_NULL);
if (eError != PVRSRV_OK)
{
return eError;
}
-
+ /* remove the device from the power manager */
eError = PVRSRVRemovePowerDevice (((PVRSRV_DEVICE_NODE*)pvDeviceNode)->sDevId.ui32DeviceIndex);
if (eError != PVRSRV_OK)
{
return eError;
}
-
+ /* Only unmap the registers if they were mapped here */
if (!psSGXDeviceMap->pvRegsCpuVBase)
{
-
+ /* UnMap Regs */
if (psDevInfo->pvRegsBaseKM != IMG_NULL)
{
OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
#if defined(SGX_FEATURE_HOST_PORT)
if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
{
-
+ /* unMap Host Port */
if (psDevInfo->pvHostPortBaseKM != IMG_NULL)
{
OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM,
IMG_NULL);
}
}
-#endif
+#endif /* #ifdef SGX_FEATURE_HOST_PORT */
-
+ /* DeAllocate devinfo */
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_SGXDEV_INFO),
psDevInfo,
if (psDeviceMemoryHeap != IMG_NULL)
{
-
+ /* Free the device memory heap info. */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
psDeviceMemoryHeap,
#if defined(RESTRICTED_REGISTERS) && defined(SGX_FEATURE_MP)
+/*!
+*******************************************************************************
+
+ @Function SGXDumpMasterDebugReg
+
+ @Description
+
+ Dump a single SGX debug register value
+
+ @Input psDevInfo - SGX device info
+ @Input pszName - string used for logging
+ @Input ui32RegAddr - SGX register offset
+
+ @Return IMG_VOID
+
+******************************************************************************/
static IMG_VOID SGXDumpMasterDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_CHAR *pszName,
IMG_UINT32 ui32RegAddr)
PVR_LOG(("(HYD) %s%08X", pszName, ui32RegVal));
}
-#endif
+#endif /* defined(RESTRICTED_REGISTERS) */
+
+/*!
+*******************************************************************************
+
+ @Function SGXDumpDebugReg
+
+ @Description
+ Dump a single SGX debug register value
+
+ @Input psDevInfo - SGX device info
+ @Input ui32CoreNum - processor number
+ @Input pszName - string used for logging
+ @Input ui32RegAddr - SGX register offset
+
+ @Return IMG_VOID
+
+******************************************************************************/
static IMG_VOID SGXDumpDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32CoreNum,
IMG_CHAR *pszName,
PVR_LOG(("(P%u) %s%08X", ui32CoreNum, pszName, ui32RegVal));
}
-static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
- IMG_BOOL bDumpSGXRegs)
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) || defined(FIX_HW_BRN_31620)
+static INLINE IMG_UINT32 GetDirListBaseReg(IMG_UINT32 ui32Index)
+{
+ if (ui32Index == 0)
+ {
+ return EUR_CR_BIF_DIR_LIST_BASE0;
+ }
+ else
+ {
+ return (EUR_CR_BIF_DIR_LIST_BASE1 + ((ui32Index - 1) * 0x4));
+ }
+}
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function SGXDumpDebugInfo
+
+ @Description
+
+ Dump useful debugging info
+
+ @Input psDevInfo - SGX device info
+ @Input bDumpSGXRegs - Whether to dump SGX debug registers. Must not be done
+ when SGX is not powered.
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bDumpSGXRegs)
{
IMG_UINT32 ui32CoreNum;
#endif
for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++)
{
-
+ /* Dump HW event status */
SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS: ", EUR_CR_EVENT_STATUS);
SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS2: ", EUR_CR_EVENT_STATUS2);
SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_CTRL: ", EUR_CR_BIF_CTRL);
#if defined(EUR_CR_BIF_BANK0)
- SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_BANK0: ", EUR_CR_BIF_BANK0);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_BANK0: ", EUR_CR_BIF_BANK0);
#endif
SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_INT_STAT: ", EUR_CR_BIF_INT_STAT);
SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_FAULT: ", EUR_CR_BIF_FAULT);
#if defined(EUR_CR_PDS_PC_BASE)
SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_PDS_PC_BASE: ", EUR_CR_PDS_PC_BASE);
#endif
+#if defined(RESTRICTED_REGISTERS)
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_BANK_SET: ", EUR_CR_BIF_BANK_SET);
+
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATECTL: ", EUR_CR_CLKGATECTL);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATESTATUS: ", EUR_CR_CLKGATESTATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_MTE_CTRL: ", EUR_CR_MTE_CTRL);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_OTHER_PDS_EXEC: ", EUR_CR_EVENT_OTHER_PDS_EXEC);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_OTHER_PDS_DATA: ", EUR_CR_EVENT_OTHER_PDS_DATA);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_OTHER_PDS_INFO: ", EUR_CR_EVENT_OTHER_PDS_INFO);
+
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_ZLS_PAGE_THRESHOLD: ", EUR_CR_DPM_ZLS_PAGE_THRESHOLD);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_TA_GLOBAL_LIST: ", EUR_CR_DPM_TA_GLOBAL_LIST);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_STATE_CONTEXT_ID: ", EUR_CR_DPM_STATE_CONTEXT_ID);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_CONTEXT_PB_BASE: ", EUR_CR_DPM_CONTEXT_PB_BASE);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS1: ", EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS1);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_3D_FREE_LIST_STATUS1: ", EUR_CR_DPM_3D_FREE_LIST_STATUS1);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS2: ", EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS2);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_3D_FREE_LIST_STATUS2: ", EUR_CR_DPM_3D_FREE_LIST_STATUS2);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_ABORT_STATUS_MTILE: ", EUR_CR_DPM_ABORT_STATUS_MTILE);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_PAGE_STATUS: ", EUR_CR_DPM_PAGE_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_PAGE: ", EUR_CR_DPM_PAGE);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_GLOBAL_PAGE_STATUS: ", EUR_CR_DPM_GLOBAL_PAGE_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_LOAD_STATUS: ", EUR_CR_VDM_CONTEXT_LOAD_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_STORE_STATUS: ", EUR_CR_VDM_CONTEXT_STORE_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_TASK_KICK_STATUS: ", EUR_CR_VDM_TASK_KICK_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_STORE_STATE0: ", EUR_CR_VDM_CONTEXT_STORE_STATE0);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_STORE_STATE1: ", EUR_CR_VDM_CONTEXT_STORE_STATE1);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_REQUESTING: ", EUR_CR_DPM_REQUESTING);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_REQUESTING: ", EUR_CR_DPM_REQUESTING);
+
+#endif
}
- }
+ #if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && !defined(FIX_HW_BRN_31620)
+ {
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32PDDevPAddr;
+
+ /*
+ If there was a SGX pagefault check the page table too see if the
+ host thinks the fault is correct
+ */
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ if (ui32RegVal & EUR_CR_BIF_INT_STAT_PF_N_RW_MASK)
+ {
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+ ui32RegVal &= EUR_CR_BIF_FAULT_ADDR_MASK;
+ ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0);
+ ui32PDDevPAddr &= EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK;
+ MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32RegVal);
+ }
+ }
+ #else
+ {
+ IMG_UINT32 ui32FaultAddress;
+ IMG_UINT32 ui32Bank0;
+ IMG_UINT32 ui32DirListIndex;
+ IMG_UINT32 ui32PDDevPAddr;
+
+ ui32FaultAddress = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ EUR_CR_BIF_FAULT);
+ ui32FaultAddress = ui32FaultAddress & EUR_CR_BIF_FAULT_ADDR_MASK;
+
+ ui32Bank0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0);
+
+ /* Check the EDM's's memory context */
+ ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_EDM_MASK) >> EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT;
+ ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ GetDirListBaseReg(ui32DirListIndex));
+ PVR_LOG(("Checking EDM memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+ MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+
+ /* Check the TA's memory context */
+ ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_TA_MASK) >> EUR_CR_BIF_BANK0_INDEX_TA_SHIFT;
+ ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ GetDirListBaseReg(ui32DirListIndex));
+ PVR_LOG(("Checking TA memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+ MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+
+ /* Check the 3D's memory context */
+ ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_3D_MASK) >> EUR_CR_BIF_BANK0_INDEX_3D_SHIFT;
+ ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ GetDirListBaseReg(ui32DirListIndex));
+ PVR_LOG(("Checking 3D memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+ MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+
+ #if defined(EUR_CR_BIF_BANK0_INDEX_2D_MASK)
+ /* Check the 2D's memory context */
+ ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_2D_MASK) >> EUR_CR_BIF_BANK0_INDEX_2D_SHIFT;
+ ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ GetDirListBaseReg(ui32DirListIndex));
+ PVR_LOG(("Checking 2D memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+ MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+ #endif
-
+ #if defined(EUR_CR_BIF_BANK0_INDEX_PTLA_MASK)
+ /* Check the 2D's memory context */
+ ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_PTLA_MASK) >> EUR_CR_BIF_BANK0_INDEX_PTLA_SHIFT;
+ ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ GetDirListBaseReg(ui32DirListIndex));
+ PVR_LOG(("Checking PTLA memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+ MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+ #endif
+
+ #if defined(EUR_CR_BIF_BANK0_INDEX_HOST_MASK)
+ /* Check the Host's memory context */
+ ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_HOST_MASK) >> EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT;
+ ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ GetDirListBaseReg(ui32DirListIndex));
+ PVR_LOG(("Checking Host memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+ MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+ #endif
+ }
+ #endif
+ }
+ /*
+ Dump out the outstanding queue items.
+ */
QueueDumpDebugInfo();
{
-
-
+ /*
+ Dump out the Host control.
+ */
SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
IMG_UINT32 *pui32HostCtlBuffer = (IMG_UINT32 *)psSGXHostCtl;
IMG_UINT32 ui32LoopCounter;
}
{
-
-
+ /*
+ Dump out the TA/3D control.
+ */
IMG_UINT32 *pui32TA3DCtlBuffer = psDevInfo->psKernelSGXTA3DCtlMemInfo->pvLinAddrKM;
IMG_UINT32 ui32LoopCounter;
ui32WriteOffset = *pui32MKTraceBuffer;
pui32MKTraceBuffer++;
- PVR_LOG(("Last SGX microkernel status code: %08X", ui32LastStatusCode));
+ PVR_LOG(("Last SGX microkernel status code: %08X %s",
+ ui32LastStatusCode, SGXUKernelStatusString(ui32LastStatusCode)));
#if defined(PVRSRV_DUMP_MK_TRACE)
-
-
+ /*
+ Dump the raw microkernel trace buffer to the log.
+ */
{
IMG_UINT32 ui32LoopCounter;
IMG_UINT32 *pui32BufPtr;
pui32BufPtr = pui32MKTraceBuffer +
(((ui32WriteOffset + ui32LoopCounter) % SGXMK_TRACE_BUFFER_SIZE) * 4);
- PVR_LOG(("\t(MKT-%X) %08X %08X %08X %08X", ui32LoopCounter,
- pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0]));
+ PVR_LOG(("\t(MKT-%X) %08X %08X %08X %08X %s", ui32LoopCounter,
+ pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0],
+ SGXUKernelStatusString(pui32BufPtr[0])));
}
}
- #endif
+ #endif /* PVRSRV_DUMP_MK_TRACE */
}
- #endif
+ #endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */
{
-
-
+ /*
+ Dump out the kernel CCB.
+ */
PVR_LOG(("SGX Kernel CCB WO:0x%X RO:0x%X",
psDevInfo->psKernelCCBCtl->ui32WriteOffset,
psDevInfo->psKernelCCBCtl->ui32ReadOffset));
psCommand->ui32Data[2], psCommand->ui32Data[3]));
}
}
- #endif
+ #endif /* PVRSRV_DUMP_KERNEL_CCB */
}
#if defined (TTRACE)
PVRSRVDumpTimeTraceBuffers();
#if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY)
+/*!
+*******************************************************************************
+
+ @Function HWRecoveryResetSGX
+
+ @Description
+
+ Resets SGX
+
+ Note: may be called from an ISR so should not call pdump.
+
+ @Input psDevInfo - dev info
+
+ @Input ui32Component - core component to reset
+
+ @Return IMG_VOID
+
+******************************************************************************/
static
IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_UINT32 ui32Component,
PVRSRV_ERROR eError;
PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
-
- PVR_UNREFERENCED_PARAMETER(ui32Component);
-
+#if defined(SUPPORT_HWRECOVERY_TRACE_LIMIT)
+ static IMG_UINT32 ui32Clockinus = 0;
+ static IMG_UINT32 ui32HWRecoveryCount=0;
+ IMG_UINT32 ui32TempClockinus=0;
+#endif
+
+ PVR_UNREFERENCED_PARAMETER(ui32Component);
+ /*
+ Ensure that hardware recovery is serialised with any power transitions.
+ */
eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
if(eError != PVRSRV_OK)
{
-
-
-
+ /*
+ Unable to obtain lock because there is already a power transition
+ in progress.
+ */
PVR_DPF((PVR_DBG_WARNING,"HWRecoveryResetSGX: Power transition in progress"));
return;
}
psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
PVR_LOG(("HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
-
+
+#if defined(SUPPORT_HWRECOVERY_TRACE_LIMIT)
+/*
+ * The following defines are system specific and should be defined in
+ * the corresponding sysconfig.h file. The values indicated are examples only.
+ SYS_SGX_HWRECOVERY_TRACE_RESET_TIME_PERIOD 5000000 //(5 Seconds)
+ SYS_SGX_MAX_HWRECOVERY_OCCURANCE_COUNT 5
+ */
+ ui32TempClockinus = OSClockus();
+ if((ui32TempClockinus-ui32Clockinus) < SYS_SGX_HWRECOVERY_TRACE_RESET_TIME_PERIOD){
+ ui32HWRecoveryCount++;
+ if(SYS_SGX_MAX_HWRECOVERY_OCCURANCE_COUNT <= ui32HWRecoveryCount){
+ OSPanic();
+ }
+ }else{
+ ui32Clockinus = ui32TempClockinus;
+ SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
+ ui32HWRecoveryCount = 0;
+ }
+#else
SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
-
+#endif
+ /* Suspend pdumping. */
PDUMPSUSPEND();
-
-#if defined(FIX_HW_BRN_23281)
-
- for (eError = PVRSRV_ERROR_RETRY; eError == PVRSRV_ERROR_RETRY;)
-#endif
- {
- eError = SGXInitialise(psDevInfo, IMG_TRUE);
- }
+ /* Reset and re-initialise SGX. */
+ eError = SGXInitialise(psDevInfo, IMG_TRUE);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"HWRecoveryResetSGX: SGXInitialise failed (%d)", eError));
}
-
+ /* Resume pdumping. */
PDUMPRESUME();
PVRSRVPowerUnlock(ui32CallerID);
-
+ /* Send a dummy kick so that we start processing again */
SGXScheduleProcessQueuesKM(psDeviceNode);
-
-
+ /* Flush any old commands from the queues. */
PVRSRVProcessQueues(IMG_TRUE);
}
-#endif
+#endif /* #if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY) */
#if defined(SUPPORT_HW_RECOVERY)
+/*!
+******************************************************************************
+
+ @Function SGXOSTimer
+
+ @Description
+
+ Timer function for SGX
+
+ @Input pvData - private data
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
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 ui32LockupCounter = 0; /* To prevent false positives */
static IMG_UINT32 ui32OpenCLDelayCounter = 0;
static IMG_UINT32 ui32NumResets = 0;
#if defined(FIX_HW_BRN_31093)
IMG_BOOL bLockup = IMG_FALSE;
IMG_BOOL bPoweredDown;
-
+ /* increment a timestamp */
psDevInfo->ui32TimeStamp++;
#if defined(NO_HARDWARE)
bPoweredDown = IMG_TRUE;
#else
bPoweredDown = (SGXIsDevicePowered(psDeviceNode)) ? IMG_FALSE : IMG_TRUE;
-#endif
+#endif /* NO_HARDWARE */
-
-
+ /*
+ * Check whether EDM timer tasks are getting scheduled. If not, assume
+ * that SGX has locked up and reset the chip.
+ */
+
+ /* Check whether the timer should be running */
if (bPoweredDown)
{
ui32LockupCounter = 0;
}
else
{
-
+ /* The PDS timer should be running. */
ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg0);
if (psDevInfo->ui32EDMTaskReg1 != 0)
{
#if defined(FIX_HW_BRN_31093)
if (bBRN31093Inval == IMG_FALSE)
{
-
+ /* It could be a BIF hang so do a INVAL_PTE */
#if defined(FIX_HW_BRN_29997)
IMG_UINT32 ui32BIFCtrl;
-
+ /* Pause the BIF before issuing the invalidate */
ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_PAUSE_MASK);
-
+ /* delay for 200 clocks */
SGXWaitClocks(psDevInfo, 200);
#endif
-
+ /* Flag that we have attempt to un-block the BIF */
bBRN31093Inval = IMG_TRUE;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, EUR_CR_BIF_CTRL_INVAL_PTE_MASK);
-
+ /* delay for 200 clocks */
SGXWaitClocks(psDevInfo, 200);
#if defined(FIX_HW_BRN_29997)
-
+ /* un-pause the BIF by restoring the BIF_CTRL */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
#endif
}
else
#endif
{
- PVR_DPF((PVR_DBG_ERROR, "SGXOSTimer() detected SGX lockup (0x%x tasks)", ui32EDMTasks));
+ PVR_DPF((PVR_DBG_ERROR, "SGXOSTimer() detected SGX lockup (0x%x tasks)", ui32EDMTasks));
bLockup = IMG_TRUE;
(psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount = 0;
{
SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
-
+ /* increment the counter so we know the host detected the lockup */
psSGXHostCtl->ui32HostDetectedLockups ++;
-
+ /* Reset the chip and process the queues. */
HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
}
}
-#endif
+#endif /* defined(SUPPORT_HW_RECOVERY) */
+
#if defined(SYS_USING_INTERRUPTS)
+/*
+ SGX ISR Handler
+*/
IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
{
IMG_BOOL bInterruptProcessed = IMG_FALSE;
-
+ /* Real Hardware */
{
IMG_UINT32 ui32EventStatus, ui32EventEnable;
IMG_UINT32 ui32EventClear = 0;
PVRSRV_DEVICE_NODE *psDeviceNode;
PVRSRV_SGXDEV_INFO *psDevInfo;
-
+ /* check for null pointers */
if(pvData == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "SGX_ISRHandler: Invalid params\n"));
ui32EventStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE);
-
+ /* test only the unmasked bits */
ui32EventStatus &= ui32EventEnable;
#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
ui32EventStatus2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
ui32EventEnable2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE2);
-
+ /* test only the unmasked bits */
ui32EventStatus2 &= ui32EventEnable2;
-#endif
+#endif /* defined(SGX_FEATURE_DATA_BREAKPOINTS) */
-
+ /* Thought: is it better to insist that the bit assignment in
+ the "clear" register(s) matches that of the "status" register(s)?
+ It would greatly simplify this LISR */
if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
{
{
ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK;
}
-#endif
+#endif /* defined(SGX_FEATURE_DATA_BREAKPOINTS) */
if (ui32EventClear || ui32EventClear2)
{
bInterruptProcessed = IMG_TRUE;
-
+ /* Clear master interrupt bit */
ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
-
+ /* clear the events */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32EventClear2);
}
}
+/*
+ SGX MISR Handler
+*/
static IMG_VOID SGX_MISRHandler (IMG_VOID *pvData)
{
PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
}
-#endif
-
-
+#endif /* #if defined (SYS_USING_INTERRUPTS) */
#if defined(SUPPORT_MEMORY_TILING)
+
+IMG_INTERNAL
PVRSRV_ERROR SGX_AllocMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
- PVRSRV_KERNEL_MEM_INFO *psMemInfo,
- IMG_UINT32 ui32TilingStride,
- IMG_UINT32 *pui32RangeIndex)
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32XTileStride,
+ IMG_UINT32 *pui32RangeIndex)
{
-#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
- PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
- IMG_UINT32 i;
- IMG_UINT32 ui32Start;
- IMG_UINT32 ui32End;
- IMG_UINT32 ui32Offset;
- IMG_UINT32 ui32Val;
-
-
- for(i=0; i<10; i++)
- {
- if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0)
- {
-
- psDevInfo->ui32MemTilingUsage |= 1U << i;
-
- *pui32RangeIndex = i;
- goto RangeAllocated;
- }
- }
-
- PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: all tiling ranges in use"));
- return PVRSRV_ERROR_EXCEEDED_HW_LIMITS;
-
-RangeAllocated:
- ui32Offset = EUR_CR_BIF_TILE0 + (i<<2);
-
- ui32Start = psMemInfo->sDevVAddr.uiAddr;
- ui32End = ui32Start + psMemInfo->uAllocSize + SGX_MMU_PAGE_SIZE - 1;
-
- ui32Val = ((ui32TilingStride << EUR_CR_BIF_TILE0_CFG_SHIFT) & EUR_CR_BIF_TILE0_CFG_MASK)
- | (((ui32End>>20) << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK)
- | (((ui32Start>>20) << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK)
- | (0x8 << EUR_CR_BIF_TILE0_CFG_SHIFT);
-
-
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
- PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
-
- ui32Offset = EUR_CR_BIF_TILE0_ADDR_EXT + (i<<2);
-
- ui32Val = (((ui32End>>12) << EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK)
- | (((ui32Start>>12) << EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MIN_MASK);
-
-
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
- PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
-
- return PVRSRV_OK;
-#else
- PVR_UNREFERENCED_PARAMETER(psDeviceNode);
- PVR_UNREFERENCED_PARAMETER(psMemInfo);
- PVR_UNREFERENCED_PARAMETER(ui32TilingStride);
- PVR_UNREFERENCED_PARAMETER(pui32RangeIndex);
-
- PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: device does not support memory tiling"));
- return PVRSRV_ERROR_NOT_SUPPORTED;
-#endif
+ return SGX_AllocMemTilingRangeInt(psDeviceNode->pvDevice,
+ psMemInfo->sDevVAddr.uiAddr,
+ psMemInfo->sDevVAddr.uiAddr + ((IMG_UINT32) psMemInfo->uAllocSize) + SGX_MMU_PAGE_SIZE - 1,
+ ui32XTileStride,
+ pui32RangeIndex);
}
+IMG_INTERNAL
PVRSRV_ERROR SGX_FreeMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_UINT32 ui32RangeIndex)
{
-#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
IMG_UINT32 ui32Offset;
IMG_UINT32 ui32Val;
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* clear the usage bit */
psDevInfo->ui32MemTilingUsage &= ~(1<<ui32RangeIndex);
-
+ /* disable the range */
ui32Offset = EUR_CR_BIF_TILE0 + (ui32RangeIndex<<2);
ui32Val = 0;
-
OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
return PVRSRV_OK;
-#else
- PVR_UNREFERENCED_PARAMETER(psDeviceNode);
- PVR_UNREFERENCED_PARAMETER(ui32RangeIndex);
-
- PVR_DPF((PVR_DBG_ERROR,"SGX_FreeMemTilingRange: device does not support memory tiling"));
- return PVRSRV_ERROR_NOT_SUPPORTED;
-#endif
}
-#endif
+
+#endif /* defined(SUPPORT_MEMORY_TILING) */
+
static IMG_VOID SGXCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode)
{
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
#else
PVR_UNREFERENCED_PARAMETER(psDevInfo);
- #endif
+ #endif /* SGX_FEATURE_MP */
}
+/*!
+*******************************************************************************
+
+ @Function SGXRegisterDevice
+
+ @Description
+
+ Registers the device with the system
+
+ @Input: psDeviceNode - device node
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
{
DEVICE_MEMORY_INFO *psDevMemoryInfo;
DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
-
+ /* setup details that never change */
psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
#if defined(PDUMP)
{
-
+ /* memory space names are set up in system code */
SGX_DEVICE_MAP *psSGXDeviceMemMap;
SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
(IMG_VOID**)&psSGXDeviceMemMap);
}
psDeviceNode->sDevId.pszPDumpRegName = SGX_PDUMPREG_NAME;
-#endif
+#endif /* PDUMP */
psDeviceNode->pfnInitDevice = &DevInitSGXPart1;
psDeviceNode->pfnDeInitDevice = &DevDeInitSGX;
psDeviceNode->pfnPDumpInitDevice = &SGXResetPDump;
psDeviceNode->pfnMMUGetContextID = &MMU_GetPDumpContextID;
#endif
-
-
+ /*
+ MMU callbacks
+ */
psDeviceNode->pfnMMUInitialise = &MMU_Initialise;
psDeviceNode->pfnMMUFinalise = &MMU_Finalise;
psDeviceNode->pfnMMUInsertHeap = &MMU_InsertHeap;
psDeviceNode->pfnMMUGetCacheFlushRange = IMG_NULL;
psDeviceNode->pfnMMUGetPDPhysAddr = IMG_NULL;
#endif
-#if defined (SYS_USING_INTERRUPTS)
-
+ psDeviceNode->pfnMMUMapPagesSparse = &MMU_MapPagesSparse;
+ psDeviceNode->pfnMMUMapShadowSparse = &MMU_MapShadowSparse;
+#if defined (SYS_USING_INTERRUPTS)
+ /*
+ SGX ISR handler
+ */
psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
#endif
psDeviceNode->pfnFreeMemTilingRange = SGX_FreeMemTilingRange;
#endif
-
-
+ /*
+ SGX command complete handler
+ */
psDeviceNode->pfnDeviceCommandComplete = &SGXCommandComplete;
psDeviceNode->pfnCacheInvalidate = SGXCacheInvalidate;
-
-
+ /*
+ and setup the device's memory map:
+ */
psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
-
+ /* size of address space */
psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_FEATURE_ADDRESS_SPACE_SIZE;
-
+ /* flags, backing store details to be specified by system */
psDevMemoryInfo->ui32Flags = 0;
-
+ /* device memory heap info about each heap in a device address space */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
(IMG_VOID **)&psDevMemoryInfo->psDeviceMemoryHeap, 0,
psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
-
-
+ /*
+ setup heaps
+ Note: backing store to be setup by system (defaults to UMA)
+ */
-
+ /************* general ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_HEAP_SIZE;
psDeviceMemoryHeap->pszName = "General";
psDeviceMemoryHeap->pszBSName = "General BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
-
+ /* specify the mapping heap ID for this device */
psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
#endif
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
+#if defined(SUPPORT_MEMORY_TILING)
+ /************* VPB tiling ***************/
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VPB_TILED_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VPB_TILED_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_VPB_TILED_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "VPB Tiled";
+ psDeviceMemoryHeap->pszBSName = "VPB Tiled BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+ /* set the default (4k). System can override these as required */
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap->ui32XTileStride = SGX_VPB_TILED_HEAP_STRIDE;
+ PVR_DPF((PVR_DBG_WARNING, "VPB tiling heap tiling stride = 0x%x", psDeviceMemoryHeap->ui32XTileStride));
+ psDeviceMemoryHeap++;/* advance to the next heap */
+#endif
-
+#if defined(SUPPORT_ION)
+ /************* Ion Heap ***************/
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_ION_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_ION_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_ION_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "Ion";
+ psDeviceMemoryHeap->pszBSName = "Ion BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+ /* specify the ion heap ID for this device */
+ psDevMemoryInfo->ui32IonHeapID = SGX_ION_HEAP_ID;
+ /* set the default (4k). System can override these as required */
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;/* advance to the next heap */
+#endif
+
+ /************* TA data ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_TADATA_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_TADATA_HEAP_SIZE;
psDeviceMemoryHeap->pszName = "TA Data";
psDeviceMemoryHeap->pszBSName = "TA Data BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* kernel code ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_CODE_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_CODE_HEAP_SIZE;
psDeviceMemoryHeap->pszName = "Kernel Code";
psDeviceMemoryHeap->pszBSName = "Kernel Code BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* Kernel Video Data ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_DATA_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_DATA_HEAP_SIZE;
psDeviceMemoryHeap->pszName = "KernelData";
psDeviceMemoryHeap->pszBSName = "KernelData BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* PixelShaderUSSE ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PIXELSHADER_HEAP_BASE;
-
-
-
-
-
-
+ /*
+ The actual size of the pixel and vertex shader heap must be such that all
+ addresses are within range of the one of the USSE code base registers, but
+ the addressable range is hardware-dependent.
+ SGX_PIXELSHADER_HEAP_SIZE is defined to be the maximum possible size
+ to ensure that the heap layout is consistent across all SGXs.
+ */
psDeviceMemoryHeap->ui32HeapSize = ((10 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_PIXELSHADER_HEAP_SIZE);
psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
psDeviceMemoryHeap->pszName = "PixelShaderUSSE";
psDeviceMemoryHeap->pszBSName = "PixelShaderUSSE BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* VertexShaderUSSE ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VERTEXSHADER_HEAP_BASE;
-
+ /* See comment above with PixelShaderUSSE ui32HeapSize */
psDeviceMemoryHeap->ui32HeapSize = ((4 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_VERTEXSHADER_HEAP_SIZE);
psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
psDeviceMemoryHeap->pszName = "VertexShaderUSSE";
psDeviceMemoryHeap->pszBSName = "VertexShaderUSSE BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* PDS Pixel Code/Data ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
psDeviceMemoryHeap->pszName = "PDSPixelCodeData";
psDeviceMemoryHeap->pszBSName = "PDSPixelCodeData BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* PDS Vertex Code/Data ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
psDeviceMemoryHeap->pszName = "PDSVertexCodeData";
psDeviceMemoryHeap->pszBSName = "PDSVertexCodeData BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* CacheCoherent ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SYNCINFO_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_SYNCINFO_HEAP_SIZE;
psDeviceMemoryHeap->pszName = "CacheCoherent";
psDeviceMemoryHeap->pszBSName = "CacheCoherent BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
-
+ /* set the sync heap id */
psDevMemoryInfo->ui32SyncHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* Shared 3D Parameters ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SHARED_3DPARAMETERS_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SHARED_3DPARAMETERS_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_SHARED_3DPARAMETERS_HEAP_SIZE;
| PVRSRV_HAP_MULTI_PROCESS;
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* Percontext 3D Parameters ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PERCONTEXT_3DPARAMETERS_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE;
| PVRSRV_MEM_RAM_BACKED_ALLOCATION
| PVRSRV_HAP_SINGLE_PROCESS;
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
-
+ /************* General Mapping ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_MAPPING_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_MAPPING_HEAP_SIZE;
psDeviceMemoryHeap->pszName = "GeneralMapping";
psDeviceMemoryHeap->pszBSName = "GeneralMapping BS";
#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410)
-
-
-
-
-
-
-
+ /*
+ if((2D hardware is enabled)
+ && (multi-mem contexts enabled)
+ && (BRN23410 is present))
+ - then don't make the heap per-context otherwise
+ the TA and 2D requestors must always be aligned to
+ the same address space which could affect performance
+ */
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
- #else
+ #else /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410) */
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
- #endif
+ #endif /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410) */
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
-
+ /* specify the mapping heap ID for this device */
psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
- psDeviceMemoryHeap++;
-#endif
+ psDeviceMemoryHeap++;/* advance to the next heap */
+#endif /* #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) */
#if defined(SGX_FEATURE_2D_HARDWARE)
-
+ /************* 2D HW Heap ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_2D_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_2D_HEAP_SIZE;
| PVRSRV_HAP_SINGLE_PROCESS;
psDeviceMemoryHeap->pszName = "2D";
psDeviceMemoryHeap->pszBSName = "2D BS";
-
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
-#endif
-
-
-#if defined(FIX_HW_BRN_26915)
-
-
- psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_CGBUFFER_HEAP_ID);
- psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_CGBUFFER_HEAP_BASE;
- psDeviceMemoryHeap->ui32HeapSize = SGX_CGBUFFER_HEAP_SIZE;
- psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
- | PVRSRV_MEM_RAM_BACKED_ALLOCATION
- | PVRSRV_HAP_SINGLE_PROCESS;
- psDeviceMemoryHeap->pszName = "CGBuffer";
- psDeviceMemoryHeap->pszBSName = "CGBuffer BS";
+ psDeviceMemoryHeap++;/* advance to the next heap */
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE) */
- psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
- psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
-#endif
-
+ /* set the heap count */
psDevMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
return PVRSRV_OK;
return PVRSRV_OK;
}
-#endif
+#endif /* PDUMP */
+
+
+/*!
+*******************************************************************************
+
+ @Function SGXGetClientInfoKM
+
+ @Description Gets the client information
+ @Input hDevCookie
+ @Output psClientInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
SGX_CLIENT_INFO* psClientInfo)
{
PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
-
-
+ /*
+ If this is the first client to connect to SGX perform initialisation
+ */
psDevInfo->ui32ClientRefCount++;
-
-
+ /*
+ Copy information to the client info.
+ */
psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
-
-
+ /*
+ Copy requested information.
+ */
OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData, sizeof(psClientInfo->asDevData));
-
+ /* just return OK */
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+
+ @Function SGXPanic
+
+ @Description
+
+ Called when an unrecoverable situation is detected. Dumps SGX debug
+ information and tells the OS to panic.
+
+ @Input psDevInfo - SGX device info
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo)
{
PVR_LOG(("SGX panic"));
}
+/*!
+*******************************************************************************
+
+ @Function SGXDevInitCompatCheck
+
+ @Description
+
+ Check compatibility of host driver and microkernel (DDK and build options)
+ for SGX devices at services/device initialisation
+
+ @Input psDeviceNode - device node
+
+ @Return PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVRSRV_ERROR eError;
IMG_UINT32 ui32BuildOptions, ui32BuildOptionsMismatch;
#if !defined(NO_HARDWARE)
PPVRSRV_KERNEL_MEM_INFO psMemInfo;
- PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
+ PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt; /*!< internal misc info for ukernel */
PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
- SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes;
+ SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes; /*!< microkernel structure sizes */
IMG_BOOL bStructSizesFailed;
-
+ /* Exceptions list for core rev check, format is pairs of (hw rev, sw rev) */
IMG_BOOL bCheckCoreRev;
const IMG_UINT32 aui32CoreRevExceptions[] =
{
IMG_UINT i;
#endif
-
+ /* Ensure it's a SGX device */
if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX)
{
PVR_LOG(("(FAIL) SGXInit: Device not of type SGX"));
psDevInfo = psDeviceNode->pvDevice;
-
-
+ /*
+ * 1. Check kernel-side and client-side build options
+ * 2. Ensure ukernel DDK version and driver DDK version are compatible
+ * 3. Check ukernel build options against kernel-side build options
+ */
+
+ /*
+ * Check KM build options against client-side host driver
+ */
+
ui32BuildOptions = (SGX_BUILD_OPTIONS);
if (ui32BuildOptions != psDevInfo->ui32ClientBuildOptions)
{
#if !defined (NO_HARDWARE)
psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
-
+ /* Clear state (not strictly necessary since this is the first call) */
psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
psSGXMiscInfoInt->ui32MiscInfoFlags = 0;
psSGXMiscInfoInt->ui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES;
eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode, IMG_NULL);
-
+ /*
+ * Validate DDK version
+ */
if(eError != PVRSRV_OK)
{
PVR_LOG(("(FAIL) SGXInit: Unable to validate device DDK version"));
PVR_LOG(("(FAIL) SGXInit: Incompatible driver DDK revision (%d)/device DDK revision (%d).",
PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild));
eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
- PVR_DBG_BREAK;
goto chk_exit;
}
else
PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild));
}
-
+ /*
+ * Check hardware core revision is compatible with the one in software
+ */
if (psSGXFeatures->ui32CoreRevSW == 0)
{
-
-
+ /*
+ Head core revision cannot be checked.
+ */
PVR_LOG(("SGXInit: HW core rev (%x) check skipped.",
psSGXFeatures->ui32CoreRev));
}
else
{
-
+ /* For some cores the hw/sw core revisions are expected not to match. For these
+ * exceptional cases the core rev compatibility check should be skipped.
+ */
bCheckCoreRev = IMG_TRUE;
for(i=0; i<ui32NumCoreExceptions; i+=2)
{
}
}
-
+ /*
+ * Check ukernel structure sizes are the same as those in the driver
+ */
psSGXStructSizes = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXStructSizes;
bStructSizesFailed = IMG_FALSE;
PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: SGXMKIF structure sizes match. [ OK ]"));
}
-
+ /*
+ * Check ukernel build options against KM host driver
+ */
+
ui32BuildOptions = psSGXFeatures->ui32BuildOptions;
if (ui32BuildOptions != (SGX_BUILD_OPTIONS))
{
{
PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Driver and microkernel build options match. [ OK ]"));
}
-#endif
+#endif // NO_HARDWARE
eError = PVRSRV_OK;
chk_exit:
#endif
}
+/*
+ * @Function SGXGetMiscInfoUkernel
+ *
+ * @Description Returns misc info (e.g. SGX build info/flags) from microkernel
+ *
+ * @Input psDevInfo : device info from init phase
+ * @Input psDeviceNode : device node, used for scheduling ukernel to query SGX features
+ *
+ * @Return PVRSRV_ERROR :
+ *
+ */
static
PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_HANDLE hDevMemContext)
{
PVRSRV_ERROR eError;
- SGXMKIF_COMMAND sCommandData;
- PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
- PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
- SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes;
+ SGXMKIF_COMMAND sCommandData; /* CCB command data */
+ PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt; /*!< internal misc info for ukernel */
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; /*!< sgx features for client */
+ SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes; /*!< internal info: microkernel structure sizes */
PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
-
+ /* Reset SGX features */
OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
OSMemSet(psSGXStructSizes, 0, sizeof(*psSGXStructSizes));
-
- sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
+ /* set up buffer address for SGX features in CCB */
+ sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr; /* device V addr of output buffer */
PDUMPCOMMENT("Microkernel kick for SGXGetMiscInfo");
eError = SGXScheduleCCBCommandKM(psDeviceNode,
return eError;
}
-
+ /* FIXME: DWORD value to determine code path in ukernel?
+ * E.g. could use getMiscInfo to obtain register values for diagnostics? */
+
#if !defined(NO_HARDWARE)
{
IMG_BOOL bExit;
}
} END_LOOP_UNTIL_TIMEOUT();
-
+ /*if the loop exited because a timeout*/
if (!bExit)
{
PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Timeout occurred waiting for misc info."));
return PVRSRV_ERROR_TIMEOUT;
}
}
-#endif
+#endif /* NO_HARDWARE */
return PVRSRV_OK;
}
+/*
+ * @Function SGXGetMiscInfoKM
+ *
+ * @Description Returns miscellaneous SGX info
+ *
+ * @Input psDevInfo : device info from init phase
+ * @Input psDeviceNode : device node, used for scheduling ukernel to query SGX features
+ *
+ * @Output psMiscInfo : query request plus user-mode mem for holding returned data
+ *
+ * @Return PVRSRV_ERROR :
+ *
+ */
IMG_EXPORT
PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
SGX_MISC_INFO *psMiscInfo,
PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
IMG_UINT32 *pui32MiscInfoFlags = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->ui32MiscInfoFlags;
-
+ /* Reset the misc info state flags */
*pui32MiscInfoFlags = 0;
#if !defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
IMG_UINT32 ui32EndRegVal;
SGXMKIF_COMMAND sCommandData;
-
+ /* Set or Clear BP? */
if(psMiscInfo->uData.sSGXBreakpointInfo.bBPEnable)
{
-
+ /* set the break point */
IMG_DEV_VIRTADDR sBPDevVAddr = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddr;
IMG_DEV_VIRTADDR sBPDevVAddrEnd = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddrEnd;
-
+ /* BP address */
ui32StartRegVal = sBPDevVAddr.uiAddr & EUR_CR_BREAKPOINT0_START_ADDRESS_MASK;
ui32EndRegVal = sBPDevVAddrEnd.uiAddr & EUR_CR_BREAKPOINT0_END_ADDRESS_MASK;
ui32CtrlREnable = psMiscInfo->uData.sSGXBreakpointInfo.bRead;
ui32CtrlTrapEnable = psMiscInfo->uData.sSGXBreakpointInfo.bTrapped;
-
+ /* normal data BP */
ui32RegVal = ((ui32MaskDM<<EUR_CR_BREAKPOINT0_MASK_DM_SHIFT) & EUR_CR_BREAKPOINT0_MASK_DM_MASK) |
((ui32CtrlWEnable<<EUR_CR_BREAKPOINT0_CTRL_WENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK) |
((ui32CtrlREnable<<EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK) |
}
else
{
-
+ /* clear the break point */
ui32RegVal = ui32StartRegVal = ui32EndRegVal = 0;
}
-
+ /* setup the command */
sCommandData.ui32Data[0] = psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex;
sCommandData.ui32Data[1] = ui32StartRegVal;
sCommandData.ui32Data[2] = ui32EndRegVal;
sCommandData.ui32Data[3] = ui32RegVal;
-
+ /* clear signal flags */
psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
PDUMPCOMMENT("Microkernel kick for setting a data breakpoint");
}
#if defined(NO_HARDWARE)
-
+ /* clear signal flags */
psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
#else
{
if (psDevInfo->psSGXHostCtl->ui32BPSetClearSignal != 0)
{
bExit = IMG_TRUE;
-
+ /* clear signal flags */
psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
break;
}
} END_LOOP_UNTIL_TIMEOUT();
-
+ /*if the loop exited because a timeout*/
if (!bExit)
{
PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: Timeout occurred waiting BP set/clear"));
return PVRSRV_ERROR_TIMEOUT;
}
}
-#endif
+#endif /* NO_HARDWARE */
return PVRSRV_OK;
}
case SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT:
{
-
-
-
-
-
-
-
+ /* This request checks to see whether a breakpoint has
+ been trapped. If so, it returns the number of the
+ breakpoint number that was trapped in ui32BPIndex,
+ sTrappedBPDevVAddr to the address which was trapped,
+ and sets bTrappedBP. Otherwise, bTrappedBP will be
+ false, and other fields should be ignored. */
+ /* The uKernel is not used, since if we are stopped on a
+ breakpoint, it is not possible to guarantee that the
+ uKernel would be able to run */
#if !defined(NO_HARDWARE)
#if defined(SGX_FEATURE_MP)
IMG_BOOL bTrappedBPMaster;
IMG_UINT32 ui32CoreNum, ui32TrappedBPCoreNum;
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
IMG_UINT32 ui32PipeNum, ui32TrappedBPPipeNum;
+/* ui32PipeNum is the pipe number plus 1, or 0 to represent "partition" */
#define NUM_PIPES_PLUS_ONE (SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES+1)
#endif
IMG_BOOL bTrappedBPAny;
-#endif
+#endif /* defined(SGX_FEATURE_MP) */
IMG_BOOL bFoundOne;
#if defined(SGX_FEATURE_MP)
bTrappedBPMaster = !!(EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT));
bTrappedBPAny = bTrappedBPMaster;
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
- ui32TrappedBPPipeNum = 0;
+ ui32TrappedBPPipeNum = 0; /* just to keep the (incorrect) compiler happy */
#endif
for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++)
{
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
-
-
-
+ /* FIXME: this macro makes the assumption that the PARTITION regs are the same
+ distance before the PIPE0 regs as the PIPE1 regs are after it, _and_
+ assumes that the fields in the partition regs are in the same place
+ in the pipe regs. Need to validate these assumptions, or assert them */
#define SGX_MP_CORE_PIPE_SELECT(r,c,p) \
((SGX_MP_CORE_SELECT(EUR_CR_PARTITION_##r,c) + p*(EUR_CR_PIPE0_##r-EUR_CR_PARTITION_##r)))
for (ui32PipeNum = 0; ui32PipeNum < NUM_PIPES_PLUS_ONE; ui32PipeNum++)
ui32TrappedBPPipeNum = ui32PipeNum;
}
}
-#else
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
bFoundOne = !!(EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum)));
if (bFoundOne)
{
bTrappedBPAny = IMG_TRUE;
ui32TrappedBPCoreNum = ui32CoreNum;
}
-#endif
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
}
psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = bTrappedBPAny;
-#else
+#else /* defined(SGX_FEATURE_MP) */
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
#error Not yet considered the case for per-pipe regs in non-mp case
#endif
psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = 0 != (EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT));
-#endif
+#endif /* defined(SGX_FEATURE_MP) */
if (psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP)
{
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum, ui32TrappedBPPipeNum));
ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum, ui32TrappedBPPipeNum));
-#else
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum));
ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum));
-#endif
-#else
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+#else /* defined(SGX_FEATURE_MP) */
ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO0);
ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO1);
-#endif
+#endif /* defined(SGX_FEATURE_MP) */
#ifdef SGX_FEATURE_PERPIPE_BKPT_REGS
psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT;
psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_MASK);
psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT;
psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_SHIFT;
-#else
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT;
psMiscInfo->uData.sSGXBreakpointInfo.sTrappedBPDevVAddr.uiAddr = ui32Info0 & EUR_CR_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK;
psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPBurstLength = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT;
psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_RNW_MASK);
psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT;
psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_SHIFT;
-#endif
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
#if defined(SGX_FEATURE_MP)
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
-
+ /* mp, per-pipe regbanks */
psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:(ui32TrappedBPCoreNum + (ui32TrappedBPPipeNum<<10));
-#else
-
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+ /* mp, regbanks unsplit */
psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:ui32TrappedBPCoreNum;
-#endif
-#else
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+#else /* defined(SGX_FEATURE_MP) */
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
-
+ /* non-mp, per-pipe regbanks */
#error non-mp perpipe regs not yet supported
-#else
-
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+ /* non-mp */
psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = 65534;
-#endif
-#endif
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+#endif /* defined(SGX_FEATURE_MP) */
}
-#endif
+#endif /* !defined(NO_HARDWARE) */
return PVRSRV_OK;
}
case SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT:
{
-
-
-
+ /* This request resumes from the currently trapped breakpoint. */
+ /* Core number must be supplied */
+ /* Polls for notify to be acknowledged by h/w */
#if !defined(NO_HARDWARE)
#if defined(SGX_FEATURE_MP)
IMG_UINT32 ui32CoreNum;
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
IMG_UINT32 ui32PipeNum;
#endif
-#endif
+#endif /* defined(SGX_FEATURE_MP) */
IMG_UINT32 ui32OldSeqNum, ui32NewSeqNum;
#if defined(SGX_FEATURE_MP)
ui32PipeNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum >> 10;
ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum & 1023;
bMaster = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum > 32767;
-#else
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum;
bMaster = ui32CoreNum > SGX_FEATURE_MP_CORE_COUNT_3D;
-#endif
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
if (bMaster)
{
-
-
+ /* master */
+ /* EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK | EUR_CR_MASTER_BREAKPOINT_SEQNUM_MASK */
ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT_TRAP, EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_MASK);
do
while (ui32OldSeqNum == ui32NewSeqNum);
}
else
-#endif
+#endif /* defined(SGX_FEATURE_MP) */
{
-
+ /* core */
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, ui32CoreNum, ui32PipeNum));
OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP, ui32CoreNum, ui32PipeNum), EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_MASK);
ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, ui32CoreNum, ui32PipeNum));
}
while (ui32OldSeqNum == ui32NewSeqNum);
-#else
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP, ui32CoreNum), EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK);
do
ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
}
while (ui32OldSeqNum == ui32NewSeqNum);
-#endif
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
}
-#endif
+#endif /* !defined(NO_HARDWARE) */
return PVRSRV_OK;
}
-#endif
+#endif /* SGX_FEATURE_DATA_BREAKPOINTS) */
case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
{
case SGX_MISC_INFO_REQUEST_SPM:
{
-
+ /* this is dealt with in UM */
return PVRSRV_OK;
}
case SGX_MISC_INFO_REQUEST_SGXREV:
{
PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+// PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode, hDevMemContext);
if(eError != PVRSRV_OK)
{
}
psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
-
+ /* Copy SGX features into misc info struct, to return to client */
psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
-
+ /* Debug output */
PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: Core 0x%x, sw ID 0x%x, sw Rev 0x%x\n",
psSGXFeatures->ui32CoreRev,
psSGXFeatures->ui32CoreIdSW,
psSGXFeatures->ui32DDKVersion,
psSGXFeatures->ui32DDKBuild));
-
+ /* done! */
return PVRSRV_OK;
}
psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
-
+ /* Reset the misc information to prevent
+ * confusion with values returned from the ukernel
+ */
OSMemSet(psMemInfo->pvLinAddrKM, 0,
sizeof(PVRSRV_SGX_MISCINFO_INFO));
PVRVERSION_BRANCH;
psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
-
+ /* Also report the kernel module build options -- used in SGXConnectionCheck() */
psSGXFeatures->ui32BuildOptions = (SGX_BUILD_OPTIONS);
#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
-
+ /* Report the EDM status buffer location in memory */
psSGXFeatures->sDevVAEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->sDevVAddr;
psSGXFeatures->pvEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
#endif
-
+ /* Copy SGX features into misc info struct, to return to client */
psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
return PVRSRV_OK;
}
{
PVRSRV_ERROR eError;
PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
- PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemSrc;
- PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemDest;
+ PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemSrc; /* user-defined mem read */
+ PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemDest; /* user-defined mem write */
{
-
+ /* Set the mem read flag; src is user-defined */
*pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMREAD;
psSGXMemSrc = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessSrc;
if(psMiscInfo->sDevVAddrSrc.uiAddr != 0)
{
- psSGXMemSrc->sDevVAddr = psMiscInfo->sDevVAddrSrc;
+ psSGXMemSrc->sDevVAddr = psMiscInfo->sDevVAddrSrc; /* src address */
}
else
{
if( psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMCOPY)
{
-
+ /* Set the mem write flag; dest is user-defined */
*pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMWRITE;
psSGXMemDest = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessDest;
if(psMiscInfo->sDevVAddrDest.uiAddr != 0)
{
- psSGXMemDest->sDevVAddr = psMiscInfo->sDevVAddrDest;
+ psSGXMemDest->sDevVAddr = psMiscInfo->sDevVAddrDest; /* dest address */
}
else
{
}
}
-
+ /* Get physical address of PD for memory read (may need to switch context in microkernel) */
if(psMiscInfo->hDevMemContext != IMG_NULL)
{
SGXGetMMUPDAddrKM( (IMG_HANDLE)psDeviceNode, hDevMemContext, &psSGXMemSrc->sPDDevPAddr);
-
+ /* Single app will always use the same src and dest mem context */
psSGXMemDest->sPDDevPAddr = psSGXMemSrc->sPDDevPAddr;
}
else
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* Submit the task to the ukernel */
eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
if(eError != PVRSRV_OK)
{
return PVRSRV_ERROR_INVALID_MISCINFO;
}
#endif
-
+ /* Copy SGX features into misc info struct, to return to client */
psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
return PVRSRV_OK;
}
-#endif
+#endif /* SUPPORT_SGX_EDM_MEMORY_DEBUG */
#if defined(SUPPORT_SGX_HWPERF)
case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON;
SGXMKIF_COMMAND sCommandData = {0};
-
+ /* Check for valid flags */
if ((psSetHWPerfStatus->ui32NewHWPerfStatus & ~ui32ValidFlags) != 0)
{
return PVRSRV_ERROR_INVALID_PARAMS;
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
"SGX ukernel HWPerf status %u\n",
psSetHWPerfStatus->ui32NewHWPerfStatus);
- #endif
+ #endif /* PDUMP */
-
+ /* Copy the new group selector(s) to the host ctl for the ukernel */
#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfGroup[0],
&psSetHWPerfStatus->aui32PerfGroup[0],
OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfBit[0],
&psSetHWPerfStatus->aui32PerfBit[0],
sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit));
+ psDevInfo->psSGXHostCtl->ui32PerfCounterBitSelect = psSetHWPerfStatus->ui32PerfCounterBitSelect;
+ psDevInfo->psSGXHostCtl->ui32PerfSumMux = psSetHWPerfStatus->ui32PerfSumMux;
#if defined(PDUMP)
PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
offsetof(SGXMKIF_HOST_CTL, aui32PerfGroup),
sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit),
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
- #endif
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PerfCounterBitSelect),
+ sizeof(psDevInfo->psSGXHostCtl->ui32PerfCounterBitSelect),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PerfSumMux),
+ sizeof(psDevInfo->psSGXHostCtl->ui32PerfSumMux),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif /* PDUMP */
#else
psDevInfo->psSGXHostCtl->ui32PerfGroup = psSetHWPerfStatus->ui32PerfGroup;
#if defined(PDUMP)
sizeof(psDevInfo->psSGXHostCtl->ui32PerfGroup),
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
- #endif
- #endif
+ #endif /* PDUMP */
+ #endif /* SGX_FEATURE_EXTENDED_PERF_COUNTERS */
-
+ /* Kick the ukernel to update the hardware state */
sCommandData.ui32Data[0] = psSetHWPerfStatus->ui32NewHWPerfStatus;
eError = SGXScheduleCCBCommandKM(psDeviceNode,
SGXMKIF_CMD_SETHWPERFSTATUS,
IMG_FALSE);
return eError;
}
-#endif
+#endif /* SUPPORT_SGX_HWPERF */
case SGX_MISC_INFO_DUMP_DEBUG_INFO:
{
PVR_LOG(("User requested SGX debug info"));
-
+ /* Dump SGX debug data to the kernel log. */
SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_FALSE);
return PVRSRV_OK;
}
+ case SGX_MISC_INFO_DUMP_DEBUG_INFO_FORCE_REGS:
+ {
+ PVR_LOG(("User requested SGX debug info"));
+
+ /* Dump SGX debug data to the kernel log. */
+ SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
+
+ return PVRSRV_OK;
+ }
+
+#if defined(DEBUG)
+ /* Don't allow user-mode to reboot the device in production drivers */
case SGX_MISC_INFO_PANIC:
{
PVR_LOG(("User requested SGX panic"));
return PVRSRV_OK;
}
+#endif
default:
{
-
+ /* switch statement fell though, so: */
return PVRSRV_ERROR_INVALID_PARAMS;
}
}
}
+/******************************************************************************
+ End of file (sgxinit.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
-#include <stddef.h>
+/*************************************************************************/ /*!
+@Title Device specific kickTA routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h> /* For the macro offsetof() */
#include "services_headers.h"
#include "sgxinfo.h"
#include "sgxinfokm.h"
#include "sgxutils.h"
#include "ttrace.h"
+/*!
+******************************************************************************
+
+ @Function SGXDoKickKM
+
+ @Description
+
+ Really kicks the TA
+
+ @Input hDevHandle - Device handle
+
+ @Return ui32Error - success or failure
+
+******************************************************************************/
IMG_EXPORT
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK_KM *psCCBKick)
PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT, KICK_TOKEN_DOKICK);
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
+ /* override QAC warning about stricter alignment */
+ /* PRQA S 3305 1 */
psTACmd = CCB_DATA_FROM_OFFSET(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset);
PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CMD_START, KICK_TOKEN_DOKICK);
+
+#if defined(TTRACE)
+ if (psCCBKick->bFirstKickOrResume)
+ {
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK,
+ PVRSRV_TRACE_CLASS_FLAGS,
+ KICK_TOKEN_FIRST_KICK);
+ }
+
+ if (psCCBKick->bLastInScene)
+ {
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK,
+ PVRSRV_TRACE_CLASS_FLAGS,
+ KICK_TOKEN_LAST_KICK);
+ }
+#endif
PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CCB,
KICK_TOKEN_CCB_OFFSET, psCCBKick->ui32CCBOffset);
-
+ /* TA/3D dependency */
if (psCCBKick->hTA3DSyncInfo)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
if (psCCBKick->ui32NumTAStatusVals != 0)
{
-
+ /* Copy status vals over */
for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
{
#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
if (psCCBKick->ui32Num3DStatusVals != 0)
{
-
+ /* Copy status vals over */
for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
{
#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
-
+ /* SRC and DST sync dependencies */
psTACmd->ui32NumTASrcSyncs = psCCBKick->ui32NumTASrcSyncs;
for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
{
psTACmd->asTASrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psTACmd->asTASrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
-
+ /* Get ui32ReadOpsPending snapshot and copy into the CCB - before incrementing. */
psTACmd->asTASrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
-
+ /* Copy ui32WriteOpsPending snapshot into the CCB. */
psTACmd->asTASrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
}
psTACmd->asTADstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psTACmd->asTADstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
-
+ /* Get ui32ReadOpsPending snapshot and copy into the CCB */
psTACmd->asTADstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
-
+ /* Copy ui32WriteOpsPending snapshot into the CCB - before incrementing */
psTACmd->asTADstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
}
psTACmd->as3DSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psTACmd->as3DSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
-
+ /* Get ui32ReadOpsPending snapshot and copy into the CCB - before incrementing. */
psTACmd->as3DSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
-
+ /* Copy ui32WriteOpsPending snapshot into the CCB. */
psTACmd->as3DSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
}
-#else
-
+#else /* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
+ /* texture dependencies */
psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
{
psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
-
+ /* Get ui32ReadOpsPending snapshot and copy into the CCB - before incrementing. */
psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
-
+ /* Copy ui32WriteOpsPending snapshot into the CCB. */
psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
}
-#endif
+#endif/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
{
if (psSyncInfo)
{
+ psSyncInfo->psSyncData->ui64LastWrite = ui64KickCount;
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_DST_SYNC,
psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psHWDeviceSyncList->asSyncData[i].sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
#if defined(PDUMP)
if (PDumpIsCaptureFrameKM())
+ offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal);
IMG_UINT32 ui32ROpsOffset = ui32SyncOffset
+ offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal);
+ IMG_UINT32 ui32ROps2Offset = ui32SyncOffset
+ + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOps2PendingVal);
PDUMPCOMMENT("HWDeviceSyncObject for RT: %i\r\n", i);
if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
{
-
+ /*
+ * Init the ROpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT ROpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /*
+ * Init the WOpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT WOpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
sizeof(IMG_UINT32),
0,
MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+ /*
+ * Force the ROps2Complete value to 0.
+ */
+ PDUMPCOMMENT("Modify RT %d ROps2PendingVal in HWDevSyncList\r\n", i);
+ PDUMPMEM(&ui32ModifiedValue,
+ psHWDstSyncListMemInfo,
+ ui32ROps2Offset,
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
}
- #endif
+ #endif /* defined(PDUMP) */
}
else
{
psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr.uiAddr = 0;
psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr.uiAddr = 0;
+ psHWDeviceSyncList->asSyncData[i].sReadOps2CompleteDevVAddr.uiAddr = 0;
psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = 0;
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOps2PendingVal = 0;
psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = 0;
}
}
}
-
-
-
+ /*
+ NOTE: THIS MUST BE THE LAST THING WRITTEN TO THE TA COMMAND!
+ Set the ready for so the uKernel will process the command.
+ */
psTACmd->ui32CtrlFlags |= SGXMKIF_CMDTA_CTRLFLAGS_READY;
#if defined(PDUMP)
if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
{
-
+ /*
+ * Init the ROpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT TA-SRC ROpsComplete\r\n", i);
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /*
+ * Init the WOpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT TA-SRC WOpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
{
-
+ /*
+ * Init the ROpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT TA-DST ROpsComplete\r\n", i);
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /*
+ * Init the WOpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT TA-DST WOpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
{
-
+ /*
+ * Init the ROpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT 3D-SRC ROpsComplete\r\n", i);
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /*
+ * Init the WOpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT 3D-SRC WOpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
0,
MAKEUNIQUETAG(psCCBMemInfo));
}
-#else
+#else/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
{
IMG_UINT32 ui32ModifiedValue;
if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
{
-
+ /*
+ * Init the ROpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT ROpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /*
+ * Init the WOpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT WOpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ /*
+ * Init the ROps2Complete value to 0.
+ */
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOps2Complete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOps2Complete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
}
psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
}
-#endif
+#endif/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
{
#endif
}
}
-#endif
+#endif /* defined(PDUMP) */
PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CMD_END,
KICK_TOKEN_DOKICK);
{
for (i=0; i < psCCBKick->ui32NumDstSyncObjects; i++)
{
-
+ /* Client will retry, so undo the write ops pending increment done above. */
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
if (psSyncInfo)
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
psSyncInfo->psSyncData->ui32ReadOpsPending--;
}
-#else
+#else/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
psSyncInfo->psSyncData->ui32ReadOpsPending--;
}
-#endif
+#endif/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
KICK_TOKEN_DOKICK);
#if defined(NO_HARDWARE)
-
+ /* TA/3D dependency */
if (psCCBKick->hTA3DSyncInfo)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
}
-
+ /* Copy status vals over */
for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
{
#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->asTAStatusUpdate[i].hKernelMemInfo;
-
+ /* derive offset into meminfo and write the status value */
*(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+ (psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr.uiAddr
- psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
}
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
-
+ /* SRC and DST dependencies */
for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
}
-#else
-
+#else/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
+ /* texture dependencies */
for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
}
-#endif
+#endif/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
if (psCCBKick->bTerminateOrAbort)
{
}
}
-
+ /* Copy status vals over */
for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
{
#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->as3DStatusUpdate[i].hKernelMemInfo;
-
+ /* derive offset into meminfo and write the status value */
*(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+ (psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr.uiAddr
- psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
return eError;
}
+/******************************************************************************
+ End of file (sgxkick.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific power routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <stddef.h>
SGX_TIMING_INFORMATION *psSGXTimingInfo,
IMG_HANDLE *phTimer)
{
-
-
-
+ /*
+ Install timer callback for HW recovery at 50 times lower
+ frequency than the microkernel timer.
+ */
*phTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
1000 * 50 / psSGXTimingInfo->ui32uKernelFreq);
if(*phTimer == IMG_NULL)
return PVRSRV_OK;
}
-#endif
+#endif /* SUPPORT_HW_RECOVERY*/
+
+
+/*!
+******************************************************************************
+
+ @Function SGXUpdateTimingInfo
+
+ @Description
+
+ Derives the microkernel timing info from the system-supplied values
+ @Input psDeviceNode : SGX Device node
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock;
if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq)
{
-
-
+ /*
+ The ukernel timer frequency has changed.
+ */
IMG_HANDLE hNewTimer;
eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer);
}
else
{
-
+ /* Failed to allocate the new timer, leave the old one. */
}
}
}
psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq;
}
-#endif
+#endif /* SUPPORT_HW_RECOVERY*/
-
+ /* Copy the SGX clock speed for use in the kernel */
psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq;
-
+ /* FIXME: no need to duplicate - remove it from psDevInfo */
psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock;
#if defined(PDUMP)
PDUMPCOMMENT("Host Control - Microkernel clock");
offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock),
sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
-#endif
+#endif /* PDUMP */
if (psSGXTimingInfo->bEnableActivePM)
{
ui32ActivePowManSampleRate =
psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
-
-
-
-
-
-
-
+ /*
+ ui32ActivePowerCounter has the value 0 when SGX is not idle.
+ When SGX becomes idle, the value of ui32ActivePowerCounter is changed from 0 to ui32ActivePowManSampleRate.
+ The ukernel timer routine decrements the value of ui32ActivePowerCounter if it is not 0.
+ When the ukernel timer decrements ui32ActivePowerCounter from 1 to 0, the ukernel timer will
+ request power down.
+ Therefore the minimum value of ui32ActivePowManSampleRate is 1.
+ */
ui32ActivePowManSampleRate += 1;
}
else
offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate),
sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
-#endif
+#endif /* PDUMP */
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function SGXStartTimer
+
+ @Description
+
+ Start the microkernel timer
+
+ @Input psDevInfo : SGX Device Info
+
+ @Return IMG_VOID :
+
+******************************************************************************/
static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO *psDevInfo)
{
#if defined(SUPPORT_HW_RECOVERY)
}
#else
PVR_UNREFERENCED_PARAMETER(psDevInfo);
- #endif
+ #endif /* SUPPORT_HW_RECOVERY */
}
+/*!
+******************************************************************************
+
+ @Function SGXPollForClockGating
+
+ @Description
+
+ Wait until the SGX core clocks have gated.
+
+ @Input psDevInfo : SGX Device Info
+ @Input ui32Register : Offset of register to poll
+ @Input ui32Register : Value of register to poll for
+ @Input pszComment : Description of poll
+
+ @Return IMG_VOID :
+
+******************************************************************************/
static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32Register,
IMG_UINT32 ui32RegisterValue,
#if !defined(NO_HARDWARE)
PVR_ASSERT(psDevInfo != IMG_NULL);
-
+ /* PRQA S 0505 1 */ /* QAC does not like assert() */
if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2),
0,
ui32RegisterValue,
IMG_FALSE) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SGXPollForClockGating: %s failed.", pszComment));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
PVR_DBG_BREAK;
}
- #endif
+ #endif /* NO_HARDWARE */
PDUMPCOMMENT("%s", pszComment);
PDUMPREGPOL(SGX_PDUMPREG_NAME, ui32Register, 0, ui32RegisterValue, PDUMP_POLL_OPERATOR_EQUAL);
}
+/*!
+******************************************************************************
+
+ @Function SGXPrePowerState
+
+ @Description
+
+ does necessary preparation before power state transition
+
+ @Input hDevHandle : SGX Device Node
+ @Input eNewPowerState : New power state
+ @Input eCurrentPowerState : Current power state
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
PVRSRV_DEV_POWER_STATE eNewPowerState,
PVRSRV_DEV_POWER_STATE eCurrentPowerState)
IMG_UINT32 ui32CoresEnabled;
#if defined(SUPPORT_HW_RECOVERY)
-
+ /* Disable timer callback for HW recovery */
eError = OSDisableTimer(psDevInfo->hTimer);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer"));
return eError;
}
- #endif
+ #endif /* SUPPORT_HW_RECOVERY */
if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
{
-
+ /* Request the ukernel to idle SGX and save its state. */
ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
PDUMPCOMMENT("SGX power off request");
}
else
{
-
+ /* Request the ukernel to idle SGX. */
ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
PDUMPCOMMENT("SGX idle request");
return eError;
}
-
+ /* Wait for the ukernel to complete processing. */
#if !defined(NO_HARDWARE)
if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
ui32CompleteStatus,
IMG_FALSE) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed."));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
PVR_DBG_BREAK;
}
- #endif
+ #endif /* NO_HARDWARE */
#if defined(PDUMP)
PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel.");
PDUMP_POLL_OPERATOR_EQUAL,
0,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
- #endif
+ #endif /* PDUMP */
#if defined(SGX_FEATURE_MP)
ui32CoresEnabled = ((OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE) & EUR_CR_MASTER_CORE_ENABLE_MASK) >> EUR_CR_MASTER_CORE_ENABLE_SHIFT) + 1;
for (ui32Core = 0; ui32Core < ui32CoresEnabled; ui32Core++)
{
-
+ /* Wait for SGX clock gating. */
SGXPollForClockGating(psDevInfo,
SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core),
psDevInfo->ui32ClkGateStatusMask,
}
#if defined(SGX_FEATURE_MP)
-
+ /* Wait for SGX master clock gating. */
SGXPollForClockGating(psDevInfo,
psDevInfo->ui32MasterClkGateStatusReg,
psDevInfo->ui32MasterClkGateStatusMask,
psDevInfo->ui32MasterClkGateStatus2Reg,
psDevInfo->ui32MasterClkGateStatus2Mask,
"Wait for SGX master clock gating (2)");
- #endif
+ #endif /* SGX_FEATURE_MP */
if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
{
-
+ /* Finally, de-initialise some registers. */
eError = SGXDeinitialise(psDevInfo);
if (eError != PVRSRV_OK)
{
}
+/*!
+******************************************************************************
+
+ @Function SGXPostPowerState
+
+ @Description
+
+ does necessary preparation after power state transition
+
+ @Input hDevHandle : SGX Device Node
+ @Input eNewPowerState : New power state
+ @Input eCurrentPowerState : Current power state
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle,
PVRSRV_DEV_POWER_STATE eNewPowerState,
PVRSRV_DEV_POWER_STATE eCurrentPowerState)
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
-
+ /* Reset the power manager flags. */
psSGXHostCtl->ui32PowerStatus = 0;
#if defined(PDUMP)
PDUMPCOMMENT("Host Control - Reset power status");
offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
- #endif
+ #endif /* PDUMP */
if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
{
-
-
-
+ /*
+ Coming up from off, re-initialise SGX.
+ */
+ /*
+ Re-generate the timing data required by SGX.
+ */
eError = SGXUpdateTimingInfo(psDeviceNode);
if (eError != PVRSRV_OK)
{
return eError;
}
-
-
+ /*
+ Run the SGX init script.
+ */
eError = SGXInitialise(psDevInfo, IMG_FALSE);
if (eError != PVRSRV_OK)
{
}
else
{
-
-
+ /*
+ Coming up from idle, restart the ukernel.
+ */
SGXMKIF_COMMAND sCommand = {0};
sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME;
}
+/*!
+******************************************************************************
+
+ @Function SGXPreClockSpeedChange
+
+ @Description
+
+ Does processing required before an SGX clock speed change.
+
+ @Input hDevHandle : SGX Device Node
+ @Input bIdleDevice : Whether the microkernel needs to be idled
+ @Input eCurrentPowerState : Power state of the device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE hDevHandle,
IMG_BOOL bIdleDevice,
PVRSRV_DEV_POWER_STATE eCurrentPowerState)
{
if (bIdleDevice)
{
-
+ /*
+ * Idle SGX.
+ */
PDUMPSUSPEND();
eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE,
}
+/*!
+******************************************************************************
+
+ @Function SGXPostClockSpeedChange
+
+ @Description
+
+ Does processing required after an SGX clock speed change.
+
+ @Input hDevHandle : SGX Device Node
+ @Input bIdleDevice : Whether the microkernel had been idled previously
+ @Input eCurrentPowerState : Power state of the device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE hDevHandle,
IMG_BOOL bIdleDevice,
PVRSRV_DEV_POWER_STATE eCurrentPowerState)
{
PVRSRV_ERROR eError;
-
-
+ /*
+ Re-generate the timing data required by SGX.
+ */
eError = SGXUpdateTimingInfo(psDeviceNode);
if (eError != PVRSRV_OK)
{
if (bIdleDevice)
{
-
+ /*
+ * Resume SGX.
+ */
eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON,
PVRSRV_DEV_POWER_STATE_IDLE);
}
+/******************************************************************************
+ End of file (sgxpower.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific reset routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "sgxdefs.h"
#include "sgxmmu.h"
#include "pdump_km.h"
+/*!
+*******************************************************************************
+
+ @Function SGXInitClocks
+
+ @Description
+ Initialise the SGX clocks
+
+ @Input psDevInfo - device info. structure
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SGXInitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32PDUMPFlags)
{
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
ui32RegVal = psDevInfo->ui32ClkGateCtl;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL, ui32RegVal);
}
+/*!
+*******************************************************************************
+
+ @Function SGXResetInitBIFContexts
+
+ @Description
+ Initialise the BIF memory contexts
+
+ @Input psDevInfo - SGX Device Info
+
+ @Return IMG_VOID
+
+******************************************************************************/
static IMG_VOID SGXResetInitBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32PDUMPFlags)
{
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
ui32RegVal = 0;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK_SET, ui32RegVal, ui32PDUMPFlags);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
-#endif
+#endif /* SGX_FEATURE_MULTIPLE_MEM_CONTEXTS */
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the BIF directory list\r\n");
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, ui32DirListReg, ui32RegVal, ui32PDUMPFlags);
}
}
-#endif
+#endif /* SGX_FEATURE_MULTIPLE_MEM_CONTEXTS */
}
+/*!
+*******************************************************************************
+
+ @Function SGXResetSetupBIFContexts
+
+ @Description
+ Configure the BIF for the EDM context
+
+ @Input psDevInfo - SGX Device Info
+
+ @Return IMG_VOID
+
+******************************************************************************/
static IMG_VOID SGXResetSetupBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32PDUMPFlags)
{
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
-
+ /* Set up EDM for bank 0 to point at kernel context */
ui32RegVal = (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT);
#if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
-
+ /* Set up 2D core for bank 0 to point at kernel context */
ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_2D_SHIFT);
- #endif
+ #endif /* SGX_FEATURE_2D_HARDWARE */
#if defined(FIX_HW_BRN_23410)
-
+ /* Set up TA core for bank 0 to point at kernel context to guarantee it is a valid context */
ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_TA_SHIFT);
- #endif
+ #endif /* FIX_HW_BRN_23410 */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Set up EDM requestor page table in BIF\r\n");
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
- #endif
+ #endif /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) */
{
IMG_UINT32 ui32EDMDirListReg;
-
+ /* Set up EDM context with kernel page directory */
#if (SGX_BIF_DIR_LIST_INDEX_EDM == 0)
ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0;
#else
-
+ /* Bases 0 and 1 are not necessarily contiguous */
ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1);
- #endif
+ #endif /* SGX_BIF_DIR_LIST_INDEX_EDM */
ui32RegVal = psDevInfo->sKernelPDDevPAddr.uiAddr >> SGX_MMU_PDE_ADDR_ALIGNSHIFT;
}
+/*!
+*******************************************************************************
+
+ @Function SGXResetSleep
+
+ @Description
+
+ Sleep for a short time to allow reset register writes to complete.
+ Required because no status registers are available to poll on.
+
+ @Input psDevInfo - SGX Device Info
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+ @Input bPDump - Pdump the sleep
+
+ @Return Nothing
+
+******************************************************************************/
static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32PDUMPFlags,
IMG_BOOL bPDump)
ui32ReadRegister = EUR_CR_MASTER_SOFT_RESET;
#else
ui32ReadRegister = EUR_CR_SOFT_RESET;
- #endif
+ #endif /* SGX_FEATURE_MP */
#endif
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
-
+ /* Sleep for 100 SGX clocks */
SGXWaitClocks(psDevInfo, 100);
if (bPDump)
{
}
#if defined(EMULATOR)
-
-
+ /*
+ Read a register to make sure we wait long enough on the emulator...
+ */
OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32ReadRegister);
#endif
}
#if !defined(SGX_FEATURE_MP)
+/*!
+*******************************************************************************
+
+ @Function SGXResetSoftReset
+
+ @Description
+
+ Write to the SGX soft reset register.
+
+ @Input psDevInfo - SGX Device Info
+ @Input bResetBIF - Include the BIF in the soft reset
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+ @Input bPDump - Pdump the sleep
+
+ @Return Nothing
+
+******************************************************************************/
static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_BOOL bResetBIF,
IMG_UINT32 ui32PDUMPFlags,
IMG_UINT32 ui32SoftResetRegVal;
ui32SoftResetRegVal =
-
+ /* add common reset bits: */
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;
+/* add conditional reset bits: */
#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK;
#endif
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
if (bResetBIF)
{
}
+/*!
+*******************************************************************************
+
+ @Function SGXResetInvalDC
+
+ @Description
+
+ Invalidate the BIF Directory Cache and wait for the operation to complete.
+
+ @Input psDevInfo - SGX Device Info
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+
+ @Return Nothing
+
+******************************************************************************/
static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32PDUMPFlags,
IMG_BOOL bPDump)
{
IMG_UINT32 ui32RegVal;
-
+ /* Invalidate BIF Directory cache. */
#if defined(EUR_CR_BIF_CTRL_INVAL)
ui32RegVal = EUR_CR_BIF_CTRL_INVAL_ALL_MASK;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, ui32RegVal);
#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
{
-
-
-
+ /*
+ Wait for the DC invalidate to complete - indicated by
+ outstanding reads reaching zero.
+ */
if (PollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
0,
EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
PDUMPREGPOLWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_REQ_STAT, 0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK, ui32PDUMPFlags, PDUMP_POLL_OPERATOR_EQUAL);
}
}
-#endif
+#endif /* SGX_FEATURE_MULTIPLE_MEM_CONTEXTS */
}
-#endif
+#endif /* SGX_FEATURE_MP */
+
+
+/*!
+*******************************************************************************
+ @Function SGXReset
+ @Description
+
+ Reset chip
+
+ @Input psDevInfo - device info. structure
+ @Input bHardwareRecovery - true if recovering powered hardware,
+ false if powering up
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_BOOL bHardwareRecovery,
IMG_UINT32 ui32PDUMPFlags)
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX reset sequence\r\n");
#if defined(FIX_HW_BRN_23944)
-
+ /* Pause the BIF. */
ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
if (ui32RegVal & ui32BifFaultMask)
{
-
+ /* Page fault needs to be cleared before resetting the BIF. */
ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK | EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
}
-#endif
+#endif /* defined(FIX_HW_BRN_23944) */
-
+ /* Reset all including BIF */
SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
-
-
+ /*
+ Initialise the BIF state.
+ */
#if defined(SGX_FEATURE_36BIT_MMU)
-
+ /* enable 36bit addressing mode if the MMU supports it*/
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK, ui32PDUMPFlags);
#endif
SGXResetInitBIFContexts(psDevInfo, ui32PDUMPFlags);
#if defined(EUR_CR_BIF_MEM_ARB_CONFIG)
-
-
+ /*
+ Initialise the memory arbiter to its default state
+ */
ui32RegVal = (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT) |
(7UL << EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT) |
(12UL << EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal, ui32PDUMPFlags);
-#endif
+#endif /* EUR_CR_BIF_MEM_ARB_CONFIG */
#if defined(SGX_FEATURE_SYSTEM_CACHE)
#if defined(SGX_BYPASS_SYSTEM_CACHE)
-
+ /* set the SLC to bypass all accesses */
ui32RegVal = MNE_CR_CTRL_BYPASS_ALL_MASK;
#else
#if defined(FIX_HW_BRN_26620)
ui32RegVal = 0;
#else
-
+ /* set the SLC to bypass cache-coherent accesses */
ui32RegVal = MNE_CR_CTRL_BYP_CC_MASK;
#endif
#if defined(FIX_HW_BRN_34028)
-
+ /* Bypass the MNE for the USEC requester */
ui32RegVal |= (8 << MNE_CR_CTRL_BYPASS_SHIFT);
#endif
- #endif
+ #endif /* SGX_BYPASS_SYSTEM_CACHE */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, MNE_CR_CTRL, ui32RegVal);
PDUMPREG(SGX_PDUMPREG_NAME, MNE_CR_CTRL, ui32RegVal);
-#endif
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
if (bHardwareRecovery)
{
-
-
-
-
-
-
-
+ /*
+ Set all requestors to the dummy PD which forces all memory
+ accesses to page fault.
+ This enables us to flush out BIF requests from parts of SGX
+ which do not have their own soft reset.
+ Note: sBIFResetPDDevPAddr.uiAddr is a relative address (2GB max)
+ MSB is the bus master flag; 1 == enabled
+ */
ui32RegVal = (IMG_UINT32)psDevInfo->sBIFResetPDDevPAddr.uiAddr;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
-
+ /* Bring BIF out of reset. */
SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
-
-
+ /*
+ Check for a page fault from parts of SGX which do not have a reset.
+ */
for (;;)
{
IMG_UINT32 ui32BifIntStat = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
break;
}
-
-
-
+ /*
+ There is a page fault, so reset the BIF again, map in the dummy page,
+ bring the BIF up and invalidate the Directory Cache.
+ */
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;
-
+ /* Put the BIF into reset. */
SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_FALSE);
-
+ /* Map in the dummy page. */
psDevInfo->pui32BIFResetPD[ui32PDIndex] = (psDevInfo->sBIFResetPTDevPAddr.uiAddr
>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
-
+ /* Clear outstanding events. */
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);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
-
+ /* Bring the BIF out of reset. */
SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_FALSE);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
-
+ /* Invalidate Directory Cache. */
SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
-
+ /* Unmap the dummy page and try again. */
psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0;
psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0;
}
}
else
{
-
+ /* Bring BIF out of reset. */
SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
}
-
-
+ /*
+ Initialise the BIF memory contexts before bringing the rest of SGX out of reset.
+ */
SGXResetSetupBIFContexts(psDevInfo, ui32PDUMPFlags);
#if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
-
+ /* check that the heap base has the right alignment (1Mb) */
#if ((SGX_2D_HEAP_BASE & ~EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK) != 0)
#error "SGXReset: SGX_2D_HEAP_BASE doesn't match EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK alignment"
#endif
-
+ /* Set up 2D requestor base */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE, ui32PDUMPFlags);
#endif
-
+ /* Invalidate BIF Directory cache. */
SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
PVR_DPF((PVR_DBG_MESSAGE,"Soft Reset of SGX"));
-
+ /* Take chip out of reset */
ui32RegVal = 0;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
-
+ /* wait a bit */
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX MP reset sequence\r\n");
-
+ /* Put hydra into soft reset */
ui32RegVal = EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK |
EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK |
EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK |
- EUR_CR_MASTER_SOFT_RESET_MCI_RESET_MASK |
EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK;
+ if (bHardwareRecovery)
+ {
+ ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_MCI_RESET_MASK;
+ }
+
#if defined(SGX_FEATURE_PTLA)
ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_MASK;
#endif
ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_SLC_RESET_MASK;
#endif
-
+ /* Hard reset the slave cores */
ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(0) |
EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(1) |
EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(2) |
#endif
#if defined(PVR_SLC_8KB_ADDRESS_MODE)
(4 << EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_SHIFT) |
+ #endif
+ #if defined(FIX_HW_BRN_33809)
+ (2 << EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_SHIFT) |
#endif
(0xC << EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SHIFT);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE3_MASK |
EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TA_MASK;
#endif
- #endif
+ #endif /* SGX_BYPASS_SYSTEM_CACHE */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the hydra SLC bypass control\r\n");
PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
-#endif
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
-
+ /* Remove the resets */
ui32RegVal = 0;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal);
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Remove the resets from all of SGX\r\n");
#if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_31620) || defined(FIX_HW_BRN_31671) || defined(FIX_HW_BRN_32085)
#if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_32085)
-
+ /* disable prefetch */
ui32RegVal = (1<<EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT);
#else
ui32RegVal = (1<<EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT) | EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_MASK;
#endif
#if !defined(FIX_HW_BRN_31620) && !defined(FIX_HW_BRN_31671)
-
+ /* enable the DC TLB */
ui32RegVal |= EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK;
#endif
-
+ /* Master bank */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_MMU_CTRL, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_BIF_MMU_CTRL, ui32RegVal, ui32PDUMPFlags);
#if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_32085)
-
+ /* disable prefetch */
ui32RegVal = (1<<EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT);
#else
ui32RegVal = (1<<EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT) | EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_MASK;
#endif
#if !defined(FIX_HW_BRN_31620) && !defined(FIX_HW_BRN_31671)
-
+ /* enable the DC TLB */
ui32RegVal |= EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK;
#endif
-
+ /* Per-core */
{
IMG_UINT32 ui32Core;
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX MP reset sequence\r\n");
}
-#endif
+#endif /* SGX_FEATURE_MP */
+/******************************************************************************
+ End of file (sgxreset.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific transfer queue routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if defined(TRANSFER_QUEUE)
#if defined(PDUMP)
IMG_BOOL bPersistentProcess = IMG_FALSE;
-
+ /*
+ * For persistent processes, the HW kicks should not go into the
+ * extended init phase; only keep memory transactions from the
+ * window system which are necessary to run the client app.
+ */
{
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc != IMG_NULL)
bPersistentProcess = psPerProc->bPDumpPersistent;
}
}
-#endif
+#endif /* PDUMP */
#if defined(FIX_HW_BRN_31620)
hDevMemContext = psKick->hDevMemContext;
#endif
TRANSFER_TOKEN_SUBMIT);
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
+ /* override QAC warning about stricter alignment */
+ /* PRQA S 3305 1 */
psSharedTransferCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CMD_START, TRANSFER_TOKEN_SUBMIT);
psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
}
-
+ /* filter out multiple occurrences of the same sync object from srcs or dests
+ * note : the same sync can still be used to synchronize both src and dst.
+ */
for (loop = 0; loop < MIN(SGX_MAX_TRANSFER_SYNC_OPS, psKick->ui32NumSrcSync); loop++)
{
IMG_UINT32 i;
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+ psSyncInfo->psSyncData->ui64LastWrite = ui64KickCount;
+
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_DST_SYNC,
psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
psSharedTransferCmd->asDstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
psSharedTransferCmd->asDstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ psSharedTransferCmd->asDstSyncs[i].ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
psSharedTransferCmd->asDstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psSharedTransferCmd->asDstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psSharedTransferCmd->asDstSyncs[i].sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
i++;
}
}
PVR_ASSERT(i == ui32RealDstSyncNum);
-
+ /*
+ * We allow source and destination sync objects to be the
+ * same, which is why the read/write pending updates are delayed
+ * until the transfer command has been updated with the current
+ * values from the objects.
+ */
for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
{
if (abSrcSyncEnable[loop])
{
psSyncInfo = psKick->ahSrcSyncInfo[loop];
- PDUMPCOMMENT("Hack src surface write op in transfer cmd\r\n");
+ PDUMPCOMMENT("Tweak src surface write op in transfer cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)),
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
- PDUMPCOMMENT("Hack src surface read op in transfer cmd\r\n");
+ PDUMPCOMMENT("Tweak src surface read op in transfer cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal)),
{
if (abDstSyncEnable[i])
{
+ IMG_UINT32 ui32PDumpReadOp2 = 0;
psSyncInfo = psKick->ahDstSyncInfo[loop];
- PDUMPCOMMENT("Hack dest surface write op in transfer cmd\r\n");
+ PDUMPCOMMENT("Tweak dest surface write op in transfer cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)),
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
- PDUMPCOMMENT("Hack dest surface read op in transfer cmd\r\n");
+ PDUMPCOMMENT("Tweak dest surface read op in transfer cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal)),
sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Tweak dest surface read op2 in transfer cmd\r\n");
+ PDUMPMEM(&ui32PDumpReadOp2,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOps2PendingVal)),
+ sizeof(ui32PDumpReadOp2),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
i++;
}
}
-
+ /*
+ * We allow the first source and destination sync objects to be the
+ * same, which is why the read/write pending updates are delayed
+ * until the transfer command has been updated with the current
+ * values from the objects.
+ */
for (loop = 0; loop < (psKick->ui32NumSrcSync); loop++)
{
if (abSrcSyncEnable[loop])
if (eError == PVRSRV_ERROR_RETRY)
{
-
+ /* Client will retry, so undo the sync ops pending increment(s) done above. */
if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
{
for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
}
}
-
+ /* Command needed to be synchronised with the TA? */
if (psKick->hTASyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
psSyncInfo->psSyncData->ui32WriteOpsPending--;
}
-
+ /* Command needed to be synchronised with the 3D? */
if (psKick->h3DSyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
#if defined(NO_HARDWARE)
if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE) == 0)
{
-
+ /* Update sync objects pretending that we have done the job*/
for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
{
if (abSrcSyncEnable[loop])
IMG_HANDLE hDevMemContext = IMG_NULL;
#if defined(PDUMP)
IMG_BOOL bPersistentProcess = IMG_FALSE;
-
+ /*
+ * For persistent processes, the HW kicks should not go into the
+ * extended init phase; only keep memory transactions from the
+ * window system which are necessary to run the client app.
+ */
{
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc != IMG_NULL)
bPersistentProcess = psPerProc->bPDumpPersistent;
}
}
-#endif
+#endif /* PDUMP */
#if defined(FIX_HW_BRN_31620)
hDevMemContext = psKick->hDevMemContext;
#endif
PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset"));
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
+ /* override QAC warning about stricter alignment */
+ /* PRQA S 3305 1 */
ps2DCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
OSMemSet(ps2DCmd, 0, sizeof(*ps2DCmd));
-
+ /* Command needs to be synchronised with the TA? */
if (psKick->hTASyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
}
-
+ /* Command needs to be synchronised with the 3D? */
if (psKick->h3DSyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
}
-
+ /*
+ * We allow the first source and destination sync objects to be the
+ * same, which is why the read/write pending updates are delayed
+ * until the transfer command has been updated with the current
+ * values from the objects.
+ */
ps2DCmd->ui32NumSrcSync = psKick->ui32NumSrcSync;
for (i = 0; i < psKick->ui32NumSrcSync; i++)
{
ps2DCmd->sDstSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
ps2DCmd->sDstSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ ps2DCmd->sDstSyncData.ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ ps2DCmd->sDstSyncData.sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
}
-
+ /* Read/Write ops pending updates, delayed from above */
for (i = 0; i < psKick->ui32NumSrcSync; i++)
{
psSyncInfo = psKick->ahSrcSyncInfo[i];
|| ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
&& (bPersistentProcess == IMG_FALSE) )
{
-
+ /* Pdump the command from the per context CCB */
PDUMPCOMMENT("Shared part of 2D command\r\n");
PDUMPMEM(ps2DCmd,
psCCBMemInfo,
{
psSyncInfo = psKick->ahSrcSyncInfo[i];
- PDUMPCOMMENT("Hack src surface write op in 2D cmd\r\n");
+ PDUMPCOMMENT("Tweak src surface write op in 2D cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32WriteOpsPendingVal),
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
- PDUMPCOMMENT("Hack src surface read op in 2D cmd\r\n");
+ PDUMPCOMMENT("Tweak src surface read op in 2D cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32ReadOpsPendingVal),
if (psKick->hDstSyncInfo != IMG_NULL)
{
+ IMG_UINT32 ui32PDumpReadOp2 = 0;
psSyncInfo = psKick->hDstSyncInfo;
- PDUMPCOMMENT("Hack dest surface write op in 2D cmd\r\n");
+ PDUMPCOMMENT("Tweak dest surface write op in 2D cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32WriteOpsPendingVal),
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
- PDUMPCOMMENT("Hack dest surface read op in 2D cmd\r\n");
+ PDUMPCOMMENT("Tweak dest surface read op in 2D cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOpsPendingVal),
sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
+ PDUMPCOMMENT("Tweak dest surface read op2 in 2D cmd\r\n");
+ PDUMPMEM(&ui32PDumpReadOp2,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOps2PendingVal),
+ sizeof(ui32PDumpReadOp2),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
}
-
+ /* Read/Write ops pending updates, delayed from above */
for (i = 0; i < psKick->ui32NumSrcSync; i++)
{
psSyncInfo = psKick->ahSrcSyncInfo[i];
if (eError == PVRSRV_ERROR_RETRY)
{
-
-
+ /* Client will retry, so undo the write ops pending increment
+ done above.
+ */
#if defined(PDUMP)
if (PDumpIsCaptureFrameKM())
{
psSyncInfo->psSyncData->ui32WriteOpsPending--;
}
-
+ /* Command needed to be synchronised with the TA? */
if (psKick->hTASyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
psSyncInfo->psSyncData->ui32WriteOpsPending--;
}
-
+ /* Command needed to be synchronised with the 3D? */
if (psKick->h3DSyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
#if defined(NO_HARDWARE)
-
+ /* Update sync objects pretending that we have done the job*/
for(i = 0; i < psKick->ui32NumSrcSync; i++)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
return eError;
}
-#endif
-#endif
+#endif /* SGX_FEATURE_2D_HARDWARE */
+#endif /* TRANSFER_QUEUE */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific utility routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Device specific functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <stddef.h>
#include "ttrace.h"
#ifdef __linux__
-#include <linux/kernel.h>
-#include <linux/string.h>
+#include <linux/kernel.h> // sprintf
+#include <linux/string.h> // strncpy, strlen
#else
#include <stdio.h>
#endif
+IMG_UINT64 ui64KickCount;
+
#if defined(SYS_CUSTOM_POWERDOWN)
PVRSRV_ERROR SysPowerDownMISR(PVRSRV_DEVICE_NODE * psDeviceNode, IMG_UINT32 ui32CallerID);
+/*!
+******************************************************************************
+
+ @Function SGXPostActivePowerEvent
+
+ @Description
+
+ post power event functionality (e.g. restart)
+
+ @Input psDeviceNode : SGX Device Node
+ @Input ui32CallerID - KERNEL_ID or ISR_ID
+
+ @Return IMG_VOID :
+
+******************************************************************************/
static IMG_VOID SGXPostActivePowerEvent(PVRSRV_DEVICE_NODE * psDeviceNode,
IMG_UINT32 ui32CallerID)
{
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
-
+ /* Update the counter for stats. */
psSGXHostCtl->ui32NumActivePowerEvents++;
if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE) != 0)
{
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXPostActivePowerEvent: SGX requests immediate restart"));
-
-
+ /*
+ Events were queued during the active power
+ request, so SGX will need to be restarted.
+ */
if (ui32CallerID == ISR_ID)
{
psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function SGXTestActivePowerEvent
+
+ @Description
+
+ Checks whether the microkernel has generated an active power event. If so,
+ perform the power transition.
+
+ @Input psDeviceNode : SGX Device Node
+ @Input ui32CallerID - KERNEL_ID or ISR_ID
+
+ @Return IMG_VOID :
+
+******************************************************************************/
IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_UINT32 ui32CallerID)
{
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
- if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) &&
- ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0))
+#if defined(SYS_SUPPORTS_SGX_IDLE_CALLBACK)
+ if (!psDevInfo->bSGXIdle &&
+ ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) != 0))
{
-
+ psDevInfo->bSGXIdle = IMG_TRUE;
+ SysSGXIdleTransition(psDevInfo->bSGXIdle);
+ }
+ else if (psDevInfo->bSGXIdle &&
+ ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) == 0))
+ {
+ psDevInfo->bSGXIdle = IMG_FALSE;
+ SysSGXIdleTransition(psDevInfo->bSGXIdle);
+ }
+#endif /* SYS_SUPPORTS_SGX_IDLE_CALLBACK */
+
+ /*
+ * Quickly check (without lock) if there is an APM event we should handle.
+ * This check fails most of the time so we don't want to incur lock overhead.
+ * Check the flags in the reverse order that microkernel clears them to prevent
+ * us from seeing an inconsistent state.
+ */
+ if (((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0) &&
+ ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0))
+ {
+ eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ return;
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXTestActivePowerEvent failed to acquire lock - "
+ "ui32CallerID:%d eError:%u", ui32CallerID, eError));
+ return;
+ }
+
+ /*
+ * Check again (with lock) if APM event has been cleared or handled. A race
+ * condition may allow multiple threads to pass the quick check.
+ */
+ if (((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) ||
+ ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0))
+ {
+ PVRSRVPowerUnlock(ui32CallerID);
+ return;
+ }
+
+ /* Microkernel is idle and is requesting to be powered down. */
psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
-
+ /* Suspend pdumping. */
PDUMPSUSPEND();
#if defined(SYS_CUSTOM_POWERDOWN)
-
-
-
+ /*
+ Some power down code cannot be executed inside an MISR on
+ some platforms that use mutexes inside the power code.
+ */
eError = SysPowerDownMISR(psDeviceNode, ui32CallerID);
#else
eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
- PVRSRV_DEV_POWER_STATE_OFF,
- ui32CallerID, IMG_FALSE);
+ PVRSRV_DEV_POWER_STATE_OFF);
if (eError == PVRSRV_OK)
{
SGXPostActivePowerEvent(psDeviceNode, ui32CallerID);
}
#endif
- if (eError == PVRSRV_ERROR_RETRY)
- {
-
-
- psSGXHostCtl->ui32InterruptClearFlags &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
- eError = PVRSRV_OK;
- }
+ PVRSRVPowerUnlock(ui32CallerID);
-
+ /* Resume pdumping */
PDUMPRESUME();
}
}
+/******************************************************************************
+ FUNCTION : SGXAcquireKernelCCBSlot
+
+ PURPOSE : Attempts to obtain a slot in the Kernel CCB
+
+ PARAMETERS : psCCB - the CCB
+
+ RETURNS : Address of space if available, IMG_NULL otherwise
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(SGXAcquireKernelCCBSlot)
#endif
OSSleepms(1);
} END_LOOP_UNTIL_TIMEOUT();
-
+ /* Time out on waiting for CCB space */
return IMG_NULL;
}
+/*!
+******************************************************************************
+
+ @Function SGXScheduleCCBCommand
+
+ @Description - Submits a CCB command and kicks the ukernel (without
+ power management)
+
+ @Input psDevInfo - pointer to device info
+ @Input eCmdType - see SGXMKIF_CMD_*
+ @Input psCommandData - kernel CCB command
+ @Input ui32CallerID - KERNEL_ID or ISR_ID
+ @Input ui32PDumpFlags
+
+ @Return ui32Error - success or failure
+
+******************************************************************************/
PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
SGXMKIF_CMD_TYPE eCmdType,
SGXMKIF_COMMAND *psCommandData,
PVRSRV_ERROR eError = PVRSRV_OK;
SGXMKIF_COMMAND *psSGXCommand;
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
#if defined(FIX_HW_BRN_31620)
IMG_UINT32 ui32CacheMasks[4];
IMG_UINT32 i;
psMMUContext = psDevInfo->hKernelMMUContext;
psDeviceNode->pfnMMUGetCacheFlushRange(psMMUContext, &ui32CacheMasks[0]);
-
+ /* Put the apps memory context in the bottom half */
if (hDevMemContext)
{
BM_CONTEXT *psBMContext = (BM_CONTEXT *) hDevMemContext;
psDeviceNode->pfnMMUGetCacheFlushRange(psMMUContext, &ui32CacheMasks[2]);
}
-
+ /* If we have an outstanding flush request then set the cachecontrol bit */
if (ui32CacheMasks[0] || ui32CacheMasks[1] || ui32CacheMasks[2] || ui32CacheMasks[3])
{
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
#endif
#if defined(FIX_HW_BRN_28889)
-
-
-
-
+ /*
+ If the data cache and bif cache need invalidating there has been a cleanup
+ request. Therefore, we need to send the invalidate seperately and wait
+ for it to complete.
+ */
if ( (eCmdType != SGXMKIF_CMD_PROCESS_QUEUES) &&
((psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_DATA) != 0) &&
((psDevInfo->ui32CacheControl & (SGXMKIF_CC_INVAL_BIF_PT | SGXMKIF_CC_INVAL_BIF_PD)) != 0))
goto Exit;
}
-
+ /* Wait for the invalidate to happen */
#if !defined(NO_HARDWARE)
if(PollForValueKM(&psSGXHostCtl->ui32InvalStatus,
PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
#endif
#if defined(PDUMP)
-
+ /* Pdump the poll as well. */
PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for BIF cache invalidate request to complete");
PDUMPMEMPOL(psSGXHostCtlMemInfo,
offsetof(SGXMKIF_HOST_CTL, ui32InvalStatus),
PDUMP_POLL_OPERATOR_EQUAL,
0,
MAKEUNIQUETAG(psSGXHostCtlMemInfo));
- #endif
+ #endif /* PDUMP */
psSGXHostCtl->ui32InvalStatus &= ~(PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE);
PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
SGXMKIF_COMMAND sPDECacheCommand = {0};
IMG_DEV_PHYADDR sDevPAddr;
-
+ /* Put the kernel info in the top 1/2 of the data */
psMMUContext = psDevInfo->hKernelMMUContext;
psDeviceNode->pfnMMUGetPDPhysAddr(psMMUContext, &sDevPAddr);
sPDECacheCommand.ui32Data[1] = ui32CacheMasks[0];
sPDECacheCommand.ui32Data[2] = ui32CacheMasks[1];
-
+ /* Put the apps memory context in the bottom half */
if (hDevMemContext)
{
BM_CONTEXT *psBMContext = (BM_CONTEXT *) hDevMemContext;
psMMUContext = psBMContext->psMMUContext;
psDeviceNode->pfnMMUGetPDPhysAddr(psMMUContext, &sDevPAddr);
-
+ /* Or in 1 to the lsb to show we have a valid context */
sPDECacheCommand.ui32Data[3] = sDevPAddr.uiAddr | 1;
sPDECacheCommand.ui32Data[4] = ui32CacheMasks[2];
sPDECacheCommand.ui32Data[5] = ui32CacheMasks[3];
}
-
+ /* Only do a kick if there is any update */
if (sPDECacheCommand.ui32Data[1] | sPDECacheCommand.ui32Data[2] | sPDECacheCommand.ui32Data[4] |
sPDECacheCommand.ui32Data[5])
{
}
#endif
#if defined(PDUMP)
-
+ /*
+ * For persistent processes, the HW kicks should not go into the
+ * extended init phase; only keep memory transactions from the
+ * window system which are necessary to run the client app.
+ */
{
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc != IMG_NULL)
bPersistentProcess = psPerProc->bPDumpPersistent;
}
}
-#endif
+#endif /* PDUMP */
psKernelCCB = psDevInfo->psKernelCCBInfo;
psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
-
+ /* Wait for CCB space timed out */
if(!psSGXCommand)
{
PVR_DPF((PVR_DBG_ERROR, "SGXScheduleCCBCommand: Wait for CCB space timed out")) ;
goto Exit;
}
-
+ /* embed cache control word */
psCommandData->ui32CacheControl = psDevInfo->ui32CacheControl;
#if defined(PDUMP)
-
+ /* Accumulate any cache invalidates that may have happened */
psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
#endif
-
+ /* and clear it */
psDevInfo->ui32CacheControl = 0;
-
+ /* Copy command data over */
*psSGXCommand = *psCommandData;
if (eCmdType >= SGXMKIF_CMD_MAX)
goto Exit;
}
- if ((eCmdType == SGXMKIF_CMD_TA) && bLastInScene)
+ if (eCmdType == SGXMKIF_CMD_2D ||
+ eCmdType == SGXMKIF_CMD_TRANSFER ||
+ ((eCmdType == SGXMKIF_CMD_TA) && bLastInScene))
{
SYS_DATA *psSysData;
-
+ /* CPU cache clean control */
SysAcquireData(&psSysData);
if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
OSCleanCPUCacheKM();
}
-
+ /* Clear the pending op */
psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
}
PVR_ASSERT(eCmdType < SGXMKIF_CMD_MAX);
- psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType];
+ psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType]; /* PRQA S 3689 */ /* misuse of enums for bounds checking */
#if defined(PDUMP)
if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) &&
(bPersistentProcess == IMG_FALSE) )
{
-
+ /* Poll for space in the CCB. */
PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for space in the Kernel CCB\r\n");
PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
ui32PDumpFlags,
MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
-
+ /* Overwrite cache control with pdump shadow */
PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
psKernelCCB->psCCBMemInfo,
psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND) +
if (PDumpIsCaptureFrameKM()
|| ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
{
-
+ /* Clear cache invalidate shadow */
psDevInfo->sPDContext.ui32CacheControl = 0;
}
}
#endif
#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
-
+ /* Make sure the previous command has been read before send the next one */
eError = PollForValueKM (psKernelCCB->pui32ReadOffset,
*psKernelCCB->pui32WriteOffset,
0xFF,
}
#endif
-
-
+ /*
+ Increment the write offset
+ */
*psKernelCCB->pui32WriteOffset = (*psKernelCCB->pui32WriteOffset + 1) & 255;
#if defined(PDUMP)
*psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+ /*
+ * New command submission is considered a proper handling of any pending APM
+ * event, so mark it as handled to prevent other host threads from taking
+ * action.
+ */
+ psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+
OSWriteMemoryBarrier();
-
+ /* Order is importent for post processor! */
PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_MKSYNC, PVRSRV_TRACE_CLASS_NONE,
MKSYNC_TOKEN_KERNEL_CCB_OFFSET, *psKernelCCB->pui32WriteOffset);
PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_MKSYNC, PVRSRV_TRACE_CLASS_NONE,
OSMemoryBarrier();
#if defined(NO_HARDWARE)
-
+ /* Increment read offset */
*psKernelCCB->pui32ReadOffset = (*psKernelCCB->pui32ReadOffset + 1) & 255;
#endif
+ ui64KickCount++;
Exit:
return eError;
}
+/*!
+******************************************************************************
+
+ @Function SGXScheduleCCBCommandKM
+
+ @Description - Submits a CCB command and kicks the ukernel
+
+ @Input psDeviceNode - pointer to SGX device node
+ @Input eCmdType - see SGXMKIF_CMD_*
+ @Input psCommandData - kernel CCB command
+ @Input ui32CallerID - KERNEL_ID or ISR_ID
+ @Input ui32PDumpFlags
+
+ @Return ui32Error - success or failure
+
+******************************************************************************/
PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
SGXMKIF_CMD_TYPE eCmdType,
SGXMKIF_COMMAND *psCommandData,
IMG_HANDLE hDevMemContext,
IMG_BOOL bLastInScene)
{
- PVRSRV_ERROR eError;
+ PVRSRV_ERROR eError;
-
+ eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (ui32CallerID == ISR_ID)
+ {
+ SYS_DATA *psSysData;
+
+ /*
+ ISR failed to acquire lock so it must be held by a kernel thread.
+ Bring up and kick SGX if necessary when the lock is available.
+ */
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ eError = PVRSRV_OK;
+
+ SysAcquireData(&psSysData);
+ OSScheduleMISR(psSysData);
+ }
+ else
+ {
+ /*
+ Return to srvclient for retry.
+ */
+ }
+
+ return eError;
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
+ "ui32CallerID:%d eError:%u", ui32CallerID, eError));
+ return eError;
+ }
+
+ /* Note that a power-up has been dumped in the init phase. */
PDUMPSUSPEND();
-
+ /* Ensure that SGX is powered up before kicking the ukernel. */
eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
- PVRSRV_DEV_POWER_STATE_ON,
- ui32CallerID,
- IMG_TRUE);
+ PVRSRV_DEV_POWER_STATE_ON);
PDUMPRESUME();
}
else
{
- if (eError == PVRSRV_ERROR_RETRY)
- {
- if (ui32CallerID == ISR_ID)
- {
- SYS_DATA *psSysData;
-
-
-
-
- psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
- eError = PVRSRV_OK;
-
- SysAcquireData(&psSysData);
- OSScheduleMISR(psSysData);
- }
- else
- {
-
-
- }
- }
- else
- {
- PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
- "ui32CallerID:%d eError:%u", ui32CallerID, eError));
- }
-
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
+ "ui32CallerID:%d eError:%u", ui32CallerID, eError));
return eError;
}
}
+/*!
+******************************************************************************
+
+ @Function SGXScheduleProcessQueuesKM
+
+ @Description - Software command complete handler
+
+ @Input psDeviceNode - SGX device node
+
+******************************************************************************/
PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVRSRV_ERROR eError;
ui32PowerStatus = psHostCtl->ui32PowerStatus;
if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
{
-
+ /* The ukernel has no work to do so don't waste power. */
return PVRSRV_OK;
}
}
+/*!
+******************************************************************************
+
+ @Function SGXIsDevicePowered
+
+ @Description
+
+ Whether the device is powered, for the purposes of lockup detection.
+
+ @Input psDeviceNode - pointer to device node
+
+ @Return IMG_BOOL : Whether device is powered
+
+******************************************************************************/
IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode)
{
return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
}
+/*!
+*******************************************************************************
+
+ @Function SGXGetInternalDevInfoKM
+
+ @Description
+ Gets device information that is not intended to be passed
+ on beyond the srvclient libs.
+
+ @Input hDevCookie
+
+ @Output psSGXInternalDevInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
#if defined (SUPPORT_SID_INTERFACE)
psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags;
psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
-
+ /* This should be patched up by OS bridge code */
psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
(IMG_HANDLE)psDevInfo->psKernelSGXHostCtlMemInfo;
}
+/*****************************************************************************
+ FUNCTION : SGXCleanupRequest
+
+ PURPOSE : Wait for the microkernel to clean up its references to either a
+ render context or render target.
+
+ PARAMETERS : psDeviceNode - SGX device node
+ psHWDataDevVAddr - Device Address of the resource
+ ui32CleanupType - PVRSRV_CLEANUPCMD_*
+ bForceCleanup - Skips sync polling
+
+ RETURNS : error status
+*****************************************************************************/
PVRSRV_ERROR SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_DEV_VIRTADDR *psHWDataDevVAddr,
IMG_UINT32 ui32CleanupType,
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Failed to submit clean-up command"));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
PVR_DBG_BREAK;
return eError;
}
-
+ /* Wait for the uKernel process the cleanup request */
#if !defined(NO_HARDWARE)
if(PollForValueKM(&psHostCtl->ui32CleanupStatus,
PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
{
PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Wait for uKernel to clean up (%u) failed", ui32CleanupType));
eError = PVRSRV_ERROR_TIMEOUT;
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
PVR_DBG_BREAK;
}
#endif
#if defined(PDUMP)
-
+ /*
+ Pdump the poll as well.
+ Note:
+ We don't expect the cleanup to report busy as the client should have
+ ensured the the resource has been finished with before requesting
+ it's cleanup. This isn't true of the abnormal termination case but
+ we don't expect to PDump that. Unless/until PDump has flow control
+ there isn't anything else we can do.
+ */
PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for clean-up request to complete");
PDUMPMEMPOL(psHostCtlMemInfo,
offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus),
- PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
- PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE,
PDUMP_POLL_OPERATOR_EQUAL,
0,
MAKEUNIQUETAG(psHostCtlMemInfo));
- #endif
+ #endif /* PDUMP */
if (eError != PVRSRV_OK)
{
return eError;
}
}
+
+ if (psHostCtl->ui32CleanupStatus & PVRSRV_USSE_EDM_CLEANUPCMD_BUSY)
+ {
+ /* Only one flag should be set */
+ PVR_ASSERT((psHostCtl->ui32CleanupStatus & PVRSRV_USSE_EDM_CLEANUPCMD_DONE) == 0);
+ eError = PVRSRV_ERROR_RETRY;
+ psHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_BUSY);
+ }
+ else
+ {
+ eError = PVRSRV_OK;
+ psHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE);
+ }
- psHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE);
PDUMPMEM(IMG_NULL, psHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psHostCtlMemInfo));
-
+ /* Request the cache invalidate */
#if defined(SGX_FEATURE_SYSTEM_CACHE)
psDevInfo->ui32CacheControl |= (SGXMKIF_CC_INVAL_BIF_SL | SGXMKIF_CC_INVAL_DATA);
#else
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_DATA;
#endif
- return PVRSRV_OK;
+ return eError;
}
PVRSRV_KERNEL_MEM_INFO *psHWRenderContextMemInfo;
IMG_HANDLE hBlockAlloc;
PRESMAN_ITEM psResItem;
+ IMG_BOOL bCleanupTimerRunning;
+ IMG_PVOID pvTimeData;
} SGX_HW_RENDER_CONTEXT_CLEANUP;
PVRSRV_CLEANUPCMD_RC,
bForceCleanup);
-
- PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
- psCleanup->psHWRenderContextMemInfo);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (!psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+ psCleanup->bCleanupTimerRunning = IMG_TRUE;
+ }
+ else
+ {
+ if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+ {
+ eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ }
+ else
+ {
+ if (psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
- sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
- psCleanup,
- psCleanup->hBlockAlloc);
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Free the Device Mem allocated */
+ PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+ psCleanup->psHWRenderContextMemInfo);
+ /* Finally, free the cleanup structure itself */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+ /*not nulling pointer, copy on stack*/
+ }
return eError;
}
PVRSRV_KERNEL_MEM_INFO *psHWTransferContextMemInfo;
IMG_HANDLE hBlockAlloc;
PRESMAN_ITEM psResItem;
+ IMG_BOOL bCleanupTimerRunning;
+ IMG_PVOID pvTimeData;
} SGX_HW_TRANSFER_CONTEXT_CLEANUP;
PVRSRV_CLEANUPCMD_TC,
bForceCleanup);
-
- PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
- psCleanup->psHWTransferContextMemInfo);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (!psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+ psCleanup->bCleanupTimerRunning = IMG_TRUE;
+ }
+ else
+ {
+ if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+ {
+ eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ }
+ else
+ {
+ if (psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
- sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
- psCleanup,
- psCleanup->hBlockAlloc);
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Free the Device Mem allocated */
+ PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+ psCleanup->psHWTransferContextMemInfo);
+ /* Finally, free the cleanup structure itself */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+ /*not nulling pointer, copy on stack*/
+ }
return eError;
}
| PVRSRV_MEM_CACHE_CONSISTENT,
ui32HWRenderContextSize,
32,
+ IMG_NULL,
+ 0,
+ 0,0,0,IMG_NULL, /* No sparse mapping data */
&psCleanup->psHWRenderContextMemInfo,
"HW Render Context");
goto exit2;
}
-
+ /* Pass the DevVAddr of the new context back up through the bridge */
psHWRenderContextDevVAddr->uiAddr = psCleanup->psHWRenderContextMemInfo->sDevVAddr.uiAddr;
-
+ /* Retrieve the PDDevPAddr */
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevMemContextInt,
hDevMemContext,
psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
-
-
-
-
-
+ /*
+ patch-in the Page-Directory Device-Physical address. Note that this is
+ copied-in one byte at a time, as we have no guarantee that the usermode-
+ provided ui32OffsetToPDDevPAddr is a validly-aligned address for the
+ current CPU architecture.
+ */
pSrc = (IMG_UINT8 *)&sPDDevPAddr;
pDst = (IMG_UINT8 *)psCleanup->psHWRenderContextMemInfo->pvLinAddrKM;
pDst += ui32OffsetToPDDevPAddr;
}
#if defined(PDUMP)
-
+ /* PDUMP the HW context */
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW Render context struct");
PDUMPMEM(
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psCleanup->psHWRenderContextMemInfo));
-
+ /* PDUMP the PDDevPAddr */
PDUMPCOMMENT("Page directory address in HW render context");
PDUMPPDDEVPADDR(
psCleanup->psHWRenderContextMemInfo,
psCleanup->hBlockAlloc = hBlockAlloc;
psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_HW_RENDER_CONTEXT,
return (IMG_HANDLE)psCleanup;
+/* Error exit paths */
exit2:
PVRSRVFreeDeviceMemKM(hDeviceNode,
psCleanup->psHWRenderContextMemInfo);
sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
psCleanup,
psCleanup->hBlockAlloc);
-
+ /*not nulling pointer, out of scope*/
exit0:
return IMG_NULL;
}
| PVRSRV_MEM_CACHE_CONSISTENT,
ui32HWTransferContextSize,
32,
+ IMG_NULL,
+ 0,
+ 0,0,0,IMG_NULL, /* No sparse mapping data */
&psCleanup->psHWTransferContextMemInfo,
"HW Render Context");
goto exit2;
}
-
+ /* Pass the DevVAddr of the new context back up through the bridge */
psHWTransferContextDevVAddr->uiAddr = psCleanup->psHWTransferContextMemInfo->sDevVAddr.uiAddr;
-
+ /* Retrieve the PDDevPAddr */
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevMemContextInt,
hDevMemContext,
psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
-
-
-
-
-
+ /*
+ patch-in the Page-Directory Device-Physical address. Note that this is
+ copied-in one byte at a time, as we have no guarantee that the usermode-
+ provided ui32OffsetToPDDevPAddr is a validly-aligned address for the
+ current CPU architecture.
+ */
pSrc = (IMG_UINT8 *)&sPDDevPAddr;
pDst = (IMG_UINT8 *)psCleanup->psHWTransferContextMemInfo->pvLinAddrKM;
pDst += ui32OffsetToPDDevPAddr;
}
#if defined(PDUMP)
-
+ /* PDUMP the HW Transfer Context */
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW Transfer context struct");
PDUMPMEM(
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psCleanup->psHWTransferContextMemInfo));
-
+ /* PDUMP the PDDevPAddr */
PDUMPCOMMENT("Page directory address in HW transfer context");
PDUMPPDDEVPADDR(
psCleanup->hBlockAlloc = hBlockAlloc;
psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_HW_TRANSFER_CONTEXT,
return (IMG_HANDLE)psCleanup;
+/* Error exit paths */
exit2:
PVRSRVFreeDeviceMemKM(hDeviceNode,
psCleanup->psHWTransferContextMemInfo);
sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
psCleanup,
psCleanup->hBlockAlloc);
-
+ /*not nulling pointer, out of scope*/
exit0:
return IMG_NULL;
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
-
+ /*
+ cannot be sure that offset (passed from user-land) is safe to deref
+ as a word-ptr on current CPU arch: copy one byte at a time.
+ */
pDst = (IMG_UINT8 *)psCleanup->psHWTransferContextMemInfo->pvLinAddrKM;
pDst += ui32OffsetOfPriorityField;
pSrc = (IMG_UINT8 *)&ui32Priority;
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
-
+ /*
+ cannot be sure that offset (passed from user-land) is safe to deref
+ as a word-ptr on current CPU arch: copy one byte at a time.
+ */
pDst = (IMG_UINT8 *)psCleanup->psHWRenderContextMemInfo->pvLinAddrKM;
pDst += ui32OffsetOfPriorityField;
PVRSRV_KERNEL_MEM_INFO *psHW2DContextMemInfo;
IMG_HANDLE hBlockAlloc;
PRESMAN_ITEM psResItem;
+ IMG_BOOL bCleanupTimerRunning;
+ IMG_PVOID pvTimeData;
} SGX_HW_2D_CONTEXT_CLEANUP;
static PVRSRV_ERROR SGXCleanupHW2DContextCallback(IMG_PVOID pvParam,
PVR_UNREFERENCED_PARAMETER(ui32Param);
-
+ /* First, ensure the context is no longer being utilised */
eError = SGXCleanupRequest(psCleanup->psDeviceNode,
&psCleanup->psHW2DContextMemInfo->sDevVAddr,
PVRSRV_CLEANUPCMD_2DC,
bForceCleanup);
-
- PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
- psCleanup->psHW2DContextMemInfo);
-
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
- sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
- psCleanup,
- psCleanup->hBlockAlloc);
-
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (!psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+ psCleanup->bCleanupTimerRunning = IMG_TRUE;
+ }
+ else
+ {
+ if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+ {
+ eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ }
+ else
+ {
+ if (psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Free the Device Mem allocated */
+ PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+ psCleanup->psHW2DContextMemInfo);
+
+ /* Finally, free the cleanup structure itself */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+ /*not nulling pointer, copy on stack*/
+ }
return eError;
}
| PVRSRV_MEM_CACHE_CONSISTENT,
ui32HW2DContextSize,
32,
+ IMG_NULL,
+ 0,
+ 0,0,0,IMG_NULL, /* No sparse mapping data */
&psCleanup->psHW2DContextMemInfo,
"HW 2D Context");
goto exit2;
}
-
+ /* Pass the DevVAddr of the new context back up through the bridge */
psHW2DContextDevVAddr->uiAddr = psCleanup->psHW2DContextMemInfo->sDevVAddr.uiAddr;
-
+ /* Retrieve the PDDevPAddr */
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevMemContextInt,
hDevMemContext,
psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
-
-
-
-
-
+ /*
+ patch-in the Page-Directory Device-Physical address. Note that this is
+ copied-in one byte at a time, as we have no guarantee that the usermode-
+ provided ui32OffsetToPDDevPAddr is a validly-aligned address for the
+ current CPU architecture.
+ */
pSrc = (IMG_UINT8 *)&sPDDevPAddr;
pDst = (IMG_UINT8 *)psCleanup->psHW2DContextMemInfo->pvLinAddrKM;
pDst += ui32OffsetToPDDevPAddr;
}
#if defined(PDUMP)
-
+ /* PDUMP the HW 2D Context */
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW 2D context struct");
PDUMPMEM(
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psCleanup->psHW2DContextMemInfo));
-
+ /* PDUMP the PDDevPAddr */
PDUMPCOMMENT("Page directory address in HW 2D transfer context");
PDUMPPDDEVPADDR(
psCleanup->psHW2DContextMemInfo,
psCleanup->hBlockAlloc = hBlockAlloc;
psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_HW_2D_CONTEXT,
return (IMG_HANDLE)psCleanup;
+/* Error exit paths */
exit2:
PVRSRVFreeDeviceMemKM(hDeviceNode,
psCleanup->psHW2DContextMemInfo);
sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
psCleanup,
psCleanup->hBlockAlloc);
-
+ /*not nulling pointer, out of scope*/
exit0:
return IMG_NULL;
}
return eError;
}
-#endif
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE)*/
+/*!****************************************************************************
+ @Function SGX2DQuerySyncOpsCompleteKM
+
+ @Input psSyncInfo : Sync object to be queried
+
+ @Return IMG_TRUE - ops complete, IMG_FALSE - ops pending
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(SGX2DQuerySyncOpsComplete)
#endif
);
}
+/*!****************************************************************************
+ @Function SGX2DQueryBlitsCompleteKM
+
+ @Input psDevInfo : SGX device info structure
+
+ @Input psSyncInfo : Sync object to be queried
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
{
-
+ /* Instant success */
PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Blits complete."));
return PVRSRV_OK;
}
-
+ /* Not complete yet */
if (!bWaitForComplete)
{
-
+ /* Just report not complete */
PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Ops pending."));
return PVRSRV_ERROR_CMD_NOT_PROCESSED;
}
-
+ /* Start polling */
PVR_DPF((PVR_DBG_MESSAGE, "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling."));
LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
{
-
+ /* Success */
PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Wait over. Blits complete."));
return PVRSRV_OK;
}
OSSleepms(1);
} END_LOOP_UNTIL_TIMEOUT();
-
+ /* Timed out */
PVR_DPF((PVR_DBG_ERROR,"SGX2DQueryBlitsCompleteKM: Timed out. Ops pending."));
#if defined(DEBUG)
ui32Clocksx16 = (IMG_UINT32)(ui64Clocks / 16);
return ui32Clocksx16;
-#endif
+#endif /* EUR_CR_TIMER */
}
IMG_VOID SGXWaitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32SGXClocks)
{
-
-
+ /*
+ Round up to the next microsecond.
+ */
OSWaitus(1 + (ui32SGXClocks * 1000000 / psDevInfo->ui32CoreClockSpeed));
}
-IMG_EXPORT
-PVRSRV_ERROR PVRSRVGetSGXRevDataKM(PVRSRV_DEVICE_NODE* psDeviceNode, IMG_UINT32 *pui32SGXCoreRev,
- IMG_UINT32 *pui32SGXCoreID)
-{
- PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
- SGX_MISC_INFO sMiscInfo;
- PVRSRV_ERROR eError;
-
- sMiscInfo.eRequest = SGX_MISC_INFO_REQUEST_SGXREV;
- eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, NULL);
-
- *pui32SGXCoreRev = sMiscInfo.uData.sSGXFeatures.ui32CoreRev;
- *pui32SGXCoreID = sMiscInfo.uData.sSGXFeatures.ui32CoreID;
- return eError;
-}
-
-
-PVRSRV_ERROR SGXContextSuspend(PVRSRV_DEVICE_NODE *psDeviceNode,
- IMG_DEV_VIRTADDR *psHWContextDevVAddr,
- IMG_BOOL bResume)
-{
- PVRSRV_ERROR eError;
- SGXMKIF_COMMAND sCommand = {0};
-
- sCommand.ui32Data[0] = psHWContextDevVAddr->uiAddr;
- sCommand.ui32Data[1] = bResume ? PVRSRV_CTXSUSPCMD_RESUME : PVRSRV_CTXSUSPCMD_SUSPEND;
-
- eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_CONTEXTSUSPEND, &sCommand, KERNEL_ID, 0, IMG_NULL, IMG_FALSE);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,"SGXContextSuspend: Failed to submit context suspend command"));
- return eError;
- }
-
- return eError;
-}
-
+/******************************************************************************
+ End of file (sgxutils.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific utility routines declarations
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Inline functions/structures specific to SGX
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "perproc.h"
#include "sgxinfokm.h"
-
+/* PRQA S 3410 7 */ /* macros require the absence of some brackets */
#define CCB_OFFSET_IS_VALID(type, psCCBMemInfo, psCCBKick, offset) \
((sizeof(type) <= (psCCBMemInfo)->uAllocSize) && \
((psCCBKick)->offset <= (psCCBMemInfo)->uAllocSize - sizeof(type)))
((type *)(((IMG_CHAR *)(psCCBMemInfo)->pvLinAddrKM) + \
(psCCBKick)->offset))
+extern IMG_UINT64 ui64KickCount;
+
IMG_IMPORT
IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_UINT32 ui32TimeWraps,
IMG_UINT32 ui32Time);
+/*!
+*******************************************************************************
+
+ @Function SGXWaitClocks
+
+ @Description
+
+ Wait for a specified number of SGX clock cycles to elapse.
+
+ @Input psDevInfo - SGX Device Info
+ @Input ui32SGXClocks - number of clock cycles to wait
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SGXWaitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32SGXClocks);
PVRSRV_ERROR PVRSRVGetSGXRevDataKM(PVRSRV_DEVICE_NODE* psDeviceNode, IMG_UINT32 *pui32SGXCoreRev,
IMG_UINT32 *pui32SGXCoreID);
+/*!
+******************************************************************************
+
+ @Function SGXContextSuspend
+
+ @Description - Interface to the SGX microkernel to instruct it to suspend or
+ resume processing on a given context. This will interrupt current
+ processing of this context if a task is already running and is
+ interruptable.
+
+ @Input psDeviceNode SGX device node
+ @Input psHWContextDevVAddr SGX virtual address of the context to be suspended
+ or resumed. Can be of type SGXMKIF_HWRENDERCONTEXT,
+ SGXMKIF_HWTRANSFERCONTEXT or SGXMKIF_HW2DCONTEXT
+ @Input bResume IMG_TRUE to put a context into suspend state,
+ IMG_FALSE to resume a previously suspended context
+
+******************************************************************************/
PVRSRV_ERROR SGXContextSuspend(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_DEV_VIRTADDR *psHWContextDevVAddr,
IMG_BOOL bResume);
+/******************************************************************************
+ End of file (sgxutils.h)
+******************************************************************************/
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
pvrsrvkm-y += \
services4/srvkm/env/linux/osfunc.o \
services4/srvkm/common/deviceclass.o \
services4/srvkm/common/handle.o \
services4/srvkm/common/hash.o \
+ services4/srvkm/common/lists.o \
+ services4/srvkm/common/mem.o \
+ services4/srvkm/common/mem_debug.o \
services4/srvkm/common/metrics.o \
+ services4/srvkm/common/osfunc_common.o \
+ services4/srvkm/common/pdump_common.o \
+ services4/srvkm/common/perproc.o \
+ services4/srvkm/common/power.o \
services4/srvkm/common/pvrsrv.o \
services4/srvkm/common/queue.o \
services4/srvkm/common/ra.o \
+ services4/srvkm/common/refcount.o \
services4/srvkm/common/resman.o \
- services4/srvkm/common/power.o \
- services4/srvkm/common/mem.o \
- services4/srvkm/common/pdump_common.o \
services4/srvkm/bridged/bridged_support.o \
services4/srvkm/bridged/bridged_pvr_bridge.o \
- services4/srvkm/common/perproc.o \
services4/system/$(PVR_SYSTEM)/sysconfig.o \
- services4/system/$(PVR_SYSTEM)/sysutils.o \
- services4/srvkm/common/lists.o \
- services4/srvkm/common/mem_debug.o \
- services4/srvkm/common/osfunc_common.o
+ services4/system/$(PVR_SYSTEM)/sysutils.o
+
+pvrsrvkm-$(CONFIG_ION_OMAP) += \
+ services4/srvkm/env/linux/ion.o
+
+ifeq ($(SUPPORT_ION),1)
+pvrsrvkm-y += \
+ services4/srvkm/env/linux/ion.o
+endif
+
+ifeq ($(TTRACE),1)
+pvrsrvkm-y += \
+ services4/srvkm/common/ttrace.o
+endif
ifneq ($(W),1)
CFLAGS_osfunc.o := -Werror
CFLAGS_lists.o := -Werror
CFLAGS_mem_debug.o := -Werror
CFLAGS_osfunc_common.o := -Werror
+CFLAGS_refcount.o := -Werror
endif
# SUPPORT_SGX==1 only
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
modules := srvkm
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Environmental Data header file
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Linux-specific part of system data.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _ENV_DATA_
#define _ENV_DATA_
#include <linux/workqueue.h>
#endif
+/*
+ * Env data specific to linux - convenient place to put this
+ */
+
+/* Fairly arbitrary sizes - hopefully enough for all bridge calls */
#define PVRSRV_MAX_BRIDGE_IN_SIZE 0x1000
#define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000
#else
struct tasklet_struct sMISRTasklet;
#endif
+#if defined (SUPPORT_ION)
+ IMG_HANDLE hIonHeaps;
+ IMG_HANDLE hIonDev;
+#endif
} ENV_DATA;
-#endif
+#endif /* _ENV_DATA_ */
+/*****************************************************************************
+ End of file (env_data.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OS specific per process data interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Linux per process data
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __ENV_PERPROC_H__
#define __ENV_PERPROC_H__
#include "services.h"
#include "handle.h"
+#define ION_CLIENT_NAME_SIZE 50
typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
{
IMG_HANDLE hBlockAlloc;
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
struct list_head sDRMAuthListHead;
#endif
+#if defined (SUPPORT_ION)
+ struct ion_client *psIONClient;
+ IMG_CHAR azIonClientName[ION_CLIENT_NAME_SIZE];
+#endif
} PVRSRV_ENV_PER_PROCESS_DATA;
IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID);
-#endif
+#endif /* __ENV_PERPROC_H__ */
+/******************************************************************************
+ End of file (env_perproc.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Event Object
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
} PVRSRV_LINUX_EVENT_OBJECT;
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectListCreate
+
+ @Description
+
+ Linux wait object list creation
+
+ @Output hOSEventKM : Pointer to the event object list handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
{
PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectListDestroy
+
+ @Description
+
+ Linux wait object list destruction
+
+ @Input hOSEventKM : Event object list handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
{
}
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEventObjectList, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectDelete
+
+ @Description
+
+ Linux wait object removal
+
+ @Input hOSEventObjectList : Event object list handle
+ @Input hOSEventObject : Event object handle
+ @Input bResManCallback : Called from the resman
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject)
{
if(hOSEventObjectList)
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectDeleteCallback
+
+ @Description
+
+ Linux wait object removal
+
+ @Input hOSEventObject : Event object handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bForceCleanup)
{
PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
#endif
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectAdd
+
+ @Description
+
+ Linux wait object addition
+
+ @Input hOSEventObjectList : Event object list handle
+ @Output phOSEventObject : Pointer to the event object handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
{
PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* allocate completion variable */
if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT),
(IMG_VOID **)&psLinuxEventObject, IMG_NULL,
"Linux Event Object") != PVRSRV_OK)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectSignal
+
+ @Description
+
+ Linux wait object signaling function
+
+ @Input hOSEventObjectList : Event object list handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
{
PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
psList = &psLinuxEventObjectList->sList;
-
+ /*
+ * We don't take the write lock in interrupt context, so we don't
+ * need to use read_lock_irqsave.
+ */
read_lock(&psLinuxEventObjectList->sLock);
list_for_each(psListEntry, psList)
{
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectWait
+
+ @Description
+
+ Linux wait object routine
+
+ @Input hOSEventObject : Event object handle
+
+ @Input ui32MSTimeout : Time out value in msec
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
{
IMG_UINT32 ui32TimeStamp;
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Event Object
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux specific Services code internal interfaces
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Interfaces between various parts of the Linux specific
+ Services code, that don't have any other obvious
+ header file to go into.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __LINKAGE_H__
#define __LINKAGE_H__
void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el);
-#endif
+#endif /* PVR_MANUAL_POWER_CONTROL */
-#endif
+#endif /* DEBUG */
-#endif
+#endif /* __LINKAGE_H__ */
+/*****************************************************************************
+ End of file (linkage.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Main driver lock
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description The main driver lock, held in most places in
+ the driver.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __LOCK_H__
#define __LOCK_H__
+/*
+ * Main driver lock, used to ensure driver code is single threaded.
+ * There are some places where this lock must not be taken, such as
+ * in the mmap related deriver entry points.
+ */
extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
-#endif
+#endif /* __LOCK_H__ */
+/*****************************************************************************
+ End of file (lock.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Misc memory management utility functions for Linux
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
#endif
#endif
+#if !defined(PVR_LINUX_MEM_AREA_POOL_MAX_PAGES)
+#define PVR_LINUX_MEM_AREA_POOL_MAX_PAGES 0
+#endif
+
+#include <linux/kernel.h>
+#include <asm/atomic.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <asm/io.h>
#include <linux/highmem.h>
#include <linux/sched.h>
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0))
+#include <linux/shrinker.h>
+#endif
+#endif
+
#include "img_defs.h"
#include "services.h"
#include "servicesint.h"
#include "lists.h"
#endif
+/*
+ * The page pool entry count is an atomic int so that the shrinker function
+ * can return it even when we can't take the lock that protects the page pool
+ * list.
+ */
+static atomic_t g_sPagePoolEntryCount = ATOMIC_INIT(0);
+
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
typedef enum {
DEBUG_MEM_ALLOC_TYPE_KMALLOC,
DEBUG_MEM_ALLOC_TYPE_IOREMAP,
DEBUG_MEM_ALLOC_TYPE_IO,
DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ DEBUG_MEM_ALLOC_TYPE_ION,
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ DEBUG_MEM_ALLOC_TYPE_VMAP,
+#endif
DEBUG_MEM_ALLOC_TYPE_COUNT
-}DEBUG_MEM_ALLOC_TYPE;
+} DEBUG_MEM_ALLOC_TYPE;
typedef struct _DEBUG_MEM_ALLOC_REC
{
DEBUG_MEM_ALLOC_TYPE eAllocType;
- IMG_VOID *pvKey;
+ IMG_VOID *pvKey; /* Some unique value (private to the eAllocType) */
IMG_VOID *pvCpuVAddr;
IMG_UINT32 ulCpuPAddr;
IMG_VOID *pvPrivateData;
struct _DEBUG_MEM_ALLOC_REC *psNext;
struct _DEBUG_MEM_ALLOC_REC **ppsThis;
-}DEBUG_MEM_ALLOC_REC;
+} DEBUG_MEM_ALLOC_REC;
static IMPLEMENT_LIST_ANY_VA_2(DEBUG_MEM_ALLOC_REC, IMG_BOOL, IMG_FALSE)
static IMPLEMENT_LIST_ANY_VA(DEBUG_MEM_ALLOC_REC)
static 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;
+/* vmalloc + kmalloc + alloc_pages + kmem_cache */
+static IMG_UINT32 g_SysRAMWaterMark; /* Doesn't include page pool */
+static IMG_UINT32 g_SysRAMHighWaterMark; /* *DOES* include page pool */
+static inline IMG_UINT32
+SysRAMTrueWaterMark(void)
+{
+ return g_SysRAMWaterMark + PAGES_TO_BYTES(atomic_read(&g_sPagePoolEntryCount));
+}
+
+/* ioremap + io */
static IMG_UINT32 g_IOMemWaterMark;
static IMG_UINT32 g_IOMemHighWaterMark;
static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType);
-static struct proc_dir_entry *g_SeqFileMemoryRecords =0;
+static struct proc_dir_entry *g_SeqFileMemoryRecords;
static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off);
static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el);
static void* ProcSeqOff2ElementMemoryRecords(struct seq_file * sfile, loff_t off);
static IMG_UINT32 g_LinuxMemAreaHighWaterMark;
-static struct proc_dir_entry *g_SeqFileMemArea=0;
+static struct proc_dir_entry *g_SeqFileMemArea;
static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off);
static void ProcSeqShowMemArea(struct seq_file *sfile,void* el);
static void ProcSeqStartstopDebugMutex(struct seq_file *sfile,IMG_BOOL start);
#endif
-static LinuxKMemCache *psLinuxMemAreaCache;
+typedef struct
+{
+ /* Linkage for page pool LRU list */
+ struct list_head sPagePoolItem;
+
+ struct page *psPage;
+} LinuxPagePoolEntry;
+
+static LinuxKMemCache *g_PsLinuxMemAreaCache;
+static LinuxKMemCache *g_PsLinuxPagePoolCache;
+static LIST_HEAD(g_sPagePoolList);
+static int g_iPagePoolMaxEntries;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea);
#endif
-PVRSRV_ERROR
-LinuxMMInit(IMG_VOID)
-{
-#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- LinuxInitMutex(&g_sDebugMutex);
-#endif
-
-#if defined(DEBUG_LINUX_MEM_AREAS)
- {
- g_SeqFileMemArea = CreateProcReadEntrySeq(
- "mem_areas",
- NULL,
- ProcSeqNextMemArea,
- ProcSeqShowMemArea,
- ProcSeqOff2ElementMemArea,
- ProcSeqStartstopDebugMutex
- );
- if(!g_SeqFileMemArea)
- {
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
- }
-#endif
-
-
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- {
- g_SeqFileMemoryRecords =CreateProcReadEntrySeq(
- "meminfo",
- NULL,
- ProcSeqNextMemoryRecords,
- ProcSeqShowMemoryRecords,
- ProcSeqOff2ElementMemoryRecords,
- ProcSeqStartstopDebugMutex
- );
- if(!g_SeqFileMemoryRecords)
- {
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
- }
-#endif
-
- psLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
- if(!psLinuxMemAreaCache)
- {
- PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
-
- return PVRSRV_OK;
-}
-
-#if defined(DEBUG_LINUX_MEM_AREAS)
-static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
-{
- LinuxMemArea *psLinuxMemArea;
-
- psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
- PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%d bytes",
- __FUNCTION__,
- psCurrentRecord->psLinuxMemArea,
- LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
- psCurrentRecord->psLinuxMemArea->ui32ByteSize));
-
- LinuxMemAreaDeepFree(psLinuxMemArea);
-}
-#endif
-
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
-static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
+static inline IMG_BOOL
+AreaIsUncached(IMG_UINT32 ui32AreaFlags)
{
-
- PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
- "type=%s "
- "CpuVAddr=%p "
- "CpuPAddr=0x%08x, "
- "allocated @ file=%s,line=%d",
- __FUNCTION__,
- DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
- psCurrentRecord->pvCpuVAddr,
- psCurrentRecord->ulCpuPAddr,
- psCurrentRecord->pszFileName,
- psCurrentRecord->ui32Line));
- switch(psCurrentRecord->eAllocType)
- {
- case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
- KFreeWrapper(psCurrentRecord->pvCpuVAddr);
- break;
- case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
- IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
- break;
- case DEBUG_MEM_ALLOC_TYPE_IO:
-
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__);
- break;
- case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
- VFreeWrapper(psCurrentRecord->pvCpuVAddr);
- break;
- case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
-
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__);
- break;
- case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
- KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
- break;
- default:
- PVR_ASSERT(0);
- }
+ return (ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED)) != 0;
}
-#endif
-
-IMG_VOID
-LinuxMMCleanup(IMG_VOID)
+static inline IMG_BOOL
+CanFreeToPool(LinuxMemArea *psLinuxMemArea)
{
-
-#if defined(DEBUG_LINUX_MEM_AREAS)
- {
- if(g_LinuxMemAreaCount)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%d bytes)",
- __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
- }
-
- List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords,
- LinuxMMCleanup_MemAreas_ForEachCb);
-
- RemoveProcEntrySeq( g_SeqFileMemArea );
- }
-#endif
-
-
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- {
-
-
- List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords,
- LinuxMMCleanup_MemRecords_ForEachVa);
-
- RemoveProcEntrySeq( g_SeqFileMemoryRecords );
- }
-#endif
-
- if(psLinuxMemAreaCache)
- {
- KMemCacheDestroyWrapper(psLinuxMemAreaCache);
- psLinuxMemAreaCache=NULL;
- }
+ return AreaIsUncached(psLinuxMemArea->ui32AreaFlags) && !psLinuxMemArea->bNeedsCacheInvalidate;
}
-
IMG_VOID *
_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
{
IMG_VOID *pvRet;
pvRet = kmalloc(ui32ByteSize, uFlags);
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- if(pvRet)
+ if (pvRet)
{
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
pvRet,
ui32ByteSize,
pszFileName,
ui32Line
- );
+ );
}
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord);
g_WaterMarkData[eAllocType] += ui32Bytes;
- if(g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
+ if (g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
{
g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
}
- if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+ 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)
{
+ IMG_UINT32 ui32SysRAMTrueWaterMark;
+
g_SysRAMWaterMark += ui32Bytes;
- if(g_SysRAMWaterMark > g_SysRAMHighWaterMark)
+ ui32SysRAMTrueWaterMark = SysRAMTrueWaterMark();
+
+ if (ui32SysRAMTrueWaterMark > g_SysRAMHighWaterMark)
{
- g_SysRAMHighWaterMark = g_SysRAMWaterMark;
+ g_SysRAMHighWaterMark = ui32SysRAMTrueWaterMark;
}
}
- else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
{
g_IOMemWaterMark += ui32Bytes;
- if(g_IOMemWaterMark > g_IOMemHighWaterMark)
+ if (g_IOMemWaterMark > g_IOMemHighWaterMark)
{
g_IOMemHighWaterMark = g_IOMemWaterMark;
}
eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE);
pvKey = va_arg(va, IMG_VOID*);
- if(psCurrentRecord->eAllocType == eAllocType
+ if (psCurrentRecord->eAllocType == eAllocType
&& psCurrentRecord->pvKey == pvKey)
{
- eAllocType = psCurrentRecord->eAllocType;
- g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes;
-
- if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
- || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
- || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
- || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ eAllocType = psCurrentRecord->eAllocType;
+ g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes;
+
+ if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ g_SysRAMWaterMark -= psCurrentRecord->ui32Bytes;
+ }
+ else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+ {
+ g_IOMemWaterMark -= psCurrentRecord->ui32Bytes;
+ }
+
+ List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord);
+ kfree(psCurrentRecord);
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ return IMG_FALSE;
+ }
+}
+
+
+static IMG_VOID
+DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+/* DEBUG_MEM_ALLOC_REC **ppsCurrentRecord;*/
+
+ LinuxLockMutex(&g_sDebugMutex);
+
+ /* Locate the corresponding allocation entry */
+ if (!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
+ DebugMemAllocRecordRemove_AnyVaCb,
+ eAllocType,
+ pvKey))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s with pvKey=%p (called from %s, line %d\n",
+ __FUNCTION__, DebugMemAllocRecordTypeToString(eAllocType), pvKey,
+ pszFileName, ui32Line));
+ }
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+static IMG_CHAR *
+DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
+{
+ IMG_CHAR *apszDebugMemoryRecordTypes[] = {
+ "KMALLOC",
+ "VMALLOC",
+ "ALLOC_PAGES",
+ "IOREMAP",
+ "IO",
+ "KMEM_CACHE_ALLOC",
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ "VMAP"
+#endif
+ };
+ return apszDebugMemoryRecordTypes[eAllocType];
+}
+#endif
+
+
+static IMG_BOOL
+AllocFlagsToPGProt(pgprot_t *pPGProtFlags, IMG_UINT32 ui32AllocFlags)
+{
+ pgprot_t PGProtFlags;
+
+ switch (ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+ PGProtFlags = PAGE_KERNEL;
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ PGProtFlags = PGPROT_WC(PAGE_KERNEL);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ PGProtFlags = PGPROT_UC(PAGE_KERNEL);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Unknown mapping flags=0x%08x",
+ __FUNCTION__, ui32AllocFlags));
+ dump_stack();
+ return IMG_FALSE;
+ }
+
+ *pPGProtFlags = PGProtFlags;
+
+ return IMG_TRUE;
+}
+
+IMG_VOID *
+_VMallocWrapper(IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AllocFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ pgprot_t PGProtFlags;
+ IMG_VOID *pvRet;
+
+ if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags))
+ {
+ return NULL;
+ }
+
+ /* Allocate virtually contiguous pages */
+ pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if (pvRet)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ pvRet,
+ pvRet,
+ 0,
+ NULL,
+ PAGE_ALIGN(ui32Bytes),
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvRet;
+}
+
+
+IMG_VOID
+_VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ vfree(pvCpuVAddr);
+}
+
+
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+static IMG_VOID *
+_VMapWrapper(struct page **ppsPageList, IMG_UINT32 ui32NumPages, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+ pgprot_t PGProtFlags;
+ IMG_VOID *pvRet;
+
+ if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags))
+ {
+ return NULL;
+ }
+
+ pvRet = vmap(ppsPageList, ui32NumPages, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if (pvRet)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMAP,
+ pvRet,
+ pvRet,
+ 0,
+ NULL,
+ PAGES_TO_BYTES(ui32NumPages),
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvRet;
+}
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags) _VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags) _VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags, NULL, 0)
+#endif
+
+
+static IMG_VOID
+_VUnmapWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMAP, pvCpuVAddr, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ vunmap(pvCpuVAddr);
+}
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VUnmapWrapper(pvCpuVAddr) _VUnmapWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VUnmapWrapper(pvCpuVAddr) _VUnmapWrapper(pvCpuVAddr, NULL, 0)
+#endif
+
+#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
+
+
+IMG_VOID
+_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ kmem_cache_free(psCache, pvObject);
+}
+
+
+const IMG_CHAR *
+KMemCacheNameWrapper(LinuxKMemCache *psCache)
+{
+ PVR_UNREFERENCED_PARAMETER(psCache);
+
+ /* In this case kmem_cache_t is an incomplete typedef,
+ * so we can't even de-reference to get the name member. It is also a GPL export symbol */
+ return "";
+}
+
+
+static LinuxPagePoolEntry *
+LinuxPagePoolEntryAlloc(IMG_VOID)
+{
+ return KMemCacheAllocWrapper(g_PsLinuxPagePoolCache, GFP_KERNEL);
+}
+
+static IMG_VOID
+LinuxPagePoolEntryFree(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ KMemCacheFreeWrapper(g_PsLinuxPagePoolCache, psPagePoolEntry);
+}
+
+
+static struct page *
+AllocPageFromLinux(void)
+{
+ struct page *psPage;
+
+ psPage = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+ if (!psPage)
+ {
+ return NULL;
+
+ }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+ /* Reserve those pages to allow them to be re-mapped to user space */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ SetPageReserved(psPage);
+#else
+ mem_map_reserve(psPage);
+#endif
+#endif
+ return psPage;
+}
+
+
+static IMG_VOID
+FreePageToLinux(struct page *psPage)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ ClearPageReserved(psPage);
+#else
+ mem_map_reserve(psPage);
+#endif
+#endif
+ __free_pages(psPage, 0);
+}
+
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+static DEFINE_MUTEX(g_sPagePoolMutex);
+
+static inline void
+PagePoolLock(void)
+{
+ mutex_lock(&g_sPagePoolMutex);
+}
+
+static inline void
+PagePoolUnlock(void)
+{
+ mutex_unlock(&g_sPagePoolMutex);
+}
+
+static inline int
+PagePoolTrylock(void)
+{
+ return mutex_trylock(&g_sPagePoolMutex);
+}
+
+#else /* (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) */
+static inline void
+PagePoolLock(void)
+{
+}
+
+static inline void
+PagePoolUnlock(void)
+{
+}
+
+static inline int
+PagePoolTrylock(void)
+{
+ return 1;
+}
+#endif /* (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) */
+
+
+static inline void
+AddEntryToPool(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ list_add_tail(&psPagePoolEntry->sPagePoolItem, &g_sPagePoolList);
+ atomic_inc(&g_sPagePoolEntryCount);
+}
+
+static inline void
+RemoveEntryFromPool(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ list_del(&psPagePoolEntry->sPagePoolItem);
+ atomic_dec(&g_sPagePoolEntryCount);
+}
+
+static inline LinuxPagePoolEntry *
+RemoveFirstEntryFromPool(void)
+{
+ LinuxPagePoolEntry *psPagePoolEntry;
+
+ if (list_empty(&g_sPagePoolList))
+ {
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+
+ return NULL;
+ }
+
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) > 0);
+
+ psPagePoolEntry = list_first_entry(&g_sPagePoolList, LinuxPagePoolEntry, sPagePoolItem);
+
+ RemoveEntryFromPool(psPagePoolEntry);
+
+ return psPagePoolEntry;
+}
+
+static struct page *
+AllocPage(IMG_UINT32 ui32AreaFlags, IMG_BOOL *pbFromPagePool)
+{
+ struct page *psPage = NULL;
+
+ /*
+ * Only uncached allocations can come from the page pool.
+ * The page pool is currently used to reduce the cost of
+ * invalidating the CPU cache when uncached memory is allocated.
+ */
+ if (AreaIsUncached(ui32AreaFlags) && atomic_read(&g_sPagePoolEntryCount) != 0)
+ {
+ LinuxPagePoolEntry *psPagePoolEntry;
+
+ PagePoolLock();
+ psPagePoolEntry = RemoveFirstEntryFromPool();
+ PagePoolUnlock();
+
+ /* List may have changed since we checked the counter */
+ if (psPagePoolEntry)
{
- g_SysRAMWaterMark -= psCurrentRecord->ui32Bytes;
+ psPage = psPagePoolEntry->psPage;
+ LinuxPagePoolEntryFree(psPagePoolEntry);
+ *pbFromPagePool = IMG_TRUE;
}
- else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
- || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+ }
+
+ if (!psPage)
+ {
+ psPage = AllocPageFromLinux();
+ if (psPage)
{
- g_IOMemWaterMark -= psCurrentRecord->ui32Bytes;
+ *pbFromPagePool = IMG_FALSE;
}
-
- List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord);
- kfree(psCurrentRecord);
-
- return IMG_TRUE;
}
- else
+
+ return psPage;
+
+}
+
+static IMG_VOID
+FreePage(IMG_BOOL bToPagePool, struct page *psPage)
+{
+ /* Only uncached allocations can be freed to the page pool */
+ if (bToPagePool && atomic_read(&g_sPagePoolEntryCount) < g_iPagePoolMaxEntries)
{
- return IMG_FALSE;
+ LinuxPagePoolEntry *psPagePoolEntry = LinuxPagePoolEntryAlloc();
+ if (psPagePoolEntry)
+ {
+ psPagePoolEntry->psPage = psPage;
+
+ PagePoolLock();
+ AddEntryToPool(psPagePoolEntry);
+ PagePoolUnlock();
+
+ return;
+ }
}
-}
+ FreePageToLinux(psPage);
+}
static IMG_VOID
-DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+FreePagePool(IMG_VOID)
{
- LinuxLockMutex(&g_sDebugMutex);
+ LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
-
- if(!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
- DebugMemAllocRecordRemove_AnyVaCb,
- eAllocType,
- pvKey))
+ PagePoolLock();
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ PVR_TRACE(("%s: Freeing %d pages from pool", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+#else
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+ PVR_ASSERT(list_empty(&g_sPagePoolList));
+#endif
+
+ list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
{
- 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));
+ RemoveEntryFromPool(psPagePoolEntry);
+
+ FreePageToLinux(psPagePoolEntry->psPage);
+ LinuxPagePoolEntryFree(psPagePoolEntry);
}
- LinuxUnLockMutex(&g_sDebugMutex);
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+
+ PagePoolUnlock();
}
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+static struct shrinker g_sShrinker;
+#endif
-static IMG_CHAR *
-DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
+static int
+ShrinkPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkControl)
{
- IMG_CHAR *apszDebugMemoryRecordTypes[] = {
- "KMALLOC",
- "VMALLOC",
- "ALLOC_PAGES",
- "IOREMAP",
- "IO",
- "KMEM_CACHE_ALLOC"
- };
- return apszDebugMemoryRecordTypes[eAllocType];
-}
-#endif
+ unsigned long uNumToScan = psShrinkControl->nr_to_scan;
+ PVR_ASSERT(psShrinker == &g_sShrinker);
+ (void)psShrinker;
+ if (uNumToScan != 0)
+ {
+ LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
-IMG_VOID *
-_VMallocWrapper(IMG_UINT32 ui32Bytes,
- IMG_UINT32 ui32AllocFlags,
- IMG_CHAR *pszFileName,
- IMG_UINT32 ui32Line)
+ PVR_TRACE(("%s: Number to scan: %ld", __FUNCTION__, uNumToScan));
+ PVR_TRACE(("%s: Pages in pool before scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+
+ if (!PagePoolTrylock())
+ {
+ PVR_TRACE(("%s: Couldn't get page pool lock", __FUNCTION__));
+ return -1;
+ }
+
+ list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
+ {
+ RemoveEntryFromPool(psPagePoolEntry);
+
+ FreePageToLinux(psPagePoolEntry->psPage);
+ LinuxPagePoolEntryFree(psPagePoolEntry);
+
+ if (--uNumToScan == 0)
+ {
+ break;
+ }
+ }
+
+ if (list_empty(&g_sPagePoolList))
+ {
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+ }
+
+ PagePoolUnlock();
+
+ PVR_TRACE(("%s: Pages in pool after scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+ }
+
+ return atomic_read(&g_sPagePoolEntryCount);
+}
+#endif
+
+static IMG_BOOL
+AllocPages(IMG_UINT32 ui32AreaFlags, struct page ***pppsPageList, IMG_HANDLE *phBlockPageList, IMG_UINT32 ui32NumPages, IMG_BOOL *pbFromPagePool)
{
- pgprot_t PGProtFlags;
- IMG_VOID *pvRet;
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+ IMG_INT32 i; /* Must be signed; see "for" loop conditions */
+ PVRSRV_ERROR eError;
+ IMG_BOOL bFromPagePool = IMG_FALSE;
+
+ eError = OSAllocMem(0, sizeof(*ppsPageList) * ui32NumPages, (IMG_VOID **)&ppsPageList, &hBlockPageList,
+ "Array of pages");
+ if (eError != PVRSRV_OK)
+ {
+ goto failed_page_list_alloc;
+ }
- switch(ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ *pbFromPagePool = IMG_TRUE;
+ for(i = 0; i < (IMG_INT32)ui32NumPages; i++)
{
- case PVRSRV_HAP_CACHED:
- PGProtFlags = PAGE_KERNEL;
- break;
- case PVRSRV_HAP_WRITECOMBINE:
- PGProtFlags = PGPROT_WC(PAGE_KERNEL);
- break;
- case PVRSRV_HAP_UNCACHED:
- PGProtFlags = PGPROT_UC(PAGE_KERNEL);
- break;
- default:
- PVR_DPF((PVR_DBG_ERROR,
- "VMAllocWrapper: unknown mapping flags=0x%08x",
- ui32AllocFlags));
- dump_stack();
- return NULL;
+ ppsPageList[i] = AllocPage(ui32AreaFlags, &bFromPagePool);
+ if (!ppsPageList[i])
+ {
+ goto failed_alloc_pages;
+ }
+ *pbFromPagePool &= bFromPagePool;
}
-
- pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
-
+ *pppsPageList = ppsPageList;
+ *phBlockPageList = hBlockPageList;
+
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- if(pvRet)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ ppsPageList,
+ 0,
+ 0,
+ NULL,
+ PAGES_TO_BYTES(ui32NumPages),
+ "unknown",
+ 0
+ );
+#endif
+
+ return IMG_TRUE;
+
+failed_alloc_pages:
+ for(i--; i >= 0; i--)
{
- DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
- pvRet,
- pvRet,
- 0,
- NULL,
- PAGE_ALIGN(ui32Bytes),
- pszFileName,
- ui32Line
- );
+ FreePage(*pbFromPagePool, ppsPageList[i]);
}
-#else
- PVR_UNREFERENCED_PARAMETER(pszFileName);
- PVR_UNREFERENCED_PARAMETER(ui32Line);
-#endif
+ (IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList);
- return pvRet;
+failed_page_list_alloc:
+ return IMG_FALSE;
}
-IMG_VOID
-_VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+static IMG_VOID
+FreePages(IMG_BOOL bToPagePool, struct page **ppsPageList, IMG_HANDLE hBlockPageList, IMG_UINT32 ui32NumPages)
{
+ IMG_INT32 i;
+
+ for(i = 0; i < (IMG_INT32)ui32NumPages; i++)
+ {
+ FreePage(bToPagePool, ppsPageList[i]);
+ }
+
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr, pszFileName, ui32Line);
-#else
- PVR_UNREFERENCED_PARAMETER(pszFileName);
- PVR_UNREFERENCED_PARAMETER(ui32Line);
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, ppsPageList, __FILE__, __LINE__);
#endif
- vfree(pvCpuVAddr);
+
+ (IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList);
}
LinuxMemArea *
NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
{
- LinuxMemArea *psLinuxMemArea;
+ LinuxMemArea *psLinuxMemArea = NULL;
IMG_VOID *pvCpuVAddr;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ IMG_UINT32 ui32NumPages = 0;
+ struct page **ppsPageList = NULL;
+ IMG_HANDLE hBlockPageList;
+#endif
+ IMG_BOOL bFromPagePool = IMG_FALSE;
psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
goto failed;
}
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+ if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool))
+ {
+ goto failed;
+ }
+
+ pvCpuVAddr = VMapWrapper(ppsPageList, ui32NumPages, ui32AreaFlags);
+#else /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
- if(!pvCpuVAddr)
+ if (!pvCpuVAddr)
{
goto failed;
}
-
+/* PG_reserved was deprecated in linux-2.6.15 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
-
+ /* Reserve those pages to allow them to be re-mapped to user space */
ReservePages(pvCpuVAddr, ui32Bytes);
#endif
+#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ psLinuxMemArea->uData.sVmalloc.ppsPageList = ppsPageList;
+ psLinuxMemArea->uData.sVmalloc.hBlockPageList = hBlockPageList;
+#endif
psLinuxMemArea->ui32ByteSize = ui32Bytes;
psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
#endif
-
- if(ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
- OSInvalidateCPUCacheRangeKM(psLinuxMemArea, pvCpuVAddr, ui32Bytes);
+ /* This works around a problem where Linux will not invalidate
+ * the cache for physical memory it frees that is direct mapped.
+ *
+ * As a result, cache entries remain that may be subsequently flushed
+ * to these physical pages after they have been allocated for another
+ * purpose. For a subsequent cached use of this memory, that is not a
+ * problem, but if we are allocating uncached or write-combined memory,
+ * and bypassing the cache, it can cause subsequent uncached writes to
+ * the memory to be replaced with junk from the cache.
+ *
+ * If the pages are from our page cache, no cache invalidate is needed.
+ *
+ * This just handles the __vmalloc() case (when we have a kernel virtual
+ * address range). The alloc_pages() path is handled in mmap.c.
+ */
+ if (AreaIsUncached(ui32AreaFlags) && !bFromPagePool)
+ {
+ OSInvalidateCPUCacheRangeKM(psLinuxMemArea, 0, pvCpuVAddr, ui32Bytes);
+ }
return psLinuxMemArea;
failed:
PVR_DPF((PVR_DBG_ERROR, "%s: failed!", __FUNCTION__));
- if(psLinuxMemArea)
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ if (ppsPageList)
+ {
+ FreePages(bFromPagePool, ppsPageList, hBlockPageList, ui32NumPages);
+ }
+#endif
+ if (psLinuxMemArea)
+ {
LinuxMemAreaStructFree(psLinuxMemArea);
+ }
+
return NULL;
}
IMG_VOID
FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
{
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ IMG_UINT32 ui32NumPages;
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+#endif
+
PVR_ASSERT(psLinuxMemArea);
PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
#endif
+ PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p",
+ __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress));
+
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ VUnmapWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+ ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ ppsPageList = psLinuxMemArea->uData.sVmalloc.ppsPageList;
+ hBlockPageList = psLinuxMemArea->uData.sVmalloc.hBlockPageList;
+
+ FreePages(CanFreeToPool(psLinuxMemArea), ppsPageList, hBlockPageList, ui32NumPages);
+#else
+/* PG_reserved was deprecated in linux-2.6.15 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
- UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
+ 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);
+#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
LinuxMemAreaStructFree(psLinuxMemArea);
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+/* Reserve pages of memory in order that they're not automatically
+ deallocated after the last user reference dies. */
static IMG_VOID
ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
{
}
+/* Un-reserve pages of memory in order that they can be freed. */
static IMG_VOID
UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
{
#endif
}
}
-#endif
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) */
IMG_VOID *
{
IMG_VOID *pvIORemapCookie;
- switch(ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ switch (ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
{
case PVRSRV_HAP_CACHED:
pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, ui32Bytes);
}
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- if(pvIORemapCookie)
+ if (pvIORemapCookie)
{
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
pvIORemapCookie,
ui32Bytes,
pszFileName,
ui32Line
- );
+ );
}
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
IMG_VOID *pvIORemapCookie;
psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
return NULL;
}
pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
- if(!pvIORemapCookie)
+ if (!pvIORemapCookie)
{
LinuxMemAreaStructFree(psLinuxMemArea);
return NULL;
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+/*
+ * Avoid using remap_pfn_range on RAM, if possible. On x86 systems, with
+ * PAT enabled, remap_pfn_range checks the page attributes requested by
+ * remap_pfn_range against those of the direct kernel mapping for those
+ * pages (if any). This is rather annoying if the pages have been obtained
+ * with alloc_pages, where we just ask for raw pages; we don't care about
+ * the direct mapping. This latter issue arises when device memory is
+ * exported from one process to another. Services implements this
+ * using memory wrapping, which ends up creating an external KV memory area.
+ */
static IMG_BOOL
TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig)
{
IMG_UINT32 ui32AddrChk;
IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
-
+ /*
+ * If bPhysContig is IMG_TRUE, we must assume psSysPhysAddr points
+ * to the address of the first page, not an array of page addresses.
+ */
for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
ui32 < ui32NumPages;
ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
LinuxMemArea *psLinuxMemArea;
psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
return NULL;
}
IMG_UINT32 ui32AreaFlags)
{
LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
return NULL;
}
-
+ /* Nothing to activly do. We just keep a record of the physical range. */
psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
psLinuxMemArea->ui32ByteSize = ui32Bytes;
ui32Bytes,
"unknown",
0
- );
+ );
#endif
#if defined(DEBUG_LINUX_MEM_AREAS)
(IMG_VOID *)psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr, __FILE__, __LINE__);
#endif
-
+ /* Nothing more to do than free the LinuxMemArea struct */
LinuxMemAreaStructFree(psLinuxMemArea);
}
NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
{
LinuxMemArea *psLinuxMemArea;
- IMG_UINT32 ui32PageCount;
- struct page **pvPageList;
+ IMG_UINT32 ui32NumPages;
+ struct page **ppsPageList;
IMG_HANDLE hBlockPageList;
- IMG_INT32 i;
- PVRSRV_ERROR eError;
-
+ IMG_BOOL bFromPagePool;
+
psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
goto failed_area_alloc;
}
- ui32PageCount = RANGE_TO_PAGES(ui32Bytes);
- eError = OSAllocMem(0, sizeof(*pvPageList) * ui32PageCount, (IMG_VOID **)&pvPageList, &hBlockPageList,
- "Array of pages");
- if(eError != PVRSRV_OK)
+ ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+ if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool))
{
- goto failed_page_list_alloc;
+ goto failed_alloc_pages;
}
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
+ psLinuxMemArea->uData.sPageList.ppsPageList = ppsPageList;
+ psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+ /* We defer the cache flush to the first user mapping of this memory */
+ psLinuxMemArea->bNeedsCacheInvalidate = AreaIsUncached(ui32AreaFlags) && !bFromPagePool;
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+
+failed_alloc_pages:
+ LinuxMemAreaStructFree(psLinuxMemArea);
+failed_area_alloc:
+ PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
+
+ return NULL;
+}
+
+
+IMG_VOID
+FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ IMG_UINT32 ui32NumPages;
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+
+ PVR_ASSERT(psLinuxMemArea);
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ ppsPageList = psLinuxMemArea->uData.sPageList.ppsPageList;
+ hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
- for(i=0; i<(IMG_INT32)ui32PageCount; i++)
+ FreePages(CanFreeToPool(psLinuxMemArea), ppsPageList, hBlockPageList, ui32NumPages);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+#if defined(CONFIG_ION_OMAP)
+
+#include "env_perproc.h"
+
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+
+extern struct ion_client *gpsIONClient;
+
+LinuxMemArea *
+NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength)
+{
+ const IMG_UINT32 ui32AllocDataLen =
+ offsetof(struct omap_ion_tiler_alloc_data, handle);
+ struct omap_ion_tiler_alloc_data asAllocData[2] = {};
+ u32 *pu32PageAddrs[2] = { NULL, NULL };
+ IMG_UINT32 i, ui32NumHandlesPerFd;
+ IMG_BYTE *pbPrivData = pvPrivData;
+ IMG_CPU_PHYADDR *pCPUPhysAddrs;
+ int iNumPages[2] = { 0, 0 };
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate LinuxMemArea struct", __func__));
+ goto err_out;
+ }
+
+ /* Depending on the UM config, userspace might give us info for
+ * one or two ION allocations. Divide the total size of data we
+ * were given by this ui32AllocDataLen, and check it's 1 or 2.
+ * Otherwise abort.
+ */
+ BUG_ON(ui32PrivDataLength != ui32AllocDataLen &&
+ ui32PrivDataLength != ui32AllocDataLen * 2);
+ ui32NumHandlesPerFd = ui32PrivDataLength / ui32AllocDataLen;
+
+ /* Shuffle the alloc data into separate Y & UV bits and
+ * make two separate allocations via the tiler.
+ */
+ for(i = 0; i < ui32NumHandlesPerFd; i++)
{
- pvPageList[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
- if(!pvPageList[i])
+ memcpy(&asAllocData[i], &pbPrivData[i * ui32AllocDataLen], ui32AllocDataLen);
+
+ if (omap_ion_tiler_alloc(gpsIONClient, &asAllocData[i]) < 0)
{
- 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
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate via ion_tiler", __func__));
+ goto err_free;
+ }
+
+ if (omap_tiler_pages(gpsIONClient, asAllocData[i].handle, &iNumPages[i],
+ &pu32PageAddrs[i]) < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to compute tiler pages", __func__));
+ goto err_free;
+ }
+ }
+
+ /* Assume the user-allocator has already done the tiler math and that the
+ * number of tiler pages allocated matches any other allocation type.
+ */
+ BUG_ON(ui32Bytes != (iNumPages[0] + iNumPages[1]) * PAGE_SIZE);
+ BUG_ON(sizeof(IMG_CPU_PHYADDR) != sizeof(int));
+ /* Glue the page lists together */
+ pCPUPhysAddrs = vmalloc(sizeof(IMG_CPU_PHYADDR) * (iNumPages[0] + iNumPages[1]));
+ if (!pCPUPhysAddrs)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate page list", __func__));
+ goto err_free;
}
+ for(i = 0; i < iNumPages[0]; i++)
+ pCPUPhysAddrs[i].uiAddr = pu32PageAddrs[0][i];
+ for(i = 0; i < iNumPages[1]; i++)
+ pCPUPhysAddrs[iNumPages[0] + i].uiAddr = pu32PageAddrs[1][i];
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
- pvPageList,
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ION,
+ asAllocData[0].handle,
0,
0,
NULL,
PAGE_ALIGN(ui32Bytes),
"unknown",
0
- );
+ );
#endif
- psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
- psLinuxMemArea->uData.sPageList.pvPageList = pvPageList;
- psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
+ for(i = 0; i < 2; i++)
+ psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i] = asAllocData[i].handle;
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ION;
+ psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs = pCPUPhysAddrs;
psLinuxMemArea->ui32ByteSize = ui32Bytes;
psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
-
- if(ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
- {
- psLinuxMemArea->bNeedsCacheInvalidate = IMG_TRUE;
- }
+ /* We defer the cache flush to the first user mapping of this memory */
+ psLinuxMemArea->bNeedsCacheInvalidate = AreaIsUncached(ui32AreaFlags);
#if defined(DEBUG_LINUX_MEM_AREAS)
DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
#endif
+err_out:
return psLinuxMemArea;
-
-failed_alloc_pages:
- for(i--; i >= 0; i--)
- {
- __free_pages(pvPageList[i], 0);
- }
- (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
- psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
-failed_page_list_alloc:
+
+err_free:
LinuxMemAreaStructFree(psLinuxMemArea);
-failed_area_alloc:
- PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
-
- return NULL;
+ psLinuxMemArea = IMG_NULL;
+ goto err_out;
}
IMG_VOID
-FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea)
{
- IMG_UINT32 ui32PageCount;
- struct page **pvPageList;
- IMG_HANDLE hBlockPageList;
- IMG_INT32 i;
-
- PVR_ASSERT(psLinuxMemArea);
- PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
+ IMG_UINT32 i;
#if defined(DEBUG_LINUX_MEM_AREAS)
DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
#endif
-
- ui32PageCount = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
- pvPageList = psLinuxMemArea->uData.sPageList.pvPageList;
- hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
-
+
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList, __FILE__, __LINE__);
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ION,
+ psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[0],
+ __FILE__, __LINE__);
#endif
- for(i=0;i<(IMG_INT32)ui32PageCount;i++)
+ for(i = 0; i < 2; 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);
+ if (!psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i])
+ break;
+ ion_free(gpsIONClient, psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i]);
+ psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i] = IMG_NULL;
}
- (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
- psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
+ /* free copy of page list, originals are freed by ion_free */
+ vfree(psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs);
+ psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs = IMG_NULL;
LinuxMemAreaStructFree(psLinuxMemArea);
}
+#endif /* defined(CONFIG_ION_OMAP) */
struct page*
LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
IMG_UINT32 ui32PageIndex;
IMG_CHAR *pui8Addr;
- switch(psLinuxMemArea->eAreaType)
+ switch (psLinuxMemArea->eAreaType)
{
case LINUX_MEM_AREA_ALLOC_PAGES:
ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
- return psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+ return psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageIndex];
case LINUX_MEM_AREA_VMALLOC:
pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
return vmalloc_to_page(pui8Addr);
case LINUX_MEM_AREA_SUB_ALLOC:
-
+ /* PRQA S 3670 3 */ /* ignore recursive warning */
return LinuxMemAreaOffsetToPage(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+ ui32ByteOffset);
return kmem_cache_create(pszName, Size, Align, ui32Flags, NULL
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
, NULL
-#endif
- );
+#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) */
+ );
}
kmem_cache_size(psCache),
pszFileName,
ui32Line
- );
+ );
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
PVR_UNREFERENCED_PARAMETER(ui32Line);
}
-IMG_VOID
-_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
-{
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
-#else
- PVR_UNREFERENCED_PARAMETER(pszFileName);
- PVR_UNREFERENCED_PARAMETER(ui32Line);
-#endif
-
- kmem_cache_free(psCache, pvObject);
-}
-
-
-const IMG_CHAR *
-KMemCacheNameWrapper(LinuxKMemCache *psCache)
-{
- PVR_UNREFERENCED_PARAMETER(psCache);
-
-
- return "";
-}
-
-
LinuxMemArea *
NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
IMG_UINT32 ui32ByteOffset,
PVR_ASSERT((ui32ByteOffset+ui32Bytes) <= psParentLinuxMemArea->ui32ByteSize);
psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
return NULL;
}
DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
#endif
-
+ /* Nothing more to do than free the LinuxMemArea structure */
LinuxMemAreaStructFree(psLinuxMemArea);
}
static LinuxMemArea *
LinuxMemAreaStructAlloc(IMG_VOID)
{
+/* debug */
#if 0
LinuxMemArea *psLinuxMemArea;
- psLinuxMemArea = kmem_cache_alloc(psLinuxMemAreaCache, GFP_KERNEL);
+ psLinuxMemArea = kmem_cache_alloc(g_PsLinuxMemAreaCache, GFP_KERNEL);
printk(KERN_ERR "%s: psLinuxMemArea=%p\n", __FUNCTION__, psLinuxMemArea);
dump_stack();
return psLinuxMemArea;
#else
- return KMemCacheAllocWrapper(psLinuxMemAreaCache, GFP_KERNEL);
+ return KMemCacheAllocWrapper(g_PsLinuxMemAreaCache, GFP_KERNEL);
#endif
}
static IMG_VOID
LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea)
{
- KMemCacheFreeWrapper(psLinuxMemAreaCache, psLinuxMemArea);
-
-
+ KMemCacheFreeWrapper(g_PsLinuxMemAreaCache, psLinuxMemArea);
+ /* debug */
+ //printk(KERN_ERR "%s(%p)\n", __FUNCTION__, psLinuxMemArea);
}
IMG_VOID
LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
{
- switch(psLinuxMemArea->eAreaType)
+ switch (psLinuxMemArea->eAreaType)
{
case LINUX_MEM_AREA_VMALLOC:
FreeVMallocLinuxMemArea(psLinuxMemArea);
case LINUX_MEM_AREA_IOREMAP:
FreeIORemapLinuxMemArea(psLinuxMemArea);
break;
- case LINUX_MEM_AREA_EXTERNAL_KV:
- FreeExternalKVLinuxMemArea(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;
+ case LINUX_MEM_AREA_ION:
+ FreeIONLinuxMemArea(psLinuxMemArea);
+ break;
default:
PVR_DPF((PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
__FUNCTION__, psLinuxMemArea->eAreaType));
LinuxLockMutex(&g_sDebugMutex);
- if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
{
g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
- if(g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
+ if (g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
{
g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
}
}
g_LinuxMemAreaCount++;
-
+ /* Create a new memory allocation record */
psNewRecord = kmalloc(sizeof(DEBUG_LINUX_MEM_AREA_REC), GFP_KERNEL);
- if(psNewRecord)
+ if (psNewRecord)
{
-
+ /* Record the allocation */
psNewRecord->psLinuxMemArea = psLinuxMemArea;
psNewRecord->ui32Flags = ui32Flags;
psNewRecord->pid = OSGetCurrentProcessIDKM();
__FUNCTION__));
}
-
+ /* Sanity check the flags */
pi8FlagsString = HAPFlagsToString(ui32Flags);
- if(strstr(pi8FlagsString, "UNKNOWN"))
+ if (strstr(pi8FlagsString, "UNKNOWN"))
{
PVR_DPF((PVR_DBG_ERROR,
"%s: Unexpected flags (0x%08x) associated with psLinuxMemArea @ %p",
__FUNCTION__,
ui32Flags,
psLinuxMemArea));
-
+ //dump_stack();
}
LinuxUnLockMutex(&g_sDebugMutex);
LinuxMemArea *psLinuxMemArea;
psLinuxMemArea = va_arg(va, LinuxMemArea*);
- if(psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
+ if (psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
{
return psCurrentRecord;
}
MatchLinuxMemArea_AnyVaCb,
psLinuxMemArea);
+/*exit_unlock:*/
LinuxUnLockMutex(&g_sDebugMutex);
return psCurrentRecord;
LinuxLockMutex(&g_sDebugMutex);
- if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
{
g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
}
g_LinuxMemAreaCount--;
-
+ /* Locate the corresponding allocation entry */
psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
MatchLinuxMemArea_AnyVaCb,
psLinuxMemArea);
- if(psCurrentRecord)
+ if (psCurrentRecord)
{
-
+ /* Unlink the allocation record */
List_DEBUG_LINUX_MEM_AREA_REC_Remove(psCurrentRecord);
kfree(psCurrentRecord);
}
IMG_VOID *
LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
{
- switch(psLinuxMemArea->eAreaType)
+ switch (psLinuxMemArea->eAreaType)
{
case LINUX_MEM_AREA_VMALLOC:
return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
case LINUX_MEM_AREA_SUB_ALLOC:
{
IMG_CHAR *pAddr =
- LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
- if(!pAddr)
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea); /* PRQA S 3670 */ /* ignore recursive warning */
+ if (!pAddr)
{
return NULL;
}
CpuPAddr.uiAddr = 0;
- switch(psLinuxMemArea->eAreaType)
+ switch (psLinuxMemArea->eAreaType)
{
case LINUX_MEM_AREA_IOREMAP:
{
CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
break;
}
+ case LINUX_MEM_AREA_ION:
+ {
+ IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ CpuPAddr = psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs[ui32PageIndex];
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ break;
+ }
case LINUX_MEM_AREA_ALLOC_PAGES:
{
struct page *page;
IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
- page = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+ page = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageIndex];
CpuPAddr.uiAddr = page_to_phys(page);
CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
break;
IMG_BOOL
LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
{
- switch(psLinuxMemArea->eAreaType)
+ 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_EXTERNAL_KV:
+ return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+ case LINUX_MEM_AREA_ION:
case LINUX_MEM_AREA_VMALLOC:
case LINUX_MEM_AREA_ALLOC_PAGES:
- return IMG_FALSE;
+ return IMG_FALSE;
case LINUX_MEM_AREA_SUB_ALLOC:
-
- return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+ /* PRQA S 3670 1 */ /* ignore recursive warning */
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
default:
PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
const IMG_CHAR *
LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
{
-
- switch(eMemAreaType)
+ /* Note we explicitly check the types instead of e.g.
+ * using the type to index an array of strings so
+ * we remain orthogonal to enum changes */
+ switch (eMemAreaType)
{
case LINUX_MEM_AREA_IOREMAP:
return "LINUX_MEM_AREA_IOREMAP";
return "LINUX_MEM_AREA_SUB_ALLOC";
case LINUX_MEM_AREA_ALLOC_PAGES:
return "LINUX_MEM_AREA_ALLOC_PAGES";
+ case LINUX_MEM_AREA_ION:
+ return "LINUX_MEM_AREA_ION";
default:
PVR_ASSERT(0);
}
#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start)
{
- if(start)
+ if (start)
{
LinuxLockMutex(&g_sDebugMutex);
}
LinuxUnLockMutex(&g_sDebugMutex);
}
}
-#endif
+#endif /* defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) */
#if defined(DEBUG_LINUX_MEM_AREAS)
}
}
-
+/* seq_file version of generating output, for reference check proc.c:CreateProcReadEntrySeq */
static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off)
{
DEBUG_LINUX_MEM_AREA_REC *psRecord;
static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off)
{
DEBUG_LINUX_MEM_AREA_REC *psRecord;
- if(!off)
+ if (!off)
{
return PVR_PROC_SEQ_START_TOKEN;
}
static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
{
DEBUG_LINUX_MEM_AREA_REC *psRecord = (DEBUG_LINUX_MEM_AREA_REC*)el;
- if(el == PVR_PROC_SEQ_START_TOKEN)
+ if (el == PVR_PROC_SEQ_START_TOKEN)
{
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
- seq_printf( sfile,
+ seq_printf(sfile,
"Number of Linux Memory Areas: %u\n"
"At the current water mark these areas correspond to %u bytes (excluding SUB areas)\n"
"At the highest water mark these areas corresponded to %u bytes (excluding SUB areas)\n"
"Bytes",
"Pid",
"Flags"
- );
+ );
#else
- seq_printf( sfile,
+ seq_printf(sfile,
"<mem_areas_header>\n"
"\t<count>%u</count>\n"
- "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%u\"/>\n"
- "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%u\"/>\n"
+ "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%u\"/>\n" /* (excluding SUB areas) */
+ "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%u\"/>\n" /* (excluding SUB areas) */
"</mem_areas_header>\n",
g_LinuxMemAreaCount,
g_LinuxMemAreaWaterMark,
g_LinuxMemAreaHighWaterMark
- );
+ );
#endif
return;
}
- seq_printf( sfile,
+ seq_printf(sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
"%8p %-24s %8p %08x %-8d %-5u %08x=(%s)\n",
#else
"\t<type>%s</type>\n"
"\t<cpu_virtual>%8p</cpu_virtual>\n"
"\t<cpu_physical>%08x</cpu_physical>\n"
- "\t<bytes>%ld</bytes>\n"
+ "\t<bytes>%d</bytes>\n"
"\t<pid>%u</pid>\n"
- "\t<flags>%08lx</flags>\n"
+ "\t<flags>%08x</flags>\n"
"\t<flags_string>%s</flags_string>\n"
"</linux_mem_area>\n",
#endif
psRecord->pid,
psRecord->ui32Flags,
HAPFlagsToString(psRecord->ui32Flags)
- );
+ );
}
-#endif
+#endif /* DEBUG_LINUX_MEM_AREAS */
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
}
-
+/* seq_file version of generating output, for reference check proc.c:CreateProcReadEntrySeq */
static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off)
{
DEBUG_MEM_ALLOC_REC *psRecord;
DecOffMemAllocRec_AnyVaCb,
&off);
#if defined(DEBUG_LINUX_XML_PROC_FILES)
- if(!psRecord)
+ if (!psRecord)
{
- seq_printf( sfile, "</meminfo>\n");
+ seq_printf(sfile, "</meminfo>\n");
}
#endif
static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
{
DEBUG_MEM_ALLOC_REC *psRecord;
- if(!off)
+ if (!off)
{
return PVR_PROC_SEQ_START_TOKEN;
}
&off);
#if defined(DEBUG_LINUX_XML_PROC_FILES)
- if(!psRecord)
+ if (!psRecord)
{
- seq_printf( sfile, "</meminfo>\n");
+ seq_printf(sfile, "</meminfo>\n");
}
#endif
static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
{
DEBUG_MEM_ALLOC_REC *psRecord = (DEBUG_MEM_ALLOC_REC*)el;
- if(el == PVR_PROC_SEQ_START_TOKEN)
+ if (el == PVR_PROC_SEQ_START_TOKEN)
{
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
-
- seq_printf( sfile, "%-60s: %d bytes\n",
+ /* NOTE: If you update this code, please also update the XML varient below
+ * too! */
+
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes allocated via kmalloc",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated via kmalloc",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes allocated via vmalloc",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated via vmalloc",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes allocated via alloc_pages",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated via alloc_pages",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes allocated via ioremap",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated via ioremap",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes reserved for \"IO\" memory areas",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated for \"IO\" memory areas",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes allocated via kmem_cache_alloc",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated via kmem_cache_alloc",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes mapped via vmap",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes mapped via vmap",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+#endif
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ seq_printf(sfile, "%-60s: %d pages\n",
+ "Number of pages in page pool",
+ atomic_read(&g_sPagePoolEntryCount));
+#endif
seq_printf( sfile, "\n");
-
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"The Current Water Mark for memory allocated from system RAM",
- g_SysRAMWaterMark);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ SysRAMTrueWaterMark());
+ seq_printf(sfile, "%-60s: %d bytes\n",
"The Highest Water Mark for memory allocated from system RAM",
g_SysRAMHighWaterMark);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"The Current Water Mark for memory allocated from IO memory",
g_IOMemWaterMark);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"The Highest Water Mark for memory allocated from IO memory",
g_IOMemHighWaterMark);
seq_printf( sfile, "\n");
- seq_printf( sfile, "Details for all known allocations:\n"
+ seq_printf(sfile, "Details for all known allocations:\n"
"%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
"Type",
"CpuVAddr",
"PrivateData",
"Filename:Line");
-#else
-
+#else /* DEBUG_LINUX_XML_PROC_FILES */
- seq_printf( sfile, "<meminfo>\n<meminfo_header>\n");
- seq_printf( sfile,
+ /* Note: If you want to update the description property of a watermark
+ * ensure that the key property remains unchanged so that watermark data
+ * logged over time from different driver revisions may remain comparable
+ */
+ seq_printf(sfile, "<meminfo>\n<meminfo_header>\n");
+ seq_printf(sfile,
"<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr8\" description=\"io_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr9\" description=\"io_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
- seq_printf( sfile,"\n" );
-
- seq_printf( sfile,
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ seq_printf(sfile,
+ "<watermark key=\"mr12\" description=\"vmap_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+ seq_printf(sfile,
+ "<watermark key=\"mr13\" description=\"vmap_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+#endif
+ seq_printf(sfile,
"<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%d\"/>\n",
- g_SysRAMWaterMark);
- seq_printf( sfile,
+ SysRAMTrueWaterMark());
+ seq_printf(sfile,
"<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%d\"/>\n",
g_SysRAMHighWaterMark);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%d\"/>\n",
g_IOMemWaterMark);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%d\"/>\n",
g_IOMemHighWaterMark);
- seq_printf( sfile, "</meminfo_header>\n");
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ seq_printf(sfile,
+ "<watermark key=\"mr18\" description=\"page_pool_current\" bytes=\"%d\"/>\n",
+ PAGES_TO_BYTES(atomic_read(&g_sPagePoolEntryCount)));
+#endif
+ seq_printf(sfile, "</meminfo_header>\n");
-#endif
+#endif /* DEBUG_LINUX_XML_PROC_FILES */
return;
}
- if(psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ if (psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
{
- seq_printf( sfile,
+ seq_printf(sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
"%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
#else
}
else
{
- seq_printf( sfile,
+ seq_printf(sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
"%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
#else
}
}
-#endif
+#endif /* defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) */
#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
+/* This could be moved somewhere more general */
const IMG_CHAR *
HAPFlagsToString(IMG_UINT32 ui32Flags)
{
"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;
+ /* FIXME create an enum for the cache type that we can
+ * cast and select so we get compiler warnings when
+ * when this code isn't complete due to new flags */
+ if (ui32Flags & PVRSRV_HAP_UNCACHED) {
+ ui32CacheTypeIndex = 0;
+ } else if (ui32Flags & PVRSRV_HAP_CACHED) {
+ ui32CacheTypeIndex = 1;
+ } else if (ui32Flags & PVRSRV_HAP_WRITECOMBINE) {
+ ui32CacheTypeIndex = 2;
+ } else {
+ ui32CacheTypeIndex = 3;
PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type (%u)",
__FUNCTION__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)));
}
-
- if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY){
+ /* FIXME create an enum for the map type that we can
+ * cast and select so we get compiler warnings when
+ * when this code isn't complete due to new flags */
+ if (ui32Flags & PVRSRV_HAP_KERNEL_ONLY) {
ui32MapTypeIndex = 0;
- }else if(ui32Flags & PVRSRV_HAP_SINGLE_PROCESS){
+ } else if (ui32Flags & PVRSRV_HAP_SINGLE_PROCESS) {
ui32MapTypeIndex = 1;
- }else if(ui32Flags & PVRSRV_HAP_MULTI_PROCESS){
+ } else if (ui32Flags & PVRSRV_HAP_MULTI_PROCESS) {
ui32MapTypeIndex = 2;
- }else if(ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS){
+ } else if (ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS) {
ui32MapTypeIndex = 3;
- }else if(ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL){
+ } else if (ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL) {
ui32MapTypeIndex = 4;
- }else{
+ } else {
ui32MapTypeIndex = 5;
PVR_DPF((PVR_DBG_ERROR, "%s: unknown map type (%u)",
__FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK)));
}
#endif
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%d bytes",
+ __FUNCTION__,
+ psCurrentRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
+ psCurrentRecord->psLinuxMemArea->ui32ByteSize));
+ /* Note this will also remove psCurrentRecord from g_LinuxMemAreaRecords
+ * but that's ok since we have already got a pointer to the next area. */
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
+
+{
+
+/* It's a bug if anything remains allocated at this point. We
+ * report an error, and simply brute force free anything we find. */
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
+ "type=%s "
+ "CpuVAddr=%p "
+ "CpuPAddr=0x%08x, "
+ "allocated @ file=%s,line=%d",
+ __FUNCTION__,
+ DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
+ psCurrentRecord->pvCpuVAddr,
+ psCurrentRecord->ulCpuPAddr,
+ psCurrentRecord->pszFileName,
+ psCurrentRecord->ui32Line));
+ switch (psCurrentRecord->eAllocType)
+ {
+ case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
+ KFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
+ IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IO:
+ /* Nothing needed except to free the record */
+ 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;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ case DEBUG_MEM_ALLOC_TYPE_VMAP:
+ VUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+#endif
+ default:
+ PVR_ASSERT(0);
+ }
+}
+#endif
+
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+static struct shrinker g_sShrinker =
+{
+ .shrink = ShrinkPagePool,
+ .seeks = DEFAULT_SEEKS
+};
+
+static IMG_BOOL g_bShrinkerRegistered;
+#endif
+
+IMG_VOID
+LinuxMMCleanup(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ if (g_LinuxMemAreaCount)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%d bytes)",
+ __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
+ }
+
+ List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords, LinuxMMCleanup_MemAreas_ForEachCb);
+
+ if (g_SeqFileMemArea)
+ {
+ RemoveProcEntrySeq(g_SeqFileMemArea);
+ }
+ }
+#endif
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+ if (g_bShrinkerRegistered)
+ {
+ unregister_shrinker(&g_sShrinker);
+ }
+#endif
+
+ /*
+ * The page pool must be freed after any remaining mem areas, but before
+ * the remaining memory resources.
+ */
+ FreePagePool();
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+
+ /*
+ * It's a bug if anything remains allocated at this point. We
+ * report an error, and simply brute force free anything we find.
+ */
+ List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords, LinuxMMCleanup_MemRecords_ForEachVa);
+
+ if (g_SeqFileMemoryRecords)
+ {
+ RemoveProcEntrySeq(g_SeqFileMemoryRecords);
+ }
+ }
+#endif
+
+ if (g_PsLinuxMemAreaCache)
+ {
+ KMemCacheDestroyWrapper(g_PsLinuxMemAreaCache);
+ }
+
+ if (g_PsLinuxPagePoolCache)
+ {
+ KMemCacheDestroyWrapper(g_PsLinuxPagePoolCache);
+ }
+}
+
+PVRSRV_ERROR
+LinuxMMInit(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ LinuxInitMutex(&g_sDebugMutex);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ g_SeqFileMemArea = CreateProcReadEntrySeq(
+ "mem_areas",
+ NULL,
+ ProcSeqNextMemArea,
+ ProcSeqShowMemArea,
+ ProcSeqOff2ElementMemArea,
+ ProcSeqStartstopDebugMutex
+ );
+ if (!g_SeqFileMemArea)
+ {
+ goto failed;
+ }
+ }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+ g_SeqFileMemoryRecords = CreateProcReadEntrySeq(
+ "meminfo",
+ NULL,
+ ProcSeqNextMemoryRecords,
+ ProcSeqShowMemoryRecords,
+ ProcSeqOff2ElementMemoryRecords,
+ ProcSeqStartstopDebugMutex
+ );
+ if (!g_SeqFileMemoryRecords)
+ {
+ goto failed;
+ }
+ }
+#endif
+
+ g_PsLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
+ if (!g_PsLinuxMemAreaCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate mem area kmem_cache", __FUNCTION__));
+ goto failed;
+ }
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ g_iPagePoolMaxEntries = PVR_LINUX_MEM_AREA_POOL_MAX_PAGES;
+ if (g_iPagePoolMaxEntries <= 0 || g_iPagePoolMaxEntries > INT_MAX/2)
+ {
+ g_iPagePoolMaxEntries = INT_MAX/2;
+ PVR_TRACE(("%s: No limit set for page pool size", __FUNCTION__));
+ }
+ else
+ {
+ PVR_TRACE(("%s: Maximum page pool size: %d", __FUNCTION__, g_iPagePoolMaxEntries));
+ }
+
+ g_PsLinuxPagePoolCache = KMemCacheCreateWrapper("img-mm-pool", sizeof(LinuxPagePoolEntry), 0, 0);
+ if (!g_PsLinuxPagePoolCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate page pool kmem_cache", __FUNCTION__));
+ goto failed;
+ }
+#endif
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+ register_shrinker(&g_sShrinker);
+ g_bShrinkerRegistered = IMG_TRUE;
+#endif
+
+ return PVRSRV_OK;
+
+failed:
+ LinuxMMCleanup();
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Linux Memory Management.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares various memory management utility functions
+ for Linux.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __IMG_LINUX_MM_H__
#define __IMG_LINUX_MM_H__
#define ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+#define PAGES_TO_BYTES(pages) ((pages) << PAGE_SHIFT)
+
#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
typedef enum {
LINUX_MEM_AREA_IOREMAP,
- LINUX_MEM_AREA_EXTERNAL_KV,
+ 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_ION,
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ LINUX_MEM_AREA_VMAP,
+#endif
LINUX_MEM_AREA_TYPE_COUNT
}LINUX_MEM_AREA_TYPE;
typedef struct _LinuxMemArea LinuxMemArea;
+/* FIXME - describe this structure. */
struct _LinuxMemArea {
LINUX_MEM_AREA_TYPE eAreaType;
union _uData
{
struct _sIORemap
{
-
+ /* Note: The memory this represents is _not_ implicitly
+ * page aligned, neither is its size */
IMG_CPU_PHYADDR CPUPhysAddr;
IMG_VOID *pvIORemapCookie;
}sIORemap;
struct _sExternalKV
{
-
+ /* Note: The memory this represents is _not_ implicitly
+ * page aligned, neither is its size */
IMG_BOOL bPhysContig;
union {
-
+ /*
+ * SYSPhysAddr is valid if bPhysContig is true, else
+ * pSysPhysAddr is valid
+ */
IMG_SYS_PHYADDR SysPhysAddr;
IMG_SYS_PHYADDR *pSysPhysAddr;
} uPhysAddr;
}sExternalKV;
struct _sIO
{
-
+ /* Note: The memory this represents is _not_ implicitly
+ * page aligned, neither is its size */
IMG_CPU_PHYADDR CPUPhysAddr;
}sIO;
struct _sVmalloc
{
-
+ /* Note the memory this represents _is_ implicitly
+ * page aligned _and_ so is its size */
IMG_VOID *pvVmallocAddress;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+#endif
}sVmalloc;
struct _sPageList
{
-
- struct page **pvPageList;
+ /* Note the memory this represents _is_ implicitly
+ * page aligned _and_ so is its size */
+ struct page **ppsPageList;
IMG_HANDLE hBlockPageList;
}sPageList;
+ struct _sIONTilerAlloc
+ {
+ /* Note the memory this represents _is_ implicitly
+ * page aligned _and_ so is its size */
+ IMG_CPU_PHYADDR *pCPUPhysAddrs;
+ struct ion_handle *psIONHandle[2];
+ }sIONTilerAlloc;
struct _sSubAlloc
{
-
+ /* Note: The memory this represents is _not_ implicitly
+ * page aligned, neither is its size */
LinuxMemArea *psParentLinuxMemArea;
IMG_UINT32 ui32ByteOffset;
}sSubAlloc;
}uData;
- IMG_UINT32 ui32ByteSize;
+ IMG_UINT32 ui32ByteSize; /* Size of memory area */
+
+ IMG_UINT32 ui32AreaFlags; /* Flags passed at creation time */
- IMG_UINT32 ui32AreaFlags;
+ IMG_BOOL bMMapRegistered; /* Registered with mmap code */
- IMG_BOOL bMMapRegistered;
+ IMG_BOOL bNeedsCacheInvalidate; /* Cache should be invalidated on first map? */
- IMG_BOOL bNeedsCacheInvalidate;
+ IMG_HANDLE hBMHandle; /* Handle back to BM for this allocation */
-
+ /* List entry for global list of areas registered for mmap */
struct list_head sMMapItem;
-
+ /*
+ * Head of list of all mmap offset structures associated with this
+ * memory area.
+ */
struct list_head sMMapOffsetStructList;
};
#endif
+/*!
+ *******************************************************************************
+ * @Function LinuxMMInit
+ *
+ * @Description
+ *
+ * Initialise linux memory management code.
+ * This should be called during services initialisation.
+ *
+ * @Return none
+******************************************************************************/
PVRSRV_ERROR LinuxMMInit(IMG_VOID);
+/*!
+ *******************************************************************************
+ *
+ * @Function LinuxMMCleanup
+ *
+ * @Description
+ *
+ * Cleanup state for the linux memory management code.
+ * This should be called at services cleanup.
+ *
+ * @Return none
+******************************************************************************/
IMG_VOID LinuxMMCleanup(IMG_VOID);
+/*!
+ *******************************************************************************
+ * @brief Wrappers for kmalloc/kfree with optional /proc/pvr/km tracking
+ * They can also be used as more concise replacements for OSAllocMem
+ * in Linux specific code.
+ *
+ * @param ui32ByteSize
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define KMallocWrapper(ui32ByteSize, uFlags) _KMallocWrapper(ui32ByteSize, uFlags, __FILE__, __LINE__)
#else
IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *szFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param pvCpuVAddr
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
#else
IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param ui32Bytes
+ * @param ui32AllocFlags
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
#else
IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param pvCpuVAddr
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
#else
IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief Allocates virtually contiguous pages
+ *
+ * @param ui32Bytes number of bytes to reserve
+ * @param ui32AreaFlags Heap caching and mapping Flags
+ *
+ * @return Page-aligned address of virtual allocation or NULL on error
+ ******************************************************************************/
LinuxMemArea *NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+/*!
+ *******************************************************************************
+ * @brief Deallocates virtually contiguous pages
+ *
+ * @param LinuxMemArea from NewVMallocLinuxMemArea
+ *
+ ******************************************************************************/
IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief Reserve physical IO memory and create a CPU virtual mapping for it
+ *
+ * @param BasePAddr
+ * @param ui32Bytes
+ * @param ui32MappingFlags
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
_IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief Reserve physical IO memory and create a CPU virtual mapping for it
+ *
+ * @param BasePAddr
+ * @param ui32Bytes
+ * @param ui32AreaFlags Heap caching and mapping Flags
+ *
+ * @return
+ ******************************************************************************/
LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ********************************************************************************/
IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief Register physical memory which already has a CPU virtual mapping
+ *
+ * @param pBasePAddr
+ * @param pvCPUVAddr
+ * @param bPhysContig
+ * @param ui32Bytes
+ * @param ui32AreaFlags Heap caching and mapping Flags
+ *
+ * @return
+ ******************************************************************************/
LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ ******************************************************************************
+ * @brief Unmaps an IO memory mapping created using IORemap
+ *
+ * @param pvIORemapCookie
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define IOUnmapWrapper(pvIORemapCookie) \
_IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ * @param ui32ByteOffset
+ *
+ * @return
+ ******************************************************************************/
struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param pszName
+ * @param Size
+ * @param Align
+ * @param ui32Flags
+ *
+ * @return
+ ******************************************************************************/
LinuxKMemCache *KMemCacheCreateWrapper(IMG_CHAR *pszName, size_t Size, size_t Align, IMG_UINT32 ui32Flags);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psCache
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID KMemCacheDestroyWrapper(LinuxKMemCache *psCache);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psCache
+ * @param Flags
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__)
#else
IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
#endif
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psCache
+ * @param pvObject
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__)
#else
IMG_VOID _KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psCache
+ *
+ * @return
+ ******************************************************************************/
const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param BasePAddr
+ * @param ui32Bytes
+ * @param ui32AreaFlags Heap caching and mapping Flags
+ *
+ * @return
+ ******************************************************************************/
LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param ui32Bytes
+ * @param ui32AreaFlags E.g Heap caching and mapping Flags
+ *
+ * @return
+ ******************************************************************************/
LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+#if defined(CONFIG_ION_OMAP)
+
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param ui32Bytes
+ * @param ui32AreaFlags E.g Heap caching and mapping Flags
+ *
+ * @return
+ ******************************************************************************/
+LinuxMemArea *
+NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength);
+
+
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
+IMG_VOID FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+#else /* defined(CONFIG_ION_OMAP) */
+
+static inline LinuxMemArea *
+NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32AreaFlags);
+ PVR_UNREFERENCED_PARAMETER(pvPrivData);
+ PVR_UNREFERENCED_PARAMETER(ui32PrivDataLength);
+ BUG();
+ return IMG_NULL;
+}
+
+static inline IMG_VOID FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_UNREFERENCED_PARAMETER(psLinuxMemArea);
+ BUG();
+}
+
+#endif /* defined(CONFIG_ION_OMAP) */
+
+
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psParentLinuxMemArea
+ * @param ui32ByteOffset
+ * @param ui32Bytes
+ *
+ * @return
+ ******************************************************************************/
LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
IMG_UINT32 ui32ByteOffset,
IMG_UINT32 ui32Bytes);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief For debug builds, LinuxMemAreas are tracked in /proc
+ *
+ * @param psLinuxMemArea
+ *
+ ******************************************************************************/
#if defined(LINUX_MEM_AREAS_DEBUG)
IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea);
#else
#endif
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ * @param ui32ByteOffset
+ *
+ * @return
+ ******************************************************************************/
IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
#define LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset).uiAddr)
+/*!
+ *******************************************************************************
+ * @brief Indicate whether a LinuxMemArea is physically contiguous
+ *
+ * @param psLinuxMemArea
+ *
+ * @return IMG_TRUE if the physical address range is contiguous, else IMG_FALSE
+ ******************************************************************************/
IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief Return the real underlying LinuxMemArea
+ *
+ * @param psLinuxMemArea
+ *
+ * @return The real underlying LinuxMemArea
+ ******************************************************************************/
static inline LinuxMemArea *
LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
{
}
+/*!
+ *******************************************************************************
+ * @brief Return type of real underlying LinuxMemArea
+ *
+ * @param psLinuxMemArea
+ *
+ * @return The areas eAreaType or for SUB areas; return the parents eAreaType.
+ ******************************************************************************/
static inline LINUX_MEM_AREA_TYPE
LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
{
}
+/*!
+ *******************************************************************************
+ * @brief Converts the enum type of a LinuxMemArea to a const string
+ *
+ * @param eMemAreaType
+ *
+ * @return const string representation of type
+ ******************************************************************************/
const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param ui32Flags
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG) || defined(DEBUG_LINUX_MEM_AREAS)
const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags);
#endif
-#endif
+#endif /* __IMG_LINUX_MM_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux mmap interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
#include <linux/wrapper.h>
#endif
#include <linux/slab.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+#include <linux/highmem.h>
+#endif
#include <asm/io.h>
#include <asm/page.h>
#include <asm/shmparam.h>
#include <drm/drmP.h>
#endif
-#include "img_defs.h"
-#include "services.h"
-#include "servicesint.h"
+#include "services_headers.h"
+
#include "pvrmmap.h"
#include "mutils.h"
#include "mmap.h"
#include "mm.h"
-#include "pvr_debug.h"
-#include "osfunc.h"
#include "proc.h"
#include "mutex.h"
#include "handle.h"
#error "The mmap code requires PVR_SECURE_HANDLES"
#endif
-static PVRSRV_LINUX_MUTEX g_sMMapMutex;
+/* WARNING:
+ * The mmap code has its own mutex, to prevent a possible deadlock,
+ * when using gPVRSRVLock.
+ * The Linux kernel takes the mm->mmap_sem before calling the mmap
+ * entry points (PVRMMap, MMapVOpen, MMapVClose), but the ioctl
+ * entry point may take mm->mmap_sem during fault handling, or
+ * before calling get_user_pages. If gPVRSRVLock was used in the
+ * mmap entry points, a deadlock could result, due to the ioctl
+ * and mmap code taking the two locks in different orders.
+ * As a corollary to this, the mmap entry points must not call
+ * any driver code that relies on gPVRSRVLock is held.
+ */
+PVRSRV_LINUX_MUTEX g_sMMapMutex;
static LinuxKMemCache *g_psMemmapCache = NULL;
static LIST_HEAD(g_sMMapAreaList);
#if defined(DEBUG_LINUX_MMAP_AREAS)
static struct proc_dir_entry *g_ProcMMap;
-#endif
+#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+/*
+ * Now that we are using mmap2 in srvclient, almost (*) the full 32
+ * bit offset is available. The range of values is divided into two.
+ * The first part of the range, from FIRST_PHYSICAL_PFN to
+ * LAST_PHYSICAL_PFN, is for raw page mappings (VM_PFNMAP). The
+ * resulting 43 bit (*) physical address range should be enough for
+ * the current range of processors we support.
+ *
+ * NB: (*) -- the above figures assume 4KB page size. The offset
+ * argument to mmap2() is in units of 4,096 bytes regardless of page
+ * size. Thus, we lose (PAGE_SHIFT-12) bits of resolution on other
+ * architectures.
+ *
+ * The second part of the range, from FIRST_SPECIAL_PFN to LAST_SPECIAL_PFN,
+ * is used for all other mappings. These other mappings will always
+ * consist of pages with associated page structures, and need not
+ * represent a contiguous range of physical addresses.
+ *
+ */
#define MMAP2_PGOFF_RESOLUTION (32-PAGE_SHIFT+12)
#define RESERVED_PGOFF_BITS 1
#define MAX_MMAP_HANDLE ((1UL<<(MMAP2_PGOFF_RESOLUTION-RESERVED_PGOFF_BITS))-1)
#define FIRST_SPECIAL_PFN (LAST_PHYSICAL_PFN + 1)
#define LAST_SPECIAL_PFN (FIRST_SPECIAL_PFN + MAX_MMAP_HANDLE)
-#else
+#else /* !defined(PVR_MAKE_ALL_PFNS_SPECIAL) */
#if PAGE_SHIFT != 12
#error This build variant has not yet been made non-4KB page-size aware
#endif
+/*
+ * Since we no longer have to worry about clashes with the mmap
+ * offsets used for pure PFN mappings (VM_PFNMAP), there is greater
+ * freedom in choosing the mmap handles. This is useful if the
+ * mmap offset space has to be shared with another driver component.
+ */
+
#if defined(PVR_MMAP_OFFSET_BASE)
#define FIRST_SPECIAL_PFN PVR_MMAP_OFFSET_BASE
#else
#define MAX_MMAP_HANDLE 0x7fffffffUL
#endif
-#endif
+#endif /* !defined(PVR_MAKE_ALL_PFNS_SPECIAL) */
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
static inline IMG_BOOL
PFNIsPhysical(IMG_UINT32 pfn)
{
-
- return ( (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+ /* Unsigned, no need to compare >=0 */
+ return (/*(pfn >= FIRST_PHYSICAL_PFN) &&*/ (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
}
static inline IMG_BOOL
PFNIsSpecial(IMG_UINT32 pfn)
{
-
- return ((pfn >= FIRST_SPECIAL_PFN) ) ? IMG_TRUE : IMG_FALSE;
+ /* Unsigned, no need to compare <=MAX_UINT */
+ return ((pfn >= FIRST_SPECIAL_PFN) /*&& (pfn <= LAST_SPECIAL_PFN)*/) ? IMG_TRUE : IMG_FALSE;
}
#endif
}
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+/*
+ * Determine whether physical or special mappings will be used for
+ * a given memory area. At present, this decision is made on
+ * whether the mapping represents a contiguous range of physical
+ * addresses, which is a requirement for raw page mappings (VM_PFNMAP).
+ * In the VMA structure for such a mapping, vm_pgoff is the PFN
+ * (page frame number, the physical address divided by the page size)
+ * of the first page in the VMA. The second page is assumed to have
+ * PFN (vm_pgoff + 1), the third (vm_pgoff + 2) and so on.
+ */
static inline IMG_BOOL
LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
{
static inline IMG_UINT32
GetCurrentThreadID(IMG_VOID)
{
-
+ /*
+ * The PID is the thread ID, as each thread is a
+ * seperate process.
+ */
return (IMG_UINT32)current->pid;
}
#endif
+/*
+ * Create an offset structure, which is used to hold per-process
+ * mmap data.
+ */
static PKV_OFFSET_STRUCT
CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
{
psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
-
+ /*
+ * We store the TID in case two threads within a process
+ * generate the same offset structure, and both end up on the
+ * list of structures waiting to be mapped, at the same time.
+ * This could happen if two sub areas within the same page are
+ * being mapped at the same time.
+ * The TID allows the mmap entry point to distinguish which
+ * mapping is being done by which thread.
+ */
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
psOffsetStruct->ui32TID = GetCurrentThreadID();
#endif
psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
#if defined(DEBUG_LINUX_MMAP_AREAS)
-
+ /* Extra entries to support proc filesystem debug info */
psOffsetStruct->pszName = pszName;
#endif
}
+/*
+ * There are no alignment constraints for mapping requests made by user
+ * mode Services. For this, and potentially other reasons, the
+ * mapping created for a users request may look different to the
+ * original request in terms of size and alignment.
+ *
+ * This function determines an offset that the user can add to the mapping
+ * that is _actually_ created which will point to the memory they are
+ * _really_ interested in.
+ *
+ */
static inline IMG_VOID
DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
IMG_UINT32 *pui32RealByteSize,
}
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapOSMemHandleToMMapData
+
+ @Description
+
+ Determine various parameters needed to mmap a memory area, and to
+ locate the memory within the mapped area.
+
+ @input psPerProc : Per-process data.
+ @input hMHandle : Memory handle.
+ @input pui32MMapOffset : pointer to location for returned mmap offset.
+ @input pui32ByteOffset : pointer to location for returned byte offset.
+ @input pui32RealByteSize : pointer to location for returned real byte size.
+ @input pui32UserVaddr : pointer to location for returned user mode address.
+
+ @output pui32MMapOffset : points to mmap offset to be used in mmap2 sys call.
+ @output pui32ByteOffset : points to byte offset of start of memory
+ within mapped area returned by mmap2.
+ @output pui32RealByteSize : points to size of area to be mapped.
+ @output pui32UserVAddr : points to user mode address of start of
+ mapping, or 0 if it hasn't been mapped yet.
+
+ @Return PVRSRV_ERROR : PVRSRV_OK, or error code.
+
+ ******************************************************************************/
PVRSRV_ERROR
PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined (SUPPORT_SID_INTERFACE)
psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
- DetermineUsersSizeAndByteOffset(psLinuxMemArea,
- pui32RealByteSize,
- pui32ByteOffset);
+ /* Sparse mappings have to ask the BM for the virtual size */
+ if (psLinuxMemArea->hBMHandle)
+ {
+ *pui32RealByteSize = BM_GetVirtualSize(psLinuxMemArea->hBMHandle);
+ *pui32ByteOffset = 0;
+ }
+ else
+ {
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ pui32RealByteSize,
+ pui32ByteOffset);
+ }
-
+ /* Check whether this memory area has already been mapped */
list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
{
if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
{
-
- PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
-
+ if (!psLinuxMemArea->hBMHandle)
+ {
+ PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
+ }
+ /*
+ * User mode locking is required to stop two threads racing to
+ * map the same memory area. The lock should prevent a
+ * second thread retrieving mmap data for a given handle,
+ * before the first thread has done the mmap.
+ * Without locking, both threads may attempt the mmap,
+ * and one of them will fail.
+ */
*pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
*pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
- psOffsetStruct->ui32RefCount++;
+ PVRSRVOffsetStructIncRef(psOffsetStruct);
eError = PVRSRV_OK;
goto exit_unlock;
}
}
-
+ /* Memory area won't have been mapped yet */
*pui32UserVAddr = 0;
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
goto exit_unlock;
}
-
+ /*
+ * Offset structures representing physical mappings are added to
+ * a list, so that they can be located when the memory area is mapped.
+ */
list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
psOffsetStruct->bOnMMapList = IMG_TRUE;
- psOffsetStruct->ui32RefCount++;
+ PVRSRVOffsetStructIncRef(psOffsetStruct);
eError = PVRSRV_OK;
-
-
-
+ /* Need to scale up the offset to counter the shifting that
+ is done in the mmap2() syscall, as it expects the pgoff
+ argument to be in units of 4,096 bytes irrespective of
+ page size */
*pui32MMapOffset = *pui32MMapOffset << (PAGE_SHIFT - 12);
exit_unlock:
}
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapReleaseMMapData
+
+ @Description
+
+ Release mmap data.
+
+ @input psPerProc : Per-process data.
+ @input hMHandle : Memory handle.
+ @input pbMUnmap : pointer to location for munmap flag.
+ @input pui32UserVAddr : pointer to location for user mode address of mapping.
+ @input pui32ByteSize : pointer to location for size of mapping.
+
+ @Output pbMUnmap : points to flag that indicates whether an munmap is
+ required.
+ @output pui32UserVAddr : points to user mode address to munmap.
+
+ @Return PVRSRV_ERROR : PVRSRV_OK, or error code.
+
+ ******************************************************************************/
PVRSRV_ERROR
PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined (SUPPORT_SID_INTERFACE)
psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
-
+ /* Find the offset structure */
list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
{
if (psOffsetStruct->ui32PID == ui32PID)
goto exit_unlock;
}
- psOffsetStruct->ui32RefCount--;
+ PVRSRVOffsetStructDecRef(psOffsetStruct);
*pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
}
}
-
+ /* MMap data not found */
#if defined (SUPPORT_SID_INTERFACE)
PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle %x (memory area %p)", __FUNCTION__, hMHandle, psLinuxMemArea));
#else
if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
{
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
-
+ /*
+ * If the offset is physical, make sure the thread IDs match,
+ * as different threads may be mapping different memory areas
+ * with the same offset.
+ */
if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
#endif
{
}
+/*
+ * Map a memory area into user space.
+ * Note, the ui32ByteOffset is _not_ implicitly page aligned since
+ * LINUX_MEM_AREA_SUB_ALLOC LinuxMemAreas have no alignment constraints.
+ */
static IMG_BOOL
DoMapToUser(LinuxMemArea *psLinuxMemArea,
struct vm_area_struct* ps_vma,
{
IMG_UINT32 ui32ByteSize;
+ if ((psLinuxMemArea->hBMHandle) && (ui32ByteOffset != 0))
+ {
+ /* Partial mapping of sparse allocations should never happen */
+ return IMG_FALSE;
+ }
+
if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
{
- return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),
+ return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea), /* PRQA S 3670 */ /* allow recursion */
ps_vma,
psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
}
-
+ /*
+ * Note that ui32ByteSize may be larger than the size of the memory
+ * area being mapped, as the former is a multiple of the page size.
+ */
ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
#if defined (__sparc__)
-
+ /*
+ * For LINUX_MEM_AREA_EXTERNAL_KV, we don't know where the address range
+ * we are being asked to map has come from, that is, whether it is memory
+ * or I/O. For all architectures other than SPARC, there is no distinction.
+ * Since we don't currently support SPARC, we won't worry about it.
+ */
#error "SPARC not supported"
#endif
PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
-
+ /*
+ * Since the memory is contiguous, we can map the whole range in one
+ * go .
+ */
+
+ PVR_ASSERT(psLinuxMemArea->hBMHandle == IMG_NULL);
+
result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
if(result == 0)
#endif
{
-
+ /*
+ * Memory may be non-contiguous, so we map the range page,
+ * by page. Since VM_PFNMAP mappings are assumed to be physically
+ * contiguous, we can't legally use REMAP_PFN_RANGE (that is, we
+ * could, but the resulting VMA may confuse other bits of the kernel
+ * that attempt to interpret it).
+ * The only alternative is to use VM_INSERT_PAGE, which requires
+ * finding the page structure corresponding to each page, or
+ * if mixed maps are supported (VM_MIXEDMAP), vm_insert_mixed.
+ */
IMG_UINT32 ulVMAPos;
IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
IMG_UINT32 ui32PA;
+ IMG_UINT32 ui32AdjustedPA = ui32ByteOffset;
#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
IMG_BOOL bMixedMap = IMG_FALSE;
#endif
-
+ /* First pass, validate the page frame numbers */
for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
{
- IMG_UINT32 pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+ IMG_UINT32 pfn;
+ IMG_BOOL bMapPage = IMG_TRUE;
- if (!pfn_valid(pfn))
- {
+ if (psLinuxMemArea->hBMHandle)
+ {
+ if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32PA))
+ {
+ bMapPage = IMG_FALSE;
+ }
+ }
+
+ if (bMapPage)
+ {
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32AdjustedPA);
+ if (!pfn_valid(pfn))
+ {
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
- PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%x", __FUNCTION__, pfn));
- return IMG_FALSE;
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%x", __FUNCTION__, pfn));
+ return IMG_FALSE;
#else
- bMixedMap = IMG_TRUE;
+ bMixedMap = IMG_TRUE;
#endif
- }
+ }
+ ui32AdjustedPA += PAGE_SIZE;
+ }
}
#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
ps_vma->vm_flags |= VM_MIXEDMAP;
}
#endif
-
+ /* Second pass, get the page structures and insert the pages */
ulVMAPos = ps_vma->vm_start;
+ ui32AdjustedPA = ui32ByteOffset;
for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
{
IMG_UINT32 pfn;
IMG_INT result;
+ IMG_BOOL bMapPage = IMG_TRUE;
+
+ if (psLinuxMemArea->hBMHandle)
+ {
+ /* We have a sparse allocation, check if this page should be mapped */
+ if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32PA))
+ {
+ bMapPage = IMG_FALSE;
+ }
+ }
- pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+ if (bMapPage)
+ {
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32AdjustedPA);
#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
- if (bMixedMap)
- {
- result = vm_insert_mixed(ps_vma, ulVMAPos, pfn);
- if(result != 0)
- {
- PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_mixed failed (%d)", __FUNCTION__, result));
- return IMG_FALSE;
- }
- }
- else
+ if (bMixedMap)
+ {
+ result = vm_insert_mixed(ps_vma, ulVMAPos, pfn);
+ if(result != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_mixed failed (%d)", __FUNCTION__, result));
+ return IMG_FALSE;
+ }
+ }
+ else
#endif
- {
- struct page *psPage;
-
- PVR_ASSERT(pfn_valid(pfn));
-
- psPage = pfn_to_page(pfn);
-
- result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage);
- if(result != 0)
- {
- PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
- return IMG_FALSE;
- }
- }
- ulVMAPos += PAGE_SIZE;
- }
+ {
+ struct page *psPage;
+
+ PVR_ASSERT(pfn_valid(pfn));
+
+ psPage = pfn_to_page(pfn);
+
+ result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage);
+ if(result != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
+ return IMG_FALSE;
+ }
+ }
+ ui32AdjustedPA += PAGE_SIZE;
+ }
+ ulVMAPos += PAGE_SIZE;
+ }
}
return IMG_TRUE;
MMapVOpenNoLock(struct vm_area_struct* ps_vma)
{
PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
- PVR_ASSERT(psOffsetStruct != IMG_NULL)
- psOffsetStruct->ui32Mapped++;
+
+ PVR_ASSERT(psOffsetStruct != IMG_NULL);
PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+ PVRSRVOffsetStructIncMapped(psOffsetStruct);
+
if (psOffsetStruct->ui32Mapped > 1)
{
PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %u)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
}
+/*
+ * Linux mmap open entry point.
+ */
static void
MMapVOpen(struct vm_area_struct* ps_vma)
{
MMapVCloseNoLock(struct vm_area_struct* ps_vma)
{
PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
- PVR_ASSERT(psOffsetStruct != IMG_NULL)
+ PVR_ASSERT(psOffsetStruct != IMG_NULL);
#if defined(DEBUG_LINUX_MMAP_AREAS)
PVR_DPF((PVR_DBG_MESSAGE,
#endif
PVR_ASSERT(!psOffsetStruct->bOnMMapList);
- psOffsetStruct->ui32Mapped--;
+ PVRSRVOffsetStructDecMapped(psOffsetStruct);
if (psOffsetStruct->ui32Mapped == 0)
{
if (psOffsetStruct->ui32RefCount != 0)
ps_vma->vm_private_data = NULL;
}
+/*
+ * Linux mmap close entry point.
+ */
static void
MMapVClose(struct vm_area_struct* ps_vma)
{
LinuxUnLockMutex(&g_sMMapMutex);
}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+/*
+ * This vma operation is used to read data from mmap regions. It is called
+ * by access_process_vm, which is called to handle PTRACE_PEEKDATA ptrace
+ * requests and reads from /proc/<pid>/mem.
+ */
+static int MMapVAccess(struct vm_area_struct *ps_vma, unsigned long addr,
+ void *buf, int len, int write)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ LinuxMemArea *psLinuxMemArea;
+ unsigned long ulOffset;
+ int iRetVal = -EINVAL;
+ IMG_VOID *pvKernelAddr;
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+ psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+ ulOffset = addr - ps_vma->vm_start;
+
+ if (ulOffset+len > psLinuxMemArea->ui32ByteSize)
+ /* Out of range. We shouldn't get here, because the kernel will do
+ the necessary checks before calling access_process_vm. */
+ goto exit_unlock;
+
+ pvKernelAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+ if (pvKernelAddr)
+ {
+ memcpy(buf, pvKernelAddr+ulOffset, len);
+ iRetVal = len;
+ }
+ else
+ {
+ IMG_UINT32 pfn, ui32OffsetInPage;
+ struct page *page;
+
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ulOffset);
+
+ if (!pfn_valid(pfn))
+ goto exit_unlock;
+
+ page = pfn_to_page(pfn);
+ ui32OffsetInPage = ADDR_TO_PAGE_OFFSET(ulOffset);
+
+ if (ui32OffsetInPage+len > PAGE_SIZE)
+ /* The region crosses a page boundary */
+ goto exit_unlock;
+
+ pvKernelAddr = kmap(page);
+ memcpy(buf, pvKernelAddr+ui32OffsetInPage, len);
+ kunmap(page);
+
+ iRetVal = len;
+ }
+
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+ return iRetVal;
+}
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) */
static struct vm_operations_struct MMapIOOps =
{
.open=MMapVOpen,
- .close=MMapVClose
+ .close=MMapVClose,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+ .access=MMapVAccess,
+#endif
};
+/*!
+ *******************************************************************************
+
+ @Function PVRMMap
+
+ @Description
+
+ Driver mmap entry point.
+
+ @input pFile : unused.
+ @input ps_vma : pointer to linux memory area descriptor.
+
+ @Return 0, or Linux error code.
+
+ ******************************************************************************/
int
PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
{
- IMG_UINT32 ui32ByteSize;
+ LinuxMemArea *psFlushMemArea = IMG_NULL;
PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_UINT32 ui32ByteSize;
+ IMG_VOID *pvBase = IMG_NULL;
int iRetVal = 0;
+ IMG_UINT32 ui32ByteOffset = 0; /* Keep compiler happy */
PVR_UNREFERENCED_PARAMETER(pFile);
ui32ByteSize, ui32ByteSize));
psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+
if (psOffsetStruct == IMG_NULL)
{
#if defined(SUPPORT_DRI_DRM)
LinuxUnLockMutex(&g_sMMapMutex);
#if !defined(SUPPORT_DRI_DRM_EXT)
-
+ /* Pass unknown requests onto the DRM module */
return drm_mmap(pFile, ps_vma);
#else
-
- return -ENOENT;
+ /*
+ * Indicate to caller that the request is not for us.
+ * Do not return this error elsewhere in this function, as the
+ * caller may use it as a clue as to whether the mmap request
+ * should be passed on to another component (e.g. drm_mmap).
+ */
+ return -ENOENT;
#endif
#else
PVR_UNREFERENCED_PARAMETER(pFile);
#endif
goto unlock_and_return;
}
+
list_del(&psOffsetStruct->sMMapItem);
psOffsetStruct->bOnMMapList = IMG_FALSE;
-
+ /* Only support shared writeable mappings */
if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
((ps_vma->vm_flags & VM_SHARED) == 0))
{
ps_vma->vm_flags |= VM_RESERVED;
ps_vma->vm_flags |= VM_IO;
-
+ /*
+ * Disable mremap because our nopage handler assumes all
+ * page requests have already been validated.
+ */
ps_vma->vm_flags |= VM_DONTEXPAND;
-
+ /* Don't allow mapping to be inherited across a process fork */
ps_vma->vm_flags |= VM_DONTCOPY;
ps_vma->vm_private_data = (void *)psOffsetStruct;
switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
{
case PVRSRV_HAP_CACHED:
-
+ /* This is the default, do nothing. */
break;
case PVRSRV_HAP_WRITECOMBINE:
- ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
+ ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
break;
case PVRSRV_HAP_UNCACHED:
ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
break;
default:
PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
- iRetVal = -EINVAL;
+ iRetVal = -EINVAL;
goto unlock_and_return;
}
-
+ /* Install open and close handlers for ref-counting */
ps_vma->vm_ops = &MMapIOOps;
if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
goto unlock_and_return;
}
- PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0)
+ PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0);
psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
-
+ /* Compute the flush region (if necessary) inside the mmap mutex */
if(psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate)
{
- IMG_UINT32 ui32RealByteSize, ui32ByteOffset;
- IMG_VOID *pvBase;
+ IMG_UINT32 ui32DummyByteSize;
DetermineUsersSizeAndByteOffset(psOffsetStruct->psLinuxMemArea,
- &ui32RealByteSize,
+ &ui32DummyByteSize,
&ui32ByteOffset);
- ui32RealByteSize = psOffsetStruct->psLinuxMemArea->ui32ByteSize;
pvBase = (IMG_VOID *)ps_vma->vm_start + ui32ByteOffset;
+ psFlushMemArea = psOffsetStruct->psLinuxMemArea;
- OSInvalidateCPUCacheRangeKM(psOffsetStruct->psLinuxMemArea,
- pvBase, ui32RealByteSize);
psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate = IMG_FALSE;
}
-
+ /* Call the open routine to increment the usage count */
MMapVOpenNoLock(ps_vma);
-
+
PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
__FUNCTION__, ps_vma->vm_pgoff));
-
+
unlock_and_return:
if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
{
- DestroyOffsetStruct(psOffsetStruct);
+ DestroyOffsetStruct(psOffsetStruct);
}
LinuxUnLockMutex(&g_sMMapMutex);
-
+
+ if(psFlushMemArea)
+ {
+ OSInvalidateCPUCacheRangeKM(psFlushMemArea, ui32ByteOffset, pvBase,
+ psFlushMemArea->ui32ByteSize);
+ }
+
return iRetVal;
}
#if defined(DEBUG_LINUX_MMAP_AREAS)
+/*
+ * Lock MMap regions list (called on page start/stop while reading /proc/mmap)
+
+ * sfile : seq_file that handles /proc file
+ * start : TRUE if it's start, FALSE if it's stop
+ *
+*/
static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start)
{
if(start)
}
+/*
+ * Convert offset (index from KVOffsetTable) to element
+ * (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * off : index into the KVOffsetTable from which to print
+ *
+ * returns void* : Pointer to element that will be dumped
+ *
+*/
static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off)
{
LinuxMemArea *psLinuxMemArea;
return (void*)0;
}
+/*
+ * Gets next MMap element to show. (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ * off : index into the KVOffsetTable from which to print
+ *
+ * returns void* : Pointer to element to show (0 ends iteration)
+*/
static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off)
{
return ProcSeqOff2ElementMMapRegistrations(sfile,off);
}
+/*
+ * Show MMap element (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ *
+*/
static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
{
KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
#endif
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapRegisterArea
+
+ @Description
+
+ Register a memory area with the mmap code.
+
+ @input psLinuxMemArea : pointer to memory area.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
PVRSRV_ERROR
PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
{
PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
-
+ /* Check this mem area hasn't already been registered */
if(psLinuxMemArea->bMMapRegistered)
{
PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
#if defined(DEBUG_LINUX_MMAP_AREAS)
g_ui32RegisteredAreas++;
-
+ /*
+ * Sub memory areas are excluded from g_ui32TotalByteSize so that we
+ * don't count memory twice, once for the parent and again for sub
+ * allocationis.
+ */
if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
{
g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
}
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapRemoveRegisterArea
+
+ @Description
+
+ Unregister a memory area with the mmap code.
+
+ @input psLinuxMemArea : pointer to memory area.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
PVRSRV_ERROR
PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
{
if (psOffsetStruct->ui32Mapped != 0)
{
PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %u", __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
+ dump_stack();
+ PVRSRVDumpRefCountCCB();
eError = PVRSRV_ERROR_STILL_MAPPED;
goto exit_unlock;
}
else
{
-
+ /*
+ * An offset structure is created when a call is made to get
+ * the mmap data for a physical mapping. If the data is never
+ * used for mmap, we will be left with an umapped offset
+ * structure.
+ */
PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped", __FUNCTION__, psOffsetStruct));
}
}
+/*!
+ *******************************************************************************
+
+ @Function LinuxMMapPerProcessConnect
+
+ @Description
+
+ Per-process mmap initialisation code.
+
+ @input psEnvPerProc : pointer to OS specific per-process data.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
PVRSRV_ERROR
LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
{
return PVRSRV_OK;
}
+/*!
+ *******************************************************************************
+
+ @Function LinuxMMapPerProcessDisconnect
+
+ @Description
+
+ Per-process mmap deinitialisation code.
+
+ @input psEnvPerProc : pointer to OS specific per-process data.
+
+ ******************************************************************************/
IMG_VOID
LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
{
}
+/*!
+ *******************************************************************************
+
+ @Function LinuxMMapPerProcessHandleOptions
+
+ @Description
+
+ Set secure handle options required by mmap code.
+
+ @input psHandleBase : pointer to handle base.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
{
PVRSRV_ERROR eError;
}
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapInit
+
+ @Description
+
+ MMap initialisation code
+
+ ******************************************************************************/
IMG_VOID
PVRMMapInit(IMG_VOID)
{
ProcSeqOff2ElementMMapRegistrations,
ProcSeqStartstopMMapRegistations
);
-#endif
+#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */
return;
error:
}
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapCleanup
+
+ @Description
+
+ Mmap deinitialisation code
+
+ ******************************************************************************/
IMG_VOID
PVRMMapCleanup(IMG_VOID)
{
#if defined(DEBUG_LINUX_MMAP_AREAS)
RemoveProcEntrySeq(g_ProcMMap);
-#endif
+#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */
if(g_psMemmapCache)
{
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux mmap interface declaration
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined(__MMAP_H__)
#define __MMAP_H__
#include <linux/list.h>
#if defined(VM_MIXEDMAP)
+/*
+ * Mixed maps allow us to avoid using raw PFN mappings (VM_PFNMAP) for
+ * pages without pages structures ("struct page"), giving us more
+ * freedom in choosing the mmap offset for mappings. Mixed maps also
+ * allow both the mmap and the wrap code to be simplified somewhat.
+ */
#define PVR_MAKE_ALL_PFNS_SPECIAL
#endif
#include "perproc.h"
#include "mm.h"
+/*
+ * This structure represents the relationship between an mmap2 file
+ * offset and a LinuxMemArea for a given process.
+ */
typedef struct KV_OFFSET_STRUCT_TAG
{
-
+ /*
+ * Mapping count. Incremented when the mapping is created, and
+ * if the mapping is inherited across a process fork.
+ */
IMG_UINT32 ui32Mapped;
-
+ /*
+ * Offset to be passed to mmap2 to map the associated memory area
+ * into user space. The offset may represent the page frame number
+ * of the first page in the area (if the area is physically
+ * contiguous), or it may represent the secure handle associated
+ * with the area.
+ */
IMG_UINT32 ui32MMapOffset;
IMG_UINT32 ui32RealByteSize;
-
+ /* Memory area associated with this offset structure */
LinuxMemArea *psLinuxMemArea;
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
-
+ /* ID of the thread that owns this structure */
IMG_UINT32 ui32TID;
#endif
-
+ /* ID of the process that owns this structure */
IMG_UINT32 ui32PID;
-
+ /*
+ * For offsets that represent actual page frame numbers, this structure
+ * is temporarily put on a list so that it can be found from the
+ * driver mmap entry point. This flag indicates the structure is
+ * on the list.
+ */
IMG_BOOL bOnMMapList;
-
+ /* Reference count for this structure */
IMG_UINT32 ui32RefCount;
-
+ /*
+ * User mode address of start of mapping. This is not necessarily the
+ * first user mode address of the memory area.
+ */
IMG_UINT32 ui32UserVAddr;
-
+ /* Extra entries to support proc filesystem debug info */
#if defined(DEBUG_LINUX_MMAP_AREAS)
const IMG_CHAR *pszName;
#endif
-
+ /* List entry field for MMap list */
struct list_head sMMapItem;
-
+ /* List entry field for per-memory area list */
struct list_head sAreaItem;
}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+/*!
+ *******************************************************************************
+ * @Function Mmap initialisation code
+ ******************************************************************************/
IMG_VOID PVRMMapInit(IMG_VOID);
+/*!
+ *******************************************************************************
+ * @Function Mmap de-initialisation code
+ ******************************************************************************/
IMG_VOID PVRMMapCleanup(IMG_VOID);
+/*!
+ *******************************************************************************
+ * @Function Registers a memory area with the mmap code
+ *
+ * @Input psLinuxMemArea
+ *
+ * @Return PVRSRV_ERROR status
+ ******************************************************************************/
PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @Function Unregisters a memory area from the mmap code
+ *
+ * @Input psLinuxMemArea
+ *
+ * @Return PVRSRV_ERROR status
+ ******************************************************************************/
PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ ******************************************************************************
+ * @Function When a userspace services client, requests to map a memory
+ * area to userspace, this function validates the request and
+ * returns the details that the client must use when calling mmap(2).
+ *
+ * @Input psPerProc Per process data.
+ * @Input hMHandle Handle associated with the memory to map.
+ * This is a (secure) handle to the OS specific
+ * memory handle structure (hOSMemHandle), or
+ * a handle to a structure that contains the
+ * memory handle.
+ * @Output pui32MMapOffset The page aligned offset that the client must
+ * pass to the mmap2 system call.
+ * @Output pui32ByteOffset The real mapping that will be created for the
+ * services client may have a different
+ * size/alignment from it request. This offset
+ * is returned to the client and should be added
+ * to virtual address returned from mmap2 to get
+ * the first address corresponding to its request.
+ * @Output pui32RealByteOffset The size that the mapping will really be,
+ * that the client must also pass to mmap/munmap.
+ *
+ * @Output pui32UserVAddr Pointer to returned user mode address of
+ * mapping.
+ * @Return PVRSRV_ERROR
+ ******************************************************************************/
PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hMHandle,
IMG_UINT32 *pui32RealByteSize,
IMG_UINT32 *pui32UserVAddr);
+/*!
+ *******************************************************************************
+
+ @Function Release mmap data.
+
+ @Input psPerProc Per-process data.
+ @Input hMHandle Memory handle.
+
+ @Output pbMUnmap Flag that indicates whether an munmap is
+ required.
+ @Output pui32RealByteSize Location for size of mapping.
+ @Output pui32UserVAddr User mode address to munmap.
+
+ @Return PVRSRV_ERROR
+ ******************************************************************************/
PVRSRV_ERROR
PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined (SUPPORT_SID_INTERFACE)
IMG_UINT32 *pui32RealByteSize,
IMG_UINT32 *pui32UserVAddr);
+/*!
+ *******************************************************************************
+ * @Function driver mmap entry point
+ *
+ * @Input pFile : user file structure
+ *
+ * @Input ps_vma : vm area structure
+ *
+ * @Return 0 for success, -errno for failure.
+ ******************************************************************************/
int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
-#endif
+#endif /* __MMAP_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux module setup
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
#endif
#endif
-#if defined(SUPPORT_DRI_DRM)
+#if defined(SUPPORT_DRI_DRM) && !defined(SUPPORT_DRI_DRM_PLUGIN)
#define PVR_MOD_STATIC
#else
-
+ /*
+ * For LDM drivers, define PVR_LDM_MODULE to indicate generic LDM
+ * support is required, besides indicating the exact support
+ * required (e.g. platform, or PCI device).
+ */
#if defined(LDM_PLATFORM)
#define PVR_LDM_PLATFORM_MODULE
+ #define PVR_LDM_DEVICE_CLASS
#define PVR_LDM_MODULE
#else
#if defined(LDM_PCI)
+ #define PVR_LDM_DEVICE_CLASS
#define PVR_LDM_PCI_MODULE
#define PVR_LDM_MODULE
+ #else
+ #if defined(SYS_SHARES_WITH_3PKM)
+ #define PVR_LDM_DEVICE_CLASS
+ #endif
#endif
#endif
#define PVR_MOD_STATIC static
#if defined(PVR_LDM_PLATFORM_MODULE)
#include <linux/platform_device.h>
-#endif
+#endif /* PVR_LDM_PLATFORM_MODULE */
#if defined(PVR_LDM_PCI_MODULE)
#include <linux/pci.h>
-#endif
+#endif /* PVR_LDM_PCI_MODULE */
+
+#if defined(PVR_LDM_DEVICE_CLASS)
+#include <linux/device.h>
+#endif /* PVR_LDM_DEVICE_CLASS */
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
#include <asm/uaccess.h>
#include "private_data.h"
#include "lock.h"
#include "linkage.h"
+#include "buffer_manager.h"
#if defined(SUPPORT_DRI_DRM)
#include "pvr_drm.h"
#endif
-#define DRVNAME PVRSRV_MODNAME
+/*
+ * DRVNAME is the name we use to register our driver.
+ * DEVNAME is the name we use to register actual device nodes.
+ */
+#if defined(PVR_LDM_MODULE)
+//#define DRVNAME PVR_LDM_DRIVER_REGISTRATION_NAME
+#define DRVNAME PVRSRV_MODNAME
+#endif
#define DEVNAME PVRSRV_MODNAME
#if defined(SUPPORT_DRI_DRM)
#define PRIVATE_DATA(pFile) ((pFile)->private_data)
#endif
+/*
+ * This is all module configuration stuff required by the linux kernel.
+ */
MODULE_SUPPORTED_DEVICE(DEVNAME);
#if defined(PVRSRV_NEED_PVR_DPF)
extern IMG_UINT32 gPVRDebugLevel;
module_param(gPVRDebugLevel, uint, 0644);
MODULE_PARM_DESC(gPVRDebugLevel, "Sets the level of debug output (default 0x7)");
-#endif
+#endif /* defined(PVRSRV_NEED_PVR_DPF) */
+
+#if defined(CONFIG_ION_OMAP)
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+extern struct ion_device *omap_ion_device;
+struct ion_client *gpsIONClient;
+EXPORT_SYMBOL(gpsIONClient);
+#endif /* defined(CONFIG_ION_OMAP) */
-
+/* PRQA S 3207 2 */ /* ignore 'not used' warning */
EXPORT_SYMBOL(PVRGetDisplayClassJTable);
EXPORT_SYMBOL(PVRGetBufferClassJTable);
-#if defined(PVR_LDM_MODULE)
+#if defined(PVR_LDM_DEVICE_CLASS) && !defined(SUPPORT_DRI_DRM)
+/*
+ * Device class used for /sys entries (and udev device node creation)
+ */
static struct class *psPvrClass;
#endif
#if !defined(SUPPORT_DRI_DRM)
+/*
+ * This is the major number we use for all nodes in /dev.
+ */
static int AssignedMajorNumber;
+/*
+ * These are the operations that will be associated with the device node
+ * we create.
+ *
+ * With gcc -W, specifying only the non-null members produces "missing
+ * initializer" warnings.
+*/
static int PVRSRVOpen(struct inode* pInode, struct file* pFile);
static int PVRSRVRelease(struct inode* pInode, struct file* pFile);
PVRSRV_LINUX_MUTEX gPVRSRVLock;
+/* PID of process being released */
IMG_UINT32 gui32ReleasePID;
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
#if defined(PVR_LDM_PLATFORM_MODULE)
#define LDM_DEV struct platform_device
#define LDM_DRV struct platform_driver
-#endif
+#endif /*PVR_LDM_PLATFORM_MODULE */
#if defined(PVR_LDM_PCI_MODULE)
#define LDM_DEV struct pci_dev
#define LDM_DRV struct pci_driver
-#endif
+#endif /* PVR_LDM_PCI_MODULE */
+/*
+ * This is the driver interface we support.
+ */
#if defined(PVR_LDM_PLATFORM_MODULE)
static int PVRSRVDriverRemove(LDM_DEV *device);
static int PVRSRVDriverProbe(LDM_DEV *device);
static int PVRSRVDriverResume(LDM_DEV *device);
#if defined(PVR_LDM_PCI_MODULE)
+/* This structure is used by the Linux module code */
struct pci_device_id powervr_id_table[] __devinitdata = {
{PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID)},
#if defined (SYS_SGX_DEV1_DEVICE_ID)
};
#endif
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverProbe
+
+ @Description
+
+ See whether a given device is really one we can drive. The platform bus
+ handler has already established that we should be able to service this device
+ because of the name match. We probably don't need to do anything else.
+
+ @input pDevice - the device for which a probe is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
#if defined(PVR_LDM_PLATFORM_MODULE)
static int PVRSRVDriverProbe(LDM_DEV *pDevice)
#endif
PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice));
-#if 0
-
+#if 0 /* INTEGRATION_POINT */
+ /* Some systems require device-specific system initialisation.
+ * E.g. this lets the OS track a device's dependencies on various
+ * system hardware.
+ *
+ * Note: some systems use this to enable HW that SysAcquireData
+ * will depend on, therefore it must be called first.
+ */
if (PerDeviceSysInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
{
return -EINVAL;
}
#endif
-
+ /* SysInitialise only designed to be called once.
+ */
psSysData = SysAcquireDataNoCheck();
- if ( psSysData == IMG_NULL)
+ if (psSysData == IMG_NULL)
{
gpsPVRLDMDev = pDevice;
-
if (SysInitialise() != PVRSRV_OK)
{
return -ENODEV;
}
}
+#if defined(CONFIG_ION_OMAP)
+ gpsIONClient = ion_client_create(omap_ion_device,
+ 1 << ION_HEAP_TYPE_CARVEOUT |
+ 1 << OMAP_ION_HEAP_TYPE_TILER,
+ "pvr");
+ if (IS_ERR_OR_NULL(gpsIONClient))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDriverProbe: Couldn't create ion client"));
+ return PTR_ERR(gpsIONClient);
+ }
+#endif /* defined(CONFIG_ION_OMAP) */
+
return 0;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverRemove
+
+ @Description
+
+ This call is the opposite of the probe call: it is called when the device is
+ being removed from the driver's control. See the file $KERNELDIR/drivers/
+ base/bus.c:device_release_driver() for the call to this function.
+
+ This is the correct place to clean up anything our driver did while it was
+ asoociated with the device.
+
+ @input pDevice - the device for which driver detachment is happening
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
#if defined (PVR_LDM_PLATFORM_MODULE)
static int PVRSRVDriverRemove(LDM_DEV *pDevice)
#endif
PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
+#if defined(CONFIG_ION_OMAP)
+ ion_client_destroy(gpsIONClient);
+ gpsIONClient = IMG_NULL;
+#endif
+
SysAcquireData(&psSysData);
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
gpsPVRLDMDev = IMG_NULL;
-#if 0
+#if 0 /* INTEGRATION_POINT */
+ /* See previous integration point for details. */
if (PerDeviceSysDeInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
{
return -EINVAL;
return;
#endif
}
-#endif
+#endif /* defined(PVR_LDM_MODULE) */
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+static PVRSRV_LINUX_MUTEX gsPMMutex;
+static IMG_BOOL bDriverIsSuspended;
+static IMG_BOOL bDriverIsShutdown;
+#endif
+
#if defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV)
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverShutdown
+
+ @Description
+
+ Suspend device operation for system shutdown. This is called as part of the
+ system halt/reboot process. The driver is put into a quiescent state by
+ setting the power state to D3.
+
+ @input pDevice - the device for which shutdown is requested
+
+ @Return nothing
+
+*****************************************************************************/
+#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
+ !defined(SUPPORT_DRI_DRM_PLUGIN)
+void PVRSRVDriverShutdown(struct drm_device *pDevice)
+#else
PVR_MOD_STATIC void PVRSRVDriverShutdown(LDM_DEV *pDevice)
+#endif
{
PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
- (void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+ LinuxLockMutex(&gsPMMutex);
+
+ if (!bDriverIsShutdown && !bDriverIsSuspended)
+ {
+ /*
+ * Take the bridge mutex, and never release it, to stop
+ * processes trying to use the driver after it has been
+ * shutdown.
+ */
+ LinuxLockMutex(&gPVRSRVLock);
+
+ (void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+ }
+
+ bDriverIsShutdown = IMG_TRUE;
+
+ /* The bridge mutex is held on exit */
+ LinuxUnLockMutex(&gsPMMutex);
}
-#endif
+#endif /* defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV) */
#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
-#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV)
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverSuspend
+
+ @Description
+
+ For 2.6 kernels:
+ Suspend device operation. We always get three calls to this regardless of
+ the state (D1-D3) chosen. The order is SUSPEND_DISABLE, SUSPEND_SAVE_STATE
+ then SUSPEND_POWER_DOWN. We take action as soon as we get the disable call,
+ the other states not being handled by us yet.
+
+ For MontaVista 2.4 kernels:
+ This call gets made once only when someone does something like
+
+ # echo -e -n "suspend powerdown 0" >/sys.devices/legacy/pvrsrv0/power
+
+ The 3rd, numeric parameter (0) in the above has no relevence and is not
+ passed into us. The state parameter is always zero and the level parameter
+ is always SUSPEND_POWER_DOWN. Vive la difference!
+
+ @input pDevice - the device for which resume is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
+ !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(SUPPORT_DRM_MODESET)
+int PVRSRVDriverSuspend(struct pci_dev *pDevice, pm_message_t state)
+#else
int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
+#endif
#else
PVR_MOD_STATIC int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state)
#endif
{
+ int res = 0;
#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice));
- if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+ LinuxLockMutex(&gsPMMutex);
+
+ if (!bDriverIsSuspended && !bDriverIsShutdown)
{
- return -EINVAL;
+ LinuxLockMutex(&gPVRSRVLock);
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) == PVRSRV_OK)
+ {
+ /* The bridge mutex will be held until we resume */
+ bDriverIsSuspended = IMG_TRUE;
+ }
+ else
+ {
+ LinuxUnLockMutex(&gPVRSRVLock);
+ res = -EINVAL;
+ }
}
+
+ LinuxUnLockMutex(&gsPMMutex);
#endif
- return 0;
+ return res;
}
-#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV)
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverResume
+
+ @Description
+
+ Resume device operation following a lull due to earlier suspension. It is
+ implicit we're returning to D0 (fully operational) state. We always get three
+ calls to this using level thus: RESUME_POWER_ON, RESUME_RESTORE_STATE then
+ RESUME_ENABLE. On 2.6 kernels We don't do anything until we get the enable
+ call; on the MontaVista set-up we only ever get the RESUME_POWER_ON call.
+
+ @input pDevice - the device for which resume is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
+ !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(SUPPORT_DRM_MODESET)
+int PVRSRVDriverResume(struct pci_dev *pDevice)
+#else
int PVRSRVDriverResume(struct drm_device *pDevice)
+#endif
#else
PVR_MOD_STATIC int PVRSRVDriverResume(LDM_DEV *pDevice)
#endif
{
+ int res = 0;
#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
- if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+ LinuxLockMutex(&gsPMMutex);
+
+ if (bDriverIsSuspended && !bDriverIsShutdown)
{
- return -EINVAL;
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+ {
+ bDriverIsSuspended = IMG_FALSE;
+ LinuxUnLockMutex(&gPVRSRVLock);
+ }
+ else
+ {
+ /* The bridge mutex is not released on failure */
+ res = -EINVAL;
+ }
}
+
+ LinuxUnLockMutex(&gsPMMutex);
#endif
- return 0;
+ return res;
}
-#endif
+#endif /* defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM) */
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)
+/*
+ * If PVR_LDM_PCI_MODULE is defined (and PVR_MANUAL_POWER_CONTROL is *NOT* defined),
+ * the device can be suspended and resumed without suspending/resuming the
+ * system, by writing values into the power/state sysfs file for the device.
+ * To suspend:
+ * echo -n 2 > power/state
+ * To Resume:
+ * echo -n 0 > power/state
+ *
+ * The problem with this approach is that the device is usually left
+ * powered up; it is the responsibility of the bus driver to remove
+ * the power.
+ *
+ * Defining PVR_MANUAL_POWER_CONTROL is intended to make it easier to
+ * debug power management issues, especially when power is really removed
+ * from the device. It is easier to debug the driver if it is not being
+ * suspended/resumed with the rest of the system.
+ *
+ * When PVR_MANUAL_POWER_CONTROL is defined, the following proc entry is
+ * created:
+ * /proc/pvr/power_control
+ * The driver suspend/resume entry points defined below no longer suspend or
+ * resume the device. To suspend the device, type the following:
+ * echo 2 > /proc/pvr/power_control
+ * To resume the device, type:
+ * echo 0 > /proc/pvr/power_control
+ *
+ * The following example shows how to suspend/resume the device independently
+ * of the rest of the system.
+ * Suspend the device:
+ * echo 2 > /proc/pvr/power_control
+ * Suspend the system. Then you should be able to suspend and resume
+ * as normal. To resume the device type the following:
+ * echo 0 > /proc/pvr/power_control
+ */
+
IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
{
IMG_CHAR data_buffer[2];
#endif
+/*!
+******************************************************************************
+
+ @Function PVRSRVOpen
+
+ @Description
+
+ Release access the PVR services node - called when a file is closed, whether
+ at exit or using close(2) system call.
+
+ @input pInode - the inode for the file being openeded
+
+ @input pFile - the file handle data for the actual file being opened
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
#if defined(SUPPORT_DRI_DRM)
int PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
#else
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRelease
+
+ @Description
+
+ Release access the PVR services node - called when a file is closed, whether
+ at exit or using close(2) system call.
+
+ @input pInode - the inode for the file being released
+
+ @input pFile - the file handle data for the actual file being released
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
#if defined(SUPPORT_DRI_DRM)
void PVRSRVRelease(void *pvPrivData)
#else
#endif
{
PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ int err = 0;
LinuxLockMutex(&gPVRSRVLock);
list_del(&psPrivateData->sDRMAuthListItem);
#endif
-
+ if(psPrivateData->hKernelMemInfo)
+ {
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ /* Look up the meminfo we just exported */
+ if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psPrivateData->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__));
+ err = -EFAULT;
+ goto err_unlock;
+ }
+
+ /* Tell the XProc about the export if required */
+ if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+ {
+ BM_XProcIndexRelease(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+ }
+
+ /* This drops the psMemInfo refcount bumped on export */
+ if(FreeMemCallBackCommon(psKernelMemInfo, 0,
+ PVRSRV_FREE_CALLBACK_ORIGIN_EXTERNAL) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: FreeMemCallBackCommon failed", __FUNCTION__));
+ err = -EFAULT;
+ goto err_unlock;
+ }
+ }
+
+ /* Usually this is the same as OSGetCurrentProcessIDKM(),
+ * but not necessarily (e.g. fork(), child closes last..)
+ */
gui32ReleasePID = psPrivateData->ui32OpenPID;
PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID);
gui32ReleasePID = 0;
psPrivateData, psPrivateData->hBlockAlloc);
#if !defined(SUPPORT_DRI_DRM)
- PRIVATE_DATA(pFile) = IMG_NULL;
+ PRIVATE_DATA(pFile) = IMG_NULL; /*nulling shared pointer*/
#endif
}
+err_unlock:
LinuxUnLockMutex(&gPVRSRVLock);
-
-#if !defined(SUPPORT_DRI_DRM)
- return 0;
+#if defined(SUPPORT_DRI_DRM)
+ return;
+#else
+ return err;
#endif
}
+/*!
+******************************************************************************
+
+ @Function PVRCore_Init
+
+ @Description
+
+ Insert the driver into the kernel.
+
+ The device major number is allocated by the kernel dynamically. This means
+ that the device node (nominally /dev/pvrsrv) will need to be re-made at boot
+ time if the number changes between subsequent loads of the module. While the
+ number often stays constant between loads this is not guaranteed. The node
+ is made as root on the shell with:
+
+ mknod /dev/pvrsrv c nnn 0
+
+ where nnn is the major number found in /proc/devices for DEVNAME and also
+ reported by the PVR_DPF() - look at the boot log using dmesg' to see this).
+
+ Currently the auto-generated script /etc/init.d/rc.pvr handles creation of
+ the device. In other environments the device may be created either through
+ devfs or sysfs.
+
+ Readable proc-filesystem entries under /proc/pvr are created with
+ CreateProcEntries(). These can be read at runtime to get information about
+ the device (eg. 'cat /proc/pvr/vm')
+
+ __init places the function in a special memory section that the kernel frees
+ once the function has been run. Refer also to module_init() macro call below.
+
+ @input none
+
+ @Return none
+
+*****************************************************************************/
#if defined(SUPPORT_DRI_DRM)
int PVRCore_Init(void)
#else
int error;
#if !defined(PVR_LDM_MODULE)
PVRSRV_ERROR eError;
-#else
+#endif
+#if !defined(SUPPORT_DRI_DRM) && defined(PVR_LDM_DEVICE_CLASS)
struct device *psDev;
#endif
#if !defined(SUPPORT_DRI_DRM)
-
+ /*
+ * Must come before attempting to print anything via Services.
+ * For DRM, the initialisation will already have been done.
+ */
PVRDPFInit();
#endif
PVR_TRACE(("PVRCore_Init"));
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+ LinuxInitMutex(&gsPMMutex);
+#endif
LinuxInitMutex(&gPVRSRVLock);
if (CreateProcEntries ())
#if defined(PVR_LDM_MODULE)
-#if defined(PVR_LDM_PLATFORM_MODULE)
+#if defined(PVR_LDM_PLATFORM_MODULE) || defined(SUPPORT_DRI_DRM_PLUGIN)
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;
}
#endif
-#endif
+#endif /* PVR_LDM_PLATFORM_MODULE */
#if defined(PVR_LDM_PCI_MODULE)
if ((error = pci_register_driver(&powervr_driver)) != 0)
goto init_failed;
}
-#endif
+#endif /* PVR_LDM_PCI_MODULE */
+#endif /* defined(PVR_LDM_MODULE) */
-#else
-
+#if !defined(PVR_LDM_MODULE)
+ /*
+ * Drivers using LDM, will call SysInitialise in the probe/attach code
+ */
if ((eError = SysInitialise()) != PVRSRV_OK)
{
error = -ENODEV;
#endif
goto init_failed;
}
-#endif
+#endif /* !defined(PVR_LDM_MODULE) */
#if !defined(SUPPORT_DRI_DRM)
AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
}
PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
-#endif
-#if defined(PVR_LDM_MODULE)
-
+#if defined(PVR_LDM_DEVICE_CLASS)
+ /*
+ * This code (using GPL symbols) facilitates automatic device
+ * node creation on platforms with udev (or similar).
+ */
psPvrClass = class_create(THIS_MODULE, "pvr");
if (IS_ERR(psPvrClass))
psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
NULL,
-#endif
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) */
DEVNAME);
if (IS_ERR(psDev))
{
error = -EBUSY;
goto destroy_class;
}
-#endif
+#endif /* defined(PVR_LDM_DEVICE_CLASS) */
+#endif /* !defined(SUPPORT_DRI_DRM) */
return 0;
-#if defined(PVR_LDM_MODULE)
+#if !defined(SUPPORT_DRI_DRM)
+#if defined(PVR_LDM_DEVICE_CLASS)
destroy_class:
class_destroy(psPvrClass);
unregister_device:
- unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME);
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME);
#endif
-#if !defined(SUPPORT_DRI_DRM)
sys_deinit:
#endif
#if defined(PVR_LDM_MODULE)
platform_driver_unregister(&powervr_driver);
#endif
-#else
-
+#else /* defined(PVR_LDM_MODULE) */
+ /* LDM drivers call SysDeinitialise during PVRSRVDriverRemove */
{
SYS_DATA *psSysData;
(void) SysDeinitialise(psSysData);
}
}
-#endif
+#endif /* defined(PVR_LDM_MODULE) */
init_failed:
PVRMMapCleanup();
LinuxMMCleanup();
return error;
-}
+} /*PVRCore_Init*/
+
+
+/*!
+*****************************************************************************
+
+ @Function PVRCore_Cleanup
+
+ @Description
+
+ Remove the driver from the kernel.
+
+ There's no way we can get out of being unloaded other than panicking; we
+ just do everything and plough on regardless of error.
+
+ __exit places the function in a special memory section that the kernel frees
+ once the function has been run. Refer also to module_exit() macro call below.
+ Note that the for LDM on MontaVista kernels, the positioning of the driver
+ de-registration is the opposite way around than would be suggested by the
+ registration case or the 2,6 kernel case. This is the correct way to do it
+ and the kernel panics if you change it. You have been warned.
+ @input none
+
+ @Return none
+
+*****************************************************************************/
#if defined(SUPPORT_DRI_DRM)
void PVRCore_Cleanup(void)
#else
SysAcquireData(&psSysData);
#endif
-#if defined(PVR_LDM_MODULE)
+#if !defined(SUPPORT_DRI_DRM)
+
+#if defined(PVR_LDM_DEVICE_CLASS)
device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
class_destroy(psPvrClass);
#endif
-#if !defined(SUPPORT_DRI_DRM)
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
if (
-#endif
- unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME)
+#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME)
#if !(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
;
-#else
+#else /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */
)
{
PVR_DPF((PVR_DBG_ERROR," can't unregister device major %d", AssignedMajorNumber));
}
-#endif
-#endif
+#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */
+#endif /* !defined(SUPPORT_DRI_DRM) */
#if defined(PVR_LDM_MODULE)
platform_driver_unregister(&powervr_driver);
#endif
-#else
+#else /* defined(PVR_LDM_MODULE) */
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
if (gPVRPowerLevel != 0)
{
}
}
#endif
-
+ /* LDM drivers call SysDeinitialise during PVRSRVDriverRemove */
(void) SysDeinitialise(psSysData);
-#endif
+#endif /* defined(PVR_LDM_MODULE) */
PVRMMapCleanup();
PVR_TRACE(("PVRCore_Cleanup: unloading"));
}
+/*
+ * These macro calls define the initialisation and removal functions of the
+ * driver. Although they are prefixed `module_', they apply when compiling
+ * statically as well; in both cases they define the function the kernel will
+ * run to start/stop the driver.
+*/
#if !defined(SUPPORT_DRI_DRM)
module_init(PVRCore_Init);
module_exit(PVRCore_Cleanup);
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux mutex interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
#include <linux/errno.h>
}
-#else
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */
IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
{
if(down_interruptible(&psPVRSRVMutex->sSemaphore) == -EINTR)
{
-
+ /* The process was sent a signal while waiting for the semaphore
+ * (e.g. a kill signal from userspace)
+ */
return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR;
}else{
atomic_dec(&psPVRSRVMutex->Count);
return (IMG_BOOL)iCount;
}
-#endif
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux mutex interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
#ifndef __INCLUDED_LINUX_MUTEX_H_
#define __INCLUDED_LINUX_MUTEX_H_
typedef struct mutex PVRSRV_LINUX_MUTEX;
-#else
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */
typedef struct {
struct semaphore sSemaphore;
-
+ /* since Linux's struct semaphore is intended to be
+ * opaque we don't poke inside for the count and
+ * instead we track it outselves. (So we can implement
+ * LinuxIsLockedMutex)
+ */
atomic_t Count;
}PVRSRV_LINUX_MUTEX;
extern IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
-#endif
+#endif /* __INCLUDED_LINUX_MUTEX_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux memory interface support functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
static IMG_VOID
PVRLinuxX86PATProbe(IMG_VOID)
{
-
- if (cpu_has_pat)
+ /*
+ * cpu_has_pat indicates whether PAT support is available on the CPU,
+ * but doesn't indicate if it has been enabled.
+ */
+ if (cpu_has_pat) /* PRQA S 3335 */ /* ignore 'no function declared' */
{
u64 pat;
IMG_UINT pat_index;
IMG_UINT pat_entry;
PVR_TRACE(("%s: PAT available", __FUNCTION__));
-
+ /*
+ * There is no Linux API for finding out if write combining
+ * is avaialable through the PAT, so we take the direct
+ * approach, and see if the PAT MSR contains a write combining
+ * entry.
+ */
rdmsrl(MSR_IA32_CR_PAT, pat);
PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32)));
PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat)));
{
PVR_TRACE(("%s: Write combining not available", __FUNCTION__));
}
-#else
+#else /* defined(SUPPORT_LINUX_X86_WRITECOMBINE) */
PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__));
-#endif
-#endif
+#endif /* defined(SUPPORT_LINUX_X86_WRITECOMBINE) */
+#endif /* DEBUG */
}
pgprot_t
pvr_pgprot_writecombine(pgprot_t prot)
{
-
-
+ /*
+ * It would be worth checking from time to time to see if a
+ * pgprot_writecombine function (or similar) is introduced on Linux for
+ * x86 processors. If so, this function, and PVRLinuxX86PATProbe can be
+ * removed, and a macro used to select between pgprot_writecombine and
+ * pgprot_noncached, dpending on the value for of
+ * SUPPORT_LINUX_X86_WRITECOMBINE.
+ */
+ /* PRQA S 0481,0482 2 */ /* scalar expressions */
return (g_write_combining_available) ?
__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot);
}
-#endif
+#endif /* defined(SUPPORT_LINUX_X86_PAT) */
IMG_VOID
PVRLinuxMUtilsInit(IMG_VOID)
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Memory management support utils
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares various memory management support functions
+ for Linux.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __IMG_LINUX_MUTILS_H__
#define __IMG_LINUX_MUTILS_H__
IMG_VOID PVRLinuxMUtilsInit(IMG_VOID);
-#endif
+#endif /* __IMG_LINUX_MUTILS_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Environment related functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
#include "event.h"
#include "linkage.h"
#include "pvr_uaccess.h"
+#include "lock.h"
+
+#if defined (SUPPORT_ION)
+#include "ion.h"
+#endif
+
+#if defined (CONFIG_X86_PAE)
+#error Physical Address Extension not supported with the driver
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait)
#endif
-//#if defined(PVR_LINUX_USING_WORKQUEUES) && !defined(CONFIG_PREEMPT)
+#if defined(PVR_LINUX_USING_WORKQUEUES) && !defined(CONFIG_PREEMPT)
+/*
+ * Services spins at certain points waiting for events (e.g. swap
+ * chain destrucion). If those events rely on workqueues running,
+ * it needs to be possible to preempt the waiting thread.
+ * Removing the need for CONFIG_PREEMPT will require adding preemption
+ * points at various points in Services.
+ */
//#error "A preemptible Linux kernel is required when using workqueues"
-//#endif
+#endif
#if defined(EMULATOR)
#define EVENT_OBJECT_TIMEOUT_MS (2000)
#else
#define EVENT_OBJECT_TIMEOUT_MS (100)
-#endif
+#endif /* EMULATOR */
#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
if (ui32Size > PAGE_SIZE)
{
-
+ /* Try to allocate the memory using vmalloc */
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
*ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename, ui32Line);
#else
return lAddr >= VMALLOC_START && lAddr < VMALLOC_END;
}
-#endif
+#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)) */
#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
IMG_UINT32 ui32Size,
IMG_UINT32 ui32PageSize,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_HANDLE hBMHandle,
IMG_VOID **ppvCpuVAddr,
IMG_HANDLE *phOSMemHandle)
{
PVR_UNREFERENCED_PARAMETER(ui32PageSize);
#if 0
-
+ /* For debug: force all OSAllocPages allocations to have a kernel
+ * virtual address */
if(ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS)
{
ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
}
#endif
+ if(ui32AllocFlags & PVRSRV_MEM_ION)
+ {
+ /* We'll only see HAP_SINGLE_PROCESS with MEM_ION */
+ BUG_ON((ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) != PVRSRV_HAP_SINGLE_PROCESS);
+
+ psLinuxMemArea = NewIONLinuxMemArea(ui32Size, ui32AllocFlags,
+ pvPrivData, ui32PrivDataLength);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ PVRMMapRegisterArea(psLinuxMemArea);
+ goto ExitSkipSwitch;
+ }
+
switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
{
case PVRSRV_HAP_KERNEL_ONLY:
}
case PVRSRV_HAP_SINGLE_PROCESS:
{
-
-
+ /* Currently PVRSRV_HAP_SINGLE_PROCESS implies that we dont need a
+ * kernel virtual mapping, but will need a user space virtual mapping */
+
psLinuxMemArea = NewAllocPagesLinuxMemArea(ui32Size, ui32AllocFlags);
if(!psLinuxMemArea)
{
case PVRSRV_HAP_MULTI_PROCESS:
{
-
+ /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel
+ * virtual mapping and potentially multiple user space virtual
+ * mappings: Note: these eat into our limited kernel virtual
+ * address space. */
+
#if defined(VIVT_CACHE) || defined(__sh__)
-
+ /* ARM9 caches are tagged with virtual pages, not physical. As we are going to
+ * share this memory in different address spaces, we don't want it to be cached.
+ * ARM11 has physical tagging, so we can cache this memory without fear of virtual
+ * address aliasing in the TLB, as long as the kernel supports cache colouring for
+ * VIPT architectures. */
ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
#endif
psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
return PVRSRV_ERROR_INVALID_PARAMS;
}
+ /*
+ In case of sparse mapping we need to handle back to the BM as it
+ knows the mapping info
+ */
+ if (ui32AllocFlags & PVRSRV_MEM_SPARSE)
+ {
+ psLinuxMemArea->hBMHandle = hBMHandle;
+ }
+
+ExitSkipSwitch:
*ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
*phOSMemHandle = psLinuxMemArea;
}
*phOSMemHandleRet = psLinuxMemArea;
-
+ /* KERNEL_ONLY areas are never mmapable. */
if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
{
return PVRSRV_OK;
}
+IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ PVR_ASSERT(psLinuxMemArea);
+
+ if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV)
+ return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+ return IMG_FALSE;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function OSMemCopy
+
+ @Description Copies memory around
+ @Input pvDst - pointer to dst
+ @Output pvSrc - pointer to src
+ @Input ui32Size - bytes to copy
+
+ @Return none
+
+******************************************************************************/
IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
{
#if defined(USE_UNOPTIMISED_MEMCPY)
}
+/*!
+******************************************************************************
+
+ @Function OSMemSet
+
+ @Description Function that does the same as the C memset() functions
+
+ @Modified *pvDest : pointer to start of buffer to be set
+
+ @Input ui8Value: value to set each byte to
+
+ @Input ui32Size : number of bytes to set
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
{
#if defined(USE_UNOPTIMISED_MEMSET)
}
+/*!
+******************************************************************************
+ @Function OSStringCopy
+ @Description strcpy
+******************************************************************************/
IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
{
return (strcpy(pszDest, pszSrc));
}
+/*!
+******************************************************************************
+ @Function OSSNPrintf
+ @Description snprintf
+******************************************************************************/
IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFormat, ...)
{
va_list argList;
return iCount;
}
+/*!
+******************************************************************************
+
+ @Function OSBreakResourceLock
+
+ @Description unlocks an OS dependant resource
+
+ @Input phResource - pointer to OS dependent resource structure
+ @Input ui32ID - Lock value to look for
+
+ @Return
+
+******************************************************************************/
IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
{
volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
}
+/*!
+******************************************************************************
+
+ @Function OSCreateResource
+
+ @Description creates a OS dependant resource object
+
+ @Input phResource - pointer to OS dependent resource
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource)
{
psResource->ui32ID = 0;
}
+/*!
+******************************************************************************
+
+ @Function OSDestroyResource
+
+ @Description destroys an OS dependant resource object
+
+ @Input phResource - pointer to OS dependent resource
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource)
{
OSBreakResourceLock (psResource, psResource->ui32ID);
}
+/*!
+******************************************************************************
+
+ @Function OSInitEnvData
+
+ @Description Allocates space for env specific data
+
+ @Input ppvEnvSpecificData - pointer to pointer in which to return
+ allocated data.
+ @Input ui32MMUMode - MMU mode.
+
+ @Return nothing
+
+******************************************************************************/
PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData)
{
ENV_DATA *psEnvData;
PVRSRV_ERROR eError;
-
+ /* allocate env specific data */
eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), (IMG_VOID **)&psEnvData, IMG_NULL,
"Environment Data");
if (eError != PVRSRV_OK)
if (eError != PVRSRV_OK)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return eError;
}
-
+ /* ISR installation flags */
psEnvData->bMISRInstalled = IMG_FALSE;
psEnvData->bLISRInstalled = IMG_FALSE;
-
+ /* copy structure back */
*ppvEnvSpecificData = psEnvData;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSDeInitEnvData
+
+ @Description frees env specific data memory
+
+ @Input pvEnvSpecificData - pointer to private structure
+
+ @Return PVRSRV_OK on success else PVRSRV_ERROR_OUT_OF_MEMORY
+
+******************************************************************************/
PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
{
ENV_DATA *psEnvData = (ENV_DATA*)pvEnvSpecificData;
psEnvData->pvBridgeData = IMG_NULL;
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSReleaseThreadQuanta
+ @Description
+ Releases thread quanta
+
+ @Return nothing
+
+******************************************************************************/
IMG_VOID OSReleaseThreadQuanta(IMG_VOID)
{
schedule();
}
+/*!
+******************************************************************************
+
+ @Function OSClockus
+
+ @Description
+ This function returns the clock in microseconds
+ @Input void
+
+ @Return - clock (us)
+
+******************************************************************************/
IMG_UINT32 OSClockus(IMG_VOID)
{
IMG_UINT32 time, j = jiffies;
}
+/*!
+******************************************************************************
+
+ @Function OSFuncHighResTimerCreate
+
+ @Description
+ This function creates a high res timer who's handle is returned
+ @Input nothing
+
+ @Return handle
+
+******************************************************************************/
IMG_HANDLE OSFuncHighResTimerCreate(IMG_VOID)
{
-
+ /* We don't need a handle, but we must return non-NULL */
return (IMG_HANDLE) 1;
}
+/*!
+******************************************************************************
+
+ @Function OSFuncHighResTimerGetus
+ @Description
+ This function returns the current timestamp in us
+
+ @Input nothing
+
+ @Return handle
+
+******************************************************************************/
IMG_UINT32 OSFuncHighResTimerGetus(IMG_HANDLE hTimer)
{
return (IMG_UINT32) jiffies_to_usecs(jiffies);
}
+/*!
+******************************************************************************
+
+ @Function OSFuncHighResTimerDestroy
+ @Description
+ This function will destroy the high res timer
+
+ @Input nothing
+
+ @Return handle
+
+******************************************************************************/
IMG_VOID OSFuncHighResTimerDestroy(IMG_HANDLE hTimer)
{
PVR_UNREFERENCED_PARAMETER(hTimer);
}
+/*!
+******************************************************************************
+
+ @Function OSGetCurrentProcessIDKM
+
+ @Description Returns handle for current process
+
+ @Return ID of current process
+
+*****************************************************************************/
IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
{
if (in_interrupt())
}
+/*!
+******************************************************************************
+
+ @Function OSGetPageSize
+
+ @Description gets page size
+
+ @Return page size
+
+******************************************************************************/
IMG_UINT32 OSGetPageSize(IMG_VOID)
{
#if defined(__sh__)
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+/*!
+******************************************************************************
+
+ @Function DeviceISRWrapper
+
+ @Description wrapper for Device ISR function to conform to ISR OS interface
+
+ @Return
+
+******************************************************************************/
static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
, struct pt_regs *regs
+/*!
+******************************************************************************
+
+ @Function SystemISRWrapper
+
+ @Description wrapper for System ISR function to conform to ISR OS interface
+
+ @Input Interrupt - NT interrupt object.
+ @Input Context - Context parameter
+
+ @Return
+
+******************************************************************************/
static irqreturn_t SystemISRWrapper(int irq, void *dev_id
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
, struct pt_regs *regs
return bStatus ? IRQ_HANDLED : IRQ_NONE;
#endif
}
+/*!
+******************************************************************************
+
+ @Function OSInstallDeviceLISR
+
+ @Description Installs a Device ISR
+
+ @Input pvSysData
+ @Input ui32Irq - IRQ number
+ @Input pszISRName - ISR name
+ @Input pvDeviceNode - device node contains ISR function and data argument
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
IMG_UINT32 ui32Irq,
IMG_CHAR *pszISRName,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSUninstallDeviceLISR
+
+ @Description Uninstalls a Device ISR
+
+ @Input pvSysData - sysdata
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
}
+/*!
+******************************************************************************
+
+ @Function OSInstallSystemLISR
+
+ @Description Installs a System ISR
+
+ @Input psSysData
+ @Input ui32Irq - IRQ number
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
}
+/*!
+******************************************************************************
+
+ @Function OSUninstallSystemLISR
+
+ @Description Uninstalls a System ISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
}
#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+/*!
+******************************************************************************
+
+ @Function MISRWrapper
+
+ @Description OS dependent MISR wrapper
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
static void MISRWrapper(
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
void *data
}
+/*!
+******************************************************************************
+
+ @Function OSInstallMISR
+
+ @Description Installs an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
}
+/*!
+******************************************************************************
+
+ @Function OSUninstallMISR
+
+ @Description Uninstalls an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
}
+/*!
+******************************************************************************
+
+ @Function OSScheduleMISR
+
+ @Description Schedules an OS dependent MISR
+
+ @Input pvSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
return PVRSRV_OK;
}
-#else
+#else /* defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */
#if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
+/*!
+******************************************************************************
+
+ @Function MISRWrapper
+
+ @Description OS dependent MISR wrapper
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
static void MISRWrapper(
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
void *data
}
+/*!
+******************************************************************************
+
+ @Function OSInstallMISR
+
+ @Description Installs an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
}
+/*!
+******************************************************************************
+
+ @Function OSUninstallMISR
+
+ @Description Uninstalls an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
}
+/*!
+******************************************************************************
+
+ @Function OSScheduleMISR
+
+ @Description Schedules an OS dependent MISR
+
+ @Input pvSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
return PVRSRV_OK;
}
-#else
+#else /* #if defined(PVR_LINUX_MISR_USING_WORKQUEUE) */
+/*!
+******************************************************************************
+
+ @Function MISRWrapper
+
+ @Description OS dependent MISR wrapper
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
static void MISRWrapper(unsigned long data)
{
SYS_DATA *psSysData;
}
+/*!
+******************************************************************************
+
+ @Function OSInstallMISR
+
+ @Description Installs an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
}
+/*!
+******************************************************************************
+
+ @Function OSUninstallMISR
+
+ @Description Uninstalls an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSScheduleMISR
+
+ @Description Schedules an OS dependent MISR
+
+ @Input pvSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
return PVRSRV_OK;
}
-#endif
-#endif
+#endif /* #if defined(PVR_LINUX_MISR_USING_WORKQUEUE) */
+#endif /* #if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */
-#endif
+#endif /* #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) */
IMG_VOID OSPanic(IMG_VOID)
{
#else
#define OS_TAS(p) tas(p)
#endif
+/*!
+******************************************************************************
+
+ @Function OSLockResource
+
+ @Description locks an OS dependant Resource
+
+ @Input phResource - pointer to OS dependent Resource
+ @Input bBlock - do we want to block?
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE *psResource,
IMG_UINT32 ui32ID)
}
+/*!
+******************************************************************************
+
+ @Function OSUnlockResource
+
+ @Description unlocks an OS dependant resource
+
+ @Input phResource - pointer to OS dependent resource structure
+
+ @Return
+
+******************************************************************************/
PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
{
volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
}
+/*!
+******************************************************************************
+
+ @Function OSIsResourceLocked
+
+ @Description tests if resource is locked
+
+ @Input phResource - pointer to OS dependent resource structure
+
+ @Return error status
+
+******************************************************************************/
IMG_BOOL OSIsResourceLocked (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
{
volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
IMG_VOID OSPowerLockUnwrap (IMG_VOID)
{
}
-#endif
+#endif /* SYS_CUSTOM_POWERLOCK_WRAP */
IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE hOSMemHandle,
PVR_ASSERT(hOSMemHandle != IMG_NULL);
-
-
psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
uiByteOffset = (IMG_UINTPTR_T)pvLinAddr - (IMG_UINTPTR_T)LinuxMemAreaToCpuVAddr(psLinuxMemArea);
}
+/*!
+******************************************************************************
+
+ @Function OSMapPhysToLin
+
+ @Description Maps the physical memory into linear addr range
+
+ @Input BasePAddr : physical cpu address
+
+ @Input ui32Bytes - bytes to map
+
+ @Input ui32CacheType - cache type
+
+ @Return : Linear addr of mapping on success, else NULL
+
+ ******************************************************************************/
IMG_VOID *
OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
IMG_UINT32 ui32Bytes,
{
if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
{
-
+ /*
+ * Provide some backwards compatibility, until all callers
+ * have been updated to pass a non-null OSMemHandle pointer.
+ * Such callers must not call OSMapLinToCPUPhys.
+ */
if(phOSMemHandle == IMG_NULL)
{
IMG_VOID *pvIORemapCookie;
return IMG_NULL;
}
+/*!
+******************************************************************************
+ @Function OSUnMapPhysToLin
+ @Description Unmaps memory that was mapped with OSMapPhysToLin
+ @Return TRUE on success, else FALSE
+******************************************************************************/
IMG_BOOL
OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle)
{
- PVR_TRACE(("%s: unmapping %d bytes from %p", __FUNCTION__, ui32Bytes, pvLinAddr));
-
PVR_UNREFERENCED_PARAMETER(ui32Bytes);
if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
return IMG_FALSE;
}
+/*!
+******************************************************************************
+ @Function RegisterExternalMem
+ @Description Registers external memory for user mode mapping
+ @Return TRUE on success, else FALSE, MemHandle out
+******************************************************************************/
static PVRSRV_ERROR
RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
IMG_VOID *pvCPUVAddr,
}
case PVRSRV_HAP_MULTI_PROCESS:
{
-
+ /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel
+ * virtual mapping and potentially multiple user space virtual mappings.
+ * Beware that the kernel virtual address space is a limited resource.
+ */
#if defined(VIVT_CACHE) || defined(__sh__)
-
+ /*
+ * ARM9 caches are tagged with virtual pages, not physical. As we are going to
+ * share this memory in different address spaces, we don't want it to be cached.
+ * ARM11 has physical tagging, so we can cache this memory without fear of virtual
+ * address aliasing in the TLB, as long as the kernel supports cache colouring for
+ * VIPT architectures.
+ */
ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
#endif
psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
}
+/*!
+******************************************************************************
+ @Function OSRegisterMem
+ @Description Registers external memory for user mode mapping
+ @Output phOSMemHandle - handle to registered memory
+ @Return TRUE on success, else FALSE
+******************************************************************************/
PVRSRV_ERROR
OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
IMG_VOID *pvCPUVAddr,
}
+/*!
+******************************************************************************
+ @Function OSUnRegisterMem
+ @Description UnRegisters external memory for user mode mapping
+ @Return TRUE on success, else FALSE
+******************************************************************************/
PVRSRV_ERROR
OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
IMG_UINT32 ui32Bytes,
return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
}
+/*!
+******************************************************************************
+ @Function OSReservePhys
+ @Description Registers physical memory for user mode mapping
+ @Output ppvCpuVAddr
+ @Output phOsMemHandle handle to registered memory
+ @Return TRUE on success, else FALSE
+******************************************************************************/
PVRSRV_ERROR
OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
IMG_UINT32 ui32Bytes,
IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE hBMHandle,
IMG_VOID **ppvCpuVAddr,
IMG_HANDLE *phOSMemHandle)
{
LinuxMemArea *psLinuxMemArea;
#if 0
-
+ /* For debug: force all OSReservePhys reservations to have a kernel
+ * virtual address */
if(ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS)
{
ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
{
case PVRSRV_HAP_KERNEL_ONLY:
{
-
+ /* Currently PVRSRV_HAP_KERNEL_ONLY implies that a kernel virtual
+ * mapping is required for the allocation and no user virtual
+ * mappings are allowed: Note these eat into our limited kernel
+ * virtual address space */
psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
if(!psLinuxMemArea)
{
}
case PVRSRV_HAP_SINGLE_PROCESS:
{
-
+ /* Currently this implies that we dont need a kernel virtual
+ * mapping, but will need a user space virtual mapping */
psLinuxMemArea = NewIOLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
if(!psLinuxMemArea)
{
}
case PVRSRV_HAP_MULTI_PROCESS:
{
-
+ /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel
+ * virtual mapping and potentially multiple user space virtual mappings.
+ * Beware that the kernel virtual address space is a limited resource.
+ */
#if defined(VIVT_CACHE) || defined(__sh__)
-
+ /*
+ * ARM9 caches are tagged with virtual pages, not physical. As we are going to
+ * share this memory in different address spaces, we don't want it to be cached.
+ * ARM11 has physical tagging, so we can cache this memory without fear of virtual
+ * address aliasing in the TLB, as long as the kernel supports cache colouring for
+ * VIPT architectures.
+ */
ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
#endif
psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
return PVRSRV_ERROR_INVALID_FLAGS;
}
+ /*
+ In case of sparse mapping we need to handle back to the BM as it
+ knows the mapping info
+ */
+ if (ui32MappingFlags & PVRSRV_MEM_SPARSE)
+ {
+ PVR_ASSERT(hBMHandle != IMG_NULL);
+ psLinuxMemArea->hBMHandle = hBMHandle;
+ }
+
*phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
*ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ @Function OSUnReservePhys
+ @Description UnRegisters physical memory for user mode mapping
+ @Return TRUE on success, else FALSE
+******************************************************************************/
PVRSRV_ERROR
OSUnReservePhys(IMG_VOID *pvCpuVAddr,
IMG_UINT32 ui32Bytes,
}
+/*!
+******************************************************************************
+ @Function OSBaseAllocContigMemory
+ @Description Allocate a block of contiguous virtual non-paged memory.
+ @Input ui32Size - number of bytes to allocate
+ @Output ppvLinAddr - pointer to variable that will receive the linear address of buffer
+ @Return PVRSRV_OK if allocation successed else returns PVRSRV_ERROR_OUT_OF_MEMORY
+ **************************************************************************/
PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
{
#if !defined(NO_HARDWARE)
return PVRSRV_ERROR_OUT_OF_MEMORY;
#else
+/*
+ * On Linux, the returned virtual address should be used for CPU access,
+ * and not be remapped into the CPU virtual address using ioremap. The fact
+ * that the RAM is being managed by the kernel, and already has a virtual
+ * address, seems to lead to problems when the attributes of the memory are
+ * changed in the ioremap call (such as from cached to non-cached).
+ */
IMG_VOID *pvKernLinAddr;
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
return PVRSRV_OK;
-#endif
+#endif /* !defined(NO_HARDWARE) */
}
+/*!
+******************************************************************************
+ @Function OSBaseFreeContigMemory
+ @Description Frees memory allocated with OSBaseAllocContigMemory
+ @Input LinAddr - pointer to buffer allocated with OSBaseAllocContigMemory
+ **************************************************************************/
PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
{
#if !defined(NO_HARDWARE)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSWriteHWReg
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Offset :
+
+ @input ui32Value :
+
+ @Return none
+
+******************************************************************************/
+
IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
{
#if !defined(NO_HARDWARE)
#if defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+/*!
+******************************************************************************
+
+ @Function OSPCISetDev
+
+ @Description
+
+ Set a PCI device for subsequent use.
+
+ @input pvPCICookie : Pointer to OS specific PCI structure/cookie
+
+ @input eFlags : Flags
+
+ @Return Pointer to PCI device handle
+
+******************************************************************************/
PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags)
{
int err;
return IMG_NULL;
}
- if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */
{
pci_set_master(psPVRPCI->psPCIDev);
}
- if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI) /* PRQA S 3358 */ /* misuse of enums */
{
#if defined(CONFIG_PCI_MSI)
err = pci_enable_msi(psPVRPCI->psPCIDev);
if (err != 0)
{
PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: Couldn't enable MSI (%d)", err));
- psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;
+ psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI; /* PRQA S 1474,3358,4130 */ /* misuse of enums */
}
#else
PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: MSI support not enabled in the kernel"));
#endif
}
-
+ /* Initialise the PCI resource tracking array */
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)
+ @Function OSPCIAcquireDev
+
+ @Description
+
+ Acquire a PCI device for subsequent use.
+
+ @input ui16VendorID : Vendor PCI ID
+
+ @input ui16VendorID : Device PCI ID
+
+ @input eFlags : Flags
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
+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);
}
+/*!
+******************************************************************************
+
+ @Function OSPCIIRQ
+
+ @Description
+
+ Get the interrupt number for the device.
+
+ @input hPVRPCI : PCI device handle
+
+ @input pui32IRQ : Pointer to where the interrupt number should be returned
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
{
PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
return PVRSRV_OK;
}
+/* Functions supported by OSPCIAddrRangeFunc */
enum HOST_PCI_ADDR_RANGE_FUNC
{
HOST_PCI_ADDR_RANGE_FUNC_LEN,
HOST_PCI_ADDR_RANGE_FUNC_RELEASE
};
+/*!
+******************************************************************************
+
+ @Function OSPCIAddrRangeFunc
+
+ @Description
+
+ Internal support function for various address range related functions
+
+ @input eFunc : Function to perform
+
+ @input hPVRPCI : PCI device handle
+
+ @input ui32Index : Address range index
+
+ @Return function dependent
+
+******************************************************************************/
static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
PVRSRV_PCI_DEV_HANDLE hPVRPCI,
IMG_UINT32 ui32Index)
return 0;
}
+/*!
+******************************************************************************
+
+ @Function OSPCIAddrRangeLen
+
+ @Description
+
+ Returns length of a given address range length
+
+ @input hPVRPCI : PCI device handle
+
+ @input ui32Index : Address range index
+
+ @Return Length of address range, or 0 if no such range
+
+******************************************************************************/
IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
{
return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index);
}
+/*!
+******************************************************************************
+
+ @Function OSPCIAddrRangeStart
+
+ @Description
+
+ Returns the start of a given address range
+
+ @input hPVRPCI : PCI device handle
+
+ @input ui32Index : Address range index
+
+ @Return Start of address range, or 0 if no such range
+
+******************************************************************************/
IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
{
return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index);
}
+/*!
+******************************************************************************
+
+ @Function OSPCIAddrRangeEnd
+
+ @Description
+
+ Returns the end of a given address range
+
+ @input hPVRPCI : PCI device handle"ayy
+
+ @input ui32Index : Address range index
+
+ @Return End of address range, or 0 if no such range
+
+******************************************************************************/
IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
{
return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index);
}
+/*!
+******************************************************************************
+
+ @Function OSPCIRequestAddrRange
+
+ @Description
+
+ Request a given address range index for subsequent use
+
+ @input hPVRPCI : PCI device handle
+
+ @input ui32Index : Address range index
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
IMG_UINT32 ui32Index)
{
return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSPCIReleaseAddrRange
+
+ @Description
+
+ Release a given address range that is no longer being used
+
+ @input hPVRPCI : PCI device handle
+
+ @input ui32Index : Address range index
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
{
return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSPCIReleaseDev
+
+ @Description
+
+ Release a PCI device that is no longer being used
+
+ @input hPVRPCI : PCI device handle
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
{
PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
PVR_TRACE(("OSPCIReleaseDev"));
-
+ /* Release all PCI regions that are currently in use */
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
{
if (psPVRPCI->abPCIResourceInUse[i])
}
#if defined(CONFIG_PCI_MSI)
- if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI) /* PRQA S 3358 */ /* misuse of enums */
{
pci_disable_msi(psPVRPCI->psPCIDev);
}
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
- if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */
{
pci_clear_master(psPVRPCI->psPCIDev);
}
pci_disable_device(psPVRPCI->psPCIDev);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID *)psPVRPCI, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSPCISuspendDev
+
+ @Description
+
+ Prepare PCI device to be turned off by power management
+
+ @input hPVRPCI : PCI device handle
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
{
PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
PVR_TRACE(("OSPCISuspendDev"));
-
+ /* Release all PCI regions that are currently in use */
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
{
if (psPVRPCI->abPCIResourceInUse[i])
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSPCIResumeDev
+
+ @Description
+
+ Prepare a PCI device to be resumed by power management
+
+ @input hPVRPCI : PCI device handle
+
+ @input pvPCICookie : Pointer to OS specific PCI structure/cookie
+
+ @input eFlags : Flags
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
{
PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
return PVRSRV_ERROR_PCI_CALL_FAILED;
}
- if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */
pci_set_master(psPVRPCI->psPCIDev);
-
+ /* Restore the PCI resource tracking array */
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
{
if (psPVRPCI->abPCIResourceInUse[i])
return PVRSRV_OK;
}
-#endif
+#endif /* #if defined(CONFIG_PCI) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) */
#define OS_MAX_TIMERS 8
+/* Timer callback strucure used by OSAddTimer */
typedef struct TIMER_CALLBACK_DATA_TAG
{
IMG_BOOL bInUse;
#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
DEFINE_MUTEX(sTimerStructLock);
#else
-
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+/* The lock is used to control access to sTimers */
+/* PRQA S 0671,0685 1 */ /* C99 macro not understood by QAC */
static spinlock_t sTimerStructLock = SPIN_LOCK_UNLOCKED;
+#else
+static DEFINE_SPINLOCK(sTimerStructLock);
+#endif
#endif
static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
if (!psTimerCBData->bActive)
return;
-
+ /* call timer callback */
psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
-
+ /* reset timer */
mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
}
+/*!
+******************************************************************************
+
+ @Function OSTimerCallbackWrapper
+
+ @Description
+
+ OS specific timer callback wrapper function
+
+ @Input ui32Data : timer callback data
+
+ @Return NONE
+
+******************************************************************************/
static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
{
TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA*)ui32Data;
}
#endif
+/*!
+******************************************************************************
+
+ @Function OSAddTimer
+
+ @Description
+
+ OS specific function to install a timer callback
+
+ @Input pfnTimerFunc : timer callback
+
+ @Input *pvData :callback data
+
+ @Input ui32MsTimeout: callback period
+
+ @Return IMG_HANDLE : valid handle success, NULL failure
+
+******************************************************************************/
IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout)
{
TIMER_CALLBACK_DATA *psTimerCBData;
unsigned long ulLockFlags;
#endif
-
+ /* check callback */
if(!pfnTimerFunc)
{
PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));
return IMG_NULL;
}
-
+ /* Allocate timer callback data structure */
#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
mutex_lock(&sTimerStructLock);
#else
psTimerCBData->pvData = pvData;
psTimerCBData->bActive = IMG_FALSE;
-
-
-
+ /*
+ HZ = ticks per second
+ ui32MsTimeout = required ms delay
+ ticks = (Hz * ui32MsTimeout) / 1000
+ */
psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
? 1
: ((HZ * ui32MsTimeout) / 1000);
-
+ /* initialise object */
init_timer(&psTimerCBData->sTimer);
-
-
+ /* setup timer object */
+ /* PRQA S 0307,0563 1 */ /* ignore warning about inconpartible ptr casting */
psTimerCBData->sTimer.function = (IMG_VOID *)OSTimerCallbackWrapper;
psTimerCBData->sTimer.data = (IMG_UINT32)psTimerCBData;
return &sTimers[ui32i];
}
+/*!
+******************************************************************************
+
+ @Function OSRemoveTimer
+
+ @Description
+
+ OS specific function to remove a timer callback
+
+ @Input hTimer : timer handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
{
TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
PVR_ASSERT(psTimerCBData->bInUse);
PVR_ASSERT(!psTimerCBData->bActive);
-
+ /* free timer callback data struct */
psTimerCBData->bInUse = IMG_FALSE;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSEnableTimer
+
+ @Description
+
+ OS specific function to enable a timer callback
+
+ @Input hTimer : timer handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
{
TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
PVR_ASSERT(psTimerCBData->bInUse);
PVR_ASSERT(!psTimerCBData->bActive);
-
+ /* Start timer arming */
psTimerCBData->bActive = IMG_TRUE;
-
+ /* set the expire time */
psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
-
+ /* Add the timer to the list */
add_timer(&psTimerCBData->sTimer);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSDisableTimer
+
+ @Description
+
+ OS specific function to disable a timer callback
+
+ @Input hTimer : timer handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
{
TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
PVR_ASSERT(psTimerCBData->bInUse);
PVR_ASSERT(psTimerCBData->bActive);
-
+ /* Stop timer from arming */
psTimerCBData->bActive = IMG_FALSE;
smp_mb();
flush_scheduled_work();
#endif
-
+ /* remove timer */
del_timer_sync(&psTimerCBData->sTimer);
#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
-
+ /*
+ * This second flush is to catch the case where the timer ran
+ * before we managed to delete it, in which case, it will have
+ * queued more work for the workqueue. Since the bActive flag
+ * has been cleared, this second flush won't result in the
+ * timer being rearmed.
+ */
flush_workqueue(psTimerWorkQueue);
#endif
#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectCreateKM
+
+ @Description
+
+ OS specific function to create an event object
+
+ @Input pszName : Globally unique event object name (if null name must be autogenerated)
+
+ @Output psEventObject : OS event object info structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT_KM *psEventObject)
#else
{
if(pszName)
{
-
+ /* copy over the event object name */
strncpy(psEventObject->szName, pszName, EVENTOBJNAME_MAXLENGTH);
}
else
{
-
+ /* autogenerate a name */
static IMG_UINT16 ui16NameIndex = 0;
#if defined (SUPPORT_SID_INTERFACE)
snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_KM_%d", ui16NameIndex++);
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectDestroyKM
+
+ @Description
+
+ OS specific function to destroy an event object
+
+ @Input psEventObject : OS event object info structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT_KM *psEventObject)
#else
return eError;
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectWaitKM
+
+ @Description
+
+ OS specific function to wait for an event object. Called from client
+
+ @Input hOSEventKM : OS and kernel specific handle to event object
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSEventObjectWaitKM(IMG_HANDLE hOSEventKM)
{
PVRSRV_ERROR eError;
return eError;
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectOpenKM
+
+ @Description
+
+ OS specific function to open an event object. Called from client
+
+ @Input psEventObject : Pointer to an event object
+ @Output phOSEvent : OS and kernel specific handle to event object
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT_KM *psEventObject,
#else
return eError;
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectCloseKM
+
+ @Description
+
+ OS specific function to close an event object. Called from client
+
+ @Input psEventObject : Pointer to an event object
+ @OInput hOSEventKM : OS and kernel specific handle to event object
+
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT_KM *psEventObject,
#else
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectSignalKM
+
+ @Description
+
+ OS specific function to 'signal' an event object. Called from L/MISR
+
+ @Input hOSEventKM : OS and kernel specific handle to event object
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSEventObjectSignalKM(IMG_HANDLE hOSEventKM)
{
PVRSRV_ERROR eError;
return eError;
}
+/*!
+******************************************************************************
+
+ @Function OSProcHasPrivSrvInit
+
+ @Description
+
+ Does the process have sufficient privileges to initialise services?
+
+ @Input none
+
+ @Return IMG_BOOL :
+
+******************************************************************************/
IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
{
return (capable(CAP_SYS_MODULE) != 0) ? IMG_TRUE : IMG_FALSE;
}
+/*!
+******************************************************************************
+
+ @Function OSCopyToUser
+
+ @Description
+
+ Copy a block of data into user space
+
+ @Input pvSrc
+
+ @Output pvDest
+
+ @Input ui32Bytes
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
IMG_VOID *pvDest,
IMG_VOID *pvSrc,
return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
}
+/*!
+******************************************************************************
+
+ @Function OSCopyFromUser
+
+ @Description
+
+ Copy a block of data from the user space
+
+ @Output pvDest
+
+ @Input pvSrc
+
+ @Input ui32Bytes
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess,
IMG_VOID *pvDest,
IMG_VOID *pvSrc,
return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
}
+/*!
+******************************************************************************
+
+ @Function OSAccessOK
+
+ @Description
+
+ Checks if a user space pointer is valide
+
+ @Input eVerification
+
+ @Input pvUserPtr
+
+ @Input ui32Bytes
+
+ @Return IMG_BOOL :
+
+******************************************************************************/
IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT32 ui32Bytes)
{
IMG_INT linuxType;
} sWrapMemInfo;
+/*!
+******************************************************************************
+
+ @Function *CPUVAddrToPFN
+
+ @Description
+
+ Find the PFN associated with a given CPU virtual address, and return
+ the associated page structure, if it exists.
+ The page in question must be present (i.e. no fault handling required),
+ and must be writable. A get_page is done on the returned page structure.
+
+ @Input psVMArea - pointer to VM area structure
+ ulCPUVAddr - CPU virtual address
+ pulPFN - Pointer to returned PFN.
+ ppsPAge - Pointer to returned page structure pointer.
+
+ @Output *pulPFN - Set to PFN
+ *ppsPage - Pointer to the page structure if present, else NULL.
+ @Return IMG_TRUE if PFN lookup was succesful.
+
+******************************************************************************/
static IMG_BOOL CPUVAddrToPFN(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUVAddr, IMG_UINT32 *pulPFN, struct page **ppsPage)
{
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
#endif
}
+/*!
+******************************************************************************
+
+ @Function OSReleasePhysPageAddr
+
+ @Description
+
+ Release wrapped memory.
+
+ @Input hOSWrapMem : Driver cookie
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
{
sWrapMemInfo *psInfo = (sWrapMemInfo *)hOSWrapMem;
PVR_ASSERT(psPage != NULL);
-
+ /*
+ * If the number of pages mapped is not the same as
+ * the number of pages in the address range, then
+ * get_user_pages must have failed, so we are cleaning
+ * up after failure, and the pages can't be dirty.
+ */
if (psInfo->iNumPagesMapped == psInfo->iNumPages)
{
if (!PageReserved(psPage))
return PVRSRV_OK;
}
+#if defined(CONFIG_TI_TILER)
+
+static IMG_UINT32 CPUAddrToTilerPhy(IMG_UINT32 uiAddr)
+{
+ IMG_UINT32 ui32PhysAddr = 0;
+ pte_t *ptep, pte;
+ pgd_t *pgd;
+ pmd_t *pmd;
+
+ pgd = pgd_offset(current->mm, uiAddr);
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ goto err_out;
+
+ pmd = pmd_offset(pgd, uiAddr);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ goto err_out;
+
+ ptep = pte_offset_map(pmd, uiAddr);
+ if (!ptep)
+ goto err_out;
+
+ pte = *ptep;
+ if (!pte_present(pte))
+ goto err_out;
+
+ ui32PhysAddr = (pte & PAGE_MASK) | (~PAGE_MASK & uiAddr);
+
+ /* If the physAddr is not in the TILER physical range
+ * then we don't proceed.
+ */
+ if (ui32PhysAddr < 0x60000000 && ui32PhysAddr > 0x7fffffff)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CPUAddrToTilerPhy: Not in tiler range"));
+ ui32PhysAddr = 0;
+ goto err_out;
+ }
+
+err_out:
+ return ui32PhysAddr;
+}
+
+#endif /* defined(CONFIG_TI_TILER) */
+
+/*!
+******************************************************************************
+
+ @Function OSAcquirePhysPageAddr
+
+ @Description
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
IMG_UINT32 ui32Bytes,
IMG_SYS_PHYADDR *psSysPAddr,
sWrapMemInfo *psInfo = NULL;
IMG_BOOL bHavePageStructs = IMG_FALSE;
IMG_BOOL bHaveNoPageStructs = IMG_FALSE;
- IMG_BOOL bPFNMismatch = IMG_FALSE;
IMG_BOOL bMMapSemHeld = IMG_FALSE;
PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-
+ /* Align start and end addresses to page boundaries */
ulStartAddr = ulStartAddrOrig & PAGE_MASK;
ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
ulAddrRange = ulBeyondEndAddr - ulStartAddr;
-
+ /*
+ * Check for address range calculation overflow, and attempts to wrap
+ * zero bytes.
+ */
if (ulBeyondEndAddr <= ulStartAddr)
{
PVR_DPF((PVR_DBG_ERROR,
goto error;
}
-
+ /* Allocate information structure */
psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
if (psInfo == NULL)
{
psInfo->iNumPages = (IMG_INT)(ulAddrRange >> PAGE_SHIFT);
psInfo->iPageOffset = (IMG_INT)(ulStartAddrOrig & ~PAGE_MASK);
-
+ /* Allocate physical address array */
psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL);
if (psInfo->psPhysAddr == NULL)
{
}
memset(psInfo->psPhysAddr, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr));
-
+ /* Allocate page array */
psInfo->ppsPages = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL);
if (psInfo->ppsPages == NULL)
{
}
memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
-
+ /* Default error code from now on */
eError = PVRSRV_ERROR_BAD_MAPPING;
-
+ /* Set the mapping type to aid clean up */
psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
-
+ /* Lock down user memory */
down_read(¤t->mm->mmap_sem);
bMMapSemHeld = IMG_TRUE;
-
+ /* Get page list */
psInfo->iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
if (psInfo->iNumPagesMapped >= 0)
{
-
+ /* See if we got all the pages we wanted */
if (psInfo->iNumPagesMapped != psInfo->iNumPages)
{
PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't map all the pages needed (wanted: %d, got %d)", psInfo->iNumPages, psInfo->iNumPagesMapped));
goto error;
}
-
+ /* Build list of physical page addresses */
for (i = 0; i < psInfo->iNumPages; i++)
{
IMG_CPU_PHYADDR CPUPhysAddr;
PVR_DPF((PVR_DBG_MESSAGE, "OSAcquirePhysPageAddr: get_user_pages failed (%d), using CPU page table", psInfo->iNumPagesMapped));
-
+ /* Reset some fields */
psInfo->eType = WRAP_TYPE_NULL;
psInfo->iNumPagesMapped = 0;
memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
-
-
+ /*
+ * get_user_pages didn't work. If this is due to the address range
+ * representing memory mapped I/O, then we'll look for the pages
+ * in the appropriate memory region of the process.
+ */
+
+ /* Set the mapping type to aid clean up */
psInfo->eType = WRAP_TYPE_FIND_VMA;
psVMArea = find_vma(current->mm, ulStartAddrOrig);
psInfo->psVMArea = psVMArea;
#endif
-
+ /*
+ * find_vma locates a region with an end point past a given
+ * virtual address. So check the address is actually in the region.
+ */
if (ulStartAddrOrig < psVMArea->vm_start)
{
PVR_DPF((PVR_DBG_ERROR,
goto error;
}
-
+ /* Now check the end address is in range */
if (ulBeyondEndAddrOrig > psVMArea->vm_end)
{
PVR_DPF((PVR_DBG_ERROR,
goto error;
}
-
+ /* Does the region represent memory mapped I/O? */
if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) != (VM_IO | VM_RESERVED))
{
PVR_DPF((PVR_DBG_ERROR,
goto error;
}
-
+ /* We require read and write access */
if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE))
{
PVR_DPF((PVR_DBG_ERROR,
}
if (psInfo->ppsPages[i] == NULL)
{
+#if defined(CONFIG_TI_TILER)
+ /* This could be tiler memory.*/
+ IMG_UINT32 ui32TilerAddr = CPUAddrToTilerPhy(ulAddr);
+ if (ui32TilerAddr)
+ {
+ bHavePageStructs = IMG_TRUE;
+ psInfo->iNumPagesMapped++;
+ psInfo->psPhysAddr[i].uiAddr = ui32TilerAddr;
+ psSysPAddr[i].uiAddr = ui32TilerAddr;
+ continue;
+ }
+#endif /* defined(CONFIG_TI_TILER) */
bHaveNoPageStructs = IMG_TRUE;
-
-#if defined(VM_PFNMAP)
- if ((psVMArea->vm_flags & VM_PFNMAP) != 0)
- {
- IMG_UINT32 ulPFNRaw = ((ulAddr - psVMArea->vm_start) >> PAGE_SHIFT) + psVMArea->vm_pgoff;
-
- if (ulPFNRaw != ulPFN)
- {
- bPFNMismatch = IMG_TRUE;
- }
- }
-#endif
}
else
{
if (!bHaveNoPageStructs)
{
-
+ /* The ideal case; every page has a page structure */
goto exit;
}
goto error;
}
- if (bPFNMismatch)
- {
- PVR_DPF((PVR_DBG_ERROR,
- "OSAcquirePhysPageAddr: PFN calculation mismatch for VM_PFNMAP region"));
- goto error;
- }
-
exit:
PVR_ASSERT(bMMapSemHeld);
up_read(¤t->mm->mmap_sem);
-
+ /* Return the cookie */
*phOSWrapMem = (IMG_HANDLE)psInfo;
if (bHaveNoPageStructs)
{
- PVR_DPF((PVR_DBG_WARNING,
+ PVR_DPF((PVR_DBG_MESSAGE,
"OSAcquirePhysPageAddr: Region contains pages which can't be locked down (no page structures)"));
}
PVR_ASSERT(psInfo->eType != 0);
-#if 0
-
-
- OSCleanCPUCacheRangeKM(pvCPUVAddr, (IMG_VOID *)((IMG_CHAR *)pvCPUVAddr + ui32Bytes));
-#endif
-
return PVRSRV_OK;
error:
}
typedef void (*InnerCacheOp_t)(const void *pvStart, const void *pvEnd);
+
+#if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+typedef void (*OuterCacheOp_t)(phys_addr_t uStart, phys_addr_t uEnd);
+#else
typedef void (*OuterCacheOp_t)(unsigned long ulStart, unsigned long ulEnd);
+#endif
#if defined(CONFIG_OUTER_CACHE)
-typedef unsigned long (*MemAreaToPhys_t)(LinuxMemArea *psLinuxMemArea,
+typedef IMG_BOOL (*MemAreaToPhys_t)(LinuxMemArea *psLinuxMemArea,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum);
-
-static unsigned long VMallocAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum)
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart);
+
+static IMG_BOOL VMallocAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart)
{
- return vmalloc_to_pfn(pvRangeAddrStart + ui32PageNum * PAGE_SIZE) << PAGE_SHIFT;
+ *pulStart = vmalloc_to_pfn(pvRangeAddrStart + ui32PageNum * PAGE_SIZE) << PAGE_SHIFT;
+ return IMG_TRUE;
}
-static unsigned long ExternalKVAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum)
+static IMG_BOOL ExternalKVAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart)
{
IMG_SYS_PHYADDR SysPAddr;
IMG_CPU_PHYADDR CpuPAddr;
SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageNumOffset + ui32PageNum];
CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
- return CpuPAddr.uiAddr;
+ *pulStart = CpuPAddr.uiAddr;
+ return IMG_TRUE;
}
-static unsigned long AllocPagesAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum)
+static IMG_BOOL AllocPagesAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart)
{
struct page *pPage;
- pPage = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageNumOffset + ui32PageNum];
- return page_to_pfn(pPage) << PAGE_SHIFT;
+
+ pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageNumOffset + ui32PageNum];
+ *pulStart = page_to_pfn(pPage) << PAGE_SHIFT;
+ return IMG_TRUE;
+}
+
+static IMG_BOOL AllocPagesSparseAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart)
+{
+ IMG_UINT32 ui32VirtOffset = (ui32PageNumOffset + ui32PageNum) << PAGE_SHIFT;
+ IMG_UINT32 ui32PhysOffset;
+ struct page *pPage;
+
+ if (BM_VirtOffsetToPhysical(psLinuxMemArea->hBMHandle, ui32VirtOffset, &ui32PhysOffset))
+ {
+ PVR_ASSERT(ui32PhysOffset <= ui32VirtOffset);
+ pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PhysOffset >> PAGE_SHIFT];
+ *pulStart = page_to_pfn(pPage) << PAGE_SHIFT;
+ return IMG_TRUE;
+ }
+
+ return IMG_FALSE;
}
-#endif
-#ifndef __mips__
+static IMG_BOOL IONAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+ CpuPAddr = psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs[ui32PageNumOffset + ui32PageNum];
+ *pulStart = CpuPAddr.uiAddr;
+ return IMG_TRUE;
+}
+
+#endif /* defined(CONFIG_OUTER_CACHE) */
+
+/* g_sMMapMutex must be held while this function is called */
+
static
IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
IMG_VOID *pvRangeAddrStart, IMG_UINT32 ui32Length)
PKV_OFFSET_STRUCT psOffsetStruct;
IMG_VOID *pvMinVAddr;
-
+ /* There's no kernel-virtual for this type of allocation, so if
+ * we're flushing it, it must be user-virtual, and therefore
+ * have a mapping.
+ */
list_for_each_entry(psOffsetStruct, psMMapOffsetStructList, sAreaItem)
{
if(OSGetCurrentProcessIDKM() != psOffsetStruct->ui32PID)
pvMinVAddr = (IMG_VOID *)psOffsetStruct->ui32UserVAddr;
-
+ /* Within permissible range */
if(pvRangeAddrStart >= pvMinVAddr &&
ui32Length <= psOffsetStruct->ui32RealByteSize)
return pvMinVAddr;
return IMG_NULL;
}
+extern PVRSRV_LINUX_MUTEX g_sMMapMutex;
+
+static inline void DoInnerCacheOp(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length,
+ InnerCacheOp_t pfnInnerCacheOp)
+{
+ LinuxMemArea *psLinuxMemArea = hOSMemHandle;
+
+ if (!psLinuxMemArea->hBMHandle)
+ {
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ }
+ else
+ {
+ IMG_UINT32 ui32ByteRemain = ui32Length;
+ IMG_UINT32 ui32BytesToDo = PAGE_SIZE - (((IMG_UINT32) pvRangeAddrStart) & (~PAGE_MASK));
+ IMG_UINT8 *pbDo = (IMG_UINT8 *) pvRangeAddrStart;
+
+ while(ui32ByteRemain)
+ {
+ if (BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32ByteOffset + (ui32Length - ui32ByteRemain)))
+ {
+ pfnInnerCacheOp(pbDo, pbDo + ui32BytesToDo);
+ }
+ pbDo += ui32BytesToDo;
+ ui32ByteRemain -= ui32BytesToDo;
+ ui32BytesToDo = MIN(ui32ByteRemain, PAGE_SIZE);
+ }
+ }
+}
+
static
IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length,
InnerCacheOp_t pfnInnerCacheOp,
PVR_ASSERT(psLinuxMemArea != IMG_NULL);
- ui32AreaLength = psLinuxMemArea->ui32ByteSize;
+ LinuxLockMutex(&g_sMMapMutex);
+
psMMapOffsetStructList = &psLinuxMemArea->sMMapOffsetStructList;
+ ui32AreaLength = psLinuxMemArea->ui32ByteSize;
PVR_ASSERT(ui32Length <= ui32AreaLength);
psLinuxMemArea = psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
}
-
+ /* Recursion surely isn't possible? */
PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
switch(psLinuxMemArea->eAreaType)
{
pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + ui32AreaOffset;
-
+ /* Outside permissible range */
if(pvRangeAddrStart < pvMinVAddr)
goto err_blocked;
- pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ DoInnerCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvRangeAddrStart,
+ ui32Length,
+ pfnInnerCacheOp);
}
else
{
-
-
+ /* If this isn't a vmalloc address, assume we're flushing by
+ * user-virtual. Compute the mmap base vaddr and use this to
+ * compute the offset in vmalloc space.
+ */
pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
pvRangeAddrStart, ui32Length);
if(!pvMinVAddr)
goto err_blocked;
- pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ DoInnerCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvRangeAddrStart,
+ ui32Length,
+ pfnInnerCacheOp);
#if defined(CONFIG_OUTER_CACHE)
-
+ /*
+ * We don't need to worry about cache aliasing here because
+ * we have already flushed the virtually-indexed caches (L1
+ * etc.) by the supplied user-virtual addresses.
+ *
+ * The vmalloc address will only be used to determine
+ * affected physical pages for outer cache flushing.
+ */
pvRangeAddrStart = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress +
(ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr);
}
pfnMemAreaToPhys = VMallocAreaToPhys;
-#else
+#else /* defined(CONFIG_OUTER_CACHE) */
}
-#endif
+#endif /* defined(CONFIG_OUTER_CACHE) */
break;
}
case LINUX_MEM_AREA_EXTERNAL_KV:
{
-
+ /* We'll only see bPhysContig for frame buffers, and we shouldn't
+ * be flushing those (they're write combined or uncached).
+ */
if (psLinuxMemArea->uData.sExternalKV.bPhysContig == IMG_TRUE)
{
PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush contiguous external memory", __func__));
-
goto err_blocked;
}
-
+ /* If it has a kernel virtual address, something odd has happened.
+ * We expect EXTERNAL_KV _only_ from the wrapping of ALLOC_PAGES.
+ */
if (psLinuxMemArea->uData.sExternalKV.pvExternalKV != IMG_NULL)
{
PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush external memory with a kernel virtual address", __func__));
-
goto err_blocked;
}
-
-
pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
pvRangeAddrStart, ui32Length);
if(!pvMinVAddr)
goto err_blocked;
- pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ DoInnerCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvRangeAddrStart,
+ ui32Length,
+ pfnInnerCacheOp);
#if defined(CONFIG_OUTER_CACHE)
ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
break;
}
+ case LINUX_MEM_AREA_ION:
+ {
+ pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+ pvRangeAddrStart, ui32Length);
+ if(!pvMinVAddr)
+ goto err_blocked;
+
+ DoInnerCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvRangeAddrStart,
+ ui32Length,
+ pfnInnerCacheOp);
+
+#if defined(CONFIG_OUTER_CACHE)
+ ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
+ pfnMemAreaToPhys = IONAreaToPhys;
+#endif
+ break;
+ }
+
case LINUX_MEM_AREA_ALLOC_PAGES:
{
pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
if(!pvMinVAddr)
goto err_blocked;
- pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ DoInnerCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvRangeAddrStart,
+ ui32Length,
+ pfnInnerCacheOp);
#if defined(CONFIG_OUTER_CACHE)
ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
- pfnMemAreaToPhys = AllocPagesAreaToPhys;
+ if (psLinuxMemArea->hBMHandle)
+ {
+ pfnMemAreaToPhys = AllocPagesSparseAreaToPhys;
+ }
+ else
+ {
+ pfnMemAreaToPhys = AllocPagesAreaToPhys;
+ }
#endif
break;
}
PVR_DBG_BREAK;
}
+ LinuxUnLockMutex(&g_sMMapMutex);
+
#if defined(CONFIG_OUTER_CACHE)
PVR_ASSERT(pfnMemAreaToPhys != IMG_NULL);
-
+ /* Outer caches need some more work, to get a list of physical addresses */
{
unsigned long ulStart, ulEnd, ulLength, ulStartOffset, ulEndOffset;
IMG_UINT32 i, ui32NumPages;
+ IMG_BOOL bValidPage;
-
+ /* Length and offsets of flush region WRT page alignment */
ulLength = (unsigned long)ui32Length;
ulStartOffset = ((unsigned long)pvRangeAddrStart) & (PAGE_SIZE - 1);
ulEndOffset = ((unsigned long)pvRangeAddrStart + ulLength) & (PAGE_SIZE - 1);
-
+ /* The affected pages, rounded up */
ui32NumPages = (ulStartOffset + ulLength + PAGE_SIZE - 1) >> PAGE_SHIFT;
for(i = 0; i < ui32NumPages; i++)
{
- ulStart = pfnMemAreaToPhys(psLinuxMemArea, pvRangeAddrStart,
- ui32PageNumOffset, i);
- ulEnd = ulStart + PAGE_SIZE;
-
- if(i == ui32NumPages - 1 && ulEndOffset != 0)
- ulEnd = ulStart + ulEndOffset;
-
- if(i == 0)
- ulStart += ulStartOffset;
-
- pfnOuterCacheOp(ulStart, ulEnd);
+ bValidPage = pfnMemAreaToPhys(psLinuxMemArea, pvRangeAddrStart,
+ ui32PageNumOffset, i, &ulStart);
+ if (bValidPage)
+ {
+ ulEnd = ulStart + PAGE_SIZE;
+
+ if(i == ui32NumPages - 1 && ulEndOffset != 0)
+ ulEnd = ulStart + ulEndOffset;
+
+ if(i == 0)
+ ulStart += ulStartOffset;
+
+ pfnOuterCacheOp(ulStart, ulEnd);
+ }
}
}
#endif
"%p-%p (type %d)", __func__,
pvRangeAddrStart, pvRangeAddrStart + ui32Length,
psLinuxMemArea->eAreaType));
+ LinuxUnLockMutex(&g_sMMapMutex);
return IMG_FALSE;
}
-#endif
-
#if defined(__i386__)
#define ROUND_UP(x,a) (((x) + (a) - 1) & ~((a) - 1))
mb();
for(pbBase = pbStart; pbBase < pbEnd; pbBase += boot_cpu_data.x86_clflush_size)
+ {
clflush(pbBase);
+ }
mb();
}
IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
{
-
+ /* No clean feature on x86 */
ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
}
}
IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
-
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ /* Write-back and invalidate */
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
x86_flush_cache_range, IMG_NULL);
}
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
-
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ /* No clean feature on x86 */
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
x86_flush_cache_range, IMG_NULL);
}
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
-
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ /* No invalidate-only support */
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
x86_flush_cache_range, IMG_NULL);
}
-#else
+#else /* defined(__i386__) */
#if defined(__arm__)
IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
{
-
+ /* No full (inner) cache clean op */
ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
-#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
- outer_clean_all();
+#if defined(CONFIG_OUTER_CACHE)
+ outer_clean_range(0, ULONG_MAX);
#endif
}
IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
{
ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
-#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
+#if defined(CONFIG_OUTER_CACHE) && \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ /* To use the "deferred flush" (not clean) DDK feature you need a kernel
+ * implementation of outer_flush_all() for ARM CPUs with an outer cache
+ * controller (e.g. PL310, common with Cortex A9 and later).
+ *
+ * Reference DDKs don't require this functionality, as they will only
+ * clean the cache, never flush (clean+invalidate) it.
+ */
outer_flush_all();
#endif
}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
static inline size_t pvr_dmac_range_len(const void *pvStart, const void *pvEnd)
{
return (size_t)((char *)pvEnd - (char *)pvStart);
}
+#endif
static void pvr_dmac_inv_range(const void *pvStart, const void *pvEnd)
{
}
IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
- dmac_flush_range, (OuterCacheOp_t)outer_flush_range);
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
+ dmac_flush_range, outer_flush_range);
}
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
- pvr_dmac_clean_range, (OuterCacheOp_t)outer_clean_range);
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
+ pvr_dmac_clean_range, outer_clean_range);
}
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
- pvr_dmac_inv_range, (OuterCacheOp_t)outer_inv_range);
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
+ pvr_dmac_inv_range, outer_inv_range);
}
-#else
+#else /* defined(__arm__) */
#if defined(__mips__)
+/*
+ * dmac cache functions are supposed to be used for dma
+ * memory which comes from dma-able memory. However examining
+ * the implementation of dmac cache functions and experimenting,
+ * can assert that dmac functions are safe to use for high-mem
+ * memory as well for our OS{Clean/Flush/Invalidate}Cache functions
+ *
+ */
+
IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
{
-
+ /* dmac functions flush full cache if size is larger than
+ * p-cache size. This is a workaround for the fact that
+ * __flush_cache_all is not an exported symbol. Please
+ * replace with custom function if available in latest
+ * version of linux being used.
+ * Arbitrary large number (1MB) which should be larger than
+ * mips p-cache sizes for some time in future.
+ * */
dma_cache_wback(0, 0x100000);
}
IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
{
-
+ /* dmac functions flush full cache if size is larger than
+ * p-cache size. This is a workaround for the fact that
+ * __flush_cache_all is not an exported symbol. Please
+ * replace with custom function if available in latest
+ * version of linux being used.
+ * Arbitrary large number (1MB) which should be larger than
+ * mips p-cache sizes for some time in future.
+ * */
dma_cache_wback_inv(0, 0x100000);
}
+static inline IMG_UINT32 pvr_dma_range_len(const void *pvStart, const void *pvEnd)
+{
+ return (IMG_UINT32)((char *)pvEnd - (char *)pvStart);
+}
+
+static void pvr_dma_cache_wback_inv(const void *pvStart, const void *pvEnd)
+{
+ dma_cache_wback_inv((IMG_UINTPTR_T)pvStart, pvr_dma_range_len(pvStart, pvEnd));
+}
+
+static void pvr_dma_cache_wback(const void *pvStart, const void *pvEnd)
+{
+ dma_cache_wback((IMG_UINTPTR_T)pvStart, pvr_dma_range_len(pvStart, pvEnd));
+}
+
+static void pvr_dma_cache_inv(const void *pvStart, const void *pvEnd)
+{
+ dma_cache_inv((IMG_UINTPTR_T)pvStart, pvr_dma_range_len(pvStart, pvEnd));
+}
+
IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- if (ui32Length)
- dma_cache_wback_inv((IMG_UINTPTR_T)pvRangeAddrStart, ui32Length);
- return IMG_TRUE;
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
+ pvr_dma_cache_wback_inv, IMG_NULL);
}
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- if (ui32Length)
- dma_cache_wback((IMG_UINTPTR_T)pvRangeAddrStart, ui32Length);
- return IMG_TRUE;
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
+ pvr_dma_cache_wback, IMG_NULL);
}
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- if (ui32Length)
- dma_cache_inv((IMG_UINTPTR_T)pvRangeAddrStart, ui32Length);
- return IMG_TRUE;
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
+ pvr_dma_cache_inv, IMG_NULL);
}
-#else
+#else /* defined(__mips__) */
#error "Implement CPU cache flush/clean/invalidate primitives for this CPU!"
-#endif
+#endif /* defined(__mips__) */
+
+#endif /* defined(__arm__) */
-#endif
+#endif /* defined(__i386__) */
-#endif
+typedef struct _AtomicStruct
+{
+ atomic_t RefCount;
+} AtomicStruct;
+
+PVRSRV_ERROR OSAtomicAlloc(IMG_PVOID *ppvRefCount)
+{
+ AtomicStruct *psRefCount;
+ psRefCount = kmalloc(sizeof(AtomicStruct), GFP_KERNEL);
+ if (psRefCount == NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ atomic_set(&psRefCount->RefCount, 0);
+
+ *ppvRefCount = psRefCount;
+ return PVRSRV_OK;
+}
+
+IMG_VOID OSAtomicFree(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ PVR_ASSERT(atomic_read(&psRefCount->RefCount) == 0);
+ kfree(psRefCount);
+}
+
+IMG_VOID OSAtomicInc(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ atomic_inc(&psRefCount->RefCount);
+}
+
+IMG_BOOL OSAtomicDecAndTest(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ return atomic_dec_and_test(&psRefCount->RefCount) ? IMG_TRUE:IMG_FALSE;
+}
+
+IMG_UINT32 OSAtomicRead(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ return (IMG_UINT32) atomic_read(&psRefCount->RefCount);
+}
+
+IMG_VOID OSReleaseBridgeLock(IMG_VOID)
+{
+ LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+IMG_VOID OSReacquireBridgeLock(IMG_VOID)
+{
+ LinuxLockMutex(&gPVRSRVLock);
+}
+
+typedef struct _OSTime
+{
+ unsigned long ulTime;
+} OSTime;
+
+PVRSRV_ERROR OSTimeCreateWithUSOffset(IMG_PVOID *pvRet, IMG_UINT32 ui32USOffset)
+{
+ OSTime *psOSTime;
+
+ psOSTime = kmalloc(sizeof(OSTime), GFP_KERNEL);
+ if (psOSTime == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psOSTime->ulTime = usecs_to_jiffies(jiffies_to_usecs(jiffies) + ui32USOffset);
+ *pvRet = psOSTime;
+ return PVRSRV_OK;
+}
+
+
+IMG_BOOL OSTimeHasTimePassed(IMG_PVOID pvData)
+{
+ OSTime *psOSTime = pvData;
+
+ if (time_is_before_jiffies(psOSTime->ulTime))
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+IMG_VOID OSTimeDestroy(IMG_PVOID pvData)
+{
+ kfree(pvData);
+}
+
+IMG_VOID OSGetCurrentProcessNameKM(IMG_CHAR *pszName, IMG_UINT32 ui32Size)
+{
+ strncpy(pszName, current->comm, MIN(ui32Size,TASK_COMM_LEN));
+}
+
+/* One time osfunc initialisation */
PVRSRV_ERROR PVROSFuncInit(IMG_VOID)
{
#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
}
}
#endif
+
+#if defined (SUPPORT_ION)
+ {
+ PVRSRV_ERROR eError;
+
+ eError = IonInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: IonInit failed", __FUNCTION__));
+ }
+ }
+#endif
return PVRSRV_OK;
}
+/*
+ * Osfunc deinitialisation.
+ * Note that PVROSFuncInit may not have been called
+ */
IMG_VOID PVROSFuncDeInit(IMG_VOID)
{
+#if defined (SUPPORT_ION)
+ IonDeinit();
+#endif
#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
if (psTimerWorkQueue != NULL)
{
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux specific per process data functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
#include "osperproc.h"
#include "env_perproc.h"
#include "proc.h"
+#if defined (SUPPORT_ION)
+#include "linux/ion.h"
+extern struct ion_device *psIonDev;
+#endif
extern IMG_UINT32 gui32ReleasePID;
PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
psEnvPerProc->hBlockAlloc = hBlockAlloc;
-
+ /* Linux specific mmap processing */
LinuxMMapPerProcessConnect(psEnvPerProc);
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
-
+ /* Linked list of PVRSRV_FILE_PRIVATE_DATA structures */
INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead);
#endif
-
+#if defined(SUPPORT_ION)
+ OSSNPrintf(psEnvPerProc->azIonClientName, ION_CLIENT_NAME_SIZE, "pvr_ion_client-%d", OSGetCurrentProcessIDKM());
+ psEnvPerProc->psIONClient =
+ ion_client_create(psIonDev,
+ 1 << ION_HEAP_TYPE_SYSTEM_CONTIG |
+ 1 << ION_HEAP_TYPE_SYSTEM,
+ psEnvPerProc->azIonClientName);
+
+ if (IS_ERR_OR_NULL(psEnvPerProc->psIONClient))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPerProcessPrivateDataInit: Couldn't create "
+ "ion client for per process data"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+#endif /* SUPPORT_ION */
return PVRSRV_OK;
}
psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
-
+ /* Linux specific mmap processing */
LinuxMMapPerProcessDisconnect(psEnvPerProc);
-
+ /* Remove per process /proc entries */
RemovePerProcessProcDir(psEnvPerProc);
eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
hOsPrivateData,
psEnvPerProc->hBlockAlloc);
-
+ /*not nulling pointer, copy on stack*/
if (eError != PVRSRV_OK)
{
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Parameter dump macro target routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if defined (SUPPORT_SGX) || defined (SUPPORT_VGX)
#if defined (PDUMP)
#include <asm/atomic.h>
#include <stdarg.h>
#if defined (SUPPORT_SGX)
-#include "sgxdefs.h"
+#include "sgxdefs.h" /* Is this still needed? */
#endif
#include "services_headers.h"
#include "dbgdrvif.h"
#if defined (SUPPORT_SGX)
-#include "sgxmmu.h"
+#include "sgxmmu.h"/* Is this still needed? */
#endif
#include "mm.h"
#include "pdump_km.h"
#include "pdump_int.h"
-#include <linux/kernel.h>
-#include <linux/string.h>
+#include <linux/kernel.h> // sprintf
+#include <linux/string.h> // strncpy, strlen
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);
#define PDUMP_DATAMASTER_PIXEL (1)
#define PDUMP_DATAMASTER_EDM (3)
+/*
+ Maximum file size to split output files
+*/
#define MAX_FILE_SIZE 0x40000000
static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
-IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
-
static inline IMG_BOOL PDumpSuspended(IMG_VOID)
{
return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
}
+/*!
+ * \name PDumpOSGetScriptString
+ */
PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
IMG_UINT32 *pui32MaxLen)
{
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSGetMessageString
+ */
PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg,
IMG_UINT32 *pui32MaxLen)
{
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSGetFilenameString
+ */
PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
IMG_UINT32 *pui32MaxLen)
{
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSWriteString2
+ */
IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
{
return PDumpWriteString2(hScript, ui32Flags);
}
+/*!
+ * \name PDumpOSBufprintf
+ */
PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
{
IMG_CHAR* pszBuf = hBuf;
va_end(vaArgs);
- if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */
{
PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSVSprintf
+ */
PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
{
IMG_INT32 n;
n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
- if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */
{
PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSDebugPrintf
+ */
IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
{
PVR_UNREFERENCED_PARAMETER(pszFormat);
-
+ /* FIXME: Implement using services PVR_DBG or otherwise with kprintf */
}
+/*!
+ * \name PDumpOSSprintf
+ */
PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
{
IMG_INT32 n;
va_end(vaArgs);
- if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */
{
PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSBuflen
+ */
IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
{
IMG_CHAR* pszBuf = hBuffer;
return(ui32Count);
}
+/*!
+ * \name PDumpOSVerifyLineEnding
+ */
IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
{
IMG_UINT32 ui32Count;
IMG_CHAR* pszBuf = hBuffer;
-
+ /* strlen */
ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
-
+ /* Put \r \n sequence at the end if it isn't already there */
if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
{
pszBuf[ui32Count] = '\n';
}
}
+/*!
+ * \name PDumpOSGetStream
+ */
IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
{
return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
}
+/*!
+ * \name PDumpOSGetStreamOffset
+ */
IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
{
PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
return gpfnDbgDrv->pfnGetStreamOffset(psStream);
}
+/*!
+ * \name PDumpOSGetParamFileNum
+ */
IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
{
return gsDBGPdumpState.ui32ParamFileNum;
}
+/*!
+ * \name PDumpOSWriteString
+ */
IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
IMG_UINT8 *psui8Data,
IMG_UINT32 ui32Size,
ui32Flags);
}
+/*!
+ * \name PDumpOSCheckForSplitting
+ */
IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
{
-
+ /* File size limit not implemented for this OS.
+ */
PVR_UNREFERENCED_PARAMETER(hStream);
PVR_UNREFERENCED_PARAMETER(ui32Size);
PVR_UNREFERENCED_PARAMETER(ui32Flags);
}
+/*!
+ * \name PDumpOSJTInitialised
+ */
IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
{
if(gpfnDbgDrv)
return IMG_FALSE;
}
+/*!
+ * \name PDumpOSIsSuspended
+ */
inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
{
return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
}
+/*!
+ * \name PDumpOSCPUVAddrToDevPAddr
+ */
IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
IMG_CPU_PHYADDR sCpuPAddr;
PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
- PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+ PVR_UNREFERENCED_PARAMETER(ui32PageSize); /* for when no assert */
-
+ /* Caller must now alway supply hOSMemHandle, even though we only (presently)
+ use it here in the linux implementation */
PVR_ASSERT (hOSMemHandle != IMG_NULL);
sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
-
+ /* convert CPU physical addr to device physical */
*psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
}
+/*!
+ * \name PDumpOSCPUVAddrToPhysPages
+ */
IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
IMG_PUINT8 pui8LinAddr,
{
if(hOSMemHandle)
{
-
+ /*
+ * If a Services memory handle is provided then use it.
+ */
IMG_CPU_PHYADDR sCpuPAddr;
PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
}
}
+/*!
+ * \name PDumpOSDebugDriverWrite
+ */
IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream,
PDUMP_DDWMODE eDbgDrvWriteMode,
IMG_UINT8 *pui8Data,
return 0xFFFFFFFFU;
}
+/*!
+ * \name PDumpOSReleaseExecution
+ */
IMG_VOID PDumpOSReleaseExecution(IMG_VOID)
{
OSReleaseThreadQuanta();
}
+/**************************************************************************
+ * Function Name : PDumpInit
+ * Outputs : None
+ * Returns :
+ * Description : Reset connection to vldbgdrv
+ * Then try to connect to PDUMP streams
+**************************************************************************/
IMG_VOID PDumpInit(IMG_VOID)
{
IMG_UINT32 i;
DBGKM_CONNECT_NOTIFIER sConnectNotifier;
-
+ /* If we tried this earlier, then we might have connected to the driver
+ * But if pdump.exe was running then the stream connected would fail
+ */
if (!gpfnDbgDrv)
{
- DBGDrvGetServiceTable((IMG_VOID **)&gpfnDbgDrv);
+ DBGDrvGetServiceTable(&gpfnDbgDrv);
-
+ // If something failed then no point in trying to connect streams
if (gpfnDbgDrv == IMG_NULL)
{
return;
}
-
+ /*
+ * Pass the connection notify callback
+ */
sConnectNotifier.pfnConnectNotifier = &PDumpConnectionNotify;
gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
gsDBGPdumpState.pszMsg = IMG_NULL;
}
-
+ /*
+ * Remove the connection notify callback
+ */
sConnectNotifier.pfnConnectNotifier = 0;
gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
gsDBGPdumpState.pszMsg = IMG_NULL;
}
-
+ /*
+ * Remove the connection notify callback
+ */
sConnectNotifier.pfnConnectNotifier = 0;
gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
gpfnDbgDrv = IMG_NULL;
}
+/**************************************************************************
+ * Function Name : PDumpStartInitPhaseKM
+ * Inputs : None
+ * Outputs : None
+ * Returns : None
+ * Description : Resume init phase state
+**************************************************************************/
PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
{
IMG_UINT32 i;
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpStopInitPhaseKM
+ * Inputs : None
+ * Outputs : None
+ * Returns : None
+ * Description : End init phase state
+**************************************************************************/
PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
{
IMG_UINT32 i;
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpIsLastCaptureFrameKM
+ * Inputs : None
+ * Outputs : None
+ * Returns : True or false
+ * Description : Tests whether the current frame is being pdumped
+**************************************************************************/
IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
{
return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
}
+/**************************************************************************
+ * Function Name : PDumpIsCaptureFrameKM
+ * Inputs : None
+ * Outputs : None
+ * Returns : True or false
+ * Description : Tests whether the current frame is being pdumped
+**************************************************************************/
IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID)
{
if (PDumpSuspended())
return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
}
+/**************************************************************************
+ * Function Name : PDumpSetFrameKM
+ * Inputs : None
+ * Outputs : None
+ * Returns : None
+ * Description : Sets a frame
+**************************************************************************/
PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame)
{
IMG_UINT32 ui32Stream;
}
+/*****************************************************************************
+ FUNCTION : PDumpWriteString2
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
{
return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
}
+/*****************************************************************************
+ FUNCTION : PDumpWriteILock
+
+ PURPOSE : Writes, making sure it all goes...
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
{
IMG_UINT32 ui32Written = 0;
}
-
+ /*
+ Set the stream marker to split output files
+ */
if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
{
return IMG_TRUE;
}
+/*****************************************************************************
+ FUNCTION : DbgSetFrame
+
+ PURPOSE : Sets the frame in the stream
+
+ PARAMETERS : psStream - Stream pointer
+ ui32Frame - Frame number to set
+
+ RETURNS : None
+*****************************************************************************/
static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
{
gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
}
+/*****************************************************************************
+ FUNCTION : DbgSetMarker
+
+ PURPOSE : Sets the marker of the stream to split output files
+
+ PARAMETERS : psStream - Stream pointer
+ ui32Marker - Marker number to set
+
+ RETURNS : None
+*****************************************************************************/
static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
{
gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
atomic_dec(&gsPDumpSuspended);
}
-#endif
-#endif
+#endif /* #if defined (PDUMP) */
+#endif /* #if defined (SUPPORT_SGX) */
+/*****************************************************************************
+ End of file (PDUMP.C)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux private data structure
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __INCLUDED_PRIVATE_DATA_H_
#define __INCLUDED_PRIVATE_DATA_H_
#include <drm/drmP.h>
#endif
+/* This structure is required in the rare case that a process creates
+ * a connection to services, but before closing the file descriptor,
+ * does a fork(). This fork() will duplicate the file descriptor in the
+ * child process. If the parent process dies before the child, this can
+ * cause the PVRSRVRelease() method to be called in a different process
+ * context than the original PVRSRVOpen(). This is bad because we need
+ * to update the per-process data reference count and/or free the
+ * per-process data. So we must keep a record of which PID's per-process
+ * data to inspect during ->release().
+ */
+
typedef struct
{
-
+ /* PID that created this services connection */
IMG_UINT32 ui32OpenPID;
-
+ /* Global kernel MemInfo handle */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
#endif
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
-
+ /* The private data is on a list in the per-process data structure */
struct list_head sDRMAuthListItem;
struct drm_file *psDRMFile;
#endif
#if defined(SUPPORT_MEMINFO_IDS)
-
+ /* Globally unique "stamp" for kernel MemInfo */
IMG_UINT64 ui64Stamp;
-#endif
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
-
+ /* Accounting for OSAllocMem */
IMG_HANDLE hBlockAlloc;
#if defined(SUPPORT_DRI_DRM_EXT)
- IMG_PVOID pPriv;
+ IMG_PVOID pPriv; /*private data for extending this struct*/
#endif
}
PVRSRV_FILE_PRIVATE_DATA;
-#endif
+#endif /* __INCLUDED_PRIVATE_DATA_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Proc files implementation.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Functions for creating and reading proc filesystem entries.
+ Proc filesystem support must be built into the kernel for
+ these functions to be any use.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
#include "lists.h"
+// The proc entry for our /proc/pvr directory
static struct proc_dir_entry * dir;
static const IMG_CHAR PVRProcDirRoot[] = "pvr";
static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
+/*!
+******************************************************************************
+
+ @Function : printAppend
+
+ @Description
+
+ Print into the supplied buffer at the specified offset remaining within
+ the specified total buffer size.
+
+ @Input size : the total size of the buffer
+
+ @Input off : the offset into the buffer to start printing
+
+ @Input format : the printf format string
+
+ @Input ... : format args
+
+ @Return : The number of chars now in the buffer (original value of 'off'
+ plus number of chars added); 'size' if full.
+
+*****************************************************************************/
off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
{
IMG_INT n;
n = vsnprintf (buffer+off, space, format, ap);
va_end (ap);
-
+ /* According to POSIX, n is greater than or equal to the size available if
+ * the print would have overflowed the buffer. Other platforms may
+ * return -1 if printing was truncated.
+ */
if (n >= (IMG_INT)space || n < 0)
{
-
+ /* Ensure final string is terminated */
buffer[size - 1] = 0;
return (off_t)(size - 1);
}
}
+/*!
+******************************************************************************
+
+ @Function : ProcSeq1ElementOff2Element
+
+ @Description
+
+ Heleper Offset -> Element function for /proc files with only one entry
+ without header.
+
+ @Input sfile : seq_file object related to /proc/ file
+
+ @Input off : the offset into the buffer (id of object)
+
+ @Return : Pointer to element to be shown.
+
+*****************************************************************************/
void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
{
PVR_UNREFERENCED_PARAMETER(sfile);
-
+ // Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL
if(!off)
return (void*)2;
return NULL;
}
+/*!
+******************************************************************************
+
+ @Function : ProcSeq1ElementHeaderOff2Element
+
+ @Description
+
+ Heleper Offset -> Element function for /proc files with only one entry
+ with header.
+
+ @Input sfile : seq_file object related to /proc/ file
+
+ @Input off : the offset into the buffer (id of object)
+
+ @Return : Pointer to element to be shown.
+
+*****************************************************************************/
void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
{
PVR_UNREFERENCED_PARAMETER(sfile);
return PVR_PROC_SEQ_START_TOKEN;
}
-
+ // Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL
if(off == 1)
return (void*)2;
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_open
+
+ @Description
+ File opening function passed to proc_dir_entry->proc_fops for /proc entries
+ created by CreateProcReadEntrySeq.
+
+ @Input inode : inode entry of opened /proc file
+
+ @Input file : file entry of opened /proc file
+
+ @Return : 0 if no errors
+
+*****************************************************************************/
static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
{
IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
struct seq_file *seq = (struct seq_file*)file->private_data;
struct proc_dir_entry* pvr_proc_entry = PDE(inode);
-
+ /* Add pointer to handlers to seq_file structure */
seq->private = pvr_proc_entry->data;
return ret;
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_write
+
+ @Description
+ File writing function passed to proc_dir_entry->proc_fops for /proc files.
+ It's exacly the same function that is used as default one (->fs/proc/generic.c),
+ it calls proc_dir_entry->write_proc for writing procedure.
+
+*****************************************************************************/
static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_start
+
+ @Description
+ Seq_file start function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+ This function ises off2element handler.
+
+ @Input proc_seq_file : sequence file entry
+
+ @Input pos : offset within file (id of entry)
+
+ @Return : Pointer to element from we start enumeration (0 ends it)
+
+*****************************************************************************/
static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
{
PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
return handlers->off2element(proc_seq_file, *pos);
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_stop
+
+ @Description
+ Seq_file stop function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+
+ @Input proc_seq_file : sequence file entry
+
+ @Input v : current element pointer
+
+*****************************************************************************/
static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
{
PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
handlers->startstop(proc_seq_file, IMG_FALSE);
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_next
+
+ @Description
+ Seq_file next element function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+ It uses supplied 'next' handler for fetching next element (or 0 if there is no one)
+
+ @Input proc_seq_file : sequence file entry
+
+ @Input pos : offset within file (id of entry)
+
+ @Input v : current element pointer
+
+ @Return : next element pointer (or 0 if end)
+
+*****************************************************************************/
static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
{
PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
return handlers->off2element(proc_seq_file, *pos);
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_show
+
+ @Description
+ Seq_file show element function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+ It call proper 'show' handler to show (dump) current element using seq_* functions
+
+ @Input proc_seq_file : sequence file entry
+
+ @Input v : current element pointer
+
+ @Return : 0 if everything is OK
+
+*****************************************************************************/
static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
{
PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntryInDirSeq
+
+ @Description
+
+ Create a file under the given directory. These dynamic files can be used at
+ runtime to get or set information about the device. Whis version uses seq_file
+ interface
+
+ @Input pdir : parent directory
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+ supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return Ptr to proc entry , 0 for failure
+
+
+*****************************************************************************/
static struct proc_dir_entry* CreateProcEntryInDirSeq(
struct proc_dir_entry *pdir,
const IMG_CHAR * name,
file->proc_fops = &pvr_proc_operations;
file->write_proc = whandler;
-
+ /* Pass the handlers */
file->data = kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
if(file->data)
{
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcReadEntrySeq
+
+ @Description
+
+ Create a file under /proc/pvr. These dynamic files can be used at runtime
+ to get information about the device. Creation WILL fail if proc support is
+ not compiled into the kernel. That said, the Linux kernel is not even happy
+ to build without /proc support these days. This version uses seq_file structure
+ for handling content generation.
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+ supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Return Ptr to proc entry , 0 for failure
+
+*****************************************************************************/
struct proc_dir_entry* CreateProcReadEntrySeq (
const IMG_CHAR * name,
IMG_VOID* data,
NULL);
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntrySeq
+
+ @Description
+
+ @Description
+
+ Create a file under /proc/pvr. These dynamic files can be used at runtime
+ to get information about the device. Creation WILL fail if proc support is
+ not compiled into the kernel. That said, the Linux kernel is not even happy
+ to build without /proc support these days. This version uses seq_file structure
+ for handling content generation and is fuller than CreateProcReadEntrySeq (it
+ supports write access);
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+ supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return Ptr to proc entry , 0 for failure
+
+*****************************************************************************/
struct proc_dir_entry* CreateProcEntrySeq (
const IMG_CHAR * name,
IMG_VOID* data,
+/*!
+******************************************************************************
+
+ @Function : CreatePerProcessProcEntrySeq
+
+ @Description
+
+ Create a file under /proc/pvr/<current process ID>. Apart from the
+ directory where the file is created, this works the same way as
+ CreateProcEntry. It's seq_file version.
+
+
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+ supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return Ptr to proc entry , 0 for failure
+
+*****************************************************************************/
struct proc_dir_entry* CreatePerProcessProcEntrySeq (
const IMG_CHAR * name,
IMG_VOID* data,
}
+/*!
+******************************************************************************
+
+ @Function : RemoveProcEntrySeq
+
+ @Description
+
+ Remove a single node (created using *Seq function) under /proc/pvr.
+
+ @Input proc_entry : structure returned by Create function.
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
{
if (dir)
}
}
+/*!
+******************************************************************************
+
+ @Function : RemovePerProcessProcEntry Seq
+
+ @Description
+
+ Remove a single node under the per process proc directory (created by *Seq function).
+
+ Remove a single node (created using *Seq function) under /proc/pvr.
+
+ @Input proc_entry : structure returned by Create function.
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
{
PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
}
}
+/*!
+******************************************************************************
+
+ @Function : pvr_read_proc_vm
+
+ @Description
+
+ When the user accesses the proc filesystem entry for the device, we are
+ called here to create the content for the 'file'. We can print anything we
+ want here. If the info we want to return is too big for one page ('count'
+ chars), we return successive chunks on each call. For a number of ways of
+ achieving this, refer to proc_file_read() in linux/fs/proc/generic.c.
+
+ Here, as we are accessing lists of information, we output '1' in '*start' to
+ instruct proc to advance 'off' by 1 on each call. The number of chars placed
+ in the buffer is returned. Multiple calls are made here by the proc
+ filesystem until we set *eof. We can return zero without setting eof to
+ instruct proc to flush 'page' (causing it to be printed) if there is not
+ enough space left (eg for a complete line).
+
+ @Input page : where to write the output
+
+ @Input start : memory location into which should be written next offset
+ to read from.
+
+ @Input off : the offset into the /proc file being read
+
+ @Input count : the size of the buffer 'page'
+
+ @Input eof : memory location into which 1 should be written when at EOF
+
+ @Input data : data specific to this /proc file entry
+
+ @Return : length of string written to page
+
+*****************************************************************************/
static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
IMG_INT count, IMG_INT *eof, IMG_VOID *data)
{
-
+ /* PRQA S 0307 1 */ /* ignore warning about casting to different pointer type */
pvr_read_proc_t *pprn = (pvr_read_proc_t *)data;
off_t len = pprn (page, (size_t)count, off);
len = 0;
*eof = 1;
}
- else if (!len)
+ else if (!len) /* not enough space in the buffer */
{
- *start = (IMG_CHAR *) 0;
+ *start = (IMG_CHAR *) 0; /* don't advance the offset */
}
else
{
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntryInDir
+
+ @Description
+
+ Create a file under the given directory. These dynamic files can be used at
+ runtime to get or set information about the device.
+
+ @Input pdir : parent directory
+
+ @Input name : the name of the file to create
+
+ @Input rhandler : the function to supply the content
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return success code : 0 or -errno.
+
+*****************************************************************************/
static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
{
struct proc_dir_entry * file;
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntry
+
+ @Description
+
+ Create a file under /proc/pvr. These dynamic files can be used at runtime
+ to get or set information about the device.
+
+ This interface is fuller than CreateProcReadEntry, and supports write access;
+ it is really just a wrapper for the native linux functions.
+
+ @Input name : the name of the file to create under /proc/pvr
+
+ @Input rhandler : the function to supply the content
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return success code : 0 or -errno.
+
+*****************************************************************************/
IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
{
return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
}
+/*!
+******************************************************************************
+
+ @Function : CreatePerProcessProcEntry
+
+ @Description
+
+ Create a file under /proc/pvr/<current process ID>. Apart from the
+ directory where the file is created, this works the same way as
+ CreateProcEntry.
+
+ @Input name : the name of the file to create under the per process /proc directory
+
+ @Input rhandler : the function to supply the content
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return success code : 0 or -errno.
+
+*****************************************************************************/
IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
{
PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcReadEntry
+
+ @Description
+
+ Create a file under /proc/pvr. These dynamic files can be used at runtime
+ to get information about the device. Creation WILL fail if proc support is
+ not compiled into the kernel. That said, the Linux kernel is not even happy
+ to build without /proc support these days.
+
+ @Input name : the name of the file to create
+
+ @Input handler : the function to call to provide the content
+
+ @Return 0 for success, -errno for failure
+
+*****************************************************************************/
IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
{
struct proc_dir_entry * file;
return -ENOMEM;
}
-
+ /* PRQA S 0307 1 */ /* ignore warning about casting to different pointer type */
file = create_proc_read_entry (name, S_IFREG | S_IRUGO, dir, pvr_read_proc, (IMG_VOID *)handler);
if (file)
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntries
+
+ @Description
+
+ Create a directory /proc/pvr and the necessary entries within it. These
+ dynamic files can be used at runtime to get information about the device.
+ Creation might fail if proc support is not compiled into the kernel or if
+ there is no memory
+
+ @Input none
+
+ @Return nothing
+
+*****************************************************************************/
IMG_INT CreateProcEntries(IMG_VOID)
{
dir = proc_mkdir (PVRProcDirRoot, NULL);
}
+/*!
+******************************************************************************
+
+ @Function : RemoveProcEntry
+
+ @Description
+
+ Remove a single node under /proc/pvr.
+
+ @Input name : the name of the node to remove
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
{
if (dir)
}
+/*!
+******************************************************************************
+
+ @Function : RemovePerProcessProcEntry
+
+ @Description
+
+ Remove a single node under the per process proc directory.
+
+ @Input name : the name of the node to remove
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
{
PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
}
+/*!
+******************************************************************************
+
+ @Function : RemovePerProcessProcDir
+
+ @Description
+
+ Remove the per process directorty under /proc/pvr.
+
+ @Input psPerProc : environment specific per process data
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
{
if (psPerProc->psProcDir)
}
}
+/*!
+******************************************************************************
+
+ @Function : RemoveProcEntries
+
+ Description
+
+ Proc filesystem entry deletion - Remove all proc filesystem entries for
+ the driver.
+
+ @Input none
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemoveProcEntries(IMG_VOID)
{
#ifdef DEBUG
RemoveProcEntrySeq( g_pProcDebugLevel );
#ifdef PVR_MANUAL_POWER_CONTROL
RemoveProcEntrySeq( g_pProcPowerLevel );
-#endif
+#endif /* PVR_MANUAL_POWER_CONTROL */
#endif
RemoveProcEntrySeq(g_pProcQueue);
remove_proc_entry(PVRProcDirRoot, NULL);
}
+/*****************************************************************************
+ FUNCTION : ProcSeqShowVersion
+
+ PURPOSE : Print the content of version to /proc file
+
+ PARAMETERS : sfile - /proc seq_file
+ el - Element to print
+*****************************************************************************/
static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
{
SYS_DATA *psSysData;
seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
}
+/*!
+******************************************************************************
+
+ @Function procDumpSysNodes (plus deviceTypeToString and deviceClassToString)
+
+ @Description
+
+ Format the contents of /proc/pvr/nodes
+
+ @Input buf : where to place format contents data.
+
+ @Input size : the size of the buffer into which to place data
+
+ @Input off : how far into the file we are.
+
+ @Return amount of data placed in buffer, 0, or END_OF_FILE :
+
+******************************************************************************/
static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
{
switch (deviceType)
}
}
+/*****************************************************************************
+ FUNCTION : ProcSeqShowSysNodes
+
+ PURPOSE : Print the content of version to /proc file
+
+ PARAMETERS : sfile - /proc seq_file
+ el - Element to print
+*****************************************************************************/
static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
{
PVRSRV_DEVICE_NODE *psDevNode;
psDevNode->hResManContext);
}
+/*****************************************************************************
+ FUNCTION : ProcSeqOff2ElementSysNodes
+
+ PURPOSE : Transale offset to element (/proc stuff)
+
+ PARAMETERS : sfile - /proc seq_file
+ off - the offset into the buffer
+
+ RETURNS : element to print
+*****************************************************************************/
static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
{
SYS_DATA *psSysData;
psSysData = SysAcquireDataNoCheck();
if (psSysData != IMG_NULL)
{
-
+ /* Find Dev Node */
psDevNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
DecOffPsDev_AnyVaCb,
&off);
}
-
+ /* Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL */
return (void*)psDevNode;
}
+/*****************************************************************************
+ End of file (proc.c)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Proc interface definition.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Functions for creating and reading proc filesystem entries.
+ Refer to proc.c
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __SERVICES_PROC_H__
#define __SERVICES_PROC_H__
-#include <asm/system.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
+#include <asm/system.h> // va_list etc
+#include <linux/proc_fs.h> // read_proc_t etc
+#include <linux/seq_file.h> // seq_file
#define END_OF_FILE (off_t) -1
} PVR_PROC_SEQ_HANDLERS;
+/** off2element function for elements with only ONE element (no header) */
void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off);
+/** off2element function for elements with only ONE element (+ header) */
void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off);
off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Bridge Module (kernel side)
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Receives calls from the user portion of services and
+ despatches them to functions in the kernel portion.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "img_defs.h"
#include "services.h"
#include "linkage.h"
#include "pvr_bridge_km.h"
#include "pvr_uaccess.h"
+#include "refcount.h"
+#include "buffer_manager.h"
#if defined(SUPPORT_DRI_DRM)
#include <drm/drmP.h>
#endif
#endif
+/* VGX: */
#if defined(SUPPORT_VGX)
#include "vgx_bridge.h"
#endif
+/* SGX: */
#if defined(SUPPORT_SGX)
#include "sgx_bridge.h"
#endif
#if defined(SUPPORT_MEMINFO_IDS)
static IMG_UINT64 ui64Stamp;
-#endif
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
PVRSRV_ERROR
LinuxBridgeInit(IMG_VOID)
#if defined(DEBUG_BRIDGE_KM)
+/*
+ * Lock MMap regions list (called on page start/stop while reading /proc/mmap)
+ *
+ * sfile : seq_file that handles /proc file
+ * start : TRUE if it's start, FALSE if it's stop
+ *
+ */
static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start)
{
if(start)
}
+/*
+ * Convert offset (index from KVOffsetTable) to element
+ * (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * off : index into the KVOffsetTable from which to print
+ *
+ * returns void* : Pointer to element that will be dumped
+ *
+*/
static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
{
if(!off)
return (void*)&g_BridgeDispatchTable[off-1];
}
+/*
+ * Gets next MMap element to show. (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ * off : index into the KVOffsetTable from which to print
+ *
+ * returns void* : Pointer to element to show (0 ends iteration)
+*/
static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
{
return ProcSeqOff2ElementBridgeStats(sfile,off);
}
+/*
+ * Show MMap element (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ *
+*/
static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
{
PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
psEntry->ui32CopyToUserTotalBytes);
}
-#endif
+#endif /* DEBUG_BRIDGE_KM */
#if defined(SUPPORT_DRI_DRM)
goto unlock_and_return;
}
-
+ /* FIXME - Currently the CopyFromUserWrapper which collects stats about
+ * how much data is shifted to/from userspace isn't available to us
+ * here. */
if(OSCopyFromUser(IMG_NULL,
psBridgePackageKM,
psBridgePackageUM,
}
else
{
-
+ /* lookup per-process data for this process */
psPerProc = PVRSRVPerProcessData(ui32PID);
if(psPerProc == IMG_NULL)
{
break;
}
-
+ /*
+ * The DRM file structure we are using for Services
+ * is not one that DRI authentication was done on.
+ * Look for an authenticated file structure for
+ * this process, making sure the DRM master is the
+ * same as ours.
+ */
psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
if (psEnvPerProc == IMG_NULL)
{
default:
break;
}
-#endif
+#endif /* defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) */
err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
if(err != PVRSRV_OK)
PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT =
(PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut;
PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+ IMG_HANDLE hMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
- if (pvr_get_user(psPrivateData->hKernelMemInfo, &psExportDeviceMemOUT->hMemInfo) != 0)
+ if (pvr_get_user(hMemInfo, &psExportDeviceMemOUT->hMemInfo) != 0)
{
err = -EFAULT;
goto unlock_and_return;
}
+
+ /* Look up the meminfo we just exported */
+ if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psKernelMemInfo,
+ hMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__));
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+
+ /* Bump the refcount; decremented on release of the fd */
+ PVRSRVKernelMemInfoIncRef(psKernelMemInfo);
+
+ /* Tell the XProc about the export if required */
+ if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+ {
+ BM_XProcIndexAcquire(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+ }
+
+ psPrivateData->hKernelMemInfo = hMemInfo;
#if defined(SUPPORT_MEMINFO_IDS)
psPrivateData->ui64Stamp = ++ui64Stamp;
+ psKernelMemInfo->ui64Stamp = psPrivateData->ui64Stamp;
if (pvr_put_user(psPrivateData->ui64Stamp, &psExportDeviceMemOUT->ui64Stamp) != 0)
{
err = -EFAULT;
#if defined(SUPPORT_MEMINFO_IDS)
case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY_2:
{
PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
(PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut;
}
break;
}
-#endif
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
default:
break;
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Debug Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides kernel side Debug Functionality
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <linux/string.h>
+#include <linux/string.h> // strncpy, strlen
#include <stdarg.h>
#include "img_types.h"
#include "servicesext.h"
#include "linkage.h"
#include "pvr_uaccess.h"
+#if !defined(CONFIG_PREEMPT)
+#define PVR_DEBUG_ALWAYS_USE_SPINLOCK
+#endif
+
static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
const IMG_CHAR* pszFormat, va_list VArgs)
IMG_FORMAT_PRINTF(3, 0);
const IMG_CHAR *pszFormat, ...)
IMG_FORMAT_PRINTF(3, 4);
+/* NOTE: Must NOT be static! Used in module.c.. */
IMG_UINT32 gPVRDebugLevel =
(DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING);
-#endif
+#endif /* defined(PVRSRV_NEED_PVR_DPF) || defined(PVRSRV_NEED_PVR_TRACE) */
#define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+/* Message buffer for non-IRQ messages */
static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+#endif
+/* Message buffer for IRQ messages */
static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+/* The lock is used to control access to gszBufferNonIRQ */
static PVRSRV_LINUX_MUTEX gsDebugMutexNonIRQ;
+#endif
-
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+/* The lock is used to control access to gszBufferIRQ */
+/* PRQA S 0671,0685 1 */ /* ignore warnings about C99 style initialisation */
static spinlock_t gsDebugLockIRQ = SPIN_LOCK_UNLOCKED;
#else
static DEFINE_SPINLOCK(gsDebugLockIRQ);
#endif
-#if !defined (USE_SPIN_LOCK)
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+#if !defined (USE_SPIN_LOCK) /* to keep QAC happy */
#define USE_SPIN_LOCK (in_interrupt() || !preemptible())
#endif
+#endif
static inline void GetBufferLock(unsigned long *pulLockFlags)
{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
if (USE_SPIN_LOCK)
+#endif
{
spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
}
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
else
{
LinuxLockMutex(&gsDebugMutexNonIRQ);
}
+#endif
}
static inline void ReleaseBufferLock(unsigned long ulLockFlags)
{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
if (USE_SPIN_LOCK)
+#endif
{
spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
}
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
else
{
LinuxUnLockMutex(&gsDebugMutexNonIRQ);
}
+#endif
}
static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
if (USE_SPIN_LOCK)
+#endif
{
*ppszBuf = gszBufferIRQ;
*pui32BufSiz = sizeof(gszBufferIRQ);
}
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
else
{
*ppszBuf = gszBufferNonIRQ;
*pui32BufSiz = sizeof(gszBufferNonIRQ);
}
+#endif
}
+/*
+ * Append a string to a buffer using formatted conversion.
+ * The function takes a variable number of arguments, pointed
+ * to by the var args list.
+ */
static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs)
{
IMG_UINT32 ui32Used;
i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
pszBuf[ui32BufSiz - 1] = 0;
-
+ /* Return true if string was truncated */
return (i32Len < 0 || i32Len >= (IMG_INT32)ui32Space) ? IMG_TRUE : IMG_FALSE;
}
+/* Actually required for ReleasePrintf too */
+
IMG_VOID PVRDPFInit(IMG_VOID)
{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
LinuxInitMutex(&gsDebugMutexNonIRQ);
+#endif
}
+/*!
+******************************************************************************
+ @Function PVRSRVReleasePrintf
+ @Description To output an important message to the user in release builds
+ @Input pszFormat - The message format string
+ @Input ... - Zero or more arguments for use by the format string
+ @Return None
+ ******************************************************************************/
IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
{
va_list vaArgs;
}
-#if defined(PVRSRV_NEED_PVR_ASSERT)
-
-IMG_VOID PVRSRVDebugAssertFail(const IMG_CHAR* pszFile, IMG_UINT32 uLine)
-{
- PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine, "Debug assertion failed!");
- BUG();
-}
-
-#endif
-
#if defined(PVRSRV_NEED_PVR_TRACE)
+/*!
+******************************************************************************
+ @Function PVRTrace
+ @Description To output a debug message to the user
+ @Input pszFormat - The message format string
+ @Input ... - Zero or more arguments for use by the format string
+ @Return None
+ ******************************************************************************/
IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
{
va_list VArgs;
va_end(VArgs);
}
-#endif
+#endif /* defined(PVRSRV_NEED_PVR_TRACE) */
#if defined(PVRSRV_NEED_PVR_DPF)
+/*
+ * Append a string to a buffer using formatted conversion.
+ * The function takes a variable number of arguments, calling
+ * VBAppend to do the actual work.
+ */
static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
{
va_list VArgs;
return bTrunc;
}
+/*!
+******************************************************************************
+ @Function PVRSRVDebugPrintf
+ @Description To output a debug message to the user
+ @Input uDebugLevel - The current debug level
+ @Input pszFile - The source file generating the message
+ @Input uLine - The line of the source file
+ @Input pszFormat - The message format string
+ @Input ... - Zero or more arguments for use by the format string
+ @Return None
+ ******************************************************************************/
IMG_VOID PVRSRVDebugPrintf (
IMG_UINT32 ui32DebugLevel,
const IMG_CHAR* pszFullFileName,
GetBufferLock(&ulLockFlags);
-
+ /* Add in the level of warning */
if (bTrace == IMG_FALSE)
{
switch(ui32DebugLevel)
}
else
{
-
+ /* Traces don't need a location */
if (bTrace == IMG_FALSE)
{
#ifdef DEBUG_LOG_PATH_TRUNCATE
-
+ /* Buffer for rewriting filepath in log messages */
static IMG_CHAR szFileNameRewrite[PVR_MAX_FILEPATH_LEN];
IMG_CHAR* pszTruncIter;
IMG_CHAR* pszTruncBackInter;
-
+ /* Truncate path (DEBUG_LOG_PATH_TRUNCATE shoud be set to EURASIA env var)*/
if (strlen(pszFullFileName) > strlen(DEBUG_LOG_PATH_TRUNCATE)+1)
pszFileName = pszFullFileName + strlen(DEBUG_LOG_PATH_TRUNCATE)+1;
-
+ /* Try to find '/../' entries and remove it together with
+ previous entry. Repeat unit all removed */
strncpy(szFileNameRewrite, pszFileName,PVR_MAX_FILEPATH_LEN);
if(strlen(szFileNameRewrite) == PVR_MAX_FILEPATH_LEN-1) {
while(*pszTruncIter++ != 0)
{
IMG_CHAR* pszNextStartPoint;
-
+ /* Find '/../' pattern */
if(
!( ( *pszTruncIter == '/' && (pszTruncIter-4 >= szFileNameRewrite) ) &&
( *(pszTruncIter-1) == '.') &&
( *(pszTruncIter-3) == '/') )
) continue;
-
+ /* Find previous '/' */
pszTruncBackInter = pszTruncIter - 3;
while(*(--pszTruncBackInter) != '/')
{
}
pszNextStartPoint = pszTruncBackInter;
-
+ /* Remove found region */
while(*pszTruncIter != 0)
{
*pszTruncBackInter++ = *pszTruncIter++;
}
*pszTruncBackInter = 0;
-
+ /* Start again */
pszTruncIter = pszNextStartPoint;
}
pszFileName = szFileNameRewrite;
-
+ /* Remove first '/' if exist (it's always relative path */
if(*pszFileName == '/') pszFileName++;
#endif
{
pszFileName = pszLeafName;
}
-#endif
+#endif /* __sh__ */
if (BAppend(pszBuf, ui32BufSiz, " [%u, %s]", ui32Line, pszFileName))
{
}
}
-#endif
+#endif /* PVRSRV_NEED_PVR_DPF */
#if defined(DEBUG)
IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
{
-#define _PROC_SET_BUFFER_SZ 2
+#define _PROC_SET_BUFFER_SZ 6
IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
- if (count != _PROC_SET_BUFFER_SZ)
+ if (count > _PROC_SET_BUFFER_SZ)
{
return -EINVAL;
}
return -EINVAL;
if (data_buffer[count - 1] != '\n')
return -EINVAL;
- gPVRDebugLevel = data_buffer[0] - '0';
+ if (sscanf(data_buffer, "%i", &gPVRDebugLevel) == 0)
+ return -EINVAL;
+ gPVRDebugLevel &= (1 << DBGPRIV_DBGLEVEL_COUNT) - 1;
}
return (count);
}
seq_printf(sfile, "%u\n", gPVRDebugLevel);
}
-#endif
+#endif /* defined(DEBUG) */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title PowerVR drm driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description linux module setup
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if defined(SUPPORT_DRI_DRM)
#include <linux/version.h>
#include "pvr_drm_mod.h"
#endif
+#if defined(NO_HARDWARE)
+#define PVR_DRM_NAME SYS_SGX_DEV_NAME
+#else
#define PVR_DRM_NAME PVRSRV_MODNAME
+#endif
+
#define PVR_DRM_DESC "Imagination Technologies PVR DRM"
+#define PVR_DRM_DATE "20110701"
+
+#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+#define PVR_NEW_STYLE_DRM_PLATFORM_DEV
+#else
+#define PVR_OLD_STYLE_DRM_PLATFORM_DEV
+#endif
+#endif
+
+/*
+ * Prior to Linux 2.6.36, we couldn't do the release processing in post close
+ * when workqueues were being used, because drm_release held the big kernel
+ * lock (BKL) when it called post close.
+ * If the resman needs to wait for processing being done by a workqueue,
+ * that processing won't complete whilst the lock is held by another thread,
+ * as the workqueue won't get scheduled.
+ */
+#undef PVR_DRI_DRM_USE_POST_CLOSE
+#if (defined(SUPPORT_DRI_DRM_EXT) && !defined(PVR_LINUX_USING_WORKQUEUES)) || \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+#define PVR_DRI_DRM_USE_POST_CLOSE
+#endif
+
DECLARE_WAIT_QUEUE_HEAD(sWaitForInit);
+#if defined(SUPPORT_DRM_MODESET)
+static struct drm_driver sPVRDrmDriver;
+#endif
+
+/* Once bInitComplete and bInitFailed are set, they stay set */
IMG_BOOL bInitComplete;
IMG_BOOL bInitFailed;
-#if !defined(PVR_DRI_DRM_NOT_PCI)
+#if !defined(PVR_DRI_DRM_NOT_PCI) && !defined(SUPPORT_DRI_DRM_PLUGIN)
#if defined(PVR_DRI_DRM_PLATFORM_DEV)
struct platform_device *gpsPVRLDMDev;
#else
#define PVR_DRM_FILE struct drm_file *
-#if !defined(SUPPORT_DRI_DRM_EXT)
+#if !defined(SUPPORT_DRI_DRM_EXT) && !defined(SUPPORT_DRI_DRM_PLUGIN)
#if defined(PVR_DRI_DRM_PLATFORM_DEV)
-#if defined(PVR_LDM_PLATFORM_PRE_REGISTERED)
+#if defined(PVR_LDM_PLATFORM_PRE_REGISTERED) || defined(NO_HARDWARE)
static struct platform_device_id asPlatIdList[] = {
{SYS_SGX_DEV_NAME, 0},
{}
};
#endif
-#else
+#else /* defined(PVR_DRI_DRM_PLATFORM_DEV) */
static struct pci_device_id asPciIdList[] = {
#if defined(PVR_DRI_DRM_NOT_PCI)
{1, 1, 1, 1, 0, 0, 0},
-#else
+#else /* defined(PVR_DRI_DRM_NOT_PCI) */
{SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
#if defined(SYS_SGX_DEV1_DEVICE_ID)
{SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-#endif
-#endif
+#endif /* defined(SYS_SGX_DEV1_DEVICE_ID) */
+#endif /* defined(PVR_DRI_DRM_NOT_PCI) */
{0}
};
-#endif
-#endif
+#endif /* defined(PVR_DRI_DRM_PLATFORM_DEV) */
+#endif /* !defined(SUPPORT_DRI_DRM_EXT) */
DRI_DRM_STATIC int
PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags)
PVR_TRACE(("PVRSRVDrmLoad"));
gpsPVRDRMDev = dev;
-#if !defined(PVR_DRI_DRM_NOT_PCI)
+#if !defined(PVR_DRI_DRM_NOT_PCI) && !defined(SUPPORT_DRI_DRM_PLUGIN)
#if defined(PVR_DRI_DRM_PLATFORM_DEV)
gpsPVRLDMDev = dev->platformdev;
#else
goto exit;
}
#endif
-
+ /* Module initialisation */
iRes = PVRCore_Init();
if (iRes != 0)
{
return PVRSRVOpen(dev, file);
}
-#if defined(SUPPORT_DRI_DRM_EXT) && !defined(PVR_LINUX_USING_WORKQUEUES)
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE) || defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+DRI_DRM_STATIC int
+PVRSRVDrmRelease(struct drm_device *dev, struct drm_file *file)
+#else
DRI_DRM_STATIC void
PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file)
+#endif
{
PVRSRVRelease(file->driver_priv);
file->driver_priv = NULL;
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+ return 0;
+#endif
}
#else
DRI_DRM_STATIC int
if (ret != 0)
{
-
+ /*
+ * An error means drm_release didn't call drm_lastclose,
+ * but it will have freed file_priv.
+ */
PVR_DPF((PVR_DBG_ERROR, "%s : drm_release failed: %d",
__FUNCTION__, ret));
}
}
#endif
+#if defined(SUPPORT_DRM_MODESET)
+static int
+PVRSRVPciProbe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ PVR_TRACE(("PVRSRVPciProbe"));
+
+ return drm_get_dev(dev, id, &sPVRDrmDriver);
+}
+
+static void
+PVRSRVPciRemove(struct pci_dev *dev)
+{
+ struct drm_device *psDrmDev;
+
+ PVR_TRACE(("PVRSRVPciRemove"));
+
+ psDrmDev = pci_get_drvdata(dev);
+ drm_put_dev(psDrmDev);
+}
+#endif
+
+/*
+ * For Linux 2.6.33 and above, the DRM ioctl entry point is of the unlocked
+ * variety. The big kernel lock is still taken for ioctls, unless
+ * the DRM_UNLOCKED flag is set. If you revise one of the driver specific
+ * ioctls, or add a new one, consider whether the gPVRSRVLock mutex needs
+ * to be taken.
+ */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
#define PVR_DRM_FOPS_IOCTL .unlocked_ioctl
#define PVR_DRM_UNLOCKED DRM_UNLOCKED
#endif
};
+#if !defined(SUPPORT_DRI_DRM_PLUGIN)
static int pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls);
+#endif
-#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT)
+#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) && \
+ !defined(SUPPORT_DRI_DRM_PLUGIN)
static int PVRSRVDrmProbe(struct platform_device *pDevice);
static int PVRSRVDrmRemove(struct platform_device *pDevice);
-#endif
+#endif /* defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) */
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+static PVRSRV_DRM_PLUGIN sPVRDrmPlugin =
+{
+ .name = PVR_DRM_NAME,
+ .open = PVRSRVDrmOpen,
+ .load = PVRSRVDrmLoad,
+ .unload = PVRSRVDrmUnload,
+
+ .release = PVRSRVDrmRelease,
+
+ .mmap = PVRMMap,
+
+ .ioctls = sPVRDrmIoctls,
+ .num_ioctls = DRM_ARRAY_SIZE(sPVRDrmIoctls),
+ .ioctl_start = 0
+};
+#else /* defined(SUPPORT_DRI_DRM_PLUGIN) */
static struct drm_driver sPVRDrmDriver =
{
-#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+#if defined(PVR_OLD_STYLE_DRM_PLATFORM_DEV)
.driver_features = DRIVER_USE_PLATFORM_DEVICE,
#else
.driver_features = 0,
.load = PVRSRVDrmLoad,
.unload = PVRSRVDrmUnload,
.open = PVRSRVDrmOpen,
-#if !defined(PVR_DRI_DRM_PLATFORM_DEV)
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE)
+ .postclose = PVRSRVDrmPostClose,
+#endif
+#if !defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRM_MODESET)
.suspend = PVRSRVDriverSuspend,
.resume = PVRSRVDriverResume,
#endif
{
.owner = THIS_MODULE,
.open = drm_open,
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE)
+ .release = drm_release,
+#else
.release = PVRSRVDrmRelease,
+#endif
PVR_DRM_FOPS_IOCTL = drm_ioctl,
.mmap = PVRMMap,
.poll = drm_poll,
.fasync = drm_fasync,
},
-#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+#if defined(PVR_OLD_STYLE_DRM_PLATFORM_DEV)
.platform_driver =
{
.id_table = asPlatIdList,
.shutdown = PVRSRVDriverShutdown,
},
#else
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
.pci_driver =
{
.name = PVR_DRM_NAME,
.id_table = asPciIdList,
+#if defined(SUPPORT_DRM_MODESET)
+ .probe = PVRSRVPciProbe,
+ .remove = PVRSRVPciRemove,
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+#endif
},
-#else
- .kdriver =
- {
- PVR_DRM_NAME,
- asPciIdList,
- },
#endif
#endif
.name = PVR_DRM_NAME,
.desc = PVR_DRM_DESC,
- .date = PVR_BUILD_DATE,
+ .date = PVR_DRM_DATE,
.major = PVRVERSION_MAJ,
.minor = PVRVERSION_MIN,
.patchlevel = PVRVERSION_BUILD,
};
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
-static struct pci_driver pci_pvr_driver = {
- .name = PVR_DRM_NAME,
- .id_table = asPciIdList,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) && !defined(PVR_DRI_DRM_PLATFORM_DEV)
+static struct pci_driver sPVRPCIDriver =
+{
+ .name = PVR_DRM_NAME,
+ .id_table = asPciIdList,
+#if defined(SUPPORT_DRM_MODESET)
+ .probe = PVRSRVPciProbe,
+ .remove = PVRSRVPciRemove,
+#endif
+};
+#endif
+
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+#if defined(NO_HARDWARE)
+static void PVRSRVDeviceRelease(struct device unref__ *pDevice)
+{
+}
+
+static struct platform_device sPVRPlatDevice = {
+ .name = PVR_DRM_NAME,
+ .id = -1,
+ .dev = {
+ .release = PVRSRVDeviceRelease
+ }
+};
+#endif
+
+static struct platform_driver sPVRPlatDriver =
+{
+ .id_table = asPlatIdList,
+ .driver =
+ {
+ .name = PVR_DRM_NAME,
+ },
+ .probe = PVRSRVDrmProbe,
+ .remove = PVRSRVDrmRemove,
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+ .shutdown = PVRSRVDriverShutdown,
};
#endif
+#endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */
-#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT)
+#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) && \
+ !defined(SUPPORT_DRI_DRM_PLUGIN)
static int
PVRSRVDrmProbe(struct platform_device *pDevice)
{
PVR_TRACE(("PVRSRVDrmProbe"));
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+ gpsPVRLDMDev = pDevice;
+
+ return drm_platform_init(&sPVRDrmDriver, gpsPVRLDMDev);
+#else
return drm_get_platform_dev(pDevice, &sPVRDrmDriver);
+#endif
}
static int
{
PVR_TRACE(("PVRSRVDrmRemove"));
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+ drm_platform_exit(&sPVRDrmDriver, gpsPVRLDMDev);
+#else
drm_put_dev(gpsPVRDRMDev);
-
+#endif
return 0;
}
+#endif
-#endif
static int __init PVRSRVDrmInit(void)
{
int iRes;
+#if !defined(SUPPORT_DRI_DRM_PLUGIN)
sPVRDrmDriver.num_ioctls = pvr_max_ioctl;
+#endif
-
+#if defined(SUPPORT_DRM_MODESET)
+ sPVRDrmDriver.driver_features |= DRIVER_MODESET;
+#endif
+
+ /* Must come before attempting to print anything via Services */
PVRDPFInit();
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+ iRes = platform_driver_register(&sPVRPlatDriver);
+#if defined(NO_HARDWARE)
+ if (iRes == 0)
+ {
+ iRes = platform_device_register(&sPVRPlatDevice);
+ if (iRes != 0)
+ {
+ platform_driver_unregister(&sPVRPlatDriver);
+ }
+ }
+#endif
+#else /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+ iRes = SysDRMRegisterPlugin(&sPVRDrmPlugin);
+#else /* defined(SUPPORT_DRI_DRM_PLUGIN) */
#if defined(PVR_DRI_DRM_NOT_PCI)
iRes = drm_pvr_dev_add();
if (iRes != 0)
return iRes;
}
#endif
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
- iRes = drm_init(&sPVRDrmDriver);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+ iRes = drm_platform_init(&sPVRDrmDriver, gpsPVRLDMDev);
#else
- iRes = drm_pci_init(&sPVRDrmDriver,&pci_pvr_driver);
+ iRes = drm_pci_init(&sPVRDrmDriver, &sPVRPCIDriver);
#endif
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+ iRes = drm_init(&sPVRDrmDriver);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+
#if defined(PVR_DRI_DRM_NOT_PCI)
if (iRes != 0)
{
drm_pvr_dev_remove();
}
#endif
+#endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#endif /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
return iRes;
}
static void __exit PVRSRVDrmExit(void)
{
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
- drm_exit(&sPVRDrmDriver);
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+#if defined(NO_HARDWARE)
+ platform_device_unregister(&sPVRPlatDevice);
+#endif
+ platform_driver_unregister(&sPVRPlatDriver);
+#else /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+ SysDRMUnregisterPlugin(&sPVRDrmPlugin);
+#else /* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+ drm_platform_exit(&sPVRDrmDriver, gpsPVRLDMDev);
#else
- drm_pci_exit(&sPVRDrmDriver,&pci_pvr_driver);
+ drm_pci_exit(&sPVRDrmDriver, &sPVRPCIDriver);
#endif
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+ drm_exit(&sPVRDrmDriver);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
#if defined(PVR_DRI_DRM_NOT_PCI)
drm_pvr_dev_remove();
#endif
+#endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#endif /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
}
+/*
+ * These macro calls define the initialisation and removal functions of the
+ * driver. Although they are prefixed `module_', they apply when compiling
+ * statically as well; in both cases they define the function the kernel will
+ * run to start/stop the driver.
+*/
module_init(PVRSRVDrmInit);
module_exit(PVRSRVDrmExit);
-#endif
-#endif
+#endif /* !defined(SUPPORT_DRI_DRM_EXT) */
+#endif /* defined(SUPPORT_DRI_DRM) */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title PowerVR drm driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description drm module
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined(__PVR_DRM_H__)
#define __PVR_DRM_H__
int PVRSRVOpen(struct drm_device *dev, struct drm_file *pFile);
void PVRSRVRelease(void *pvPrivData);
+#if !defined(SUPPORT_DRI_DRM_PLUGIN)
#if defined(PVR_DRI_DRM_PLATFORM_DEV)
void PVRSRVDriverShutdown(LDM_DEV *pDevice);
int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state);
int PVRSRVDriverResume(LDM_DEV *pDevice);
#else
+#if defined(SUPPORT_DRM_MODESET)
+int PVRSRVDriverSuspend(struct pci_dev *pDevice, pm_message_t state);
+int PVRSRVDriverResume(struct pci_dev *pDevice);
+#else
int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state);
int PVRSRVDriverResume(struct drm_device *pDevice);
-#endif
+#endif /* defined(SUPPORT_DRM_MODESET) */
+#endif /* defined(PVR_DRI_DRM_PLATFORM_DEV) */
+#endif /* !defined(SUPPORT_DRI_DRM_PLUGIN) */
int PVRSRV_BridgeDispatchKM(struct drm_device *dev, void *arg, struct drm_file *pFile);
#if defined(SUPPORT_DRI_DRM_EXT)
#define DRI_DRM_STATIC
+/*Exported functions to common drm layer*/
int PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags);
int PVRSRVDrmUnload(struct drm_device *dev);
int PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file);
int PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
#else
#define DRI_DRM_STATIC static
-#endif
+#endif /* defined(SUPPORT_DRI_DRM_EXT) */
#if defined(DISPLAY_CONTROLLER)
extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device *);
#endif
#if !defined(SUPPORT_DRI_DRM_EXT)
+/*
+ * We need the command number names to begin with "DRM_" for newer versions
+ * of the macro used to fill out the DRM ioctl table. Similarly, the
+ * ioctl number names must begin with "DRM_IOCTL_". The suffixes for the
+ * two sets of strings must match (e.g. end with "PVR_SRVKM" in both
+ * cases).
+ */
+
#define DRM_PVR_SRVKM PVR_DRM_SRVKM_CMD
#define DRM_PVR_IS_MASTER PVR_DRM_IS_MASTER_CMD
#define DRM_PVR_UNPRIV PVR_DRM_UNPRIV_CMD
#define DRM_PVR_DBGDRV PVR_DRM_DBGDRV_CMD
#define DRM_PVR_DISP PVR_DRM_DISP_CMD
+/* IOCTL numbers, relative to DRM_COMMAND_BASE */
#define DRM_IOCTL_PVR_SRVKM _IO(0, DRM_PVR_SRVKM)
#define DRM_IOCTL_PVR_IS_MASTER _IO(0, DRM_PVR_IS_MASTER)
#define DRM_IOCTL_PVR_UNPRIV _IO(0, DRM_PVR_UNPRIV)
#define DRM_IOCTL_PVR_DBGDRV _IO(0, DRM_PVR_DBGDRV)
#define DRM_IOCTL_PVR_DISP _IO(0, DRM_PVR_DISP)
-#endif
+#endif /* !defined(SUPPORT_DRI_DRM_EXT) */
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+typedef struct {
+ char *name;
+
+ int (*load)(struct drm_device *dev, unsigned long flags);
+ int (*unload)(struct drm_device *dev);
+
+ int (*open)(struct drm_device *dev, struct drm_file *file);
+ int (*release)(struct drm_device *dev, struct drm_file *file);
+
+ int (*mmap)(struct file* pFile, struct vm_area_struct* ps_vma);
+
+ struct drm_ioctl_desc *ioctls;
+ int num_ioctls;
+ int ioctl_start;
+} PVRSRV_DRM_PLUGIN;
+
+int SysDRMRegisterPlugin(PVRSRV_DRM_PLUGIN *psDRMPlugin);
+void SysDRMUnregisterPlugin(PVRSRV_DRM_PLUGIN *psDRMPlugin);
+#endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */
-#endif
+#endif /* defined(SUPPORT_DRI_DRM) */
-#endif
+#endif /* defined(__PVR_DRM_H__) */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Utility functions for user space access
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __PVR_UACCESS_H__
#define __PVR_UACCESS_H__
static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pvFrom, unsigned long ulBytes)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-
+ /*
+ * The compile time correctness checking introduced for copy_from_user in
+ * Linux 2.6.33 isn't fully comaptible with our usage of the function.
+ */
if (access_ok(VERIFY_READ, pvFrom, ulBytes))
{
return __copy_from_user(pvTo, pvFrom, ulBytes);
#define pvr_put_user put_user
#define pvr_get_user get_user
-#endif
+#endif /* __PVR_UACCESS_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OCP HW definitions.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _OCPDEFS_H_
#define _OCPDEFS_H_
+/* Register EUR_CR_OCP_REVISION */
#define EUR_CR_OCP_REVISION 0xFE00
#define EUR_CR_OCP_REVISION_REV_MASK 0xFFFFFFFFUL
#define EUR_CR_OCP_REVISION_REV_SHIFT 0
#define EUR_CR_OCP_REVISION_REV_SIGNED 0
+/* Register EUR_CR_OCP_HWINFO */
#define EUR_CR_OCP_HWINFO 0xFE04
#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_MASK 0x00000003UL
#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_SHIFT 0
#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_SHIFT 2
#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_SIGNED 0
+/* Register EUR_CR_OCP_SYSCONFIG */
#define EUR_CR_OCP_SYSCONFIG 0xFE10
#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_MASK 0x0000000CUL
#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_SHIFT 2
#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_SHIFT 4
#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_0 */
#define EUR_CR_OCP_IRQSTATUS_RAW_0 0xFE24
#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_1 */
#define EUR_CR_OCP_IRQSTATUS_RAW_1 0xFE28
#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_2 */
#define EUR_CR_OCP_IRQSTATUS_RAW_2 0xFE2C
#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_0 */
#define EUR_CR_OCP_IRQSTATUS_0 0xFE30
#define EUR_CR_OCP_IRQSTATUS_0_INIT_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_0_INIT_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_0_INIT_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_1 */
#define EUR_CR_OCP_IRQSTATUS_1 0xFE34
#define EUR_CR_OCP_IRQSTATUS_1_TARGET_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_1_TARGET_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_1_TARGET_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_2 */
#define EUR_CR_OCP_IRQSTATUS_2 0xFE38
#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_SET_0 */
#define EUR_CR_OCP_IRQENABLE_SET_0 0xFE3C
#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_SET_1 */
#define EUR_CR_OCP_IRQENABLE_SET_1 0xFE40
#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_SET_2 */
#define EUR_CR_OCP_IRQENABLE_SET_2 0xFE44
#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_CLR_0 */
#define EUR_CR_OCP_IRQENABLE_CLR_0 0xFE48
#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_CLR_1 */
#define EUR_CR_OCP_IRQENABLE_CLR_1 0xFE4C
#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_CLR_2 */
#define EUR_CR_OCP_IRQENABLE_CLR_2 0xFE50
#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_SIGNED 0
+/* Register EUR_CR_OCP_PAGE_CONFIG */
#define EUR_CR_OCP_PAGE_CONFIG 0xFF00
#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_MASK 0x00000001UL
#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_SHIFT 0
#define EUR_CR_OCP_PAGE_CONFIG_SIZE_SHIFT 3
#define EUR_CR_OCP_PAGE_CONFIG_SIZE_SIGNED 0
+/* Register EUR_CR_OCP_INTERRUPT_EVENT */
#define EUR_CR_OCP_INTERRUPT_EVENT 0xFF04
#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_MASK 0x00000001UL
#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_SHIFT 0
#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_SHIFT 10
#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_SIGNED 0
+/* Register EUR_CR_OCP_DEBUG_CONFIG */
#define EUR_CR_OCP_DEBUG_CONFIG 0xFF08
#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_MASK 0x00000003UL
#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_SHIFT 0
#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_SHIFT 31
#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_SIGNED 0
+/* Register EUR_CR_OCP_DEBUG_STATUS */
#define EUR_CR_OCP_DEBUG_STATUS 0xFF0C
#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_MASK 0x00000003UL
#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_SHIFT 0
#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_SIGNED 0
-#endif
+#endif /* _OCPDEFS_H_ */
+/*****************************************************************************
+ End of file (ocpdefs.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Hardware defs for SGX530.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _SGX530DEFS_KM_H_
#define _SGX530DEFS_KM_H_
+/* Register EUR_CR_CLKGATECTL */
#define EUR_CR_CLKGATECTL 0x0000
#define EUR_CR_CLKGATECTL_2D_CLKG_MASK 0x00000003U
#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT 0
#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT 20
#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+/* Register EUR_CR_CLKGATESTATUS */
#define EUR_CR_CLKGATESTATUS 0x0004
#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK 0x00000001U
#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT 0
#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK 0x00100000U
#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+/* Register EUR_CR_CLKGATECTLOVR */
#define EUR_CR_CLKGATECTLOVR 0x0008
#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK 0x00000003U
#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT 0
#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK 0x00300000U
#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+/* Register EUR_CR_CORE_ID */
#define EUR_CR_CORE_ID 0x0010
#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFU
#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
#define EUR_CR_CORE_ID_ID_SHIFT 16
+/* Register EUR_CR_CORE_REVISION */
#define EUR_CR_CORE_REVISION 0x0014
#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
#define EUR_CR_DESIGNER_REV_FIELD1 0x0018
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
#define EUR_CR_DESIGNER_REV_FIELD2 0x001C
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+/* Register EUR_CR_SOFT_RESET */
#define EUR_CR_SOFT_RESET 0x0080
#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000040U
#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 6
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS2 */
#define EUR_CR_EVENT_STATUS2 0x0118
#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 4
#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS */
#define EUR_CR_EVENT_STATUS 0x012CU
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
#define EUR_CR_EVENT_HOST_ENABLE 0x0130
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
#define EUR_CR_EVENT_HOST_CLEAR 0x0134
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_PDS_EXEC_BASE */
#define EUR_CR_PDS_EXEC_BASE 0x0AB8
#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_EVENT_KICKER */
#define EUR_CR_EVENT_KICKER 0x0AC4
#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0x0FFFFFF0U
#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+/* Register EUR_CR_EVENT_KICK */
#define EUR_CR_EVENT_KICK 0x0AC8
#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+/* Register EUR_CR_EVENT_TIMER */
#define EUR_CR_EVENT_TIMER 0x0ACC
#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+/* Register EUR_CR_PDS_INV0 */
#define EUR_CR_PDS_INV0 0x0AD0
#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV1 */
#define EUR_CR_PDS_INV1 0x0AD4
#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV2 */
#define EUR_CR_PDS_INV2 0x0AD8
#define EUR_CR_PDS_INV2_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV2_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV3 */
#define EUR_CR_PDS_INV3 0x0ADC
#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV_CSC */
#define EUR_CR_PDS_INV_CSC 0x0AE0
#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+/* Register EUR_CR_PDS_PC_BASE */
#define EUR_CR_PDS_PC_BASE 0x0B2C
#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x3FFFFFFFU
#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+/* Register EUR_CR_BIF_CTRL */
#define EUR_CR_BIF_CTRL 0x0C00
#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+/* Register EUR_CR_BIF_INT_STAT */
#define EUR_CR_BIF_INT_STAT 0x0C04
#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFU
#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+/* Register EUR_CR_BIF_FAULT */
#define EUR_CR_BIF_FAULT 0x0C08
#define EUR_CR_BIF_FAULT_ADDR_MASK 0x0FFFF000U
#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_TWOD_REQ_BASE */
#define EUR_CR_BIF_TWOD_REQ_BASE 0x0C88
#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_TA_REQ_BASE */
#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_2D_BLIT_STATUS */
#define EUR_CR_2D_BLIT_STATUS 0x0E04
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x00FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_MASK 0x03000000U
#define EUR_CR_USE_CODE_BASE_DM_SHIFT 24
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
#define EUR_CR_MNE_CR_CTRL 0x0D00
#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_SHIFT 0
#define EUR_CR_MNE_CR_CTRL_INVAL 0x0D20
-#endif
+#endif /* _SGX530DEFS_KM_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Hardware defs for SGX540.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _SGX540DEFS_KM_H_
#define _SGX540DEFS_KM_H_
+/* Register EUR_CR_CLKGATECTL */
#define EUR_CR_CLKGATECTL 0x0000
#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000003U
#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 0
#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK 0x10000000U
#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+/* Register EUR_CR_CLKGATECTL2 */
#define EUR_CR_CLKGATECTL2 0x0004
#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK 0x00000003U
#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT 0
#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT 18
#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK 0x00300000U
#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+/* Register EUR_CR_CLKGATESTATUS */
#define EUR_CR_CLKGATESTATUS 0x0008
#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000001U
#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00100000U
#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 20
+/* Register EUR_CR_CLKGATECTLOVR */
#define EUR_CR_CLKGATECTLOVR 0x000C
#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000003U
#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x000C0000U
#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 18
+/* Register EUR_CR_POWER */
#define EUR_CR_POWER 0x001C
#define EUR_CR_POWER_PIPE_DISABLE_MASK 0x00000001U
#define EUR_CR_POWER_PIPE_DISABLE_SHIFT 0
+/* Register EUR_CR_CORE_ID */
#define EUR_CR_CORE_ID 0x0020
#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFU
#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
#define EUR_CR_CORE_ID_ID_SHIFT 16
+/* Register EUR_CR_CORE_REVISION */
#define EUR_CR_CORE_REVISION 0x0024
#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
#define EUR_CR_DESIGNER_REV_FIELD1 0x0028
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
#define EUR_CR_DESIGNER_REV_FIELD2 0x002C
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+/* Register EUR_CR_SOFT_RESET */
#define EUR_CR_SOFT_RESET 0x0080
#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00020000U
#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 17
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS2 */
#define EUR_CR_EVENT_STATUS2 0x0118
#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 4
#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS */
#define EUR_CR_EVENT_STATUS 0x012CU
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
#define EUR_CR_EVENT_HOST_ENABLE 0x0130
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
#define EUR_CR_EVENT_HOST_CLEAR 0x0134
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_TIMER */
#define EUR_CR_TIMER 0x0144
#define EUR_CR_TIMER_VALUE_MASK 0xFFFFFFFFU
#define EUR_CR_TIMER_VALUE_SHIFT 0
+/* Register EUR_CR_EVENT_KICK1 */
#define EUR_CR_EVENT_KICK1 0x0AB0
#define EUR_CR_EVENT_KICK1_NOW_MASK 0x000000FFU
#define EUR_CR_EVENT_KICK1_NOW_SHIFT 0
+/* Register EUR_CR_PDS_EXEC_BASE */
#define EUR_CR_PDS_EXEC_BASE 0x0AB8
#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_EVENT_KICK2 */
#define EUR_CR_EVENT_KICK2 0x0AC0
#define EUR_CR_EVENT_KICK2_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK2_NOW_SHIFT 0
+/* Register EUR_CR_EVENT_KICKER */
#define EUR_CR_EVENT_KICKER 0x0AC4
#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0x0FFFFFF0U
#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+/* Register EUR_CR_EVENT_KICK */
#define EUR_CR_EVENT_KICK 0x0AC8
#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+/* Register EUR_CR_EVENT_TIMER */
#define EUR_CR_EVENT_TIMER 0x0ACC
#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+/* Register EUR_CR_PDS_INV0 */
#define EUR_CR_PDS_INV0 0x0AD0
#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV1 */
#define EUR_CR_PDS_INV1 0x0AD4
#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+/* Register EUR_CR_EVENT_KICK3 */
#define EUR_CR_EVENT_KICK3 0x0AD8
#define EUR_CR_EVENT_KICK3_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK3_NOW_SHIFT 0
+/* Register EUR_CR_PDS_INV3 */
#define EUR_CR_PDS_INV3 0x0ADC
#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV_CSC */
#define EUR_CR_PDS_INV_CSC 0x0AE0
#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+/* Register EUR_CR_PDS_PC_BASE */
#define EUR_CR_PDS_PC_BASE 0x0B2C
#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x00FFFFFFU
#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+/* Register EUR_CR_BIF_CTRL */
#define EUR_CR_BIF_CTRL 0x0C00
#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+/* Register EUR_CR_BIF_INT_STAT */
#define EUR_CR_BIF_INT_STAT 0x0C04
#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFU
#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+/* Register EUR_CR_BIF_FAULT */
#define EUR_CR_BIF_FAULT 0x0C08
#define EUR_CR_BIF_FAULT_SB_MASK 0x000001F0U
#define EUR_CR_BIF_FAULT_SB_SHIFT 4
#define EUR_CR_BIF_FAULT_ADDR_MASK 0x0FFFF000U
#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_TA_REQ_BASE */
#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_2D_BLIT_STATUS */
#define EUR_CR_2D_BLIT_STATUS 0x0E04
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x00FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_MASK 0x03000000U
#define EUR_CR_USE_CODE_BASE_DM_SHIFT 24
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
-#endif
+#endif /* _SGX540DEFS_KM_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Hardware defs for SGX544.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _SGX544DEFS_KM_H_
#define _SGX544DEFS_KM_H_
+/* Register EUR_CR_CLKGATECTL */
#define EUR_CR_CLKGATECTL 0x0000
#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000003U
#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 0
#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK 0x10000000U
#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATECTL2 */
#define EUR_CR_CLKGATECTL2 0x0004
#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK 0x00000003U
#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT 0
#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_MASK 0x0C000000U
#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_SHIFT 26
#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATESTATUS */
#define EUR_CR_CLKGATESTATUS 0x0008
#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000001U
#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_MASK 0x01000000U
#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_SHIFT 24
#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_SIGNED 0
+/* Register EUR_CR_CLKGATECTLOVR */
#define EUR_CR_CLKGATECTLOVR 0x000C
#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000003U
#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_MASK 0x00300000U
#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_SHIFT 20
#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_SIGNED 0
+/* Register EUR_CR_POWER */
#define EUR_CR_POWER 0x001C
#define EUR_CR_POWER_PIPE_DISABLE_MASK 0x00000001U
#define EUR_CR_POWER_PIPE_DISABLE_SHIFT 0
#define EUR_CR_POWER_PIPE_DISABLE_SIGNED 0
+/* Register EUR_CR_CORE_ID */
#define EUR_CR_CORE_ID 0x0020
#define EUR_CR_CORE_ID_CONFIG_MULTI_MASK 0x00000001U
#define EUR_CR_CORE_ID_CONFIG_MULTI_SHIFT 0
#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
#define EUR_CR_CORE_ID_ID_SHIFT 16
#define EUR_CR_CORE_ID_ID_SIGNED 0
+/* Register EUR_CR_CORE_REVISION */
#define EUR_CR_CORE_REVISION 0x0024
#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
#define EUR_CR_CORE_REVISION_DESIGNER_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
#define EUR_CR_DESIGNER_REV_FIELD1 0x0028
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
#define EUR_CR_DESIGNER_REV_FIELD2 0x002C
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SIGNED 0
+/* Register EUR_CR_SOFT_RESET */
#define EUR_CR_SOFT_RESET 0x0080
#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK 0x00080000U
#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_SHIFT 19
#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS2 */
#define EUR_CR_EVENT_STATUS2 0x0118
#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS */
#define EUR_CR_EVENT_STATUS 0x012C
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
#define EUR_CR_EVENT_HOST_ENABLE 0x0130
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
#define EUR_CR_EVENT_HOST_CLEAR 0x0134
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_TIMER */
#define EUR_CR_TIMER 0x0144
#define EUR_CR_TIMER_VALUE_MASK 0xFFFFFFFFU
#define EUR_CR_TIMER_VALUE_SHIFT 0
#define EUR_CR_TIMER_VALUE_SIGNED 0
+/* Register EUR_CR_EVENT_KICK1 */
#define EUR_CR_EVENT_KICK1 0x0AB0
#define EUR_CR_EVENT_KICK1_NOW_MASK 0x000000FFU
#define EUR_CR_EVENT_KICK1_NOW_SHIFT 0
#define EUR_CR_EVENT_KICK1_NOW_SIGNED 0
+/* Register EUR_CR_EVENT_KICK2 */
#define EUR_CR_EVENT_KICK2 0x0AC0
#define EUR_CR_EVENT_KICK2_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK2_NOW_SHIFT 0
#define EUR_CR_EVENT_KICK2_NOW_SIGNED 0
+/* Register EUR_CR_EVENT_KICKER */
#define EUR_CR_EVENT_KICKER 0x0AC4
#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
#define EUR_CR_EVENT_KICKER_ADDRESS_SIGNED 0
+/* Register EUR_CR_EVENT_KICK */
#define EUR_CR_EVENT_KICK 0x0AC8
#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
#define EUR_CR_EVENT_KICK_NOW_SIGNED 0
+/* Register EUR_CR_EVENT_TIMER */
#define EUR_CR_EVENT_TIMER 0x0ACC
#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
#define EUR_CR_EVENT_TIMER_VALUE_SIGNED 0
+/* Register EUR_CR_PDS_INV0 */
#define EUR_CR_PDS_INV0 0x0AD0
#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV0_DSC_SHIFT 0
#define EUR_CR_PDS_INV0_DSC_SIGNED 0
+/* Register EUR_CR_PDS_INV1 */
#define EUR_CR_PDS_INV1 0x0AD4
#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV1_DSC_SHIFT 0
#define EUR_CR_PDS_INV1_DSC_SIGNED 0
+/* Register EUR_CR_EVENT_KICK3 */
#define EUR_CR_EVENT_KICK3 0x0AD8
#define EUR_CR_EVENT_KICK3_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK3_NOW_SHIFT 0
#define EUR_CR_EVENT_KICK3_NOW_SIGNED 0
+/* Register EUR_CR_PDS_INV3 */
#define EUR_CR_PDS_INV3 0x0ADC
#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV3_DSC_SHIFT 0
#define EUR_CR_PDS_INV3_DSC_SIGNED 0
+/* Register EUR_CR_PDS_INV_CSC */
#define EUR_CR_PDS_INV_CSC 0x0AE0
#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
#define EUR_CR_PDS_INV_CSC_KICK_SIGNED 0
+/* Register EUR_CR_BIF_CTRL */
#define EUR_CR_BIF_CTRL 0x0C00
#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_MASK 0x00080000U
#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SHIFT 19
#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SIGNED 0
+/* Register EUR_CR_BIF_INT_STAT */
#define EUR_CR_BIF_INT_STAT 0x0C04
#define EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK 0x00003FFFU
#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SHIFT 0
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00080000U
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 19
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SIGNED 0
+/* Register EUR_CR_BIF_FAULT */
#define EUR_CR_BIF_FAULT 0x0C08
#define EUR_CR_BIF_FAULT_CID_MASK 0x0000000FU
#define EUR_CR_BIF_FAULT_CID_SHIFT 0
#define EUR_CR_BIF_FAULT_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
#define EUR_CR_BIF_FAULT_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_TILE0 */
#define EUR_CR_BIF_TILE0 0x0C0C
#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT 0
#define EUR_CR_BIF_TILE0_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE0_CFG_SHIFT 24
#define EUR_CR_BIF_TILE0_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE1 */
#define EUR_CR_BIF_TILE1 0x0C10
#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT 0
#define EUR_CR_BIF_TILE1_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE1_CFG_SHIFT 24
#define EUR_CR_BIF_TILE1_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE2 */
#define EUR_CR_BIF_TILE2 0x0C14
#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT 0
#define EUR_CR_BIF_TILE2_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE2_CFG_SHIFT 24
#define EUR_CR_BIF_TILE2_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE3 */
#define EUR_CR_BIF_TILE3 0x0C18
#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT 0
#define EUR_CR_BIF_TILE3_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE3_CFG_SHIFT 24
#define EUR_CR_BIF_TILE3_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE4 */
#define EUR_CR_BIF_TILE4 0x0C1C
#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT 0
#define EUR_CR_BIF_TILE4_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE4_CFG_SHIFT 24
#define EUR_CR_BIF_TILE4_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE5 */
#define EUR_CR_BIF_TILE5 0x0C20
#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT 0
#define EUR_CR_BIF_TILE5_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE5_CFG_SHIFT 24
#define EUR_CR_BIF_TILE5_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE6 */
#define EUR_CR_BIF_TILE6 0x0C24
#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT 0
#define EUR_CR_BIF_TILE6_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE6_CFG_SHIFT 24
#define EUR_CR_BIF_TILE6_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE7 */
#define EUR_CR_BIF_TILE7 0x0C28
#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT 0
#define EUR_CR_BIF_TILE7_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE7_CFG_SHIFT 24
#define EUR_CR_BIF_TILE7_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE8 */
#define EUR_CR_BIF_TILE8 0x0C2C
#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT 0
#define EUR_CR_BIF_TILE8_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE8_CFG_SHIFT 24
#define EUR_CR_BIF_TILE8_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE9 */
#define EUR_CR_BIF_TILE9 0x0C30
#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT 0
#define EUR_CR_BIF_TILE9_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE9_CFG_SHIFT 24
#define EUR_CR_BIF_TILE9_CFG_SIGNED 0
+/* Register EUR_CR_BIF_CTRL_INVAL */
#define EUR_CR_BIF_CTRL_INVAL 0x0C34
#define EUR_CR_BIF_CTRL_INVAL_PTE_MASK 0x00000004U
#define EUR_CR_BIF_CTRL_INVAL_PTE_SHIFT 2
#define EUR_CR_BIF_CTRL_INVAL_ALL_MASK 0x00000008U
#define EUR_CR_BIF_CTRL_INVAL_ALL_SHIFT 3
#define EUR_CR_BIF_CTRL_INVAL_ALL_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE1 */
#define EUR_CR_BIF_DIR_LIST_BASE1 0x0C38
#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE2 */
#define EUR_CR_BIF_DIR_LIST_BASE2 0x0C3C
#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE3 */
#define EUR_CR_BIF_DIR_LIST_BASE3 0x0C40
#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE4 */
#define EUR_CR_BIF_DIR_LIST_BASE4 0x0C44
#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE5 */
#define EUR_CR_BIF_DIR_LIST_BASE5 0x0C48
#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE6 */
#define EUR_CR_BIF_DIR_LIST_BASE6 0x0C4C
#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE7 */
#define EUR_CR_BIF_DIR_LIST_BASE7 0x0C50
#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_SET */
#define EUR_CR_BIF_BANK_SET 0x0C74
#define EUR_CR_BIF_BANK_SET_SELECT_2D_MASK 0x00000001U
#define EUR_CR_BIF_BANK_SET_SELECT_2D_SHIFT 0
#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_MASK 0x00000200U
#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SHIFT 9
#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SIGNED 0
+/* Register EUR_CR_BIF_BANK0 */
#define EUR_CR_BIF_BANK0 0x0C78
#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK 0x0000000FU
#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT 0
#define EUR_CR_BIF_BANK0_INDEX_PTLA_MASK 0x000F0000U
#define EUR_CR_BIF_BANK0_INDEX_PTLA_SHIFT 16
#define EUR_CR_BIF_BANK0_INDEX_PTLA_SIGNED 0
+/* Register EUR_CR_BIF_BANK1 */
#define EUR_CR_BIF_BANK1 0x0C7C
#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK 0x0000000FU
#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT 0
#define EUR_CR_BIF_BANK1_INDEX_3D_MASK 0x0000F000U
#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT 12
#define EUR_CR_BIF_BANK1_INDEX_3D_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_TA_REQ_BASE */
#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0xFFF00000U
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
#define EUR_CR_BIF_MEM_REQ_STAT_READS_SIGNED 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0xFFF00000U
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0xFFF00000U
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_STATUS */
#define EUR_CR_BIF_BANK_STATUS 0x0CB4
#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001U
#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002U
#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SIGNED 0
+/* Register EUR_CR_BIF_MMU_CTRL */
#define EUR_CR_BIF_MMU_CTRL 0x0CD0
#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_MASK 0x00000001U
#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_SHIFT 0
#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_MASK 0x00000020U
#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_SHIFT 5
#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_SIGNED 0
+/* Register EUR_CR_2D_BLIT_STATUS */
#define EUR_CR_2D_BLIT_STATUS 0x0E04
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
#define EUR_CR_2D_BLIT_STATUS_BUSY_SIGNED 0
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SIGNED 0
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0_START */
#define EUR_CR_BREAKPOINT0_START 0x0F44
#define EUR_CR_BREAKPOINT0_START_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT0_START_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT0_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0_END */
#define EUR_CR_BREAKPOINT0_END 0x0F48
#define EUR_CR_BREAKPOINT0_END_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT0_END_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT0_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0 */
#define EUR_CR_BREAKPOINT0 0x0F4C
#define EUR_CR_BREAKPOINT0_MASK_DM_MASK 0x00000038U
#define EUR_CR_BREAKPOINT0_MASK_DM_SHIFT 3
#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK 0x00000001U
#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT 0
#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1_START */
#define EUR_CR_BREAKPOINT1_START 0x0F50
#define EUR_CR_BREAKPOINT1_START_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT1_START_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT1_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1_END */
#define EUR_CR_BREAKPOINT1_END 0x0F54
#define EUR_CR_BREAKPOINT1_END_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT1_END_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT1_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1 */
#define EUR_CR_BREAKPOINT1 0x0F58
#define EUR_CR_BREAKPOINT1_MASK_DM_MASK 0x00000038U
#define EUR_CR_BREAKPOINT1_MASK_DM_SHIFT 3
#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_MASK 0x00000001U
#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_SHIFT 0
#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2_START */
#define EUR_CR_BREAKPOINT2_START 0x0F5C
#define EUR_CR_BREAKPOINT2_START_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT2_START_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT2_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2_END */
#define EUR_CR_BREAKPOINT2_END 0x0F60
#define EUR_CR_BREAKPOINT2_END_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT2_END_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT2_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2 */
#define EUR_CR_BREAKPOINT2 0x0F64
#define EUR_CR_BREAKPOINT2_MASK_DM_MASK 0x00000038U
#define EUR_CR_BREAKPOINT2_MASK_DM_SHIFT 3
#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_MASK 0x00000001U
#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_SHIFT 0
#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3_START */
#define EUR_CR_BREAKPOINT3_START 0x0F68
#define EUR_CR_BREAKPOINT3_START_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT3_START_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT3_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3_END */
#define EUR_CR_BREAKPOINT3_END 0x0F6C
#define EUR_CR_BREAKPOINT3_END_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT3_END_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT3_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3 */
#define EUR_CR_BREAKPOINT3 0x0F70
#define EUR_CR_BREAKPOINT3_MASK_DM_MASK 0x00000038U
#define EUR_CR_BREAKPOINT3_MASK_DM_SHIFT 3
#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_MASK 0x00000001U
#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_SHIFT 0
#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT_READ */
#define EUR_CR_BREAKPOINT_READ 0x0F74
#define EUR_CR_BREAKPOINT_READ_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT_READ_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT_READ_ADDRESS_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP */
#define EUR_CR_PARTITION_BREAKPOINT_TRAP 0x0F78
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT */
#define EUR_CR_PARTITION_BREAKPOINT 0x0F7C
#define EUR_CR_PARTITION_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
#define EUR_CR_PARTITION_BREAKPOINT_MODULE_ID_SHIFT 6
#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_MASK 0x00000004U
#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_SHIFT 2
#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0 */
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0 0x0F80
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1 */
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1 0x0F84
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_0 */
#define EUR_CR_USE_CODE_BASE_0 0x0A0C
#define EUR_CR_USE_CODE_BASE_ADDR_00_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_00_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_00_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_00_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_00_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_1 */
#define EUR_CR_USE_CODE_BASE_1 0x0A10
#define EUR_CR_USE_CODE_BASE_ADDR_01_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_01_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_01_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_01_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_01_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_2 */
#define EUR_CR_USE_CODE_BASE_2 0x0A14
#define EUR_CR_USE_CODE_BASE_ADDR_02_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_02_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_02_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_02_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_02_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_3 */
#define EUR_CR_USE_CODE_BASE_3 0x0A18
#define EUR_CR_USE_CODE_BASE_ADDR_03_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_03_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_03_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_03_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_03_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_4 */
#define EUR_CR_USE_CODE_BASE_4 0x0A1C
#define EUR_CR_USE_CODE_BASE_ADDR_04_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_04_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_04_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_04_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_04_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_5 */
#define EUR_CR_USE_CODE_BASE_5 0x0A20
#define EUR_CR_USE_CODE_BASE_ADDR_05_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_05_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_05_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_05_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_05_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_6 */
#define EUR_CR_USE_CODE_BASE_6 0x0A24
#define EUR_CR_USE_CODE_BASE_ADDR_06_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_06_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_06_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_06_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_06_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_7 */
#define EUR_CR_USE_CODE_BASE_7 0x0A28
#define EUR_CR_USE_CODE_BASE_ADDR_07_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_07_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_07_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_07_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_07_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_8 */
#define EUR_CR_USE_CODE_BASE_8 0x0A2C
#define EUR_CR_USE_CODE_BASE_ADDR_08_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_08_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_08_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_08_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_08_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_9 */
#define EUR_CR_USE_CODE_BASE_9 0x0A30
#define EUR_CR_USE_CODE_BASE_ADDR_09_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_09_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_09_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_09_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_09_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_10 */
#define EUR_CR_USE_CODE_BASE_10 0x0A34
#define EUR_CR_USE_CODE_BASE_ADDR_10_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_10_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_10_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_10_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_10_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_11 */
#define EUR_CR_USE_CODE_BASE_11 0x0A38
#define EUR_CR_USE_CODE_BASE_ADDR_11_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_11_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_11_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_11_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_11_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_12 */
#define EUR_CR_USE_CODE_BASE_12 0x0A3C
#define EUR_CR_USE_CODE_BASE_ADDR_12_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_12_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_12_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_12_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_12_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_13 */
#define EUR_CR_USE_CODE_BASE_13 0x0A40
#define EUR_CR_USE_CODE_BASE_ADDR_13_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_13_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_13_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_13_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_13_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_14 */
#define EUR_CR_USE_CODE_BASE_14 0x0A44
#define EUR_CR_USE_CODE_BASE_ADDR_14_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_14_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_14_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_14_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_14_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_15 */
#define EUR_CR_USE_CODE_BASE_15 0x0A48
#define EUR_CR_USE_CODE_BASE_ADDR_15_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_15_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_15_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_15_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_15_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP */
#define EUR_CR_PIPE0_BREAKPOINT_TRAP 0x0F88
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT */
#define EUR_CR_PIPE0_BREAKPOINT 0x0F8C
#define EUR_CR_PIPE0_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
#define EUR_CR_PIPE0_BREAKPOINT_MODULE_ID_SHIFT 6
#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_MASK 0x00000004U
#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_SHIFT 2
#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0 */
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0 0x0F90
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1 */
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1 0x0F94
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP */
#define EUR_CR_PIPE1_BREAKPOINT_TRAP 0x0F98
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT */
#define EUR_CR_PIPE1_BREAKPOINT 0x0F9C
#define EUR_CR_PIPE1_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
#define EUR_CR_PIPE1_BREAKPOINT_MODULE_ID_SHIFT 6
#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_MASK 0x00000004U
#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_SHIFT 2
#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0 */
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0 0x0FA0
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1 */
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1 0x0FA4
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_SIGNED 0
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
-#endif
+#endif /* _SGX544DEFS_KM_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX hw definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _SGXDEFS_H_
#define _SGXDEFS_H_
#include "sgxmpplusdefs.h"
#else
#include "sgxmpdefs.h"
-#endif
-#else
+#endif /* SGX554 */
+#else /* SGX_FEATURE_MP */
#if defined(SGX_FEATURE_SYSTEM_CACHE)
#include "mnemedefs.h"
#endif
-#endif
+#endif /* SGX_FEATURE_MP */
+
+/*****************************************************************************
+ Core specific defines.
+*****************************************************************************/
-#endif
+#endif /* _SGXDEFS_H_ */
+/*****************************************************************************
+ End of file (sgxdefs.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX HW errata definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Specifies associations between SGX core revisions
+ and SW workarounds required to fix HW errata that exist
+ in specific core revisions
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _SGXERRATA_KM_H_
#define _SGXERRATA_KM_H_
+/* ignore warnings about unrecognised preprocessing directives in conditional inclusion directives */
+/* PRQA S 3115 ++ */
+
#if defined(SGX520) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX520 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 100
- #define FIX_HW_BRN_28889
- #else
#if SGX_CORE_REV == 111
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX520 Core Revision unspecified"
#endif
#endif
- #endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX530) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX530 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 110
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
- #else
- #if SGX_CORE_REV == 111
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
- #else
- #if SGX_CORE_REV == 1111
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
- #else
#if SGX_CORE_REV == 120
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 121
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 125
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 130
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX530 Core Revision unspecified"
#endif
#endif
#endif
- #endif
- #endif
- #endif
#endif
#endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX531) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX531 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
#if SGX_CORE_REV == 101
- #define FIX_HW_BRN_26620
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_26620/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 110
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX531 Core Revision unspecified"
#endif
#endif
#endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if (defined(SGX535) || defined(SGX535_V1_1)) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX535 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 112
- #define FIX_HW_BRN_23281
- #define FIX_HW_BRN_23410
- #define FIX_HW_BRN_22693
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_22997
- #define FIX_HW_BRN_23030
- #else
- #if SGX_CORE_REV == 113
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_23281
- #define FIX_HW_BRN_23944
- #define FIX_HW_BRN_23410
- #else
#if SGX_CORE_REV == 121
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_23944
- #define FIX_HW_BRN_23410
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_23944/* Workaround in code (services) */
+ #define FIX_HW_BRN_23410/* Workaround in code (services) and ucode */
#else
#if SGX_CORE_REV == 126
- #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX535 Core Revision unspecified"
#endif
#endif
#endif
- #endif
- #endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX540) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX540 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
#if SGX_CORE_REV == 101
- #define FIX_HW_BRN_25499
- #define FIX_HW_BRN_25503
- #define FIX_HW_BRN_26620
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_25499/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_25503/* Workaround in code (services) */
+ #define FIX_HW_BRN_26620/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 110
- #define FIX_HW_BRN_25503
- #define FIX_HW_BRN_26620
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_25503/* Workaround in code (services) */
+ #define FIX_HW_BRN_26620/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 120
- #define FIX_HW_BRN_26620
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_26620/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 121
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 130
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX540 Core Revision unspecified"
#endif
#endif
#endif
#endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
-#if defined(SGX541) && !defined(SGX_CORE_DEFINED)
- #if defined(SGX_FEATURE_MP)
-
- #define SGX_CORE_REV_HEAD 0
- #if defined(USE_SGX_CORE_REV_HEAD)
-
- #define SGX_CORE_REV SGX_CORE_REV_HEAD
- #endif
-
- #if SGX_CORE_REV == 100
- #define FIX_HW_BRN_27270
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_27510
-
- #else
- #if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
- #else
- #error "sgxerrata.h: SGX541 Core Revision unspecified"
- #endif
- #endif
-
- #define SGX_CORE_DEFINED
- #else
- #error "sgxerrata.h: SGX541 only supports MP configs (SGX_FEATURE_MP)"
- #endif
-#endif
#if defined(SGX543) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX543 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 113
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_29997
- #define FIX_HW_BRN_30954
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_32044
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
- #define FIX_HW_BRN_36513
- #else
#if SGX_CORE_REV == 122
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_29997
- #define FIX_HW_BRN_30954
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
+ #define FIX_HW_BRN_29954/* turns off regbank split feature */
+ #define FIX_HW_BRN_29997/* workaround in services */
+ #define FIX_HW_BRN_30954/* workaround in services */
+ #define FIX_HW_BRN_31093/* workaround in services */
+ #define FIX_HW_BRN_31195/* workaround in services */
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #define FIX_HW_BRN_31278/* disabled prefetching in MMU */
+ #define FIX_HW_BRN_31542/* workaround in uKernel and Services */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_31620/* workaround in services */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #define FIX_HW_BRN_32044 /* workaround in uKernel, services and client drivers */
+ #define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
- #define FIX_HW_BRN_36513
-
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 1221
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
+ #define FIX_HW_BRN_29954/* turns off regbank split feature */
+ #define FIX_HW_BRN_31195/* workaround in services */
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #define FIX_HW_BRN_31278/* disabled prefetching in MMU */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_31671
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_31542/* workaround in uKernel and Services */
+ #define FIX_HW_BRN_31671/* workaround in uKernel */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #define FIX_HW_BRN_32044/* workaround in uKernel, services and client drivers */
+ #define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
- #define FIX_HW_BRN_36513
-
- #else
- #if SGX_CORE_REV == 140
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_30954
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
- #define FIX_HW_BRN_33920
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_36513
-
- #else
- #if SGX_CORE_REV == 1401
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_30954
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
- #define FIX_HW_BRN_33920
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_36513
-
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 141
- #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_29954/* turns off regbank split feature */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31671
- #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31671 /* workaround in uKernel */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_36513
-
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 142
- #define FIX_HW_BRN_29954
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31671
- #define FIX_HW_BRN_31780
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_36513
-
- #else
- #if SGX_CORE_REV == 211
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
+ #define FIX_HW_BRN_29954/* turns off regbank split feature */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_31671 /* workaround in uKernel */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
- #define FIX_HW_BRN_36513
-
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 2111
- #define FIX_HW_BRN_30982
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
+ #define FIX_HW_BRN_30982 /* workaround in uKernel and services */
+ #define FIX_HW_BRN_31093/* workaround in services */
+ #define FIX_HW_BRN_31195/* workaround in services */
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #define FIX_HW_BRN_31278/* disabled prefetching in MMU */
+ #define FIX_HW_BRN_31542/* workaround in uKernel and Services */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_31620/* workaround in services */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #define FIX_HW_BRN_32044 /* workaround in uKernel, services and client drivers */
+ #define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
- #define FIX_HW_BRN_36513
-
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 213
- #define FIX_HW_BRN_31272
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31671
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_31671 /* workaround in uKernel */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
- #define FIX_HW_BRN_36513
-
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 216
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_36513
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == 302
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == 303
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
#else
#error "sgxerrata.h: SGX543 Core Revision unspecified"
#endif
#endif
#endif
- #endif
- #endif
- #endif
- #endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX544) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX544 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 100
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #else
- #if SGX_CORE_REV == 102
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_31272
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32085
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_36513
- #endif
- #else
- #if SGX_CORE_REV == 103
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_31272
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32085
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
- #define FIX_HW_BRN_36513
- #else
#if SGX_CORE_REV == 104
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
+ #define FIX_HW_BRN_29954/* turns off regbank split feature */
+ #define FIX_HW_BRN_31093/* workaround in services */
+ #define FIX_HW_BRN_31195/* workaround in services */
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #define FIX_HW_BRN_31278/* disabled prefetching in MMU */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31671
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_31542 /* workaround in uKernel and Services */
+ #define FIX_HW_BRN_31620/* workaround in services */
+ #define FIX_HW_BRN_31671 /* workaround in uKernel */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #define FIX_HW_BRN_32044 /* workaround in uKernel, services and client drivers */
+ #define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
- #define FIX_HW_BRN_36513
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == 105
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
- #define FIX_HW_BRN_36513
- #else
- #if SGX_CORE_REV == 106
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_33920
- #else
- #if SGX_CORE_REV == 110
- #define FIX_HW_BRN_31272
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31780
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == 112
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == 114
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == 115
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #if defined(SGX_FEATURE_MP)
- #if SGX_FEATURE_MP_CORE_COUNT > 1
- #define FIX_HW_BRN_36513
- #endif
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ #else
+ #if SGX_CORE_REV == 116
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657/* workaround in ukernel */
#endif
+ #define FIX_HW_BRN_33809/* workaround in kernel (enable burst combiner) */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
#else
#error "sgxerrata.h: SGX544 Core Revision unspecified"
#endif
#endif
#endif
- #endif
- #endif
- #endif
- #endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX545) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX545 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 100
- #define FIX_HW_BRN_26620
- #define FIX_HW_BRN_27266
- #define FIX_HW_BRN_27456
- #define FIX_HW_BRN_29702
- #define FIX_HW_BRN_29823
- #else
#if SGX_CORE_REV == 109
- #define FIX_HW_BRN_29702
- #define FIX_HW_BRN_29823
- #define FIX_HW_BRN_31939
- #else
- #if SGX_CORE_REV == 1012
- #define FIX_HW_BRN_31939
- #else
- #if SGX_CORE_REV == 1013
- #define FIX_HW_BRN_31939
+ #define FIX_HW_BRN_29702/* Workaround in services */
+ #define FIX_HW_BRN_29823/* Workaround in services */
+ #define FIX_HW_BRN_31939/* workaround in uKernel */
#else
#if SGX_CORE_REV == 10131
#else
#if SGX_CORE_REV == 10141
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX545 Core Revision unspecified"
#endif
#endif
#endif
#endif
- #endif
- #endif
- #endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX554) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX554 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
#if SGX_CORE_REV == 1251
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_36513
-
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
#else
#error "sgxerrata.h: SGX554 Core Revision unspecified"
#endif
#endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#endif
#endif
-#endif
+/* restore warning */
+/* PRQA S 3115 -- */
+
+#endif /* _SGXERRATA_KM_H_ */
+/******************************************************************************
+ End of file (sgxerrata.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX fexture definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if defined(SGX520)
#define SGX_CORE_FRIENDLY_NAME "SGX520"
#define SGX_CORE_ID SGX_CORE_ID_520
#define SGX_FEATURE_AUTOCLOCKGATING
#define SGX_FEATURE_MONOLITHIC_UKERNEL
#define SGX_FEATURE_MULTI_EVENT_KICK
+// #define SGX_FEATURE_DATA_BREAKPOINTS
+// #define SGX_FEATURE_PERPIPE_BKPT_REGS
+// #define SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES (2)
+// #define SGX_FEATURE_2D_HARDWARE
+// #define SGX_FEATURE_PTLA
#define SGX_FEATURE_EXTENDED_PERF_COUNTERS
#define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING)
#if defined(SGX_FEATURE_MP)
#define SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH
- #endif
#define SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH
+ #endif
#define SGX_FEATURE_SW_ISP_CONTEXT_SWITCH
#endif
#else
#define SGX_FEATURE_MAX_TA_RENDER_TARGETS (512)
#define SGX_FEATURE_SECONDARY_REQUIRES_USE_KICK
#define SGX_FEATURE_WRITEBACK_DCU
-
-
+ //FIXME: this is defined in the build config for now
+ //#define SGX_FEATURE_36BIT_MMU
#define SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
#define SGX_FEATURE_MULTI_EVENT_KICK
#define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
#define SGX_FEATURE_AUTOCLOCKGATING
#define SGX_FEATURE_MONOLITHIC_UKERNEL
#define SGX_FEATURE_MULTI_EVENT_KICK
+// #define SGX_FEATURE_DATA_BREAKPOINTS
+// #define SGX_FEATURE_PERPIPE_BKPT_REGS
+// #define SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES (2)
#define SGX_FEATURE_2D_HARDWARE
#define SGX_FEATURE_PTLA
#define SGX_FEATURE_EXTENDED_PERF_COUNTERS
#if defined(SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH) \
|| defined(SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH)
+/* Enable the define so common code for HW VDMCS code is compiled */
#define SGX_FEATURE_VDM_CONTEXT_SWITCH
#endif
-#if defined(FIX_HW_BRN_22693)
-#undef SGX_FEATURE_AUTOCLOCKGATING
-#endif
+/*
+ 'switch-off' features if defined BRNs affect the feature
+*/
#if defined(FIX_HW_BRN_27266)
#undef SGX_FEATURE_36BIT_MMU
#endif
-#if defined(FIX_HW_BRN_27456)
-#undef SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
-#endif
-
#if defined(FIX_HW_BRN_22934) \
|| defined(FIX_HW_BRN_25499)
#undef SGX_FEATURE_MULTI_EVENT_KICK
#undef SGX_FEATURE_BIF_NUM_DIRLISTS
#endif
+/*
+ Derive other definitions:
+*/
+
+/* define default MP core count */
#if defined(SGX_FEATURE_MP)
#if defined(SGX_FEATURE_MP_CORE_COUNT_TA) && defined(SGX_FEATURE_MP_CORE_COUNT_3D)
#if (SGX_FEATURE_MP_CORE_COUNT_TA > SGX_FEATURE_MP_CORE_COUNT_3D)
#error Number of TA cores larger than number of 3D cores not supported in current driver
-#endif
+#endif /* (SGX_FEATURE_MP_CORE_COUNT_TA > SGX_FEATURE_MP_CORE_COUNT_3D) */
#else
#if defined(SGX_FEATURE_MP_CORE_COUNT)
#define SGX_FEATURE_MP_CORE_COUNT_TA (SGX_FEATURE_MP_CORE_COUNT)
#error Either SGX_FEATURE_MP_CORE_COUNT or \
both SGX_FEATURE_MP_CORE_COUNT_TA and SGX_FEATURE_MP_CORE_COUNT_3D \
must be defined when SGX_FEATURE_MP is defined
-#endif
-#endif
+#endif /* SGX_FEATURE_MP_CORE_COUNT */
+#endif /* defined(SGX_FEATURE_MP_CORE_COUNT_TA) && defined(SGX_FEATURE_MP_CORE_COUNT_3D) */
#else
#define SGX_FEATURE_MP_CORE_COUNT (1)
#define SGX_FEATURE_MP_CORE_COUNT_TA (1)
#define SGX_FEATURE_MP_CORE_COUNT_3D (1)
-#endif
+#endif /* SGX_FEATURE_MP */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && !defined(SUPPORT_SGX_PRIORITY_SCHEDULING)
#define SUPPORT_SGX_PRIORITY_SCHEDULING
#include "img_types.h"
+/******************************************************************************
+ End of file (sgxfeaturedefs.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX MMU defines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides SGX MMU declarations and macros
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined(__SGXMMU_KM_H__)
#define __SGXMMU_KM_H__
+/* to be implemented */
+
+/* SGX MMU maps 4Kb pages */
#define SGX_MMU_PAGE_SHIFT (12)
#define SGX_MMU_PAGE_SIZE (1U<<SGX_MMU_PAGE_SHIFT)
#define SGX_MMU_PAGE_MASK (SGX_MMU_PAGE_SIZE - 1U)
+/* PD details */
#define SGX_MMU_PD_SHIFT (10)
#define SGX_MMU_PD_SIZE (1U<<SGX_MMU_PD_SHIFT)
#define SGX_MMU_PD_MASK (0xFFC00000U)
+/* PD Entry details */
#if defined(SGX_FEATURE_36BIT_MMU)
#define SGX_MMU_PDE_ADDR_MASK (0xFFFFFF00U)
#define SGX_MMU_PDE_ADDR_ALIGNSHIFT (4)
#define SGX_MMU_PDE_ADDR_ALIGNSHIFT (0)
#endif
#define SGX_MMU_PDE_VALID (0x00000001U)
+/* variable page size control field */
#define SGX_MMU_PDE_PAGE_SIZE_4K (0x00000000U)
#define SGX_MMU_PDE_PAGE_SIZE_16K (0x00000002U)
#define SGX_MMU_PDE_PAGE_SIZE_64K (0x00000004U)
#define SGX_MMU_PDE_PAGE_SIZE_4M (0x0000000AU)
#define SGX_MMU_PDE_PAGE_SIZE_MASK (0x0000000EU)
+/* PT details */
#define SGX_MMU_PT_SHIFT (10)
#define SGX_MMU_PT_SIZE (1U<<SGX_MMU_PT_SHIFT)
#define SGX_MMU_PT_MASK (0x003FF000U)
+/* PT Entry details */
#if defined(SGX_FEATURE_36BIT_MMU)
#define SGX_MMU_PTE_ADDR_MASK (0xFFFFFF00U)
#define SGX_MMU_PTE_ADDR_ALIGNSHIFT (4)
#define SGX_MMU_PTE_CACHECONSISTENT (0x00000008U)
#define SGX_MMU_PTE_EDMPROTECT (0x00000010U)
-#endif
+#endif /* __SGXMMU_KM_H__ */
+/*****************************************************************************
+ End of file (sgxmmu.h)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Hardware defs for SGXMP.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
-#ifndef _SGXMPDEFS_H_
-#define _SGXMPDEFS_H_
+The contents of this file are subject to the MIT license as set out below.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGXMPDEFS_KM_H_
+#define _SGXMPDEFS_KM_H_
+
+/* Register EUR_CR_MASTER_BIF_CTRL */
#define EUR_CR_MASTER_BIF_CTRL 0x4C00
#define EUR_CR_MASTER_BIF_CTRL_NOREORDER_MASK 0x00000001U
#define EUR_CR_MASTER_BIF_CTRL_NOREORDER_SHIFT 0
#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_DPM_MASK 0x00080000U
#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SHIFT 19
#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SIGNED 0
+/* Register EUR_CR_MASTER_BIF_CTRL_INVAL */
#define EUR_CR_MASTER_BIF_CTRL_INVAL 0x4C34
#define EUR_CR_MASTER_BIF_CTRL_INVAL_PTE_MASK 0x00000004U
#define EUR_CR_MASTER_BIF_CTRL_INVAL_PTE_SHIFT 2
#define EUR_CR_MASTER_BIF_CTRL_INVAL_ALL_MASK 0x00000008U
#define EUR_CR_MASTER_BIF_CTRL_INVAL_ALL_SHIFT 3
#define EUR_CR_MASTER_BIF_CTRL_INVAL_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_BIF_MMU_CTRL */
#define EUR_CR_MASTER_BIF_MMU_CTRL 0x4CD0
#define EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_MASK 0x00000001U
#define EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_SHIFT 0
#define EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK 0x00000010U
#define EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_SHIFT 4
#define EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL */
#define EUR_CR_MASTER_SLC_CTRL 0x4D00
#define EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_MASK 0x00800000U
#define EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_SHIFT 23
#define EUR_CR_MASTER_SLC_CTRL_PAUSE_MASK 0x00000100U
#define EUR_CR_MASTER_SLC_CTRL_PAUSE_SHIFT 8
#define EUR_CR_MASTER_SLC_CTRL_PAUSE_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_BYPASS */
#define EUR_CR_MASTER_SLC_CTRL_BYPASS 0x4D04
#define EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_N_MASK 0x08000000U
#define EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_N_SHIFT 27
#define EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_MASK 0x00000001U
#define EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_SHIFT 0
#define EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_USSE_INVAL */
#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL 0x4D08
#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_ADDR_MASK 0xFFFFFFFFU
#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_ADDR_SHIFT 0
#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_ADDR_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_INVAL */
#define EUR_CR_MASTER_SLC_CTRL_INVAL 0x4D28
#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_EVENT_MASK 0x00000008U
#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_EVENT_SHIFT 3
#define EUR_CR_MASTER_SLC_CTRL_INVAL_ALL_MASK 0x00000001U
#define EUR_CR_MASTER_SLC_CTRL_INVAL_ALL_SHIFT 0
#define EUR_CR_MASTER_SLC_CTRL_INVAL_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_FLUSH */
#define EUR_CR_MASTER_SLC_CTRL_FLUSH 0x4D2C
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_EVENT_MASK 0x00000080U
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_EVENT_SHIFT 7
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_ALL_MASK 0x00000010U
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_ALL_SHIFT 4
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_FLUSH_INV */
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV 0x4D34
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_EVENT_MASK 0x00000080U
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_EVENT_SHIFT 7
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_ALL_MASK 0x00000010U
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_ALL_SHIFT 4
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_READ */
#define EUR_CR_MASTER_BREAKPOINT_READ 0x4F18
#define EUR_CR_MASTER_BREAKPOINT_READ_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_MASTER_BREAKPOINT_READ_ADDRESS_SHIFT 4
#define EUR_CR_MASTER_BREAKPOINT_READ_ADDRESS_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_TRAP */
#define EUR_CR_MASTER_BREAKPOINT_TRAP 0x4F1C
#define EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
#define EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
#define EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
#define EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
#define EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT */
#define EUR_CR_MASTER_BREAKPOINT 0x4F20
#define EUR_CR_MASTER_BREAKPOINT_ID_MASK 0x00000030U
#define EUR_CR_MASTER_BREAKPOINT_ID_SHIFT 4
#define EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK 0x00000004U
#define EUR_CR_MASTER_BREAKPOINT_TRAPPED_SHIFT 2
#define EUR_CR_MASTER_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0 */
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0 0x4F24
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1 */
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1 0x4F28
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_MASTER_CORE */
#define EUR_CR_MASTER_CORE 0x4000
#define EUR_CR_MASTER_CORE_ENABLE_MASK 0x00000003U
#define EUR_CR_MASTER_CORE_ENABLE_SHIFT 0
#define EUR_CR_MASTER_CORE_ENABLE_SIGNED 0
+/* Register EUR_CR_MASTER_CORE_ID */
#define EUR_CR_MASTER_CORE_ID 0x4010
#define EUR_CR_MASTER_CORE_ID_CONFIG_MULTI_MASK 0x00000001U
#define EUR_CR_MASTER_CORE_ID_CONFIG_MULTI_SHIFT 0
#define EUR_CR_MASTER_CORE_ID_ID_MASK 0xFFFF0000U
#define EUR_CR_MASTER_CORE_ID_ID_SHIFT 16
#define EUR_CR_MASTER_CORE_ID_ID_SIGNED 0
+/* Register EUR_CR_MASTER_CORE_REVISION */
#define EUR_CR_MASTER_CORE_REVISION 0x4014
#define EUR_CR_MASTER_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
#define EUR_CR_MASTER_CORE_REVISION_MAINTENANCE_SHIFT 0
#define EUR_CR_MASTER_CORE_REVISION_DESIGNER_MASK 0xFF000000U
#define EUR_CR_MASTER_CORE_REVISION_DESIGNER_SHIFT 24
#define EUR_CR_MASTER_CORE_REVISION_DESIGNER_SIGNED 0
+/* Register EUR_CR_MASTER_SOFT_RESET */
#define EUR_CR_MASTER_SOFT_RESET 0x4080
#define EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(i) (0x00000001U << (0 + ((i) * 1)))
#define EUR_CR_MASTER_SOFT_RESET_CORE_RESET_SHIFT(i) (0 + ((i) * 1))
#define EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_SHIFT 10
#define EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_SIGNED 0
-#endif
+#endif /* _SGXMPDEFS_KM_H_ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Buffer Management.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Manages buffers mapped into two virtual memory spaces, host and
+ device and referenced by handles.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _BUFFER_MANAGER_H_
#define _BUFFER_MANAGER_H_
extern "C"{
#endif
+/* forward reference */
typedef struct _BM_HEAP_ BM_HEAP;
+/*
+ * The mapping structure is used to record relations between CPU virtual,
+ * CPU physical and device virtual addresses for large chunks of memory
+ * from which we have resource-allocator draw our buffers.
+ *
+ * There is one per contiguous pool and one per import from the host OS.
+ */
struct _BM_MAPPING_
{
enum
{
- hm_wrapped = 1,
- hm_wrapped_scatter,
- hm_wrapped_virtaddr,
- hm_wrapped_scatter_virtaddr,
- hm_env,
- hm_contiguous
+ hm_wrapped = 1, /*!< wrapped user supplied contiguous*/
+ hm_wrapped_scatter, /*!< wrapped user supplied scattered */
+ hm_wrapped_virtaddr, /*!< wrapped user supplied contiguous with virtual address*/
+ hm_wrapped_scatter_virtaddr, /*!< wrapped user supplied scattered with virtual address*/
+ hm_env, /*!< obtained from environment */
+ hm_contiguous /*!< contigous arena */
} eCpuMemoryOrigin;
- BM_HEAP *pBMHeap;
- RA_ARENA *pArena;
+ BM_HEAP *pBMHeap; /* which BM heap */
+ RA_ARENA *pArena; /* whence the memory comes */
IMG_CPU_VIRTADDR CpuVAddr;
IMG_CPU_PHYADDR CpuPAddr;
IMG_DEV_VIRTADDR DevVAddr;
IMG_SYS_PHYADDR *psSysAddr;
IMG_SIZE_T uSize;
+ IMG_SIZE_T uSizeVM;
IMG_HANDLE hOSMemHandle;
IMG_UINT32 ui32Flags;
+
+ /* Sparse mapping data */
+ IMG_UINT32 ui32ChunkSize;
+ IMG_UINT32 ui32NumVirtChunks;
+ IMG_UINT32 ui32NumPhysChunks;
+ IMG_BOOL *pabMapChunk;
};
+/*
+ * The buffer structure handles individual allocations from the user; thus
+ * there is one allocated per call to BM_Alloc and one per call to BM_Wrap.
+ * We record a mapping reference so we know where to return allocated
+ * resources at BM_Free time.
+ */
typedef struct _BM_BUF_
{
IMG_CPU_VIRTADDR *CpuVAddr;
struct _BM_HEAP_ *psNext;
struct _BM_HEAP_ **ppsThis;
+ /* BIF tile stride for this heap */
+ IMG_UINT32 ui32XTileStride;
};
+/*
+ * The bm-context structure
+ */
struct _BM_CONTEXT_
{
MMU_CONTEXT *psMMUContext;
-
+ /*
+ * Resource allocation arena of dual mapped pages. For devices
+ * where the hardware imposes different constraints on the valid
+ * device virtual address range depending on the use of the buffer
+ * we maintain two allocation arenas, one low address range, the
+ * other high. For devices without such a constrain we do not
+ * create the high arena, instead all allocations come from the
+ * low arena.
+ */
BM_HEAP *psBMHeap;
-
+ /*
+ * The Shared Heaps
+ */
BM_HEAP *psBMSharedHeap;
PVRSRV_DEVICE_NODE *psDeviceNode;
-
+ /*
+ * Hash table management.
+ */
HASH_TABLE *pBufferHash;
-
+ /*
+ * Resman item handle
+ */
IMG_HANDLE hResItem;
IMG_UINT32 ui32RefCount;
-
-
+ /*
+ linked list next pointer
+ */
struct _BM_CONTEXT_ *psNext;
struct _BM_CONTEXT_ **ppsThis;
};
-
-
+/* refcount.c needs to know the internals of this structure */
+typedef struct _XPROC_DATA_{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32AllocFlags;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32PageSize;
+ RA_ARENA *psArena;
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_VOID *pvCpuVAddr;
+ IMG_HANDLE hOSMemHandle;
+} XPROC_DATA;
+
+extern XPROC_DATA gXProcWorkaroundShareData[];
+/*
+ Buffer handle.
+*/
typedef IMG_VOID *BM_HANDLE;
+/** Buffer manager allocation flags.
+ *
+ * Flags passed to BM_Alloc to specify buffer capabilities.
+ *
+ * @defgroup BP Buffer Manager Allocation Flags
+ * @{
+ */
+
+/** Pool number mask. */
#define BP_POOL_MASK 0x7
+/* Request physically contiguous pages of memory */
#define BP_CONTIGUOUS (1 << 3)
#define BP_PARAMBUFFER (1 << 4)
#define BM_MAX_DEVMEM_ARENAS 2
+/** @} */
+
+/**
+ * @Function BM_CreateContext
+ *
+ * @Description
+ *
+ * @Input
+
+ * @Return
+ */
+
IMG_HANDLE
BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_DEV_PHYADDR *psPDDevPAddr,
IMG_BOOL *pbCreated);
+/**
+ * @Function BM_DestroyContext
+ *
+ * @Description
+ *
+ * @Input
+ *
+ * @Return PVRSRV_ERROR
+ */
PVRSRV_ERROR
BM_DestroyContext (IMG_HANDLE hBMContext,
IMG_BOOL *pbCreated);
+/**
+ * @Function BM_CreateHeap
+ *
+ * @Description
+ *
+ * @Input
+ *
+ * @Return
+ */
IMG_HANDLE
BM_CreateHeap (IMG_HANDLE hBMContext,
DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo);
+/**
+ * @Function BM_DestroyHeap
+ *
+ * @Description
+ *
+ * @Input
+ *
+ * @Return
+ */
IMG_VOID
BM_DestroyHeap (IMG_HANDLE hDevMemHeap);
+/**
+ * @Function BM_Reinitialise
+ *
+ * @Description
+ *
+ * Reinitialises the buffer manager after a power event. Calling this
+ * function will reprogram MMU registers and renable the MMU.
+ *
+ * @Input None
+ * @Return None
+ */
+
IMG_BOOL
BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode);
+/**
+ * @Function BM_Alloc
+ *
+ * @Description
+ *
+ * Allocate a buffer mapped into both host and device virtual memory
+ * maps.
+ *
+ * @Input uSize - require size in bytes of the buffer.
+ * @Input/Output pui32Flags - bit mask of buffer property flags + recieves heap flags.
+ * @Input uDevVAddrAlignment - required alignment in bytes, or 0.
+ * @Input pvPrivData - private data passed to OS allocator
+ * @Input ui32PrivDataLength - length of private data
+ * @Input ui32ChunkSize - Chunk size
+ * @Input ui32NumVirtChunks - Number of virtual chunks
+ * @Input ui32NumPhysChunks - Number of physical chunks
+ * @Input pabMapChunk - Chunk mapping array
+ * @Output phBuf - receives the buffer handle.
+ * @Return IMG_TRUE - Success, IMG_FALSE - Failed.
+ */
IMG_BOOL
BM_Alloc (IMG_HANDLE hDevMemHeap,
IMG_DEV_VIRTADDR *psDevVAddr,
IMG_SIZE_T uSize,
IMG_UINT32 *pui32Flags,
IMG_UINT32 uDevVAddrAlignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
BM_HANDLE *phBuf);
+/**
+ * @Function BM_Wrap
+ *
+ * @Description
+ *
+ * Create a buffer which wraps user provided host physical memory.
+ * The wrapped memory must be page aligned. BM_Wrap will roundup the
+ * size to a multiple of host pages.
+ *
+ * @Input ui32Size - size of memory to wrap.
+ * @Input ui32Offset - Offset into page of memory to wrap.
+ * @Input bPhysContig - Is the wrap physically contiguous.
+ * @Input psSysAddr - list of system physical page addresses of memory to wrap.
+ * @Input pvCPUVAddr - optional CPU kernel virtual address (Page aligned) of memory to wrap.
+ * @Input uFlags - bit mask of buffer property flags.
+ * @Input phBuf - receives the buffer handle.
+ * @Return IMG_TRUE - Success, IMG_FALSE - Failed
+ */
IMG_BOOL
BM_Wrap ( IMG_HANDLE hDevMemHeap,
IMG_SIZE_T ui32Size,
IMG_UINT32 *pui32Flags,
BM_HANDLE *phBuf);
+/**
+ * @Function BM_Free
+ *
+ * @Description
+ *
+ * Free a buffer previously allocated via BM_Alloc.
+ *
+ * @Input hBuf - buffer handle.
+ * @Return None.
+ */
IMG_VOID
BM_Free (BM_HANDLE hBuf,
IMG_UINT32 ui32Flags);
+/**
+ * @Function BM_HandleToCpuVaddr
+ *
+ * @Description
+ *
+ * Retrieve the host virtual address associated with a buffer.
+ *
+ * @Input hBuf - buffer handle.
+ *
+ * @Return buffers host virtual address.
+ */
IMG_CPU_VIRTADDR
BM_HandleToCpuVaddr (BM_HANDLE hBuf);
+/**
+ * @Function BM_HandleToDevVaddr
+ *
+ * @Description
+ *
+ * Retrieve the device virtual address associated with a buffer.
+ *
+ * @Input hBuf - buffer handle.
+ * @Return buffers device virtual address.
+ */
IMG_DEV_VIRTADDR
BM_HandleToDevVaddr (BM_HANDLE hBuf);
+/**
+ * @Function BM_HandleToSysPaddr
+ *
+ * @Description
+ *
+ * Retrieve the system physical address associated with a buffer.
+ *
+ * @Input hBuf - buffer handle.
+ * @Return buffers device virtual address.
+ */
IMG_SYS_PHYADDR
BM_HandleToSysPaddr (BM_HANDLE hBuf);
+/**
+ * @Function BM_HandleToMemOSHandle
+ *
+ * @Description
+ *
+ * Retrieve the underlying memory handle associated with a buffer.
+ *
+ * @Input hBuf - buffer handle.
+ * @Return An OS Specific memory handle
+ */
IMG_HANDLE
BM_HandleToOSMemHandle (BM_HANDLE hBuf);
+/**
+ * @Function BM_GetPhysPageAddr
+ *
+ * @Description
+ *
+ * Retreive physical address backing dev V address
+ *
+ * @Input psMemInfo
+ * @Input sDevVPageAddr
+ * @Output psDevPAddr
+ * @Return PVRSRV_ERROR
+ */
IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
IMG_DEV_VIRTADDR sDevVPageAddr,
IMG_DEV_PHYADDR *psDevPAddr);
+/*!
+******************************************************************************
+ @Function BM_GetMMUContext
+
+ @Description
+ utility function to return the MMU context
+
+ @inputs hDevMemHeap - the Dev mem heap handle
+
+ @Return MMU context, else NULL
+**************************************************************************/
MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap);
+/*!
+******************************************************************************
+ @Function BM_GetMMUContextFromMemContext
+
+ @Description
+ utility function to return the MMU context
+
+ @inputs hDevMemHeap - the Dev mem heap handle
+
+ @Return MMU context, else NULL
+**************************************************************************/
MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext);
+/*!
+******************************************************************************
+ @Function BM_GetMMUHeap
+
+ @Description
+ utility function to return the MMU heap handle
+
+ @inputs hDevMemHeap - the Dev mem heap handle
+
+ @Return MMU heap handle, else NULL
+**************************************************************************/
IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap);
+/*!
+******************************************************************************
+ @Function BM_GetDeviceNode
+
+ @Description utility function to return the devicenode from the BM Context
+
+ @inputs hDevMemContext - the Dev Mem Context
+
+ @Return MMU heap handle, else NULL
+**************************************************************************/
PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext);
+/*!
+******************************************************************************
+ @Function BM_GetMappingHandle
+
+ @Description utility function to return the mapping handle from a meminfo
+
+ @inputs psMemInfo - kernel meminfo
+
+ @Return mapping handle, else NULL
+**************************************************************************/
IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+/*!
+******************************************************************************
+ @Function BM_Export
+
+ @Description Export a buffer previously allocated via BM_Alloc.
+
+ @inputs hBuf - buffer handle.
+
+ @Return None.
+**************************************************************************/
IMG_VOID BM_Export(BM_HANDLE hBuf);
+/*!
+******************************************************************************
+ @Function BM_FreeExport
+
+ @Description Free a buffer previously exported via BM_Export.
+
+ @inputs hBuf - buffer handle.
+ ui32Flags - flags
+
+ @Return None.
+**************************************************************************/
IMG_VOID BM_FreeExport(BM_HANDLE hBuf, IMG_UINT32 ui32Flags);
+/*!
+******************************************************************************
+ @Function BM_MappingHandleFromBuffer
+
+ @Description utility function to get the BM mapping handle from a BM buffer
+
+ @Input hBuffer - Handle to BM buffer
+
+ @Return BM mapping handle
+**************************************************************************/
+IMG_HANDLE BM_MappingHandleFromBuffer(IMG_HANDLE hBuffer);
+
+/*!
+******************************************************************************
+ @Function BM_GetVirtualSize
+
+ @Description utility function to get the VM size of a BM mapping
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Return VM size of mapping
+**************************************************************************/
+IMG_UINT32 BM_GetVirtualSize(IMG_HANDLE hBMHandle);
+
+/*!
+******************************************************************************
+ @Function BM_MapPageAtOffset
+
+ @Description utility function check if the specificed offset in a BM mapping
+ is a page that needs tp be mapped
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Input ui32Offset - Offset into import
+
+ @Return IMG_TRUE if the page should be mapped
+**************************************************************************/
+IMG_BOOL BM_MapPageAtOffset(IMG_HANDLE hBMHandle, IMG_UINT32 ui32Offset);
+
+/*!
+******************************************************************************
+ @Function BM_VirtOffsetToPhyscial
+
+ @Description utility function find of physical offset of a sparse allocation
+ from it's virtual offset.
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Input ui32VirtOffset - Virtual offset into allocation
+
+ @Output pui32PhysOffset - Physical offset
+
+ @Return IMG_TRUE if the virtual offset is physically backed
+**************************************************************************/
+IMG_BOOL BM_VirtOffsetToPhysical(IMG_HANDLE hBMHandle,
+ IMG_UINT32 ui32VirtOffset,
+ IMG_UINT32 *pui32PhysOffset);
+
+/* The following are present for the "share mem" workaround for
+ cross-process mapping. This is only valid for a specific
+ use-case, and only tested on Linux (Android) and only
+ superficially at that. Do not rely on this API! */
+/* The two "Set" functions set a piece of "global" state in the buffer
+ manager, and "Unset" removes this global state. Therefore, there
+ is no thread-safety here and it's the caller's responsibility to
+ ensure that a mutex is acquired before using these functions or any
+ device memory allocation functions, including, especially,
+ callbacks from RA. */
+/* Once a "Share Index" is set by this means, any requests from the RA
+ to import a block of physical memory shall cause the physical
+ memory allocation to be refcounted, and shared iff the IDs chosen
+ match */
+/* This API is difficult to use, but saves a lot of plumbing in other
+ APIs. The next generation of this library should have this functionality
+ plumbed in properly */
PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index);
PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index);
PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32Index);
-IMG_UINT32 BM_XProcWorkaroundGetRefCount(IMG_UINT32 ui32Index);
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexAcquireDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index);
+IMG_VOID _BM_XProcIndexReleaseDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index);
+
+#define BM_XProcIndexAcquire(x...) \
+ _BM_XProcIndexAcquireDebug(__FILE__, __LINE__, x)
+#define BM_XProcIndexRelease(x...) \
+ _BM_XProcIndexReleaseDebug(__FILE__, __LINE__, x)
+
+#else
+IMG_VOID _BM_XProcIndexAcquire(IMG_UINT32 ui32Index);
+IMG_VOID _BM_XProcIndexRelease(IMG_UINT32 ui32Index);
+
+#define BM_XProcIndexAcquire(x) \
+ _BM_XProcIndexAcquire( x)
+#define BM_XProcIndexRelease(x) \
+ _BM_XProcIndexRelease( x)
+#endif
+
#if defined(__cplusplus)
}
#endif
#endif
-
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Common Device header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Device related function templates and defines
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __DEVICE_H__
#define __DEVICE_H__
extern "C" {
#endif
-#include "ra.h"
-#include "resman.h"
+#include "ra.h" /* RA_ARENA */
+#include "resman.h" /* PRESMAN_ITEM */
+/* BM context forward reference */
typedef struct _BM_CONTEXT_ BM_CONTEXT;
+/* pre-defined MMU structure forward references */
typedef struct _MMU_HEAP_ MMU_HEAP;
typedef struct _MMU_CONTEXT_ MMU_CONTEXT;
+/* physical resource types: */
+/* contiguous system memory */
#define PVRSRV_BACKINGSTORE_SYSMEM_CONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+0))
+/* non-contiguous system memory */
#define PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+1))
+/* contiguous local device memory */
#define PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+2))
+/* non-contiguous local device memory */
#define PVRSRV_BACKINGSTORE_LOCALMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+3))
+/* heap types: */
typedef IMG_UINT32 DEVICE_MEMORY_HEAP_TYPE;
#define DEVICE_MEMORY_HEAP_PERCONTEXT 0
#define DEVICE_MEMORY_HEAP_KERNEL 1
#define DEVICE_MEMORY_HEAP_SHARED_EXPORTED 3
#define PVRSRV_DEVICE_NODE_FLAGS_PORT80DISPLAY 1
-#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV 2
+#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV 2 /* FIXME : Optimal Invalidation is not default */
typedef struct _DEVICE_MEMORY_HEAP_INFO_
{
-
+ /* heap identifier */
IMG_UINT32 ui32HeapID;
-
+ /* heap identifier string */
IMG_CHAR *pszName;
-
+ /* backing store identifier string */
IMG_CHAR *pszBSName;
-
+ /* Device virtual address of base of heap */
IMG_DEV_VIRTADDR sDevVAddrBase;
-
+ /* heapsize in bytes */
IMG_UINT32 ui32HeapSize;
-
+ /* Flags, includes physical resource (backing store type). Must be available to SOC */
IMG_UINT32 ui32Attribs;
-
+ /* Heap type: per device, kernel only, shared, shared_exported */
DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
-
+ /* kernel heap handle */
IMG_HANDLE hDevMemHeap;
-
+ /* ptr to local memory allocator for this heap */
RA_ARENA *psLocalDevMemArena;
-
+ /* MMU data page size (4kb, 16kb, 256kb, 1Mb, 4Mb) */
IMG_UINT32 ui32DataPageSize;
IMG_UINT32 ui32XTileStride;
typedef struct _DEVICE_MEMORY_INFO_
{
-
+ /* size of address space, as log2 */
IMG_UINT32 ui32AddressSpaceSizeLog2;
-
-
-
+ /*
+ flags, includes physical memory resource types available to the system.
+ Allows for validation at heap creation, define PVRSRV_BACKINGSTORE_XXX
+ */
IMG_UINT32 ui32Flags;
-
+ /* heap count. Doesn't include additional heaps from PVRSRVCreateDeviceMemHeap */
IMG_UINT32 ui32HeapCount;
-
+ /* the sync heap id - common code needs to know */
IMG_UINT32 ui32SyncHeapID;
-
+ /* heap for buffer mappings */
IMG_UINT32 ui32MappingHeapID;
-
+ /* heap for ion buffers */
+ IMG_UINT32 ui32IonHeapID;
+
+ /* device memory heap info about each heap in a device address space */
DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
-
+ /* BM kernel context for the device */
BM_CONTEXT *pBMKernelContext;
-
+ /* BM context list for the device*/
BM_CONTEXT *pBMContext;
} DEVICE_MEMORY_INFO;
+/*!
+ ****************************************************************************
+ Device memory descriptor for a given system
+ ****************************************************************************/
typedef struct DEV_ARENA_DESCRIPTOR_TAG
{
- IMG_UINT32 ui32HeapID;
+ IMG_UINT32 ui32HeapID; /*!< memory pool has a unique id for diagnostic purposes */
- IMG_CHAR *pszName;
+ IMG_CHAR *pszName; /*!< memory pool has a unique string for diagnostic purposes */
- IMG_DEV_VIRTADDR BaseDevVAddr;
+ IMG_DEV_VIRTADDR BaseDevVAddr; /*!< Device virtual base address of the managed memory pool. */
- IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32Size; /*!< Size in bytes of the managed memory pool. */
- DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
+ DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;/*!< heap type */
-
+ /* MMU data page size (4kb, 16kb, 256kb, 1Mb, 4Mb) */
IMG_UINT32 ui32DataPageSize;
DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeapInfo;
} DEV_ARENA_DESCRIPTOR;
+/*
+ PDUMP MMU atttributes
+*/
typedef struct _PDUMP_MMU_ATTRIB_
{
PVRSRV_DEVICE_IDENTIFIER sDevId;
IMG_CHAR *pszPDRegRegion;
-
+ /* data page info */
IMG_UINT32 ui32DataPageMask;
-
+ /* page table info */
IMG_UINT32 ui32PTEValid;
IMG_UINT32 ui32PTSize;
IMG_UINT32 ui32PTEAlignShift;
-
+ /* page directory info */
IMG_UINT32 ui32PDEMask;
IMG_UINT32 ui32PDEAlignShift;
} PDUMP_MMU_ATTRIB;
+/* forward reference to _SYS_DATA_ */
typedef struct _SYS_DATA_TAG_ *PSYS_DATA;
typedef struct _PVRSRV_DEVICE_NODE_
PVRSRV_DEVICE_IDENTIFIER sDevId;
IMG_UINT32 ui32RefCount;
-
-
-
+ /*
+ callbacks the device must support:
+ */
+ /* device initialiser */
PVRSRV_ERROR (*pfnInitDevice) (IMG_VOID*);
-
+ /* device deinitialiser */
PVRSRV_ERROR (*pfnDeInitDevice) (IMG_VOID*);
-
+ /* device post-finalise compatibility check */
PVRSRV_ERROR (*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*);
-
+ /* device MMU interface */
PVRSRV_ERROR (*pfnMMUInitialise)(struct _PVRSRV_DEVICE_NODE_*, MMU_CONTEXT**, IMG_DEV_PHYADDR*);
IMG_VOID (*pfnMMUFinalise)(MMU_CONTEXT*);
IMG_VOID (*pfnMMUInsertHeap)(MMU_CONTEXT*, MMU_HEAP*);
IMG_SIZE_T uSize,
IMG_UINT32 ui32MemFlags,
IMG_HANDLE hUniqueTag);
+ IMG_VOID (*pfnMMUMapPagesSparse)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR devVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
IMG_VOID (*pfnMMUMapShadow)(MMU_HEAP *pMMU,
IMG_DEV_VIRTADDR MapBaseDevVAddr,
IMG_SIZE_T uSize,
IMG_DEV_VIRTADDR *pDevVAddr,
IMG_UINT32 ui32MemFlags,
IMG_HANDLE hUniqueTag);
+ IMG_VOID (*pfnMMUMapShadowSparse)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ 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_VOID (*pfnMMUGetCacheFlushRange)(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask);
IMG_VOID (*pfnMMUGetPDPhysAddr)(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr);
-
+ /* tiling range control functions */
PVRSRV_ERROR (*pfnAllocMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
PVRSRV_KERNEL_MEM_INFO *psMemInfo,
IMG_UINT32 ui32TilingStride,
PVRSRV_ERROR (*pfnFreeMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
IMG_UINT32 ui32RangeIndex);
-
+ /* LISR handler for device */
IMG_BOOL (*pfnDeviceISR)(IMG_VOID*);
-
+ /* ISR data */
IMG_VOID *pvISRData;
-
+ /* System/SOC specific interrupt bit relating to this device */
IMG_UINT32 ui32SOCInterruptBit;
-
+ /* MISR handler for device */
IMG_VOID (*pfnDeviceMISR)(IMG_VOID*);
-
+ /* Software command complete callback for device */
IMG_VOID (*pfnDeviceCommandComplete)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
-
+ /* Flag indicating that command complete callback needs to be reprocessed */
IMG_BOOL bReProcessDeviceCommandComplete;
IMG_VOID (*pfnCacheInvalidate)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
-
+ /* information about the device's address space and heaps */
DEVICE_MEMORY_INFO sDevMemoryInfo;
-
+ /* private device information */
IMG_VOID *pvDevice;
- IMG_UINT32 ui32pvDeviceSize;
+ IMG_UINT32 ui32pvDeviceSize; /* required by GetClassDeviceInfo API */
-
+ /* Resource Manager Context */
PRESMAN_CONTEXT hResManContext;
-
+ /* pointer back to parent sysdata */
PSYS_DATA psSysData;
-
+ /* default MMU PT/PD backing store to use for the device */
RA_ARENA *psLocalDevMemArena;
IMG_UINT32 ui32Flags;
struct _PVRSRV_DEVICE_NODE_ **ppsThis;
#if defined(PDUMP)
-
+ /* device-level callback which is called when pdump.exe starts.
+ * Should be implemented in device-specific init code, e.g. sgxinit.c
+ */
PVRSRV_ERROR (*pfnPDumpInitDevice)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
-
+ /* device-level callback to return pdump ID associated to a memory context */
IMG_UINT32 (*pfnMMUGetContextID)(IMG_HANDLE hDevMemContext);
#endif
} PVRSRV_DEVICE_NODE;
#if !defined(USE_CODE)
-IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PollForValueKM(volatile IMG_UINT32* pui32LinMemAddr,
- IMG_UINT32 ui32Value,
- IMG_UINT32 ui32Mask,
- IMG_UINT32 ui32Timeoutus,
- IMG_UINT32 ui32PollPeriodus,
- IMG_BOOL bAllowPreemption);
+/*!
+******************************************************************************
-#endif
+ @Function PollForValueKM
+
+ @Description
+ Polls for a value to match a masked read of sysmem
+
+ @Input pui32LinMemAddr : CPU linear address of the mem to poll
+ @Input ui32Value : req'd value
+ @Input ui32Mask : Mask
+ @Input ui32Timeoutus : maximum total time to wait (us)
+ @Input ui32PollPeriodus : minimum delay between consecutive polls (us)
+ @Input bAllowPreemption : allow the polling loop to be preempted
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PollForValueKM(volatile IMG_UINT32* pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Timeoutus,
+ IMG_UINT32 ui32PollPeriodus,
+ IMG_BOOL bAllowPreemption);
+
+#endif /* !defined(USE_CODE) */
#if defined (USING_ISR_INTERRUPTS)
PVRSRV_ERROR IMG_CALLCONV PollForInterruptKM(IMG_UINT32 ui32Value,
- IMG_UINT32 ui32Mask,
- IMG_UINT32 ui32Waitus,
- IMG_UINT32 ui32Tries);
-#endif
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries);
+
+#endif /* #if defined (USING_ISR_INTERRUPTS) */
+/* The following functions don't really belong here (srvkm.h might be a better
+ * place), but as they use the device data structures, this is the most convenient
+ * place for them. */
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);
}
#endif
-#endif
+#endif /* __DEVICE_H__ */
+/******************************************************************************
+ End of file (device.h)
+******************************************************************************/
-/**********************************************************************
+/*************************************************************************/ /*!
+@Title Handle Manager API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide handle management
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __HANDLE_H__
+#define __HANDLE_H__
+
+/*
+ * Handle API
+ * ----------
+ * The handle API is intended to provide handles for kernel resources,
+ * which can then be passed back to user space processes.
*
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
+ * The following functions comprise the API. Each function takes a
+ * pointer to a PVRSRV_HANDLE_BASE strcture, one of which is allocated
+ * for each process, and stored in the per-process data area. Use
+ * KERNEL_HANDLE_BASE for handles not allocated for a particular process,
+ * or for handles that need to be allocated before the PVRSRV_HANDLE_BASE
+ * structure for the process is available.
*
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ * PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType,
+ * PVRSRV_HANDLE_ALLOC_FLAG eFlag);
*
- ******************************************************************************/
-
-#ifndef __HANDLE_H__
-#define __HANDLE_H__
+ * Allocate a handle phHandle, for the resource of type eType pointed to by
+ * pvData.
+ *
+ * For handles that have a definite lifetime, where the corresponding
+ * resource is explicitly created and destroyed, eFlag should be zero.
+ *
+ * If the resource is not explicitly created and destroyed, eFlag should be
+ * set to PVRSRV_HANDLE_ALLOC_FLAG_SHARED. For a given process, the same
+ * handle will be returned each time a handle for the resource is allocated
+ * with the PVRSRV_HANDLE_ALLOC_FLAG_SHARED flag.
+ *
+ * If a particular resource may be referenced multiple times by a
+ * given process, setting eFlag to PVRSRV_HANDLE_ALLOC_FLAG_MULTI
+ * will allow multiple handles to be allocated for the resource.
+ * Such handles cannot be found with PVRSRVFindHandle.
+ *
+ * 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);
+ *
+ * This function is similar to PVRSRVAllocHandle, except that the allocated
+ * handles are associated with a parent handle, hParent, that has been
+ * allocated previously. Subhandles are automatically deallocated when their
+ * parent handle is dealloacted.
+ * Subhandles can be treated as ordinary handles. For example, they may
+ * have subhandles of their own, and may be explicity deallocated using
+ * PVRSRVReleaseHandle (see below).
+ *
+ * PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Find the handle previously allocated for the resource pointed to by
+ * pvData, of type eType. Handles allocated with the flag
+ * PVRSRV_HANDLE_ALLOC_FLAG_MULTI cannot be found using this
+ * function.
+ *
+ * PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Given a handle for a resource of type eType, return the pointer to the
+ * resource.
+ *
+ * PVRSRV_ERROR PVRSRVLookuSubHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType,
+ * IMH_HANDLE hAncestor);
+ *
+ * Similar to PVRSRVLookupHandle, but checks the handle is a descendent
+ * of hAncestor.
+ *
+ * PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+ *
+ * This function returns the resource pointer corresponding to the
+ * given handle, and the resource type in peType. This function is
+ * intended for situations where a handle may be one of several types,
+ * but the type isn't known beforehand.
+ *
+ * PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Deallocate a handle of given type.
+ *
+ * PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * This function combines the functionality of PVRSRVLookupHandle and
+ * PVRSRVReleaseHandle, deallocating the handle after looking it up.
+ *
+ * PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Return the parent of a handle in *phParent, or IMG_NULL if the handle has
+ * no parent.
+ *
+ * PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_UINT32 ui32BatchSize)
+ *
+ * Allocate a new handle batch. This preallocates ui32BatchSize handles.
+ * Batch mode simplifies the handling of handle allocation failures.
+ * The handle API is unchanged in batch mode, except that handles freed
+ * in batch mode will not be available for reallocation until the batch
+ * is committed or released (see below).
+ *
+ * PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+ * void PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+ *
+ * When handle allocation from a handle batch is complete, the
+ * batch must be committed by calling PVRSRVCommitHandleBatch. If
+ * an error occurred, and none of the handles in the batch are no
+ * longer needed, PVRSRVReleaseHandleBatch must be called.
+ * The macros PVRSRVAllocHandleNR, and PVRSRVAllocSubHandleNR
+ * are defined for use in batch mode. These work the same way
+ * as PVRSRVAllocHandle and PVRSRVAllocSubHandle, except that
+ * they don't return a value, relying on the fact that
+ * PVRSRVCommitHandleBatch will not commit any of the handles
+ * in a batch if there was an error allocating one of the
+ * handles in the batch.
+ *
+ * PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_UINT32 ui32MaxHandle)
+ * Set the maximum handle number. This is intended to restrict the
+ * handle range so that it will fit within a given field width. For
+ * example, setting the maximum handle number to 0x7fffffff, would
+ * ensure the handles would fit within a 31 bit width field. This
+ * facility should be used with caution, as it restricts the number of
+ * handles that can be allocated.
+ *
+ * IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+ * Return the maximum handle number, or 0 if the setting of a limit
+ * is not supported.
+ *
+ * PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+ * Allows unused handle space to be reclaimed, by calling
+ * PVRSRVPurgeHandles. Note that allocating handles may have a
+ * higher overhead if purging is enabled.
+ *
+ * PVRSRV_ERROR PVRSRVPurgeHandles((PVRSRV_HANDLE_BASE *psBase)
+ * Purge handles for a handle base that has purging enabled.
+ */
#if defined (__cplusplus)
extern "C" {
typedef enum
{
-
+ /* No flags */
PVRSRV_HANDLE_ALLOC_FLAG_NONE = 0,
-
+ /* Share a handle that already exists for a given data pointer */
PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 0x01,
-
+ /* Muliple handles can point at the given data pointer */
PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 0x02,
-
+ /* Subhandles are allocated in a private handle space */
PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 0x04
} PVRSRV_HANDLE_ALLOC_FLAG;
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);
-#endif
+#endif /* #if defined (SUPPORT_SID_INTERFACE) */
PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize);
PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID);
-#else
+#else /* #if defined (PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)*/
#define KERNEL_HANDLE_BASE IMG_NULL
PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
{
PVR_UNREFERENCED_PARAMETER(psBase);
-
+ /*
+ * Unlike the other functions here, the returned results will need
+ * to be handled differently for the secure and non-secure cases.
+ */
*peType = PVRSRV_HANDLE_TYPE_NONE;
*ppvData = hHandle;
return PVRSRV_OK;
}
-#endif
+#endif /* #if defined (PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)*/
+/*
+ * Versions of PVRSRVAllocHandle and PVRSRVAllocSubHandle with no return
+ * values. Intended for use with batched handle allocation, relying on
+ * CommitHandleBatch to detect handle allocation errors.
+ */
#define PVRSRVAllocHandleNR(psBase, phHandle, pvData, eType, eFlag) \
(IMG_VOID)PVRSRVAllocHandle(psBase, phHandle, pvData, eType, eFlag)
}
#endif
-#endif
+#endif /* __HANDLE_H__ */
+/******************************************************************************
+ End of file (handle.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Self scaling hash tables
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements simple self scaling hash tables.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _HASH_H_
#define _HASH_H_
extern "C" {
#endif
+/*
+ * Keys passed to the comparsion function are only guaranteed to
+ * be aligned on an IMG_UINTPTR_T boundary.
+ */
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);
IMG_UINTPTR_T v
);
+/*!
+******************************************************************************
+ @Function HASH_Func_Default
+
+ @Description Hash function intended for hashing keys composed of
+ IMG_UINTPTR_T arrays.
+
+ @Input uKeySize - the size of the hash key, in bytes.
+ @Input pKey - a pointer to the key to hash.
+ @Input uHashTabLen - the length of the hash table.
+
+ @Return The hash value.
+******************************************************************************/
IMG_UINT32 HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+/*!
+******************************************************************************
+ @Function HASH_Key_Comp_Default
+
+ @Description Compares keys composed of IMG_UINTPTR_T arrays.
+
+ @Input uKeySize - the size of the hash key, in bytes.
+ @Input pKey1 - pointer to first hash key to compare.
+ @Input pKey2 - pointer to second hash key to compare.
+
+ @Return IMG_TRUE - the keys match.
+ IMG_FALSE - the keys don't match.
+******************************************************************************/
IMG_BOOL HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+/*!
+******************************************************************************
+ @Function HASH_Create_Extended
+
+ @Description Create a self scaling hash table, using the supplied
+ key size, and the supllied hash and key comparsion
+ functions.
+
+ @Input uInitialLen - initial and minimum length of the
+ hash table, where the length refers to the number
+ of entries in the hash table, not its size in
+ bytes.
+ @Input uKeySize - the size of the key, in bytes.
+ @Input pfnHashFunc - pointer to hash function.
+ @Input pfnKeyComp - pointer to key comparsion function.
+
+ @Return IMG_NULL or hash table handle.
+******************************************************************************/
HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp);
+/*!
+******************************************************************************
+ @Function HASH_Create
+
+ @Description Create a self scaling hash table with a key
+ consisting of a single IMG_UINTPTR_T, and using
+ the default hash and key comparison functions.
+
+ @Input uInitialLen - initial and minimum length of the
+ hash table, where the length refers to the
+ number of entries in the hash table, not its size
+ in bytes.
+
+ @Return IMG_NULL or hash table handle.
+******************************************************************************/
HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen);
+/*!
+******************************************************************************
+ @Function HASH_Delete
+
+ @Description Delete a hash table created by HASH_Create_Extended or
+ HASH_Create. All entries in the table must have been
+ removed before calling this function.
+
+ @Input pHash - hash table
+
+ @Return None
+******************************************************************************/
IMG_VOID HASH_Delete (HASH_TABLE *pHash);
+/*!
+******************************************************************************
+ @Function HASH_Insert_Extended
+
+ @Description Insert a key value pair into a hash table created
+ with HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to the key.
+ @Input v - the value associated with the key.
+
+ @Return IMG_TRUE - success.
+ IMG_FALSE - failure.
+******************************************************************************/
IMG_BOOL HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v);
+/*!
+******************************************************************************
+ @Function HASH_Insert
+
+ @Description Insert a key value pair into a hash table created with
+ HASH_Create.
+
+ @Input pHash - the hash table.
+ @Input k - the key value.
+ @Input v - the value associated with the key.
+
+ @Return IMG_TRUE - success.
+ IMG_FALSE - failure.
+******************************************************************************/
IMG_BOOL HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+/*!
+******************************************************************************
+ @Function HASH_Remove_Extended
+
+ @Description Remove a key from a hash table created with
+ HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to key.
+
+ @Return 0 if the key is missing, or the value associated
+ with the key.
+******************************************************************************/
IMG_UINTPTR_T HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey);
+/*!
+******************************************************************************
+ @Function HASH_Remove
+
+ @Description Remove a key value pair from a hash table created
+ with HASH_Create.
+
+ @Input pHash - the hash table
+ @Input k - the key
+
+ @Return 0 if the key is missing, or the value associated
+ with the key.
+******************************************************************************/
IMG_UINTPTR_T HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+/*!
+******************************************************************************
+ @Function HASH_Retrieve_Extended
+
+ @Description Retrieve a value from a hash table created with
+ HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to the key.
+
+ @Return 0 if the key is missing, or the value associated with
+ the key.
+******************************************************************************/
IMG_UINTPTR_T HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey);
+/*!
+******************************************************************************
+ @Function HASH_Retrieve
+
+ @Description Retrieve a value from a hash table created with
+ HASH_Create.
+
+ @Input pHash - the hash table
+ @Input k - the key
+
+ @Return 0 if the key is missing, or the value associated with
+ the key.
+******************************************************************************/
IMG_UINTPTR_T HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+/*!
+******************************************************************************
+ @Function HASH_Interate
+
+ @Description Iterate over every entry in the hash table
+
+ @Input pHash - the old hash table
+ @Input HASH_pfnCallback - the size of the old hash table
+
+ @Return Callback error if any, otherwise PVRSRV_OK
+******************************************************************************/
PVRSRV_ERROR HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback);
#ifdef HASH_TRACE
+/*!
+******************************************************************************
+ @Function HASH_Dump
+
+ @Description Dump out some information about a hash table.
+
+ @Input pHash - the hash table
+
+ @Return None
+******************************************************************************/
IMG_VOID HASH_Dump (HASH_TABLE *pHash);
#endif
}
#endif
-#endif
+#endif /* _HASH_H_ */
+
+/******************************************************************************
+ End of file (hash.h)
+******************************************************************************/
+
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linked list shared functions templates.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Definition of the linked list function templates.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __LISTS_UTILS__
#define __LISTS_UTILS__
+/* instruct QAC to ignore warnings about the following custom formatted macros */
+/* PRQA S 0881,3410 ++ */
#include <stdarg.h>
#include "img_types.h"
+/*
+ - USAGE -
+
+ The list functions work with any structure that provides the fields psNext and
+ ppsThis. In order to make a function available for a given type, it is required
+ to use the funcion template macro that creates the actual code.
+
+ There are 4 main types of functions:
+ - INSERT : given a pointer to the head pointer of the list and a pointer to
+ the node, inserts it as the new head.
+ - REMOVE : given a pointer to a node, removes it from its list.
+ - FOR EACH : apply a function over all the elements of a list.
+ - ANY : apply a function over the elements of a list, until one of them
+ return a non null value, and then returns it.
+
+ The two last functions can have a variable argument form, with allows to pass
+ additional parameters to the callback function. In order to do this, the
+ callback function must take two arguments, the first is the current node and
+ the second is a list of variable arguments (va_list).
+
+ The ANY functions have also another for wich specifies the return type of the
+ callback function and the default value returned by the callback function.
+
+*/
+
+/*!
+******************************************************************************
+ @Function List_##TYPE##_ForEach
+
+ @Description Apply a callback function to all the elements of a list.
+
+ @Input psHead - the head of the list to be processed.
+ @Input pfnCallBack - the function to be applied to each element
+ of the list.
+
+ @Return None
+******************************************************************************/
#define DECLARE_LIST_FOR_EACH(TYPE) \
IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))
}
+/*!
+******************************************************************************
+ @Function List_##TYPE##_Any
+
+ @Description Applies a callback function to the elements of a list until
+ the function returns a non null value, then returns it.
+
+ @Input psHead - the head of the list to be processed.
+ @Input pfnCallBack - the function to be applied to each element
+ of the list.
+
+ @Return None
+******************************************************************************/
#define DECLARE_LIST_ANY(TYPE) \
IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))
}
+/*with variable arguments, that will be passed as a va_list to the callback function*/
+
#define DECLARE_LIST_ANY_VA(TYPE) \
IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)
return pResult;\
}
+/*those ones are for extra type safety, so there's no need to use castings for the results*/
+
#define DECLARE_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))
}
+/*!
+******************************************************************************
+ @Function List_##TYPE##_Remove
+
+ @Description Removes a given node from the list.
+
+ @Input psNode - the pointer to the node to be removed.
+
+ @Return None
+******************************************************************************/
#define DECLARE_LIST_REMOVE(TYPE) \
IMG_VOID List_##TYPE##_Remove(TYPE *psNode)
}\
}
+/*!
+******************************************************************************
+ @Function List_##TYPE##_Insert
+
+ @Description Inserts a given node at the beginnning of the list.
+
+ @Input psHead - The pointer to the pointer to the head node.
+ @Input psNode - The pointer to the node to be inserted.
+
+ @Return None
+******************************************************************************/
#define DECLARE_LIST_INSERT(TYPE) \
IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)
}\
}
+/*!
+******************************************************************************
+ @Function List_##TYPE##_Reverse
+
+ @Description Reverse a list in place
+
+ @Input ppsHead - The pointer to the pointer to the head node.
+
+ @Return None
+******************************************************************************/
#define DECLARE_LIST_REVERSE(TYPE) \
IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)
#endif
+/* re-enable warnings */
+/* PRQA S 0881,3410 -- */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Time measurement interface.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _METRICS_
#define _METRICS_
#if defined(__sh__)
-#define TST_REG ((volatile IMG_UINT8 *) (psDevInfo->pvSOCRegsBaseKM))
+#define TST_REG ((volatile IMG_UINT8 *) (psDevInfo->pvSOCRegsBaseKM)) // timer start register
-#define TCOR_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+28))
-#define TCNT_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+32))
-#define TCR_2 ((volatile IMG_UINT16 *)(psDevInfo->pvSOCRegsBaseKM+36))
+#define TCOR_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+28)) // timer constant register_2
+#define TCNT_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+32)) // timer counter register_2
+#define TCR_2 ((volatile IMG_UINT16 *)(psDevInfo->pvSOCRegsBaseKM+36)) // timer control register_2
#define TIMER_DIVISOR 4
-#endif
+#endif /* defined(__sh__) */
-
-
-#else
+#else /* defined(DEBUG) || defined(TIMING) */
-#endif
+#endif /* defined(DEBUG) || defined(TIMING) */
#if defined(__cplusplus)
}
#endif
-#endif
+#endif /* _METRICS_ */
+/**************************************************************************
+ End of file (metrics.h)
+**************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title OS functions header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS specific API definitions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifdef DEBUG_RELEASE_BUILD
#pragma optimize( "", off )
#define DEBUG 1
#endif
-
+/* setup conditional pageable / non-pageable select */
+ /* Non-Vista OSs only need pageable */
#define PVRSRV_PAGEABLE_SELECT PVRSRV_OS_PAGEABLE_HEAP
+/******************************************************************************
+ * Static defines
+ *****************************************************************************/
#define KERNEL_ID 0xffffffffL
#define POWER_MANAGER_ID 0xfffffffeL
#define ISR_ID 0xfffffffdL
#define HOST_PAGEMASK (HOST_PAGESIZE()-1)
#define HOST_PAGEALIGN(addr) (((addr) + HOST_PAGEMASK) & ~HOST_PAGEMASK)
-#define PVRSRV_OS_HEAP_MASK 0xf
-#define PVRSRV_OS_PAGEABLE_HEAP 0x1
-#define PVRSRV_OS_NON_PAGEABLE_HEAP 0x2
+/******************************************************************************
+ * Host memory heaps
+ *****************************************************************************/
+#define PVRSRV_OS_HEAP_MASK 0xf /* host heap flags mask */
+#define PVRSRV_OS_PAGEABLE_HEAP 0x1 /* allocation pageable */
+#define PVRSRV_OS_NON_PAGEABLE_HEAP 0x2 /* allocation non pageable */
IMG_UINT32 OSClockus(IMG_VOID);
IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE *phOSMemHandle);
IMG_BOOL OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
-PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hBMHandle, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle);
PVRSRV_ERROR OSUnReservePhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+/* Some terminology:
+ *
+ * FLUSH Flush w/ invalidate
+ * CLEAN Flush w/o invalidate
+ * INVALIDATE Invalidate w/o flush
+ */
+
#if defined(__linux__) && defined(__KERNEL__)
IMG_VOID OSFlushCPUCacheKM(IMG_VOID);
IMG_VOID OSCleanCPUCacheKM(IMG_VOID);
IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length);
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length);
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length);
-#else
+#else /* defined(__linux__) && defined(__KERNEL__) */
#ifdef INLINE_IS_PRAGMA
#pragma inline(OSFlushCPUCacheKM)
#pragma inline(OSFlushCPUCacheRangeKM)
#endif
static INLINE IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
PVR_UNREFERENCED_PARAMETER(ui32Length);
return IMG_FALSE;
#pragma inline(OSCleanCPUCacheRangeKM)
#endif
static INLINE IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
PVR_UNREFERENCED_PARAMETER(ui32Length);
return IMG_FALSE;
#pragma inline(OSInvalidateCPUCacheRangeKM)
#endif
static INLINE IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
PVR_UNREFERENCED_PARAMETER(ui32Length);
return IMG_FALSE;
}
-#endif
+#endif /* defined(__linux__) && defined(__KERNEL__) */
-#if (defined(__linux__) || defined(__QNXNTO__))
+#if defined(__linux__) || defined(__QNXNTO__)
PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
IMG_VOID *pvCpuVAddr,
IMG_SIZE_T ui32Bytes,
IMG_SIZE_T ui32Bytes,
IMG_UINT32 ui32Flags,
IMG_HANDLE hOSMemHandle);
-#else
+#else /* defined(__linux__) */
#ifdef INLINE_IS_PRAGMA
#pragma inline(OSRegisterDiscontigMem)
#endif
return PVRSRV_ERROR_NOT_SUPPORTED;
}
-#endif
+#endif /* defined(__linux__) */
-#if (defined(__linux__) || defined(__QNXNTO__))
+#if defined(__linux__) || defined(__QNXNTO__)
#ifdef INLINE_IS_PRAGMA
#pragma inline(OSReserveDiscontigPhys)
#endif
#else
extern IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(IMG_SYS_PHYADDR SysPAddr);
-
- return OSReservePhys(SysSysPAddrToCpuPAddr(pBasePAddr[0]), ui32Bytes, ui32Flags, ppvCpuVAddr, phOSMemHandle);
+ /*
+ * On uITRON we know:
+ * 1. We will only be called with a non-contig physical if we
+ * already have a contiguous CPU linear
+ * 2. There is a one->one mapping of CpuPAddr -> CpuVAddr
+ * 3. Looking up the first CpuPAddr will find the first CpuVAddr
+ * 4. We don't need to unmap
+ */
+
+ return OSReservePhys(SysSysPAddrToCpuPAddr(pBasePAddr[0]), ui32Bytes, ui32Flags, IMG_NULL, ppvCpuVAddr, phOSMemHandle);
#endif
}
#if defined(__linux__) || defined(__QNXNTO__)
OSUnRegisterDiscontigMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
#endif
-
+ /* We don't need to unmap */
return PVRSRV_OK;
}
-#else
+#else /* defined(__linux__) */
#ifdef INLINE_IS_PRAGMA
return PVRSRV_ERROR_NOT_SUPPORTED;
}
-#endif
+#endif /* defined(__linux__) */
PVRSRV_ERROR OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
IMG_VOID *pvCpuVAddr,
IMG_UINTPTR_T OSGetCurrentThreadID( IMG_VOID );
IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
-PVRSRV_ERROR OSAllocPages_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_UINT32 ui32PageSize, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phPageAlloc);
+PVRSRV_ERROR OSAllocPages_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_UINT32 ui32PageSize,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength, IMG_HANDLE hBMHandle, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phPageAlloc);
PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hPageAlloc);
+/*---------------------
+The set of macros below follows this pattern:
+
+f(x) = if F -> f2(g(x))
+ else -> g(x)
+
+g(x) = if G -> g2(h(x))
+ else -> h(x)
+
+h(x) = ...
+
+-----------------------*/
+
+/*If level 3 wrapper is enabled, we add a PVR_TRACE and call the next level, else just call the next level*/
#ifdef PVRSRV_LOG_MEMORY_ALLOCS
#define OSAllocMem(flags, size, linAddr, blockAlloc, logStr) \
(PVR_TRACE(("OSAllocMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): " logStr " (size = 0x%lx)", size)), \
OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
- #define OSAllocPages(flags, size, pageSize, linAddr, pageAlloc) \
+ #define OSAllocPages(flags, size, pageSize, privdata, privdatalength, bmhandle, linAddr, pageAlloc) \
(PVR_TRACE(("OSAllocPages(" #flags ", " #size ", " #pageSize ", " #linAddr ", " #pageAlloc "): (size = 0x%lx)", size)), \
- OSAllocPages_Impl(flags, size, pageSize, linAddr, pageAlloc))
+ OSAllocPages_Impl(flags, size, pageSize, linAddr, privdata, privdatalength, bmhandle, pageAlloc))
#define OSFreeMem(flags, size, linAddr, blockAlloc) \
(PVR_TRACE(("OSFreeMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): (pointer = 0x%X)", linAddr)), \
OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
#endif
+/*If level 2 wrapper is enabled declare the function,
+else alias to level 1 wrapper, else the wrapper function will be used*/
#ifdef PVRSRV_DEBUG_OS_MEMORY
PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
} eValid;
} OSMEM_DEBUG_INFO;
- #define TEST_BUFFER_PADDING_STATUS (sizeof(OSMEM_DEBUG_INFO))
- #define TEST_BUFFER_PADDING_AFTER (8)
+ #define TEST_BUFFER_PADDING_STATUS (sizeof(OSMEM_DEBUG_INFO))
+ #define TEST_BUFFER_PADDING_AFTER (8)
#define TEST_BUFFER_PADDING (TEST_BUFFER_PADDING_STATUS + TEST_BUFFER_PADDING_AFTER)
#else
#define OSAllocMem_Debug_Wrapper OSAllocMem_Debug_Linux_Memory_Allocations
#define OSFreeMem_Debug_Wrapper OSFreeMem_Debug_Linux_Memory_Allocations
#endif
+/*If level 1 wrapper is enabled declare the functions with extra parameters
+else alias to level 0 and declare the functions without the extra debugging parameters*/
#if (defined(__linux__) || defined(__QNXNTO__)) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
return sCpuPAddr;
}
#endif
+
+#if defined(__linux__)
+IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleIsPhysContig)
+#endif
+static INLINE IMG_BOOL OSMemHandleIsPhysContig(IMG_HANDLE hOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ return IMG_FALSE;
+}
+#endif
+
PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData);
PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData);
IMG_CHAR* OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc);
IMG_HANDLE *phOSEvent);
PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT *psEventObject,
IMG_HANDLE hOSEventKM);
-#endif
+#endif /* #if defined (SUPPORT_SID_INTERFACE) */
PVRSRV_ERROR OSBaseAllocContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR *pLinAddr, IMG_CPU_PHYADDR *pPhysAddr);
#define OSPowerLockWrap SysPowerLockWrap
#define OSPowerLockUnwrap SysPowerLockUnwrap
#else
+/******************************************************************************
+ @Function OSPowerLockWrap
+
+ @Description OS-specific wrapper around the power lock
+
+ @Input bTryLock - don't block on lock contention
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
PVRSRV_ERROR OSPowerLockWrap(IMG_BOOL bTryLock);
+/******************************************************************************
+ @Function OSPowerLockUnwrap
+
+ @Description OS-specific wrapper around the power unlock
+
+ @Return IMG_VOID
+******************************************************************************/
IMG_VOID OSPowerLockUnwrap(IMG_VOID);
-#endif
+#endif /* SYS_CUSTOM_POWERLOCK_WRAP */
+/*!
+******************************************************************************
+
+ @Function OSWaitus
+
+ @Description
+ This function implements a busy wait of the specified microseconds
+ This function does NOT release thread quanta
+ @Input ui32Timeus - (us)
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus);
+/*!
+******************************************************************************
+
+ @Function OSSleepms
+ @Description
+ This function implements a sleep of the specified milliseconds
+ This function may allow pre-emption if implemented
+
+ @Input ui32Timems - (ms)
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID OSSleepms(IMG_UINT32 ui32Timems);
IMG_HANDLE OSFuncHighResTimerCreate(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);
+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);
+
#ifndef OSReadHWReg
IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
#endif
PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData);
+/******************************************************************************
+
+ @Function OSPanic
+
+ @Description Take action in response to an unrecoverable driver error
+
+ @Input IMG_VOID
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID OSPanic(IMG_VOID);
IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID);
PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
-#if (defined(__linux__) || defined(__QNXNTO__))
+#if defined(__linux__) || defined(__QNXNTO__)
PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
IMG_SIZE_T ui32Bytes,
IMG_SYS_PHYADDR *psSysPAddr,
mb();
}
-#else
+#else /* defined(__linux__) && defined(__KERNEL__) */
#ifdef INLINE_IS_PRAGMA
#pragma inline(OSWriteMemoryBarrier)
#endif
static INLINE IMG_VOID OSMemoryBarrier(IMG_VOID) { }
-#endif
+#endif /* defined(__linux__) && defined(__KERNEL__) */
+
+/* Atomic functions */
+PVRSRV_ERROR OSAtomicAlloc(IMG_PVOID *ppvRefCount);
+IMG_VOID OSAtomicFree(IMG_PVOID pvRefCount);
+IMG_VOID OSAtomicInc(IMG_PVOID pvRefCount);
+IMG_BOOL OSAtomicDecAndTest(IMG_PVOID pvRefCount);
+IMG_UINT32 OSAtomicRead(IMG_PVOID pvRefCount);
+
+PVRSRV_ERROR OSTimeCreateWithUSOffset(IMG_PVOID *pvRet, IMG_UINT32 ui32MSOffset);
+IMG_BOOL OSTimeHasTimePassed(IMG_PVOID pvData);
+IMG_VOID OSTimeDestroy(IMG_PVOID pvData);
+
+#if defined(__linux__)
+IMG_VOID OSReleaseBridgeLock(IMG_VOID);
+IMG_VOID OSReacquireBridgeLock(IMG_VOID);
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReleaseBridgeLock)
+#endif
+static INLINE IMG_VOID OSReleaseBridgeLock(IMG_VOID) { }
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReacquireBridgeLock)
+#endif
+static INLINE IMG_VOID OSReacquireBridgeLock(IMG_VOID) { }
+
+#endif
+
+#if defined(__linux__)
+IMG_VOID OSGetCurrentProcessNameKM(IMG_CHAR *pszName, IMG_UINT32 ui32Size);
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSGetCurrentProcessNameKM)
+#endif
+static INLINE IMG_VOID OSGetCurrentProcessNameKM(IMG_CHAR *pszName, IMG_UINT32 ui32Size)
+{
+ PVR_UNREFERENCED_PARAMETER(pszName);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+}
+
+#endif
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* __OSFUNC_H__ */
+
+/******************************************************************************
+ End of file (osfunc.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OS specific per process data interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS specific per process data interface
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __OSPERPROC_H__
#define __OSPERPROC_H__
PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData);
PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
-#else
+#else /* defined(__linux__) */
#ifdef INLINE_IS_PRAGMA
#pragma inline(OSPerProcessPrivateDataInit)
#endif
return PVRSRV_OK;
}
-#endif
+#endif /* defined(__linux__) */
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* __OSPERPROC_H__ */
+/******************************************************************************
+ End of file (osperproc.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Parameter dump internal common functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
#ifndef __PDUMP_INT_H__
#define __PDUMP_INT_H__
extern "C" {
#endif
+/*
+ * This file contains internal pdump utility functions which may be accessed
+ * from OS-specific code. The header should not be included outside of srvkm
+ * pdump files.
+ */
+
#if !defined(_UITRON)
+/*
+ * No dbgdriver on uitron, so ignore any common functions for communicating
+ * with dbgdriver.
+ */
#include "dbgdrvif.h"
+/* Callbacks which are registered with the debug driver. */
IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID);
-#endif
+#endif /* !defined(_UITRON) */
typedef enum
{
-
+ /* Continuous writes are always captured in the dbgdrv; the buffer will
+ * expand if no client/sink process is running.
+ */
PDUMP_WRITE_MODE_CONTINUOUS = 0,
-
+ /* Last frame capture */
PDUMP_WRITE_MODE_LASTFRAME,
-
+ /* Capture frame, binary data */
PDUMP_WRITE_MODE_BINCM,
-
+ /* Persistent capture, append data to init phase */
PDUMP_WRITE_MODE_PERSISTENT
} PDUMP_DDWMODE;
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* __PDUMP_INT_H__ */
+
+/******************************************************************************
+ End of file (pdump_int.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title pdump functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for pdump functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _PDUMP_KM_H_
#define _PDUMP_KM_H_
+/*
+ * Include the OS abstraction APIs
+ */
#include "pdump_osfunc.h"
#if defined(__cplusplus)
extern "C" {
#endif
+/*
+ * Pull in pdump flags from services include
+ */
#include "pdump.h"
#define PDUMP_PD_UNIQUETAG (IMG_HANDLE)0
#define PDUMP_PT_UNIQUETAG (IMG_HANDLE)0
+/*
+ * PDump streams (common to all OSes)
+ */
#define PDUMP_STREAM_PARAM2 0
#define PDUMP_STREAM_SCRIPT2 1
#define PDUMP_STREAM_DRIVERINFO 2
#define PDUMP_NUM_STREAMS 3
#if defined(PDUMP_DEBUG_OUTFILES)
+/* counter increments each time debug write is called */
extern IMG_UINT32 g_ui32EveryLineCounter;
#endif
PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID);
IMG_IMPORT PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame);
IMG_IMPORT PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags);
-
-
IMG_IMPORT PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags);
PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
IMG_UINT32 ui32NumBytes,
IMG_UINT32 ui32PageSize,
IMG_HANDLE hUniqueTag,
- IMG_BOOL bInterleaved);
+ IMG_BOOL bInterleaved,
+ IMG_BOOL bSparse);
PVRSRV_ERROR PDumpFreePageTable(PVRSRV_DEVICE_IDENTIFIER *psDevID,
IMG_HANDLE hOSMemHandle,
IMG_CPU_VIRTADDR pvLinAddr,
IMG_VOID PDumpSuspendKM(IMG_VOID);
IMG_VOID PDumpResumeKM(IMG_VOID);
-
+ /* New pdump common functions */
PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
#define PDUMPRESUME PDumpResumeKM
#else
- #if (((defined(LINUX) || defined(__QNXNTO__)) || defined(GCC_IA32)) || defined(GCC_ARM))
+#if defined LINUX || defined (__QNXNTO__) || defined GCC_IA32 || defined GCC_ARM
#define PDUMPMEMPOL(args...)
#define PDUMPMEM(args...)
#define PDUMPMEMPTENTRIES(args...)
}
#endif
-#endif
+#endif /* _PDUMP_KM_H_ */
+/******************************************************************************
+ End of file (pdump_km.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OS-independent interface to helper functions for pdump
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <stdarg.h>
#endif
+/*
+ * Some OSes (WinXP,CE) allocate the string on the stack, but some
+ * (Linux,Symbian) use a global variable/lock instead.
+ * Would be good to use the same across all OSes.
+ *
+ * A handle is returned which represents IMG_CHAR* type on all OSes except
+ * Symbian when it represents PDumpState* type.
+ *
+ * The allocated buffer length is also returned on OSes where it's
+ * supported (e.g. Linux).
+ */
#define MAX_PDUMP_STRING_LENGTH (256)
+#if defined(__QNXNTO__)
+#define PDUMP_GET_SCRIPT_STRING() \
+ IMG_CHAR pszScript[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1; \
+ IMG_HANDLE hScript = (IMG_HANDLE)pszScript;
+
+#define PDUMP_GET_MSG_STRING() \
+ IMG_CHAR pszMsg[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1;
+#define PDUMP_GET_FILE_STRING() \
+ IMG_CHAR pszFileName[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1;
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING() \
+ IMG_CHAR pszScript[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_CHAR pszFileName[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLenScript = MAX_PDUMP_STRING_LENGTH-1; \
+ IMG_UINT32 ui32MaxLenFileName = MAX_PDUMP_STRING_LENGTH-1; \
+ IMG_HANDLE hScript = (IMG_HANDLE)pszScript;
+#else /* WIN32 or QNX */
-
+ /*
+ * Linux
+ */
#define PDUMP_GET_SCRIPT_STRING() \
IMG_HANDLE hScript; \
IMG_UINT32 ui32MaxLen; \
eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLenFileName);\
if(eError != PVRSRV_OK) return eError;
-
+ /*!
+ * @name PDumpOSGetScriptString
+ * @brief Get the "script" buffer
+ * @param phScript - buffer handle for pdump script
+ * @param pui32MaxLen - max length of the script buffer
+ * FIXME: the max length should be internal to the OS-specific code
+ * @return error (always PVRSRV_OK on some OSes)
+ */
PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, IMG_UINT32 *pui32MaxLen);
-
+ /*!
+ * @name PDumpOSGetMessageString
+ * @brief Get the "message" buffer
+ * @param pszMsg - buffer pointer for pdump messages
+ * @param pui32MaxLen - max length of the message buffer
+ * FIXME: the max length should be internal to the OS-specific code
+ * @return error (always PVRSRV_OK on some OSes)
+ */
PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg, IMG_UINT32 *pui32MaxLen);
-
+ /*!
+ * @name PDumpOSGetFilenameString
+ * @brief Get the "filename" buffer
+ * @param ppszFile - buffer pointer for filename
+ * @param pui32MaxLen - max length of the filename buffer
+ * FIXME: the max length should be internal to the OS-specific code
+ * @return error (always PVRSRV_OK on some OSes)
+ */
PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, IMG_UINT32 *pui32MaxLen);
+#endif /* WIN32 or QNX */
+/*
+ * Define macro for processing variable args list in OS-independent
+ * manner. See e.g. PDumpComment().
+ */
#define PDUMP_va_list va_list
#define PDUMP_va_start va_start
+/*!
+ * @name PDumpOSGetStream
+ * @brief Get a handle to the labelled stream (cast the handle to PDBG_STREAM to use it)
+ * @param ePDumpStream - stream label
+ */
IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream);
+/*!
+ * @name PDumpOSGetStreamOffset
+ * @brief Return current offset within the labelled stream
+ * @param ePDumpStream - stream label
+ */
IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream);
+/*!
+ * @name PDumpOSGetParamFileNum
+ * @brief Return file number of the 'script' stream, in the case that the file was split
+ * @param ePDumpStream - stream label
+ */
IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID);
+/*!
+ * @name PDumpOSCheckForSplitting
+ * @brief Check if the requested pdump params are too large for a single file
+ * @param hStream - pdump stream
+ * @param ui32Size - size of params to dump (bytes)
+ * @param ui32Flags - pdump flags
+ */
IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags);
+/*!
+ * @name PDumpOSIsSuspended
+ * @brief Is the pdump stream busy?
+ * @return IMG_BOOL
+ */
IMG_BOOL PDumpOSIsSuspended(IMG_VOID);
+/*!
+ * @name PDumpOSIsSuspended
+ * @brief Is the pdump jump table initialised?
+ * @return IMG_BOOL
+ */
IMG_BOOL PDumpOSJTInitialised(IMG_VOID);
+/*!
+ * @name PDumpOSWriteString
+ * @brief General function for writing to pdump stream.
+ * Usually more convenient to use PDumpOSWriteString2 below.
+ * @param hDbgStream - pdump stream handle
+ * @param psui8Data - data to write
+ * @param ui32Size - size of write
+ * @param ui32Flags - pdump flags
+ * @return error
+ */
IMG_BOOL PDumpOSWriteString(IMG_HANDLE hDbgStream,
IMG_UINT8 *psui8Data,
IMG_UINT32 ui32Size,
IMG_UINT32 ui32Flags);
+/*!
+ * @name PDumpOSWriteString2
+ * @brief Write a string to the "script" output stream
+ * @param pszScript - buffer to write (ptr to state structure on Symbian)
+ * @param ui32Flags - pdump flags
+ * @return error
+ */
IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags);
+/*!
+ * @name PDumpOSBufprintf
+ * @brief Printf to OS-specific pdump state buffer
+ * @param hBuf - buffer handle to write into (ptr to state structure on Symbian)
+ * @param ui32ScriptSizeMax - maximum size of data to write (not supported on all OSes)
+ * @param pszFormat - format string
+ */
PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+/*!
+ * @name PDumpOSDebugPrintf
+ * @brief Debug message during pdumping
+ * @param pszFormat - format string
+ */
IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+/*
+ * FIXME: Is this function useful for Symbian?
+ * Write into a IMG_CHAR* on all OSes. Can be allocated on the stack or heap.
+ */
+/*!
+ * @name PDumpOSSprintf
+ * @brief Printf to IMG char array
+ * @param pszComment - char array to print into
+ * @param pszFormat - format string
+ */
PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+/*!
+ * @name PDumpOSVSprintf
+ * @brief Printf to IMG string using variable args (see stdarg.h). This is necessary
+ * because the ... notation does not support nested function calls.
+ * @param pszMsg - char array to print into
+ * @param ui32ScriptSizeMax - maximum size of data to write (not supported on all OSes)
+ * @param pszFormat - format string
+ * @param vaArgs - variable args structure (from stdarg.h)
+ */
PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) IMG_FORMAT_PRINTF(3, 0);
+/*!
+ * @name PDumpOSBuflen
+ * @param hBuffer - handle to buffer (ptr to state structure on Symbian)
+ * @param ui32BuffeRSizeMax - max size of buffer (chars)
+ * @return length of buffer, will always be <= ui32BufferSizeMax
+ */
IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+/*!
+ * @name PDumpOSVerifyLineEnding
+ * @brief Put \r\n sequence at the end if it isn't already there
+ * @param hBuffer - handle to buffer
+ * @param ui32BufferSizeMax - max size of buffer (chars)
+ */
IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+/*!
+ * @name PDumpOSCPUVAddrToDevPAddr
+ * @brief OS function to convert CPU virtual to device physical for dumping pages
+ * @param hOSMemHandle mem allocation handle (used if kernel virtual mem space is limited, e.g. linux)
+ * @param ui32Offset dword offset into allocation (for use with mem handle, e.g. linux)
+ * @param pui8LinAddr CPU linear addr (usually a kernel virtual address)
+ * @param ui32PageSize page size, used for assertion check
+ * @return psDevPAddr device physical addr
+ */
IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
IMG_UINT32 ui32PageSize,
IMG_DEV_PHYADDR *psDevPAddr);
+/*!
+ * @name PDumpOSCPUVAddrToPhysPages
+ * @brief OS function to convert CPU virtual to backing physical pages
+ * @param hOSMemHandle mem allocation handle (used if kernel virtual mem space is limited, e.g. linux)
+ * @param ui32Offset offset within mem allocation block
+ * @param pui8LinAddr CPU linear addr
+ * @param ui32DataPageMask mask for data page (= data page size -1)
+ * @return pui32PageOffset CPU page offset (same as device page offset if page sizes equal)
+ */
IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
IMG_PUINT8 pui8LinAddr,
IMG_UINT32 ui32DataPageMask,
IMG_UINT32 *pui32PageOffset);
+/*!
+ * @name PDumpOSReleaseExecution
+ * @brief OS function to switch to another process, to clear pdump buffers
+ */
IMG_VOID PDumpOSReleaseExecution(IMG_VOID);
+/*!
+ * @name PDumpOSIsCaptureFrameKM
+ * @brief Is the current frame a capture frame?
+ */
IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID);
+/*!
+ * @name PDumpOSSetFrameKM
+ * @brief Set frame counter
+ */
PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame);
#if defined (__cplusplus)
--- /dev/null
+/*************************************************************************/ /*!
+@Title Vista-specific Perf initialisation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef _PERFKM_H_
+#define _PERFKM_H_
+
+#include "img_types.h"
+
+/*
+ * Note, WDDM needs to perform initialisation and deinitialisation
+ * in order to support HW performance measurement. Other platforms
+ * should not need to do anything in these functions.
+ */
+#define PERFINIT()
+#define PERFDEINIT()
+
+#endif /* _PERFKM_H_ */
+
+/******************************************************************************
+ End of file (perfkm.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Handle Manager API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Perprocess data
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __PERPROC_H__
#define __PERPROC_H__
#endif
PVRSRV_HANDLE_BASE *psHandleBase;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* Handles are being allocated in batches */
IMG_BOOL bHandlesBatched;
#else
#if defined (PVR_SECURE_HANDLES)
-
+ /* Handles are being allocated in batches */
IMG_BOOL bHandlesBatched;
-#endif
-#endif
+#endif /* PVR_SECURE_HANDLES */
+#endif /* SUPPORT_SID_INTERFACE */
IMG_UINT32 ui32RefCount;
-
+ /* True if the process is the initialisation server. */
IMG_BOOL bInitProcess;
#if defined(PDUMP)
-
+ /* True if pdump data from the process is 'persistent' */
IMG_BOOL bPDumpPersistent;
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* True if this process is marked for pdumping. This flag is
+ * significant in a multi-app environment.
+ */
IMG_BOOL bPDumpActive;
-#endif
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
#endif
-
+ /*
+ * OS specific data can be stored via this handle.
+ * See osperproc.h for a generic mechanism for initialising
+ * this field.
+ */
IMG_HANDLE hOsPrivateData;
} PVRSRV_PER_PROCESS_DATA;
}
#endif
-#endif
+#endif /* __PERPROC_H__ */
+/******************************************************************************
+ End of file (perproc.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Power Management Functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for power management functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef POWER_H
#define POWER_H
#endif
+/*!
+ *****************************************************************************
+ * Power management
+ *****************************************************************************/
typedef struct _PVRSRV_POWER_DEV_TAG_
{
IMG_IMPORT
PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
- PVRSRV_DEV_POWER_STATE eNewPowerState,
- IMG_UINT32 ui32CallerID,
- IMG_BOOL bRetainMutex);
+ PVRSRV_DEV_POWER_STATE eNewPowerState);
IMG_IMPORT
PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* POWER_H */
+/******************************************************************************
+ End of file (power.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Command Queue API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Internal structures and definitions for command queues
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef QUEUE_H
#define QUEUE_H
extern "C" {
#endif
+/*!
+ * Macro to Read Offset in given command queue
+ */
#define UPDATE_QUEUE_ROFF(psQueue, ui32Size) \
(psQueue)->ui32ReadOffset = ((psQueue)->ui32ReadOffset + (ui32Size)) \
& ((psQueue)->ui32QueueSize - 1);
+/*!
+ generic cmd complete structure.
+ This structure represents the storage required between starting and finishing
+ a given cmd and is required to hold the generic sync object update data.
+ note: for any given system we know what command types we support and
+ therefore how much storage is required for any number of commands in progress
+ */
typedef struct _COMMAND_COMPLETE_DATA_
{
IMG_BOOL bInUse;
-
- IMG_UINT32 ui32DstSyncCount;
- IMG_UINT32 ui32SrcSyncCount;
- PVRSRV_SYNC_OBJECT *psDstSync;
- PVRSRV_SYNC_OBJECT *psSrcSync;
- IMG_UINT32 ui32AllocSize;
+ /* <arg(s) to PVRSRVProcessQueues>; */ /*!< TBD */
+ IMG_UINT32 ui32DstSyncCount; /*!< number of dst sync objects */
+ IMG_UINT32 ui32SrcSyncCount; /*!< number of src sync objects */
+ PVRSRV_SYNC_OBJECT *psDstSync; /*!< dst sync ptr list,
+ allocated on back of this structure */
+ PVRSRV_SYNC_OBJECT *psSrcSync; /*!< src sync ptr list,
+ allocated on back of this structure */
+ IMG_UINT32 ui32AllocSize; /*!< allocated size*/
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete; /*!< Command complete callback */
+ IMG_HANDLE hCallbackData; /*!< Command complete callback data */
}COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
#if !defined(USE_CODE)
PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
IMG_UINT32 ui32SrcSyncCount,
PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
- IMG_SIZE_T ui32DataByteSize );
+ IMG_SIZE_T ui32DataByteSize,
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete,
+ IMG_HANDLE hCallbackData);
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
IMG_UINT32 ui32CmdCount);
-#endif
+#endif /* !defined(USE_CODE) */
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* QUEUE_H */
+/******************************************************************************
+ End of file (queue.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Resource Allocator API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _RA_H_
#define _RA_H_
#include "hash.h"
#include "osfunc.h"
-typedef struct _RA_ARENA_ RA_ARENA;
+/** Resource arena.
+ * struct _RA_ARENA_ deliberately opaque
+ */
+typedef struct _RA_ARENA_ RA_ARENA; //PRQA S 3313
typedef struct _BM_MAPPING_ BM_MAPPING;
+/** Enable support for arena statistics. */
#define RA_STATS
+/** Resource arena statistics. */
struct _RA_STATISTICS_
{
-
+ /** total number of segments add to the arena */
IMG_SIZE_T uSpanCount;
-
+ /** number of current live segments within the arena */
IMG_SIZE_T uLiveSegmentCount;
-
+ /** number of current free segments within the arena */
IMG_SIZE_T uFreeSegmentCount;
-
+ /** total number of resource within the arena */
IMG_SIZE_T uTotalResourceCount;
-
+ /** number of free resource within the arena */
IMG_SIZE_T uFreeResourceCount;
-
+ /** total number of resources allocated from the arena */
IMG_SIZE_T uCumulativeAllocs;
-
+ /** total number of resources returned to the arena */
IMG_SIZE_T uCumulativeFrees;
-
+ /** total number of spans allocated by the callback mechanism */
IMG_SIZE_T uImportCount;
-
+ /** total number of spans deallocated by the callback mechanism */
IMG_SIZE_T uExportCount;
};
typedef struct _RA_STATISTICS_ RA_STATISTICS;
};
typedef struct _RA_SEGMENT_DETAILS_ RA_SEGMENT_DETAILS;
+/**
+ * @Function RA_Create
+ *
+ * @Description
+ *
+ * To create a resource arena.
+ *
+ * @Input name - the name of the arena for diagnostic purposes.
+ * @Input base - the base of an initial resource span or 0.
+ * @Input uSize - the size of an initial resource span or 0.
+ * @Input pRef - the reference to return for the initial resource or 0.
+ * @Input uQuantum - the arena allocation quantum.
+ * @Input alloc - a resource allocation callback or 0.
+ * @Input free - a resource de-allocation callback or 0.
+ * @Input import_handle - handle passed to alloc and free or 0.
+ * @Return arena handle, or IMG_NULL.
+ */
RA_ARENA *
RA_Create (IMG_CHAR *name,
IMG_UINTPTR_T base,
IMG_SIZE_T *pActualSize,
BM_MAPPING **ppsMapping,
IMG_UINT32 uFlags,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_UINTPTR_T *pBase),
IMG_VOID (*imp_free) (IMG_VOID *,
IMG_UINTPTR_T,
IMG_HANDLE),
IMG_VOID *import_handle);
+/**
+ * @Function RA_Delete
+ *
+ * @Description
+ *
+ * To delete a resource arena. All resources allocated from the arena
+ * must be freed before deleting the arena.
+ *
+ * @Input pArena - the arena to delete.
+ * @Return None
+ */
IMG_VOID
RA_Delete (RA_ARENA *pArena);
+/**
+ * @Function RA_TestDelete
+ *
+ * @Description
+ *
+ * To test whether it is safe to delete a resource arena. If any allocations
+ * have not been freed, the RA must not be deleted.
+ *
+ * @Input pArena - the arena to test.
+ * @Return IMG_BOOL - IMG_TRUE if is safe to go on and call RA_Delete.
+ */
IMG_BOOL
RA_TestDelete (RA_ARENA *pArena);
+/**
+ * @Function RA_Add
+ *
+ * @Description
+ *
+ * To add a resource span to an arena. The span must not overlap with
+ * any span previously added to the arena.
+ *
+ * @Input pArena - the arena to add a span into.
+ * @Input base - the base of the span.
+ * @Input uSize - the extent of the span.
+ * @Return IMG_TRUE - success, IMG_FALSE - failure
+ */
IMG_BOOL
RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize);
+/**
+ * @Function RA_Alloc
+ *
+ * @Description
+ *
+ * To allocate resource from an arena.
+ *
+ * @Input pArena - the arena
+ * @Input uRequestSize - the size of resource segment requested.
+ * @Output pActualSize - the actual_size of resource segment allocated,
+ * typcially rounded up by quantum.
+ * @Output ppsMapping - the user reference associated with allocated
+ * resource span.
+ * @Input uFlags - flags influencing allocation policy.
+ * @Input uAlignment - the alignment constraint required for the
+ * allocated segment, use 0 if alignment not required.
+ * @Input uAlignmentOffset - the required alignment offset
+ * @Input pvPrivData - private data passed to OS allocator
+ * @Input ui32PrivData - length of private data
+ *
+ * @Output pBase - allocated base resource
+ * @Return IMG_TRUE - success, IMG_FALSE - failure
+ */
IMG_BOOL
RA_Alloc (RA_ARENA *pArena,
IMG_SIZE_T uSize,
IMG_UINT32 uFlags,
IMG_UINT32 uAlignment,
IMG_UINT32 uAlignmentOffset,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_UINTPTR_T *pBase);
+/**
+ * @Function RA_Free
+ *
+ * @Description To free a resource segment.
+ *
+ * @Input pArena - the arena the segment was originally allocated from.
+ * @Input base - the base of the resource span to free.
+ * @Input bFreeBackingStore - Should backing store memory be freed?
+ *
+ * @Return None
+ */
IMG_VOID
RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore);
}
+/**
+ * @Function RA_GetNextLiveSegment
+ *
+ * @Description Returns details of the next live resource segments
+ *
+ * @Input pArena - the arena the segment was originally allocated from.
+ * @Output psSegDetails - rtn details of segments
+ *
+ * @Return IMG_TRUE if operation succeeded
+ */
IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails);
+/**
+ * @Function RA_GetStats
+ *
+ * @Description gets stats on a given arena
+ *
+ * @Input pArena - the arena the segment was originally allocated from.
+ * @Input ppszStr - string to write stats to
+ * @Input pui32StrLen - length of string
+ *
+ * @Return PVRSRV_ERROR
+ */
PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
IMG_CHAR **ppszStr,
IMG_UINT32 *pui32StrLen);
IMG_CHAR **ppszStr,
IMG_UINT32 *pui32StrLen);
-#endif
+#endif /* #ifdef RA_STATS */
#endif
--- /dev/null
+/*************************************************************************/ /*!
+@Title Services reference count debugging
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __REFCOUNT_H__
+#define __REFCOUNT_H__
+
+#include "pvr_bridge_km.h"
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+
+void PVRSRVDumpRefCountCCB(void);
+
+#define PVRSRVKernelSyncInfoIncRef(x...) \
+ PVRSRVKernelSyncInfoIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelSyncInfoDecRef(x...) \
+ PVRSRVKernelSyncInfoDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelMemInfoIncRef(x...) \
+ PVRSRVKernelMemInfoIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelMemInfoDecRef(x...) \
+ PVRSRVKernelMemInfoDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufIncRef(x...) \
+ PVRSRVBMBufIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufDecRef(x...) \
+ PVRSRVBMBufDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufIncExport(x...) \
+ PVRSRVBMBufIncExport2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufDecExport(x...) \
+ PVRSRVBMBufDecExport2(__FILE__, __LINE__, x)
+
+void PVRSRVKernelSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelMemInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVBMBufIncRef2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufDecRef2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufIncExport2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMXProcIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ IMG_UINT32 ui32Index);
+void PVRSRVBMXProcDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ IMG_UINT32 ui32Index);
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+#include "mmap.h"
+
+#define PVRSRVOffsetStructIncRef(x...) \
+ PVRSRVOffsetStructIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructDecRef(x...) \
+ PVRSRVOffsetStructDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructIncMapped(x...) \
+ PVRSRVOffsetStructIncMapped2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructDecMapped(x...) \
+ PVRSRVOffsetStructDecMapped2(__FILE__, __LINE__, x)
+
+void PVRSRVOffsetStructIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructIncMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+
+#endif /* defined(__linux__) */
+
+#else /* defined(PVRSRV_REFCOUNT_DEBUG) */
+
+static INLINE void PVRSRVDumpRefCountCCB(void) { }
+
+static INLINE void PVRSRVKernelSyncInfoIncRef(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+ PVRSRVAcquireSyncInfoKM(psKernelSyncInfo);
+}
+
+static INLINE void PVRSRVKernelSyncInfoDecRef(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+ PVRSRVReleaseSyncInfoKM(psKernelSyncInfo);
+}
+
+static INLINE void PVRSRVKernelMemInfoIncRef(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ psKernelMemInfo->ui32RefCount++;
+}
+
+static INLINE void PVRSRVKernelMemInfoDecRef(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ psKernelMemInfo->ui32RefCount--;
+}
+
+static INLINE void PVRSRVBMBufIncRef(BM_BUF *pBuf)
+{
+ pBuf->ui32RefCount++;
+}
+
+static INLINE void PVRSRVBMBufDecRef(BM_BUF *pBuf)
+{
+ pBuf->ui32RefCount--;
+}
+
+static INLINE void PVRSRVBMBufIncExport(BM_BUF *pBuf)
+{
+ pBuf->ui32ExportCount++;
+}
+
+static INLINE void PVRSRVBMBufDecExport(BM_BUF *pBuf)
+{
+ pBuf->ui32ExportCount--;
+}
+
+static INLINE void PVRSRVBMXProcIncRef(IMG_UINT32 ui32Index)
+{
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount++;
+}
+
+static INLINE void PVRSRVBMXProcDecRef(IMG_UINT32 ui32Index)
+{
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount--;
+}
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+#include "mmap.h"
+
+static INLINE void PVRSRVOffsetStructIncRef(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32RefCount++;
+}
+
+static INLINE void PVRSRVOffsetStructDecRef(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32RefCount--;
+}
+
+static INLINE void PVRSRVOffsetStructIncMapped(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32Mapped++;
+}
+
+static INLINE void PVRSRVOffsetStructDecMapped(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32Mapped--;
+}
+
+#endif /* defined(__linux__) */
+
+#endif /* defined(PVRSRV_REFCOUNT_DEBUG) */
+
+#endif /* __REFCOUNT_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Resource Manager API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource management
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __RESMAN_H__
#define __RESMAN_H__
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_DMA_CLIENT_FIFO_DATA,
-
-
-
-
-
- RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
- RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+/******************************************************************************
+ * resman definitions
+ *****************************************************************************/
+enum {
+ /* SGX: */
+ RESMAN_TYPE_SHARED_PB_DESC = 1, /*!< Parameter buffer kernel stubs */
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, /*!< Shared parameter buffer creation lock */
+ RESMAN_TYPE_HW_RENDER_CONTEXT, /*!< Hardware Render Context Resource */
+ RESMAN_TYPE_HW_TRANSFER_CONTEXT, /*!< Hardware transfer Context Resource */
+ RESMAN_TYPE_HW_2D_CONTEXT, /*!< Hardware 2D Context Resource */
+ RESMAN_TYPE_TRANSFER_CONTEXT, /*!< Transfer Queue context */
+
+ /* VGX: */
+ RESMAN_TYPE_DMA_CLIENT_FIFO_DATA, /*!< VGX DMA Client FIFO data */
+
+ /* DISPLAY CLASS: */
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, /*!< Display Class Swapchain Reference Resource */
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE, /*!< Display Class Device Resource */
+
+ /* BUFFER CLASS: */
+ RESMAN_TYPE_BUFFERCLASS_DEVICE, /*!< Buffer Class Device Resource */
- RESMAN_TYPE_BUFFERCLASS_DEVICE,
-
-
- RESMAN_TYPE_OS_USERMODE_MAPPING,
-
-
- RESMAN_TYPE_DEVICEMEM_CONTEXT,
- RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
- RESMAN_TYPE_DEVICEMEM_MAPPING,
- RESMAN_TYPE_DEVICEMEM_WRAP,
- RESMAN_TYPE_DEVICEMEM_ALLOCATION,
- RESMAN_TYPE_EVENT_OBJECT,
- RESMAN_TYPE_SHARED_MEM_INFO,
- RESMAN_TYPE_MODIFY_SYNC_OPS,
- RESMAN_TYPE_SYNC_INFO,
+ /* OS specific User mode Mappings: */
+ RESMAN_TYPE_OS_USERMODE_MAPPING, /*!< OS specific User mode mappings */
+ /* COMMON: */
+ RESMAN_TYPE_DEVICEMEM_CONTEXT, /*!< Device Memory Context Resource */
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING, /*!< Device Memory Mapping Resource */
+ RESMAN_TYPE_DEVICEMEM_MAPPING, /*!< Device Memory Mapping Resource */
+ RESMAN_TYPE_DEVICEMEM_WRAP, /*!< Device Memory Wrap Resource */
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION, /*!< Device Memory Allocation Resource */
+ RESMAN_TYPE_DEVICEMEM_ION, /*!< Device Memory Ion Resource */
+ RESMAN_TYPE_EVENT_OBJECT, /*!< Event Object */
+ RESMAN_TYPE_SHARED_MEM_INFO, /*!< Shared system memory meminfo */
+ RESMAN_TYPE_MODIFY_SYNC_OPS, /*!< Syncobject synchronisation Resource*/
+ RESMAN_TYPE_SYNC_INFO, /*!< Syncobject Resource*/
- RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION
+ /* KERNEL: */
+ RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION /*!< Device Memory Allocation Resource */
};
-#define RESMAN_CRITERIA_ALL 0x00000000
-#define RESMAN_CRITERIA_RESTYPE 0x00000001
-#define RESMAN_CRITERIA_PVOID_PARAM 0x00000002
-#define RESMAN_CRITERIA_UI32_PARAM 0x00000004
+#define RESMAN_CRITERIA_ALL 0x00000000 /*!< match by criteria all */
+#define RESMAN_CRITERIA_RESTYPE 0x00000001 /*!< match by criteria type */
+#define RESMAN_CRITERIA_PVOID_PARAM 0x00000002 /*!< match by criteria param1 */
+#define RESMAN_CRITERIA_UI32_PARAM 0x00000004 /*!< match by criteria param2 */
typedef PVRSRV_ERROR (*RESMAN_FREE_FN)(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bForceCleanup);
typedef struct _RESMAN_ITEM_ *PRESMAN_ITEM;
typedef struct _RESMAN_CONTEXT_ *PRESMAN_CONTEXT;
+/******************************************************************************
+ * resman functions
+ *****************************************************************************/
+
+/*
+ Note:
+ Resource cleanup can fail with retry in which case we don't remove
+ it from resman's list and either UM or KM will try to release the
+ resource at a later date (and will keep trying until a non-retry
+ error is returned)
+*/
+
PVRSRV_ERROR ResManInit(IMG_VOID);
IMG_VOID ResManDeInit(IMG_VOID);
}
#endif
-#endif
+#endif /* __RESMAN_H__ */
+
+/******************************************************************************
+ End of file (resman.h)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Command queues and synchronisation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Internal structures and definitions for command queues and
+ synchronisation
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
#ifndef SERVICES_HEADERS_H
#define SERVICES_HEADERS_H
#include "pvr_debug.h"
#include "metrics.h"
#include "osfunc.h"
+#include "refcount.h"
-#endif
+#endif /* SERVICES_HEADERS_H */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Services kernel module internal header file
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef SRVKM_H
#define SRVKM_H
extern "C" {
#endif
-
+ /** Use PVR_DPF() unless message is necessary in release build
+ */
#ifdef PVR_DISABLE_LOGGING
#define PVR_LOG(X)
#else
-
+ /* PRQA S 3410 1 */ /* this macro requires no brackets in order to work */
#define PVR_LOG(X) PVRSRVReleasePrintf X;
#endif
}
#endif
-
+/******************
+HIGHER LEVEL MACROS
+*******************/
+
+/*----------------------------------------------------------------------------
+Repeats the body of the loop for a certain minimum time, or until the body
+exits by its own means (break, return, goto, etc.)
+
+Example of usage:
+
+LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+{
+ if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
+ {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+} END_LOOP_UNTIL_TIMEOUT();
+
+-----------------------------------------------------------------------------*/
+
+/* uiNotLastLoop will remain at 1 until the timeout has expired, at which time
+ * it will be decremented and the loop executed one final time. This is necessary
+ * when preemption is enabled.
+ */
+/* PRQA S 3411,3431 12 */ /* critical format, leave alone */
#define LOOP_UNTIL_TIMEOUT(TIMEOUT) \
{\
IMG_UINT32 uiOffset, uiStart, uiCurrent; \
#define END_LOOP_UNTIL_TIMEOUT() \
}
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVGetErrorStringKM
+
+ @Description Returns a text string relating to the PVRSRV_ERROR enum.
+
+ ******************************************************************************/
IMG_IMPORT
const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError);
-#endif
+#endif /* SRVKM_H */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Timed Trace header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Timed Trace header. Contines structures and functions used
+ in the timed trace subsystem.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "services_headers.h"
#include "ttrace_common.h"
#include "ttrace_tokens.h"
1, (IMG_UINT8 *) &psPAddr.uiAddr);
}
-#else
+#else /* defined(PVRSRV_NEED_PVR_TIME_TRACE) */
#define PVR_TTRACE(group, class, token) \
((void) 0)
#define PVR_TTRACE_SYNC_OBJECT(group, token, syncobj, op) \
((void) 0)
-#endif
+#endif /* defined(PVRSRV_NEED_PVR_TIME_TRACE) */
IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceInit(IMG_VOID);
IMG_IMPORT IMG_VOID PVRSRVTimeTraceDeinit(IMG_VOID);
IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceBufferDestroy(IMG_UINT32 ui32PID);
IMG_IMPORT IMG_VOID PVRSRVDumpTimeTraceBuffers(IMG_VOID);
-#endif
+#endif /* __TTRACE_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Timed Trace header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Timed Trace common header. Contains shared defines and
+ structures which are shared with the post processing tool.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "img_types.h"
#ifndef __TTRACE_COMMON_H__
#define __TTRACE_COMMON_H__
+/*
+ * Trace item
+ * ==========
+ *
+ * A trace item contains a trace header, a timestamp, a UID and a
+ * data header all of which are 32-bit and mandatory. If there
+ * is no data then the data header size is set to 0.
+ *
+ * Trace header
+ * ------------
+ * 31 27 23 19 15 11 7 3
+ * GGGG GGGG CCCC CCCC TTTT TTTT TTTT TTTT
+ *
+ * G = group
+ * Note:
+ * Group 0xff means the message is padding
+ *
+ * C = class
+ * T = Token
+ *
+ * Data header
+ *-----------
+ * 31 27 23 19 15 11 7 3
+ * SSSS SSSS SSSS SSSS TTTT CCCC CCCC CCCC
+ *
+ * S = data packet size
+ * T = Type
+ * 0000 - 8 bit
+ * 0001 - 16 bit
+ * 0010 - 32 bit
+ * 0011 - 64 bit
+ *
+ * C = data item count
+ *
+ * Note: It might look strange having both the packet
+ * size and the data item count, but the idea
+ * is the you might have a "special" data type
+ * who's size might not be known by the post
+ * processing program and rather then fail
+ * processing the buffer after that point if we
+ * know the size we can just skip it and move to
+ * the next item.
+ */
+
+
#define PVRSRV_TRACE_HEADER 0
#define PVRSRV_TRACE_TIMESTAMP 1
#define PVRSRV_TRACE_HOSTUID 2
#define TIME_TRACE_BUFFER_SIZE 4096
+/* Type defines for trace items */
#define PVRSRV_TRACE_TYPE_UI8 0
#define PVRSRV_TRACE_TYPE_UI16 1
#define PVRSRV_TRACE_TYPE_UI32 2
#define PVRSRV_TRACE_SYNC_WO_DEV_VADDR 5
#define PVRSRV_TRACE_SYNC_RO_DEV_VADDR 6
#define PVRSRV_TRACE_SYNC_OP 7
-#define PVRSRV_TRACE_TYPE_SYNC_SIZE ((PVRSRV_TRACE_SYNC_OP + 1) * sizeof(IMG_UINT32))
+ #define PVRSRV_TRACE_SYNC_RO2P 8
+ #define PVRSRV_TRACE_SYNC_RO2C 9
+ #define PVRSRV_TRACE_SYNC_RO2_DEV_VADDR 10
+#define PVRSRV_TRACE_TYPE_SYNC_SIZE ((PVRSRV_TRACE_SYNC_RO2_DEV_VADDR + 1) * sizeof(IMG_UINT32))
-#endif
+#endif /* __TTRACE_COMMON_H__*/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Timed Trace header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Timed Trace token header. Contains defines for all the tokens
+ used.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef __TTRACE_TOKENS_H__
#define __TTRACE_TOKENS_H__
+/* All defines should use decimal so to not confuse the post processing tool */
+
+/* Trace groups */
#define PVRSRV_TRACE_GROUP_KICK 0
#define PVRSRV_TRACE_GROUP_TRANSFER 1
#define PVRSRV_TRACE_GROUP_QUEUE 2
#define PVRSRV_TRACE_GROUP_PADDING 255
+/* Trace classes */
#define PVRSRV_TRACE_CLASS_FUNCTION_ENTER 0
#define PVRSRV_TRACE_CLASS_FUNCTION_EXIT 1
#define PVRSRV_TRACE_CLASS_SYNC 2
#define PVRSRV_TRACE_CLASS_CMD_END 5
#define PVRSRV_TRACE_CLASS_CMD_COMP_START 6
#define PVRSRV_TRACE_CLASS_CMD_COMP_END 7
+#define PVRSRV_TRACE_CLASS_FLAGS 8
#define PVRSRV_TRACE_CLASS_NONE 255
+/* Operation about to happen on the sync object */
#define PVRSRV_SYNCOP_SAMPLE 0
#define PVRSRV_SYNCOP_COMPLETE 1
#define PVRSRV_SYNCOP_DUMP 2
+/*
+ * Trace tokens
+ * ------------
+ * These only need to unique within a group.
+ */
+
+/* Kick group tokens */
#define KICK_TOKEN_DOKICK 0
#define KICK_TOKEN_CCB_OFFSET 1
#define KICK_TOKEN_TA3D_SYNC 2
#define KICK_TOKEN_3D_SYNC 4
#define KICK_TOKEN_SRC_SYNC 5
#define KICK_TOKEN_DST_SYNC 6
+#define KICK_TOKEN_FIRST_KICK 7
+#define KICK_TOKEN_LAST_KICK 8
+/* Transfer Queue group tokens */
#define TRANSFER_TOKEN_SUBMIT 0
#define TRANSFER_TOKEN_TA_SYNC 1
#define TRANSFER_TOKEN_3D_SYNC 2
#define TRANSFER_TOKEN_DST_SYNC 4
#define TRANSFER_TOKEN_CCB_OFFSET 5
+/* Queue group tokens */
#define QUEUE_TOKEN_GET_SPACE 0
#define QUEUE_TOKEN_INSERTKM 1
#define QUEUE_TOKEN_SUBMITKM 2
#define QUEUE_TOKEN_DST_SYNC 9
#define QUEUE_TOKEN_COMMAND_TYPE 10
+/* uKernel Sync tokens */
#define MKSYNC_TOKEN_KERNEL_CCB_OFFSET 0
#define MKSYNC_TOKEN_CORE_CLK 1
#define MKSYNC_TOKEN_UKERNEL_CLK 2
-#endif
+#endif /* __TTRACE_TOKENS_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Common System APIs and structures
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides common system-specific declarations and macros
+ that are supported by all system's
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _SYSCOMMON_H
#define _SYSCOMMON_H
-#include "sysconfig.h"
-#include "sysinfo.h"
+#include "sysconfig.h" /* System specific system defines */
+#include "sysinfo.h" /* globally accessible system info */
#include "servicesint.h"
#include "queue.h"
#include "power.h"
extern "C" {
#endif
+/*!
+ ****************************************************************************
+ device id management structure
+ ****************************************************************************/
typedef struct _SYS_DEVICE_ID_TAG
{
IMG_UINT32 uiID;
} SYS_DEVICE_ID;
+/*
+ the max number of independent local backing stores services supports
+ (grow this number if ever required)
+*/
#define SYS_MAX_LOCAL_DEVMEM_ARENAS 4
typedef IMG_HANDLE (*PFN_HTIMER_CREATE) (IMG_VOID);
typedef IMG_UINT32 (*PFN_HTIMER_GETUS) (IMG_HANDLE);
typedef IMG_VOID (*PFN_HTIMER_DESTROY) (IMG_HANDLE);
+/*!
+ ****************************************************************************
+ Top level system data structure
+ ****************************************************************************/
typedef struct _SYS_DATA_TAG_
{
- IMG_UINT32 ui32NumDevices;
+ IMG_UINT32 ui32NumDevices; /*!< number of devices in system */
SYS_DEVICE_ID sDeviceID[SYS_DEVICE_COUNT];
- PVRSRV_DEVICE_NODE *psDeviceNodeList;
- PVRSRV_POWER_DEV *psPowerDeviceList;
- PVRSRV_RESOURCE sPowerStateChangeResource;
- PVRSRV_SYS_POWER_STATE eCurrentPowerState;
- PVRSRV_SYS_POWER_STATE eFailedPowerState;
- IMG_UINT32 ui32CurrentOSPowerState;
- PVRSRV_QUEUE_INFO *psQueueList;
- PVRSRV_KERNEL_SYNC_INFO *psSharedSyncInfoList;
- IMG_PVOID pvEnvSpecificData;
- IMG_PVOID pvSysSpecificData;
- PVRSRV_RESOURCE sQProcessResource;
- IMG_VOID *pvSOCRegsBase;
- IMG_HANDLE hSOCTimerRegisterOSMemHandle;
- IMG_UINT32 *pvSOCTimerRegisterKM;
- IMG_VOID *pvSOCClockGateRegsBase;
+ PVRSRV_DEVICE_NODE *psDeviceNodeList; /*!< list of private device info structures */
+ PVRSRV_POWER_DEV *psPowerDeviceList; /*!< list of devices registered with the power manager */
+ PVRSRV_RESOURCE sPowerStateChangeResource; /*!< lock for power state transitions */
+ PVRSRV_SYS_POWER_STATE eCurrentPowerState; /*!< current Kernel services power state */
+ PVRSRV_SYS_POWER_STATE eFailedPowerState; /*!< Kernel services power state (Failed to transition to) */
+ IMG_UINT32 ui32CurrentOSPowerState; /*!< current OS specific power state */
+ PVRSRV_QUEUE_INFO *psQueueList; /*!< list of all command queues in the system */
+ PVRSRV_KERNEL_SYNC_INFO *psSharedSyncInfoList; /*!< list of cross process syncinfos */
+ IMG_PVOID pvEnvSpecificData; /*!< Environment specific data */
+ IMG_PVOID pvSysSpecificData; /*!< Unique to system, accessible at system layer only */
+ PVRSRV_RESOURCE sQProcessResource; /*!< Command Q processing access lock */
+ IMG_VOID *pvSOCRegsBase; /*!< SOC registers base linear address */
+ IMG_HANDLE hSOCTimerRegisterOSMemHandle; /*!< SOC Timer register (if present) */
+ IMG_UINT32 *pvSOCTimerRegisterKM; /*!< SOC Timer register (if present) */
+ IMG_VOID *pvSOCClockGateRegsBase; /*!< SOC Clock gating registers (if present) */
IMG_UINT32 ui32SOCClockGateRegsSize;
struct _DEVICE_COMMAND_DATA_ *apsDeviceCommandData[SYS_DEVICE_COUNT];
-
+ /*!< command complete data and callback function store for every command for every device */
- RA_ARENA *apsLocalDevMemArena[SYS_MAX_LOCAL_DEVMEM_ARENAS];
+ RA_ARENA *apsLocalDevMemArena[SYS_MAX_LOCAL_DEVMEM_ARENAS]; /*!< RA Arenas for local device memory heap management */
- IMG_CHAR *pszVersionString;
+ IMG_CHAR *pszVersionString; /*!< Human readable string showing relevent system version info */
#if defined (SUPPORT_SID_INTERFACE)
- PVRSRV_EVENTOBJECT_KM *psGlobalEventObject;
+ PVRSRV_EVENTOBJECT_KM *psGlobalEventObject; /*!< OS Global Event Object */
#else
- PVRSRV_EVENTOBJECT *psGlobalEventObject;
+ PVRSRV_EVENTOBJECT *psGlobalEventObject; /*!< OS Global Event Object */
#endif
- PVRSRV_MISC_INFO_CPUCACHEOP_TYPE ePendingCacheOpType;
+ PVRSRV_MISC_INFO_CPUCACHEOP_TYPE ePendingCacheOpType; /*!< Deferred CPU cache op control */
PFN_HTIMER_CREATE pfnHighResTimerCreate;
PFN_HTIMER_GETUS pfnHighResTimerGetus;
} SYS_DATA;
+/****************************************************************************
+ * common function prototypes
+ ****************************************************************************/
+
+#if defined (CUSTOM_DISPLAY_SEGMENT)
+PVRSRV_ERROR SysGetDisplaySegmentAddress (IMG_VOID *pvDevInfo, IMG_VOID *pvPhysicalAddress, IMG_UINT32 *pui32Length);
+#endif
PVRSRV_ERROR SysInitialise(IMG_VOID);
PVRSRV_ERROR SysFinalise(IMG_VOID);
PVRSRV_DEV_POWER_STATE eNewPowerState,
PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+#if defined(SYS_SUPPORTS_SGX_IDLE_CALLBACK)
+IMG_VOID SysSGXIdleTransition(IMG_BOOL bSGXIdle);
+#endif /* SYS_SUPPORTS_SGX_IDLE_CALLBACK */
+
#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
PVRSRV_ERROR SysPowerLockWrap(IMG_BOOL bTryLock);
IMG_VOID SysPowerLockUnwrap(IMG_VOID);
#if !defined(USE_CODE)
+/*!
+******************************************************************************
+
+ @Function SysAcquireData
+
+ @Description returns reference to to sysdata
+ creating one on first call
+
+ @Input ppsSysData - pointer to copy reference into
+
+ @Return ppsSysData updated
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(SysAcquireData)
#endif
static INLINE IMG_VOID SysAcquireData(SYS_DATA **ppsSysData)
{
-
+ /* Copy pointer back system information pointer */
*ppsSysData = gpsSysData;
-
+ /*
+ Verify we've not been called before being initialised. Instinctively
+ we should do this check first, but in the failing case we'll just write
+ null back and the compiler won't warn about an uninitialised varible.
+ */
+ PVR_ASSERT (gpsSysData != IMG_NULL);
+}
+
+/*!
+******************************************************************************
+ @Function SysAcquireDataNoCheck
- PVR_ASSERT (gpsSysData != IMG_NULL);
-}
+ @Description returns reference to to sysdata
+ creating one on first call
+
+ @Input none
+ @Return psSysData - pointer to copy reference into
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(SysAcquireDataNoCheck)
#endif
static INLINE SYS_DATA * SysAcquireDataNoCheck(IMG_VOID)
{
-
+ /* return pointer back system information pointer */
return gpsSysData;
}
+/*!
+******************************************************************************
+
+ @Function SysInitialiseCommon
+
+ @Description Performs system initialisation common to all systems
+
+ @Input psSysData - pointer to system data
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(SysInitialiseCommon)
#endif
{
PVRSRV_ERROR eError;
-
+ /* Initialise Services */
eError = PVRSRVInit(psSysData);
return eError;
}
+/*!
+******************************************************************************
+
+ @Function SysDeinitialiseCommon
+
+ @Description Performs system deinitialisation common to all systems
+
+ @Input psSysData - pointer to system data
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(SysDeinitialiseCommon)
#endif
static INLINE IMG_VOID SysDeinitialiseCommon(SYS_DATA *psSysData)
{
-
+ /* De-initialise Services */
PVRSRVDeInit(psSysData);
OSDestroyResource(&psSysData->sPowerStateChangeResource);
}
-#endif
+#endif /* !defined(USE_CODE) */
+/*
+ * SysReadHWReg and SysWriteHWReg differ from OSReadHWReg and OSWriteHWReg
+ * in that they are always intended for use with real hardware, even on
+ * NO_HARDWARE systems.
+ */
#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
+#else /* !(defined(NO_HARDWARE) && defined(__linux__)) */
+/*!
+******************************************************************************
+
+ @Function SysReadHWReg
+
+ @Description
+
+ register read function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Offset :
+
+ @Return register value
+
+******************************************************************************/
static inline IMG_UINT32 SysReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
{
return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
}
+/*!
+******************************************************************************
+
+ @Function SysWriteHWReg
+
+ @Description
+
+ register write function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Offset :
+
+ @input ui32Value :
+
+ @Return none
+
+******************************************************************************/
static inline IMG_VOID SysWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
{
writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
}
-#endif
+#endif /* !(defined(NO_HARDWARE) && defined(__linux__)) */
#if defined(__cplusplus)
}
}
#endif
+/*****************************************************************************
+ End of file (syscommon.h)
+*****************************************************************************/
OSReservePhys(TimerRegPhysBase,
4,
PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED,
+ IMG_NULL,
(IMG_VOID **)&gpsSysData->pvSOCTimerRegisterKM,
&gpsSysData->hSOCTimerRegisterOSMemHandle);
}
OSReservePhys(TimerRegPhysBase,
4,
PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED,
+ IMG_NULL,
(IMG_VOID **)&gpsSysData->pvSOCTimerRegisterKM,
&gpsSysData->hSOCTimerRegisterOSMemHandle);
}
#endif
-#define SYS_DEVICE_COUNT 15
+#define SYS_DEVICE_COUNT 15
#endif
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX kernel/client driver interface structures and prototypes
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined(__OEMFUNCS_H__)
#define __OEMFUNCS_H__
extern "C" {
#endif
+/* function in/out data structures: */
typedef IMG_UINT32 (*PFN_SRV_BRIDGEDISPATCH)( IMG_UINT32 Ioctl,
IMG_BYTE *pInBuf,
IMG_UINT32 InBufLen,
IMG_BYTE *pOutBuf,
IMG_UINT32 OutBufLen,
IMG_UINT32 *pdwBytesTransferred);
+/*
+ Function table for kernel 3rd party driver to kernel services
+*/
typedef struct PVRSRV_DC_OEM_JTABLE_TAG
{
PFN_SRV_BRIDGEDISPATCH pfnOEMBridgeDispatch;
}
#endif
-#endif
+#endif /* __OEMFUNCS_H__ */
+
+/*****************************************************************************
+ End of file (oemfuncs.h)
+*****************************************************************************/
+
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title System Configuration
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description System Configuration functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "sysconfig.h"
#include "services_headers.h"
#include "ocpdefs.h"
+/* top level system data anchor point*/
SYS_DATA* gpsSysData = (SYS_DATA*)IMG_NULL;
SYS_DATA gsSysData;
static SYS_SPECIFIC_DATA gsSysSpecificData;
SYS_SPECIFIC_DATA *gpsSysSpecificData;
-static IMG_UINT32 gui32SGXDeviceID;
-static SGX_DEVICE_MAP gsSGXDeviceMap;
-static PVRSRV_DEVICE_NODE *gpsSGXDevNode;
+/* SGX structures */
+static IMG_UINT32 gui32SGXDeviceID;
+static SGX_DEVICE_MAP gsSGXDeviceMap;
+static PVRSRV_DEVICE_NODE *gpsSGXDevNode;
-#define DEVICE_SGX_INTERRUPT (1 << 0)
#if defined(NO_HARDWARE) || defined(SGX_OCP_REGS_ENABLED)
static IMG_CPU_VIRTADDR gsSGXRegsCPUVAddr;
return eError;
}
-#else
+#else /* defined(SGX_OCP_REGS_ENABLED) */
static INLINE PVRSRV_ERROR EnableSGXClocksWrap(SYS_DATA *psSysData)
{
return EnableSGXClocks(psSysData);
}
-#endif
+#endif /* defined(SGX_OCP_REGS_ENABLED) */
static INLINE PVRSRV_ERROR EnableSystemClocksWrap(SYS_DATA *psSysData)
{
#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
if(eError == PVRSRV_OK)
{
-
+ /*
+ * The SGX Clocks are enabled separately if active power
+ * management is enabled.
+ */
eError = EnableSGXClocksWrap(psSysData);
if (eError != PVRSRV_OK)
{
return eError;
}
+/*!
+******************************************************************************
+
+ @Function SysLocateDevices
+
+ @Description Specifies devices in the systems memory map
+
+ @Input psSysData - sys data
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData)
{
#if defined(NO_HARDWARE)
PVR_UNREFERENCED_PARAMETER(psSysData);
-
+ /* SGX Device: */
gsSGXDeviceMap.ui32Flags = 0x0;
#if defined(NO_HARDWARE)
-
-
+ /*
+ * For no hardware, allocate some contiguous memory for the
+ * register block.
+ */
+
+ /* Registers */
gsSGXDeviceMap.ui32RegsSize = SYS_OMAP4430_SGX_REGS_SIZE;
eError = OSBaseAllocContigMemory(gsSGXDeviceMap.ui32RegsSize,
gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr;
gsSGXDeviceMap.sRegsSysPBase = SysCpuPAddrToSysPAddr(gsSGXDeviceMap.sRegsCpuPBase);
#if defined(__linux__)
-
+ /* Indicate the registers are already mapped */
gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
#else
-
+ /*
+ * FIXME: Could we just use the virtual address returned by
+ * OSBaseAllocContigMemory?
+ */
gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL;
#endif
OSMemSet(gsSGXRegsCPUVAddr, 0, gsSGXDeviceMap.ui32RegsSize);
-
-
-
+ /*
+ device interrupt IRQ
+ Note: no interrupts available on no hardware system
+ */
gsSGXDeviceMap.ui32IRQ = 0;
-#else
+#else /* defined(NO_HARDWARE) */
#if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO)
-
+ /* get the resource and IRQ through platform resource API */
dev_res = platform_get_resource(gpsPVRLDMDev, IORESOURCE_MEM, 0);
if (dev_res == NULL)
{
gsSGXDeviceMap.ui32IRQ = dev_irq;
PVR_TRACE(("SGX IRQ: %d", gsSGXDeviceMap.ui32IRQ));
-#else
+#else /* defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) */
gsSGXDeviceMap.sRegsSysPBase.uiAddr = SYS_OMAP4430_SGX_REGS_SYS_PHYS_BASE;
gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
gsSGXDeviceMap.ui32RegsSize = SYS_OMAP4430_SGX_REGS_SIZE;
gsSGXDeviceMap.ui32IRQ = SYS_OMAP4430_SGX_IRQ;
-#endif
+#endif /* defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) */
#if defined(SGX_OCP_REGS_ENABLED)
gsSGXRegsCPUVAddr = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
gsSGXDeviceMap.ui32RegsSize,
return PVRSRV_ERROR_BAD_MAPPING;
}
-
+ /* Indicate the registers are already mapped */
gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
gpvOCPRegsLinAddr = gsSGXRegsCPUVAddr;
#endif
-#endif
+#endif /* defined(NO_HARDWARE) */
#if defined(PDUMP)
{
-
+ /* initialise memory region name for pdumping */
static IMG_CHAR pszPDumpDevName[] = "SGXMEM";
gsSGXDeviceMap.pszPDumpDevName = pszPDumpDevName;
}
#endif
-
+ /* add other devices here: */
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function SysCreateVersionString
+
+ @Description Read the version string
+
+ @Return IMG_CHAR * : Version string
+
+******************************************************************************/
static IMG_CHAR *SysCreateVersionString(void)
{
static IMG_CHAR aszVersionString[100];
}
+/*!
+******************************************************************************
+
+ @Function SysInitialise
+
+ @Description Initialises kernel services at 'driver load' time
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SysInitialise(IMG_VOID)
{
IMG_UINT32 i;
gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT;
-
+ /* init device ID's */
for(i=0; i<SYS_DEVICE_COUNT; i++)
{
gpsSysData->sDeviceID[i].uiID = i;
}
#if !defined(SGX_DYNAMIC_TIMING_INFO)
-
+ /* Set up timing information*/
psTimingInfo = &gsSGXDeviceMap.sTimingInfo;
psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
psTimingInfo->bEnableActivePM = IMG_TRUE;
#else
psTimingInfo->bEnableActivePM = IMG_FALSE;
-#endif
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ;
#endif
-
-
+ /*
+ Setup the Source Clock Divider value
+ */
gpsSysSpecificData->ui32SrcClockDiv = 3;
-
-
-
-
+ /*
+ Locate the devices within the system, specifying
+ the physical addresses of each devices components
+ (regs, mem, ports etc.)
+ */
eError = SysLocateDevices(gpsSysData);
if (eError != PVRSRV_OK)
{
}
SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME);
-
-
+ eError = SysDvfsInitialize(gpsSysSpecificData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialize DVFS"));
+ (IMG_VOID)SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_DVFS_INIT);
+ /*
+ Register devices with the system
+ This also sets up their memory maps/heaps
+ */
eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice,
DEVICE_SGX_INTERRUPT, &gui32SGXDeviceID);
if (eError != PVRSRV_OK)
}
SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_REGDEV);
-
-
-
-
+ /*
+ Once all devices are registered, specify the backing store
+ and, if required, customise the memory heap config
+ */
psDeviceNode = gpsSysData->psDeviceNodeList;
while(psDeviceNode)
{
-
+ /* perform any OEM SOC address space customisations here */
switch(psDeviceNode->sDevId.eDeviceType)
{
case PVRSRV_DEVICE_TYPE_SGX:
DEVICE_MEMORY_INFO *psDevMemoryInfo;
DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
-
-
-
+ /*
+ specify the backing store to use for the devices MMU PT/PDs
+ - the PT/PDs are always UMA in this system
+ */
psDeviceNode->psLocalDevMemArena = IMG_NULL;
-
+ /* useful pointers */
psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
-
+ /* specify the backing store for all SGX heaps */
for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++)
{
psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG;
return PVRSRV_ERROR_INIT_FAILURE;
}
-
+ /* advance to next device */
psDeviceNode = psDeviceNode->psNext;
}
gpsSysData = IMG_NULL;
return eError;
}
-#endif
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
eError = PVRSRVInitialiseDevice(gui32SGXDeviceID);
if (eError != PVRSRV_OK)
SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV);
#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
-
+ /* SGX defaults to D3 power state */
DisableSGXClocks(gpsSysData);
-#endif
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
#if !defined(PVR_NO_OMAP_TIMER)
#if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA)
OSReservePhys(TimerRegPhysBase,
4,
PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED,
+ IMG_NULL,
(IMG_VOID **)&gpsSysData->pvSOCTimerRegisterKM,
&gpsSysData->hSOCTimerRegisterOSMemHandle);
}
-#endif
+#endif /* !defined(PVR_NO_OMAP_TIMER) */
+
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function SysFinalise
+
+ @Description Final part of initialisation at 'driver load' time
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SysFinalise(IMG_VOID)
{
PVRSRV_ERROR eError = PVRSRV_OK;
PVR_DPF((PVR_DBG_ERROR,"SysFinalise: Failed to Enable SGX clocks (%d)", eError));
return eError;
}
-#endif
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
eError = OSInstallMISR(gpsSysData);
if (eError != PVRSRV_OK)
SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_MISR);
#if defined(SYS_USING_INTERRUPTS)
-
+ /* install a Device ISR */
eError = OSInstallDeviceLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ, "SGX ISR", gpsSGXDevNode);
if (eError != PVRSRV_OK)
{
return eError;
}
SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR);
-#endif
-
+#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ SysEnableSGXInterrupts(gpsSysData);
+#endif
+#endif /* defined(SYS_USING_INTERRUPTS) */
#if defined(__linux__)
-
+ /* Create a human readable version string for this system */
gpsSysData->pszVersionString = SysCreateVersionString();
if (!gpsSysData->pszVersionString)
{
#endif
#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
-
+ /* SGX defaults to D3 power state */
DisableSGXClocks(gpsSysData);
-#endif
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
gpsSysSpecificData->bSGXInitComplete = IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function SysDeinitialise
+
+ @Description De-initialises kernel services at 'driver unload' time
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR SysDeinitialise (SYS_DATA *psSysData)
{
PVRSRV_ERROR eError;
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+
if(gpsSysData->pvSOCTimerRegisterKM)
{
OSUnReservePhys(gpsSysData->pvSOCTimerRegisterKM,
gpsSysData->hSOCTimerRegisterOSMemHandle);
}
+
#if defined(SYS_USING_INTERRUPTS)
if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR))
{
- eError = OSUninstallDeviceLISR(psSysData);
+ eError = OSUninstallDeviceLISR(gpsSysData);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallDeviceLISR failed"));
if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_MISR))
{
- eError = OSUninstallMISR(psSysData);
+ eError = OSUninstallMISR(gpsSysData);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallMISR failed"));
{
#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
PVR_ASSERT(SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS));
-
+ /* Reenable SGX clocks whilst SGX is being deinitialised. */
eError = EnableSGXClocksWrap(gpsSysData);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: EnableSGXClocks failed"));
return eError;
}
-#endif
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
-
+ /* Deinitialise SGX */
eError = PVRSRVDeinitialiseDevice (gui32SGXDeviceID);
if (eError != PVRSRV_OK)
{
}
}
+ if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_DVFS_INIT))
+ {
+ eError = SysDvfsDeinitialize(gpsSysSpecificData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: Failed to de-init DVFS"));
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+ }
+
if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME))
{
eError = SysPMRuntimeUnregister();
}
}
-
-
+ /*
+ Disable system clocks - must happen after last access to hardware.
+ */
if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS))
{
DisableSystemClocks(gpsSysData);
if(gsSGXRegsCPUVAddr != IMG_NULL)
{
#if defined(NO_HARDWARE)
-
+ /* Free hardware resources. */
OSBaseFreeContigMemory(SYS_OMAP4430_SGX_REGS_SIZE, gsSGXRegsCPUVAddr, gsSGXDeviceMap.sRegsCpuPBase);
#else
#if defined(SGX_OCP_REGS_ENABLED)
gpvOCPRegsLinAddr = IMG_NULL;
#endif
-#endif
+#endif /* defined(NO_HARDWARE) */
gsSGXRegsCPUVAddr = IMG_NULL;
gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
}
-#endif
+#endif /* defined(NO_HARDWARE) || defined(SGX_OCP_REGS_ENABLED) */
gpsSysSpecificData->ui32SysSpecificData = 0;
}
+/*!
+******************************************************************************
+
+ @Function SysGetDeviceMemoryMap
+
+ @Description returns a device address map for the specified device
+
+ @Input eDeviceType - device type
+ @Input ppvDeviceMap - void ptr to receive device specific info.
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_VOID **ppvDeviceMap)
{
{
case PVRSRV_DEVICE_TYPE_SGX:
{
-
+ /* just return a pointer to the structure */
*ppvDeviceMap = (IMG_VOID*)&gsSGXDeviceMap;
break;
}
+/*!
+******************************************************************************
+ @Function SysCpuPAddrToDevPAddr
+
+ @Description Compute a device physical address from a cpu physical
+ address. Relevant when
+
+ @Input cpu_paddr - cpu physical address.
+ @Input eDeviceType - device type required if DevPAddr
+ address spaces vary across devices
+ in the same system
+ @Return device physical address.
+
+******************************************************************************/
IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_CPU_PHYADDR CpuPAddr)
{
PVR_UNREFERENCED_PARAMETER(eDeviceType);
-
+ /* Note: for UMA system we assume DevP == CpuP */
DevPAddr.uiAddr = CpuPAddr.uiAddr;
return DevPAddr;
}
+/*!
+******************************************************************************
+ @Function SysSysPAddrToCpuPAddr
+
+ @Description Compute a cpu physical address from a system physical
+ address.
+
+ @Input sys_paddr - system physical address.
+ @Return cpu physical address.
+
+******************************************************************************/
IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR sys_paddr)
{
IMG_CPU_PHYADDR cpu_paddr;
-
+ /* This would only be an inequality if the CPU's MMU did not point to
+ sys address 0, ie. multi CPU system */
cpu_paddr.uiAddr = sys_paddr.uiAddr;
return cpu_paddr;
}
+/*!
+******************************************************************************
+ @Function SysCpuPAddrToSysPAddr
+
+ @Description Compute a system physical address from a cpu physical
+ address.
+
+ @Input cpu_paddr - cpu physical address.
+ @Return device physical address.
+
+******************************************************************************/
IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr)
{
IMG_SYS_PHYADDR sys_paddr;
-
+ /* This would only be an inequality if the CPU's MMU did not point to
+ sys address 0, ie. multi CPU system */
sys_paddr.uiAddr = cpu_paddr.uiAddr;
return sys_paddr;
}
+/*!
+******************************************************************************
+ @Function SysSysPAddrToDevPAddr
+
+ @Description Compute a device physical address from a system physical
+ address.
+
+ @Input SysPAddr - system physical address.
+ @Input eDeviceType - device type required if DevPAddr
+ address spaces vary across devices
+ in the same system
+
+ @Return Device physical address.
+
+******************************************************************************/
IMG_DEV_PHYADDR SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr)
{
IMG_DEV_PHYADDR DevPAddr;
PVR_UNREFERENCED_PARAMETER(eDeviceType);
-
+ /* Note: for UMA system we assume DevP == CpuP */
DevPAddr.uiAddr = SysPAddr.uiAddr;
return DevPAddr;
}
+/*!
+******************************************************************************
+ @Function SysDevPAddrToSysPAddr
+
+ @Description Compute a device physical address from a system physical
+ address.
+
+ @Input DevPAddr - device physical address.
+ @Input eDeviceType - device type required if DevPAddr
+ address spaces vary across devices
+ in the same system
+
+ @Return System physical address.
+
+******************************************************************************/
IMG_SYS_PHYADDR SysDevPAddrToSysPAddr(PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR DevPAddr)
{
IMG_SYS_PHYADDR SysPAddr;
PVR_UNREFERENCED_PARAMETER(eDeviceType);
-
+ /* Note: for UMA system we assume DevP == SysP */
SysPAddr.uiAddr = DevPAddr.uiAddr;
return SysPAddr;
}
+/*****************************************************************************
+ @Function SysRegisterExternalDevice
+
+ @Description Called when a 3rd party device registers with services
+
+ @Input psDeviceNode - the new device node.
+
+ @Return IMG_VOID
+*****************************************************************************/
IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVR_UNREFERENCED_PARAMETER(psDeviceNode);
}
+/*****************************************************************************
+ @Function SysRemoveExternalDevice
+
+ @Description Called when a 3rd party device unregisters from services
+
+ @Input psDeviceNode - the device node being removed.
+
+ @Return IMG_VOID
+*****************************************************************************/
IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVR_UNREFERENCED_PARAMETER(psDeviceNode);
}
+/*!
+******************************************************************************
+ @Function SysGetInterruptSource
+
+ @Description Returns System specific information about the device(s) that
+ generated the interrupt in the system
+
+ @Input psSysData
+ @Input psDeviceNode
+ @Return System specific information indicating which device(s)
+ generated the interrupt
+
+******************************************************************************/
IMG_UINT32 SysGetInterruptSource(SYS_DATA *psSysData,
PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVR_UNREFERENCED_PARAMETER(psSysData);
#if defined(NO_HARDWARE)
-
+ /* no interrupts in no_hw system just return all bits */
return 0xFFFFFFFF;
#else
-
+ /* Not a shared irq, so we know this is an interrupt for this device */
return psDeviceNode->ui32SOCInterruptBit;
#endif
}
+/*!
+******************************************************************************
+ @Function SysClearInterrupts
+
+ @Description Clears specified system interrupts
+
+ @Input psSysData
+ @Input ui32ClearBits
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits)
{
PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
-#if defined(NO_HARDWARE)
PVR_UNREFERENCED_PARAMETER(psSysData);
-#else
+#if !defined(NO_HARDWARE)
#if defined(SGX_OCP_NO_INT_BYPASS)
OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_IRQSTATUS_2, 0x1);
#endif
-
+ /* Flush posted writes */
OSReadHWReg(((PVRSRV_SGXDEV_INFO *)gpsSGXDevNode->pvDevice)->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR);
-#endif
+#endif /* defined(NO_HARDWARE) */
}
#if defined(SGX_OCP_NO_INT_BYPASS)
+/*!
+******************************************************************************
+ @Function SysEnableSGXInterrupts
+
+ @Description Enables SGX interrupts
+
+ @Input psSysData
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SysEnableSGXInterrupts(SYS_DATA *psSysData)
{
SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
}
}
+/*!
+******************************************************************************
+ @Function SysDisableSGXInterrupts
+
+ @Description Disables SGX interrupts
+
+ @Input psSysData
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SysDisableSGXInterrupts(SYS_DATA *psSysData)
{
SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
SYS_SPECIFIC_DATA_CLEAR(psSysSpecData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
}
}
-#endif
+#endif /* defined(SGX_OCP_NO_INT_BYPASS) */
+/*!
+******************************************************************************
+
+ @Function SysSystemPrePowerState
+
+ @Description Perform system-level processing required before a power transition
+
+ @Input eNewPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
{
PVRSRV_ERROR eError = PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function SysSystemPostPowerState
+
+ @Description Perform system-level processing required after a power transition
+
+ @Input eNewPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
{
PVRSRV_ERROR eError = PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function SysDevicePrePowerState
+
+ @Description Perform system level processing required before a device power
+ transition
+
+ @Input ui32DeviceIndex :
+ @Input eNewPowerState :
+ @Input eCurrentPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
PVRSRV_DEV_POWER_STATE eNewPowerState,
PVRSRV_DEV_POWER_STATE eCurrentPowerState)
PVR_DPF((PVR_DBG_MESSAGE, "SysDevicePrePowerState: SGX Entering state D3"));
DisableSGXClocks(gpsSysData);
}
-#else
+#else /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
PVR_UNREFERENCED_PARAMETER(eNewPowerState );
-#endif
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function SysDevicePostPowerState
+
+ @Description Perform system level processing required after a device power
+ transition
+
+ @Input ui32DeviceIndex :
+ @Input eNewPowerState :
+ @Input eCurrentPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
PVRSRV_DEV_POWER_STATE eNewPowerState,
PVRSRV_DEV_POWER_STATE eCurrentPowerState)
PVR_DPF((PVR_DBG_MESSAGE, "SysDevicePostPowerState: SGX Leaving state D3"));
eError = EnableSGXClocksWrap(gpsSysData);
}
-#else
+#else /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
PVR_UNREFERENCED_PARAMETER(eCurrentPowerState);
-#endif
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
return eError;
}
+#if defined(SYS_SUPPORTS_SGX_IDLE_CALLBACK)
+
+IMG_VOID SysSGXIdleTransition(IMG_BOOL bSGXIdle)
+{
+ PVR_DPF((PVR_DBG_MESSAGE, "SysSGXIdleTransition switch to %u", bSGXIdle));
+}
+
+#endif /* defined(SYS_SUPPORTS_SGX_IDLE_CALLBACK) */
+
+/*****************************************************************************
+ @Function SysOEMFunction
+
+ @Description marshalling function for custom OEM functions
+
+ @Input ui32ID - function ID
+ @Input pvIn - in data
+ @Output pvOut - out data
+ @Return PVRSRV_ERROR
+*****************************************************************************/
PVRSRV_ERROR SysOEMFunction ( IMG_UINT32 ui32ID,
IMG_VOID *pvIn,
IMG_UINT32 ulInSize,
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;
}
+/******************************************************************************
+ End of file (sysconfig.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined(__SOCCONFIG_H__)
#define __SOCCONFIG_H__
#define SYS_SGX_CLOCK_SPEED 304742400
#endif
-#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ (100)
-#define SYS_SGX_PDS_TIMER_FREQ (1000)
+#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ (100) // 10ms (100hz)
+#define SYS_SGX_PDS_TIMER_FREQ (1000) // 1ms (1000hz)
+/* Allow the AP latency to be overridden in the build config */
#if !defined(SYS_SGX_ACTIVE_POWER_LATENCY_MS)
#define SYS_SGX_ACTIVE_POWER_LATENCY_MS (2)
#endif
#define SYS_OMAP4430_SGX_REGS_SYS_PHYS_BASE 0x56000000
-
#define SYS_OMAP4430_SGX_REGS_SIZE 0xFFFF
-#define SYS_OMAP4430_SGX_IRQ 53
+#define SYS_OMAP4430_SGX_IRQ 53 /* OMAP4 IRQ's are offset by 32 */
+
+#define SYS_OMAP4430_DSS_REGS_SYS_PHYS_BASE 0x58000000
+#define SYS_OMAP4430_DSS_REGS_SIZE 0x7000
+
+#define SYS_OMAP4430_DSS_HDMI_INTERRUPT_STATUS_REG 0x6028
+#define SYS_OMAP4430_DSS_HDMI_INTERRUPT_ENABLE_REG 0x602c
+
+#define SYS_OMAP4430_DSS_HDMI_INTERRUPT_VSYNC_ENABLE_MASK 0x10000
+#define SYS_OMAP4430_DSS_HDMI_INTERRUPT_VSYNC_STATUS_MASK 0x10000
+
+#define SYS_OMAP4430_DSS_LCD_INTERRUPT_STATUS_REG 0x1018
+#define SYS_OMAP4430_DSS_LCD_INTERRUPT_ENABLE_REG 0x101c
+
+#define SYS_OMAP4430_DSS_LCD_INTERRUPT_VSYNC_ENABLE_MASK 0x40002
+#define SYS_OMAP4430_DSS_LCD_INTERRUPT_VSYNC_STATUS_MASK 0x40002
+
#define SYS_OMAP4430_GP11TIMER_ENABLE_SYS_PHYS_BASE 0x48088038
#define SYS_OMAP4430_GP11TIMER_REGS_SYS_PHYS_BASE 0x4808803C
#define SYS_OMAP4430_GP11TIMER_TSICR_SYS_PHYS_BASE 0x48088054
+/* Interrupt bits */
+#define DEVICE_SGX_INTERRUPT (1<<0)
+#define DEVICE_MSVDX_INTERRUPT (1<<1)
+#define DEVICE_DISP_INTERRUPT (1<<2)
+
#if defined(__linux__)
+/*
+ * Recent OMAP4 kernels register SGX as platform device "omap_gpu".
+ * This device must be used with the Linux power management calls
+ * in sysutils_linux.c, in order for SGX to be powered on.
+ */
+#if defined(PVR_LDM_PLATFORM_PRE_REGISTERED_DEV)
+#define SYS_SGX_DEV_NAME PVR_LDM_PLATFORM_PRE_REGISTERED_DEV
+#else
#define SYS_SGX_DEV_NAME "omap_gpu"
-#endif
+#endif /* defined(PVR_LDM_PLATFORM_PRE_REGISTERED_DEV) */
+#endif /* defined(__linux__) */
+/*****************************************************************************
+ * system specific data structures
+ *****************************************************************************/
-#endif
+#endif /* __SYSCONFIG_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined(__SYSINFO_H__)
#define __SYSINFO_H__
+/*!< System specific poll/timeout details */
#if defined(PVR_LINUX_USING_WORKQUEUES)
+/*
+ * The workqueue based 3rd party display driver may be blocked for up
+ * to 500ms waiting for a vsync when the screen goes blank, so we
+ * need to wait longer for the hardware if a flush of the swap chain is
+ * required.
+ */
#define MAX_HW_TIME_US (1000000)
#define WAIT_TRY_COUNT (20000)
#else
#endif
-#define SYS_DEVICE_COUNT 15
+#define SYS_DEVICE_COUNT 15 /* SGX, DISPLAYCLASS (external), BUFFERCLASS (external) */
-#endif
+#endif /* __SYSINFO_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Local system definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides local system declarations and macros
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#if !defined(__SYSLOCAL_H__)
#define __SYSLOCAL_H__
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
#include <linux/semaphore.h>
#include <linux/resource.h>
-#else
+#else /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) */
#include <asm/semaphore.h>
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
#include <asm/arch/resource.h>
-#endif
-#endif
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) */
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
#if ((defined(DEBUG) || defined(TIMING)) && \
(LINUX_VERSION_CODE == KERNEL_VERSION(2,6,34))) && \
!defined(PVR_NO_OMAP_TIMER)
+/*
+ * We need to explicitly enable the GPTIMER11 clocks, or we'll get an
+ * abort when we try to access the timer registers.
+ */
#define PVR_OMAP4_TIMING_PRCM
#endif
#if !defined(PVR_NO_OMAP_TIMER)
#define PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA
#endif
-#endif
+#endif /* defined(__linux__) */
#if !defined(NO_HARDWARE) && \
- defined(SYS_USING_INTERRUPTS) && \
- defined(SGX540)
+ defined(SYS_USING_INTERRUPTS)
#define SGX_OCP_REGS_ENABLED
#endif
#if defined(__linux__)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) && defined(SGX_OCP_REGS_ENABLED)
+#if defined(SGX_OCP_REGS_ENABLED)
#define SGX_OCP_NO_INT_BYPASS
#endif
#endif
extern "C" {
#endif
+/*****************************************************************************
+ * system specific data structures
+ *****************************************************************************/
+/*****************************************************************************
+ * system specific function prototypes
+ *****************************************************************************/
IMG_VOID DisableSystemClocks(SYS_DATA *psSysData);
PVRSRV_ERROR EnableSystemClocks(SYS_DATA *psSysData);
IMG_VOID DisableSGXClocks(SYS_DATA *psSysData);
PVRSRV_ERROR EnableSGXClocks(SYS_DATA *psSysData);
+/*
+ * Various flags to indicate what has been initialised, and what
+ * has been temporarily deinitialised for power management purposes.
+ */
#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_PM_DISABLE_SYSCLOCKS 0x00000400
#define SYS_SPECIFIC_DATA_ENABLE_OCPREGS 0x00000800
#define SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME 0x00001000
-#if defined(SGX_OCP_REGS_ENABLED) && defined(SGX_OCP_NO_INT_BYPASS)
#define SYS_SPECIFIC_DATA_IRQ_ENABLED 0x00002000
-#endif
+#define SYS_SPECIFIC_DATA_DVFS_INIT 0x00004000
#define SYS_SPECIFIC_DATA_SET(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData |= (flag)))
#if defined(PVR_OMAP_USE_DM_TIMER_API)
struct omap_dm_timer *psGPTimer;
#endif
-#endif
+ IMG_UINT32 ui32SGXFreqListSize;
+ IMG_UINT32 *pui32SGXFreqList;
+ IMG_UINT32 ui32SGXFreqListIndex;
+#endif /* defined(__linux__) */
} SYS_SPECIFIC_DATA;
extern SYS_SPECIFIC_DATA *gpsSysSpecificData;
PVRSRV_ERROR SysPMRuntimeRegister(void);
PVRSRV_ERROR SysPMRuntimeUnregister(void);
-#else
+PVRSRV_ERROR SysDvfsInitialize(SYS_SPECIFIC_DATA *psSysSpecificData);
+PVRSRV_ERROR SysDvfsDeinitialize(SYS_SPECIFIC_DATA *psSysSpecificData);
+
+#else /* defined(__linux__) */
#ifdef INLINE_IS_PRAGMA
#pragma inline(SysPMRuntimeRegister)
return PVRSRV_OK;
}
-#endif
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysDvfsInitialize)
+#endif
+static INLINE PVRSRV_ERROR SysDvfsInitialize(void)
+{
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysDvfsDeinitialize)
+#endif
+static INLINE PVRSRV_ERROR SysDvfsDeinitialize(void)
+{
+ return PVRSRV_OK;
+}
+
+#endif /* defined(__linux__) */
#if defined(__cplusplus)
}
#endif
-#endif
+#endif /* __SYSLOCAL_H__ */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Shared (User/kernel) and System dependent utilities
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides system-specific functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/* Pull in the correct system dependent sysutils source */
#if defined(__linux__)
#include "sysutils_linux.c"
#endif
+
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title System dependent utilities
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides system-specific functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/hardirq.h>
#include <linux/mutex.h>
+#include <linux/slab.h>
#include "sgxdefs.h"
#include "services_headers.h"
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#if defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK)
+#include <linux/opp.h>
+#endif
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include <linux/omap_gpu.h>
+
+#include "pvr_drm.h"
+#endif
+
#define ONE_MHZ 1000000
#define HZ_TO_MHZ(m) ((m) / ONE_MHZ)
PowerLockUnwrap(psSysData->pvSysSpecificData);
}
+/*
+ * This function should be called to unwrap the Services power lock, prior
+ * to calling any function that might sleep.
+ * This function shouldn't be called prior to calling EnableSystemClocks
+ * or DisableSystemClocks, as those functions perform their own power lock
+ * unwrapping.
+ * If the function returns IMG_TRUE, UnwrapSystemPowerChange must be
+ * called to rewrap the power lock, prior to returning to Services.
+ */
IMG_BOOL WrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData)
{
return IMG_TRUE;
{
}
-static inline IMG_UINT32 scale_by_rate(IMG_UINT32 val, IMG_UINT32 rate1, IMG_UINT32 rate2)
-{
- if (rate1 >= rate2)
- {
- return val * (rate1 / rate2);
- }
-
- return val / (rate2 / rate1);
-}
-
-static inline IMG_UINT32 scale_prop_to_SGX_clock(IMG_UINT32 val, IMG_UINT32 rate)
-{
- return scale_by_rate(val, rate, SYS_SGX_CLOCK_SPEED);
-}
-
-static inline IMG_UINT32 scale_inv_prop_to_SGX_clock(IMG_UINT32 val, IMG_UINT32 rate)
-{
- return scale_by_rate(val, SYS_SGX_CLOCK_SPEED, rate);
-}
-
+/*
+ * Return SGX timining information to caller.
+ */
IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psTimingInfo)
{
- IMG_UINT32 rate;
-
- rate = SYS_SGX_CLOCK_SPEED;
#if !defined(NO_HARDWARE)
PVR_ASSERT(atomic_read(&gpsSysSpecificData->sSGXClocksEnabled) != 0);
#endif
- 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);
+#if defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK)
+ psTimingInfo->ui32CoreClockSpeed =
+ gpsSysSpecificData->pui32SGXFreqList[gpsSysSpecificData->ui32SGXFreqListIndex];
+#else /* defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK) */
+ psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
+#endif
+ psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
+ psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ;
#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
psTimingInfo->bEnableActivePM = IMG_TRUE;
#else
psTimingInfo->bEnableActivePM = IMG_FALSE;
-#endif
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
}
+/*!
+******************************************************************************
+
+ @Function EnableSGXClocks
+
+ @Description Enable SGX clocks
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR EnableSGXClocks(SYS_DATA *psSysData)
{
#if !defined(NO_HARDWARE)
SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
-
+ /* SGX clocks already enabled? */
if (atomic_read(&psSysSpecData->sSGXClocksEnabled) != 0)
{
return PVRSRV_OK;
PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: Enabling SGX Clocks"));
#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
+#if defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK)
+ {
+ struct gpu_platform_data *pdata;
+ IMG_UINT32 max_freq_index;
+ int res;
+
+ pdata = (struct gpu_platform_data *)gpsPVRLDMDev->dev.platform_data;
+ max_freq_index = psSysSpecData->ui32SGXFreqListSize - 2;
+
+ /*
+ * Request maximum frequency from DVFS layer if not already set. DVFS may
+ * report busy if early in initialization, but all other errors are
+ * considered serious. Upon any error we proceed assuming our safe frequency
+ * value to be in use as indicated by the "unknown" index.
+ */
+ if (psSysSpecData->ui32SGXFreqListIndex != max_freq_index)
+ {
+ PVR_ASSERT(pdata->device_scale != IMG_NULL);
+ res = pdata->device_scale(&gpsPVRLDMDev->dev,
+ &gpsPVRLDMDev->dev,
+ psSysSpecData->pui32SGXFreqList[max_freq_index]);
+ if (res == 0)
+ {
+ psSysSpecData->ui32SGXFreqListIndex = max_freq_index;
+ }
+ else if (res == -EBUSY)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "EnableSGXClocks: Unable to scale SGX frequency (EBUSY)"));
+ psSysSpecData->ui32SGXFreqListIndex = psSysSpecData->ui32SGXFreqListSize - 1;
+ }
+ else if (res < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: Unable to scale SGX frequency (%d)", res));
+ psSysSpecData->ui32SGXFreqListIndex = psSysSpecData->ui32SGXFreqListSize - 1;
+ }
+ }
+ }
+#endif /* defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK) */
{
-
+ /*
+ * pm_runtime_get_sync returns 1 after the module has
+ * been reloaded.
+ */
int res = pm_runtime_get_sync(&gpsPVRLDMDev->dev);
if (res < 0)
{
return PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK;
}
}
-#endif
+#endif /* defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI) */
+
SysEnableSGXInterrupts(psSysData);
-
+ /* Indicate that the SGX clocks are enabled */
atomic_set(&psSysSpecData->sSGXClocksEnabled, 1);
-#else
+#else /* !defined(NO_HARDWARE) */
PVR_UNREFERENCED_PARAMETER(psSysData);
-#endif
+#endif /* !defined(NO_HARDWARE) */
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function DisableSGXClocks
+
+ @Description Disable SGX clocks.
+
+ @Return none
+
+******************************************************************************/
IMG_VOID DisableSGXClocks(SYS_DATA *psSysData)
{
#if !defined(NO_HARDWARE)
SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
-
+ /* SGX clocks already disabled? */
if (atomic_read(&psSysSpecData->sSGXClocksEnabled) == 0)
{
return;
PVR_DPF((PVR_DBG_ERROR, "DisableSGXClocks: pm_runtime_put_sync failed (%d)", -res));
}
}
-#endif
+#if defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK)
+ {
+ struct gpu_platform_data *pdata;
+ int res;
+
+ pdata = (struct gpu_platform_data *)gpsPVRLDMDev->dev.platform_data;
+
+ /*
+ * Request minimum frequency (list index 0) from DVFS layer if not already
+ * set. DVFS may report busy if early in initialization, but all other errors
+ * are considered serious. Upon any error we proceed assuming our safe frequency
+ * value to be in use as indicated by the "unknown" index.
+ */
+ if (psSysSpecData->ui32SGXFreqListIndex != 0)
+ {
+ PVR_ASSERT(pdata->device_scale != IMG_NULL);
+ res = pdata->device_scale(&gpsPVRLDMDev->dev,
+ &gpsPVRLDMDev->dev,
+ psSysSpecData->pui32SGXFreqList[0]);
+ if (res == 0)
+ {
+ psSysSpecData->ui32SGXFreqListIndex = 0;
+ }
+ else if (res == -EBUSY)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "DisableSGXClocks: Unable to scale SGX frequency (EBUSY)"));
+ psSysSpecData->ui32SGXFreqListIndex = psSysSpecData->ui32SGXFreqListSize - 1;
+ }
+ else if (res < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DisableSGXClocks: Unable to scale SGX frequency (%d)", res));
+ psSysSpecData->ui32SGXFreqListIndex = psSysSpecData->ui32SGXFreqListSize - 1;
+ }
+ }
+ }
+#endif /* defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK) */
+#endif /* defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI) */
-
+ /* Indicate that the SGX clocks are disabled */
atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
-#else
+#else /* !defined(NO_HARDWARE) */
PVR_UNREFERENCED_PARAMETER(psSysData);
-#endif
+#endif /* !defined(NO_HARDWARE) */
}
#if (defined(DEBUG) || defined(TIMING)) && !defined(PVR_NO_OMAP_TIMER)
#if defined(PVR_OMAP_USE_DM_TIMER_API)
#define GPTIMER_TO_USE 11
+/*!
+******************************************************************************
+
+ @Function AcquireGPTimer
+
+ @Description Acquire a GP timer
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
{
PVR_ASSERT(psSysSpecData->psGPTimer == NULL);
-
+ /*
+ * This code could try requesting registers 9, 10, and 11,
+ * stopping at the first succesful request. We'll stick with
+ * 11 for now, as it avoids having to hard code yet more
+ * physical addresses into the code.
+ */
psSysSpecData->psGPTimer = omap_dm_timer_request_specific(GPTIMER_TO_USE);
if (psSysSpecData->psGPTimer == NULL)
{
return PVRSRV_ERROR_CLOCK_REQUEST_FAILED;
}
-
+ /* Set timer source to system clock */
omap_dm_timer_set_source(psSysSpecData->psGPTimer, OMAP_TIMER_SRC_SYS_CLK);
omap_dm_timer_enable(psSysSpecData->psGPTimer);
-
+ /* Set autoreload, and start value of 0 */
omap_dm_timer_set_load_start(psSysSpecData->psGPTimer, 1, 0);
omap_dm_timer_start(psSysSpecData->psGPTimer);
-
+ /*
+ * The DM timer API doesn't have a mechansim for obtaining the
+ * physical address of the counter register.
+ */
psSysSpecData->sTimerRegPhysBase.uiAddr = SYS_OMAP4430_GP11TIMER_REGS_SYS_PHYS_BASE;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function ReleaseGPTimer
+
+ @Description Release a GP timer
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static void ReleaseGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
{
if (psSysSpecData->psGPTimer != NULL)
{
-
+ /* Always returns 0 */
(void) omap_dm_timer_stop(psSysSpecData->psGPTimer);
omap_dm_timer_disable(psSysSpecData->psGPTimer);
}
}
-#else
+#else /* PVR_OMAP_USE_DM_TIMER_API */
+/*!
+******************************************************************************
+
+ @Function AcquireGPTimer
+
+ @Description Acquire a GP timer
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
{
#if defined(PVR_OMAP4_TIMING_PRCM)
PVR_ASSERT(psSysSpecData->sTimerRegPhysBase.uiAddr == 0);
#if defined(PVR_OMAP4_TIMING_PRCM)
-
+ /* assert our dependence on the GPTIMER11 module */
psCLK = clk_get(NULL, "gpt11_fck");
if (IS_ERR(psCLK))
{
PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't enable GPTIMER11 interface clock (%d)", res));
goto ExitDisableGPT11FCK;
}
-#endif
+#endif /* defined(PVR_OMAP4_TIMING_PRCM) */
-
+ /* Set the timer to non-posted mode */
sTimerRegPhysBase.uiAddr = SYS_OMAP4430_GP11TIMER_TSICR_SYS_PHYS_BASE;
pui32TimerEnable = OSMapPhysToLin(sTimerRegPhysBase,
4,
{
PVR_TRACE(("Setting GPTIMER11 mode to posted (currently is non-posted)"));
-
+ /* Set posted mode */
*pui32TimerEnable |= 4;
}
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
hTimerEnable);
-
+ /* Enable the timer */
sTimerRegPhysBase.uiAddr = SYS_OMAP4430_GP11TIMER_ENABLE_SYS_PHYS_BASE;
pui32TimerEnable = OSMapPhysToLin(sTimerRegPhysBase,
4,
goto ExitDisableGPT11ICK;
}
-
+ /* Enable and set autoreload on overflow */
*pui32TimerEnable = 3;
OSUnMapPhysToLin(pui32TimerEnable,
ExitDisableGPT11FCK:
clk_disable(psSysSpecData->psGPT11_FCK);
ExitError:
-#endif
+#endif /* defined(PVR_OMAP4_TIMING_PRCM) */
eError = PVRSRV_ERROR_CLOCK_REQUEST_FAILED;
Exit:
return eError;
}
+/*!
+******************************************************************************
+
+ @Function ReleaseGPTimer
+
+ @Description Release a GP timer
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static void ReleaseGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
{
IMG_HANDLE hTimerDisable;
return;
}
-
+ /* Disable the timer */
pui32TimerDisable = OSMapPhysToLin(psSysSpecData->sTimerRegPhysBase,
4,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
clk_disable(psSysSpecData->psGPT11_ICK);
clk_disable(psSysSpecData->psGPT11_FCK);
-#endif
+#endif /* defined(PVR_OMAP4_TIMING_PRCM) */
}
-#endif
-#else
+#endif /* PVR_OMAP_USE_DM_TIMER_API */
+#else /* (DEBUG || TIMING) && !PVR_NO_OMAP_TIMER */
static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
{
PVR_UNREFERENCED_PARAMETER(psSysSpecData);
{
PVR_UNREFERENCED_PARAMETER(psSysSpecData);
}
-#endif
+#endif /* (DEBUG || TIMING) && !PVR_NO_OMAP_TIMER */
+
+/*!
+******************************************************************************
+
+ @Function EnableSystemClocks
+
+ @Description Setup up the clocks for the graphics device to work.
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
PVRSRV_ERROR EnableSystemClocks(SYS_DATA *psSysData)
{
SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
return AcquireGPTimer(psSysSpecData);
}
+/*!
+******************************************************************************
+
+ @Function DisableSystemClocks
+
+ @Description Disable the graphics clocks.
+
+ @Return none
+
+******************************************************************************/
IMG_VOID DisableSystemClocks(SYS_DATA *psSysData)
{
SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
PVR_TRACE(("DisableSystemClocks: Disabling System Clocks"));
-
+ /*
+ * Always disable the SGX clocks when the system clocks are disabled.
+ * This saves having to make an explicit call to DisableSGXClocks if
+ * active power management is enabled.
+ */
DisableSGXClocks(psSysData);
ReleaseGPTimer(psSysSpecData);
#endif
return PVRSRV_OK;
}
+
+PVRSRV_ERROR SysDvfsInitialize(SYS_SPECIFIC_DATA *psSysSpecificData)
+{
+#if !defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK)
+ PVR_UNREFERENCED_PARAMETER(psSysSpecificData);
+#else /* !defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK) */
+ IMG_UINT32 i, *freq_list;
+ IMG_INT32 opp_count;
+ unsigned long freq;
+ struct opp *opp;
+
+ /*
+ * We query and store the list of SGX frequencies just this once under the
+ * assumption that they are unchanging, e.g. no disabling of high frequency
+ * option for thermal management. This is currently valid for 4430 and 4460.
+ */
+ rcu_read_lock();
+ opp_count = opp_get_opp_count(&gpsPVRLDMDev->dev);
+ if (opp_count < 1)
+ {
+ rcu_read_unlock();
+ PVR_DPF((PVR_DBG_ERROR, "SysDvfsInitialize: Could not retrieve opp count"));
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+
+ /*
+ * Allocate the frequency list with a slot for each available frequency plus
+ * one additional slot to hold a designated frequency value to assume when in
+ * an unknown frequency state.
+ */
+ freq_list = kmalloc((opp_count + 1) * sizeof(IMG_UINT32), GFP_ATOMIC);
+ if (!freq_list)
+ {
+ rcu_read_unlock();
+ PVR_DPF((PVR_DBG_ERROR, "SysDvfsInitialize: Could not allocate frequency list"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /*
+ * Fill in frequency list from lowest to highest then finally the "unknown"
+ * frequency value. We use the highest available frequency as our assumed value
+ * when in an unknown state, because it is safer for APM and hardware recovery
+ * timers to be longer than intended rather than shorter.
+ */
+ freq = 0;
+ for (i = 0; i < opp_count; i++)
+ {
+ opp = opp_find_freq_ceil(&gpsPVRLDMDev->dev, &freq);
+ if (IS_ERR_OR_NULL(opp))
+ {
+ rcu_read_unlock();
+ PVR_DPF((PVR_DBG_ERROR, "SysDvfsInitialize: Could not retrieve opp level %d", i));
+ kfree(freq_list);
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+ freq_list[i] = (IMG_UINT32)freq;
+ freq++;
+ }
+ rcu_read_unlock();
+ freq_list[opp_count] = freq_list[opp_count - 1];
+
+ psSysSpecificData->ui32SGXFreqListSize = opp_count + 1;
+ psSysSpecificData->pui32SGXFreqList = freq_list;
+
+ /* Start in unknown state - no frequency request to DVFS yet made */
+ psSysSpecificData->ui32SGXFreqListIndex = opp_count;
+#endif /* !defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK) */
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysDvfsDeinitialize(SYS_SPECIFIC_DATA *psSysSpecificData)
+{
+#if !defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK)
+ PVR_UNREFERENCED_PARAMETER(psSysSpecificData);
+#else /* !defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK) */
+ /*
+ * We assume this function is only called if SysDvfsInitialize() was
+ * completed successfully before.
+ *
+ * The DVFS interface does not allow us to actually unregister as a
+ * user of SGX, so we do the next best thing which is to lower our
+ * required frequency to the minimum if not already set. DVFS may
+ * report busy if early in initialization, but all other errors are
+ * considered serious.
+ */
+ if (psSysSpecificData->ui32SGXFreqListIndex != 0)
+ {
+ struct gpu_platform_data *pdata;
+ IMG_INT32 res;
+
+ pdata = (struct gpu_platform_data *)gpsPVRLDMDev->dev.platform_data;
+
+ PVR_ASSERT(pdata->device_scale != IMG_NULL);
+ res = pdata->device_scale(&gpsPVRLDMDev->dev,
+ &gpsPVRLDMDev->dev,
+ psSysSpecificData->pui32SGXFreqList[0]);
+ if (res == -EBUSY)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "SysDvfsDeinitialize: Unable to scale SGX frequency (EBUSY)"));
+ }
+ else if (res < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SysDvfsDeinitialize: Unable to scale SGX frequency (%d)", res));
+ }
+
+ psSysSpecificData->ui32SGXFreqListIndex = 0;
+ }
+
+ kfree(psSysSpecificData->pui32SGXFreqList);
+ psSysSpecificData->pui32SGXFreqList = 0;
+ psSysSpecificData->ui32SGXFreqListSize = 0;
+#endif /* !defined(SYS_OMAP4_HAS_DVFS_FRAMEWORK) */
+
+ return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+static struct omap_gpu_plugin sOMAPGPUPlugin;
+
+#define SYS_DRM_SET_PLUGIN_FIELD(d, s, f) (d)->f = (s)->f
+int
+SysDRMRegisterPlugin(PVRSRV_DRM_PLUGIN *psDRMPlugin)
+{
+ int iRes;
+
+ SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, name);
+ SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, open);
+ SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, load);
+ SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, unload);
+ SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, release);
+ SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, mmap);
+ SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, ioctls);
+ SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, num_ioctls);
+ SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, ioctl_start);
+
+ iRes = omap_gpu_register_plugin(&sOMAPGPUPlugin);
+ if (iRes != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: omap_gpu_register_plugin failed (%d)", __FUNCTION__, iRes));
+ }
+
+ return iRes;
+}
+
+void
+SysDRMUnregisterPlugin(PVRSRV_DRM_PLUGIN *psDRMPlugin)
+{
+ int iRes = omap_gpu_unregister_plugin(&sOMAPGPUPlugin);
+ if (iRes != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: omap_gpu_unregister_plugin failed (%d)", __FUNCTION__, iRes));
+ }
+}
+#endif
OSReservePhys(TimerRegPhysBase,
4,
PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED,
+ IMG_NULL,
(IMG_VOID **)&gpsSysData->pvSOCTimerRegisterKM,
&gpsSysData->hSOCTimerRegisterOSMemHandle);
}
/**********************************************************************
*
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
/**********************************************************************
*
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
*
******************************************************************************/
+#include "sysconfig.h"
#include "services_headers.h"
#include "kerneldisplay.h"
#include "oemfuncs.h"
#include "sgxinfo.h"
#include "sgxinfokm.h"
#include "syslocal.h"
-#include "sysconfig.h"
#include "ocpdefs.h"
-#if !defined(NO_HARDWARE) && \
- defined(SYS_USING_INTERRUPTS) && \
- defined(SGX530) && (SGX_CORE_REV == 125)
-#define SGX_OCP_REGS_ENABLED
-#endif
-
SYS_DATA* gpsSysData = (SYS_DATA*)IMG_NULL;
SYS_DATA gsSysData;
#define DEVICE_SGX_INTERRUPT (1 << 0)
-#if defined(NO_HARDWARE)
+#if defined(NO_HARDWARE) || defined(SGX_OCP_REGS_ENABLED)
static IMG_CPU_VIRTADDR gsSGXRegsCPUVAddr;
#endif
+#if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO)
+extern struct platform_device *gpsPVRLDMDev;
+#endif
+
IMG_UINT32 PVRSRV_BridgeDispatchKM(IMG_UINT32 Ioctl,
IMG_BYTE *pInBuf,
IMG_UINT32 InBufLen,
IMG_UINT32 OutBufLen,
IMG_UINT32 *pdwBytesTransferred);
-#if defined(DEBUG) && defined(DUMP_OMAP34xx_CLOCKS) && defined(__linux__)
-
-#pragma GCC diagnostic ignored "-Wstrict-prototypes"
-#include <mach/clock.h>
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
-#include <../mach-omap2/clock_34xx.h>
-#define ONCHIP_CLKS onchip_clks
-#else
-#include <../mach-omap2/clock34xx.h>
-#define ONCHIP_CLKS onchip_34xx_clks
-#endif
-
-static void omap3_clk_recalc(struct clk *clk) {}
-static void omap3_followparent_recalc(struct clk *clk) {}
-static void omap3_propagate_rate(struct clk *clk) {}
-static void omap3_table_recalc(struct clk *clk) {}
-static long omap3_round_to_table_rate(struct clk *clk, unsigned long rate) { return 0; }
-static int omap3_select_table_rate(struct clk *clk, unsigned long rate) { return 0; }
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
-static void omap3_dpll_recalc(struct clk *clk, unsigned long parent_rate,
- u8 rate_storage) {}
-static void omap3_clkoutx2_recalc(struct clk *clk, unsigned long parent_rate,
- u8 rate_storage) {}
-static void omap3_dpll_allow_idle(struct clk *clk) {}
-static void omap3_dpll_deny_idle(struct clk *clk) {}
-static u32 omap3_dpll_autoidle_read(struct clk *clk) { return 0; }
-static int omap3_noncore_dpll_enable(struct clk *clk) { return 0; }
-static void omap3_noncore_dpll_disable(struct clk *clk) {}
-static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) { return 0; }
-static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) { return 0; }
-void followparent_recalc(struct clk *clk, unsigned long new_parent_rate,
- u8 rate_storage) {}
-long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) { return 0; }
-void omap2_clksel_recalc(struct clk *clk, unsigned long new_parent_rate,
- u8 rate_storage) {}
-long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate) { return 0; }
-int omap2_clksel_set_rate(struct clk *clk, unsigned long rate) { return 0; }
-void omap2_fixed_divisor_recalc(struct clk *clk, unsigned long new_parent_rate,
- u8 rate_storage) {}
-void omap2_init_clksel_parent(struct clk *clk) {}
-#endif
-
-static void dump_omap34xx_clocks(void)
-{
- struct clk **c;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
- struct vdd_prcm_config *t1 = vdd1_rate_table;
- struct vdd_prcm_config *t2 = vdd2_rate_table;
-
- t1 = t1;
- t2 = t2;
-#else
-
- omap3_dpll_allow_idle(0);
- omap3_dpll_deny_idle(0);
- omap3_dpll_autoidle_read(0);
- omap3_clk_recalc(0);
- omap3_followparent_recalc(0);
- omap3_propagate_rate(0);
- omap3_table_recalc(0);
- omap3_round_to_table_rate(0, 0);
- omap3_select_table_rate(0, 0);
-#endif
-
- for(c = ONCHIP_CLKS; c < ONCHIP_CLKS + ARRAY_SIZE(ONCHIP_CLKS); c++)
- {
- struct clk *cp = *c, *copy;
- unsigned long rate;
- copy = clk_get(NULL, cp->name);
- if(!copy)
- continue;
- rate = clk_get_rate(copy);
- if (rate < 1000000)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: clock %s is %lu KHz (%lu Hz)", __func__, cp->name, rate/1000, rate));
- }
- else
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: clock %s is %lu MHz (%lu Hz)", __func__, cp->name, rate/1000000, rate));
- }
- }
-}
-
-#else
-
-static INLINE void dump_omap34xx_clocks(void) {}
-
-#endif
-
#if defined(SGX_OCP_REGS_ENABLED)
-#define SYS_TI81xx_OCP_REGS_SYS_PHYS_BASE (SYS_TI81xx_SGX_REGS_SYS_PHYS_BASE + EUR_CR_OCP_REVISION)
-#define SYS_TI81xx_OCP_REGS_SIZE 0x110
-
static IMG_CPU_VIRTADDR gpvOCPRegsLinAddr;
static PVRSRV_ERROR EnableSGXClocksWrap(SYS_DATA *psSysData)
{
PVRSRV_ERROR eError = EnableSGXClocks(psSysData);
+#if !defined(SGX_OCP_NO_INT_BYPASS)
if(eError == PVRSRV_OK)
{
- OSWriteHWReg(gpvOCPRegsLinAddr,
- EUR_CR_OCP_DEBUG_CONFIG - EUR_CR_OCP_REVISION,
- EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_MASK);
+ OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_SYSCONFIG, 0x14);
+ OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_DEBUG_CONFIG, EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_MASK);
}
-
+#endif
return eError;
}
if(eError == PVRSRV_OK)
{
- EnableSGXClocksWrap(psSysData);
+ eError = EnableSGXClocksWrap(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ DisableSystemClocks(psSysData);
+ }
}
#endif
#if defined(NO_HARDWARE)
PVRSRV_ERROR eError;
IMG_CPU_PHYADDR sCpuPAddr;
+#else
+#if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO)
+ struct resource *dev_res;
+ int dev_irq;
+#endif
#endif
PVR_UNREFERENCED_PARAMETER(psSysData);
#if defined(NO_HARDWARE)
- eError = OSBaseAllocContigMemory(SYS_TI81xx_SGX_REGS_SIZE,
+ gsSGXDeviceMap.ui32RegsSize = SYS_TI81xx_SGX_REGS_SIZE;
+
+ eError = OSBaseAllocContigMemory(gsSGXDeviceMap.ui32RegsSize,
&gsSGXRegsCPUVAddr,
&sCpuPAddr);
if(eError != PVRSRV_OK)
}
gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr;
gsSGXDeviceMap.sRegsSysPBase = SysCpuPAddrToSysPAddr(gsSGXDeviceMap.sRegsCpuPBase);
- gsSGXDeviceMap.ui32RegsSize = SYS_TI81xx_SGX_REGS_SIZE;
#if defined(__linux__)
gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL;
#endif
- OSMemSet(gsSGXRegsCPUVAddr, 0, SYS_TI81xx_SGX_REGS_SIZE);
+ OSMemSet(gsSGXRegsCPUVAddr, 0, gsSGXDeviceMap.ui32RegsSize);
gsSGXDeviceMap.ui32IRQ = 0;
#else
+#if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO)
+
+ dev_res = platform_get_resource(gpsPVRLDMDev, IORESOURCE_MEM, 0);
+ if (dev_res == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: platform_get_resource failed", __FUNCTION__));
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+ dev_irq = platform_get_irq(gpsPVRLDMDev, 0);
+ if (dev_irq < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: platform_get_irq failed (%d)", __FUNCTION__, -dev_irq));
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+ gsSGXDeviceMap.sRegsSysPBase.uiAddr = dev_res->start;
+ gsSGXDeviceMap.sRegsCpuPBase =
+ SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
+ PVR_TRACE(("SGX register base: 0x%lx", (unsigned long)gsSGXDeviceMap.sRegsCpuPBase.uiAddr));
+ gsSGXDeviceMap.ui32RegsSize = (unsigned int)(dev_res->end - dev_res->start);
+ PVR_TRACE(("SGX register size: %d",gsSGXDeviceMap.ui32RegsSize));
+
+ gsSGXDeviceMap.ui32IRQ = dev_irq;
+ PVR_TRACE(("SGX IRQ: %d", gsSGXDeviceMap.ui32IRQ));
+#else
gsSGXDeviceMap.sRegsSysPBase.uiAddr = SYS_TI81xx_SGX_REGS_SYS_PHYS_BASE;
gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
gsSGXDeviceMap.ui32RegsSize = SYS_TI81xx_SGX_REGS_SIZE;
gsSGXDeviceMap.ui32IRQ = SYS_TI81xx_SGX_IRQ;
+#endif
+#if defined(SGX_OCP_REGS_ENABLED)
+ gsSGXRegsCPUVAddr = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
+ gsSGXDeviceMap.ui32RegsSize,
+ PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY,
+ IMG_NULL);
+
+ if (gsSGXRegsCPUVAddr == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysLocateDevices: Failed to map SGX registers"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+
+
+ gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
+ gpvOCPRegsLinAddr = gsSGXRegsCPUVAddr;
+#endif
#endif
#if defined(PDUMP)
}
-IMG_CHAR *SysCreateVersionString(IMG_CPU_PHYADDR sRegRegion)
+static IMG_CHAR *SysCreateVersionString(void)
{
static IMG_CHAR aszVersionString[100];
SYS_DATA *psSysData;
#if !defined(NO_HARDWARE)
IMG_VOID *pvRegsLinAddr;
- pvRegsLinAddr = OSMapPhysToLin(sRegRegion,
+ pvRegsLinAddr = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
SYS_TI81xx_SGX_REGS_SIZE,
PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY,
IMG_NULL);
IMG_UINT32 i;
PVRSRV_ERROR eError;
PVRSRV_DEVICE_NODE *psDeviceNode;
+#if !defined(PVR_NO_OMAP_TIMER)
IMG_CPU_PHYADDR TimerRegPhysBase;
+#endif
#if !defined(SGX_DYNAMIC_TIMING_INFO)
SGX_TIMING_INFORMATION* psTimingInfo;
#endif
return eError;
}
- TimerRegPhysBase.uiAddr = SYS_TI81xx_GP7TIMER_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);
-
#if !defined(SGX_DYNAMIC_TIMING_INFO)
psTimingInfo = &gsSGXDeviceMap.sTimingInfo;
- if(cpu_is_ti816x())
- {
- psTimingInfo->ui32CoreClockSpeed = SYS_389x_SGX_CLOCK_SPEED;
- }
- else
- {
- psTimingInfo->ui32CoreClockSpeed = SYS_387x_SGX_CLOCK_SPEED;
- }
-
+if(cpu_is_ti816x())
+ psTimingInfo->ui32CoreClockSpeed = SYS_389x_SGX_CLOCK_SPEED;
+else
+ psTimingInfo->ui32CoreClockSpeed = SYS_387x_SGX_CLOCK_SPEED;
psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
psTimingInfo->bEnableActivePM = IMG_TRUE;
return eError;
}
SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV);
-
-#if defined(SGX_OCP_REGS_ENABLED)
+#if 0
+ eError = SysPMRuntimeRegister();
+ if (eError != PVRSRV_OK)
{
- IMG_SYS_PHYADDR sOCPRegsSysPBase;
- IMG_CPU_PHYADDR sOCPRegsCpuPBase;
-
- sOCPRegsSysPBase.uiAddr = SYS_TI81xx_OCP_REGS_SYS_PHYS_BASE;
- sOCPRegsCpuPBase = SysSysPAddrToCpuPAddr(sOCPRegsSysPBase);
-
- gpvOCPRegsLinAddr = OSMapPhysToLin(sOCPRegsCpuPBase,
- SYS_TI81xx_OCP_REGS_SIZE,
- PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY,
- IMG_NULL);
-
- if (gpvOCPRegsLinAddr == IMG_NULL)
- {
- PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to map OCP registers"));
- return PVRSRV_ERROR_BAD_MAPPING;
- }
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register with OSPM!"));
+ (IMG_VOID)SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
}
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME);
#endif
-
}
#endif
- dump_omap34xx_clocks();
-
eError = PVRSRVInitialiseDevice(gui32SGXDeviceID);
if (eError != PVRSRV_OK)
{
DisableSGXClocks(gpsSysData);
#endif
+#if !defined(PVR_NO_OMAP_TIMER)
+#if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA)
+ TimerRegPhysBase = gsSysSpecificData.sTimerRegPhysBase;
+#else
+ TimerRegPhysBase.uiAddr = SYS_TI81xx_GP7TIMER_REGS_SYS_PHYS_BASE;
+#endif
+ gpsSysData->pvSOCTimerRegisterKM = IMG_NULL;
+ gpsSysData->hSOCTimerRegisterOSMemHandle = 0;
+ if (TimerRegPhysBase.uiAddr != 0)
+ {
+ OSReservePhys(TimerRegPhysBase,
+ 4,
+ PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED,
+ IMG_NULL,
+ (IMG_VOID **)&gpsSysData->pvSOCTimerRegisterKM,
+ &gpsSysData->hSOCTimerRegisterOSMemHandle);
+ }
+#endif
+
return PVRSRV_OK;
}
eError = EnableSGXClocksWrap(gpsSysData);
if (eError != PVRSRV_OK)
{
- PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to Enable SGX clocks (%d)", eError));
- (IMG_VOID)SysDeinitialise(gpsSysData);
- gpsSysData = IMG_NULL;
+ PVR_DPF((PVR_DBG_ERROR,"SysFinalise: Failed to Enable SGX clocks (%d)", eError));
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"));
- (IMG_VOID)SysDeinitialise(gpsSysData);
- gpsSysData = IMG_NULL;
return eError;
}
SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_MISR);
+#if defined(SYS_USING_INTERRUPTS)
eError = OSInstallDeviceLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ, "SGX ISR", gpsSGXDevNode);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SysFinalise: Failed to install ISR"));
- (IMG_VOID)SysDeinitialise(gpsSysData);
- gpsSysData = IMG_NULL;
return eError;
}
SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR);
#endif
+#if defined(__linux__)
- gpsSysData->pszVersionString = SysCreateVersionString(gsSGXDeviceMap.sRegsCpuPBase);
+ gpsSysData->pszVersionString = SysCreateVersionString();
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));
+ PVR_TRACE(("SysFinalise: Version string: %s", gpsSysData->pszVersionString));
}
+#endif
#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
{
PVRSRV_ERROR eError;
+ if(gpsSysData->pvSOCTimerRegisterKM)
+ {
+ OSUnReservePhys(gpsSysData->pvSOCTimerRegisterKM,
+ 4,
+ PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED,
+ gpsSysData->hSOCTimerRegisterOSMemHandle);
+ }
+
#if defined(SYS_USING_INTERRUPTS)
if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR))
{
return eError;
}
}
+#endif
if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_MISR))
{
return eError;
}
}
-#else
- PVR_UNREFERENCED_PARAMETER(psSysData);
-#endif
if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV))
{
return eError;
}
}
-
-#if defined(SGX_OCP_REGS_ENABLED)
- OSUnMapPhysToLin(gpvOCPRegsLinAddr,
- SYS_TI81xx_OCP_REGS_SIZE,
- PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY,
- IMG_NULL);
+#if 0
+ if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME))
+ {
+ eError = SysPMRuntimeUnregister();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: Failed to unregister with OSPM!"));
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+ }
#endif
-
if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS))
}
}
- 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(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV))
+#if defined(NO_HARDWARE) || defined(SGX_OCP_REGS_ENABLED)
+ if(gsSGXRegsCPUVAddr != IMG_NULL)
{
+#if defined(NO_HARDWARE)
OSBaseFreeContigMemory(SYS_TI81xx_SGX_REGS_SIZE, gsSGXRegsCPUVAddr, gsSGXDeviceMap.sRegsCpuPBase);
- }
+#else
+#if defined(SGX_OCP_REGS_ENABLED)
+ OSUnMapPhysToLin(gsSGXRegsCPUVAddr,
+ gsSGXDeviceMap.ui32RegsSize,
+ PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY,
+ IMG_NULL);
+
+ gpvOCPRegsLinAddr = IMG_NULL;
#endif
+#endif
+ gsSGXRegsCPUVAddr = IMG_NULL;
+ gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
+ }
+#endif
gpsSysSpecificData->ui32SysSpecificData = 0;
IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits)
{
- PVR_UNREFERENCED_PARAMETER(psSysData);
PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
-
+#if defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+#else
+#if defined(SGX_OCP_NO_INT_BYPASS)
+ OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_IRQSTATUS_2, 0x1);
+#endif
- OSReadHWReg(((PVRSRV_SGXDEV_INFO *)gpsSGXDevNode->pvDevice)->pvRegsBaseKM,
- EUR_CR_EVENT_HOST_CLEAR);
+ OSReadHWReg(((PVRSRV_SGXDEV_INFO *)gpsSGXDevNode->pvDevice)->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR);
+#endif
}
+#if defined(SGX_OCP_NO_INT_BYPASS)
+IMG_VOID SysEnableSGXInterrupts(SYS_DATA *psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_LISR) && !SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_IRQ_ENABLED))
+ {
+ OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_IRQSTATUS_2, 0x1);
+ OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_IRQENABLE_SET_2, 0x1);
+ SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+ }
+}
+
+IMG_VOID SysDisableSGXInterrupts(SYS_DATA *psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
+
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_IRQ_ENABLED))
+ {
+ OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_IRQENABLE_CLR_2, 0x1);
+ SYS_SPECIFIC_DATA_CLEAR(psSysSpecData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+ }
+}
+#endif
PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
{
#if !defined(__SOCCONFIG_H__)
#define __SOCCONFIG_H__
-#include "syscommon.h"
#define VS_PRODUCT_NAME "TI81xx"
/**********************************************************************
*
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
#if defined(PVR_LINUX_USING_WORKQUEUES)
#define MAX_HW_TIME_US (1000000)
+#define WAIT_TRY_COUNT (20000)
#else
#define MAX_HW_TIME_US (500000)
+#define WAIT_TRY_COUNT (10000)
#endif
-#define WAIT_TRY_COUNT (10000)
-#define SYS_DEVICE_COUNT 3
+#define SYS_DEVICE_COUNT 15
#endif
/**********************************************************************
*
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
#endif
#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
+#if !defined(LDM_PLATFORM)
+#error "LDM_PLATFORM must be set"
+#endif
+/*#define PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO*/
+//#include <linux/platform_device.h>
+#endif
+
+#if ((defined(DEBUG) || defined(TIMING)) && \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32))) && \
+ !defined(PVR_NO_OMAP_TIMER)
+#define PVR_OMAP3_TIMING_PRCM
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
+/*#include <plat/gpu.h>*/
+#if !defined(PVR_NO_OMAP_TIMER)
+/*#define PVR_OMAP_USE_DM_TIMER_API*/
+//#include <plat/dmtimer.h>
+#endif
+#endif
+
+#if !defined(PVR_NO_OMAP_TIMER)
+//#define PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA
+#endif
#endif
+#if !defined(NO_HARDWARE) && \
+ defined(SYS_USING_INTERRUPTS) && \
+ defined(SGX540)
+#define SGX_OCP_REGS_ENABLED
+#endif
+
+#if defined(__linux__)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) && defined(SGX_OCP_REGS_ENABLED)
+/*#define SGX_OCP_NO_INT_BYPASS*/
+#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);
#define SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR 0x00000200
#define SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS 0x00000400
+#define SYS_SPECIFIC_DATA_ENABLE_OCPREGS 0x00000800
+#define SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME 0x00001000
+#if defined(SGX_OCP_REGS_ENABLED) && defined(SGX_OCP_NO_INT_BYPASS)
+#define SYS_SPECIFIC_DATA_IRQ_ENABLED 0x00002000
+#endif
#define SYS_SPECIFIC_DATA_SET(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData |= (flag)))
IMG_UINT32 ui32SysSpecificData;
PVRSRV_DEVICE_NODE *psSGXDevNode;
IMG_BOOL bSGXInitComplete;
+#if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA)
+ IMG_CPU_PHYADDR sTimerRegPhysBase;
+#endif
#if !defined(__linux__)
IMG_BOOL bSGXClocksEnabled;
#endif
atomic_t sNotifyLockCPU;
IMG_BOOL bCallVDD2PostFunc;
#endif
- struct clk *psCORE_CK;
- struct clk *psSGX_FCK;
- struct clk *psSGX_ICK;
- struct clk *psMPU_CK;
+ struct clk *psCORE_CK;
+ struct clk *psSGX_FCK;
+ struct clk *psSGX_ICK;
+
#if defined(DEBUG) || defined(TIMING)
struct clk *psGPT11_FCK;
struct clk *psGPT11_ICK;
#endif
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
- struct constraint_handle *pVdd2Handle;
-#endif
+#if defined(PVR_OMAP_USE_DM_TIMER_API)
+ struct omap_dm_timer *psGPTimer;
+#endif
#endif
} SYS_SPECIFIC_DATA;
extern SYS_SPECIFIC_DATA *gpsSysSpecificData;
+#if defined(SGX_OCP_REGS_ENABLED) && defined(SGX_OCP_NO_INT_BYPASS)
+IMG_VOID SysEnableSGXInterrupts(SYS_DATA* psSysData);
+IMG_VOID SysDisableSGXInterrupts(SYS_DATA* psSysData);
+#else
+#define SysEnableSGXInterrupts(psSysData)
+#define SysDisableSGXInterrupts(psSysData)
+#endif
+
#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
IMG_BOOL WrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData);
IMG_VOID UnwrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData);
#endif
+#if defined(__linux__)
+
+PVRSRV_ERROR SysPMRuntimeRegister(void);
+PVRSRV_ERROR SysPMRuntimeUnregister(void);
+
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysPMRuntimeRegister)
+#endif
+static INLINE PVRSRV_ERROR SysPMRuntimeRegister(void)
+{
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysPMRuntimeUnregister)
+#endif
+static INLINE PVRSRV_ERROR SysPMRuntimeUnregister(void)
+{
+ return PVRSRV_OK;
+}
+
+#endif
+
#if defined(__cplusplus)
}
#endif
/**********************************************************************
*
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
******************************************************************************/
#if defined(__linux__)
-#if defined(PVR_LINUX_USING_WORKQUEUES)
-#include "sysutils_linux_wqueue_compat.c"
-#else
#include "sysutils_linux.c"
#endif
-#endif
/**********************************************************************
*
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/hardirq.h>
-#include <linux/spinlock.h>
-#include <asm/bug.h>
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
-#include <linux/semaphore.h>
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,31))
-//#include <plat/resource.h>
-#include <plat/omap-pm.h>
-#else
-#include <mach/resource.h>
-#endif
-#else
-#include <asm/semaphore.h>
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
-#include <asm/arch/resource.h>
-#endif
-#endif
+#include <linux/mutex.h>
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) && \
- (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27))
-#define CONSTRAINT_NOTIFICATIONS
-#endif
#include "sgxdefs.h"
#include "services_headers.h"
#include "sysinfo.h"
#include "sgxinfokm.h"
#include "syslocal.h"
+//#include <linux/platform_device.h>
+//#include <linux/pm_runtime.h>
+
#define ONE_MHZ 1000000
#define HZ_TO_MHZ(m) ((m) / ONE_MHZ)
-#if defined(SUPPORT_OMAP3430_SGXFCLK_96M)
+#if defined(SUPPORT_TI81xx_SGXFCLK_96M)
#define SGX_PARENT_CLOCK "cm_96m_fck"
#else
#define SGX_PARENT_CLOCK "core_ck"
#endif
-//#define DEBUG
-#if !defined(PDUMP) && !defined(NO_HARDWARE)
-static IMG_BOOL PowerLockWrappedOnCPU(SYS_SPECIFIC_DATA *psSysSpecData)
-{
- IMG_INT iCPU;
- IMG_BOOL bLocked = IMG_FALSE;
-
- if (!in_interrupt())
- {
- iCPU = get_cpu();
- bLocked = (iCPU == atomic_read(&psSysSpecData->sPowerLockCPU));
-
- put_cpu();
- }
+#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
+extern struct platform_device *gpsPVRLDMDev;
+#endif
- return bLocked;
-}
-static IMG_VOID PowerLockWrap(SYS_SPECIFIC_DATA *psSysSpecData)
+static PVRSRV_ERROR PowerLockWrap(SYS_SPECIFIC_DATA *psSysSpecData, IMG_BOOL bTryLock)
{
- IMG_INT iCPU;
-
- if (!in_interrupt())
- {
-
- iCPU = get_cpu();
-
-
- PVR_ASSERT(iCPU != -1);
-
- PVR_ASSERT(!PowerLockWrappedOnCPU(psSysSpecData));
-
- spin_lock(&psSysSpecData->sPowerLock);
+ if (!in_interrupt())
+ {
+ if (bTryLock)
+ {
+ int locked = mutex_trylock(&psSysSpecData->sPowerLock);
+ if (locked == 0)
+ {
+ return PVRSRV_ERROR_RETRY;
+ }
+ }
+ else
+ {
+ mutex_lock(&psSysSpecData->sPowerLock);
+ }
+ }
- atomic_set(&psSysSpecData->sPowerLockCPU, iCPU);
- }
+ return PVRSRV_OK;
}
static IMG_VOID PowerLockUnwrap(SYS_SPECIFIC_DATA *psSysSpecData)
{
- if (!in_interrupt())
- {
- PVR_ASSERT(PowerLockWrappedOnCPU(psSysSpecData));
-
- atomic_set(&psSysSpecData->sPowerLockCPU, -1);
-
- spin_unlock(&psSysSpecData->sPowerLock);
-
- put_cpu();
- }
+ if (!in_interrupt())
+ {
+ mutex_unlock(&psSysSpecData->sPowerLock);
+ }
}
-PVRSRV_ERROR SysPowerLockWrap(SYS_DATA *psSysData)
+PVRSRV_ERROR SysPowerLockWrap(IMG_BOOL bTryLock)
{
- SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+ SYS_DATA *psSysData;
- PowerLockWrap(psSysSpecData);
+ SysAcquireData(&psSysData);
- return PVRSRV_OK;
+ return PowerLockWrap(psSysData->pvSysSpecificData, bTryLock);
}
-IMG_VOID SysPowerLockUnwrap(SYS_DATA *psSysData)
+IMG_VOID SysPowerLockUnwrap(IMG_VOID)
{
- SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+ SYS_DATA *psSysData;
- PowerLockUnwrap(psSysSpecData);
-}
-#else
-static IMG_BOOL PowerLockWrappedOnCPU(SYS_SPECIFIC_DATA unref__ *psSysSpecData)
-{
- return IMG_FALSE;
-}
+ SysAcquireData(&psSysData);
-static IMG_VOID PowerLockWrap(SYS_SPECIFIC_DATA unref__ *psSysSpecData)
-{
+ PowerLockUnwrap(psSysData->pvSysSpecificData);
}
-static IMG_VOID PowerLockUnwrap(SYS_SPECIFIC_DATA unref__ *psSysSpecData)
-{
-}
-PVRSRV_ERROR SysPowerLockWrap(SYS_DATA unref__ *psSysData)
-{
- return PVRSRV_OK;
-}
-IMG_VOID SysPowerLockUnwrap(SYS_DATA unref__ *psSysData)
-{
-}
-#endif
IMG_BOOL WrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData)
{
- IMG_BOOL bPowerLock = PowerLockWrappedOnCPU(psSysSpecData);
-
- if (bPowerLock)
- {
- PowerLockUnwrap(psSysSpecData);
- }
-
- return bPowerLock;
+ return IMG_TRUE;
}
IMG_VOID UnwrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData)
{
- PowerLockWrap(psSysSpecData);
}
static inline IMG_UINT32 scale_by_rate(IMG_UINT32 val, IMG_UINT32 rate1, IMG_UINT32 rate2)
static inline IMG_UINT32 scale_prop_to_SGX_clock(IMG_UINT32 val, IMG_UINT32 rate)
{
-
if(cpu_is_ti816x())
{
- return scale_by_rate(val, rate, SYS_389x_SGX_CLOCK_SPEED);
+ return scale_by_rate(val, rate, SYS_389x_SGX_CLOCK_SPEED);
}
else
{
- return scale_by_rate(val, rate, SYS_387x_SGX_CLOCK_SPEED);
+ return scale_by_rate(val, rate, SYS_387x_SGX_CLOCK_SPEED);
}
+
}
static inline IMG_UINT32 scale_inv_prop_to_SGX_clock(IMG_UINT32 val, IMG_UINT32 rate)
{
if(cpu_is_ti816x())
- {
- return scale_by_rate(val, SYS_389x_SGX_CLOCK_SPEED, rate);
- }
+ return scale_by_rate(val, SYS_389x_SGX_CLOCK_SPEED, rate);
else
- {
- return scale_by_rate(val, SYS_387x_SGX_CLOCK_SPEED, rate);
- }
+ return scale_by_rate(val, SYS_387x_SGX_CLOCK_SPEED, rate);
+
}
IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psTimingInfo)
{
IMG_UINT32 rate;
-#if defined(NO_HARDWARE)
if(cpu_is_ti816x())
- {
- rate = SYS_389x_SGX_CLOCK_SPEED;
- }
+ rate = SYS_389x_SGX_CLOCK_SPEED;
else
- {
- rate = SYS_387x_SGX_CLOCK_SPEED;
- }
+ rate = SYS_387x_SGX_CLOCK_SPEED;
-#else
+#if !defined(NO_HARDWARE)
PVR_ASSERT(atomic_read(&gpsSysSpecificData->sSGXClocksEnabled) != 0);
-
- rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK);
- PVR_ASSERT(rate != 0);
#endif
psTimingInfo->ui32CoreClockSpeed = rate;
psTimingInfo->ui32HWRecoveryFreq = scale_prop_to_SGX_clock(SYS_SGX_HWRECOVERY_TIMEOUT_FREQ, rate);
psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
}
-#if defined(CONSTRAINT_NOTIFICATIONS)
-#if !defined(SGX_DYNAMIC_TIMING_INFO)
-#error "SGX_DYNAMIC_TIMING_INFO must be defined for this platform"
-#endif
-
-static struct constraint_id cnstr_id_vdd2 = {
- .type = RES_OPP_CO,
- .data = (IMG_VOID *)"vdd2_opp"
-};
-
-#if !defined(PDUMP) && !defined(NO_HARDWARE)
-static inline IMG_BOOL ConstraintNotificationsEnabled(SYS_SPECIFIC_DATA *psSysSpecData)
-{
- return (atomic_read(&psSysSpecData->sSGXClocksEnabled) != 0) && psSysSpecData->bSGXInitComplete && psSysSpecData->bConstraintNotificationsEnabled;
-
-}
-
-static IMG_BOOL NotifyLockedOnCPU(SYS_SPECIFIC_DATA *psSysSpecData)
-{
- IMG_INT iCPU = get_cpu();
- IMG_BOOL bLocked = (iCPU == atomic_read(&psSysSpecData->sNotifyLockCPU));
-
- put_cpu();
-
- return bLocked;
-}
-
-static IMG_VOID NotifyLock(SYS_SPECIFIC_DATA *psSysSpecData)
-{
- IMG_INT iCPU;
-
- BUG_ON(in_interrupt());
-
-
- iCPU = get_cpu();
-
-
- PVR_ASSERT(iCPU != -1);
-
- PVR_ASSERT(!NotifyLockedOnCPU(psSysSpecData));
-
- spin_lock(&psSysSpecData->sNotifyLock);
-
- atomic_set(&psSysSpecData->sNotifyLockCPU, iCPU);
-}
-
-static IMG_VOID NotifyUnlock(SYS_SPECIFIC_DATA *psSysSpecData)
-{
- PVR_ASSERT(NotifyLockedOnCPU(psSysSpecData));
-
- atomic_set(&psSysSpecData->sNotifyLockCPU, -1);
-
- spin_unlock(&psSysSpecData->sNotifyLock);
-
- put_cpu();
-}
-
-static int VDD2PostFunc(struct notifier_block *n, unsigned long event, IMG_VOID *ptr)
-{
- PVR_UNREFERENCED_PARAMETER(n);
- PVR_UNREFERENCED_PARAMETER(event);
- PVR_UNREFERENCED_PARAMETER(ptr);
-
- if (in_interrupt())
- {
- PVR_DPF((PVR_DBG_ERROR, "%s Called in interrupt context. Ignoring.", __FUNCTION__));
- return 0;
- }
-
-
- if (!NotifyLockedOnCPU(gpsSysSpecificData))
- {
- return 0;
- }
-
-#if defined(DEBUG)
- if (ConstraintNotificationsEnabled(gpsSysSpecificData))
- {
- IMG_UINT32 rate;
-
- rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK);
-
- PVR_ASSERT(rate != 0);
-
- PVR_DPF((PVR_DBG_MESSAGE, "%s: SGX clock rate: %dMHz", __FUNCTION__, HZ_TO_MHZ(rate)));
- }
-#endif
- if (gpsSysSpecificData->bCallVDD2PostFunc)
- {
- PVRSRVDevicePostClockSpeedChange(gpsSysSpecificData->psSGXDevNode->sDevId.ui32DeviceIndex, IMG_TRUE, IMG_NULL);
-
- gpsSysSpecificData->bCallVDD2PostFunc = IMG_FALSE;
- }
- else
- {
- if (ConstraintNotificationsEnabled(gpsSysSpecificData))
- {
- PVR_TRACE(("%s: Not calling PVR clock speed notification functions", __FUNCTION__));
- }
- }
-
- NotifyUnlock(gpsSysSpecificData);
-
- return 0;
-}
-
-static int VDD2PreFunc(struct notifier_block *n, unsigned long event, IMG_VOID *ptr)
-{
- PVR_UNREFERENCED_PARAMETER(n);
- PVR_UNREFERENCED_PARAMETER(event);
- PVR_UNREFERENCED_PARAMETER(ptr);
-
- if (in_interrupt())
- {
- PVR_DPF((PVR_DBG_WARNING, "%s Called in interrupt context. Ignoring.", __FUNCTION__));
- return 0;
- }
-
- if (PowerLockWrappedOnCPU(gpsSysSpecificData))
- {
- PVR_DPF((PVR_DBG_WARNING, "%s Called from within a power transition. Ignoring.", __FUNCTION__));
- return 0;
- }
-
- NotifyLock(gpsSysSpecificData);
-
- PVR_ASSERT(!gpsSysSpecificData->bCallVDD2PostFunc);
-
- if (ConstraintNotificationsEnabled(gpsSysSpecificData))
- {
- PVRSRV_ERROR eError;
-
- eError = PVRSRVDevicePreClockSpeedChange(gpsSysSpecificData->psSGXDevNode->sDevId.ui32DeviceIndex, IMG_TRUE, IMG_NULL);
-
- gpsSysSpecificData->bCallVDD2PostFunc = (eError == PVRSRV_OK);
-
- }
-
- return 0;
-}
-
-static struct notifier_block sVDD2Pre = {
- VDD2PreFunc,
- NULL
-};
-
-static struct notifier_block sVDD2Post = {
- VDD2PostFunc,
- NULL
-};
-
-static IMG_VOID RegisterConstraintNotifications(IMG_VOID)
-{
- PVR_TRACE(("Registering constraint notifications"));
-
- PVR_ASSERT(!gpsSysSpecificData->bConstraintNotificationsEnabled);
-
- constraint_register_pre_notification(gpsSysSpecificData->pVdd2Handle, &sVDD2Pre,
- max_vdd2_opp+1);
-
- constraint_register_post_notification(gpsSysSpecificData->pVdd2Handle, &sVDD2Post,
- max_vdd2_opp+1);
-
-
- NotifyLock(gpsSysSpecificData);
- gpsSysSpecificData->bConstraintNotificationsEnabled = IMG_TRUE;
- NotifyUnlock(gpsSysSpecificData);
-
- PVR_TRACE(("VDD2 constraint notifications registered"));
-}
-
-static IMG_VOID UnRegisterConstraintNotifications(IMG_VOID)
-{
- PVR_TRACE(("Unregistering constraint notifications"));
-
-
- NotifyLock(gpsSysSpecificData);
- gpsSysSpecificData->bConstraintNotificationsEnabled = IMG_FALSE;
- NotifyUnlock(gpsSysSpecificData);
-
-
- constraint_unregister_pre_notification(gpsSysSpecificData->pVdd2Handle, &sVDD2Pre,
- max_vdd2_opp+1);
-
- constraint_unregister_post_notification(gpsSysSpecificData->pVdd2Handle, &sVDD2Post,
- max_vdd2_opp+1);
-}
-#else
-static IMG_VOID RegisterConstraintNotifications(IMG_VOID)
-{
-}
-
-static IMG_VOID UnRegisterConstraintNotifications(IMG_VOID)
-{
-}
-#endif
-#endif
-
PVRSRV_ERROR EnableSGXClocks(SYS_DATA *psSysData)
{
#if !defined(NO_HARDWARE)
SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
- long lNewRate;
- long lRate;
IMG_INT res;
-
+ long lRate,lNewRate;
if (atomic_read(&psSysSpecData->sSGXClocksEnabled) != 0)
{
}
PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: Enabling SGX Clocks"));
-
- res = clk_enable(psSysSpecData->psSGX_FCK);
+
+ 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_UNABLE_TO_ENABLE_CLOCK;
- }
+ {
+ PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: Couldn't enable SGX functional clock (%d)", res));
+ return PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK;
+ }
+if(cpu_is_ti816x())
+ lNewRate = clk_round_rate(psSysSpecData->psSGX_FCK, SYS_389x_SGX_CLOCK_SPEED + ONE_MHZ);
+else
+ lNewRate = clk_round_rate(psSysSpecData->psSGX_FCK, SYS_387x_SGX_CLOCK_SPEED + ONE_MHZ);
+ if (lNewRate <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: Couldn't round SGX functional clock rate"));
+ return PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE;
+ }
-#if 0
- lNewRate = clk_round_rate(psSysSpecData->psSGX_FCK, SYS_SGX_CLOCK_SPEED + ONE_MHZ);
- if (lNewRate <= 0)
- {
- PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: Couldn't round SGX functional clock rate"));
- return PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE;
- }
-
- lRate = clk_get_rate(psSysSpecData->psSGX_FCK);
- if (lRate != lNewRate)
- {
- res = clk_set_rate(psSysSpecData->psSGX_FCK, lNewRate);
- if (res < 0)
- {
- PVR_DPF((PVR_DBG_WARNING, "EnableSGXClocks: Couldn't set SGX functional clock rate (%d)", res));
- }
- }
-#endif
+ lRate = clk_get_rate(psSysSpecData->psSGX_FCK);
+ if (lRate != lNewRate)
+ {
+ res = clk_set_rate(psSysSpecData->psSGX_FCK, lNewRate);
+ if (res < 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "EnableSGXClocks: Couldn't set SGX functional clock rate (%d)", res));
+ return PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE;
+ }
+ }
-// IMG_UINT32 rate = clk_get_rate(psSysSpecData->psSGX_FCK);
-// PVR_TRACE((PVR_DBG_MESSAGE, "EnableSGXClocks: SGX Functional Clock is %dMhz", HZ_TO_MHZ(rate)));
#if defined(DEBUG)
+ {
+ IMG_UINT32 rate = clk_get_rate(psSysSpecData->psSGX_FCK);
+ PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: SGX Functional Clock is %dMhz", HZ_TO_MHZ(rate)));
+ }
+#endif
+
+
+
+#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
{
- IMG_UINT32 rate = clk_get_rate(psSysSpecData->psSGX_FCK);
- PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: SGX Functional Clock is %dMhz", HZ_TO_MHZ(rate)));
+
+// int res = pm_runtime_get_sync(&gpsPVRLDMDev->dev);
+// if (res < 0)
+// {
+// PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: pm_runtime_get_sync failed (%d)", -res));
+// return PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK;
+// }
}
#endif
+// SysEnableSGXInterrupts(psSysData);
atomic_set(&psSysSpecData->sSGXClocksEnabled, 1);
#if !defined(NO_HARDWARE)
SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
-
if (atomic_read(&psSysSpecData->sSGXClocksEnabled) == 0)
{
return;
}
-
+
PVR_DPF((PVR_DBG_MESSAGE, "DisableSGXClocks: Disabling SGX Clocks"));
+
+ clk_disable(psSysSpecData->psSGX_FCK);
+
+ clk_disable(psSysSpecData->psSGX_ICK);
- if (psSysSpecData->psSGX_FCK)
+// SysDisableSGXInterrupts(psSysData);
+
+#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
{
- clk_disable(psSysSpecData->psSGX_FCK);
+// int res = pm_runtime_put_sync(&gpsPVRLDMDev->dev);
+// if (res < 0)
+// {
+// PVR_DPF((PVR_DBG_ERROR, "DisableSGXClocks: pm_runtime_put_sync failed (%d)", -res));
+// }
}
+#endif
-
atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
#else
#endif
}
-PVRSRV_ERROR EnableSystemClocks(SYS_DATA *psSysData)
+#if (defined(DEBUG) || defined(TIMING)) && !defined(PVR_NO_OMAP_TIMER)
+#if defined(PVR_OMAP_USE_DM_TIMER_API)
+#define GPTIMER_TO_USE 11
+static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
{
- SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
- struct clk *psCLK;
- IMG_INT res;
- PVRSRV_ERROR eError;
- IMG_BOOL bPowerLock;
+ PVR_ASSERT(psSysSpecData->psGPTimer == NULL);
-#if defined(DEBUG) || defined(TIMING)
- IMG_INT rate;
- struct clk *sys_ck;
- IMG_CPU_PHYADDR TimerRegPhysBase;
- IMG_HANDLE hTimerEnable;
- IMG_UINT32 *pui32TimerEnable;
+
+ psSysSpecData->psGPTimer = omap_dm_timer_request_specific(GPTIMER_TO_USE);
+ if (psSysSpecData->psGPTimer == NULL)
+ {
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: omap_dm_timer_request_specific failed", __FUNCTION__));
+ return PVRSRV_ERROR_CLOCK_REQUEST_FAILED;
+ }
-#endif
+
+ omap_dm_timer_set_source(psSysSpecData->psGPTimer, OMAP_TIMER_SRC_SYS_CLK);
+ omap_dm_timer_enable(psSysSpecData->psGPTimer);
- PVR_TRACE(("EnableSystemClocks: Enabling System Clocks"));
+
+ omap_dm_timer_set_load_start(psSysSpecData->psGPTimer, 1, 0);
- if (!psSysSpecData->bSysClocksOneTimeInit)
- {
- bPowerLock = IMG_FALSE;
+ omap_dm_timer_start(psSysSpecData->psGPTimer);
- spin_lock_init(&psSysSpecData->sPowerLock);
- atomic_set(&psSysSpecData->sPowerLockCPU, -1);
- spin_lock_init(&psSysSpecData->sNotifyLock);
- atomic_set(&psSysSpecData->sNotifyLockCPU, -1);
+
+ psSysSpecData->sTimerRegPhysBase.uiAddr = SYS_TI81xx_GP7TIMER_REGS_SYS_PHYS_BASE;
- atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
-
- psCLK = clk_get(NULL, "sgx_ck");
-
- if (IS_ERR(psCLK))
- {
- PVR_DPF((PVR_DBG_ERROR, "EnableSsystemClocks: Couldn't get SGX Functional Clock"));
- goto ExitError;
- }
- psSysSpecData->psSGX_FCK = psCLK;
+ return PVRSRV_OK;
+}
- psSysSpecData->bSysClocksOneTimeInit = IMG_TRUE;
- }
- else
+static void ReleaseGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+ if (psSysSpecData->psGPTimer != NULL)
{
-
- bPowerLock = PowerLockWrappedOnCPU(psSysSpecData);
- if (bPowerLock)
- {
- PowerLockUnwrap(psSysSpecData);
- }
- }
+
+ (void) omap_dm_timer_stop(psSysSpecData->psGPTimer);
-#if defined(CONSTRAINT_NOTIFICATIONS)
- psSysSpecData->pVdd2Handle = constraint_get(PVRSRV_MODNAME, &cnstr_id_vdd2);
- if (IS_ERR(psSysSpecData->pVdd2Handle))
- {
- PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get VDD2 constraint handle"));
- goto ExitError;
+ omap_dm_timer_disable(psSysSpecData->psGPTimer);
+
+ omap_dm_timer_free(psSysSpecData->psGPTimer);
+
+ psSysSpecData->sTimerRegPhysBase.uiAddr = 0;
+
+ psSysSpecData->psGPTimer = NULL;
}
- RegisterConstraintNotifications();
+}
+#else
+static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+#if defined(PVR_OMAP3_TIMING_PRCM)
+ struct clk *psCLK;
+ IMG_INT res;
+ struct clk *sys_ck;
+ IMG_INT rate;
+#endif
+ PVRSRV_ERROR eError;
+
+ IMG_CPU_PHYADDR sTimerRegPhysBase;
+ IMG_HANDLE hTimerEnable;
+ IMG_UINT32 *pui32TimerEnable;
+#if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA)
+ PVR_ASSERT(psSysSpecData->sTimerRegPhysBase.uiAddr == 0);
#endif
-#if defined(DEBUG) || defined(TIMING)
- if(cpu_is_ti816x()) {
- psCLK = clk_get(NULL, "gpt6_fck");
- } else {
- psCLK = clk_get(NULL, "gpt7_fck");
- }
+
+#if defined(PVR_OMAP3_TIMING_PRCM)
+if(cpu_is_ti816x())
+ psCLK = clk_get(NULL, "gpt6_fck");
+else
+ psCLK = clk_get(NULL, "gpt6_fck");
if (IS_ERR(psCLK))
{
PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get GPTIMER11 functional clock"));
- goto ExitUnRegisterConstraintNotifications;
+ goto ExitError;
}
psSysSpecData->psGPT11_FCK = psCLK;
- if(cpu_is_ti816x()) {
- psCLK = clk_get(NULL, "gpt6_ick");
- } else {
- psCLK = clk_get(NULL, "gpt7_ick");
- }
+if(cpu_is_ti816x())
+ psCLK = clk_get(NULL, "gpt6_ick");
+else
+ psCLK = clk_get(NULL, "gpt7_ick");
if (IS_ERR(psCLK))
{
PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get GPTIMER11 interface clock"));
- goto ExitUnRegisterConstraintNotifications;
+ goto ExitError;
}
psSysSpecData->psGPT11_ICK = psCLK;
if (res < 0)
{
PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't enable GPTIMER11 functional clock (%d)", res));
- goto ExitUnRegisterConstraintNotifications;
+ goto ExitError;
}
res = clk_enable(psSysSpecData->psGPT11_ICK);
PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't enable GPTIMER11 interface clock (%d)", res));
goto ExitDisableGPT11FCK;
}
+#endif
- TimerRegPhysBase.uiAddr = SYS_TI81xx_GP7TIMER_TSICR_SYS_PHYS_BASE;
- pui32TimerEnable = OSMapPhysToLin(TimerRegPhysBase,
+ sTimerRegPhysBase.uiAddr = SYS_TI81xx_GP7TIMER_TSICR_SYS_PHYS_BASE;
+ pui32TimerEnable = OSMapPhysToLin(sTimerRegPhysBase,
4,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
&hTimerEnable);
goto ExitDisableGPT11ICK;
}
- rate = *pui32TimerEnable;
- if(!(rate & 4))
+ if(!(*pui32TimerEnable & 4))
{
PVR_TRACE(("Setting GPTIMER11 mode to posted (currently is non-posted)"));
- *pui32TimerEnable = rate | 4;
+ *pui32TimerEnable |= 4;
}
OSUnMapPhysToLin(pui32TimerEnable,
hTimerEnable);
- TimerRegPhysBase.uiAddr = SYS_TI81xx_GP7TIMER_ENABLE_SYS_PHYS_BASE;
- pui32TimerEnable = OSMapPhysToLin(TimerRegPhysBase,
+ sTimerRegPhysBase.uiAddr = SYS_TI81xx_GP7TIMER_ENABLE_SYS_PHYS_BASE;
+ pui32TimerEnable = OSMapPhysToLin(sTimerRegPhysBase,
4,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
&hTimerEnable);
goto ExitDisableGPT11ICK;
}
-
*pui32TimerEnable = 3;
OSUnMapPhysToLin(pui32TimerEnable,
4,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
hTimerEnable);
-
-#endif
-
-#if defined(PDUMP) && !defined(NO_HARDWARE) && defined(CONSTRAINT_NOTIFICATIONS)
- PVR_TRACE(("EnableSystemClocks: Setting SGX OPP constraint"));
-
-
- res = constraint_set(psSysSpecData->pVdd2Handle, max_vdd2_opp);
- if (res != 0)
- {
- PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: constraint_set failed (%d)", res));
- goto ExitConstraintSetFailed;
- }
+#if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA)
+ psSysSpecData->sTimerRegPhysBase = sTimerRegPhysBase;
#endif
+
eError = PVRSRV_OK;
+
goto Exit;
-#if defined(PDUMP) && !defined(NO_HARDWARE) && defined(CONSTRAINT_NOTIFICATIONS)
-ExitConstraintSetFailed:
-#endif
-#if defined(DEBUG) || defined(TIMING)
ExitDisableGPT11ICK:
+#if defined(PVR_OMAP3_TIMING_PRCM)
clk_disable(psSysSpecData->psGPT11_ICK);
ExitDisableGPT11FCK:
clk_disable(psSysSpecData->psGPT11_FCK);
-ExitUnRegisterConstraintNotifications:
+ExitError:
#endif
-#if defined(CONSTRAINT_NOTIFICATIONS)
- UnRegisterConstraintNotifications();
- constraint_put(psSysSpecData->pVdd2Handle);
-#endif
+ eError = PVRSRV_ERROR_CLOCK_REQUEST_FAILED;
Exit:
- if (bPowerLock)
- {
- PowerLockWrap(psSysSpecData);
- }
-
-ExitError:
- eError = PVRSRV_ERROR_DISABLE_CLOCK_FAILURE;
return eError;
}
-IMG_VOID DisableSystemClocks(SYS_DATA *psSysData)
+static void ReleaseGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
{
- SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
- IMG_BOOL bPowerLock;
-#if defined(DEBUG) || defined(TIMING)
- IMG_CPU_PHYADDR TimerRegPhysBase;
IMG_HANDLE hTimerDisable;
IMG_UINT32 *pui32TimerDisable;
-#endif
-
- PVR_TRACE(("DisableSystemClocks: Disabling System Clocks"));
-
-
- DisableSGXClocks(psSysData);
-
- bPowerLock = PowerLockWrappedOnCPU(psSysSpecData);
- if (bPowerLock)
- {
-
- PowerLockUnwrap(psSysSpecData);
- }
-
-#if defined(PDUMP) && !defined(NO_HARDWARE) && defined(CONSTRAINT_NOTIFICATIONS)
+ IMG_CPU_PHYADDR TimerRegPhysBase;
+#if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA)
+ if (psSysSpecData->sTimerRegPhysBase.uiAddr == 0)
{
- int res;
-
- PVR_TRACE(("DisableSystemClocks: Removing SGX OPP constraint"));
-
-
- res = constraint_remove(psSysSpecData->pVdd2Handle);
- if (res != 0)
- {
- PVR_DPF((PVR_DBG_WARNING, "DisableSystemClocks: constraint_remove failed (%d)", res));
- }
+ return;
}
#endif
-
-#if defined(CONSTRAINT_NOTIFICATIONS)
- UnRegisterConstraintNotifications();
-#endif
-
-#if defined(DEBUG) || defined(TIMING)
-
- TimerRegPhysBase.uiAddr = SYS_TI81xx_GP7TIMER_ENABLE_SYS_PHYS_BASE;
+ TimerRegPhysBase.uiAddr = SYS_TI81xx_GP7TIMER_ENABLE_SYS_PHYS_BASE;
pui32TimerDisable = OSMapPhysToLin(TimerRegPhysBase,
4,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
hTimerDisable);
}
+#if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA)
+ psSysSpecData->sTimerRegPhysBase.uiAddr = 0;
+#endif
+
+#if defined(PVR_OMAP3_TIMING_PRCM)
clk_disable(psSysSpecData->psGPT11_ICK);
clk_disable(psSysSpecData->psGPT11_FCK);
-
+#endif
+}
+#endif
+#else
+static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysSpecData);
+ return PVRSRV_OK;
+}
+static void ReleaseGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysSpecData);
+}
#endif
-#if defined(CONSTRAINT_NOTIFICATIONS)
- constraint_put(psSysSpecData->pVdd2Handle);
-#endif
- if (bPowerLock)
+
+PVRSRV_ERROR EnableSystemClocks(SYS_DATA *psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+ struct clk *psCLK;
+ PVR_TRACE(("EnableSystemClocks: Enabling System Clocks"));
+
+ if (!psSysSpecData->bSysClocksOneTimeInit)
{
- PowerLockWrap(psSysSpecData);
+ mutex_init(&psSysSpecData->sPowerLock);
+
+ atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
+
+
+ psCLK = clk_get(NULL, "sgx_ck");
+ if (IS_ERR(psCLK))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "EnableSsystemClocks: Couldn't get SGX Functional Clock"));
+ return PVRSRV_ERROR_UNABLE_TO_GET_CLOCK;
+ }
+ psSysSpecData->psSGX_FCK = psCLK;
+
}
+
+ return AcquireGPTimer(psSysSpecData);
+}
+
+IMG_VOID DisableSystemClocks(SYS_DATA *psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+ PVR_TRACE(("DisableSystemClocks: Disabling System Clocks"));
+
+ DisableSGXClocks(psSysData);
+
+ ReleaseGPTimer(psSysSpecData);
+
+}
+
+PVRSRV_ERROR SysPMRuntimeRegister(void)
+{
+#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
+// pm_runtime_enable(&gpsPVRLDMDev->dev);
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysPMRuntimeUnregister(void)
+{
+#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
+// pm_runtime_disable(&gpsPVRLDMDev->dev);
+#endif
+ return PVRSRV_OK;
}
+++ /dev/null
-/**********************************************************************
- *
- * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
-#include <linux/version.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/hardirq.h>
-#include <linux/mutex.h>
-
-#include "sgxdefs.h"
-#include "services_headers.h"
-#include "sysinfo.h"
-#include "sgxapi_km.h"
-#include "sysconfig.h"
-#include "sgxinfokm.h"
-#include "syslocal.h"
-
-#if !defined(PVR_LINUX_USING_WORKQUEUES)
-#error "PVR_LINUX_USING_WORKQUEUES must be defined"
-#endif
-
-#define ONE_MHZ 1000000
-#define HZ_TO_MHZ(m) ((m) / ONE_MHZ)
-
-#if defined(SUPPORT_OMAP3430_SGXFCLK_96M)
-#define SGX_PARENT_CLOCK "cm_96m_fck"
-#else
-#define SGX_PARENT_CLOCK "core_ck"
-#endif
-
-static PVRSRV_ERROR PowerLockWrap(SYS_SPECIFIC_DATA *psSysSpecData, IMG_BOOL bTryLock)
-{
- if (!in_interrupt())
- {
- if (bTryLock)
- {
- int locked = mutex_trylock(&psSysSpecData->sPowerLock);
- if (locked == 0)
- {
- return PVRSRV_ERROR_RETRY;
- }
- }
- else
- {
- mutex_lock(&psSysSpecData->sPowerLock);
- }
- }
-
- return PVRSRV_OK;
-}
-
-static IMG_VOID PowerLockUnwrap(SYS_SPECIFIC_DATA *psSysSpecData)
-{
- if (!in_interrupt())
- {
- mutex_unlock(&psSysSpecData->sPowerLock);
- }
-}
-
-PVRSRV_ERROR SysPowerLockWrap(IMG_BOOL bTryLock)
-{
- SYS_DATA *psSysData;
-
- SysAcquireData(&psSysData);
-
- return PowerLockWrap(psSysData->pvSysSpecificData, bTryLock);
-}
-
-IMG_VOID SysPowerLockUnwrap(IMG_VOID)
-{
- SYS_DATA *psSysData;
-
- SysAcquireData(&psSysData);
-
- PowerLockUnwrap(psSysData->pvSysSpecificData);
-}
-
-
-IMG_BOOL WrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData)
-{
- return IMG_TRUE;
-}
-
-IMG_VOID UnwrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData)
-{
-}
-
-static inline IMG_UINT32 scale_by_rate(IMG_UINT32 val, IMG_UINT32 rate1, IMG_UINT32 rate2)
-{
- if (rate1 >= rate2)
- {
- return val * (rate1 / rate2);
- }
-
- return val / (rate2 / rate1);
-}
-
-static inline IMG_UINT32 scale_prop_to_SGX_clock(IMG_UINT32 val, IMG_UINT32 rate)
-{
- if(cpu_is_ti816x())
- {
- return scale_by_rate(val, rate, SYS_389x_SGX_CLOCK_SPEED);
- }
- else
- {
-
- return scale_by_rate(val, rate, SYS_387x_SGX_CLOCK_SPEED);
- }
-}
-
-static inline IMG_UINT32 scale_inv_prop_to_SGX_clock(IMG_UINT32 val, IMG_UINT32 rate)
-{
- if(cpu_is_ti816x())
- {
- return scale_by_rate(val, SYS_389x_SGX_CLOCK_SPEED, rate);
- }
- else
- {
- return scale_by_rate(val, SYS_387x_SGX_CLOCK_SPEED, rate);
- }
-}
-
-IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psTimingInfo)
-{
- IMG_UINT32 rate;
-
-#if defined(NO_HARDWARE)
- if(cpu_is_ti816x())
- {
- rate = SYS_389x_SGX_CLOCK_SPEED;
- }
- else
- {
- rate = SYS_387x_SGX_CLOCK_SPEED;
- }
-
-#else
- PVR_ASSERT(atomic_read(&gpsSysSpecificData->sSGXClocksEnabled) != 0);
-
- rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK);
- PVR_ASSERT(rate != 0);
-#endif
- 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);
-#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
- psTimingInfo->bEnableActivePM = IMG_TRUE;
-#else
- psTimingInfo->bEnableActivePM = IMG_FALSE;
-#endif
- psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
-}
-
-PVRSRV_ERROR EnableSGXClocks(SYS_DATA *psSysData)
-{
-#if !defined(NO_HARDWARE)
- SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
-/*
- long lNewRate;
- long lRate;
-*/
- IMG_INT res;
-
-
- if (atomic_read(&psSysSpecData->sSGXClocksEnabled) != 0)
- {
- return PVRSRV_OK;
- }
-
- PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: Enabling SGX Clocks"));
-
-#if defined(DEBUG)
- {
-
- IMG_UINT32 rate = clk_get_rate(psSysSpecData->psMPU_CK);
- PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: CPU Clock is %dMhz", HZ_TO_MHZ(rate)));
- }
-#endif
-
- res = clk_enable(psSysSpecData->psSGX_FCK);
- if(res != 0)
- {
- PVR_DPF((PVR_DBG_ERROR, "EnableSsystemClocks: Couldn't enable SGX Clock"));
- return PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK;;
- }
-// else
-// PVR_TRACE(("EnableSystemClocks: SGX clk_enable successful"));
-
-// res = clk_get_rate(psSysSpecData->psSGX_FCK);
-// PVR_TRACE(("Default SGX clock rate is %dMHz", HZ_TO_MHZ(res)));
-
- if(cpu_is_ti816x())
- res = clk_set_rate(psSysSpecData->psSGX_FCK,SYS_389x_SGX_CLOCK_SPEED);
- else
- res = clk_set_rate(psSysSpecData->psSGX_FCK,SYS_387x_SGX_CLOCK_SPEED);
-
- if(res != 0)
- {
- PVR_DPF((PVR_DBG_ERROR, "EnableSsystemClocks: Couldn't set SGX Functional Clock rate"));
- return PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE;
- }
- else
- {
- res = clk_get_rate(psSysSpecData->psSGX_FCK);
-// PVR_TRACE(("SGX clock rate after set_clk_rate() is %dMHz", HZ_TO_MHZ(res)));
- }
-/*
- 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_UNABLE_TO_ENABLE_CLOCK;
- }
-*/
-/*
- 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_UNABLE_TO_ENABLE_CLOCK;
- }
-
- lNewRate = clk_round_rate(psSysSpecData->psSGX_FCK, SYS_SGX_CLOCK_SPEED + ONE_MHZ);
- if (lNewRate <= 0)
- {
- PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: Couldn't round SGX functional clock rate"));
- return PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE;
- }
-
-
- lRate = clk_get_rate(psSysSpecData->psSGX_FCK);
- if (lRate != lNewRate)
- {
- res = clk_set_rate(psSysSpecData->psSGX_FCK, lNewRate);
- if (res < 0)
- {
- PVR_DPF((PVR_DBG_WARNING, "EnableSGXClocks: Couldn't set SGX functional clock rate (%d)", res));
- }
- }
-*/
-#if defined(DEBUG)
- {
- IMG_UINT32 rate = clk_get_rate(psSysSpecData->psSGX_FCK);
- PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: SGX Functional Clock is %dMhz", HZ_TO_MHZ(rate)));
- }
-#endif
-
-
- atomic_set(&psSysSpecData->sSGXClocksEnabled, 1);
-
-#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 (atomic_read(&psSysSpecData->sSGXClocksEnabled) == 0)
- {
- return;
- }
-
- PVR_DPF((PVR_DBG_MESSAGE, "DisableSGXClocks: Disabling SGX Clocks"));
-
-/* if (psSysSpecData->psSGX_ICK)
- {
- clk_disable(psSysSpecData->psSGX_ICK);
- }
-*/
- if (psSysSpecData->psSGX_FCK)
- {
- clk_disable(psSysSpecData->psSGX_FCK);
- }
-
-
- atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
-
-#else
- PVR_UNREFERENCED_PARAMETER(psSysData);
-#endif
-}
-
-PVRSRV_ERROR EnableSystemClocks(SYS_DATA *psSysData)
-{
- SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
- struct clk *psCLK;
-// IMG_INT res;
-// IMG_BOOL bPowerLock;
- PVRSRV_ERROR eError;
-
-#if defined(DEBUG) || defined(TIMING)
- IMG_INT res;
- IMG_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->sPowerLock);
-
- atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
-
- // if(cpu_is_ti816x())
- // {
- psCLK = clk_get(NULL, "sgx_ck");
- // } else {
- // psCLK = clk_get(NULL, "gfx_fck");
- // }
- if (IS_ERR(psCLK))
- {
- PVR_DPF((PVR_DBG_ERROR, "EnableSsystemClocks: Couldn't get SGX Functional Clock"));
- goto ExitError;
- }
- psSysSpecData->psSGX_FCK = psCLK;
-
- psSysSpecData->bSysClocksOneTimeInit = IMG_TRUE;
- }
-/* else
- {
-
- bPowerLock = PowerLockWrappedOnCPU(psSysSpecData);
- if (bPowerLock)
- {
- PowerLockUnwrap(psSysSpecData);
- }
- }
-
-*/
-
-/*
- psCLK = clk_get(NULL, SGX_PARENT_CLOCK);
- 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(DEBUG) || defined(TIMING)
- if(cpu_is_ti816x()) {
- psCLK = clk_get(NULL, "gpt6_fck");
- } else {
- psCLK = clk_get(NULL, "gpt7_fck");
- }
- if (IS_ERR(psCLK))
- {
- PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get GPTIMER11 functional clock"));
- goto ExitUnRegisterConstraintNotifications;
- }
- psSysSpecData->psGPT11_FCK = psCLK;
-
- if(cpu_is_ti816x()) {
- psCLK = clk_get(NULL, "gpt6_ick");
- } else {
- psCLK = clk_get(NULL, "gpt7_ick");
- }
- if (IS_ERR(psCLK))
- {
- PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get GPTIMER11 interface clock"));
- goto ExitUnRegisterConstraintNotifications;
- }
- 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 ExitUnRegisterConstraintNotifications;
- }
-
- 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 ExitUnRegisterConstraintNotifications;
- }
- }
-*/
- 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 ExitUnRegisterConstraintNotifications;
- }
-
- 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_TI81xx_GP7TIMER_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_TI81xx_GP7TIMER_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
-
- eError = PVRSRV_OK;
- goto Exit;
-
-#if defined(DEBUG) || defined(TIMING)
-ExitDisableGPT11ICK:
- clk_disable(psSysSpecData->psGPT11_ICK);
-ExitDisableGPT11FCK:
- clk_disable(psSysSpecData->psGPT11_FCK);
-ExitUnRegisterConstraintNotifications:
-#endif
-ExitError:
- eError = PVRSRV_ERROR_DISABLE_CLOCK_FAILURE;
-Exit:
- return eError;
-}
-
-IMG_VOID DisableSystemClocks(SYS_DATA *psSysData)
-{
-#if defined(DEBUG) || defined(TIMING)
- SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
- IMG_CPU_PHYADDR TimerRegPhysBase;
- IMG_HANDLE hTimerDisable;
- IMG_UINT32 *pui32TimerDisable;
-#endif
-
- PVR_TRACE(("DisableSystemClocks: Disabling System Clocks"));
-
-
- DisableSGXClocks(psSysData);
-
-#if defined(DEBUG) || defined(TIMING)
-
- TimerRegPhysBase.uiAddr = SYS_TI81xx_GP7TIMER_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
-}
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- **************************************************************************/
+/*************************************************************************/ /*!
+@File linuxsrv.h
+@Title Module defs for pvr core drivers.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _LINUXSRV_H__
#define _LINUXSRV_H__
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
ccflags-y += \
-I$(TOP)/tools/intern/debug/dbgdriv/common \
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
+# The contents of this file are subject to the MIT license as set out below.
#
-# This program is distributed in the hope it will be useful but, except
-# as otherwise stated in writing, without any warranty; without even the
-# implied warranty of merchantability or fitness for a particular purpose.
-# See the GNU General Public License for more details.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Imagination Technologies Ltd. <gpl-support@imgtec.com>
-# Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
modules := dbgdrv
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Debug Driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description 32 Bit kernel mode debug driver
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifdef LINUX
#include <linux/string.h>
struct _DBG_LASTFRAME_BUFFER_ *psNext;
} *PDBG_LASTFRAME_BUFFER;
+/******************************************************************************
+ Global vars
+******************************************************************************/
static PDBG_STREAM g_psStreamList = 0;
static PDBG_LASTFRAME_BUFFER g_psLFBufferList;
IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize);
PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream);
+/***************************************************************************
+ Declare kernel mode service table.
+***************************************************************************/
DBGKM_SERVICE_TABLE g_sDBGKMServices =
{
sizeof (DBGKM_SERVICE_TABLE),
};
+/* Static function declarations */
static IMG_UINT32 DBGDrivWritePersist(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
static IMG_VOID InvalidateAllStreams(IMG_VOID);
+/*****************************************************************************
+ Code
+*****************************************************************************/
DBGKM_CONNECT_NOTIFIER g_fnDBGKMNotifier;
+/*!
+ @name ExtDBGDrivSetConnectNotifier
+ @brief Registers one or more services callback functions which are called on events in the dbg driver
+ @param fn_notifier - services callbacks
+ @return none
+ */
IMG_VOID IMG_CALLCONV ExtDBGDrivSetConnectNotifier(DBGKM_CONNECT_NOTIFIER fn_notifier)
{
-
+ /* Set the callback function which enables the debug driver to
+ * communicate to services KM when pdump is connected.
+ */
g_fnDBGKMNotifier = fn_notifier;
}
+/*!
+ @name ExtDBGDrivCreateStream
+ */
IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR * pszName, IMG_UINT32 ui32CapMode, IMG_UINT32 ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size)
{
IMG_VOID * pvRet;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
pvRet=DBGDrivCreateStream(pszName, ui32CapMode, ui32OutMode, ui32Flags, ui32Size);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return pvRet;
}
+/*!
+ @name ExtDBGDrivDestroyStream
+ */
void IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivDestroyStream(psStream);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return;
}
+/*!
+ @name ExtDBGDrivFindStream
+ */
IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
{
IMG_VOID * pvRet;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
pvRet=DBGDrivFindStream(pszName, bResetStream);
PVR_DPF((PVR_DBG_ERROR, "pfnConnectNotifier not initialised.\n"));
}
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return pvRet;
}
+/*!
+ @name ExtDBGDrivWriteString
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret=DBGDrivWriteString(psStream, pszString, ui32Level);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivReadString
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret=DBGDrivReadString(psStream, pszString, ui32Limit);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivWrite
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret=DBGDrivWrite(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivRead
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret=DBGDrivRead(psStream, bReadInitBuffer, ui32OutBuffSize, pui8OutBuf);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivSetCaptureMode
+ */
void IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivSetCaptureMode(psStream, ui32Mode, ui32Start, ui32End, ui32SampleRate);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return;
}
+/*!
+ @name ExtDBGDrivSetOutputMode
+ */
void IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivSetOutputMode(psStream, ui32OutMode);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return;
}
+/*!
+ @name ExtDBGDrivSetDebugLevel
+ */
void IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivSetDebugLevel(psStream, ui32DebugLevel);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return;
}
+/*!
+ @name ExtDBGDrivSetFrame
+ */
void IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivSetFrame(psStream, ui32Frame);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return;
}
+/*!
+ @name ExtDBGDrivGetFrame
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret=DBGDrivGetFrame(psStream);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivIsLastCaptureFrame
+ */
IMG_BOOL IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
{
IMG_BOOL bRet;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
bRet = DBGDrivIsLastCaptureFrame(psStream);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return bRet;
}
+/*!
+ @name ExtDBGDrivIsCaptureFrame
+ */
IMG_BOOL IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
{
IMG_BOOL bRet;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
bRet = DBGDrivIsCaptureFrame(psStream, bCheckPreviousFrame);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return bRet;
}
+/*!
+ @name ExtDBGDrivOverrideMode
+ */
void IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivOverrideMode(psStream, ui32Mode);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return;
}
+/*!
+ @name ExtDBGDrivDefaultMode
+ */
void IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivDefaultMode(psStream);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return;
}
+/*!
+ @name ExtDBGDrivWrite2
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivWritePersist
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivWritePersist(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret=DBGDrivWritePersist(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
PVR_DPF((PVR_DBG_ERROR, "An error occurred in DBGDrivWritePersist."));
}
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivWriteStringCM
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret=DBGDrivWriteStringCM(psStream, pszString, ui32Level);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivWriteCM
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret=DBGDrivWriteCM(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivSetMarker
+ */
void IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivSetMarker(psStream, ui32Marker);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return;
}
+/*!
+ @name ExtDBGDrivGetMarker
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream)
{
IMG_UINT32 ui32Marker;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Marker = DBGDrivGetMarker(psStream);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Marker;
}
+/*!
+ @name ExtDBGDrivWriteLF
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret = DBGDrivWriteLF(psStream, pui8InBuf, ui32InBuffSize, ui32Level, ui32Flags);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivReadLF
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret = DBGDrivReadLF(psStream, ui32OutBuffSize, pui8OutBuf);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivStartInitPhase
+ */
IMG_VOID IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivStartInitPhase(psStream);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return;
}
+/*!
+ @name ExtDBGDrivStopInitPhase
+ */
IMG_VOID IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivStopInitPhase(psStream);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return;
}
+/*!
+ @name ExtDBGDrivGetStreamOffset
+ */
IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream)
{
IMG_UINT32 ui32Ret;
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
ui32Ret = DBGDrivGetStreamOffset(psStream);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
return ui32Ret;
}
+/*!
+ @name ExtDBGDrivSetStreamOffset
+ */
IMG_VOID IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset)
{
-
+ /* Aquire API Mutex */
HostAquireMutex(g_pvAPIMutex);
DBGDrivSetStreamOffset(psStream, ui32StreamOffset);
-
+ /* Release API Mutex */
HostReleaseMutex(g_pvAPIMutex);
}
+/*!
+ @name ExtDBGDrivWaitForEvent
+ */
IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent)
{
#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
DBGDrivWaitForEvent(eEvent);
-#else
- PVR_UNREFERENCED_PARAMETER(eEvent);
-#endif
-}
-
+#else /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
+ PVR_UNREFERENCED_PARAMETER(eEvent); /* PRQA S 3358 */
+#endif /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
+}
+
+/*!****************************************************************************
+ @name AtoI
+ @brief Returns the integer value of a decimal string
+ @param szIn - String with hexadecimal value
+ @return IMG_UINT32 integer value, 0 if string is null or not valid
+ Based on Max`s one, now copes with (only) hex ui32ords, upper or lower case a-f.
+*****************************************************************************/
IMG_UINT32 AtoI(IMG_CHAR *szIn)
{
IMG_INT iLen = 0;
IMG_INT iPos;
IMG_CHAR bc;
-
+ //get len of string
while (szIn[iLen] > 0)
{
iLen ++;
}
-
+ //nothing to do
if (iLen == 0)
{
return (0);
}
-
+ /* See if we have an 'x' or 'X' before the number to make it a hex number */
iPos=0;
while (szIn[iPos] == '0')
{
szIn[iPos]='0';
}
-
+ //go through string from right (least significant) to left
for (iPos = iLen - 1; iPos >= 0; iPos --)
{
bc = szIn[iPos];
- if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16)
+ if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16) //handle lower case a-f
{
bc -= 'a' - 0xa;
}
else
- if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16)
+ if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16) //handle upper case A-F
{
bc -= 'A' - 0xa;
}
else
- if ((bc >= '0') && (bc <= '9'))
+ if ((bc >= '0') && (bc <= '9')) //if char out of range, return 0
{
bc -= '0';
}
}
+/*!****************************************************************************
+ @name StreamValid
+ @brief Validates supplied debug buffer.
+ @param psStream - debug stream
+ @return true if valid
+*****************************************************************************/
static IMG_BOOL StreamValid(PDBG_STREAM psStream)
{
PDBG_STREAM psThis;
}
+/*!****************************************************************************
+ @name StreamValidForRead
+ @brief Validates supplied debug buffer for read op.
+ @param psStream - debug stream
+ @return true if readable
+*****************************************************************************/
static IMG_BOOL StreamValidForRead(PDBG_STREAM psStream)
{
if( StreamValid(psStream) &&
return(IMG_FALSE);
}
+/*!****************************************************************************
+ @name StreamValidForWrite
+ @brief Validates supplied debug buffer for write op.
+ @param psStream - debug stream
+ @return true if writable
+*****************************************************************************/
static IMG_BOOL StreamValidForWrite(PDBG_STREAM psStream)
{
if( StreamValid(psStream) &&
}
+/*!****************************************************************************
+ @name Write
+ @brief Copies data from a buffer into selected stream. Stream size is fixed.
+ @param psStream - stream for output
+ @param pui8Data - input buffer
+ @param ui32InBuffSize - size of input
+ @return none
+*****************************************************************************/
static void Write(PDBG_STREAM psStream,IMG_PUINT8 pui8Data,IMG_UINT32 ui32InBuffSize)
{
-
-
+ /*
+ Split copy into two bits as necessary (if we're allowed to wrap).
+ */
if (!psStream->bCircularAllowed)
{
-
+ //PVR_ASSERT( (psStream->ui32WPtr + ui32InBuffSize) < psStream->ui32Size );
}
if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size)
{
-
+ /* Yes we need two bits, calculate their sizes */
IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
-
+ /* Copy first block to current location */
HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
(IMG_PVOID) pui8Data,
ui32B1);
-
+ /* Copy second block to start of buffer */
HostMemCopy(psStream->pvBase,
(IMG_PVOID)(pui8Data + ui32B1),
ui32B2);
-
+ /* Set pointer to be the new end point */
psStream->ui32WPtr = ui32B2;
}
else
- {
+ { /* Can fit block in single chunk */
HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
(IMG_PVOID) pui8Data,
ui32InBuffSize);
}
+/*!****************************************************************************
+ @name MonoOut
+ @brief Output data to mono display. [Possibly deprecated]
+ @param pszString - input
+ @param bNewLine - line wrapping
+ @return none
+*****************************************************************************/
void MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine)
{
#if defined (_WIN64)
pScreen += g_ui32Line * 160;
-
-
+ /*
+ Write the string.
+ */
i=0;
do
{
g_ui32Line++;
}
-
-
+ /*
+ Scroll if necssary.
+ */
if (g_ui32Line == g_ui32MonoLines)
{
g_ui32Line = g_ui32MonoLines - 1;
#endif
}
+/*!****************************************************************************
+ @name WriteExpandingBuffer
+ @brief Copies data from a buffer into selected stream. Stream size may be expandable.
+ @param psStream - stream for output
+ @param pui8InBuf - input buffer
+ @param ui32InBuffSize - size of input
+ @return bytes copied
+*****************************************************************************/
static IMG_UINT32 WriteExpandingBuffer(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
{
IMG_UINT ui32Space;
-
-
+ /*
+ How much space have we got in the buffer ?
+ */
ui32Space = SpaceInStream(psStream);
-
-
+ /*
+ Don't copy anything if we don't have space or buffers not enabled.
+ */
if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
{
PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %x is disabled", (IMG_UINTPTR_T) psStream));
return(0);
}
-
-
+ /*
+ Check if we can expand the buffer
+ */
if (psStream->psCtrl->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION)
{
-
-
-
+ /*
+ Don't do anything if we've got less that 32 ui8tes of space and
+ we're not allowing expansion of buffer space...
+ */
if (ui32Space < 32)
{
PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %x is full and isn't expandable", (IMG_UINTPTR_T) psStream));
{
IMG_UINT32 ui32NewBufSize;
-
-
+ /*
+ Find new buffer size
+ */
ui32NewBufSize = 2 * psStream->ui32Size;
PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanding buffer size = %x, new size = %x",
ui32NewBufSize += ui32InBuffSize;
}
-
-
+ /*
+ Attempt to expand the buffer
+ */
if (!ExpandStreamBuffer(psStream,ui32NewBufSize))
{
if (ui32Space < 32)
}
else
{
-
+ /* out of memory */
PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: Unable to expand %x. Out of memory.", (IMG_UINTPTR_T) psStream));
InvalidateAllStreams();
return (0xFFFFFFFFUL);
}
}
-
-
+ /*
+ Recalc the space in the buffer
+ */
ui32Space = SpaceInStream(psStream);
PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanded buffer, free space = %x",
ui32Space));
}
}
-
-
+ /*
+ Only copy what we can..
+ */
if (ui32Space <= (ui32InBuffSize + 4))
{
ui32InBuffSize = ui32Space - 4;
}
-
-
+ /*
+ Write the stuff...
+ */
Write(psStream,pui8InBuf,ui32InBuffSize);
#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
return(ui32InBuffSize);
}
+/*****************************************************************************
+******************************************************************************
+******************************************************************************
+ THE ACTUAL FUNCTIONS
+******************************************************************************
+******************************************************************************
+*****************************************************************************/
+
+/*!****************************************************************************
+ @name DBGDrivCreateStream
+ @brief Creates a pdump/debug stream
+ @param pszName - stream name
+ @param ui32CapMode - capture mode (framed, continuous, hotkey)
+ @param ui32OutMode - output mode (see dbgdrvif.h)
+ @param ui32Flags - output flags, text stream bit is set for pdumping
+ @param ui32Size - size of stream buffer in pages
+ @return none
+*****************************************************************************/
IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR * pszName,
IMG_UINT32 ui32CapMode,
IMG_UINT32 ui32OutMode,
static IMG_CHAR pszNameInitSuffix[] = "_Init";
IMG_UINT32 ui32OffSuffix;
-
-
-
+ /*
+ If we already have a buffer using this name just return
+ its handle.
+ */
psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
if (psStream)
return ((IMG_VOID *) psStream);
}
-
-
+ /*
+ Allocate memory for control structures
+ */
psStream = HostNonPageablePageAlloc(1);
psInitStream = HostNonPageablePageAlloc(1);
psLFBuffer = HostNonPageablePageAlloc(1);
return((IMG_VOID *) 0);
}
-
+ /* Allocate memory for buffer */
if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
{
pvBase = HostNonPageablePageAlloc(ui32Size);
return((IMG_VOID *) 0);
}
-
+ /* Setup control state */
psCtrl->ui32Flags = ui32Flags;
psCtrl->ui32CapMode = ui32CapMode;
psCtrl->ui32OutMode = ui32OutMode;
psCtrl->ui32SampleRate = 1;
psCtrl->bInitPhaseComplete = IMG_FALSE;
-
-
+ /*
+ Setup internal debug buffer state.
+ */
psStream->psNext = 0;
psStream->pvBase = pvBase;
psStream->psCtrl = psCtrl;
psStream->ui32Marker = 0;
psStream->bCircularAllowed = IMG_TRUE;
psStream->ui32InitPhaseWOff = 0;
-
-
-
+ /* Allocate memory for buffer */
if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
{
pvBase = HostNonPageablePageAlloc(ui32Size);
return((IMG_VOID *) 0);
}
-
+ /* Initialise the stream for the init phase */
psInitStream->psNext = 0;
psInitStream->pvBase = pvBase;
psInitStream->psCtrl = psCtrl;
psInitStream->ui32Marker = 0;
psInitStream->bCircularAllowed = IMG_FALSE;
psInitStream->ui32InitPhaseWOff = 0;
-
-
-
psStream->psInitStream = psInitStream;
-
+ /* Setup last frame buffer */
psLFBuffer->psStream = psStream;
psLFBuffer->ui32BufLen = 0UL;
g_ui32HotkeyMiddumpStart = 0xffffffffUL;
g_ui32HotkeyMiddumpEnd = 0xffffffffUL;
-
-
+ /*
+ Copy buffer name.
+ */
ui32Off = 0;
do
ui32Off++;
}
while ((pszName[ui32Off] != 0) && (ui32Off < (4096UL - sizeof(DBG_STREAM))));
- psStream->szName[ui32Off] = pszName[ui32Off];
-
-
+ psStream->szName[ui32Off] = pszName[ui32Off]; /* PRQA S 3689 */
+ /*
+ Append suffix to init phase name
+ */
ui32OffSuffix = 0;
do
{
}
while ( (pszNameInitSuffix[ui32OffSuffix] != 0) &&
(ui32Off < (4096UL - sizeof(DBG_STREAM))));
- psInitStream->szName[ui32Off] = pszNameInitSuffix[ui32OffSuffix];
-
-
+ psInitStream->szName[ui32Off] = pszNameInitSuffix[ui32OffSuffix]; /* PRQA S 3689 */
+ /*
+ Insert into list.
+ */
psStream->psNext = g_psStreamList;
g_psStreamList = psStream;
return((IMG_VOID *) psStream);
}
+/*!****************************************************************************
+ @name DBGDrivDestroyStream
+ @brief Delete a stream and free its memory
+ @param psStream - stream to be removed
+ @return none
+*****************************************************************************/
void IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream)
{
PDBG_STREAM psStreamThis;
PVR_DPF((PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n", psStream->szName ));
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValid(psStream))
{
return;
psLFBuffer = FindLFBuf(psStream);
-
-
+ /*
+ Remove from linked list.
+ */
psStreamThis = g_psStreamList;
psStreamPrev = 0;
psLFThis = psLFThis->psNext;
}
}
-
-
+ /*
+ Dectivate hotkey it the stream is of this type.
+ */
if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
{
DeactivateHotKeys();
}
-
-
+ /*
+ And free its memory.
+ */
if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
{
HostNonPageablePageFree(psStream->psCtrl);
return;
}
+/*!****************************************************************************
+ @name DBGDrivFindStream
+ @brief Finds/resets a named stream
+ @param pszName - stream name
+ @param bResetStream - whether to reset the stream, e.g. to end pdump init phase
+ @return none
+*****************************************************************************/
IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
{
PDBG_STREAM psStream;
pszName,
(bResetStream == IMG_TRUE) ? "with reset" : "no reset"));
-
-
+ /*
+ Scan buffer names for supplied one.
+ */
for (psThis = g_psStreamList; psThis != IMG_NULL; psThis = psThis->psNext)
{
bAreSame = IMG_TRUE;
}
{
-
-
+ /* mark init stream to prevent further reading by pdump client */
psStream->psInitStream->ui32InitPhaseWOff = psStream->psInitStream->ui32WPtr;
PVR_DPF((PVR_DBGDRIV_MESSAGE, "Set %s client marker bo %x, total bw %x",
psStream->szName,
PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: An error occurred for stream %s\r\n", psStream->szName ));
-
-
-
-
-
-
-
-
+ /*
+ Validate buffer.
+ */
+ /*
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+*/
+ /* Write what we can of the error message */
ui32Space = SpaceInStream(psStream);
-
+ /* Make sure there's space for termination character */
if(ui32Space > 0)
{
ui32Space--;
pui8Buffer[ui32WPtr++] = '\0';
psStream->ui32WPtr = ui32WPtr;
-
+ /* Buffer will accept no more params from Services/client driver */
psStream->psCtrl->ui32Flags |= DEBUG_FLAGS_READONLY;
}
+/*!****************************************************************************
+ @name InvalidateAllStreams
+ @brief invalidate all streams in list
+ @return none
+*****************************************************************************/
static IMG_VOID InvalidateAllStreams(IMG_VOID)
{
PDBG_STREAM psStream = g_psStreamList;
+/*!****************************************************************************
+ @name DBGDrivWriteStringCM
+ @brief Write capture mode data, wraps DBGDrivWriteString
+ @param psStream - stream
+ @param pszString - input buffer
+ @param ui32Level - debug level
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
{
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValidForWrite(psStream))
{
return(0xFFFFFFFFUL);
}
-
-
+ /*
+ Only write string if debug capture mode adds up...
+ */
if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
{
if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
}
+/*!****************************************************************************
+ @name DBGDrivWriteString
+ @brief Write string to stream (note stream buffer size is assumed fixed)
+ @param psStream - stream
+ @param pszString - string to write
+ @param ui32Level - verbosity level
+ @return -1; invalid stream
+ 0; other error (e.g. stream not enabled)
+ else number of characters written
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
{
IMG_UINT32 ui32Len;
IMG_UINT32 ui32WPtr;
IMG_UINT8 * pui8Buffer;
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValidForWrite(psStream))
{
return(0xFFFFFFFFUL);
}
-
-
+ /*
+ Check debug level.
+ */
if ((psStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
{
return(0xFFFFFFFFUL);
}
-
-
-
+ /*
+ Output to standard debug out ? (don't if async out
+ flag is set).
+ */
if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_ASYNC) == 0)
{
if (psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STANDARDDBG)
PVR_DPF((PVR_DBG_MESSAGE,"%s: %s\r\n",psStream->szName, pszString));
}
-
-
+ /*
+ Output to mono monitor ?
+ */
if (psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_MONO)
{
MonoOut(psStream->szName,IMG_FALSE);
}
}
-
-
+ /*
+ Don't bother writing the string if it's not flagged
+ */
if (
!(
((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) != 0) ||
return(0xFFFFFFFFUL);
}
-
-
+ /*
+ How much space have we got in the buffer ?
+ */
ui32Space=SpaceInStream(psStream);
-
+ /* Make sure there's space for termination character */
if(ui32Space > 0)
{
ui32Space--;
if (ui32Len < ui32Space)
{
-
+ /* copy terminator */
pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
ui32Len++;
ui32WPtr++;
ui32WPtr = 0;
}
-
+ /* Write pointer, and length */
psStream->ui32WPtr = ui32WPtr;
psStream->ui32DataWritten+= ui32Len;
} else
return(ui32Len);
}
+/*!****************************************************************************
+ @name DBGDrivReadString
+ @brief Reads string from debug stream
+ @param psStream - stream
+ @param pszString - string to read
+ @param ui32Limit - max size to read
+ @return -1; invalid stream
+ 0; other error (e.g. stream not enabled)
+ else number of characters read
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
{
IMG_UINT32 ui32OutLen;
IMG_UINT32 ui32Offset;
IMG_UINT8 *pui8Buff;
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValidForRead(psStream))
{
return(0);
}
-
-
+ /*
+ Stream appears to be in list so carry on.
+ */
pui8Buff = (IMG_UINT8 *)psStream->pvBase;
ui32Offset = psStream->ui32RPtr;
return(0);
}
-
-
+ /*
+ Find length of string.
+ */
ui32Len = 0;
while((pui8Buff[ui32Offset] != 0) && (ui32Offset != psStream->ui32WPtr))
{
ui32Offset++;
ui32Len++;
-
-
+ /*
+ Reset offset if buffer wrapped.
+ */
if (ui32Offset == psStream->ui32Size)
{
ui32Offset = 0;
ui32OutLen = ui32Len + 1;
-
-
+ /*
+ Only copy string if target has enough space.
+ */
if (ui32Len > ui32Limit)
{
return(0);
}
-
-
+ /*
+ Copy it.
+ */
ui32Offset = psStream->ui32RPtr;
ui32Len = 0;
ui32Offset++;
ui32Len++;
-
-
+ /*
+ If wrap as necessary
+ */
if (ui32Offset == psStream->ui32Size)
{
ui32Offset = 0;
return(ui32OutLen);
}
+/*!****************************************************************************
+ @name DBGDrivWrite
+ @brief Write binary buffer to stream (fixed size)
+ @param psStream - stream
+ @param pui8InBuf - buffer to write
+ @param ui32InBuffSize - size
+ @param ui32Level - verbosity level
+ @return bytes written, 0 if recoverable error, -1 if unrecoverable error
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
{
IMG_UINT32 ui32Space;
DBG_STREAM *psStream;
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValidForWrite(psMainStream))
{
return(0xFFFFFFFFUL);
}
-
-
+ /*
+ Check debug level.
+ */
if ((psMainStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
{
return(0xFFFFFFFFUL);
}
-
-
+ /*
+ Only write data if debug mode adds up...
+ */
if (psMainStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
{
if ((psMainStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
{
-
+ /* throw away non-capturing data */
return(ui32InBuffSize);
}
}
{
if ((psMainStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
{
-
+ /* throw away non-capturing data */
return(ui32InBuffSize);
}
}
psStream = psMainStream->psInitStream;
}
-
-
+ /*
+ How much space have we got in the buffer ?
+ */
ui32Space=SpaceInStream(psStream);
PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv %d b for %s: Roff = %x, WOff = %x",
psStream->ui32RPtr,
psStream->ui32WPtr));
-
-
+ /*
+ Don't copy anything if we don't have space or buffers not enabled.
+ */
if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
{
PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite: buffer %x is disabled", (IMG_UINTPTR_T) psStream));
return(0);
}
-
-
+ /*
+ Only copy what we can..
+ */
if (ui32Space <= (ui32InBuffSize + 4))
{
ui32InBuffSize = ui32Space - 8;
}
-
-
+ /*
+ Write the stuff...
+ */
Write(psStream,(IMG_UINT8 *) &ui32InBuffSize,4);
Write(psStream,pui8InBuf,ui32InBuffSize);
return(ui32InBuffSize);
}
+/*!****************************************************************************
+ @name DBGDrivWriteCM
+ @brief Write capture mode data, wraps DBGDrivWrite
+ @param psStream - stream
+ @param pui8InBuf - input buffer
+ @param ui32InBuffSize - buffer size
+ @param ui32Level - verbosity level
+ @return bytes written, 0 if recoverable error, -1 if unrecoverable error
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
{
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValidForWrite(psStream))
{
return(0xFFFFFFFFUL);
}
-
-
+ /*
+ Only write data if debug mode adds up...
+ */
if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
{
if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
{
-
+ /* throw away non-capturing data */
return(ui32InBuffSize);
}
}
{
if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
{
-
+ /* throw away non-capturing data */
return(ui32InBuffSize);
}
}
}
+/*!****************************************************************************
+ @name DBGDrivWritePersist
+ @brief Copies data from a buffer into selected stream's init phase. Stream size should be expandable.
+ @param psStream - stream for output
+ @param pui8InBuf - input buffer
+ @param ui32InBuffSize - size of input
+ @param ui32Level - not used
+ @return bytes copied, 0 if recoverable error, -1 if unrecoverable error
+*****************************************************************************/
static IMG_UINT32 DBGDrivWritePersist(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
{
DBG_STREAM *psStream;
PVR_UNREFERENCED_PARAMETER(ui32Level);
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValidForWrite(psMainStream))
{
return(0xFFFFFFFFUL);
}
-
+ /* Always append persistent data to init phase so it's available on
+ * subsequent app runs.
+ */
psStream = psMainStream->psInitStream;
if(psStream->bCircularAllowed == IMG_TRUE)
{
return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
}
+/*!****************************************************************************
+ @name DBGDrivWrite2
+ @brief Copies data from a buffer into selected (expandable) stream.
+ @param psMainStream - stream for output
+ @param pui8InBuf - input buffer
+ @param ui32InBuffSize - size of input
+ @param ui32Level - debug level of input
+ @return bytes copied, 0 if recoverable error, -1 if unrecoverable error
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
{
DBG_STREAM *psStream;
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValidForWrite(psMainStream))
{
PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite2: stream not valid"));
return(0xFFFFFFFFUL);
}
-
-
+ /*
+ Check debug level.
+ */
if ((psMainStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
{
return(0);
return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
}
+/*!****************************************************************************
+ @name DBGDrivRead
+ @brief Read from debug driver buffers
+ @param psMainStream - stream
+ @param bReadInitBuffer - whether to read from the init stream or the main stream
+ @param ui32OutBuffSize - available space in client buffer
+ @param pui8OutBuf - output buffer
+ @return bytes read, 0 if failure occurred
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psMainStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
{
IMG_UINT32 ui32Data;
DBG_STREAM *psStream;
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValidForRead(psMainStream))
{
PVR_DPF((PVR_DBG_ERROR, "DBGDrivRead: buffer %x is invalid", (IMG_UINTPTR_T) psMainStream));
psStream = psMainStream;
}
-
+ /* Don't read beyond the init phase marker point */
if (psStream->ui32RPtr == psStream->ui32WPtr ||
((psStream->ui32InitPhaseWOff > 0) &&
(psStream->ui32RPtr >= psStream->ui32InitPhaseWOff)) )
return(0);
}
-
-
+ /*
+ Get amount of data in buffer.
+ */
if (psStream->ui32RPtr <= psStream->ui32WPtr)
{
ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
ui32Data = psStream->ui32WPtr + (psStream->ui32Size - psStream->ui32RPtr);
}
-
-
+ /*
+ Don't read beyond the init phase marker point
+ */
if ((psStream->ui32InitPhaseWOff > 0) &&
(psStream->ui32InitPhaseWOff < psStream->ui32WPtr))
{
ui32Data = psStream->ui32InitPhaseWOff - psStream->ui32RPtr;
}
-
-
+ /*
+ Only transfer what target buffer can handle.
+ */
if (ui32Data > ui32OutBuffSize)
{
ui32Data = ui32OutBuffSize;
psStream->ui32RPtr,
psStream->ui32WPtr));
-
-
+ /*
+ Split copy into two bits as necessay.
+ */
if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size)
- {
+ { /* Calc block 1 and block 2 sizes */
IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
IMG_UINT32 ui32B2 = ui32Data - ui32B1;
-
+ /* Copy up to end of circular buffer */
HostMemCopy((IMG_VOID *) pui8OutBuf,
(IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
ui32B1);
-
+ /* Copy from start of circular buffer */
HostMemCopy((IMG_VOID *)(pui8OutBuf + ui32B1),
psStream->pvBase,
ui32B2);
-
+ /* Update read pointer now that we've copied the data out */
psStream->ui32RPtr = ui32B2;
}
else
- {
+ { /* Copy data from wherever */
HostMemCopy((IMG_VOID *) pui8OutBuf,
(IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
ui32Data);
-
+ /* Update read pointer now that we've copied the data out */
psStream->ui32RPtr += ui32Data;
-
+ /* Check for wrapping */
if (psStream->ui32RPtr == psStream->ui32Size)
{
psStream->ui32RPtr = 0;
return(ui32Data);
}
+/*!****************************************************************************
+ @name DBGDrivSetCaptureMode
+ @brief Set capture mode
+ @param psStream - stream
+ @param ui32Mode - capturing mode
+ @param ui32Start - start frame (frame mode only)
+ @param ui32End - end frame (frame mode)
+ @param ui32SampleRate - sampling frequency (frame mode)
+*****************************************************************************/
void IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
{
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValid(psStream))
{
return;
psStream->psCtrl->ui32End = ui32End;
psStream->psCtrl->ui32SampleRate = ui32SampleRate;
-
-
+ /*
+ Activate hotkey it the stream is of this type.
+ */
if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
{
ActivateHotKeys(psStream);
}
}
+/*!****************************************************************************
+ @name DBGDrivSetOutputMode
+ @brief Change output mode
+ @param psStream - stream
+ @param ui32OutMode - output mode
+ @return none
+*****************************************************************************/
void IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
{
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValid(psStream))
{
return;
psStream->psCtrl->ui32OutMode = ui32OutMode;
}
+/*!****************************************************************************
+ @name DBGDrivSetDebugLevel
+ @brief Change debug level
+ @param psStream - stream
+ @param ui32DebugLevel - verbosity level
+ @return none
+*****************************************************************************/
void IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
{
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValid(psStream))
{
return;
psStream->psCtrl->ui32DebugLevel = ui32DebugLevel;
}
+/*!****************************************************************************
+ @name DBGDrivSetFrame
+ @brief Advance frame counter
+ @param psStream - stream
+ @param ui32Frame - frame number
+ @return none
+*****************************************************************************/
void IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
{
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValid(psStream))
{
return;
}
}
-
+ /* Check to see if hotkey press has been registered (from keyboard filter) */
if (g_bHotKeyRegistered)
{
g_bHotKeyRegistered = IMG_FALSE;
if (!g_bHotKeyPressed)
{
-
-
+ /*
+ Capture the next frame.
+ */
g_ui32HotKeyFrame = psStream->psCtrl->ui32Current + 2;
-
-
+ /*
+ Do the flag.
+ */
g_bHotKeyPressed = IMG_TRUE;
}
-
-
+ /*
+ If in framed hotkey mode, then set start frame.
+ */
if (((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY) != 0))
{
if (!g_bHotkeyMiddump)
{
-
+ /* Turn on */
g_ui32HotkeyMiddumpStart = g_ui32HotKeyFrame + 1;
g_ui32HotkeyMiddumpEnd = 0xffffffff;
g_bHotkeyMiddump = IMG_TRUE;
}
else
{
-
+ /* Turn off */
g_ui32HotkeyMiddumpEnd = g_ui32HotKeyFrame;
PVR_DPF((PVR_DBG_MESSAGE,"Turning off sampling\n"));
}
}
-
-
+ /*
+ Clear the hotkey frame indicator when over that frame.
+ */
if (psStream->psCtrl->ui32Current > g_ui32HotKeyFrame)
{
g_bHotKeyPressed = IMG_FALSE;
}
}
+/*!****************************************************************************
+ @name DBGDrivGetFrame
+ @brief Retrieve current frame number
+ @param psStream - stream
+ @return frame number
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream)
{
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValid(psStream))
{
return(0);
return(psStream->psCtrl->ui32Current);
}
+/*!****************************************************************************
+ @name DBGDrivIsLastCaptureFrame
+ @brief Is this the last frame to be captured?
+ @param psStream - stream
+ @return true if last capture frame, false otherwise
+*****************************************************************************/
IMG_BOOL IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
{
IMG_UINT32 ui32NextFrame;
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValid(psStream))
{
return IMG_FALSE;
return IMG_FALSE;
}
+/*!****************************************************************************
+ @name DBGDrivIsCaptureFrame
+ @brief Is this a capture frame?
+ @param psStream - stream
+ @param bCheckPreviousFrame - set if it needs to be 1 frame ahead
+ @return true if capturing this frame, false otherwise
+*****************************************************************************/
IMG_BOOL IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
{
IMG_UINT32 ui32FrameShift = bCheckPreviousFrame ? 1UL : 0UL;
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValid(psStream))
{
return IMG_FALSE;
if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
{
-
+ /* Needs to be one frame ahead, so disppatch can turn everything on */
if (g_bHotkeyMiddump)
{
if ((psStream->psCtrl->ui32Current >= (g_ui32HotkeyMiddumpStart - ui32FrameShift)) &&
return IMG_FALSE;
}
+/*!****************************************************************************
+ @name DBGDrivOverrideMode
+ @brief Override capture mode
+ @param psStream - stream
+ @param ui32Mode - capture mode
+ @return none
+*****************************************************************************/
void IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
{
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValid(psStream))
{
return;
psStream->psCtrl->ui32CapMode = ui32Mode;
}
+/*!****************************************************************************
+ @name DBGDrivDefaultMode
+ @param psStream - stream
+ @return none
+*****************************************************************************/
void IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream)
{
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValid(psStream))
{
return;
psStream->psCtrl->ui32CapMode = psStream->psCtrl->ui32DefaultMode;
}
+/*!****************************************************************************
+ @name DBGDrivSetClientMarker
+ @brief Sets the marker to prevent reading initphase beyond data on behalf of previous app
+ @param psStream - stream
+ @param ui32Marker - byte offset in init buffer
+ @return nothing
+*****************************************************************************/
IMG_VOID IMG_CALLCONV DBGDrivSetClientMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
{
-
-
+ /*
+ Validate buffer
+ */
if (!StreamValid(psStream))
{
return;
psStream->ui32InitPhaseWOff = ui32Marker;
}
+/*!****************************************************************************
+ @name DBGDrivSetMarker
+ @brief Sets the marker in the stream to split output files
+ @param psStream, ui32Marker
+ @return nothing
+*****************************************************************************/
void IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
{
-
-
+ /*
+ Validate buffer
+ */
if (!StreamValid(psStream))
{
return;
psStream->ui32Marker = ui32Marker;
}
+/*!****************************************************************************
+ @name DBGDrivGetMarker
+ @brief Gets the marker in the stream to split output files
+ @param psStream - stream
+ @return marker offset
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream)
{
-
-
+ /*
+ Validate buffer
+ */
if (!StreamValid(psStream))
{
return 0;
}
+/*!****************************************************************************
+ @name DBGDrivGetStreamOffset
+ @brief Gets the amount of data written to the stream
+ @param psMainStream - stream
+ @return bytes written
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psMainStream)
{
PDBG_STREAM psStream;
-
-
+ /*
+ Validate buffer
+ */
if (!StreamValid(psMainStream))
{
return 0;
return psStream->ui32DataWritten;
}
+/*!****************************************************************************
+ @name DBGDrivSetStreamOffset
+ @brief Sets the amount of data written to the stream
+ @param psMainStream - stream
+ @param ui32StreamOffset - stream offset
+ @return Nothing
+*****************************************************************************/
IMG_VOID IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psMainStream, IMG_UINT32 ui32StreamOffset)
{
PDBG_STREAM psStream;
-
-
+ /*
+ Validate buffer
+ */
if (!StreamValid(psMainStream))
{
return;
psStream->ui32DataWritten = ui32StreamOffset;
}
+/*!****************************************************************************
+ @name DBGDrivGetServiceTable
+ @brief get jump table for Services driver
+ @return pointer to jump table
+*****************************************************************************/
IMG_PVOID IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID)
{
return((IMG_PVOID)&g_sDBGKMServices);
}
+/*!****************************************************************************
+ @name DBGDrivWriteLF
+ @brief Store data that should only be kept from the last frame dumped
+ @param psStream - stream
+ @param pui8InBuf - input buffer
+ @param ui32InBuffSize - size
+ @param ui32Level - verbosity level
+ @param ui32Flags - flags
+ @return bytes written
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
{
PDBG_LASTFRAME_BUFFER psLFBuffer;
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValidForWrite(psStream))
{
return(0xFFFFFFFFUL);
}
-
-
+ /*
+ Check debug level.
+ */
if ((psStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
{
return(0xFFFFFFFFUL);
}
-
-
+ /*
+ Only write data if debug mode adds up...
+ */
if ((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0)
{
if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
{
-
+ /* throw away non-capturing data */
return(ui32InBuffSize);
}
}
{
if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
{
-
+ /* throw away non-capturing data */
return(ui32InBuffSize);
}
}
if (ui32Flags & WRITELF_FLAGS_RESETBUF)
{
-
-
+ /*
+ Copy the data into the buffer
+ */
ui32InBuffSize = (ui32InBuffSize > LAST_FRAME_BUF_SIZE) ? LAST_FRAME_BUF_SIZE : ui32InBuffSize;
HostMemCopy((IMG_VOID *)psLFBuffer->ui8Buffer, (IMG_VOID *)pui8InBuf, ui32InBuffSize);
psLFBuffer->ui32BufLen = ui32InBuffSize;
}
else
{
-
-
+ /*
+ Append the data to the end of the buffer
+ */
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);
}
+/*!****************************************************************************
+ @name DBGDrivReadLF
+ @brief Read data that should only be kept from the last frame dumped
+ @param psStream - stream
+ @param ui32OutBuffSize - buffer size
+ @param pui8OutBuf - output buffer
+ @return bytes read
+*****************************************************************************/
IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
{
PDBG_LASTFRAME_BUFFER psLFBuffer;
IMG_UINT32 ui32Data;
-
-
+ /*
+ Validate buffer.
+ */
if (!StreamValidForRead(psStream))
{
return(0);
psLFBuffer = FindLFBuf(psStream);
-
-
+ /*
+ Get amount of data to copy
+ */
ui32Data = (ui32OutBuffSize < psLFBuffer->ui32BufLen) ? ui32OutBuffSize : psLFBuffer->ui32BufLen;
-
-
+ /*
+ Copy the data into the buffer
+ */
HostMemCopy((IMG_VOID *)pui8OutBuf, (IMG_VOID *)psLFBuffer->ui8Buffer, ui32Data);
return ui32Data;
}
+/*!****************************************************************************
+ @name DBGDrivStartInitPhase
+ @brief Marks start of init phase
+ @param psStream - stream
+ @return void
+*****************************************************************************/
IMG_VOID IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream)
{
psStream->psCtrl->bInitPhaseComplete = IMG_FALSE;
}
+/*!****************************************************************************
+ @name DBGDrivStopInitPhase
+ @brief Marks end of init phase
+ @param psStream - stream
+ @return void
+*****************************************************************************/
IMG_VOID IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream)
{
psStream->psCtrl->bInitPhaseComplete = IMG_TRUE;
}
#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+/*!****************************************************************************
+ @name DBGDrivWaitForEvent
+ @brief waits for an event
+ @param eEvent - debug driver event
+ @return void
+*****************************************************************************/
IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent)
{
HostWaitForEvent(eEvent);
}
#endif
+/*!****************************************************************************
+ @name ExpandStreamBuffer
+ @brief allocates a new buffer when the current one is full
+ @param psStream - stream
+ @param ui32NewSize - new size
+ @return IMG_TRUE - if allocation succeeded, IMG_FALSE - if not
+*****************************************************************************/
IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize)
{
IMG_VOID * pvNewBuf;
IMG_UINT32 ui32NewROffset;
IMG_UINT32 ui32SpaceInOldBuf;
-
-
+ /*
+ First check new size is bigger than existing size
+ */
if (psStream->ui32Size >= ui32NewSize)
{
return IMG_FALSE;
}
-
-
+ /*
+ Calc space in old buffer
+ */
ui32SpaceInOldBuf = SpaceInStream(psStream);
-
-
+ /*
+ Allocate new buffer
+ */
ui32NewSizeInPages = ((ui32NewSize + 0xfffUL) & ~0xfffUL) / 4096UL;
if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
if(psStream->bCircularAllowed)
{
-
-
-
+ /*
+ Copy over old buffer to new one, we place data at start of buffer
+ even if Read offset is not at start of buffer
+ */
if (psStream->ui32RPtr <= psStream->ui32WPtr)
{
-
-
+ /*
+ No wrapping of data so copy data to start of new buffer
+ */
HostMemCopy(pvNewBuf,
(IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
psStream->ui32WPtr - psStream->ui32RPtr);
{
IMG_UINT32 ui32FirstCopySize;
-
-
+ /*
+ The data has wrapped around the buffer, copy beginning of buffer first
+ */
ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
HostMemCopy(pvNewBuf,
(IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
ui32FirstCopySize);
-
-
+ /*
+ Now second half
+ */
HostMemCopy((IMG_VOID *)((IMG_UINTPTR_T)pvNewBuf + ui32FirstCopySize),
(IMG_VOID *)(IMG_PBYTE)psStream->pvBase,
psStream->ui32WPtr);
}
else
{
-
+ /* Copy everything in the old buffer to the new one */
HostMemCopy(pvNewBuf, psStream->pvBase, psStream->ui32WPtr);
ui32NewROffset = psStream->ui32RPtr;
}
-
-
-
+ /*
+ New Write offset is at end of data
+ */
ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
-
-
+ /*
+ Free old buffer
+ */
if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
{
HostNonPageablePageFree(psStream->pvBase);
HostPageablePageFree(psStream->pvBase);
}
-
-
+ /*
+ Now set new params up
+ */
psStream->pvBase = pvNewBuf;
psStream->ui32RPtr = ui32NewROffset;
psStream->ui32WPtr = ui32NewWOffset;
return IMG_TRUE;
}
+/*!****************************************************************************
+ @name SpaceInStream
+ @brief remaining space in stream
+ @param psStream - stream
+ @return bytes remaining
+*****************************************************************************/
IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
{
IMG_UINT32 ui32Space;
if (psStream->bCircularAllowed)
{
-
+ /* Allow overwriting the buffer which was already read */
if (psStream->ui32RPtr > psStream->ui32WPtr)
{
ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
}
else
{
-
+ /* Don't overwrite anything */
ui32Space = psStream->ui32Size - psStream->ui32WPtr;
}
}
+/*!****************************************************************************
+ @name DestroyAllStreams
+ @brief delete all streams in list
+ @return none
+*****************************************************************************/
void DestroyAllStreams(void)
{
while (g_psStreamList != IMG_NULL)
return;
}
+/*!****************************************************************************
+ @name FindLFBuf
+ @brief finds last frame stream
+ @param psStream - stream to find
+ @return stream if found, NULL otherwise
+*****************************************************************************/
PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream)
{
PDBG_LASTFRAME_BUFFER psLFBuffer;
return psLFBuffer;
}
+/******************************************************************************
+ End of file (DBGDRIV.C)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Debug Driver interface definition.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _DBGDRIV_
#define _DBGDRIV_
+/*****************************************************************************
+ The odd constant or two
+*****************************************************************************/
#define BUFFER_SIZE 64*PAGESIZE
#define DBGDRIV_VERSION 0x100
extern IMG_VOID * g_pvAPIMutex;
+/*****************************************************************************
+ KM mode functions
+*****************************************************************************/
IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR * pszName,
IMG_UINT32 ui32CapMode,
IMG_UINT32 ui32OutMode,
IMG_VOID DestroyAllStreams(IMG_VOID);
+/*****************************************************************************
+ Function prototypes
+*****************************************************************************/
IMG_UINT32 AtoI(IMG_CHAR *szIn);
IMG_VOID HostMemSet(IMG_VOID *pvDest,IMG_UINT8 ui8Value,IMG_UINT32 ui32Size);
IMG_VOID HostMemCopy(IMG_VOID *pvDest,IMG_VOID *pvSrc,IMG_UINT32 ui32Size);
IMG_VOID MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine);
+/*****************************************************************************
+ Secure handle Function prototypes
+*****************************************************************************/
IMG_SID PStream2SID(PDBG_STREAM psStream);
PDBG_STREAM SID2PStream(IMG_SID hStream);
IMG_BOOL AddSIDEntry(PDBG_STREAM psStream);
IMG_BOOL RemoveSIDEntry(PDBG_STREAM psStream);
+/*****************************************************************************
+ Declarations for Service table entry points
+*****************************************************************************/
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);
#endif
+/*****************************************************************************
+ End of file (DBGDRIV.H)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title IOCTL implementations for debug device.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _IOCTL_
#define _IOCTL_
+/*****************************************************************************
+ Global vars
+*****************************************************************************/
+
#define MAX_DBGVXD_W32_API 25
extern IMG_UINT32 (*g_DBGDrivProc[MAX_DBGVXD_W32_API])(IMG_VOID *, IMG_VOID *);
#endif
+/*****************************************************************************
+ End of file (IOCTL.H)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Resource Handle Manager
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource handle management
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include "img_defs.h"
#include "dbgdrvif.h"
#include "dbgdriv.h"
+/* max number of streams held in SID info table */
#define MAX_SID_ENTRIES 8
typedef struct _SID_INFO
{
if (psStream == gaSID_Xlat_Table[iIdx].psStream)
{
-
+ /* idx is one based */
return (IMG_SID)iIdx+1;
}
}
PDBG_STREAM SID2PStream(IMG_SID hStream)
{
-
+ /* changed to zero based */
IMG_INT32 iIdx = (IMG_INT32)hStream-1;
if (iIdx >= 0 && iIdx < MAX_SID_ENTRIES)
{
if (psStream == gaSID_Xlat_Table[iIdx].psStream)
{
-
+ /* already created */
return IMG_TRUE;
}
if (gaSID_Xlat_Table[iIdx].psStream == (PDBG_STREAM)IMG_NULL)
{
-
+ /* free entry */
gaSID_Xlat_Table[iIdx].psStream = psStream;
return IMG_TRUE;
}
}
+/******************************************************************************
+ End of file (handle.c)
+******************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Host function definitions for debug device.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _HOSTFUNC_
#define _HOSTFUNC_
+/*****************************************************************************
+ Defines
+*****************************************************************************/
#define HOST_PAGESIZE (4096)
#define DBG_MEMORY_INITIALIZER (0xe2)
+/*****************************************************************************
+ Function prototypes
+*****************************************************************************/
IMG_UINT32 HostReadRegistryDWORDFromString(IMG_CHAR *pcKey, IMG_CHAR *pcValueName, IMG_UINT32 *pui32Data);
IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages);
IMG_VOID HostWaitForEvent(DBG_EVENT eEvent);
IMG_VOID HostSignalEvent(DBG_EVENT eEvent);
IMG_VOID HostDestroyEventObjects(IMG_VOID);
-#endif
+#endif /*defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
#endif
+/*****************************************************************************
+ End of file (HOSTFUNC.H)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
-
-#if (!defined(LINUX) && !defined(__QNXNTO__))
+/*************************************************************************/ /*!
+@Title Debug driver utilities implementations.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Hotkey stuff
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+
+#if !defined(LINUX) && !defined(__QNXNTO__)
#include <ntddk.h>
#include <windef.h>
#endif
+/*****************************************************************************
+ Global vars
+*****************************************************************************/
IMG_UINT32 g_ui32HotKeyFrame = 0xFFFFFFFF;
IMG_BOOL g_bHotKeyPressed = IMG_FALSE;
IMG_BOOL g_bHotKeyRegistered = IMG_FALSE;
+/* Hotkey stuff */
PRIVATEHOTKEYDATA g_PrivateHotKeyData;
+/*****************************************************************************
+ Code
+*****************************************************************************/
+
+
+/******************************************************************************
+ * Function Name: ReadInHotKeys
+ *
+ * Inputs : none
+ * Outputs : -
+ * Returns : nothing
+ * Globals Used : -
+ *
+ * Description : Gets Hot key entries from system.ini
+ *****************************************************************************/
IMG_VOID ReadInHotKeys(IMG_VOID)
{
- g_PrivateHotKeyData.ui32ScanCode = 0x58;
+ g_PrivateHotKeyData.ui32ScanCode = 0x58; /* F12 */
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
+ /*
+ Find buffer names etc..
+ */
HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ScanCode" , &g_PrivateHotKeyData.ui32ScanCode);
HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ShiftState", &g_PrivateHotKeyData.ui32ShiftState);
-#endif
}
+/******************************************************************************
+ * Function Name: RegisterKeyPressed
+ *
+ * Inputs : IMG_UINT32 dwui32ScanCode, PHOTKEYINFO pInfo
+ * Outputs : -
+ * Returns : nothing
+ * Globals Used : -
+ *
+ * Description : Called when hotkey pressed.
+ *****************************************************************************/
IMG_VOID RegisterKeyPressed(IMG_UINT32 dwui32ScanCode, PHOTKEYINFO pInfo)
{
PDBG_STREAM psStream;
if (!g_bHotKeyPressed)
{
-
-
+ /*
+ Capture the next frame.
+ */
g_ui32HotKeyFrame = psStream->psCtrl->ui32Current + 2;
-
-
+ /*
+ Do the flag.
+ */
g_bHotKeyPressed = IMG_TRUE;
}
}
}
+/******************************************************************************
+ * Function Name: ActivateHotKeys
+ *
+ * Inputs : -
+ * Outputs : -
+ * Returns : -
+ * Globals Used : -
+ *
+ * Description : Installs HotKey callbacks
+ *****************************************************************************/
IMG_VOID ActivateHotKeys(PDBG_STREAM psStream)
{
-
-
+ /*
+ Setup hotkeys.
+ */
ReadInHotKeys();
-
-
+ /*
+ Has it already been allocated.
+ */
if (!g_PrivateHotKeyData.sHotKeyInfo.hHotKey)
{
if (g_PrivateHotKeyData.ui32ScanCode != 0)
{
PVR_DPF((PVR_DBG_MESSAGE,"Activate HotKey for PDUMP.\n"));
-
-
+ /*
+ Add in stream data.
+ */
g_PrivateHotKeyData.sHotKeyInfo.pvStream = psStream;
DefineHotKey(g_PrivateHotKeyData.ui32ScanCode, g_PrivateHotKeyData.ui32ShiftState, &g_PrivateHotKeyData.sHotKeyInfo);
}
}
+/******************************************************************************
+ * Function Name: DeactivateHotKeys
+ *
+ * Inputs : -
+ * Outputs : -
+ * Returns : -
+ * Globals Used : -
+ *
+ * Description : Removes HotKey callbacks
+ *****************************************************************************/
IMG_VOID DeactivateHotKeys(IMG_VOID)
{
if (g_PrivateHotKeyData.sHotKeyInfo.hHotKey != 0)
}
+/*****************************************************************************
+ End of file (HOTKEY.C)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Debug driver utilities header file.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Hotkey stuff
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifndef _HOTKEY_
#define _HOTKEY_
IMG_UINT32 ui32ShiftState;
IMG_UINT32 ui32HotKeyProc;
IMG_VOID *pvStream;
- IMG_UINT32 hHotKey;
+ IMG_UINT32 hHotKey; /* handle. */
} HOTKEYINFO, *PHOTKEYINFO;
typedef struct _privatehotkeydata
} PRIVATEHOTKEYDATA, *PPRIVATEHOTKEYDATA;
+/*****************************************************************************
+ Hotkey stuff
+*****************************************************************************/
IMG_VOID ReadInHotKeys (IMG_VOID);
IMG_VOID ActivateHotKeys(PDBG_STREAM psStream);
IMG_VOID DeactivateHotKeys(IMG_VOID);
#endif
+/*****************************************************************************
+ End of file (HOTKEY.H)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title IOCTL implementations for debug device.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#ifdef LINUX
#include <asm/uaccess.h>
#include "pvr_uaccess.h"
-#endif
+#endif /* LINUX */
#include "img_types.h"
#include "dbgdrvif.h"
#include "dbgdriv_ioctl.h"
+/*****************************************************************************
+ Code
+*****************************************************************************/
+
+/*****************************************************************************
+ FUNCTION : DBGDrivCreateStream
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_CREATESTREAM psIn;
return(IMG_TRUE);
}
+/*****************************************************************************
+ FUNCTION : DBGDrivDestroyStream
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivDestroyStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_STREAM *ppsStream;
return(IMG_TRUE);
}
+/*****************************************************************************
+ FUNCTION : DBGDrivGetStream
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_FINDSTREAM psParams;
return(IMG_TRUE);
}
+/*****************************************************************************
+ FUNCTION : DBGDrivWriteString
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivWriteString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_WRITESTRING psParams;
}
else
{
-
+ /* invalid SID */
*pui32OutLen = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivWriteStringCM
+
+ PURPOSE : Same as DBGDrivWriteString, but takes notice of capture mode.
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivWriteStringCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_WRITESTRING psParams;
}
else
{
-
+ /* invalid SID */
*pui32OutLen = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivReadString
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivReadString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
IMG_UINT32 * pui32OutLen;
}
else
{
-
+ /* invalid SID */
*pui32OutLen = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivWrite
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivWrite(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
IMG_UINT32 * pui32BytesCopied;
}
else
{
-
+ /* invalid SID */
*pui32BytesCopied = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivWrite2
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivWrite2(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
IMG_UINT32 * pui32BytesCopied;
}
else
{
-
+ /* invalid SID */
*pui32BytesCopied = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivWriteCM
+
+ PURPOSE : Same as DBGDIOCDrivWrite2, but takes notice of capture mode.
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivWriteCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
IMG_UINT32 * pui32BytesCopied;
}
else
{
-
+ /* invalid SID */
*pui32BytesCopied = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivRead
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivRead(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
IMG_UINT32 * pui32BytesCopied;
}
else
{
-
+ /* invalid SID */
*pui32BytesCopied = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivSetCaptureMode
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivSetCaptureMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_SETDEBUGMODE psParams;
}
else
{
-
+ /* invalid SID */
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivSetOutMode
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivSetOutMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_SETDEBUGOUTMODE psParams;
}
else
{
-
+ /* invalid SID */
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivSetDebugLevel
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivSetDebugLevel(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_SETDEBUGLEVEL psParams;
}
else
{
-
+ /* invalid SID */
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivSetFrame
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivSetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_SETFRAME psParams;
}
else
{
-
+ /* invalid SID */
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivGetFrame
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_STREAM psStream;
}
else
{
-
+ /* invalid SID */
*pui32Current = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivIsCaptureFrame
+
+ PURPOSE : Determines if this frame is a capture frame
+
+ PARAMETERS :
+
+ RETURNS : IMG_TRUE if current frame is to be captured
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivIsCaptureFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_ISCAPTUREFRAME psParams;
}
else
{
-
+ /* invalid SID */
*pui32Current = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivOverrideMode
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivOverrideMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_OVERRIDEMODE psParams;
}
else
{
-
+ /* invalid SID */
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivDefaultMode
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivDefaultMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_STREAM psStream;
}
else
{
-
+ /* invalid SID */
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivSetMarker
+
+ PURPOSE : Sets the marker in the stream to split output files
+
+ PARAMETERS : pvInBuffer, pvOutBuffer
+
+ RETURNS : success
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_SETMARKER psParams;
}
else
{
-
+ /* invalid SID */
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivGetMarker
+
+ PURPOSE : Gets the marker in the stream to split output files
+
+ PARAMETERS : pvInBuffer, pvOutBuffer
+
+ RETURNS : success
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_STREAM psStream;
}
else
{
-
+ /* invalid SID */
*pui32Current = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDrivGetServiceTable
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
IMG_PVOID * ppvOut;
return(IMG_TRUE);
}
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivWriteLF
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivWriteLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
PDBG_IN_WRITE_LF psInParams;
}
else
{
-
+ /* invalid SID */
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivReadLF
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivReadLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
IMG_UINT32 * pui32BytesCopied;
}
else
{
-
+ /* invalid SID */
*pui32BytesCopied = 0;
return(IMG_FALSE);
}
}
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivWaitForEvent
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_UINT32 DBGDIOCDrivWaitForEvent(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
{
DBG_EVENT eEvent = (DBG_EVENT)(*(IMG_UINT32 *)pvInBuffer);
return(IMG_TRUE);
}
+/*
+ VxD DIOC interface jump table.
+*/
IMG_UINT32 (*g_DBGDrivProc[25])(IMG_VOID *, IMG_VOID *) =
{
DBGDIOCDrivCreateStream,
DBGDIOCDrivWaitForEvent
};
+/*****************************************************************************
+ End of file (IOCTL.C)
+*****************************************************************************/
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Debug driver file
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
-#endif
+#endif /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
#include "img_types.h"
#include "pvr_debug.h"
#define PVR_STRING_TERMINATOR '\0'
#define PVR_IS_FILE_SEPARATOR(character) ( ((character) == '\\') || ((character) == '/') )
+/******************************************************************************/
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDebugPrintf
+
+ @Description To output a debug message to the user
+
+ @Input uDebugLevel: The current debug level
+ @Input pszFile: The source file generating the message
+ @Input uLine: The line of the source file
+ @Input pszFormat: The message format string
+ @Input ...: Zero or more arguments for use by the format string
+
+ @Return none
+******************************************************************************/
void PVRSRVDebugPrintf (
IMG_UINT32 ui32DebugLevel,
const IMG_CHAR* pszFileName,
{
pszFileName = pszLeafName;
}
-#endif
+#endif /* __sh__ */
bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
char *szBufferEnd = szBuffer;
char *szBufferLimit = szBuffer + sizeof(szBuffer) - 1;
-
+ /* The Limit - End pointer arithmetic we're doing in snprintf
+ ensures that our buffer remains null terminated from this */
*szBufferLimit = '\0';
snprintf(szBufferEnd, szBufferLimit - szBufferEnd, "PVR_K:");
szBufferEnd += strlen(szBufferEnd);
-
+ /* Add in the level of warning */
if (bTrace == IMG_FALSE)
{
switch(ui32DebugLevel)
va_end (vaArgs);
szBufferEnd += strlen(szBufferEnd);
-
+ /*
+ * Metrics and Traces don't need a location
+ */
if (bTrace == IMG_FALSE)
{
snprintf(szBufferEnd, szBufferLimit - szBufferEnd,
printk(KERN_INFO "%s\r\n", szBuffer);
}
}
-#endif
+#endif /* defined(DEBUG) && !defined(SUPPORT_DRI_DRM) */
+
+/*!
+******************************************************************************
+
+ @Function HostMemSet
+
+ @Description Function that does the same as the C memset() function
+ @Modified *pvDest : pointer to start of buffer to be set
+
+ @Input ui8Value: value to set each byte to
+
+ @Input ui32Size : number of bytes to set
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID HostMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
{
memset(pvDest, (int) ui8Value, (size_t) ui32Size);
}
+/*!
+******************************************************************************
+
+ @Function HostMemCopy
+
+ @Description Function that does the same as the C memscpy() function
+
+ @Input pvDst - pointer to dst
+ @Output pvSrc - pointer to src
+ @Input ui32Size - bytes to copy
+
+ @Return none
+
+******************************************************************************/
IMG_VOID HostMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
{
#if defined(USE_UNOPTIMISED_MEMCPY)
IMG_UINT32 HostReadRegistryDWORDFromString(char *pcKey, char *pcValueName, IMG_UINT32 *pui32Data)
{
-
+ /* FIXME: Not yet implemented */
return 0;
}
IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages)
{
- return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+ return (void*)vmalloc(ui32Pages * PAGE_SIZE);/*, GFP_KERNEL);*/
}
IMG_VOID HostPageablePageFree(IMG_VOID * pvBase)
IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages)
{
- return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+ return (void*)vmalloc(ui32Pages * PAGE_SIZE);/*, GFP_KERNEL);*/
}
IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase)
IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID **ppvMdl)
{
-
+ /* FIXME: Not yet implemented */
return IMG_NULL;
}
IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess)
{
-
+ /* FIXME: Not yet implemented */
}
IMG_VOID HostCreateRegDeclStreams(IMG_VOID)
{
-
+ /* FIXME: Not yet implemented */
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
switch(eEvent)
{
case DBG_EVENT_STREAM_DATA:
-
+ /*
+ * More than one process may be woken up.
+ * Any process that wakes up should consume
+ * all the data from the streams.
+ */
wait_event_interruptible_timeout(sStreamDataEvent, iStreamData != 0, EVENT_WAIT_TIMEOUT_JIFFIES);
iStreamData = 0;
break;
default:
-
+ /*
+ * For unknown events, enter an interruptible sleep.
+ */
msleep_interruptible(EVENT_WAIT_TIMEOUT_MS);
break;
}
IMG_VOID HostDestroyEventObjects(IMG_VOID)
{
}
-#endif
+#endif /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
-/**********************************************************************
- *
- * Copyright (C) Imagination Technologies Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Debug driver main file
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/fs.h>
#include "pvr_drm_shared.h"
#include "pvr_drm.h"
-#else
+#else /* defined(SUPPORT_DRI_DRM) */
#define DRVNAME "dbgdrv"
MODULE_SUPPORTED_DEVICE(DRVNAME);
.mmap = dbgdrv_mmap,
};
-#endif
-
-IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+#endif /* defined(SUPPORT_DRI_DRM) */
-IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table)
+IMG_VOID DBGDrvGetServiceTable(DBGKM_SERVICE_TABLE **fn_table)
{
extern DBGKM_SERVICE_TABLE g_sDBGKMServices;
class_destroy(psDbgDrvClass);
#endif
unregister_chrdev(AssignedMajorNumber, DRVNAME);
-#endif
+#endif /* !defined(SUPPORT_DRI_DRM) */
#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
HostDestroyEventObjects();
#endif
int err = -EBUSY;
#endif
-
+ /* Init API mutex */
if ((g_pvAPIMutex=HostCreateMutex()) == IMG_NULL)
{
return -ENOMEM;
}
#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
-
+ /*
+ * The current implementation of HostCreateEventObjects on Linux
+ * can never fail, so there is no need to check for error.
+ */
(void) HostCreateEventObjects();
#endif
}
#if defined(LDM_PLATFORM) || defined(LDM_PCI)
-
+ /*
+ * This code (using GPL symbols) facilitates automatic device
+ * node creation on platforms with udev (or similar).
+ */
psDbgDrvClass = class_create(THIS_MODULE, DRVNAME);
if (IS_ERR(psDbgDrvClass))
{
__func__, PTR_ERR(psDev)));
goto ErrDestroyClass;
}
-#endif
-#endif
+#endif /* defined(LDM_PLATFORM) || defined(LDM_PCI) */
+#endif /* !defined(SUPPORT_DRI_DRM) */
return 0;
class_destroy(psDbgDrvClass);
#endif
return err;
-#endif
+#endif /* !defined(SUPPORT_DRI_DRM) */
}
#if defined(SUPPORT_DRI_DRM)
goto init_failed;
}
-
+ /* Extra -1 because ioctls start at DEBUG_SERVICE_IOCTL_BASE + 1 */
cmd = MAKEIOCTLINDEX(pIP->ui32Cmd) - DEBUG_SERVICE_IOCTL_BASE - 1;
if(pIP->ui32Cmd == DEBUG_SERVICE_READ)
}
+/******************************************************************************
+ * Function Name: RemoveHotKey
+ *
+ * Inputs : -
+ * Outputs : -
+ * Returns : -
+ * Globals Used : -
+ *
+ * Description : Removes HotKey callbacks
+ *****************************************************************************/
IMG_VOID RemoveHotKey (IMG_UINT32 hHotKey)
{
PVR_UNREFERENCED_PARAMETER(hHotKey);
}
+/******************************************************************************
+ * Function Name: DefineHotKey
+ *
+ * Inputs : -
+ * Outputs : -
+ * Returns : -
+ * Globals Used : -
+ *
+ * Description : Removes HotKey callbacks
+ *****************************************************************************/
IMG_VOID DefineHotKey (IMG_UINT32 ui32ScanCode, IMG_UINT32 ui32ShiftState, PHOTKEYINFO psInfo)
{
PVR_UNREFERENCED_PARAMETER(ui32ScanCode);