summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/xfree86
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86')
-rw-r--r--xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml377
-rw-r--r--xc/programs/Xserver/hw/xfree86/doc/sgml/DRIcomp.sgml501
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile9
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h11
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c16
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c114
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c36
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/i810/i810_memory.c8
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c734
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h125
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/Imakefile21
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h113
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c102
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c111
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c1242
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h116
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h54
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c447
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h601
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/r128/r128_sarea.h77
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/Imakefile3
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/Imakefile4
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h13
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/i810_drm.h129
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/r128_drm.h111
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmI810.c28
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmR128.c198
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile15
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel20
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux56
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/agpsupport.c17
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h19
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h133
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_bufs.c409
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c1562
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drm.h188
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.c147
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.h160
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c1484
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm.h269
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.c124
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h355
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_state.c1088
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c12
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_bufs.c309
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_context.c214
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_dma.c908
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drm.h111
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.c737
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.h226
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c34
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c163
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmI810.c87
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmR128.c199
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h19
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h42
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/xf86drmI810.h46
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/xf86drmMga.h147
-rw-r--r--xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h80
59 files changed, 12145 insertions, 2536 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml b/xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml
index 895ce09a7..e95ff113a 100644
--- a/xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml
+++ b/xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml
@@ -3,17 +3,17 @@
]>
<!-- Created: Mon Feb 28 13:00:00 2000 by brian@precisioninsight.com -->
-<!-- Revised: Mon Mar 6 20:10:02 2000 by kevin@precisioninsight.com -->
+<!-- Revised: Fri May 19 09:41:48 2000 by martin@valinux.com -->
<article>
- <title>DRI Users Guide
+ <title>DRI User Guide
<author><htmlurl url="http://www.precisioninsight.com/"
name="Precision Insight, Inc.">
- <date>6 March 2000
+ <date>18 May 2000
<ident>
- $XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml,v 1.3 2000/03/08 05:38:41 dawes Exp $
+ $XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml,v 1.3 2000/04/05 05:38:41 brianp Exp $
</ident>
<toc>
@@ -25,7 +25,7 @@
<bf>Copyright &copy; 2000 by Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.</bf>
- <p>
+<p>
<bf>Permission is granted to make and distribute verbatim copies
of this document provided the copyright notice and this permission
notice are preserved on all copies.</bf>
@@ -43,6 +43,8 @@
trademarks of 3Dlabs Inc. Ltd.
3dfx, Voodoo3, Voodoo4, and Voodoo5 are registered trademarks of
3dfx Interactive, Incorporated.
+ Matrox is a registered trademark of Matrox Electronic Systems Ltd.
+ ATI Rage is a registered trademark of ATI Technologies, Inc.
All other trademarks mentioned are the property of their
respective owners.
@@ -60,9 +62,13 @@
software downloads.
<p>
This document does not cover compilation or installation of
- XFree86 4.0;
- it is assumed that you've already installed a Linux distribution which
- includes XFree86 4.0.
+ XFree86 4.0.
+ It is assumed that you've already installed a Linux distribution which
+ includes XFree86 4.0 or that you're an experienced Linux developer
+ who has compiled the DRI for himself.
+ DRI download, compilation and installation instructions can be found
+ at <htmlurl url="http://dri.sourceforge.net/DRIcompile.html"
+ name="http://dri.sourceforge.net/DRIcompile.html">
<sect>Supported Hardware
<p>
@@ -71,8 +77,8 @@
Support for Alpha, and perhaps other CPUs, should be available in the
future.
<p>
- XFree86 4.0 includes 3D acceleration for the following
- graphics hardware:
+ XFree86 4.0 (or later versions) includes 3D acceleration for the
+ following graphics hardware:
<itemize>
<item>3dfx:
@@ -87,6 +93,19 @@
</itemize>
There are many configurations of 3dfx cards on the market.
Not all have been tested.
+ <item>Matrox G400
+ <item>ATI Rage 128
+ <itemize>
+ <item>Rage Fury AGP
+ <item>Rage Magnum AGP
+ <item>XPERT 2000 AGP
+ <item>XPERT 128 AGP
+ <item>XPERT 99 AGP
+ <item>All-in-Wonder 128 AGP
+ </itemize>
+ The PCI versions of these cards also have minimal support.
+ Note that there are also Rage 128 Pro based boards on the
+ market, and these are not yet supported.
<item>3Dlabs Oxygen GMX 2000 (MX/Gamma based)
</itemize>
@@ -94,8 +113,6 @@
Support for the following hardware is underway:
<itemize>
<item>Intel i810
- <item>Matrox G400
- <item>ATI Rage 128
<item>3dfx Voodoo4 and Voodoo5 series
</itemize>
@@ -104,8 +121,10 @@
<p>
<itemize>
<item>XFree86 4.0
- <item>Linux kernel 2.2.x (later kernels will be supported in
+ <item>For the 3dfx Voodoo3 driver, Linux kernel 2.2.x (later
+ kernels will be supported in
the near future, and may be required for some chipsets)
+ <item>For the Matrox G400, Linux kernel 2.3.51, with AGP support
</itemize>
<p>
Mesa 3.3 (beta) is included with XFree86 4.0; there is no need to
@@ -119,20 +138,17 @@
<sect1>Kernel module
<p>
- Before starting the X server you must install the correct kernel
- module for your hardware.
- <p>
- This can be done by executing the following as root:
- <verb>
- insmod XXX/drivername.o
- </verb>
- <p>
- For example, on 3dfx hardware, the kernel module is called tdfx.o
- so you you would type insmod XXX/tdfx.o
-
- <p>
- Verify that the kernel module was installed by checking that
- /proc/dri/0 exists.
+ XFree86 4.0.1 added automatic kernel module loading to the X server.
+ On Linux, the X server uses modprobe to load kernel modules.
+ The DRM kernel modules should be in /lib/modules/KERNEL-VERSION/misc/
+ for automatic loading to work.
+<p>
+ Optionally, DRM kernel modules can be loaded manually with insmod
+ prior to starting the X server.
+<p>
+ You can verify that the kernel module was installed with lsmod,
+ checking the X server startup log, and checking that /proc/dri/0
+ exists.
<sect1>XF86Config file
<p>
@@ -199,6 +215,7 @@
<p>
Next, the Device section of the XF86Config file must describe your
particular hardware.
+ <p>
For example, here's the Device section for a 3dfx Voodoo3 card:
<verb>
@@ -210,6 +227,27 @@
</verb>
<p>
+ Here's the Device section for a Matrox G400 card:
+ <verb>
+ Section "Device"
+ Identifier "G400"
+ VendorName "Matrox"
+ Driver "mga"
+ VideoRam 32768
+ EndSection
+ </verb>
+
+ <p>
+ Here's the Device section for an ATI Rage 128 card:
+ <verb>
+ Section "Device"
+ Identifier "Rage128"
+ VendorName "ATI"
+ Driver "r128"
+ EndSection
+ </verb>
+
+ <p>
Finally, the Screen section of the XF86Config file may have to be
specially configured as well.
For example, Voodoo3 hardware acceleration is only available
@@ -227,7 +265,10 @@
EndSubsection
EndSection
</verb>
-
+ <p>
+ Replace <em>Voodoo3</em> with <em>G400</em> for Matrox G400.
+ <p>
+ Replace <em>Voodoo3</em> with <em>Rage128</em> for ATI Rage 128.
<p>
If there are errors in the XF86Config file, the X server will
log errors to the file /var/log/XFree86.0.log
@@ -301,6 +342,25 @@
if means that the libGL.so.1 file is not the right location.
Proceed to the trouble shooting section.
+ <sect1>libOSMesa.so
+<p>
+ OSMesa (Off-Screen Mesa) is an interface and driver for rendering
+ 3D images into a user-allocated block of memory rather than an
+ on-screen window.
+<p>
+ libOSMesa.so implements the OSMesa interface and must be linked
+ with your application if you want to use the OSMesa functions.
+ You must also link with libGL.so. For example:
+ <verb>
+ gcc osdemo.c -L/usr/X11R6/lib -lOSMesa -lGLU -lGL -o osdemo
+ </verb>
+<p>
+ In stand-alone Mesa this interface was compiled into the monolithic
+ libGL.so (formerly libMesaGL.so) library.
+ In XFree86 4.0.1 and later this interface is implemented in a
+ separate library.
+<p>
+
<sect1>glxinfo
<p>
glxinfo is a useful program for checking which version of
@@ -346,20 +406,25 @@
<enum>
<item>
<tt/LIBGL_DEBUG/, if defined will cause libGL.so to print error
- and diagnostic messages. This can help to solve problems.
+ and diagnostic messages.
+ This can help to solve problems.
+ Setting <tt/LIBGL_DEBUG/ to <tt/verbose/ may provide additional
+ information.
<item>
<tt/LIBGL_ALWAYS_INDIRECT/, if defined this will force libGL.so
to always use indirect rendering instead of hardware
- acceleration.
+ acceleration.
This can be useful to isolate rendering errors.
<item>
- <tt/LIBGL_DRIVERS_DIR/ can be used to override the default
- directory which is searched for 3D drivers.
+ <tt/LIBGL_DRIVERS_PATH/ can be used to override the default
+ directories which are searched for 3D drivers.
+ The value is one or more paths separated by colons.
In a typical XFree86 installation, the 3D drivers should be in
- /usr/X11R6/lib/modules/dri/.
- This environment variable can be used to specify a different
- directory.
+ /usr/X11R6/lib/modules/dri/ and <tt/LIBGL_DRIVERS_PATH/ need
+ not be defined.
Note that this feature is disabled for set-uid programs.
+ This variable replaces the <tt/LIBGL_DRIVERS_DIR/ env var used
+ in XFree86 4.0.
</enum>
<p>
Mesa-based drivers (this includes most of the drivers listed
@@ -531,6 +596,40 @@
<sect1>3dfx Voodoo3
<p>
+ <sect2>Configuration
+<p>
+ Your XF86Config file's device section must specify the
+ <tt>tdfx</tt> device:
+ <verb>
+ Section "Device"
+ Identifier "Voodoo3"
+ VendorName "3dfx"
+ Driver "tdfx"
+ EndSection
+ </verb>
+ The Screen section should then reference the Voodoo3 device:
+ <verb>
+ Section "Screen"
+ Identifier "Screen 1"
+ Device "Voodoo3"
+ Monitor "High Res Monitor"
+ DefaultDepth 16
+ Subsection "Display"
+ Depth 16
+ Modes "1280x1024" "1024x768" "800x600" "640x480"
+ ViewPort 0 0
+ EndSubsection
+ EndSection
+ </verb>
+ <p>
+ The kernel module for the Voodoo3 is named <tt>tdfx.o</tt> and
+ should be installed in /lib/modules/KERNEL-VERSION/misc/.
+ It will be automatically loaded by the Xserver if needed.
+ <p>
+ The DRI 3D driver for the Voodoo3 should be in
+ <tt>/usr/X11R6/lib/modules/dri/tdfx_dri.so</tt>.
+ This will be automatically loaded by libGL.so.
+
<sect2>Troubleshooting
<p>
<itemize>
@@ -539,6 +638,9 @@
bit/pixel screen mode.
Use <tt/xdpyinfo/ to verify that all your visuals are depth 16.
Edit your XF86Config file if needed.
+ <item>
+ The <tt>/dev/3dfx</tt> device is not used for DRI; it's only for
+ Glide on older 3dfx hardware.
</itemize>
<sect2>Performance
@@ -565,6 +667,9 @@
<p>
<itemize>
<item>
+ Glide cannot be used directly; only OpenGL-based programs are
+ supported on the Voodoo3.
+ <item>
SSystem has problems because of poorly set near and far
clipping planes.
The office.unc Performer model also suffers from this problem.
@@ -573,10 +678,120 @@
<sect1>Intel i810
<p>
+ Information to be added in the future.
+
<sect1>Matrox G400
<p>
+ <sect2>Configuration
+<p>
+ Your XF86Config file's device section must specify the
+ <tt>mga</tt> device:
+ <verb>
+ Section "Device"
+ Identifier "G400"
+ VendorName "Matrox"
+ Driver "mga"
+ EndSection
+ </verb>
+ The Screen section should then reference the G400 mga device:
+ <verb>
+ Section "Screen"
+ Identifier "Screen 1"
+ Device "G400"
+ Monitor "High Res Monitor"
+ DefaultDepth 16
+ Subsection "Display"
+ Depth 16
+ Modes "1280x1024" "1024x768" "800x600" "640x480"
+ ViewPort 0 0
+ EndSubsection
+ EndSection
+ </verb>
+ <p>
+ The kernel module for the G400 is named <tt>mga.o</tt> and
+ should be installed in /lib/modules/KERNEL-VERSION/misc/.
+ It will be automatically loaded by the Xserver if needed.
+ <p>
+ The DRI 3D driver for the G400 should be in
+ <tt>/usr/X11R6/lib/modules/dri/mga_dri.so</tt>.
+ This will be automatically loaded by libGL.so.
+
+ <sect2>Troubleshooting
+<p>
+ <itemize>
+ <item>
+ 3D acceleration for the G400 is only supported in the 16
+ bit/pixel screen mode at this time. 32bpp will be supported
+ in the future.
+ Use <tt/xdpyinfo/ to verify that all your visuals are depth 16.
+ Edit your XF86Config file if needed.
+ </itemize>
+
+ <sect2>Performance
+<p>
+ No data at this time.
+
+ <sect2>Known Problems
+<p>
+ No data at this time.
+
+
<sect1>ATI Rage 128
<p>
+ <sect2>Configuration
+<p>
+ Your XF86Config file's device section must specify the
+ <tt>r128</tt> device:
+ <verb>
+ Section "Device"
+ Identifier "Rage128"
+ VendorName "ATI"
+ Driver "r128"
+ EndSection
+ </verb>
+ The Screen section should then reference the Rage 128 device:
+ <verb>
+ Section "Screen"
+ Identifier "Screen 1"
+ Device "Rage128"
+ Monitor "High Res Monitor"
+ DefaultDepth 16
+ Subsection "Display"
+ Depth 16
+ Modes "1280x1024" "1024x768" "800x600" "640x480"
+ ViewPort 0 0
+ EndSubsection
+ Subsection "Display"
+ Depth 32
+ Modes "1280x1024" "1024x768" "800x600" "640x480"
+ ViewPort 0 0
+ EndSubsection
+ EndSection
+ </verb>
+ <p>
+ The kernel module for the Rage 128 is named <tt>r128.o</tt> and
+ should be installed in /lib/modules/KERNEL-VERSION/misc/.
+ It will be automatically loaded by the Xserver if needed.
+ <p>
+ The DRI 3D driver for the Rage 128 should be in
+ <tt>/usr/X11R6/lib/modules/dri/r128_dri.so</tt>.
+ This will be automatically loaded by libGL.so.
+ <p>
+ You may also set your screen depth to 32 for 32bpp mode.
+ <p>
+
+ <sect2>Performance
+<p>
+ While PCI Rage 128 based cards are supported, they do not yet
+ support PCI GART, so they will not perform as well as their
+ AGP counterparts.
+
+ <sect2>Known Problems
+<p>
+ DGA is not yet supported in the ATI Rage 128 X server. This
+ feature will be added in a future release.
+
+
<sect1>3DLabs Oxygen GMX 2000
<p>
The driver for this hardware was experimental and is no longer being
@@ -621,6 +836,50 @@
which will be addressed in the future.
+ <sect1>libGL.so and dlopen()
+<p>
+ A number of popular OpenGL applications on Linux (such as Quake3,
+ HereticII, Heavy Gear 2, etc) dynamically open the libGL.so
+ library at runtime with dlopen(), rather than linking with -lGL
+ at compile/link time.
+<p>
+ If dynamic loading of libGL.so is not implemented carefully, there
+ can be a number of serious problems.
+ Here are the things to be careful of in your application:
+ <itemize>
+ <item>Specify the RTLD_GLOBAL flag to dlopen().
+ If you don't do this then you'll likely see a runtime error message
+ complaining that _glapi_Context is undefined when libGL.so
+ tries to open a hardware-specific driver.
+ Without this flag, <em>nested</em> opening of dynamic libraries
+ does not work.
+ <item>Do not close the library with dlclose() until after
+ XCloseDisplay() has been called.
+ When libGL.so initializes itself it registers several callbacks
+ functions with Xlib.
+ When XCloseDisplay() is called those callback functions are
+ called.
+ If libGL.so has already been unloaded with dlclose() this will
+ cause a segmentation fault.
+ <item>
+ Your application should link with -lpthread.
+ On Linux, libGL.so uses the pthreads library in order to provide
+ thread safety.
+ There is apparently a bug in the dlopen()/dlclose() code which
+ causes crashes if the library uses pthreads but the parent
+ application doesn't.
+ The only known work-around is to link the application with
+ -lpthread.
+ </itemize>
+
+ Some applications don't yet incorporate these procedures and
+ may fail.
+ For example, changing the graphics settings in some video games
+ will expose this problem.
+ The DRI developers are working with game vendors to prevent this
+ problem in the future.
+
+
<sect1>Bug Database
<p>
The DRI bug database which includes bugs related to specific
@@ -654,6 +913,9 @@
<item>Visit the <htmlurl url="http://dri.sourceforge.net"
name="DRI project on SourceForge.net"> for the latest development
news about the DRI and 3D drivers.
+ <item>The <htmlurl url="http://dri.sourceforge.net/DRIcompile.html"
+ name="DRI Compilation Guide"> explains how to download, compile
+ and install the DRI for yourself.
</itemize>
<sect1>Support
@@ -664,54 +926,13 @@
<htmlurl url="http://sourceforge.net/mail/?group_id=387"
name="SourceForge"> is a forum for people to discuss DRI problems.
<item>
- XXX IHV support?
- <item>
- XXX Linux distro support?
+ In the future there may be IHV and Linux vendor support resources
+ for the DRI.
</itemize>
</article>
-<!--
-1. Introduction
-2. Supported Hardware
-3. Prerequisite Software
-4. Start-Up
-5. Using 3D Acceleration
- 5.1 libGL.so
- 5.2 glxinfo
- 5.3 Environment variables
-6. General Trouble Shooting
-7. Hardware-Specific Information
- 7.1 3dfx
- 7.2 Intel i810
- 7.3 Matrox G400
- 7.4 ATI Rage 128
- 7.5 3DLabs Gamma
-8. Limitation and Known Bugs
- 8.1 OpenGL
- 8.2 GLX
- 8.3 Signal Handling
- 8.4 Scheduling
- 8.5 Bug Database
-9. Resources
- 9.1 Software Resources
- GLU
- GLUT
- Glide3
- Utilities and demos
- Sample XF86Config files
- 9.2 Documentation
- www.XFree86.org
- www.opengl.org
- www.linux.com
- www.precisioninsight.com
- sourceforge.net
- 9.3 Support
- IHVs
- RedHat
- -->
-
<!-- Local Variables: -->
<!-- fill-column: 72 -->
<!-- End: -->
diff --git a/xc/programs/Xserver/hw/xfree86/doc/sgml/DRIcomp.sgml b/xc/programs/Xserver/hw/xfree86/doc/sgml/DRIcomp.sgml
new file mode 100644
index 000000000..eeda0e057
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/doc/sgml/DRIcomp.sgml
@@ -0,0 +1,501 @@
+<!doctype linuxdoc system>
+<!-- Created: Sun Mar 12 13:00:00 2000 by brian@precisioninsight.com -->
+<!-- Revised: Fri May 19 09:36:02 2000 by martin@valinux.com -->
+<!-- $Id: DRIcomp.sgml,v 1.6.12.1 2000/05/30 14:47:49 dfr Exp $ -->
+
+ <article>
+
+ <title>DRI Compilation Guide
+ <author>
+ <htmlurl url="http://www.precisioninsight.com/"
+ name="Precision Insight, Inc.">
+ <date>18 May 2000
+
+ <ident>
+ $XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml,v 1.3 2000/04/05 05:38:41 brianp Exp $
+ </ident>
+
+ <toc>
+
+ <sect>Preamble
+
+ <sect1>Copyright
+ <p>
+ <bf>Copyright &copy; 2000 by Precision Insight, Inc.,
+ Cedar Park, Texas.
+ All Rights Reserved.</bf>
+ <p>
+ <bf>Permission is granted to make and distribute verbatim copies
+ of this document provided the copyright notice and this permission
+ notice are preserved on all copies.</bf>
+
+ <sect1>Trademarks
+ <p>
+ OpenGL is a registered trademark and SGI is a trademark of
+ Silicon Graphics, Inc.
+ Unix is a registered trademark of The Open Group.
+ The `X' device and X Window System are trademarks of The Open Group.
+ XFree86 is a trademark of The XFree86 Project.
+ Linux is a registered trademark of Linus Torvalds.
+ Intel is a registered trademark of Intel Corporation.
+ 3Dlabs, GLINT, and Oxygen are either registered trademarks or
+ trademarks of 3Dlabs Inc. Ltd.
+ 3dfx, Voodoo3, Voodoo4, and Voodoo5 are registered trademarks of
+ 3dfx Interactive, Incorporated.
+ Matrox is a registered trademark of Matrox Electronic Systems Ltd.
+ ATI Rage is a registered trademark of ATI Technologies, Inc.
+ All other trademarks mentioned are the property of their
+ respective owners.
+
+
+ <sect>Introduction
+ <p>
+ This document describes how to download, compile and install the
+ DRI project.
+ This information is intended for experienced Linux developers.
+ Beginners are probably better off installing precompiled packages.
+ <p>
+ Edits, corrections and updates to this document may be mailed
+ to brian@precisioninsight.com.
+
+
+ <sect>Prerequisites
+ <p>
+ You'll need the following:
+ <itemize>
+ <item>At least 400MB of free disk space. More is needed if you want
+ to build with debugging information or keep several build trees.
+ <item>A fast system. Using a PIII-550 it takes about 1/2 hour to
+ build everthing.
+ <item>GCC compiler and related tools.
+ <item>ssh (secure shell) for registed developer downloading of the
+ DRI source tree
+ </itemize>
+
+ <p>
+ For 3dfx Voodoo3 hardware, you'll also need:
+ <itemize>
+ <item>Glide3x headers and runtime library if you want to use the
+ 3dfx driver.
+ These can be obtained from
+ <htmlurl url="http://linux.3dfx.com/open_source/glide_kit.htm"
+ name="linux.3dfx.com">.
+ <item>Linux kernel 2.2.x.
+ The DRI developers have been using stock RedHat 6.1 systems
+ (kernel 2.2.12-20).
+ Later kernel versions will be supported in the future.
+ </itemize>
+
+ <p>
+ For Matrox G400 hardware, you'll also need:
+ <itemize>
+ <item>Linux kernel 2.3.51. Other kernel versions may work but
+ this one is known to work.
+ </itemize>
+
+ <p>
+ For ATI Rage hardware, you'll also need:
+ <itemize>
+ <item>Linux kernel 2.3.51. Other kernel versions may work but
+ this one is known to work.
+ </itemize>
+
+
+ <sect>Kernel preparation
+ <p>
+ You may have to upgrade your Linux kernel in order to use the DRI.
+ This is because you need a kernel version which supports AGP.
+ Building a new Linux kernel can be difficult for beginners but
+ there are resouces on the Internet to help.
+ This document assumes experience with configuring, building and
+ installing Linux kernels.
+ <p>
+ Linux kernels can be downloaded from
+ <htmlurl url="http://www.kernel.org/pub/linux/kernel/"
+ name="www.kernel.org">
+ <p>
+ Download the needed kernel and put it in /usr/src.
+ Create a directory for the source and unpack it.
+ For example:
+ <verb>
+ cd /usr/src
+ rm -f linux
+ mkdir linux-2.3.51
+ ln -s linux-2.3.51 linux
+ bzcat linux-2.3.51.tar.bz2 | tar xf -
+ </verb>
+ <p>
+ Now configure your kernel.
+ You might, for example, use <tt>make menuconfig</tt> and do the
+ following:
+
+ <itemize>
+ <item>Go to <em>Code maturity level options</em>
+ <item>Enable <em>Prompt for development and/or incomplete
+ code/drivers</em>
+ <item>hit ESC
+ <item>Go to <em>Character devices</em>
+ <item>Disable <em>Direct Rendering Manager (XFree86 DRI support)</em>
+ since we'll use the DRI module from the XFree86/DRI tree.
+ <item>Go to <em>/dev/agpgart (AGP Support) (EXPERIMENTAL) (NEW)</em>
+ <item>Hit SPACE twice
+ <item>Enable all chipsets' support for AGP
+ </itemize>
+
+ <p>It's recommended that you turn on MTRRs under <em>Processor type
+ and Features</em>, but not required.
+
+ <p>
+ Configure the rest of the kernel as required for your system
+ (i.e. ethernet, scsi, etc)
+ <p>
+ Exit, saving your kernel configuration.
+ <p>
+ Edit your /etc/lilo.conf file.
+ Make sure you have an image entry as follows (or similar):
+ <verb>
+ image=/boot/vmlinuz
+ label=linux.2.3.51
+ read-only
+ root=/dev/hda1
+ </verb>
+ <p>
+ The important part is that you have /boot/vmlinuz without a
+ trailing version number.
+ If this is the first entry in your /etc/lilo.conf AND you
+ haven't set a default, then this will be your default kernel.
+
+ <p>
+ Now compile the new kernel:
+
+ <verb>
+ cd /usr/src/linux-2.3.51
+ make dep ; make bzImage
+ make modules ; make modules_install
+ make install
+ </verb>
+ Note that the final part, make install, will automatically run
+ lilo for you.
+ <p>
+ Now reboot to use this new kernel.
+
+
+ <sect>Downloading the XFree86/DRI CVS Sources
+ <p>
+ The DRI project is hosted by VA Linux Systems'
+ <htmlurl url="http://sourceforge.net/project/?group_id=387"
+ name="SourceForge">.
+ The DRI source code, which is a subset of the XFree86 source tree,
+ is kept in a CVS repository there.
+ <p>
+ The DRI CVS sources may be accessed either anonymously or as a
+ registered SourceForge user.
+ It's recommended that you become a registered SourceForge user so
+ that you may submit non-annonymous bug reports and can participate
+ in the mailing lists.
+
+ <sect1>Anonymous CVS download:
+ <p>
+ <enum>
+ <item>Create a directory to store the CVS files:
+ <p>
+ <verb>
+ cd ~
+ mkdir DRI-CVS
+ </verb>
+ You could put your CVS directory in a different place but we'll
+ use <tt>~/DRI-CVS/</tt> here.
+ <p>
+ <item>Check out the CVS sources:
+ <p>
+ <verb>
+ cd ~/DRI-CVS
+ cvs -d:pserver:anonymous@cvs.dri.sourceforge.net:/cvsroot/dri login
+ (hit ENTER when prompted for a password)
+ cvs -z3 -d:pserver:anonymous@cvs.dri.sourceforge.net:/cvsroot/dri co xc
+ </verb>
+ <p>
+ The -z3 flag causes compression to be used in order to reduce
+ the download time.
+ </enum>
+
+
+ <sect1>Registered CVS download:
+ <p>
+ <enum>
+ <item>Create a directory to store the CVS files:
+ <p>
+ <verb>
+ cd ~
+ mkdir DRI-CVS
+ </verb>
+ You could put your CVS directory in a different place but we'll
+ use <tt>~/DRI-CVS/</tt> here.
+ <p>
+ <item>Set the CVS_RSH environment variable:
+ <p>
+ <verb>
+ setenv CVS_RSH ssh // if using csh or tcsh
+ export CVS_RSH=ssh // if using sh or bash
+ </verb>
+ <item>Check out the CVS sources:
+ <p>
+ <verb>
+ cd ~/DRI-CVS
+ cvs -z3 -dYOURID@cvs.dri.sourceforge.net:/cvsroot/dri co xc
+ </verb>
+ Replace <tt>YOURID</tt> with your CVS login name.
+ You'll be prompted to enter your sourceforge password.
+ <p>
+ The -z3 flag causes compression to be used in order to reduce
+ the download time.
+ </enum>
+
+
+ <sect>Updating your CVS sources
+ <p>
+ In the future you'll want to occasionally update your local copy of
+ the DRI source code to get the latest changes.
+ This can be done with:
+ <verb>
+ cd ~/DRI-CVS
+ cvs -z3 update -dA xc
+ </verb>
+ The -d flag causes any new subdirectories to be created and -A causes
+ most recent trunc sources to be fetched, not branch sources.
+
+
+ <sect>Compiling the XFree86/DRI tree
+ <sect1>Make a build tree
+ <p>
+ Rather than placing object files and library files right in the
+ source tree, they're instead put into a parallel <em>build</em> tree.
+ The build tree is made with the <tt>lndir</tt> command:
+ <verb>
+ cd ~/DRI-CVS
+ ln -s xc XFree40
+ mkdir build
+ cd build
+ lndir -silent -ignorelinks ../XFree40
+ </verb>
+ <p>
+ The build tree will be populated with symbolic links which point
+ back into the CVS source tree.
+ <p>
+ Advanced users may have several build trees for compiling and
+ testing with different options.
+
+ <sect1>Edit the host.def file
+ <p>
+ The <tt>~/DRI-CVS/build/xc/config/cf/host.def</tt> file is used
+ to configure the XFree86 build process.
+ You can change it to customize your build options or make adjustments
+ for your particular system configuration
+ <p>
+ The default <tt>host.def</tt> file will look something like this:
+ <verb>
+ #define DefaultCCOptions -Wall
+ #define DefaultGcc2i386Opt -O2
+ #define LibraryCDebugFlags -O2
+ #define BuildServersOnly YES
+ #define XF86CardDrivers vga tdfx mga r128
+ #define LinuxDistribution LinuxRedHat
+ #define DefaultCCOptions -ansi GccWarningOptions -pipe
+ #define BuildXF86DRI YES
+ #define HasGlide3 YES
+ /* Optionally turn these on for debugging */
+ /* #define GlxBuiltInTdfx YES */
+ /* #define GlxBuiltInMga YES */
+ /* #define GlxBuiltInR128 YES */
+ /* #define DoLoadableServer NO */
+ #define SharedLibFont NO
+ </verb>
+ The <tt>ProjectRoot</tt> variable specifies where the XFree86 files
+ will be installed.
+ You probably don't want to use <tt>/usr/X11R6/</tt> because that
+ would overwrite your default X files.
+ The following is recommended:
+ <verb>
+ #define ProjectRoot /usr/XF86-main
+ </verb>
+ <p>
+ Especially note the <em>XF86CardDrivers</em> line to be sure your
+ driver is listed.
+ <p>
+ If you have 3dfx hardware be sure that the Glide 3x headers are
+ installed in <tt>/usr/include/glide3/</tt> and that the Glide 3x
+ library is installed at <tt>/usr/lib/libglide3x.so</tt>.
+ <p>
+ If you do not have 3dfx hardware comment out the <tt>HasGlide3</tt>
+ line in <tt>host.def</tt>.
+ <p>
+
+ <sect1>Compile
+ <p>
+ To compile the complete DRI tree:
+ <verb>
+ cd ~/DRI-CVS/build/xc/
+ make World >& World.LOG
+ </verb>
+ Or if you want to watch the compilation progress:
+ <verb>
+ cd ~/DRI-CVS/build/xc/
+ make World >& World.LOG &
+ tail -f World.LOG
+ </verb>
+ With the default compilation flags it's normal to get a lot of
+ warnings during compilation.
+ <p>
+ Building will take some time so you may want to go check your
+ email or visit slashdot.
+
+ <sect1>Check for compilation errors
+ <p>
+ Using your text editor, examine <tt>World.LOG</tt> for errors
+ by searching for the pattern <tt>***</tt>.
+ <p>
+ Verify that the DRI kernel module(s) for your system were built:
+ <verb>
+ cd ~/DRI-CVS/build/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel
+ ls
+ </verb>
+ <p>
+ For the 3dfx Voodoo, you should see <em>tdfx.o</em>.
+ For the Matrox G400, you should see <em>mga.o</em>.
+ For the ATI Rage 128, you should see <em>r128.o</em>.
+ <p>
+ If the DRI kernel module(s) failed to build you should verify
+ that you're using the right version of the Linux kernel.
+ The most recent kernels are not always supported.
+ <p>
+ If your build machine is running a different version of the kernel
+ than your target machine (i.e. 2.2.12-20 vs. 2.3.99-pre6), make will
+ select the wrong kernel headers. This can be fixed by explicitly
+ setting the value of <tt>TREE</tt>.
+ If the path to your kernel source is
+ <tt>/bigdisk/linux-2.3.99-pre6</tt>,
+ <verb>
+ cd ~/DRI-CVS/build/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel
+ make TREE=/bigdisk/linux-2.3.99-pre6
+ </verb>
+ or alternatively, edit Makefile to include this change.
+ <p>
+ After fixing the errors, do <tt>make World</tt> again.
+ Later, you might just compile parts of the source tree but it's
+ important that the whole tree will build first.
+
+
+ <sect>Installing
+ <p>
+ After the DRI tree has been compiled you can install the XFree86
+ headers, libraries, programs, etc for testing.
+
+ <sect1>X Installation
+ <p>
+ As mentioned above, the install directory is specified by the
+ <tt>ProjectRoot</tt> variable in the <tt>host.def</tt> file.
+ Create that directory now if it doesn't already exist:
+ <verb>
+ mkdir /usr/XF86-main
+ </verb>
+ <p>
+ You'll have to change to root since the install process puts
+ several files in <tt>/etc/X11/</tt> and sets the setuid flag on
+ the X server executable.
+ <verb>
+ cd ~/DRI-CVS/build/xc
+ su
+ make install
+ </verb>
+ Edit your <tt>/etc/ld.so.conf</tt> file and put
+ <tt>/usr/XF86-main/lib</tt> as the first line.
+ Continue with:
+ <verb>
+ ldconfig
+ exit
+ </verb>
+ <p>
+ Look in <tt>/usr/XF86-main</tt> to be sure the files installed
+ there.
+ <P>
+ Strictly speaking, installing the DRI tree isn't required.
+ It's possible to run and test the X server directly from the
+ build directory but it's a bit error prone.
+
+ <sect1>Update Locale Information
+ <p>
+ To update your X locale information do the following:
+ <verb>
+ cd ~/DRI-CVS/build/xc/nls
+ xmkmf
+ make
+ make install
+ </verb>
+ This will prevent a locale error message from being printed
+ when you run Xlib programs.
+
+ <sect>X Server Configuration
+ <p>
+ If your X server is currently running you'll have to stop it
+ and return to a virtual terminal.
+ <p>
+ First, setup your XF86Config file.
+ It should load the GLX and DRI modules and specify the driver to
+ use for your hardware.
+ See the <htmlurl url="http://dri.sourceforge.net/DRIuserguide.html"
+ name="DRI User Guide"> for detailed information.
+ <p>
+ You may want to make a backup copy of your existing
+ <tt>/etc/X11/XF86Config</tt> file first.
+ <p>
+ It's very important that you set the <tt>ModulePath</tt> option to
+ point to your installation directory:
+ <verb>
+ ModulePath "/usr/XF86-main/lib/modules"
+ </verb>
+ <p>
+ Double check with this:
+ <verb>
+ grep ModulePath /etc/X11/XF86Config
+ </verb>
+ <p>
+ Next, your <tt>~/.xinitrc</tt> file controls which clients will be
+ launched when your X server starts.
+ You might put the following in yours:
+ <verb>
+ xset b off
+ xsetroot -solid "#004070"
+ xmodmap -e "clear mod4"
+ xrdb -merge ~/.Xdefaults
+ xterm -geometry +0+0 &
+ xterm -geometry +512+0 &
+ fvwm
+ </verb>
+ <p>
+
+ <sect>X Server Start-up
+ <p>
+ The X server can be started with:
+ <p>
+ <verb>
+ xinit -- /usr/XF86-main/bin/XFree86
+ </verb>
+ <p>
+ Automatic loading of DRM kernel modules was added to the X server
+ in XFree86 4.0.1.
+ This feature, and manual loading of kernel modules, is documented
+ in the DRI user guide.
+ <p>
+ At this point your X server should be up and running with
+ hardware-accelerated direct rendering.
+ Please read the
+ <htmlurl url="http://dri.sourceforge.net/DRIuserguide.html"
+ name="DRI User Guide"> for trouble shooting information.
+
+
+ </article>
+
+
+ <!-- Local Variables: -->
+ <!-- fill-column: 72 -->
+ <!-- End: -->
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile b/xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile
index 331396f38..9e167d6c7 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile
+++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile
@@ -6,13 +6,9 @@ XCOMM
#define IHaveModules
#include <Server.tmpl>
-#
-# Uncomment these to build with DRI support when available
-#
-#undef BuildXF86DRI
#if BuildXF86DRI
-DRISRCS = i810_dri.c i810_drm.c
-DRIOBJS = i810_dri.o i810_drm.o
+DRISRCS = i810_dri.c
+DRIOBJS = i810_dri.o
DRIINCLUDES = -I$(SERVERSRC)/GL/dri -I$(LIBSRC)/GL/dri \
-I$(XF86OSSRC)/linux/drm/kernel
DRIDEFINES = $(GLX_DEFINES)
@@ -63,7 +59,6 @@ InstallDriverSDKNonExecFile(i810_cursor.c,$(DRIVERSDKDIR)/drivers/i810)
InstallDriverSDKNonExecFile(i810_driver.c,$(DRIVERSDKDIR)/drivers/i810)
InstallDriverSDKNonExecFile(i810_dri.c,$(DRIVERSDKDIR)/drivers/i810)
InstallDriverSDKNonExecFile(i810_dri.h,$(DRIVERSDKDIR)/drivers/i810)
-InstallDriverSDKNonExecFile(i810_dripriv.h,$(DRIVERSDKDIR)/drivers/i810)
InstallDriverSDKNonExecFile(i810_io.c,$(DRIVERSDKDIR)/drivers/i810)
InstallDriverSDKNonExecFile(i810_memory.c,$(DRIVERSDKDIR)/drivers/i810)
InstallDriverSDKNonExecFile(i810_wmark.c,$(DRIVERSDKDIR)/drivers/i810)
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h
index 6aceea540..58a17ad74 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h
+++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h
@@ -36,16 +36,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef _I810_H_
#define _I810_H_
-
+#include "compiler.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "i810_reg.h"
#include "xaa.h"
#include "xf86Cursor.h"
-#undef XF86DRI
-
-
#ifdef XF86DRI
#include "xf86drm.h"
#include "sarea.h"
@@ -211,8 +208,8 @@ typedef struct _I810Rec {
extern Bool I810DRIScreenInit(ScreenPtr pScreen);
extern void I810DRICloseScreen(ScreenPtr pScreen);
extern Bool I810DRIFinishScreenInit(ScreenPtr pScreen);
-extern Bool I810drmInitDma(ScrnInfoPtr pScrn);
-extern Bool I810drmCleanupDma(ScrnInfoPtr pScrn);
+extern Bool I810InitDma(ScrnInfoPtr pScrn);
+extern Bool I810CleanupDma(ScrnInfoPtr pScrn);
#define I810PTR(p) ((I810Ptr)((p)->driverPrivate))
#define I810REGPTR(p) (&(I810PTR(p)->ModeReg))
@@ -312,7 +309,7 @@ extern void I810EmitInvarientState(ScrnInfoPtr pScrn);
/* To remove all debugging, make sure I810_DEBUG is defined as a
* preprocessor symbol, and equal to zero.
*/
-#define I810_DEBUG 0
+#define I810_DEBUG 0
#ifndef I810_DEBUG
#warning "Debugging enabled - expect reduced performance"
extern int I810_DEBUG;
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c
index 0f67180d2..1a410bcd1 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c
@@ -271,6 +271,7 @@ I810WaitLpRing( ScrnInfoPtr pScrn, int n, int timeout_millis )
DRICloseScreen(screenInfo.screens[pScrn->scrnIndex]);
}
#endif
+ pI810->AccelInfoRec = NULL; /* Stops recursive behavior */
FatalError("lockup\n");
}
@@ -301,13 +302,9 @@ I810Sync( ScrnInfoPtr pScrn )
#ifdef XF86DRI
/* VT switching tries to do this.
*/
- if (!pI810->LockHeld) {
+ if (!pI810->LockHeld && pI810->directRenderingEnabled) {
return;
}
-
-
-/* if (pI810->directRenderingEnabled) */
-/* DRIUnlockLockQueiscent( pScrn->pScreen ); */
#endif
/* Send a flush instruction and then wait till the ring is empty.
@@ -635,19 +632,19 @@ I810RefreshRing(ScrnInfoPtr pScrn)
}
-
+/* Emit on gaining VT?
+ */
void
I810EmitInvarientState(ScrnInfoPtr pScrn)
{
I810Ptr pI810 = I810PTR(pScrn);
- BEGIN_LP_RING( 8 );
+ BEGIN_LP_RING( 10 );
OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
OUT_RING( GFX_CMD_CONTEXT_SEL | CS_UPDATE_USE | CS_USE_CTX0 );
OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
OUT_RING( 0 );
-
OUT_RING( GFX_OP_COLOR_CHROMA_KEY );
OUT_RING( CC1_UPDATE_KILL_WRITE |
CC1_DISABLE_KILL_WRITE |
@@ -658,5 +655,8 @@ I810EmitInvarientState(ScrnInfoPtr pScrn)
OUT_RING( 0 );
OUT_RING( 0 );
+/* OUT_RING( CMD_OP_Z_BUFFER_INFO ); */
+/* OUT_RING( pI810->DepthBuffer.Start | pI810->auxPitchBits); */
+
ADVANCE_LP_RING();
}
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c
index c63f9ed20..591207b65 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c
@@ -1,4 +1,4 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c,v 1.2 2000/03/02 16:07:49 martin Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c,v 1.3 1999/09/27 06:29:57 dawes Exp $ */
#include "xf86.h"
#include "xf86_OSproc.h"
@@ -20,10 +20,6 @@
#include "i810.h"
#include "i810_dri.h"
-#include "xf86drm.h"
-#include "dristruct.h"
-
-
static char I810KernelDriverName[] = "i810";
static char I810ClientDriverName[] = "i810";
@@ -62,6 +58,43 @@ static int i810_pitch_flags[] = {
0
};
+Bool I810CleanupDma(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ Bool ret_val;
+
+ ret_val = drmI810CleanupDma(pI810->drmSubFD);
+ if(ret_val == FALSE) ErrorF("I810 Dma Cleanup Failed\n");
+ return ret_val;
+}
+
+Bool I810InitDma(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RingBuffer *ring = &(pI810->LpRing);
+ drmI810Init info;
+ Bool ret_val;
+
+ info.start = ring->mem.Start;
+ info.end = ring->mem.End;
+ info.size = ring->mem.Size;
+ info.ring_map_idx = 6;
+ info.buffer_map_idx = 5;
+ info.sarea_off = sizeof(XF86DRISAREARec);
+
+ info.front_offset = 0;
+ info.back_offset = pI810->BackBuffer.Start;
+ info.depth_offset = pI810->DepthBuffer.Start;
+ info.w = pScrn->virtualX;
+ info.h = pScrn->virtualY;
+ info.pitch = pI810->auxPitch;
+ info.pitch_bits = pI810->auxPitchBits;
+
+ ret_val = drmI810InitDma(pI810->drmSubFD, &info);
+ if(ret_val == FALSE) ErrorF("I810 Dma Initialization Failed\n");
+ return ret_val;
+}
+
static Bool
I810InitVisualConfigs(ScreenPtr pScreen)
{
@@ -260,8 +293,13 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
int width = pScrn->displayWidth * pI810->cpp;
int i;
- /* ToDo : save agpHandles? */
-
+#if XFree86LOADER
+ /* Check that the GLX, DRI, and DRM modules have been loaded by testing
+ * for known symbols in each module. */
+ if (!LoaderSymbol("GlxSetVisualConfigs")) return FALSE;
+ if (!LoaderSymbol("DRIScreenInit")) return FALSE;
+ if (!LoaderSymbol("drmAvailable")) return FALSE;
+#endif
pDRIInfo = DRICreateInfoRec();
if (!pDRIInfo) {
@@ -279,10 +317,12 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
pDRIInfo->drmDriverName = I810KernelDriverName;
pDRIInfo->clientDriverName = I810ClientDriverName;
pDRIInfo->busIdString = xalloc(64);
+
sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
((pciConfigPtr)pI810->PciInfo->thisCard)->busnum,
((pciConfigPtr)pI810->PciInfo->thisCard)->devnum,
((pciConfigPtr)pI810->PciInfo->thisCard)->funcnum);
+
pDRIInfo->ddxDriverMajorVersion = 0;
pDRIInfo->ddxDriverMinorVersion = 1;
pDRIInfo->ddxDriverPatchVersion = 0;
@@ -302,7 +342,7 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
/* For now the mapping works by using a fixed size defined
* in the SAREA header
*/
- if (sizeof(XF86DRISAREARec)+sizeof(drm_i810_sarea_t)>SAREA_MAX) {
+ if (sizeof(XF86DRISAREARec)+sizeof(I810SAREARec)>SAREA_MAX) {
ErrorF("Data does not fit in SAREA\n");
return FALSE;
}
@@ -378,9 +418,9 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
* under the DRI.
*/
- dcacheHandle = drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL);
+ drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL, &dcacheHandle);
pI810->dcacheHandle = dcacheHandle;
-
+
#define Elements(x) sizeof(x)/sizeof(*x)
for (pitch_idx = 0 ; pitch_idx < Elements(i810_pitches) ; pitch_idx++)
@@ -392,9 +432,8 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
"Couldn't find depth/back buffer pitch");
DRICloseScreen(pScreen);
return FALSE;
- }
- else {
- back_size = i810_pitches[pitch_idx] * pScrn->virtualY;
+ } else {
+ back_size = i810_pitches[pitch_idx] * (pScrn->virtualY + 4);
back_size = ((back_size + 4096 - 1) / 4096) * 4096;
}
@@ -411,14 +450,18 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
} else {
sysmem_size = sysmem_size - 2*back_size;
}
-
- sysmem_size -= 4096;
- if(sysmem_size > ((48*1024*1024) - 1) ) {
- sysmem_size = (48*1024*1024) - (2*4096);
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "User requested more memory then fits in the agp aperture\n"
+
+ if(sysmem_size > 48*1024*1024) {
+ sysmem_size = 48*1024*1024;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "User requested more memory then fits in the agp aperture\n"
"Truncating to %d bytes of memory\n",
sysmem_size);
}
+
+ sysmem_size -= 4096; /* remove 4k for the hw cursor */
+
pI810->SysMem.Start = 0;
pI810->SysMem.Size = sysmem_size;
pI810->SysMem.End = sysmem_size;
@@ -428,7 +471,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
if (dcacheHandle != 0) {
/* The Z buffer is always aligned to the 48 mb mark in the aperture */
-
if(drmAgpBind(pI810->drmSubFD, dcacheHandle, 48*1024*1024) == 0) {
xf86memset (&pI810->DcacheMem, 0, sizeof(I810MemRange));
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -454,7 +496,7 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: no dcache memory found\n");
}
- agpHandle = drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL);
+ drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, &agpHandle);
pI810->backHandle = agpHandle;
if(agpHandle != 0) {
@@ -481,8 +523,8 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
if(dcacheHandle == 0) {
/* The Z buffer is always aligned to the 48 mb mark in the aperture */
- agpHandle = drmAgpAlloc(pI810->drmSubFD, back_size, 0,
- NULL);
+ drmAgpAlloc(pI810->drmSubFD, back_size, 0,
+ NULL, &agpHandle);
pI810->zHandle = agpHandle;
if(agpHandle != 0) {
@@ -509,8 +551,7 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
/* Now allocate and bind the agp space. This memory will include the
* regular framebuffer as well as texture memory.
*/
-
- agpHandle = drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL);
+ drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL, &agpHandle);
if(agpHandle == 0) {
ErrorF("drmAgpAlloc failed\n");
DRICloseScreen(pScreen);
@@ -524,8 +565,8 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
return FALSE;
}
- agpHandle = drmAgpAlloc(pI810->drmSubFD, 4096, 2,
- (unsigned long *)&pI810->CursorPhysical);
+ drmAgpAlloc(pI810->drmSubFD, 4096, 2,
+ (unsigned long *)&pI810->CursorPhysical, &agpHandle);
pI810->cursorHandle = agpHandle;
if (agpHandle != 0) {
@@ -545,7 +586,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
pI810->CursorPhysical = 0;
}
-
I810SetTiledMemory(pScrn, 1,
pI810->DepthBuffer.Start,
i810_pitches[pitch_idx],
@@ -558,10 +598,9 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
pI810->auxPitch = i810_pitches[pitch_idx];
pI810->auxPitchBits = i810_pitch_flags[pitch_idx];
-
pI810->SavedDcacheMem = pI810->DcacheMem;
-
pI810DRI->backbufferSize = pI810->BackBuffer.Size;
+
if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->BackBuffer.Start,
pI810->BackBuffer.Size, DRM_AGP, 0,
&pI810DRI->backbuffer) < 0) {
@@ -586,6 +625,13 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
I810AllocHigh( &(pI810->BufferMem), &(pI810->SysMem),
I810_DMA_BUF_NR * I810_DMA_BUF_SZ);
+ if(pI810->BufferMem.Start == 0 ||
+ pI810->BufferMem.End - pI810->BufferMem.Start >
+ I810_DMA_BUF_NR * I810_DMA_BUF_SZ) {
+ ErrorF("Not enough memory for dma buffers\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
if(drmAddMap(pI810->drmSubFD, (drmHandle)pI810->BufferMem.Start,
pI810->BufferMem.Size, DRM_AGP, 0,
&pI810->buffer_map) < 0) {
@@ -608,7 +654,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
/* Use the rest of memory for textures. */
pI810DRI->textureSize = pI810->SysMem.Size;
-
i = mylog2(pI810DRI->textureSize / I810_NR_TEX_REGIONS);
if (i < I810_LOG_MIN_TEX_REGION_SIZE)
@@ -617,15 +662,14 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
pI810DRI->logTextureGranularity = i;
pI810DRI->textureSize = (pI810DRI->textureSize >> i) << i; /* truncate */
-
if(pI810DRI->textureSize < 512*1024) {
ErrorF("Less then 512k for textures\n");
DRICloseScreen(pScreen);
+ return FALSE;
}
I810AllocLow( &(pI810->TexMem), &(pI810->SysMem),
pI810DRI->textureSize);
-
if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->TexMem.Start,
pI810->TexMem.Size, DRM_AGP, 0,
@@ -650,7 +694,7 @@ Bool I810DRIScreenInit(ScreenPtr pScreen)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] added %d %d byte DMA buffers\n",
bufs, I810_DMA_BUF_SZ);
- I810drmInitDma(pScrn);
+ I810InitDma(pScrn);
/* Okay now initialize the dma engine */
@@ -718,7 +762,7 @@ I810DRICloseScreen(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I810Ptr pI810 = I810PTR(pScrn);
- I810drmCleanupDma(pScrn);
+ I810CleanupDma(pScrn);
if(pI810->dcacheHandle) drmAgpFree(pI810->drmSubFD, pI810->dcacheHandle);
if(pI810->backHandle) drmAgpFree(pI810->drmSubFD, pI810->backHandle);
@@ -768,7 +812,7 @@ I810DestroyContext(ScreenPtr pScreen, drmContext hwContext,
Bool
I810DRIFinishScreenInit(ScreenPtr pScreen)
{
- drm_i810_sarea_t *sPriv = (drm_i810_sarea_t *)DRIGetSAREAPrivate(pScreen);
+ I810SAREARec *sPriv = (I810SAREARec *)DRIGetSAREAPrivate(pScreen);
xf86memset( sPriv, 0, sizeof(sPriv) );
return DRIFinishScreenInit(pScreen);
}
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c
index e489d17c9..99369f50b 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c
@@ -207,31 +207,19 @@ static const char *ramdacSymbols[] = {
#ifdef XF86DRI
static const char *drmSymbols[] = {
+ "drmAvailable",
"drmAddBufs",
"drmAddMap",
- "drmAvailable",
- "drmCtlAddCommand",
"drmCtlInstHandler",
"drmGetInterruptFromBusID",
- "drmMapBufs",
- "drmMarkBufs",
- "drmUnmapBufs",
"drmAgpAcquire",
"drmAgpRelease",
"drmAgpEnable",
"drmAgpAlloc",
"drmAgpFree",
"drmAgpBind",
- "drmAgpUnbind",
- "drmAgpVersionMajor",
- "drmAgpVersionMinor",
- "drmAgpGetMode",
- "drmAgpBase",
- "drmAgpSize",
- "drmAgpMemoryUsed",
- "drmAgpMemoryAvail",
- "drmAgpVendorId",
- "drmAgpDeviceId",
+ "drmI810CleanupDma",
+ "drmI810InitDma",
NULL
};
@@ -1047,7 +1035,6 @@ DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
pI810 = I810PTR(pScrn);
hwp = VGAHWPTR(pScrn);
-
if (I810_DEBUG&DEBUG_VERBOSE_VGA) {
ErrorF("Setting mode in I810Restore:\n");
i810PrintMode( vgaReg, i810Reg );
@@ -1113,7 +1100,7 @@ DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
temp &= ~INTERLACE_ENABLE;
temp |= i810Reg->InterlaceControl;
hwp->writeCrtc(hwp, INTERLACE_CNTL, temp);
-
+
temp=pI810->readControl(pI810, GRX, ADDRESS_MAPPING);
temp &= 0xE0; /* Save reserved bits 7:5 */
temp |= i810Reg->AddressMapping;
@@ -1553,7 +1540,6 @@ I810AllocateFront(ScrnInfoPtr pScrn) {
xf86memset( &(pI810->LpRing), 0, sizeof( I810RingBuffer ) );
if(I810AllocLow( &(pI810->LpRing.mem), &(pI810->SysMem), 16*4096 )) {
-
if (I810_DEBUG & DEBUG_VERBOSE_MEMORY)
ErrorF( "ring buffer at local %lx\n",
pI810->LpRing.mem.Start);
@@ -1607,6 +1593,7 @@ I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) {
/* Have to init the DRM earlier than in other drivers to get agp
* memory. Wonder if this is going to be a problem...
*/
+
#ifdef XF86DRI
/*
* Setup DRI after visuals have been established, but before cfbScreenInit
@@ -1625,7 +1612,7 @@ I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) {
return FALSE;
I810AllocateFront(pScrn);
#endif
-
+
if (!I810MapMem(pScrn)) return FALSE;
pScrn->memPhysBase = (int)pI810->FbBase;
@@ -1729,6 +1716,7 @@ I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) {
}
}
#endif
+
#ifdef XF86DRI
if (!pI810->directRenderingEnabled) {
pI810->DoneFrontAlloc = FALSE;
@@ -1738,6 +1726,7 @@ I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) {
}
#endif
+
if (!xf86InitFBManager(pScreen, &(pI810->FbMemBox))) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to init memory manager\n");
@@ -1762,7 +1751,7 @@ I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) {
}
}
-#if XF86DRI
+#ifdef XF86DRI
if (pI810->LpRing.mem.Start == 0) {
pI810->directRenderingEnabled = 0;
I810DRICloseScreen(pScreen);
@@ -1892,9 +1881,10 @@ I810LeaveVT(int scrnIndex, int flags) {
pI810->LockHeld = 1;
}
#endif
-
- I810RefreshRing( pScrn );
- I810Sync( pScrn );
+ if(pI810->AccelInfoRec != NULL) {
+ I810RefreshRing( pScrn );
+ I810Sync( pScrn );
+ }
I810Restore(pScrn);
vgaHWLock(hwp);
}
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_memory.c b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_memory.c
index 2cedd9682..f499ffa2d 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_memory.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_memory.c
@@ -46,7 +46,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "i810.h"
#include "i810_reg.h"
+#ifdef linux
#include <linux/agpgart.h>
+#endif
int I810AllocLow( I810MemRange *result, I810MemRange *pool, int size )
{
@@ -83,6 +85,7 @@ extern int xf86errno;
int I810AllocateGARTMemory( ScrnInfoPtr pScrn )
{
+#ifdef linux
struct _agp_info agpinf;
struct _agp_bind bind;
struct _agp_allocate alloc;
@@ -220,18 +223,23 @@ int I810AllocateGARTMemory( ScrnInfoPtr pScrn )
return TRUE;
+#else
+ return FALSE;
+#endif
}
void I810FreeGARTMemory( ScrnInfoPtr pScrn )
{
+#ifdef linux
I810Ptr pI810 = I810PTR(pScrn);
if (pI810->gartfd != -1) {
xf86close( pI810->gartfd );
pI810->gartfd = -1;
}
+#endif
}
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c
index df23db4f6..0f4ba439a 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c
@@ -22,7 +22,7 @@
#include "mga.h"
#include "mga_macros.h"
#include "mga_dri.h"
-#include "mga_dripriv.h"
+#include "mga_wrap.h"
static char MGAKernelDriverName[] = "mga";
static char MGAClientDriverName[] = "mga";
@@ -51,172 +51,195 @@ extern void Mga32DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
extern void Mga32DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
RegionPtr prgnSrc, CARD32 index);
-static Bool
-MGAInitVisualConfigs(ScreenPtr pScreen)
+Bool MgaCleanupDma(ScrnInfoPtr pScrn)
{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- MGAPtr pMGA = MGAPTR(pScrn);
- int numConfigs = 0;
- __GLXvisualConfig *pConfigs = 0;
- MGAConfigPrivPtr pMGAConfigs = 0;
- MGAConfigPrivPtr *pMGAConfigPtrs = 0;
- int i;
+ MGAPtr pMGA = MGAPTR(pScrn);
+ Bool ret_val;
+
+ ret_val = drmMgaCleanupDma(pMGA->drmSubFD);
+ if(ret_val == FALSE) ErrorF("Mga Dma Cleanup Failed\n");
+
+ return ret_val;
+}
- switch (pScrn->bitsPerPixel) {
- case 8:
- case 24:
- case 32:
- break;
- case 16:
- numConfigs = 4;
+Bool MgaLockUpdate(ScrnInfoPtr pScrn, drmLockFlags flags)
+{
+ MGAPtr pMGA = MGAPTR(pScrn);
+ Bool ret_val;
+
+ ret_val = drmMgaLockUpdate(pMGA->drmSubFD, flags);
+ if(ret_val == FALSE) ErrorF("LockUpdate failed\n");
+
+ return ret_val;
+}
- if (!(pConfigs = (__GLXvisualConfig*)xnfcalloc(sizeof(__GLXvisualConfig),
- numConfigs))) {
+Bool MgaInitDma(ScrnInfoPtr pScrn, int prim_size)
+{
+ MGAPtr pMGA = MGAPTR(pScrn);
+ MGADRIPtr pMGADRI = (MGADRIPtr)pMGA->pDRIInfo->devPrivate;
+ MGADRIServerPrivatePtr pMGADRIServer = pMGA->DRIServerInfo;
+ drmMgaInit init;
+ Bool ret_val;
+
+ memset(&init, 0, sizeof(drmMgaInit));
+ init.reserved_map_agpstart = 0;
+ init.reserved_map_idx = 3;
+ init.buffer_map_idx = 4;
+ init.sarea_priv_offset = sizeof(XF86DRISAREARec);
+ init.primary_size = prim_size;
+ init.warp_ucode_size = pMGADRIServer->warp_ucode_size;
+
+ switch(pMGA->Chipset) {
+ case PCI_CHIP_MGAG400:
+ init.chipset = MGA_CARD_TYPE_G400;
+ break;
+ case PCI_CHIP_MGAG200:
+ init.chipset = MGA_CARD_TYPE_G200;
+ break;
+ case PCI_CHIP_MGAG200_PCI:
+ default:
+ ErrorF("Direct rendering not supported on this card/chipset\n");
return FALSE;
- }
- if (!(pMGAConfigs = (MGAConfigPrivPtr)xnfcalloc(sizeof(MGAConfigPrivRec),
+ }
+
+ init.frontOffset = pMGADRI->frontOffset;
+ init.backOffset = pMGADRI->backOffset;
+ init.depthOffset = pMGADRI->depthOffset;
+ init.textureOffset = pMGADRI->textureOffset;
+ init.textureSize = pMGADRI->textureSize;
+ init.agpTextureSize = pMGADRI->agpTextureSize;
+ init.cpp = pMGADRI->cpp;
+ init.stride = pMGADRI->frontPitch;
+ init.mAccess = pMGA->MAccess;
+ init.sgram = !pMGA->HasSDRAM;
+
+ memcpy(&init.WarpIndex, &pMGADRIServer->WarpIndex,
+ sizeof(drmMgaWarpIndex) * MGA_MAX_WARP_PIPES);
+
+ ErrorF("Mga Dma Initialization start\n");
+
+ ret_val = drmMgaInitDma(pMGA->drmSubFD, &init);
+ if(ret_val == FALSE) ErrorF("Mga Dma Initialization Failed\n");
+ else ErrorF("Mga Dma Initialization done\n");
+ return ret_val;
+}
+
+static Bool
+MGAInitVisualConfigs(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ MGAPtr pMGA = MGAPTR(pScrn);
+ int numConfigs = 0;
+ __GLXvisualConfig *pConfigs = 0;
+ MGAConfigPrivPtr pMGAConfigs = 0;
+ MGAConfigPrivPtr *pMGAConfigPtrs = 0;
+ int i, db, depth, stencil, accum;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ case 24:
+ case 32:
+ break;
+ case 16:
+ numConfigs = 4;
+
+ if (!(pConfigs = (__GLXvisualConfig*)xnfcalloc(sizeof(__GLXvisualConfig),
numConfigs))) {
- xfree(pConfigs);
- return FALSE;
- }
- if (!(pMGAConfigPtrs = (MGAConfigPrivPtr*)xnfcalloc(sizeof(MGAConfigPrivPtr),
- numConfigs))) {
- xfree(pConfigs);
- xfree(pMGAConfigs);
- return FALSE;
- }
- for (i=0; i<numConfigs; i++)
- pMGAConfigPtrs[i] = &pMGAConfigs[i];
+ return FALSE;
+ }
+ if (!(pMGAConfigs = (MGAConfigPrivPtr)xnfcalloc(sizeof(MGAConfigPrivRec),
+ numConfigs))) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+ if (!(pMGAConfigPtrs = (MGAConfigPrivPtr*)xnfcalloc(sizeof(MGAConfigPrivPtr),
+ numConfigs))) {
+ xfree(pConfigs);
+ xfree(pMGAConfigs);
+ return FALSE;
+ }
+ for (i=0; i<numConfigs; i++)
+ pMGAConfigPtrs[i] = &pMGAConfigs[i];
+
+ i = 0;
+ depth = 1;
+ for (accum = 0; accum <= 1; accum++) {
+ for (stencil = 0; stencil <= 0; stencil++) { /* no stencil for now */
+ for (db=0; db<=1; db++) {
+ pConfigs[i].vid = -1;
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 5;
+ pConfigs[i].greenSize = 6;
+ pConfigs[i].blueSize = 5;
+ pConfigs[i].redMask = 0x0000F800;
+ pConfigs[i].greenMask = 0x000007E0;
+ pConfigs[i].blueMask = 0x0000001F;
+ pConfigs[i].alphaMask = 0;
+ if (accum) {
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ if (db)
+ pConfigs[i].doubleBuffer = TRUE;
+ else
+ pConfigs[i].doubleBuffer = FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 16;
+ if (depth)
+ pConfigs[i].depthSize = 16;
+ else
+ pConfigs[i].depthSize = 0;
+ if (stencil)
+ pConfigs[i].stencilSize = 8;
+ else
+ pConfigs[i].stencilSize = 0;
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (stencil)
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ else
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ pConfigs[i].transparentPixel = 0;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ if (i!=numConfigs) {
+ ErrorF("Incorrect initialization of visuals\n");
+ return FALSE;
+ }
+ break;
+ default:
+ ; /* unexpected bits/pixelx */
+ }
+ pMGA->numVisualConfigs = numConfigs;
+ pMGA->pVisualConfigs = pConfigs;
+ pMGA->pVisualConfigsPriv = pMGAConfigs;
+ GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pMGAConfigPtrs);
+ return TRUE;
+}
- /* config 0: db=FALSE, depth=0
- config 1: db=FALSE, depth=16
- config 2: db=TRUE, depth=0;
- config 3: db=TRUE, depth=16
- */
- pConfigs[0].vid = -1;
- pConfigs[0].class = -1;
- pConfigs[0].rgba = TRUE;
- pConfigs[0].redSize = 8;
- pConfigs[0].greenSize = 8;
- pConfigs[0].blueSize = 8;
- pConfigs[0].redMask = 0x00FF0000;
- pConfigs[0].greenMask = 0x0000FF00;
- pConfigs[0].blueMask = 0x000000FF;
- pConfigs[0].alphaMask = 0;
- pConfigs[0].accumRedSize = 0;
- pConfigs[0].accumGreenSize = 0;
- pConfigs[0].accumBlueSize = 0;
- pConfigs[0].accumAlphaSize = 0;
- pConfigs[0].doubleBuffer = FALSE;
- pConfigs[0].stereo = FALSE;
- pConfigs[0].bufferSize = 16;
- pConfigs[0].depthSize = 0;
- pConfigs[0].stencilSize = 0;
- pConfigs[0].auxBuffers = 0;
- pConfigs[0].level = 0;
- pConfigs[0].visualRating = 0;
- pConfigs[0].transparentPixel = 0;
- pConfigs[0].transparentRed = 0;
- pConfigs[0].transparentGreen = 0;
- pConfigs[0].transparentBlue = 0;
- pConfigs[0].transparentAlpha = 0;
- pConfigs[0].transparentIndex = 0;
-
- pConfigs[1].vid = -1;
- pConfigs[1].class = -1;
- pConfigs[1].rgba = TRUE;
- pConfigs[1].redSize = 8;
- pConfigs[1].greenSize = 8;
- pConfigs[1].blueSize = 8;
- pConfigs[1].redMask = 0x00FF0000;
- pConfigs[1].greenMask = 0x0000FF00;
- pConfigs[1].blueMask = 0x000000FF;
- pConfigs[1].alphaMask = 0;
- pConfigs[1].accumRedSize = 0;
- pConfigs[1].accumGreenSize = 0;
- pConfigs[1].accumBlueSize = 0;
- pConfigs[1].accumAlphaSize = 0;
- pConfigs[1].doubleBuffer = FALSE;
- pConfigs[1].stereo = FALSE;
- pConfigs[1].bufferSize = 16;
- pConfigs[1].depthSize = 16;
- pConfigs[1].stencilSize = 0;
- pConfigs[1].auxBuffers = 0;
- pConfigs[1].level = 0;
- pConfigs[1].visualRating = 0;
- pConfigs[1].transparentPixel = 0;
- pConfigs[1].transparentRed = 0;
- pConfigs[1].transparentGreen = 0;
- pConfigs[1].transparentBlue = 0;
- pConfigs[1].transparentAlpha = 0;
- pConfigs[1].transparentIndex = 0;
-
- pConfigs[2].vid = -1;
- pConfigs[2].class = -1;
- pConfigs[2].rgba = TRUE;
- pConfigs[2].redSize = 8;
- pConfigs[2].greenSize = 8;
- pConfigs[2].blueSize = 8;
- pConfigs[2].redMask = 0x00FF0000;
- pConfigs[2].greenMask = 0x0000FF00;
- pConfigs[2].blueMask = 0x000000FF;
- pConfigs[2].alphaMask = 0;
- pConfigs[2].accumRedSize = 0;
- pConfigs[2].accumGreenSize = 0;
- pConfigs[2].accumBlueSize = 0;
- pConfigs[2].accumAlphaSize = 0;
- pConfigs[2].doubleBuffer = TRUE;
- pConfigs[2].stereo = FALSE;
- pConfigs[2].bufferSize = 16;
- pConfigs[2].depthSize = 0;
- pConfigs[2].stencilSize = 0;
- pConfigs[2].auxBuffers = 0;
- pConfigs[2].level = 0;
- pConfigs[2].visualRating = 0;
- pConfigs[2].transparentPixel = 0;
- pConfigs[2].transparentRed = 0;
- pConfigs[2].transparentGreen = 0;
- pConfigs[2].transparentBlue = 0;
- pConfigs[2].transparentAlpha = 0;
- pConfigs[2].transparentIndex = 0;
-
- pConfigs[3].vid = -1;
- pConfigs[3].class = -1;
- pConfigs[3].rgba = TRUE;
- pConfigs[3].redSize = 8;
- pConfigs[3].greenSize = 8;
- pConfigs[3].blueSize = 8;
- pConfigs[3].redMask = 0x00FF0000;
- pConfigs[3].greenMask = 0x0000FF00;
- pConfigs[3].blueMask = 0x000000FF;
- pConfigs[3].alphaMask = 0;
- pConfigs[3].accumRedSize = 0;
- pConfigs[3].accumGreenSize = 0;
- pConfigs[3].accumBlueSize = 0;
- pConfigs[3].accumAlphaSize = 0;
- pConfigs[3].doubleBuffer = TRUE;
- pConfigs[3].stereo = FALSE;
- pConfigs[3].bufferSize = 16;
- pConfigs[3].depthSize = 16;
- pConfigs[3].stencilSize = 0;
- pConfigs[3].auxBuffers = 0;
- pConfigs[3].level = 0;
- pConfigs[3].visualRating = 0;
- pConfigs[3].transparentPixel = 0;
- pConfigs[3].transparentRed = 0;
- pConfigs[3].transparentGreen = 0;
- pConfigs[3].transparentBlue = 0;
- pConfigs[3].transparentAlpha = 0;
- pConfigs[3].transparentIndex = 0;
- break;
- }
- pMGA->numVisualConfigs = numConfigs;
- pMGA->pVisualConfigs = pConfigs;
- pMGA->pVisualConfigsPriv = pMGAConfigs;
- GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pMGAConfigPtrs);
- return TRUE;
+static unsigned int mylog2(unsigned int n)
+{
+ unsigned int log2 = 1;
+ while (n>1) n >>= 1, log2++;
+ return log2;
}
+
Bool MGADRIScreenInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
@@ -224,10 +247,24 @@ Bool MGADRIScreenInit(ScreenPtr pScreen)
DRIInfoPtr pDRIInfo;
MGADRIPtr pMGADRI;
MGADRIServerPrivatePtr pMGADRIServer;
- int bufs;
- int prim_size;
- int init_offset;
+ int bufs, size;
+ int prim_size;
+ int init_offset;
+ int i;
+#if XFree86LOADER
+ /* Check that the GLX, DRI, and DRM modules have been loaded by testing
+ * for canonical symbols in each module. */
+ if (!LoaderSymbol("GlxSetVisualConfigs")) return FALSE;
+ if (!LoaderSymbol("DRIScreenInit")) return FALSE;
+ if (!LoaderSymbol("drmAvailable")) return FALSE;
+#endif
+
+ if((pScrn->bitsPerPixel / 8) != 2) {
+ ErrorF("Direct Rendering only supported in 16 bpp mode\n");
+ return FALSE;
+ }
+
pDRIInfo = DRICreateInfoRec();
if (!pDRIInfo) return FALSE;
pMGA->pDRIInfo = pDRIInfo;
@@ -247,28 +284,25 @@ Bool MGADRIScreenInit(ScreenPtr pScreen)
pDRIInfo->frameBufferStride = pScrn->displayWidth*(pScrn->bitsPerPixel/8);
pDRIInfo->ddxDrawableTableEntry = MGA_MAX_DRAWABLES;
+ MGADRIWrapFunctions( pScreen, pDRIInfo );
+
if (SAREA_MAX_DRAWABLES < MGA_MAX_DRAWABLES)
pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
else
pDRIInfo->maxDrawableTableEntry = MGA_MAX_DRAWABLES;
-#ifdef NOT_DONE
- /* FIXME need to extend DRI protocol to pass this size back to client
- * for SAREA mapping that includes a device private record
- */
- pDRIInfo->SAREASize =
- ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */
- /* + shared memory device private rec */
-#else
/* For now the mapping works by using a fixed size defined
* in the SAREA header
*/
- if (sizeof(XF86DRISAREARec)+sizeof(drm_mga_sarea_t)>SAREA_MAX) {
+ if (sizeof(XF86DRISAREARec)+sizeof(MGASAREARec)>SAREA_MAX) {
ErrorF("Data does not fit in SAREA\n");
return FALSE;
}
+
+ ErrorF("\n\n\nSarea %d+%d: %d\n", sizeof(XF86DRISAREARec),
+ sizeof(MGASAREARec), sizeof(XF86DRISAREARec) + sizeof(MGASAREARec));
+
pDRIInfo->SAREASize = SAREA_MAX;
-#endif
if (!(pMGADRI = (MGADRIPtr)xnfcalloc(sizeof(MGADRIRec),1))) {
DRIDestroyInfoRec(pMGA->pDRIInfo);
@@ -277,7 +311,7 @@ Bool MGADRIScreenInit(ScreenPtr pScreen)
return FALSE;
}
if (!(pMGADRIServer = (MGADRIServerPrivatePtr)
- xnfcalloc(sizeof(MGADRIServerPrivate),1))) {
+ xnfcalloc(sizeof(MGADRIServerPrivateRec),1))) {
xfree(pMGADRI);
DRIDestroyInfoRec(pMGA->pDRIInfo);
pMGA->pDRIInfo=0;
@@ -334,25 +368,44 @@ Bool MGADRIScreenInit(ScreenPtr pScreen)
pMGADRIServer->regs);
/* Agp Support */
+ pMGADRIServer->agpAcquired = FALSE;
+ pMGADRIServer->agpHandle = 0;
+ pMGADRIServer->agpSizep = 0;
+ pMGADRIServer->agp_map = 0;
+
if(drmAgpAcquire(pMGA->drmSubFD) < 0) {
DRICloseScreen(pScreen);
ErrorF("drmAgpAcquire failed\n");
return FALSE;
}
+ pMGADRIServer->agpAcquired = TRUE;
+
pMGADRIServer->warp_ucode_size = mgaGetMicrocodeSize(pScreen);
if(pMGADRIServer->warp_ucode_size == 0) {
ErrorF("microcodeSize is zero\n");
DRICloseScreen(pScreen);
return FALSE;
}
+
+ pMGADRIServer->agpMode = drmAgpGetMode(pMGA->drmSubFD);
+ /* Default to 1X agp mode */
+ pMGADRIServer->agpMode &= ~0x00000002;
+ if (drmAgpEnable(pMGA->drmSubFD, pMGADRIServer->agpMode) < 0) {
+ ErrorF("drmAgpEnable failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ ErrorF("drmAgpEnabled succeeded\n");
prim_size = 65536;
init_offset = ((prim_size + pMGADRIServer->warp_ucode_size +
4096 - 1) / 4096) * 4096;
- pMGADRIServer->agpSizep = drmAgpSize(pMGA->drmSubFD);
- pMGADRIServer->agpBase = drmAgpBase(pMGA->drmSubFD);
- if (drmAddMap(pMGA->drmSubFD, (drmHandle)pMGADRIServer->agpBase,
+ pMGADRIServer->agpSizep = init_offset;
+ pMGADRI->agpSize = (drmAgpSize(pMGA->drmSubFD)) - init_offset;
+
+ pMGADRIServer->agpBase = (drmAddress) drmAgpBase(pMGA->drmSubFD);
+ if (drmAddMap(pMGA->drmSubFD, 0,
init_offset, DRM_AGP, 0,
&pMGADRIServer->agp_private) < 0) {
DRICloseScreen(pScreen);
@@ -370,12 +423,15 @@ Bool MGADRIScreenInit(ScreenPtr pScreen)
/* Now allocate and bind a default of 8 megs */
- pMGADRIServer->agpHandle = drmAgpAlloc(pMGA->drmSubFD, 0x00800000, 0, 0);
+ drmAgpAlloc(pMGA->drmSubFD, 0x00800000, 0, 0,
+ &pMGADRIServer->agpHandle);
+
if(pMGADRIServer->agpHandle == 0) {
ErrorF("drmAgpAlloc failed\n");
DRICloseScreen(pScreen);
return FALSE;
}
+
if(drmAgpBind(pMGA->drmSubFD, pMGADRIServer->agpHandle, 0) < 0) {
DRICloseScreen(pScreen);
ErrorF("drmAgpBind failed\n");
@@ -384,72 +440,121 @@ Bool MGADRIScreenInit(ScreenPtr pScreen)
mgaInstallMicrocode(pScreen, prim_size);
- ErrorF("init_offset: %x\n", init_offset);
- pMGADRI->agpSize = pMGADRIServer->agpSizep - init_offset;
- ErrorF("pMGADRI->agpSize: %x\n", pMGADRI->agpSize);
-
- if(drmAddMap(pMGA->drmSubFD, (drmHandle)pMGADRIServer->agpBase + init_offset,
+ if(drmAddMap(pMGA->drmSubFD, (drmHandle)init_offset,
pMGADRI->agpSize, DRM_AGP, 0,
&pMGADRI->agp) < 0) {
ErrorF("Failed to map public agp area\n");
DRICloseScreen(pScreen);
return FALSE;
}
- ErrorF("Mapped public agp area\n");
+
+
+ switch(pMGA->Chipset) {
+ case PCI_CHIP_MGAG400:
+ pMGADRI->chipset = MGA_CARD_TYPE_G400;
+ break;
+ case PCI_CHIP_MGAG200:
+ pMGADRI->chipset = MGA_CARD_TYPE_G200;
+ break;
+ case PCI_CHIP_MGAG200_PCI:
+ default:
+ ErrorF("Direct rendering not supported on this card/chipset\n");
+ return FALSE;
+ }
+
+
+ pMGADRI->width = pScrn->virtualX;
+ pMGADRI->height = pScrn->virtualY;
+ pMGADRI->mem = pScrn->videoRam * 1024;
+ pMGADRI->cpp = pScrn->bitsPerPixel / 8;
+ pMGADRI->frontPitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
+
+
+ pMGADRI->frontOffset = 0; /* pMGA->YDstOrg * (pScrn->bitsPerPixel / 8) */
+ pMGADRI->backOffset = ((pScrn->virtualY+129) * pScrn->displayWidth *
+ (pScrn->bitsPerPixel / 8) + 4095) & ~0xFFF;
+
+
+ fprintf(stderr, "calced backoffset: 0x%x\n",
+ pMGADRI->backOffset);
+
+
+#if 0
+ size = 2 * pScrn->virtualX * pScrn->virtualY;
+ pMGADRI->depthOffset = (pMGADRI->backOffset + size + 4095) & ~0xFFF;
+ pMGADRI->textureOffset = pMGADRI->depthOffset + size;
+ pMGADRI->textureSize = pMGA->FbUsableSize - pMGADRI->textureOffset;
+#else
+ size = 2 * pScrn->virtualX * pScrn->virtualY;
+ size += 4095;
+ size &= ~4095;
+ pMGADRI->depthOffset = pMGA->FbUsableSize - size;
+ pMGADRI->depthOffset &= ~4095;
+ pMGADRI->textureOffset = pMGADRI->backOffset + size;
+ pMGADRI->textureSize = pMGADRI->depthOffset - pMGADRI->textureOffset;
+
+ if (pMGADRI->depthOffset < pMGADRI->textureOffset + 512*1024) {
+ ErrorF("Insufficient memory for direct rendering\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+#endif
+
+ pMGADRI->mAccess = pMGA->MAccess;
+
+ i = mylog2(pMGADRI->textureSize / MGA_NR_TEX_REGIONS);
+ if (i < MGA_LOG_MIN_TEX_REGION_SIZE)
+ i = MGA_LOG_MIN_TEX_REGION_SIZE;
+
+ pMGADRI->logTextureGranularity = i;
+ pMGADRI->textureSize = (pMGADRI->textureSize >> i) << i; /* truncate */
+
+
/* Here is where we need to do initialization of the dma engine */
-
- pMGADRIServer->agpMode = drmAgpGetMode(pMGA->drmSubFD);
- /* Default to 1X agp mode */
- pMGADRIServer->agpMode &= ~0x00000002;
- if (drmAgpEnable(pMGA->drmSubFD, pMGADRIServer->agpMode) < 0) {
- ErrorF("drmAgpEnable failed\n");
- DRICloseScreen(pScreen);
- return FALSE;
- }
- ErrorF("drmAgpEnabled succeeded\n");
- if((bufs = drmAddBufs(pMGA->drmSubFD,
- /*63*/ 15,
- /* 65536 */ 524288,
+ if((bufs = drmAddBufs(pMGA->drmSubFD,
+ MGA_DMA_BUF_NR,
+ MGA_DMA_BUF_SZ,
DRM_AGP_BUFFER,
init_offset)) <= 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"[drm] failure adding %d %d byte DMA buffers\n",
- /* 63 */ 15,
- /* 65536 */ 524288);
+ MGA_DMA_BUF_NR,
+ MGA_DMA_BUF_SZ);
DRICloseScreen(pScreen);
return FALSE;
}
+
+ pMGADRI->agpBufferOffset = init_offset + pMGADRIServer->agp_private;
+
+ /* Calculate texture constants for AGP texture space
+ */
+ {
+ CARD32 agpTextureOffset = MGA_DMA_BUF_SZ * MGA_DMA_BUF_NR;
+ CARD32 agpTextureSize = pMGADRI->agpSize - agpTextureOffset;
+
+ i = mylog2(agpTextureSize / MGA_NR_TEX_REGIONS);
+ if (i < MGA_LOG_MIN_TEX_REGION_SIZE)
+ i = MGA_LOG_MIN_TEX_REGION_SIZE;
+
+ pMGADRI->logAgpTextureGranularity = i;
+ pMGADRI->agpTextureSize = (agpTextureSize >> i) << i;
+ pMGADRI->agpTextureOffset = agpTextureOffset;
+ }
+
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"[drm] added %d %d byte DMA buffers\n",
- bufs, /* 65536 */ 524288);
+ bufs, MGA_DMA_BUF_SZ);
- if((mgadrmInitDma(pScrn, prim_size)) != TRUE) {
+ if((MgaInitDma(pScrn, prim_size)) != TRUE) {
ErrorF("Failed to initialize dma engine\n");
DRICloseScreen(pScreen);
return FALSE;
}
-
- ErrorF("Initialized Dma Engine\n");
+ ErrorF("Initialized Dma Engine\n");
- if(drmMarkBufs(pMGA->drmSubFD, 0.133333, 0.266666) != 0) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "[drm] failure marking DMA buffers\n");
- DRICloseScreen(pScreen);
- return FALSE;
- }
- if (!(pMGADRIServer->drmBufs = drmMapBufs(pMGA->drmSubFD))) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "[drm] failure mapping DMA buffers\n");
- DRICloseScreen(pScreen);
- return FALSE;
- }
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] buffers mapped with %p\n",
- pMGADRIServer->drmBufs);
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] %d DMA buffers mapped\n",
- pMGADRIServer->drmBufs->count);
if (!pMGADRIServer->irq) {
pMGADRIServer->irq = drmGetInterruptFromBusID(pMGA->drmSubFD,
((pciConfigPtr)pMGA->PciInfo
@@ -481,16 +586,26 @@ MGADRICloseScreen(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
MGAPtr pMGA = MGAPTR(pScrn);
MGADRIServerPrivatePtr pMGADRIServer = pMGA->DRIServerInfo;
-
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "[drm] unmapping %d buffers\n",
- pMGADRIServer->drmBufs->count);
- if (drmUnmapBufs(pMGADRIServer->drmBufs)) {
- xf86DrvMsg(pScreen->myNum, X_INFO,
- "[drm] unable to unmap DMA buffers\n");
+
+ MgaCleanupDma(pScrn);
+
+ if(pMGADRIServer->agp_map) {
+ ErrorF("Unmapped agp region\n");
+ drmUnmap(pMGADRIServer->agp_map, pMGADRIServer->agpSizep);
+ pMGADRIServer->agp_map = 0;
}
- mgadrmCleanupDma(pScrn);
-
+ if(pMGADRIServer->agpHandle) {
+ ErrorF("Freeing agp memory\n");
+ drmAgpFree(pMGA->drmSubFD, pMGADRIServer->agpHandle);
+ pMGADRIServer->agpHandle = 0;
+ pMGADRIServer->agpSizep = 0;
+ }
+ if(pMGADRIServer->agpAcquired == TRUE) {
+ ErrorF("releasing agp module\n");
+ drmAgpRelease(pMGA->drmSubFD);
+ pMGADRIServer->agpAcquired = FALSE;
+ }
+
DRICloseScreen(pScreen);
if (pMGA->pDRIInfo) {
@@ -518,9 +633,6 @@ MGACreateContext(ScreenPtr pScreen, VisualPtr visual,
drmContext hwContext, void *pVisualConfigPriv,
DRIContextType contextStore)
{
- MGADRIContextPtr ctx;
-
- ctx = (MGADRIContextPtr)contextStore;
return TRUE;
}
@@ -528,106 +640,120 @@ static void
MGADestroyContext(ScreenPtr pScreen, drmContext hwContext,
DRIContextType contextStore)
{
- MGADRIContextPtr ctx;
- ctx = (MGADRIContextPtr)contextStore;
}
Bool
MGADRIFinishScreenInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ MGASAREAPtr sPriv;
MGAPtr pMGA = MGAPTR(pScrn);
- MGADRIPtr pMGADRI;
- int size;
+ if (!pMGA->pDRIInfo) return FALSE;
+
+ sPriv = (MGASAREAPtr)DRIGetSAREAPrivate(pScreen);
pMGA->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
- /* pMGA->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */
- pMGADRI = (MGADRIPtr)pMGA->pDRIInfo->devPrivate;
- pMGADRI->deviceID = pMGA->PciInfo->chipType;
- pMGADRI->width = pScrn->virtualX;
- pMGADRI->height = pScrn->virtualY;
- pMGADRI->mem = pScrn->videoRam * 1024;
- pMGADRI->cpp = pScrn->bitsPerPixel / 8;
- pMGADRI->stride = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
- pMGADRI->backOffset = ((pScrn->virtualY+129) * pScrn->displayWidth *
- (pScrn->bitsPerPixel / 8) + 4095) & ~0xFFF;
- size = 2 * pScrn->virtualX * pScrn->virtualY;
- pMGADRI->depthOffset = (pMGADRI->backOffset + size + 4095) & ~0xFFF;
- pMGADRI->textureOffset = pMGADRI->depthOffset + size;
- /*
- * The rest of the framebuffer is for textures except for the
- * memory for the hardware cursor.
- */
- pMGADRI->textureSize = pMGA->FbUsableSize - pMGADRI->textureOffset;
- pMGADRI->fbOffset = pMGA->YDstOrg * (pScrn->bitsPerPixel / 8);
+ xf86memset( sPriv, 0, sizeof(MGASAREARec) );
return DRIFinishScreenInit(pScreen);
}
-void MGASwapContext(ScreenPtr pScreen)
+
+void mgaGetQuiescence( ScrnInfoPtr pScrn )
{
-#if 0
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- MGAPtr pMga = MGAPTR(pScrn);
- MGAFBLayout *pLayout = &pMga->CurrentLayout;
-
- usleep(500);
- ErrorF("Syncing : swap\n");
- MGABUSYWAIT();
- ErrorF("Sync : swap 1\n");
- MGAStormSync(pScrn);
- ErrorF("Syncing done\n");
- pMga->AccelInfoRec->NeedToSync = TRUE;
-
- WAITFIFO(12);
- OUTREG(MGAREG_MACCESS, pMga->MAccess);
- OUTREG(MGAREG_PITCH, pLayout->displayWidth);
- OUTREG(MGAREG_YDSTORG, pMga->YDstOrg);
- OUTREG(MGAREG_PLNWT, pMga->PlaneMask);
- OUTREG(MGAREG_BCOL, pMga->BgColor);
- OUTREG(MGAREG_FCOL, pMga->FgColor);
- OUTREG(MGAREG_SRCORG, pMga->SrcOrg);
- OUTREG(MGAREG_DSTORG, pMga->DstOrg);
- OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT);
- OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); /* (maxX << 16) | minX */
- OUTREG(MGAREG_YTOP, 0x00000000); /* minPixelPointer */
- OUTREG(MGAREG_YBOT, 0x007FFFFF); /* maxPixelPointer */
- pMga->AccelFlags &= ~CLIPPER_ON;
-#endif
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ pMga->have_quiescense = 1;
+
+ if (pMga->directRenderingEnabled) {
+ MGAFBLayout *pLayout = &pMga->CurrentLayout;
+
+ MgaLockUpdate(pScrn, (DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH));
+
+ WAITFIFO(12);
+ OUTREG(MGAREG_MACCESS, pMga->MAccess);
+ OUTREG(MGAREG_PITCH, pLayout->displayWidth);
+ OUTREG(MGAREG_YDSTORG, pMga->YDstOrg);
+ OUTREG(MGAREG_PLNWT, pMga->PlaneMask);
+ OUTREG(MGAREG_BCOL, pMga->BgColor);
+ OUTREG(MGAREG_FCOL, pMga->FgColor);
+ OUTREG(MGAREG_SRCORG, pMga->SrcOrg);
+ OUTREG(MGAREG_DSTORG, pMga->DstOrg);
+ OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT);
+ OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); /* (maxX << 16) | minX */
+ OUTREG(MGAREG_YTOP, 0x00000000); /* minPixelPointer */
+ OUTREG(MGAREG_YBOT, 0x007FFFFF); /* maxPixelPointer */
+ pMga->AccelFlags &= ~CLIPPER_ON;
+ }
}
-void MGALostContext(ScreenPtr pScreen)
+
+
+void MGASwapContext(ScreenPtr pScreen)
{
-#if 0
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- MGAPtr pMga = MGAPTR(pScrn);
- MGAFBLayout *pLayout = &pMga->CurrentLayout;
-
- ErrorF("Syncing : lost\n");
- MGAStormSync(pScrn);
- ErrorF("Sync : lost 1\n");
- MGABUSYWAIT();
- ErrorF("Syncing done\n");
-#endif
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ /* Arrange for dma_quiescence and xaa sync to be called as
+ * appropriate.
+ */
+ pMga->have_quiescense = 0;
+ pMga->AccelInfoRec->NeedToSync = TRUE;
}
+
+
+/* This is really only called from validate/postvalidate as we
+ * override the dri lock/unlock. Want to remove validate/postvalidate
+ * processing, but need to remove all client-side use of drawable lock
+ * first (otherwise there is noone recover when a client dies holding
+ * the drawable lock).
+ *
+ * What does this mean?
+ *
+ * - The above code gets executed every time a
+ * window changes shape or the focus changes, which isn't really
+ * optimal.
+ * - The X server therefore believes it needs to do an XAA sync
+ * *and* a dma quiescense ioctl each time that happens.
+ *
+ * We don't wrap wakeuphandler any longer, so at least we can say that
+ * this doesn't happen *every time the mouse moves*...
+ */
static void
MGADRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
DRIContextType oldContextType, void *oldContext,
DRIContextType newContextType, void *newContext)
{
- if ((syncType == DRI_3D_SYNC) && (oldContextType == DRI_2D_CONTEXT) &&
- (newContextType == DRI_2D_CONTEXT)) { /* Entering from Wakeup */
- MGASwapContext(pScreen);
- }
- if ((syncType == DRI_2D_SYNC) && (oldContextType == DRI_NO_CONTEXT) &&
- (newContextType == DRI_2D_CONTEXT)) { /* Exiting from Block Handler */
- MGALostContext(pScreen);
- }
+ if (syncType == DRI_3D_SYNC &&
+ oldContextType == DRI_2D_CONTEXT &&
+ newContextType == DRI_2D_CONTEXT)
+ {
+ MGASwapContext(pScreen);
+ }
}
-/* Needs to be written */
-void MGASelectBuffer(MGAPtr pMGA, int which)
+
+void
+MGASelectBuffer(ScrnInfoPtr pScrn, int which)
{
+ MGAPtr pMga = MGAPTR(pScrn);
+ MGADRIPtr pMGADRI = (MGADRIPtr)pMga->pDRIInfo->devPrivate;
+
+ switch (which) {
+ case MGA_BACK:
+ OUTREG(MGAREG_DSTORG, pMGADRI->backOffset);
+ OUTREG(MGAREG_SRCORG, pMGADRI->backOffset);
+ break;
+ case MGA_DEPTH:
+ OUTREG(MGAREG_DSTORG, pMGADRI->depthOffset);
+ OUTREG(MGAREG_SRCORG, pMGADRI->depthOffset);
+ break;
+ default:
+ case MGA_FRONT:
+ OUTREG(MGAREG_DSTORG, pMGADRI->frontOffset);
+ OUTREG(MGAREG_SRCORG, pMGADRI->frontOffset);
+ break;
+ }
}
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h b/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h
index 7196bc954..b8518ee89 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h
+++ b/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h
@@ -4,9 +4,11 @@
#define _MGA_DRI_
#include <xf86drm.h>
-#include "mga_drm_public.h"
+#include <xf86drmMga.h>
-typedef struct _mga_dri_server_private {
+#define MGA_MAX_DRAWABLES 256
+
+typedef struct {
int reserved_map_agpstart;
int reserved_map_idx;
int buffer_map_idx;
@@ -17,6 +19,7 @@ typedef struct _mga_dri_server_private {
int sgram;
unsigned long agpMode;
unsigned long agpHandle;
+ Bool agpAcquired;
drmHandle agp_private;
drmSize agpSizep;
drmAddress agpBase;
@@ -24,27 +27,115 @@ typedef struct _mga_dri_server_private {
drmHandle regs;
drmSize regsSize;
drmAddress regsMap;
- mgaWarpIndex WarpIndex[MGA_MAX_WARP_PIPES];
+ drmMgaWarpIndex WarpIndex[MGA_MAX_WARP_PIPES];
drmBufMapPtr drmBufs;
CARD8 *agp_map;
-} MGADRIServerPrivate, *MGADRIServerPrivatePtr;
+} MGADRIServerPrivateRec, *MGADRIServerPrivatePtr;
typedef struct {
- int deviceID;
- int width;
- int height;
- int mem;
- int cpp;
- int stride;
- int fbOffset;
- int backOffset;
- int depthOffset;
- int textureOffset;
- int textureSize;
- drmHandle agp;
- drmSize agpSize;
+ int chipset;
+ int width;
+ int height;
+ int mem;
+ int cpp;
+ unsigned int frontOffset;
+ unsigned int frontPitch;
+
+ unsigned int backOffset;
+ unsigned int backPitch;
+
+ unsigned int depthOffset;
+ unsigned int depthPitch;
+
+ unsigned int textureOffset;
+ unsigned int textureSize;
+ int logTextureGranularity;
+
+ /* Allow calculation of setup dma addresses.
+ */
+ unsigned int agpBufferOffset;
+
+ unsigned int agpTextureOffset;
+ unsigned int agpTextureSize;
+ int logAgpTextureGranularity;
+
+ /* Redundant?
+ */
+ unsigned int frontOrg;
+ unsigned int backOrg;
+ unsigned int depthOrg;
+
+ unsigned int mAccess;
+
+ drmHandle agp;
+ drmSize agpSize;
} MGADRIRec, *MGADRIPtr;
+/* WARNING: Do not change the SAREA structure without changing the kernel
+ * as well */
+typedef struct {
+ unsigned char next, prev;
+ unsigned char in_use;
+ unsigned int age;
+} MGATexRegionRec, *MGATexRegionPtr;
+
+typedef struct {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex dma buffer.
+ */
+ unsigned int ContextState[MGA_CTX_SETUP_SIZE];
+ unsigned int ServerState[MGA_2D_SETUP_SIZE];
+ unsigned int TexState[2][MGA_TEX_SETUP_SIZE];
+ unsigned int WarpPipe;
+ unsigned int dirty;
+
+ unsigned int nbox;
+ XF86DRIClipRectRec boxes[MGA_NR_SAREA_CLIPRECTS];
+
+ /* Information about the most recently used 3d drawable. The
+ * client fills in the req_* fields, the server fills in the
+ * exported_ fields and puts the cliprects into boxes, above.
+ *
+ * The client clears the exported_drawable field before
+ * clobbering the boxes data.
+ */
+ unsigned int req_drawable; /* the X drawable id */
+ unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */
+
+ unsigned int exported_drawable;
+ unsigned int exported_index;
+ unsigned int exported_stamp;
+ unsigned int exported_buffers;
+ unsigned int exported_nfront;
+ unsigned int exported_nback;
+ int exported_back_x, exported_front_x, exported_w;
+ int exported_back_y, exported_front_y, exported_h;
+ XF86DRIClipRectRec exported_boxes[MGA_NR_SAREA_CLIPRECTS];
+
+ /* Counters for aging textures and for client-side throttling.
+ */
+ unsigned int last_enqueue; /* last time a buffer was enqueued */
+ unsigned int last_dispatch; /* age of the most recently dispatched buffer */
+ unsigned int last_quiescent; /* */
+
+ /* LRU lists for texture memory in agp space and on the card */
+
+ MGATexRegionRec texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS+1];
+ unsigned int texAge[MGA_NR_TEX_HEAPS];
+ /* Mechanism to validate card state.
+ */
+ int ctxOwner;
+} MGASAREARec, *MGASAREAPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} MGAConfigPrivRec, *MGAConfigPrivPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} MGADRIContextRec, *MGADRIContextPtr;
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/Imakefile b/xc/programs/Xserver/hw/xfree86/drivers/r128/Imakefile
index e3f7178bf..8f0f33a35 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/r128/Imakefile
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/Imakefile
@@ -6,9 +6,16 @@ XCOMM
#define IHaveModules
#include <Server.tmpl>
-SRCS = r128_driver.c r128_cursor.c r128_accel.c # r128_i2c.c
+#if BuildXF86DRI
+DRISRCS = r128_dri.c
+DRIOBJS = r128_dri.o
+DRIINCLUDES = -I$(SERVERSRC)/GL/dri -I$(LIBSRC)/GL/dri
+DRIDEFINES = $(GLX_DEFINES)
+#endif
+
+SRCS = r128_driver.c r128_cursor.c r128_accel.c $(DRISRCS) # r128_i2c.c
-OBJS = r128_driver.o r128_cursor.o r128_accel.o # r128_i2c.o
+OBJS = r128_driver.o r128_cursor.o r128_accel.o $(DRIOBJS) # r128_i2c.o
#if defined(XF86DriverSDK)
INCLUDES = -I. -I../../include
@@ -22,9 +29,12 @@ INCLUDES = -I. -I$(XF86COMSRC) -I$(XF86OSSRC) \
-I$(XF86SRC)/ddc -I$(XF86SRC)/i2c -I$(XF86OSSRC)/vbe \
-I$(XF86SRC)/int10 -I$(SERVERSRC)/Xext \
-I$(FONTINCSRC) -I$(SERVERSRC)/include -I$(XINCLUDESRC) \
- -I$(EXTINCSRC) -I$(XF86SRC)/xf24_32bpp
+ -I$(EXTINCSRC) -I$(XF86SRC)/xf24_32bpp \
+ $(DRIINCLUDES)
#endif
+DEFINES = $(DRIDEFINES)
+
#if MakeHasPosixVariableSubstitutions
SubdirLibraryRule($(OBJS))
#endif
@@ -49,5 +59,10 @@ InstallDriverSDKNonExecFile(r128_cursor.c,$(DRIVERSDKDIR)/drivers/r128)
InstallDriverSDKNonExecFile(r128_driver.c,$(DRIVERSDKDIR)/drivers/r128)
InstallDriverSDKNonExecFile(r128_reg.h,$(DRIVERSDKDIR)/drivers/r128)
+InstallDriverSDKNonExecFile(r128_dri.c,$(DRIVERSDKDIR)/drivers/r128)
+InstallDriverSDKNonExecFile(r128_dri.h,$(DRIVERSDKDIR)/drivers/r128)
+InstallDriverSDKNonExecFile(r128_dripriv.h,$(DRIVERSDKDIR)/drivers/r128)
+InstallDriverSDKNonExecFile(r128_sarea.h,$(DRIVERSDKDIR)/drivers/r128)
+
InstallDriverSDKObjectModule(r128,$(DRIVERSDKMODULEDIR),drivers)
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h
index d5d120153..acb04f96e 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h
@@ -1,8 +1,8 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h,v 1.8 2000/02/23 04:47:18 martin Exp $ */
/**************************************************************************
-Copyright 1999 ATI Technologies Inc. and Precision Insight, Inc.,
- Cedar Park, Texas.
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
@@ -40,6 +40,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R128_TIMEOUT 2000000 /* Fall out of wait loops after this count */
#define R128_MMIOSIZE 0x80000
+ /* R128_NAME is used for the server-side
+ ddx driver, the client-side DRI driver,
+ and the kernel-level DRM driver. */
#define R128_NAME "r128"
#define R128_VERSION_MAJOR 3
#define R128_VERSION_MINOR 0
@@ -157,7 +160,7 @@ typedef struct {
unsigned char *FB; /* Map of frame buffer */
CARD32 MemCntl;
- CARD32 BusCntl;
+ CARD32 BusCntl;
unsigned long FbMapSize; /* Size of frame buffer, in bytes */
int Flags; /* Saved copy of mode flags */
@@ -168,6 +171,8 @@ typedef struct {
R128SaveRec ModeReg; /* Current mode */
Bool (*CloseScreen)(int, ScreenPtr);
+ Bool PaletteSavedOnVT; /* Palette saved on last VT switch */
+
I2CBusPtr i2c;
XAAInfoRecPtr accel;
xf86CursorInfoPtr cursor;
@@ -199,8 +204,98 @@ typedef struct {
int scanline_words;
int scanline_direct;
int scanline_bpp; /* Only used for ImageWrite */
+
+#ifdef XF86DRI
+ Bool directRenderingEnabled;
+ DRIInfoPtr pDRIInfo;
+ int drmFD;
+ int numVisualConfigs;
+ __GLXvisualConfig *pVisualConfigs;
+ R128ConfigPrivPtr pVisualConfigsPriv;
+
+ drmHandle fbHandle;
+
+ drmSize registerSize;
+ drmHandle registerHandle;
+
+ Bool IsPCI; /* Current card is a PCI card */
+
+ drmSize agpSize;
+ drmHandle agpMemHandle; /* Handle from drmAgpAlloc */
+ unsigned long agpOffset;
+ unsigned char *AGP; /* Map */
+ int agpMode;
+
+ Bool CCEInUse; /* CCE is currently active */
+ int CCEMode; /* CCE mode that server/clients use */
+ int CCEFifoSize; /* Size of the CCE command FIFO */
+ Bool CCESecure; /* CCE security enabled */
+ int CCEusecTimeout; /* CCE timeout in usecs */
+ Bool CCE2D; /* CCE is used for X server 2D prims */
+
+ /* CCE ring buffer data */
+ unsigned long ringStart; /* Offset into AGP space */
+ drmHandle ringHandle; /* Handle from drmAddMap */
+ drmSize ringMapSize; /* Size of map */
+ int ringSize; /* Size of ring (in MB) */
+ unsigned char *ring; /* Map */
+ int ringSizeLog2QW;
+
+ unsigned long ringReadOffset; /* Offset into AGP space */
+ drmHandle ringReadPtrHandle; /* Handle from drmAddMap */
+ drmSize ringReadMapSize; /* Size of map */
+ unsigned char *ringReadPtr; /* Map */
+
+ /* CCE vertex buffer data */
+ unsigned long vbStart; /* Offset into AGP space */
+ drmHandle vbHandle; /* Handle from drmAddMap */
+ drmSize vbMapSize; /* Size of map */
+ int vbSize; /* Size of vert bufs (in MB) */
+ unsigned char *vb; /* Map */
+ int vbBufSize; /* Size of individual vert buf */
+ int vbNumBufs; /* Number of vert bufs */
+ drmBufMapPtr vbBufs; /* Buffer map */
+
+ /* CCE indirect buffer data */
+ unsigned long indStart; /* Offset into AGP space */
+ drmHandle indHandle; /* Handle from drmAddMap */
+ drmSize indMapSize; /* Size of map */
+ int indSize; /* Size of indirect bufs (in MB) */
+ unsigned char *ind; /* Map */
+
+ /* CCE AGP Texture data */
+ unsigned long agpTexStart; /* Offset into AGP space */
+ drmHandle agpTexHandle; /* Handle from drmAddMap */
+ drmSize agpTexMapSize; /* Size of map */
+ int agpTexSize; /* Size of AGP tex space (in MB) */
+ unsigned char *agpTex; /* Map */
+ int log2AGPTexGran;
+
+ /* DRI screen private data */
+ int fbX;
+ int fbY;
+ int backX;
+ int backY;
+ int depthX;
+ int depthY;
+ int textureX;
+ int textureY;
+ int textureSize;
+ int log2TexGran;
+#endif
} R128InfoRec, *R128InfoPtr;
+#define R128WaitForFifo(pScrn, entries) \
+do { \
+ if (info->fifo_slots < entries) R128WaitForFifoFunction(pScrn, entries); \
+ info->fifo_slots -= entries; \
+} while (0)
+
+extern void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries);
+extern void R128WaitForIdle(ScrnInfoPtr pScrn);
+extern void R128EngineReset(ScrnInfoPtr pScrn);
+extern void R128EngineFlush(ScrnInfoPtr pScrn);
+
extern int INPLL(ScrnInfoPtr pScrn, int addr);
extern void R128WaitForVerticalSync(ScrnInfoPtr pScrn);
@@ -208,4 +303,16 @@ extern Bool R128AccelInit(ScreenPtr pScreen);
extern void R128EngineInit(ScrnInfoPtr pScrn);
extern Bool R128CursorInit(ScreenPtr pScreen);
+extern int R128MinBits(int val);
+
+#ifdef XF86DRI
+extern Bool R128DRIScreenInit(ScreenPtr pScreen);
+extern void R128DRICloseScreen(ScreenPtr pScreen);
+extern Bool R128DRIFinishScreenInit(ScreenPtr pScreen);
+extern void R128CCEStart(ScrnInfoPtr pScrn);
+extern void R128CCEStop(ScrnInfoPtr pScrn);
+extern void R128CCEResetRing(ScrnInfoPtr pScrn);
+extern void R128CCEWaitForIdle(ScrnInfoPtr pScrn);
+#endif
+
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c
index 5b0223661..f42569767 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c
@@ -1,8 +1,8 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c,v 1.7 2000/02/23 04:47:18 martin Exp $ */
/**************************************************************************
-Copyright 1999 ATI Technologies Inc. and Precision Insight, Inc.,
- Cedar Park, Texas.
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
@@ -95,6 +95,19 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* DDC support */
#include "xf86DDC.h"
+ /* DRI support */
+#ifdef XF86DRI
+#include "GL/glxint.h"
+#include "xf86drm.h"
+#include "sarea.h"
+#define _XF86DRI_SERVER_
+#include "xf86dri.h"
+#include "dri.h"
+#include "r128_dri.h"
+#include "r128_dripriv.h"
+#include "r128_sarea.h"
+#endif
+
/* Driver data structures */
#include "r128.h"
#include "r128_reg.h"
@@ -122,7 +135,7 @@ static struct {
};
/* Flush all dirty data in the Pixel Cache to memory. */
-static void R128EngineFlush(ScrnInfoPtr pScrn)
+void R128EngineFlush(ScrnInfoPtr pScrn)
{
int i;
R128MMIO_VARS();
@@ -134,11 +147,12 @@ static void R128EngineFlush(ScrnInfoPtr pScrn)
}
/* Reset graphics card to known state. */
-static void R128EngineReset(ScrnInfoPtr pScrn)
+void R128EngineReset(ScrnInfoPtr pScrn)
{
- CARD32 clock_cntl_index;
- CARD32 mclk_cntl;
- CARD32 gen_reset_cntl;
+ R128InfoPtr info = R128PTR(pScrn);
+ CARD32 clock_cntl_index;
+ CARD32 mclk_cntl;
+ CARD32 gen_reset_cntl;
R128MMIO_VARS();
R128EngineFlush(pScrn);
@@ -158,17 +172,15 @@ static void R128EngineReset(ScrnInfoPtr pScrn)
OUTPLL(R128_MCLK_CNTL, mclk_cntl);
OUTREG(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl);
-}
-#define R128WaitForFifo(pScrn, entries) \
-do { \
- if (info->fifo_slots < entries) R128WaitForFifoFunction(pScrn, entries); \
- info->fifo_slots -= entries; \
-} while (0)
+#ifdef XF86DRI
+ if (R128CCE_USE_RING_BUFFER(info->CCEMode)) R128CCEResetRing(pScrn);
+#endif
+}
/* The FIFO has 64 slots. This routines waits until at least `entries' of
these slots are empty. */
-static void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries)
+void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries)
{
R128InfoPtr info = R128PTR(pScrn);
int i;
@@ -186,15 +198,19 @@ static void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries)
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"FIFO timed out, resetting engine...\n");
R128EngineReset(pScrn);
+#if XF86DRI
+ if (info->CCE2D) R128CCEStart(pScrn);
+#endif
}
}
/* Wait for the graphics engine to be completely idle: the FIFO has
drained, the Pixel Cache is flushed, and the engine is idle. This is a
standard "sync" function that will make the hardware "quiescent". */
-static void R128WaitForIdle(ScrnInfoPtr pScrn)
+void R128WaitForIdle(ScrnInfoPtr pScrn)
{
- int i;
+ R128InfoPtr info = R128PTR(pScrn);
+ int i;
R128MMIO_VARS();
R128WaitForFifoFunction(pScrn, 64);
@@ -213,6 +229,9 @@ static void R128WaitForIdle(ScrnInfoPtr pScrn)
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Idle timed out, resetting engine...\n");
R128EngineReset(pScrn);
+#if XF86DRI
+ if (info->CCE2D) R128CCEStart(pScrn);
+#endif
}
}
@@ -966,19 +985,33 @@ void R128EngineInit(ScrnInfoPtr pScrn)
OUTREG(R128_DP_SRC_BKGD_CLR, 0x00000000);
OUTREG(R128_DP_WRITE_MASK, 0xffffffff);
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ OUTREGP(R128_DP_DATATYPE,
+ R128_HOST_BIG_ENDIAN_EN, ~R128_HOST_BIG_ENDIAN_EN);
+#else
+ OUTREGP(R128_DP_DATATYPE, 0, ~R128_HOST_BIG_ENDIAN_EN);
+#endif
+
R128WaitForIdle(pScrn);
}
-/* Initialize XAA for supported acceleration and also initialize the
- graphics hardware for acceleration. */
-Bool R128AccelInit(ScreenPtr pScreen)
+#ifdef XF86DRI
+ /* FIXME: When direct rendering is enabled, we should use the CCE to
+ draw 2D commands */
+static void R128CCEAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a)
{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- R128InfoPtr info = R128PTR(pScrn);
- XAAInfoRecPtr a;
+ a->Flags = 0;
+
+ /* Sync */
+ a->Sync = R128CCEWaitForIdle;
+
+}
+#endif
+
+static void R128MMIOAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a)
+{
+ R128InfoPtr info = R128PTR(pScrn);
- if (!(a = info->accel = XAACreateInfoRec())) return FALSE;
-
a->Flags = (PIXMAP_CACHE
| OFFSCREEN_PIXMAPS
| LINEAR_FRAMEBUFFER);
@@ -1065,7 +1098,26 @@ Bool R128AccelInit(ScreenPtr pScreen)
| SCANLINE_PAD_DWORD
| SYNC_AFTER_IMAGE_WRITE);
#endif
-
+}
+
+/* Initialize XAA for supported acceleration and also initialize the
+ graphics hardware for acceleration. */
+Bool R128AccelInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ XAAInfoRecPtr a;
+
+ if (!(a = info->accel = XAACreateInfoRec())) return FALSE;
+
+#ifdef XF86DRI
+ /* FIXME: When direct rendering is enabled, we should use the CCE to
+ draw 2D commands */
+ if (info->CCE2D) R128CCEAccelInit(pScrn, a);
+ else
+#endif
+ R128MMIOAccelInit(pScrn, a);
+
R128EngineInit(pScrn);
return XAAInit(pScreen, a);
}
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c
index a96872702..2667443d9 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c
@@ -1,8 +1,8 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c,v 1.6 2000/03/06 22:59:26 dawes Exp $ */
/**************************************************************************
-Copyright 1999 ATI Technologies Inc. and Precision Insight, Inc.,
- Cedar Park, Texas.
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
@@ -60,6 +60,19 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* DDC support */
#include "xf86DDC.h"
+ /* DRI support */
+#ifdef XF86DRI
+#include "GL/glxint.h"
+#include "xf86drm.h"
+#include "sarea.h"
+#define _XF86DRI_SERVER_
+#include "xf86dri.h"
+#include "dri.h"
+#include "r128_dri.h"
+#include "r128_dripriv.h"
+#include "r128_sarea.h"
+#endif
+
/* Driver data structures */
#include "r128.h"
#include "r128_reg.h"
@@ -92,16 +105,19 @@ static void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
(xorigin,yorigin). */
static void R128SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
- R128InfoPtr info = R128PTR(pScrn);
- int xorigin = 0;
- int yorigin = 0;
- int total_y = pScrn->frameY1 - pScrn->frameY0;
+ R128InfoPtr info = R128PTR(pScrn);
+ xf86CursorInfoPtr cursor = info->cursor;
+ int xorigin = 0;
+ int yorigin = 0;
+ int total_y = pScrn->frameY1 - pScrn->frameY0;
R128MMIO_VARS();
- if (x < 0) xorigin = -x;
- if (y < 0) yorigin = -y;
- if (y > total_y) y = total_y;
- if (info->Flags & V_DBLSCAN) y *= 2;
+ if (x < 0) xorigin = -x;
+ if (y < 0) yorigin = -y;
+ if (y > total_y) y = total_y;
+ if (info->Flags & V_DBLSCAN) y *= 2;
+ if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1;
+ if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1;
OUTREG(R128_CUR_HORZ_VERT_OFF, R128_CUR_LOCK | (xorigin << 16) | yorigin);
OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK
@@ -126,47 +142,58 @@ static void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
#if X_BYTE_ORDER == X_BIG_ENDIAN
switch(info->pixel_bytes) {
- case 4:
- case 3:
- for (y = 0; y < 64; y++) {
- P_SWAP32(d,s);
- d++; s++;
- P_SWAP32(d,s);
- d++; s++;
- P_SWAP32(d,s);
- d++; s++;
- P_SWAP32(d,s);
- d++; s++;
- }
- break;
- case 2:
- for (y = 0; y < 64; y++) {
- P_SWAP16(d,s);
- d++; s++;
- P_SWAP16(d,s);
- d++; s++;
- P_SWAP16(d,s);
- d++; s++;
- P_SWAP16(d,s);
- d++; s++;
- }
- break;
- default:
- for (y = 0; y < 64; y++) {
+ case 4:
+ case 3:
+ for (y = 0; y < 64; y++) {
+ P_SWAP32(d,s);
+ d++; s++;
+ P_SWAP32(d,s);
+ d++; s++;
+ P_SWAP32(d,s);
+ d++; s++;
+ P_SWAP32(d,s);
+ d++; s++;
+ }
+ break;
+ case 2:
+ for (y = 0; y < 64; y++) {
+ P_SWAP16(d,s);
+ d++; s++;
+ P_SWAP16(d,s);
+ d++; s++;
+ P_SWAP16(d,s);
+ d++; s++;
+ P_SWAP16(d,s);
+ d++; s++;
+ }
+ break;
+ default:
+ for (y = 0; y < 64; y++) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
- }
+ }
}
#else
- for (y = 0; y < 64; y++) {
+ for (y = 0; y < 64; y++) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
#endif
+
+ /* Set the area after the cursor to be all transparent so that we
+ won't display corrupted cursors on the screen */
+ for (y = 0; y < 64; y++) {
+ *d++ = 0xffffffff; /* The AND bits */
+ *d++ = 0xffffffff;
+ *d++ = 0x00000000; /* The XOR bits */
+ *d++ = 0x00000000;
+ }
+
+
OUTREG(R128_CRTC_GEN_CNTL, save);
}
@@ -204,6 +231,7 @@ Bool R128CursorInit(ScreenPtr pScreen)
FBAreaPtr fbarea;
int width;
int height;
+ int size;
if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE;
@@ -227,8 +255,9 @@ Bool R128CursorInit(ScreenPtr pScreen)
cursor->ShowCursor = R128ShowCursor;
cursor->UseHWCursor = R128UseHWCursor;
+ size = (cursor->MaxWidth/4) * cursor->MaxHeight;
width = pScrn->displayWidth;
- height = (1024 + 1023) / pScrn->displayWidth;
+ height = (size*2 + 1023) / pScrn->displayWidth;
fbarea = xf86AllocateOffscreenArea(pScreen,
width,
height,
@@ -246,7 +275,7 @@ Bool R128CursorInit(ScreenPtr pScreen)
info->cursor_start = R128_ALIGN((fbarea->box.x1
+ width * fbarea->box.y1)
* info->pixel_bytes, 16);
- info->cursor_end = info->cursor_start + 1024;
+ info->cursor_end = info->cursor_start + size;
}
R128TRACE(("R128CursorInit (0x%08x-0x%08x)\n",
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c
new file mode 100644
index 000000000..cb647d6b6
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c
@@ -0,0 +1,1242 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+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
+on 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
+ATI, PRECISION INSIGHT AND/OR THEIR 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:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ * Rickard E. Faith <faith@precisioninsight.com>
+ * Daryll Strauss <daryll@precisioninsight.com>
+ *
+ */
+
+
+ /* X and server generic header files */
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86RAC.h"
+#include "xf86cmap.h"
+#include "xf86fbman.h"
+
+ /* Backing store, software cursor, and
+ colormap initialization */
+#include "mibstore.h"
+#include "mipointer.h"
+#include "micmap.h"
+
+ /* CFB support */
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb16.h"
+#include "cfb24.h"
+#include "cfb32.h"
+#include "cfb24_32.h"
+
+ /* XAA and Cursor Support */
+#include "xaa.h"
+#include "xf86Cursor.h"
+
+ /* PCI support */
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+
+ /* DDC support */
+#include "xf86DDC.h"
+
+ /* DRI support */
+#include "GL/glxint.h"
+#include "GL/glxtokens.h"
+#include "xf86drm.h"
+#include "xf86drmR128.h"
+#include "sarea.h"
+#define _XF86DRI_SERVER_
+#include "xf86dri.h"
+#include "dri.h"
+#include "r128_dri.h"
+#include "r128_sarea.h"
+#include "r128_dripriv.h"
+
+ /* Driver data structures */
+#include "r128.h"
+#include "r128_reg.h"
+
+#define R128_WATERMARK_L 16
+#define R128_WATERMARK_M 8
+#define R128_WATERMARK_N 8
+#define R128_WATERMARK_K 128
+
+static int CCEFifoSlots = 0;
+
+#define R128CCEWaitForFifo(pScrn, entries) \
+do { \
+ if (CCEFifoSlots < entries) R128WaitForFifoFunction(pScrn, entries); \
+ CCEFifoSlots -= entries; \
+} while (0)
+
+/* Wait for at least `entries' slots are free. The actual number of
+ slots available is stored in info->CCEFifoSize. */
+static void R128CCEWaitForFifoFunction(ScrnInfoPtr pScrn, int entries)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int i;
+
+ for (;;) {
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ CCEFifoSlots = INREG(R128_PM4_STAT) & R128_PM4_FIFOCNT_MASK;
+ if (CCEFifoSlots >= entries) return;
+ }
+ R128EngineReset(pScrn);
+ if (info->CCE2D) R128CCEStart(pScrn);
+ }
+}
+
+/* Wait until the CCE is completely idle: the FIFO has drained and the
+ CCE is idle. */
+void R128CCEWaitForIdle(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int i;
+
+ if (!info->CCEInUse || info->CCEMode == R128_PM4_NONPM4) return;
+
+ if (R128CCE_USE_RING_BUFFER(info->CCEMode)) {
+ volatile CARD32 *r128RingReadPtr =
+ (volatile CARD32 *)(info->ringReadPtr);
+ R128SAREAPrivPtr pSAREAPriv;
+
+ OUTREGP(R128_PM4_BUFFER_DL_WPTR,
+ R128_PM4_BUFFER_DL_DONE, ~R128_PM4_BUFFER_DL_DONE);
+
+ pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScrn->pScreen);
+
+ for (;;) {
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ if (*r128RingReadPtr == pSAREAPriv->ringWrite) {
+ int pm4stat = INREG(R128_PM4_STAT);
+ if ((pm4stat & R128_PM4_FIFOCNT_MASK) >= info->CCEFifoSize
+ && !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE)))
+ return;
+ }
+ }
+ R128EngineReset(pScrn);
+ if (info->CCE2D) R128CCEStart(pScrn);
+ }
+ } else {
+ R128CCEWaitForFifoFunction(pScrn, info->CCEFifoSize);
+
+ for (;;) {
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ if (!(INREG(R128_PM4_STAT)
+ & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) {
+ R128EngineFlush(pScrn);
+ return;
+ }
+ }
+ R128EngineReset(pScrn);
+ if (info->CCE2D) R128CCEStart(pScrn);
+ }
+ }
+}
+
+/* Reset the ring buffer status, if the engine was reset */
+void R128CCEResetRing(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ R128SAREAPrivPtr pSAREAPriv;
+ volatile CARD32 *r128RingReadPtr;
+
+ if (!info->CCEInUse || info->CCEMode == R128_PM4_NONPM4) return;
+
+ r128RingReadPtr = (volatile CARD32 *)(info->ringReadPtr);
+ pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScrn->pScreen);
+
+ OUTREG(R128_PM4_BUFFER_DL_WPTR, 0);
+ OUTREG(R128_PM4_BUFFER_DL_RPTR, 0);
+ pSAREAPriv->ringWrite = 0;
+ *r128RingReadPtr = 0;
+
+ /* Resetting the ring turns off the CCE */
+ info->CCEInUse = FALSE;
+}
+
+/* Start the CCE, but only if it is not already in use and the requested
+ mode is a CCE mode. The mode is stored in info->CCEMode. */
+void R128CCEStart(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ if (info->CCEInUse || info->CCEMode == R128_PM4_NONPM4) return;
+
+ R128WaitForIdle(pScrn);
+ OUTREG(R128_PM4_BUFFER_CNTL, info->CCEMode | info->ringSizeLog2QW);
+ (void)INREG(R128_PM4_BUFFER_ADDR); /* as per the sample code */
+ OUTREG(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
+ info->CCEInUse = TRUE;
+}
+
+/* Stop the CCE, but only if it is in use and the requested mode is not
+ the non-CCE mode. This function also flushes any outstanding
+ requests before switching modes.*/
+void R128CCEStop(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ if (!info->CCEInUse || info->CCEMode == R128_PM4_NONPM4) return;
+
+ R128CCEWaitForIdle(pScrn);
+ OUTREG(R128_PM4_MICRO_CNTL, 0);
+ OUTREG(R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4);
+ R128EngineReset(pScrn);
+ info->CCEInUse = FALSE;
+}
+
+/* Initialize the visual configs that are supported by the hardware.
+ These are combined with the visual configs that the indirect
+ rendering core supports, and the intersection is exported to the
+ client. */
+static Bool R128InitVisualConfigs(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr pR128 = R128PTR(pScrn);
+ int numConfigs = 0;
+ __GLXvisualConfig *pConfigs = 0;
+ R128ConfigPrivPtr pR128Configs = 0;
+ R128ConfigPrivPtr *pR128ConfigPtrs = 0;
+ int i, accum, stencil;
+
+ switch (pR128->pixel_code) {
+ case 8: /* 8bpp mode is not support */
+ case 15: /* FIXME */
+ case 24: /* FIXME */
+ return FALSE;
+
+#define R128_USE_ACCUM 1
+#define R128_USE_STENCIL 0 /* Only in 24 depth mode */
+
+ case 16:
+ numConfigs = 1;
+ if (R128_USE_ACCUM) numConfigs *= 2;
+
+ if (!(pConfigs
+ = (__GLXvisualConfig*)xnfcalloc(sizeof(__GLXvisualConfig),
+ numConfigs))) {
+ return FALSE;
+ }
+ if (!(pR128Configs
+ = (R128ConfigPrivPtr)xnfcalloc(sizeof(R128ConfigPrivRec),
+ numConfigs))) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+ if (!(pR128ConfigPtrs
+ = (R128ConfigPrivPtr*)xnfcalloc(sizeof(R128ConfigPrivPtr),
+ numConfigs))) {
+ xfree(pConfigs);
+ xfree(pR128Configs);
+ return FALSE;
+ }
+
+ i = 0;
+ for (accum = 0; accum <= R128_USE_ACCUM; accum++) {
+ pR128ConfigPtrs[i] = &pR128Configs[i];
+
+ pConfigs[i].vid = -1;
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 5;
+ pConfigs[i].greenSize = 6;
+ pConfigs[i].blueSize = 5;
+ pConfigs[i].redMask = 0x0000F800;
+ pConfigs[i].greenMask = 0x000007E0;
+ pConfigs[i].blueMask = 0x0000001F;
+
+ pConfigs[i].alphaMask = 0;
+ if (accum) { /* Simulated in software */
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ pConfigs[i].doubleBuffer = TRUE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 16;
+ pConfigs[i].depthSize = 16;
+ pConfigs[i].stencilSize = 0;
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (accum)
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ else
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ pConfigs[i].transparentPixel = 0;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ break;
+ case 32:
+ numConfigs = 1;
+ if (R128_USE_ACCUM) numConfigs *= 2;
+ if (R128_USE_STENCIL) numConfigs *= 2;
+
+ if (!(pConfigs
+ = (__GLXvisualConfig*)xnfcalloc(sizeof(__GLXvisualConfig),
+ numConfigs))) {
+ return FALSE;
+ }
+ if (!(pR128Configs
+ = (R128ConfigPrivPtr)xnfcalloc(sizeof(R128ConfigPrivRec),
+ numConfigs))) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+ if (!(pR128ConfigPtrs
+ = (R128ConfigPrivPtr*)xnfcalloc(sizeof(R128ConfigPrivPtr),
+ numConfigs))) {
+ xfree(pConfigs);
+ xfree(pR128Configs);
+ return FALSE;
+ }
+
+ i = 0;
+ for (accum = 0; accum <= R128_USE_ACCUM; accum++) {
+ for (stencil = 0; stencil <= R128_USE_STENCIL; stencil++) {
+ pR128ConfigPtrs[i] = &pR128Configs[i];
+
+ pConfigs[i].vid = -1;
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 8;
+ pConfigs[i].greenSize = 8;
+ pConfigs[i].blueSize = 8;
+ pConfigs[i].redMask = 0x00FF0000;
+ pConfigs[i].greenMask = 0x0000FF00;
+ pConfigs[i].blueMask = 0x000000FF;
+
+ pConfigs[i].alphaMask = 0;
+ if (accum) { /* Simulated in software */
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ pConfigs[i].doubleBuffer = TRUE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 24;
+ if (stencil) {
+ pConfigs[i].depthSize = 24;
+ pConfigs[i].stencilSize = 8;
+ } else {
+ pConfigs[i].depthSize = 32;
+ pConfigs[i].stencilSize = 0;
+ }
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (accum)
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ else
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ pConfigs[i].transparentPixel = 0;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ break;
+ }
+
+ pR128->numVisualConfigs = numConfigs;
+ pR128->pVisualConfigs = pConfigs;
+ pR128->pVisualConfigsPriv = pR128Configs;
+ GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pR128ConfigPtrs);
+ return TRUE;
+}
+
+/* Create the Rage 128-specific context information */
+static Bool R128CreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drmContext hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore)
+{
+ /* Nothing yet */
+ return TRUE;
+}
+
+/* Destroy the Rage 128-specific context information */
+static void R128DestroyContext(ScreenPtr pScreen, drmContext hwContext,
+ DRIContextType contextStore)
+{
+ /* Nothing yet */
+}
+
+/* Called when the X server is woken up to allow the last client's
+ context to be saved and the X server's context to be loaded. This is
+ not necessary for the Rage 128 since the client detects when it's
+ context is not currently loaded and then load's it itself. Since the
+ registers to start and stop the CCE are privileged, only the X server
+ can start/stop the engine. */
+static void R128EnterServer(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr pR128 = R128PTR(pScrn);
+
+ if (pR128->accel) pR128->accel->NeedToSync = TRUE;
+
+#if 1
+ if (!pR128->CCE2D) R128CCEStop(pScrn);
+#else
+ if (pR128->CCE2D) R128CCEWaitForIdle(pScrn);
+ else R128CCEStop(pScrn);
+#endif
+}
+
+/* Called when the X server goes to sleep to allow the X server's
+ context to be saved and the last client's context to be loaded. This
+ is not necessary for the Rage 128 since the client detects when it's
+ context is not currently loaded and then load's it itself. Since the
+ registers to start and stop the CCE are privileged, only the X server
+ can start/stop the engine. */
+static void R128LeaveServer(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr pR128 = R128PTR(pScrn);
+
+#if 1
+ if (!pR128->CCE2D) R128CCEStart(pScrn);
+#else
+ if (pR128->CCE2D) R128CCEWaitForIdle(pScrn);
+ else R128CCEStart(pScrn);
+#endif
+}
+
+/* Contexts can be swapped by the X server if necessary. This callback
+ is currently only used to perform any functions necessary when
+ entering or leaving the X server, and in the future might not be
+ necessary. */
+static void R128DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType oldContextType, void *oldContext,
+ DRIContextType newContextType, void *newContext)
+{
+ if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) &&
+ (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */
+ R128EnterServer(pScreen);
+ }
+ if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) &&
+ (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */
+ R128LeaveServer(pScreen);
+ }
+}
+
+/* Initialize the state of the back and depth buffers. */
+static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
+{
+ /* FIXME: This routine needs to have acceleration turned on */
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr pR128 = R128PTR(pScrn);
+ BoxPtr pbox;
+ int nbox;
+ int depth;
+
+ /* FIXME: Use accel when CCE 2D code is written */
+ if (pR128->CCE2D) return;
+
+ /* FIXME: This should be based on the __GLXvisualConfig info */
+ switch (pScrn->bitsPerPixel) {
+ case 8: depth = 0x000000ff; break;
+ case 16: depth = 0x0000ffff; break;
+ case 24: depth = 0x00ffffff; break;
+ case 32: depth = 0xffffffff; break;
+ default: depth = 0x00000000; break;
+ }
+
+ /* FIXME: Copy XAAPaintWindow() and use REGION_TRANSLATE() */
+ /* FIXME: Only initialize the back and depth buffers for contexts
+ that request them */
+
+ pbox = REGION_RECTS(prgn);
+ nbox = REGION_NUM_RECTS(prgn);
+
+ (*pR128->accel->SetupForSolidFill)(pScrn, 0, GXcopy, -1);
+ for (; nbox; nbox--, pbox++) {
+ (*pR128->accel->SubsequentSolidFillRect)(pScrn,
+ pbox->x1 + pR128->fbX,
+ pbox->y1 + pR128->fbY,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ (*pR128->accel->SubsequentSolidFillRect)(pScrn,
+ pbox->x1 + pR128->backX,
+ pbox->y1 + pR128->backY,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ }
+
+ (*pR128->accel->SetupForSolidFill)(pScrn, depth, GXcopy, -1);
+ for (; nbox; nbox--, pbox++)
+ (*pR128->accel->SubsequentSolidFillRect)(pScrn,
+ pbox->x1 + pR128->depthX,
+ pbox->y1 + pR128->depthY,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+
+ pR128->accel->NeedToSync = TRUE;
+}
+
+/* Copy the back and depth buffers when the X server moves a window. */
+static void R128DRIMoveBuffers(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 index)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr pR128 = R128PTR(pScrn);
+
+ /* FIXME: This routine needs to have acceleration turned on */
+ /* FIXME: Copy XAACopyWindow() and use REGION_TRANSLATE() */
+ /* FIXME: Only initialize the back and depth buffers for contexts
+ that request them */
+
+ /* FIXME: Use accel when CCE 2D code is written */
+ if (pR128->CCE2D) return;
+}
+
+/* Initialize the AGP state. Request memory for use in AGP space, and
+ initialize the Rage 128 registers to point to that memory. */
+static Bool R128DRIAgpInit(R128InfoPtr pR128, ScreenPtr pScreen)
+{
+ unsigned char *R128MMIO = pR128->MMIO;
+ unsigned long mode;
+ unsigned int vendor, device;
+ int ret;
+ unsigned long cntl;
+ int s, l;
+ int flags;
+
+ if (drmAgpAcquire(pR128->drmFD) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not available\n");
+ return FALSE;
+ }
+
+ /* Modify the mode if the default mode is
+ not appropriate for this particular
+ combination of graphics card and AGP
+ chipset. */
+
+ mode = drmAgpGetMode(pR128->drmFD); /* Default mode */
+ vendor = drmAgpVendorId(pR128->drmFD);
+ device = drmAgpDeviceId(pR128->drmFD);
+
+ mode &= ~R128_AGP_MODE_MASK;
+ switch (pR128->agpMode) {
+ case 2: mode |= R128_AGP_2X_MODE;
+ case 1: default: mode |= R128_AGP_1X_MODE;
+ }
+
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
+ mode, vendor, device,
+ pR128->PciInfo->vendor,
+ pR128->PciInfo->chipType);
+
+ if (drmAgpEnable(pR128->drmFD, mode) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n");
+ drmAgpRelease(pR128->drmFD);
+ return FALSE;
+ }
+
+ pR128->agpOffset = 0;
+
+ if ((ret = drmAgpAlloc(pR128->drmFD, pR128->agpSize*1024*1024, 0, NULL,
+ &pR128->agpMemHandle)) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret);
+ drmAgpRelease(pR128->drmFD);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] %d kB allocated with handle 0x%08x\n",
+ pR128->agpSize*1024, pR128->agpMemHandle);
+
+ if (drmAgpBind(pR128->drmFD, pR128->agpMemHandle, pR128->agpOffset) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n");
+ drmAgpFree(pR128->drmFD, pR128->agpMemHandle);
+ drmAgpRelease(pR128->drmFD);
+ return FALSE;
+ }
+
+ /* Initialize the CCE ring buffer data */
+ pR128->ringStart = pR128->agpOffset;
+ pR128->ringMapSize = pR128->ringSize*1024*1024 + 4096;
+ pR128->ringSizeLog2QW = R128MinBits(pR128->ringSize*1024*1024/8) - 1;
+
+ pR128->ringReadOffset = pR128->ringStart + pR128->ringMapSize;
+ pR128->ringReadMapSize = 4096;
+
+ /* Reserve space for the vertex buffer */
+ pR128->vbStart = pR128->ringReadOffset + pR128->ringReadMapSize;
+ pR128->vbMapSize = pR128->vbSize*1024*1024;
+
+ /* Reserve space for the indirect buffer */
+ pR128->indStart = pR128->vbStart + pR128->vbMapSize;
+ pR128->indMapSize = pR128->indSize*1024*1024;
+
+ /* Reserve the rest for AGP textures */
+ pR128->agpTexStart = pR128->indStart + pR128->indMapSize;
+ s = (pR128->agpSize*1024*1024 - pR128->agpTexStart);
+ l = R128MinBits((s-1) / R128_NR_TEX_REGIONS);
+ if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
+ pR128->agpTexMapSize = (s >> l) << l;
+ pR128->log2AGPTexGran = l;
+
+ if (pR128->CCESecure) flags = DRM_READ_ONLY;
+ else flags = 0;
+
+ if (drmAddMap(pR128->drmFD, pR128->ringStart, pR128->ringMapSize,
+ DRM_AGP, flags, &pR128->ringHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add ring mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] ring handle = 0x%08lx\n", pR128->ringHandle);
+
+ if (drmMap(pR128->drmFD, pR128->ringHandle, pR128->ringMapSize,
+ (drmAddressPtr)&pR128->ring) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Ring mapped at 0x%08lx\n",
+ (unsigned long)pR128->ring);
+
+ if (drmAddMap(pR128->drmFD, pR128->ringReadOffset, pR128->ringReadMapSize,
+ DRM_AGP, flags, &pR128->ringReadPtrHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add ring read ptr mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] ring read ptr handle = 0x%08lx\n",
+ pR128->ringReadPtrHandle);
+
+ if (drmMap(pR128->drmFD, pR128->ringReadPtrHandle, pR128->ringReadMapSize,
+ (drmAddressPtr)&pR128->ringReadPtr) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map ring read ptr\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Ring read ptr mapped at 0x%08lx\n",
+ (unsigned long)pR128->ringReadPtr);
+
+ if (drmAddMap(pR128->drmFD, pR128->vbStart, pR128->vbMapSize,
+ DRM_AGP, 0, &pR128->vbHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add vertex buffers mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] vertex buffers handle = 0x%08lx\n", pR128->vbHandle);
+
+ if (drmMap(pR128->drmFD, pR128->vbHandle, pR128->vbMapSize,
+ (drmAddressPtr)&pR128->vb) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map vertex buffers\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Vertex buffers mapped at 0x%08lx\n",
+ (unsigned long)pR128->vb);
+
+ if (drmAddMap(pR128->drmFD, pR128->indStart, pR128->indMapSize,
+ DRM_AGP, flags, &pR128->indHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add indirect buffers mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] indirect buffers handle = 0x%08lx\n", pR128->indHandle);
+
+ if (drmMap(pR128->drmFD, pR128->indHandle, pR128->indMapSize,
+ (drmAddressPtr)&pR128->ind) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map indirect buffers\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Indirect buffers mapped at 0x%08lx\n",
+ (unsigned long)pR128->ind);
+
+ if (drmAddMap(pR128->drmFD, pR128->agpTexStart, pR128->agpTexMapSize,
+ DRM_AGP, 0, &pR128->agpTexHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add AGP texture map mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] AGP texture map handle = 0x%08lx\n",
+ pR128->agpTexHandle);
+
+ if (drmMap(pR128->drmFD, pR128->agpTexHandle, pR128->agpTexMapSize,
+ (drmAddressPtr)&pR128->agpTex) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map AGP texture map\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] AGP Texture map mapped at 0x%08lx\n",
+ (unsigned long)pR128->agpTex);
+
+ /* Initialize Rage 128's AGP registers */
+ cntl = INREG(R128_AGP_CNTL);
+ cntl &= ~R128_AGP_APER_SIZE_MASK;
+ switch (pR128->agpSize) {
+ case 256: cntl |= R128_AGP_APER_SIZE_256MB; break;
+ case 128: cntl |= R128_AGP_APER_SIZE_128MB; break;
+ case 64: cntl |= R128_AGP_APER_SIZE_64MB; break;
+ case 32: cntl |= R128_AGP_APER_SIZE_32MB; break;
+ case 16: cntl |= R128_AGP_APER_SIZE_16MB; break;
+ case 8: cntl |= R128_AGP_APER_SIZE_8MB; break;
+ case 4: cntl |= R128_AGP_APER_SIZE_4MB; break;
+ default:
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Illegal aperture size %d kB\n",
+ pR128->agpSize*1024);
+ return FALSE;
+ }
+ OUTREG(R128_AGP_BASE, pR128->ringHandle); /* Ring buf is at AGP offset 0 */
+ OUTREG(R128_AGP_CNTL, cntl);
+
+ return TRUE;
+}
+
+/* Add a map for the MMIO registers that will be accessed by any
+ DRI-based clients. */
+static Bool R128DRIMapInit(R128InfoPtr pR128, ScreenPtr pScreen)
+{
+ int flags;
+
+ if (pR128->CCESecure) flags = DRM_READ_ONLY;
+ else flags = 0;
+
+ /* Map registers */
+ pR128->registerSize = R128_MMIOSIZE;
+ if (drmAddMap(pR128->drmFD, pR128->MMIOAddr, pR128->registerSize,
+ DRM_REGISTERS, flags, &pR128->registerHandle) < 0) {
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] register handle = 0x%08lx\n", pR128->registerHandle);
+
+ return TRUE;
+}
+
+/* Initialize the ring buffer state for use in the X server and any
+ DRI-based clients. */
+static void R128DRICCEInitRingBuffer(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ unsigned long addr;
+
+ /* FIXME: When we use the CCE for the X server, we should move this
+ function (and the support functions above) to r128_accel.c */
+
+ /* The manual (p. 2) says this address is
+ in "VM space". This means it's an
+ offset from the start of AGP space. */
+ OUTREG(R128_PM4_BUFFER_OFFSET, info->ringStart | 0x02000000);
+
+ OUTREG(R128_PM4_BUFFER_DL_WPTR, 0);
+ OUTREG(R128_PM4_BUFFER_DL_RPTR, 0);
+
+ /* DL_RPTR_ADDR is a physical address.
+ This should be in the SAREA. */
+ *(volatile long unsigned *)(info->ringReadPtr) = 0;
+ OUTREG(R128_PM4_BUFFER_DL_RPTR_ADDR, (info->ringReadPtrHandle));
+
+ /* Set watermark control */
+ OUTREG(R128_PM4_BUFFER_WM_CNTL,
+ ((R128_WATERMARK_L/4) << R128_WMA_SHIFT)
+ | ((R128_WATERMARK_M/4) << R128_WMB_SHIFT)
+ | ((R128_WATERMARK_N/4) << R128_WMC_SHIFT)
+ | ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT));
+
+ addr = INREG(R128_PM4_BUFFER_ADDR); /* Force read. Why? Because it's
+ in the examples... */
+
+#if 0
+ R128CCEWaitForIdle(pScrn);
+#endif
+
+ /* Turn on bus mastering */
+ info->BusCntl &= ~R128_BUS_MASTER_DIS;
+ OUTREGP(R128_BUS_CNTL, 0, ~R128_BUS_MASTER_DIS);
+}
+
+/* Initialize the kernel data structures. */
+static int R128DRIKernelInit(R128InfoPtr pR128, ScreenPtr pScreen)
+{
+ drmR128Init drmInfo;
+
+ drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec);
+ drmInfo.is_pci = pR128->IsPCI;
+ drmInfo.cce_mode = pR128->CCEMode;
+ drmInfo.cce_fifo_size = pR128->CCEFifoSize;
+ drmInfo.cce_secure = pR128->CCESecure;
+ drmInfo.ring_size = pR128->ringSize*1024*1024;
+ drmInfo.usec_timeout = pR128->CCEusecTimeout;
+
+ drmInfo.fb_offset = pR128->LinearAddr;
+ drmInfo.agp_ring_offset = pR128->ringHandle;
+ drmInfo.agp_read_ptr_offset = pR128->ringReadPtrHandle;
+ drmInfo.agp_vertbufs_offset = pR128->vbHandle;
+ drmInfo.agp_indbufs_offset = pR128->indHandle;
+ drmInfo.agp_textures_offset = pR128->agpTexHandle;
+ drmInfo.mmio_offset = pR128->registerHandle;
+
+ if (drmR128InitCCE(pR128->drmFD, &drmInfo) < 0) return FALSE;
+
+ return TRUE;
+}
+
+/* Add a map for the vertex buffers that will be accessed by any
+ DRI-based clients. */
+static Bool R128DRIBufInit(R128InfoPtr pR128, ScreenPtr pScreen)
+{
+ /* Initialize vertex buffers */
+ if ((pR128->vbNumBufs = drmAddBufs(pR128->drmFD,
+ pR128->vbMapSize / pR128->vbBufSize,
+ pR128->vbBufSize,
+ DRM_AGP_BUFFER,
+ pR128->vbStart)) <= 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Could not create vertex buffers list\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] Added %d %d byte vertex buffers\n",
+ pR128->vbNumBufs, pR128->vbBufSize);
+
+ if (drmMarkBufs(pR128->drmFD, 0.133333, 0.266666)) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Failed to mark vertex buffers list\n");
+ return FALSE;
+ }
+
+ if (!(pR128->vbBufs = drmMapBufs(pR128->drmFD))) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Failed to map vertex buffers list\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] Mapped %d vertex buffers\n",
+ pR128->vbBufs->count);
+
+ return TRUE;
+}
+
+/* Load the microcode for the CCE */
+static void R128DRILoadMicrocode(ScrnInfoPtr pScrn)
+{
+ unsigned char *R128MMIO = R128PTR(pScrn)->MMIO;
+ int i;
+ unsigned long R128Microcode[] = {
+ /* CCE microcode (from ATI) */
+ 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, 1617039951,
+ 0, 774592877, 0, 1987540286, 0, 2307490946U, 0, 599558925, 0, 589505315, 0,
+ 596487092, 0, 589505315, 1, 11544576, 1, 206848, 1, 311296, 1, 198656, 2,
+ 912273422, 11, 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12,
+ 28, 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9, 30, 1,
+ 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656, 1, 15630, 1, 51200,
+ 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1, 15717, 1, 15718, 2, 43, 1,
+ 15936948, 1, 570480831, 1, 14715071, 12, 322123831, 1, 33953125, 12, 55, 1,
+ 33559908, 1, 15718, 2, 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1,
+ 509952, 1, 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
+ 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1, 15975928, 1,
+ 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2, 268449859, 2, 10307, 12,
+ 176, 1, 15734, 1, 15735, 1, 15630, 1, 15631, 1, 5253120, 6, 3145810, 16,
+ 2150645232U, 1, 15864, 2, 82, 1, 343310, 1, 1064207, 2, 3145813, 1, 15728,
+ 1, 7817, 1, 15729, 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002,
+ 1, 16008, 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
+ 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1, 180224, 1,
+ 103824738, 2, 112, 2, 3145839, 0, 536885440, 1, 114880, 14, 125, 12,
+ 206975, 1, 33559995, 12, 198784, 0, 33570236, 1, 15803, 0, 15804, 3,
+ 294912, 1, 294912, 3, 442370, 1, 11544576, 0, 811612160, 1, 12593152, 1,
+ 11536384, 1, 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1,
+ 14793, 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
+ 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1, 114880, 14,
+ 159, 12, 198784, 1, 1109409213, 12, 198783, 1, 1107312059, 12, 198784, 1,
+ 1109409212, 2, 162, 1, 1075854781, 1, 1073757627, 1, 1075854780, 1, 540672,
+ 1, 10485760, 6, 3145894, 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0,
+ 0, 0, 256, 14, 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858,
+ 1, 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1, 33560360, 1,
+ 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1, 409611, 9, 188, 0,
+ 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+ };
+
+ R128WaitForIdle(pScrn);
+
+ OUTREG(R128_PM4_MICROCODE_ADDR, 0);
+ for (i = 0; i < 256; i += 1) {
+ OUTREG(R128_PM4_MICROCODE_DATAH, R128Microcode[i*2]);
+ OUTREG(R128_PM4_MICROCODE_DATAL, R128Microcode[i*2 + 1]);
+ }
+}
+
+/* Initialize the CCE state, and start the CCE (if used by the X server) */
+static void R128DRICCEInit(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ /* CCEMode is initialized in r128_driver.c */
+ switch (info->CCEMode) {
+ case R128_PM4_NONPM4: info->CCEFifoSize = 0; break;
+ case R128_PM4_192PIO: info->CCEFifoSize = 192; break;
+ case R128_PM4_192BM: info->CCEFifoSize = 192; break;
+ case R128_PM4_128PIO_64INDBM: info->CCEFifoSize = 128; break;
+ case R128_PM4_128BM_64INDBM: info->CCEFifoSize = 128; break;
+ case R128_PM4_64PIO_128INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64BM_128INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64PIO_64VCBM_64INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64BM_64VCBM_64INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64; break;
+ }
+
+ if (info->CCE2D) {
+ /* Make sure the CCE is on for the X server */
+ R128CCEStart(pScrn);
+ } else {
+ /* Make sure the CCE is off for the X server */
+ OUTREG(R128_PM4_MICRO_CNTL, 0);
+ OUTREG(R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4);
+ }
+}
+
+/* Initialize the screen-specific data structures for the DRI and the
+ Rage 128. This is the main entry point to the device-specific
+ initialization code. It calls device-independent DRI functions to
+ create the DRI data structures and initialize the DRI state. */
+Bool R128DRIScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr pR128 = R128PTR(pScrn);
+ DRIInfoPtr pDRIInfo;
+ R128DRIPtr pR128DRI;
+
+ switch (pR128->pixel_code) {
+ case 8:
+ /* These modes are not supported (yet). */
+ case 15:
+ case 24:
+ return FALSE;
+
+ /* Only 16 and 32 color depths are supports currently. */
+ case 16:
+ case 32:
+ break;
+ }
+
+ /* Create the DRI data structure, and fill it in before calling the
+ DRIScreenInit(). */
+ if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
+
+ pR128->pDRIInfo = pDRIInfo;
+ pDRIInfo->drmDriverName = R128_NAME;
+ pDRIInfo->clientDriverName = R128_NAME;
+ pDRIInfo->busIdString = xalloc(64);
+ sprintf(pDRIInfo->busIdString,
+ "PCI:%d:%d:%d",
+ pR128->PciInfo->bus,
+ pR128->PciInfo->device,
+ pR128->PciInfo->func);
+ pDRIInfo->ddxDriverMajorVersion = R128_VERSION_MAJOR;
+ pDRIInfo->ddxDriverMinorVersion = R128_VERSION_MINOR;
+ pDRIInfo->ddxDriverPatchVersion = R128_VERSION_PATCH;
+ pDRIInfo->frameBufferPhysicalAddress = pR128->LinearAddr;
+ pDRIInfo->frameBufferSize = pR128->FbMapSize;
+ pDRIInfo->frameBufferStride = (pScrn->displayWidth
+ * pR128->pixel_bytes);
+ pDRIInfo->ddxDrawableTableEntry = R128_MAX_DRAWABLES;
+ pDRIInfo->maxDrawableTableEntry = (SAREA_MAX_DRAWABLES
+ < R128_MAX_DRAWABLES
+ ? SAREA_MAX_DRAWABLES
+ : R128_MAX_DRAWABLES);
+
+#ifdef NOT_DONE
+ /* FIXME: Need to extend DRI protocol to pass this size back to
+ * client for SAREA mapping that includes a device private record
+ */
+ pDRIInfo->SAREASize =
+ ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */
+ /* + shared memory device private rec */
+#else
+ /* For now the mapping works by using a fixed size defined
+ * in the SAREA header
+ */
+ if (sizeof(XF86DRISAREARec)+sizeof(R128SAREAPriv)>SAREA_MAX) {
+ ErrorF("Data does not fit in SAREA\n");
+ return FALSE;
+ }
+ pDRIInfo->SAREASize = SAREA_MAX;
+#endif
+
+ if (!(pR128DRI = (R128DRIPtr)xnfcalloc(sizeof(R128DRIRec),1))) {
+ DRIDestroyInfoRec(pR128->pDRIInfo);
+ pR128->pDRIInfo = NULL;
+ return FALSE;
+ }
+ pDRIInfo->devPrivate = pR128DRI;
+ pDRIInfo->devPrivateSize = sizeof(R128DRIRec);
+ pDRIInfo->contextSize = sizeof(R128DRIContextRec);
+
+ pDRIInfo->CreateContext = R128CreateContext;
+ pDRIInfo->DestroyContext = R128DestroyContext;
+ pDRIInfo->SwapContext = R128DRISwapContext;
+ pDRIInfo->InitBuffers = R128DRIInitBuffers;
+ pDRIInfo->MoveBuffers = R128DRIMoveBuffers;
+ pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
+
+ if (!DRIScreenInit(pScreen, pDRIInfo, &pR128->drmFD)) {
+ xfree(pDRIInfo->devPrivate);
+ pDRIInfo->devPrivate = NULL;
+ DRIDestroyInfoRec(pDRIInfo);
+ pDRIInfo = NULL;
+ return FALSE;
+ }
+
+ /* Initialize AGP */
+ if (!pR128->IsPCI && !R128DRIAgpInit(pR128, pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* DRIScreenInit doesn't add all the
+ common mappings. Add additional
+ mappings here. */
+ if (!R128DRIMapInit(pR128, pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Initialize the ring buffer */
+ if (!pR128->IsPCI) R128DRICCEInitRingBuffer(pScrn);
+
+ /* Initialize the kernel data structures */
+ if (!R128DRIKernelInit(pR128, pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Initialize vertex buffers list */
+ if (!pR128->IsPCI && !R128DRIBufInit(pR128, pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* FIXME: When are these mappings unmapped? */
+
+ if (!R128InitVisualConfigs(pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Visual configs initialized\n");
+
+ /* Load the CCE Microcode */
+ R128DRILoadMicrocode(pScrn);
+
+ /* Reset the Graphics Engine */
+ R128EngineReset(pScrn);
+
+ return TRUE;
+}
+
+/* Finish initializing the device-dependent DRI state, and call
+ DRIFinishScreenInit() to complete the device-independent DRI
+ initialization. */
+Bool R128DRIFinishScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr pR128 = R128PTR(pScrn);
+ R128SAREAPrivPtr pSAREAPriv;
+ R128DRIPtr pR128DRI;
+
+ /* Init and start the CCE */
+ R128DRICCEInit(pScrn);
+
+ pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
+ memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
+
+ pR128->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
+ /* pR128->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */
+
+ pR128DRI = (R128DRIPtr)pR128->pDRIInfo->devPrivate;
+ pR128DRI->registerHandle = pR128->registerHandle;
+ pR128DRI->registerSize = pR128->registerSize;
+
+ pR128DRI->ringHandle = pR128->ringHandle;
+ pR128DRI->ringMapSize = pR128->ringMapSize;
+ pR128DRI->ringSize = pR128->ringSize*1024*1024;
+
+ pR128DRI->ringReadPtrHandle = pR128->ringReadPtrHandle;
+ pR128DRI->ringReadMapSize = pR128->ringReadMapSize;
+
+ pR128DRI->vbHandle = pR128->vbHandle;
+ pR128DRI->vbMapSize = pR128->vbMapSize;
+ pR128DRI->vbOffset = pR128->vbStart;
+ pR128DRI->vbBufSize = pR128->vbBufSize;
+
+ pR128DRI->indHandle = pR128->indHandle;
+ pR128DRI->indMapSize = pR128->indMapSize;
+
+ pR128DRI->agpTexHandle = pR128->agpTexHandle;
+ pR128DRI->agpTexMapSize = pR128->agpTexMapSize;
+ pR128DRI->log2AGPTexGran = pR128->log2AGPTexGran;
+ pR128DRI->agpTexOffset = pR128->agpTexStart;
+
+ pR128DRI->deviceID = pR128->Chipset;
+ pR128DRI->width = pScrn->virtualX;
+ pR128DRI->height = pScrn->virtualY;
+ pR128DRI->depth = pScrn->depth;
+ pR128DRI->bpp = pScrn->bitsPerPixel;
+
+ pR128DRI->fbX = pR128->fbX;
+ pR128DRI->fbY = pR128->fbY;
+ pR128DRI->backX = pR128->backX;
+ pR128DRI->backY = pR128->backY;
+ pR128DRI->depthX = pR128->depthX;
+ pR128DRI->depthY = pR128->depthY;
+ pR128DRI->textureX = pR128->textureX;
+ pR128DRI->textureY = pR128->textureY;
+ pR128DRI->textureSize = pR128->textureSize;
+ pR128DRI->log2TexGran = pR128->log2TexGran;
+
+ pR128DRI->IsPCI = pR128->IsPCI;
+
+ pR128DRI->CCEMode = pR128->CCEMode;
+ pR128DRI->CCEFifoSize = pR128->CCEFifoSize;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%08lx %d\n",
+ pR128DRI->registerHandle, pR128DRI->registerSize);
+ return DRIFinishScreenInit(pScreen);
+}
+
+/* The screen is being closed, so clean up any state and free any
+ resources used by the DRI. */
+void R128DRICloseScreen(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr pR128 = R128PTR(pScrn);
+
+ /* Stop the CCE if it is still in use */
+ if (pR128->CCE2D) R128CCEStop(pScrn);
+
+ /* De-allocate vertex buffers */
+ if (pR128->vbBufs) {
+ drmUnmapBufs(pR128->vbBufs);
+ pR128->vbBufs = NULL;
+ }
+
+ /* De-allocate all kernel resources */
+ drmR128CleanupCCE(pR128->drmFD);
+
+ /* De-allocate all AGP resources */
+ if (pR128->agpTex) {
+ drmUnmap(pR128->agpTex, pR128->agpTexMapSize);
+ pR128->agpTex = NULL;
+ }
+ if (pR128->ind) {
+ drmUnmap(pR128->ind, pR128->indMapSize);
+ pR128->ind = NULL;
+ }
+ if (pR128->vb) {
+ drmUnmap(pR128->vb, pR128->vbMapSize);
+ pR128->vb = NULL;
+ }
+ if (pR128->ringReadPtr) {
+ drmUnmap(pR128->ringReadPtr, pR128->ringReadMapSize);
+ pR128->ringReadPtr = NULL;
+ }
+ if (pR128->ring) {
+ drmUnmap(pR128->ring, pR128->ringMapSize);
+ pR128->ring = NULL;
+ }
+ if (pR128->agpMemHandle) {
+ drmAgpUnbind(pR128->drmFD, pR128->agpMemHandle);
+ drmAgpFree(pR128->drmFD, pR128->agpMemHandle);
+ pR128->agpMemHandle = 0;
+ drmAgpRelease(pR128->drmFD);
+ }
+
+ /* De-allocate all DRI resources */
+ DRICloseScreen(pScreen);
+
+ /* De-allocate all DRI data structures */
+ if (pR128->pDRIInfo) {
+ if (pR128->pDRIInfo->devPrivate) {
+ xfree(pR128->pDRIInfo->devPrivate);
+ pR128->pDRIInfo->devPrivate = NULL;
+ }
+ DRIDestroyInfoRec(pR128->pDRIInfo);
+ pR128->pDRIInfo = NULL;
+ }
+ if (pR128->pVisualConfigs) {
+ xfree(pR128->pVisualConfigs);
+ pR128->pVisualConfigs = NULL;
+ }
+ if (pR128->pVisualConfigsPriv) {
+ xfree(pR128->pVisualConfigsPriv);
+ pR128->pVisualConfigsPriv = NULL;
+ }
+}
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h
new file mode 100644
index 000000000..533aadb2f
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h
@@ -0,0 +1,116 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+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
+on 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
+ATI, PRECISION INSIGHT AND/OR THEIR 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:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ * Rickard E. Faith <faith@precisioninsight.com>
+ *
+ */
+
+#ifndef _R128_DRI_
+#define _R128_DRI_
+
+#include <xf86drm.h>
+
+/* DRI Driver defaults */
+#define R128_DEFAULT_CCE_PIO_MODE R128_PM4_64PIO_64VCBM_64INDBM
+#define R128_DEFAULT_CCE_BM_MODE R128_PM4_64BM_64VCBM_64INDBM
+#define R128_DEFAULT_AGP_MODE 2
+#define R128_DEFAULT_AGP_SIZE 8 /* MB (must be a power of 2 and > 4MB) */
+#define R128_DEFAULT_RING_SIZE 1 /* MB (must be page aligned) */
+#define R128_DEFAULT_VB_SIZE 1 /* MB (must be page aligned) */
+#define R128_DEFAULT_IND_SIZE 1 /* MB (must be page aligned) */
+#define R128_DEFAULT_AGP_TEX_SIZE 1 /* MB (must be page aligned) */
+
+#define R128_DEFAULT_VB_BUF_SIZE 16384 /* bytes */
+#define R128_DEFAULT_CCE_TIMEOUT 10000 /* usecs */
+
+#define R128_AGP_MAX_MODE 2
+
+#define R128CCE_USE_RING_BUFFER(m) \
+(((m) == R128_PM4_192BM) || \
+ ((m) == R128_PM4_128BM_64INDBM) || \
+ ((m) == R128_PM4_64BM_128INDBM) || \
+ ((m) == R128_PM4_64BM_64VCBM_64INDBM))
+
+typedef struct {
+ /* MMIO register data */
+ drmHandle registerHandle;
+ drmSize registerSize;
+
+ /* CCE ring buffer data */
+ drmHandle ringHandle;
+ drmSize ringMapSize;
+ int ringSize;
+
+ /* CCE ring read pointer data */
+ drmHandle ringReadPtrHandle;
+ drmSize ringReadMapSize;
+
+ /* CCE vertex buffer data */
+ drmHandle vbHandle;
+ drmSize vbMapSize;
+ int vbOffset;
+ int vbBufSize;
+
+ /* CCE indirect buffer data */
+ drmHandle indHandle;
+ drmSize indMapSize;
+
+ /* CCE AGP Texture data */
+ drmHandle agpTexHandle;
+ drmSize agpTexMapSize;
+ int log2AGPTexGran;
+ int agpTexOffset;
+
+ /* DRI screen private data */
+ int deviceID; /* PCI device ID */
+ int width; /* Width in pixels of display */
+ int height; /* Height in scanlines of display */
+ int depth; /* Depth of display (8, 15, 16, 24) */
+ int bpp; /* Bit depth of display (8, 16, 24, 32) */
+
+ int fbX; /* Start of frame buffer */
+ int fbY;
+ int backX; /* Start of shared back buffer */
+ int backY;
+ int depthX; /* Start of shared depth buffer */
+ int depthY;
+ int textureX; /* Start of texture data in frame buffer */
+ int textureY;
+ int textureSize;
+ int log2TexGran;
+
+ int IsPCI; /* Current card is a PCI card */
+
+ int CCEMode; /* CCE mode that server/clients use */
+ int CCEFifoSize; /* Size of the CCE command FIFO */
+} R128DRIRec, *R128DRIPtr;
+
+#endif
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h
new file mode 100644
index 000000000..acec5e269
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h
@@ -0,0 +1,54 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+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
+on 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
+ATI, PRECISION INSIGHT AND/OR THEIR 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:
+ * Rickard E. Faith <faith@precisioninsight.com>
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ */
+
+#ifndef _R128_DRIPRIV_H_
+#define _R128_DRIPRIV_H_
+
+#define R128_MAX_DRAWABLES 256
+
+extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs,
+ void **configprivs);
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} R128ConfigPrivRec, *R128ConfigPrivPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} R128DRIContextRec, *R128DRIContextPtr;
+
+#endif
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c
index b5da4cb6e..f30d86aa8 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c
@@ -1,8 +1,8 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c,v 1.26 2000/03/06 23:17:44 martin Exp $ */
/**************************************************************************
-Copyright 1999 ATI Technologies Inc. and Precision Insight, Inc.,
- Cedar Park, Texas.
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
@@ -107,6 +107,19 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* VESA support */
#include "vbe.h"
+ /* DRI support */
+#ifdef XF86DRI
+#include "GL/glxint.h"
+#include "xf86drm.h"
+#include "sarea.h"
+#define _XF86DRI_SERVER_
+#include "xf86dri.h"
+#include "dri.h"
+#include "r128_dri.h"
+#include "r128_dripriv.h"
+#include "r128_sarea.h"
+#endif
+
/* Driver data structures */
#include "r128.h"
#include "r128_reg.h"
@@ -176,17 +189,41 @@ typedef enum {
OPTION_HW_CURSOR,
OPTION_DAC_6BIT,
OPTION_DAC_8BIT,
+#ifdef XF86DRI
+ OPTION_IS_PCI,
+ OPTION_CCE_PIO,
+ OPTION_NO_SECURITY,
+ OPTION_USEC_TIMEOUT,
+ OPTION_AGP_MODE,
+ OPTION_AGP_SIZE,
+ OPTION_RING_SIZE,
+ OPTION_VERT_SIZE,
+ OPTION_VBUF_SIZE,
+ OPTION_USE_CCE_2D,
+#endif
OPTION_FBDEV
} R128Opts;
static OptionInfoRec R128Options[] = {
- { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
- { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
- { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, TRUE },
- { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE },
- { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE },
- { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE },
- { -1, NULL, OPTV_NONE, {0}, FALSE }
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, TRUE },
+ { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE },
+#ifdef XF86DRI
+ { OPTION_IS_PCI, "ForcePCIMode", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_CCE_PIO, "CCEPIOMode", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_NO_SECURITY, "CCENoSecurity", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_USEC_TIMEOUT, "CCEusecTimeout", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_VERT_SIZE, "VBListSize", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_VBUF_SIZE, "VBSize", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_USE_CCE_2D, "UseCCEfor2D", OPTV_BOOLEAN, {0}, FALSE },
+#endif
+ { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
};
R128RAMRec R128RAM[] = { /* Memory Specifications
@@ -299,6 +336,38 @@ static const char *ramdacSymbols[] = {
NULL
};
+#ifdef XF86DRI
+static const char *drmSymbols[] = {
+ "drmAddBufs",
+ "drmAddMap",
+ "drmAvailable",
+ "drmCtlAddCommand",
+ "drmCtlInstHandler",
+ "drmGetInterruptFromBusID",
+ "drmMapBufs",
+ "drmMarkBufs",
+ "drmUnmapBufs",
+ NULL
+};
+
+static const char *driSymbols[] = {
+ "DRIGetDrawableIndex",
+ "DRIFinishScreenInit",
+ "DRIDestroyInfoRec",
+ "DRICloseScreen",
+ "DRIDestroyInfoRec",
+ "DRIScreenInit",
+ "DRIDestroyInfoRec",
+ "DRICreateInfoRec",
+ "DRILock",
+ "DRIUnlock",
+ "DRIGetSAREAPrivate",
+ "DRIGetContext",
+ "GlxSetVisualConfigs",
+ NULL
+};
+#endif
+
static MODULESETUPPROTO(R128Setup);
static XF86ModuleVersionInfo R128VersRec =
@@ -347,6 +416,10 @@ static pointer R128Setup(pointer module, pointer opts, int *errmaj,
xaaSymbols,
xf8_32bppSymbols,
ramdacSymbols,
+#ifdef XF86DRI
+ drmSymbols,
+ driSymbols,
+#endif
fbdevHWSymbols,
vbeSymbols,
0 /* ddcsymbols */,
@@ -518,7 +591,7 @@ static void R128Unblank(ScrnInfoPtr pScrn)
}
/* Compute log base 2 of val. */
-static int R128MinBits(int val)
+int R128MinBits(int val)
{
int bits;
@@ -779,6 +852,7 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn)
int offset = 0; /* RAM Type */
MessageType from;
unsigned char *R128MMIO;
+
/* Chipset */
from = X_PROBED;
if (dev->chipset && *dev->chipset) {
@@ -876,7 +950,7 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn)
switch (info->MemCntl & 0x3) {
case 0: /* SDR SGRAM 1:1 */
switch (info->Chipset) {
- case PCI_CHIP_RAGE128RE:
+ case PCI_CHIP_RAGE128RE:
case PCI_CHIP_RAGE128RF: offset = 0; break; /* 128-bit SDR SGRAM 1:1 */
case PCI_CHIP_RAGE128RK:
case PCI_CHIP_RAGE128RL:
@@ -895,12 +969,28 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn)
pScrn->videoRam);
from = X_CONFIG;
pScrn->videoRam = dev->videoRam;
- }
+ }
pScrn->videoRam &= ~1023;
info->FbMapSize = pScrn->videoRam * 1024;
xf86DrvMsg(pScrn->scrnIndex, from,
"VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name);
+#ifdef XF86DRI
+ /* AGP/PCI */
+ if (xf86ReturnOptValBool(R128Options, OPTION_IS_PCI, FALSE)) {
+ info->IsPCI = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n");
+ } else {
+ switch (info->Chipset) {
+ case PCI_CHIP_RAGE128RE:
+ case PCI_CHIP_RAGE128RK: info->IsPCI = TRUE; break;
+ case PCI_CHIP_RAGE128RF:
+ case PCI_CHIP_RAGE128RL:
+ case PCI_CHIP_RAGE128PF:
+ default: info->IsPCI = FALSE; break;
+ }
+ }
+#endif
return TRUE;
}
@@ -1053,6 +1143,143 @@ static Bool R128PreInitInt10(ScrnInfoPtr pScrn)
return TRUE;
}
+#ifdef XF86DRI
+static Bool R128PreInitDRI(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (info->IsPCI) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "CCE in PIO mode\n");
+ info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;
+ } else if (xf86ReturnOptValBool(R128Options, OPTION_CCE_PIO, FALSE)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "CCE in PIO mode\n");
+ info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "CCE in BM mode\n");
+ info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
+ }
+
+ if (xf86ReturnOptValBool(R128Options, OPTION_USE_CCE_2D, FALSE)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using CCE for 2D\n");
+ info->CCE2D = TRUE;
+ } else {
+ info->CCE2D = FALSE;
+ }
+
+ if (xf86ReturnOptValBool(R128Options, OPTION_NO_SECURITY, FALSE)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "WARNING!!! CCE Security checks disabled!!! **********\n");
+ info->CCESecure = FALSE;
+ } else {
+ info->CCESecure = TRUE;
+ }
+
+ info->agpMode = R128_DEFAULT_AGP_MODE;
+ info->agpSize = R128_DEFAULT_AGP_SIZE;
+ info->ringSize = R128_DEFAULT_RING_SIZE;
+ info->vbSize = R128_DEFAULT_VB_SIZE;
+ info->indSize = R128_DEFAULT_IND_SIZE;
+ info->agpTexSize = R128_DEFAULT_AGP_TEX_SIZE;
+
+ info->vbBufSize = R128_DEFAULT_VB_BUF_SIZE;
+
+ info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT;
+
+ if (!info->IsPCI) {
+ if (xf86GetOptValInteger(R128Options,
+ OPTION_AGP_MODE, &(info->agpMode))) {
+ if (info->agpMode < 1 || info->agpMode > R128_AGP_MAX_MODE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal AGP Mode: %d\n", info->agpMode);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using AGP %dx mode\n", info->agpMode);
+ }
+
+ if (xf86GetOptValInteger(R128Options,
+ OPTION_AGP_SIZE, (int *)&(info->agpSize))) {
+ switch (info->agpSize) {
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ case 256:
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal AGP size: %d MB\n", info->agpSize);
+ return FALSE;
+ }
+ }
+
+ if (xf86GetOptValInteger(R128Options,
+ OPTION_RING_SIZE, &(info->ringSize))) {
+ if (info->ringSize < 1 || info->ringSize >= info->agpSize) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal ring buffer size: %d MB\n",
+ info->ringSize);
+ return FALSE;
+ }
+ }
+
+ if (xf86GetOptValInteger(R128Options,
+ OPTION_VERT_SIZE, &(info->vbSize))) {
+ if (info->vbSize < 1 || info->vbSize >= info->agpSize) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal vertex buffers list size: %d MB\n",
+ info->vbSize);
+ return FALSE;
+ }
+ }
+
+ if (xf86GetOptValInteger(R128Options,
+ OPTION_VBUF_SIZE, &(info->vbBufSize))) {
+ int numBufs = info->vbSize*1024*1024/info->vbBufSize;
+ if (numBufs < 2 || numBufs > 512) { /* FIXME: 512 is arbitrary */
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal individual vertex buffer size: %d bytes\n",
+ info->vbBufSize);
+ return FALSE;
+ }
+ }
+
+ if (info->ringSize + info->vbSize + info->indSize + info->agpTexSize >
+ info->agpSize) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Buffers are too big for requested AGP space\n");
+ return FALSE;
+ }
+
+ info->agpTexSize = info->agpSize - (info->ringSize +
+ info->vbSize +
+ info->indSize);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using %d MB AGP aperture\n", info->agpSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using %d MB for the ring buffer\n", info->ringSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using %d MB for vertex buffers\n", info->vbSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using %d MB for indirect buffers\n", info->indSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using %d MB for AGP textures\n", info->agpTexSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using %d byte vertex buffers\n", info->vbBufSize);
+ }
+
+ if (xf86GetOptValInteger(R128Options, OPTION_USEC_TIMEOUT,
+ &(info->CCEusecTimeout))) {
+ /* This option checked by the R128 DRM kernel module */
+ }
+
+ return TRUE;
+}
+#endif
+
extern xf86MonPtr ConfiguredMonitor;
static void
@@ -1152,6 +1379,10 @@ static Bool R128PreInit(ScrnInfoPtr pScrn, int flags)
if (!R128PreInitAccel(pScrn)) goto fail;
+#ifdef XF86DRI
+ if (!R128PreInitDRI(pScrn)) goto fail;
+#endif
+
return TRUE;
fail:
@@ -1231,9 +1462,20 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen,
R128TRACE(("R128ScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset));
+#ifdef XF86DRI
+ /* Turn off the CCE for now. */
+ info->CCEInUse = FALSE;
+#endif
+
if (!R128MapMem(pScrn)) return FALSE;
pScrn->fbOffset = 0;
-
+#ifdef XF86DRI
+ info->fbX = 0;
+ info->fbY = 0;
+#endif
+
+ info->PaletteSavedOnVT = FALSE;
+
R128Save(pScrn);
if (info->FBDev) {
if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
@@ -1251,6 +1493,18 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen,
pScrn->rgbBits,
pScrn->defaultVisual)) return FALSE;
+#ifdef XF86DRI
+ /* Setup DRI after visuals have been
+ established, but before cfbScreenInit is
+ called. cfbScreenInit will eventually
+ call the driver's InitGLXVisuals call
+ back. */
+ if (!xf86ReturnOptValBool(R128Options, OPTION_NOACCEL, FALSE))
+ info->directRenderingEnabled = R128DRIScreenInit(pScreen);
+ else
+ info->directRenderingEnabled = FALSE;
+#endif
+
#ifdef USE_FB
if (!fbScreenInit (pScreen, info->FB,
pScrn->virtualX, pScrn->virtualY,
@@ -1358,6 +1612,101 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen,
}
}
+#ifdef XF86DRI
+ /* Allocate frame buffer space for the
+ shared back and depth buffers as well
+ as for local textures. */
+ if (info->directRenderingEnabled) {
+ FBAreaPtr fbarea;
+ int width_bytes = pScrn->displayWidth * info->pixel_bytes;
+ int maxy = info->FbMapSize / width_bytes;
+ int l;
+
+ /* Allocate the shared back buffer */
+ if ((fbarea = xf86AllocateOffscreenArea(pScreen,
+ pScrn->virtualX,
+ pScrn->virtualY,
+ 32, NULL, NULL, NULL))) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved back buffer from (%d,%d) to (%d,%d)\n",
+ fbarea->box.x1, fbarea->box.y1,
+ fbarea->box.x2, fbarea->box.y2);
+
+ info->backX = fbarea->box.x1;
+ info->backY = fbarea->box.y1;
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve back buffer\n");
+ info->backX = -1;
+ info->backY = -1;
+ }
+
+ /* Allocate the shared depth buffer */
+ if ((fbarea = xf86AllocateOffscreenArea(pScreen,
+ pScrn->virtualX,
+ pScrn->virtualY,
+ 32, NULL, NULL, NULL))) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved depth buffer from (%d,%d) to (%d,%d)\n",
+ fbarea->box.x1, fbarea->box.y1,
+ fbarea->box.x2, fbarea->box.y2);
+
+ info->depthX = fbarea->box.x1;
+ info->depthY = fbarea->box.y1;
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve depth buffer\n");
+ info->depthX = -1;
+ info->depthY = -1;
+ }
+
+ /* Allocate local texture space */
+ if (((maxy - MemBox.y2 - 1) * width_bytes) >
+ (pScrn->virtualX * pScrn->virtualY * 2 * info->pixel_bytes)) {
+ info->textureX = 0;
+ info->textureY = MemBox.y2 + 1;
+ info->textureSize = (maxy - MemBox.y2 - 1) * width_bytes;
+
+ l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
+ if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
+
+ info->log2TexGran = l;
+ info->textureSize = (info->textureSize >> l) << l;
+
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved %d kb for textures: (%d,%d)-(%d,%d)\n",
+ info->textureSize/1024,
+ info->textureX, info->textureY,
+ pScrn->displayWidth, maxy);
+ } else if ((fbarea = xf86AllocateOffscreenArea(pScreen,
+ pScrn->virtualX,
+ pScrn->virtualY * 2,
+ 32,
+ NULL, NULL, NULL))) {
+ info->textureX = fbarea->box.x1;
+ info->textureY = fbarea->box.y1;
+ info->textureSize = ((fbarea->box.y2 - fbarea->box.y1) *
+ (fbarea->box.x2 - fbarea->box.x1) *
+ info->pixel_bytes);
+
+ l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
+ if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
+
+ info->log2TexGran = l;
+ info->textureSize = (info->textureSize >> l) << l;
+
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved %d kb for textures: (%d,%d)-(%d,%d)\n",
+ info->textureSize/1024,
+ fbarea->box.x1, fbarea->box.y1,
+ fbarea->box.x2, fbarea->box.y2);
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Unable to reserve texture space in frame buffer\n");
+ info->textureX = -1;
+ info->textureY = -1;
+ }
+ }
+#endif
+
/* Backing store setup */
miInitializeBackingStore(pScreen);
xf86SetBackingStore(pScreen);
@@ -1453,6 +1802,21 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen,
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+#ifdef XF86DRI
+ /* DRI finalization */
+ if (info->directRenderingEnabled) {
+ /* Now that mi, cfb, drm and others have
+ done their thing, complete the DRI
+ setup. */
+ info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen);
+ }
+ if (info->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering disabled\n");
+ }
+#endif
+
return TRUE;
}
@@ -1473,7 +1837,7 @@ static void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
OUTREG(R128_GEN_INT_CNTL, restore->gen_int_cntl);
OUTREG(R128_CAP0_TRIG_CNTL, restore->cap0_trig_cntl);
OUTREG(R128_CAP1_TRIG_CNTL, restore->cap1_trig_cntl);
- OUTREG(R128_BUS_CNTL, restore->bus_cntl);
+ OUTREG(R128_BUS_CNTL, restore->bus_cntl);
}
/* Write CRTC registers. */
@@ -1603,7 +1967,7 @@ static void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
save->gen_int_cntl = INREG(R128_GEN_INT_CNTL);
save->cap0_trig_cntl = INREG(R128_CAP0_TRIG_CNTL);
save->cap1_trig_cntl = INREG(R128_CAP1_TRIG_CNTL);
- save->bus_cntl = INREG(R128_BUS_CNTL);
+ save->bus_cntl = INREG(R128_BUS_CNTL);
}
/* Read CRTC registers. */
@@ -2025,7 +2389,7 @@ static Bool R128Init(ScrnInfoPtr pScrn, DisplayModePtr mode, R128SavePtr save)
R128InitPLLRegisters(pScrn, save, mode, &info->pll, dot_clock);
if (!R128InitDDARegisters(pScrn, save, mode, &info->pll, info))
return FALSE;
- R128InitPalette(save, info);
+ if (!info->PaletteSavedOnVT) R128InitPalette(save, info);
R128TRACE(("R128Init returns %p\n", save));
return TRUE;
@@ -2037,6 +2401,7 @@ static Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
R128InfoPtr info = R128PTR(pScrn);
if (!R128Init(pScrn, mode, &info->ModeReg)) return FALSE;
+ /* FIXME? DRILock/DRIUnlock here? */
R128Blank(pScrn);
R128RestoreMode(pScrn, &info->ModeReg);
R128Unblank(pScrn);
@@ -2096,14 +2461,43 @@ static void R128AdjustFrame(int scrnIndex, int x, int y, int flags)
mode. */
static Bool R128EnterVT(int scrnIndex, int flags)
{
- ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ R128InfoPtr info = R128PTR(pScrn);
R128TRACE(("R128EnterVT\n"));
+#ifdef XF86DRI
+ if (R128PTR(pScrn)->directRenderingEnabled) {
+ R128CCEStart(pScrn);
+ DRIUnlock(pScrn->pScreen);
+ }
+#endif
if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE;
+ info->PaletteSavedOnVT = FALSE;
R128AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
return TRUE;
}
+/* Called when VT switching away from the X server. Restore the original
+ text mode. */
+static void R128LeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ R128InfoPtr info = R128PTR(pScrn);
+ R128SavePtr save = &info->ModeReg;
+
+ R128TRACE(("R128LeaveVT\n"));
+#ifdef XF86DRI
+ if (R128PTR(pScrn)->directRenderingEnabled) {
+ DRILock(pScrn->pScreen, 0);
+ R128CCEStop(pScrn);
+ }
+#endif
+ R128SavePalette(pScrn, save);
+ info->PaletteSavedOnVT = TRUE;
+ R128Restore(pScrn);
+}
+
static Bool
R128EnterVTFBDev(int scrnIndex, int flags)
{
@@ -2116,8 +2510,6 @@ R128EnterVTFBDev(int scrnIndex, int flags)
return TRUE;
}
-/* Called when VT switching away from the X server. Restore the original
- text mode. */
static void R128LeaveVTFBDev(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
@@ -2127,14 +2519,6 @@ static void R128LeaveVTFBDev(int scrnIndex, int flags)
fbdevHWLeaveVT(scrnIndex,flags);
}
-static void R128LeaveVT(int scrnIndex, int flags)
-{
- ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-
- R128TRACE(("R128LeaveVT\n"));
- R128Restore(pScrn);
-}
-
/* Called at the end of each server generation. Restore the original text
mode, unmap video memory, and unwrap and call the saved CloseScreen
function. */
@@ -2144,6 +2528,15 @@ static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen)
R128InfoPtr info = R128PTR(pScrn);
R128TRACE(("R128CloseScreen\n"));
+
+#ifdef XF86DRI
+ /* Disable direct rendering */
+ if (info->directRenderingEnabled) {
+ R128DRICloseScreen(pScreen);
+ info->directRenderingEnabled = FALSE;
+ }
+#endif
+
if (pScrn->vtSema) {
R128Restore(pScrn);
R128UnmapMem(pScrn);
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h
index 86652affa..144fd9efe 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h
@@ -1,8 +1,8 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h,v 1.6 2000/02/23 04:47:19 martin Exp $ */
/**************************************************************************
-Copyright 1999 ATI Technologies Inc. and Precision Insight, Inc.,
- Cedar Park, Texas.
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
@@ -159,9 +159,20 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
#define R128_AGP_APER_OFFSET 0x0178
#define R128_AGP_BASE 0x0170
#define R128_AGP_CNTL 0x0174
+# define R128_AGP_APER_SIZE_256MB (0x00 << 0)
+# define R128_AGP_APER_SIZE_128MB (0x20 << 0)
+# define R128_AGP_APER_SIZE_64MB (0x30 << 0)
+# define R128_AGP_APER_SIZE_32MB (0x38 << 0)
+# define R128_AGP_APER_SIZE_16MB (0x3c << 0)
+# define R128_AGP_APER_SIZE_8MB (0x3e << 0)
+# define R128_AGP_APER_SIZE_4MB (0x3f << 0)
+# define R128_AGP_APER_SIZE_MASK (0x3f << 0)
#define R128_AGP_COMMAND 0x0f58 /* PCI */
#define R128_AGP_PLL_CNTL 0x0010 /* PLL */
#define R128_AGP_STATUS 0x0f54 /* PCI */
+# define R128_AGP_1X_MODE 0x01
+# define R128_AGP_2X_MODE 0x02
+# define R128_AGP_MODE_MASK 0x03
#define R128_AMCGPIO_A_REG 0x01a0
#define R128_AMCGPIO_EN_REG 0x01a8
#define R128_AMCGPIO_MASK 0x0194
@@ -169,6 +180,15 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
#define R128_ATTRDR 0x03c1 /* VGA */
#define R128_ATTRDW 0x03c0 /* VGA */
#define R128_ATTRX 0x03c0 /* VGA */
+# define R128_AUX1_SC_EN (1 << 0)
+# define R128_AUX1_SC_MODE_OR (0 << 1)
+# define R128_AUX1_SC_MODE_NAND (1 << 1)
+# define R128_AUX2_SC_EN (1 << 2)
+# define R128_AUX2_SC_MODE_OR (0 << 3)
+# define R128_AUX2_SC_MODE_NAND (1 << 3)
+# define R128_AUX3_SC_EN (1 << 4)
+# define R128_AUX3_SC_MODE_OR (0 << 5)
+# define R128_AUX3_SC_MODE_NAND (1 << 5)
#define R128_AUX_SC_CNTL 0x1660
#define R128_AUX1_SC_BOTTOM 0x1670
#define R128_AUX1_SC_LEFT 0x1664
@@ -257,11 +277,12 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
#define R128_BRUSH_SCALE 0x1470
#define R128_BRUSH_Y_X 0x1474
#define R128_BUS_CNTL 0x0030
-# define R128_BUS_RD_DISCARD_EN (1 << 24)
-# define R128_BUS_RD_ABORT_EN (1 << 25)
-# define R128_BUS_MSTR_DISCONNECT_EN (1 << 28)
-# define R128_BUS_WRT_BURST (1 << 29)
-# define R128_BUS_READ_BURST (1 << 30)
+# define R128_BUS_MASTER_DIS (1 << 6)
+# define R128_BUS_RD_DISCARD_EN (1 << 24)
+# define R128_BUS_RD_ABORT_EN (1 << 25)
+# define R128_BUS_MSTR_DISCONNECT_EN (1 << 28)
+# define R128_BUS_WRT_BURST (1 << 29)
+# define R128_BUS_READ_BURST (1 << 30)
#define R128_BUS_CNTL1 0x0034
#define R128_CACHE_CNTL 0x1724
@@ -297,6 +318,9 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
#define R128_CONFIG_REG_APER_SIZE 0x0110
#define R128_CONFIG_XSTRAP 0x00e4
#define R128_CONSTANT_COLOR_C 0x1d34
+# define R128_CONSTANT_COLOR_MASK 0x00ffffff
+# define R128_CONSTANT_COLOR_ONE 0x00ffffff
+# define R128_CONSTANT_COLOR_ZERO 0x00000000
#define R128_CRC_CMDFIFO_ADDR 0x0740
#define R128_CRC_CMDFIFO_DOUT 0x0744
#define R128_CRTC_CRNT_FRAME 0x0214
@@ -360,8 +384,13 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
#define R128_DEFAULT_SC_BOTTOM_RIGHT 0x16e8
# define R128_DEFAULT_SC_RIGHT_MAX (0x1fff << 0)
# define R128_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16)
-#define R128_DESTINATION_3D_CLR_CMP_MSK 0x1824
+#define R128_FOG_3D_TABLE_START 0x1810
+#define R128_FOG_3D_TABLE_END 0x1814
+#define R128_FOG_3D_TABLE_DENSITY 0x181c
+#define R128_FOG_TABLE_INDEX 0x1a14
+#define R128_FOG_TABLE_DATA 0x1a18
#define R128_DESTINATION_3D_CLR_CMP_VAL 0x1820
+#define R128_DESTINATION_3D_CLR_CMP_MSK 0x1824
#define R128_DEVICE_ID 0x0f02 /* PCI */
#define R128_DP_BRUSH_BKGD_CLR 0x1478
#define R128_DP_BRUSH_FRGD_CLR 0x147c
@@ -373,6 +402,7 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
# define R128_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15)
# define R128_DST_X_DIR_LEFT_TO_RIGHT (1 << 31)
#define R128_DP_DATATYPE 0x16c4
+# define R128_HOST_BIG_ENDIAN_EN (1 << 29)
#define R128_DP_GUI_MASTER_CNTL 0x146c
# define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
# define R128_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
@@ -388,6 +418,19 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
# define R128_GMC_BRUSH_8x8_COLOR (10 << 4)
# define R128_GMC_BRUSH_1X8_COLOR (12 << 4)
# define R128_GMC_BRUSH_SOLID_COLOR (13 << 4)
+# define R128_GMC_BRUSH_NONE (15 << 4)
+# define R128_GMC_DST_8BPP_CI (2 << 8)
+# define R128_GMC_DST_15BPP (3 << 8)
+# define R128_GMC_DST_16BPP (4 << 8)
+# define R128_GMC_DST_24BPP (5 << 8)
+# define R128_GMC_DST_32BPP (6 << 8)
+# define R128_GMC_DST_8BPP_RGB (7 << 8)
+# define R128_GMC_DST_Y8 (8 << 8)
+# define R128_GMC_DST_RGB8 (9 << 8)
+# define R128_GMC_DST_VYUY (11 << 8)
+# define R128_GMC_DST_YVYU (12 << 8)
+# define R128_GMC_DST_AYUV444 (14 << 8)
+# define R128_GMC_DST_ARGB4444 (15 << 8)
# define R128_GMC_DST_DATATYPE_MASK (0x0f << 8)
# define R128_GMC_DST_DATATYPE_SHIFT 8
# define R128_GMC_SRC_DATATYPE_MASK (3 << 12)
@@ -395,8 +438,11 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
# define R128_GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12)
# define R128_GMC_SRC_DATATYPE_COLOR (3 << 12)
# define R128_GMC_BYTE_PIX_ORDER (1 << 14)
+# define R128_GMC_BYTE_MSB_TO_LSB (0 << 14)
# define R128_GMC_BYTE_LSB_TO_MSB (1 << 14)
# define R128_GMC_CONVERSION_TEMP (1 << 15)
+# define R128_GMC_CONVERSION_TEMP_6500 (0 << 15)
+# define R128_GMC_CONVERSION_TEMP_9300 (1 << 15)
# define R128_GMC_ROP3_MASK (0xff << 16)
# define R128_DP_SRC_SOURCE_MASK (7 << 24)
# define R128_DP_SRC_SOURCE_MEMORY (2 << 24)
@@ -404,7 +450,7 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
# define R128_GMC_3D_FCN_EN (1 << 27)
# define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28)
# define R128_AUX_CLIP_DIS (1 << 29)
-# define R128_GMC_WR_MSK_DS (1 << 30)
+# define R128_GMC_WR_MSK_DIS (1 << 30)
# define R128_GMC_LD_BRUSH_Y_X (1 << 31)
# define R128_ROP3_ZERO 0x00000000
# define R128_ROP3_DSa 0x00880000
@@ -456,6 +502,7 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
#define R128_DST_PITCH 0x1408
#define R128_DST_PITCH_OFFSET 0x142c
#define R128_DST_PITCH_OFFSET_C 0x1c80
+# define R128_PITCH_SHIFT 21
#define R128_DST_WIDTH 0x140c
#define R128_DST_WIDTH_HEIGHT 0x1598
#define R128_DST_WIDTH_X 0x1588
@@ -573,7 +620,6 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
#define R128_MEM_VGA_RP_SEL 0x003c
#define R128_MEM_VGA_WP_SEL 0x0038
#define R128_MIN_GRANT 0x0f3e /* PCI */
-#define R128_MISC_3D_STATE_CNTL_REG 0x1CA0
#define R128_MM_DATA 0x0004
#define R128_MM_INDEX 0x0000
#define R128_MPLL_CNTL 0x000e /* PLL */
@@ -592,7 +638,10 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
#define R128_PC_DEBUG_MODE 0x1760
#define R128_PC_GUI_CTLSTAT 0x1748
#define R128_PC_GUI_MODE 0x1744
+# define R128_PC_IGNORE_UNIFY (1 << 5)
#define R128_PC_NGUI_CTLSTAT 0x0184
+# define R128_PC_FLUSH_GUI (3 << 0)
+# define R128_PC_RI_GUI (1 << 2)
# define R128_PC_FLUSH_ALL 0x00ff
# define R128_PC_BUSY (1 << 31)
#define R128_PC_NGUI_MODE 0x0180
@@ -689,6 +738,538 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l
#define R128_XDLL_CNTL 0x000c /* PLL */
#define R128_XPLL_CNTL 0x000b /* PLL */
+ /* Registers for CCE and Microcode Engine */
+#define R128_PM4_MICROCODE_ADDR 0x07d4
+#define R128_PM4_MICROCODE_RADDR 0x07d8
+#define R128_PM4_MICROCODE_DATAH 0x07dc
+#define R128_PM4_MICROCODE_DATAL 0x07e0
+
+#define R128_PM4_BUFFER_OFFSET 0x0700
+#define R128_PM4_BUFFER_CNTL 0x0704
+# define R128_PM4_NONPM4 (0 << 28)
+# define R128_PM4_192PIO (1 << 28)
+# define R128_PM4_192BM (2 << 28)
+# define R128_PM4_128PIO_64INDBM (3 << 28)
+# define R128_PM4_128BM_64INDBM (4 << 28)
+# define R128_PM4_64PIO_128INDBM (5 << 28)
+# define R128_PM4_64BM_128INDBM (6 << 28)
+# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28)
+# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28)
+# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
+#define R128_PM4_BUFFER_WM_CNTL 0x0708
+# define R128_WMA_SHIFT 0
+# define R128_WMB_SHIFT 8
+# define R128_WMC_SHIFT 16
+# define R128_WB_WM_SHIFT 24
+#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c
+#define R128_PM4_BUFFER_DL_RPTR 0x0710
+#define R128_PM4_BUFFER_DL_WPTR 0x0714
+# define R128_PM4_BUFFER_DL_DONE (1 << 31)
+#define R128_PM4_VC_FPU_SETUP 0x071c
+# define R128_FRONT_DIR_CW (0 << 0)
+# define R128_FRONT_DIR_CCW (1 << 0)
+# define R128_FRONT_DIR_MASK (1 << 0)
+# define R128_BACKFACE_CULL (0 << 1)
+# define R128_BACKFACE_POINTS (1 << 1)
+# define R128_BACKFACE_LINES (2 << 1)
+# define R128_BACKFACE_SOLID (3 << 1)
+# define R128_BACKFACE_MASK (3 << 1)
+# define R128_FRONTFACE_CULL (0 << 3)
+# define R128_FRONTFACE_POINTS (1 << 3)
+# define R128_FRONTFACE_LINES (2 << 3)
+# define R128_FRONTFACE_SOLID (3 << 3)
+# define R128_FRONTFACE_MASK (3 << 3)
+# define R128_FPU_COLOR_SOLID (0 << 5)
+# define R128_FPU_COLOR_FLAT (1 << 5)
+# define R128_FPU_COLOR_GOURAUD (2 << 5)
+# define R128_FPU_COLOR_GOURAUD2 (3 << 5)
+# define R128_FPU_SUB_PIX_2BITS (0 << 7)
+# define R128_FPU_SUB_PIX_4BITS (1 << 7)
+# define R128_FPU_MODE_2D (0 << 8)
+# define R128_FPU_MODE_3D (1 << 8)
+# define R128_TRAP_BITS_DISABLE (1 << 9)
+# define R128_EDGE_ANTIALIAS (1 << 10)
+# define R128_SUPERSAMPLE (1 << 11)
+# define R128_XFACTOR_2 (0 << 12)
+# define R128_XFACTOR_4 (1 << 12)
+# define R128_YFACTOR_2 (0 << 13)
+# define R128_YFACTOR_4 (1 << 13)
+# define R128_FLAT_SHADE_VERTEX_D3D (0 << 14)
+# define R128_FLAT_SHADE_VERTEX_OGL (1 << 14)
+# define R128_FPU_ROUND_TRUNCATE (0 << 15)
+# define R128_FPU_ROUND_NEAREST (1 << 15)
+# define R128_WM_SEL_8DW (0 << 16)
+# define R128_WM_SEL_16DW (1 << 16)
+# define R128_WM_SEL_32DW (2 << 16)
+#define R128_PM4_STAT 0x07b8
+# define R128_PM4_FIFOCNT_MASK 0x0fff
+# define R128_PM4_BUSY (1 << 16)
+# define R128_PM4_GUI_ACTIVE (1 << 31)
+#define R128_PM4_BUFFER_ADDR 0x07f0
+#define R128_PM4_MICRO_CNTL 0x07fc
+# define R128_PM4_MICRO_FREERUN (1 << 30)
+#define R128_PM4_FIFO_DATA_EVEN 0x1000
+#define R128_PM4_FIFO_DATA_ODD 0x1004
+
#define R128_SCALE_3D_CNTL 0x1a00
+# define R128_SCALE_DITHER_ERR_DIFF (0 << 1)
+# define R128_SCALE_DITHER_TABLE (1 << 1)
+# define R128_TEX_CACHE_SIZE_FULL (0 << 2)
+# define R128_TEX_CACHE_SIZE_HALF (1 << 2)
+# define R128_DITHER_INIT_CURR (0 << 3)
+# define R128_DITHER_INIT_RESET (1 << 3)
+# define R128_ROUND_24BIT (1 << 4)
+# define R128_TEX_CACHE_DISABLE (1 << 5)
+# define R128_SCALE_3D_NOOP (0 << 6)
+# define R128_SCALE_3D_SCALE (1 << 6)
+# define R128_SCALE_3D_TEXMAP_SHADE (2 << 6)
+# define R128_SCALE_PIX_BLEND (0 << 8)
+# define R128_SCALE_PIX_REPLICATE (1 << 8)
+# define R128_TEX_CACHE_SPLIT (1 << 9)
+# define R128_APPLE_YUV_MODE (1 << 10)
+# define R128_TEX_CACHE_PALLETE_MODE (1 << 11)
+# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12)
+# define R128_ALPHA_COMB_ADD_NCLAMP (1 << 12)
+# define R128_ALPHA_COMB_SUB_DST_SRC_CLAMP (2 << 12)
+# define R128_ALPHA_COMB_SUB_DST_SRC_NCLAMP (3 << 12)
+# define R128_FOG_TABLE (1 << 14)
+# define R128_SIGNED_DST_CLAMP (1 << 15)
+# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16)
+# define R128_ALPHA_BLEND_SRC_ONE (1 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16)
+# define R128_ALPHA_BLEND_SRC_DSTALPHA (6 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDSTALPHA (7 << 16)
+# define R128_ALPHA_BLEND_SRC_DSTCOLOR (8 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDSTCOLOR (9 << 16)
+# define R128_ALPHA_BLEND_SRC_SAT (10 << 16)
+# define R128_ALPHA_BLEND_SRC_BLEND (11 << 16)
+# define R128_ALPHA_BLEND_SRC_INVBLEND (12 << 16)
+# define R128_ALPHA_BLEND_DST_ZERO (0 << 20)
+# define R128_ALPHA_BLEND_DST_ONE (1 << 20)
+# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20)
+# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20)
+# define R128_ALPHA_BLEND_DST_DSTALPHA (6 << 20)
+# define R128_ALPHA_BLEND_DST_INVDSTALPHA (7 << 20)
+# define R128_ALPHA_BLEND_DST_DSTCOLOR (8 << 20)
+# define R128_ALPHA_BLEND_DST_INVDSTCOLOR (9 << 20)
+# define R128_ALPHA_TEST_NEVER (0 << 24)
+# define R128_ALPHA_TEST_LESS (1 << 24)
+# define R128_ALPHA_TEST_LESSEQUAL (2 << 24)
+# define R128_ALPHA_TEST_EQUAL (3 << 24)
+# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24)
+# define R128_ALPHA_TEST_GREATER (5 << 24)
+# define R128_ALPHA_TEST_NEQUAL (6 << 24)
+# define R128_ALPHA_TEST_ALWAYS (7 << 24)
+# define R128_COMPOSITE_SHADOW_CMP_EQUAL (0 << 28)
+# define R128_COMPOSITE_SHADOW_CMP_NEQUAL (1 << 28)
+# define R128_COMPOSITE_SHADOW (1 << 29)
+# define R128_TEX_MAP_ALPHA_IN_TEXTURE (1 << 30)
+# define R128_TEX_CACHE_LINE_SIZE_8QW (0 << 31)
+# define R128_TEX_CACHE_LINE_SIZE_4QW (1 << 31)
+
+#define R128_SETUP_CNTL 0x1bc4
+# define R128_DONT_START_TRIANGLE (1 << 0)
+# define R128_Z_BIAS (0 << 1)
+# define R128_DONT_START_ANY_ON (1 << 2)
+# define R128_COLOR_SOLID_COLOR (0 << 3)
+# define R128_COLOR_FLAT_VERT_1 (1 << 3)
+# define R128_COLOR_FLAT_VERT_2 (2 << 3)
+# define R128_COLOR_FLAT_VERT_3 (3 << 3)
+# define R128_COLOR_GOURAUD (4 << 3)
+# define R128_PRIM_TYPE_TRI (0 << 7)
+# define R128_PRIM_TYPE_LINE (1 << 7)
+# define R128_PRIM_TYPE_POINT (2 << 7)
+# define R128_PRIM_TYPE_POLY_EDGE (3 << 7)
+# define R128_TEXTURE_ST_MULT_W (0 << 9)
+# define R128_TEXTURE_ST_DIRECT (1 << 9)
+# define R128_STARTING_VERTEX_1 (1 << 14)
+# define R128_STARTING_VERTEX_2 (2 << 14)
+# define R128_STARTING_VERTEX_3 (3 << 14)
+# define R128_ENDING_VERTEX_1 (1 << 16)
+# define R128_ENDING_VERTEX_2 (2 << 16)
+# define R128_ENDING_VERTEX_3 (3 << 16)
+# define R128_SU_POLY_LINE_LAST (0 << 18)
+# define R128_SU_POLY_LINE_NOT_LAST (1 << 18)
+# define R128_SUB_PIX_2BITS (0 << 19)
+# define R128_SUB_PIX_4BITS (1 << 19)
+# define R128_SET_UP_CONTINUE (1 << 31)
+
+#define R128_WINDOW_XY_OFFSET 0x1bcc
+# define R128_WINDOW_Y_SHIFT 4
+# define R128_WINDOW_X_SHIFT 20
+
+#define R128_Z_OFFSET_C 0x1c90
+#define R128_Z_PITCH_C 0x1c94
+#define R128_Z_STEN_CNTL_C 0x1c98
+# define R128_Z_PIX_WIDTH_16 (0 << 1)
+# define R128_Z_PIX_WIDTH_24 (1 << 1)
+# define R128_Z_PIX_WIDTH_32 (2 << 1)
+# define R128_Z_PIX_WIDTH_MASK (3 << 1)
+# define R128_Z_TEST_NEVER (0 << 4)
+# define R128_Z_TEST_LESS (1 << 4)
+# define R128_Z_TEST_LESSEQUAL (2 << 4)
+# define R128_Z_TEST_EQUAL (3 << 4)
+# define R128_Z_TEST_GREATEREQUAL (4 << 4)
+# define R128_Z_TEST_GREATER (5 << 4)
+# define R128_Z_TEST_NEQUAL (6 << 4)
+# define R128_Z_TEST_ALWAYS (7 << 4)
+# define R128_Z_TEST_MASK (7 << 4)
+# define R128_STENCIL_TEST_NEVER (0 << 12)
+# define R128_STENCIL_TEST_LESS (1 << 12)
+# define R128_STENCIL_TEST_LESSEQUAL (2 << 12)
+# define R128_STENCIL_TEST_EQUAL (3 << 12)
+# define R128_STENCIL_TEST_GREATEREQUAL (4 << 12)
+# define R128_STENCIL_TEST_GREATER (5 << 12)
+# define R128_STENCIL_TEST_NEQUAL (6 << 12)
+# define R128_STENCIL_TEST_ALWAYS (7 << 12)
+# define R128_STENCIL_S_FAIL_KEEP (0 << 16)
+# define R128_STENCIL_S_FAIL_ZERO (1 << 16)
+# define R128_STENCIL_S_FAIL_REPLACE (2 << 16)
+# define R128_STENCIL_S_FAIL_INC (3 << 16)
+# define R128_STENCIL_S_FAIL_DEC (4 << 16)
+# define R128_STENCIL_S_FAIL_INV (5 << 16)
+# define R128_STENCIL_ZPASS_KEEP (0 << 20)
+# define R128_STENCIL_ZPASS_ZERO (1 << 20)
+# define R128_STENCIL_ZPASS_REPLACE (2 << 20)
+# define R128_STENCIL_ZPASS_INC (3 << 20)
+# define R128_STENCIL_ZPASS_DEC (4 << 20)
+# define R128_STENCIL_ZPASS_INV (5 << 20)
+# define R128_STENCIL_ZFAIL_KEEP (0 << 24)
+# define R128_STENCIL_ZFAIL_ZERO (1 << 24)
+# define R128_STENCIL_ZFAIL_REPLACE (2 << 24)
+# define R128_STENCIL_ZFAIL_INC (3 << 24)
+# define R128_STENCIL_ZFAIL_DEC (4 << 24)
+# define R128_STENCIL_ZFAIL_INV (5 << 24)
+#define R128_TEX_CNTL_C 0x1c9c
+# define R128_Z_ENABLE (1 << 0)
+# define R128_Z_WRITE_ENABLE (1 << 1)
+# define R128_STENCIL_ENABLE (1 << 3)
+# define R128_SHADE_ENABLE (0 << 4)
+# define R128_TEXMAP_ENABLE (1 << 4)
+# define R128_SEC_TEXMAP_ENABLE (1 << 5)
+# define R128_FOG_ENABLE (1 << 7)
+# define R128_DITHER_ENABLE (1 << 8)
+# define R128_ALPHA_ENABLE (1 << 9)
+# define R128_ALPHA_TEST_ENABLE (1 << 10)
+# define R128_SPEC_LIGHT_ENABLE (1 << 11)
+# define R128_TEX_CHROMA_KEY_ENABLE (1 << 12)
+# define R128_ALPHA_IN_TEX_COMPLETE_A (0 << 13)
+# define R128_ALPHA_IN_TEX_LSB_A (1 << 13)
+# define R128_LIGHT_DIS (0 << 14)
+# define R128_LIGHT_COPY (1 << 14)
+# define R128_LIGHT_MODULATE (2 << 14)
+# define R128_LIGHT_ADD (3 << 14)
+# define R128_LIGHT_BLEND_CONSTANT (4 << 14)
+# define R128_LIGHT_BLEND_TEXTURE (5 << 14)
+# define R128_LIGHT_BLEND_VERTEX (6 << 14)
+# define R128_LIGHT_BLEND_CONST_COLOR (7 << 14)
+# define R128_ALPHA_LIGHT_DIS (0 << 18)
+# define R128_ALPHA_LIGHT_COPY (1 << 18)
+# define R128_ALPHA_LIGHT_MODULATE (2 << 18)
+# define R128_ALPHA_LIGHT_ADD (3 << 18)
+# define R128_ANTI_ALIAS (1 << 21)
+# define R128_TEX_CACHE_FLUSH (1 << 23)
+# define R128_LOD_BIAS_SHIFT 24
+#define R128_MISC_3D_STATE_CNTL_REG 0x1ca0
+# define R128_REF_ALPHA_MASK 0xff
+# define R128_MISC_SCALE_3D_NOOP (0 << 8)
+# define R128_MISC_SCALE_3D_SCALE (1 << 8)
+# define R128_MISC_SCALE_3D_TEXMAP_SHADE (2 << 8)
+# define R128_MISC_SCALE_PIX_BLEND (0 << 10)
+# define R128_MISC_SCALE_PIX_REPLICATE (1 << 10)
+# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12)
+# define R128_ALPHA_COMB_ADD_NO_CLAMP (1 << 12)
+# define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP (2 << 12)
+# define R128_ALPHA_COMB_SUB_SRC_DST_NO_CLAMP (3 << 12)
+# define R128_FOG_VERTEX (0 << 14)
+# define R128_FOG_TABLE (1 << 14)
+# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16)
+# define R128_ALPHA_BLEND_SRC_ONE (1 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16)
+# define R128_ALPHA_BLEND_SRC_DESTALPHA (6 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDESTALPHA (7 << 16)
+# define R128_ALPHA_BLEND_SRC_DESTCOLOR (8 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDESTCOLOR (9 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCALPHASAT (10 << 16)
+# define R128_ALPHA_BLEND_SRC_BOTHSRCALPHA (11 << 16)
+# define R128_ALPHA_BLEND_SRC_BOTHINVSRCALPHA (12 << 16)
+# define R128_ALPHA_BLEND_SRC_MASK (15 << 16)
+# define R128_ALPHA_BLEND_DST_ZERO (0 << 20)
+# define R128_ALPHA_BLEND_DST_ONE (1 << 20)
+# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20)
+# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20)
+# define R128_ALPHA_BLEND_DST_DESTALPHA (6 << 20)
+# define R128_ALPHA_BLEND_DST_INVDESTALPHA (7 << 20)
+# define R128_ALPHA_BLEND_DST_DESTCOLOR (8 << 20)
+# define R128_ALPHA_BLEND_DST_INVDESTCOLOR (9 << 20)
+# define R128_ALPHA_BLEND_DST_SRCALPHASAT (10 << 20)
+# define R128_ALPHA_BLEND_DST_MASK (15 << 20)
+# define R128_ALPHA_TEST_NEVER (0 << 24)
+# define R128_ALPHA_TEST_LESS (1 << 24)
+# define R128_ALPHA_TEST_LESSEQUAL (2 << 24)
+# define R128_ALPHA_TEST_EQUAL (3 << 24)
+# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24)
+# define R128_ALPHA_TEST_GREATER (5 << 24)
+# define R128_ALPHA_TEST_NEQUAL (6 << 24)
+# define R128_ALPHA_TEST_ALWAYS (7 << 24)
+# define R128_ALPHA_TEST_MASK (7 << 24)
+#define R128_TEXTURE_CLR_CMP_CLR_C 0x1ca4
+#define R128_TEXTURE_CLR_CMP_MSK_C 0x1ca8
+#define R128_FOG_COLOR_C 0x1cac
+# define R128_FOG_BLUE_SHIFT 0
+# define R128_FOG_GREEN_SHIFT 8
+# define R128_FOG_RED_SHIFT 16
+#define R128_PRIM_TEX_CNTL_C 0x1cb0
+# define R128_MIN_BLEND_NEAREST (0 << 1)
+# define R128_MIN_BLEND_LINEAR (1 << 1)
+# define R128_MIN_BLEND_MIPNEAREST (2 << 1)
+# define R128_MIN_BLEND_MIPLINEAR (3 << 1)
+# define R128_MIN_BLEND_LINEARMIPNEAREST (4 << 1)
+# define R128_MIN_BLEND_LINEARMIPLINEAR (5 << 1)
+# define R128_MIN_BLEND_MASK (7 << 1)
+# define R128_MAG_BLEND_NEAREST (0 << 4)
+# define R128_MAG_BLEND_LINEAR (1 << 4)
+# define R128_MAG_BLEND_MASK (7 << 4)
+# define R128_MIP_MAP_DISABLE (1 << 7)
+# define R128_TEX_CLAMP_S_WRAP (0 << 8)
+# define R128_TEX_CLAMP_S_MIRROR (1 << 8)
+# define R128_TEX_CLAMP_S_CLAMP (2 << 8)
+# define R128_TEX_CLAMP_S_BORDER_COLOR (3 << 8)
+# define R128_TEX_CLAMP_S_MASK (3 << 8)
+# define R128_TEX_WRAP_S (1 << 10)
+# define R128_TEX_CLAMP_T_WRAP (0 << 11)
+# define R128_TEX_CLAMP_T_MIRROR (1 << 11)
+# define R128_TEX_CLAMP_T_CLAMP (2 << 11)
+# define R128_TEX_CLAMP_T_BORDER_COLOR (3 << 11)
+# define R128_TEX_CLAMP_T_MASK (3 << 11)
+# define R128_TEX_WRAP_T (1 << 13)
+# define R128_TEX_PERSPECTIVE_DISABLE (1 << 14)
+# define R128_DATATYPE_VQ (0 << 16)
+# define R128_DATATYPE_CI4 (1 << 16)
+# define R128_DATATYPE_CI8 (2 << 16)
+# define R128_DATATYPE_ARGB1555 (3 << 16)
+# define R128_DATATYPE_RGB565 (4 << 16)
+# define R128_DATATYPE_RGB888 (5 << 16)
+# define R128_DATATYPE_ARGB8888 (6 << 16)
+# define R128_DATATYPE_RGB332 (7 << 16)
+# define R128_DATATYPE_Y8 (8 << 16)
+# define R128_DATATYPE_RGB8 (9 << 16)
+# define R128_DATATYPE_CI16 (10 << 16)
+# define R128_DATATYPE_YUV422 (11 << 16)
+# define R128_DATATYPE_YUV422_2 (12 << 16)
+# define R128_DATATYPE_AYUV444 (14 << 16)
+# define R128_DATATYPE_ARGB4444 (15 << 16)
+# define R128_PALLETE_EITHER (0 << 20)
+# define R128_PALLETE_1 (1 << 20)
+# define R128_PALLETE_2 (2 << 20)
+# define R128_PSEUDOCOLOR_DT_RGB565 (0 << 24)
+# define R128_PSEUDOCOLOR_DT_ARGB1555 (1 << 24)
+# define R128_PSEUDOCOLOR_DT_ARGB4444 (2 << 24)
+#define R128_PRIM_TEXTURE_COMBINE_CNTL_C 0x1cb4
+# define R128_COMB_DIS (0 << 0)
+# define R128_COMB_COPY (1 << 0)
+# define R128_COMB_COPY_INP (2 << 0)
+# define R128_COMB_MODULATE (3 << 0)
+# define R128_COMB_MODULATE2X (4 << 0)
+# define R128_COMB_MODULATE4X (5 << 0)
+# define R128_COMB_ADD (6 << 0)
+# define R128_COMB_ADD_SIGNED (7 << 0)
+# define R128_COMB_BLEND_VERTEX (8 << 0)
+# define R128_COMB_BLEND_TEXTURE (9 << 0)
+# define R128_COMB_BLEND_CONST (10 << 0)
+# define R128_COMB_BLEND_PREMULT (11 << 0)
+# define R128_COMB_BLEND_PREV (12 << 0)
+# define R128_COMB_BLEND_PREMULT_INV (13 << 0)
+# define R128_COMB_ADD_SIGNED2X (14 << 0)
+# define R128_COMB_BLEND_CONST_COLOR (15 << 0)
+# define R128_COMB_MASK (15 << 0)
+# define R128_COLOR_FACTOR_TEX (4 << 4)
+# define R128_COLOR_FACTOR_NTEX (5 << 4)
+# define R128_COLOR_FACTOR_ALPHA (6 << 4)
+# define R128_COLOR_FACTOR_NALPHA (7 << 4)
+# define R128_COLOR_FACTOR_MASK (15 << 4)
+# define R128_INPUT_FACTOR_CONST_COLOR (2 << 10)
+# define R128_INPUT_FACTOR_CONST_ALPHA (3 << 10)
+# define R128_INPUT_FACTOR_INT_COLOR (4 << 10)
+# define R128_INPUT_FACTOR_INT_ALPHA (5 << 10)
+# define R128_INPUT_FACTOR_MASK (15 << 10)
+# define R128_COMB_ALPHA_DIS (0 << 14)
+# define R128_COMB_ALPHA_COPY (1 << 14)
+# define R128_COMB_ALPHA_COPY_INP (2 << 14)
+# define R128_COMB_ALPHA_MODULATE (3 << 14)
+# define R128_COMB_ALPHA_MODULATE2X (4 << 14)
+# define R128_COMB_ALPHA_MODULATE4X (5 << 14)
+# define R128_COMB_ALPHA_ADD (6 << 14)
+# define R128_COMB_ALPHA_ADD_SIGNED (7 << 14)
+# define R128_COMB_ALPHA_ADD_SIGNED2X (14 << 14)
+# define R128_COMB_ALPHA_MASK (15 << 14)
+# define R128_ALPHA_FACTOR_TEX_ALPHA (6 << 18)
+# define R128_ALPHA_FACTOR_NTEX_ALPHA (7 << 18)
+# define R128_ALPHA_FACTOR_MASK (15 << 18)
+# define R128_INP_FACTOR_A_CONST_ALPHA (1 << 25)
+# define R128_INP_FACTOR_A_INT_ALPHA (2 << 25)
+# define R128_INP_FACTOR_A_MASK (7 << 25)
+#define R128_TEX_SIZE_PITCH_C 0x1cb8
+# define R128_TEX_PITCH_SHIFT 0
+# define R128_TEX_SIZE_SHIFT 4
+# define R128_TEX_HEIGHT_SHIFT 8
+# define R128_TEX_MIN_SIZE_SHIFT 12
+# define R128_SEC_TEX_PITCH_SHIFT 16
+# define R128_SEC_TEX_SIZE_SHIFT 20
+# define R128_SEC_TEX_HEIGHT_SHIFT 24
+# define R128_SEC_TEX_MIN_SIZE_SHIFT 28
+# define R128_TEX_PITCH_MASK (0x0f << 0)
+# define R128_TEX_SIZE_MASK (0x0f << 4)
+# define R128_TEX_HEIGHT_MASK (0x0f << 8)
+# define R128_TEX_MIN_SIZE_MASK (0x0f << 12)
+# define R128_SEC_TEX_PITCH_MASK (0x0f << 16)
+# define R128_SEC_TEX_SIZE_MASK (0x0f << 20)
+# define R128_SEC_TEX_HEIGHT_MASK (0x0f << 24)
+# define R128_SEC_TEX_MIN_SIZE_MASK (0x0f << 28)
+# define R128_TEX_SIZE_PITCH_SHIFT 0
+# define R128_SEC_TEX_SIZE_PITCH_SHIFT 16
+# define R128_TEX_SIZE_PITCH_MASK (0xffff << 0)
+# define R128_SEC_TEX_SIZE_PITCH_MASK (0xffff << 16)
+#define R128_PRIM_TEX_0_OFFSET_C 0x1cbc
+#define R128_PRIM_TEX_1_OFFSET_C 0x1cc0
+#define R128_PRIM_TEX_2_OFFSET_C 0x1cc4
+#define R128_PRIM_TEX_3_OFFSET_C 0x1cc8
+#define R128_PRIM_TEX_4_OFFSET_C 0x1ccc
+#define R128_PRIM_TEX_5_OFFSET_C 0x1cd0
+#define R128_PRIM_TEX_6_OFFSET_C 0x1cd4
+#define R128_PRIM_TEX_7_OFFSET_C 0x1cd8
+#define R128_PRIM_TEX_8_OFFSET_C 0x1cdc
+#define R128_PRIM_TEX_9_OFFSET_C 0x1ce0
+#define R128_PRIM_TEX_10_OFFSET_C 0x1ce4
+# define R128_TEX_NO_TILE (0 << 30)
+# define R128_TEX_TILED_BY_HOST (1 << 30)
+# define R128_TEX_TILED_BY_STORAGE (2 << 30)
+# define R128_TEX_TILED_BY_STORAGE2 (3 << 30)
+
+#define R128_SEC_TEX_CNTL_C 0x1d00
+# define R128_SEC_SELECT_PRIM_ST (0 << 0)
+# define R128_SEC_SELECT_SEC_ST (1 << 0)
+#define R128_SEC_TEX_COMBINE_CNTL_C 0x1d04
+# define R128_INPUT_FACTOR_PREV_COLOR (8 << 10)
+# define R128_INPUT_FACTOR_PREV_ALPHA (9 << 10)
+# define R128_INP_FACTOR_A_PREV_ALPHA (4 << 25)
+#define R128_SEC_TEX_0_OFFSET_C 0x1d08
+#define R128_SEC_TEX_1_OFFSET_C 0x1d0c
+#define R128_SEC_TEX_2_OFFSET_C 0x1d10
+#define R128_SEC_TEX_3_OFFSET_C 0x1d14
+#define R128_SEC_TEX_4_OFFSET_C 0x1d18
+#define R128_SEC_TEX_5_OFFSET_C 0x1d1c
+#define R128_SEC_TEX_6_OFFSET_C 0x1d20
+#define R128_SEC_TEX_7_OFFSET_C 0x1d24
+#define R128_SEC_TEX_8_OFFSET_C 0x1d28
+#define R128_SEC_TEX_9_OFFSET_C 0x1d2c
+#define R128_SEC_TEX_10_OFFSET_C 0x1d30
+#define R128_CONSTANT_COLOR_C 0x1d34
+# define R128_CONSTANT_BLUE_SHIFT 0
+# define R128_CONSTANT_GREEN_SHIFT 8
+# define R128_CONSTANT_RED_SHIFT 16
+# define R128_CONSTANT_ALPHA_SHIFT 24
+#define R128_PRIM_TEXTURE_BORDER_COLOR_C 0x1d38
+# define R128_PRIM_TEX_BORDER_BLUE_SHIFT 0
+# define R128_PRIM_TEX_BORDER_GREEN_SHIFT 8
+# define R128_PRIM_TEX_BORDER_RED_SHIFT 16
+# define R128_PRIM_TEX_BORDER_ALPHA_SHIFT 24
+#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c
+# define R128_SEC_TEX_BORDER_BLUE_SHIFT 0
+# define R128_SEC_TEX_BORDER_GREEN_SHIFT 8
+# define R128_SEC_TEX_BORDER_RED_SHIFT 16
+# define R128_SEC_TEX_BORDER_ALPHA_SHIFT 24
+#define R128_STEN_REF_MASK_C 0x1d40
+# define R128_STEN_REFERENCE_SHIFT 0
+# define R128_STEN_MASK_SHIFT 16
+# define R128_STEN_WRITE_MASK_SHIFT 24
+#define R128_PLANE_3D_MASK_C 0x1d44
+
+
+ /* Constants */
+#define R128_AGP_TEX_OFFSET 0x02000000
+
+#define R128_VB_AGE_REG R128_GUI_SCRATCH_REG0
+#define R128_SWAP_AGE_REG R128_GUI_SCRATCH_REG1
+
+ /* CCE packet types */
+#define R128_CCE_PACKET0 0x00000000
+#define R128_CCE_PACKET0_ONE_REG_WR 0x00008000
+#define R128_CCE_PACKET1 0x40000000
+#define R128_CCE_PACKET2 0x80000000
+#define R128_CCE_PACKET3_NOP 0xC0001000
+#define R128_CCE_PACKET3_PAINT 0xC0001100
+#define R128_CCE_PACKET3_BITBLT 0xC0001200
+#define R128_CCE_PACKET3_SMALLTEXT 0xC0001300
+#define R128_CCE_PACKET3_HOSTDATA_BLT 0xC0001400
+#define R128_CCE_PACKET3_POLYLINE 0xC0001500
+#define R128_CCE_PACKET3_SCALING 0xC0001600
+#define R128_CCE_PACKET3_TRANS_SCALING 0xC0001700
+#define R128_CCE_PACKET3_POLYSCANLINES 0xC0001800
+#define R128_CCE_PACKET3_NEXT_CHAR 0xC0001900
+#define R128_CCE_PACKET3_PAINT_MULTI 0xC0001A00
+#define R128_CCE_PACKET3_BITBLT_MULTI 0xC0001B00
+#define R128_CCE_PACKET3_PLY_NEXTSCAN 0xC0001D00
+#define R128_CCE_PACKET3_SET_SCISSORS 0xC0001E00
+#define R128_CCE_PACKET3_SET_MODE24BPP 0xC0001F00
+#define R128_CCE_PACKET3_CNTL_PAINT 0xC0009100
+#define R128_CCE_PACKET3_CNTL_BITBLT 0xC0009200
+#define R128_CCE_PACKET3_CNTL_SMALLTEXT 0xC0009300
+#define R128_CCE_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400
+#define R128_CCE_PACKET3_CNTL_POLYLINE 0xC0009500
+#define R128_CCE_PACKET3_CNTL_SCALING 0xC0009600
+#define R128_CCE_PACKET3_CNTL_TRANS_SCALING 0xC0009700
+#define R128_CCE_PACKET3_CNTL_POLYSCANLINES 0xC0009800
+#define R128_CCE_PACKET3_CNTL_NEXT_CHAR 0xC0009900
+#define R128_CCE_PACKET3_CNTL_PAINT_MULTI 0xC0009A00
+#define R128_CCE_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00
+#define R128_CCE_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00
+#define R128_CCE_PACKET3_3D_SAVE_CONTEXT 0xC0002000
+#define R128_CCE_PACKET3_3D_PLAY_CONTEXT 0xC0002100
+#define R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300
+#define R128_CCE_PACKET3_3D_RNDR_GEN_PRIM 0xC0002500
+#define R128_CCE_PACKET3_LOAD_PALETTE 0xC0002C00
+#define R128_CCE_PACKET3_PURGE 0xC0002D00
+#define R128_CCE_PACKET3_NEXT_VERTEX_BUNDLE 0xC0002E00
+# define R128_CCE_PACKET_MASK 0xC0000000
+# define R128_CCE_PACKET_COUNT_MASK 0x3fff0000
+# define R128_CCE_PACKET_MAX_DWORDS (1 << 14)
+# define R128_CCE_PACKET0_REG_MASK 0x000007ff
+# define R128_CCE_PACKET1_REG0_MASK 0x000007ff
+# define R128_CCE_PACKET1_REG1_MASK 0x003ff800
+
+#define R128_CCE_VC_FRMT_RHW 0x00000001
+#define R128_CCE_VC_FRMT_DIFFUSE_BGR 0x00000002
+#define R128_CCE_VC_FRMT_DIFFUSE_A 0x00000004
+#define R128_CCE_VC_FRMT_DIFFUSE_ARGB 0x00000008
+#define R128_CCE_VC_FRMT_SPEC_BGR 0x00000010
+#define R128_CCE_VC_FRMT_SPEC_F 0x00000020
+#define R128_CCE_VC_FRMT_SPEC_FRGB 0x00000040
+#define R128_CCE_VC_FRMT_S_T 0x00000080
+#define R128_CCE_VC_FRMT_S2_T2 0x00000100
+#define R128_CCE_VC_FRMT_RHW2 0x00000200
+
+#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001
+#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007
+#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010
+#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020
+#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030
+#define R128_CCE_VC_CNTL_NUM_SHIFT 16
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_sarea.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_sarea.h
new file mode 100644
index 000000000..c5d99df34
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_sarea.h
@@ -0,0 +1,77 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+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
+on 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
+ATI, PRECISION INSIGHT AND/OR THEIR 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:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ */
+
+#ifndef _R128_SAREA_H_
+#define _R128_SAREA_H_
+
+/* There are 2 heaps (local/AGP). Each region within a heap is a
+ minimum of 64k, and there are at most 64 of them per heap. */
+#define R128_LOCAL_TEX_HEAP 0
+#define R128_AGP_TEX_HEAP 1
+#define R128_NR_TEX_HEAPS 2
+#define R128_NR_TEX_REGIONS 64
+#define R128_LOG_TEX_GRANULARITY 16
+
+typedef struct {
+ unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char in_use; /* owned by a client, or free? */
+ int age; /* tracked by clients to update local LRU's */
+} R128TexRegion;
+
+typedef struct {
+ /* Maintain an LRU of contiguous regions of texture space. If you
+ * think you own a region of texture memory, and it has an age
+ * different to the one you set, then you are mistaken and it has
+ * been stolen by another client. If global texAge hasn't changed,
+ * there is no need to walk the list.
+ *
+ * These regions can be used as a proxy for the fine-grained texture
+ * information of other clients - by maintaining them in the same
+ * lru which is used to age their own textures, clients have an
+ * approximate lru for the whole of global texture space, and can
+ * make informed decisions as to which areas to kick out. There is
+ * no need to choose whether to kick out your own texture or someone
+ * else's - simply eject them all in LRU order.
+ */
+ /* Last elt is sentinal */
+ R128TexRegion texList[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
+ /* last time texture was uploaded */
+ int texAge[R128_NR_TEX_HEAPS];
+
+ int ctxOwner; /* last context to upload state */
+
+ int ringWrite; /* current ring buffer write index */
+} R128SAREAPriv, *R128SAREAPrivPtr;
+
+#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/Imakefile b/xc/programs/Xserver/hw/xfree86/os-support/Imakefile
index 7041d435a..c42f5b2b7 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/Imakefile
+++ b/xc/programs/Xserver/hw/xfree86/os-support/Imakefile
@@ -100,6 +100,7 @@ OS_SUBDIR = sco
#if BuildXF86DRI && !DoLoadableServer
DRM_SRC = $(OS_SUBDIR)/drm/?*.c
DRM_OBJ = $(OS_SUBDIR)/drm/?*.o
+DRM_DONES = $(OS_SUBDIR)/drm/DONE
#endif
SUBDIRS = $(OS_SUBDIR) $(BUS_SUBDIR) misc vbe
@@ -107,7 +108,7 @@ SUBDIRS = $(OS_SUBDIR) $(BUS_SUBDIR) misc vbe
SRCS = $(OS_SUBDIR)/?*.c $(BUS_SUBDIR)/?*.c misc/?*.c vbe/?*.c $(DRM_SRC)
OBJS = $(OS_SUBDIR)/?*.o $(BUS_SUBDIR)/?*.o misc/?*.o vbe/?*.o $(DRM_OBJ)
-DONES = $(OS_SUBDIR)/DONE $(BUS_SUBDIR)/DONE misc/DONE vbe/DONE
+DONES = $(OS_SUBDIR)/DONE $(BUS_SUBDIR)/DONE misc/DONE vbe/DONE $(DRM_DONES)
#if HasParallelMake
MakeMutex($(SUBDIRS) $(OBJS) $(DONES))
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/Imakefile b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/Imakefile
index 0d413c5c8..4639b530d 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/Imakefile
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/Imakefile
@@ -14,8 +14,8 @@ MOBJ = drmmodule.o
MTRR_DEFINES = -DHAS_MTRR_SUPPORT
#endif
-SRCS = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c xf86drmI810.c xf86drmMga.c $(MSRC)
-OBJS = xf86drm.o xf86drmHash.o xf86drmRandom.o xf86drmSL.o xf86drmI810.o xf86drmMga.o $(MOBJ)
+SRCS = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c xf86drmI810.c xf86drmMga.c xf86drmR128.c $(MSRC)
+OBJS = xf86drm.o xf86drmHash.o xf86drmRandom.o xf86drmSL.o xf86drmI810.o xf86drmMga.o xf86drmR128.o $(MOBJ)
INCLUDES = -I$(XF86COMSRC) -I$(XF86OSSRC) -I. -I$(SERVERSRC)/include \
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h
index f61a70eb7..9e0ade357 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h
@@ -69,6 +69,7 @@ typedef struct drm_clip_rect {
/* Seperate include files for the i810/mga specific structures */
#include "mga_drm.h"
#include "i810_drm.h"
+#include "r128_drm.h"
typedef struct drm_version {
int version_major; /* Major version */
@@ -341,8 +342,18 @@ typedef struct drm_agp_info {
/* I810 specific ioctls */
#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t)
#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t)
-#define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t)
+#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t)
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
+#define DRM_IOCTL_I810_GETBUF DRM_IOWR(0x45, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46)
+
+/* Rage 128 specific ioctls */
+#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
+#define DRM_IOCTL_R128_RESET DRM_IO( 0x41)
+#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42)
+#define DRM_IOCTL_R128_CCEIDL DRM_IO( 0x43)
+#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t)
+#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t)
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/i810_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/i810_drm.h
index 0754874c6..4c8e09f6a 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/i810_drm.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/i810_drm.h
@@ -5,35 +5,112 @@
* if you change them, you must change the defines in the Xserver.
*/
-/* Might one day want to support the client-side ringbuffer code again.
- */
#ifndef _I810_DEFINES_
#define _I810_DEFINES_
-#define I810_USE_BATCH 1
#define I810_DMA_BUF_ORDER 12
#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER)
#define I810_DMA_BUF_NR 256
-#define I810_NR_SAREA_CLIPRECTS 2
+#define I810_NR_SAREA_CLIPRECTS 8
/* Each region is a minimum of 64k, and there are at most 64 of them.
*/
-
#define I810_NR_TEX_REGIONS 64
#define I810_LOG_MIN_TEX_REGION_SIZE 16
#endif
+#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
+#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
+#define I810_UPLOAD_CTX 0x4
+#define I810_UPLOAD_BUFFERS 0x8
+#define I810_UPLOAD_TEX0 0x10
+#define I810_UPLOAD_TEX1 0x20
+#define I810_UPLOAD_CLIPRECTS 0x40
+
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer. These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+/* Destbuffer state
+ * - backbuffer linear offset and pitch -- invarient in the current dri
+ * - zbuffer linear offset and pitch -- also invarient
+ * - drawing origin in back and depth buffers.
+ *
+ * Keep the depth/back buffer state here to acommodate private buffers
+ * in the future.
+ */
+#define I810_DESTREG_DI0 0 /* CMD_OP_DESTBUFFER_INFO (2 dwords) */
+#define I810_DESTREG_DI1 1
+#define I810_DESTREG_DV0 2 /* GFX_OP_DESTBUFFER_VARS (2 dwords) */
+#define I810_DESTREG_DV1 3
+#define I810_DESTREG_DR0 4 /* GFX_OP_DRAWRECT_INFO (4 dwords) */
+#define I810_DESTREG_DR1 5
+#define I810_DESTREG_DR2 6
+#define I810_DESTREG_DR3 7
+#define I810_DESTREG_DR4 8
+#define I810_DEST_SETUP_SIZE 10
+
+/* Context state
+ */
+#define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */
+#define I810_CTXREG_CF1 1
+#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
+#define I810_CTXREG_ST1 3
+#define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */
+#define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */
+#define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
+#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
+#define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
+#define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
+#define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
+#define I810_CTXREG_MA2 11 /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */
+#define I810_CTXREG_SDM 12 /* GFX_OP_SRC_DEST_MONO */
+#define I810_CTXREG_FOG 13 /* GFX_OP_FOG_COLOR */
+#define I810_CTXREG_B1 14 /* GFX_OP_BOOL_1 */
+#define I810_CTXREG_B2 15 /* GFX_OP_BOOL_2 */
+#define I810_CTXREG_LCS 16 /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */
+#define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */
+#define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */
+#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */
+#define I810_CTX_SETUP_SIZE 20
+
+/* Texture state (per tex unit)
+ */
+#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */
+#define I810_TEXREG_MI1 1
+#define I810_TEXREG_MI2 2
+#define I810_TEXREG_MI3 3
+#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */
+#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */
+#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */
+#define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */
+#define I810_TEX_SETUP_SIZE 8
+
+#define I810_FRONT 0x1
+#define I810_BACK 0x2
+#define I810_DEPTH 0x4
+
+
typedef struct _drm_i810_init {
- enum {
- I810_INIT_DMA = 0x01,
- I810_CLEANUP_DMA = 0x02
+ enum {
+ I810_INIT_DMA = 0x01,
+ I810_CLEANUP_DMA = 0x02
} func;
- int ring_map_idx;
- int buffer_map_idx;
+ int ring_map_idx;
+ int buffer_map_idx;
int sarea_priv_offset;
- unsigned long ring_start;
- unsigned long ring_end;
- unsigned long ring_size;
+ unsigned int ring_start;
+ unsigned int ring_end;
+ unsigned int ring_size;
+ unsigned int front_offset;
+ unsigned int back_offset;
+ unsigned int depth_offset;
+ unsigned int w;
+ unsigned int h;
+ unsigned int pitch;
+ unsigned int pitch_bits;
} drm_i810_init_t;
/* Warning: If you change the SAREA structure you must change the Xserver
@@ -46,6 +123,11 @@ typedef struct _drm_i810_tex_region {
} drm_i810_tex_region_t;
typedef struct _drm_i810_sarea {
+ unsigned int ContextState[I810_CTX_SETUP_SIZE];
+ unsigned int BufferState[I810_DEST_SETUP_SIZE];
+ unsigned int TexState[2][I810_TEX_SETUP_SIZE];
+ unsigned int dirty;
+
unsigned int nbox;
drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
@@ -72,12 +154,18 @@ typedef struct _drm_i810_sarea {
int last_dispatch; /* age of the most recently dispatched buffer */
int last_quiescent; /* */
int ctxOwner; /* last context to upload state */
+
+ int vertex_prim;
+
} drm_i810_sarea_t;
-typedef struct _drm_i810_general {
- int idx;
- int used;
-} drm_i810_general_t;
+typedef struct _drm_i810_clear {
+ int clear_color;
+ int clear_depth;
+ int flags;
+} drm_i810_clear_t;
+
+
/* These may be placeholders if we have more cliprects than
* I810_NR_SAREA_CLIPRECTS. In that case, the client sets discard to
@@ -90,4 +178,11 @@ typedef struct _drm_i810_vertex {
int discard; /* client is finished with the buffer? */
} drm_i810_vertex_t;
+typedef struct drm_i810_dma {
+ void *virtual;
+ int request_idx;
+ int request_size;
+ int granted;
+} drm_i810_dma_t;
+
#endif /* _I810_DRM_H_ */
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/r128_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/r128_drm.h
new file mode 100644
index 000000000..0379a5fae
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/r128_drm.h
@@ -0,0 +1,111 @@
+/* r128_drm.h -- Public header for the r128 driver
+ * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Authors: Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ * $XFree86$
+ */
+
+#ifndef _R128_DRM_H_
+#define _R128_DRM_H_
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmR128.h)
+ */
+typedef struct drm_r128_init {
+ enum {
+ R128_INIT_CCE = 0x01,
+ R128_CLEANUP_CCE = 0x02
+ } func;
+ int sarea_priv_offset;
+ int is_pci;
+ int cce_mode;
+ int cce_fifo_size;
+ int cce_secure;
+ int ring_size;
+ int usec_timeout;
+
+ int fb_offset;
+ int agp_ring_offset;
+ int agp_read_ptr_offset;
+ int agp_vertbufs_offset;
+ int agp_indbufs_offset;
+ int agp_textures_offset;
+ int mmio_offset;
+} drm_r128_init_t;
+
+typedef struct drm_r128_packet {
+ unsigned long *buffer;
+ int count;
+ int flags;
+} drm_r128_packet_t;
+
+typedef enum drm_r128_prim {
+ _DRM_R128_PRIM_NONE = 0x0001,
+ _DRM_R128_PRIM_POINT = 0x0002,
+ _DRM_R128_PRIM_LINE = 0x0004,
+ _DRM_R128_PRIM_POLY_LINE = 0x0008,
+ _DRM_R128_PRIM_TRI_LIST = 0x0010,
+ _DRM_R128_PRIM_TRI_FAN = 0x0020,
+ _DRM_R128_PRIM_TRI_STRIP = 0x0040,
+ _DRM_R128_PRIM_TRI_TYPE2 = 0x0080
+} drm_r128_prim_t;
+
+typedef struct drm_r128_vertex {
+ /* Indices here refer to the offset into
+ buflist in drm_buf_get_t. */
+ int send_count; /* Number of buffers to send */
+ int *send_indices; /* List of handles to buffers */
+ int *send_sizes; /* Lengths of data to send */
+ drm_r128_prim_t prim; /* Primitive type */
+ int request_count; /* Number of buffers requested */
+ int *request_indices; /* Buffer information */
+ int *request_sizes;
+ int granted_count; /* Number of buffers granted */
+} drm_r128_vertex_t;
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (r128_sarea.h)
+ */
+#define R128_LOCAL_TEX_HEAP 0
+#define R128_AGP_TEX_HEAP 1
+#define R128_NR_TEX_HEAPS 2
+#define R128_NR_TEX_REGIONS 64
+#define R128_LOG_TEX_GRANULARITY 16
+
+typedef struct drm_tex_region {
+ unsigned char next, prev;
+ unsigned char in_use;
+ int age;
+} drm_tex_region_t;
+
+typedef struct drm_r128_sarea {
+ drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
+ int tex_age[R128_NR_TEX_HEAPS];
+ int ctx_owner;
+ int ring_write;
+} drm_r128_sarea_t;
+
+#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmI810.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmI810.c
index 1248c70a9..067c6376e 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmI810.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmI810.c
@@ -58,23 +58,29 @@ Bool drmI810CleanupDma(int driSubFD)
return TRUE;
}
-Bool drmI810InitDma(int driSubFD, unsigned long start, unsigned long end,
- unsigned long size, int ring_map_idx, int buffer_map_idx,
- int sarea_off)
+Bool drmI810InitDma(int driSubFD, drmI810Init *info)
{
drm_i810_init_t init;
memset(&init, 0, sizeof(drm_i810_init_t));
+
init.func = I810_INIT_DMA;
- init.ring_map_idx = ring_map_idx;
- init.buffer_map_idx = buffer_map_idx;
- init.ring_start = start;
- init.ring_end = end;
- init.ring_size = size;
- init.sarea_priv_offset = sarea_off;
+ init.ring_map_idx = info->ring_map_idx;
+ init.buffer_map_idx = info->buffer_map_idx;
+ init.ring_start = info->start;
+ init.ring_end = info->end;
+ init.ring_size = info->size;
+ init.sarea_priv_offset = info->sarea_off;
+ init.front_offset = info->front_offset;
+ init.back_offset = info->back_offset;
+ init.depth_offset = info->depth_offset;
+ init.w = info->w;
+ init.h = info->h;
+ init.pitch = info->pitch;
+ init.pitch_bits = info->pitch_bits;
if(ioctl(driSubFD, DRM_IOCTL_I810_INIT, &init)) {
- return FALSE;
- }
+ return FALSE;
+ }
return TRUE;
}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmR128.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmR128.c
new file mode 100644
index 000000000..4195c90ba
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmR128.c
@@ -0,0 +1,198 @@
+/* xf86drmR128.c -- User-level interface to Rage 128 DRM device
+ * Created: Sun Apr 9 18:13:54 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Author: Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ * $XFree86$
+ *
+ */
+
+#ifdef XFree86Server
+# include "xf86.h"
+# include "xf86_OSproc.h"
+# include "xf86_ansic.h"
+# include "xf86Priv.h"
+# define _DRM_MALLOC xalloc
+# define _DRM_FREE xfree
+# ifndef XFree86LOADER
+# include <sys/stat.h>
+# include <sys/mman.h>
+# endif
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+# include <string.h>
+# include <ctype.h>
+# include <fcntl.h>
+# include <errno.h>
+# include <signal.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/ioctl.h>
+# include <sys/mman.h>
+# include <sys/time.h>
+# ifdef DRM_USE_MALLOC
+# define _DRM_MALLOC malloc
+# define _DRM_FREE free
+extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *);
+extern int xf86RemoveSIGIOHandler(int fd);
+# else
+# include <Xlibint.h>
+# define _DRM_MALLOC Xmalloc
+# define _DRM_FREE Xfree
+# endif
+#endif
+
+/* Not all systems have MAP_FAILED defined */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#include "xf86drm.h"
+#include "xf86drmR128.h"
+#include "drm.h"
+
+int drmR128InitCCE(int fd, drmR128Init *info)
+{
+ drm_r128_init_t init;
+
+ memset(&init, 0, sizeof(drm_r128_init_t));
+
+ init.func = R128_INIT_CCE;
+ init.sarea_priv_offset = info->sarea_priv_offset;
+ init.is_pci = info->is_pci;
+ init.cce_mode = info->cce_mode;
+ init.cce_fifo_size = info->cce_fifo_size;
+ init.cce_secure = info->cce_secure;
+ init.ring_size = info->ring_size;
+ init.usec_timeout = info->usec_timeout;
+
+ init.fb_offset = info->fb_offset;
+ init.agp_ring_offset = info->agp_ring_offset;
+ init.agp_read_ptr_offset = info->agp_read_ptr_offset;
+ init.agp_vertbufs_offset = info->agp_vertbufs_offset;
+ init.agp_indbufs_offset = info->agp_indbufs_offset;
+ init.agp_textures_offset = info->agp_textures_offset;
+ init.mmio_offset = info->mmio_offset;
+
+ if (ioctl(fd, DRM_IOCTL_R128_INIT, &init)) return -errno;
+
+ return 0;
+}
+
+int drmR128CleanupCCE(int fd)
+{
+ drm_r128_init_t init;
+
+ memset(&init, 0, sizeof(drm_r128_init_t));
+
+ init.func = R128_CLEANUP_CCE;
+
+ if (ioctl(fd, DRM_IOCTL_R128_INIT, &init)) return -errno;
+
+ return 0;
+}
+
+int drmR128EngineReset(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_R128_RESET, NULL)) return -errno;
+
+ return 0;
+}
+
+int drmR128EngineFlush(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_R128_FLUSH, NULL)) return -errno;
+
+ return 0;
+}
+
+int drmR128CCEWaitForIdle(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_R128_CCEIDL, NULL)) return -errno;
+
+ return 0;
+}
+
+int drmR128SubmitPackets(int fd, CARD32 *buffer, int *count, int flags)
+{
+ drm_r128_packet_t packet;
+ int ret;
+
+ memset(&packet, 0, sizeof(drm_r128_packet_t));
+
+ packet.count = *count;
+ packet.flags = flags;
+
+ while (packet.count > 0) {
+ packet.buffer = buffer + (*count - packet.count);
+ ret = ioctl(fd, DRM_IOCTL_R128_PACKET, &packet);
+ if (ret < 0 && ret != -EAGAIN) {
+ *count = packet.count;
+ return -errno;
+ }
+ }
+
+ *count = 0;
+ return 0;
+}
+
+int drmR128GetVertexBuffers(int fd, int count, int *indices, int *sizes)
+{
+ drm_r128_vertex_t v;
+
+ v.send_count = 0;
+ v.send_indices = NULL;
+ v.send_sizes = NULL;
+ v.prim = DRM_R128_PRIM_NONE;
+ v.request_count = count;
+ v.request_indices = indices;
+ v.request_sizes = sizes;
+ v.granted_count = 0;
+
+ if (ioctl(fd, DRM_IOCTL_R128_VERTEX, &v)) return -errno;
+
+ return v.granted_count;
+}
+
+int drmR128FlushVertexBuffers(int fd, int count, int *indices,
+ int *sizes, drmR128PrimType prim)
+{
+ drm_r128_vertex_t v;
+
+ v.send_count = count;
+ v.send_indices = indices;
+ v.send_sizes = sizes;
+ v.prim = prim;
+ v.request_count = 0;
+ v.request_indices = NULL;
+ v.request_sizes = NULL;
+ v.granted_count = 0;
+
+ if (ioctl(fd, DRM_IOCTL_R128_VERTEX, &v) < 0) return -errno;
+
+ return 0;
+}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile
index 96388450b..fdaecb972 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile
@@ -13,15 +13,16 @@ MOBJ = drmmodule.o
MTRR_DEFINES = -DHAS_MTRR_SUPPORT
#endif
-SRCS = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c $(MSRC)
-OBJS = xf86drm.o xf86drmHash.o xf86drmRandom.o xf86drmSL.o $(MOBJ)
-
+SRCS = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c xf86drmI810.c xf86drmMga.c xf86drmR128.c $(MSRC)
+OBJS = xf86drm.o xf86drmHash.o xf86drmRandom.o xf86drmSL.o xf86drmI810.o xf86drmMga.o xf86drmR128.o $(MOBJ)
INCLUDES = -I$(XF86COMSRC) -I$(XF86OSSRC) -I. -I$(SERVERSRC)/include \
-I$(XINCLUDESRC) -I$(EXTINCSRC) -I../.. -Ikernel
DEFINES = $(MTRR_DEFINES) $(GLX_DEFINES)
+#if DoLoadableServer
+
ModuleObjectRule()
LibraryModuleTarget(drm,$(OBJS))
NormalLintTarget($(SRCS))
@@ -30,6 +31,14 @@ NormalLintTarget($(SRCS))
InstallLibraryModule(drm,$(MODULEDIR),linux)
#endif
+#else
+
+SubdirLibraryRule($(OBJS))
+NormalLibraryObjectRule()
+
+#endif
+
+
#define IHaveSubdirs
SUBDIRS = kernel
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel
index 44d75c487..a169473af 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel
@@ -14,7 +14,8 @@
L_TARGET := libdrm.a
L_OBJS := init.o memory.o proc.o auth.o context.o drawable.o bufs.o \
- lists.o lock.o ioctl.o fops.o vm.o dma.o
+ lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o \
+ agpsupport.o
M_OBJS :=
@@ -26,6 +27,14 @@ ifdef CONFIG_DRM_TDFX
M_OBJS += tdfx.o
endif
+ifdef CONFIG_DRM_MGA
+M_OBJS += mga.o
+endif
+
+ifdef CONFIG_DRM_R128
+M_OBJS += r128.o
+endif
+
include $(TOPDIR)/Rules.make
gamma.o: gamma_drv.o gamma_dma.o $(L_TARGET)
@@ -33,3 +42,12 @@ gamma.o: gamma_drv.o gamma_dma.o $(L_TARGET)
tdfx.o: tdfx_drv.o tdfx_context.o $(L_TARGET)
$(LD) $(LD_RFLAG) -r -o $@ tdfx_drv.o tdfx_context.o -L. -ldrm
+
+i810.o: i810_drv.o i810_context.o $(L_TARGET)
+ $(LD) $(LD_RFLAG) -r -o $@ i810_drv.o i810_bufs.o i810_dma.o i810_context.o -L. -ldrm
+
+mga.o: mga_drv.o mga_context.o mga_dma.o mga_bufs.o $(L_TARGET)
+ $(LD) $(LD_RFLAG) -r -o $@ mga_drv.o mga_bufs.o mga_dma.o mga_context.o mga_state.o -L. -ldrm
+
+r128.o: r128_drv.o r128_context.o $(L_TARGET)
+ $(LD) $(LD_RFLAG) -r -o $@ r128_drv.o r128_context.o -L. -ldrm
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux
index 8a41f880b..368c3c850 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux
@@ -1,8 +1,7 @@
# Makefile -- For the Direct Rendering Manager module (drm)
# Created: Mon Jan 4 09:26:53 1999 by faith@precisioninsight.com
-# Revised: Sun Feb 13 23:15:59 2000 by kevin@precisioninsight.com
#
-# Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+# Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
# All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
@@ -31,12 +30,14 @@
# *** Setup
-MODS= gamma.o tdfx.o
+# **** End of SMP/MODVERSIONS detection
+
+MODS= gamma.o tdfx.o r128.o
LIBS= libdrm.a
PROGS= drmstat
DRMOBJS= init.o memory.o proc.o auth.o context.o drawable.o bufs.o \
- lists.o lock.o ioctl.o fops.o vm.o dma.o
+ lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
DRMHEADERS= drm.h drmP.h
GAMMAOBJS= gamma_drv.o gamma_dma.o
@@ -45,9 +46,14 @@ GAMMAHEADERS= gamma_drv.h $(DRMHEADERS)
TDFXOBJS= tdfx_drv.o tdfx_context.o
TDFXHEADERS= tdfx_drv.h $(DRMHEADERS)
+R128OBJS= r128_drv.o r128_dma.o r128_bufs.o r128_context.o
+R128HEADERS= r128_drv.h r128_drm.h $(DRMHEADERS)
+
PROGOBJS= drmstat.po xf86drm.po xf86drmHash.po xf86drmRandom.po sigio.po
PROGHEADERS= xf86drm.h $(DRMHEADERS)
+INC= /usr/include
+
CFLAGS= -O2 $(WARNINGS)
WARNINGS= -Wall -Wwrite-strings -Wpointer-arith -Wcast-align \
-Wstrict-prototypes -Wshadow -Wnested-externs \
@@ -102,7 +108,27 @@ SMP := $(shell gcc -E -nostdinc -I$(TREE) picker.c 2>/dev/null \
| grep -s 'SMP = ' | cut -d' ' -f3)
MODVERSIONS := $(shell gcc -E -I $(TREE) picker.c 2>/dev/null \
| grep -s 'MODVERSIONS = ' | cut -d' ' -f3)
-all::;@echo KERNEL HEADERS IN $(TREE): SMP=${SMP} MODVERSIONS=${MODVERSIONS}
+AGP := $(shell gcc -E -nostdinc -I$(TREE) picker.c 2>/dev/null \
+ | grep -s 'AGP = ' | cut -d' ' -f3)
+ifeq ($(AGP),0)
+AGP := $(shell gcc -E -nostdinc -I$(TREE) picker.c 2>/dev/null \
+ | grep -s 'AGP_MODULE = ' | cut -d' ' -f3)
+endif
+
+ifeq ($(AGP),1)
+MODCFLAGS += -DDRM_AGP
+DRMOBJS += agpsupport.o
+MODS += mga.o i810.o
+
+MGAOBJS= mga_drv.o mga_dma.o mga_bufs.o mga_state.o mga_context.o
+MGAHEADERS= mga_drv.h $(DRMHEADERS)
+
+I810OBJS= i810_drv.o i810_dma.o i810_bufs.o i810_context.o
+I810HEADERS= i810_drv.h $(DRMHEADERS)
+endif
+
+all::;@echo KERNEL HEADERS IN $(TREE): SMP=${SMP} MODVERSIONS=${MODVERSIONS} \
+ AGP=${AGP}
all:: $(LIBS) $(MODS) $(PROGS)
endif
@@ -116,6 +142,7 @@ ifeq ($(MODVERSIONS),1)
MODCFLAGS += -DMODVERSIONS -include $(TREE)/linux/modversions.h
endif
+
# **** End of configuration
libdrm.a: $(DRMOBJS)
@@ -128,6 +155,17 @@ gamma.o: $(GAMMAOBJS) $(LIBS)
tdfx.o: $(TDFXOBJS) $(LIBS)
$(LD) -r $^ -o $@
+r128.o: $(R128OBJS) $(LIBS)
+ $(LD) -r $^ -o $@
+
+ifeq ($(AGP),1)
+mga.o: $(MGAOBJS) $(LIBS)
+ $(LD) -r $^ -o $@
+
+i810.o: $(I810OBJS) $(LIBS)
+ $(LD) -r $^ -o $@
+endif
+
drmstat: $(PROGOBJS)
$(CC) $(PRGCFLAGS) $^ $(PRGLIBS) -o $@
@@ -149,8 +187,12 @@ ChangeLog:
$(DRMOBJS): $(DRMHEADERS)
$(GAMMAOBJS): $(GAMMAHEADERS)
$(TDFXOBJS): $(TDFXHEADERS)
+$(R128OBJS): $(R128HEADERS)
+ifeq ($(AGP),1)
+$(MGAOBJS): $(MGAHEADERS)
+$(I810OBJS): $(I810HEADERS)
+endif
$(PROGOBJS): $(PROGHEADERS)
clean:
- rm -f *.o *.po *~ core $(PROGS)
-
+ rm -f *.o *.a *.po *~ core $(PROGS)
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/agpsupport.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/agpsupport.c
index fb58154d6..14fb8b53f 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/agpsupport.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/agpsupport.c
@@ -159,6 +159,8 @@ int drm_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
-EFAULT);
if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
return -ENOMEM;
+
+ memset(entry, 0, sizeof(*entry));
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
type = (u32) request.type;
@@ -237,6 +239,8 @@ int drm_agp_bind(struct inode *inode, struct file *filp, unsigned int cmd,
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;
}
@@ -254,8 +258,10 @@ int drm_agp_free(struct inode *inode, struct file *filp, unsigned int cmd,
if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
return -EINVAL;
if (entry->bound) drm_unbind_agp(entry->memory);
- entry->prev->next = entry->next;
- entry->next->prev = entry->prev;
+
+ if (entry->prev) entry->prev->next = entry->next;
+ else dev->agp->memory = entry->next;
+ if (entry->next) entry->next->prev = entry->prev;
drm_free_agp(entry->memory, entry->pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return 0;
@@ -269,15 +275,12 @@ drm_agp_head_t *drm_agp_init(void)
for (fill = &drm_agp_fill[0]; fill->name; fill++) {
char *n = (char *)fill->name;
-#if 0
- *fill->f = (drm_agp_func_u)get_module_symbol(NULL, n);
-#endif
*fill->f = (drm_agp_func_u)get_module_symbol(NULL, n);
- printk("%s resolves to 0x%08lx\n", n, (*fill->f).address);
+ DRM_DEBUG("%s resolves to 0x%08lx\n", n, (*fill->f).address);
if (!(*fill->f).address) agp_available = 0;
}
- printk("agp_available = %d\n", agp_available);
+ DRM_DEBUG("agp_available = %d\n", agp_available);
if (agp_available) {
if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h
index 3af5d5b1e..c63d0f637 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h
@@ -1,8 +1,7 @@
/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
- * Revised: Mon Feb 14 00:15:23 2000 by kevin@precisioninsight.com
*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -71,9 +70,10 @@ typedef struct drm_clip_rect {
unsigned short y2;
} drm_clip_rect_t;
-/* Seperate include files for the i810/mga specific structures */
+/* Seperate include files for the i810/mga/r128 specific structures */
#include "mga_drm.h"
#include "i810_drm.h"
+#include "r128_drm.h"
typedef struct drm_version {
int version_major; /* Major version */
@@ -341,12 +341,23 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t)
#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t)
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x45, drm_lock_t )
+#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
/* I810 specific ioctls */
#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t)
#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t)
-#define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t)
+#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t)
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
+#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46)
+
+/* Rage 128 specific ioctls */
+#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
+#define DRM_IOCTL_R128_RESET DRM_IO( 0x41)
+#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42)
+#define DRM_IOCTL_R128_CCEIDL DRM_IO( 0x43)
+#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t)
+#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t)
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h
index 312fba36f..43670e28a 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h
@@ -1,8 +1,7 @@
/* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*-
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
- * Revised: Sun Feb 13 23:34:30 2000 by kevin@precisioninsight.com
*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -48,8 +47,12 @@
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
+#ifdef DRM_AGP
+#include <linux/types.h>
+#include <linux/agp_backend.h>
+#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-#include <asm/spinlock.h>
+#include <linux/tqueue.h>
#include <linux/poll.h>
#endif
#include "drm.h"
@@ -69,21 +72,27 @@
#define DRM_FLAG_DEBUG 0x01
#define DRM_FLAG_NOCTX 0x02
-#define DRM_MEM_DMA 0
-#define DRM_MEM_SAREA 1
-#define DRM_MEM_DRIVER 2
-#define DRM_MEM_MAGIC 3
-#define DRM_MEM_IOCTLS 4
-#define DRM_MEM_MAPS 5
-#define DRM_MEM_VMAS 6
-#define DRM_MEM_BUFS 7
-#define DRM_MEM_SEGS 8
-#define DRM_MEM_PAGES 9
-#define DRM_MEM_FILES 10
-#define DRM_MEM_QUEUES 11
-#define DRM_MEM_CMDS 12
-#define DRM_MEM_MAPPINGS 13
-#define DRM_MEM_BUFLISTS 14
+#define DRM_MEM_DMA 0
+#define DRM_MEM_SAREA 1
+#define DRM_MEM_DRIVER 2
+#define DRM_MEM_MAGIC 3
+#define DRM_MEM_IOCTLS 4
+#define DRM_MEM_MAPS 5
+#define DRM_MEM_VMAS 6
+#define DRM_MEM_BUFS 7
+#define DRM_MEM_SEGS 8
+#define DRM_MEM_PAGES 9
+#define DRM_MEM_FILES 10
+#define DRM_MEM_QUEUES 11
+#define DRM_MEM_CMDS 12
+#define DRM_MEM_MAPPINGS 13
+#define DRM_MEM_BUFLISTS 14
+#define DRM_MEM_AGPLISTS 15
+#define DRM_MEM_TOTALAGP 16
+#define DRM_MEM_BOUNDAGP 17
+#define DRM_MEM_CTXBITMAP 18
+
+#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
/* Backward compatibility section */
/* _PAGE_WT changed to _PAGE_PWT in 2.2.6 */
@@ -218,8 +227,8 @@ typedef struct drm_magic_entry {
} drm_magic_entry_t;
typedef struct drm_magic_head {
- struct drm_magic_entry *head;
- struct drm_magic_entry *tail;
+ struct drm_magic_entry *head;
+ struct drm_magic_entry *tail;
} drm_magic_head_t;
typedef struct drm_vma_entry {
@@ -235,6 +244,7 @@ typedef struct drm_buf {
int used; /* Amount of buffer in use (for DMA) */
unsigned long offset; /* Byte offset (used internally) */
void *address; /* Address of buffer */
+ unsigned long bus_address; /* Bus address of buffer */
struct drm_buf *next; /* Kernel-only: used for free list */
__volatile__ int waiting; /* On kernel DMA queue */
__volatile__ int pending; /* On hardware DMA queue */
@@ -250,12 +260,16 @@ typedef struct drm_buf {
DRM_LIST_PRIO = 4,
DRM_LIST_RECLAIM = 5
} list; /* Which list we're on */
+
#if DRM_DMA_HISTOGRAM
cycles_t time_queued; /* Queued to kernel DMA queue */
cycles_t time_dispatched; /* Dispatched to hardware */
cycles_t time_completed; /* Completed by hardware */
cycles_t time_freed; /* Back on freelist */
#endif
+
+ int dev_priv_size; /* Size of buffer private stoarge */
+ void *dev_private; /* Per-buffer private storage */
} drm_buf_t;
#if DRM_DMA_HISTOGRAM
@@ -376,6 +390,9 @@ typedef struct drm_device_dma {
int page_count;
unsigned long *pagelist;
unsigned long byte_count;
+ enum {
+ _DRM_DMA_USE_AGP = 0x01
+ } flags;
/* DMA support */
drm_buf_t *this_buffer; /* Buffer being sent */
@@ -384,6 +401,41 @@ typedef struct drm_device_dma {
wait_queue_head_t waiting; /* Processes waiting on free bufs */
} drm_device_dma_t;
+#ifdef DRM_AGP
+typedef struct drm_agp_mem {
+ unsigned long handle;
+ agp_memory *memory;
+ unsigned long bound; /* address */
+ int pages;
+ struct drm_agp_mem *prev;
+ struct drm_agp_mem *next;
+} drm_agp_mem_t;
+
+typedef struct drm_agp_head {
+ agp_kern_info agp_info;
+ const char *chipset;
+ drm_agp_mem_t *memory;
+ unsigned long mode;
+ int enabled;
+ int acquired;
+ unsigned long base;
+ int agp_mtrr;
+} drm_agp_head_t;
+
+typedef struct {
+ void (*free_memory)(agp_memory *);
+ agp_memory *(*allocate_memory)(size_t, u32);
+ int (*bind_memory)(agp_memory *, off_t);
+ int (*unbind_memory)(agp_memory *);
+ void (*enable)(u32);
+ int (*acquire)(void);
+ void (*release)(void);
+ void (*copy_info)(agp_kern_info *);
+} drm_agp_func_t;
+
+extern drm_agp_func_t drm_agp;
+#endif
+
typedef struct drm_device {
const char *name; /* Simple driver name */
char *unique; /* Unique identifier: e.g., busid */
@@ -462,6 +514,12 @@ typedef struct drm_device {
struct fasync_struct *buf_async;/* Processes waiting for SIGIO */
wait_queue_head_t buf_readers; /* Processes waiting to read */
wait_queue_head_t buf_writers; /* Processes waiting to ctx switch */
+
+#ifdef DRM_AGP
+ drm_agp_head_t *agp;
+#endif
+ unsigned long *ctx_bitmap;
+ void *dev_private;
} drm_device_t;
@@ -533,6 +591,14 @@ extern void drm_free_pages(unsigned long address, int order,
extern void *drm_ioremap(unsigned long offset, unsigned long size);
extern void drm_ioremapfree(void *pt, unsigned long size);
+#ifdef DRM_AGP
+extern agp_memory *drm_alloc_agp(int pages, u32 type);
+extern int drm_free_agp(agp_memory *handle, int pages);
+extern int drm_bind_agp(agp_memory *handle, unsigned int start);
+extern int drm_unbind_agp(agp_memory *handle);
+#endif
+
+
/* Buffer management support (bufs.c) */
extern int drm_order(unsigned long size);
extern int drm_addmap(struct inode *inode, struct file *filp,
@@ -642,5 +708,32 @@ extern int drm_flush_unblock(drm_device_t *dev, int context,
drm_lock_flags_t flags);
extern int drm_flush_block_and_flush(drm_device_t *dev, int context,
drm_lock_flags_t flags);
+
+ /* Context Bitmap support (ctxbitmap.c) */
+extern int drm_ctxbitmap_init(drm_device_t *dev);
+extern void drm_ctxbitmap_cleanup(drm_device_t *dev);
+extern int drm_ctxbitmap_next(drm_device_t *dev);
+extern void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle);
+
+#ifdef DRM_AGP
+ /* AGP/GART support (agpsupport.c) */
+extern drm_agp_head_t *drm_agp_init(void);
+extern int drm_agp_acquire(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_release(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_enable(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_info(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_alloc(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_free(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_unbind(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_bind(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+#endif
#endif
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_bufs.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_bufs.c
index 49455b434..9737ae92d 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_bufs.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_bufs.c
@@ -32,152 +32,28 @@
#define __NO_VERSION__
#include "drmP.h"
+#include "i810_drv.h"
#include "linux/un.h"
int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_desc_t request;
- drm_buf_entry_t *entry;
- drm_buf_t *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;
-
- if (!dma) return -EINVAL;
-
- copy_from_user_ret(&request,
- (drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
-
- count = request.count;
- order = drm_order(request.size);
- size = 1 << order;
- agp_offset = request.agp_start;
- 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;
-
- 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);
-
- down(&dev->struct_sem);
- entry = &dma->bufs[order];
- if (entry->buf_count) {
- up(&dev->struct_sem);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM; /* May only call once for each order */
- }
-
- entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
- DRM_MEM_BUFS);
- if (!entry->buflist) {
- up(&dev->struct_sem);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
- memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
- entry->buf_size = size;
- entry->page_order = page_order;
-
- while(entry->buf_count < count) {
- 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 = agp_offset - dev->agp->base + offset;/* ?? */
- buf->bus_address = agp_offset + offset;
- buf->address = agp_offset + offset + dev->agp->base;
- buf->next = NULL;
- buf->waiting = 0;
- buf->pending = 0;
- init_waitqueue_head(&buf->dma_wait);
- buf->pid = 0;
-#if DRM_DMA_HISTOGRAM
- buf->time_queued = 0;
- buf->time_dispatched = 0;
- buf->time_completed = 0;
- buf->time_freed = 0;
-#endif
- DRM_DEBUG("buffer %d @ %p\n",
- entry->buf_count, buf->address);
- }
- byte_count += PAGE_SIZE << page_order;
- }
-
- dma->buflist = drm_realloc(dma->buflist,
- dma->buf_count * sizeof(*dma->buflist),
- (dma->buf_count + entry->buf_count)
- * sizeof(*dma->buflist),
- DRM_MEM_BUFS);
- for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
- dma->buflist[i] = &entry->buflist[i - dma->buf_count];
-
- dma->buf_count += entry->buf_count;
- dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
-
- drm_freelist_create(&entry->freelist, entry->buf_count);
- for (i = 0; i < entry->buf_count; i++) {
- drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
- }
-
- up(&dev->struct_sem);
-
- request.count = entry->buf_count;
- request.size = size;
-
- copy_to_user_ret((drm_buf_desc_t *)arg,
- &request,
- sizeof(request),
- -EFAULT);
-
- atomic_dec(&dev->buf_alloc);
- return 0;
-}
-
-int i810_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_desc_t request;
- int count;
- int order;
- int size;
- int total;
- int page_order;
- drm_buf_entry_t *entry;
- unsigned long page;
- drm_buf_t *buf;
- int alignment;
- unsigned long offset;
- int i;
- int byte_count;
- int page_count;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t request;
+ drm_buf_entry_t *entry;
+ drm_buf_t *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;
if (!dma) return -EINVAL;
@@ -186,20 +62,17 @@ int i810_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd,
sizeof(request),
-EFAULT);
- 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 */
-
+ count = request.count;
+ order = drm_order(request.size);
+ size = 1 << order;
+ agp_offset = request.agp_start;
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;
-
+ total = PAGE_SIZE << page_order;
+ byte_count = 0;
+
+ 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);
@@ -207,15 +80,15 @@ int i810_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd,
}
atomic_inc(&dev->buf_alloc);
spin_unlock(&dev->count_lock);
-
+
down(&dev->struct_sem);
entry = &dma->bufs[order];
if (entry->buf_count) {
up(&dev->struct_sem);
atomic_dec(&dev->buf_alloc);
- return -ENOMEM; /* May only call once for each order */
+ return -ENOMEM; /* May only call once for each order */
}
-
+
entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (!entry->buflist) {
@@ -224,69 +97,45 @@ int i810_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd,
return -ENOMEM;
}
memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
- entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
- DRM_MEM_SEGS);
- if (!entry->seglist) {
- drm_free(entry->buflist,
- count * sizeof(*entry->buflist),
- DRM_MEM_BUFS);
- up(&dev->struct_sem);
- atomic_dec(&dev->buf_alloc);
- return -ENOMEM;
- }
- memset(entry->seglist, 0, count * sizeof(*entry->seglist));
-
- dma->pagelist = drm_realloc(dma->pagelist,
- dma->page_count * sizeof(*dma->pagelist),
- (dma->page_count + (count << page_order))
- * sizeof(*dma->pagelist),
- DRM_MEM_PAGES);
- DRM_DEBUG("pagelist: %d entries\n",
- dma->page_count + (count << page_order));
-
-
- entry->buf_size = size;
+
+ entry->buf_size = size;
entry->page_order = page_order;
- byte_count = 0;
- page_count = 0;
- while (entry->buf_count < count) {
- if (!(page = drm_alloc_pages(page_order, DRM_MEM_DMA))) break;
- entry->seglist[entry->seg_count++] = page;
- for (i = 0; i < (1 << page_order); i++) {
- DRM_DEBUG("page %d @ 0x%08lx\n",
- dma->page_count + page_count,
- page + PAGE_SIZE * i);
- dma->pagelist[dma->page_count + page_count++]
- = page + 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 *)(page + offset);
- buf->next = NULL;
- buf->waiting = 0;
- buf->pending = 0;
- init_waitqueue_head(&buf->dma_wait);
- buf->pid = 0;
+ 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 = offset;
+ buf->bus_address = dev->agp->base + agp_offset + offset;
+ buf->address = (void *)(agp_offset + offset + dev->agp->base);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+ init_waitqueue_head(&buf->dma_wait);
+ buf->pid = 0;
+
+ buf->dev_private = drm_alloc(sizeof(drm_i810_buf_priv_t),
+ DRM_MEM_BUFS);
+ buf->dev_priv_size = sizeof(drm_i810_buf_priv_t);
+ memset(buf->dev_private, 0, sizeof(drm_i810_buf_priv_t));
+
#if DRM_DMA_HISTOGRAM
- buf->time_queued = 0;
- buf->time_dispatched = 0;
- buf->time_completed = 0;
- buf->time_freed = 0;
+ buf->time_queued = 0;
+ buf->time_dispatched = 0;
+ buf->time_completed = 0;
+ buf->time_freed = 0;
#endif
- DRM_DEBUG("buffer %d @ %p\n",
- entry->buf_count, buf->address);
- }
+ offset = offset + alignment;
+ entry->buf_count++;
byte_count += PAGE_SIZE << page_order;
+
+ DRM_DEBUG("buffer %d @ %p\n",
+ entry->buf_count, buf->address);
}
-
+
dma->buflist = drm_realloc(dma->buflist,
dma->buf_count * sizeof(*dma->buflist),
(dma->buf_count + entry->buf_count)
@@ -294,45 +143,43 @@ int i810_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_MEM_BUFS);
for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
dma->buflist[i] = &entry->buflist[i - dma->buf_count];
-
- 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);
-
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
drm_freelist_create(&entry->freelist, entry->buf_count);
for (i = 0; i < entry->buf_count; i++) {
drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
}
-
+
up(&dev->struct_sem);
-
+
request.count = entry->buf_count;
request.size = size;
-
+
copy_to_user_ret((drm_buf_desc_t *)arg,
&request,
sizeof(request),
-EFAULT);
-
+
atomic_dec(&dev->buf_alloc);
+ dma->flags = _DRM_DMA_USE_AGP;
return 0;
}
int i810_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
- drm_buf_desc_t request;
+ drm_buf_desc_t request;
- copy_from_user_ret(&request,
- (drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ copy_from_user_ret(&request,
+ (drm_buf_desc_t *)arg,
+ sizeof(request),
+ -EFAULT);
- if(request.flags & _DRM_AGP_BUFFER)
- return i810_addbufs_agp(inode, filp, cmd, arg);
- else
- return i810_addbufs_pci(inode, filp, cmd, arg);
+ if(request.flags & _DRM_AGP_BUFFER)
+ return i810_addbufs_agp(inode, filp, cmd, arg);
+ else
+ return -EINVAL;
}
int i810_infobufs(struct inode *inode, struct file *filp, unsigned int cmd,
@@ -486,99 +333,3 @@ int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd,
return 0;
}
-int i810_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_device_dma_t *dma = dev->dma;
- int retcode = 0;
- const int zero = 0;
- unsigned long virtual;
- unsigned long address;
- drm_buf_map_t request;
- int i;
-
- if (!dma) return -EINVAL;
-
- DRM_DEBUG("\n");
-
- 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);
-
- copy_from_user_ret(&request,
- (drm_buf_map_t *)arg,
- sizeof(request),
- -EFAULT);
-
- if (request.count >= dma->buf_count) {
- if(dma->flags & _DRM_DMA_USE_AGP) {
- /* This is an ugly vicious hack */
- drm_map_t *map = NULL;
- for(i = 0; i < dev->map_count; i++) {
- map = dev->maplist[i];
- if(map->type == _DRM_AGP) break;
- }
- if (i >= dev->map_count || !map) {
- retcode = -EINVAL;
- goto done;
- }
-
- virtual = do_mmap(filp, 0, map->size, PROT_READ|PROT_WRITE,
- MAP_SHARED, (unsigned long)map->handle);
- }
- else {
- virtual = do_mmap(filp, 0, dma->byte_count,
- PROT_READ|PROT_WRITE, MAP_SHARED, 0);
- }
- if (virtual > -1024UL) {
- /* Real error */
- retcode = (signed long)virtual;
- goto done;
- }
- request.virtual = (void *)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);
-
- copy_to_user_ret((drm_buf_map_t *)arg,
- &request,
- sizeof(request),
- -EFAULT);
-
- return retcode;
-}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c
index 09959b657..f041f2098 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c
@@ -25,8 +25,9 @@
*
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
* Jeff Hartmann <jhartmann@precisioninsight.com>
+ * Keith Whitwell <keithw@precisioninsight.com>
*
- * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c,v 1.1 2000/02/11 17:26:04 dawes Exp $
+ * $XFree86$
*
*/
@@ -36,6 +37,13 @@
#include <linux/interrupt.h> /* For task queue support */
+#define I810_BUF_FREE 2
+#define I810_BUF_CLIENT 1
+#define I810_BUF_HARDWARE 0
+
+#define I810_BUF_UNMAPPED 0
+#define I810_BUF_MAPPED 1
+
#define I810_REG(reg) 2
#define I810_BASE(reg) ((unsigned long) \
dev->maplist[I810_REG(reg)]->handle)
@@ -43,544 +51,835 @@
#define I810_DEREF(reg) *(__volatile__ int *)I810_ADDR(reg)
#define I810_READ(reg) I810_DEREF(reg)
#define I810_WRITE(reg,val) do { I810_DEREF(reg) = val; } while (0)
-
-void i810_dma_init(drm_device_t *dev)
+#define I810_DEREF16(reg) *(__volatile__ u16 *)I810_ADDR(reg)
+#define I810_READ16(reg) I810_DEREF16(reg)
+#define I810_WRITE16(reg,val) do { I810_DEREF16(reg) = val; } while (0)
+
+#define RING_LOCALS unsigned int outring, ringmask; volatile char *virt;
+
+#define BEGIN_LP_RING(n) do { \
+ if (I810_VERBOSE) \
+ DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \
+ n, __FUNCTION__); \
+ if (dev_priv->ring.space < n*4) \
+ i810_wait_ring(dev, n*4); \
+ dev_priv->ring.space -= n*4; \
+ outring = dev_priv->ring.tail; \
+ ringmask = dev_priv->ring.tail_mask; \
+ virt = dev_priv->ring.virtual_start; \
+} while (0)
+
+#define ADVANCE_LP_RING() do { \
+ if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \
+ dev_priv->ring.tail = outring; \
+ I810_WRITE(LP_RING + RING_TAIL, outring); \
+} while(0)
+
+#define OUT_RING(n) do { \
+ if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
+ *(volatile unsigned int *)(virt + outring) = n; \
+ outring += 4; \
+ outring &= ringmask; \
+} while (0);
+
+static inline void i810_print_status_page(drm_device_t *dev)
{
- printk(KERN_INFO "i810_dma_init\n");
+ drm_device_dma_t *dma = dev->dma;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ u32 *temp = (u32 *)dev_priv->hw_status_page;
+ int i;
+
+ DRM_DEBUG( "hw_status: Interrupt Status : %x\n", temp[0]);
+ DRM_DEBUG( "hw_status: LpRing Head ptr : %x\n", temp[1]);
+ DRM_DEBUG( "hw_status: IRing Head ptr : %x\n", temp[2]);
+ DRM_DEBUG( "hw_status: Reserved : %x\n", temp[3]);
+ DRM_DEBUG( "hw_status: Driver Counter : %d\n", temp[5]);
+ for(i = 6; i < dma->buf_count + 6; i++) {
+ DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]);
+ }
}
-void i810_dma_cleanup(drm_device_t *dev)
+static drm_buf_t *i810_freelist_get(drm_device_t *dev)
{
- printk(KERN_INFO "i810_dma_cleanup\n");
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+ int used;
+
+ /* Linear search might not be the best solution */
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[ i ];
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ /* In use is already a pointer */
+ used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
+ I810_BUF_CLIENT);
+ if(used == I810_BUF_FREE) {
+ return buf;
+ }
+ }
+ return NULL;
}
-static inline void i810_dma_dispatch(drm_device_t *dev, unsigned long address,
- unsigned long length)
+/* This should only be called if the buffer is not sent to the hardware
+ * yet, the hardware updates in use for us once its on the ring buffer.
+ */
+
+static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
{
- printk(KERN_INFO "i810_dma_dispatch\n");
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ int used;
+
+ /* In use is already a pointer */
+ used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
+ if(used != I810_BUF_CLIENT) {
+ DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
+ return -EINVAL;
+ }
+
+ return 0;
}
-static inline void i810_dma_quiescent(drm_device_t *dev)
+static struct file_operations i810_buffer_fops = {
+ open: i810_open,
+ flush: drm_flush,
+ release: i810_release,
+ ioctl: i810_ioctl,
+ mmap: i810_mmap_buffers,
+ read: drm_read,
+ fasync: drm_fasync,
+ poll: drm_poll,
+};
+
+int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_buf_t *buf = dev_priv->mmap_buffer;
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+ vma->vm_flags |= (VM_IO | VM_DONTCOPY);
+ vma->vm_file = filp;
+
+ buf_priv->currently_mapped = I810_BUF_MAPPED;
+
+ if (remap_page_range(vma->vm_start,
+ VM_OFFSET(vma),
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot)) return -EAGAIN;
+ return 0;
}
-static inline void i810_dma_ready(drm_device_t *dev)
+static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
{
- i810_dma_quiescent(dev);
- printk(KERN_INFO "i810_dma_ready\n");
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ struct file_operations *old_fops;
+ int retcode = 0;
+
+ if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
+ down(&current->mm->mmap_sem);
+ old_fops = filp->f_op;
+ filp->f_op = &i810_buffer_fops;
+ dev_priv->mmap_buffer = buf;
+ buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ buf->bus_address);
+ dev_priv->mmap_buffer = NULL;
+ filp->f_op = old_fops;
+ if ((unsigned long)buf_priv->virtual > -1024UL) {
+ /* Real error */
+ DRM_DEBUG("mmap error\n");
+ retcode = (signed int)buf_priv->virtual;
+ buf_priv->virtual = 0;
+ }
+ up(&current->mm->mmap_sem);
+ return retcode;
}
-static inline int i810_dma_is_ready(drm_device_t *dev)
+static int i810_unmap_buffer(drm_buf_t *buf)
{
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ int retcode = 0;
- i810_dma_quiescent(dev);
+ if(buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL;
+ down(&current->mm->mmap_sem);
+ retcode = do_munmap((unsigned long)buf_priv->virtual,
+ (size_t) buf->total);
+ buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+ buf_priv->virtual = 0;
+ up(&current->mm->mmap_sem);
- printk(KERN_INFO "i810_dma_is_ready\n");
- return 1;
+ return retcode;
}
-
-static void i810_dma_service(int irq, void *device, struct pt_regs *regs)
+static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
+ struct file *filp)
{
- drm_device_t *dev = (drm_device_t *)device;
- drm_device_dma_t *dma = dev->dma;
-
- atomic_inc(&dev->total_irq);
- if (i810_dma_is_ready(dev)) {
- /* Free previous buffer */
- if (test_and_set_bit(0, &dev->dma_flag)) {
- atomic_inc(&dma->total_missed_free);
- return;
- }
- if (dma->this_buffer) {
- drm_free_buffer(dev, dma->this_buffer);
- dma->this_buffer = NULL;
- }
- clear_bit(0, &dev->dma_flag);
-
- /* Dispatch new buffer */
- queue_task(&dev->tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ drm_file_t *priv = filp->private_data;
+ drm_buf_t *buf;
+ drm_i810_buf_priv_t *buf_priv;
+ int retcode = 0;
+
+ buf = i810_freelist_get(dev);
+ if (!buf) {
+ retcode = -ENOMEM;
+ DRM_DEBUG("%s retcode %d\n", __FUNCTION__, retcode);
+ goto out_get_buf;
+ }
+
+ retcode = i810_map_buffer(buf, filp);
+ if(retcode) {
+ i810_freelist_put(dev, buf);
+ DRM_DEBUG("mapbuf failed in %s retcode %d\n",
+ __FUNCTION__, retcode);
+ goto out_get_buf;
}
+ buf->pid = priv->pid;
+ buf_priv = buf->dev_private;
+ d->granted = 1;
+ d->request_idx = buf->idx;
+ d->request_size = buf->total;
+ d->virtual = buf_priv->virtual;
+
+out_get_buf:
+ return retcode;
}
-/* Only called by i810_dma_schedule. */
-static int i810_do_dma(drm_device_t *dev, int locked)
+static unsigned long i810_alloc_page(drm_device_t *dev)
{
- unsigned long address;
- unsigned long length;
- drm_buf_t *buf;
- int retcode = 0;
- drm_device_dma_t *dma = dev->dma;
-#if DRM_DMA_HISTOGRAM
- cycles_t dma_start, dma_stop;
-#endif
-
- if (test_and_set_bit(0, &dev->dma_flag)) {
- atomic_inc(&dma->total_missed_dma);
- return -EBUSY;
- }
+ unsigned long address;
+
+ address = __get_free_page(GFP_KERNEL);
+ if(address == 0UL)
+ return 0;
-#if DRM_DMA_HISTOGRAM
- dma_start = get_cycles();
-#endif
-
- if (!dma->next_buffer) {
- DRM_ERROR("No next_buffer\n");
- clear_bit(0, &dev->dma_flag);
- return -EINVAL;
- }
+ atomic_inc(&mem_map[MAP_NR((void *) address)].count);
+ set_bit(PG_locked, &mem_map[MAP_NR((void *) address)].flags);
+
+ return address;
+}
- buf = dma->next_buffer;
- address = (unsigned long)buf->bus_address;
- length = buf->used;
+static void i810_free_page(drm_device_t *dev, unsigned long page)
+{
+ if(page == 0UL)
+ return;
+ atomic_dec(&mem_map[MAP_NR((void *) page)].count);
+ clear_bit(PG_locked, &mem_map[MAP_NR((void *) page)].flags);
+ wake_up(&mem_map[MAP_NR((void *) page)].wait);
+ free_page(page);
+ return;
+}
- DRM_DEBUG("context %d, buffer %d (%ld bytes)\n",
- buf->context, buf->idx, length);
-
- if (buf->list == DRM_LIST_RECLAIM) {
- drm_clear_next_buffer(dev);
- drm_free_buffer(dev, buf);
- clear_bit(0, &dev->dma_flag);
- return -EINVAL;
- }
-
- if (!length) {
- DRM_ERROR("0 length buffer\n");
- drm_clear_next_buffer(dev);
- drm_free_buffer(dev, buf);
- clear_bit(0, &dev->dma_flag);
- return 0;
- }
-
- if (!i810_dma_is_ready(dev)) {
- clear_bit(0, &dev->dma_flag);
- return -EBUSY;
- }
+static int i810_dma_cleanup(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
- if (buf->while_locked) {
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
- DRM_ERROR("Dispatching buffer %d from pid %d"
- " \"while locked\", but no lock held\n",
- buf->idx, buf->pid);
+ if(dev->dev_private) {
+ int i;
+ drm_i810_private_t *dev_priv =
+ (drm_i810_private_t *) dev->dev_private;
+
+ if(dev_priv->ring.virtual_start) {
+ drm_ioremapfree((void *) dev_priv->ring.virtual_start,
+ dev_priv->ring.Size);
+ }
+ if(dev_priv->hw_status_page != 0UL) {
+ i810_free_page(dev, dev_priv->hw_status_page);
+ /* Need to rewrite hardware status page */
+ I810_WRITE(0x02080, 0x1ffff000);
}
- } else {
- if (!locked && !drm_lock_take(&dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- atomic_inc(&dma->total_missed_lock);
- clear_bit(0, &dev->dma_flag);
- return -EBUSY;
+ drm_free(dev->dev_private, sizeof(drm_i810_private_t),
+ DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[ i ];
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ drm_ioremapfree(buf_priv->kernel_virtual, buf->total);
}
}
+ return 0;
+}
- if (dev->last_context != buf->context
- && !(dev->queuelist[buf->context]->flags
- & _DRM_CONTEXT_PRESERVED)) {
- /* PRE: dev->last_context != buf->context */
- if (drm_context_switch(dev, dev->last_context, buf->context)) {
- drm_clear_next_buffer(dev);
- drm_free_buffer(dev, buf);
+static int i810_wait_ring(drm_device_t *dev, int n)
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
+ int iters = 0;
+ unsigned long end;
+ unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+
+ end = jiffies + (HZ*3);
+ while (ring->space < n) {
+ int i;
+
+ ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring->space = ring->head - (ring->tail+8);
+ if (ring->space < 0) ring->space += ring->Size;
+
+ if (ring->head != last_head)
+ end = jiffies + (HZ*3);
+
+ iters++;
+ if((signed)(end - jiffies) <= 0) {
+ DRM_ERROR("space: %d wanted %d\n", ring->space, n);
+ DRM_ERROR("lockup\n");
+ goto out_wait_ring;
}
- retcode = -EBUSY;
- goto cleanup;
-
- /* POST: we will wait for the context
- switch and will dispatch on a later call
- when dev->last_context == buf->context.
- NOTE WE HOLD THE LOCK THROUGHOUT THIS
- TIME! */
- }
-
- drm_clear_next_buffer(dev);
- buf->pending = 1;
- buf->waiting = 0;
- buf->list = DRM_LIST_PEND;
-#if DRM_DMA_HISTOGRAM
- buf->time_dispatched = get_cycles();
-#endif
-
- i810_dma_dispatch(dev, address, length);
- drm_free_buffer(dev, dma->this_buffer);
- dma->this_buffer = buf;
-
- atomic_add(length, &dma->total_bytes);
- atomic_inc(&dma->total_dmas);
- if (!buf->while_locked && !dev->context_flag && !locked) {
- if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("\n");
- }
+ for (i = 0 ; i < 2000 ; i++) ;
}
-cleanup:
-
- clear_bit(0, &dev->dma_flag);
-
-#if DRM_DMA_HISTOGRAM
- dma_stop = get_cycles();
- atomic_inc(&dev->histo.dma[drm_histogram_slot(dma_stop - dma_start)]);
-#endif
- return retcode;
+out_wait_ring:
+ return iters;
}
-static void i810_dma_schedule_timer_wrapper(unsigned long dev)
+static void i810_kernel_lost_context(drm_device_t *dev)
{
- i810_dma_schedule((drm_device_t *)dev, 0);
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
+
+ ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring->tail = I810_READ(LP_RING + RING_TAIL);
+ ring->space = ring->head - (ring->tail+8);
+ if (ring->space < 0) ring->space += ring->Size;
}
-static void i810_dma_schedule_tq_wrapper(void *dev)
+static int i810_freelist_init(drm_device_t *dev)
{
- i810_dma_schedule(dev, 0);
+ drm_device_dma_t *dma = dev->dma;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ int my_idx = 24;
+ u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
+ int i;
+
+ if(dma->buf_count > 1019) {
+ /* Not enough space in the status page for the freelist */
+ return -EINVAL;
+ }
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[ i ];
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+ buf_priv->in_use = hw_status++;
+ buf_priv->my_use_idx = my_idx;
+ my_idx += 4;
+
+ *buf_priv->in_use = I810_BUF_FREE;
+
+ buf_priv->kernel_virtual = drm_ioremap(buf->bus_address,
+ buf->total);
+ }
+ return 0;
}
-int i810_dma_schedule(drm_device_t *dev, int locked)
+static int i810_dma_initialize(drm_device_t *dev,
+ drm_i810_private_t *dev_priv,
+ drm_i810_init_t *init)
{
- int next;
- drm_queue_t *q;
- drm_buf_t *buf;
- int retcode = 0;
- int processed = 0;
- int missed;
- int expire = 20;
- drm_device_dma_t *dma = dev->dma;
-#if DRM_DMA_HISTOGRAM
- cycles_t schedule_start;
-#endif
+ drm_map_t *sarea_map;
- if (test_and_set_bit(0, &dev->interrupt_flag)) {
- /* Not reentrant */
- atomic_inc(&dma->total_missed_sched);
- return -EBUSY;
+ dev->dev_private = (void *) dev_priv;
+ memset(dev_priv, 0, sizeof(drm_i810_private_t));
+
+ if (init->ring_map_idx >= dev->map_count ||
+ init->buffer_map_idx >= dev->map_count) {
+ i810_dma_cleanup(dev);
+ DRM_ERROR("ring_map or buffer_map are invalid\n");
+ return -EINVAL;
+ }
+
+ dev_priv->ring_map_idx = init->ring_map_idx;
+ dev_priv->buffer_map_idx = init->buffer_map_idx;
+ sarea_map = dev->maplist[0];
+ dev_priv->sarea_priv = (drm_i810_sarea_t *)
+ ((u8 *)sarea_map->handle +
+ init->sarea_priv_offset);
+
+ atomic_set(&dev_priv->flush_done, 0);
+ init_waitqueue_head(&dev_priv->flush_queue);
+
+ dev_priv->ring.Start = init->ring_start;
+ dev_priv->ring.End = init->ring_end;
+ dev_priv->ring.Size = init->ring_size;
+
+ dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
+ init->ring_start,
+ init->ring_size);
+
+ dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+ if (dev_priv->ring.virtual_start == NULL) {
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not ioremap virtual address for"
+ " ring buffer\n");
+ return -ENOMEM;
}
- missed = atomic_read(&dma->total_missed_sched);
-#if DRM_DMA_HISTOGRAM
- schedule_start = get_cycles();
-#endif
+ dev_priv->w = init->w;
+ dev_priv->h = init->h;
+ dev_priv->pitch = init->pitch;
+ dev_priv->back_offset = init->back_offset;
+ dev_priv->depth_offset = init->depth_offset;
-again:
- if (dev->context_flag) {
- clear_bit(0, &dev->interrupt_flag);
- return -EBUSY;
+ dev_priv->front_di1 = init->front_offset | init->pitch_bits;
+ dev_priv->back_di1 = init->back_offset | init->pitch_bits;
+ dev_priv->zi1 = init->depth_offset | init->pitch_bits;
+
+
+ /* Program Hardware Status Page */
+ dev_priv->hw_status_page = i810_alloc_page(dev);
+ memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
+ if(dev_priv->hw_status_page == 0UL) {
+ i810_dma_cleanup(dev);
+ DRM_ERROR("Can not allocate hardware status page\n");
+ return -ENOMEM;
}
- if (dma->next_buffer) {
- /* Unsent buffer that was previously
- selected, but that couldn't be sent
- because the lock could not be obtained
- or the DMA engine wasn't ready. Try
- again. */
- atomic_inc(&dma->total_tried);
- if (!(retcode = i810_do_dma(dev, locked))) {
- atomic_inc(&dma->total_hit);
- ++processed;
- }
- } else {
- do {
- next = drm_select_queue(dev,
- i810_dma_schedule_timer_wrapper);
- if (next >= 0) {
- q = dev->queuelist[next];
- buf = drm_waitlist_get(&q->waitlist);
- dma->next_buffer = buf;
- dma->next_queue = q;
- if (buf && buf->list == DRM_LIST_RECLAIM) {
- drm_clear_next_buffer(dev);
- drm_free_buffer(dev, buf);
- }
- }
- } while (next >= 0 && !dma->next_buffer);
- if (dma->next_buffer) {
- if (!(retcode = i810_do_dma(dev, locked))) {
- ++processed;
- }
- }
+ DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
+
+ I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
+ DRM_DEBUG("Enabled hardware status page\n");
+
+ /* Now we need to init our freelist */
+ if(i810_freelist_init(dev) != 0) {
+ i810_dma_cleanup(dev);
+ DRM_ERROR("Not enough space in the status page for"
+ " the freelist\n");
+ return -ENOMEM;
}
+ return 0;
+}
- if (--expire) {
- if (missed != atomic_read(&dma->total_missed_sched)) {
- atomic_inc(&dma->total_lost);
- if (i810_dma_is_ready(dev)) goto again;
- }
- if (processed && i810_dma_is_ready(dev)) {
- atomic_inc(&dma->total_lost);
- processed = 0;
- goto again;
- }
- }
+int i810_dma_init(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i810_private_t *dev_priv;
+ drm_i810_init_t init;
+ int retcode = 0;
- clear_bit(0, &dev->interrupt_flag);
+ copy_from_user_ret(&init, (drm_i810_init_t *)arg,
+ sizeof(init), -EFAULT);
-#if DRM_DMA_HISTOGRAM
- atomic_inc(&dev->histo.schedule[drm_histogram_slot(get_cycles()
- - schedule_start)]);
-#endif
- return retcode;
+ switch(init.func) {
+ case I810_INIT_DMA:
+ dev_priv = drm_alloc(sizeof(drm_i810_private_t),
+ DRM_MEM_DRIVER);
+ if(dev_priv == NULL) return -ENOMEM;
+ retcode = i810_dma_initialize(dev, dev_priv, &init);
+ break;
+ case I810_CLEANUP_DMA:
+ retcode = i810_dma_cleanup(dev);
+ break;
+ default:
+ retcode = -EINVAL;
+ break;
+ }
+
+ return retcode;
}
-static int i810_dma_priority(drm_device_t *dev, drm_dma_t *d)
-{
- unsigned long address;
- unsigned long length;
- int must_free = 0;
- int retcode = 0;
- int i;
- int idx;
- drm_buf_t *buf;
- drm_buf_t *last_buf = NULL;
- drm_device_dma_t *dma = dev->dma;
- DECLARE_WAITQUEUE(entry, current);
- /* Turn off interrupt handling */
- while (test_and_set_bit(0, &dev->interrupt_flag)) {
- schedule();
- if (signal_pending(current)) return -EINTR;
- }
- if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) {
- while (!drm_lock_take(&dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- schedule();
- if (signal_pending(current)) {
- clear_bit(0, &dev->interrupt_flag);
- return -EINTR;
- }
- }
- ++must_free;
+
+/* Most efficient way to verify state for the i810 is as it is
+ * emitted. Non-conformant state is silently dropped.
+ *
+ * Use 'volatile' & local var tmp to force the emitted values to be
+ * identical to the verified ones.
+ */
+static void i810EmitContextVerified( drm_device_t *dev,
+ volatile unsigned int *code )
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ int i, j = 0;
+ unsigned int tmp;
+ RING_LOCALS;
+
+ BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
+
+ OUT_RING( GFX_OP_COLOR_FACTOR );
+ OUT_RING( code[I810_CTXREG_CF1] );
+
+ OUT_RING( GFX_OP_STIPPLE );
+ OUT_RING( code[I810_CTXREG_ST1] );
+
+ for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
+ tmp = code[i];
+
+ if ((tmp & (7<<29)) == (3<<29) &&
+ (tmp & (0x1f<<24)) < (0x1d<<24))
+ {
+ OUT_RING( tmp );
+ j++;
+ }
}
- atomic_inc(&dma->total_prio);
- for (i = 0; i < d->send_count; i++) {
- idx = d->send_indices[i];
- if (idx < 0 || idx >= dma->buf_count) {
- DRM_ERROR("Index %d (of %d max)\n",
- d->send_indices[i], dma->buf_count - 1);
- continue;
- }
- buf = dma->buflist[ idx ];
- if (buf->pid != current->pid) {
- DRM_ERROR("Process %d using buffer owned by %d\n",
- current->pid, buf->pid);
- retcode = -EINVAL;
- goto cleanup;
- }
- if (buf->list != DRM_LIST_NONE) {
- DRM_ERROR("Process %d using %d's buffer on list %d\n",
- current->pid, buf->pid, buf->list);
- retcode = -EINVAL;
- goto cleanup;
- }
- /* This isn't a race condition on
- buf->list, since our concern is the
- buffer reclaim during the time the
- process closes the /dev/drm? handle, so
- it can't also be doing DMA. */
- buf->list = DRM_LIST_PRIO;
- buf->used = d->send_sizes[i];
- buf->context = d->context;
- buf->while_locked = d->flags & _DRM_DMA_WHILE_LOCKED;
- address = (unsigned long)buf->address;
- length = buf->used;
- if (!length) {
- DRM_ERROR("0 length buffer\n");
- }
- if (buf->pending) {
- DRM_ERROR("Sending pending buffer:"
- " buffer %d, offset %d\n",
- d->send_indices[i], i);
- retcode = -EINVAL;
- goto cleanup;
- }
- if (buf->waiting) {
- DRM_ERROR("Sending waiting buffer:"
- " buffer %d, offset %d\n",
- d->send_indices[i], i);
- retcode = -EINVAL;
- goto cleanup;
+ if (j & 1)
+ OUT_RING( 0 );
+
+ ADVANCE_LP_RING();
+}
+
+static void i810EmitTexVerified( drm_device_t *dev,
+ volatile unsigned int *code )
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ int i, j = 0;
+ unsigned int tmp;
+ RING_LOCALS;
+
+ BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
+
+ OUT_RING( GFX_OP_MAP_INFO );
+ OUT_RING( code[I810_TEXREG_MI1] );
+ OUT_RING( code[I810_TEXREG_MI2] );
+ OUT_RING( code[I810_TEXREG_MI3] );
+
+ for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
+ tmp = code[i];
+
+ if ((tmp & (7<<29)) == (3<<29) &&
+ (tmp & (0x1f<<24)) < (0x1d<<24))
+ {
+ OUT_RING( tmp );
+ j++;
}
- buf->pending = 1;
+ }
- if (dev->last_context != buf->context
- && !(dev->queuelist[buf->context]->flags
- & _DRM_CONTEXT_PRESERVED)) {
- add_wait_queue(&dev->context_wait, &entry);
- current->state = TASK_INTERRUPTIBLE;
- /* PRE: dev->last_context != buf->context */
- drm_context_switch(dev, dev->last_context,
- buf->context);
- /* POST: we will wait for the context
- switch and will dispatch on a later call
- when dev->last_context == buf->context.
- NOTE WE HOLD THE LOCK THROUGHOUT THIS
- TIME! */
- schedule();
- current->state = TASK_RUNNING;
- remove_wait_queue(&dev->context_wait, &entry);
- if (signal_pending(current)) {
- retcode = -EINTR;
- goto cleanup;
- }
- if (dev->last_context != buf->context) {
- DRM_ERROR("Context mismatch: %d %d\n",
- dev->last_context,
- buf->context);
- }
- }
+ if (j & 1)
+ OUT_RING( 0 );
-#if DRM_DMA_HISTOGRAM
- buf->time_queued = get_cycles();
- buf->time_dispatched = buf->time_queued;
-#endif
- i810_dma_dispatch(dev, address, length);
- if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("\n");
- }
+ ADVANCE_LP_RING();
+}
- atomic_add(length, &dma->total_bytes);
- atomic_inc(&dma->total_dmas);
-
- if (last_buf) {
- drm_free_buffer(dev, last_buf);
- }
- last_buf = buf;
+
+/* Need to do some additional checking when setting the dest buffer.
+ */
+static void i810EmitDestVerified( drm_device_t *dev,
+ volatile unsigned int *code )
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ unsigned int tmp;
+ RING_LOCALS;
+
+ BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
+
+ tmp = code[I810_DESTREG_DI1];
+ if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
+ OUT_RING( CMD_OP_DESTBUFFER_INFO );
+ OUT_RING( tmp );
+ } else
+ DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
+ tmp, dev_priv->front_di1, dev_priv->back_di1);
+
+ /* invarient:
+ */
+ OUT_RING( CMD_OP_Z_BUFFER_INFO );
+ OUT_RING( dev_priv->zi1 );
+
+ OUT_RING( GFX_OP_DESTBUFFER_VARS );
+ OUT_RING( code[I810_DESTREG_DV1] );
+
+ OUT_RING( GFX_OP_DRAWRECT_INFO );
+ OUT_RING( code[I810_DESTREG_DR1] );
+ OUT_RING( code[I810_DESTREG_DR2] );
+ OUT_RING( code[I810_DESTREG_DR3] );
+ OUT_RING( code[I810_DESTREG_DR4] );
+ OUT_RING( 0 );
+
+ ADVANCE_LP_RING();
+}
+
+
+
+static void i810EmitState( drm_device_t *dev )
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+
+ if (dirty & I810_UPLOAD_BUFFERS) {
+ i810EmitDestVerified( dev, sarea_priv->BufferState );
+ sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
}
+ if (dirty & I810_UPLOAD_CTX) {
+ i810EmitContextVerified( dev, sarea_priv->ContextState );
+ sarea_priv->dirty &= ~I810_UPLOAD_CTX;
+ }
-cleanup:
- if (last_buf) {
- i810_dma_ready(dev);
- drm_free_buffer(dev, last_buf);
+ if (dirty & I810_UPLOAD_TEX0) {
+ i810EmitTexVerified( dev, sarea_priv->TexState[0] );
+ sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
}
-
- if (must_free && !dev->context_flag) {
- if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("\n");
- }
+
+ if (dirty & I810_UPLOAD_TEX1) {
+ i810EmitTexVerified( dev, sarea_priv->TexState[1] );
+ sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
}
- clear_bit(0, &dev->interrupt_flag);
- return retcode;
}
-static int i810_dma_send_buffers(drm_device_t *dev, drm_dma_t *d)
+
+
+/* need to verify
+ */
+static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
+ unsigned int clear_color,
+ unsigned int clear_zval )
{
- DECLARE_WAITQUEUE(entry, current);
- drm_buf_t *last_buf = NULL;
- int retcode = 0;
- drm_device_dma_t *dma = dev->dma;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int pitch = dev_priv->pitch;
+ int cpp = 2;
+ int i;
+ RING_LOCALS;
+
+ i810_kernel_lost_context(dev);
+
+ if (nbox > I810_NR_SAREA_CLIPRECTS)
+ nbox = I810_NR_SAREA_CLIPRECTS;
+
+ for (i = 0 ; i < nbox ; i++, pbox++) {
+ unsigned int x = pbox->x1;
+ unsigned int y = pbox->y1;
+ unsigned int width = (pbox->x2 - x) * cpp;
+ unsigned int height = pbox->y2 - y;
+ unsigned int start = y * pitch + x * cpp;
+
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+ pbox->x2 > dev_priv->w ||
+ pbox->y2 > dev_priv->h)
+ continue;
- if (d->flags & _DRM_DMA_BLOCK) {
- last_buf = dma->buflist[d->send_indices[d->send_count-1]];
- add_wait_queue(&last_buf->dma_wait, &entry);
- }
-
- if ((retcode = drm_dma_enqueue(dev, d))) {
- if (d->flags & _DRM_DMA_BLOCK)
- remove_wait_queue(&last_buf->dma_wait, &entry);
- return retcode;
- }
-
- i810_dma_schedule(dev, 0);
-
- if (d->flags & _DRM_DMA_BLOCK) {
- DRM_DEBUG("%d waiting\n", current->pid);
- current->state = TASK_INTERRUPTIBLE;
- for (;;) {
- if (!last_buf->waiting
- && !last_buf->pending)
- break; /* finished */
- schedule();
- if (signal_pending(current)) {
- retcode = -EINTR; /* Can't restart */
- break;
- }
+ if ( flags & I810_FRONT ) {
+ DRM_DEBUG("clear front\n");
+ BEGIN_LP_RING( 6 );
+ OUT_RING( BR00_BITBLT_CLIENT |
+ BR00_OP_COLOR_BLT | 0x3 );
+ OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+ OUT_RING( (height << 16) | width );
+ OUT_RING( start );
+ OUT_RING( clear_color );
+ OUT_RING( 0 );
+ ADVANCE_LP_RING();
}
- current->state = TASK_RUNNING;
- DRM_DEBUG("%d running\n", current->pid);
- remove_wait_queue(&last_buf->dma_wait, &entry);
- if (!retcode
- || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) {
- if (!waitqueue_active(&last_buf->dma_wait)) {
- drm_free_buffer(dev, last_buf);
- }
+
+ if ( flags & I810_BACK ) {
+ DRM_DEBUG("clear back\n");
+ BEGIN_LP_RING( 6 );
+ OUT_RING( BR00_BITBLT_CLIENT |
+ BR00_OP_COLOR_BLT | 0x3 );
+ OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+ OUT_RING( (height << 16) | width );
+ OUT_RING( dev_priv->back_offset + start );
+ OUT_RING( clear_color );
+ OUT_RING( 0 );
+ ADVANCE_LP_RING();
}
- if (retcode) {
- DRM_ERROR("ctx%d w%d p%d c%d i%d l%d %d/%d\n",
- d->context,
- last_buf->waiting,
- last_buf->pending,
- DRM_WAITCOUNT(dev, d->context),
- last_buf->idx,
- last_buf->list,
- last_buf->pid,
- current->pid);
+
+ if ( flags & I810_DEPTH ) {
+ DRM_DEBUG("clear depth\n");
+ BEGIN_LP_RING( 6 );
+ OUT_RING( BR00_BITBLT_CLIENT |
+ BR00_OP_COLOR_BLT | 0x3 );
+ OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+ OUT_RING( (height << 16) | width );
+ OUT_RING( dev_priv->depth_offset + start );
+ OUT_RING( clear_zval );
+ OUT_RING( 0 );
+ ADVANCE_LP_RING();
}
}
- return retcode;
}
-int i810_dma(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+static void i810_dma_dispatch_swap( drm_device_t *dev )
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_device_dma_t *dma = dev->dma;
- int retcode = 0;
- drm_dma_t d;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int pitch = dev_priv->pitch;
+ int cpp = 2;
+ int ofs = dev_priv->back_offset;
+ int i;
+ RING_LOCALS;
+
+ DRM_DEBUG("swapbuffers\n");
+
+ i810_kernel_lost_context(dev);
+
+ if (nbox > I810_NR_SAREA_CLIPRECTS)
+ nbox = I810_NR_SAREA_CLIPRECTS;
+
+ for (i = 0 ; i < nbox; i++, pbox++)
+ {
+ unsigned int w = pbox->x2 - pbox->x1;
+ unsigned int h = pbox->y2 - pbox->y1;
+ unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
+ unsigned int start = ofs + dst;
+
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+ pbox->x2 > dev_priv->w ||
+ pbox->y2 > dev_priv->h)
+ continue;
+
+ DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
+ pbox[i].x1, pbox[i].y1,
+ pbox[i].x2, pbox[i].y2);
+
+ BEGIN_LP_RING( 6 );
+ OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
+ OUT_RING( pitch | (0xCC << 16));
+ OUT_RING( (h << 16) | (w * cpp));
+ OUT_RING( dst );
+ OUT_RING( pitch );
+ OUT_RING( start );
+ ADVANCE_LP_RING();
+ }
+}
- printk("i810_dma start\n");
- copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
- DRM_DEBUG("%d %d: %d send, %d req\n",
- current->pid, d.context, d.send_count, d.request_count);
- if (d.context == DRM_KERNEL_CONTEXT || d.context >= dev->queue_slots) {
- DRM_ERROR("Process %d using context %d\n",
- current->pid, d.context);
- return -EINVAL;
+static void i810_dma_dispatch_vertex(drm_device_t *dev,
+ drm_buf_t *buf,
+ int discard,
+ int used)
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_clip_rect_t *box = sarea_priv->boxes;
+ int nbox = sarea_priv->nbox;
+ unsigned long address = (unsigned long)buf->bus_address;
+ unsigned long start = address - dev->agp->base;
+ int i = 0, u;
+ RING_LOCALS;
+
+ i810_kernel_lost_context(dev);
+
+ if (nbox > I810_NR_SAREA_CLIPRECTS)
+ nbox = I810_NR_SAREA_CLIPRECTS;
+
+ if (discard) {
+ u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+ I810_BUF_HARDWARE);
+ if(u != I810_BUF_CLIENT) {
+ DRM_DEBUG("xxxx 2\n");
+ }
}
- if (d.send_count < 0 || d.send_count > dma->buf_count) {
- DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
- current->pid, d.send_count, dma->buf_count);
- return -EINVAL;
+ if (used > 4*1024)
+ used = 0;
+
+ if (sarea_priv->dirty)
+ i810EmitState( dev );
+
+ DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
+ address, used, nbox);
+
+ dev_priv->counter++;
+ DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter);
+ DRM_DEBUG( "i810_dma_dispatch\n");
+ DRM_DEBUG( "start : %lx\n", start);
+ DRM_DEBUG( "used : %d\n", used);
+ DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4);
+
+ if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
+ *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE |
+ sarea_priv->vertex_prim |
+ ((used/4)-2));
+
+ if (used & 4) {
+ *(u32 *)((u32)buf_priv->virtual + used) = 0;
+ used += 4;
+ }
+
+ i810_unmap_buffer(buf);
}
- if (d.request_count < 0 || d.request_count > dma->buf_count) {
- DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
- current->pid, d.request_count, dma->buf_count);
- return -EINVAL;
+
+ if (used) {
+ do {
+ if (i < nbox) {
+ BEGIN_LP_RING(4);
+ OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
+ SC_ENABLE );
+ OUT_RING( GFX_OP_SCISSOR_INFO );
+ OUT_RING( box[i].x1 | (box[i].y1<<16) );
+ OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) );
+ ADVANCE_LP_RING();
+ }
+
+ BEGIN_LP_RING(4);
+ OUT_RING( CMD_OP_BATCH_BUFFER );
+ OUT_RING( start | BB1_PROTECTED );
+ OUT_RING( start + used - 4 );
+ OUT_RING( 0 );
+ ADVANCE_LP_RING();
+
+ } while (++i < nbox);
}
- if (d.send_count) {
-#if 0
- if (d.flags & _DRM_DMA_PRIORITY)
- retcode = i810_dma_priority(dev, &d);
- else
- retcode = i810_dma_send_buffers(dev, &d);
-#endif
- printk("i810_dma priority\n");
-
- retcode = i810_dma_priority(dev, &d);
+ BEGIN_LP_RING(10);
+ OUT_RING( CMD_STORE_DWORD_IDX );
+ OUT_RING( 20 );
+ OUT_RING( dev_priv->counter );
+ OUT_RING( 0 );
+
+ if (discard) {
+ OUT_RING( CMD_STORE_DWORD_IDX );
+ OUT_RING( buf_priv->my_use_idx );
+ OUT_RING( I810_BUF_FREE );
+ OUT_RING( 0 );
}
- d.granted_count = 0;
+ OUT_RING( CMD_REPORT_HEAD );
+ OUT_RING( 0 );
+ ADVANCE_LP_RING();
+}
- if (!retcode && d.request_count) {
- retcode = drm_dma_get_buffers(dev, &d);
- }
- DRM_DEBUG("%d returning, granted = %d\n",
- current->pid, d.granted_count);
- copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
+/* Interrupts are only for flushing */
+static void i810_dma_service(int irq, void *device, struct pt_regs *regs)
+{
+ drm_device_t *dev = (drm_device_t *)device;
+ u16 temp;
+
+ atomic_inc(&dev->total_irq);
+ temp = I810_READ16(I810REG_INT_IDENTITY_R);
+ temp = temp & ~(0x6000);
+ if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R,
+ temp); /* Clear all interrupts */
+ else
+ return;
+
+ queue_task(&dev->tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
+static void i810_dma_task_queue(void *device)
+{
+ drm_device_t *dev = (drm_device_t *) device;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
- printk("i810_dma end (granted)\n");
- return retcode;
+ atomic_set(&dev_priv->flush_done, 1);
+ wake_up_interruptible(&dev_priv->flush_queue);
}
int i810_irq_install(drm_device_t *dev, int irq)
{
int retcode;
-
+ u16 temp;
+
if (!irq) return -EINVAL;
down(&dev->struct_sem);
@@ -591,6 +890,7 @@ int i810_irq_install(drm_device_t *dev, int irq)
dev->irq = irq;
up(&dev->struct_sem);
+ DRM_DEBUG( "Interrupt Install : %d\n", irq);
DRM_DEBUG("%d\n", irq);
dev->context_flag = 0;
@@ -603,16 +903,25 @@ int i810_irq_install(drm_device_t *dev, int irq)
dev->tq.next = NULL;
dev->tq.sync = 0;
- dev->tq.routine = i810_dma_schedule_tq_wrapper;
+ dev->tq.routine = i810_dma_task_queue;
dev->tq.data = dev;
-
/* Before installing handler */
- /* TODO */
+ temp = I810_READ16(I810REG_HWSTAM);
+ temp = temp & 0x6000;
+ I810_WRITE16(I810REG_HWSTAM, temp);
+
+ temp = I810_READ16(I810REG_INT_MASK_R);
+ temp = temp & 0x6000;
+ I810_WRITE16(I810REG_INT_MASK_R, temp); /* Unmask interrupts */
+ temp = I810_READ16(I810REG_INT_ENABLE_R);
+ temp = temp & 0x6000;
+ I810_WRITE16(I810REG_INT_ENABLE_R, temp); /* Disable all interrupts */
+
/* Install handler */
if ((retcode = request_irq(dev->irq,
i810_dma_service,
- 0,
+ SA_SHIRQ,
dev->devname,
dev))) {
down(&dev->struct_sem);
@@ -620,15 +929,21 @@ int i810_irq_install(drm_device_t *dev, int irq)
up(&dev->struct_sem);
return retcode;
}
-
- /* After installing handler */
- /* TODO */
+ temp = I810_READ16(I810REG_INT_ENABLE_R);
+ temp = temp & 0x6000;
+ temp = temp | 0x0003;
+ I810_WRITE16(I810REG_INT_ENABLE_R,
+ temp); /* Enable bp & user interrupts */
return 0;
}
int i810_irq_uninstall(drm_device_t *dev)
{
int irq;
+ u16 temp;
+
+
+/* return 0; */
down(&dev->struct_sem);
irq = dev->irq;
@@ -636,16 +951,25 @@ int i810_irq_uninstall(drm_device_t *dev)
up(&dev->struct_sem);
if (!irq) return -EINVAL;
-
+
+ DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
DRM_DEBUG("%d\n", irq);
-
- /* TODO : Disable interrupts */
+
+ temp = I810_READ16(I810REG_INT_IDENTITY_R);
+ temp = temp & ~(0x6000);
+ if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R,
+ temp); /* Clear all interrupts */
+
+ temp = I810_READ16(I810REG_INT_ENABLE_R);
+ temp = temp & 0x6000;
+ I810_WRITE16(I810REG_INT_ENABLE_R,
+ temp); /* Disable all interrupts */
+
free_irq(irq, dev);
return 0;
}
-
int i810_control(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
@@ -654,8 +978,7 @@ int i810_control(struct inode *inode, struct file *filp, unsigned int cmd,
drm_control_t ctl;
int retcode;
- printk(KERN_INFO "i810_control\n");
- i810_dma_init(dev);
+ DRM_DEBUG( "i810_control\n");
copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT);
@@ -674,20 +997,161 @@ int i810_control(struct inode *inode, struct file *filp, unsigned int cmd,
return 0;
}
+static inline void i810_dma_emit_flush(drm_device_t *dev)
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+ i810_kernel_lost_context(dev);
+
+ BEGIN_LP_RING(2);
+ OUT_RING( CMD_REPORT_HEAD );
+ OUT_RING( GFX_OP_USER_INTERRUPT );
+ ADVANCE_LP_RING();
+
+/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
+/* atomic_set(&dev_priv->flush_done, 1); */
+/* wake_up_interruptible(&dev_priv->flush_queue); */
+}
+
+static inline void i810_dma_quiescent_emit(drm_device_t *dev)
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+ i810_kernel_lost_context(dev);
+
+ BEGIN_LP_RING(4);
+ OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+ OUT_RING( CMD_REPORT_HEAD );
+ OUT_RING( 0 );
+ OUT_RING( GFX_OP_USER_INTERRUPT );
+ ADVANCE_LP_RING();
+
+/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
+/* atomic_set(&dev_priv->flush_done, 1); */
+/* wake_up_interruptible(&dev_priv->flush_queue); */
+}
+
+static void i810_dma_quiescent(drm_device_t *dev)
+{
+ DECLARE_WAITQUEUE(entry, current);
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ unsigned long end;
+
+ if(dev_priv == NULL) {
+ return;
+ }
+ atomic_set(&dev_priv->flush_done, 0);
+ current->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(&dev_priv->flush_queue, &entry);
+ end = jiffies + (HZ*3);
+
+ for (;;) {
+ i810_dma_quiescent_emit(dev);
+ if (atomic_read(&dev_priv->flush_done) == 1) break;
+ if((signed)(end - jiffies) <= 0) {
+ DRM_ERROR("lockup\n");
+ break;
+ }
+ schedule_timeout(HZ*3);
+ if (signal_pending(current)) {
+ break;
+ }
+ }
+
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev_priv->flush_queue, &entry);
+
+ return;
+}
+
+static int i810_flush_queue(drm_device_t *dev)
+{
+ DECLARE_WAITQUEUE(entry, current);
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ unsigned long end;
+ int i, ret = 0;
+
+ if(dev_priv == NULL) {
+ return 0;
+ }
+ atomic_set(&dev_priv->flush_done, 0);
+ current->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(&dev_priv->flush_queue, &entry);
+ end = jiffies + (HZ*3);
+ for (;;) {
+ i810_dma_emit_flush(dev);
+ if (atomic_read(&dev_priv->flush_done) == 1) break;
+ if((signed)(end - jiffies) <= 0) {
+ DRM_ERROR("lockup\n");
+ break;
+ }
+ schedule_timeout(HZ*3);
+ if (signal_pending(current)) {
+ ret = -EINTR; /* Can't restart */
+ break;
+ }
+ }
+
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev_priv->flush_queue, &entry);
+
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[ i ];
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+ int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
+ I810_BUF_FREE);
+
+ if (used == I810_BUF_HARDWARE)
+ DRM_DEBUG("reclaimed from HARDWARE\n");
+ if (used == I810_BUF_CLIENT)
+ DRM_DEBUG("still on client HARDWARE\n");
+ }
+
+ return ret;
+}
+
+/* Must be called with the lock held */
+void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
+{
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+
+ if (!dma) return;
+ if (!dev->dev_private) return;
+ if (!dma->buflist) return;
+
+ i810_flush_queue(dev);
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[ i ];
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+ if (buf->pid == pid && buf_priv) {
+ int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+ I810_BUF_FREE);
+
+ if (used == I810_BUF_CLIENT)
+ DRM_DEBUG("reclaimed from client\n");
+ if(buf_priv->currently_mapped == I810_BUF_MAPPED)
+ buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+ }
+ }
+}
+
int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
+
DECLARE_WAITQUEUE(entry, current);
int ret = 0;
drm_lock_t lock;
- drm_queue_t *q;
-#if DRM_DMA_HISTOGRAM
- cycles_t start;
-
- dev->lck_start = start = get_cycles();
-#endif
copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
@@ -696,26 +1160,18 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
current->pid, lock.context);
return -EINVAL;
}
+
+ DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+ lock.context, current->pid, dev->lock.hw_lock->lock,
+ lock.flags);
- if (lock.context < 0 || lock.context >= dev->queue_count) {
+ if (lock.context < 0) {
return -EINVAL;
}
- q = dev->queuelist[lock.context];
-
- ret = drm_flush_block_and_flush(dev, lock.context, lock.flags);
+ /* Only one queue:
+ */
if (!ret) {
- if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
- != lock.context) {
- long j = jiffies - dev->lock.lock_time;
-
- if (j > 0 && j <= DRM_LOCK_SLICE) {
- /* Can't take lock if we just had it and
- there is contention. */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(j);
- }
- }
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
if (!dev->lock.hw_lock) {
@@ -728,13 +1184,13 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
dev->lock.pid = current->pid;
dev->lock.lock_time = jiffies;
atomic_inc(&dev->total_locks);
- atomic_inc(&q->total_locks);
break; /* Got lock */
}
/* Contention */
atomic_inc(&dev->total_sleeps);
current->state = TASK_INTERRUPTIBLE;
+ DRM_DEBUG("Calling lock schedule\n");
schedule();
if (signal_pending(current)) {
ret = -ERESTARTSYS;
@@ -744,19 +1200,153 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
current->state = TASK_RUNNING;
remove_wait_queue(&dev->lock.lock_queue, &entry);
}
-
- drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */
if (!ret) {
- if (lock.flags & _DRM_LOCK_READY)
- i810_dma_ready(dev);
- if (lock.flags & _DRM_LOCK_QUIESCENT)
- i810_dma_quiescent(dev);
+ if (lock.flags & _DRM_LOCK_QUIESCENT) {
+ DRM_DEBUG("_DRM_LOCK_QUIESCENT\n");
+ DRM_DEBUG("fred\n");
+ i810_dma_quiescent(dev);
+ }
}
+ DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
+ return ret;
+}
+
+int i810_flush_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+
+ DRM_DEBUG("i810_flush_ioctl\n");
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("i810_flush_ioctl called without lock held\n");
+ return -EINVAL;
+ }
+
+ i810_flush_queue(dev);
+ return 0;
+}
+
+
+int i810_dma_vertex(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_device_dma_t *dma = dev->dma;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ u32 *hw_status = (u32 *)dev_priv->hw_status_page;
+ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+ dev_priv->sarea_priv;
+ drm_i810_vertex_t vertex;
+
+ copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex),
+ -EFAULT);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("i810_dma_vertex called without lock held\n");
+ return -EINVAL;
+ }
+
+ DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
+ vertex.idx, vertex.used, vertex.discard);
+
+ i810_dma_dispatch_vertex( dev,
+ dma->buflist[ vertex.idx ],
+ vertex.discard, vertex.used );
-#if DRM_DMA_HISTOGRAM
- atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
-#endif
+ atomic_add(vertex.used, &dma->total_bytes);
+ atomic_inc(&dma->total_dmas);
+ sarea_priv->last_enqueue = dev_priv->counter-1;
+ sarea_priv->last_dispatch = (int) hw_status[5];
+
+ return 0;
+}
+
+
+
+int i810_clear_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i810_clear_t clear;
+
+ copy_from_user_ret(&clear, (drm_i810_clear_t *)arg, sizeof(clear),
+ -EFAULT);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("i810_clear_bufs called without lock held\n");
+ return -EINVAL;
+ }
+
+ i810_dma_dispatch_clear( dev, clear.flags,
+ clear.clear_color,
+ clear.clear_depth );
+ return 0;
+}
+
+int i810_swap_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+
+ DRM_DEBUG("i810_swap_bufs\n");
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("i810_swap_buf called without lock held\n");
+ return -EINVAL;
+ }
+
+ i810_dma_dispatch_swap( dev );
+ return 0;
+}
+
+int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ u32 *hw_status = (u32 *)dev_priv->hw_status_page;
+ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+ dev_priv->sarea_priv;
+
+ sarea_priv->last_dispatch = (int) hw_status[5];
+ return 0;
+}
+
+int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ int retcode = 0;
+ drm_i810_dma_t d;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ u32 *hw_status = (u32 *)dev_priv->hw_status_page;
+ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+ dev_priv->sarea_priv;
+
+ DRM_DEBUG("getbuf\n");
+ copy_from_user_ret(&d, (drm_i810_dma_t *)arg, sizeof(d), -EFAULT);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("i810_dma called without lock held\n");
+ return -EINVAL;
+ }
- return ret;
+ d.granted = 0;
+
+ retcode = i810_dma_get_buffer(dev, &d, filp);
+
+ DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
+ current->pid, retcode, d.granted);
+
+ copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
+ sarea_priv->last_dispatch = (int) hw_status[5];
+
+ return retcode;
}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drm.h
new file mode 100644
index 000000000..4c8e09f6a
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drm.h
@@ -0,0 +1,188 @@
+#ifndef _I810_DRM_H_
+#define _I810_DRM_H_
+
+/* WARNING: These defines must be the same as what the Xserver uses.
+ * if you change them, you must change the defines in the Xserver.
+ */
+
+#ifndef _I810_DEFINES_
+#define _I810_DEFINES_
+
+#define I810_DMA_BUF_ORDER 12
+#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER)
+#define I810_DMA_BUF_NR 256
+#define I810_NR_SAREA_CLIPRECTS 8
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define I810_NR_TEX_REGIONS 64
+#define I810_LOG_MIN_TEX_REGION_SIZE 16
+#endif
+
+#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
+#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
+#define I810_UPLOAD_CTX 0x4
+#define I810_UPLOAD_BUFFERS 0x8
+#define I810_UPLOAD_TEX0 0x10
+#define I810_UPLOAD_TEX1 0x20
+#define I810_UPLOAD_CLIPRECTS 0x40
+
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer. These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+/* Destbuffer state
+ * - backbuffer linear offset and pitch -- invarient in the current dri
+ * - zbuffer linear offset and pitch -- also invarient
+ * - drawing origin in back and depth buffers.
+ *
+ * Keep the depth/back buffer state here to acommodate private buffers
+ * in the future.
+ */
+#define I810_DESTREG_DI0 0 /* CMD_OP_DESTBUFFER_INFO (2 dwords) */
+#define I810_DESTREG_DI1 1
+#define I810_DESTREG_DV0 2 /* GFX_OP_DESTBUFFER_VARS (2 dwords) */
+#define I810_DESTREG_DV1 3
+#define I810_DESTREG_DR0 4 /* GFX_OP_DRAWRECT_INFO (4 dwords) */
+#define I810_DESTREG_DR1 5
+#define I810_DESTREG_DR2 6
+#define I810_DESTREG_DR3 7
+#define I810_DESTREG_DR4 8
+#define I810_DEST_SETUP_SIZE 10
+
+/* Context state
+ */
+#define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */
+#define I810_CTXREG_CF1 1
+#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
+#define I810_CTXREG_ST1 3
+#define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */
+#define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */
+#define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
+#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
+#define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
+#define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
+#define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
+#define I810_CTXREG_MA2 11 /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */
+#define I810_CTXREG_SDM 12 /* GFX_OP_SRC_DEST_MONO */
+#define I810_CTXREG_FOG 13 /* GFX_OP_FOG_COLOR */
+#define I810_CTXREG_B1 14 /* GFX_OP_BOOL_1 */
+#define I810_CTXREG_B2 15 /* GFX_OP_BOOL_2 */
+#define I810_CTXREG_LCS 16 /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */
+#define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */
+#define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */
+#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */
+#define I810_CTX_SETUP_SIZE 20
+
+/* Texture state (per tex unit)
+ */
+#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */
+#define I810_TEXREG_MI1 1
+#define I810_TEXREG_MI2 2
+#define I810_TEXREG_MI3 3
+#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */
+#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */
+#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */
+#define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */
+#define I810_TEX_SETUP_SIZE 8
+
+#define I810_FRONT 0x1
+#define I810_BACK 0x2
+#define I810_DEPTH 0x4
+
+
+typedef struct _drm_i810_init {
+ enum {
+ I810_INIT_DMA = 0x01,
+ I810_CLEANUP_DMA = 0x02
+ } func;
+ int ring_map_idx;
+ int buffer_map_idx;
+ int sarea_priv_offset;
+ unsigned int ring_start;
+ unsigned int ring_end;
+ unsigned int ring_size;
+ unsigned int front_offset;
+ unsigned int back_offset;
+ unsigned int depth_offset;
+ unsigned int w;
+ unsigned int h;
+ unsigned int pitch;
+ unsigned int pitch_bits;
+} drm_i810_init_t;
+
+/* Warning: If you change the SAREA structure you must change the Xserver
+ * structure as well */
+
+typedef struct _drm_i810_tex_region {
+ unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char in_use; /* owned by a client, or free? */
+ int age; /* tracked by clients to update local LRU's */
+} drm_i810_tex_region_t;
+
+typedef struct _drm_i810_sarea {
+ unsigned int ContextState[I810_CTX_SETUP_SIZE];
+ unsigned int BufferState[I810_DEST_SETUP_SIZE];
+ unsigned int TexState[2][I810_TEX_SETUP_SIZE];
+ unsigned int dirty;
+
+ unsigned int nbox;
+ drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
+
+ /* Maintain an LRU of contiguous regions of texture space. If
+ * you think you own a region of texture memory, and it has an
+ * age different to the one you set, then you are mistaken and
+ * it has been stolen by another client. If global texAge
+ * hasn't changed, there is no need to walk the list.
+ *
+ * These regions can be used as a proxy for the fine-grained
+ * texture information of other clients - by maintaining them
+ * in the same lru which is used to age their own textures,
+ * clients have an approximate lru for the whole of global
+ * texture space, and can make informed decisions as to which
+ * areas to kick out. There is no need to choose whether to
+ * kick out your own texture or someone else's - simply eject
+ * them all in LRU order.
+ */
+
+ drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS+1];
+ /* Last elt is sentinal */
+ int texAge; /* last time texture was uploaded */
+ int last_enqueue; /* last time a buffer was enqueued */
+ int last_dispatch; /* age of the most recently dispatched buffer */
+ int last_quiescent; /* */
+ int ctxOwner; /* last context to upload state */
+
+ int vertex_prim;
+
+} drm_i810_sarea_t;
+
+typedef struct _drm_i810_clear {
+ int clear_color;
+ int clear_depth;
+ int flags;
+} drm_i810_clear_t;
+
+
+
+/* These may be placeholders if we have more cliprects than
+ * I810_NR_SAREA_CLIPRECTS. In that case, the client sets discard to
+ * false, indicating that the buffer will be dispatched again with a
+ * new set of cliprects.
+ */
+typedef struct _drm_i810_vertex {
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int discard; /* client is finished with the buffer? */
+} drm_i810_vertex_t;
+
+typedef struct drm_i810_dma {
+ void *virtual;
+ int request_idx;
+ int request_size;
+ int granted;
+} drm_i810_dma_t;
+
+#endif /* _I810_DRM_H_ */
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.c
index f33153a36..75b402daa 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.c
@@ -33,11 +33,13 @@
#define EXPORT_SYMTAB
#include "drmP.h"
#include "i810_drv.h"
+
+
EXPORT_SYMBOL(i810_init);
EXPORT_SYMBOL(i810_cleanup);
#define I810_NAME "i810"
-#define I810_DESC "Matrox g200/g400"
+#define I810_DESC "Intel I810"
#define I810_DATE "19991213"
#define I810_MAJOR 0
#define I810_MINOR 0
@@ -54,6 +56,7 @@ static struct file_operations i810_fops = {
mmap: drm_mmap,
read: drm_read,
fasync: drm_fasync,
+ poll: drm_poll,
};
static struct miscdevice i810_misc = {
@@ -77,21 +80,18 @@ static drm_ioctl_desc_t i810_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { i810_addbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { i810_markbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { i810_infobufs, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { i810_mapbufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { i810_freebufs, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { i810_addctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { i810_rmctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { i810_modctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { i810_getctx, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { i810_switchctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { i810_newctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { i810_resctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { i810_dma, 1, 0 },
-
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { i810_lock, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { i810_unlock, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
@@ -104,6 +104,14 @@ static drm_ioctl_desc_t i810_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
+
+ [DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_I810_CLEAR)] = { i810_clear_bufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)] = { i810_flush_ioctl,1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)] = { i810_swap_bufs, 1, 0 },
};
#define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls)
@@ -121,7 +129,7 @@ MODULE_PARM(i810, "s");
int init_module(void)
{
- printk("doing i810_init()\n");
+ DRM_DEBUG("doing i810_init()\n");
return i810_init();
}
@@ -364,7 +372,7 @@ int i810_init(void)
#ifdef MODULE
drm_parse_options(i810);
#endif
- printk("doing misc_register\n");
+ DRM_DEBUG("doing misc_register\n");
if ((retcode = misc_register(&i810_misc))) {
DRM_ERROR("Cannot register \"%s\"\n", I810_NAME);
return retcode;
@@ -372,13 +380,22 @@ int i810_init(void)
dev->device = MKDEV(MISC_MAJOR, i810_misc.minor);
dev->name = I810_NAME;
- printk("doing mem init\n");
+ DRM_DEBUG("doing mem init\n");
drm_mem_init();
- printk("doing proc init\n");
+ DRM_DEBUG("doing proc init\n");
drm_proc_init(dev);
- printk("doing agp init\n");
+ DRM_DEBUG("doing agp init\n");
dev->agp = drm_agp_init();
- printk("doing ctxbitmap init\n");
+ if(dev->agp == NULL) {
+ DRM_INFO("The i810 drm module requires the agpgart module"
+ " to function correctly\nPlease load the agpgart"
+ " module before you load the i810 module\n");
+ drm_proc_cleanup();
+ misc_deregister(&i810_misc);
+ i810_takedown(dev);
+ return -ENOMEM;
+ }
+ DRM_DEBUG("doing ctxbitmap init\n");
if((retcode = drm_ctxbitmap_init(dev))) {
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
drm_proc_cleanup();
@@ -386,10 +403,6 @@ int i810_init(void)
i810_takedown(dev);
return retcode;
}
-#if 0
- printk("doing i810_dma_init\n");
- i810_dma_init(dev);
-#endif
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
I810_NAME,
@@ -417,7 +430,6 @@ void i810_cleanup(void)
DRM_INFO("Module unloaded\n");
}
drm_ctxbitmap_cleanup(dev);
- i810_dma_cleanup(dev);
i810_takedown(dev);
if (dev->agp) {
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
@@ -484,24 +496,82 @@ int i810_release(struct inode *inode, struct file *filp)
drm_device_t *dev = priv->dev;
int retcode = 0;
- DRM_DEBUG("open_count = %d\n", dev->open_count);
- if (!(retcode = drm_release(inode, filp))) {
- MOD_DEC_USE_COUNT;
- atomic_inc(&dev->total_close);
- spin_lock(&dev->count_lock);
- if (!--dev->open_count) {
- if (atomic_read(&dev->ioctl_count) || dev->blocked) {
- DRM_ERROR("Device busy: %d %d\n",
- atomic_read(&dev->ioctl_count),
- dev->blocked);
- spin_unlock(&dev->count_lock);
- return -EBUSY;
+ DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
+ current->pid, dev->device, dev->open_count);
+
+ if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
+ && dev->lock.pid == current->pid) {
+ i810_reclaim_buffers(dev, priv->pid);
+ DRM_ERROR("Process %d dead, freeing lock for context %d\n",
+ current->pid,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+ drm_lock_free(dev,
+ &dev->lock.hw_lock->lock,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+
+ /* FIXME: may require heavy-handed reset of
+ hardware at this point, possibly
+ processed via a callback to the X
+ server. */
+ } else if (dev->lock.hw_lock) {
+ /* The lock is required to reclaim buffers */
+ DECLARE_WAITQUEUE(entry, current);
+ add_wait_queue(&dev->lock.lock_queue, &entry);
+ for (;;) {
+ if (!dev->lock.hw_lock) {
+ /* Device has been unregistered */
+ retcode = -EINTR;
+ break;
+ }
+ if (drm_lock_take(&dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ dev->lock.pid = priv->pid;
+ dev->lock.lock_time = jiffies;
+ atomic_inc(&dev->total_locks);
+ break; /* Got lock */
+ }
+ /* Contention */
+ atomic_inc(&dev->total_sleeps);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (signal_pending(current)) {
+ retcode = -ERESTARTSYS;
+ break;
}
- spin_unlock(&dev->count_lock);
- return i810_takedown(dev);
}
- spin_unlock(&dev->count_lock);
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev->lock.lock_queue, &entry);
+ if(!retcode) {
+ i810_reclaim_buffers(dev, priv->pid);
+ drm_lock_free(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT);
+ }
+ }
+ drm_fasync(-1, filp, 0);
+
+ down(&dev->struct_sem);
+ if (priv->prev) priv->prev->next = priv->next;
+ else dev->file_first = priv->next;
+ if (priv->next) priv->next->prev = priv->prev;
+ else dev->file_last = priv->prev;
+ up(&dev->struct_sem);
+
+ drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+ MOD_DEC_USE_COUNT;
+ atomic_inc(&dev->total_close);
+ spin_lock(&dev->count_lock);
+ if (!--dev->open_count) {
+ if (atomic_read(&dev->ioctl_count) || dev->blocked) {
+ DRM_ERROR("Device busy: %d %d\n",
+ atomic_read(&dev->ioctl_count),
+ dev->blocked);
+ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ spin_unlock(&dev->count_lock);
+ return i810_takedown(dev);
}
+ spin_unlock(&dev->count_lock);
return retcode;
}
@@ -566,8 +636,7 @@ int i810_unlock(struct inode *inode, struct file *filp, unsigned int cmd,
atomic_inc(&dev->total_unlocks);
if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
atomic_inc(&dev->total_contends);
- drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
- i810_dma_schedule(dev, 1);
+ drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
if (!dev->context_flag) {
if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT)) {
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.h
index 0f5f42bb6..334cacb2a 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.h
@@ -32,6 +32,50 @@
#ifndef _I810_DRV_H_
#define _I810_DRV_H_
+typedef struct drm_i810_buf_priv {
+ u32 *in_use;
+ int my_use_idx;
+ int currently_mapped;
+ void *virtual;
+ void *kernel_virtual;
+ int map_count;
+ struct vm_area_struct *vma;
+} drm_i810_buf_priv_t;
+
+typedef struct _drm_i810_ring_buffer{
+ int tail_mask;
+ unsigned long Start;
+ unsigned long End;
+ unsigned long Size;
+ u8 *virtual_start;
+ int head;
+ int tail;
+ int space;
+} drm_i810_ring_buffer_t;
+
+typedef struct drm_i810_private {
+ int ring_map_idx;
+ int buffer_map_idx;
+
+ drm_i810_ring_buffer_t ring;
+ drm_i810_sarea_t *sarea_priv;
+
+ unsigned long hw_status_page;
+ unsigned long counter;
+
+ atomic_t flush_done;
+ wait_queue_head_t flush_queue; /* Processes waiting until flush */
+ drm_buf_t *mmap_buffer;
+
+
+ u32 front_di1, back_di1, zi1;
+
+ int back_offset;
+ int depth_offset;
+ int w, h;
+ int pitch;
+} drm_i810_private_t;
+
/* i810_drv.c */
extern int i810_init(void);
extern void i810_cleanup(void);
@@ -46,16 +90,22 @@ extern int i810_unlock(struct inode *inode, struct file *filp,
/* i810_dma.c */
extern int i810_dma_schedule(drm_device_t *dev, int locked);
-extern int i810_dma(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+extern int i810_getbuf(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
extern int i810_irq_install(drm_device_t *dev, int irq);
extern int i810_irq_uninstall(drm_device_t *dev);
extern int i810_control(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int i810_lock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern void i810_dma_init(drm_device_t *dev);
-extern void i810_dma_cleanup(drm_device_t *dev);
+extern int i810_dma_init(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int i810_flush_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid);
+extern int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
/* i810_bufs.c */
@@ -67,10 +117,108 @@ extern int i810_markbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int i810_freebufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int i810_mapbufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
extern int i810_addmap(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+ /* i810_context.c */
+extern int i810_resctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int i810_addctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int i810_modctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int i810_getctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int i810_switchctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int i810_newctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int i810_rmctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+extern int i810_context_switch(drm_device_t *dev, int old, int new);
+extern int i810_context_switch_complete(drm_device_t *dev, int new);
+
+#define I810_VERBOSE 0
+
+
+int i810_dma_vertex(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+int i810_swap_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+int i810_clear_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
+#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
+#define CMD_REPORT_HEAD (7<<23)
+#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1)
+#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1)
+
+#define INST_PARSER_CLIENT 0x00000000
+#define INST_OP_FLUSH 0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+
+#define BB1_START_ADDR_MASK (~0x7)
+#define BB1_PROTECTED (1<<0)
+#define BB1_UNPROTECTED (0<<0)
+#define BB2_END_ADDR_MASK (~0x7)
+
+#define I810REG_HWSTAM 0x02098
+#define I810REG_INT_IDENTITY_R 0x020a4
+#define I810REG_INT_MASK_R 0x020a8
+#define I810REG_INT_ENABLE_R 0x020a0
+
+#define LP_RING 0x2030
+#define HP_RING 0x2040
+#define RING_TAIL 0x00
+#define TAIL_ADDR 0x000FFFF8
+#define RING_HEAD 0x04
+#define HEAD_WRAP_COUNT 0xFFE00000
+#define HEAD_WRAP_ONE 0x00200000
+#define HEAD_ADDR 0x001FFFFC
+#define RING_START 0x08
+#define START_ADDR 0x00FFFFF8
+#define RING_LEN 0x0C
+#define RING_NR_PAGES 0x000FF000
+#define RING_REPORT_MASK 0x00000006
+#define RING_REPORT_64K 0x00000002
+#define RING_REPORT_128K 0x00000004
+#define RING_NO_REPORT 0x00000000
+#define RING_VALID_MASK 0x00000001
+#define RING_VALID 0x00000001
+#define RING_INVALID 0x00000000
+
+#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define SC_UPDATE_SCISSOR (0x1<<1)
+#define SC_ENABLE_MASK (0x1<<0)
+#define SC_ENABLE (0x1<<0)
+
+#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define SCI_YMIN_MASK (0xffff<<16)
+#define SCI_XMIN_MASK (0xffff<<0)
+#define SCI_YMAX_MASK (0xffff<<16)
+#define SCI_XMAX_MASK (0xffff<<0)
+
+#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x2)
+#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+#define GFX_OP_PRIMITIVE ((0x3<<29)|(0x1f<<24))
+
+#define CMD_OP_Z_BUFFER_INFO ((0x0<<29)|(0x16<<23))
+#define CMD_OP_DESTBUFFER_INFO ((0x0<<29)|(0x15<<23))
+
+#define BR00_BITBLT_CLIENT 0x40000000
+#define BR00_OP_COLOR_BLT 0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR13_SOLID_PATTERN 0x80000000
+
+
#endif
+
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c
index 2e24e5b48..fe6a7b525 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c
@@ -25,17 +25,15 @@
*
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
* Jeff Hartmann <jhartmann@precisioninsight.com>
+ * Keith Whitwell <keithw@precisioninsight.com>
*
- * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c,v 1.1 2000/02/11 17:26:07 dawes Exp $
+ * $XFree86$
*
*/
#define __NO_VERSION__
#include "drmP.h"
#include "mga_drv.h"
-#include "mgareg_flags.h"
-#include "mga_dma.h"
-#include "mga_state.h"
#include <linux/interrupt.h> /* For task queue support */
@@ -48,643 +46,575 @@
#define MGA_WRITE(reg,val) do { MGA_DEREF(reg) = val; } while (0)
#define PDEA_pagpxfer_enable 0x2
-#define MGA_SYNC_TAG 0x423f4200
-typedef enum {
- TT_GENERAL,
- TT_BLIT,
- TT_VECTOR,
- TT_VERTEX
-} transferType_t;
+static int mga_flush_queue(drm_device_t *dev);
-
-static void mga_delay(void)
+static unsigned long mga_alloc_page(drm_device_t *dev)
{
- return;
+ unsigned long address;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ address = __get_free_page(GFP_KERNEL);
+ if(address == 0UL) {
+ return 0;
+ }
+ atomic_inc(&mem_map[MAP_NR((void *) address)].count);
+ set_bit(PG_locked, &mem_map[MAP_NR((void *) address)].flags);
+
+ return address;
}
-int mga_dma_cleanup(drm_device_t *dev)
+static void mga_free_page(drm_device_t *dev, unsigned long page)
{
- if(dev->dev_private) {
- drm_mga_private_t *dev_priv =
- (drm_mga_private_t *) dev->dev_private;
-
- if(dev_priv->ioremap) {
- int temp = (dev_priv->warp_ucode_size +
- dev_priv->primary_size +
- PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
+ DRM_DEBUG("%s\n", __FUNCTION__);
- drm_ioremapfree((void *) dev_priv->ioremap, temp);
- }
-
- drm_free(dev->dev_private, sizeof(drm_mga_private_t),
- DRM_MEM_DRIVER);
- dev->dev_private = NULL;
+ if(page == 0UL) {
+ return;
}
-
- return 0;
+ atomic_dec(&mem_map[MAP_NR((void *) page)].count);
+ clear_bit(PG_locked, &mem_map[MAP_NR((void *) page)].flags);
+ wake_up(&mem_map[MAP_NR((void *) page)].wait);
+ free_page(page);
+ return;
}
-static int mga_alloc_kernel_queue(drm_device_t *dev)
+static void mga_delay(void)
{
- drm_queue_t *queue = NULL;
- /* Allocate a new queue */
- down(&dev->struct_sem);
-
- if(dev->queue_count != 0) {
- /* Reseting the kernel context here is not
- * a race, since it can only happen when that
- * queue is empty.
- */
- queue = dev->queuelist[DRM_KERNEL_CONTEXT];
- printk("Kernel queue already allocated\n");
- } else {
- queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES);
- if(!queue) {
- up(&dev->struct_sem);
- printk("out of memory\n");
- return -ENOMEM;
- }
- ++dev->queue_count;
- dev->queuelist = drm_alloc(sizeof(*dev->queuelist),
- DRM_MEM_QUEUES);
- if(!dev->queuelist) {
- up(&dev->struct_sem);
- drm_free(queue, sizeof(*queue), DRM_MEM_QUEUES);
- printk("out of memory\n");
- return -ENOMEM;
- }
- }
-
- memset(queue, 0, sizeof(*queue));
- atomic_set(&queue->use_count, 1);
- atomic_set(&queue->finalization, 0);
- atomic_set(&queue->block_count, 0);
- atomic_set(&queue->block_read, 0);
- atomic_set(&queue->block_write, 0);
- atomic_set(&queue->total_queued, 0);
- atomic_set(&queue->total_flushed, 0);
- atomic_set(&queue->total_locks, 0);
-
- init_waitqueue_head(&queue->write_queue);
- init_waitqueue_head(&queue->read_queue);
- init_waitqueue_head(&queue->flush_queue);
-
- queue->flags = 0;
-
- drm_waitlist_create(&queue->waitlist, dev->dma->buf_count);
-
- dev->queue_slots = 1;
- dev->queuelist[DRM_KERNEL_CONTEXT] = queue;
- dev->queue_count--;
-
- up(&dev->struct_sem);
- printk("%d (new)\n", dev->queue_count - 1);
- return DRM_KERNEL_CONTEXT;
+ return;
}
-static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
- drm_mga_private_t *dev_priv;
- drm_map_t *prim_map = NULL;
- drm_map_t *sarea_map = NULL;
- int temp;
+void mga_flush_write_combine(void)
+{
+ int xchangeDummy;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ __asm__ volatile(" push %%eax ; xchg %%eax, %0 ; pop %%eax" : : "m" (xchangeDummy));
+ __asm__ volatile(" push %%eax ; push %%ebx ; push %%ecx ; push %%edx ;"
+ " movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ;"
+ " pop %%eax" : /* no outputs */ : /* no inputs */ );
+}
- dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
- if(dev_priv == NULL) return -ENOMEM;
- dev->dev_private = (void *) dev_priv;
+/* These are two age tags that will never be sent to
+ * the hardware */
+#define MGA_BUF_USED 0xffffffff
+#define MGA_BUF_FREE 0
- printk("dev_private\n");
+static int mga_freelist_init(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_freelist_t *item;
+ int i;
- memset(dev_priv, 0, sizeof(drm_mga_private_t));
- atomic_set(&dev_priv->pending_bufs, 0);
+ DRM_DEBUG("%s\n", __FUNCTION__);
- if((init->reserved_map_idx >= dev->map_count) ||
- (init->buffer_map_idx >= dev->map_count)) {
- mga_dma_cleanup(dev);
- printk("reserved_map or buffer_map are invalid\n");
- return -EINVAL;
- }
+ dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+ if(dev_priv->head == NULL) return -ENOMEM;
+ memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
+ dev_priv->head->age = MGA_BUF_USED;
- if(mga_alloc_kernel_queue(dev) != DRM_KERNEL_CONTEXT) {
- mga_dma_cleanup(dev);
- DRM_ERROR("Kernel context queue not present\n");
+ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[ i ];
+ buf_priv = buf->dev_private;
+ item = drm_alloc(sizeof(drm_mga_freelist_t),
+ DRM_MEM_DRIVER);
+ if(item == NULL) return -ENOMEM;
+ memset(item, 0, sizeof(drm_mga_freelist_t));
+ item->age = MGA_BUF_FREE;
+ item->prev = dev_priv->head;
+ item->next = dev_priv->head->next;
+ if(dev_priv->head->next != NULL)
+ dev_priv->head->next->prev = item;
+ if(item->next == NULL) dev_priv->tail = item;
+ item->buf = buf;
+ buf_priv->my_freelist = item;
+ buf_priv->discard = 0;
+ buf_priv->dispatched = 0;
+ dev_priv->head->next = item;
}
-
- dev_priv->reserved_map_idx = init->reserved_map_idx;
- dev_priv->buffer_map_idx = init->buffer_map_idx;
- sarea_map = dev->maplist[0];
- dev_priv->sarea_priv = (drm_mga_sarea_t *)
- ((u8 *)sarea_map->handle +
- init->sarea_priv_offset);
- printk("sarea_priv\n");
-
- /* Scale primary size to the next page */
- dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) /
- PAGE_SIZE) * PAGE_SIZE;
- dev_priv->warp_ucode_size = init->warp_ucode_size;
- dev_priv->chipset = init->chipset;
- dev_priv->fbOffset = init->fbOffset;
- dev_priv->backOffset = init->backOffset;
- dev_priv->depthOffset = init->depthOffset;
- dev_priv->textureOffset = init->textureOffset;
- dev_priv->textureSize = init->textureSize;
- dev_priv->cpp = init->cpp;
- dev_priv->sgram = init->sgram;
- dev_priv->stride = init->stride;
-
- dev_priv->frontOrg = init->frontOrg;
- dev_priv->backOrg = init->backOrg;
- dev_priv->depthOrg = init->depthOrg;
- dev_priv->mAccess = init->mAccess;
-
- printk("memcpy\n");
- memcpy(&dev_priv->WarpIndex, &init->WarpIndex,
- sizeof(mgaWarpIndex) * MGA_MAX_WARP_PIPES);
- printk("memcpy done\n");
- prim_map = dev->maplist[init->reserved_map_idx];
- dev_priv->prim_phys_head = dev->agp->base + init->reserved_map_agpstart;
- temp = init->warp_ucode_size + dev_priv->primary_size;
- temp = ((temp + PAGE_SIZE - 1) /
- PAGE_SIZE) * PAGE_SIZE;
- printk("temp : %x\n", temp);
- printk("dev->agp->base: %lx\n", dev->agp->base);
- printk("init->reserved_map_agpstart: %x\n", init->reserved_map_agpstart);
-
-
- dev_priv->ioremap = drm_ioremap(dev->agp->base + init->reserved_map_agpstart,
- temp);
- if(dev_priv->ioremap == NULL) {
- printk("Ioremap failed\n");
- mga_dma_cleanup(dev);
- return -ENOMEM;
- }
-
-
+ return 0;
+}
- dev_priv->prim_head = (u32 *)dev_priv->ioremap;
- printk("dev_priv->prim_head : %p\n", dev_priv->prim_head);
- dev_priv->current_dma_ptr = dev_priv->prim_head;
- dev_priv->prim_num_dwords = 0;
- dev_priv->prim_max_dwords = dev_priv->primary_size / 4;
-
- printk("dma initialization\n");
+static void mga_freelist_cleanup(drm_device_t *dev)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_freelist_t *item;
+ drm_mga_freelist_t *prev;
- /* Private is now filled in, initialize the hardware */
- {
- PRIMLOCALS;
- PRIMRESET( dev_priv );
- PRIMGETPTR( dev_priv );
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, 0);
- PRIMOUTREG(MGAREG_SOFTRAP, 0);
- PRIMADVANCE( dev_priv );
+ DRM_DEBUG("%s\n", __FUNCTION__);
- /* Poll for the first buffer to insure that
- * the status register will be correct
- */
- printk("phys_head : %lx\n", phys_head);
+ item = dev_priv->head;
+ while(item) {
+ prev = item;
+ item = item->next;
+ drm_free(prev, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+ }
- MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
+ dev_priv->head = dev_priv->tail = NULL;
+}
- while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) {
- int i;
- for(i = 0 ; i < 4096; i++) mga_delay();
+/* Frees dispatch lock */
+static inline void mga_dma_quiescent(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned long end;
+ int i;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ end = jiffies + (HZ*3);
+ while(1) {
+ if(!test_and_set_bit(MGA_IN_DISPATCH,
+ &dev_priv->dispatch_status)) {
+ break;
}
-
- MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
-
- MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) |
- PDEA_pagpxfer_enable));
-
- while(MGA_READ(MGAREG_DWGSYNC) == MGA_SYNC_TAG) {
- int i;
- for(i = 0; i < 4096; i++) mga_delay();
+ if((signed)(end - jiffies) <= 0) {
+ DRM_ERROR("irqs: %d wanted %d\n",
+ atomic_read(&dev->total_irq),
+ atomic_read(&dma->total_lost));
+ DRM_ERROR("lockup\n");
+ goto out_nolock;
}
+ for (i = 0 ; i < 2000 ; i++) mga_delay();
+ }
+ end = jiffies + (HZ*3);
+ DRM_DEBUG("quiescent status : %x\n", MGA_READ(MGAREG_STATUS));
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) {
+ if((signed)(end - jiffies) <= 0) {
+ DRM_ERROR("irqs: %d wanted %d\n",
+ atomic_read(&dev->total_irq),
+ atomic_read(&dma->total_lost));
+ DRM_ERROR("lockup\n");
+ goto out_status;
+ }
+ for (i = 0 ; i < 2000 ; i++) mga_delay();
+ }
+ sarea_priv->dirty |= MGA_DMA_FLUSH;
+out_status:
+ clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
+out_nolock:
+}
+
+static void mga_reset_freelist(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ int i;
+
+ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[ i ];
+ buf_priv = buf->dev_private;
+ buf_priv->my_freelist->age = MGA_BUF_FREE;
}
-
- printk("dma init was successful\n");
- return 0;
}
-int mga_dma_init(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+/* Least recently used :
+ * These operations are not atomic b/c they are protected by the
+ * hardware lock */
+
+drm_buf_t *mga_freelist_get(drm_device_t *dev)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_mga_init_t init;
+ DECLARE_WAITQUEUE(entry, current);
+ drm_mga_private_t *dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+ drm_mga_freelist_t *prev;
+ drm_mga_freelist_t *next;
+ static int failed = 0;
+
+ DRM_DEBUG("%s : tail->age : %d last_prim_age : %d\n", __FUNCTION__,
+ dev_priv->tail->age, dev_priv->last_prim_age);
- copy_from_user_ret(&init, (drm_mga_init_t *)arg, sizeof(init), -EFAULT);
+ if(failed >= 1000 && dev_priv->tail->age >= dev_priv->last_prim_age) {
+ DRM_DEBUG("I'm waiting on the freelist!!! %d\n",
+ dev_priv->last_prim_age);
+ set_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
+ current->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(&dev_priv->buf_queue, &entry);
+ for (;;) {
+ mga_dma_schedule(dev, 0);
+ if(!test_bit(MGA_IN_GETBUF,
+ &dev_priv->dispatch_status))
+ break;
+ atomic_inc(&dev->total_sleeps);
+ schedule();
+ if (signal_pending(current)) {
+ clear_bit(MGA_IN_GETBUF,
+ &dev_priv->dispatch_status);
+ goto failed_getbuf;
+ }
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev_priv->buf_queue, &entry);
+ }
- switch(init.func) {
- case MGA_INIT_DMA:
- return mga_dma_initialize(dev, &init);
- case MGA_CLEANUP_DMA:
- return mga_dma_cleanup(dev);
+ if(dev_priv->tail->age < dev_priv->last_prim_age) {
+ prev = dev_priv->tail->prev;
+ next = dev_priv->tail;
+ prev->next = NULL;
+ next->prev = next->next = NULL;
+ dev_priv->tail = prev;
+ next->age = MGA_BUF_USED;
+ failed = 0;
+ return next->buf;
}
- return -EINVAL;
+failed_getbuf:
+ failed++;
+ return NULL;
}
-#define MGA_ILOAD_CMD (DC_opcod_iload | DC_atype_rpl | \
- DC_linear_linear | DC_bltmod_bfcol | \
- (0xC << DC_bop_SHIFT) | DC_sgnzero_enable | \
- DC_shftzero_enable | DC_clipdis_enable)
-
-static void __mga_iload_small(drm_device_t *dev,
- drm_buf_t *buf,
- int use_agp)
+int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf)
{
- drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_private_t *dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- unsigned long address = (unsigned long)buf->bus_address;
- int length = buf->used;
- int y1 = buf_priv->boxes[0].y1;
- int x1 = buf_priv->boxes[0].x1;
- int y2 = buf_priv->boxes[0].y2;
- int x2 = buf_priv->boxes[0].x2;
- int dstorg = buf_priv->ContextState[MGA_CTXREG_DSTORG];
- int maccess = buf_priv->ContextState[MGA_CTXREG_MACCESS];
- PRIMLOCALS;
-
- PRIMRESET(dev_priv);
- PRIMGETPTR(dev_priv);
+ drm_mga_freelist_t *prev;
+ drm_mga_freelist_t *head;
+ drm_mga_freelist_t *next;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if(buf_priv->my_freelist->age == MGA_BUF_USED) {
+ /* Discarded buffer, put it on the tail */
+ next = buf_priv->my_freelist;
+ next->age = MGA_BUF_FREE;
+ prev = dev_priv->tail;
+ prev->next = next;
+ next->prev = prev;
+ next->next = NULL;
+ dev_priv->tail = next;
+ DRM_DEBUG("Discarded\n");
+ } else {
+ /* Normally aged buffer, put it on the head + 1,
+ * as the real head is a sentinal element
+ */
+ next = buf_priv->my_freelist;
+ head = dev_priv->head;
+ prev = head->next;
+ head->next = next;
+ prev->prev = next;
+ next->prev = head;
+ next->next = prev;
+ }
- PRIMOUTREG(MGAREG_DSTORG, dstorg | use_agp);
- PRIMOUTREG(MGAREG_MACCESS, maccess);
- PRIMOUTREG(MGAREG_PITCH, (1 << 15));
- PRIMOUTREG(MGAREG_YDST, y1 * (x2 - x1));
- PRIMOUTREG(MGAREG_LEN, 1);
- PRIMOUTREG(MGAREG_FXBNDRY, ((x2 - x1) * (y2 - y1) - 1) << 16);
- PRIMOUTREG(MGAREG_AR0, (x2 - x1) * (y2 - y1) - 1);
- PRIMOUTREG(MGAREG_AR3, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, MGA_ILOAD_CMD);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_SECADDRESS, address | TT_BLIT);
- PRIMOUTREG(MGAREG_SECEND, (address + length) | use_agp);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, 0);
- PRIMOUTREG(MGAREG_SOFTRAP, 0);
- PRIMADVANCE(dev_priv);
-#if 0
- /* For now we need to set this in the ioctl */
- sarea_priv->dirty |= MGASAREA_NEW_CONTEXT;
-#endif
- MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
- while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
-
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
+ return 0;
}
-static void __mga_iload_xy(drm_device_t *dev,
- drm_buf_t *buf,
- int use_agp)
+static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init)
{
- drm_mga_private_t *dev_priv = dev->dev_private;
- drm_mga_buf_priv_t *buf_priv = buf->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- unsigned long address = (unsigned long)buf->bus_address;
- int length = buf->used;
- int y1 = buf_priv->boxes[0].y1;
- int x1 = buf_priv->boxes[0].x1;
- int y2 = buf_priv->boxes[0].y2;
- int x2 = buf_priv->boxes[0].x2;
- int dstorg = buf_priv->ContextState[MGA_CTXREG_DSTORG];
- int maccess = buf_priv->ContextState[MGA_CTXREG_MACCESS];
- int pitch = buf_priv->ServerState[MGA_2DREG_PITCH];
- int width, height;
- int texperdword = 0;
- PRIMLOCALS;
-
- width = (x2 - x1);
- height = (y2 - y1);
- switch((maccess & 0x00000003)) {
- case 0:
- texperdword = 4;
- break;
- case 1:
- texperdword = 2;
- break;
- case 2:
- texperdword = 1;
- break;
- default:
- DRM_ERROR("Invalid maccess value passed to __mga_iload_xy\n");
- return;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_prim_buf_t *prim_buffer;
+ int i, temp, size_of_buf;
+ int offset = init->reserved_map_agpstart;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) /
+ PAGE_SIZE) * PAGE_SIZE;
+ size_of_buf = dev_priv->primary_size / MGA_NUM_PRIM_BUFS;
+ dev_priv->warp_ucode_size = init->warp_ucode_size;
+ dev_priv->prim_bufs = drm_alloc(sizeof(drm_mga_prim_buf_t *) *
+ (MGA_NUM_PRIM_BUFS + 1),
+ DRM_MEM_DRIVER);
+ if(dev_priv->prim_bufs == NULL) {
+ DRM_ERROR("Unable to allocate memory for prim_buf\n");
+ return -ENOMEM;
}
+ memset(dev_priv->prim_bufs,
+ 0, sizeof(drm_mga_prim_buf_t *) * (MGA_NUM_PRIM_BUFS + 1));
- x2 = x1 + width;
- x2 = (x2 + (texperdword - 1)) & ~(texperdword - 1);
- x1 = (x1 + (texperdword - 1)) & ~(texperdword - 1);
- width = x2 - x1;
-
- PRIMRESET(dev_priv);
- PRIMGETPTR(dev_priv);
- PRIMOUTREG(MGAREG_DSTORG, dstorg | use_agp);
- PRIMOUTREG(MGAREG_MACCESS, maccess);
- PRIMOUTREG(MGAREG_PITCH, pitch);
- PRIMOUTREG(MGAREG_YDSTLEN, (y1 << 16) | height);
-
- PRIMOUTREG(MGAREG_FXBNDRY, ((x1+width-1) << 16) | x1);
- PRIMOUTREG(MGAREG_AR0, width * height - 1);
- PRIMOUTREG(MGAREG_AR3, 0 );
- PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, MGA_ILOAD_CMD);
-
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_SECADDRESS, address | TT_BLIT);
- PRIMOUTREG(MGAREG_SECEND, (address + length) | use_agp);
+ temp = init->warp_ucode_size + dev_priv->primary_size;
+ temp = ((temp + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, 0);
- PRIMOUTREG(MGAREG_SOFTRAP, 0);
- PRIMADVANCE(dev_priv);
-#if 0
- /* For now we need to set this in the ioctl */
- sarea_priv->dirty |= MGASAREA_NEW_CONTEXT;
-#endif
- MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
- while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
-
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
+ dev_priv->ioremap = drm_ioremap(dev->agp->base + offset,
+ temp);
+ if(dev_priv->ioremap == NULL) {
+ DRM_DEBUG("Ioremap failed\n");
+ return -ENOMEM;
+ }
+ init_waitqueue_head(&dev_priv->wait_queue);
+
+ for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) {
+ prim_buffer = drm_alloc(sizeof(drm_mga_prim_buf_t),
+ DRM_MEM_DRIVER);
+ if(prim_buffer == NULL) return -ENOMEM;
+ memset(prim_buffer, 0, sizeof(drm_mga_prim_buf_t));
+ prim_buffer->phys_head = offset + dev->agp->base;
+ prim_buffer->current_dma_ptr =
+ prim_buffer->head =
+ (u32 *) (dev_priv->ioremap +
+ offset -
+ init->reserved_map_agpstart);
+ prim_buffer->num_dwords = 0;
+ prim_buffer->max_dwords = size_of_buf / sizeof(u32);
+ prim_buffer->max_dwords -= 5; /* Leave room for the softrap */
+ prim_buffer->sec_used = 0;
+ prim_buffer->idx = i;
+ prim_buffer->prim_age = i + 1;
+ offset = offset + size_of_buf;
+ dev_priv->prim_bufs[i] = prim_buffer;
+ }
+ dev_priv->current_prim_idx = 0;
+ dev_priv->next_prim =
+ dev_priv->last_prim =
+ dev_priv->current_prim =
+ dev_priv->prim_bufs[0];
+ dev_priv->next_prim_age = 2;
+ dev_priv->last_prim_age = 1;
+ set_bit(MGA_BUF_IN_USE, &dev_priv->current_prim->buffer_status);
+ return 0;
}
-static void mga_dma_dispatch_iload(drm_device_t *dev, drm_buf_t *buf)
+void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim)
{
- drm_mga_buf_priv_t *buf_priv = buf->dev_private;
-
- int use_agp = PDEA_pagpxfer_enable;
- int x1 = buf_priv->boxes[0].x1;
- int x2 = buf_priv->boxes[0].x2;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int use_agp = PDEA_pagpxfer_enable;
+ unsigned long end;
+ int i;
+ int next_idx;
+ PRIMLOCALS;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ dev_priv->last_prim = prim;
- if((x2 - x1) < 32) {
- printk("using iload small\n");
- __mga_iload_small(dev, buf, use_agp);
+ /* We never check for overflow, b/c there is always room */
+ PRIMPTR(prim);
+ if(num_dwords <= 0) {
+ DRM_DEBUG("num_dwords == 0 when dispatched\n");
+ goto out_prim_wait;
+ }
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_SOFTRAP, 0);
+ PRIMFINISH(prim);
+
+ end = jiffies + (HZ*3);
+ if(sarea_priv->dirty & MGA_DMA_FLUSH) {
+ DRM_DEBUG("Dma top flush\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) {
+ if((signed)(end - jiffies) <= 0) {
+ DRM_ERROR("irqs: %d wanted %d\n",
+ atomic_read(&dev->total_irq),
+ atomic_read(&dma->total_lost));
+ DRM_ERROR("lockup in fire primary "
+ "(Dma Top Flush)\n");
+ goto out_prim_wait;
+ }
+
+ for (i = 0 ; i < 4096 ; i++) mga_delay();
+ }
+ sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
} else {
- printk("using iload xy\n");
- __mga_iload_xy(dev, buf, use_agp);
- }
-}
-
-static void mga_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf)
-{
- drm_mga_private_t *dev_priv = dev->dev_private;
- drm_mga_buf_priv_t *buf_priv = buf->dev_private;
- unsigned long address = (unsigned long)buf->bus_address;
- int length = buf->used;
- int use_agp = PDEA_pagpxfer_enable;
- int i, count;
- PRIMLOCALS;
-
- PRIMRESET(dev_priv);
-
- count = buf_priv->nbox;
- if (count == 0)
- count = 1;
-
- mgaEmitState( dev_priv, buf_priv );
-
- for (i = 0 ; i < count ; i++) {
- if (i < buf_priv->nbox)
- mgaEmitClipRect( dev_priv, &buf_priv->boxes[i] );
-
- PRIMGETPTR(dev_priv);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_SECADDRESS, address | TT_VERTEX);
- PRIMOUTREG( MGAREG_SECEND, (address + length) | use_agp);
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DWGSYNC, 0);
- PRIMOUTREG( MGAREG_SOFTRAP, 0);
- PRIMADVANCE(dev_priv);
+ DRM_DEBUG("Status wait\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00020001) != 0x00020000) {
+ if((signed)(end - jiffies) <= 0) {
+ DRM_ERROR("irqs: %d wanted %d\n",
+ atomic_read(&dev->total_irq),
+ atomic_read(&dma->total_lost));
+ DRM_ERROR("lockup in fire primary "
+ "(Status Wait)\n");
+ goto out_prim_wait;
+ }
+
+ for (i = 0 ; i < 4096 ; i++) mga_delay();
+ }
}
- PRIMGETPTR( dev_priv );
-
- MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
- while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
-
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
+ mga_flush_write_combine();
+ atomic_inc(&dev_priv->pending_bufs);
+ MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
+ MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
+ prim->num_dwords = 0;
+ sarea_priv->last_enqueue = prim->prim_age;
+
+ next_idx = prim->idx + 1;
+ if(next_idx >= MGA_NUM_PRIM_BUFS)
+ next_idx = 0;
+
+ dev_priv->next_prim = dev_priv->prim_bufs[next_idx];
+ return;
+
+ out_prim_wait:
+ prim->num_dwords = 0;
+ prim->sec_used = 0;
+ clear_bit(MGA_BUF_IN_USE, &prim->buffer_status);
+ wake_up_interruptible(&dev_priv->wait_queue);
+ clear_bit(MGA_BUF_SWAP_PENDING, &prim->buffer_status);
+ clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
}
-
-/* Used internally for the small buffers generated from client state
- * information.
- */
-static void mga_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf)
+int mga_advance_primary(drm_device_t *dev)
{
+ DECLARE_WAITQUEUE(entry, current);
drm_mga_private_t *dev_priv = dev->dev_private;
- unsigned long address = (unsigned long)buf->bus_address;
- int length = buf->used;
- int use_agp = PDEA_pagpxfer_enable;
- PRIMLOCALS;
-
- PRIMRESET(dev_priv);
- PRIMGETPTR(dev_priv);
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_SECADDRESS, address | TT_GENERAL);
- PRIMOUTREG( MGAREG_SECEND, (address + length) | use_agp);
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DWGSYNC, 0);
- PRIMOUTREG( MGAREG_SOFTRAP, 0);
- PRIMADVANCE(dev_priv);
+ drm_mga_prim_buf_t *prim_buffer;
+ drm_device_dma_t *dma = dev->dma;
+ int next_prim_idx;
+ int ret = 0;
+
+ /* This needs to reset the primary buffer if available,
+ * we should collect stats on how many times it bites
+ * it's tail */
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ next_prim_idx = dev_priv->current_prim_idx + 1;
+ if(next_prim_idx >= MGA_NUM_PRIM_BUFS)
+ next_prim_idx = 0;
+ prim_buffer = dev_priv->prim_bufs[next_prim_idx];
+ set_bit(MGA_IN_WAIT, &dev_priv->dispatch_status);
+
+ /* In use is cleared in interrupt handler */
+
+ if(test_and_set_bit(MGA_BUF_IN_USE, &prim_buffer->buffer_status)) {
+ add_wait_queue(&dev_priv->wait_queue, &entry);
+ current->state = TASK_INTERRUPTIBLE;
+
+ for (;;) {
+ mga_dma_schedule(dev, 0);
+ if(!test_and_set_bit(MGA_BUF_IN_USE,
+ &prim_buffer->buffer_status))
+ break;
+ atomic_inc(&dev->total_sleeps);
+ atomic_inc(&dma->total_missed_sched);
+ schedule();
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev_priv->wait_queue, &entry);
+ if(ret) return ret;
+ }
+ clear_bit(MGA_IN_WAIT, &dev_priv->dispatch_status);
+
+ /* This primary buffer is now free to use */
+ prim_buffer->current_dma_ptr = prim_buffer->head;
+ prim_buffer->num_dwords = 0;
+ prim_buffer->sec_used = 0;
+ prim_buffer->prim_age = dev_priv->next_prim_age++;
+ if(prim_buffer->prim_age == 0 || prim_buffer->prim_age == 0xffffffff) {
+ mga_flush_queue(dev);
+ mga_dma_quiescent(dev);
+ mga_reset_freelist(dev);
+ prim_buffer->prim_age = (dev_priv->next_prim_age += 2);
+ }
- MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
- while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
+ /* Reset all buffer status stuff */
+ clear_bit(MGA_BUF_NEEDS_OVERFLOW, &prim_buffer->buffer_status);
+ clear_bit(MGA_BUF_FORCE_FIRE, &prim_buffer->buffer_status);
+ clear_bit(MGA_BUF_SWAP_PENDING, &prim_buffer->buffer_status);
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
+ dev_priv->current_prim = prim_buffer;
+ dev_priv->current_prim_idx = next_prim_idx;
+ return 0;
}
-/* Frees dispatch lock */
-static inline void mga_dma_quiescent(drm_device_t *dev)
+/* More dynamic performance decisions */
+static inline int mga_decide_to_fire(drm_device_t *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
- while(1) {
- atomic_inc(&dev_priv->dispatch_lock);
- if(atomic_read(&dev_priv->dispatch_lock) == 1) {
- break;
- } else {
- atomic_dec(&dev_priv->dispatch_lock);
- }
- }
- while((MGA_READ(MGAREG_STATUS) & 0x00020001) != 0x00020000) ;
-#if 0
- MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
-#endif
- while(MGA_READ(MGAREG_DWGSYNC) == MGA_SYNC_TAG) ;
- MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
- while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
- atomic_dec(&dev_priv->dispatch_lock);
-}
+ DRM_DEBUG("%s\n", __FUNCTION__);
-/* Keeps dispatch lock held */
+ if(test_bit(MGA_BUF_FORCE_FIRE, &dev_priv->next_prim->buffer_status)) {
+ atomic_inc(&dma->total_prio);
+ return 1;
+ }
-static inline int mga_dma_is_ready(drm_device_t *dev)
-{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-
- atomic_inc(&dev_priv->dispatch_lock);
- if(atomic_read(&dev_priv->dispatch_lock) == 1) {
- /* We got the lock */
- return 1;
- } else {
- atomic_dec(&dev_priv->dispatch_lock);
- return 0;
+ if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) &&
+ dev_priv->next_prim->num_dwords) {
+ atomic_inc(&dma->total_prio);
+ return 1;
}
-}
-static inline int mga_dma_is_ready_no_hold(drm_device_t *dev)
-{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) &&
+ dev_priv->next_prim->num_dwords) {
+ atomic_inc(&dma->total_prio);
+ return 1;
+ }
- atomic_inc(&dev_priv->dispatch_lock);
- if(atomic_read(&dev_priv->dispatch_lock) == 1) {
- /* We got the lock, but free it */
- atomic_dec(&dev_priv->dispatch_lock);
- return 1;
- } else {
- atomic_dec(&dev_priv->dispatch_lock);
- return 0;
+ if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS - 1) {
+ if(test_bit(MGA_BUF_SWAP_PENDING,
+ &dev_priv->next_prim->buffer_status)) {
+ atomic_inc(&dma->total_dmas);
+ return 1;
+ }
}
-}
-static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
-{
- drm_device_t *dev = (drm_device_t *)device;
- drm_device_dma_t *dma = dev->dma;
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-
- atomic_dec(&dev_priv->dispatch_lock);
- atomic_inc(&dev->total_irq);
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
-
- /* Free previous buffer */
- if (test_and_set_bit(0, &dev->dma_flag)) {
- atomic_inc(&dma->total_missed_free);
- return;
- }
- if (dma->this_buffer) {
- drm_free_buffer(dev, dma->this_buffer);
- dma->this_buffer = NULL;
+ if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS / 2) {
+ if(dev_priv->next_prim->sec_used >= MGA_DMA_BUF_NR / 8) {
+ atomic_inc(&dma->total_hit);
+ return 1;
+ }
}
- clear_bit(0, &dev->dma_flag);
- /* Dispatch new buffer */
- queue_task(&dev->tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ if(atomic_read(&dev_priv->pending_bufs) >= MGA_NUM_PRIM_BUFS / 2) {
+ if(dev_priv->next_prim->sec_used >= MGA_DMA_BUF_NR / 4) {
+ atomic_inc(&dma->total_missed_free);
+ return 1;
+ }
+ }
+ atomic_inc(&dma->total_tried);
+ return 0;
}
-/* Only called by mga_dma_schedule. */
-static int mga_do_dma(drm_device_t *dev, int locked)
+int mga_dma_schedule(drm_device_t *dev, int locked)
{
- drm_buf_t *buf;
- int retcode = 0;
- drm_device_dma_t *dma = dev->dma;
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_mga_buf_priv_t *buf_priv;
+ drm_device_dma_t *dma = dev->dma;
- printk("mga_do_dma\n");
- if (test_and_set_bit(0, &dev->dma_flag)) {
+ if (test_and_set_bit(0, &dev->dma_flag)) {
atomic_inc(&dma->total_missed_dma);
return -EBUSY;
}
-
- if (!dma->next_buffer) {
- DRM_ERROR("No next_buffer\n");
- clear_bit(0, &dev->dma_flag);
- return -EINVAL;
- }
-
- buf = dma->next_buffer;
-
- printk("context %d, buffer %d\n", buf->context, buf->idx);
-
- if (buf->list == DRM_LIST_RECLAIM) {
- drm_clear_next_buffer(dev);
- drm_free_buffer(dev, buf);
- clear_bit(0, &dev->dma_flag);
- return -EINVAL;
- }
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
- if (!buf->used) {
- DRM_ERROR("0 length buffer\n");
- drm_clear_next_buffer(dev);
- drm_free_buffer(dev, buf);
- clear_bit(0, &dev->dma_flag);
- return 0;
- }
-
- if (mga_dma_is_ready(dev) == 0) {
- clear_bit(0, &dev->dma_flag);
- return -EBUSY;
+ if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) ||
+ test_bit(MGA_IN_WAIT, &dev_priv->dispatch_status) ||
+ test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) {
+ locked = 1;
}
- /* Always hold the hardware lock while dispatching.
- */
- if (!locked && !drm_lock_take(&dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- atomic_inc(&dma->total_missed_lock);
- clear_bit(0, &dev->dma_flag);
- atomic_dec(&dev_priv->dispatch_lock);
- return -EBUSY;
+ if (!locked &&
+ !drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) {
+ atomic_inc(&dma->total_missed_lock);
+ clear_bit(0, &dev->dma_flag);
+ DRM_DEBUG("Not locked\n");
+ return -EBUSY;
}
-
- dma->next_queue = dev->queuelist[DRM_KERNEL_CONTEXT];
- drm_clear_next_buffer(dev);
- buf->pending = 1;
- buf->waiting = 0;
- buf->list = DRM_LIST_PEND;
-
- buf_priv = buf->dev_private;
-
- printk("dispatch!\n");
- switch (buf_priv->dma_type) {
- case MGA_DMA_GENERAL:
- mga_dma_dispatch_general(dev, buf);
- break;
- case MGA_DMA_VERTEX:
- mga_dma_dispatch_vertex(dev, buf);
- break;
-/* case MGA_DMA_SETUP: */
-/* mga_dma_dispatch_setup(dev, address, length); */
-/* break; */
- case MGA_DMA_ILOAD:
- mga_dma_dispatch_iload(dev, buf);
- break;
- default:
- printk("bad buffer type %x in dispatch\n", buf_priv->dma_type);
- break;
+ DRM_DEBUG("I'm locked\n");
+
+ if(!test_and_set_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status)) {
+ /* Fire dma buffer */
+ if(mga_decide_to_fire(dev)) {
+ DRM_DEBUG("idx :%d\n", dev_priv->next_prim->idx);
+ clear_bit(MGA_BUF_FORCE_FIRE,
+ &dev_priv->next_prim->buffer_status);
+ if(dev_priv->current_prim == dev_priv->next_prim) {
+ /* Schedule overflow for a later time */
+ set_bit(MGA_BUF_NEEDS_OVERFLOW,
+ &dev_priv->next_prim->buffer_status);
+ }
+ mga_fire_primary(dev, dev_priv->next_prim);
+ } else {
+ clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
+ }
+ } else {
+ DRM_DEBUG("I can't get the dispatch lock\n");
}
- atomic_dec(&dev_priv->pending_bufs);
-
- drm_free_buffer(dev, dma->this_buffer);
- dma->this_buffer = buf;
-
- atomic_add(buf->used, &dma->total_bytes);
- atomic_inc(&dma->total_dmas);
-
+
if (!locked) {
if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT)) {
@@ -692,90 +622,242 @@ static int mga_do_dma(drm_device_t *dev, int locked)
}
}
- clear_bit(0, &dev->dma_flag);
-
- if(!atomic_read(&dev_priv->pending_bufs)) {
- wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue);
- }
-
-#if 0
- wake_up_interruptible(&dev->lock.lock_queue);
-#endif
-
- /* We hold the dispatch lock until the interrupt handler
- * frees it
- */
- return retcode;
+ if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) &&
+ dev_priv->next_prim->num_dwords == 0 &&
+ atomic_read(&dev_priv->pending_bufs) == 0) {
+ /* Everything has been processed by the hardware */
+ clear_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status);
+ wake_up_interruptible(&dev_priv->flush_queue);
+ }
+
+ if(test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) &&
+ dev_priv->tail->age < dev_priv->last_prim_age) {
+ clear_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
+ DRM_DEBUG("Waking up buf queue\n");
+ wake_up_interruptible(&dev_priv->buf_queue);
+ } else if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) {
+ DRM_DEBUG("Not waking buf_queue on %d %d\n",
+ atomic_read(&dev->total_irq),
+ dev_priv->last_prim_age);
+ }
+
+ clear_bit(0, &dev->dma_flag);
+ return 0;
}
-static void mga_dma_schedule_timer_wrapper(unsigned long dev)
+static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
{
- mga_dma_schedule((drm_device_t *)dev, 0);
+ drm_device_t *dev = (drm_device_t *)device;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_prim_buf_t *last_prim_buffer;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ atomic_inc(&dev->total_irq);
+ if((MGA_READ(MGAREG_STATUS) & 0x00000001) != 0x00000001) return;
+ MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
+ last_prim_buffer = dev_priv->last_prim;
+ last_prim_buffer->num_dwords = 0;
+ last_prim_buffer->sec_used = 0;
+ dev_priv->sarea_priv->last_dispatch =
+ dev_priv->last_prim_age = last_prim_buffer->prim_age;
+ clear_bit(MGA_BUF_IN_USE, &last_prim_buffer->buffer_status);
+ wake_up_interruptible(&dev_priv->wait_queue);
+ clear_bit(MGA_BUF_SWAP_PENDING, &last_prim_buffer->buffer_status);
+ clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
+ atomic_dec(&dev_priv->pending_bufs);
+ queue_task(&dev->tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
}
-static void mga_dma_schedule_tq_wrapper(void *dev)
+static void mga_dma_task_queue(void *device)
{
- mga_dma_schedule(dev, 0);
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ mga_dma_schedule((drm_device_t *)device, 0);
}
-int mga_dma_schedule(drm_device_t *dev, int locked)
+int mga_dma_cleanup(drm_device_t *dev)
{
- drm_queue_t *q;
- drm_buf_t *buf;
- int retcode = 0;
- int processed = 0;
- int missed;
- int expire = 20;
- drm_device_dma_t *dma = dev->dma;
-
- printk("mga_dma_schedule\n");
-
- if (test_and_set_bit(0, &dev->interrupt_flag)) {
- /* Not reentrant */
- atomic_inc(&dma->total_missed_sched);
- return -EBUSY;
- }
- missed = atomic_read(&dma->total_missed_sched);
+ DRM_DEBUG("%s\n", __FUNCTION__);
-again:
- /* There is only one queue:
- */
- if (!dma->next_buffer && DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
- q = dev->queuelist[DRM_KERNEL_CONTEXT];
- buf = drm_waitlist_get(&q->waitlist);
- dma->next_buffer = buf;
- dma->next_queue = q;
- if (buf && buf->list == DRM_LIST_RECLAIM) {
- drm_clear_next_buffer(dev);
- drm_free_buffer(dev, buf);
+ if(dev->dev_private) {
+ drm_mga_private_t *dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+
+ if(dev_priv->ioremap) {
+ int temp = (dev_priv->warp_ucode_size +
+ dev_priv->primary_size +
+ PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
+
+ drm_ioremapfree((void *) dev_priv->ioremap, temp);
+ }
+ if(dev_priv->status_page != NULL) {
+ iounmap(dev_priv->status_page);
+ }
+ if(dev_priv->real_status_page != 0UL) {
+ mga_free_page(dev, dev_priv->real_status_page);
+ }
+ if(dev_priv->prim_bufs != NULL) {
+ int i;
+ for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) {
+ if(dev_priv->prim_bufs[i] != NULL) {
+ drm_free(dev_priv->prim_bufs[i],
+ sizeof(drm_mga_prim_buf_t),
+ DRM_MEM_DRIVER);
+ }
+ }
+ drm_free(dev_priv->prim_bufs, sizeof(void *) *
+ (MGA_NUM_PRIM_BUFS + 1),
+ DRM_MEM_DRIVER);
+ }
+ if(dev_priv->head != NULL) {
+ mga_freelist_cleanup(dev);
}
+
+
+ drm_free(dev->dev_private, sizeof(drm_mga_private_t),
+ DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
}
- if (dma->next_buffer) {
- if (!(retcode = mga_do_dma(dev, locked)))
- ++processed;
+ return 0;
+}
+
+static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
+ drm_mga_private_t *dev_priv;
+ drm_map_t *sarea_map = NULL;
+ int i;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ if(dev_priv == NULL) return -ENOMEM;
+ dev->dev_private = (void *) dev_priv;
+
+ memset(dev_priv, 0, sizeof(drm_mga_private_t));
+
+ if((init->reserved_map_idx >= dev->map_count) ||
+ (init->buffer_map_idx >= dev->map_count)) {
+ mga_dma_cleanup(dev);
+ DRM_DEBUG("reserved_map or buffer_map are invalid\n");
+ return -EINVAL;
}
+
+ dev_priv->reserved_map_idx = init->reserved_map_idx;
+ dev_priv->buffer_map_idx = init->buffer_map_idx;
+ sarea_map = dev->maplist[0];
+ dev_priv->sarea_priv = (drm_mga_sarea_t *)
+ ((u8 *)sarea_map->handle +
+ init->sarea_priv_offset);
- /* Try again if we succesfully dispatched a buffer, or if someone
- * tried to schedule while we were working.
- */
- if (--expire) {
- if (missed != atomic_read(&dma->total_missed_sched)) {
- atomic_inc(&dma->total_lost);
- if (mga_dma_is_ready_no_hold(dev))
- goto again;
- }
+ /* Scale primary size to the next page */
+ dev_priv->chipset = init->chipset;
+ dev_priv->frontOffset = init->frontOffset;
+ dev_priv->backOffset = init->backOffset;
+ dev_priv->depthOffset = init->depthOffset;
+ dev_priv->textureOffset = init->textureOffset;
+ dev_priv->textureSize = init->textureSize;
+ dev_priv->cpp = init->cpp;
+ dev_priv->sgram = init->sgram;
+ dev_priv->stride = init->stride;
- if (processed && mga_dma_is_ready_no_hold(dev)) {
- atomic_inc(&dma->total_lost);
- processed = 0;
- goto again;
- }
+ dev_priv->mAccess = init->mAccess;
+ init_waitqueue_head(&dev_priv->flush_queue);
+ init_waitqueue_head(&dev_priv->buf_queue);
+ dev_priv->WarpPipe = -1;
+
+ DRM_DEBUG("chipset: %d ucode_size: %d backOffset: %x depthOffset: %x\n",
+ dev_priv->chipset, dev_priv->warp_ucode_size,
+ dev_priv->backOffset, dev_priv->depthOffset);
+ DRM_DEBUG("cpp: %d sgram: %d stride: %d maccess: %x\n",
+ dev_priv->cpp, dev_priv->sgram, dev_priv->stride,
+ dev_priv->mAccess);
+
+ memcpy(&dev_priv->WarpIndex, &init->WarpIndex,
+ sizeof(drm_mga_warp_index_t) * MGA_MAX_WARP_PIPES);
+
+ for (i = 0 ; i < MGA_MAX_WARP_PIPES ; i++)
+ DRM_DEBUG("warp pipe %d: installed: %d phys: %lx size: %x\n",
+ i,
+ dev_priv->WarpIndex[i].installed,
+ dev_priv->WarpIndex[i].phys_addr,
+ dev_priv->WarpIndex[i].size);
+
+ if(mga_init_primary_bufs(dev, init) != 0) {
+ DRM_ERROR("Can not initialize primary buffers\n");
+ mga_dma_cleanup(dev);
+ return -ENOMEM;
}
-
- clear_bit(0, &dev->interrupt_flag);
-
- return retcode;
+ dev_priv->real_status_page = mga_alloc_page(dev);
+ if(dev_priv->real_status_page == 0UL) {
+ mga_dma_cleanup(dev);
+ DRM_ERROR("Can not allocate status page\n");
+ return -ENOMEM;
+ }
+
+ dev_priv->status_page =
+ ioremap_nocache(virt_to_bus((void *)dev_priv->real_status_page),
+ PAGE_SIZE);
+
+ if(dev_priv->status_page == NULL) {
+ mga_dma_cleanup(dev);
+ DRM_ERROR("Can not remap status page\n");
+ return -ENOMEM;
+ }
+
+ /* Write status page when secend or softrap occurs */
+ MGA_WRITE(MGAREG_PRIMPTR,
+ virt_to_bus((void *)dev_priv->real_status_page) | 0x00000003);
+
+
+ /* Private is now filled in, initialize the hardware */
+ {
+ PRIMLOCALS;
+ PRIMGETPTR( dev_priv );
+
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DWGSYNC, 0x0100);
+ PRIMOUTREG(MGAREG_SOFTRAP, 0);
+ /* Poll for the first buffer to insure that
+ * the status register will be correct
+ */
+
+ mga_flush_write_combine();
+ MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
+
+ MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) |
+ PDEA_pagpxfer_enable));
+
+ while(MGA_READ(MGAREG_DWGSYNC) != 0x0100) ;
+ }
+
+ if(mga_freelist_init(dev) != 0) {
+ DRM_ERROR("Could not initialize freelist\n");
+ mga_dma_cleanup(dev);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+int mga_dma_init(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_mga_init_t init;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ copy_from_user_ret(&init, (drm_mga_init_t *)arg, sizeof(init), -EFAULT);
+
+ switch(init.func) {
+ case MGA_INIT_DMA:
+ return mga_dma_initialize(dev, &init);
+ case MGA_CLEANUP_DMA:
+ return mga_dma_cleanup(dev);
+ }
+
+ return -EINVAL;
}
int mga_irq_install(drm_device_t *dev, int irq)
@@ -792,7 +874,7 @@ int mga_irq_install(drm_device_t *dev, int irq)
dev->irq = irq;
up(&dev->struct_sem);
- printk("install irq handler %d\n", irq);
+ DRM_DEBUG("install irq handler %d\n", irq);
dev->context_flag = 0;
dev->interrupt_flag = 0;
@@ -802,17 +884,15 @@ int mga_irq_install(drm_device_t *dev, int irq)
dev->dma->this_buffer = NULL;
dev->tq.next = NULL;
dev->tq.sync = 0;
- dev->tq.routine = mga_dma_schedule_tq_wrapper;
+ dev->tq.routine = mga_dma_task_queue;
dev->tq.data = dev;
/* Before installing handler */
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
MGA_WRITE(MGAREG_IEN, 0);
-
/* Install handler */
if ((retcode = request_irq(dev->irq,
mga_dma_service,
- 0,
+ SA_SHIRQ,
dev->devname,
dev))) {
down(&dev->struct_sem);
@@ -820,11 +900,9 @@ int mga_irq_install(drm_device_t *dev, int irq)
up(&dev->struct_sem);
return retcode;
}
-
/* After installing handler */
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
+ MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
MGA_WRITE(MGAREG_IEN, 0x00000001);
-
return 0;
}
@@ -838,19 +916,13 @@ int mga_irq_uninstall(drm_device_t *dev)
up(&dev->struct_sem);
if (!irq) return -EINVAL;
-
- printk("remove irq handler %d\n", irq);
-
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
+ DRM_DEBUG("remove irq handler %d\n", irq);
+ MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
MGA_WRITE(MGAREG_IEN, 0);
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
-
free_irq(irq, dev);
-
return 0;
}
-
int mga_control(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
@@ -859,7 +931,9 @@ int mga_control(struct inode *inode, struct file *filp, unsigned int cmd,
drm_control_t ctl;
copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT);
-
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
switch (ctl.func) {
case DRM_INST_HANDLER:
return mga_irq_install(dev, ctl.irq);
@@ -870,36 +944,69 @@ int mga_control(struct inode *inode, struct file *filp, unsigned int cmd,
}
}
-int mga_flush_queue(drm_device_t *dev)
+static int mga_flush_queue(drm_device_t *dev)
{
DECLARE_WAITQUEUE(entry, current);
- drm_queue_t *q = dev->queuelist[DRM_KERNEL_CONTEXT];
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
int ret = 0;
-
- printk("mga_flush_queue\n");
- if(atomic_read(&dev_priv->pending_bufs) != 0) {
- current->state = TASK_INTERRUPTIBLE;
- add_wait_queue(&q->flush_queue, &entry);
- for (;;) {
- if (!atomic_read(&dev_priv->pending_bufs)) break;
- printk("Calling schedule from flush_queue : %d\n",
- atomic_read(&dev_priv->pending_bufs));
- mga_dma_schedule(dev, 1);
- schedule();
- if (signal_pending(current)) {
- ret = -EINTR; /* Can't restart */
- break;
- }
- }
- printk("Exited out of schedule from flush_queue\n");
- current->state = TASK_RUNNING;
- remove_wait_queue(&q->flush_queue, &entry);
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if(dev_priv == NULL) {
+ return 0;
}
+ if(dev_priv->next_prim->num_dwords != 0) {
+ set_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status);
+ current->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(&dev_priv->flush_queue, &entry);
+ for (;;) {
+ mga_dma_schedule(dev, 0);
+ if (!test_bit(MGA_IN_FLUSH,
+ &dev_priv->dispatch_status))
+ break;
+ atomic_inc(&dev->total_sleeps);
+ schedule();
+ if (signal_pending(current)) {
+ ret = -EINTR; /* Can't restart */
+ clear_bit(MGA_IN_FLUSH,
+ &dev_priv->dispatch_status);
+ break;
+ }
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev_priv->flush_queue, &entry);
+ }
return ret;
}
+/* Must be called with the lock held */
+void mga_reclaim_buffers(drm_device_t *dev, pid_t pid)
+{
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+
+ if (!dma) return;
+ if(dev->dev_private == NULL) return;
+ if(dma->buflist == NULL) return;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ mga_flush_queue(dev);
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[ i ];
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+
+ /* Only buffers that need to get reclaimed ever
+ * get set to free
+ */
+ if (buf->pid == pid && buf_priv) {
+ if(buf_priv->my_freelist->age == MGA_BUF_USED)
+ buf_priv->my_freelist->age = MGA_BUF_FREE;
+ }
+ }
+}
+
int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
@@ -909,6 +1016,7 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
int ret = 0;
drm_lock_t lock;
+ DRM_DEBUG("%s\n", __FUNCTION__);
copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
if (lock.context == DRM_KERNEL_CONTEXT) {
@@ -916,16 +1024,15 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
current->pid, lock.context);
return -EINVAL;
}
-
- printk("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
- lock.context, current->pid, dev->lock.hw_lock->lock,
- lock.flags);
-
+
+ DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+ lock.context, current->pid, dev->lock.hw_lock->lock,
+ lock.flags);
if (lock.context < 0) {
return -EINVAL;
}
-
+
/* Only one queue:
*/
@@ -948,8 +1055,6 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
/* Contention */
atomic_inc(&dev->total_sleeps);
current->state = TASK_INTERRUPTIBLE;
- current->policy |= SCHED_YIELD;
- printk("Calling lock schedule\n");
schedule();
if (signal_pending(current)) {
ret = -ERESTARTSYS;
@@ -962,17 +1067,46 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
if (!ret) {
if (lock.flags & _DRM_LOCK_QUIESCENT) {
- printk("_DRM_LOCK_QUIESCENT\n");
- ret = mga_flush_queue(dev);
- if(ret != 0) {
- drm_lock_free(dev, &dev->lock.hw_lock->lock,
- lock.context);
- } else {
- mga_dma_quiescent(dev);
- }
+ DRM_DEBUG("_DRM_LOCK_QUIESCENT\n");
+ mga_flush_queue(dev);
+ mga_dma_quiescent(dev);
}
}
- printk("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
+
+ DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
return ret;
}
+int mga_flush_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_lock_t lock;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("mga_flush_ioctl called without lock held\n");
+ return -EINVAL;
+ }
+
+ if(lock.flags & _DRM_LOCK_FLUSH || lock.flags & _DRM_LOCK_FLUSH_ALL) {
+ drm_mga_prim_buf_t *temp_buf =
+ dev_priv->prim_bufs[dev_priv->current_prim_idx];
+
+ if(temp_buf && temp_buf->num_dwords) {
+ set_bit(MGA_BUF_FORCE_FIRE, &temp_buf->buffer_status);
+ mga_advance_primary(dev);
+ mga_dma_schedule(dev, 1);
+ }
+ }
+ if(lock.flags & _DRM_LOCK_QUIESCENT) {
+ mga_flush_queue(dev);
+ mga_dma_quiescent(dev);
+ }
+
+ return 0;
+}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm.h
new file mode 100644
index 000000000..7228b9051
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm.h
@@ -0,0 +1,269 @@
+/* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*-
+ * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Authors: Jeff Hartmann <jhartmann@precisioninsight.com>
+ * Keith Whitwell <keithw@precisioninsight.com>
+ *
+ * $XFree86$
+ */
+
+#ifndef _MGA_DRM_H_
+#define _MGA_DRM_H_
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmMga.h)
+ */
+#ifndef _MGA_DEFINES_
+#define _MGA_DEFINES_
+
+#define MGA_F 0x1 /* fog */
+#define MGA_A 0x2 /* alpha */
+#define MGA_S 0x4 /* specular */
+#define MGA_T2 0x8 /* multitexture */
+
+#define MGA_WARP_TGZ 0
+#define MGA_WARP_TGZF (MGA_F)
+#define MGA_WARP_TGZA (MGA_A)
+#define MGA_WARP_TGZAF (MGA_F|MGA_A)
+#define MGA_WARP_TGZS (MGA_S)
+#define MGA_WARP_TGZSF (MGA_S|MGA_F)
+#define MGA_WARP_TGZSA (MGA_S|MGA_A)
+#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A)
+#define MGA_WARP_T2GZ (MGA_T2)
+#define MGA_WARP_T2GZF (MGA_T2|MGA_F)
+#define MGA_WARP_T2GZA (MGA_T2|MGA_A)
+#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F)
+#define MGA_WARP_T2GZS (MGA_T2|MGA_S)
+#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F)
+#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A)
+#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A)
+
+#define MGA_MAX_G400_PIPES 16
+#define MGA_MAX_G200_PIPES 8 /* no multitex */
+#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES
+
+#define MGA_CARD_TYPE_G200 1
+#define MGA_CARD_TYPE_G400 2
+
+#define MGA_FRONT 0x1
+#define MGA_BACK 0x2
+#define MGA_DEPTH 0x4
+
+/* 3d state excluding texture units:
+ */
+#define MGA_CTXREG_DSTORG 0 /* validated */
+#define MGA_CTXREG_MACCESS 1
+#define MGA_CTXREG_PLNWT 2
+#define MGA_CTXREG_DWGCTL 3
+#define MGA_CTXREG_ALPHACTRL 4
+#define MGA_CTXREG_FOGCOLOR 5
+#define MGA_CTXREG_WFLAG 6
+#define MGA_CTXREG_TDUAL0 7
+#define MGA_CTXREG_TDUAL1 8
+#define MGA_CTXREG_FCOL 9
+#define MGA_CTX_SETUP_SIZE 10
+
+/* 2d state
+ */
+#define MGA_2DREG_PITCH 0
+#define MGA_2D_SETUP_SIZE 1
+
+/* Each texture unit has a state:
+ */
+#define MGA_TEXREG_CTL 0
+#define MGA_TEXREG_CTL2 1
+#define MGA_TEXREG_FILTER 2
+#define MGA_TEXREG_BORDERCOL 3
+#define MGA_TEXREG_ORG 4 /* validated */
+#define MGA_TEXREG_ORG1 5
+#define MGA_TEXREG_ORG2 6
+#define MGA_TEXREG_ORG3 7
+#define MGA_TEXREG_ORG4 8
+#define MGA_TEXREG_WIDTH 9
+#define MGA_TEXREG_HEIGHT 10
+#define MGA_TEX_SETUP_SIZE 11
+
+/* What needs to be changed for the current vertex dma buffer?
+ */
+#define MGA_UPLOAD_CTX 0x1
+#define MGA_UPLOAD_TEX0 0x2
+#define MGA_UPLOAD_TEX1 0x4
+#define MGA_UPLOAD_PIPE 0x8
+#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */
+#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */
+#define MGA_UPLOAD_2D 0x40
+#define MGA_WAIT_AGE 0x80 /* handled client-side */
+#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */
+#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock
+ quiescent */
+
+/* 32 buffers of 64k each, total 2 meg.
+ */
+#define MGA_DMA_BUF_ORDER 16
+#define MGA_DMA_BUF_SZ (1<<MGA_DMA_BUF_ORDER)
+#define MGA_DMA_BUF_NR 31
+
+/* Keep these small for testing.
+ */
+#define MGA_NR_SAREA_CLIPRECTS 8
+
+/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
+ * regions, subject to a minimum region size of (1<<16) == 64k.
+ *
+ * Clients may subdivide regions internally, but when sharing between
+ * clients, the region size is the minimum granularity.
+ */
+
+#define MGA_CARD_HEAP 0
+#define MGA_AGP_HEAP 1
+#define MGA_NR_TEX_HEAPS 2
+#define MGA_NR_TEX_REGIONS 16
+#define MGA_LOG_MIN_TEX_REGION_SIZE 16
+#endif
+
+typedef struct _drm_mga_warp_index {
+ int installed;
+ unsigned long phys_addr;
+ int size;
+} drm_mga_warp_index_t;
+
+typedef struct drm_mga_init {
+ enum {
+ MGA_INIT_DMA = 0x01,
+ MGA_CLEANUP_DMA = 0x02
+ } func;
+ int reserved_map_agpstart;
+ int reserved_map_idx;
+ int buffer_map_idx;
+ int sarea_priv_offset;
+ int primary_size;
+ int warp_ucode_size;
+ unsigned int frontOffset;
+ unsigned int backOffset;
+ unsigned int depthOffset;
+ unsigned int textureOffset;
+ unsigned int textureSize;
+ unsigned int agpTextureOffset;
+ unsigned int agpTextureSize;
+ unsigned int cpp;
+ unsigned int stride;
+ int sgram;
+ int chipset;
+ drm_mga_warp_index_t WarpIndex[MGA_MAX_WARP_PIPES];
+ unsigned int mAccess;
+} drm_mga_init_t;
+
+/* Warning: if you change the sarea structure, you must change the Xserver
+ * structures as well */
+
+typedef struct _drm_mga_tex_region {
+ unsigned char next, prev;
+ unsigned char in_use;
+ unsigned int age;
+} drm_mga_tex_region_t;
+
+typedef struct _drm_mga_sarea {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex dma buffer.
+ */
+ unsigned int ContextState[MGA_CTX_SETUP_SIZE];
+ unsigned int ServerState[MGA_2D_SETUP_SIZE];
+ unsigned int TexState[2][MGA_TEX_SETUP_SIZE];
+ unsigned int WarpPipe;
+ unsigned int dirty;
+
+ unsigned int nbox;
+ drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
+
+
+ /* Information about the most recently used 3d drawable. The
+ * client fills in the req_* fields, the server fills in the
+ * exported_ fields and puts the cliprects into boxes, above.
+ *
+ * The client clears the exported_drawable field before
+ * clobbering the boxes data.
+ */
+ unsigned int req_drawable; /* the X drawable id */
+ unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */
+
+ unsigned int exported_drawable;
+ unsigned int exported_index;
+ unsigned int exported_stamp;
+ unsigned int exported_buffers;
+ unsigned int exported_nfront;
+ unsigned int exported_nback;
+ int exported_back_x, exported_front_x, exported_w;
+ int exported_back_y, exported_front_y, exported_h;
+ drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
+
+ /* Counters for aging textures and for client-side throttling.
+ */
+ unsigned int last_enqueue; /* last time a buffer was enqueued */
+ unsigned int last_dispatch; /* age of the most recently dispatched buffer */
+ unsigned int last_quiescent; /* */
+
+
+ /* LRU lists for texture memory in agp space and on the card
+ */
+ drm_mga_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS+1];
+ unsigned int texAge[MGA_NR_TEX_HEAPS];
+
+ /* Mechanism to validate card state.
+ */
+ int ctxOwner;
+} drm_mga_sarea_t;
+
+/* Device specific ioctls:
+ */
+typedef struct _drm_mga_clear {
+ unsigned int clear_color;
+ unsigned int clear_depth;
+ unsigned int flags;
+} drm_mga_clear_t;
+
+typedef struct _drm_mga_swap {
+ int dummy;
+} drm_mga_swap_t;
+
+typedef struct _drm_mga_iload {
+ int idx;
+ int length;
+ unsigned int destOrg;
+} drm_mga_iload_t;
+
+typedef struct _drm_mga_vertex {
+ int idx; /* buffer to queue */
+ int used; /* bytes in use */
+ int discard; /* client finished with buffer? */
+} drm_mga_vertex_t;
+
+typedef struct _drm_mga_indices {
+ int idx; /* buffer to queue */
+ unsigned int start;
+ unsigned int end;
+ int discard; /* client finished with buffer? */
+} drm_mga_indices_t;
+
+#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.c
index 8bc25617e..5fabe1f25 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.c
@@ -54,6 +54,7 @@ static struct file_operations mga_fops = {
mmap: drm_mmap,
read: drm_read,
fasync: drm_fasync,
+ poll: drm_poll,
};
static struct miscdevice mga_misc = {
@@ -105,9 +106,12 @@ static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_clear_bufs, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_swap_bufs, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_iload, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_swap_bufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_clear_bufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_iload, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_vertex, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)] = { mga_flush_ioctl, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_indices, 1, 0 },
};
#define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls)
@@ -380,6 +384,21 @@ int mga_init(void)
drm_proc_init(dev);
DRM_DEBUG("doing agp init\n");
dev->agp = drm_agp_init();
+ if(dev->agp == NULL) {
+ DRM_DEBUG("The mga drm module requires the agpgart module"
+ " to function correctly\nPlease load the agpgart"
+ " module before you load the mga module\n");
+ drm_proc_cleanup();
+ misc_deregister(&mga_misc);
+ mga_takedown(dev);
+ return -ENOMEM;
+ }
+#ifdef CONFIG_MTRR
+ dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base,
+ dev->agp->agp_info.aper_size * 1024 * 1024,
+ MTRR_TYPE_WRCOMB,
+ 1);
+#endif
DRM_DEBUG("doing ctxbitmap init\n");
if((retcode = drm_ctxbitmap_init(dev))) {
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
@@ -416,6 +435,16 @@ void mga_cleanup(void)
}
drm_ctxbitmap_cleanup(dev);
mga_dma_cleanup(dev);
+#ifdef CONFIG_MTRR
+ if(dev->agp && dev->agp->agp_mtrr) {
+ 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);
+ }
+#endif
+
mga_takedown(dev);
if (dev->agp) {
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
@@ -482,27 +511,86 @@ int mga_release(struct inode *inode, struct file *filp)
drm_device_t *dev = priv->dev;
int retcode = 0;
- DRM_DEBUG("open_count = %d\n", dev->open_count);
- if (!(retcode = drm_release(inode, filp))) {
- MOD_DEC_USE_COUNT;
- atomic_inc(&dev->total_close);
- spin_lock(&dev->count_lock);
- if (!--dev->open_count) {
- if (atomic_read(&dev->ioctl_count) || dev->blocked) {
- DRM_ERROR("Device busy: %d %d\n",
- atomic_read(&dev->ioctl_count),
- dev->blocked);
- spin_unlock(&dev->count_lock);
- return -EBUSY;
+ DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
+ current->pid, dev->device, dev->open_count);
+
+ if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
+ && dev->lock.pid == current->pid) {
+ mga_reclaim_buffers(dev, priv->pid);
+ DRM_ERROR("Process %d dead, freeing lock for context %d\n",
+ current->pid,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+ drm_lock_free(dev,
+ &dev->lock.hw_lock->lock,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+
+ /* FIXME: may require heavy-handed reset of
+ hardware at this point, possibly
+ processed via a callback to the X
+ server. */
+ } else if (dev->lock.hw_lock) {
+ /* The lock is required to reclaim buffers */
+ DECLARE_WAITQUEUE(entry, current);
+ add_wait_queue(&dev->lock.lock_queue, &entry);
+ for (;;) {
+ if (!dev->lock.hw_lock) {
+ /* Device has been unregistered */
+ retcode = -EINTR;
+ break;
+ }
+ if (drm_lock_take(&dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ dev->lock.pid = priv->pid;
+ dev->lock.lock_time = jiffies;
+ atomic_inc(&dev->total_locks);
+ break; /* Got lock */
+ }
+ /* Contention */
+ atomic_inc(&dev->total_sleeps);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (signal_pending(current)) {
+ retcode = -ERESTARTSYS;
+ break;
}
- spin_unlock(&dev->count_lock);
- return mga_takedown(dev);
}
- spin_unlock(&dev->count_lock);
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev->lock.lock_queue, &entry);
+ if(!retcode) {
+ mga_reclaim_buffers(dev, priv->pid);
+ drm_lock_free(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT);
+ }
}
+ drm_fasync(-1, filp, 0);
+
+ down(&dev->struct_sem);
+ if (priv->prev) priv->prev->next = priv->next;
+ else dev->file_first = priv->next;
+ if (priv->next) priv->next->prev = priv->prev;
+ else dev->file_last = priv->prev;
+ up(&dev->struct_sem);
+
+ drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+ MOD_DEC_USE_COUNT;
+ atomic_inc(&dev->total_close);
+ spin_lock(&dev->count_lock);
+ if (!--dev->open_count) {
+ if (atomic_read(&dev->ioctl_count) || dev->blocked) {
+ DRM_ERROR("Device busy: %d %d\n",
+ atomic_read(&dev->ioctl_count),
+ dev->blocked);
+ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ spin_unlock(&dev->count_lock);
+ return mga_takedown(dev);
+ }
+ spin_unlock(&dev->count_lock);
return retcode;
}
+
/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */
int mga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h
index bc7808b0a..ee75a03e2 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h
@@ -26,48 +26,79 @@
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
* Jeff Hartmann <jhartmann@precisioninsight.com>
*
- * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h,v 1.1 2000/02/11 17:26:08 dawes Exp $
+ * $XFree86$
*/
#ifndef _MGA_DRV_H_
#define _MGA_DRV_H_
-#include "mga_drm_public.h"
+
+#define MGA_BUF_IN_USE 0
+#define MGA_BUF_SWAP_PENDING 1
+#define MGA_BUF_FORCE_FIRE 2
+#define MGA_BUF_NEEDS_OVERFLOW 3
+
+typedef struct {
+ u32 buffer_status;
+ unsigned int num_dwords;
+ unsigned int max_dwords;
+ u32 *current_dma_ptr;
+ u32 *head;
+ u32 phys_head;
+ unsigned int prim_age;
+ int sec_used;
+ int idx;
+} drm_mga_prim_buf_t;
+
+typedef struct _drm_mga_freelist {
+ unsigned int age;
+ drm_buf_t *buf;
+ struct _drm_mga_freelist *next;
+ struct _drm_mga_freelist *prev;
+} drm_mga_freelist_t;
+
+#define MGA_IN_DISPATCH 0
+#define MGA_IN_FLUSH 1
+#define MGA_IN_WAIT 2
+#define MGA_IN_GETBUF 3
typedef struct _drm_mga_private {
+ u32 dispatch_status;
+ unsigned int next_prim_age;
+ __volatile__ unsigned int last_prim_age;
int reserved_map_idx;
int buffer_map_idx;
drm_mga_sarea_t *sarea_priv;
int primary_size;
int warp_ucode_size;
int chipset;
- int fbOffset;
- int backOffset;
- int depthOffset;
- int textureOffset;
- int textureSize;
+ unsigned int frontOffset;
+ unsigned int backOffset;
+ unsigned int depthOffset;
+ unsigned int textureOffset;
+ unsigned int textureSize;
int cpp;
- int stride;
+ unsigned int stride;
int sgram;
int use_agp;
- mgaWarpIndex WarpIndex[MGA_MAX_G400_PIPES];
- __volatile__ unsigned long softrap_age;
- atomic_t dispatch_lock;
+ drm_mga_warp_index_t WarpIndex[MGA_MAX_G400_PIPES];
+ unsigned int WarpPipe;
atomic_t pending_bufs;
- void *ioremap;
- u32 *prim_head;
- u32 *current_dma_ptr;
- u32 prim_phys_head;
- int prim_num_dwords;
- int prim_max_dwords;
-
-
+ void *status_page;
+ unsigned long real_status_page;
+ u8 *ioremap;
+ drm_mga_prim_buf_t **prim_bufs;
+ drm_mga_prim_buf_t *next_prim;
+ drm_mga_prim_buf_t *last_prim;
+ drm_mga_prim_buf_t *current_prim;
+ int current_prim_idx;
+ drm_mga_freelist_t *head;
+ drm_mga_freelist_t *tail;
+ wait_queue_head_t flush_queue; /* Processes waiting until flush */
+ wait_queue_head_t wait_queue; /* Processes waiting until interrupt */
+ wait_queue_head_t buf_queue; /* Processes waiting for a free buf */
/* Some validated register values:
*/
- u32 frontOrg;
- u32 backOrg;
- u32 depthOrg;
u32 mAccess;
-
} drm_mga_private_t;
/* mga_drv.c */
@@ -92,16 +123,19 @@ extern int mga_control(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_lock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-#if 0
-extern void mga_dma_init(drm_device_t *dev);
-extern void mga_dma_cleanup(drm_device_t *dev);
-#endif
+/* mga_dma_init does init and release */
extern int mga_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_dma_cleanup(drm_device_t *dev);
-
-/* mga_dma_init does init and release */
+extern int mga_flush_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern void mga_flush_write_combine(void);
+extern unsigned int mga_create_sync_tag(drm_device_t *dev);
+extern drm_buf_t *mga_freelist_get(drm_device_t *dev);
+extern int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf);
+extern int mga_advance_primary(drm_device_t *dev);
+extern void mga_reclaim_buffers(drm_device_t *dev, pid_t pid);
/* mga_bufs.c */
@@ -124,6 +158,10 @@ extern int mga_swap_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_iload(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+extern int mga_vertex(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int mga_indices(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
/* mga_context.c */
extern int mga_resctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
@@ -144,13 +182,124 @@ extern int mga_context_switch(drm_device_t *dev, int old, int new);
extern int mga_context_switch_complete(drm_device_t *dev, int new);
+typedef enum {
+ TT_GENERAL,
+ TT_BLIT,
+ TT_VECTOR,
+ TT_VERTEX
+} transferType_t;
+
+typedef struct {
+ drm_mga_freelist_t *my_freelist;
+ int discard;
+ int dispatched;
+} drm_mga_buf_priv_t;
+
+#define DWGREG0 0x1c00
+#define DWGREG0_END 0x1dff
+#define DWGREG1 0x2c00
+#define DWGREG1_END 0x2dff
+
+#define ISREG0(r) (r >= DWGREG0 && r <= DWGREG0_END)
+#define ADRINDEX0(r) (u8)((r - DWGREG0) >> 2)
+#define ADRINDEX1(r) (u8)(((r - DWGREG1) >> 2) | 0x80)
+#define ADRINDEX(r) (ISREG0(r) ? ADRINDEX0(r) : ADRINDEX1(r))
+
+#define MGA_VERBOSE 0
+#define MGA_NUM_PRIM_BUFS 8
+
+#define PRIMLOCALS u8 tempIndex[4]; u32 *dma_ptr; u32 phys_head; \
+ int outcount, num_dwords
+
+#define PRIM_OVERFLOW(dev, dev_priv, length) do { \
+ drm_mga_prim_buf_t *tmp_buf = \
+ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+ if( test_bit(MGA_BUF_NEEDS_OVERFLOW, \
+ &tmp_buf->buffer_status)) { \
+ mga_advance_primary(dev); \
+ mga_dma_schedule(dev, 1); \
+ } else if( tmp_buf->max_dwords - tmp_buf->num_dwords < length ||\
+ tmp_buf->sec_used > MGA_DMA_BUF_NR/2) { \
+ set_bit(MGA_BUF_FORCE_FIRE, &tmp_buf->buffer_status); \
+ mga_advance_primary(dev); \
+ mga_dma_schedule(dev, 1); \
+ } \
+} while(0)
+
+#define PRIMGETPTR(dev_priv) do { \
+ drm_mga_prim_buf_t *tmp_buf = \
+ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+ if(MGA_VERBOSE) \
+ DRM_DEBUG("PRIMGETPTR in %s\n", __FUNCTION__); \
+ dma_ptr = tmp_buf->current_dma_ptr; \
+ num_dwords = tmp_buf->num_dwords; \
+ phys_head = tmp_buf->phys_head; \
+ outcount = 0; \
+} while(0)
+
+#define PRIMPTR(prim_buf) do { \
+ if(MGA_VERBOSE) \
+ DRM_DEBUG("PRIMPTR in %s\n", __FUNCTION__); \
+ dma_ptr = prim_buf->current_dma_ptr; \
+ num_dwords = prim_buf->num_dwords; \
+ phys_head = prim_buf->phys_head; \
+ outcount = 0; \
+} while(0)
+
+#define PRIMFINISH(prim_buf) do { \
+ if (MGA_VERBOSE) { \
+ DRM_DEBUG( "PRIMFINISH in %s\n", __FUNCTION__); \
+ if (outcount & 3) \
+ DRM_DEBUG(" --- truncation\n"); \
+ } \
+ prim_buf->num_dwords = num_dwords; \
+ prim_buf->current_dma_ptr = dma_ptr; \
+} while(0)
+
+#define PRIMADVANCE(dev_priv) do { \
+drm_mga_prim_buf_t *tmp_buf = \
+ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+ if (MGA_VERBOSE) { \
+ DRM_DEBUG("PRIMADVANCE in %s\n", __FUNCTION__); \
+ if (outcount & 3) \
+ DRM_DEBUG(" --- truncation\n"); \
+ } \
+ tmp_buf->num_dwords = num_dwords; \
+ tmp_buf->current_dma_ptr = dma_ptr; \
+} while (0)
+
+#define PRIMUPDATE(dev_priv) do { \
+ drm_mga_prim_buf_t *tmp_buf = \
+ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+ tmp_buf->sec_used++; \
+} while (0)
+
+#define AGEBUF(dev_priv, buf_priv) do { \
+ drm_mga_prim_buf_t *tmp_buf = \
+ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+ buf_priv->my_freelist->age = tmp_buf->prim_age; \
+} while (0)
+
+
+#define PRIMOUTREG(reg, val) do { \
+ tempIndex[outcount]=ADRINDEX(reg); \
+ dma_ptr[1+outcount] = val; \
+ if (MGA_VERBOSE) \
+ DRM_DEBUG(" PRIMOUT %d: 0x%x -- 0x%x\n", \
+ num_dwords + 1 + outcount, ADRINDEX(reg), val); \
+ if( ++outcount == 4) { \
+ outcount = 0; \
+ dma_ptr[0] = *(u32 *)tempIndex; \
+ dma_ptr+=5; \
+ num_dwords += 5; \
+ } \
+}while (0)
+
+/* A reduced set of the mga registers.
+ */
#define MGAREG_MGA_EXEC 0x0100
-#define MGAREG_AGP_PLL 0x1e4c
#define MGAREG_ALPHACTRL 0x2c7c
-#define MGAREG_ALPHASTART 0x2c70
-#define MGAREG_ALPHAXINC 0x2c74
-#define MGAREG_ALPHAYINC 0x2c78
#define MGAREG_AR0 0x1c60
#define MGAREG_AR1 0x1c64
#define MGAREG_AR2 0x1c68
@@ -158,39 +307,16 @@ extern int mga_context_switch_complete(drm_device_t *dev, int new);
#define MGAREG_AR4 0x1c70
#define MGAREG_AR5 0x1c74
#define MGAREG_AR6 0x1c78
-#define MGAREG_BCOL 0x1c20
#define MGAREG_CXBNDRY 0x1c80
#define MGAREG_CXLEFT 0x1ca0
#define MGAREG_CXRIGHT 0x1ca4
#define MGAREG_DMAPAD 0x1c54
-#define MGAREG_DR0_Z32LSB 0x2c50
-#define MGAREG_DR0_Z32MSB 0x2c54
-#define MGAREG_DR2_Z32LSB 0x2c60
-#define MGAREG_DR2_Z32MSB 0x2c64
-#define MGAREG_DR3_Z32LSB 0x2c68
-#define MGAREG_DR3_Z32MSB 0x2c6c
-#define MGAREG_DR0 0x1cc0
-#define MGAREG_DR2 0x1cc8
-#define MGAREG_DR3 0x1ccc
-#define MGAREG_DR4 0x1cd0
-#define MGAREG_DR6 0x1cd8
-#define MGAREG_DR7 0x1cdc
-#define MGAREG_DR8 0x1ce0
-#define MGAREG_DR10 0x1ce8
-#define MGAREG_DR11 0x1cec
-#define MGAREG_DR12 0x1cf0
-#define MGAREG_DR14 0x1cf8
-#define MGAREG_DR15 0x1cfc
#define MGAREG_DSTORG 0x2cb8
-#define MGAREG_DWG_INDIR_WT 0x1e80
#define MGAREG_DWGCTL 0x1c00
#define MGAREG_DWGSYNC 0x2c4c
#define MGAREG_FCOL 0x1c24
#define MGAREG_FIFOSTATUS 0x1e10
#define MGAREG_FOGCOL 0x1cf4
-#define MGAREG_FOGSTART 0x1cc4
-#define MGAREG_FOGXINC 0x1cd4
-#define MGAREG_FOGYINC 0x1ce4
#define MGAREG_FXBNDRY 0x1c84
#define MGAREG_FXLEFT 0x1ca8
#define MGAREG_FXRIGHT 0x1cac
@@ -198,44 +324,22 @@ extern int mga_context_switch_complete(drm_device_t *dev, int new);
#define MGAREG_IEN 0x1e1c
#define MGAREG_LEN 0x1c5c
#define MGAREG_MACCESS 0x1c04
-#define MGAREG_MCTLWTST 0x1c08
-#define MGAREG_MEMRDBK 0x1e44
-#define MGAREG_OPMODE 0x1e54
-#define MGAREG_PAT0 0x1c10
-#define MGAREG_PAT1 0x1c14
#define MGAREG_PITCH 0x1c8c
#define MGAREG_PLNWT 0x1c1c
#define MGAREG_PRIMADDRESS 0x1e58
#define MGAREG_PRIMEND 0x1e5c
#define MGAREG_PRIMPTR 0x1e50
-#define MGAREG_RST 0x1e40
#define MGAREG_SECADDRESS 0x2c40
#define MGAREG_SECEND 0x2c44
#define MGAREG_SETUPADDRESS 0x2cd0
#define MGAREG_SETUPEND 0x2cd4
-#define MGAREG_SGN 0x1c58
-#define MGAREG_SHIFT 0x1c50
#define MGAREG_SOFTRAP 0x2c48
-#define MGAREG_SPECBSTART 0x2c98
-#define MGAREG_SPECBXINC 0x2c9c
-#define MGAREG_SPECBYINC 0x2ca0
-#define MGAREG_SPECGSTART 0x2c8c
-#define MGAREG_SPECGXINC 0x2c90
-#define MGAREG_SPECGYINC 0x2c94
-#define MGAREG_SPECRSTART 0x2c80
-#define MGAREG_SPECRXINC 0x2c84
-#define MGAREG_SPECRYINC 0x2c88
-#define MGAREG_SRC0 0x1c30
-#define MGAREG_SRC1 0x1c34
-#define MGAREG_SRC2 0x1c38
-#define MGAREG_SRC3 0x1c3c
#define MGAREG_SRCORG 0x2cb4
#define MGAREG_STATUS 0x1e14
#define MGAREG_STENCIL 0x2cc8
#define MGAREG_STENCILCTL 0x2ccc
#define MGAREG_TDUALSTAGE0 0x2cf8
#define MGAREG_TDUALSTAGE1 0x2cfc
-#define MGAREG_TEST0 0x1e48
#define MGAREG_TEXBORDERCOL 0x2c5c
#define MGAREG_TEXCTL 0x2c30
#define MGAREG_TEXCTL2 0x2c3c
@@ -249,18 +353,6 @@ extern int mga_context_switch_complete(drm_device_t *dev, int new);
#define MGAREG_TEXTRANS 0x2c34
#define MGAREG_TEXTRANSHIGH 0x2c38
#define MGAREG_TEXWIDTH 0x2c28
-#define MGAREG_TMR0 0x2c00
-#define MGAREG_TMR1 0x2c04
-#define MGAREG_TMR2 0x2c08
-#define MGAREG_TMR3 0x2c0c
-#define MGAREG_TMR4 0x2c10
-#define MGAREG_TMR5 0x2c14
-#define MGAREG_TMR6 0x2c18
-#define MGAREG_TMR7 0x2c1c
-#define MGAREG_TMR8 0x2c20
-#define MGAREG_VBIADDR0 0x3e08
-#define MGAREG_VBIADDR1 0x3e0c
-#define MGAREG_VCOUNT 0x1e20
#define MGAREG_WACCEPTSEQ 0x1dd4
#define MGAREG_WCODEADDR 0x1e6c
#define MGAREG_WFLAG 0x1dc4
@@ -270,18 +362,8 @@ extern int mga_context_switch_complete(drm_device_t *dev, int new);
#define MGAREG_WGETMSB 0x1dc8
#define MGAREG_WIADDR 0x1dc0
#define MGAREG_WIADDR2 0x1dd8
-#define MGAREG_WIADDRNB 0x1e60
-#define MGAREG_WIADDRNB1 0x1e04
-#define MGAREG_WIADDRNB2 0x1e00
-#define MGAREG_WIMEMADDR 0x1e68
-#define MGAREG_WIMEMDATA 0x2000
-#define MGAREG_WIMEMDATA1 0x2100
#define MGAREG_WMISC 0x1e70
-#define MGAREG_WR 0x2d00
#define MGAREG_WVRTXSZ 0x1dcc
-#define MGAREG_XDST 0x1cb0
-#define MGAREG_XYEND 0x1c44
-#define MGAREG_XYSTRT 0x1c40
#define MGAREG_YBOT 0x1c9c
#define MGAREG_YDST 0x1c90
#define MGAREG_YDSTLEN 0x1c88
@@ -289,4 +371,77 @@ extern int mga_context_switch_complete(drm_device_t *dev, int new);
#define MGAREG_YTOP 0x1c98
#define MGAREG_ZORG 0x1c0c
+#define PDEA_pagpxfer_enable 0x2
+
+#define WIA_wmode_suspend 0x0
+#define WIA_wmode_start 0x3
+#define WIA_wagp_agp 0x4
+
+#define DC_opcod_line_open 0x0
+#define DC_opcod_autoline_open 0x1
+#define DC_opcod_line_close 0x2
+#define DC_opcod_autoline_close 0x3
+#define DC_opcod_trap 0x4
+#define DC_opcod_texture_trap 0x6
+#define DC_opcod_bitblt 0x8
+#define DC_opcod_iload 0x9
+#define DC_atype_rpl 0x0
+#define DC_atype_rstr 0x10
+#define DC_atype_zi 0x30
+#define DC_atype_blk 0x40
+#define DC_atype_i 0x70
+#define DC_linear_xy 0x0
+#define DC_linear_linear 0x80
+#define DC_zmode_nozcmp 0x0
+#define DC_zmode_ze 0x200
+#define DC_zmode_zne 0x300
+#define DC_zmode_zlt 0x400
+#define DC_zmode_zlte 0x500
+#define DC_zmode_zgt 0x600
+#define DC_zmode_zgte 0x700
+#define DC_solid_disable 0x0
+#define DC_solid_enable 0x800
+#define DC_arzero_disable 0x0
+#define DC_arzero_enable 0x1000
+#define DC_sgnzero_disable 0x0
+#define DC_sgnzero_enable 0x2000
+#define DC_shftzero_disable 0x0
+#define DC_shftzero_enable 0x4000
+#define DC_bop_SHIFT 16
+#define DC_trans_SHIFT 20
+#define DC_bltmod_bmonolef 0x0
+#define DC_bltmod_bmonowf 0x8000000
+#define DC_bltmod_bplan 0x2000000
+#define DC_bltmod_bfcol 0x4000000
+#define DC_bltmod_bu32bgr 0x6000000
+#define DC_bltmod_bu32rgb 0xe000000
+#define DC_bltmod_bu24bgr 0x16000000
+#define DC_bltmod_bu24rgb 0x1e000000
+#define DC_pattern_disable 0x0
+#define DC_pattern_enable 0x20000000
+#define DC_transc_disable 0x0
+#define DC_transc_enable 0x40000000
+#define DC_clipdis_disable 0x0
+#define DC_clipdis_enable 0x80000000
+
+#define SETADD_mode_vertlist 0x0
+
+
+#define MGA_CLEAR_CMD (DC_opcod_trap | DC_arzero_enable | \
+ DC_sgnzero_enable | DC_shftzero_enable | \
+ (0xC << DC_bop_SHIFT) | DC_clipdis_enable | \
+ DC_solid_enable | DC_transc_enable)
+
+
+#define MGA_COPY_CMD (DC_opcod_bitblt | DC_atype_rpl | DC_linear_xy | \
+ DC_solid_disable | DC_arzero_disable | \
+ DC_sgnzero_enable | DC_shftzero_enable | \
+ (0xC << DC_bop_SHIFT) | DC_bltmod_bfcol | \
+ DC_pattern_disable | DC_transc_disable | \
+ DC_clipdis_enable) \
+
+#define MGA_FLUSH_CMD (DC_opcod_texture_trap | (0xF << DC_trans_SHIFT) |\
+ DC_arzero_enable | DC_sgnzero_enable | \
+ DC_atype_i)
+
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_state.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_state.c
index d09881bad..32f6bcf4b 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_state.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_state.c
@@ -26,337 +26,1047 @@
* Authors: Jeff Hartmann <jhartmann@precisioninsight.com>
* Keith Whitwell <keithw@precisioninsight.com>
*
- * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_state.c,v 1.1 2000/02/11 17:26:08 dawes Exp $
+ * $XFree86$
*
*/
#define __NO_VERSION__
#include "drmP.h"
#include "mga_drv.h"
-#include "mgareg_flags.h"
-#include "mga_dma.h"
-#include "mga_state.h"
#include "drm.h"
-void mgaEmitClipRect( drm_mga_private_t *dev_priv, xf86drmClipRectRec *box )
+static void mgaEmitClipRect( drm_mga_private_t *dev_priv,
+ drm_clip_rect_t *box )
{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->ContextState;
PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ /* This takes 10 dwords */
PRIMGETPTR( dev_priv );
+
+ /* Force reset of dwgctl (eliminates clip disable) */
+#if 1
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DWGSYNC, 0 );
+ PRIMOUTREG( MGAREG_DWGSYNC, 0 );
+ PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
+#else
+ PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
+ PRIMOUTREG( MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000 );
+ PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
+ PRIMOUTREG( MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000 );
+#endif
- /* The G400 seems to have an issue with the second WARP not
- * stalling clipper register writes. This bothers me, but the only
- * way I could get it to never clip the last triangle under any
- * circumstances is by inserting TWO dwgsync commands.
- */
- if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
- PRIMOUTREG( MGAREG_DWGSYNC, 0 );
- PRIMOUTREG( MGAREG_DWGSYNC, 0 );
- }
-
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
PRIMOUTREG( MGAREG_CXBNDRY, ((box->x2)<<16)|(box->x1) );
- PRIMOUTREG( MGAREG_YTOP, box->y1 * dev_priv->stride );
- PRIMOUTREG( MGAREG_YBOT, box->y2 * dev_priv->stride );
+ PRIMOUTREG( MGAREG_YTOP, box->y1 * dev_priv->stride/2 );
+ PRIMOUTREG( MGAREG_YBOT, box->y2 * dev_priv->stride/2 );
+
PRIMADVANCE( dev_priv );
}
-
-static void mgaEmitContext(drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv)
+static void mgaEmitContext(drm_mga_private_t *dev_priv )
{
- unsigned int *regs = buf_priv->ContextState;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->ContextState;
PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ /* This takes a max of 15 dwords */
PRIMGETPTR( dev_priv );
+
PRIMOUTREG( MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG] );
PRIMOUTREG( MGAREG_MACCESS, regs[MGA_CTXREG_MACCESS] );
PRIMOUTREG( MGAREG_PLNWT, regs[MGA_CTXREG_PLNWT] );
PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
+
PRIMOUTREG( MGAREG_ALPHACTRL, regs[MGA_CTXREG_ALPHACTRL] );
PRIMOUTREG( MGAREG_FOGCOL, regs[MGA_CTXREG_FOGCOLOR] );
PRIMOUTREG( MGAREG_WFLAG, regs[MGA_CTXREG_WFLAG] );
+ PRIMOUTREG( MGAREG_ZORG, dev_priv->depthOffset ); /* invarient */
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
PRIMOUTREG( MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG] );
PRIMOUTREG( MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0] );
- PRIMOUTREG( MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1] );
- }
+ PRIMOUTREG( MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1] );
+ PRIMOUTREG( MGAREG_FCOL, regs[MGA_CTXREG_FCOL] );
+ } else {
+ PRIMOUTREG( MGAREG_FCOL, regs[MGA_CTXREG_FCOL] );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ }
PRIMADVANCE( dev_priv );
}
-static void mgaG200EmitTex( drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv )
+static void mgaG200EmitTex( drm_mga_private_t *dev_priv )
{
- unsigned int *regs = buf_priv->TexState[0];
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->TexState[0];
PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
PRIMGETPTR( dev_priv );
- PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
- PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
- PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
- PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
- PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
- PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
- PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
- PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
- PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );
- PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
- PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );
- PRIMOUTREG(0x2d00 + 24*4, regs[MGA_TEXREG_WIDTH] );
- PRIMOUTREG(0x2d00 + 34*4, regs[MGA_TEXREG_HEIGHT] );
+ /* This takes 20 dwords */
+
+ PRIMOUTREG( MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
+ PRIMOUTREG( MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
+ PRIMOUTREG( MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
+ PRIMOUTREG( MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
+
+ PRIMOUTREG( MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
+ PRIMOUTREG( MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
+ PRIMOUTREG( MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
+ PRIMOUTREG( MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
+
+ PRIMOUTREG( MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );
+ PRIMOUTREG( MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
+ PRIMOUTREG( MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );
+ PRIMOUTREG( 0x2d00 + 24*4, regs[MGA_TEXREG_WIDTH] );
+
+ PRIMOUTREG( 0x2d00 + 34*4, regs[MGA_TEXREG_HEIGHT] );
+ PRIMOUTREG( MGAREG_TEXTRANS, 0xffff );
+ PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
PRIMADVANCE( dev_priv );
}
-static void mgaG400EmitTex0( drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv )
+static void mgaG400EmitTex0( drm_mga_private_t *dev_priv )
{
- unsigned int *regs = buf_priv->TexState[0];
- int multitex = buf_priv->WarpPipe & MGA_T2;
-
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->TexState[0];
+ int multitex = sarea_priv->WarpPipe & MGA_T2;
PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
PRIMGETPTR( dev_priv );
-
- PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
- PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
- PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
- PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
- PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
- PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
- PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
- PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
- PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );
- PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
- PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );
- PRIMOUTREG(0x2d00 + 49*4, 0);
- PRIMOUTREG(0x2d00 + 57*4, 0);
- PRIMOUTREG(0x2d00 + 53*4, 0);
- PRIMOUTREG(0x2d00 + 61*4, 0);
+ /* This takes a max of 30 dwords */
+
+ PRIMOUTREG( MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
+ PRIMOUTREG( MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
+ PRIMOUTREG( MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
+ PRIMOUTREG( MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
+
+ PRIMOUTREG( MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
+ PRIMOUTREG( MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
+ PRIMOUTREG( MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
+ PRIMOUTREG( MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
+
+ PRIMOUTREG( MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );
+ PRIMOUTREG( MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
+ PRIMOUTREG( MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );
+ PRIMOUTREG( 0x2d00 + 49*4, 0 );
+
+ PRIMOUTREG( 0x2d00 + 57*4, 0 );
+ PRIMOUTREG( 0x2d00 + 53*4, 0 );
+ PRIMOUTREG( 0x2d00 + 61*4, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
if (!multitex) {
- PRIMOUTREG(0x2d00 + 52*4, 0x40 );
- PRIMOUTREG(0x2d00 + 60*4, 0x40 );
+ PRIMOUTREG( 0x2d00 + 52*4, 0x40 );
+ PRIMOUTREG( 0x2d00 + 60*4, 0x40 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
}
- PRIMOUTREG(0x2d00 + 54*4, regs[MGA_TEXREG_WIDTH] | 0x40 );
- PRIMOUTREG(0x2d00 + 62*4, regs[MGA_TEXREG_HEIGHT] | 0x40 );
+ PRIMOUTREG( 0x2d00 + 54*4, regs[MGA_TEXREG_WIDTH] | 0x40 );
+ PRIMOUTREG( 0x2d00 + 62*4, regs[MGA_TEXREG_HEIGHT] | 0x40 );
+ PRIMOUTREG( MGAREG_TEXTRANS, 0xffff );
+ PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff );
PRIMADVANCE( dev_priv );
}
#define TMC_map1_enable 0x80000000
-
-static void mgaG400EmitTex1( drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv )
+static void mgaG400EmitTex1( drm_mga_private_t *dev_priv )
{
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int *regs = sarea_priv->TexState[1];
-
PRIMLOCALS;
- PRIMGETPTR(dev_priv);
-
- PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | TMC_map1_enable);
- PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
- PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
- PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
- PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
- PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
- PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
- PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
- PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );
- PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
- PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );
+ DRM_DEBUG("%s\n", __FUNCTION__);
- PRIMOUTREG(0x2d00 + 49*4, 0);
- PRIMOUTREG(0x2d00 + 57*4, 0);
- PRIMOUTREG(0x2d00 + 53*4, 0);
- PRIMOUTREG(0x2d00 + 61*4, 0);
+ PRIMGETPTR( dev_priv );
- PRIMOUTREG(0x2d00 + 52*4, regs[MGA_TEXREG_WIDTH] | 0x40 );
- PRIMOUTREG(0x2d00 + 60*4, regs[MGA_TEXREG_HEIGHT] | 0x40 );
+ /* This takes 25 dwords */
- PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
+ PRIMOUTREG( MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | TMC_map1_enable );
+ PRIMOUTREG( MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
+ PRIMOUTREG( MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
+ PRIMOUTREG( MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
- PRIMADVANCE( dev_priv );
+ PRIMOUTREG( MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
+ PRIMOUTREG( MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
+ PRIMOUTREG( MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
+ PRIMOUTREG( MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
+
+ PRIMOUTREG( MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );
+ PRIMOUTREG( MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
+ PRIMOUTREG( MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );
+ PRIMOUTREG( 0x2d00 + 49*4, 0 );
+
+ PRIMOUTREG( 0x2d00 + 57*4, 0 );
+ PRIMOUTREG( 0x2d00 + 53*4, 0 );
+ PRIMOUTREG( 0x2d00 + 61*4, 0 );
+ PRIMOUTREG( 0x2d00 + 52*4, regs[MGA_TEXREG_WIDTH] | 0x40 );
+
+ PRIMOUTREG( 0x2d00 + 60*4, regs[MGA_TEXREG_HEIGHT] | 0x40 );
+ PRIMOUTREG( MGAREG_TEXTRANS, 0xffff );
+ PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff );
+ PRIMOUTREG( MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
+
+ PRIMADVANCE( dev_priv );
}
+/* Required when switching from multitexturing to single texturing.
+ */
+static void mgaG400EmitTexFlush( drm_mga_private_t *dev_priv )
+{
+ PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ PRIMGETPTR( dev_priv );
+
+ /* This takes 15 dwords */
+
+ PRIMOUTREG( MGAREG_YDST, 0 );
+ PRIMOUTREG( MGAREG_FXLEFT, 0 );
+ PRIMOUTREG( MGAREG_FXRIGHT, 1 );
+ PRIMOUTREG( MGAREG_DWGCTL, MGA_FLUSH_CMD );
+
+ PRIMOUTREG( MGAREG_LEN + MGAREG_MGA_EXEC, 1 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DWGSYNC, 0x7000 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+
+ PRIMOUTREG( MGAREG_TEXCTL2, 0 );
+ PRIMOUTREG( MGAREG_LEN + MGAREG_MGA_EXEC, 0 );
+ PRIMOUTREG( MGAREG_TEXCTL2, 0x80 );
+ PRIMOUTREG( MGAREG_LEN + MGAREG_MGA_EXEC, 0 );
-static void mgaG400EmitPipe(drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv)
+ PRIMADVANCE( dev_priv );
+}
+
+static void mgaG400EmitPipe( drm_mga_private_t *dev_priv )
{
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int pipe = sarea_priv->WarpPipe;
float fParam = 12800.0f;
PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
- PRIMGETPTR(dev_priv);
- PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
-
+ PRIMGETPTR( dev_priv );
+
+ /* This takes 30 dwords */
+
/* Establish vertex size.
*/
if (pipe & MGA_T2) {
- PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001e09);
- PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
+ PRIMOUTREG( MGAREG_WIADDR2, WIA_wmode_suspend );
+ PRIMOUTREG( MGAREG_WVRTXSZ, 0x00001e09 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+
+ PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 );
+ PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 );
+ PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 );
+ PRIMOUTREG( MGAREG_WACCEPTSEQ, 0x1e000000 );
} else {
- PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001807);
- PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x18000000);
- }
-
- PRIMOUTREG(MGAREG_WFLAG, 0);
- PRIMOUTREG(MGAREG_WFLAG1, 0);
-
- PRIMOUTREG(0x2d00 + 56*4, *((u32 *)(&fParam)));
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_WIADDR2, WIA_wmode_suspend );
+ PRIMOUTREG( MGAREG_WVRTXSZ, 0x00001807 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+
+ PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 );
+ PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 );
+ PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 );
+ PRIMOUTREG( MGAREG_WACCEPTSEQ, 0x18000000 );
+ }
+
+ PRIMOUTREG( MGAREG_WFLAG, 0 );
+ PRIMOUTREG( MGAREG_WFLAG1, 0 );
+ PRIMOUTREG( 0x2d00 + 56*4, *((u32 *)(&fParam)) );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
- PRIMOUTREG(0x2d00 + 49*4, 0); /* Tex stage 0 */
- PRIMOUTREG(0x2d00 + 57*4, 0); /* Tex stage 0 */
- PRIMOUTREG(0x2d00 + 53*4, 0); /* Tex stage 1 */
- PRIMOUTREG(0x2d00 + 61*4, 0); /* Tex stage 1 */
+ PRIMOUTREG( 0x2d00 + 49*4, 0 ); /* Tex stage 0 */
+ PRIMOUTREG( 0x2d00 + 57*4, 0 ); /* Tex stage 0 */
+ PRIMOUTREG( 0x2d00 + 53*4, 0 ); /* Tex stage 1 */
+ PRIMOUTREG( 0x2d00 + 61*4, 0 ); /* Tex stage 1 */
- PRIMOUTREG(0x2d00 + 54*4, 0x40); /* Tex stage 0 : w */
- PRIMOUTREG(0x2d00 + 62*4, 0x40); /* Tex stage 0 : h */
- PRIMOUTREG(0x2d00 + 52*4, 0x40); /* Tex stage 1 : w */
- PRIMOUTREG(0x2d00 + 60*4, 0x40); /* Tex stage 1 : h */
+ PRIMOUTREG( 0x2d00 + 54*4, 0x40 ); /* Tex stage 0 : w */
+ PRIMOUTREG( 0x2d00 + 62*4, 0x40 ); /* Tex stage 0 : h */
+ PRIMOUTREG( 0x2d00 + 52*4, 0x40 ); /* Tex stage 1 : w */
+ PRIMOUTREG( 0x2d00 + 60*4, 0x40 ); /* Tex stage 1 : h */
/* Dma pading required due to hw bug */
- PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
- PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
- PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
- PRIMOUTREG(MGAREG_WIADDR2, (dev_priv->WarpIndex[pipe].phys_addr |
- WIA_wmode_start | WIA_wagp_agp));
- PRIMADVANCE(dev_priv);
+ PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff );
+ PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff );
+ PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff );
+ PRIMOUTREG( MGAREG_WIADDR2, (u32)(dev_priv->WarpIndex[pipe].phys_addr |
+ WIA_wmode_start | WIA_wagp_agp) );
+ PRIMADVANCE( dev_priv );
}
-static void mgaG200EmitPipe( drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv )
+static void mgaG200EmitPipe( drm_mga_private_t *dev_priv )
{
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int pipe = sarea_priv->WarpPipe;
PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
- PRIMGETPTR(dev_priv);
- PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
- PRIMOUTREG(MGAREG_WVRTXSZ, 7);
- PRIMOUTREG(MGAREG_WFLAG, 0);
- PRIMOUTREG(0x2d00 + 24*4, 0); /* tex w/h */
+ PRIMGETPTR( dev_priv );
- PRIMOUTREG(0x2d00 + 25*4, 0x100);
- PRIMOUTREG(0x2d00 + 34*4, 0); /* tex w/h */
- PRIMOUTREG(0x2d00 + 42*4, 0xFFFF);
- PRIMOUTREG(0x2d00 + 60*4, 0xFFFF);
+ /* This takes 15 dwords */
+
+ PRIMOUTREG( MGAREG_WIADDR, WIA_wmode_suspend );
+ PRIMOUTREG( MGAREG_WVRTXSZ, 7 );
+ PRIMOUTREG( MGAREG_WFLAG, 0 );
+ PRIMOUTREG( 0x2d00 + 24*4, 0 ); /* tex w/h */
+
+ PRIMOUTREG( 0x2d00 + 25*4, 0x100 );
+ PRIMOUTREG( 0x2d00 + 34*4, 0 ); /* tex w/h */
+ PRIMOUTREG( 0x2d00 + 42*4, 0xFFFF );
+ PRIMOUTREG( 0x2d00 + 60*4, 0xFFFF );
/* Dma pading required due to hw bug */
- PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
- PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
- PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
- PRIMOUTREG(MGAREG_WIADDR, (dev_priv->WarpIndex[pipe].phys_addr |
- WIA_wmode_start | WIA_wagp_agp));
+ PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff );
+ PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff );
+ PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff );
+ PRIMOUTREG( MGAREG_WIADDR, (u32)(dev_priv->WarpIndex[pipe].phys_addr |
+ WIA_wmode_start | WIA_wagp_agp) );
- PRIMADVANCE(dev_priv);
+ PRIMADVANCE( dev_priv );
}
-void mgaEmitState( drm_mga_private_t *dev_priv, drm_mga_buf_priv_t *buf_priv )
+static void mgaEmitState( drm_mga_private_t *dev_priv )
{
- unsigned int dirty = buf_priv->dirty;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+ DRM_DEBUG("%s\n", __FUNCTION__);
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
- if (dirty & MGASAREA_NEW_CONTEXT)
- mgaEmitContext( dev_priv, buf_priv );
+ int multitex = sarea_priv->WarpPipe & MGA_T2;
- if (dirty & MGASAREA_NEW_TEX1)
- mgaG400EmitTex1( dev_priv, buf_priv );
-
- if (dirty & MGASAREA_NEW_TEX0)
- mgaG400EmitTex0( dev_priv, buf_priv );
+ if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
+ if ((dev_priv->WarpPipe & MGA_T2) && !multitex) {
+ mgaG400EmitTexFlush( dev_priv );
+ }
+ mgaG400EmitPipe( dev_priv );
+ dev_priv->WarpPipe = sarea_priv->WarpPipe;
+ }
+
+ if (dirty & MGA_UPLOAD_CTX) {
+ mgaEmitContext( dev_priv );
+ sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
+ }
- if (dirty & MGASAREA_NEW_PIPE)
- mgaG400EmitPipe( dev_priv, buf_priv );
+ if (dirty & MGA_UPLOAD_TEX0) {
+ mgaG400EmitTex0( dev_priv );
+ sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+ }
+
+ if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
+ mgaG400EmitTex1( dev_priv );
+ sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
+ }
} else {
- if (dirty & MGASAREA_NEW_CONTEXT)
- mgaEmitContext( dev_priv, buf_priv );
+ if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
+ mgaG200EmitPipe( dev_priv );
+ dev_priv->WarpPipe = sarea_priv->WarpPipe;
+ }
- if (dirty & MGASAREA_NEW_TEX0)
- mgaG200EmitTex( dev_priv, buf_priv );
+ if (dirty & MGA_UPLOAD_CTX) {
+ mgaEmitContext( dev_priv );
+ sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
+ }
- if (dirty & MGASAREA_NEW_PIPE)
- mgaG200EmitPipe( dev_priv, buf_priv );
- }
+ if (dirty & MGA_UPLOAD_TEX0) {
+ mgaG200EmitTex( dev_priv );
+ sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+ }
+ }
}
-
/* Disallow all write destinations except the front and backbuffer.
*/
-static int mgaCopyContext(drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv)
+static int mgaVerifyContext(drm_mga_private_t *dev_priv )
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int *regs = sarea_priv->ContextState;
-
- if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOrg &&
- regs[MGA_CTXREG_DSTORG] != dev_priv->backOrg)
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
+ regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
+ DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n",
+ regs[MGA_CTXREG_DSTORG], dev_priv->frontOffset,
+ dev_priv->backOffset);
+ regs[MGA_CTXREG_DSTORG] = 0;
return -1;
+ }
- memcpy(buf_priv->ContextState, sarea_priv->ContextState,
- sizeof(buf_priv->ContextState));
return 0;
}
-
/* Disallow texture reads from PCI space.
*/
-static int mgaCopyTex(drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv,
+static int mgaVerifyTex(drm_mga_private_t *dev_priv,
int unit)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1)
- return -1;
+ DRM_DEBUG("%s\n", __FUNCTION__);
- memcpy(buf_priv->TexState[unit], sarea_priv->TexState[unit],
- sizeof(buf_priv->TexState[0]));
+ if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
+ DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n",
+ sarea_priv->TexState[unit][MGA_TEXREG_ORG],
+ unit);
+ sarea_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
+ return -1;
+ }
return 0;
}
-
-int mgaCopyAndVerifyState( drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv )
+static int mgaVerifyState( drm_mga_private_t *dev_priv )
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- unsigned int dirty = sarea_priv->dirty ;
+ unsigned int dirty = sarea_priv->dirty;
int rv = 0;
- buf_priv->dirty = sarea_priv->dirty;
- buf_priv->WarpPipe = sarea_priv->WarpPipe;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
- if (dirty & MGASAREA_NEW_CONTEXT)
- rv |= mgaCopyContext( dev_priv, buf_priv );
+ if (dirty & MGA_UPLOAD_CTX)
+ rv |= mgaVerifyContext( dev_priv );
- if (dirty & MGASAREA_NEW_TEX0)
- rv |= mgaCopyTex( dev_priv, buf_priv, 0 );
+ if (dirty & MGA_UPLOAD_TEX0)
+ rv |= mgaVerifyTex( dev_priv, 0 );
if (dev_priv->chipset == MGA_CARD_TYPE_G400)
{
- if (dirty & MGASAREA_NEW_TEX1)
- rv |= mgaCopyTex( dev_priv, buf_priv, 1 );
+ if (dirty & MGA_UPLOAD_TEX1)
+ rv |= mgaVerifyTex( dev_priv, 1 );
- if (dirty & MGASAREA_NEW_PIPE)
- rv |= (buf_priv->WarpPipe > MGA_MAX_G400_PIPES);
+ if (dirty & MGA_UPLOAD_PIPE)
+ rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES);
}
else
{
- if (dirty & MGASAREA_NEW_PIPE)
- rv |= (buf_priv->WarpPipe > MGA_MAX_G200_PIPES);
+ if (dirty & MGA_UPLOAD_PIPE)
+ rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES);
}
return rv == 0;
}
+static int mgaVerifyIload( drm_mga_private_t *dev_priv,
+ unsigned long bus_address,
+ unsigned int dstOrg, int length )
+{
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if(dstOrg < dev_priv->textureOffset ||
+ dstOrg + length >
+ (dev_priv->textureOffset + dev_priv->textureSize)) {
+ return -EINVAL;
+ }
+ if(length % 64) {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* This copies a 64 byte aligned agp region to the frambuffer
+ * with a standard blit, the ioctl needs to do checking */
+
+static void mga_dma_dispatch_tex_blit( drm_device_t *dev,
+ unsigned long bus_address,
+ int length,
+ unsigned int destOrg )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ int use_agp = PDEA_pagpxfer_enable | 0x00000001;
+ u16 y2;
+ PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ y2 = length / 64;
+
+ PRIM_OVERFLOW( dev, dev_priv, 30 );
+ PRIMGETPTR( dev_priv );
+
+ PRIMOUTREG( MGAREG_DSTORG, destOrg );
+ PRIMOUTREG( MGAREG_MACCESS, 0x00000000 );
+ DRM_DEBUG("srcorg : %lx\n", bus_address | use_agp);
+ PRIMOUTREG( MGAREG_SRCORG, (u32) bus_address | use_agp );
+ PRIMOUTREG( MGAREG_AR5, 64 );
+
+ PRIMOUTREG( MGAREG_PITCH, 64 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DWGCTL, MGA_COPY_CMD );
+
+ PRIMOUTREG( MGAREG_AR0, 63 );
+ PRIMOUTREG( MGAREG_AR3, 0 );
+ PRIMOUTREG( MGAREG_FXBNDRY, (63 << 16) );
+ PRIMOUTREG( MGAREG_YDSTLEN+MGAREG_MGA_EXEC, y2 );
+
+ PRIMOUTREG( MGAREG_SRCORG, 0 );
+ PRIMOUTREG( MGAREG_PITCH, dev_priv->stride / dev_priv->cpp );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMADVANCE( dev_priv );
+}
+
+static void mga_dma_dispatch_vertex(drm_device_t *dev,
+ drm_buf_t *buf)
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned long address = (unsigned long)buf->bus_address;
+ int length = buf->used;
+ int use_agp = PDEA_pagpxfer_enable;
+ int i = 0;
+ int primary_needed;
+ PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ DRM_DEBUG("dispatch vertex %d addr 0x%lx, "
+ "length 0x%x nbox %d dirty %x\n",
+ buf->idx, address, length,
+ sarea_priv->nbox, sarea_priv->dirty);
+
+ DRM_DEBUG("used : %d, total : %d\n", buf->used, buf->total);
+ if(sarea_priv->WarpPipe & MGA_T2) {
+ if ((buf->used/4) % 10)
+ DRM_DEBUG("Multitex Buf is not aligned properly!!!\n");
+ } else {
+ if ((buf->used/4) % 8)
+ DRM_DEBUG("Buf is not aligned properly!!!\n");
+ }
+
+ if (buf->used) {
+ /* WARNING: if you change any of the state functions verify
+ * these numbers (Overestimating this doesn't hurt).
+ */
+ buf_priv->dispatched = 1;
+ primary_needed = (30+15+15+30+25+
+ 10 +
+ 15 * MGA_NR_SAREA_CLIPRECTS);
+ PRIM_OVERFLOW(dev, dev_priv, primary_needed);
+ mgaEmitState( dev_priv );
+
+ do {
+ if (i < sarea_priv->nbox) {
+ DRM_DEBUG("idx %d Emit box %d/%d:"
+ "%d,%d - %d,%d\n",
+ buf->idx,
+ i, sarea_priv->nbox,
+ sarea_priv->boxes[i].x1,
+ sarea_priv->boxes[i].y1,
+ sarea_priv->boxes[i].x2,
+ sarea_priv->boxes[i].y2);
+
+ mgaEmitClipRect( dev_priv,
+ &sarea_priv->boxes[i] );
+ }
+
+ PRIMGETPTR( dev_priv );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_SECADDRESS,
+ ((u32)address) | TT_VERTEX );
+ PRIMOUTREG( MGAREG_SECEND,
+ (((u32)(address + length)) | use_agp) );
+ PRIMADVANCE( dev_priv );
+ } while (++i < sarea_priv->nbox);
+ }
+
+ if (buf_priv->discard) {
+ if (buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv);
+ buf_priv->dispatched = 0;
+ mga_freelist_put(dev, buf);
+ }
+
+
+}
+
+
+static void mga_dma_dispatch_indices(drm_device_t *dev,
+ drm_buf_t *buf,
+ unsigned int start,
+ unsigned int end)
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int address = (unsigned int)buf->bus_address;
+ int use_agp = PDEA_pagpxfer_enable;
+ int i = 0;
+ int primary_needed;
+ PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ DRM_DEBUG("dispatch indices %d addr 0x%x, "
+ "start 0x%x end 0x%x nbox %d dirty %x\n",
+ buf->idx, address, start, end,
+ sarea_priv->nbox, sarea_priv->dirty);
+
+ if (start != end) {
+ /* WARNING: if you change any of the state functions verify
+ * these numbers (Overestimating this doesn't hurt).
+ */
+ buf_priv->dispatched = 1;
+ primary_needed = (25+15+30+25+
+ 10 +
+ 15 * MGA_NR_SAREA_CLIPRECTS);
+ PRIM_OVERFLOW( dev, dev_priv, primary_needed );
+ mgaEmitState( dev_priv );
+
+ do {
+ if (i < sarea_priv->nbox) {
+ DRM_DEBUG("idx %d Emit box %d/%d:"
+ "%d,%d - %d,%d\n",
+ buf->idx,
+ i, sarea_priv->nbox,
+ sarea_priv->boxes[i].x1,
+ sarea_priv->boxes[i].y1,
+ sarea_priv->boxes[i].x2,
+ sarea_priv->boxes[i].y2);
+
+ mgaEmitClipRect( dev_priv,
+ &sarea_priv->boxes[i] );
+ }
+ PRIMGETPTR( dev_priv );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_SETUPADDRESS,
+ ((address + start) |
+ SETADD_mode_vertlist) );
+ PRIMOUTREG( MGAREG_SETUPEND,
+ ((address + end) | use_agp) );
+ PRIMADVANCE( dev_priv );
+ } while (++i < sarea_priv->nbox);
+ }
+ if (buf_priv->discard) {
+ if (buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv);
+ buf_priv->dispatched = 0;
+ mga_freelist_put(dev, buf);
+ }
+}
+
+
+static void mga_dma_dispatch_clear( drm_device_t *dev, int flags,
+ unsigned int clear_color,
+ unsigned int clear_zval )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->ContextState;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ unsigned int cmd;
+ int i;
+ int primary_needed;
+ PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if ( dev_priv->sgram )
+ cmd = MGA_CLEAR_CMD | DC_atype_blk;
+ else
+ cmd = MGA_CLEAR_CMD | DC_atype_rstr;
+
+ primary_needed = nbox * 70;
+ if (primary_needed == 0) primary_needed = 70;
+ PRIM_OVERFLOW( dev, dev_priv, primary_needed );
+ PRIMGETPTR( dev_priv );
+
+ for (i = 0 ; i < nbox ; i++) {
+ unsigned int height = pbox[i].y2 - pbox[i].y1;
+
+ DRM_DEBUG("dispatch clear %d,%d-%d,%d flags %x!\n",
+ pbox[i].x1, pbox[i].y1, pbox[i].x2,
+ pbox[i].y2, flags);
+
+ if ( flags & MGA_FRONT ) {
+ DRM_DEBUG("clear front\n");
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
+ PRIMOUTREG( MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_FCOL, clear_color );
+ PRIMOUTREG( MGAREG_DSTORG, dev_priv->frontOffset );
+ PRIMOUTREG( MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
+ }
+
+ if ( flags & MGA_BACK ) {
+ DRM_DEBUG("clear back\n");
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_YDSTLEN, (pbox[i].y1<<16)|height );
+ PRIMOUTREG( MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1 );
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_FCOL, clear_color );
+ PRIMOUTREG( MGAREG_DSTORG, dev_priv->backOffset );
+ PRIMOUTREG( MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
+ }
+
+ if ( flags & MGA_DEPTH ) {
+ DRM_DEBUG("clear depth\n");
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_YDSTLEN, (pbox[i].y1<<16)|height );
+ PRIMOUTREG( MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1 );
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_FCOL, clear_zval );
+ PRIMOUTREG( MGAREG_DSTORG, dev_priv->depthOffset );
+ PRIMOUTREG( MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
+ }
+ }
+
+ /* Force reset of DWGCTL */
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
+ PRIMADVANCE( dev_priv );
+}
+
+static void mga_dma_dispatch_swap( drm_device_t *dev )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->ContextState;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int i;
+ int primary_needed;
+ PRIMLOCALS;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ primary_needed = nbox * 5;
+ primary_needed += 60;
+ PRIM_OVERFLOW(dev, dev_priv, primary_needed);
+ PRIMGETPTR( dev_priv );
+
+ PRIMOUTREG( MGAREG_DSTORG, dev_priv->frontOffset );
+ PRIMOUTREG( MGAREG_MACCESS, dev_priv->mAccess );
+ PRIMOUTREG( MGAREG_SRCORG, dev_priv->backOffset );
+ PRIMOUTREG( MGAREG_AR5, dev_priv->stride/2 );
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DWGCTL, MGA_COPY_CMD );
+
+ for (i = 0 ; i < nbox; i++) {
+ unsigned int h = pbox[i].y2 - pbox[i].y1;
+ unsigned int start = pbox[i].y1 * dev_priv->stride/2;
+
+ DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
+ pbox[i].x1, pbox[i].y1,
+ pbox[i].x2, pbox[i].y2);
+
+ PRIMOUTREG( MGAREG_AR0, start + pbox[i].x2 - 1 );
+ PRIMOUTREG( MGAREG_AR3, start + pbox[i].x1 );
+ PRIMOUTREG( MGAREG_FXBNDRY, pbox[i].x1|((pbox[i].x2 - 1)<<16) );
+ PRIMOUTREG( MGAREG_YDSTLEN+MGAREG_MGA_EXEC, (pbox[i].y1<<16)|h );
+ }
+
+ /* Force reset of DWGCTL */
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0 );
+ PRIMOUTREG( MGAREG_SRCORG, 0 );
+ PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
+
+ PRIMADVANCE( dev_priv );
+}
+
+int mga_clear_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_clear_t clear;
+
+ copy_from_user_ret(&clear, (drm_mga_clear_t *)arg, sizeof(clear),
+ -EFAULT);
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("mga_clear_bufs called without lock held\n");
+ return -EINVAL;
+ }
+
+ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
+ mga_dma_dispatch_clear( dev, clear.flags,
+ clear.clear_color,
+ clear.clear_depth );
+ PRIMUPDATE(dev_priv);
+ mga_flush_write_combine();
+ mga_dma_schedule(dev, 1);
+ return 0;
+}
+
+int mga_swap_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("mga_swap_bufs called without lock held\n");
+ return -EINVAL;
+ }
+
+ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
+ mga_dma_dispatch_swap( dev );
+ PRIMUPDATE(dev_priv);
+ set_bit(MGA_BUF_SWAP_PENDING, &dev_priv->current_prim->buffer_status);
+ mga_flush_write_combine();
+ mga_dma_schedule(dev, 1);
+ return 0;
+}
+
+int mga_iload(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_device_dma_t *dma = dev->dma;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_iload_t iload;
+ unsigned long bus_address;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ DRM_DEBUG("Starting Iload\n");
+ copy_from_user_ret(&iload, (drm_mga_iload_t *)arg, sizeof(iload),
+ -EFAULT);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("mga_iload called without lock held\n");
+ return -EINVAL;
+ }
+
+ buf = dma->buflist[ iload.idx ];
+ buf_priv = buf->dev_private;
+ bus_address = buf->bus_address;
+ DRM_DEBUG("bus_address %lx, length %d, destorg : %x\n",
+ bus_address, iload.length, iload.destOrg);
+
+ if(mgaVerifyIload(dev_priv,
+ bus_address,
+ iload.destOrg,
+ iload.length)) {
+ mga_freelist_put(dev, buf);
+ return -EINVAL;
+ }
+
+ sarea_priv->dirty |= MGA_UPLOAD_CTX;
+
+ mga_dma_dispatch_tex_blit(dev, bus_address, iload.length,
+ iload.destOrg);
+ AGEBUF(dev_priv, buf_priv);
+ buf_priv->discard = 1;
+ mga_freelist_put(dev, buf);
+ mga_flush_write_combine();
+ mga_dma_schedule(dev, 1);
+ return 0;
+}
+
+int mga_vertex(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_vertex_t vertex;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ copy_from_user_ret(&vertex, (drm_mga_vertex_t *)arg, sizeof(vertex),
+ -EFAULT);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("mga_vertex called without lock held\n");
+ return -EINVAL;
+ }
+
+ DRM_DEBUG("mga_vertex\n");
+
+ buf = dma->buflist[ vertex.idx ];
+ buf_priv = buf->dev_private;
+
+ buf->used = vertex.used;
+ buf_priv->discard = vertex.discard;
+
+ if (!mgaVerifyState(dev_priv)) {
+ if (vertex.discard) {
+ if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv);
+ buf_priv->dispatched = 0;
+ mga_freelist_put(dev, buf);
+ }
+ DRM_DEBUG("bad state\n");
+ return -EINVAL;
+ }
+
+ mga_dma_dispatch_vertex(dev, buf);
+
+ PRIMUPDATE(dev_priv);
+ mga_flush_write_combine();
+ mga_dma_schedule(dev, 1);
+ return 0;
+}
+
+
+int mga_indices(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_indices_t indices;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ copy_from_user_ret(&indices, (drm_mga_indices_t *)arg, sizeof(indices),
+ -EFAULT);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("mga_indices called without lock held\n");
+ return -EINVAL;
+ }
+
+ DRM_DEBUG("mga_indices\n");
+
+ buf = dma->buflist[ indices.idx ];
+ buf_priv = buf->dev_private;
+
+ buf_priv->discard = indices.discard;
+
+ if (!mgaVerifyState(dev_priv)) {
+ if (indices.discard) {
+ if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv);
+ buf_priv->dispatched = 0;
+ mga_freelist_put(dev, buf);
+ }
+ return -EINVAL;
+ }
+
+ mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
+
+ PRIMUPDATE(dev_priv);
+ mga_flush_write_combine();
+ mga_dma_schedule(dev, 1);
+ return 0;
+}
+
+
+
+static int mga_dma_get_buffers(drm_device_t *dev, drm_dma_t *d)
+{
+ int i;
+ drm_buf_t *buf;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ for (i = d->granted_count; i < d->request_count; i++) {
+ buf = mga_freelist_get(dev);
+ if (!buf) break;
+ buf->pid = current->pid;
+ copy_to_user_ret(&d->request_indices[i],
+ &buf->idx,
+ sizeof(buf->idx),
+ -EFAULT);
+ copy_to_user_ret(&d->request_sizes[i],
+ &buf->total,
+ sizeof(buf->total),
+ -EFAULT);
+ ++d->granted_count;
+ }
+ return 0;
+}
+
+int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_device_dma_t *dma = dev->dma;
+ int retcode = 0;
+ drm_dma_t d;
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
+ DRM_DEBUG("%d %d: %d send, %d req\n",
+ current->pid, d.context, d.send_count, d.request_count);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("mga_dma called without lock held\n");
+ return -EINVAL;
+ }
+
+ /* Please don't send us buffers.
+ */
+ if (d.send_count != 0) {
+ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+ current->pid, d.send_count);
+ return -EINVAL;
+ }
+
+ /* We'll send you buffers.
+ */
+ if (d.request_count < 0 || d.request_count > dma->buf_count) {
+ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+ current->pid, d.request_count, dma->buf_count);
+ return -EINVAL;
+ }
+
+ d.granted_count = 0;
+
+ if (d.request_count) {
+ retcode = mga_dma_get_buffers(dev, &d);
+ }
+
+ DRM_DEBUG("%d returning, granted = %d\n",
+ current->pid, d.granted_count);
+ copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
+ return retcode;
+}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c
index 54aba58c4..392abceb9 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c
@@ -1,8 +1,7 @@
/* proc.c -- /proc support for DRM -*- linux-c -*-
* Created: Mon Jan 11 09:48:47 1999 by faith@precisioninsight.com
- * Revised: Sun Feb 13 23:41:04 2000 by kevin@precisioninsight.com
*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -164,7 +163,10 @@ static int _drm_vm_info(char *buf, char **start, off_t offset, int len,
{
drm_device_t *dev = (drm_device_t *)data;
drm_map_t *map;
- const char *types[] = { "FB", "REG", "SHM" };
+ /* Hardcoded from _DRM_FRAME_BUFFER,
+ _DRM_REGISTERS, _DRM_SHM, and
+ _DRM_AGP. */
+ const char *types[] = { "FB", "REG", "SHM", "AGP" };
const char *type;
int i;
@@ -175,7 +177,7 @@ static int _drm_vm_info(char *buf, char **start, off_t offset, int len,
"address mtrr\n\n");
for (i = 0; i < dev->map_count; i++) {
map = dev->maplist[i];
- if (map->type < 0 || map->type > 2) type = "??";
+ if (map->type < 0 || map->type > 3) type = "??";
else type = types[map->type];
DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
i,
@@ -397,6 +399,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
#endif
DRM_PROC_PRINT("\n");
+#if 0
for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
pgd = pgd_offset(vma->vm_mm, i);
pmd = pmd_offset(pgd, i);
@@ -417,6 +420,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
DRM_PROC_PRINT(" 0x%08lx\n", i);
}
}
+#endif
}
return len;
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_bufs.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_bufs.c
new file mode 100644
index 000000000..bad6c5714
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_bufs.c
@@ -0,0 +1,309 @@
+/* r128_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
+ * Created: Wed Apr 12 16:19:08 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Authors: Kevin E. Martin <kevin@precisioninsight.com>
+ * Rickard E. (Rik) Faith <faith@precisioninsight.com>
+ * Jeff Hartmann <jhartmann@precisioninsight.com>
+ *
+ * $XFree86$
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "r128_drv.h"
+#include "linux/un.h"
+
+
+#ifdef DRM_AGP
+int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t request;
+ drm_buf_entry_t *entry;
+ drm_buf_t *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;
+
+ if (!dma) return -EINVAL;
+
+ copy_from_user_ret(&request,
+ (drm_buf_desc_t *)arg,
+ sizeof(request),
+ -EFAULT);
+
+ 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: %ld\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);
+
+ down(&dev->struct_sem);
+ entry = &dma->bufs[order];
+ if (entry->buf_count) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+ if (!entry->buflist) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+ offset = 0;
+
+ for (offset = 0;
+ 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 + offset);
+ buf->address = (void *)(agp_offset + offset);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+ init_waitqueue_head(&buf->dma_wait);
+ buf->pid = 0;
+
+ buf->dev_priv_size = sizeof(drm_r128_buf_priv_t);
+ buf->dev_private = drm_alloc(sizeof(drm_r128_buf_priv_t),
+ DRM_MEM_BUFS);
+ memset(buf->dev_private, 0, buf->dev_priv_size);
+
+#if DRM_DMA_HISTOGRAM
+ buf->time_queued = 0;
+ buf->time_dispatched = 0;
+ buf->time_completed = 0;
+ buf->time_freed = 0;
+#endif
+
+ byte_count += PAGE_SIZE << page_order;
+
+ DRM_DEBUG("buffer %d @ %p\n",
+ entry->buf_count, buf->address);
+ }
+
+ DRM_DEBUG("byte_count: %d\n", byte_count);
+
+ dma->buflist = drm_realloc(dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist),
+ DRM_MEM_BUFS);
+ for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
+ dma->buflist[i] = &entry->buflist[i - dma->buf_count];
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
+
+ drm_freelist_create(&entry->freelist, entry->buf_count);
+ for (i = 0; i < entry->buf_count; i++) {
+ drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
+ }
+
+ up(&dev->struct_sem);
+
+ request.count = entry->buf_count;
+ request.size = size;
+
+ copy_to_user_ret((drm_buf_desc_t *)arg,
+ &request,
+ sizeof(request),
+ -EFAULT);
+
+ dma->flags = _DRM_DMA_USE_AGP;
+
+ atomic_dec(&dev->buf_alloc);
+ return 0;
+}
+#endif
+
+int r128_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_buf_desc_t request;
+
+ if (!dev_priv || dev_priv->is_pci) return -EINVAL;
+
+ copy_from_user_ret(&request,
+ (drm_buf_desc_t *)arg,
+ sizeof(request),
+ -EFAULT);
+
+#ifdef DRM_AGP
+ if (request.flags & _DRM_AGP_BUFFER)
+ return r128_addbufs_agp(inode, filp, cmd, arg);
+ else
+#endif
+ return -EINVAL;
+}
+
+int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ int retcode = 0;
+ const int zero = 0;
+ unsigned long virtual;
+ unsigned long address;
+ drm_buf_map_t request;
+ int i;
+
+ if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL;
+
+ DRM_DEBUG("\n");
+
+ 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);
+
+ copy_from_user_ret(&request,
+ (drm_buf_map_t *)arg,
+ sizeof(request),
+ -EFAULT);
+
+ if (request.count >= dma->buf_count) {
+ if (dma->flags & _DRM_DMA_USE_AGP) {
+ drm_map_t *map;
+
+ map = dev_priv->agp_vertbufs;
+ if (!map) {
+ retcode = -EINVAL;
+ goto done;
+ }
+
+ down(&current->mm->mmap_sem);
+ virtual = do_mmap(filp, 0, map->size,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ (unsigned long)map->offset);
+ up(&current->mm->mmap_sem);
+ } else {
+ down(&current->mm->mmap_sem);
+ virtual = do_mmap(filp, 0, dma->byte_count,
+ PROT_READ|PROT_WRITE, MAP_SHARED, 0);
+ up(&current->mm->mmap_sem);
+ }
+ if (virtual > -1024UL) {
+ /* Real error */
+ retcode = (signed long)virtual;
+ goto done;
+ }
+ request.virtual = (void *)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);
+
+ copy_to_user_ret((drm_buf_map_t *)arg,
+ &request,
+ sizeof(request),
+ -EFAULT);
+
+ return retcode;
+}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_context.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_context.c
new file mode 100644
index 000000000..d288fd284
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_context.c
@@ -0,0 +1,214 @@
+/* r128_context.c -- IOCTLs for r128 contexts -*- linux-c -*-
+ * Created: Mon Dec 13 09:51:35 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Author: Rickard E. (Rik) Faith <faith@precisioninsight.com>
+ *
+ * $XFree86$
+ *
+ */
+
+#include <linux/sched.h>
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "r128_drv.h"
+
+extern drm_ctx_t r128_res_ctx;
+
+static int r128_alloc_queue(drm_device_t *dev)
+{
+#if 0
+ static int context = 0;
+#endif
+
+ return drm_ctxbitmap_next(dev);
+}
+
+int r128_context_switch(drm_device_t *dev, int old, int new)
+{
+ char buf[64];
+
+ atomic_inc(&dev->total_ctx);
+
+ if (test_and_set_bit(0, &dev->context_flag)) {
+ DRM_ERROR("Reentering -- FIXME\n");
+ return -EBUSY;
+ }
+
+#if DRM_DMA_HISTOGRAM
+ dev->ctx_start = get_cycles();
+#endif
+
+ DRM_DEBUG("Context switch from %d to %d\n", old, new);
+
+ if (new == dev->last_context) {
+ clear_bit(0, &dev->context_flag);
+ return 0;
+ }
+
+ if (drm_flags & DRM_FLAG_NOCTX) {
+ r128_context_switch_complete(dev, new);
+ } else {
+ sprintf(buf, "C %d %d\n", old, new);
+ drm_write_string(dev, buf);
+ }
+
+ return 0;
+}
+
+int r128_context_switch_complete(drm_device_t *dev, int new)
+{
+ dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
+ dev->last_switch = jiffies;
+
+ if (!_DRM_LOCK_IS_HELD(dev->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. */
+#if DRM_DMA_HISTOGRAM
+ atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
+ - dev->ctx_start)]);
+
+#endif
+ clear_bit(0, &dev->context_flag);
+ wake_up(&dev->context_wait);
+
+ return 0;
+}
+
+
+int r128_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_ctx_res_t res;
+ drm_ctx_t ctx;
+ int i;
+
+ DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
+ copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT);
+ if (res.count >= DRM_RESERVED_CONTEXTS) {
+ memset(&ctx, 0, sizeof(ctx));
+ for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
+ ctx.handle = i;
+ copy_to_user_ret(&res.contexts[i],
+ &i,
+ sizeof(i),
+ -EFAULT);
+ }
+ }
+ res.count = DRM_RESERVED_CONTEXTS;
+ copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT);
+ return 0;
+}
+
+
+int r128_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_ctx_t ctx;
+
+ copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if ((ctx.handle = r128_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
+ /* Skip kernel's context and get a new one. */
+ ctx.handle = r128_alloc_queue(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;
+ }
+
+ copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT);
+ return 0;
+}
+
+int r128_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_ctx_t ctx;
+
+ copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
+ if (ctx.flags==_DRM_CONTEXT_PRESERVED)
+ r128_res_ctx.handle=ctx.handle;
+ return 0;
+}
+
+int r128_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_ctx_t ctx;
+
+ copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
+ /* This is 0, because we don't hanlde any context flags */
+ ctx.flags = 0;
+ copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT);
+ return 0;
+}
+
+int r128_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_ctx_t ctx;
+
+ copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ DRM_DEBUG("%d\n", ctx.handle);
+ return r128_context_switch(dev, dev->last_context, ctx.handle);
+}
+
+int r128_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_ctx_t ctx;
+
+ copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ DRM_DEBUG("%d\n", ctx.handle);
+ r128_context_switch_complete(dev, ctx.handle);
+
+ return 0;
+}
+
+int r128_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_ctx_t ctx;
+
+ copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ DRM_DEBUG("%d\n", ctx.handle);
+ drm_ctxbitmap_free(dev, ctx.handle);
+
+ return 0;
+}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_dma.c
new file mode 100644
index 000000000..860c41885
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_dma.c
@@ -0,0 +1,908 @@
+/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
+ * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Authors: Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ * $XFree86$
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "r128_drv.h"
+
+#include <linux/interrupt.h> /* For task queue support */
+#include <linux/delay.h>
+
+
+
+#define DO_REMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
+
+#define DO_REMAPFREE(_m) \
+ do { \
+ if ((_m)->handle && (_m)->size) \
+ drm_ioremapfree((_m)->handle, (_m)->size); \
+ } while (0)
+
+#define DO_FIND_MAP(_m, _o) \
+ do { \
+ int _i; \
+ for (_i = 0; _i < dev->map_count; _i++) { \
+ if (dev->maplist[_i]->offset == _o) { \
+ _m = dev->maplist[_i]; \
+ break; \
+ } \
+ } \
+ } while (0)
+
+
+#define R128_MAX_VBUF_AGE 0x10000000
+#define R128_VB_AGE_REG R128_GUI_SCRATCH_REG0
+
+int R128_READ_PLL(drm_device_t *dev, int addr)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+
+ R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
+ return R128_READ(R128_CLOCK_CNTL_DATA);
+}
+
+static void r128_flush_write_combine(void)
+{
+ int xchangeDummy;
+
+ __asm__ volatile("push %%eax ;"
+ "xchg %%eax, %0 ;"
+ "pop %%eax" : : "m" (xchangeDummy));
+ __asm__ volatile("push %%eax ;"
+ "push %%ebx ;"
+ "push %%ecx ;"
+ "push %%edx ;"
+ "movl $0,%%eax ;"
+ "cpuid ;"
+ "pop %%edx ;"
+ "pop %%ecx ;"
+ "pop %%ebx ;"
+ "pop %%eax" : /* no outputs */ : /* no inputs */ );
+}
+
+static int r128_do_cleanup_cce(drm_device_t *dev)
+{
+ if (dev->dev_private) {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+
+ if (!dev_priv->is_pci) {
+ DO_REMAPFREE(dev_priv->agp_ring);
+ DO_REMAPFREE(dev_priv->agp_read_ptr);
+ DO_REMAPFREE(dev_priv->agp_vertbufs);
+ DO_REMAPFREE(dev_priv->agp_indbufs);
+ DO_REMAPFREE(dev_priv->agp_textures);
+ }
+
+ drm_free(dev->dev_private, sizeof(drm_r128_private_t),
+ DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+ }
+
+ return 0;
+}
+
+static int r128_do_init_cce(drm_device_t *dev, drm_r128_init_t *init)
+{
+ drm_r128_private_t *dev_priv;
+ int i;
+
+ dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
+ if (dev_priv == NULL) return -ENOMEM;
+ dev->dev_private = (void *)dev_priv;
+
+ memset(dev_priv, 0, sizeof(drm_r128_private_t));
+
+ dev_priv->is_pci = init->is_pci;
+
+ dev_priv->usec_timeout = init->usec_timeout;
+ if (dev_priv->usec_timeout < 1 ||
+ dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
+ drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+ return -EINVAL;
+ }
+
+ dev_priv->cce_mode = init->cce_mode;
+ dev_priv->cce_fifo_size = init->cce_fifo_size;
+ dev_priv->cce_is_bm_mode =
+ ((init->cce_mode == R128_PM4_192BM) ||
+ (init->cce_mode == R128_PM4_128BM_64INDBM) ||
+ (init->cce_mode == R128_PM4_64BM_128INDBM) ||
+ (init->cce_mode == R128_PM4_64BM_64VCBM_64INDBM));
+ dev_priv->cce_secure = init->cce_secure;
+
+ if (dev_priv->cce_is_bm_mode && dev_priv->is_pci) {
+ drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+ return -EINVAL;
+ }
+
+ for (i = 0; i < dev->map_count; i++) {
+ if (dev->maplist[i]->type == _DRM_SHM) {
+ dev_priv->sarea = dev->maplist[i];
+ break;
+ }
+ }
+
+ DO_FIND_MAP(dev_priv->fb, init->fb_offset);
+ if (!dev_priv->is_pci) {
+ DO_FIND_MAP(dev_priv->agp_ring, init->agp_ring_offset);
+ DO_FIND_MAP(dev_priv->agp_read_ptr, init->agp_read_ptr_offset);
+ DO_FIND_MAP(dev_priv->agp_vertbufs, init->agp_vertbufs_offset);
+ DO_FIND_MAP(dev_priv->agp_indbufs, init->agp_indbufs_offset);
+ DO_FIND_MAP(dev_priv->agp_textures, init->agp_textures_offset);
+ }
+ DO_FIND_MAP(dev_priv->mmio, init->mmio_offset);
+
+ dev_priv->sarea_priv =
+ (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
+ init->sarea_priv_offset);
+
+ if (!dev_priv->is_pci) {
+ DO_REMAP(dev_priv->agp_ring);
+ DO_REMAP(dev_priv->agp_read_ptr);
+ DO_REMAP(dev_priv->agp_vertbufs);
+#if 0
+ DO_REMAP(dev_priv->agp_indirectbufs);
+ DO_REMAP(dev_priv->agp_textures);
+#endif
+
+ dev_priv->ring_size = init->ring_size;
+ dev_priv->ring_sizel2qw = drm_order(init->ring_size/8);
+ dev_priv->ring_entries = init->ring_size/sizeof(u32);
+ dev_priv->ring_read_ptr = ((__volatile__ u32 *)
+ dev_priv->agp_read_ptr->handle);
+ dev_priv->ring_start = (u32 *)dev_priv->agp_ring->handle;
+ dev_priv->ring_end = ((u32 *)dev_priv->agp_ring->handle
+ + dev_priv->ring_entries);
+ }
+
+ dev_priv->submit_age = 0;
+ R128_WRITE(R128_VB_AGE_REG, dev_priv->submit_age);
+
+ return 0;
+}
+
+int r128_init_cce(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_r128_init_t init;
+
+ copy_from_user_ret(&init, (drm_r128_init_t *)arg, sizeof(init),
+ -EFAULT);
+
+ switch (init.func) {
+ case R128_INIT_CCE:
+ return r128_do_init_cce(dev, &init);
+ case R128_CLEANUP_CCE:
+ return r128_do_cleanup_cce(dev);
+ }
+
+ return -EINVAL;
+}
+
+static void r128_mark_vertbufs_done(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+ buf_priv->age = 0;
+ }
+}
+
+static int r128_do_pixcache_flush(drm_device_t *dev)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ u32 tmp;
+ int i;
+
+ tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL;
+ R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp);
+
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY))
+ return 0;
+ udelay(1);
+ }
+
+ return -EBUSY;
+}
+
+static int r128_do_wait_for_fifo(drm_device_t *dev, int entries)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
+ if (slots >= entries) return 0;
+ udelay(1);
+ }
+ return -EBUSY;
+}
+
+static int r128_do_wait_for_idle(drm_device_t *dev)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int i, ret;
+
+ if (!(ret = r128_do_wait_for_fifo(dev, 64))) return ret;
+
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
+ (void)r128_do_pixcache_flush(dev);
+ return 0;
+ }
+ udelay(1);
+ }
+ return -EBUSY;
+}
+
+int r128_do_engine_reset(drm_device_t *dev)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
+
+ (void)r128_do_pixcache_flush(dev);
+
+ clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX);
+ mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL);
+
+ R128_WRITE_PLL(R128_MCLK_CNTL,
+ mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CPP);
+
+ gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL);
+
+ R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
+ (void)R128_READ(R128_GEN_RESET_CNTL);
+ R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
+ (void)R128_READ(R128_GEN_RESET_CNTL);
+
+ R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl);
+ R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
+ R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl);
+
+ /* For CCE ring buffer only */
+ if (dev_priv->cce_is_bm_mode) {
+ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
+ R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
+ *dev_priv->ring_read_ptr = 0;
+ dev_priv->sarea_priv->ring_write = 0;
+ }
+
+ /* Reset the CCE mode */
+ (void)r128_do_wait_for_idle(dev);
+ R128_WRITE(R128_PM4_BUFFER_CNTL,
+ dev_priv->cce_mode | dev_priv->ring_sizel2qw);
+ (void)R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */
+ R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
+
+ r128_mark_vertbufs_done(dev);
+ return 0;
+}
+
+int r128_eng_reset(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+
+ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
+ dev->lock.pid != current->pid) {
+ DRM_ERROR("r128_eng_reset called without holding the lock\n");
+ return -EINVAL;
+ }
+
+ return r128_do_engine_reset(dev);
+}
+
+static int r128_do_engine_flush(drm_device_t *dev)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ u32 tmp;
+
+ tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR);
+ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp | R128_PM4_BUFFER_DL_DONE);
+
+ return 0;
+}
+
+int r128_eng_flush(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+
+ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
+ dev->lock.pid != current->pid) {
+ DRM_ERROR("r128_eng_flush called without holding the lock\n");
+ return -EINVAL;
+ }
+
+ return r128_do_engine_flush(dev);
+}
+
+static int r128_do_cce_wait_for_fifo(drm_device_t *dev, int entries)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ int slots = R128_READ(R128_PM4_STAT) & R128_PM4_FIFOCNT_MASK;
+ if (slots >= entries) return 0;
+ udelay(1);
+ }
+ return -EBUSY;
+}
+
+int r128_do_cce_wait_for_idle(drm_device_t *dev)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ if (dev_priv->cce_is_bm_mode) {
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ if (*dev_priv->ring_read_ptr == dev_priv->sarea_priv->ring_write) {
+ int pm4stat = R128_READ(R128_PM4_STAT);
+ if ((pm4stat & R128_PM4_FIFOCNT_MASK) >= dev_priv->cce_fifo_size &&
+ !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) {
+ return r128_do_pixcache_flush(dev);
+ }
+ }
+ udelay(1);
+ }
+ return -EBUSY;
+ } else {
+ int ret = r128_do_cce_wait_for_fifo(dev, dev_priv->cce_fifo_size);
+ if (ret < 0) return ret;
+
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ int pm4stat = R128_READ(R128_PM4_STAT);
+ if (!(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) {
+ return r128_do_pixcache_flush(dev);
+ }
+ udelay(1);
+ }
+ return -EBUSY;
+ }
+}
+
+int r128_cce_idle(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+
+ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
+ dev->lock.pid != current->pid) {
+ DRM_ERROR("r128_wait_idle called without holding the lock\n");
+ return -EINVAL;
+ }
+
+ return r128_do_cce_wait_for_idle(dev);
+}
+
+static int r128_submit_packets_ring_secure(drm_device_t *dev,
+ u32 *commands, int *count)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int write = dev_priv->sarea_priv->ring_write;
+ int *write_ptr = dev_priv->ring_start + write;
+ int c = *count;
+ u32 tmp = 0;
+ int psize = 0;
+ int writing = 1;
+ int timeout;
+
+ while (c > 0) {
+ tmp = *commands++;
+ if (!psize) {
+ writing = 1;
+
+ if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) {
+ if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) {
+ if ((tmp & R128_CCE_PACKET0_REG_MASK) !=
+ (R128_PM4_VC_FPU_SETUP >> 2)) {
+ writing = 0;
+ }
+ }
+ psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
+ } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) {
+ if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) {
+ if ((tmp & R128_CCE_PACKET1_REG0_MASK) !=
+ (R128_PM4_VC_FPU_SETUP >> 2)) {
+ writing = 0;
+ }
+ } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <=
+ (0x1004 << 9)) {
+ if ((tmp & R128_CCE_PACKET1_REG1_MASK) !=
+ (R128_PM4_VC_FPU_SETUP << 9)) {
+ writing = 0;
+ }
+ }
+ psize = 3;
+ } else {
+ psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
+ }
+ }
+ psize--;
+
+ if (writing) {
+ write++;
+ *write_ptr++ = tmp;
+ }
+ if (write >= dev_priv->ring_entries) {
+ write = 0;
+ write_ptr = dev_priv->ring_start;
+ }
+ timeout = 0;
+ while (write == *dev_priv->ring_read_ptr) {
+ (void)R128_READ(R128_PM4_BUFFER_DL_RPTR);
+ if (timeout++ >= dev_priv->usec_timeout)
+ return -EBUSY;
+ udelay(1);
+ }
+ c--;
+ }
+
+ if (write < 32)
+ memcpy(dev_priv->ring_end,
+ dev_priv->ring_start,
+ write * sizeof(u32));
+
+ /* Make sure WC cache has been flushed */
+ r128_flush_write_combine();
+
+ dev_priv->sarea_priv->ring_write = write;
+ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, write);
+
+ *count = 0;
+
+ return 0;
+}
+
+static int r128_submit_packets_pio_secure(drm_device_t *dev,
+ u32 *commands, int *count)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ u32 tmp = 0;
+ int psize = 0;
+ int writing = 1;
+ int addr = R128_PM4_FIFO_DATA_EVEN;
+ int ret;
+
+ while (*count > 0) {
+ tmp = *commands++;
+ if (!psize) {
+ writing = 1;
+
+ if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) {
+ if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) {
+ if ((tmp & R128_CCE_PACKET0_REG_MASK) !=
+ (R128_PM4_VC_FPU_SETUP >> 2)) {
+ writing = 0;
+ }
+ }
+ psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
+ } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) {
+ if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) {
+ if ((tmp & R128_CCE_PACKET1_REG0_MASK) !=
+ (R128_PM4_VC_FPU_SETUP >> 2)) {
+ writing = 0;
+ }
+ } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <=
+ (0x1004 << 9)) {
+ if ((tmp & R128_CCE_PACKET1_REG1_MASK) !=
+ (R128_PM4_VC_FPU_SETUP << 9)) {
+ writing = 0;
+ }
+ }
+ psize = 3;
+ } else {
+ psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
+ }
+ }
+ psize--;
+
+ if (writing) {
+ if ((ret = r128_do_cce_wait_for_fifo(dev, 1)) < 0)
+ return ret;
+ R128_WRITE(addr, tmp);
+ addr ^= 0x0004;
+ }
+
+ *count -= 1;
+ }
+
+ if (addr == R128_PM4_FIFO_DATA_ODD) {
+ if ((ret = r128_do_cce_wait_for_fifo(dev, 1)) < 0) return ret;
+ R128_WRITE(addr, R128_CCE_PACKET2);
+ }
+
+ return 0;
+}
+
+static int r128_submit_packets_ring(drm_device_t *dev,
+ u32 *commands, int *count)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int write = dev_priv->sarea_priv->ring_write;
+ int *write_ptr = dev_priv->ring_start + write;
+ int c = *count;
+ int timeout;
+
+ while (c > 0) {
+ write++;
+ *write_ptr++ = *commands++;
+ if (write >= dev_priv->ring_entries) {
+ write = 0;
+ write_ptr = dev_priv->ring_start;
+ }
+ timeout = 0;
+ while (write == *dev_priv->ring_read_ptr) {
+ (void)R128_READ(R128_PM4_BUFFER_DL_RPTR);
+ if (timeout++ >= dev_priv->usec_timeout)
+ return -EBUSY;
+ udelay(1);
+ }
+ c--;
+ }
+
+ if (write < 32)
+ memcpy(dev_priv->ring_end,
+ dev_priv->ring_start,
+ write * sizeof(u32));
+
+ /* Make sure WC cache has been flushed */
+ r128_flush_write_combine();
+
+ dev_priv->sarea_priv->ring_write = write;
+ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, write);
+
+ *count = 0;
+
+ return 0;
+}
+
+static int r128_submit_packets_pio(drm_device_t *dev,
+ u32 *commands, int *count)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int ret;
+
+ while (*count > 1) {
+ if ((ret = r128_do_cce_wait_for_fifo(dev, 2)) < 0) return ret;
+ R128_WRITE(R128_PM4_FIFO_DATA_EVEN, *commands++);
+ R128_WRITE(R128_PM4_FIFO_DATA_ODD, *commands++);
+ *count -= 2;
+ }
+
+ if (*count) {
+ if ((ret = r128_do_cce_wait_for_fifo(dev, 2)) < 0) return ret;
+ R128_WRITE(R128_PM4_FIFO_DATA_EVEN, *commands++);
+ R128_WRITE(R128_PM4_FIFO_DATA_ODD, R128_CCE_PACKET2);
+ *count = 0;
+ }
+
+ return 0;
+}
+
+static int r128_do_submit_packets(drm_device_t *dev, u32 *buffer, int count)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int c = count;
+ int ret;
+
+ if (dev_priv->cce_is_bm_mode) {
+ int left = 0;
+
+ if (c >= dev_priv->ring_entries) {
+ c = dev_priv->ring_entries-1;
+ left = count - c;
+ }
+
+ /* Since this is only used by the kernel we can use the
+ insecure ring buffer submit packet routine */
+ ret = r128_submit_packets_ring(dev, buffer, &c);
+
+ c += left;
+ } else {
+ /* Since this is only used by the kernel we can use the
+ insecure PIO submit packet routine */
+ ret = r128_submit_packets_pio(dev, buffer, &c);
+ }
+
+ if (ret < 0) return ret;
+ else return c;
+}
+
+int r128_submit_pkt(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_packet_t packet;
+ u32 *buffer;
+ int c;
+ int size;
+ int ret = 0;
+
+ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
+ dev->lock.pid != current->pid) {
+ DRM_ERROR("r128_submit_pkt called without holding the lock\n");
+ return -EINVAL;
+ }
+
+ copy_from_user_ret(&packet, (drm_r128_packet_t *)arg, sizeof(packet),
+ -EFAULT);
+
+ c = packet.count;
+ size = c * sizeof(*buffer);
+
+ if (dev_priv->cce_is_bm_mode) {
+ int left = 0;
+
+ if (c >= dev_priv->ring_entries) {
+ c = dev_priv->ring_entries-1;
+ size = c * sizeof(*buffer);
+ left = packet.count - c;
+ }
+
+ if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM;
+ copy_from_user_ret(buffer, packet.buffer, size, -EFAULT);
+
+ if (dev_priv->cce_secure)
+ ret = r128_submit_packets_ring_secure(dev, buffer, &c);
+ else
+ ret = r128_submit_packets_ring(dev, buffer, &c);
+
+ c += left;
+ } else {
+ if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM;
+ copy_from_user_ret(buffer, packet.buffer, size, -EFAULT);
+
+ if (dev_priv->cce_secure)
+ ret = r128_submit_packets_pio_secure(dev, buffer, &c);
+ else
+ ret = r128_submit_packets_pio(dev, buffer, &c);
+ }
+
+ kfree(buffer);
+
+ packet.count = c;
+ copy_to_user_ret((drm_r128_packet_t *)arg, &packet, sizeof(packet),
+ -EFAULT);
+
+ if (ret) return ret;
+ else if (c > 0) return -EAGAIN;
+
+ return 0;
+}
+
+static int r128_send_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v)
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_buf_priv_t *buf_priv;
+ drm_buf_t *buf;
+ int i, ret;
+ u32 cce[2];
+
+ /* Make sure we have valid data */
+ for (i = 0; i < v->send_count; i++) {
+ int idx = v->send_indices[i];
+
+ 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->pid != current->pid) {
+ DRM_ERROR("Process %d using buffer owned by %d\n",
+ current->pid, buf->pid);
+ return -EINVAL;
+ }
+ if (buf->pending) {
+ DRM_ERROR("Sending pending buffer:"
+ " buffer %d, offset %d\n",
+ v->send_indices[i], i);
+ return -EINVAL;
+ }
+ }
+
+ /* Wait for idle, if we've wrapped to make sure that all pending
+ buffers have been processed */
+ if (dev_priv->submit_age == R128_MAX_VBUF_AGE) {
+ if ((ret = r128_do_cce_wait_for_idle(dev)) < 0) return ret;
+ dev_priv->submit_age = 0;
+ r128_mark_vertbufs_done(dev);
+ }
+
+ /* Make sure WC cache has been flushed (if in PIO mode) */
+ if (!dev_priv->cce_is_bm_mode) r128_flush_write_combine();
+
+ /* FIXME: Add support for sending vertex buffer to the CCE here
+ instead of in client code. The v->prim holds the primitive
+ type that should be drawn. Loop over the list buffers in
+ send_indices[] and submit a packet for each VB.
+
+ This will require us to loop over the clip rects here as
+ well, which implies that we extend the kernel driver to allow
+ cliprects to be stored here. Note that the cliprects could
+ possibly come from the X server instead of the client, but
+ this will require additional changes to the DRI to allow for
+ this optimization. */
+
+ /* Submit a CCE packet that writes submit_age to R128_VB_AGE_REG */
+ cce[0] = R128CCE0(R128_CCE_PACKET0, R128_VB_AGE_REG, 0);
+ cce[1] = dev_priv->submit_age;
+ if ((ret = r128_do_submit_packets(dev, cce, 2)) < 0) {
+ /* Until we add support for sending VBs to the CCE in
+ this routine, we can recover from this error. After
+ we add that support, we won't be able to easily
+ recover, so we will probably have to implement
+ another mechanism for handling timeouts from packets
+ submitted directly by the kernel. */
+ return ret;
+ }
+
+ /* Now that the submit packet request has succeeded, we can mark
+ the buffers as pending */
+ for (i = 0; i < v->send_count; i++) {
+ buf = dma->buflist[v->send_indices[i]];
+ buf->pending = 1;
+
+ buf_priv = buf->dev_private;
+ buf_priv->age = dev_priv->submit_age;
+ }
+
+ dev_priv->submit_age++;
+
+ return 0;
+}
+
+static drm_buf_t *r128_freelist_get(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_buf_priv_t *buf_priv;
+ drm_buf_t *buf;
+ int i, t;
+
+ /* FIXME: Optimize -- use freelist code */
+
+ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+ if (buf->pid == 0) return buf;
+ }
+
+ for (t = 0; t < dev_priv->usec_timeout; t++) {
+ u32 done_age = R128_READ(R128_VB_AGE_REG);
+
+ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+ if (buf->pending && buf_priv->age <= done_age) {
+ /* The buffer has been processed, so it
+ can now be used */
+ buf->pending = 0;
+ return buf;
+ }
+ }
+ udelay(1);
+ }
+
+ return NULL;
+}
+
+
+static int r128_get_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v)
+{
+ drm_buf_t *buf;
+ int i;
+
+ for (i = v->granted_count; i < v->request_count; i++) {
+ buf = r128_freelist_get(dev);
+ if (!buf) break;
+ buf->pid = current->pid;
+ copy_to_user_ret(&v->request_indices[i],
+ &buf->idx,
+ sizeof(buf->idx),
+ -EFAULT);
+ copy_to_user_ret(&v->request_sizes[i],
+ &buf->total,
+ sizeof(buf->total),
+ -EFAULT);
+ ++v->granted_count;
+ }
+ return 0;
+}
+
+int r128_vertex_buf(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ int retcode = 0;
+ drm_r128_vertex_t v;
+
+ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
+ dev->lock.pid != current->pid) {
+ DRM_ERROR("r128_vertex_buf called without holding the lock\n");
+ return -EINVAL;
+ }
+
+ if (!dev_priv || dev_priv->is_pci) {
+ DRM_ERROR("r128_vertex_buf called with a PCI card\n");
+ return -EINVAL;
+ }
+
+ copy_from_user_ret(&v, (drm_r128_vertex_t *)arg, sizeof(v), -EFAULT);
+ DRM_DEBUG("%d: %d send, %d req\n",
+ current->pid, v.send_count, v.request_count);
+
+ if (v.send_count < 0 || v.send_count > dma->buf_count) {
+ DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
+ current->pid, v.send_count, dma->buf_count);
+ return -EINVAL;
+ }
+ if (v.request_count < 0 || v.request_count > dma->buf_count) {
+ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+ current->pid, v.request_count, dma->buf_count);
+ return -EINVAL;
+ }
+
+ if (v.send_count) {
+ retcode = r128_send_vertbufs(dev, &v);
+ }
+
+ v.granted_count = 0;
+
+ if (!retcode && v.request_count) {
+ retcode = r128_get_vertbufs(dev, &v);
+ }
+
+ DRM_DEBUG("%d returning, granted = %d\n",
+ current->pid, v.granted_count);
+ copy_to_user_ret((drm_r128_vertex_t *)arg, &v, sizeof(v), -EFAULT);
+
+ return retcode;
+}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drm.h
new file mode 100644
index 000000000..fa90d72db
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drm.h
@@ -0,0 +1,111 @@
+/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-
+ * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Authors: Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ * $XFree86$
+ */
+
+#ifndef _R128_DRM_H_
+#define _R128_DRM_H_
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmR128.h)
+ */
+typedef struct drm_r128_init {
+ enum {
+ R128_INIT_CCE = 0x01,
+ R128_CLEANUP_CCE = 0x02
+ } func;
+ int sarea_priv_offset;
+ int is_pci;
+ int cce_mode;
+ int cce_fifo_size;
+ int cce_secure;
+ int ring_size;
+ int usec_timeout;
+
+ int fb_offset;
+ int agp_ring_offset;
+ int agp_read_ptr_offset;
+ int agp_vertbufs_offset;
+ int agp_indbufs_offset;
+ int agp_textures_offset;
+ int mmio_offset;
+} drm_r128_init_t;
+
+typedef struct drm_r128_packet {
+ unsigned long *buffer;
+ int count;
+ int flags;
+} drm_r128_packet_t;
+
+typedef enum drm_r128_prim {
+ _DRM_R128_PRIM_NONE = 0x0001,
+ _DRM_R128_PRIM_POINT = 0x0002,
+ _DRM_R128_PRIM_LINE = 0x0004,
+ _DRM_R128_PRIM_POLY_LINE = 0x0008,
+ _DRM_R128_PRIM_TRI_LIST = 0x0010,
+ _DRM_R128_PRIM_TRI_FAN = 0x0020,
+ _DRM_R128_PRIM_TRI_STRIP = 0x0040,
+ _DRM_R128_PRIM_TRI_TYPE2 = 0x0080
+} drm_r128_prim_t;
+
+typedef struct drm_r128_vertex {
+ /* Indices here refer to the offset into
+ buflist in drm_buf_get_t. */
+ int send_count; /* Number of buffers to send */
+ int *send_indices; /* List of handles to buffers */
+ int *send_sizes; /* Lengths of data to send */
+ drm_r128_prim_t prim; /* Primitive type */
+ int request_count; /* Number of buffers requested */
+ int *request_indices; /* Buffer information */
+ int *request_sizes;
+ int granted_count; /* Number of buffers granted */
+} drm_r128_vertex_t;
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (r128_sarea.h)
+ */
+#define R128_LOCAL_TEX_HEAP 0
+#define R128_AGP_TEX_HEAP 1
+#define R128_NR_TEX_HEAPS 2
+#define R128_NR_TEX_REGIONS 64
+#define R128_LOG_TEX_GRANULARITY 16
+
+typedef struct drm_tex_region {
+ unsigned char next, prev;
+ unsigned char in_use;
+ int age;
+} drm_tex_region_t;
+
+typedef struct drm_r128_sarea {
+ drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
+ int tex_age[R128_NR_TEX_HEAPS];
+ int ctx_owner;
+ int ring_write;
+} drm_r128_sarea_t;
+
+#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.c
new file mode 100644
index 000000000..45ade1def
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.c
@@ -0,0 +1,737 @@
+/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
+ * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ * $XFree86$
+ *
+ */
+
+#define EXPORT_SYMTAB
+#include "drmP.h"
+#include "r128_drv.h"
+EXPORT_SYMBOL(r128_init);
+EXPORT_SYMBOL(r128_cleanup);
+
+#define R128_NAME "r128"
+#define R128_DESC "r128"
+#define R128_DATE "20000422"
+#define R128_MAJOR 0
+#define R128_MINOR 0
+#define R128_PATCHLEVEL 5
+
+static drm_device_t r128_device;
+drm_ctx_t r128_res_ctx;
+
+static struct file_operations r128_fops = {
+ open: r128_open,
+ flush: drm_flush,
+ release: r128_release,
+ ioctl: r128_ioctl,
+ mmap: drm_mmap,
+ read: drm_read,
+ fasync: drm_fasync,
+ poll: drm_poll,
+};
+
+static struct miscdevice r128_misc = {
+ minor: MISC_DYNAMIC_MINOR,
+ name: R128_NAME,
+ fops: &r128_fops,
+};
+
+static drm_ioctl_desc_t r128_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { r128_version, 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 },
+
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { r128_addbufs, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { r128_mapbufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { r128_addctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { r128_rmctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { r128_modctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { r128_getctx, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { r128_switchctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { r128_newctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { r128_resctx, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { r128_lock, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { r128_unlock, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
+
+#ifdef DRM_AGP
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
+#endif
+
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_init_cce, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_eng_reset, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_FLUSH)] = { r128_eng_flush, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_submit_pkt, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_CCEIDL)] = { r128_cce_idle, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_vertex_buf, 1, 0 },
+};
+#define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls)
+
+#ifdef MODULE
+int init_module(void);
+void cleanup_module(void);
+static char *r128 = NULL;
+
+MODULE_AUTHOR("Precision Insight, Inc., Cedar Park, Texas.");
+MODULE_DESCRIPTION("r128");
+MODULE_PARM(r128, "s");
+
+/* init_module is called when insmod is used to load the module */
+
+int init_module(void)
+{
+ return r128_init();
+}
+
+/* cleanup_module is called when rmmod is used to unload the module */
+
+void cleanup_module(void)
+{
+ r128_cleanup();
+}
+#endif
+
+#ifndef MODULE
+/* r128_setup is called by the kernel to parse command-line options passed
+ * via the boot-loader (e.g., LILO). It calls the insmod option routine,
+ * drm_parse_drm.
+ *
+ * This is not currently supported, since it requires changes to
+ * linux/init/main.c. */
+
+
+void __init r128_setup(char *str, int *ints)
+{
+ if (ints[0] != 0) {
+ DRM_ERROR("Illegal command line format, ignored\n");
+ return;
+ }
+ drm_parse_options(str);
+}
+#endif
+
+static int r128_setup(drm_device_t *dev)
+{
+ int i;
+
+ atomic_set(&dev->ioctl_count, 0);
+ atomic_set(&dev->vma_count, 0);
+ dev->buf_use = 0;
+ atomic_set(&dev->buf_alloc, 0);
+
+ drm_dma_setup(dev);
+
+ atomic_set(&dev->total_open, 0);
+ atomic_set(&dev->total_close, 0);
+ atomic_set(&dev->total_ioctl, 0);
+ atomic_set(&dev->total_irq, 0);
+ atomic_set(&dev->total_ctx, 0);
+ atomic_set(&dev->total_locks, 0);
+ atomic_set(&dev->total_unlocks, 0);
+ atomic_set(&dev->total_contends, 0);
+ atomic_set(&dev->total_sleeps, 0);
+
+ for (i = 0; i < DRM_HASH_SIZE; i++) {
+ dev->magiclist[i].head = NULL;
+ dev->magiclist[i].tail = NULL;
+ }
+ dev->maplist = NULL;
+ dev->map_count = 0;
+ dev->vmalist = NULL;
+ dev->lock.hw_lock = NULL;
+ init_waitqueue_head(&dev->lock.lock_queue);
+ dev->queue_count = 0;
+ dev->queue_reserved = 0;
+ dev->queue_slots = 0;
+ dev->queuelist = NULL;
+ dev->irq = 0;
+ 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_timer(&dev->timer);
+ init_waitqueue_head(&dev->context_wait);
+
+ dev->ctx_start = 0;
+ dev->lck_start = 0;
+
+ dev->buf_rp = dev->buf;
+ dev->buf_wp = dev->buf;
+ dev->buf_end = dev->buf + DRM_BSZ;
+ dev->buf_async = NULL;
+ init_waitqueue_head(&dev->buf_readers);
+ init_waitqueue_head(&dev->buf_writers);
+
+ r128_res_ctx.handle=-1;
+
+ 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;
+}
+
+
+static int r128_takedown(drm_device_t *dev)
+{
+ int i;
+ drm_magic_entry_t *pt, *next;
+ drm_map_t *map;
+ drm_vma_entry_t *vma, *vma_next;
+
+ DRM_DEBUG("\n");
+
+ down(&dev->struct_sem);
+ del_timer(&dev->timer);
+
+ if (dev->devname) {
+ drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
+ dev->devname = NULL;
+ }
+
+ if (dev->unique) {
+ drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
+ dev->unique = NULL;
+ dev->unique_len = 0;
+ }
+ /* Clear pid list */
+ for (i = 0; i < DRM_HASH_SIZE; i++) {
+ for (pt = dev->magiclist[i].head; pt; pt = next) {
+ next = pt->next;
+ drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+ }
+ dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
+ }
+
+#ifdef DRM_AGP
+ /* Clear AGP information */
+ if (dev->agp) {
+ drm_agp_mem_t *entry;
+ drm_agp_mem_t *nexte;
+
+ /* Remove AGP resources, but leave dev->agp
+ intact until r128_cleanup is called. */
+ for (entry = dev->agp->memory; entry; entry = nexte) {
+ nexte = entry->next;
+ if (entry->bound) drm_unbind_agp(entry->memory);
+ drm_free_agp(entry->memory, entry->pages);
+ drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+ }
+ dev->agp->memory = NULL;
+
+ if (dev->agp->acquired && drm_agp.release)
+ (*drm_agp.release)();
+
+ dev->agp->acquired = 0;
+ dev->agp->enabled = 0;
+ }
+#endif
+
+ /* Clear vma list (only built for debugging) */
+ if (dev->vmalist) {
+ for (vma = dev->vmalist; vma; vma = vma_next) {
+ vma_next = vma->next;
+ drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
+ }
+ dev->vmalist = NULL;
+ }
+
+ /* Clear map area and mtrr information */
+ if (dev->maplist) {
+ for (i = 0; i < dev->map_count; i++) {
+ map = dev->maplist[i];
+ switch (map->type) {
+ case _DRM_REGISTERS:
+ case _DRM_FRAME_BUFFER:
+#ifdef CONFIG_MTRR
+ if (map->mtrr >= 0) {
+ int retcode;
+ retcode = mtrr_del(map->mtrr,
+ map->offset,
+ map->size);
+ DRM_DEBUG("mtrr_del = %d\n", retcode);
+ }
+#endif
+ drm_ioremapfree(map->handle, map->size);
+ break;
+ case _DRM_SHM:
+ drm_free_pages((unsigned long)map->handle,
+ drm_order(map->size)
+ - PAGE_SHIFT,
+ DRM_MEM_SAREA);
+ break;
+ case _DRM_AGP:
+ /* Do nothing here, because this is all
+ handled in the AGP/GART driver. */
+ break;
+ }
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ }
+ drm_free(dev->maplist,
+ dev->map_count * sizeof(*dev->maplist),
+ DRM_MEM_MAPS);
+ dev->maplist = NULL;
+ dev->map_count = 0;
+ }
+
+ drm_dma_takedown(dev);
+
+ dev->queue_count = 0;
+ if (dev->lock.hw_lock) {
+ dev->lock.hw_lock = NULL; /* SHM removed */
+ dev->lock.pid = 0;
+ wake_up_interruptible(&dev->lock.lock_queue);
+ }
+ up(&dev->struct_sem);
+
+ return 0;
+}
+
+/* r128_init is called via init_module at module load time, or via
+ * linux/init/main.c (this is not currently supported). */
+
+int r128_init(void)
+{
+ int retcode;
+ drm_device_t *dev = &r128_device;
+
+ DRM_DEBUG("\n");
+
+ memset((void *)dev, 0, sizeof(*dev));
+ dev->count_lock = SPIN_LOCK_UNLOCKED;
+ sema_init(&dev->struct_sem, 1);
+
+#ifdef MODULE
+ drm_parse_options(r128);
+#endif
+
+ if ((retcode = misc_register(&r128_misc))) {
+ DRM_ERROR("Cannot register \"%s\"\n", R128_NAME);
+ return retcode;
+ }
+ dev->device = MKDEV(MISC_MAJOR, r128_misc.minor);
+ dev->name = R128_NAME;
+
+ drm_mem_init();
+ drm_proc_init(dev);
+
+#ifdef DRM_AGP
+ dev->agp = drm_agp_init();
+
+#ifdef CONFIG_MTRR
+ dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base,
+ dev->agp->agp_info.aper_size*1024*1024,
+ MTRR_TYPE_WRCOMB,
+ 1);
+#endif
+#endif
+
+ if((retcode = drm_ctxbitmap_init(dev))) {
+ DRM_ERROR("Cannot allocate memory for context bitmap.\n");
+ drm_proc_cleanup();
+ misc_deregister(&r128_misc);
+ r128_takedown(dev);
+ return retcode;
+ }
+
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+ R128_NAME,
+ R128_MAJOR,
+ R128_MINOR,
+ R128_PATCHLEVEL,
+ R128_DATE,
+ r128_misc.minor);
+
+ return 0;
+}
+
+/* r128_cleanup is called via cleanup_module at module unload time. */
+
+void r128_cleanup(void)
+{
+ drm_device_t *dev = &r128_device;
+
+ DRM_DEBUG("\n");
+
+ drm_proc_cleanup();
+ if (misc_deregister(&r128_misc)) {
+ DRM_ERROR("Cannot unload module\n");
+ } else {
+ DRM_INFO("Module unloaded\n");
+ }
+ drm_ctxbitmap_cleanup(dev);
+ r128_takedown(dev);
+#ifdef DRM_AGP
+ if (dev->agp) {
+ /* FIXME -- free other information, too */
+ drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
+ dev->agp = NULL;
+ }
+#endif
+}
+
+int r128_version(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_version_t version;
+ int len;
+
+ copy_from_user_ret(&version,
+ (drm_version_t *)arg,
+ sizeof(version),
+ -EFAULT);
+
+#define DRM_COPY(name,value) \
+ len = strlen(value); \
+ if (len > name##_len) len = name##_len; \
+ name##_len = strlen(value); \
+ if (len && name) { \
+ copy_to_user_ret(name, value, len, -EFAULT); \
+ }
+
+ version.version_major = R128_MAJOR;
+ version.version_minor = R128_MINOR;
+ version.version_patchlevel = R128_PATCHLEVEL;
+
+ DRM_COPY(version.name, R128_NAME);
+ DRM_COPY(version.date, R128_DATE);
+ DRM_COPY(version.desc, R128_DESC);
+
+ copy_to_user_ret((drm_version_t *)arg,
+ &version,
+ sizeof(version),
+ -EFAULT);
+ return 0;
+}
+
+int r128_open(struct inode *inode, struct file *filp)
+{
+ drm_device_t *dev = &r128_device;
+ int retcode = 0;
+
+ DRM_DEBUG("open_count = %d\n", dev->open_count);
+ if (!(retcode = drm_open_helper(inode, filp, dev))) {
+ MOD_INC_USE_COUNT;
+ atomic_inc(&dev->total_open);
+ spin_lock(&dev->count_lock);
+ if (!dev->open_count++) {
+ spin_unlock(&dev->count_lock);
+ return r128_setup(dev);
+ }
+ spin_unlock(&dev->count_lock);
+ }
+ return retcode;
+}
+
+int r128_release(struct inode *inode, struct file *filp)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ int retcode = 0;
+
+ DRM_DEBUG("open_count = %d\n", dev->open_count);
+ if (!(retcode = drm_release(inode, filp))) {
+ MOD_DEC_USE_COUNT;
+ atomic_inc(&dev->total_close);
+ spin_lock(&dev->count_lock);
+ if (!--dev->open_count) {
+ if (atomic_read(&dev->ioctl_count) || dev->blocked) {
+ DRM_ERROR("Device busy: %d %d\n",
+ atomic_read(&dev->ioctl_count),
+ dev->blocked);
+ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ spin_unlock(&dev->count_lock);
+ return r128_takedown(dev);
+ }
+ spin_unlock(&dev->count_lock);
+ }
+ return retcode;
+}
+
+/* r128_ioctl is called whenever a process performs an ioctl on /dev/drm. */
+
+int r128_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int nr = DRM_IOCTL_NR(cmd);
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ int retcode = 0;
+ drm_ioctl_desc_t *ioctl;
+ drm_ioctl_t *func;
+
+ atomic_inc(&dev->ioctl_count);
+ atomic_inc(&dev->total_ioctl);
+ ++priv->ioctl_count;
+
+ DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n",
+ current->pid, cmd, nr, dev->device, priv->authenticated);
+
+ if (nr >= R128_IOCTL_COUNT) {
+ retcode = -EINVAL;
+ } else {
+ ioctl = &r128_ioctls[nr];
+ func = ioctl->func;
+
+ if (!func) {
+ DRM_DEBUG("no function\n");
+ retcode = -EINVAL;
+ } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
+ || (ioctl->auth_needed && !priv->authenticated)) {
+ retcode = -EACCES;
+ } else {
+ retcode = (func)(inode, filp, cmd, arg);
+ }
+ }
+
+ atomic_dec(&dev->ioctl_count);
+ return retcode;
+}
+
+int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ DECLARE_WAITQUEUE(entry, current);
+ int ret = 0;
+ drm_lock_t lock;
+#if DRM_DMA_HISTOGRAM
+ cycles_t start;
+
+ dev->lck_start = start = get_cycles();
+#endif
+
+ copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+
+ if (lock.context == DRM_KERNEL_CONTEXT) {
+ DRM_ERROR("Process %d using kernel context %d\n",
+ current->pid, lock.context);
+ return -EINVAL;
+ }
+
+ DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+ lock.context, current->pid, dev->lock.hw_lock->lock,
+ lock.flags);
+
+#if 0
+ /* dev->queue_count == 0 right now for
+ r128. FIXME? */
+ if (lock.context < 0 || lock.context >= dev->queue_count)
+ return -EINVAL;
+#endif
+
+ if (!ret) {
+#if 0
+ if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
+ != lock.context) {
+ long j = jiffies - dev->lock.lock_time;
+
+ if (lock.context == r128_res_ctx.handle &&
+ j >= 0 && j < DRM_LOCK_SLICE) {
+ /* Can't take lock if we just had it and
+ there is contention. */
+ DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n",
+ lock.context, current->pid, j,
+ dev->lock.lock_time, jiffies);
+ current->state = TASK_INTERRUPTIBLE;
+ current->policy |= SCHED_YIELD;
+ schedule_timeout(DRM_LOCK_SLICE-j);
+ DRM_DEBUG("jiffies=%d\n", jiffies);
+ }
+ }
+#endif
+ add_wait_queue(&dev->lock.lock_queue, &entry);
+ for (;;) {
+ if (!dev->lock.hw_lock) {
+ /* Device has been unregistered */
+ ret = -EINTR;
+ break;
+ }
+ if (drm_lock_take(&dev->lock.hw_lock->lock,
+ lock.context)) {
+ dev->lock.pid = current->pid;
+ dev->lock.lock_time = jiffies;
+ atomic_inc(&dev->total_locks);
+ break; /* Got lock */
+ }
+
+ /* Contention */
+ atomic_inc(&dev->total_sleeps);
+ current->state = TASK_INTERRUPTIBLE;
+#if 1
+ current->policy |= SCHED_YIELD;
+#endif
+ schedule();
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev->lock.lock_queue, &entry);
+ }
+
+#if 0
+ if (!ret && dev->last_context != lock.context &&
+ lock.context != r128_res_ctx.handle &&
+ dev->last_context != r128_res_ctx.handle) {
+ add_wait_queue(&dev->context_wait, &entry);
+ current->state = TASK_INTERRUPTIBLE;
+ /* PRE: dev->last_context != lock.context */
+ r128_context_switch(dev, dev->last_context, lock.context);
+ /* POST: we will wait for the context
+ switch and will dispatch on a later call
+ when dev->last_context == lock.context
+ NOTE WE HOLD THE LOCK THROUGHOUT THIS
+ TIME! */
+ current->policy |= SCHED_YIELD;
+ schedule();
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev->context_wait, &entry);
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ } else if (dev->last_context != lock.context) {
+ DRM_ERROR("Context mismatch: %d %d\n",
+ dev->last_context, lock.context);
+ }
+ }
+#endif
+
+ if (!ret) {
+ if (lock.flags & _DRM_LOCK_READY) {
+ /* Wait for space in DMA/FIFO */
+ }
+ if (lock.flags & _DRM_LOCK_QUIESCENT) {
+ /* Make hardware quiescent */
+#if 0
+ r128_quiescent(dev);
+#endif
+ }
+ }
+
+#if 0
+ DRM_ERROR("pid = %5d, old counter = %5ld\n",
+ current->pid, current->counter);
+#endif
+ if (lock.context != r128_res_ctx.handle) {
+ current->counter = 5;
+ current->priority = DEF_PRIORITY/4;
+ }
+#if 0
+ while (current->counter > 25)
+ current->counter >>= 1; /* decrease time slice */
+ DRM_ERROR("pid = %5d, new counter = %5ld\n",
+ current->pid, current->counter);
+#endif
+ DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
+
+#if DRM_DMA_HISTOGRAM
+ atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
+#endif
+
+ return ret;
+}
+
+
+int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_lock_t lock;
+
+ copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+
+ if (lock.context == DRM_KERNEL_CONTEXT) {
+ DRM_ERROR("Process %d using kernel context %d\n",
+ current->pid, lock.context);
+ return -EINVAL;
+ }
+
+ DRM_DEBUG("%d frees lock (%d holds)\n",
+ lock.context,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+ atomic_inc(&dev->total_unlocks);
+ if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
+ atomic_inc(&dev->total_contends);
+ drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
+ /* FIXME: Try to send data to card here */
+ if (!dev->context_flag) {
+ if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ DRM_ERROR("\n");
+ }
+ }
+
+#if 0
+ current->policy |= SCHED_YIELD;
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1000);
+#endif
+
+ if (lock.context != r128_res_ctx.handle) {
+ current->counter = 5;
+ current->priority = DEF_PRIORITY;
+ }
+#if 0
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(10);
+#endif
+
+ return 0;
+}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.h
new file mode 100644
index 000000000..3b888c493
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.h
@@ -0,0 +1,226 @@
+/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
+ * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ * $XFree86$
+ *
+ */
+
+#ifndef _R128_DRV_H_
+#define _R128_DRV_H_
+
+typedef struct drm_r128_private {
+ int is_pci;
+
+ int cce_mode;
+ int cce_fifo_size;
+ int cce_is_bm_mode;
+ int cce_secure;
+
+ drm_r128_sarea_t *sarea_priv;
+
+ __volatile__ u32 *ring_read_ptr;
+
+ u32 *ring_start;
+ u32 *ring_end;
+ int ring_size;
+ int ring_sizel2qw;
+ int ring_entries;
+
+ int submit_age;
+
+ int usec_timeout;
+
+ drm_map_t *sarea;
+ drm_map_t *fb;
+ drm_map_t *agp_ring;
+ drm_map_t *agp_read_ptr;
+ drm_map_t *agp_vertbufs;
+ drm_map_t *agp_indbufs;
+ drm_map_t *agp_textures;
+ drm_map_t *mmio;
+} drm_r128_private_t;
+
+typedef struct drm_r128_buf_priv {
+ u32 age;
+} drm_r128_buf_priv_t;
+
+ /* r128_drv.c */
+extern int r128_init(void);
+extern void r128_cleanup(void);
+extern int r128_version(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_open(struct inode *inode, struct file *filp);
+extern int r128_release(struct inode *inode, struct file *filp);
+extern int r128_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_lock(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_unlock(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+ /* r128_dma.c */
+extern int r128_init_cce(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_eng_reset(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_eng_flush(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_submit_pkt(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_cce_idle(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_vertex_buf(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+ /* r128_bufs.c */
+extern int r128_addbufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_mapbufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+ /* r128_context.c */
+extern int r128_resctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_addctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_modctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_getctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_switchctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_newctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int r128_rmctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+extern int r128_context_switch(drm_device_t *dev, int old, int new);
+extern int r128_context_switch_complete(drm_device_t *dev, int new);
+
+
+/* Register definitions, register access macros and drmAddMap constants
+ * for Rage 128 kernel driver.
+ */
+
+#define R128_PC_NGUI_CTLSTAT 0x0184
+# define R128_PC_FLUSH_ALL 0x00ff
+# define R128_PC_BUSY (1 << 31)
+
+#define R128_CLOCK_CNTL_INDEX 0x0008
+#define R128_CLOCK_CNTL_DATA 0x000c
+# define R128_PLL_WR_EN (1 << 7)
+
+#define R128_MCLK_CNTL 0x000f
+# define R128_FORCE_GCP (1 << 16)
+# define R128_FORCE_PIPE3D_CPP (1 << 17)
+
+#define R128_GEN_RESET_CNTL 0x00f0
+# define R128_SOFT_RESET_GUI (1 << 0)
+
+#define R128_PM4_BUFFER_CNTL 0x0704
+# define R128_PM4_NONPM4 (0 << 28)
+# define R128_PM4_192PIO (1 << 28)
+# define R128_PM4_192BM (2 << 28)
+# define R128_PM4_128PIO_64INDBM (3 << 28)
+# define R128_PM4_128BM_64INDBM (4 << 28)
+# define R128_PM4_64PIO_128INDBM (5 << 28)
+# define R128_PM4_64BM_128INDBM (6 << 28)
+# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28)
+# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28)
+# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
+
+
+#define R128_PM4_BUFFER_DL_RPTR 0x0710
+#define R128_PM4_BUFFER_DL_WPTR 0x0714
+# define R128_PM4_BUFFER_DL_DONE (1 << 31)
+
+#define R128_PM4_VC_FPU_SETUP 0x071c
+
+#define R128_PM4_STAT 0x07b8
+# define R128_PM4_FIFOCNT_MASK 0x0fff
+# define R128_PM4_BUSY (1 << 16)
+# define R128_PM4_GUI_ACTIVE (1 << 31)
+
+#define R128_PM4_BUFFER_ADDR 0x07f0
+#define R128_PM4_MICRO_CNTL 0x07fc
+# define R128_PM4_MICRO_FREERUN (1 << 30)
+
+#define R128_PM4_FIFO_DATA_EVEN 0x1000
+#define R128_PM4_FIFO_DATA_ODD 0x1004
+
+#define R128_GUI_SCRATCH_REG0 0x15e0
+#define R128_GUI_SCRATCH_REG1 0x15e4
+#define R128_GUI_SCRATCH_REG2 0x15e8
+#define R128_GUI_SCRATCH_REG3 0x15ec
+#define R128_GUI_SCRATCH_REG4 0x15f0
+#define R128_GUI_SCRATCH_REG5 0x15f4
+
+#define R128_GUI_STAT 0x1740
+# define R128_GUI_FIFOCNT_MASK 0x0fff
+# define R128_GUI_ACTIVE (1 << 31)
+
+
+/* CCE command packets */
+#define R128_CCE_PACKET0 0x00000000
+#define R128_CCE_PACKET1 0x40000000
+#define R128_CCE_PACKET2 0x80000000
+# define R128_CCE_PACKET_MASK 0xC0000000
+# define R128_CCE_PACKET_COUNT_MASK 0x3fff0000
+# define R128_CCE_PACKET0_REG_MASK 0x000007ff
+# define R128_CCE_PACKET1_REG0_MASK 0x000007ff
+# define R128_CCE_PACKET1_REG1_MASK 0x003ff800
+
+
+#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */
+
+
+#define R128_BASE(reg) ((u32)(dev_priv->mmio->handle))
+#define R128_ADDR(reg) (R128_BASE(reg) + reg)
+
+#define R128_DEREF(reg) *(__volatile__ int *)R128_ADDR(reg)
+#define R128_READ(reg) R128_DEREF(reg)
+#define R128_WRITE(reg,val) do { R128_DEREF(reg) = val; } while (0)
+
+#define R128_DEREF8(reg) *(__volatile__ char *)R128_ADDR(reg)
+#define R128_READ8(reg) R128_DEREF8(reg)
+#define R128_WRITE8(reg,val) do { R128_DEREF8(reg) = val; } while (0)
+
+#define R128_WRITE_PLL(addr,val) \
+do { \
+ R128_WRITE8(R128_CLOCK_CNTL_INDEX, ((addr) & 0x1f) | R128_PLL_WR_EN); \
+ R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \
+} while (0)
+
+extern int R128_READ_PLL(drm_device_t *dev, int addr);
+
+#define R128CCE0(p,r,n) ((p) | ((n) << 16) | ((r) >> 2))
+#define R128CCE1(p,r1,r2) ((p) | (((r2) >> 2) << 11) | ((r1) >> 2))
+#define R128CCE2(p) ((p))
+#define R128CCE3(p,n) ((p) | ((n) << 16))
+
+#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c
index 85470ac52..9c2cea56a 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c
@@ -1,8 +1,7 @@
/* vm.c -- Memory mapping for DRM -*- linux-c -*-
* Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com
- * Revised: Mon Feb 14 00:16:45 2000 by kevin@precisioninsight.com
*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -246,13 +245,26 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
/* 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_MAYWRITE;
+#if defined(__i386__)
+ 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) {
case _DRM_FRAME_BUFFER:
case _DRM_REGISTERS:
+ case _DRM_AGP:
if (VM_OFFSET(vma) >= __pa(high_memory)) {
#if defined(__i386__)
- if (boot_cpu_data.x86 > 3) {
+ if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
}
@@ -264,6 +276,10 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
+ DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
+ " offset = 0x%lx\n",
+ map->type,
+ vma->vm_start, vma->vm_end, VM_OFFSET(vma));
vma->vm_ops = &drm_vm_ops;
break;
case _DRM_SHM:
@@ -276,19 +292,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
return -EINVAL; /* This should never happen. */
}
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
- if (map->flags & _DRM_READ_ONLY) {
-#if defined(__i386__)
- 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
- }
-
#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
/* In Linux 2.2.3 and above, this is
handled in do_mmap() in mm/mmap.c. */
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c
index 3b0f98acd..2e3c9b431 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c
@@ -1,8 +1,7 @@
/* xf86drm.c -- User-level interface to DRM device
* Created: Tue Jan 5 08:16:21 1999 by faith@precisioninsight.com
- * Revised: Sun Feb 13 23:43:32 2000 by kevin@precisioninsight.com
*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -24,6 +23,8 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
+ * Author: Rickard E. (Rik) Faith <faith@precisioninsight.com>
+ *
* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.10 2000/02/23 04:47:23 martin Exp $
*
*/
@@ -143,7 +144,7 @@ static int drm_open(const char *file)
return -errno;
}
-/* drmAvailable looks for /proc/drm, and returns 1 if it is present. */
+/* drmAvailable looks for /proc/dri, and returns 1 if it is present. */
int drmAvailable(void)
{
@@ -217,6 +218,20 @@ static int drmOpenByName(const char *name)
group = xf86ConfigDRI.group ? xf86ConfigDRI.group : DRM_DEV_GID;
#endif
+#if defined(XFree86Server)
+ if (!drmAvailable()) {
+ /* try to load the kernel module now */
+ if (!xf86LoadKernelModule(name)) {
+ ErrorF("[drm] failed to load kernel module \"%s\"\n",
+ name);
+ return -1;
+ }
+ }
+#else
+ if (!drmAvailable())
+ return -1;
+#endif
+
if (!geteuid()) {
dirmode = mode;
if (dirmode & S_IRUSR) dirmode |= S_IXUSR;
@@ -418,7 +433,8 @@ int drmAddMap(int fd,
return 0;
}
-int drmAddBufs(int fd, int count, int size, int flags)
+int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
+ int agp_offset)
{
drm_buf_desc_t request;
@@ -427,6 +443,8 @@ int drmAddBufs(int fd, int count, int size, int flags)
request.low_mark = 0;
request.high_mark = 0;
request.flags = flags;
+ request.agp_start = agp_offset;
+
if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno;
return request.count;
}
@@ -744,6 +762,143 @@ int drmDestroyDrawable(int fd, drmDrawable handle)
return 0;
}
+int drmAgpAcquire(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno;
+ return 0;
+}
+
+int drmAgpRelease(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno;
+ return 0;
+}
+
+int drmAgpEnable(int fd, unsigned long mode)
+{
+ drm_agp_mode_t m;
+
+ m.mode = mode;
+ if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno;
+ return 0;
+}
+
+int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
+ unsigned long *address, unsigned long *handle)
+{
+ drm_agp_buffer_t b;
+ *handle = 0;
+ b.size = size;
+ b.handle = 0;
+ b.type = type;
+ if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno;
+ if (address != 0UL) *address = b.physical;
+ *handle = b.handle;
+ return 0;
+}
+
+int drmAgpFree(int fd, unsigned long handle)
+{
+ drm_agp_buffer_t b;
+
+ b.size = 0;
+ b.handle = handle;
+ if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno;
+ return 0;
+}
+
+int drmAgpBind(int fd, unsigned long handle, unsigned long offset)
+{
+ drm_agp_binding_t b;
+
+ b.handle = handle;
+ b.offset = offset;
+ if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b)) return -errno;
+ return 0;
+}
+
+int drmAgpUnbind(int fd, unsigned long handle)
+{
+ drm_agp_binding_t b;
+
+ b.handle = handle;
+ b.offset = 0;
+ if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno;
+ return 0;
+}
+
+int drmAgpVersionMajor(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+ return i.agp_version_major;
+}
+
+int drmAgpVersionMinor(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+ return i.agp_version_minor;
+}
+
+unsigned long drmAgpGetMode(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.mode;
+}
+
+unsigned long drmAgpBase(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.aperture_base;
+}
+
+unsigned long drmAgpSize(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.aperture_size;
+}
+
+unsigned long drmAgpMemoryUsed(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.memory_used;
+}
+
+unsigned long drmAgpMemoryAvail(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.memory_allowed;
+}
+
+unsigned int drmAgpVendorId(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.id_vendor;
+}
+
+unsigned int drmAgpDeviceId(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.id_device;
+}
+
int drmError(int err, const char *label)
{
switch (err) {
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmI810.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmI810.c
new file mode 100644
index 000000000..b2489eeed
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmI810.c
@@ -0,0 +1,87 @@
+#ifdef XFree86Server
+# include "xf86.h"
+# include "xf86_OSproc.h"
+# include "xf86_ansic.h"
+# include "xf86Priv.h"
+# define _DRM_MALLOC xalloc
+# define _DRM_FREE xfree
+# ifndef XFree86LOADER
+# include <sys/stat.h>
+# include <sys/mman.h>
+# endif
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+# include <string.h>
+# include <ctype.h>
+# include <fcntl.h>
+# include <errno.h>
+# include <signal.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/ioctl.h>
+# include <sys/mman.h>
+# include <sys/time.h>
+# ifdef DRM_USE_MALLOC
+# define _DRM_MALLOC malloc
+# define _DRM_FREE free
+extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *);
+extern int xf86RemoveSIGIOHandler(int fd);
+# else
+# include <Xlibint.h>
+# define _DRM_MALLOC Xmalloc
+# define _DRM_FREE Xfree
+# endif
+#endif
+
+/* Not all systems have MAP_FAILED defined */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#include <sys/sysmacros.h> /* for makedev() */
+#include "xf86drm.h"
+#include "xf86drmI810.h"
+#include "drm.h"
+
+Bool drmI810CleanupDma(int driSubFD)
+{
+ drm_i810_init_t init;
+
+ memset(&init, 0, sizeof(drm_i810_init_t));
+ init.func = I810_CLEANUP_DMA;
+
+ if(ioctl(driSubFD, DRM_IOCTL_I810_INIT, &init)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Bool drmI810InitDma(int driSubFD, drmI810Init *info)
+{
+ drm_i810_init_t init;
+
+ memset(&init, 0, sizeof(drm_i810_init_t));
+
+ init.func = I810_INIT_DMA;
+ init.ring_map_idx = info->ring_map_idx;
+ init.buffer_map_idx = info->buffer_map_idx;
+ init.ring_start = info->start;
+ init.ring_end = info->end;
+ init.ring_size = info->size;
+ init.sarea_priv_offset = info->sarea_off;
+ init.front_offset = info->front_offset;
+ init.back_offset = info->back_offset;
+ init.depth_offset = info->depth_offset;
+ init.w = info->w;
+ init.h = info->h;
+ init.pitch = info->pitch;
+ init.pitch_bits = info->pitch_bits;
+
+ if(ioctl(driSubFD, DRM_IOCTL_I810_INIT, &init)) {
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmR128.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmR128.c
new file mode 100644
index 000000000..99f267f3d
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmR128.c
@@ -0,0 +1,199 @@
+/* xf86drmR128.c -- User-level interface to Rage 128 DRM device
+ * Created: Sun Apr 9 18:13:54 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Author: Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ * $XFree86$
+ *
+ */
+
+#ifdef XFree86Server
+# include "xf86.h"
+# include "xf86_OSproc.h"
+# include "xf86_ansic.h"
+# include "xf86Priv.h"
+# define _DRM_MALLOC xalloc
+# define _DRM_FREE xfree
+# ifndef XFree86LOADER
+# include <sys/stat.h>
+# include <sys/mman.h>
+# endif
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+# include <string.h>
+# include <ctype.h>
+# include <fcntl.h>
+# include <errno.h>
+# include <signal.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/ioctl.h>
+# include <sys/mman.h>
+# include <sys/time.h>
+# ifdef DRM_USE_MALLOC
+# define _DRM_MALLOC malloc
+# define _DRM_FREE free
+extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *);
+extern int xf86RemoveSIGIOHandler(int fd);
+# else
+# include <Xlibint.h>
+# define _DRM_MALLOC Xmalloc
+# define _DRM_FREE Xfree
+# endif
+#endif
+
+/* Not all systems have MAP_FAILED defined */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#include <sys/sysmacros.h> /* for makedev() */
+#include "xf86drm.h"
+#include "xf86drmR128.h"
+#include "drm.h"
+
+int drmR128InitCCE(int fd, drmR128Init *info)
+{
+ drm_r128_init_t init;
+
+ memset(&init, 0, sizeof(drm_r128_init_t));
+
+ init.func = R128_INIT_CCE;
+ init.sarea_priv_offset = info->sarea_priv_offset;
+ init.is_pci = info->is_pci;
+ init.cce_mode = info->cce_mode;
+ init.cce_fifo_size = info->cce_fifo_size;
+ init.cce_secure = info->cce_secure;
+ init.ring_size = info->ring_size;
+ init.usec_timeout = info->usec_timeout;
+
+ init.fb_offset = info->fb_offset;
+ init.agp_ring_offset = info->agp_ring_offset;
+ init.agp_read_ptr_offset = info->agp_read_ptr_offset;
+ init.agp_vertbufs_offset = info->agp_vertbufs_offset;
+ init.agp_indbufs_offset = info->agp_indbufs_offset;
+ init.agp_textures_offset = info->agp_textures_offset;
+ init.mmio_offset = info->mmio_offset;
+
+ if (ioctl(fd, DRM_IOCTL_R128_INIT, &init)) return -errno;
+
+ return 0;
+}
+
+int drmR128CleanupCCE(int fd)
+{
+ drm_r128_init_t init;
+
+ memset(&init, 0, sizeof(drm_r128_init_t));
+
+ init.func = R128_CLEANUP_CCE;
+
+ if (ioctl(fd, DRM_IOCTL_R128_INIT, &init)) return -errno;
+
+ return 0;
+}
+
+int drmR128EngineReset(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_R128_RESET, NULL)) return -errno;
+
+ return 0;
+}
+
+int drmR128EngineFlush(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_R128_FLUSH, NULL)) return -errno;
+
+ return 0;
+}
+
+int drmR128CCEWaitForIdle(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_R128_CCEIDL, NULL)) return -errno;
+
+ return 0;
+}
+
+int drmR128SubmitPackets(int fd, CARD32 *buffer, int *count, int flags)
+{
+ drm_r128_packet_t packet;
+ int ret;
+
+ memset(&packet, 0, sizeof(drm_r128_packet_t));
+
+ packet.count = *count;
+ packet.flags = flags;
+
+ while (packet.count > 0) {
+ packet.buffer = buffer + (*count - packet.count);
+ ret = ioctl(fd, DRM_IOCTL_R128_PACKET, &packet);
+ if (ret < 0 && ret != -EAGAIN) {
+ *count = packet.count;
+ return -errno;
+ }
+ }
+
+ *count = 0;
+ return 0;
+}
+
+int drmR128GetVertexBuffers(int fd, int count, int *indices, int *sizes)
+{
+ drm_r128_vertex_t v;
+
+ v.send_count = 0;
+ v.send_indices = NULL;
+ v.send_sizes = NULL;
+ v.prim = DRM_R128_PRIM_NONE;
+ v.request_count = count;
+ v.request_indices = indices;
+ v.request_sizes = sizes;
+ v.granted_count = 0;
+
+ if (ioctl(fd, DRM_IOCTL_R128_VERTEX, &v)) return -errno;
+
+ return v.granted_count;
+}
+
+int drmR128FlushVertexBuffers(int fd, int count, int *indices,
+ int *sizes, drmR128PrimType prim)
+{
+ drm_r128_vertex_t v;
+
+ v.send_count = count;
+ v.send_indices = indices;
+ v.send_sizes = sizes;
+ v.prim = prim;
+ v.request_count = 0;
+ v.request_indices = NULL;
+ v.request_sizes = NULL;
+ v.granted_count = 0;
+
+ if (ioctl(fd, DRM_IOCTL_R128_VERTEX, &v) < 0) return -errno;
+
+ return 0;
+}
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h
index 3af5d5b1e..c63d0f637 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h
@@ -1,8 +1,7 @@
/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
- * Revised: Mon Feb 14 00:15:23 2000 by kevin@precisioninsight.com
*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -71,9 +70,10 @@ typedef struct drm_clip_rect {
unsigned short y2;
} drm_clip_rect_t;
-/* Seperate include files for the i810/mga specific structures */
+/* Seperate include files for the i810/mga/r128 specific structures */
#include "mga_drm.h"
#include "i810_drm.h"
+#include "r128_drm.h"
typedef struct drm_version {
int version_major; /* Major version */
@@ -341,12 +341,23 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t)
#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t)
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x45, drm_lock_t )
+#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
/* I810 specific ioctls */
#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t)
#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t)
-#define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t)
+#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t)
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
+#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46)
+
+/* Rage 128 specific ioctls */
+#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
+#define DRM_IOCTL_R128_RESET DRM_IO( 0x41)
+#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42)
+#define DRM_IOCTL_R128_CCEIDL DRM_IO( 0x43)
+#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t)
+#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t)
#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h
index 61287e3e2..372ba595e 100644
--- a/xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h
+++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h
@@ -1,8 +1,7 @@
/* xf86drm.h -- OS-independent header for DRM user-level library interface
* Created: Tue Jan 5 08:17:23 1999 by faith@precisioninsight.com
- * Revised: Sun Feb 13 23:46:21 2000 by kevin@precisioninsight.com
*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -24,6 +23,8 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
+ * Author: Rickard E. (Rik) Faith <faith@precisioninsight.com>
+ *
* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v 1.7 2000/02/23 04:47:21 martin Exp $
*
*/
@@ -65,7 +66,8 @@ typedef struct _drmVersion {
typedef enum {
DRM_FRAME_BUFFER = 0, /* WC, no caching, no core dump */
DRM_REGISTERS = 1, /* no caching, no core dump */
- DRM_SHM = 2 /* shared, cached */
+ DRM_SHM = 2, /* shared, cached */
+ DRM_AGP = 3 /* AGP/GART */
} drmMapType;
typedef enum {
@@ -95,6 +97,11 @@ typedef enum { /* These values *MUST* match drm.h */
} drmDMAFlags;
typedef enum {
+ DRM_PAGE_ALIGN = 0x01,
+ DRM_AGP_BUFFER = 0x02
+} drmBufDescFlags;
+
+typedef enum {
DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */
DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */
DRM_LOCK_FLUSH = 0x04, /* Flush this context's DMA queue first */
@@ -196,7 +203,7 @@ typedef struct { unsigned int a[100]; } __drm_dummy_lock_t;
#endif
#ifndef DRM_CAS
-#define DRM_CAS(lock,old,new,ret) /* FAST LOCK FAILS */
+#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */
#endif
#define DRM_LIGHT_LOCK(fd,lock,context) \
@@ -291,7 +298,9 @@ extern int drmAddMap(int fd,
drmMapType type,
drmMapFlags flags,
drmHandlePtr handle);
-extern int drmAddBufs(int fd, int count, int size, int flags);
+extern int drmAddBufs(int fd, int count, int size,
+ drmBufDescFlags flags,
+ int agp_offset);
extern int drmMarkBufs(int fd, double low, double high);
extern int drmCreateContext(int fd, drmContextPtr handle);
extern int drmSetContextFlags(int fd, drmContext context,
@@ -332,6 +341,29 @@ extern int drmGetLock(int fd,
extern int drmUnlock(int fd, drmContext context);
extern int drmFinish(int fd, int context, drmLockFlags flags);
+/* AGP/GART support: X server (root) only */
+extern int drmAgpAcquire(int fd);
+extern int drmAgpRelease(int fd);
+extern int drmAgpEnable(int fd, unsigned long mode);
+extern int drmAgpAlloc(int fd, unsigned long size,
+ unsigned long type, unsigned long *address,
+ unsigned long *handle);
+extern int drmAgpFree(int fd, unsigned long handle);
+extern int drmAgpBind(int fd, unsigned long handle,
+ unsigned long offset);
+extern int drmAgpUnbind(int fd, unsigned long handle);
+
+/* AGP/GART info: authenticated client and/or X */
+extern int drmAgpVersionMajor(int fd);
+extern int drmAgpVersionMinor(int fd);
+extern unsigned long drmAgpGetMode(int fd);
+extern unsigned long drmAgpBase(int fd); /* Physical location */
+extern unsigned long drmAgpSize(int fd); /* Bytes */
+extern unsigned long drmAgpMemoryUsed(int fd);
+extern unsigned long drmAgpMemoryAvail(int fd);
+extern unsigned int drmAgpVendorId(int fd);
+extern unsigned int drmAgpDeviceId(int fd);
+
/* Support routines */
extern int drmError(int err, const char *label);
extern void *drmMalloc(int size);
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmI810.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmI810.h
new file mode 100644
index 000000000..6c11b7a10
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmI810.h
@@ -0,0 +1,46 @@
+
+/* WARNING: If you change any of these defines, make sure to change
+ * the kernel include file as well (i810_drm.h)
+ */
+
+#ifndef _XF86DRI_I810_H_
+#define _XF86DRI_I810_H_
+
+#ifndef _I810_DEFINES_
+#define _I810_DEFINES_
+#define I810_USE_BATCH 1
+
+#define I810_DMA_BUF_ORDER 12
+#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER)
+#define I810_DMA_BUF_NR 256
+
+#define I810_NR_SAREA_CLIPRECTS 8
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define I810_NR_TEX_REGIONS 64
+#define I810_LOG_MIN_TEX_REGION_SIZE 16
+#endif
+
+typedef struct _drmI810Init {
+ unsigned int start;
+ unsigned int end;
+ unsigned int size;
+ int ring_map_idx;
+ int buffer_map_idx;
+ int sarea_off;
+
+ unsigned int front_offset;
+ unsigned int back_offset;
+ unsigned int depth_offset;
+ unsigned int w;
+ unsigned int h;
+ unsigned int pitch;
+ unsigned int pitch_bits;
+} drmI810Init;
+
+
+Bool drmI810CleanupDma(int driSubFD);
+Bool drmI810InitDma(int driSubFD, drmI810Init *info );
+
+#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmMga.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmMga.h
new file mode 100644
index 000000000..3b0e4a6fc
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmMga.h
@@ -0,0 +1,147 @@
+
+/* WARNING: If you change any of these defines, make sure to change
+ * the kernel include file as well (mga_drm.h)
+ */
+
+#ifndef _XF86DRI_MGA_H_
+#define _XF86DRI_MGA_H_
+#ifndef _MGA_DEFINES_
+#define _MGA_DEFINES_
+#define MGA_F 0x1 /* fog */
+#define MGA_A 0x2 /* alpha */
+#define MGA_S 0x4 /* specular */
+#define MGA_T2 0x8 /* multitexture */
+
+#define MGA_WARP_TGZ 0
+#define MGA_WARP_TGZF (MGA_F)
+#define MGA_WARP_TGZA (MGA_A)
+#define MGA_WARP_TGZAF (MGA_F|MGA_A)
+#define MGA_WARP_TGZS (MGA_S)
+#define MGA_WARP_TGZSF (MGA_S|MGA_F)
+#define MGA_WARP_TGZSA (MGA_S|MGA_A)
+#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A)
+#define MGA_WARP_T2GZ (MGA_T2)
+#define MGA_WARP_T2GZF (MGA_T2|MGA_F)
+#define MGA_WARP_T2GZA (MGA_T2|MGA_A)
+#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F)
+#define MGA_WARP_T2GZS (MGA_T2|MGA_S)
+#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F)
+#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A)
+#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A)
+
+#define MGA_MAX_G400_PIPES 16
+#define MGA_MAX_G200_PIPES 8 /* no multitex */
+
+#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES
+
+#define MGA_CARD_TYPE_G200 1
+#define MGA_CARD_TYPE_G400 2
+#define MGA_FRONT 0x1
+#define MGA_BACK 0x2
+#define MGA_DEPTH 0x4
+
+/* 3d state excluding texture units:
+ */
+#define MGA_CTXREG_DSTORG 0 /* validated */
+#define MGA_CTXREG_MACCESS 1
+#define MGA_CTXREG_PLNWT 2
+#define MGA_CTXREG_DWGCTL 3
+#define MGA_CTXREG_ALPHACTRL 4
+#define MGA_CTXREG_FOGCOLOR 5
+#define MGA_CTXREG_WFLAG 6
+#define MGA_CTXREG_TDUAL0 7
+#define MGA_CTXREG_TDUAL1 8
+#define MGA_CTXREG_FCOL 9
+#define MGA_CTX_SETUP_SIZE 10
+
+/* 2d state
+ */
+#define MGA_2DREG_PITCH 0
+#define MGA_2D_SETUP_SIZE 1
+
+/* Each texture unit has a state:
+ */
+#define MGA_TEXREG_CTL 0
+#define MGA_TEXREG_CTL2 1
+#define MGA_TEXREG_FILTER 2
+#define MGA_TEXREG_BORDERCOL 3
+#define MGA_TEXREG_ORG 4 /* validated */
+#define MGA_TEXREG_ORG1 5
+#define MGA_TEXREG_ORG2 6
+#define MGA_TEXREG_ORG3 7
+#define MGA_TEXREG_ORG4 8
+#define MGA_TEXREG_WIDTH 9
+#define MGA_TEXREG_HEIGHT 10
+#define MGA_TEX_SETUP_SIZE 11
+
+/* What needs to be changed for the current vertex dma buffer?
+ */
+#define MGA_UPLOAD_CTX 0x1
+#define MGA_UPLOAD_TEX0 0x2
+#define MGA_UPLOAD_TEX1 0x4
+#define MGA_UPLOAD_PIPE 0x8
+#define MGA_UPLOAD_TEX0IMAGE 0x10
+#define MGA_UPLOAD_TEX1IMAGE 0x20
+#define MGA_UPLOAD_2D 0x40
+#define MGA_WAIT_AGE 0x80 /* handled client-side */
+#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */
+#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock
+ quiescent */
+
+/* 32 buffers of 64k each, total 1 meg.
+ */
+#define MGA_DMA_BUF_ORDER 16
+#define MGA_DMA_BUF_SZ (1<<MGA_DMA_BUF_ORDER)
+#define MGA_DMA_BUF_NR 31
+
+/* Keep these small for testing.
+ */
+#define MGA_NR_SAREA_CLIPRECTS 8
+
+/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
+ * regions, subject to a minimum region size of (1<<16) == 64k.
+ *
+ * Clients may subdivide regions internally, but when sharing between
+ * clients, the region size is the minimum granularity.
+ */
+
+#define MGA_CARD_HEAP 0
+#define MGA_AGP_HEAP 1
+#define MGA_NR_TEX_HEAPS 2
+#define MGA_NR_TEX_REGIONS 16
+#define MGA_LOG_MIN_TEX_REGION_SIZE 16
+#endif
+
+typedef struct _drmMgaWarpIndex {
+ int installed;
+ unsigned long phys_addr;
+ int size;
+} drmMgaWarpIndex;
+
+typedef struct _drmMgaInit {
+ int reserved_map_agpstart;
+ int reserved_map_idx;
+ int buffer_map_idx;
+ int sarea_priv_offset;
+ int primary_size;
+ int warp_ucode_size;
+ unsigned int frontOffset;
+ unsigned int backOffset;
+ unsigned int depthOffset;
+ unsigned int textureOffset;
+ unsigned int textureSize;
+ unsigned int agpTextureSize;
+ unsigned int agpTextureOffset;
+ unsigned int cpp;
+ unsigned int stride;
+ int sgram;
+ int chipset;
+ drmMgaWarpIndex WarpIndex[MGA_MAX_WARP_PIPES];
+ unsigned int mAccess;
+} drmMgaInit;
+
+
+Bool drmMgaCleanupDma(int driSubFD);
+Bool drmMgaLockUpdate(int driSubFD, drmLockFlags flags);
+Bool drmMgaInitDma(int driSubFD, drmMgaInit *info);
+#endif
diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h
new file mode 100644
index 000000000..46898a53c
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h
@@ -0,0 +1,80 @@
+/* xf86drm.h -- OS-independent header for DRM user-level library interface
+ * Created: Sun Apr 9 18:16:28 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ * Author: Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ * $XFree86$
+ *
+ */
+
+#ifndef _XF86DRI_R128_H_
+#define _XF86DRI_R128_H_
+
+/* WARNING: If you change any of these defines, make sure to change
+ * the kernel include file as well (r128_drm.h)
+ */
+
+typedef struct _drmR128Init {
+ int sarea_priv_offset;
+ int is_pci;
+ int cce_mode;
+ int cce_fifo_size;
+ int cce_secure;
+ int ring_size;
+ int usec_timeout;
+
+ int fb_offset;
+ int agp_ring_offset;
+ int agp_read_ptr_offset;
+ int agp_vertbufs_offset;
+ int agp_indbufs_offset;
+ int agp_textures_offset;
+ int mmio_offset;
+} drmR128Init;
+
+typedef enum {
+ DRM_R128_PRIM_NONE = 0x0001,
+ DRM_R128_PRIM_POINT = 0x0002,
+ DRM_R128_PRIM_LINE = 0x0004,
+ DRM_R128_PRIM_POLY_LINE = 0x0008,
+ DRM_R128_PRIM_TRI_LIST = 0x0010,
+ DRM_R128_PRIM_TRI_FAN = 0x0020,
+ DRM_R128_PRIM_TRI_STRIP = 0x0040,
+ DRM_R128_PRIM_TRI_TYPE2 = 0x0080
+} drmR128PrimType;
+
+
+extern int drmR128InitCCE(int fd, drmR128Init *info);
+extern int drmR128CleanupCCE(int fd);
+extern int drmR128EngineReset(int fd);
+extern int drmR128EngineFlush(int fd);
+extern int drmR128CCEWaitForIdle(int fd);
+extern int drmR128SubmitPackets(int fd, CARD32 *buffer, int *count, int flags);
+extern int drmR128GetVertexBuffers(int fd, int count, int *indices,
+ int *sizes);
+extern int drmR128FlushVertexBuffers(int fd, int count, int *indices,
+ int *sizes, drmR128PrimType prim);
+
+#endif