aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/drm
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/char/drm')
-rw-r--r--drivers/char/drm/Kconfig98
-rw-r--r--drivers/char/drm/Makefile33
-rw-r--r--drivers/char/drm/README.drm46
-rw-r--r--drivers/char/drm/ati_pcigart.c208
-rw-r--r--drivers/char/drm/drm.h675
-rw-r--r--drivers/char/drm/drmP.h1073
-rw-r--r--drivers/char/drm/drm_agpsupport.c448
-rw-r--r--drivers/char/drm/drm_auth.c230
-rw-r--r--drivers/char/drm/drm_bufs.c1270
-rw-r--r--drivers/char/drm/drm_context.c578
-rw-r--r--drivers/char/drm/drm_core.h34
-rw-r--r--drivers/char/drm/drm_dma.c180
-rw-r--r--drivers/char/drm/drm_drawable.c56
-rw-r--r--drivers/char/drm/drm_drv.c531
-rw-r--r--drivers/char/drm/drm_fops.c451
-rw-r--r--drivers/char/drm/drm_init.c52
-rw-r--r--drivers/char/drm/drm_ioctl.c370
-rw-r--r--drivers/char/drm/drm_irq.c370
-rw-r--r--drivers/char/drm/drm_lock.c303
-rw-r--r--drivers/char/drm/drm_memory.c181
-rw-r--r--drivers/char/drm/drm_memory.h197
-rw-r--r--drivers/char/drm/drm_memory_debug.h459
-rw-r--r--drivers/char/drm/drm_os_linux.h149
-rw-r--r--drivers/char/drm/drm_pci.c140
-rw-r--r--drivers/char/drm/drm_pciids.h224
-rw-r--r--drivers/char/drm/drm_proc.c539
-rw-r--r--drivers/char/drm/drm_sarea.h78
-rw-r--r--drivers/char/drm/drm_scatter.c231
-rw-r--r--drivers/char/drm/drm_stub.c319
-rw-r--r--drivers/char/drm/drm_sysfs.c208
-rw-r--r--drivers/char/drm/drm_vm.c678
-rw-r--r--drivers/char/drm/ffb_context.c551
-rw-r--r--drivers/char/drm/ffb_drv.c365
-rw-r--r--drivers/char/drm/ffb_drv.h286
-rw-r--r--drivers/char/drm/gamma_context.h492
-rw-r--r--drivers/char/drm/gamma_dma.c946
-rw-r--r--drivers/char/drm/gamma_drm.h90
-rw-r--r--drivers/char/drm/gamma_drv.c59
-rw-r--r--drivers/char/drm/gamma_drv.h147
-rw-r--r--drivers/char/drm/gamma_lists.h215
-rw-r--r--drivers/char/drm/gamma_lock.h140
-rw-r--r--drivers/char/drm/gamma_old_dma.h313
-rw-r--r--drivers/char/drm/i810_dma.c1385
-rw-r--r--drivers/char/drm/i810_drm.h289
-rw-r--r--drivers/char/drm/i810_drv.c126
-rw-r--r--drivers/char/drm/i810_drv.h236
-rw-r--r--drivers/char/drm/i830_dma.c1588
-rw-r--r--drivers/char/drm/i830_drm.h350
-rw-r--r--drivers/char/drm/i830_drv.c137
-rw-r--r--drivers/char/drm/i830_drv.h301
-rw-r--r--drivers/char/drm/i830_irq.c204
-rw-r--r--drivers/char/drm/i915_dma.c725
-rw-r--r--drivers/char/drm/i915_drm.h167
-rw-r--r--drivers/char/drm/i915_drv.c104
-rw-r--r--drivers/char/drm/i915_drv.h243
-rw-r--r--drivers/char/drm/i915_irq.c161
-rw-r--r--drivers/char/drm/i915_mem.c346
-rw-r--r--drivers/char/drm/mga_dma.c754
-rw-r--r--drivers/char/drm/mga_drm.h349
-rw-r--r--drivers/char/drm/mga_drv.c127
-rw-r--r--drivers/char/drm/mga_drv.h638
-rw-r--r--drivers/char/drm/mga_irq.c102
-rw-r--r--drivers/char/drm/mga_state.c1123
-rw-r--r--drivers/char/drm/mga_ucode.h11645
-rw-r--r--drivers/char/drm/mga_warp.c210
-rw-r--r--drivers/char/drm/r128_cce.c943
-rw-r--r--drivers/char/drm/r128_drm.h345
-rw-r--r--drivers/char/drm/r128_drv.c122
-rw-r--r--drivers/char/drm/r128_drv.h521
-rw-r--r--drivers/char/drm/r128_irq.c102
-rw-r--r--drivers/char/drm/r128_state.c1732
-rw-r--r--drivers/char/drm/radeon_cp.c2061
-rw-r--r--drivers/char/drm/radeon_drm.h659
-rw-r--r--drivers/char/drm/radeon_drv.c127
-rw-r--r--drivers/char/drm/radeon_drv.h1044
-rw-r--r--drivers/char/drm/radeon_irq.c251
-rw-r--r--drivers/char/drm/radeon_mem.c322
-rw-r--r--drivers/char/drm/radeon_state.c3102
-rw-r--r--drivers/char/drm/sis_drm.h42
-rw-r--r--drivers/char/drm/sis_drv.c110
-rw-r--r--drivers/char/drm/sis_drv.h52
-rw-r--r--drivers/char/drm/sis_ds.c301
-rw-r--r--drivers/char/drm/sis_ds.h145
-rw-r--r--drivers/char/drm/sis_mm.c417
-rw-r--r--drivers/char/drm/tdfx_drv.c107
-rw-r--r--drivers/char/drm/tdfx_drv.h50
86 files changed, 47878 insertions, 0 deletions
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
new file mode 100644
index 000000000000..d9a029934678
--- /dev/null
+++ b/drivers/char/drm/Kconfig
@@ -0,0 +1,98 @@
1#
2# Drm device configuration
3#
4# This driver provides support for the
5# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
6#
7config DRM
8 tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
9 depends on AGP || AGP=n
10 help
11 Kernel-level support for the Direct Rendering Infrastructure (DRI)
12 introduced in XFree86 4.0. If you say Y here, you need to select
13 the module that's right for your graphics card from the list below.
14 These modules provide support for synchronization, security, and
15 DMA transfers. Please see <http://dri.sourceforge.net/> for more
16 details. You should also select and configure AGP
17 (/dev/agpgart) support.
18
19config DRM_TDFX
20 tristate "3dfx Banshee/Voodoo3+"
21 depends on DRM && PCI
22 help
23 Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
24 graphics card. If M is selected, the module will be called tdfx.
25
26config DRM_GAMMA
27 tristate "3dlabs GMX 2000"
28 depends on DRM && BROKEN
29 help
30 This is the old gamma driver, please tell me if it might actually
31 work.
32
33config DRM_R128
34 tristate "ATI Rage 128"
35 depends on DRM && PCI
36 help
37 Choose this option if you have an ATI Rage 128 graphics card. If M
38 is selected, the module will be called r128. AGP support for
39 this card is strongly suggested (unless you have a PCI version).
40
41config DRM_RADEON
42 tristate "ATI Radeon"
43 depends on DRM && PCI
44 help
45 Choose this option if you have an ATI Radeon graphics card. There
46 are both PCI and AGP versions. You don't need to choose this to
47 run the Radeon in plain VGA mode. There is a product page at
48 <http://www.ati.com/na/pages/products/pc/radeon32/index.html>.
49 If M is selected, the module will be called radeon.
50
51config DRM_I810
52 tristate "Intel I810"
53 depends on DRM && AGP && AGP_INTEL
54 help
55 Choose this option if you have an Intel I810 graphics card. If M is
56 selected, the module will be called i810. AGP support is required
57 for this driver to work.
58
59choice
60 prompt "Intel 830M, 845G, 852GM, 855GM, 865G"
61 depends on DRM && AGP && AGP_INTEL
62 optional
63
64config DRM_I830
65 tristate "i830 driver"
66 help
67 Choose this option if you have a system that has Intel 830M, 845G,
68 852GM, 855GM or 865G integrated graphics. If M is selected, the
69 module will be called i830. AGP support is required for this driver
70 to work. This driver will eventually be replaced by the i915 one.
71
72config DRM_I915
73 tristate "i915 driver"
74 help
75 Choose this option if you have a system that has Intel 830M, 845G,
76 852GM, 855GM 865G or 915G integrated graphics. If M is selected, the
77 module will be called i915. AGP support is required for this driver
78 to work. This driver will eventually replace the I830 driver, when
79 later release of X start to use the new DDX and DRI.
80
81endchoice
82
83config DRM_MGA
84 tristate "Matrox g200/g400"
85 depends on DRM && AGP
86 help
87 Choose this option if you have a Matrox G200, G400 or G450 graphics
88 card. If M is selected, the module will be called mga. AGP
89 support is required for this driver to work.
90
91config DRM_SIS
92 tristate "SiS video cards"
93 depends on DRM && AGP
94 help
95 Choose this option if you have a SiS 630 or compatible video
96 chipset. If M is selected the module will be called sis. AGP
97 support is required for this driver to work.
98
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
new file mode 100644
index 000000000000..23ab26321e9a
--- /dev/null
+++ b/drivers/char/drm/Makefile
@@ -0,0 +1,33 @@
1#
2# Makefile for the drm device driver. This driver provides support for the
3# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
4
5drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
6 drm_drv.o drm_fops.o drm_init.o drm_ioctl.o drm_irq.o \
7 drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
8 drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
9 drm_sysfs.o
10
11gamma-objs := gamma_drv.o gamma_dma.o
12tdfx-objs := tdfx_drv.o
13r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
14mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
15i810-objs := i810_drv.o i810_dma.o
16i830-objs := i830_drv.o i830_dma.o i830_irq.o
17i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
18radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
19ffb-objs := ffb_drv.o ffb_context.o
20sis-objs := sis_drv.o sis_ds.o sis_mm.o
21
22obj-$(CONFIG_DRM) += drm.o
23obj-$(CONFIG_DRM_GAMMA) += gamma.o
24obj-$(CONFIG_DRM_TDFX) += tdfx.o
25obj-$(CONFIG_DRM_R128) += r128.o
26obj-$(CONFIG_DRM_RADEON)+= radeon.o
27obj-$(CONFIG_DRM_MGA) += mga.o
28obj-$(CONFIG_DRM_I810) += i810.o
29obj-$(CONFIG_DRM_I830) += i830.o
30obj-$(CONFIG_DRM_I915) += i915.o
31obj-$(CONFIG_DRM_FFB) += ffb.o
32obj-$(CONFIG_DRM_SIS) += sis.o
33
diff --git a/drivers/char/drm/README.drm b/drivers/char/drm/README.drm
new file mode 100644
index 000000000000..6441e01e587c
--- /dev/null
+++ b/drivers/char/drm/README.drm
@@ -0,0 +1,46 @@
1************************************************************
2* For the very latest on DRI development, please see: *
3* http://dri.sourceforge.net/ *
4************************************************************
5
6The Direct Rendering Manager (drm) is a device-independent kernel-level
7device driver that provides support for the XFree86 Direct Rendering
8Infrastructure (DRI).
9
10The DRM supports the Direct Rendering Infrastructure (DRI) in four major
11ways:
12
13 1. The DRM provides synchronized access to the graphics hardware via
14 the use of an optimized two-tiered lock.
15
16 2. The DRM enforces the DRI security policy for access to the graphics
17 hardware by only allowing authenticated X11 clients access to
18 restricted regions of memory.
19
20 3. The DRM provides a generic DMA engine, complete with multiple
21 queues and the ability to detect the need for an OpenGL context
22 switch.
23
24 4. The DRM is extensible via the use of small device-specific modules
25 that rely extensively on the API exported by the DRM module.
26
27
28Documentation on the DRI is available from:
29 http://precisioninsight.com/piinsights.html
30
31For specific information about kernel-level support, see:
32
33 The Direct Rendering Manager, Kernel Support for the Direct Rendering
34 Infrastructure
35 http://precisioninsight.com/dr/drm.html
36
37 Hardware Locking for the Direct Rendering Infrastructure
38 http://precisioninsight.com/dr/locking.html
39
40 A Security Analysis of the Direct Rendering Infrastructure
41 http://precisioninsight.com/dr/security.html
42
43************************************************************
44* For the very latest on DRI development, please see: *
45* http://dri.sourceforge.net/ *
46************************************************************
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
new file mode 100644
index 000000000000..fdca1876ecd5
--- /dev/null
+++ b/drivers/char/drm/ati_pcigart.c
@@ -0,0 +1,208 @@
1/**
2 * \file ati_pcigart.h
3 * ATI PCI GART support
4 *
5 * \author Gareth Hughes <gareth@valinux.com>
6 */
7
8/*
9 * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
10 *
11 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
12 * All Rights Reserved.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31 * DEALINGS IN THE SOFTWARE.
32 */
33
34#include "drmP.h"
35
36#if PAGE_SIZE == 65536
37# define ATI_PCIGART_TABLE_ORDER 0
38# define ATI_PCIGART_TABLE_PAGES (1 << 0)
39#elif PAGE_SIZE == 16384
40# define ATI_PCIGART_TABLE_ORDER 1
41# define ATI_PCIGART_TABLE_PAGES (1 << 1)
42#elif PAGE_SIZE == 8192
43# define ATI_PCIGART_TABLE_ORDER 2
44# define ATI_PCIGART_TABLE_PAGES (1 << 2)
45#elif PAGE_SIZE == 4096
46# define ATI_PCIGART_TABLE_ORDER 3
47# define ATI_PCIGART_TABLE_PAGES (1 << 3)
48#else
49# error - PAGE_SIZE not 64K, 16K, 8K or 4K
50#endif
51
52# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */
53# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
54
55unsigned long drm_ati_alloc_pcigart_table( void )
56{
57 unsigned long address;
58 struct page *page;
59 int i;
60 DRM_DEBUG( "%s\n", __FUNCTION__ );
61
62 address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
63 if ( address == 0UL ) {
64 return 0;
65 }
66
67 page = virt_to_page( address );
68
69 for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
70 get_page(page);
71 SetPageReserved( page );
72 }
73
74 DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
75 return address;
76}
77
78static void drm_ati_free_pcigart_table( unsigned long address )
79{
80 struct page *page;
81 int i;
82 DRM_DEBUG( "%s\n", __FUNCTION__ );
83
84 page = virt_to_page( address );
85
86 for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
87 __put_page(page);
88 ClearPageReserved( page );
89 }
90
91 free_pages( address, ATI_PCIGART_TABLE_ORDER );
92}
93
94int drm_ati_pcigart_cleanup( drm_device_t *dev,
95 unsigned long addr,
96 dma_addr_t bus_addr)
97{
98 drm_sg_mem_t *entry = dev->sg;
99 unsigned long pages;
100 int i;
101
102 /* we need to support large memory configurations */
103 if ( !entry ) {
104 DRM_ERROR( "no scatter/gather memory!\n" );
105 return 0;
106 }
107
108 if ( bus_addr ) {
109 pci_unmap_single(dev->pdev, bus_addr,
110 ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
111 PCI_DMA_TODEVICE);
112
113 pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
114 ? entry->pages : ATI_MAX_PCIGART_PAGES;
115
116 for ( i = 0 ; i < pages ; i++ ) {
117 if ( !entry->busaddr[i] ) break;
118 pci_unmap_single(dev->pdev, entry->busaddr[i],
119 PAGE_SIZE, PCI_DMA_TODEVICE);
120 }
121 }
122
123 if ( addr ) {
124 drm_ati_free_pcigart_table( addr );
125 }
126
127 return 1;
128}
129EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
130
131int drm_ati_pcigart_init( drm_device_t *dev,
132 unsigned long *addr,
133 dma_addr_t *bus_addr)
134{
135 drm_sg_mem_t *entry = dev->sg;
136 unsigned long address = 0;
137 unsigned long pages;
138 u32 *pci_gart, page_base, bus_address = 0;
139 int i, j, ret = 0;
140
141 if ( !entry ) {
142 DRM_ERROR( "no scatter/gather memory!\n" );
143 goto done;
144 }
145
146 address = drm_ati_alloc_pcigart_table();
147 if ( !address ) {
148 DRM_ERROR( "cannot allocate PCI GART page!\n" );
149 goto done;
150 }
151
152 if ( !dev->pdev ) {
153 DRM_ERROR( "PCI device unknown!\n" );
154 goto done;
155 }
156
157 bus_address = pci_map_single(dev->pdev, (void *)address,
158 ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
159 PCI_DMA_TODEVICE);
160 if (bus_address == 0) {
161 DRM_ERROR( "unable to map PCIGART pages!\n" );
162 drm_ati_free_pcigart_table( address );
163 address = 0;
164 goto done;
165 }
166
167 pci_gart = (u32 *)address;
168
169 pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
170 ? entry->pages : ATI_MAX_PCIGART_PAGES;
171
172 memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
173
174 for ( i = 0 ; i < pages ; i++ ) {
175 /* we need to support large memory configurations */
176 entry->busaddr[i] = pci_map_single(dev->pdev,
177 page_address( entry->pagelist[i] ),
178 PAGE_SIZE,
179 PCI_DMA_TODEVICE);
180 if (entry->busaddr[i] == 0) {
181 DRM_ERROR( "unable to map PCIGART pages!\n" );
182 drm_ati_pcigart_cleanup( dev, address, bus_address );
183 address = 0;
184 bus_address = 0;
185 goto done;
186 }
187 page_base = (u32) entry->busaddr[i];
188
189 for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
190 *pci_gart++ = cpu_to_le32( page_base );
191 page_base += ATI_PCIGART_PAGE_SIZE;
192 }
193 }
194
195 ret = 1;
196
197#if defined(__i386__) || defined(__x86_64__)
198 wbinvd();
199#else
200 mb();
201#endif
202
203done:
204 *addr = address;
205 *bus_addr = bus_address;
206 return ret;
207}
208EXPORT_SYMBOL(drm_ati_pcigart_init);
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
new file mode 100644
index 000000000000..587305282ea8
--- /dev/null
+++ b/drivers/char/drm/drm.h
@@ -0,0 +1,675 @@
1/**
2 * \file drm.h
3 * Header for the Direct Rendering Manager
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 *
7 * \par Acknowledgments:
8 * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
9 */
10
11/*
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All rights reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36
37#ifndef _DRM_H_
38#define _DRM_H_
39
40#if defined(__linux__)
41#include <linux/config.h>
42#include <asm/ioctl.h> /* For _IO* macros */
43#define DRM_IOCTL_NR(n) _IOC_NR(n)
44#define DRM_IOC_VOID _IOC_NONE
45#define DRM_IOC_READ _IOC_READ
46#define DRM_IOC_WRITE _IOC_WRITE
47#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE
48#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
49#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
50#if defined(__FreeBSD__) && defined(IN_MODULE)
51/* Prevent name collision when including sys/ioccom.h */
52#undef ioctl
53#include <sys/ioccom.h>
54#define ioctl(a,b,c) xf86ioctl(a,b,c)
55#else
56#include <sys/ioccom.h>
57#endif /* __FreeBSD__ && xf86ioctl */
58#define DRM_IOCTL_NR(n) ((n) & 0xff)
59#define DRM_IOC_VOID IOC_VOID
60#define DRM_IOC_READ IOC_OUT
61#define DRM_IOC_WRITE IOC_IN
62#define DRM_IOC_READWRITE IOC_INOUT
63#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
64#endif
65
66#define XFREE86_VERSION(major,minor,patch,snap) \
67 ((major << 16) | (minor << 8) | patch)
68
69#ifndef CONFIG_XFREE86_VERSION
70#define CONFIG_XFREE86_VERSION XFREE86_VERSION(4,1,0,0)
71#endif
72
73#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
74#define DRM_PROC_DEVICES "/proc/devices"
75#define DRM_PROC_MISC "/proc/misc"
76#define DRM_PROC_DRM "/proc/drm"
77#define DRM_DEV_DRM "/dev/drm"
78#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
79#define DRM_DEV_UID 0
80#define DRM_DEV_GID 0
81#endif
82
83#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
84#define DRM_MAJOR 226
85#define DRM_MAX_MINOR 15
86#endif
87#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */
88#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */
89#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
90#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */
91
92#define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */
93#define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */
94#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)
95#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
96#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
97
98
99typedef unsigned long drm_handle_t;
100typedef unsigned int drm_context_t;
101typedef unsigned int drm_drawable_t;
102typedef unsigned int drm_magic_t;
103
104
105/**
106 * Cliprect.
107 *
108 * \warning: If you change this structure, make sure you change
109 * XF86DRIClipRectRec in the server as well
110 *
111 * \note KW: Actually it's illegal to change either for
112 * backwards-compatibility reasons.
113 */
114typedef struct drm_clip_rect {
115 unsigned short x1;
116 unsigned short y1;
117 unsigned short x2;
118 unsigned short y2;
119} drm_clip_rect_t;
120
121
122/**
123 * Texture region,
124 */
125typedef struct drm_tex_region {
126 unsigned char next;
127 unsigned char prev;
128 unsigned char in_use;
129 unsigned char padding;
130 unsigned int age;
131} drm_tex_region_t;
132
133/**
134 * Hardware lock.
135 *
136 * The lock structure is a simple cache-line aligned integer. To avoid
137 * processor bus contention on a multiprocessor system, there should not be any
138 * other data stored in the same cache line.
139 */
140typedef struct drm_hw_lock {
141 __volatile__ unsigned int lock; /**< lock variable */
142 char padding[60]; /**< Pad to cache line */
143} drm_hw_lock_t;
144
145
146/**
147 * DRM_IOCTL_VERSION ioctl argument type.
148 *
149 * \sa drmGetVersion().
150 */
151typedef struct drm_version {
152 int version_major; /**< Major version */
153 int version_minor; /**< Minor version */
154 int version_patchlevel;/**< Patch level */
155 size_t name_len; /**< Length of name buffer */
156 char __user *name; /**< Name of driver */
157 size_t date_len; /**< Length of date buffer */
158 char __user *date; /**< User-space buffer to hold date */
159 size_t desc_len; /**< Length of desc buffer */
160 char __user *desc; /**< User-space buffer to hold desc */
161} drm_version_t;
162
163
164/**
165 * DRM_IOCTL_GET_UNIQUE ioctl argument type.
166 *
167 * \sa drmGetBusid() and drmSetBusId().
168 */
169typedef struct drm_unique {
170 size_t unique_len; /**< Length of unique */
171 char __user *unique; /**< Unique name for driver instantiation */
172} drm_unique_t;
173
174
175typedef struct drm_list {
176 int count; /**< Length of user-space structures */
177 drm_version_t __user *version;
178} drm_list_t;
179
180
181typedef struct drm_block {
182 int unused;
183} drm_block_t;
184
185
186/**
187 * DRM_IOCTL_CONTROL ioctl argument type.
188 *
189 * \sa drmCtlInstHandler() and drmCtlUninstHandler().
190 */
191typedef struct drm_control {
192 enum {
193 DRM_ADD_COMMAND,
194 DRM_RM_COMMAND,
195 DRM_INST_HANDLER,
196 DRM_UNINST_HANDLER
197 } func;
198 int irq;
199} drm_control_t;
200
201
202/**
203 * Type of memory to map.
204 */
205typedef enum drm_map_type {
206 _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
207 _DRM_REGISTERS = 1, /**< no caching, no core dump */
208 _DRM_SHM = 2, /**< shared, cached */
209 _DRM_AGP = 3, /**< AGP/GART */
210 _DRM_SCATTER_GATHER = 4 /**< Scatter/gather memory for PCI DMA */
211} drm_map_type_t;
212
213
214/**
215 * Memory mapping flags.
216 */
217typedef enum drm_map_flags {
218 _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
219 _DRM_READ_ONLY = 0x02,
220 _DRM_LOCKED = 0x04, /**< shared, cached, locked */
221 _DRM_KERNEL = 0x08, /**< kernel requires access */
222 _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
223 _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
224 _DRM_REMOVABLE = 0x40 /**< Removable mapping */
225} drm_map_flags_t;
226
227
228typedef struct drm_ctx_priv_map {
229 unsigned int ctx_id; /**< Context requesting private mapping */
230 void *handle; /**< Handle of map */
231} drm_ctx_priv_map_t;
232
233
234/**
235 * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
236 * argument type.
237 *
238 * \sa drmAddMap().
239 */
240typedef struct drm_map {
241 unsigned long offset; /**< Requested physical address (0 for SAREA)*/
242 unsigned long size; /**< Requested physical size (bytes) */
243 drm_map_type_t type; /**< Type of memory to map */
244 drm_map_flags_t flags; /**< Flags */
245 void *handle; /**< User-space: "Handle" to pass to mmap() */
246 /**< Kernel-space: kernel-virtual address */
247 int mtrr; /**< MTRR slot used */
248 /* Private data */
249} drm_map_t;
250
251
252/**
253 * DRM_IOCTL_GET_CLIENT ioctl argument type.
254 */
255typedef struct drm_client {
256 int idx; /**< Which client desired? */
257 int auth; /**< Is client authenticated? */
258 unsigned long pid; /**< Process ID */
259 unsigned long uid; /**< User ID */
260 unsigned long magic; /**< Magic */
261 unsigned long iocs; /**< Ioctl count */
262} drm_client_t;
263
264
265typedef enum {
266 _DRM_STAT_LOCK,
267 _DRM_STAT_OPENS,
268 _DRM_STAT_CLOSES,
269 _DRM_STAT_IOCTLS,
270 _DRM_STAT_LOCKS,
271 _DRM_STAT_UNLOCKS,
272 _DRM_STAT_VALUE, /**< Generic value */
273 _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */
274 _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */
275
276 _DRM_STAT_IRQ, /**< IRQ */
277 _DRM_STAT_PRIMARY, /**< Primary DMA bytes */
278 _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */
279 _DRM_STAT_DMA, /**< DMA */
280 _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
281 _DRM_STAT_MISSED /**< Missed DMA opportunity */
282
283 /* Add to the *END* of the list */
284} drm_stat_type_t;
285
286
287/**
288 * DRM_IOCTL_GET_STATS ioctl argument type.
289 */
290typedef struct drm_stats {
291 unsigned long count;
292 struct {
293 unsigned long value;
294 drm_stat_type_t type;
295 } data[15];
296} drm_stats_t;
297
298
299/**
300 * Hardware locking flags.
301 */
302typedef enum drm_lock_flags {
303 _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
304 _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
305 _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
306 _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
307 /* These *HALT* flags aren't supported yet
308 -- they will be used to support the
309 full-screen DGA-like mode. */
310 _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
311 _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
312} drm_lock_flags_t;
313
314
315/**
316 * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
317 *
318 * \sa drmGetLock() and drmUnlock().
319 */
320typedef struct drm_lock {
321 int context;
322 drm_lock_flags_t flags;
323} drm_lock_t;
324
325
326/**
327 * DMA flags
328 *
329 * \warning
330 * These values \e must match xf86drm.h.
331 *
332 * \sa drm_dma.
333 */
334typedef enum drm_dma_flags {
335 /* Flags for DMA buffer dispatch */
336 _DRM_DMA_BLOCK = 0x01, /**<
337 * Block until buffer dispatched.
338 *
339 * \note The buffer may not yet have
340 * been processed by the hardware --
341 * getting a hardware lock with the
342 * hardware quiescent will ensure
343 * that the buffer has been
344 * processed.
345 */
346 _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
347 _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
348
349 /* Flags for DMA buffer request */
350 _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
351 _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
352 _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
353} drm_dma_flags_t;
354
355
356/**
357 * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
358 *
359 * \sa drmAddBufs().
360 */
361typedef struct drm_buf_desc {
362 int count; /**< Number of buffers of this size */
363 int size; /**< Size in bytes */
364 int low_mark; /**< Low water mark */
365 int high_mark; /**< High water mark */
366 enum {
367 _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
368 _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
369 _DRM_SG_BUFFER = 0x04 /**< Scatter/gather memory buffer */
370 } flags;
371 unsigned long agp_start; /**<
372 * Start address of where the AGP buffers are
373 * in the AGP aperture
374 */
375} drm_buf_desc_t;
376
377
378/**
379 * DRM_IOCTL_INFO_BUFS ioctl argument type.
380 */
381typedef struct drm_buf_info {
382 int count; /**< Entries in list */
383 drm_buf_desc_t __user *list;
384} drm_buf_info_t;
385
386
387/**
388 * DRM_IOCTL_FREE_BUFS ioctl argument type.
389 */
390typedef struct drm_buf_free {
391 int count;
392 int __user *list;
393} drm_buf_free_t;
394
395
396/**
397 * Buffer information
398 *
399 * \sa drm_buf_map.
400 */
401typedef struct drm_buf_pub {
402 int idx; /**< Index into the master buffer list */
403 int total; /**< Buffer size */
404 int used; /**< Amount of buffer in use (for DMA) */
405 void __user *address; /**< Address of buffer */
406} drm_buf_pub_t;
407
408
409/**
410 * DRM_IOCTL_MAP_BUFS ioctl argument type.
411 */
412typedef struct drm_buf_map {
413 int count; /**< Length of the buffer list */
414 void __user *virtual; /**< Mmap'd area in user-virtual */
415 drm_buf_pub_t __user *list; /**< Buffer information */
416} drm_buf_map_t;
417
418
419/**
420 * DRM_IOCTL_DMA ioctl argument type.
421 *
422 * Indices here refer to the offset into the buffer list in drm_buf_get.
423 *
424 * \sa drmDMA().
425 */
426typedef struct drm_dma {
427 int context; /**< Context handle */
428 int send_count; /**< Number of buffers to send */
429 int __user *send_indices; /**< List of handles to buffers */
430 int __user *send_sizes; /**< Lengths of data to send */
431 drm_dma_flags_t flags; /**< Flags */
432 int request_count; /**< Number of buffers requested */
433 int request_size; /**< Desired size for buffers */
434 int __user *request_indices; /**< Buffer information */
435 int __user *request_sizes;
436 int granted_count; /**< Number of buffers granted */
437} drm_dma_t;
438
439
440typedef enum {
441 _DRM_CONTEXT_PRESERVED = 0x01,
442 _DRM_CONTEXT_2DONLY = 0x02
443} drm_ctx_flags_t;
444
445
446/**
447 * DRM_IOCTL_ADD_CTX ioctl argument type.
448 *
449 * \sa drmCreateContext() and drmDestroyContext().
450 */
451typedef struct drm_ctx {
452 drm_context_t handle;
453 drm_ctx_flags_t flags;
454} drm_ctx_t;
455
456
457/**
458 * DRM_IOCTL_RES_CTX ioctl argument type.
459 */
460typedef struct drm_ctx_res {
461 int count;
462 drm_ctx_t __user *contexts;
463} drm_ctx_res_t;
464
465
466/**
467 * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
468 */
469typedef struct drm_draw {
470 drm_drawable_t handle;
471} drm_draw_t;
472
473
474/**
475 * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
476 */
477typedef struct drm_auth {
478 drm_magic_t magic;
479} drm_auth_t;
480
481
482/**
483 * DRM_IOCTL_IRQ_BUSID ioctl argument type.
484 *
485 * \sa drmGetInterruptFromBusID().
486 */
487typedef struct drm_irq_busid {
488 int irq; /**< IRQ number */
489 int busnum; /**< bus number */
490 int devnum; /**< device number */
491 int funcnum; /**< function number */
492} drm_irq_busid_t;
493
494
495typedef enum {
496 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
497 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
498 _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
499} drm_vblank_seq_type_t;
500
501
502#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
503
504
505struct drm_wait_vblank_request {
506 drm_vblank_seq_type_t type;
507 unsigned int sequence;
508 unsigned long signal;
509};
510
511
512struct drm_wait_vblank_reply {
513 drm_vblank_seq_type_t type;
514 unsigned int sequence;
515 long tval_sec;
516 long tval_usec;
517};
518
519
520/**
521 * DRM_IOCTL_WAIT_VBLANK ioctl argument type.
522 *
523 * \sa drmWaitVBlank().
524 */
525typedef union drm_wait_vblank {
526 struct drm_wait_vblank_request request;
527 struct drm_wait_vblank_reply reply;
528} drm_wait_vblank_t;
529
530
531/**
532 * DRM_IOCTL_AGP_ENABLE ioctl argument type.
533 *
534 * \sa drmAgpEnable().
535 */
536typedef struct drm_agp_mode {
537 unsigned long mode; /**< AGP mode */
538} drm_agp_mode_t;
539
540
541/**
542 * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
543 *
544 * \sa drmAgpAlloc() and drmAgpFree().
545 */
546typedef struct drm_agp_buffer {
547 unsigned long size; /**< In bytes -- will round to page boundary */
548 unsigned long handle; /**< Used for binding / unbinding */
549 unsigned long type; /**< Type of memory to allocate */
550 unsigned long physical; /**< Physical used by i810 */
551} drm_agp_buffer_t;
552
553
554/**
555 * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
556 *
557 * \sa drmAgpBind() and drmAgpUnbind().
558 */
559typedef struct drm_agp_binding {
560 unsigned long handle; /**< From drm_agp_buffer */
561 unsigned long offset; /**< In bytes -- will round to page boundary */
562} drm_agp_binding_t;
563
564
565/**
566 * DRM_IOCTL_AGP_INFO ioctl argument type.
567 *
568 * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
569 * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
570 * drmAgpVendorId() and drmAgpDeviceId().
571 */
572typedef struct drm_agp_info {
573 int agp_version_major;
574 int agp_version_minor;
575 unsigned long mode;
576 unsigned long aperture_base; /* physical address */
577 unsigned long aperture_size; /* bytes */
578 unsigned long memory_allowed; /* bytes */
579 unsigned long memory_used;
580
581 /* PCI information */
582 unsigned short id_vendor;
583 unsigned short id_device;
584} drm_agp_info_t;
585
586
587/**
588 * DRM_IOCTL_SG_ALLOC ioctl argument type.
589 */
590typedef struct drm_scatter_gather {
591 unsigned long size; /**< In bytes -- will round to page boundary */
592 unsigned long handle; /**< Used for mapping / unmapping */
593} drm_scatter_gather_t;
594
595/**
596 * DRM_IOCTL_SET_VERSION ioctl argument type.
597 */
598typedef struct drm_set_version {
599 int drm_di_major;
600 int drm_di_minor;
601 int drm_dd_major;
602 int drm_dd_minor;
603} drm_set_version_t;
604
605
606#define DRM_IOCTL_BASE 'd'
607#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
608#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
609#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type)
610#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
611
612#define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t)
613#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t)
614#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t)
615#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
616#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t)
617#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t)
618#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t)
619#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, drm_set_version_t)
620
621#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
622#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)
623#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, drm_block_t)
624#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, drm_block_t)
625#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, drm_control_t)
626#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, drm_map_t)
627#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, drm_buf_desc_t)
628#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, drm_buf_desc_t)
629#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm_buf_info_t)
630#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm_buf_map_t)
631#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm_buf_free_t)
632
633#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, drm_map_t)
634
635#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, drm_ctx_priv_map_t)
636#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, drm_ctx_priv_map_t)
637
638#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, drm_ctx_t)
639#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, drm_ctx_t)
640#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, drm_ctx_t)
641#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, drm_ctx_t)
642#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, drm_ctx_t)
643#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, drm_ctx_t)
644#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, drm_ctx_res_t)
645#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, drm_draw_t)
646#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, drm_draw_t)
647#define DRM_IOCTL_DMA DRM_IOWR(0x29, drm_dma_t)
648#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, drm_lock_t)
649#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t)
650#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t)
651
652#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
653#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
654#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t)
655#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t)
656#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t)
657#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t)
658#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
659#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
660
661#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
662#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
663
664#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
665
666/**
667 * Device specific ioctls should only be in their respective headers
668 * The device specific ioctl range is from 0x40 to 0x79.
669 *
670 * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
671 * drmCommandReadWrite().
672 */
673#define DRM_COMMAND_BASE 0x40
674
675#endif
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
new file mode 100644
index 000000000000..21f4c54e1a8d
--- /dev/null
+++ b/drivers/char/drm/drmP.h
@@ -0,0 +1,1073 @@
1/**
2 * \file drmP.h
3 * Private header for Direct Rendering Manager
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
11 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
12 * All rights reserved.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31 * OTHER DEALINGS IN THE SOFTWARE.
32 */
33
34#ifndef _DRM_P_H_
35#define _DRM_P_H_
36
37/* If you want the memory alloc debug functionality, change define below */
38/* #define DEBUG_MEMORY */
39
40#ifdef __KERNEL__
41#ifdef __alpha__
42/* add include of current.h so that "current" is defined
43 * before static inline funcs in wait.h. Doing this so we
44 * can build the DRM (part of PI DRI). 4/21/2000 S + B */
45#include <asm/current.h>
46#endif /* __alpha__ */
47#include <linux/config.h>
48#include <linux/module.h>
49#include <linux/kernel.h>
50#include <linux/miscdevice.h>
51#include <linux/fs.h>
52#include <linux/proc_fs.h>
53#include <linux/init.h>
54#include <linux/file.h>
55#include <linux/pci.h>
56#include <linux/version.h>
57#include <linux/jiffies.h>
58#include <linux/smp_lock.h> /* For (un)lock_kernel */
59#include <linux/mm.h>
60#include <linux/cdev.h>
61#if defined(__alpha__) || defined(__powerpc__)
62#include <asm/pgtable.h> /* For pte_wrprotect */
63#endif
64#include <asm/io.h>
65#include <asm/mman.h>
66#include <asm/uaccess.h>
67#ifdef CONFIG_MTRR
68#include <asm/mtrr.h>
69#endif
70#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
71#include <linux/types.h>
72#include <linux/agp_backend.h>
73#endif
74#include <linux/workqueue.h>
75#include <linux/poll.h>
76#include <asm/pgalloc.h>
77#include "drm.h"
78
79#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
80#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
81
82#include "drm_os_linux.h"
83
84/***********************************************************************/
85/** \name DRM template customization defaults */
86/*@{*/
87
88/* driver capabilities and requirements mask */
89#define DRIVER_USE_AGP 0x1
90#define DRIVER_REQUIRE_AGP 0x2
91#define DRIVER_USE_MTRR 0x4
92#define DRIVER_PCI_DMA 0x8
93#define DRIVER_SG 0x10
94#define DRIVER_HAVE_DMA 0x20
95#define DRIVER_HAVE_IRQ 0x40
96#define DRIVER_IRQ_SHARED 0x80
97#define DRIVER_IRQ_VBL 0x100
98#define DRIVER_DMA_QUEUE 0x200
99
100/***********************************************************************/
101/** \name Begin the DRM... */
102/*@{*/
103
104#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
105 also include looping detection. */
106
107#define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */
108#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
109#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
110#define DRM_LOOPING_LIMIT 5000000
111#define DRM_BSZ 1024 /**< Buffer size for /dev/drm? output */
112#define DRM_TIME_SLICE (HZ/20) /**< Time slice for GLXContexts */
113#define DRM_LOCK_SLICE 1 /**< Time slice for lock, in jiffies */
114
115#define DRM_FLAG_DEBUG 0x01
116
117#define DRM_MEM_DMA 0
118#define DRM_MEM_SAREA 1
119#define DRM_MEM_DRIVER 2
120#define DRM_MEM_MAGIC 3
121#define DRM_MEM_IOCTLS 4
122#define DRM_MEM_MAPS 5
123#define DRM_MEM_VMAS 6
124#define DRM_MEM_BUFS 7
125#define DRM_MEM_SEGS 8
126#define DRM_MEM_PAGES 9
127#define DRM_MEM_FILES 10
128#define DRM_MEM_QUEUES 11
129#define DRM_MEM_CMDS 12
130#define DRM_MEM_MAPPINGS 13
131#define DRM_MEM_BUFLISTS 14
132#define DRM_MEM_AGPLISTS 15
133#define DRM_MEM_TOTALAGP 16
134#define DRM_MEM_BOUNDAGP 17
135#define DRM_MEM_CTXBITMAP 18
136#define DRM_MEM_STUB 19
137#define DRM_MEM_SGLISTS 20
138#define DRM_MEM_CTXLIST 21
139
140#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
141
142/*@}*/
143
144
145/***********************************************************************/
146/** \name Backward compatibility section */
147/*@{*/
148
149#ifndef MODULE_LICENSE
150#define MODULE_LICENSE(x)
151#endif
152
153#ifndef preempt_disable
154#define preempt_disable()
155#define preempt_enable()
156#endif
157
158#ifndef pte_offset_map
159#define pte_offset_map pte_offset
160#define pte_unmap(pte)
161#endif
162
163#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)
164static inline struct page * vmalloc_to_page(void * vmalloc_addr)
165{
166 unsigned long addr = (unsigned long) vmalloc_addr;
167 struct page *page = NULL;
168 pgd_t *pgd = pgd_offset_k(addr);
169 pmd_t *pmd;
170 pte_t *ptep, pte;
171
172 if (!pgd_none(*pgd)) {
173 pmd = pmd_offset(pgd, addr);
174 if (!pmd_none(*pmd)) {
175 preempt_disable();
176 ptep = pte_offset_map(pmd, addr);
177 pte = *ptep;
178 if (pte_present(pte))
179 page = pte_page(pte);
180 pte_unmap(ptep);
181 preempt_enable();
182 }
183 }
184 return page;
185}
186#endif
187
188#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
189#define DRM_RPR_ARG(vma)
190#else
191#define DRM_RPR_ARG(vma) vma,
192#endif
193
194#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
195
196/*@}*/
197
198
199/***********************************************************************/
200/** \name Macros to make printk easier */
201/*@{*/
202
203/**
204 * Error output.
205 *
206 * \param fmt printf() like format string.
207 * \param arg arguments
208 */
209#define DRM_ERROR(fmt, arg...) \
210 printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg)
211
212/**
213 * Memory error output.
214 *
215 * \param area memory area where the error occurred.
216 * \param fmt printf() like format string.
217 * \param arg arguments
218 */
219#define DRM_MEM_ERROR(area, fmt, arg...) \
220 printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \
221 drm_mem_stats[area].name , ##arg)
222
223#define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
224
225/**
226 * Debug output.
227 *
228 * \param fmt printf() like format string.
229 * \param arg arguments
230 */
231#if DRM_DEBUG_CODE
232#define DRM_DEBUG(fmt, arg...) \
233 do { \
234 if ( drm_debug ) \
235 printk(KERN_DEBUG \
236 "[" DRM_NAME ":%s] " fmt , \
237 __FUNCTION__ , ##arg); \
238 } while (0)
239#else
240#define DRM_DEBUG(fmt, arg...) do { } while (0)
241#endif
242
243#define DRM_PROC_LIMIT (PAGE_SIZE-80)
244
245#define DRM_PROC_PRINT(fmt, arg...) \
246 len += sprintf(&buf[len], fmt , ##arg); \
247 if (len > DRM_PROC_LIMIT) { *eof = 1; return len - offset; }
248
249#define DRM_PROC_PRINT_RET(ret, fmt, arg...) \
250 len += sprintf(&buf[len], fmt , ##arg); \
251 if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
252
253/*@}*/
254
255
256/***********************************************************************/
257/** \name Internal types and structures */
258/*@{*/
259
260#define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
261#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
262#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
263
264#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
265#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
266#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
267
268#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
269/**
270 * Get the private SAREA mapping.
271 *
272 * \param _dev DRM device.
273 * \param _ctx context number.
274 * \param _map output mapping.
275 */
276#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do { \
277 (_map) = (_dev)->context_sareas[_ctx]; \
278} while(0)
279
280/**
281 * Test that the hardware lock is held by the caller, returning otherwise.
282 *
283 * \param dev DRM device.
284 * \param filp file pointer of the caller.
285 */
286#define LOCK_TEST_WITH_RETURN( dev, filp ) \
287do { \
288 if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
289 dev->lock.filp != filp ) { \
290 DRM_ERROR( "%s called without lock held\n", \
291 __FUNCTION__ ); \
292 return -EINVAL; \
293 } \
294} while (0)
295
296/**
297 * Copy and IOCTL return string to user space
298 */
299#define DRM_COPY( name, value ) \
300 len = strlen( value ); \
301 if ( len > name##_len ) len = name##_len; \
302 name##_len = strlen( value ); \
303 if ( len && name ) { \
304 if ( copy_to_user( name, value, len ) ) \
305 return -EFAULT; \
306 }
307
308/**
309 * Ioctl function type.
310 *
311 * \param inode device inode.
312 * \param filp file pointer.
313 * \param cmd command.
314 * \param arg argument.
315 */
316typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
317 unsigned int cmd, unsigned long arg );
318
319typedef struct drm_ioctl_desc {
320 drm_ioctl_t *func;
321 int auth_needed;
322 int root_only;
323} drm_ioctl_desc_t;
324
325typedef struct drm_devstate {
326 pid_t owner; /**< X server pid holding x_lock */
327} drm_devstate_t;
328
329typedef struct drm_magic_entry {
330 drm_magic_t magic;
331 struct drm_file *priv;
332 struct drm_magic_entry *next;
333} drm_magic_entry_t;
334
335typedef struct drm_magic_head {
336 struct drm_magic_entry *head;
337 struct drm_magic_entry *tail;
338} drm_magic_head_t;
339
340typedef struct drm_vma_entry {
341 struct vm_area_struct *vma;
342 struct drm_vma_entry *next;
343 pid_t pid;
344} drm_vma_entry_t;
345
346/**
347 * DMA buffer.
348 */
349typedef struct drm_buf {
350 int idx; /**< Index into master buflist */
351 int total; /**< Buffer size */
352 int order; /**< log-base-2(total) */
353 int used; /**< Amount of buffer in use (for DMA) */
354 unsigned long offset; /**< Byte offset (used internally) */
355 void *address; /**< Address of buffer */
356 unsigned long bus_address; /**< Bus address of buffer */
357 struct drm_buf *next; /**< Kernel-only: used for free list */
358 __volatile__ int waiting; /**< On kernel DMA queue */
359 __volatile__ int pending; /**< On hardware DMA queue */
360 wait_queue_head_t dma_wait; /**< Processes waiting */
361 struct file *filp; /**< Pointer to holding file descr */
362 int context; /**< Kernel queue for this buffer */
363 int while_locked;/**< Dispatch this buffer while locked */
364 enum {
365 DRM_LIST_NONE = 0,
366 DRM_LIST_FREE = 1,
367 DRM_LIST_WAIT = 2,
368 DRM_LIST_PEND = 3,
369 DRM_LIST_PRIO = 4,
370 DRM_LIST_RECLAIM = 5
371 } list; /**< Which list we're on */
372
373 int dev_priv_size; /**< Size of buffer private storage */
374 void *dev_private; /**< Per-buffer private storage */
375} drm_buf_t;
376
377
378/** bufs is one longer than it has to be */
379typedef struct drm_waitlist {
380 int count; /**< Number of possible buffers */
381 drm_buf_t **bufs; /**< List of pointers to buffers */
382 drm_buf_t **rp; /**< Read pointer */
383 drm_buf_t **wp; /**< Write pointer */
384 drm_buf_t **end; /**< End pointer */
385 spinlock_t read_lock;
386 spinlock_t write_lock;
387} drm_waitlist_t;
388
389typedef struct drm_freelist {
390 int initialized; /**< Freelist in use */
391 atomic_t count; /**< Number of free buffers */
392 drm_buf_t *next; /**< End pointer */
393
394 wait_queue_head_t waiting; /**< Processes waiting on free bufs */
395 int low_mark; /**< Low water mark */
396 int high_mark; /**< High water mark */
397 atomic_t wfh; /**< If waiting for high mark */
398 spinlock_t lock;
399} drm_freelist_t;
400
401/**
402 * Buffer entry. There is one of this for each buffer size order.
403 */
404typedef struct drm_buf_entry {
405 int buf_size; /**< size */
406 int buf_count; /**< number of buffers */
407 drm_buf_t *buflist; /**< buffer list */
408 int seg_count;
409 int page_order;
410 unsigned long *seglist;
411
412 drm_freelist_t freelist;
413} drm_buf_entry_t;
414
415/** File private data */
416typedef struct drm_file {
417 int authenticated;
418 int minor;
419 pid_t pid;
420 uid_t uid;
421 drm_magic_t magic;
422 unsigned long ioctl_count;
423 struct drm_file *next;
424 struct drm_file *prev;
425 struct drm_head *head;
426 int remove_auth_on_close;
427 unsigned long lock_count;
428 void *driver_priv;
429} drm_file_t;
430
431/** Wait queue */
432typedef struct drm_queue {
433 atomic_t use_count; /**< Outstanding uses (+1) */
434 atomic_t finalization; /**< Finalization in progress */
435 atomic_t block_count; /**< Count of processes waiting */
436 atomic_t block_read; /**< Queue blocked for reads */
437 wait_queue_head_t read_queue; /**< Processes waiting on block_read */
438 atomic_t block_write; /**< Queue blocked for writes */
439 wait_queue_head_t write_queue; /**< Processes waiting on block_write */
440#if 1
441 atomic_t total_queued; /**< Total queued statistic */
442 atomic_t total_flushed;/**< Total flushes statistic */
443 atomic_t total_locks; /**< Total locks statistics */
444#endif
445 drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
446 drm_waitlist_t waitlist; /**< Pending buffers */
447 wait_queue_head_t flush_queue; /**< Processes waiting until flush */
448} drm_queue_t;
449
450/**
451 * Lock data.
452 */
453typedef struct drm_lock_data {
454 drm_hw_lock_t *hw_lock; /**< Hardware lock */
455 struct file *filp; /**< File descr of lock holder (0=kernel) */
456 wait_queue_head_t lock_queue; /**< Queue of blocked processes */
457 unsigned long lock_time; /**< Time of last lock in jiffies */
458} drm_lock_data_t;
459
460/**
461 * DMA data.
462 */
463typedef struct drm_device_dma {
464
465 drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */
466 int buf_count; /**< total number of buffers */
467 drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
468 int seg_count;
469 int page_count; /**< number of pages */
470 unsigned long *pagelist; /**< page list */
471 unsigned long byte_count;
472 enum {
473 _DRM_DMA_USE_AGP = 0x01,
474 _DRM_DMA_USE_SG = 0x02
475 } flags;
476
477} drm_device_dma_t;
478
479/**
480 * AGP memory entry. Stored as a doubly linked list.
481 */
482typedef struct drm_agp_mem {
483 unsigned long handle; /**< handle */
484 DRM_AGP_MEM *memory;
485 unsigned long bound; /**< address */
486 int pages;
487 struct drm_agp_mem *prev; /**< previous entry */
488 struct drm_agp_mem *next; /**< next entry */
489} drm_agp_mem_t;
490
491/**
492 * AGP data.
493 *
494 * \sa drm_agp_init() and drm_device::agp.
495 */
496typedef struct drm_agp_head {
497 DRM_AGP_KERN agp_info; /**< AGP device information */
498 drm_agp_mem_t *memory; /**< memory entries */
499 unsigned long mode; /**< AGP mode */
500 struct agp_bridge_data *bridge;
501 int enabled; /**< whether the AGP bus as been enabled */
502 int acquired; /**< whether the AGP device has been acquired */
503 unsigned long base;
504 int agp_mtrr;
505 int cant_use_aperture;
506 unsigned long page_mask;
507} drm_agp_head_t;
508
509/**
510 * Scatter-gather memory.
511 */
512typedef struct drm_sg_mem {
513 unsigned long handle;
514 void *virtual;
515 int pages;
516 struct page **pagelist;
517 dma_addr_t *busaddr;
518} drm_sg_mem_t;
519
520typedef struct drm_sigdata {
521 int context;
522 drm_hw_lock_t *lock;
523} drm_sigdata_t;
524
525/**
526 * Mappings list
527 */
528typedef struct drm_map_list {
529 struct list_head head; /**< list head */
530 drm_map_t *map; /**< mapping */
531} drm_map_list_t;
532
533typedef drm_map_t drm_local_map_t;
534
535/**
536 * Context handle list
537 */
538typedef struct drm_ctx_list {
539 struct list_head head; /**< list head */
540 drm_context_t handle; /**< context handle */
541 drm_file_t *tag; /**< associated fd private data */
542} drm_ctx_list_t;
543
544
545typedef struct drm_vbl_sig {
546 struct list_head head;
547 unsigned int sequence;
548 struct siginfo info;
549 struct task_struct *task;
550} drm_vbl_sig_t;
551
552
553/**
554 * DRM driver structure. This structure represent the common code for
555 * a family of cards. There will one drm_device for each card present
556 * in this family
557 */
558struct drm_device;
559
560struct drm_driver {
561 int (*preinit)(struct drm_device *, unsigned long flags);
562 void (*prerelease)(struct drm_device *, struct file *filp);
563 void (*pretakedown)(struct drm_device *);
564 int (*postcleanup)(struct drm_device *);
565 int (*presetup)(struct drm_device *);
566 int (*postsetup)(struct drm_device *);
567 int (*dma_ioctl)( DRM_IOCTL_ARGS );
568 int (*open_helper)(struct drm_device *, drm_file_t *);
569 void (*free_filp_priv)(struct drm_device *, drm_file_t *);
570 void (*release)(struct drm_device *, struct file *filp);
571 void (*dma_ready)(struct drm_device *);
572 int (*dma_quiescent)(struct drm_device *);
573 int (*context_ctor)(struct drm_device *dev, int context);
574 int (*context_dtor)(struct drm_device *dev, int context);
575 int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
576 void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock);
577 int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
578 /* these have to be filled in */
579 int (*postinit)(struct drm_device *, unsigned long flags);
580 irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
581 void (*irq_preinstall)(struct drm_device *dev);
582 void (*irq_postinstall)(struct drm_device *dev);
583 void (*irq_uninstall)(struct drm_device *dev);
584 void (*reclaim_buffers)(struct drm_device *dev, struct file *filp);
585 unsigned long (*get_map_ofs)(drm_map_t *map);
586 unsigned long (*get_reg_ofs)(struct drm_device *dev);
587 void (*set_version)(struct drm_device *dev, drm_set_version_t *sv);
588 int (*version)(drm_version_t *version);
589 u32 driver_features;
590 int dev_priv_size;
591 drm_ioctl_desc_t *ioctls;
592 int num_ioctls;
593 struct file_operations fops;
594 struct pci_driver pci_driver;
595};
596
597/**
598 * DRM head structure. This structure represent a video head on a card
599 * that may contain multiple heads. Embed one per head of these in the
600 * private drm_device structure.
601 */
602typedef struct drm_head {
603 int minor; /**< Minor device number */
604 struct drm_device *dev;
605 struct proc_dir_entry *dev_root; /**< proc directory entry */
606 dev_t device; /**< Device number for mknod */
607 struct class_device *dev_class;
608} drm_head_t;
609
610/**
611 * DRM device structure. This structure represent a complete card that
612 * may contain multiple heads.
613 */
614typedef struct drm_device {
615 char *unique; /**< Unique identifier: e.g., busid */
616 int unique_len; /**< Length of unique field */
617 char *devname; /**< For /proc/interrupts */
618 int if_version; /**< Highest interface version set */
619
620 int blocked; /**< Blocked due to VC switch? */
621
622 /** \name Locks */
623 /*@{*/
624 spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
625 struct semaphore struct_sem; /**< For others */
626 /*@}*/
627
628 /** \name Usage Counters */
629 /*@{*/
630 int open_count; /**< Outstanding files open */
631 atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
632 atomic_t vma_count; /**< Outstanding vma areas open */
633 int buf_use; /**< Buffers in use -- cannot alloc */
634 atomic_t buf_alloc; /**< Buffer allocation in progress */
635 /*@}*/
636
637 /** \name Performance counters */
638 /*@{*/
639 unsigned long counters;
640 drm_stat_type_t types[15];
641 atomic_t counts[15];
642 /*@}*/
643
644 /** \name Authentication */
645 /*@{*/
646 drm_file_t *file_first; /**< file list head */
647 drm_file_t *file_last; /**< file list tail */
648 drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
649 /*@}*/
650
651 /** \name Memory management */
652 /*@{*/
653 drm_map_list_t *maplist; /**< Linked list of regions */
654 int map_count; /**< Number of mappable regions */
655
656 /** \name Context handle management */
657 /*@{*/
658 drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
659 int ctx_count; /**< Number of context handles */
660 struct semaphore ctxlist_sem; /**< For ctxlist */
661
662 drm_map_t **context_sareas; /**< per-context SAREA's */
663 int max_context;
664
665 drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
666 drm_lock_data_t lock; /**< Information on hardware lock */
667 /*@}*/
668
669 /** \name DMA queues (contexts) */
670 /*@{*/
671 int queue_count; /**< Number of active DMA queues */
672 int queue_reserved; /**< Number of reserved DMA queues */
673 int queue_slots; /**< Actual length of queuelist */
674 drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
675 drm_device_dma_t *dma; /**< Optional pointer for DMA support */
676 /*@}*/
677
678 /** \name Context support */
679 /*@{*/
680 int irq; /**< Interrupt used by board */
681 int irq_enabled; /**< True if irq handler is enabled */
682 __volatile__ long context_flag; /**< Context swapping flag */
683 __volatile__ long interrupt_flag; /**< Interruption handler flag */
684 __volatile__ long dma_flag; /**< DMA dispatch flag */
685 struct timer_list timer; /**< Timer for delaying ctx switch */
686 wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
687 int last_checked; /**< Last context checked for DMA */
688 int last_context; /**< Last current context */
689 unsigned long last_switch; /**< jiffies at last context switch */
690 /*@}*/
691
692 struct work_struct work;
693 /** \name VBLANK IRQ support */
694 /*@{*/
695
696 wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
697 atomic_t vbl_received;
698 spinlock_t vbl_lock;
699 drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
700 unsigned int vbl_pending;
701
702 /*@}*/
703 cycles_t ctx_start;
704 cycles_t lck_start;
705
706 char buf[DRM_BSZ]; /**< Output buffer */
707 char *buf_rp; /**< Read pointer */
708 char *buf_wp; /**< Write pointer */
709 char *buf_end; /**< End pointer */
710 struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
711 wait_queue_head_t buf_readers; /**< Processes waiting to read */
712 wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
713
714 drm_agp_head_t *agp; /**< AGP data */
715
716 struct pci_dev *pdev; /**< PCI device structure */
717 int pci_domain; /**< PCI bus domain number */
718 int pci_bus; /**< PCI bus number */
719 int pci_slot; /**< PCI slot number */
720 int pci_func; /**< PCI function number */
721#ifdef __alpha__
722#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
723 struct pci_controler *hose;
724#else
725 struct pci_controller *hose;
726#endif
727#endif
728 drm_sg_mem_t *sg; /**< Scatter gather memory */
729 unsigned long *ctx_bitmap; /**< context bitmap */
730 void *dev_private; /**< device private data */
731 drm_sigdata_t sigdata; /**< For block_all_signals */
732 sigset_t sigmask;
733
734 struct drm_driver *driver;
735 drm_local_map_t *agp_buffer_map;
736 drm_head_t primary; /**< primary screen head */
737} drm_device_t;
738
739static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
740{
741 return ((dev->driver->driver_features & feature) ? 1 : 0);
742}
743
744#if __OS_HAS_AGP
745static inline int drm_core_has_AGP(struct drm_device *dev)
746{
747 return drm_core_check_feature(dev, DRIVER_USE_AGP);
748}
749#else
750#define drm_core_has_AGP(dev) (0)
751#endif
752
753#if __OS_HAS_MTRR
754static inline int drm_core_has_MTRR(struct drm_device *dev)
755{
756 return drm_core_check_feature(dev, DRIVER_USE_MTRR);
757}
758#else
759#define drm_core_has_MTRR(dev) (0)
760#endif
761
762/******************************************************************/
763/** \name Internal function definitions */
764/*@{*/
765
766 /* Misc. support (drm_init.h) */
767extern int drm_flags;
768extern void drm_parse_options( char *s );
769extern int drm_cpu_valid( void );
770
771 /* Driver support (drm_drv.h) */
772extern int drm_init(struct drm_driver *driver);
773extern void drm_exit(struct drm_driver *driver);
774extern int drm_version(struct inode *inode, struct file *filp,
775 unsigned int cmd, unsigned long arg);
776extern int drm_ioctl(struct inode *inode, struct file *filp,
777 unsigned int cmd, unsigned long arg);
778extern int drm_takedown(drm_device_t * dev);
779
780 /* Device support (drm_fops.h) */
781extern int drm_open(struct inode *inode, struct file *filp);
782extern int drm_stub_open(struct inode *inode, struct file *filp);
783extern int drm_open_helper(struct inode *inode, struct file *filp,
784 drm_device_t *dev);
785extern int drm_flush(struct file *filp);
786extern int drm_fasync(int fd, struct file *filp, int on);
787extern int drm_release(struct inode *inode, struct file *filp);
788
789 /* Mapping support (drm_vm.h) */
790extern void drm_vm_open(struct vm_area_struct *vma);
791extern void drm_vm_close(struct vm_area_struct *vma);
792extern void drm_vm_shm_close(struct vm_area_struct *vma);
793extern int drm_mmap_dma(struct file *filp,
794 struct vm_area_struct *vma);
795extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
796extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
797extern ssize_t drm_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
798
799 /* Memory management support (drm_memory.h) */
800#include "drm_memory.h"
801extern void drm_mem_init(void);
802extern int drm_mem_info(char *buf, char **start, off_t offset,
803 int request, int *eof, void *data);
804extern void *drm_calloc(size_t nmemb, size_t size, int area);
805extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size,
806 int area);
807extern unsigned long drm_alloc_pages(int order, int area);
808extern void drm_free_pages(unsigned long address, int order,
809 int area);
810extern void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev);
811extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
812 drm_device_t *dev);
813extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev);
814
815extern DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type);
816extern int drm_free_agp(DRM_AGP_MEM *handle, int pages);
817extern int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start);
818extern int drm_unbind_agp(DRM_AGP_MEM *handle);
819
820 /* Misc. IOCTL support (drm_ioctl.h) */
821extern int drm_irq_by_busid(struct inode *inode, struct file *filp,
822 unsigned int cmd, unsigned long arg);
823extern int drm_getunique(struct inode *inode, struct file *filp,
824 unsigned int cmd, unsigned long arg);
825extern int drm_setunique(struct inode *inode, struct file *filp,
826 unsigned int cmd, unsigned long arg);
827extern int drm_getmap(struct inode *inode, struct file *filp,
828 unsigned int cmd, unsigned long arg);
829extern int drm_getclient(struct inode *inode, struct file *filp,
830 unsigned int cmd, unsigned long arg);
831extern int drm_getstats(struct inode *inode, struct file *filp,
832 unsigned int cmd, unsigned long arg);
833extern int drm_setversion(struct inode *inode, struct file *filp,
834 unsigned int cmd, unsigned long arg);
835
836 /* Context IOCTL support (drm_context.h) */
837extern int drm_resctx( struct inode *inode, struct file *filp,
838 unsigned int cmd, unsigned long arg );
839extern int drm_addctx( struct inode *inode, struct file *filp,
840 unsigned int cmd, unsigned long arg );
841extern int drm_modctx( struct inode *inode, struct file *filp,
842 unsigned int cmd, unsigned long arg );
843extern int drm_getctx( struct inode *inode, struct file *filp,
844 unsigned int cmd, unsigned long arg );
845extern int drm_switchctx( struct inode *inode, struct file *filp,
846 unsigned int cmd, unsigned long arg );
847extern int drm_newctx( struct inode *inode, struct file *filp,
848 unsigned int cmd, unsigned long arg );
849extern int drm_rmctx( struct inode *inode, struct file *filp,
850 unsigned int cmd, unsigned long arg );
851
852extern int drm_context_switch(drm_device_t *dev, int old, int new);
853extern int drm_context_switch_complete(drm_device_t *dev, int new);
854
855extern int drm_ctxbitmap_init( drm_device_t *dev );
856extern void drm_ctxbitmap_cleanup( drm_device_t *dev );
857extern void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle );
858
859extern int drm_setsareactx( struct inode *inode, struct file *filp,
860 unsigned int cmd, unsigned long arg );
861extern int drm_getsareactx( struct inode *inode, struct file *filp,
862 unsigned int cmd, unsigned long arg );
863
864 /* Drawable IOCTL support (drm_drawable.h) */
865extern int drm_adddraw(struct inode *inode, struct file *filp,
866 unsigned int cmd, unsigned long arg);
867extern int drm_rmdraw(struct inode *inode, struct file *filp,
868 unsigned int cmd, unsigned long arg);
869
870
871 /* Authentication IOCTL support (drm_auth.h) */
872extern int drm_add_magic(drm_device_t *dev, drm_file_t *priv,
873 drm_magic_t magic);
874extern int drm_remove_magic(drm_device_t *dev, drm_magic_t magic);
875extern int drm_getmagic(struct inode *inode, struct file *filp,
876 unsigned int cmd, unsigned long arg);
877extern int drm_authmagic(struct inode *inode, struct file *filp,
878 unsigned int cmd, unsigned long arg);
879
880 /* Placeholder for ioctls past */
881extern int drm_noop(struct inode *inode, struct file *filp,
882 unsigned int cmd, unsigned long arg);
883
884 /* Locking IOCTL support (drm_lock.h) */
885extern int drm_lock(struct inode *inode, struct file *filp,
886 unsigned int cmd, unsigned long arg);
887extern int drm_unlock(struct inode *inode, struct file *filp,
888 unsigned int cmd, unsigned long arg);
889extern int drm_lock_take(__volatile__ unsigned int *lock,
890 unsigned int context);
891extern int drm_lock_transfer(drm_device_t *dev,
892 __volatile__ unsigned int *lock,
893 unsigned int context);
894extern int drm_lock_free(drm_device_t *dev,
895 __volatile__ unsigned int *lock,
896 unsigned int context);
897extern int drm_notifier(void *priv);
898
899 /* Buffer management support (drm_bufs.h) */
900extern int drm_order( unsigned long size );
901extern int drm_addmap( struct inode *inode, struct file *filp,
902 unsigned int cmd, unsigned long arg );
903extern int drm_rmmap( struct inode *inode, struct file *filp,
904 unsigned int cmd, unsigned long arg );
905extern int drm_addbufs( struct inode *inode, struct file *filp,
906 unsigned int cmd, unsigned long arg );
907extern int drm_infobufs( struct inode *inode, struct file *filp,
908 unsigned int cmd, unsigned long arg );
909extern int drm_markbufs( struct inode *inode, struct file *filp,
910 unsigned int cmd, unsigned long arg );
911extern int drm_freebufs( struct inode *inode, struct file *filp,
912 unsigned int cmd, unsigned long arg );
913extern int drm_mapbufs( struct inode *inode, struct file *filp,
914 unsigned int cmd, unsigned long arg );
915
916 /* DMA support (drm_dma.h) */
917extern int drm_dma_setup(drm_device_t *dev);
918extern void drm_dma_takedown(drm_device_t *dev);
919extern void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf);
920extern void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp);
921
922 /* IRQ support (drm_irq.h) */
923extern int drm_control( struct inode *inode, struct file *filp,
924 unsigned int cmd, unsigned long arg );
925extern int drm_irq_install( drm_device_t *dev );
926extern int drm_irq_uninstall( drm_device_t *dev );
927extern irqreturn_t drm_irq_handler( DRM_IRQ_ARGS );
928extern void drm_driver_irq_preinstall( drm_device_t *dev );
929extern void drm_driver_irq_postinstall( drm_device_t *dev );
930extern void drm_driver_irq_uninstall( drm_device_t *dev );
931
932extern int drm_wait_vblank(struct inode *inode, struct file *filp,
933 unsigned int cmd, unsigned long arg);
934extern int drm_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq);
935extern void drm_vbl_send_signals( drm_device_t *dev );
936
937 /* AGP/GART support (drm_agpsupport.h) */
938extern drm_agp_head_t *drm_agp_init(drm_device_t *dev);
939extern int drm_agp_acquire(struct inode *inode, struct file *filp,
940 unsigned int cmd, unsigned long arg);
941extern void drm_agp_do_release(drm_device_t *dev);
942extern int drm_agp_release(struct inode *inode, struct file *filp,
943 unsigned int cmd, unsigned long arg);
944extern int drm_agp_enable(struct inode *inode, struct file *filp,
945 unsigned int cmd, unsigned long arg);
946extern int drm_agp_info(struct inode *inode, struct file *filp,
947 unsigned int cmd, unsigned long arg);
948extern int drm_agp_alloc(struct inode *inode, struct file *filp,
949 unsigned int cmd, unsigned long arg);
950extern int drm_agp_free(struct inode *inode, struct file *filp,
951 unsigned int cmd, unsigned long arg);
952extern int drm_agp_unbind(struct inode *inode, struct file *filp,
953 unsigned int cmd, unsigned long arg);
954extern int drm_agp_bind(struct inode *inode, struct file *filp,
955 unsigned int cmd, unsigned long arg);
956extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type);
957extern int drm_agp_free_memory(DRM_AGP_MEM *handle);
958extern int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start);
959extern int drm_agp_unbind_memory(DRM_AGP_MEM *handle);
960
961 /* Stub support (drm_stub.h) */
962extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
963 struct drm_driver *driver);
964extern int drm_put_dev(drm_device_t * dev);
965extern int drm_get_head(drm_device_t * dev, drm_head_t *head);
966extern int drm_put_head(drm_head_t * head);
967extern unsigned int drm_debug;
968extern unsigned int drm_cards_limit;
969extern drm_head_t **drm_heads;
970extern struct drm_sysfs_class *drm_class;
971extern struct proc_dir_entry *drm_proc_root;
972
973 /* Proc support (drm_proc.h) */
974extern int drm_proc_init(drm_device_t *dev,
975 int minor,
976 struct proc_dir_entry *root,
977 struct proc_dir_entry **dev_root);
978extern int drm_proc_cleanup(int minor,
979 struct proc_dir_entry *root,
980 struct proc_dir_entry *dev_root);
981
982 /* Scatter Gather Support (drm_scatter.h) */
983extern void drm_sg_cleanup(drm_sg_mem_t *entry);
984extern int drm_sg_alloc(struct inode *inode, struct file *filp,
985 unsigned int cmd, unsigned long arg);
986extern int drm_sg_free(struct inode *inode, struct file *filp,
987 unsigned int cmd, unsigned long arg);
988
989 /* ATI PCIGART support (ati_pcigart.h) */
990extern int drm_ati_pcigart_init(drm_device_t *dev,
991 unsigned long *addr,
992 dma_addr_t *bus_addr);
993extern int drm_ati_pcigart_cleanup(drm_device_t *dev,
994 unsigned long addr,
995 dma_addr_t bus_addr);
996
997extern void *drm_pci_alloc(drm_device_t * dev, size_t size,
998 size_t align, dma_addr_t maxaddr,
999 dma_addr_t * busaddr);
1000
1001extern void drm_pci_free(drm_device_t * dev, size_t size,
1002 void *vaddr, dma_addr_t busaddr);
1003
1004 /* sysfs support (drm_sysfs.c) */
1005struct drm_sysfs_class;
1006extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner,
1007 char *name);
1008extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);
1009extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
1010 dev_t dev,
1011 struct device *device,
1012 const char *fmt, ...);
1013extern void drm_sysfs_device_remove(dev_t dev);
1014
1015
1016/* Inline replacements for DRM_IOREMAP macros */
1017static __inline__ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
1018{
1019 map->handle = drm_ioremap( map->offset, map->size, dev );
1020}
1021
1022static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, struct drm_device *dev)
1023{
1024 map->handle = drm_ioremap_nocache(map->offset, map->size, dev);
1025}
1026
1027static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
1028{
1029 if ( map->handle && map->size )
1030 drm_ioremapfree( map->handle, map->size, dev );
1031}
1032
1033static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
1034{
1035 struct list_head *_list;
1036 list_for_each( _list, &dev->maplist->head ) {
1037 drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
1038 if ( _entry->map &&
1039 _entry->map->offset == offset ) {
1040 return _entry->map;
1041 }
1042 }
1043 return NULL;
1044}
1045
1046static __inline__ void drm_core_dropmap(struct drm_map *map)
1047{
1048}
1049
1050#ifndef DEBUG_MEMORY
1051/** Wrapper around kmalloc() */
1052static __inline__ void *drm_alloc(size_t size, int area)
1053{
1054 return kmalloc(size, GFP_KERNEL);
1055}
1056
1057/** Wrapper around kfree() */
1058static __inline__ void drm_free(void *pt, size_t size, int area)
1059{
1060 kfree(pt);
1061}
1062#else
1063extern void *drm_alloc(size_t size, int area);
1064extern void drm_free(void *pt, size_t size, int area);
1065#endif
1066
1067/*@}*/
1068
1069extern unsigned long drm_core_get_map_ofs(drm_map_t *map);
1070extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
1071
1072#endif /* __KERNEL__ */
1073#endif
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
new file mode 100644
index 000000000000..8d94c0b5fa44
--- /dev/null
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -0,0 +1,448 @@
1/**
2 * \file drm_agpsupport.h
3 * DRM support for AGP/GART backend
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
11 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
12 * All Rights Reserved.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31 * OTHER DEALINGS IN THE SOFTWARE.
32 */
33
34#include "drmP.h"
35#include <linux/module.h>
36
37#if __OS_HAS_AGP
38
39/**
40 * AGP information ioctl.
41 *
42 * \param inode device inode.
43 * \param filp file pointer.
44 * \param cmd command.
45 * \param arg pointer to a (output) drm_agp_info structure.
46 * \return zero on success or a negative number on failure.
47 *
48 * Verifies the AGP device has been initialized and acquired and fills in the
49 * drm_agp_info structure with the information in drm_agp_head::agp_info.
50 */
51int drm_agp_info(struct inode *inode, struct file *filp,
52 unsigned int cmd, unsigned long arg)
53{
54 drm_file_t *priv = filp->private_data;
55 drm_device_t *dev = priv->head->dev;
56 DRM_AGP_KERN *kern;
57 drm_agp_info_t info;
58
59 if (!dev->agp || !dev->agp->acquired)
60 return -EINVAL;
61
62 kern = &dev->agp->agp_info;
63 info.agp_version_major = kern->version.major;
64 info.agp_version_minor = kern->version.minor;
65 info.mode = kern->mode;
66 info.aperture_base = kern->aper_base;
67 info.aperture_size = kern->aper_size * 1024 * 1024;
68 info.memory_allowed = kern->max_memory << PAGE_SHIFT;
69 info.memory_used = kern->current_memory << PAGE_SHIFT;
70 info.id_vendor = kern->device->vendor;
71 info.id_device = kern->device->device;
72
73 if (copy_to_user((drm_agp_info_t __user *)arg, &info, sizeof(info)))
74 return -EFAULT;
75 return 0;
76}
77
78/**
79 * Acquire the AGP device (ioctl).
80 *
81 * \param inode device inode.
82 * \param filp file pointer.
83 * \param cmd command.
84 * \param arg user argument.
85 * \return zero on success or a negative number on failure.
86 *
87 * Verifies the AGP device hasn't been acquired before and calls
88 * agp_acquire().
89 */
90int drm_agp_acquire(struct inode *inode, struct file *filp,
91 unsigned int cmd, unsigned long arg)
92{
93 drm_file_t *priv = filp->private_data;
94 drm_device_t *dev = priv->head->dev;
95
96 if (!dev->agp)
97 return -ENODEV;
98 if (dev->agp->acquired)
99 return -EBUSY;
100 if (!(dev->agp->bridge = agp_backend_acquire(dev->pdev)))
101 return -ENODEV;
102 dev->agp->acquired = 1;
103 return 0;
104}
105
106/**
107 * Release the AGP device (ioctl).
108 *
109 * \param inode device inode.
110 * \param filp file pointer.
111 * \param cmd command.
112 * \param arg user argument.
113 * \return zero on success or a negative number on failure.
114 *
115 * Verifies the AGP device has been acquired and calls agp_backend_release().
116 */
117int drm_agp_release(struct inode *inode, struct file *filp,
118 unsigned int cmd, unsigned long arg)
119{
120 drm_file_t *priv = filp->private_data;
121 drm_device_t *dev = priv->head->dev;
122
123 if (!dev->agp || !dev->agp->acquired)
124 return -EINVAL;
125 agp_backend_release(dev->agp->bridge);
126 dev->agp->acquired = 0;
127 return 0;
128
129}
130
131/**
132 * Release the AGP device.
133 *
134 * Calls agp_backend_release().
135 */
136void drm_agp_do_release(drm_device_t *dev)
137{
138 agp_backend_release(dev->agp->bridge);
139}
140
141/**
142 * Enable the AGP bus.
143 *
144 * \param inode device inode.
145 * \param filp file pointer.
146 * \param cmd command.
147 * \param arg pointer to a drm_agp_mode structure.
148 * \return zero on success or a negative number on failure.
149 *
150 * Verifies the AGP device has been acquired but not enabled, and calls
151 * agp_enable().
152 */
153int drm_agp_enable(struct inode *inode, struct file *filp,
154 unsigned int cmd, unsigned long arg)
155{
156 drm_file_t *priv = filp->private_data;
157 drm_device_t *dev = priv->head->dev;
158 drm_agp_mode_t mode;
159
160 if (!dev->agp || !dev->agp->acquired)
161 return -EINVAL;
162
163 if (copy_from_user(&mode, (drm_agp_mode_t __user *)arg, sizeof(mode)))
164 return -EFAULT;
165
166 dev->agp->mode = mode.mode;
167 agp_enable(dev->agp->bridge, mode.mode);
168 dev->agp->base = dev->agp->agp_info.aper_base;
169 dev->agp->enabled = 1;
170 return 0;
171}
172
173/**
174 * Allocate AGP memory.
175 *
176 * \param inode device inode.
177 * \param filp file pointer.
178 * \param cmd command.
179 * \param arg pointer to a drm_agp_buffer structure.
180 * \return zero on success or a negative number on failure.
181 *
182 * Verifies the AGP device is present and has been acquired, allocates the
183 * memory via alloc_agp() and creates a drm_agp_mem entry for it.
184 */
185int drm_agp_alloc(struct inode *inode, struct file *filp,
186 unsigned int cmd, unsigned long arg)
187{
188 drm_file_t *priv = filp->private_data;
189 drm_device_t *dev = priv->head->dev;
190 drm_agp_buffer_t request;
191 drm_agp_mem_t *entry;
192 DRM_AGP_MEM *memory;
193 unsigned long pages;
194 u32 type;
195 drm_agp_buffer_t __user *argp = (void __user *)arg;
196
197 if (!dev->agp || !dev->agp->acquired)
198 return -EINVAL;
199 if (copy_from_user(&request, argp, sizeof(request)))
200 return -EFAULT;
201 if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
202 return -ENOMEM;
203
204 memset(entry, 0, sizeof(*entry));
205
206 pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
207 type = (u32) request.type;
208
209 if (!(memory = drm_alloc_agp(dev->agp->bridge, pages, type))) {
210 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
211 return -ENOMEM;
212 }
213
214 entry->handle = (unsigned long)memory->key + 1;
215 entry->memory = memory;
216 entry->bound = 0;
217 entry->pages = pages;
218 entry->prev = NULL;
219 entry->next = dev->agp->memory;
220 if (dev->agp->memory)
221 dev->agp->memory->prev = entry;
222 dev->agp->memory = entry;
223
224 request.handle = entry->handle;
225 request.physical = memory->physical;
226
227 if (copy_to_user(argp, &request, sizeof(request))) {
228 dev->agp->memory = entry->next;
229 dev->agp->memory->prev = NULL;
230 drm_free_agp(memory, pages);
231 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
232 return -EFAULT;
233 }
234 return 0;
235}
236
237/**
238 * Search for the AGP memory entry associated with a handle.
239 *
240 * \param dev DRM device structure.
241 * \param handle AGP memory handle.
242 * \return pointer to the drm_agp_mem structure associated with \p handle.
243 *
244 * Walks through drm_agp_head::memory until finding a matching handle.
245 */
246static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t *dev,
247 unsigned long handle)
248{
249 drm_agp_mem_t *entry;
250
251 for (entry = dev->agp->memory; entry; entry = entry->next) {
252 if (entry->handle == handle)
253 return entry;
254 }
255 return NULL;
256}
257
258/**
259 * Unbind AGP memory from the GATT (ioctl).
260 *
261 * \param inode device inode.
262 * \param filp file pointer.
263 * \param cmd command.
264 * \param arg pointer to a drm_agp_binding structure.
265 * \return zero on success or a negative number on failure.
266 *
267 * Verifies the AGP device is present and acquired, looks-up the AGP memory
268 * entry and passes it to the unbind_agp() function.
269 */
270int drm_agp_unbind(struct inode *inode, struct file *filp,
271 unsigned int cmd, unsigned long arg)
272{
273 drm_file_t *priv = filp->private_data;
274 drm_device_t *dev = priv->head->dev;
275 drm_agp_binding_t request;
276 drm_agp_mem_t *entry;
277 int ret;
278
279 if (!dev->agp || !dev->agp->acquired)
280 return -EINVAL;
281 if (copy_from_user(&request, (drm_agp_binding_t __user *)arg, sizeof(request)))
282 return -EFAULT;
283 if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
284 return -EINVAL;
285 if (!entry->bound)
286 return -EINVAL;
287 ret = drm_unbind_agp(entry->memory);
288 if (ret == 0)
289 entry->bound = 0;
290 return ret;
291}
292
293/**
294 * Bind AGP memory into the GATT (ioctl)
295 *
296 * \param inode device inode.
297 * \param filp file pointer.
298 * \param cmd command.
299 * \param arg pointer to a drm_agp_binding structure.
300 * \return zero on success or a negative number on failure.
301 *
302 * Verifies the AGP device is present and has been acquired and that no memory
303 * is currently bound into the GATT. Looks-up the AGP memory entry and passes
304 * it to bind_agp() function.
305 */
306int drm_agp_bind(struct inode *inode, struct file *filp,
307 unsigned int cmd, unsigned long arg)
308{
309 drm_file_t *priv = filp->private_data;
310 drm_device_t *dev = priv->head->dev;
311 drm_agp_binding_t request;
312 drm_agp_mem_t *entry;
313 int retcode;
314 int page;
315
316 if (!dev->agp || !dev->agp->acquired)
317 return -EINVAL;
318 if (copy_from_user(&request, (drm_agp_binding_t __user *)arg, sizeof(request)))
319 return -EFAULT;
320 if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
321 return -EINVAL;
322 if (entry->bound)
323 return -EINVAL;
324 page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
325 if ((retcode = drm_bind_agp(entry->memory, page)))
326 return retcode;
327 entry->bound = dev->agp->base + (page << PAGE_SHIFT);
328 DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
329 dev->agp->base, entry->bound);
330 return 0;
331}
332
333/**
334 * Free AGP memory (ioctl).
335 *
336 * \param inode device inode.
337 * \param filp file pointer.
338 * \param cmd command.
339 * \param arg pointer to a drm_agp_buffer structure.
340 * \return zero on success or a negative number on failure.
341 *
342 * Verifies the AGP device is present and has been acquired and looks up the
343 * AGP memory entry. If the memory it's currently bound, unbind it via
344 * unbind_agp(). Frees it via free_agp() as well as the entry itself
345 * and unlinks from the doubly linked list it's inserted in.
346 */
347int drm_agp_free(struct inode *inode, struct file *filp,
348 unsigned int cmd, unsigned long arg)
349{
350 drm_file_t *priv = filp->private_data;
351 drm_device_t *dev = priv->head->dev;
352 drm_agp_buffer_t request;
353 drm_agp_mem_t *entry;
354
355 if (!dev->agp || !dev->agp->acquired)
356 return -EINVAL;
357 if (copy_from_user(&request, (drm_agp_buffer_t __user *)arg, sizeof(request)))
358 return -EFAULT;
359 if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
360 return -EINVAL;
361 if (entry->bound)
362 drm_unbind_agp(entry->memory);
363
364 if (entry->prev)
365 entry->prev->next = entry->next;
366 else
367 dev->agp->memory = entry->next;
368
369 if (entry->next)
370 entry->next->prev = entry->prev;
371
372 drm_free_agp(entry->memory, entry->pages);
373 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
374 return 0;
375}
376
377/**
378 * Initialize the AGP resources.
379 *
380 * \return pointer to a drm_agp_head structure.
381 *
382 */
383drm_agp_head_t *drm_agp_init(drm_device_t *dev)
384{
385 drm_agp_head_t *head = NULL;
386
387 if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
388 return NULL;
389 memset((void *)head, 0, sizeof(*head));
390 head->bridge = agp_find_bridge(dev->pdev);
391 if (!head->bridge) {
392 if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
393 drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
394 return NULL;
395 }
396 agp_copy_info(head->bridge, &head->agp_info);
397 agp_backend_release(head->bridge);
398 } else {
399 agp_copy_info(head->bridge, &head->agp_info);
400 }
401 if (head->agp_info.chipset == NOT_SUPPORTED) {
402 drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
403 return NULL;
404 }
405 head->memory = NULL;
406#if LINUX_VERSION_CODE <= 0x020408
407 head->cant_use_aperture = 0;
408 head->page_mask = ~(0xfff);
409#else
410 head->cant_use_aperture = head->agp_info.cant_use_aperture;
411 head->page_mask = head->agp_info.page_mask;
412#endif
413
414 return head;
415}
416
417/** Calls agp_allocate_memory() */
418DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type)
419{
420 return agp_allocate_memory(bridge, pages, type);
421}
422
423/** Calls agp_free_memory() */
424int drm_agp_free_memory(DRM_AGP_MEM *handle)
425{
426 if (!handle)
427 return 0;
428 agp_free_memory(handle);
429 return 1;
430}
431
432/** Calls agp_bind_memory() */
433int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start)
434{
435 if (!handle)
436 return -EINVAL;
437 return agp_bind_memory(handle, start);
438}
439
440/** Calls agp_unbind_memory() */
441int drm_agp_unbind_memory(DRM_AGP_MEM *handle)
442{
443 if (!handle)
444 return -EINVAL;
445 return agp_unbind_memory(handle);
446}
447
448#endif /* __OS_HAS_AGP */
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
new file mode 100644
index 000000000000..b428761c4e91
--- /dev/null
+++ b/drivers/char/drm/drm_auth.c
@@ -0,0 +1,230 @@
1/**
2 * \file drm_auth.h
3 * IOCTLs for authentication
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
11 *
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include "drmP.h"
37
38/**
39 * Generate a hash key from a magic.
40 *
41 * \param magic magic.
42 * \return hash key.
43 *
44 * The key is the modulus of the hash table size, #DRM_HASH_SIZE, which must be
45 * a power of 2.
46 */
47static int drm_hash_magic(drm_magic_t magic)
48{
49 return magic & (DRM_HASH_SIZE-1);
50}
51
52/**
53 * Find the file with the given magic number.
54 *
55 * \param dev DRM device.
56 * \param magic magic number.
57 *
58 * Searches in drm_device::magiclist within all files with the same hash key
59 * the one with matching magic number, while holding the drm_device::struct_sem
60 * lock.
61 */
62static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
63{
64 drm_file_t *retval = NULL;
65 drm_magic_entry_t *pt;
66 int hash = drm_hash_magic(magic);
67
68 down(&dev->struct_sem);
69 for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
70 if (pt->magic == magic) {
71 retval = pt->priv;
72 break;
73 }
74 }
75 up(&dev->struct_sem);
76 return retval;
77}
78
79/**
80 * Adds a magic number.
81 *
82 * \param dev DRM device.
83 * \param priv file private data.
84 * \param magic magic number.
85 *
86 * Creates a drm_magic_entry structure and appends to the linked list
87 * associated the magic number hash key in drm_device::magiclist, while holding
88 * the drm_device::struct_sem lock.
89 */
90int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
91{
92 int hash;
93 drm_magic_entry_t *entry;
94
95 DRM_DEBUG("%d\n", magic);
96
97 hash = drm_hash_magic(magic);
98 entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
99 if (!entry) return -ENOMEM;
100 memset(entry, 0, sizeof(*entry));
101 entry->magic = magic;
102 entry->priv = priv;
103 entry->next = NULL;
104
105 down(&dev->struct_sem);
106 if (dev->magiclist[hash].tail) {
107 dev->magiclist[hash].tail->next = entry;
108 dev->magiclist[hash].tail = entry;
109 } else {
110 dev->magiclist[hash].head = entry;
111 dev->magiclist[hash].tail = entry;
112 }
113 up(&dev->struct_sem);
114
115 return 0;
116}
117
118/**
119 * Remove a magic number.
120 *
121 * \param dev DRM device.
122 * \param magic magic number.
123 *
124 * Searches and unlinks the entry in drm_device::magiclist with the magic
125 * number hash key, while holding the drm_device::struct_sem lock.
126 */
127int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
128{
129 drm_magic_entry_t *prev = NULL;
130 drm_magic_entry_t *pt;
131 int hash;
132
133
134 DRM_DEBUG("%d\n", magic);
135 hash = drm_hash_magic(magic);
136
137 down(&dev->struct_sem);
138 for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
139 if (pt->magic == magic) {
140 if (dev->magiclist[hash].head == pt) {
141 dev->magiclist[hash].head = pt->next;
142 }
143 if (dev->magiclist[hash].tail == pt) {
144 dev->magiclist[hash].tail = prev;
145 }
146 if (prev) {
147 prev->next = pt->next;
148 }
149 up(&dev->struct_sem);
150 return 0;
151 }
152 }
153 up(&dev->struct_sem);
154
155 drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
156
157 return -EINVAL;
158}
159
160/**
161 * Get a unique magic number (ioctl).
162 *
163 * \param inode device inode.
164 * \param filp file pointer.
165 * \param cmd command.
166 * \param arg pointer to a resulting drm_auth structure.
167 * \return zero on success, or a negative number on failure.
168 *
169 * If there is a magic number in drm_file::magic then use it, otherwise
170 * searches an unique non-zero magic number and add it associating it with \p
171 * filp.
172 */
173int drm_getmagic(struct inode *inode, struct file *filp,
174 unsigned int cmd, unsigned long arg)
175{
176 static drm_magic_t sequence = 0;
177 static DEFINE_SPINLOCK(lock);
178 drm_file_t *priv = filp->private_data;
179 drm_device_t *dev = priv->head->dev;
180 drm_auth_t auth;
181
182 /* Find unique magic */
183 if (priv->magic) {
184 auth.magic = priv->magic;
185 } else {
186 do {
187 spin_lock(&lock);
188 if (!sequence) ++sequence; /* reserve 0 */
189 auth.magic = sequence++;
190 spin_unlock(&lock);
191 } while (drm_find_file(dev, auth.magic));
192 priv->magic = auth.magic;
193 drm_add_magic(dev, priv, auth.magic);
194 }
195
196 DRM_DEBUG("%u\n", auth.magic);
197 if (copy_to_user((drm_auth_t __user *)arg, &auth, sizeof(auth)))
198 return -EFAULT;
199 return 0;
200}
201
202/**
203 * Authenticate with a magic.
204 *
205 * \param inode device inode.
206 * \param filp file pointer.
207 * \param cmd command.
208 * \param arg pointer to a drm_auth structure.
209 * \return zero if authentication successed, or a negative number otherwise.
210 *
211 * Checks if \p filp is associated with the magic number passed in \arg.
212 */
213int drm_authmagic(struct inode *inode, struct file *filp,
214 unsigned int cmd, unsigned long arg)
215{
216 drm_file_t *priv = filp->private_data;
217 drm_device_t *dev = priv->head->dev;
218 drm_auth_t auth;
219 drm_file_t *file;
220
221 if (copy_from_user(&auth, (drm_auth_t __user *)arg, sizeof(auth)))
222 return -EFAULT;
223 DRM_DEBUG("%u\n", auth.magic);
224 if ((file = drm_find_file(dev, auth.magic))) {
225 file->authenticated = 1;
226 drm_remove_magic(dev, auth.magic);
227 return 0;
228 }
229 return -EINVAL;
230}
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
new file mode 100644
index 000000000000..4113bcba67fe
--- /dev/null
+++ b/drivers/char/drm/drm_bufs.c
@@ -0,0 +1,1270 @@
1/**
2 * \file drm_bufs.h
3 * Generic buffer template
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
11 *
12 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include <linux/vmalloc.h>
37#include "drmP.h"
38
39/**
40 * Compute size order. Returns the exponent of the smaller power of two which
41 * is greater or equal to given number.
42 *
43 * \param size size.
44 * \return order.
45 *
46 * \todo Can be made faster.
47 */
48int drm_order( unsigned long size )
49{
50 int order;
51 unsigned long tmp;
52
53 for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++)
54 ;
55
56 if (size & (size - 1))
57 ++order;
58
59 return order;
60}
61EXPORT_SYMBOL(drm_order);
62
63/**
64 * Ioctl to specify a range of memory that is available for mapping by a non-root process.
65 *
66 * \param inode device inode.
67 * \param filp file pointer.
68 * \param cmd command.
69 * \param arg pointer to a drm_map structure.
70 * \return zero on success or a negative value on error.
71 *
72 * Adjusts the memory offset to its absolute value according to the mapping
73 * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
74 * applicable and if supported by the kernel.
75 */
76int drm_addmap( struct inode *inode, struct file *filp,
77 unsigned int cmd, unsigned long arg )
78{
79 drm_file_t *priv = filp->private_data;
80 drm_device_t *dev = priv->head->dev;
81 drm_map_t *map;
82 drm_map_t __user *argp = (void __user *)arg;
83 drm_map_list_t *list;
84
85 if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */
86
87 map = drm_alloc( sizeof(*map), DRM_MEM_MAPS );
88 if ( !map )
89 return -ENOMEM;
90
91 if ( copy_from_user( map, argp, sizeof(*map) ) ) {
92 drm_free( map, sizeof(*map), DRM_MEM_MAPS );
93 return -EFAULT;
94 }
95
96 /* Only allow shared memory to be removable since we only keep enough
97 * book keeping information about shared memory to allow for removal
98 * when processes fork.
99 */
100 if ( (map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM ) {
101 drm_free( map, sizeof(*map), DRM_MEM_MAPS );
102 return -EINVAL;
103 }
104 DRM_DEBUG( "offset = 0x%08lx, size = 0x%08lx, type = %d\n",
105 map->offset, map->size, map->type );
106 if ( (map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK)) ) {
107 drm_free( map, sizeof(*map), DRM_MEM_MAPS );
108 return -EINVAL;
109 }
110 map->mtrr = -1;
111 map->handle = NULL;
112
113 switch ( map->type ) {
114 case _DRM_REGISTERS:
115 case _DRM_FRAME_BUFFER:
116#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__)
117 if ( map->offset + map->size < map->offset ||
118 map->offset < virt_to_phys(high_memory) ) {
119 drm_free( map, sizeof(*map), DRM_MEM_MAPS );
120 return -EINVAL;
121 }
122#endif
123#ifdef __alpha__
124 map->offset += dev->hose->mem_space->start;
125#endif
126 if (drm_core_has_MTRR(dev)) {
127 if ( map->type == _DRM_FRAME_BUFFER ||
128 (map->flags & _DRM_WRITE_COMBINING) ) {
129 map->mtrr = mtrr_add( map->offset, map->size,
130 MTRR_TYPE_WRCOMB, 1 );
131 }
132 }
133 if (map->type == _DRM_REGISTERS)
134 map->handle = drm_ioremap( map->offset, map->size,
135 dev );
136 break;
137
138 case _DRM_SHM:
139 map->handle = vmalloc_32(map->size);
140 DRM_DEBUG( "%lu %d %p\n",
141 map->size, drm_order( map->size ), map->handle );
142 if ( !map->handle ) {
143 drm_free( map, sizeof(*map), DRM_MEM_MAPS );
144 return -ENOMEM;
145 }
146 map->offset = (unsigned long)map->handle;
147 if ( map->flags & _DRM_CONTAINS_LOCK ) {
148 /* Prevent a 2nd X Server from creating a 2nd lock */
149 if (dev->lock.hw_lock != NULL) {
150 vfree( map->handle );
151 drm_free( map, sizeof(*map), DRM_MEM_MAPS );
152 return -EBUSY;
153 }
154 dev->sigdata.lock =
155 dev->lock.hw_lock = map->handle; /* Pointer to lock */
156 }
157 break;
158 case _DRM_AGP:
159 if (drm_core_has_AGP(dev)) {
160#ifdef __alpha__
161 map->offset += dev->hose->mem_space->start;
162#endif
163 map->offset += dev->agp->base;
164 map->mtrr = dev->agp->agp_mtrr; /* for getmap */
165 }
166 break;
167 case _DRM_SCATTER_GATHER:
168 if (!dev->sg) {
169 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
170 return -EINVAL;
171 }
172 map->offset += dev->sg->handle;
173 break;
174
175 default:
176 drm_free( map, sizeof(*map), DRM_MEM_MAPS );
177 return -EINVAL;
178 }
179
180 list = drm_alloc(sizeof(*list), DRM_MEM_MAPS);
181 if(!list) {
182 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
183 return -EINVAL;
184 }
185 memset(list, 0, sizeof(*list));
186 list->map = map;
187
188 down(&dev->struct_sem);
189 list_add(&list->head, &dev->maplist->head);
190 up(&dev->struct_sem);
191
192 if ( copy_to_user( argp, map, sizeof(*map) ) )
193 return -EFAULT;
194 if ( map->type != _DRM_SHM ) {
195 if ( copy_to_user( &argp->handle,
196 &map->offset,
197 sizeof(map->offset) ) )
198 return -EFAULT;
199 }
200 return 0;
201}
202
203
204/**
205 * Remove a map private from list and deallocate resources if the mapping
206 * isn't in use.
207 *
208 * \param inode device inode.
209 * \param filp file pointer.
210 * \param cmd command.
211 * \param arg pointer to a drm_map_t structure.
212 * \return zero on success or a negative value on error.
213 *
214 * Searches the map on drm_device::maplist, removes it from the list, see if
215 * its being used, and free any associate resource (such as MTRR's) if it's not
216 * being on use.
217 *
218 * \sa addmap().
219 */
220int drm_rmmap(struct inode *inode, struct file *filp,
221 unsigned int cmd, unsigned long arg)
222{
223 drm_file_t *priv = filp->private_data;
224 drm_device_t *dev = priv->head->dev;
225 struct list_head *list;
226 drm_map_list_t *r_list = NULL;
227 drm_vma_entry_t *pt, *prev;
228 drm_map_t *map;
229 drm_map_t request;
230 int found_maps = 0;
231
232 if (copy_from_user(&request, (drm_map_t __user *)arg,
233 sizeof(request))) {
234 return -EFAULT;
235 }
236
237 down(&dev->struct_sem);
238 list = &dev->maplist->head;
239 list_for_each(list, &dev->maplist->head) {
240 r_list = list_entry(list, drm_map_list_t, head);
241
242 if(r_list->map &&
243 r_list->map->handle == request.handle &&
244 r_list->map->flags & _DRM_REMOVABLE) break;
245 }
246
247 /* List has wrapped around to the head pointer, or its empty we didn't
248 * find anything.
249 */
250 if(list == (&dev->maplist->head)) {
251 up(&dev->struct_sem);
252 return -EINVAL;
253 }
254 map = r_list->map;
255 list_del(list);
256 drm_free(list, sizeof(*list), DRM_MEM_MAPS);
257
258 for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
259 if (pt->vma->vm_private_data == map) found_maps++;
260 }
261
262 if(!found_maps) {
263 switch (map->type) {
264 case _DRM_REGISTERS:
265 case _DRM_FRAME_BUFFER:
266 if (drm_core_has_MTRR(dev)) {
267 if (map->mtrr >= 0) {
268 int retcode;
269 retcode = mtrr_del(map->mtrr,
270 map->offset,
271 map->size);
272 DRM_DEBUG("mtrr_del = %d\n", retcode);
273 }
274 }
275 drm_ioremapfree(map->handle, map->size, dev);
276 break;
277 case _DRM_SHM:
278 vfree(map->handle);
279 break;
280 case _DRM_AGP:
281 case _DRM_SCATTER_GATHER:
282 break;
283 }
284 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
285 }
286 up(&dev->struct_sem);
287 return 0;
288}
289
290/**
291 * Cleanup after an error on one of the addbufs() functions.
292 *
293 * \param entry buffer entry where the error occurred.
294 *
295 * Frees any pages and buffers associated with the given entry.
296 */
297static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
298{
299 int i;
300
301 if (entry->seg_count) {
302 for (i = 0; i < entry->seg_count; i++) {
303 if (entry->seglist[i]) {
304 drm_free_pages(entry->seglist[i],
305 entry->page_order,
306 DRM_MEM_DMA);
307 }
308 }
309 drm_free(entry->seglist,
310 entry->seg_count *
311 sizeof(*entry->seglist),
312 DRM_MEM_SEGS);
313
314 entry->seg_count = 0;
315 }
316
317 if (entry->buf_count) {
318 for (i = 0; i < entry->buf_count; i++) {
319 if (entry->buflist[i].dev_private) {
320 drm_free(entry->buflist[i].dev_private,
321 entry->buflist[i].dev_priv_size,
322 DRM_MEM_BUFS);
323 }
324 }
325 drm_free(entry->buflist,
326 entry->buf_count *
327 sizeof(*entry->buflist),
328 DRM_MEM_BUFS);
329
330 entry->buf_count = 0;
331 }
332}
333
334#if __OS_HAS_AGP
335/**
336 * Add AGP buffers for DMA transfers (ioctl).
337 *
338 * \param inode device inode.
339 * \param filp file pointer.
340 * \param cmd command.
341 * \param arg pointer to a drm_buf_desc_t request.
342 * \return zero on success or a negative number on failure.
343 *
344 * After some sanity checks creates a drm_buf structure for each buffer and
345 * reallocates the buffer list of the same size order to accommodate the new
346 * buffers.
347 */
348int drm_addbufs_agp( struct inode *inode, struct file *filp,
349 unsigned int cmd, unsigned long arg )
350{
351 drm_file_t *priv = filp->private_data;
352 drm_device_t *dev = priv->head->dev;
353 drm_device_dma_t *dma = dev->dma;
354 drm_buf_desc_t request;
355 drm_buf_entry_t *entry;
356 drm_buf_t *buf;
357 unsigned long offset;
358 unsigned long agp_offset;
359 int count;
360 int order;
361 int size;
362 int alignment;
363 int page_order;
364 int total;
365 int byte_count;
366 int i;
367 drm_buf_t **temp_buflist;
368 drm_buf_desc_t __user *argp = (void __user *)arg;
369
370 if ( !dma ) return -EINVAL;
371
372 if ( copy_from_user( &request, argp,
373 sizeof(request) ) )
374 return -EFAULT;
375
376 count = request.count;
377 order = drm_order( request.size );
378 size = 1 << order;
379
380 alignment = (request.flags & _DRM_PAGE_ALIGN)
381 ? PAGE_ALIGN(size) : size;
382 page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
383 total = PAGE_SIZE << page_order;
384
385 byte_count = 0;
386 agp_offset = dev->agp->base + request.agp_start;
387
388 DRM_DEBUG( "count: %d\n", count );
389 DRM_DEBUG( "order: %d\n", order );
390 DRM_DEBUG( "size: %d\n", size );
391 DRM_DEBUG( "agp_offset: %lu\n", agp_offset );
392 DRM_DEBUG( "alignment: %d\n", alignment );
393 DRM_DEBUG( "page_order: %d\n", page_order );
394 DRM_DEBUG( "total: %d\n", total );
395
396 if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
397 if ( dev->queue_count ) return -EBUSY; /* Not while in use */
398
399 spin_lock( &dev->count_lock );
400 if ( dev->buf_use ) {
401 spin_unlock( &dev->count_lock );
402 return -EBUSY;
403 }
404 atomic_inc( &dev->buf_alloc );
405 spin_unlock( &dev->count_lock );
406
407 down( &dev->struct_sem );
408 entry = &dma->bufs[order];
409 if ( entry->buf_count ) {
410 up( &dev->struct_sem );
411 atomic_dec( &dev->buf_alloc );
412 return -ENOMEM; /* May only call once for each order */
413 }
414
415 if (count < 0 || count > 4096) {
416 up( &dev->struct_sem );
417 atomic_dec( &dev->buf_alloc );
418 return -EINVAL;
419 }
420
421 entry->buflist = drm_alloc( count * sizeof(*entry->buflist),
422 DRM_MEM_BUFS );
423 if ( !entry->buflist ) {
424 up( &dev->struct_sem );
425 atomic_dec( &dev->buf_alloc );
426 return -ENOMEM;
427 }
428 memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
429
430 entry->buf_size = size;
431 entry->page_order = page_order;
432
433 offset = 0;
434
435 while ( entry->buf_count < count ) {
436 buf = &entry->buflist[entry->buf_count];
437 buf->idx = dma->buf_count + entry->buf_count;
438 buf->total = alignment;
439 buf->order = order;
440 buf->used = 0;
441
442 buf->offset = (dma->byte_count + offset);
443 buf->bus_address = agp_offset + offset;
444 buf->address = (void *)(agp_offset + offset);
445 buf->next = NULL;
446 buf->waiting = 0;
447 buf->pending = 0;
448 init_waitqueue_head( &buf->dma_wait );
449 buf->filp = NULL;
450
451 buf->dev_priv_size = dev->driver->dev_priv_size;
452 buf->dev_private = drm_alloc( buf->dev_priv_size,
453 DRM_MEM_BUFS );
454 if(!buf->dev_private) {
455 /* Set count correctly so we free the proper amount. */
456 entry->buf_count = count;
457 drm_cleanup_buf_error(dev,entry);
458 up( &dev->struct_sem );
459 atomic_dec( &dev->buf_alloc );
460 return -ENOMEM;
461 }
462 memset( buf->dev_private, 0, buf->dev_priv_size );
463
464 DRM_DEBUG( "buffer %d @ %p\n",
465 entry->buf_count, buf->address );
466
467 offset += alignment;
468 entry->buf_count++;
469 byte_count += PAGE_SIZE << page_order;
470 }
471
472 DRM_DEBUG( "byte_count: %d\n", byte_count );
473
474 temp_buflist = drm_realloc( dma->buflist,
475 dma->buf_count * sizeof(*dma->buflist),
476 (dma->buf_count + entry->buf_count)
477 * sizeof(*dma->buflist),
478 DRM_MEM_BUFS );
479 if(!temp_buflist) {
480 /* Free the entry because it isn't valid */
481 drm_cleanup_buf_error(dev,entry);
482 up( &dev->struct_sem );
483 atomic_dec( &dev->buf_alloc );
484 return -ENOMEM;
485 }
486 dma->buflist = temp_buflist;
487
488 for ( i = 0 ; i < entry->buf_count ; i++ ) {
489 dma->buflist[i + dma->buf_count] = &entry->buflist[i];
490 }
491
492 dma->buf_count += entry->buf_count;
493 dma->byte_count += byte_count;
494
495 DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
496 DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
497
498 up( &dev->struct_sem );
499
500 request.count = entry->buf_count;
501 request.size = size;
502
503 if ( copy_to_user( argp, &request, sizeof(request) ) )
504 return -EFAULT;
505
506 dma->flags = _DRM_DMA_USE_AGP;
507
508 atomic_dec( &dev->buf_alloc );
509 return 0;
510}
511#endif /* __OS_HAS_AGP */
512
513int drm_addbufs_pci( struct inode *inode, struct file *filp,
514 unsigned int cmd, unsigned long arg )
515{
516 drm_file_t *priv = filp->private_data;
517 drm_device_t *dev = priv->head->dev;
518 drm_device_dma_t *dma = dev->dma;
519 drm_buf_desc_t request;
520 int count;
521 int order;
522 int size;
523 int total;
524 int page_order;
525 drm_buf_entry_t *entry;
526 unsigned long page;
527 drm_buf_t *buf;
528 int alignment;
529 unsigned long offset;
530 int i;
531 int byte_count;
532 int page_count;
533 unsigned long *temp_pagelist;
534 drm_buf_t **temp_buflist;
535 drm_buf_desc_t __user *argp = (void __user *)arg;
536
537 if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL;
538 if ( !dma ) return -EINVAL;
539
540 if ( copy_from_user( &request, argp, sizeof(request) ) )
541 return -EFAULT;
542
543 count = request.count;
544 order = drm_order( request.size );
545 size = 1 << order;
546
547 DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n",
548 request.count, request.size, size,
549 order, dev->queue_count );
550
551 if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
552 if ( dev->queue_count ) return -EBUSY; /* Not while in use */
553
554 alignment = (request.flags & _DRM_PAGE_ALIGN)
555 ? PAGE_ALIGN(size) : size;
556 page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
557 total = PAGE_SIZE << page_order;
558
559 spin_lock( &dev->count_lock );
560 if ( dev->buf_use ) {
561 spin_unlock( &dev->count_lock );
562 return -EBUSY;
563 }
564 atomic_inc( &dev->buf_alloc );
565 spin_unlock( &dev->count_lock );
566
567 down( &dev->struct_sem );
568 entry = &dma->bufs[order];
569 if ( entry->buf_count ) {
570 up( &dev->struct_sem );
571 atomic_dec( &dev->buf_alloc );
572 return -ENOMEM; /* May only call once for each order */
573 }
574
575 if (count < 0 || count > 4096) {
576 up( &dev->struct_sem );
577 atomic_dec( &dev->buf_alloc );
578 return -EINVAL;
579 }
580
581 entry->buflist = drm_alloc( count * sizeof(*entry->buflist),
582 DRM_MEM_BUFS );
583 if ( !entry->buflist ) {
584 up( &dev->struct_sem );
585 atomic_dec( &dev->buf_alloc );
586 return -ENOMEM;
587 }
588 memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
589
590 entry->seglist = drm_alloc( count * sizeof(*entry->seglist),
591 DRM_MEM_SEGS );
592 if ( !entry->seglist ) {
593 drm_free( entry->buflist,
594 count * sizeof(*entry->buflist),
595 DRM_MEM_BUFS );
596 up( &dev->struct_sem );
597 atomic_dec( &dev->buf_alloc );
598 return -ENOMEM;
599 }
600 memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
601
602 /* Keep the original pagelist until we know all the allocations
603 * have succeeded
604 */
605 temp_pagelist = drm_alloc( (dma->page_count + (count << page_order))
606 * sizeof(*dma->pagelist),
607 DRM_MEM_PAGES );
608 if (!temp_pagelist) {
609 drm_free( entry->buflist,
610 count * sizeof(*entry->buflist),
611 DRM_MEM_BUFS );
612 drm_free( entry->seglist,
613 count * sizeof(*entry->seglist),
614 DRM_MEM_SEGS );
615 up( &dev->struct_sem );
616 atomic_dec( &dev->buf_alloc );
617 return -ENOMEM;
618 }
619 memcpy(temp_pagelist,
620 dma->pagelist,
621 dma->page_count * sizeof(*dma->pagelist));
622 DRM_DEBUG( "pagelist: %d entries\n",
623 dma->page_count + (count << page_order) );
624
625 entry->buf_size = size;
626 entry->page_order = page_order;
627 byte_count = 0;
628 page_count = 0;
629
630 while ( entry->buf_count < count ) {
631 page = drm_alloc_pages( page_order, DRM_MEM_DMA );
632 if ( !page ) {
633 /* Set count correctly so we free the proper amount. */
634 entry->buf_count = count;
635 entry->seg_count = count;
636 drm_cleanup_buf_error(dev, entry);
637 drm_free( temp_pagelist,
638 (dma->page_count + (count << page_order))
639 * sizeof(*dma->pagelist),
640 DRM_MEM_PAGES );
641 up( &dev->struct_sem );
642 atomic_dec( &dev->buf_alloc );
643 return -ENOMEM;
644 }
645 entry->seglist[entry->seg_count++] = page;
646 for ( i = 0 ; i < (1 << page_order) ; i++ ) {
647 DRM_DEBUG( "page %d @ 0x%08lx\n",
648 dma->page_count + page_count,
649 page + PAGE_SIZE * i );
650 temp_pagelist[dma->page_count + page_count++]
651 = page + PAGE_SIZE * i;
652 }
653 for ( offset = 0 ;
654 offset + size <= total && entry->buf_count < count ;
655 offset += alignment, ++entry->buf_count ) {
656 buf = &entry->buflist[entry->buf_count];
657 buf->idx = dma->buf_count + entry->buf_count;
658 buf->total = alignment;
659 buf->order = order;
660 buf->used = 0;
661 buf->offset = (dma->byte_count + byte_count + offset);
662 buf->address = (void *)(page + offset);
663 buf->next = NULL;
664 buf->waiting = 0;
665 buf->pending = 0;
666 init_waitqueue_head( &buf->dma_wait );
667 buf->filp = NULL;
668
669 buf->dev_priv_size = dev->driver->dev_priv_size;
670 buf->dev_private = drm_alloc( buf->dev_priv_size,
671 DRM_MEM_BUFS );
672 if(!buf->dev_private) {
673 /* Set count correctly so we free the proper amount. */
674 entry->buf_count = count;
675 entry->seg_count = count;
676 drm_cleanup_buf_error(dev,entry);
677 drm_free( temp_pagelist,
678 (dma->page_count + (count << page_order))
679 * sizeof(*dma->pagelist),
680 DRM_MEM_PAGES );
681 up( &dev->struct_sem );
682 atomic_dec( &dev->buf_alloc );
683 return -ENOMEM;
684 }
685 memset( buf->dev_private, 0, buf->dev_priv_size );
686
687 DRM_DEBUG( "buffer %d @ %p\n",
688 entry->buf_count, buf->address );
689 }
690 byte_count += PAGE_SIZE << page_order;
691 }
692
693 temp_buflist = drm_realloc( dma->buflist,
694 dma->buf_count * sizeof(*dma->buflist),
695 (dma->buf_count + entry->buf_count)
696 * sizeof(*dma->buflist),
697 DRM_MEM_BUFS );
698 if (!temp_buflist) {
699 /* Free the entry because it isn't valid */
700 drm_cleanup_buf_error(dev,entry);
701 drm_free( temp_pagelist,
702 (dma->page_count + (count << page_order))
703 * sizeof(*dma->pagelist),
704 DRM_MEM_PAGES );
705 up( &dev->struct_sem );
706 atomic_dec( &dev->buf_alloc );
707 return -ENOMEM;
708 }
709 dma->buflist = temp_buflist;
710
711 for ( i = 0 ; i < entry->buf_count ; i++ ) {
712 dma->buflist[i + dma->buf_count] = &entry->buflist[i];
713 }
714
715 /* No allocations failed, so now we can replace the orginal pagelist
716 * with the new one.
717 */
718 if (dma->page_count) {
719 drm_free(dma->pagelist,
720 dma->page_count * sizeof(*dma->pagelist),
721 DRM_MEM_PAGES);
722 }
723 dma->pagelist = temp_pagelist;
724
725 dma->buf_count += entry->buf_count;
726 dma->seg_count += entry->seg_count;
727 dma->page_count += entry->seg_count << page_order;
728 dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
729
730 up( &dev->struct_sem );
731
732 request.count = entry->buf_count;
733 request.size = size;
734
735 if ( copy_to_user( argp, &request, sizeof(request) ) )
736 return -EFAULT;
737
738 atomic_dec( &dev->buf_alloc );
739 return 0;
740
741}
742
743int drm_addbufs_sg( struct inode *inode, struct file *filp,
744 unsigned int cmd, unsigned long arg )
745{
746 drm_file_t *priv = filp->private_data;
747 drm_device_t *dev = priv->head->dev;
748 drm_device_dma_t *dma = dev->dma;
749 drm_buf_desc_t __user *argp = (void __user *)arg;
750 drm_buf_desc_t request;
751 drm_buf_entry_t *entry;
752 drm_buf_t *buf;
753 unsigned long offset;
754 unsigned long agp_offset;
755 int count;
756 int order;
757 int size;
758 int alignment;
759 int page_order;
760 int total;
761 int byte_count;
762 int i;
763 drm_buf_t **temp_buflist;
764
765 if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL;
766
767 if ( !dma ) return -EINVAL;
768
769 if ( copy_from_user( &request, argp, sizeof(request) ) )
770 return -EFAULT;
771
772 count = request.count;
773 order = drm_order( request.size );
774 size = 1 << order;
775
776 alignment = (request.flags & _DRM_PAGE_ALIGN)
777 ? PAGE_ALIGN(size) : size;
778 page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
779 total = PAGE_SIZE << page_order;
780
781 byte_count = 0;
782 agp_offset = request.agp_start;
783
784 DRM_DEBUG( "count: %d\n", count );
785 DRM_DEBUG( "order: %d\n", order );
786 DRM_DEBUG( "size: %d\n", size );
787 DRM_DEBUG( "agp_offset: %lu\n", agp_offset );
788 DRM_DEBUG( "alignment: %d\n", alignment );
789 DRM_DEBUG( "page_order: %d\n", page_order );
790 DRM_DEBUG( "total: %d\n", total );
791
792 if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
793 if ( dev->queue_count ) return -EBUSY; /* Not while in use */
794
795 spin_lock( &dev->count_lock );
796 if ( dev->buf_use ) {
797 spin_unlock( &dev->count_lock );
798 return -EBUSY;
799 }
800 atomic_inc( &dev->buf_alloc );
801 spin_unlock( &dev->count_lock );
802
803 down( &dev->struct_sem );
804 entry = &dma->bufs[order];
805 if ( entry->buf_count ) {
806 up( &dev->struct_sem );
807 atomic_dec( &dev->buf_alloc );
808 return -ENOMEM; /* May only call once for each order */
809 }
810
811 if (count < 0 || count > 4096) {
812 up( &dev->struct_sem );
813 atomic_dec( &dev->buf_alloc );
814 return -EINVAL;
815 }
816
817 entry->buflist = drm_alloc( count * sizeof(*entry->buflist),
818 DRM_MEM_BUFS );
819 if ( !entry->buflist ) {
820 up( &dev->struct_sem );
821 atomic_dec( &dev->buf_alloc );
822 return -ENOMEM;
823 }
824 memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
825
826 entry->buf_size = size;
827 entry->page_order = page_order;
828
829 offset = 0;
830
831 while ( entry->buf_count < count ) {
832 buf = &entry->buflist[entry->buf_count];
833 buf->idx = dma->buf_count + entry->buf_count;
834 buf->total = alignment;
835 buf->order = order;
836 buf->used = 0;
837
838 buf->offset = (dma->byte_count + offset);
839 buf->bus_address = agp_offset + offset;
840 buf->address = (void *)(agp_offset + offset + dev->sg->handle);
841 buf->next = NULL;
842 buf->waiting = 0;
843 buf->pending = 0;
844 init_waitqueue_head( &buf->dma_wait );
845 buf->filp = NULL;
846
847 buf->dev_priv_size = dev->driver->dev_priv_size;
848 buf->dev_private = drm_alloc( buf->dev_priv_size,
849 DRM_MEM_BUFS );
850 if(!buf->dev_private) {
851 /* Set count correctly so we free the proper amount. */
852 entry->buf_count = count;
853 drm_cleanup_buf_error(dev,entry);
854 up( &dev->struct_sem );
855 atomic_dec( &dev->buf_alloc );
856 return -ENOMEM;
857 }
858
859 memset( buf->dev_private, 0, buf->dev_priv_size );
860
861 DRM_DEBUG( "buffer %d @ %p\n",
862 entry->buf_count, buf->address );
863
864 offset += alignment;
865 entry->buf_count++;
866 byte_count += PAGE_SIZE << page_order;
867 }
868
869 DRM_DEBUG( "byte_count: %d\n", byte_count );
870
871 temp_buflist = drm_realloc( dma->buflist,
872 dma->buf_count * sizeof(*dma->buflist),
873 (dma->buf_count + entry->buf_count)
874 * sizeof(*dma->buflist),
875 DRM_MEM_BUFS );
876 if(!temp_buflist) {
877 /* Free the entry because it isn't valid */
878 drm_cleanup_buf_error(dev,entry);
879 up( &dev->struct_sem );
880 atomic_dec( &dev->buf_alloc );
881 return -ENOMEM;
882 }
883 dma->buflist = temp_buflist;
884
885 for ( i = 0 ; i < entry->buf_count ; i++ ) {
886 dma->buflist[i + dma->buf_count] = &entry->buflist[i];
887 }
888
889 dma->buf_count += entry->buf_count;
890 dma->byte_count += byte_count;
891
892 DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
893 DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
894
895 up( &dev->struct_sem );
896
897 request.count = entry->buf_count;
898 request.size = size;
899
900 if ( copy_to_user( argp, &request, sizeof(request) ) )
901 return -EFAULT;
902
903 dma->flags = _DRM_DMA_USE_SG;
904
905 atomic_dec( &dev->buf_alloc );
906 return 0;
907}
908
909/**
910 * Add buffers for DMA transfers (ioctl).
911 *
912 * \param inode device inode.
913 * \param filp file pointer.
914 * \param cmd command.
915 * \param arg pointer to a drm_buf_desc_t request.
916 * \return zero on success or a negative number on failure.
917 *
918 * According with the memory type specified in drm_buf_desc::flags and the
919 * build options, it dispatches the call either to addbufs_agp(),
920 * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
921 * PCI memory respectively.
922 */
923int drm_addbufs( struct inode *inode, struct file *filp,
924 unsigned int cmd, unsigned long arg )
925{
926 drm_buf_desc_t request;
927 drm_file_t *priv = filp->private_data;
928 drm_device_t *dev = priv->head->dev;
929
930 if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
931 return -EINVAL;
932
933 if ( copy_from_user( &request, (drm_buf_desc_t __user *)arg,
934 sizeof(request) ) )
935 return -EFAULT;
936
937#if __OS_HAS_AGP
938 if ( request.flags & _DRM_AGP_BUFFER )
939 return drm_addbufs_agp( inode, filp, cmd, arg );
940 else
941#endif
942 if ( request.flags & _DRM_SG_BUFFER )
943 return drm_addbufs_sg( inode, filp, cmd, arg );
944 else
945 return drm_addbufs_pci( inode, filp, cmd, arg );
946}
947
948
949/**
950 * Get information about the buffer mappings.
951 *
952 * This was originally mean for debugging purposes, or by a sophisticated
953 * client library to determine how best to use the available buffers (e.g.,
954 * large buffers can be used for image transfer).
955 *
956 * \param inode device inode.
957 * \param filp file pointer.
958 * \param cmd command.
959 * \param arg pointer to a drm_buf_info structure.
960 * \return zero on success or a negative number on failure.
961 *
962 * Increments drm_device::buf_use while holding the drm_device::count_lock
963 * lock, preventing of allocating more buffers after this call. Information
964 * about each requested buffer is then copied into user space.
965 */
966int drm_infobufs( struct inode *inode, struct file *filp,
967 unsigned int cmd, unsigned long arg )
968{
969 drm_file_t *priv = filp->private_data;
970 drm_device_t *dev = priv->head->dev;
971 drm_device_dma_t *dma = dev->dma;
972 drm_buf_info_t request;
973 drm_buf_info_t __user *argp = (void __user *)arg;
974 int i;
975 int count;
976
977 if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
978 return -EINVAL;
979
980 if ( !dma ) return -EINVAL;
981
982 spin_lock( &dev->count_lock );
983 if ( atomic_read( &dev->buf_alloc ) ) {
984 spin_unlock( &dev->count_lock );
985 return -EBUSY;
986 }
987 ++dev->buf_use; /* Can't allocate more after this call */
988 spin_unlock( &dev->count_lock );
989
990 if ( copy_from_user( &request, argp, sizeof(request) ) )
991 return -EFAULT;
992
993 for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
994 if ( dma->bufs[i].buf_count ) ++count;
995 }
996
997 DRM_DEBUG( "count = %d\n", count );
998
999 if ( request.count >= count ) {
1000 for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
1001 if ( dma->bufs[i].buf_count ) {
1002 drm_buf_desc_t __user *to = &request.list[count];
1003 drm_buf_entry_t *from = &dma->bufs[i];
1004 drm_freelist_t *list = &dma->bufs[i].freelist;
1005 if ( copy_to_user( &to->count,
1006 &from->buf_count,
1007 sizeof(from->buf_count) ) ||
1008 copy_to_user( &to->size,
1009 &from->buf_size,
1010 sizeof(from->buf_size) ) ||
1011 copy_to_user( &to->low_mark,
1012 &list->low_mark,
1013 sizeof(list->low_mark) ) ||
1014 copy_to_user( &to->high_mark,
1015 &list->high_mark,
1016 sizeof(list->high_mark) ) )
1017 return -EFAULT;
1018
1019 DRM_DEBUG( "%d %d %d %d %d\n",
1020 i,
1021 dma->bufs[i].buf_count,
1022 dma->bufs[i].buf_size,
1023 dma->bufs[i].freelist.low_mark,
1024 dma->bufs[i].freelist.high_mark );
1025 ++count;
1026 }
1027 }
1028 }
1029 request.count = count;
1030
1031 if ( copy_to_user( argp, &request, sizeof(request) ) )
1032 return -EFAULT;
1033
1034 return 0;
1035}
1036
1037/**
1038 * Specifies a low and high water mark for buffer allocation
1039 *
1040 * \param inode device inode.
1041 * \param filp file pointer.
1042 * \param cmd command.
1043 * \param arg a pointer to a drm_buf_desc structure.
1044 * \return zero on success or a negative number on failure.
1045 *
1046 * Verifies that the size order is bounded between the admissible orders and
1047 * updates the respective drm_device_dma::bufs entry low and high water mark.
1048 *
1049 * \note This ioctl is deprecated and mostly never used.
1050 */
1051int drm_markbufs( struct inode *inode, struct file *filp,
1052 unsigned int cmd, unsigned long arg )
1053{
1054 drm_file_t *priv = filp->private_data;
1055 drm_device_t *dev = priv->head->dev;
1056 drm_device_dma_t *dma = dev->dma;
1057 drm_buf_desc_t request;
1058 int order;
1059 drm_buf_entry_t *entry;
1060
1061 if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
1062 return -EINVAL;
1063
1064 if ( !dma ) return -EINVAL;
1065
1066 if ( copy_from_user( &request,
1067 (drm_buf_desc_t __user *)arg,
1068 sizeof(request) ) )
1069 return -EFAULT;
1070
1071 DRM_DEBUG( "%d, %d, %d\n",
1072 request.size, request.low_mark, request.high_mark );
1073 order = drm_order( request.size );
1074 if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
1075 entry = &dma->bufs[order];
1076
1077 if ( request.low_mark < 0 || request.low_mark > entry->buf_count )
1078 return -EINVAL;
1079 if ( request.high_mark < 0 || request.high_mark > entry->buf_count )
1080 return -EINVAL;
1081
1082 entry->freelist.low_mark = request.low_mark;
1083 entry->freelist.high_mark = request.high_mark;
1084
1085 return 0;
1086}
1087
1088/**
1089 * Unreserve the buffers in list, previously reserved using drmDMA.
1090 *
1091 * \param inode device inode.
1092 * \param filp file pointer.
1093 * \param cmd command.
1094 * \param arg pointer to a drm_buf_free structure.
1095 * \return zero on success or a negative number on failure.
1096 *
1097 * Calls free_buffer() for each used buffer.
1098 * This function is primarily used for debugging.
1099 */
1100int drm_freebufs( struct inode *inode, struct file *filp,
1101 unsigned int cmd, unsigned long arg )
1102{
1103 drm_file_t *priv = filp->private_data;
1104 drm_device_t *dev = priv->head->dev;
1105 drm_device_dma_t *dma = dev->dma;
1106 drm_buf_free_t request;
1107 int i;
1108 int idx;
1109 drm_buf_t *buf;
1110
1111 if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
1112 return -EINVAL;
1113
1114 if ( !dma ) return -EINVAL;
1115
1116 if ( copy_from_user( &request,
1117 (drm_buf_free_t __user *)arg,
1118 sizeof(request) ) )
1119 return -EFAULT;
1120
1121 DRM_DEBUG( "%d\n", request.count );
1122 for ( i = 0 ; i < request.count ; i++ ) {
1123 if ( copy_from_user( &idx,
1124 &request.list[i],
1125 sizeof(idx) ) )
1126 return -EFAULT;
1127 if ( idx < 0 || idx >= dma->buf_count ) {
1128 DRM_ERROR( "Index %d (of %d max)\n",
1129 idx, dma->buf_count - 1 );
1130 return -EINVAL;
1131 }
1132 buf = dma->buflist[idx];
1133 if ( buf->filp != filp ) {
1134 DRM_ERROR( "Process %d freeing buffer not owned\n",
1135 current->pid );
1136 return -EINVAL;
1137 }
1138 drm_free_buffer( dev, buf );
1139 }
1140
1141 return 0;
1142}
1143
1144/**
1145 * Maps all of the DMA buffers into client-virtual space (ioctl).
1146 *
1147 * \param inode device inode.
1148 * \param filp file pointer.
1149 * \param cmd command.
1150 * \param arg pointer to a drm_buf_map structure.
1151 * \return zero on success or a negative number on failure.
1152 *
1153 * Maps the AGP or SG buffer region with do_mmap(), and copies information
1154 * about each buffer into user space. The PCI buffers are already mapped on the
1155 * addbufs_pci() call.
1156 */
1157int drm_mapbufs( struct inode *inode, struct file *filp,
1158 unsigned int cmd, unsigned long arg )
1159{
1160 drm_file_t *priv = filp->private_data;
1161 drm_device_t *dev = priv->head->dev;
1162 drm_device_dma_t *dma = dev->dma;
1163 drm_buf_map_t __user *argp = (void __user *)arg;
1164 int retcode = 0;
1165 const int zero = 0;
1166 unsigned long virtual;
1167 unsigned long address;
1168 drm_buf_map_t request;
1169 int i;
1170
1171 if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
1172 return -EINVAL;
1173
1174 if ( !dma ) return -EINVAL;
1175
1176 spin_lock( &dev->count_lock );
1177 if ( atomic_read( &dev->buf_alloc ) ) {
1178 spin_unlock( &dev->count_lock );
1179 return -EBUSY;
1180 }
1181 dev->buf_use++; /* Can't allocate more after this call */
1182 spin_unlock( &dev->count_lock );
1183
1184 if ( copy_from_user( &request, argp, sizeof(request) ) )
1185 return -EFAULT;
1186
1187 if ( request.count >= dma->buf_count ) {
1188 if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) ||
1189 (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG)) ) {
1190 drm_map_t *map = dev->agp_buffer_map;
1191
1192 if ( !map ) {
1193 retcode = -EINVAL;
1194 goto done;
1195 }
1196
1197#if LINUX_VERSION_CODE <= 0x020402
1198 down( &current->mm->mmap_sem );
1199#else
1200 down_write( &current->mm->mmap_sem );
1201#endif
1202 virtual = do_mmap( filp, 0, map->size,
1203 PROT_READ | PROT_WRITE,
1204 MAP_SHARED,
1205 (unsigned long)map->offset );
1206#if LINUX_VERSION_CODE <= 0x020402
1207 up( &current->mm->mmap_sem );
1208#else
1209 up_write( &current->mm->mmap_sem );
1210#endif
1211 } else {
1212#if LINUX_VERSION_CODE <= 0x020402
1213 down( &current->mm->mmap_sem );
1214#else
1215 down_write( &current->mm->mmap_sem );
1216#endif
1217 virtual = do_mmap( filp, 0, dma->byte_count,
1218 PROT_READ | PROT_WRITE,
1219 MAP_SHARED, 0 );
1220#if LINUX_VERSION_CODE <= 0x020402
1221 up( &current->mm->mmap_sem );
1222#else
1223 up_write( &current->mm->mmap_sem );
1224#endif
1225 }
1226 if ( virtual > -1024UL ) {
1227 /* Real error */
1228 retcode = (signed long)virtual;
1229 goto done;
1230 }
1231 request.virtual = (void __user *)virtual;
1232
1233 for ( i = 0 ; i < dma->buf_count ; i++ ) {
1234 if ( copy_to_user( &request.list[i].idx,
1235 &dma->buflist[i]->idx,
1236 sizeof(request.list[0].idx) ) ) {
1237 retcode = -EFAULT;
1238 goto done;
1239 }
1240 if ( copy_to_user( &request.list[i].total,
1241 &dma->buflist[i]->total,
1242 sizeof(request.list[0].total) ) ) {
1243 retcode = -EFAULT;
1244 goto done;
1245 }
1246 if ( copy_to_user( &request.list[i].used,
1247 &zero,
1248 sizeof(zero) ) ) {
1249 retcode = -EFAULT;
1250 goto done;
1251 }
1252 address = virtual + dma->buflist[i]->offset; /* *** */
1253 if ( copy_to_user( &request.list[i].address,
1254 &address,
1255 sizeof(address) ) ) {
1256 retcode = -EFAULT;
1257 goto done;
1258 }
1259 }
1260 }
1261 done:
1262 request.count = dma->buf_count;
1263 DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode );
1264
1265 if ( copy_to_user( argp, &request, sizeof(request) ) )
1266 return -EFAULT;
1267
1268 return retcode;
1269}
1270
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
new file mode 100644
index 000000000000..f15c86c57875
--- /dev/null
+++ b/drivers/char/drm/drm_context.c
@@ -0,0 +1,578 @@
1/**
2 * \file drm_context.h
3 * IOCTLs for generic contexts
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
11 *
12 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36/*
37 * ChangeLog:
38 * 2001-11-16 Torsten Duwe <duwe@caldera.de>
39 * added context constructor/destructor hooks,
40 * needed by SiS driver's memory management.
41 */
42
43#include "drmP.h"
44
45/******************************************************************/
46/** \name Context bitmap support */
47/*@{*/
48
49/**
50 * Free a handle from the context bitmap.
51 *
52 * \param dev DRM device.
53 * \param ctx_handle context handle.
54 *
55 * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
56 * in drm_device::context_sareas, while holding the drm_device::struct_sem
57 * lock.
58 */
59void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle )
60{
61 if ( ctx_handle < 0 ) goto failed;
62 if ( !dev->ctx_bitmap ) goto failed;
63
64 if ( ctx_handle < DRM_MAX_CTXBITMAP ) {
65 down(&dev->struct_sem);
66 clear_bit( ctx_handle, dev->ctx_bitmap );
67 dev->context_sareas[ctx_handle] = NULL;
68 up(&dev->struct_sem);
69 return;
70 }
71failed:
72 DRM_ERROR( "Attempt to free invalid context handle: %d\n",
73 ctx_handle );
74 return;
75}
76
77/**
78 * Context bitmap allocation.
79 *
80 * \param dev DRM device.
81 * \return (non-negative) context handle on success or a negative number on failure.
82 *
83 * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
84 * drm_device::context_sareas to accommodate the new entry while holding the
85 * drm_device::struct_sem lock.
86 */
87int drm_ctxbitmap_next( drm_device_t *dev )
88{
89 int bit;
90
91 if(!dev->ctx_bitmap) return -1;
92
93 down(&dev->struct_sem);
94 bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
95 if ( bit < DRM_MAX_CTXBITMAP ) {
96 set_bit( bit, dev->ctx_bitmap );
97 DRM_DEBUG( "drm_ctxbitmap_next bit : %d\n", bit );
98 if((bit+1) > dev->max_context) {
99 dev->max_context = (bit+1);
100 if(dev->context_sareas) {
101 drm_map_t **ctx_sareas;
102
103 ctx_sareas = drm_realloc(dev->context_sareas,
104 (dev->max_context - 1) *
105 sizeof(*dev->context_sareas),
106 dev->max_context *
107 sizeof(*dev->context_sareas),
108 DRM_MEM_MAPS);
109 if(!ctx_sareas) {
110 clear_bit(bit, dev->ctx_bitmap);
111 up(&dev->struct_sem);
112 return -1;
113 }
114 dev->context_sareas = ctx_sareas;
115 dev->context_sareas[bit] = NULL;
116 } else {
117 /* max_context == 1 at this point */
118 dev->context_sareas = drm_alloc(
119 dev->max_context *
120 sizeof(*dev->context_sareas),
121 DRM_MEM_MAPS);
122 if(!dev->context_sareas) {
123 clear_bit(bit, dev->ctx_bitmap);
124 up(&dev->struct_sem);
125 return -1;
126 }
127 dev->context_sareas[bit] = NULL;
128 }
129 }
130 up(&dev->struct_sem);
131 return bit;
132 }
133 up(&dev->struct_sem);
134 return -1;
135}
136
137/**
138 * Context bitmap initialization.
139 *
140 * \param dev DRM device.
141 *
142 * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
143 * the drm_device::struct_sem lock.
144 */
145int drm_ctxbitmap_init( drm_device_t *dev )
146{
147 int i;
148 int temp;
149
150 down(&dev->struct_sem);
151 dev->ctx_bitmap = (unsigned long *) drm_alloc( PAGE_SIZE,
152 DRM_MEM_CTXBITMAP );
153 if ( dev->ctx_bitmap == NULL ) {
154 up(&dev->struct_sem);
155 return -ENOMEM;
156 }
157 memset( (void *)dev->ctx_bitmap, 0, PAGE_SIZE );
158 dev->context_sareas = NULL;
159 dev->max_context = -1;
160 up(&dev->struct_sem);
161
162 for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
163 temp = drm_ctxbitmap_next( dev );
164 DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp );
165 }
166
167 return 0;
168}
169
170/**
171 * Context bitmap cleanup.
172 *
173 * \param dev DRM device.
174 *
175 * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
176 * the drm_device::struct_sem lock.
177 */
178void drm_ctxbitmap_cleanup( drm_device_t *dev )
179{
180 down(&dev->struct_sem);
181 if( dev->context_sareas ) drm_free( dev->context_sareas,
182 sizeof(*dev->context_sareas) *
183 dev->max_context,
184 DRM_MEM_MAPS );
185 drm_free( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
186 up(&dev->struct_sem);
187}
188
189/*@}*/
190
191/******************************************************************/
192/** \name Per Context SAREA Support */
193/*@{*/
194
195/**
196 * Get per-context SAREA.
197 *
198 * \param inode device inode.
199 * \param filp file pointer.
200 * \param cmd command.
201 * \param arg user argument pointing to a drm_ctx_priv_map structure.
202 * \return zero on success or a negative number on failure.
203 *
204 * Gets the map from drm_device::context_sareas with the handle specified and
205 * returns its handle.
206 */
207int drm_getsareactx(struct inode *inode, struct file *filp,
208 unsigned int cmd, unsigned long arg)
209{
210 drm_file_t *priv = filp->private_data;
211 drm_device_t *dev = priv->head->dev;
212 drm_ctx_priv_map_t __user *argp = (void __user *)arg;
213 drm_ctx_priv_map_t request;
214 drm_map_t *map;
215
216 if (copy_from_user(&request, argp, sizeof(request)))
217 return -EFAULT;
218
219 down(&dev->struct_sem);
220 if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
221 up(&dev->struct_sem);
222 return -EINVAL;
223 }
224
225 map = dev->context_sareas[request.ctx_id];
226 up(&dev->struct_sem);
227
228 request.handle = map->handle;
229 if (copy_to_user(argp, &request, sizeof(request)))
230 return -EFAULT;
231 return 0;
232}
233
234/**
235 * Set per-context SAREA.
236 *
237 * \param inode device inode.
238 * \param filp file pointer.
239 * \param cmd command.
240 * \param arg user argument pointing to a drm_ctx_priv_map structure.
241 * \return zero on success or a negative number on failure.
242 *
243 * Searches the mapping specified in \p arg and update the entry in
244 * drm_device::context_sareas with it.
245 */
246int drm_setsareactx(struct inode *inode, struct file *filp,
247 unsigned int cmd, unsigned long arg)
248{
249 drm_file_t *priv = filp->private_data;
250 drm_device_t *dev = priv->head->dev;
251 drm_ctx_priv_map_t request;
252 drm_map_t *map = NULL;
253 drm_map_list_t *r_list = NULL;
254 struct list_head *list;
255
256 if (copy_from_user(&request,
257 (drm_ctx_priv_map_t __user *)arg,
258 sizeof(request)))
259 return -EFAULT;
260
261 down(&dev->struct_sem);
262 list_for_each(list, &dev->maplist->head) {
263 r_list = list_entry(list, drm_map_list_t, head);
264 if(r_list->map &&
265 r_list->map->handle == request.handle)
266 goto found;
267 }
268bad:
269 up(&dev->struct_sem);
270 return -EINVAL;
271
272found:
273 map = r_list->map;
274 if (!map) goto bad;
275 if (dev->max_context < 0)
276 goto bad;
277 if (request.ctx_id >= (unsigned) dev->max_context)
278 goto bad;
279 dev->context_sareas[request.ctx_id] = map;
280 up(&dev->struct_sem);
281 return 0;
282}
283
284/*@}*/
285
286/******************************************************************/
287/** \name The actual DRM context handling routines */
288/*@{*/
289
290/**
291 * Switch context.
292 *
293 * \param dev DRM device.
294 * \param old old context handle.
295 * \param new new context handle.
296 * \return zero on success or a negative number on failure.
297 *
298 * Attempt to set drm_device::context_flag.
299 */
300int drm_context_switch( drm_device_t *dev, int old, int new )
301{
302 if ( test_and_set_bit( 0, &dev->context_flag ) ) {
303 DRM_ERROR( "Reentering -- FIXME\n" );
304 return -EBUSY;
305 }
306
307
308 DRM_DEBUG( "Context switch from %d to %d\n", old, new );
309
310 if ( new == dev->last_context ) {
311 clear_bit( 0, &dev->context_flag );
312 return 0;
313 }
314
315 return 0;
316}
317
318/**
319 * Complete context switch.
320 *
321 * \param dev DRM device.
322 * \param new new context handle.
323 * \return zero on success or a negative number on failure.
324 *
325 * Updates drm_device::last_context and drm_device::last_switch. Verifies the
326 * hardware lock is held, clears the drm_device::context_flag and wakes up
327 * drm_device::context_wait.
328 */
329int drm_context_switch_complete( drm_device_t *dev, int new )
330{
331 dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
332 dev->last_switch = jiffies;
333
334 if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) {
335 DRM_ERROR( "Lock isn't held after context switch\n" );
336 }
337
338 /* If a context switch is ever initiated
339 when the kernel holds the lock, release
340 that lock here. */
341 clear_bit( 0, &dev->context_flag );
342 wake_up( &dev->context_wait );
343
344 return 0;
345}
346
347/**
348 * Reserve contexts.
349 *
350 * \param inode device inode.
351 * \param filp file pointer.
352 * \param cmd command.
353 * \param arg user argument pointing to a drm_ctx_res structure.
354 * \return zero on success or a negative number on failure.
355 */
356int drm_resctx( struct inode *inode, struct file *filp,
357 unsigned int cmd, unsigned long arg )
358{
359 drm_ctx_res_t res;
360 drm_ctx_t __user *argp = (void __user *)arg;
361 drm_ctx_t ctx;
362 int i;
363
364 if ( copy_from_user( &res, argp, sizeof(res) ) )
365 return -EFAULT;
366
367 if ( res.count >= DRM_RESERVED_CONTEXTS ) {
368 memset( &ctx, 0, sizeof(ctx) );
369 for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
370 ctx.handle = i;
371 if ( copy_to_user( &res.contexts[i],
372 &i, sizeof(i) ) )
373 return -EFAULT;
374 }
375 }
376 res.count = DRM_RESERVED_CONTEXTS;
377
378 if ( copy_to_user( argp, &res, sizeof(res) ) )
379 return -EFAULT;
380 return 0;
381}
382
383/**
384 * Add context.
385 *
386 * \param inode device inode.
387 * \param filp file pointer.
388 * \param cmd command.
389 * \param arg user argument pointing to a drm_ctx structure.
390 * \return zero on success or a negative number on failure.
391 *
392 * Get a new handle for the context and copy to userspace.
393 */
394int drm_addctx( struct inode *inode, struct file *filp,
395 unsigned int cmd, unsigned long arg )
396{
397 drm_file_t *priv = filp->private_data;
398 drm_device_t *dev = priv->head->dev;
399 drm_ctx_list_t * ctx_entry;
400 drm_ctx_t __user *argp = (void __user *)arg;
401 drm_ctx_t ctx;
402
403 if ( copy_from_user( &ctx, argp, sizeof(ctx) ) )
404 return -EFAULT;
405
406 ctx.handle = drm_ctxbitmap_next( dev );
407 if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
408 /* Skip kernel's context and get a new one. */
409 ctx.handle = drm_ctxbitmap_next( dev );
410 }
411 DRM_DEBUG( "%d\n", ctx.handle );
412 if ( ctx.handle == -1 ) {
413 DRM_DEBUG( "Not enough free contexts.\n" );
414 /* Should this return -EBUSY instead? */
415 return -ENOMEM;
416 }
417
418 if ( ctx.handle != DRM_KERNEL_CONTEXT )
419 {
420 if (dev->driver->context_ctor)
421 dev->driver->context_ctor(dev, ctx.handle);
422 }
423
424 ctx_entry = drm_alloc( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
425 if ( !ctx_entry ) {
426 DRM_DEBUG("out of memory\n");
427 return -ENOMEM;
428 }
429
430 INIT_LIST_HEAD( &ctx_entry->head );
431 ctx_entry->handle = ctx.handle;
432 ctx_entry->tag = priv;
433
434 down( &dev->ctxlist_sem );
435 list_add( &ctx_entry->head, &dev->ctxlist->head );
436 ++dev->ctx_count;
437 up( &dev->ctxlist_sem );
438
439 if ( copy_to_user( argp, &ctx, sizeof(ctx) ) )
440 return -EFAULT;
441 return 0;
442}
443
444int drm_modctx( struct inode *inode, struct file *filp,
445 unsigned int cmd, unsigned long arg )
446{
447 /* This does nothing */
448 return 0;
449}
450
451/**
452 * Get context.
453 *
454 * \param inode device inode.
455 * \param filp file pointer.
456 * \param cmd command.
457 * \param arg user argument pointing to a drm_ctx structure.
458 * \return zero on success or a negative number on failure.
459 */
460int drm_getctx( struct inode *inode, struct file *filp,
461 unsigned int cmd, unsigned long arg )
462{
463 drm_ctx_t __user *argp = (void __user *)arg;
464 drm_ctx_t ctx;
465
466 if ( copy_from_user( &ctx, argp, sizeof(ctx) ) )
467 return -EFAULT;
468
469 /* This is 0, because we don't handle any context flags */
470 ctx.flags = 0;
471
472 if ( copy_to_user( argp, &ctx, sizeof(ctx) ) )
473 return -EFAULT;
474 return 0;
475}
476
477/**
478 * Switch context.
479 *
480 * \param inode device inode.
481 * \param filp file pointer.
482 * \param cmd command.
483 * \param arg user argument pointing to a drm_ctx structure.
484 * \return zero on success or a negative number on failure.
485 *
486 * Calls context_switch().
487 */
488int drm_switchctx( struct inode *inode, struct file *filp,
489 unsigned int cmd, unsigned long arg )
490{
491 drm_file_t *priv = filp->private_data;
492 drm_device_t *dev = priv->head->dev;
493 drm_ctx_t ctx;
494
495 if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
496 return -EFAULT;
497
498 DRM_DEBUG( "%d\n", ctx.handle );
499 return drm_context_switch( dev, dev->last_context, ctx.handle );
500}
501
502/**
503 * New context.
504 *
505 * \param inode device inode.
506 * \param filp file pointer.
507 * \param cmd command.
508 * \param arg user argument pointing to a drm_ctx structure.
509 * \return zero on success or a negative number on failure.
510 *
511 * Calls context_switch_complete().
512 */
513int drm_newctx( struct inode *inode, struct file *filp,
514 unsigned int cmd, unsigned long arg )
515{
516 drm_file_t *priv = filp->private_data;
517 drm_device_t *dev = priv->head->dev;
518 drm_ctx_t ctx;
519
520 if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
521 return -EFAULT;
522
523 DRM_DEBUG( "%d\n", ctx.handle );
524 drm_context_switch_complete( dev, ctx.handle );
525
526 return 0;
527}
528
529/**
530 * Remove context.
531 *
532 * \param inode device inode.
533 * \param filp file pointer.
534 * \param cmd command.
535 * \param arg user argument pointing to a drm_ctx structure.
536 * \return zero on success or a negative number on failure.
537 *
538 * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
539 */
540int drm_rmctx( struct inode *inode, struct file *filp,
541 unsigned int cmd, unsigned long arg )
542{
543 drm_file_t *priv = filp->private_data;
544 drm_device_t *dev = priv->head->dev;
545 drm_ctx_t ctx;
546
547 if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
548 return -EFAULT;
549
550 DRM_DEBUG( "%d\n", ctx.handle );
551 if ( ctx.handle == DRM_KERNEL_CONTEXT + 1 ) {
552 priv->remove_auth_on_close = 1;
553 }
554 if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
555 if (dev->driver->context_dtor)
556 dev->driver->context_dtor(dev, ctx.handle);
557 drm_ctxbitmap_free( dev, ctx.handle );
558 }
559
560 down( &dev->ctxlist_sem );
561 if ( !list_empty( &dev->ctxlist->head ) ) {
562 drm_ctx_list_t *pos, *n;
563
564 list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
565 if ( pos->handle == ctx.handle ) {
566 list_del( &pos->head );
567 drm_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
568 --dev->ctx_count;
569 }
570 }
571 }
572 up( &dev->ctxlist_sem );
573
574 return 0;
575}
576
577/*@}*/
578
diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h
new file mode 100644
index 000000000000..cc97bb906dda
--- /dev/null
+++ b/drivers/char/drm/drm_core.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright 2004 Jon Smirl <jonsmirl@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23#define CORE_AUTHOR "Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl"
24
25#define CORE_NAME "drm"
26#define CORE_DESC "DRM shared core routines"
27#define CORE_DATE "20040925"
28
29#define DRM_IF_MAJOR 1
30#define DRM_IF_MINOR 2
31
32#define CORE_MAJOR 1
33#define CORE_MINOR 0
34#define CORE_PATCHLEVEL 0
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c
new file mode 100644
index 000000000000..4a28c053c98b
--- /dev/null
+++ b/drivers/char/drm/drm_dma.c
@@ -0,0 +1,180 @@
1/**
2 * \file drm_dma.h
3 * DMA IOCTL and function support
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
11 *
12 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include "drmP.h"
37
38/**
39 * Initialize the DMA data.
40 *
41 * \param dev DRM device.
42 * \return zero on success or a negative value on failure.
43 *
44 * Allocate and initialize a drm_device_dma structure.
45 */
46int drm_dma_setup( drm_device_t *dev )
47{
48 int i;
49
50 dev->dma = drm_alloc( sizeof(*dev->dma), DRM_MEM_DRIVER );
51 if ( !dev->dma )
52 return -ENOMEM;
53
54 memset( dev->dma, 0, sizeof(*dev->dma) );
55
56 for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
57 memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
58
59 return 0;
60}
61
62/**
63 * Cleanup the DMA resources.
64 *
65 * \param dev DRM device.
66 *
67 * Free all pages associated with DMA buffers, the buffers and pages lists, and
68 * finally the the drm_device::dma structure itself.
69 */
70void drm_dma_takedown(drm_device_t *dev)
71{
72 drm_device_dma_t *dma = dev->dma;
73 int i, j;
74
75 if (!dma) return;
76
77 /* Clear dma buffers */
78 for (i = 0; i <= DRM_MAX_ORDER; i++) {
79 if (dma->bufs[i].seg_count) {
80 DRM_DEBUG("order %d: buf_count = %d,"
81 " seg_count = %d\n",
82 i,
83 dma->bufs[i].buf_count,
84 dma->bufs[i].seg_count);
85 for (j = 0; j < dma->bufs[i].seg_count; j++) {
86 if (dma->bufs[i].seglist[j]) {
87 drm_free_pages(dma->bufs[i].seglist[j],
88 dma->bufs[i].page_order,
89 DRM_MEM_DMA);
90 }
91 }
92 drm_free(dma->bufs[i].seglist,
93 dma->bufs[i].seg_count
94 * sizeof(*dma->bufs[0].seglist),
95 DRM_MEM_SEGS);
96 }
97 if (dma->bufs[i].buf_count) {
98 for (j = 0; j < dma->bufs[i].buf_count; j++) {
99 if (dma->bufs[i].buflist[j].dev_private) {
100 drm_free(dma->bufs[i].buflist[j].dev_private,
101 dma->bufs[i].buflist[j].dev_priv_size,
102 DRM_MEM_BUFS);
103 }
104 }
105 drm_free(dma->bufs[i].buflist,
106 dma->bufs[i].buf_count *
107 sizeof(*dma->bufs[0].buflist),
108 DRM_MEM_BUFS);
109 }
110 }
111
112 if (dma->buflist) {
113 drm_free(dma->buflist,
114 dma->buf_count * sizeof(*dma->buflist),
115 DRM_MEM_BUFS);
116 }
117
118 if (dma->pagelist) {
119 drm_free(dma->pagelist,
120 dma->page_count * sizeof(*dma->pagelist),
121 DRM_MEM_PAGES);
122 }
123 drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
124 dev->dma = NULL;
125}
126
127
128/**
129 * Free a buffer.
130 *
131 * \param dev DRM device.
132 * \param buf buffer to free.
133 *
134 * Resets the fields of \p buf.
135 */
136void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
137{
138 if (!buf) return;
139
140 buf->waiting = 0;
141 buf->pending = 0;
142 buf->filp = NULL;
143 buf->used = 0;
144
145 if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && waitqueue_active(&buf->dma_wait)) {
146 wake_up_interruptible(&buf->dma_wait);
147 }
148}
149
150/**
151 * Reclaim the buffers.
152 *
153 * \param filp file pointer.
154 *
155 * Frees each buffer associated with \p filp not already on the hardware.
156 */
157void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp)
158{
159 drm_device_dma_t *dma = dev->dma;
160 int i;
161
162 if (!dma) return;
163 for (i = 0; i < dma->buf_count; i++) {
164 if (dma->buflist[i]->filp == filp) {
165 switch (dma->buflist[i]->list) {
166 case DRM_LIST_NONE:
167 drm_free_buffer(dev, dma->buflist[i]);
168 break;
169 case DRM_LIST_WAIT:
170 dma->buflist[i]->list = DRM_LIST_RECLAIM;
171 break;
172 default:
173 /* Buffer already on hardware. */
174 break;
175 }
176 }
177 }
178}
179EXPORT_SYMBOL(drm_core_reclaim_buffers);
180
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c
new file mode 100644
index 000000000000..e8e8e42be4c7
--- /dev/null
+++ b/drivers/char/drm/drm_drawable.c
@@ -0,0 +1,56 @@
1/**
2 * \file drm_drawable.h
3 * IOCTLs for drawables
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
11 *
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include "drmP.h"
37
38/** No-op. */
39int drm_adddraw(struct inode *inode, struct file *filp,
40 unsigned int cmd, unsigned long arg)
41{
42 drm_draw_t draw;
43
44 draw.handle = 0; /* NOOP */
45 DRM_DEBUG("%d\n", draw.handle);
46 if (copy_to_user((drm_draw_t __user *)arg, &draw, sizeof(draw)))
47 return -EFAULT;
48 return 0;
49}
50
51/** No-op. */
52int drm_rmdraw(struct inode *inode, struct file *filp,
53 unsigned int cmd, unsigned long arg)
54{
55 return 0; /* NOOP */
56}
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
new file mode 100644
index 000000000000..1e37ed0c6b8d
--- /dev/null
+++ b/drivers/char/drm/drm_drv.c
@@ -0,0 +1,531 @@
1/**
2 * \file drm_drv.h
3 * Generic driver template
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 *
8 * To use this template, you must at least define the following (samples
9 * given for the MGA driver):
10 *
11 * \code
12 * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
13 *
14 * #define DRIVER_NAME "mga"
15 * #define DRIVER_DESC "Matrox G200/G400"
16 * #define DRIVER_DATE "20001127"
17 *
18 * #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
19 *
20 * #define drm_x mga_##x
21 * \endcode
22 */
23
24/*
25 * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
26 *
27 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
28 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
29 * All Rights Reserved.
30 *
31 * Permission is hereby granted, free of charge, to any person obtaining a
32 * copy of this software and associated documentation files (the "Software"),
33 * to deal in the Software without restriction, including without limitation
34 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35 * and/or sell copies of the Software, and to permit persons to whom the
36 * Software is furnished to do so, subject to the following conditions:
37 *
38 * The above copyright notice and this permission notice (including the next
39 * paragraph) shall be included in all copies or substantial portions of the
40 * Software.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
45 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
46 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
47 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
48 * OTHER DEALINGS IN THE SOFTWARE.
49 */
50
51#include "drmP.h"
52#include "drm_core.h"
53
54/** Ioctl table */
55drm_ioctl_desc_t drm_ioctls[] = {
56 [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0, 0 },
57 [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
58 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
59 [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_by_busid, 0, 1 },
60 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { drm_getmap, 0, 0 },
61 [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { drm_getclient, 0, 0 },
62 [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { drm_getstats, 0, 0 },
63 [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { drm_setversion, 0, 1 },
64
65 [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
66 [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_noop, 1, 1 },
67 [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 },
68 [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
69
70 [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
71 [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap, 1, 0 },
72
73 [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 },
74 [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 },
75
76 [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, 1, 1 },
77 [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, 1, 1 },
78 [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, 1, 1 },
79 [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, 1, 0 },
80 [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, 1, 1 },
81 [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, 1, 1 },
82 [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, 1, 0 },
83
84 [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
85 [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
86
87 [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { drm_lock, 1, 0 },
88 [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { drm_unlock, 1, 0 },
89
90 [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_noop, 1, 0 },
91
92 [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs, 1, 1 },
93 [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
94 [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
95 [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, 1, 0 },
96 [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
97 /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
98
99 [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 },
100
101#if __OS_HAS_AGP
102 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
103 [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
104 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
105 [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
106 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
107 [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
108 [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
109 [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
110#endif
111
112 [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { drm_sg_alloc, 1, 1 },
113 [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, 1, 1 },
114
115 [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { drm_wait_vblank, 0, 0 },
116};
117
118#define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls )
119
120/**
121 * Take down the DRM device.
122 *
123 * \param dev DRM device structure.
124 *
125 * Frees every resource in \p dev.
126 *
127 * \sa drm_device and setup().
128 */
129int drm_takedown( drm_device_t *dev )
130{
131 drm_magic_entry_t *pt, *next;
132 drm_map_t *map;
133 drm_map_list_t *r_list;
134 struct list_head *list, *list_next;
135 drm_vma_entry_t *vma, *vma_next;
136 int i;
137
138 DRM_DEBUG( "\n" );
139
140 if (dev->driver->pretakedown)
141 dev->driver->pretakedown(dev);
142
143 if (dev->unique) {
144 drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
145 dev->unique = NULL;
146 dev->unique_len = 0;
147 }
148
149 if ( dev->irq_enabled ) drm_irq_uninstall( dev );
150
151 down( &dev->struct_sem );
152 del_timer( &dev->timer );
153
154 /* Clear pid list */
155 for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
156 for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
157 next = pt->next;
158 drm_free( pt, sizeof(*pt), DRM_MEM_MAGIC );
159 }
160 dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
161 }
162
163 /* Clear AGP information */
164 if (drm_core_has_AGP(dev) && dev->agp) {
165 drm_agp_mem_t *entry;
166 drm_agp_mem_t *nexte;
167
168 /* Remove AGP resources, but leave dev->agp
169 intact until drv_cleanup is called. */
170 for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
171 nexte = entry->next;
172 if ( entry->bound ) drm_unbind_agp( entry->memory );
173 drm_free_agp( entry->memory, entry->pages );
174 drm_free( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
175 }
176 dev->agp->memory = NULL;
177
178 if ( dev->agp->acquired ) drm_agp_do_release(dev);
179
180 dev->agp->acquired = 0;
181 dev->agp->enabled = 0;
182 }
183
184 /* Clear vma list (only built for debugging) */
185 if ( dev->vmalist ) {
186 for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
187 vma_next = vma->next;
188 drm_free( vma, sizeof(*vma), DRM_MEM_VMAS );
189 }
190 dev->vmalist = NULL;
191 }
192
193 if( dev->maplist ) {
194 list_for_each_safe( list, list_next, &dev->maplist->head ) {
195 r_list = (drm_map_list_t *)list;
196
197 if ( ( map = r_list->map ) ) {
198 switch ( map->type ) {
199 case _DRM_REGISTERS:
200 case _DRM_FRAME_BUFFER:
201 if (drm_core_has_MTRR(dev)) {
202 if ( map->mtrr >= 0 ) {
203 int retcode;
204 retcode = mtrr_del( map->mtrr,
205 map->offset,
206 map->size );
207 DRM_DEBUG( "mtrr_del=%d\n", retcode );
208 }
209 }
210 drm_ioremapfree( map->handle, map->size, dev );
211 break;
212 case _DRM_SHM:
213 vfree(map->handle);
214 break;
215
216 case _DRM_AGP:
217 /* Do nothing here, because this is all
218 * handled in the AGP/GART driver.
219 */
220 break;
221 case _DRM_SCATTER_GATHER:
222 /* Handle it */
223 if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
224 drm_sg_cleanup(dev->sg);
225 dev->sg = NULL;
226 }
227 break;
228 }
229 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
230 }
231 list_del( list );
232 drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
233 }
234 drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
235 dev->maplist = NULL;
236 }
237
238 if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
239 for ( i = 0 ; i < dev->queue_count ; i++ ) {
240 if ( dev->queuelist[i] ) {
241 drm_free( dev->queuelist[i],
242 sizeof(*dev->queuelist[0]),
243 DRM_MEM_QUEUES );
244 dev->queuelist[i] = NULL;
245 }
246 }
247 drm_free( dev->queuelist,
248 dev->queue_slots * sizeof(*dev->queuelist),
249 DRM_MEM_QUEUES );
250 dev->queuelist = NULL;
251 }
252 dev->queue_count = 0;
253
254 if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
255 drm_dma_takedown( dev );
256
257 if ( dev->lock.hw_lock ) {
258 dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
259 dev->lock.filp = NULL;
260 wake_up_interruptible( &dev->lock.lock_queue );
261 }
262 up( &dev->struct_sem );
263
264 return 0;
265}
266
267
268
269/**
270 * Module initialization. Called via init_module at module load time, or via
271 * linux/init/main.c (this is not currently supported).
272 *
273 * \return zero on success or a negative number on failure.
274 *
275 * Initializes an array of drm_device structures, and attempts to
276 * initialize all available devices, using consecutive minors, registering the
277 * stubs and initializing the AGP device.
278 *
279 * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
280 * after the initialization for driver customization.
281 */
282int drm_init( struct drm_driver *driver )
283{
284 struct pci_dev *pdev = NULL;
285 struct pci_device_id *pid;
286 int i;
287
288 DRM_DEBUG( "\n" );
289
290 drm_mem_init();
291
292 for (i=0; driver->pci_driver.id_table[i].vendor != 0; i++) {
293 pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
294
295 pdev=NULL;
296 /* pass back in pdev to account for multiple identical cards */
297 while ((pdev = pci_get_subsys(pid->vendor, pid->device, pid->subvendor, pid->subdevice, pdev)) != NULL) {
298 /* stealth mode requires a manual probe */
299 pci_dev_get(pdev);
300 drm_get_dev(pdev, pid, driver);
301 }
302 }
303 return 0;
304}
305EXPORT_SYMBOL(drm_init);
306
307/**
308 * Called via cleanup_module() at module unload time.
309 *
310 * Cleans up all DRM device, calling takedown().
311 *
312 * \sa drm_init().
313 */
314static void drm_cleanup( drm_device_t *dev )
315{
316 DRM_DEBUG( "\n" );
317
318 if (!dev) {
319 DRM_ERROR("cleanup called no dev\n");
320 return;
321 }
322
323 drm_takedown( dev );
324
325 drm_ctxbitmap_cleanup( dev );
326
327 if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
328 dev->agp && dev->agp->agp_mtrr >= 0) {
329 int retval;
330 retval = mtrr_del( dev->agp->agp_mtrr,
331 dev->agp->agp_info.aper_base,
332 dev->agp->agp_info.aper_size*1024*1024 );
333 DRM_DEBUG( "mtrr_del=%d\n", retval );
334 }
335
336 if (drm_core_has_AGP(dev) && dev->agp ) {
337 drm_free( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
338 dev->agp = NULL;
339 }
340
341 if (dev->driver->postcleanup)
342 dev->driver->postcleanup(dev);
343
344 drm_put_head(&dev->primary);
345 if ( drm_put_dev(dev) )
346 DRM_ERROR( "Cannot unload module\n" );
347}
348
349void drm_exit (struct drm_driver *driver)
350{
351 int i;
352 drm_device_t *dev = NULL;
353 drm_head_t *head;
354
355 DRM_DEBUG( "\n" );
356
357 for (i = 0; i < drm_cards_limit; i++) {
358 head = drm_heads[i];
359 if (!head)
360 continue;
361 if (!head->dev)
362 continue;
363 if (head->dev->driver!=driver)
364 continue;
365 dev=head->dev;
366 }
367 if (dev) {
368 /* release the pci driver */
369 if (dev->pdev)
370 pci_dev_put(dev->pdev);
371 drm_cleanup(dev);
372 }
373 DRM_INFO( "Module unloaded\n" );
374}
375EXPORT_SYMBOL(drm_exit);
376
377/** File operations structure */
378static struct file_operations drm_stub_fops = {
379 .owner = THIS_MODULE,
380 .open = drm_stub_open
381};
382
383static int __init drm_core_init(void)
384{
385 int ret = -ENOMEM;
386
387 drm_cards_limit = (drm_cards_limit < DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
388 drm_heads = drm_calloc(drm_cards_limit,
389 sizeof(*drm_heads), DRM_MEM_STUB);
390 if(!drm_heads)
391 goto err_p1;
392
393 if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
394 goto err_p1;
395
396 drm_class = drm_sysfs_create(THIS_MODULE, "drm");
397 if (IS_ERR(drm_class)) {
398 printk (KERN_ERR "DRM: Error creating drm class.\n");
399 ret = PTR_ERR(drm_class);
400 goto err_p2;
401 }
402
403 drm_proc_root = create_proc_entry("dri", S_IFDIR, NULL);
404 if (!drm_proc_root) {
405 DRM_ERROR("Cannot create /proc/dri\n");
406 ret = -1;
407 goto err_p3;
408 }
409
410 DRM_INFO( "Initialized %s %d.%d.%d %s\n",
411 CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL,
412 CORE_DATE);
413 return 0;
414err_p3:
415 drm_sysfs_destroy(drm_class);
416err_p2:
417 unregister_chrdev(DRM_MAJOR, "drm");
418 drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
419err_p1:
420 return ret;
421}
422
423static void __exit drm_core_exit (void)
424{
425 remove_proc_entry("dri", NULL);
426 drm_sysfs_destroy(drm_class);
427
428 unregister_chrdev(DRM_MAJOR, "drm");
429
430 drm_free(drm_heads, sizeof(*drm_heads) *
431 drm_cards_limit, DRM_MEM_STUB);
432}
433
434
435module_init( drm_core_init );
436module_exit( drm_core_exit );
437
438
439/**
440 * Get version information
441 *
442 * \param inode device inode.
443 * \param filp file pointer.
444 * \param cmd command.
445 * \param arg user argument, pointing to a drm_version structure.
446 * \return zero on success or negative number on failure.
447 *
448 * Fills in the version information in \p arg.
449 */
450int drm_version( struct inode *inode, struct file *filp,
451 unsigned int cmd, unsigned long arg )
452{
453 drm_file_t *priv = filp->private_data;
454 drm_device_t *dev = priv->head->dev;
455 drm_version_t __user *argp = (void __user *)arg;
456 drm_version_t version;
457 int ret;
458
459 if ( copy_from_user( &version, argp, sizeof(version) ) )
460 return -EFAULT;
461
462 /* version is a required function to return the personality module version */
463 if ((ret = dev->driver->version(&version)))
464 return ret;
465
466 if ( copy_to_user( argp, &version, sizeof(version) ) )
467 return -EFAULT;
468 return 0;
469}
470
471
472
473/**
474 * Called whenever a process performs an ioctl on /dev/drm.
475 *
476 * \param inode device inode.
477 * \param filp file pointer.
478 * \param cmd command.
479 * \param arg user argument.
480 * \return zero on success or negative number on failure.
481 *
482 * Looks up the ioctl function in the ::ioctls table, checking for root
483 * previleges if so required, and dispatches to the respective function.
484 */
485int drm_ioctl( struct inode *inode, struct file *filp,
486 unsigned int cmd, unsigned long arg )
487{
488 drm_file_t *priv = filp->private_data;
489 drm_device_t *dev = priv->head->dev;
490 drm_ioctl_desc_t *ioctl;
491 drm_ioctl_t *func;
492 unsigned int nr = DRM_IOCTL_NR(cmd);
493 int retcode = -EINVAL;
494
495 atomic_inc( &dev->ioctl_count );
496 atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
497 ++priv->ioctl_count;
498
499 DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
500 current->pid, cmd, nr, (long)old_encode_dev(priv->head->device),
501 priv->authenticated );
502
503 if (nr < DRIVER_IOCTL_COUNT)
504 ioctl = &drm_ioctls[nr];
505 else if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
506 ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
507 else
508 goto err_i1;
509
510 func = ioctl->func;
511 /* is there a local override? */
512 if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
513 func = dev->driver->dma_ioctl;
514
515 if ( !func ) {
516 DRM_DEBUG( "no function\n" );
517 retcode = -EINVAL;
518 } else if ( ( ioctl->root_only && !capable( CAP_SYS_ADMIN ) )||
519 ( ioctl->auth_needed && !priv->authenticated ) ) {
520 retcode = -EACCES;
521 } else {
522 retcode = func( inode, filp, cmd, arg );
523 }
524
525err_i1:
526 atomic_dec( &dev->ioctl_count );
527 if (retcode) DRM_DEBUG( "ret = %x\n", retcode);
528 return retcode;
529}
530EXPORT_SYMBOL(drm_ioctl);
531
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
new file mode 100644
index 000000000000..906794247aeb
--- /dev/null
+++ b/drivers/char/drm/drm_fops.c
@@ -0,0 +1,451 @@
1/**
2 * \file drm_fops.h
3 * File operations for DRM
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Daryll Strauss <daryll@valinux.com>
7 * \author Gareth Hughes <gareth@valinux.com>
8 */
9
10/*
11 * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
12 *
13 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
14 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
15 * All Rights Reserved.
16 *
17 * Permission is hereby granted, free of charge, to any person obtaining a
18 * copy of this software and associated documentation files (the "Software"),
19 * to deal in the Software without restriction, including without limitation
20 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21 * and/or sell copies of the Software, and to permit persons to whom the
22 * Software is furnished to do so, subject to the following conditions:
23 *
24 * The above copyright notice and this permission notice (including the next
25 * paragraph) shall be included in all copies or substantial portions of the
26 * Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
31 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
32 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
33 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
34 * OTHER DEALINGS IN THE SOFTWARE.
35 */
36
37#include "drmP.h"
38#include <linux/poll.h>
39
40static int drm_setup( drm_device_t *dev )
41{
42 int i;
43 int ret;
44
45 if (dev->driver->presetup)
46 {
47 ret=dev->driver->presetup(dev);
48 if (ret!=0)
49 return ret;
50 }
51
52 atomic_set( &dev->ioctl_count, 0 );
53 atomic_set( &dev->vma_count, 0 );
54 dev->buf_use = 0;
55 atomic_set( &dev->buf_alloc, 0 );
56
57 if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
58 {
59 i = drm_dma_setup( dev );
60 if ( i < 0 )
61 return i;
62 }
63
64 for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
65 atomic_set( &dev->counts[i], 0 );
66
67 for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
68 dev->magiclist[i].head = NULL;
69 dev->magiclist[i].tail = NULL;
70 }
71
72 dev->maplist = drm_alloc(sizeof(*dev->maplist),
73 DRM_MEM_MAPS);
74 if(dev->maplist == NULL) return -ENOMEM;
75 memset(dev->maplist, 0, sizeof(*dev->maplist));
76 INIT_LIST_HEAD(&dev->maplist->head);
77
78 dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist),
79 DRM_MEM_CTXLIST);
80 if(dev->ctxlist == NULL) return -ENOMEM;
81 memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
82 INIT_LIST_HEAD(&dev->ctxlist->head);
83
84 dev->vmalist = NULL;
85 dev->sigdata.lock = dev->lock.hw_lock = NULL;
86 init_waitqueue_head( &dev->lock.lock_queue );
87 dev->queue_count = 0;
88 dev->queue_reserved = 0;
89 dev->queue_slots = 0;
90 dev->queuelist = NULL;
91 dev->irq_enabled = 0;
92 dev->context_flag = 0;
93 dev->interrupt_flag = 0;
94 dev->dma_flag = 0;
95 dev->last_context = 0;
96 dev->last_switch = 0;
97 dev->last_checked = 0;
98 init_waitqueue_head( &dev->context_wait );
99 dev->if_version = 0;
100
101 dev->ctx_start = 0;
102 dev->lck_start = 0;
103
104 dev->buf_rp = dev->buf;
105 dev->buf_wp = dev->buf;
106 dev->buf_end = dev->buf + DRM_BSZ;
107 dev->buf_async = NULL;
108 init_waitqueue_head( &dev->buf_readers );
109 init_waitqueue_head( &dev->buf_writers );
110
111 DRM_DEBUG( "\n" );
112
113 /*
114 * The kernel's context could be created here, but is now created
115 * in drm_dma_enqueue. This is more resource-efficient for
116 * hardware that does not do DMA, but may mean that
117 * drm_select_queue fails between the time the interrupt is
118 * initialized and the time the queues are initialized.
119 */
120 if (dev->driver->postsetup)
121 dev->driver->postsetup(dev);
122
123 return 0;
124}
125
126/**
127 * Open file.
128 *
129 * \param inode device inode
130 * \param filp file pointer.
131 * \return zero on success or a negative number on failure.
132 *
133 * Searches the DRM device with the same minor number, calls open_helper(), and
134 * increments the device open count. If the open count was previous at zero,
135 * i.e., it's the first that the device is open, then calls setup().
136 */
137int drm_open( struct inode *inode, struct file *filp )
138{
139 drm_device_t *dev = NULL;
140 int minor = iminor(inode);
141 int retcode = 0;
142
143 if (!((minor >= 0) && (minor < drm_cards_limit)))
144 return -ENODEV;
145
146 if (!drm_heads[minor])
147 return -ENODEV;
148
149 if (!(dev = drm_heads[minor]->dev))
150 return -ENODEV;
151
152 retcode = drm_open_helper( inode, filp, dev );
153 if ( !retcode ) {
154 atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
155 spin_lock( &dev->count_lock );
156 if ( !dev->open_count++ ) {
157 spin_unlock( &dev->count_lock );
158 return drm_setup( dev );
159 }
160 spin_unlock( &dev->count_lock );
161 }
162
163 return retcode;
164}
165EXPORT_SYMBOL(drm_open);
166
167/**
168 * Release file.
169 *
170 * \param inode device inode
171 * \param filp file pointer.
172 * \return zero on success or a negative number on failure.
173 *
174 * If the hardware lock is held then free it, and take it again for the kernel
175 * context since it's necessary to reclaim buffers. Unlink the file private
176 * data from its list and free it. Decreases the open count and if it reaches
177 * zero calls takedown().
178 */
179int drm_release( struct inode *inode, struct file *filp )
180{
181 drm_file_t *priv = filp->private_data;
182 drm_device_t *dev;
183 int retcode = 0;
184
185 lock_kernel();
186 dev = priv->head->dev;
187
188 DRM_DEBUG( "open_count = %d\n", dev->open_count );
189
190 if (dev->driver->prerelease)
191 dev->driver->prerelease(dev, filp);
192
193 /* ========================================================
194 * Begin inline drm_release
195 */
196
197 DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
198 current->pid, (long)old_encode_dev(priv->head->device), dev->open_count );
199
200 if ( priv->lock_count && dev->lock.hw_lock &&
201 _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
202 dev->lock.filp == filp ) {
203 DRM_DEBUG( "File %p released, freeing lock for context %d\n",
204 filp,
205 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
206
207 if (dev->driver->release)
208 dev->driver->release(dev, filp);
209
210 drm_lock_free( dev, &dev->lock.hw_lock->lock,
211 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
212
213 /* FIXME: may require heavy-handed reset of
214 hardware at this point, possibly
215 processed via a callback to the X
216 server. */
217 }
218 else if ( dev->driver->release && priv->lock_count && dev->lock.hw_lock ) {
219 /* The lock is required to reclaim buffers */
220 DECLARE_WAITQUEUE( entry, current );
221
222 add_wait_queue( &dev->lock.lock_queue, &entry );
223 for (;;) {
224 __set_current_state(TASK_INTERRUPTIBLE);
225 if ( !dev->lock.hw_lock ) {
226 /* Device has been unregistered */
227 retcode = -EINTR;
228 break;
229 }
230 if ( drm_lock_take( &dev->lock.hw_lock->lock,
231 DRM_KERNEL_CONTEXT ) ) {
232 dev->lock.filp = filp;
233 dev->lock.lock_time = jiffies;
234 atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
235 break; /* Got lock */
236 }
237 /* Contention */
238 schedule();
239 if ( signal_pending( current ) ) {
240 retcode = -ERESTARTSYS;
241 break;
242 }
243 }
244 __set_current_state(TASK_RUNNING);
245 remove_wait_queue( &dev->lock.lock_queue, &entry );
246 if( !retcode ) {
247 if (dev->driver->release)
248 dev->driver->release(dev, filp);
249 drm_lock_free( dev, &dev->lock.hw_lock->lock,
250 DRM_KERNEL_CONTEXT );
251 }
252 }
253
254 if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
255 {
256 dev->driver->reclaim_buffers(dev, filp);
257 }
258
259 drm_fasync( -1, filp, 0 );
260
261 down( &dev->ctxlist_sem );
262 if ( !list_empty( &dev->ctxlist->head ) ) {
263 drm_ctx_list_t *pos, *n;
264
265 list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
266 if ( pos->tag == priv &&
267 pos->handle != DRM_KERNEL_CONTEXT ) {
268 if (dev->driver->context_dtor)
269 dev->driver->context_dtor(dev, pos->handle);
270
271 drm_ctxbitmap_free( dev, pos->handle );
272
273 list_del( &pos->head );
274 drm_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
275 --dev->ctx_count;
276 }
277 }
278 }
279 up( &dev->ctxlist_sem );
280
281 down( &dev->struct_sem );
282 if ( priv->remove_auth_on_close == 1 ) {
283 drm_file_t *temp = dev->file_first;
284 while ( temp ) {
285 temp->authenticated = 0;
286 temp = temp->next;
287 }
288 }
289 if ( priv->prev ) {
290 priv->prev->next = priv->next;
291 } else {
292 dev->file_first = priv->next;
293 }
294 if ( priv->next ) {
295 priv->next->prev = priv->prev;
296 } else {
297 dev->file_last = priv->prev;
298 }
299 up( &dev->struct_sem );
300
301 if (dev->driver->free_filp_priv)
302 dev->driver->free_filp_priv(dev, priv);
303
304 drm_free( priv, sizeof(*priv), DRM_MEM_FILES );
305
306 /* ========================================================
307 * End inline drm_release
308 */
309
310 atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
311 spin_lock( &dev->count_lock );
312 if ( !--dev->open_count ) {
313 if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
314 DRM_ERROR( "Device busy: %d %d\n",
315 atomic_read( &dev->ioctl_count ),
316 dev->blocked );
317 spin_unlock( &dev->count_lock );
318 unlock_kernel();
319 return -EBUSY;
320 }
321 spin_unlock( &dev->count_lock );
322 unlock_kernel();
323 return drm_takedown( dev );
324 }
325 spin_unlock( &dev->count_lock );
326
327 unlock_kernel();
328
329 return retcode;
330}
331EXPORT_SYMBOL(drm_release);
332
333/**
334 * Called whenever a process opens /dev/drm.
335 *
336 * \param inode device inode.
337 * \param filp file pointer.
338 * \param dev device.
339 * \return zero on success or a negative number on failure.
340 *
341 * Creates and initializes a drm_file structure for the file private data in \p
342 * filp and add it into the double linked list in \p dev.
343 */
344int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
345{
346 int minor = iminor(inode);
347 drm_file_t *priv;
348 int ret;
349
350 if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */
351 if (!drm_cpu_valid()) return -EINVAL;
352
353 DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
354
355 priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
356 if(!priv) return -ENOMEM;
357
358 memset(priv, 0, sizeof(*priv));
359 filp->private_data = priv;
360 priv->uid = current->euid;
361 priv->pid = current->pid;
362 priv->minor = minor;
363 priv->head = drm_heads[minor];
364 priv->ioctl_count = 0;
365 priv->authenticated = capable(CAP_SYS_ADMIN);
366 priv->lock_count = 0;
367
368 if (dev->driver->open_helper) {
369 ret=dev->driver->open_helper(dev, priv);
370 if (ret < 0)
371 goto out_free;
372 }
373
374 down(&dev->struct_sem);
375 if (!dev->file_last) {
376 priv->next = NULL;
377 priv->prev = NULL;
378 dev->file_first = priv;
379 dev->file_last = priv;
380 } else {
381 priv->next = NULL;
382 priv->prev = dev->file_last;
383 dev->file_last->next = priv;
384 dev->file_last = priv;
385 }
386 up(&dev->struct_sem);
387
388#ifdef __alpha__
389 /*
390 * Default the hose
391 */
392 if (!dev->hose) {
393 struct pci_dev *pci_dev;
394 pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
395 if (pci_dev) {
396 dev->hose = pci_dev->sysdata;
397 pci_dev_put(pci_dev);
398 }
399 if (!dev->hose) {
400 struct pci_bus *b = pci_bus_b(pci_root_buses.next);
401 if (b) dev->hose = b->sysdata;
402 }
403 }
404#endif
405
406 return 0;
407out_free:
408 drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
409 filp->private_data=NULL;
410 return ret;
411}
412
413/** No-op. */
414int drm_flush(struct file *filp)
415{
416 drm_file_t *priv = filp->private_data;
417 drm_device_t *dev = priv->head->dev;
418
419 DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
420 current->pid, (long)old_encode_dev(priv->head->device), dev->open_count);
421 return 0;
422}
423EXPORT_SYMBOL(drm_flush);
424
425/** No-op. */
426int drm_fasync(int fd, struct file *filp, int on)
427{
428 drm_file_t *priv = filp->private_data;
429 drm_device_t *dev = priv->head->dev;
430 int retcode;
431
432 DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)old_encode_dev(priv->head->device));
433 retcode = fasync_helper(fd, filp, on, &dev->buf_async);
434 if (retcode < 0) return retcode;
435 return 0;
436}
437EXPORT_SYMBOL(drm_fasync);
438
439/** No-op. */
440unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
441{
442 return 0;
443}
444EXPORT_SYMBOL(drm_poll);
445
446
447/** No-op. */
448ssize_t drm_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
449{
450 return 0;
451}
diff --git a/drivers/char/drm/drm_init.c b/drivers/char/drm/drm_init.c
new file mode 100644
index 000000000000..62883b749e97
--- /dev/null
+++ b/drivers/char/drm/drm_init.c
@@ -0,0 +1,52 @@
1/**
2 * \file drm_init.h
3 * Setup/Cleanup for DRM
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
11 *
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include "drmP.h"
37
38/**
39 * Check whether DRI will run on this CPU.
40 *
41 * \return non-zero if the DRI will run on this CPU, or zero otherwise.
42 */
43int drm_cpu_valid(void)
44{
45#if defined(__i386__)
46 if (boot_cpu_data.x86 == 3) return 0; /* No cmpxchg on a 386 */
47#endif
48#if defined(__sparc__) && !defined(__sparc_v9__)
49 return 0; /* No cmpxchg before v9 sparc. */
50#endif
51 return 1;
52}
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
new file mode 100644
index 000000000000..39afda0ccabe
--- /dev/null
+++ b/drivers/char/drm/drm_ioctl.c
@@ -0,0 +1,370 @@
1/**
2 * \file drm_ioctl.h
3 * IOCTL processing for DRM
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com
11 *
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include "drmP.h"
37#include "drm_core.h"
38
39#include "linux/pci.h"
40
41/**
42 * Get the bus id.
43 *
44 * \param inode device inode.
45 * \param filp file pointer.
46 * \param cmd command.
47 * \param arg user argument, pointing to a drm_unique structure.
48 * \return zero on success or a negative number on failure.
49 *
50 * Copies the bus id from drm_device::unique into user space.
51 */
52int drm_getunique(struct inode *inode, struct file *filp,
53 unsigned int cmd, unsigned long arg)
54{
55 drm_file_t *priv = filp->private_data;
56 drm_device_t *dev = priv->head->dev;
57 drm_unique_t __user *argp = (void __user *)arg;
58 drm_unique_t u;
59
60 if (copy_from_user(&u, argp, sizeof(u)))
61 return -EFAULT;
62 if (u.unique_len >= dev->unique_len) {
63 if (copy_to_user(u.unique, dev->unique, dev->unique_len))
64 return -EFAULT;
65 }
66 u.unique_len = dev->unique_len;
67 if (copy_to_user(argp, &u, sizeof(u)))
68 return -EFAULT;
69 return 0;
70}
71
72/**
73 * Set the bus id.
74 *
75 * \param inode device inode.
76 * \param filp file pointer.
77 * \param cmd command.
78 * \param arg user argument, pointing to a drm_unique structure.
79 * \return zero on success or a negative number on failure.
80 *
81 * Copies the bus id from userspace into drm_device::unique, and verifies that
82 * it matches the device this DRM is attached to (EINVAL otherwise). Deprecated
83 * in interface version 1.1 and will return EBUSY when setversion has requested
84 * version 1.1 or greater.
85 */
86int drm_setunique(struct inode *inode, struct file *filp,
87 unsigned int cmd, unsigned long arg)
88{
89 drm_file_t *priv = filp->private_data;
90 drm_device_t *dev = priv->head->dev;
91 drm_unique_t u;
92 int domain, bus, slot, func, ret;
93
94 if (dev->unique_len || dev->unique) return -EBUSY;
95
96 if (copy_from_user(&u, (drm_unique_t __user *)arg, sizeof(u)))
97 return -EFAULT;
98
99 if (!u.unique_len || u.unique_len > 1024) return -EINVAL;
100
101 dev->unique_len = u.unique_len;
102 dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
103 if(!dev->unique) return -ENOMEM;
104 if (copy_from_user(dev->unique, u.unique, dev->unique_len))
105 return -EFAULT;
106
107 dev->unique[dev->unique_len] = '\0';
108
109 dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + strlen(dev->unique) + 2,
110 DRM_MEM_DRIVER);
111 if (!dev->devname)
112 return -ENOMEM;
113
114 sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, dev->unique);
115
116 /* Return error if the busid submitted doesn't match the device's actual
117 * busid.
118 */
119 ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
120 if (ret != 3)
121 return DRM_ERR(EINVAL);
122 domain = bus >> 8;
123 bus &= 0xff;
124
125 if ((domain != dev->pci_domain) ||
126 (bus != dev->pci_bus) ||
127 (slot != dev->pci_slot) ||
128 (func != dev->pci_func))
129 return -EINVAL;
130
131 return 0;
132}
133
134static int
135drm_set_busid(drm_device_t *dev)
136{
137 if (dev->unique != NULL)
138 return EBUSY;
139
140 dev->unique_len = 20;
141 dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
142 if (dev->unique == NULL)
143 return ENOMEM;
144
145 snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
146 dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
147
148 dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + 2,
149 DRM_MEM_DRIVER);
150 if (dev->devname == NULL)
151 return ENOMEM;
152
153 sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, dev->unique);
154
155 return 0;
156}
157
158
159/**
160 * Get a mapping information.
161 *
162 * \param inode device inode.
163 * \param filp file pointer.
164 * \param cmd command.
165 * \param arg user argument, pointing to a drm_map structure.
166 *
167 * \return zero on success or a negative number on failure.
168 *
169 * Searches for the mapping with the specified offset and copies its information
170 * into userspace
171 */
172int drm_getmap( struct inode *inode, struct file *filp,
173 unsigned int cmd, unsigned long arg )
174{
175 drm_file_t *priv = filp->private_data;
176 drm_device_t *dev = priv->head->dev;
177 drm_map_t __user *argp = (void __user *)arg;
178 drm_map_t map;
179 drm_map_list_t *r_list = NULL;
180 struct list_head *list;
181 int idx;
182 int i;
183
184 if (copy_from_user(&map, argp, sizeof(map)))
185 return -EFAULT;
186 idx = map.offset;
187
188 down(&dev->struct_sem);
189 if (idx < 0) {
190 up(&dev->struct_sem);
191 return -EINVAL;
192 }
193
194 i = 0;
195 list_for_each(list, &dev->maplist->head) {
196 if(i == idx) {
197 r_list = list_entry(list, drm_map_list_t, head);
198 break;
199 }
200 i++;
201 }
202 if(!r_list || !r_list->map) {
203 up(&dev->struct_sem);
204 return -EINVAL;
205 }
206
207 map.offset = r_list->map->offset;
208 map.size = r_list->map->size;
209 map.type = r_list->map->type;
210 map.flags = r_list->map->flags;
211 map.handle = r_list->map->handle;
212 map.mtrr = r_list->map->mtrr;
213 up(&dev->struct_sem);
214
215 if (copy_to_user(argp, &map, sizeof(map))) return -EFAULT;
216 return 0;
217}
218
219/**
220 * Get client information.
221 *
222 * \param inode device inode.
223 * \param filp file pointer.
224 * \param cmd command.
225 * \param arg user argument, pointing to a drm_client structure.
226 *
227 * \return zero on success or a negative number on failure.
228 *
229 * Searches for the client with the specified index and copies its information
230 * into userspace
231 */
232int drm_getclient( struct inode *inode, struct file *filp,
233 unsigned int cmd, unsigned long arg )
234{
235 drm_file_t *priv = filp->private_data;
236 drm_device_t *dev = priv->head->dev;
237 drm_client_t __user *argp = (void __user *)arg;
238 drm_client_t client;
239 drm_file_t *pt;
240 int idx;
241 int i;
242
243 if (copy_from_user(&client, argp, sizeof(client)))
244 return -EFAULT;
245 idx = client.idx;
246 down(&dev->struct_sem);
247 for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next)
248 ;
249
250 if (!pt) {
251 up(&dev->struct_sem);
252 return -EINVAL;
253 }
254 client.auth = pt->authenticated;
255 client.pid = pt->pid;
256 client.uid = pt->uid;
257 client.magic = pt->magic;
258 client.iocs = pt->ioctl_count;
259 up(&dev->struct_sem);
260
261 if (copy_to_user((drm_client_t __user *)arg, &client, sizeof(client)))
262 return -EFAULT;
263 return 0;
264}
265
266/**
267 * Get statistics information.
268 *
269 * \param inode device inode.
270 * \param filp file pointer.
271 * \param cmd command.
272 * \param arg user argument, pointing to a drm_stats structure.
273 *
274 * \return zero on success or a negative number on failure.
275 */
276int drm_getstats( struct inode *inode, struct file *filp,
277 unsigned int cmd, unsigned long arg )
278{
279 drm_file_t *priv = filp->private_data;
280 drm_device_t *dev = priv->head->dev;
281 drm_stats_t stats;
282 int i;
283
284 memset(&stats, 0, sizeof(stats));
285
286 down(&dev->struct_sem);
287
288 for (i = 0; i < dev->counters; i++) {
289 if (dev->types[i] == _DRM_STAT_LOCK)
290 stats.data[i].value
291 = (dev->lock.hw_lock
292 ? dev->lock.hw_lock->lock : 0);
293 else
294 stats.data[i].value = atomic_read(&dev->counts[i]);
295 stats.data[i].type = dev->types[i];
296 }
297
298 stats.count = dev->counters;
299
300 up(&dev->struct_sem);
301
302 if (copy_to_user((drm_stats_t __user *)arg, &stats, sizeof(stats)))
303 return -EFAULT;
304 return 0;
305}
306
307/**
308 * Setversion ioctl.
309 *
310 * \param inode device inode.
311 * \param filp file pointer.
312 * \param cmd command.
313 * \param arg user argument, pointing to a drm_lock structure.
314 * \return zero on success or negative number on failure.
315 *
316 * Sets the requested interface version
317 */
318int drm_setversion(DRM_IOCTL_ARGS)
319{
320 DRM_DEVICE;
321 drm_set_version_t sv;
322 drm_set_version_t retv;
323 int if_version;
324 drm_set_version_t __user *argp = (void __user *)data;
325 drm_version_t version;
326
327 DRM_COPY_FROM_USER_IOCTL(sv, argp, sizeof(sv));
328
329 memset(&version, 0, sizeof(version));
330
331 dev->driver->version(&version);
332 retv.drm_di_major = DRM_IF_MAJOR;
333 retv.drm_di_minor = DRM_IF_MINOR;
334 retv.drm_dd_major = version.version_major;
335 retv.drm_dd_minor = version.version_minor;
336
337 DRM_COPY_TO_USER_IOCTL(argp, retv, sizeof(sv));
338
339 if (sv.drm_di_major != -1) {
340 if (sv.drm_di_major != DRM_IF_MAJOR ||
341 sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
342 return EINVAL;
343 if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
344 dev->if_version = DRM_MAX(if_version, dev->if_version);
345 if (sv.drm_di_minor >= 1) {
346 /*
347 * Version 1.1 includes tying of DRM to specific device
348 */
349 drm_set_busid(dev);
350 }
351 }
352
353 if (sv.drm_dd_major != -1) {
354 if (sv.drm_dd_major != version.version_major ||
355 sv.drm_dd_minor < 0 || sv.drm_dd_minor > version.version_minor)
356 return EINVAL;
357
358 if (dev->driver->set_version)
359 dev->driver->set_version(dev, &sv);
360 }
361 return 0;
362}
363
364/** No-op ioctl. */
365int drm_noop(struct inode *inode, struct file *filp, unsigned int cmd,
366 unsigned long arg)
367{
368 DRM_DEBUG("\n");
369 return 0;
370}
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
new file mode 100644
index 000000000000..2e236ebcf27b
--- /dev/null
+++ b/drivers/char/drm/drm_irq.c
@@ -0,0 +1,370 @@
1/**
2 * \file drm_irq.h
3 * IRQ support
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
11 *
12 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include "drmP.h"
37
38#include <linux/interrupt.h> /* For task queue support */
39
40/**
41 * Get interrupt from bus id.
42 *
43 * \param inode device inode.
44 * \param filp file pointer.
45 * \param cmd command.
46 * \param arg user argument, pointing to a drm_irq_busid structure.
47 * \return zero on success or a negative number on failure.
48 *
49 * Finds the PCI device with the specified bus id and gets its IRQ number.
50 * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
51 * to that of the device that this DRM instance attached to.
52 */
53int drm_irq_by_busid(struct inode *inode, struct file *filp,
54 unsigned int cmd, unsigned long arg)
55{
56 drm_file_t *priv = filp->private_data;
57 drm_device_t *dev = priv->head->dev;
58 drm_irq_busid_t __user *argp = (void __user *)arg;
59 drm_irq_busid_t p;
60
61 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
62 return -EINVAL;
63
64 if (copy_from_user(&p, argp, sizeof(p)))
65 return -EFAULT;
66
67 if ((p.busnum >> 8) != dev->pci_domain ||
68 (p.busnum & 0xff) != dev->pci_bus ||
69 p.devnum != dev->pci_slot ||
70 p.funcnum != dev->pci_func)
71 return -EINVAL;
72
73 p.irq = dev->irq;
74
75 DRM_DEBUG("%d:%d:%d => IRQ %d\n",
76 p.busnum, p.devnum, p.funcnum, p.irq);
77 if (copy_to_user(argp, &p, sizeof(p)))
78 return -EFAULT;
79 return 0;
80}
81
82/**
83 * Install IRQ handler.
84 *
85 * \param dev DRM device.
86 * \param irq IRQ number.
87 *
88 * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
89 * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
90 * before and after the installation.
91 */
92int drm_irq_install( drm_device_t *dev )
93{
94 int ret;
95 unsigned long sh_flags=0;
96
97 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
98 return -EINVAL;
99
100 if ( dev->irq == 0 )
101 return -EINVAL;
102
103 down( &dev->struct_sem );
104
105 /* Driver must have been initialized */
106 if ( !dev->dev_private ) {
107 up( &dev->struct_sem );
108 return -EINVAL;
109 }
110
111 if ( dev->irq_enabled ) {
112 up( &dev->struct_sem );
113 return -EBUSY;
114 }
115 dev->irq_enabled = 1;
116 up( &dev->struct_sem );
117
118 DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
119
120 if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
121 init_waitqueue_head(&dev->vbl_queue);
122
123 spin_lock_init( &dev->vbl_lock );
124
125 INIT_LIST_HEAD( &dev->vbl_sigs.head );
126
127 dev->vbl_pending = 0;
128 }
129
130 /* Before installing handler */
131 dev->driver->irq_preinstall(dev);
132
133 /* Install handler */
134 if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
135 sh_flags = SA_SHIRQ;
136
137 ret = request_irq( dev->irq, dev->driver->irq_handler,
138 sh_flags, dev->devname, dev );
139 if ( ret < 0 ) {
140 down( &dev->struct_sem );
141 dev->irq_enabled = 0;
142 up( &dev->struct_sem );
143 return ret;
144 }
145
146 /* After installing handler */
147 dev->driver->irq_postinstall(dev);
148
149 return 0;
150}
151
152/**
153 * Uninstall the IRQ handler.
154 *
155 * \param dev DRM device.
156 *
157 * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
158 */
159int drm_irq_uninstall( drm_device_t *dev )
160{
161 int irq_enabled;
162
163 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
164 return -EINVAL;
165
166 down( &dev->struct_sem );
167 irq_enabled = dev->irq_enabled;
168 dev->irq_enabled = 0;
169 up( &dev->struct_sem );
170
171 if ( !irq_enabled )
172 return -EINVAL;
173
174 DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
175
176 dev->driver->irq_uninstall(dev);
177
178 free_irq( dev->irq, dev );
179
180 return 0;
181}
182EXPORT_SYMBOL(drm_irq_uninstall);
183
184/**
185 * IRQ control ioctl.
186 *
187 * \param inode device inode.
188 * \param filp file pointer.
189 * \param cmd command.
190 * \param arg user argument, pointing to a drm_control structure.
191 * \return zero on success or a negative number on failure.
192 *
193 * Calls irq_install() or irq_uninstall() according to \p arg.
194 */
195int drm_control( struct inode *inode, struct file *filp,
196 unsigned int cmd, unsigned long arg )
197{
198 drm_file_t *priv = filp->private_data;
199 drm_device_t *dev = priv->head->dev;
200 drm_control_t ctl;
201
202 /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
203
204 if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) )
205 return -EFAULT;
206
207 switch ( ctl.func ) {
208 case DRM_INST_HANDLER:
209 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
210 return 0;
211 if (dev->if_version < DRM_IF_VERSION(1, 2) &&
212 ctl.irq != dev->irq)
213 return -EINVAL;
214 return drm_irq_install( dev );
215 case DRM_UNINST_HANDLER:
216 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
217 return 0;
218 return drm_irq_uninstall( dev );
219 default:
220 return -EINVAL;
221 }
222}
223
224/**
225 * Wait for VBLANK.
226 *
227 * \param inode device inode.
228 * \param filp file pointer.
229 * \param cmd command.
230 * \param data user argument, pointing to a drm_wait_vblank structure.
231 * \return zero on success or a negative number on failure.
232 *
233 * Verifies the IRQ is installed.
234 *
235 * If a signal is requested checks if this task has already scheduled the same signal
236 * for the same vblank sequence number - nothing to be done in
237 * that case. If the number of tasks waiting for the interrupt exceeds 100 the
238 * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this
239 * task.
240 *
241 * If a signal is not requested, then calls vblank_wait().
242 */
243int drm_wait_vblank( DRM_IOCTL_ARGS )
244{
245 drm_file_t *priv = filp->private_data;
246 drm_device_t *dev = priv->head->dev;
247 drm_wait_vblank_t __user *argp = (void __user *)data;
248 drm_wait_vblank_t vblwait;
249 struct timeval now;
250 int ret = 0;
251 unsigned int flags;
252
253 if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL))
254 return -EINVAL;
255
256 if (!dev->irq)
257 return -EINVAL;
258
259 DRM_COPY_FROM_USER_IOCTL( vblwait, argp, sizeof(vblwait) );
260
261 switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
262 case _DRM_VBLANK_RELATIVE:
263 vblwait.request.sequence += atomic_read( &dev->vbl_received );
264 vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
265 case _DRM_VBLANK_ABSOLUTE:
266 break;
267 default:
268 return -EINVAL;
269 }
270
271 flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
272
273 if ( flags & _DRM_VBLANK_SIGNAL ) {
274 unsigned long irqflags;
275 drm_vbl_sig_t *vbl_sig;
276
277 vblwait.reply.sequence = atomic_read( &dev->vbl_received );
278
279 spin_lock_irqsave( &dev->vbl_lock, irqflags );
280
281 /* Check if this task has already scheduled the same signal
282 * for the same vblank sequence number; nothing to be done in
283 * that case
284 */
285 list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) {
286 if (vbl_sig->sequence == vblwait.request.sequence
287 && vbl_sig->info.si_signo == vblwait.request.signal
288 && vbl_sig->task == current)
289 {
290 spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
291 goto done;
292 }
293 }
294
295 if ( dev->vbl_pending >= 100 ) {
296 spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
297 return -EBUSY;
298 }
299
300 dev->vbl_pending++;
301
302 spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
303
304 if ( !( vbl_sig = drm_alloc( sizeof( drm_vbl_sig_t ), DRM_MEM_DRIVER ) ) ) {
305 return -ENOMEM;
306 }
307
308 memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
309
310 vbl_sig->sequence = vblwait.request.sequence;
311 vbl_sig->info.si_signo = vblwait.request.signal;
312 vbl_sig->task = current;
313
314 spin_lock_irqsave( &dev->vbl_lock, irqflags );
315
316 list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
317
318 spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
319 } else {
320 if (dev->driver->vblank_wait)
321 ret = dev->driver->vblank_wait( dev, &vblwait.request.sequence );
322
323 do_gettimeofday( &now );
324 vblwait.reply.tval_sec = now.tv_sec;
325 vblwait.reply.tval_usec = now.tv_usec;
326 }
327
328done:
329 DRM_COPY_TO_USER_IOCTL( argp, vblwait, sizeof(vblwait) );
330
331 return ret;
332}
333
334/**
335 * Send the VBLANK signals.
336 *
337 * \param dev DRM device.
338 *
339 * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
340 *
341 * If a signal is not requested, then calls vblank_wait().
342 */
343void drm_vbl_send_signals( drm_device_t *dev )
344{
345 struct list_head *list, *tmp;
346 drm_vbl_sig_t *vbl_sig;
347 unsigned int vbl_seq = atomic_read( &dev->vbl_received );
348 unsigned long flags;
349
350 spin_lock_irqsave( &dev->vbl_lock, flags );
351
352 list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) {
353 vbl_sig = list_entry( list, drm_vbl_sig_t, head );
354 if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
355 vbl_sig->info.si_code = vbl_seq;
356 send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
357
358 list_del( list );
359
360 drm_free( vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER );
361
362 dev->vbl_pending--;
363 }
364 }
365
366 spin_unlock_irqrestore( &dev->vbl_lock, flags );
367}
368EXPORT_SYMBOL(drm_vbl_send_signals);
369
370
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
new file mode 100644
index 000000000000..d0d6fc661625
--- /dev/null
+++ b/drivers/char/drm/drm_lock.c
@@ -0,0 +1,303 @@
1/**
2 * \file drm_lock.h
3 * IOCTLs for locking
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
11 *
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include "drmP.h"
37
38/**
39 * Lock ioctl.
40 *
41 * \param inode device inode.
42 * \param filp file pointer.
43 * \param cmd command.
44 * \param arg user argument, pointing to a drm_lock structure.
45 * \return zero on success or negative number on failure.
46 *
47 * Add the current task to the lock wait queue, and attempt to take to lock.
48 */
49int drm_lock( struct inode *inode, struct file *filp,
50 unsigned int cmd, unsigned long arg )
51{
52 drm_file_t *priv = filp->private_data;
53 drm_device_t *dev = priv->head->dev;
54 DECLARE_WAITQUEUE( entry, current );
55 drm_lock_t lock;
56 int ret = 0;
57
58 ++priv->lock_count;
59
60 if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) )
61 return -EFAULT;
62
63 if ( lock.context == DRM_KERNEL_CONTEXT ) {
64 DRM_ERROR( "Process %d using kernel context %d\n",
65 current->pid, lock.context );
66 return -EINVAL;
67 }
68
69 DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
70 lock.context, current->pid,
71 dev->lock.hw_lock->lock, lock.flags );
72
73 if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
74 if ( lock.context < 0 )
75 return -EINVAL;
76
77 add_wait_queue( &dev->lock.lock_queue, &entry );
78 for (;;) {
79 __set_current_state(TASK_INTERRUPTIBLE);
80 if ( !dev->lock.hw_lock ) {
81 /* Device has been unregistered */
82 ret = -EINTR;
83 break;
84 }
85 if ( drm_lock_take( &dev->lock.hw_lock->lock,
86 lock.context ) ) {
87 dev->lock.filp = filp;
88 dev->lock.lock_time = jiffies;
89 atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
90 break; /* Got lock */
91 }
92
93 /* Contention */
94 schedule();
95 if ( signal_pending( current ) ) {
96 ret = -ERESTARTSYS;
97 break;
98 }
99 }
100 __set_current_state(TASK_RUNNING);
101 remove_wait_queue( &dev->lock.lock_queue, &entry );
102
103 sigemptyset( &dev->sigmask );
104 sigaddset( &dev->sigmask, SIGSTOP );
105 sigaddset( &dev->sigmask, SIGTSTP );
106 sigaddset( &dev->sigmask, SIGTTIN );
107 sigaddset( &dev->sigmask, SIGTTOU );
108 dev->sigdata.context = lock.context;
109 dev->sigdata.lock = dev->lock.hw_lock;
110 block_all_signals( drm_notifier,
111 &dev->sigdata, &dev->sigmask );
112
113 if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY))
114 dev->driver->dma_ready(dev);
115
116 if ( dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT ))
117 return dev->driver->dma_quiescent(dev);
118
119 /* dev->driver->kernel_context_switch isn't used by any of the x86
120 * drivers but is used by the Sparc driver.
121 */
122
123 if (dev->driver->kernel_context_switch &&
124 dev->last_context != lock.context) {
125 dev->driver->kernel_context_switch(dev, dev->last_context,
126 lock.context);
127 }
128 DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
129
130 return ret;
131}
132
133/**
134 * Unlock ioctl.
135 *
136 * \param inode device inode.
137 * \param filp file pointer.
138 * \param cmd command.
139 * \param arg user argument, pointing to a drm_lock structure.
140 * \return zero on success or negative number on failure.
141 *
142 * Transfer and free the lock.
143 */
144int drm_unlock( struct inode *inode, struct file *filp,
145 unsigned int cmd, unsigned long arg )
146{
147 drm_file_t *priv = filp->private_data;
148 drm_device_t *dev = priv->head->dev;
149 drm_lock_t lock;
150
151 if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) )
152 return -EFAULT;
153
154 if ( lock.context == DRM_KERNEL_CONTEXT ) {
155 DRM_ERROR( "Process %d using kernel context %d\n",
156 current->pid, lock.context );
157 return -EINVAL;
158 }
159
160 atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
161
162 /* kernel_context_switch isn't used by any of the x86 drm
163 * modules but is required by the Sparc driver.
164 */
165 if (dev->driver->kernel_context_switch_unlock)
166 dev->driver->kernel_context_switch_unlock(dev, &lock);
167 else {
168 drm_lock_transfer( dev, &dev->lock.hw_lock->lock,
169 DRM_KERNEL_CONTEXT );
170
171 if ( drm_lock_free( dev, &dev->lock.hw_lock->lock,
172 DRM_KERNEL_CONTEXT ) ) {
173 DRM_ERROR( "\n" );
174 }
175 }
176
177 unblock_all_signals();
178 return 0;
179}
180
181/**
182 * Take the heavyweight lock.
183 *
184 * \param lock lock pointer.
185 * \param context locking context.
186 * \return one if the lock is held, or zero otherwise.
187 *
188 * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
189 */
190int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
191{
192 unsigned int old, new, prev;
193
194 do {
195 old = *lock;
196 if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
197 else new = context | _DRM_LOCK_HELD;
198 prev = cmpxchg(lock, old, new);
199 } while (prev != old);
200 if (_DRM_LOCKING_CONTEXT(old) == context) {
201 if (old & _DRM_LOCK_HELD) {
202 if (context != DRM_KERNEL_CONTEXT) {
203 DRM_ERROR("%d holds heavyweight lock\n",
204 context);
205 }
206 return 0;
207 }
208 }
209 if (new == (context | _DRM_LOCK_HELD)) {
210 /* Have lock */
211 return 1;
212 }
213 return 0;
214}
215
216/**
217 * This takes a lock forcibly and hands it to context. Should ONLY be used
218 * inside *_unlock to give lock to kernel before calling *_dma_schedule.
219 *
220 * \param dev DRM device.
221 * \param lock lock pointer.
222 * \param context locking context.
223 * \return always one.
224 *
225 * Resets the lock file pointer.
226 * Marks the lock as held by the given context, via the \p cmpxchg instruction.
227 */
228int drm_lock_transfer(drm_device_t *dev,
229 __volatile__ unsigned int *lock, unsigned int context)
230{
231 unsigned int old, new, prev;
232
233 dev->lock.filp = NULL;
234 do {
235 old = *lock;
236 new = context | _DRM_LOCK_HELD;
237 prev = cmpxchg(lock, old, new);
238 } while (prev != old);
239 return 1;
240}
241
242/**
243 * Free lock.
244 *
245 * \param dev DRM device.
246 * \param lock lock.
247 * \param context context.
248 *
249 * Resets the lock file pointer.
250 * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
251 * waiting on the lock queue.
252 */
253int drm_lock_free(drm_device_t *dev,
254 __volatile__ unsigned int *lock, unsigned int context)
255{
256 unsigned int old, new, prev;
257
258 dev->lock.filp = NULL;
259 do {
260 old = *lock;
261 new = 0;
262 prev = cmpxchg(lock, old, new);
263 } while (prev != old);
264 if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
265 DRM_ERROR("%d freed heavyweight lock held by %d\n",
266 context,
267 _DRM_LOCKING_CONTEXT(old));
268 return 1;
269 }
270 wake_up_interruptible(&dev->lock.lock_queue);
271 return 0;
272}
273
274/**
275 * If we get here, it means that the process has called DRM_IOCTL_LOCK
276 * without calling DRM_IOCTL_UNLOCK.
277 *
278 * If the lock is not held, then let the signal proceed as usual. If the lock
279 * is held, then set the contended flag and keep the signal blocked.
280 *
281 * \param priv pointer to a drm_sigdata structure.
282 * \return one if the signal should be delivered normally, or zero if the
283 * signal should be blocked.
284 */
285int drm_notifier(void *priv)
286{
287 drm_sigdata_t *s = (drm_sigdata_t *)priv;
288 unsigned int old, new, prev;
289
290
291 /* Allow signal delivery if lock isn't held */
292 if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
293 || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
294
295 /* Otherwise, set flag to force call to
296 drmUnlock */
297 do {
298 old = s->lock->lock;
299 new = old | _DRM_LOCK_CONT;
300 prev = cmpxchg(&s->lock->lock, old, new);
301 } while (prev != old);
302 return 0;
303}
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
new file mode 100644
index 000000000000..7f53f756c052
--- /dev/null
+++ b/drivers/char/drm/drm_memory.c
@@ -0,0 +1,181 @@
1/**
2 * \file drm_memory.h
3 * Memory management wrappers for DRM
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
11 *
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include <linux/config.h>
37#include <linux/highmem.h>
38#include "drmP.h"
39
40#ifdef DEBUG_MEMORY
41#include "drm_memory_debug.h"
42#else
43
44/** No-op. */
45void drm_mem_init(void)
46{
47}
48
49/**
50 * Called when "/proc/dri/%dev%/mem" is read.
51 *
52 * \param buf output buffer.
53 * \param start start of output data.
54 * \param offset requested start offset.
55 * \param len requested number of bytes.
56 * \param eof whether there is no more data to return.
57 * \param data private data.
58 * \return number of written bytes.
59 *
60 * No-op.
61 */
62int drm_mem_info(char *buf, char **start, off_t offset,
63 int len, int *eof, void *data)
64{
65 return 0;
66}
67
68/** Wrapper around kmalloc() */
69void *drm_calloc(size_t nmemb, size_t size, int area)
70{
71 void *addr;
72
73 addr = kmalloc(size * nmemb, GFP_KERNEL);
74 if (addr != NULL)
75 memset((void *)addr, 0, size * nmemb);
76
77 return addr;
78}
79EXPORT_SYMBOL(drm_calloc);
80
81/** Wrapper around kmalloc() and kfree() */
82void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
83{
84 void *pt;
85
86 if (!(pt = kmalloc(size, GFP_KERNEL))) return NULL;
87 if (oldpt && oldsize) {
88 memcpy(pt, oldpt, oldsize);
89 kfree(oldpt);
90 }
91 return pt;
92}
93
94/**
95 * Allocate pages.
96 *
97 * \param order size order.
98 * \param area memory area. (Not used.)
99 * \return page address on success, or zero on failure.
100 *
101 * Allocate and reserve free pages.
102 */
103unsigned long drm_alloc_pages(int order, int area)
104{
105 unsigned long address;
106 unsigned long bytes = PAGE_SIZE << order;
107 unsigned long addr;
108 unsigned int sz;
109
110 address = __get_free_pages(GFP_KERNEL, order);
111 if (!address)
112 return 0;
113
114 /* Zero */
115 memset((void *)address, 0, bytes);
116
117 /* Reserve */
118 for (addr = address, sz = bytes;
119 sz > 0;
120 addr += PAGE_SIZE, sz -= PAGE_SIZE) {
121 SetPageReserved(virt_to_page(addr));
122 }
123
124 return address;
125}
126
127/**
128 * Free pages.
129 *
130 * \param address address of the pages to free.
131 * \param order size order.
132 * \param area memory area. (Not used.)
133 *
134 * Unreserve and free pages allocated by alloc_pages().
135 */
136void drm_free_pages(unsigned long address, int order, int area)
137{
138 unsigned long bytes = PAGE_SIZE << order;
139 unsigned long addr;
140 unsigned int sz;
141
142 if (!address)
143 return;
144
145 /* Unreserve */
146 for (addr = address, sz = bytes;
147 sz > 0;
148 addr += PAGE_SIZE, sz -= PAGE_SIZE) {
149 ClearPageReserved(virt_to_page(addr));
150 }
151
152 free_pages(address, order);
153}
154
155
156#if __OS_HAS_AGP
157/** Wrapper around agp_allocate_memory() */
158DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type)
159{
160 return drm_agp_allocate_memory(bridge, pages, type);
161}
162
163/** Wrapper around agp_free_memory() */
164int drm_free_agp(DRM_AGP_MEM *handle, int pages)
165{
166 return drm_agp_free_memory(handle) ? 0 : -EINVAL;
167}
168
169/** Wrapper around agp_bind_memory() */
170int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start)
171{
172 return drm_agp_bind_memory(handle, start);
173}
174
175/** Wrapper around agp_unbind_memory() */
176int drm_unbind_agp(DRM_AGP_MEM *handle)
177{
178 return drm_agp_unbind_memory(handle);
179}
180#endif /* agp */
181#endif /* debug_memory */
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
new file mode 100644
index 000000000000..422b94268709
--- /dev/null
+++ b/drivers/char/drm/drm_memory.h
@@ -0,0 +1,197 @@
1/**
2 * \file drm_memory.h
3 * Memory management wrappers for DRM
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
11 *
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include <linux/config.h>
37#include <linux/highmem.h>
38#include <linux/vmalloc.h>
39#include "drmP.h"
40
41/**
42 * Cut down version of drm_memory_debug.h, which used to be called
43 * drm_memory.h.
44 */
45
46#if __OS_HAS_AGP
47
48#include <linux/vmalloc.h>
49
50#ifdef HAVE_PAGE_AGP
51#include <asm/agp.h>
52#else
53# ifdef __powerpc__
54# define PAGE_AGP __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
55# else
56# define PAGE_AGP PAGE_KERNEL
57# endif
58#endif
59
60/*
61 * Find the drm_map that covers the range [offset, offset+size).
62 */
63static inline drm_map_t *
64drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev)
65{
66 struct list_head *list;
67 drm_map_list_t *r_list;
68 drm_map_t *map;
69
70 list_for_each(list, &dev->maplist->head) {
71 r_list = (drm_map_list_t *) list;
72 map = r_list->map;
73 if (!map)
74 continue;
75 if (map->offset <= offset && (offset + size) <= (map->offset + map->size))
76 return map;
77 }
78 return NULL;
79}
80
81static inline void *
82agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
83{
84 unsigned long *phys_addr_map, i, num_pages = PAGE_ALIGN(size) / PAGE_SIZE;
85 struct drm_agp_mem *agpmem;
86 struct page **page_map;
87 void *addr;
88
89 size = PAGE_ALIGN(size);
90
91#ifdef __alpha__
92 offset -= dev->hose->mem_space->start;
93#endif
94
95 for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
96 if (agpmem->bound <= offset
97 && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= (offset + size))
98 break;
99 if (!agpmem)
100 return NULL;
101
102 /*
103 * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
104 * the CPU do not get remapped by the GART. We fix this by using the kernel's
105 * page-table instead (that's probably faster anyhow...).
106 */
107 /* note: use vmalloc() because num_pages could be large... */
108 page_map = vmalloc(num_pages * sizeof(struct page *));
109 if (!page_map)
110 return NULL;
111
112 phys_addr_map = agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
113 for (i = 0; i < num_pages; ++i)
114 page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
115 addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
116 vfree(page_map);
117
118 return addr;
119}
120
121static inline unsigned long
122drm_follow_page (void *vaddr)
123{
124 pgd_t *pgd = pgd_offset_k((unsigned long) vaddr);
125 pud_t *pud = pud_offset(pgd, (unsigned long) vaddr);
126 pmd_t *pmd = pmd_offset(pud, (unsigned long) vaddr);
127 pte_t *ptep = pte_offset_kernel(pmd, (unsigned long) vaddr);
128 return pte_pfn(*ptep) << PAGE_SHIFT;
129}
130
131#else /* __OS_HAS_AGP */
132
133static inline drm_map_t *drm_lookup_map(unsigned long offset, unsigned long size, drm_device_t *dev)
134{
135 return NULL;
136}
137
138static inline void *agp_remap(unsigned long offset, unsigned long size, drm_device_t *dev)
139{
140 return NULL;
141}
142
143static inline unsigned long drm_follow_page (void *vaddr)
144{
145 return 0;
146}
147
148#endif
149
150static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
151{
152 if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
153 drm_map_t *map = drm_lookup_map(offset, size, dev);
154
155 if (map && map->type == _DRM_AGP)
156 return agp_remap(offset, size, dev);
157 }
158 return ioremap(offset, size);
159}
160
161static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
162 drm_device_t *dev)
163{
164 if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
165 drm_map_t *map = drm_lookup_map(offset, size, dev);
166
167 if (map && map->type == _DRM_AGP)
168 return agp_remap(offset, size, dev);
169 }
170 return ioremap_nocache(offset, size);
171}
172
173static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
174{
175 /*
176 * This is a bit ugly. It would be much cleaner if the DRM API would use separate
177 * routines for handling mappings in the AGP space. Hopefully this can be done in
178 * a future revision of the interface...
179 */
180 if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
181 && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END))
182 {
183 unsigned long offset;
184 drm_map_t *map;
185
186 offset = drm_follow_page(pt) | ((unsigned long) pt & ~PAGE_MASK);
187 map = drm_lookup_map(offset, size, dev);
188 if (map && map->type == _DRM_AGP) {
189 vunmap(pt);
190 return;
191 }
192 }
193
194 iounmap(pt);
195}
196
197
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
new file mode 100644
index 000000000000..2c82e69a7fd2
--- /dev/null
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -0,0 +1,459 @@
1/**
2 * \file drm_memory.h
3 * Memory management wrappers for DRM.
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
11 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
12 * All Rights Reserved.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31 * OTHER DEALINGS IN THE SOFTWARE.
32 */
33
34#include <linux/config.h>
35#include "drmP.h"
36
37typedef struct drm_mem_stats {
38 const char *name;
39 int succeed_count;
40 int free_count;
41 int fail_count;
42 unsigned long bytes_allocated;
43 unsigned long bytes_freed;
44} drm_mem_stats_t;
45
46static DEFINE_SPINLOCK(DRM(mem_lock));
47static unsigned long DRM(ram_available) = 0; /* In pages */
48static unsigned long DRM(ram_used) = 0;
49static drm_mem_stats_t DRM(mem_stats)[] = {
50 [DRM_MEM_DMA] = { "dmabufs" },
51 [DRM_MEM_SAREA] = { "sareas" },
52 [DRM_MEM_DRIVER] = { "driver" },
53 [DRM_MEM_MAGIC] = { "magic" },
54 [DRM_MEM_IOCTLS] = { "ioctltab" },
55 [DRM_MEM_MAPS] = { "maplist" },
56 [DRM_MEM_VMAS] = { "vmalist" },
57 [DRM_MEM_BUFS] = { "buflist" },
58 [DRM_MEM_SEGS] = { "seglist" },
59 [DRM_MEM_PAGES] = { "pagelist" },
60 [DRM_MEM_FILES] = { "files" },
61 [DRM_MEM_QUEUES] = { "queues" },
62 [DRM_MEM_CMDS] = { "commands" },
63 [DRM_MEM_MAPPINGS] = { "mappings" },
64 [DRM_MEM_BUFLISTS] = { "buflists" },
65 [DRM_MEM_AGPLISTS] = { "agplist" },
66 [DRM_MEM_SGLISTS] = { "sglist" },
67 [DRM_MEM_TOTALAGP] = { "totalagp" },
68 [DRM_MEM_BOUNDAGP] = { "boundagp" },
69 [DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
70 [DRM_MEM_CTXLIST] = { "ctxlist" },
71 [DRM_MEM_STUB] = { "stub" },
72 { NULL, 0, } /* Last entry must be null */
73};
74
75void DRM(mem_init)(void)
76{
77 drm_mem_stats_t *mem;
78 struct sysinfo si;
79
80 for (mem = DRM(mem_stats); mem->name; ++mem) {
81 mem->succeed_count = 0;
82 mem->free_count = 0;
83 mem->fail_count = 0;
84 mem->bytes_allocated = 0;
85 mem->bytes_freed = 0;
86 }
87
88 si_meminfo(&si);
89 DRM(ram_available) = si.totalram;
90 DRM(ram_used) = 0;
91}
92
93/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
94
95static int DRM(_mem_info)(char *buf, char **start, off_t offset,
96 int request, int *eof, void *data)
97{
98 drm_mem_stats_t *pt;
99 int len = 0;
100
101 if (offset > DRM_PROC_LIMIT) {
102 *eof = 1;
103 return 0;
104 }
105
106 *eof = 0;
107 *start = &buf[offset];
108
109 DRM_PROC_PRINT(" total counts "
110 " | outstanding \n");
111 DRM_PROC_PRINT("type alloc freed fail bytes freed"
112 " | allocs bytes\n\n");
113 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
114 "system", 0, 0, 0,
115 DRM(ram_available) << (PAGE_SHIFT - 10));
116 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
117 "locked", 0, 0, 0, DRM(ram_used) >> 10);
118 DRM_PROC_PRINT("\n");
119 for (pt = DRM(mem_stats); pt->name; pt++) {
120 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
121 pt->name,
122 pt->succeed_count,
123 pt->free_count,
124 pt->fail_count,
125 pt->bytes_allocated,
126 pt->bytes_freed,
127 pt->succeed_count - pt->free_count,
128 (long)pt->bytes_allocated
129 - (long)pt->bytes_freed);
130 }
131
132 if (len > request + offset) return request;
133 *eof = 1;
134 return len - offset;
135}
136
137int DRM(mem_info)(char *buf, char **start, off_t offset,
138 int len, int *eof, void *data)
139{
140 int ret;
141
142 spin_lock(&DRM(mem_lock));
143 ret = DRM(_mem_info)(buf, start, offset, len, eof, data);
144 spin_unlock(&DRM(mem_lock));
145 return ret;
146}
147
148void *DRM(alloc)(size_t size, int area)
149{
150 void *pt;
151
152 if (!size) {
153 DRM_MEM_ERROR(area, "Allocating 0 bytes\n");
154 return NULL;
155 }
156
157 if (!(pt = kmalloc(size, GFP_KERNEL))) {
158 spin_lock(&DRM(mem_lock));
159 ++DRM(mem_stats)[area].fail_count;
160 spin_unlock(&DRM(mem_lock));
161 return NULL;
162 }
163 spin_lock(&DRM(mem_lock));
164 ++DRM(mem_stats)[area].succeed_count;
165 DRM(mem_stats)[area].bytes_allocated += size;
166 spin_unlock(&DRM(mem_lock));
167 return pt;
168}
169
170void *DRM(calloc)(size_t nmemb, size_t size, int area)
171{
172 void *addr;
173
174 addr = DRM(alloc)(nmemb * size, area);
175 if (addr != NULL)
176 memset((void *)addr, 0, size * nmemb);
177
178 return addr;
179}
180
181void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
182{
183 void *pt;
184
185 if (!(pt = DRM(alloc)(size, area))) return NULL;
186 if (oldpt && oldsize) {
187 memcpy(pt, oldpt, oldsize);
188 DRM(free)(oldpt, oldsize, area);
189 }
190 return pt;
191}
192
193void DRM(free)(void *pt, size_t size, int area)
194{
195 int alloc_count;
196 int free_count;
197
198 if (!pt) DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
199 else kfree(pt);
200 spin_lock(&DRM(mem_lock));
201 DRM(mem_stats)[area].bytes_freed += size;
202 free_count = ++DRM(mem_stats)[area].free_count;
203 alloc_count = DRM(mem_stats)[area].succeed_count;
204 spin_unlock(&DRM(mem_lock));
205 if (free_count > alloc_count) {
206 DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
207 free_count, alloc_count);
208 }
209}
210
211unsigned long DRM(alloc_pages)(int order, int area)
212{
213 unsigned long address;
214 unsigned long bytes = PAGE_SIZE << order;
215 unsigned long addr;
216 unsigned int sz;
217
218 spin_lock(&DRM(mem_lock));
219 if ((DRM(ram_used) >> PAGE_SHIFT)
220 > (DRM_RAM_PERCENT * DRM(ram_available)) / 100) {
221 spin_unlock(&DRM(mem_lock));
222 return 0;
223 }
224 spin_unlock(&DRM(mem_lock));
225
226 address = __get_free_pages(GFP_KERNEL, order);
227 if (!address) {
228 spin_lock(&DRM(mem_lock));
229 ++DRM(mem_stats)[area].fail_count;
230 spin_unlock(&DRM(mem_lock));
231 return 0;
232 }
233 spin_lock(&DRM(mem_lock));
234 ++DRM(mem_stats)[area].succeed_count;
235 DRM(mem_stats)[area].bytes_allocated += bytes;
236 DRM(ram_used) += bytes;
237 spin_unlock(&DRM(mem_lock));
238
239
240 /* Zero outside the lock */
241 memset((void *)address, 0, bytes);
242
243 /* Reserve */
244 for (addr = address, sz = bytes;
245 sz > 0;
246 addr += PAGE_SIZE, sz -= PAGE_SIZE) {
247 SetPageReserved(virt_to_page(addr));
248 }
249
250 return address;
251}
252
253void DRM(free_pages)(unsigned long address, int order, int area)
254{
255 unsigned long bytes = PAGE_SIZE << order;
256 int alloc_count;
257 int free_count;
258 unsigned long addr;
259 unsigned int sz;
260
261 if (!address) {
262 DRM_MEM_ERROR(area, "Attempt to free address 0\n");
263 } else {
264 /* Unreserve */
265 for (addr = address, sz = bytes;
266 sz > 0;
267 addr += PAGE_SIZE, sz -= PAGE_SIZE) {
268 ClearPageReserved(virt_to_page(addr));
269 }
270 free_pages(address, order);
271 }
272
273 spin_lock(&DRM(mem_lock));
274 free_count = ++DRM(mem_stats)[area].free_count;
275 alloc_count = DRM(mem_stats)[area].succeed_count;
276 DRM(mem_stats)[area].bytes_freed += bytes;
277 DRM(ram_used) -= bytes;
278 spin_unlock(&DRM(mem_lock));
279 if (free_count > alloc_count) {
280 DRM_MEM_ERROR(area,
281 "Excess frees: %d frees, %d allocs\n",
282 free_count, alloc_count);
283 }
284}
285
286void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev)
287{
288 void *pt;
289
290 if (!size) {
291 DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
292 "Mapping 0 bytes at 0x%08lx\n", offset);
293 return NULL;
294 }
295
296 if (!(pt = drm_ioremap(offset, size, dev))) {
297 spin_lock(&DRM(mem_lock));
298 ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
299 spin_unlock(&DRM(mem_lock));
300 return NULL;
301 }
302 spin_lock(&DRM(mem_lock));
303 ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
304 DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
305 spin_unlock(&DRM(mem_lock));
306 return pt;
307}
308
309void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev)
310{
311 void *pt;
312
313 if (!size) {
314 DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
315 "Mapping 0 bytes at 0x%08lx\n", offset);
316 return NULL;
317 }
318
319 if (!(pt = drm_ioremap_nocache(offset, size, dev))) {
320 spin_lock(&DRM(mem_lock));
321 ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
322 spin_unlock(&DRM(mem_lock));
323 return NULL;
324 }
325 spin_lock(&DRM(mem_lock));
326 ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
327 DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
328 spin_unlock(&DRM(mem_lock));
329 return pt;
330}
331
332void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
333{
334 int alloc_count;
335 int free_count;
336
337 if (!pt)
338 DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
339 "Attempt to free NULL pointer\n");
340 else
341 drm_ioremapfree(pt, size, dev);
342
343 spin_lock(&DRM(mem_lock));
344 DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size;
345 free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
346 alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
347 spin_unlock(&DRM(mem_lock));
348 if (free_count > alloc_count) {
349 DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
350 "Excess frees: %d frees, %d allocs\n",
351 free_count, alloc_count);
352 }
353}
354
355#if __OS_HAS_AGP
356
357DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
358{
359 DRM_AGP_MEM *handle;
360
361 if (!pages) {
362 DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n");
363 return NULL;
364 }
365
366 if ((handle = DRM(agp_allocate_memory)(pages, type))) {
367 spin_lock(&DRM(mem_lock));
368 ++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
369 DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated
370 += pages << PAGE_SHIFT;
371 spin_unlock(&DRM(mem_lock));
372 return handle;
373 }
374 spin_lock(&DRM(mem_lock));
375 ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count;
376 spin_unlock(&DRM(mem_lock));
377 return NULL;
378}
379
380int DRM(free_agp)(DRM_AGP_MEM *handle, int pages)
381{
382 int alloc_count;
383 int free_count;
384 int retval = -EINVAL;
385
386 if (!handle) {
387 DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
388 "Attempt to free NULL AGP handle\n");
389 return retval;
390 }
391
392 if (DRM(agp_free_memory)(handle)) {
393 spin_lock(&DRM(mem_lock));
394 free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
395 alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
396 DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
397 += pages << PAGE_SHIFT;
398 spin_unlock(&DRM(mem_lock));
399 if (free_count > alloc_count) {
400 DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
401 "Excess frees: %d frees, %d allocs\n",
402 free_count, alloc_count);
403 }
404 return 0;
405 }
406 return retval;
407}
408
409int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start)
410{
411 int retcode = -EINVAL;
412
413 if (!handle) {
414 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
415 "Attempt to bind NULL AGP handle\n");
416 return retcode;
417 }
418
419 if (!(retcode = DRM(agp_bind_memory)(handle, start))) {
420 spin_lock(&DRM(mem_lock));
421 ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
422 DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
423 += handle->page_count << PAGE_SHIFT;
424 spin_unlock(&DRM(mem_lock));
425 return retcode;
426 }
427 spin_lock(&DRM(mem_lock));
428 ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count;
429 spin_unlock(&DRM(mem_lock));
430 return retcode;
431}
432
433int DRM(unbind_agp)(DRM_AGP_MEM *handle)
434{
435 int alloc_count;
436 int free_count;
437 int retcode = -EINVAL;
438
439 if (!handle) {
440 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
441 "Attempt to unbind NULL AGP handle\n");
442 return retcode;
443 }
444
445 if ((retcode = DRM(agp_unbind_memory)(handle))) return retcode;
446 spin_lock(&DRM(mem_lock));
447 free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
448 alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
449 DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
450 += handle->page_count << PAGE_SHIFT;
451 spin_unlock(&DRM(mem_lock));
452 if (free_count > alloc_count) {
453 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
454 "Excess frees: %d frees, %d allocs\n",
455 free_count, alloc_count);
456 }
457 return retcode;
458}
459#endif
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
new file mode 100644
index 000000000000..b14cd370dea5
--- /dev/null
+++ b/drivers/char/drm/drm_os_linux.h
@@ -0,0 +1,149 @@
1/**
2 * \file drm_os_linux.h
3 * OS abstraction macros.
4 */
5
6
7#include <linux/interrupt.h> /* For task queue support */
8#include <linux/delay.h>
9
10/** File pointer type */
11#define DRMFILE struct file *
12/** Ioctl arguments */
13#define DRM_IOCTL_ARGS struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data
14#define DRM_ERR(d) -(d)
15/** Current process ID */
16#define DRM_CURRENTPID current->pid
17#define DRM_UDELAY(d) udelay(d)
18/** Read a byte from a MMIO region */
19#define DRM_READ8(map, offset) readb(((void __iomem *)(map)->handle) + (offset))
20/** Read a word from a MMIO region */
21#define DRM_READ16(map, offset) readw(((void __iomem *)(map)->handle) + (offset))
22/** Read a dword from a MMIO region */
23#define DRM_READ32(map, offset) readl(((void __iomem *)(map)->handle) + (offset))
24/** Write a byte into a MMIO region */
25#define DRM_WRITE8(map, offset, val) writeb(val, ((void __iomem *)(map)->handle) + (offset))
26/** Write a word into a MMIO region */
27#define DRM_WRITE16(map, offset, val) writew(val, ((void __iomem *)(map)->handle) + (offset))
28/** Write a dword into a MMIO region */
29#define DRM_WRITE32(map, offset, val) writel(val, ((void __iomem *)(map)->handle) + (offset))
30/** Read memory barrier */
31#define DRM_READMEMORYBARRIER() rmb()
32/** Write memory barrier */
33#define DRM_WRITEMEMORYBARRIER() wmb()
34/** Read/write memory barrier */
35#define DRM_MEMORYBARRIER() mb()
36/** DRM device local declaration */
37#define DRM_DEVICE drm_file_t *priv = filp->private_data; \
38 drm_device_t *dev = priv->head->dev
39
40/** IRQ handler arguments and return type and values */
41#define DRM_IRQ_ARGS int irq, void *arg, struct pt_regs *regs
42
43/** AGP types */
44#if __OS_HAS_AGP
45#define DRM_AGP_MEM struct agp_memory
46#define DRM_AGP_KERN struct agp_kern_info
47#else
48/* define some dummy types for non AGP supporting kernels */
49struct no_agp_kern {
50 unsigned long aper_base;
51 unsigned long aper_size;
52};
53#define DRM_AGP_MEM int
54#define DRM_AGP_KERN struct no_agp_kern
55#endif
56
57#if !(__OS_HAS_MTRR)
58static __inline__ int mtrr_add (unsigned long base, unsigned long size,
59 unsigned int type, char increment)
60{
61 return -ENODEV;
62}
63
64static __inline__ int mtrr_del (int reg, unsigned long base,
65 unsigned long size)
66{
67 return -ENODEV;
68}
69#define MTRR_TYPE_WRCOMB 1
70
71#endif
72
73/** Task queue handler arguments */
74#define DRM_TASKQUEUE_ARGS void *arg
75
76/** For data going into the kernel through the ioctl argument */
77#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
78 if ( copy_from_user(&arg1, arg2, arg3) ) \
79 return -EFAULT
80/** For data going from the kernel through the ioctl argument */
81#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \
82 if ( copy_to_user(arg1, &arg2, arg3) ) \
83 return -EFAULT
84/** Other copying of data to kernel space */
85#define DRM_COPY_FROM_USER(arg1, arg2, arg3) \
86 copy_from_user(arg1, arg2, arg3)
87/** Other copying of data from kernel space */
88#define DRM_COPY_TO_USER(arg1, arg2, arg3) \
89 copy_to_user(arg1, arg2, arg3)
90/* Macros for copyfrom user, but checking readability only once */
91#define DRM_VERIFYAREA_READ( uaddr, size ) \
92 (access_ok( VERIFY_READ, uaddr, size ) ? 0 : -EFAULT)
93#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
94 __copy_from_user(arg1, arg2, arg3)
95#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3) \
96 __copy_to_user(arg1, arg2, arg3)
97#define DRM_GET_USER_UNCHECKED(val, uaddr) \
98 __get_user(val, uaddr)
99
100#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data
101
102/**
103 * Get the pointer to the SAREA.
104 *
105 * Searches the SAREA on the mapping lists and points drm_device::sarea to it.
106 */
107#define DRM_GETSAREA() \
108do { \
109 drm_map_list_t *entry; \
110 list_for_each_entry( entry, &dev->maplist->head, head ) { \
111 if ( entry->map && \
112 entry->map->type == _DRM_SHM && \
113 (entry->map->flags & _DRM_CONTAINS_LOCK) ) { \
114 dev_priv->sarea = entry->map; \
115 break; \
116 } \
117 } \
118} while (0)
119
120#define DRM_HZ HZ
121
122#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
123do { \
124 DECLARE_WAITQUEUE(entry, current); \
125 unsigned long end = jiffies + (timeout); \
126 add_wait_queue(&(queue), &entry); \
127 \
128 for (;;) { \
129 __set_current_state(TASK_INTERRUPTIBLE); \
130 if (condition) \
131 break; \
132 if (time_after_eq(jiffies, end)) { \
133 ret = -EBUSY; \
134 break; \
135 } \
136 schedule_timeout((HZ/100 > 1) ? HZ/100 : 1); \
137 if (signal_pending(current)) { \
138 ret = -EINTR; \
139 break; \
140 } \
141 } \
142 __set_current_state(TASK_RUNNING); \
143 remove_wait_queue(&(queue), &entry); \
144} while (0)
145
146
147#define DRM_WAKEUP( queue ) wake_up_interruptible( queue )
148#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
149
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
new file mode 100644
index 000000000000..192e8762571c
--- /dev/null
+++ b/drivers/char/drm/drm_pci.c
@@ -0,0 +1,140 @@
1/* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */
2/**
3 * \file drm_pci.c
4 * \brief Functions and ioctls to manage PCI memory
5 *
6 * \warning These interfaces aren't stable yet.
7 *
8 * \todo Implement the remaining ioctl's for the PCI pools.
9 * \todo The wrappers here are so thin that they would be better off inlined..
10 *
11 * \author Jose Fonseca <jrfonseca@tungstengraphics.com>
12 * \author Leif Delgass <ldelgass@retinalburn.net>
13 */
14
15/*
16 * Copyright 2003 Jos�Fonseca.
17 * Copyright 2003 Leif Delgass.
18 * All Rights Reserved.
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining a
21 * copy of this software and associated documentation files (the "Software"),
22 * to deal in the Software without restriction, including without limitation
23 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
24 * and/or sell copies of the Software, and to permit persons to whom the
25 * Software is furnished to do so, subject to the following conditions:
26 *
27 * The above copyright notice and this permission notice (including the next
28 * paragraph) shall be included in all copies or substantial portions of the
29 * Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
35 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 */
38
39#include <linux/pci.h>
40#include "drmP.h"
41
42/**********************************************************************/
43/** \name PCI memory */
44/*@{*/
45
46/**
47 * \brief Allocate a PCI consistent memory block, for DMA.
48 */
49void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
50 dma_addr_t maxaddr, dma_addr_t * busaddr)
51{
52 void *address;
53#if DRM_DEBUG_MEMORY
54 int area = DRM_MEM_DMA;
55
56 spin_lock(&drm_mem_lock);
57 if ((drm_ram_used >> PAGE_SHIFT)
58 > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
59 spin_unlock(&drm_mem_lock);
60 return 0;
61 }
62 spin_unlock(&drm_mem_lock);
63#endif
64
65 /* pci_alloc_consistent only guarantees alignment to the smallest
66 * PAGE_SIZE order which is greater than or equal to the requested size.
67 * Return NULL here for now to make sure nobody tries for larger alignment
68 */
69 if (align > size)
70 return NULL;
71
72 if (pci_set_dma_mask(dev->pdev, maxaddr) != 0) {
73 DRM_ERROR("Setting pci dma mask failed\n");
74 return NULL;
75 }
76
77 address = pci_alloc_consistent(dev->pdev, size, busaddr);
78
79#if DRM_DEBUG_MEMORY
80 if (address == NULL) {
81 spin_lock(&drm_mem_lock);
82 ++drm_mem_stats[area].fail_count;
83 spin_unlock(&drm_mem_lock);
84 return NULL;
85 }
86
87 spin_lock(&drm_mem_lock);
88 ++drm_mem_stats[area].succeed_count;
89 drm_mem_stats[area].bytes_allocated += size;
90 drm_ram_used += size;
91 spin_unlock(&drm_mem_lock);
92#else
93 if (address == NULL)
94 return NULL;
95#endif
96
97 memset(address, 0, size);
98
99 return address;
100}
101EXPORT_SYMBOL(drm_pci_alloc);
102
103/**
104 * \brief Free a PCI consistent memory block.
105 */
106void
107drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
108{
109#if DRM_DEBUG_MEMORY
110 int area = DRM_MEM_DMA;
111 int alloc_count;
112 int free_count;
113#endif
114
115 if (!vaddr) {
116#if DRM_DEBUG_MEMORY
117 DRM_MEM_ERROR(area, "Attempt to free address 0\n");
118#endif
119 } else {
120 pci_free_consistent(dev->pdev, size, vaddr, busaddr);
121 }
122
123#if DRM_DEBUG_MEMORY
124 spin_lock(&drm_mem_lock);
125 free_count = ++drm_mem_stats[area].free_count;
126 alloc_count = drm_mem_stats[area].succeed_count;
127 drm_mem_stats[area].bytes_freed += size;
128 drm_ram_used -= size;
129 spin_unlock(&drm_mem_lock);
130 if (free_count > alloc_count) {
131 DRM_MEM_ERROR(area,
132 "Excess frees: %d frees, %d allocs\n",
133 free_count, alloc_count);
134 }
135#endif
136
137}
138EXPORT_SYMBOL(drm_pci_free);
139
140/*@}*/
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
new file mode 100644
index 000000000000..54a2914e3a32
--- /dev/null
+++ b/drivers/char/drm/drm_pciids.h
@@ -0,0 +1,224 @@
1/*
2 This file is auto-generated from the drm_pciids.txt in the DRM CVS
3 Please contact dri-devel@lists.sf.net to add new cards to this list
4*/
5#define radeon_PCI_IDS \
6 {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \
7 {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \
8 {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
9 {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
10 {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
11 {0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
12 {0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
13 {0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
14 {0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
15 {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
16 {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
17 {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
18 {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP}, \
19 {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
20 {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
21 {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
22 {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
23 {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
24 {0x1002, 0x4964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
25 {0x1002, 0x4965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
26 {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
27 {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
28 {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
29 {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
30 {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \
31 {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \
32 {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
33 {0x1002, 0x4C65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
34 {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
35 {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
36 {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
37 {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
38 {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
39 {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
40 {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
41 {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
42 {0x1002, 0x5149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
43 {0x1002, 0x514A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
44 {0x1002, 0x514B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
45 {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
46 {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
47 {0x1002, 0x514E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
48 {0x1002, 0x514F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
49 {0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
50 {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
51 {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
52 {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
53 {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
54 {0x1002, 0x5168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
55 {0x1002, 0x5169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
56 {0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
57 {0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
58 {0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
59 {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
60 {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
61 {0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
62 {0x1002, 0x5837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
63 {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
64 {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
65 {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
66 {0x1002, 0x5963, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
67 {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
68 {0x1002, 0x5968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
69 {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
70 {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
71 {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
72 {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
73 {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
74 {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
75 {0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
76 {0, 0, 0}
77
78#define r128_PCI_IDS \
79 {0x1002, 0x4c45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
80 {0x1002, 0x4c46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
81 {0x1002, 0x4d46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
82 {0x1002, 0x4d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
83 {0x1002, 0x5041, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
84 {0x1002, 0x5042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
85 {0x1002, 0x5043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
86 {0x1002, 0x5044, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
87 {0x1002, 0x5045, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
88 {0x1002, 0x5046, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
89 {0x1002, 0x5047, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
90 {0x1002, 0x5048, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
91 {0x1002, 0x5049, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
92 {0x1002, 0x504A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
93 {0x1002, 0x504B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
94 {0x1002, 0x504C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
95 {0x1002, 0x504D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
96 {0x1002, 0x504E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
97 {0x1002, 0x504F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
98 {0x1002, 0x5050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
99 {0x1002, 0x5051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
100 {0x1002, 0x5052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
101 {0x1002, 0x5053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
102 {0x1002, 0x5054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
103 {0x1002, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
104 {0x1002, 0x5056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
105 {0x1002, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
106 {0x1002, 0x5058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
107 {0x1002, 0x5245, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
108 {0x1002, 0x5246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
109 {0x1002, 0x5247, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
110 {0x1002, 0x524b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
111 {0x1002, 0x524c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
112 {0x1002, 0x534d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
113 {0x1002, 0x5446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
114 {0x1002, 0x544C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
115 {0x1002, 0x5452, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
116 {0, 0, 0}
117
118#define mga_PCI_IDS \
119 {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
120 {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
121 {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
122 {0, 0, 0}
123
124#define mach64_PCI_IDS \
125 {0x1002, 0x4749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
126 {0x1002, 0x4750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
127 {0x1002, 0x4751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
128 {0x1002, 0x4742, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
129 {0x1002, 0x4744, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
130 {0x1002, 0x4c49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
131 {0x1002, 0x4c50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
132 {0x1002, 0x4c51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
133 {0x1002, 0x4c42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
134 {0x1002, 0x4c44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
135 {0x1002, 0x474c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
136 {0x1002, 0x474f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
137 {0x1002, 0x4752, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
138 {0x1002, 0x4753, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
139 {0x1002, 0x474d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
140 {0x1002, 0x474e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
141 {0x1002, 0x4c52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
142 {0x1002, 0x4c53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
143 {0x1002, 0x4c4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
144 {0x1002, 0x4c4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
145 {0, 0, 0}
146
147#define sisdrv_PCI_IDS \
148 {0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
149 {0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
150 {0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
151 {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
152 {0, 0, 0}
153
154#define tdfx_PCI_IDS \
155 {0x121a, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
156 {0x121a, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
157 {0x121a, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
158 {0x121a, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
159 {0x121a, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
160 {0x121a, 0x000b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
161 {0, 0, 0}
162
163#define viadrv_PCI_IDS \
164 {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
165 {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
166 {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
167 {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
168 {0, 0, 0}
169
170#define i810_PCI_IDS \
171 {0x8086, 0x7121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
172 {0x8086, 0x7123, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
173 {0x8086, 0x7125, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
174 {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
175 {0, 0, 0}
176
177#define i830_PCI_IDS \
178 {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
179 {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
180 {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
181 {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
182 {0, 0, 0}
183
184#define gamma_PCI_IDS \
185 {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
186 {0, 0, 0}
187
188#define savage_PCI_IDS \
189 {0x5333, 0x8a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
190 {0x5333, 0x8a23, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
191 {0x5333, 0x8c10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
192 {0x5333, 0x8c11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
193 {0x5333, 0x8c12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
194 {0x5333, 0x8c13, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
195 {0x5333, 0x8c20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
196 {0x5333, 0x8c21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
197 {0x5333, 0x8c22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
198 {0x5333, 0x8c24, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
199 {0x5333, 0x8c26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
200 {0x5333, 0x8c2a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
201 {0x5333, 0x8c2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
202 {0x5333, 0x8c2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
203 {0x5333, 0x8c2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
204 {0x5333, 0x8c2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
205 {0x5333, 0x8c2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
206 {0x5333, 0x8a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
207 {0x5333, 0x8a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
208 {0x5333, 0x8d01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
209 {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
210 {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
211 {0, 0, 0}
212
213#define ffb_PCI_IDS \
214 {0, 0, 0}
215
216#define i915_PCI_IDS \
217 {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
218 {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
219 {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
220 {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
221 {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
222 {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
223 {0, 0, 0}
224
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
new file mode 100644
index 000000000000..6e06e8c6a516
--- /dev/null
+++ b/drivers/char/drm/drm_proc.c
@@ -0,0 +1,539 @@
1/**
2 * \file drm_proc.h
3 * /proc support for DRM
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 *
8 * \par Acknowledgements:
9 * Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix
10 * the problem with the proc files not outputting all their information.
11 */
12
13/*
14 * Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com
15 *
16 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
17 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
18 * All Rights Reserved.
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining a
21 * copy of this software and associated documentation files (the "Software"),
22 * to deal in the Software without restriction, including without limitation
23 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
24 * and/or sell copies of the Software, and to permit persons to whom the
25 * Software is furnished to do so, subject to the following conditions:
26 *
27 * The above copyright notice and this permission notice (including the next
28 * paragraph) shall be included in all copies or substantial portions of the
29 * Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
34 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
35 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
36 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
37 * OTHER DEALINGS IN THE SOFTWARE.
38 */
39
40#include "drmP.h"
41
42static int drm_name_info(char *buf, char **start, off_t offset,
43 int request, int *eof, void *data);
44static int drm_vm_info(char *buf, char **start, off_t offset,
45 int request, int *eof, void *data);
46static int drm_clients_info(char *buf, char **start, off_t offset,
47 int request, int *eof, void *data);
48static int drm_queues_info(char *buf, char **start, off_t offset,
49 int request, int *eof, void *data);
50static int drm_bufs_info(char *buf, char **start, off_t offset,
51 int request, int *eof, void *data);
52#if DRM_DEBUG_CODE
53static int drm_vma_info(char *buf, char **start, off_t offset,
54 int request, int *eof, void *data);
55#endif
56
57/**
58 * Proc file list.
59 */
60struct drm_proc_list {
61 const char *name; /**< file name */
62 int (*f)(char *, char **, off_t, int, int *, void *); /**< proc callback*/
63} drm_proc_list[] = {
64 { "name", drm_name_info },
65 { "mem", drm_mem_info },
66 { "vm", drm_vm_info },
67 { "clients", drm_clients_info },
68 { "queues", drm_queues_info },
69 { "bufs", drm_bufs_info },
70#if DRM_DEBUG_CODE
71 { "vma", drm_vma_info },
72#endif
73};
74#define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0]))
75
76/**
77 * Initialize the DRI proc filesystem for a device.
78 *
79 * \param dev DRM device.
80 * \param minor device minor number.
81 * \param root DRI proc dir entry.
82 * \param dev_root resulting DRI device proc dir entry.
83 * \return root entry pointer on success, or NULL on failure.
84 *
85 * Create the DRI proc root entry "/proc/dri", the device proc root entry
86 * "/proc/dri/%minor%/", and each entry in proc_list as
87 * "/proc/dri/%minor%/%name%".
88 */
89int drm_proc_init(drm_device_t *dev, int minor,
90 struct proc_dir_entry *root,
91 struct proc_dir_entry **dev_root)
92{
93 struct proc_dir_entry *ent;
94 int i, j;
95 char name[64];
96
97 sprintf(name, "%d", minor);
98 *dev_root = create_proc_entry(name, S_IFDIR, root);
99 if (!*dev_root) {
100 DRM_ERROR("Cannot create /proc/dri/%s\n", name);
101 return -1;
102 }
103
104 for (i = 0; i < DRM_PROC_ENTRIES; i++) {
105 ent = create_proc_entry(drm_proc_list[i].name,
106 S_IFREG|S_IRUGO, *dev_root);
107 if (!ent) {
108 DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
109 name, drm_proc_list[i].name);
110 for (j = 0; j < i; j++)
111 remove_proc_entry(drm_proc_list[i].name,
112 *dev_root);
113 remove_proc_entry(name, root);
114 return -1;
115 }
116 ent->read_proc = drm_proc_list[i].f;
117 ent->data = dev;
118 }
119
120 return 0;
121}
122
123
124/**
125 * Cleanup the proc filesystem resources.
126 *
127 * \param minor device minor number.
128 * \param root DRI proc dir entry.
129 * \param dev_root DRI device proc dir entry.
130 * \return always zero.
131 *
132 * Remove all proc entries created by proc_init().
133 */
134int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
135 struct proc_dir_entry *dev_root)
136{
137 int i;
138 char name[64];
139
140 if (!root || !dev_root) return 0;
141
142 for (i = 0; i < DRM_PROC_ENTRIES; i++)
143 remove_proc_entry(drm_proc_list[i].name, dev_root);
144 sprintf(name, "%d", minor);
145 remove_proc_entry(name, root);
146
147 return 0;
148}
149
150/**
151 * Called when "/proc/dri/.../name" is read.
152 *
153 * \param buf output buffer.
154 * \param start start of output data.
155 * \param offset requested start offset.
156 * \param request requested number of bytes.
157 * \param eof whether there is no more data to return.
158 * \param data private data.
159 * \return number of written bytes.
160 *
161 * Prints the device name together with the bus id if available.
162 */
163static int drm_name_info(char *buf, char **start, off_t offset, int request,
164 int *eof, void *data)
165{
166 drm_device_t *dev = (drm_device_t *)data;
167 int len = 0;
168
169 if (offset > DRM_PROC_LIMIT) {
170 *eof = 1;
171 return 0;
172 }
173
174 *start = &buf[offset];
175 *eof = 0;
176
177 if (dev->unique) {
178 DRM_PROC_PRINT("%s %s %s\n",
179 dev->driver->pci_driver.name, pci_name(dev->pdev), dev->unique);
180 } else {
181 DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, pci_name(dev->pdev));
182 }
183
184 if (len > request + offset) return request;
185 *eof = 1;
186 return len - offset;
187}
188
189/**
190 * Called when "/proc/dri/.../vm" is read.
191 *
192 * \param buf output buffer.
193 * \param start start of output data.
194 * \param offset requested start offset.
195 * \param request requested number of bytes.
196 * \param eof whether there is no more data to return.
197 * \param data private data.
198 * \return number of written bytes.
199 *
200 * Prints information about all mappings in drm_device::maplist.
201 */
202static int drm__vm_info(char *buf, char **start, off_t offset, int request,
203 int *eof, void *data)
204{
205 drm_device_t *dev = (drm_device_t *)data;
206 int len = 0;
207 drm_map_t *map;
208 drm_map_list_t *r_list;
209 struct list_head *list;
210
211 /* Hardcoded from _DRM_FRAME_BUFFER,
212 _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
213 _DRM_SCATTER_GATHER. */
214 const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
215 const char *type;
216 int i;
217
218 if (offset > DRM_PROC_LIMIT) {
219 *eof = 1;
220 return 0;
221 }
222
223 *start = &buf[offset];
224 *eof = 0;
225
226 DRM_PROC_PRINT("slot offset size type flags "
227 "address mtrr\n\n");
228 i = 0;
229 if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) {
230 r_list = list_entry(list, drm_map_list_t, head);
231 map = r_list->map;
232 if(!map) continue;
233 if (map->type < 0 || map->type > 4) type = "??";
234 else type = types[map->type];
235 DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
236 i,
237 map->offset,
238 map->size,
239 type,
240 map->flags,
241 (unsigned long)map->handle);
242 if (map->mtrr < 0) {
243 DRM_PROC_PRINT("none\n");
244 } else {
245 DRM_PROC_PRINT("%4d\n", map->mtrr);
246 }
247 i++;
248 }
249
250 if (len > request + offset) return request;
251 *eof = 1;
252 return len - offset;
253}
254
255/**
256 * Simply calls _vm_info() while holding the drm_device::struct_sem lock.
257 */
258static int drm_vm_info(char *buf, char **start, off_t offset, int request,
259 int *eof, void *data)
260{
261 drm_device_t *dev = (drm_device_t *)data;
262 int ret;
263
264 down(&dev->struct_sem);
265 ret = drm__vm_info(buf, start, offset, request, eof, data);
266 up(&dev->struct_sem);
267 return ret;
268}
269
270/**
271 * Called when "/proc/dri/.../queues" is read.
272 *
273 * \param buf output buffer.
274 * \param start start of output data.
275 * \param offset requested start offset.
276 * \param request requested number of bytes.
277 * \param eof whether there is no more data to return.
278 * \param data private data.
279 * \return number of written bytes.
280 */
281static int drm__queues_info(char *buf, char **start, off_t offset,
282 int request, int *eof, void *data)
283{
284 drm_device_t *dev = (drm_device_t *)data;
285 int len = 0;
286 int i;
287 drm_queue_t *q;
288
289 if (offset > DRM_PROC_LIMIT) {
290 *eof = 1;
291 return 0;
292 }
293
294 *start = &buf[offset];
295 *eof = 0;
296
297 DRM_PROC_PRINT(" ctx/flags use fin"
298 " blk/rw/rwf wait flushed queued"
299 " locks\n\n");
300 for (i = 0; i < dev->queue_count; i++) {
301 q = dev->queuelist[i];
302 atomic_inc(&q->use_count);
303 DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
304 "%5d/0x%03x %5d %5d"
305 " %5d/%c%c/%c%c%c %5Zd\n",
306 i,
307 q->flags,
308 atomic_read(&q->use_count),
309 atomic_read(&q->finalization),
310 atomic_read(&q->block_count),
311 atomic_read(&q->block_read) ? 'r' : '-',
312 atomic_read(&q->block_write) ? 'w' : '-',
313 waitqueue_active(&q->read_queue) ? 'r':'-',
314 waitqueue_active(&q->write_queue) ? 'w':'-',
315 waitqueue_active(&q->flush_queue) ? 'f':'-',
316 DRM_BUFCOUNT(&q->waitlist));
317 atomic_dec(&q->use_count);
318 }
319
320 if (len > request + offset) return request;
321 *eof = 1;
322 return len - offset;
323}
324
325/**
326 * Simply calls _queues_info() while holding the drm_device::struct_sem lock.
327 */
328static int drm_queues_info(char *buf, char **start, off_t offset, int request,
329 int *eof, void *data)
330{
331 drm_device_t *dev = (drm_device_t *)data;
332 int ret;
333
334 down(&dev->struct_sem);
335 ret = drm__queues_info(buf, start, offset, request, eof, data);
336 up(&dev->struct_sem);
337 return ret;
338}
339
340/**
341 * Called when "/proc/dri/.../bufs" is read.
342 *
343 * \param buf output buffer.
344 * \param start start of output data.
345 * \param offset requested start offset.
346 * \param request requested number of bytes.
347 * \param eof whether there is no more data to return.
348 * \param data private data.
349 * \return number of written bytes.
350 */
351static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
352 int *eof, void *data)
353{
354 drm_device_t *dev = (drm_device_t *)data;
355 int len = 0;
356 drm_device_dma_t *dma = dev->dma;
357 int i;
358
359 if (!dma || offset > DRM_PROC_LIMIT) {
360 *eof = 1;
361 return 0;
362 }
363
364 *start = &buf[offset];
365 *eof = 0;
366
367 DRM_PROC_PRINT(" o size count free segs pages kB\n\n");
368 for (i = 0; i <= DRM_MAX_ORDER; i++) {
369 if (dma->bufs[i].buf_count)
370 DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
371 i,
372 dma->bufs[i].buf_size,
373 dma->bufs[i].buf_count,
374 atomic_read(&dma->bufs[i]
375 .freelist.count),
376 dma->bufs[i].seg_count,
377 dma->bufs[i].seg_count
378 *(1 << dma->bufs[i].page_order),
379 (dma->bufs[i].seg_count
380 * (1 << dma->bufs[i].page_order))
381 * PAGE_SIZE / 1024);
382 }
383 DRM_PROC_PRINT("\n");
384 for (i = 0; i < dma->buf_count; i++) {
385 if (i && !(i%32)) DRM_PROC_PRINT("\n");
386 DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
387 }
388 DRM_PROC_PRINT("\n");
389
390 if (len > request + offset) return request;
391 *eof = 1;
392 return len - offset;
393}
394
395/**
396 * Simply calls _bufs_info() while holding the drm_device::struct_sem lock.
397 */
398static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
399 int *eof, void *data)
400{
401 drm_device_t *dev = (drm_device_t *)data;
402 int ret;
403
404 down(&dev->struct_sem);
405 ret = drm__bufs_info(buf, start, offset, request, eof, data);
406 up(&dev->struct_sem);
407 return ret;
408}
409
410/**
411 * Called when "/proc/dri/.../clients" is read.
412 *
413 * \param buf output buffer.
414 * \param start start of output data.
415 * \param offset requested start offset.
416 * \param request requested number of bytes.
417 * \param eof whether there is no more data to return.
418 * \param data private data.
419 * \return number of written bytes.
420 */
421static int drm__clients_info(char *buf, char **start, off_t offset,
422 int request, int *eof, void *data)
423{
424 drm_device_t *dev = (drm_device_t *)data;
425 int len = 0;
426 drm_file_t *priv;
427
428 if (offset > DRM_PROC_LIMIT) {
429 *eof = 1;
430 return 0;
431 }
432
433 *start = &buf[offset];
434 *eof = 0;
435
436 DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
437 for (priv = dev->file_first; priv; priv = priv->next) {
438 DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
439 priv->authenticated ? 'y' : 'n',
440 priv->minor,
441 priv->pid,
442 priv->uid,
443 priv->magic,
444 priv->ioctl_count);
445 }
446
447 if (len > request + offset) return request;
448 *eof = 1;
449 return len - offset;
450}
451
452/**
453 * Simply calls _clients_info() while holding the drm_device::struct_sem lock.
454 */
455static int drm_clients_info(char *buf, char **start, off_t offset,
456 int request, int *eof, void *data)
457{
458 drm_device_t *dev = (drm_device_t *)data;
459 int ret;
460
461 down(&dev->struct_sem);
462 ret = drm__clients_info(buf, start, offset, request, eof, data);
463 up(&dev->struct_sem);
464 return ret;
465}
466
467#if DRM_DEBUG_CODE
468
469static int drm__vma_info(char *buf, char **start, off_t offset, int request,
470 int *eof, void *data)
471{
472 drm_device_t *dev = (drm_device_t *)data;
473 int len = 0;
474 drm_vma_entry_t *pt;
475 struct vm_area_struct *vma;
476#if defined(__i386__)
477 unsigned int pgprot;
478#endif
479
480 if (offset > DRM_PROC_LIMIT) {
481 *eof = 1;
482 return 0;
483 }
484
485 *start = &buf[offset];
486 *eof = 0;
487
488 DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
489 atomic_read(&dev->vma_count),
490 high_memory, virt_to_phys(high_memory));
491 for (pt = dev->vmalist; pt; pt = pt->next) {
492 if (!(vma = pt->vma)) continue;
493 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
494 pt->pid,
495 vma->vm_start,
496 vma->vm_end,
497 vma->vm_flags & VM_READ ? 'r' : '-',
498 vma->vm_flags & VM_WRITE ? 'w' : '-',
499 vma->vm_flags & VM_EXEC ? 'x' : '-',
500 vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
501 vma->vm_flags & VM_LOCKED ? 'l' : '-',
502 vma->vm_flags & VM_IO ? 'i' : '-',
503 VM_OFFSET(vma));
504
505#if defined(__i386__)
506 pgprot = pgprot_val(vma->vm_page_prot);
507 DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
508 pgprot & _PAGE_PRESENT ? 'p' : '-',
509 pgprot & _PAGE_RW ? 'w' : 'r',
510 pgprot & _PAGE_USER ? 'u' : 's',
511 pgprot & _PAGE_PWT ? 't' : 'b',
512 pgprot & _PAGE_PCD ? 'u' : 'c',
513 pgprot & _PAGE_ACCESSED ? 'a' : '-',
514 pgprot & _PAGE_DIRTY ? 'd' : '-',
515 pgprot & _PAGE_PSE ? 'm' : 'k',
516 pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
517#endif
518 DRM_PROC_PRINT("\n");
519 }
520
521 if (len > request + offset) return request;
522 *eof = 1;
523 return len - offset;
524}
525
526static int drm_vma_info(char *buf, char **start, off_t offset, int request,
527 int *eof, void *data)
528{
529 drm_device_t *dev = (drm_device_t *)data;
530 int ret;
531
532 down(&dev->struct_sem);
533 ret = drm__vma_info(buf, start, offset, request, eof, data);
534 up(&dev->struct_sem);
535 return ret;
536}
537#endif
538
539
diff --git a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
new file mode 100644
index 000000000000..de782ed2f03a
--- /dev/null
+++ b/drivers/char/drm/drm_sarea.h
@@ -0,0 +1,78 @@
1/**
2 * \file drm_sarea.h
3 * \brief SAREA definitions
4 *
5 * \author Michel Dänzer <michel@daenzer.net>
6 */
7
8/*
9 * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
10 * All Rights Reserved.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice (including the next
20 * paragraph) shall be included in all copies or substantial portions of the
21 * Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
27 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29 * OTHER DEALINGS IN THE SOFTWARE.
30 */
31
32#ifndef _DRM_SAREA_H_
33#define _DRM_SAREA_H_
34
35#include "drm.h"
36
37/* SAREA area needs to be at least a page */
38#if defined(__alpha__)
39#define SAREA_MAX 0x2000
40#elif defined(__ia64__)
41#define SAREA_MAX 0x10000 /* 64kB */
42#else
43/* Intel 830M driver needs at least 8k SAREA */
44#define SAREA_MAX 0x2000
45#endif
46
47/** Maximum number of drawables in the SAREA */
48#define SAREA_MAX_DRAWABLES 256
49
50#define SAREA_DRAWABLE_CLAIMED_ENTRY 0x80000000
51
52/** SAREA drawable */
53typedef struct drm_sarea_drawable {
54 unsigned int stamp;
55 unsigned int flags;
56} drm_sarea_drawable_t;
57
58/** SAREA frame */
59typedef struct drm_sarea_frame {
60 unsigned int x;
61 unsigned int y;
62 unsigned int width;
63 unsigned int height;
64 unsigned int fullscreen;
65} drm_sarea_frame_t;
66
67/** SAREA */
68typedef struct drm_sarea {
69 /** first thing is always the DRM locking structure */
70 drm_hw_lock_t lock;
71 /** \todo Use readers/writer lock for drm_sarea::drawable_lock */
72 drm_hw_lock_t drawable_lock;
73 drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
74 drm_sarea_frame_t frame; /**< frame */
75 drm_context_t dummy_context;
76} drm_sarea_t;
77
78#endif /* _DRM_SAREA_H_ */
diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c
new file mode 100644
index 000000000000..54fddb6ea2d1
--- /dev/null
+++ b/drivers/char/drm/drm_scatter.c
@@ -0,0 +1,231 @@
1/**
2 * \file drm_scatter.h
3 * IOCTLs to manage scatter/gather memory
4 *
5 * \author Gareth Hughes <gareth@valinux.com>
6 */
7
8/*
9 * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
10 *
11 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
12 * All Rights Reserved.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31 * DEALINGS IN THE SOFTWARE.
32 */
33
34#include <linux/config.h>
35#include <linux/vmalloc.h>
36#include "drmP.h"
37
38#define DEBUG_SCATTER 0
39
40void drm_sg_cleanup( drm_sg_mem_t *entry )
41{
42 struct page *page;
43 int i;
44
45 for ( i = 0 ; i < entry->pages ; i++ ) {
46 page = entry->pagelist[i];
47 if ( page )
48 ClearPageReserved( page );
49 }
50
51 vfree( entry->virtual );
52
53 drm_free( entry->busaddr,
54 entry->pages * sizeof(*entry->busaddr),
55 DRM_MEM_PAGES );
56 drm_free( entry->pagelist,
57 entry->pages * sizeof(*entry->pagelist),
58 DRM_MEM_PAGES );
59 drm_free( entry,
60 sizeof(*entry),
61 DRM_MEM_SGLISTS );
62}
63
64int drm_sg_alloc( struct inode *inode, struct file *filp,
65 unsigned int cmd, unsigned long arg )
66{
67 drm_file_t *priv = filp->private_data;
68 drm_device_t *dev = priv->head->dev;
69 drm_scatter_gather_t __user *argp = (void __user *)arg;
70 drm_scatter_gather_t request;
71 drm_sg_mem_t *entry;
72 unsigned long pages, i, j;
73
74 DRM_DEBUG( "%s\n", __FUNCTION__ );
75
76 if (!drm_core_check_feature(dev, DRIVER_SG))
77 return -EINVAL;
78
79 if ( dev->sg )
80 return -EINVAL;
81
82 if ( copy_from_user( &request, argp, sizeof(request) ) )
83 return -EFAULT;
84
85 entry = drm_alloc( sizeof(*entry), DRM_MEM_SGLISTS );
86 if ( !entry )
87 return -ENOMEM;
88
89 memset( entry, 0, sizeof(*entry) );
90
91 pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
92 DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
93
94 entry->pages = pages;
95 entry->pagelist = drm_alloc( pages * sizeof(*entry->pagelist),
96 DRM_MEM_PAGES );
97 if ( !entry->pagelist ) {
98 drm_free( entry, sizeof(*entry), DRM_MEM_SGLISTS );
99 return -ENOMEM;
100 }
101
102 memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
103
104 entry->busaddr = drm_alloc( pages * sizeof(*entry->busaddr),
105 DRM_MEM_PAGES );
106 if ( !entry->busaddr ) {
107 drm_free( entry->pagelist,
108 entry->pages * sizeof(*entry->pagelist),
109 DRM_MEM_PAGES );
110 drm_free( entry,
111 sizeof(*entry),
112 DRM_MEM_SGLISTS );
113 return -ENOMEM;
114 }
115 memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) );
116
117 entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
118 if ( !entry->virtual ) {
119 drm_free( entry->busaddr,
120 entry->pages * sizeof(*entry->busaddr),
121 DRM_MEM_PAGES );
122 drm_free( entry->pagelist,
123 entry->pages * sizeof(*entry->pagelist),
124 DRM_MEM_PAGES );
125 drm_free( entry,
126 sizeof(*entry),
127 DRM_MEM_SGLISTS );
128 return -ENOMEM;
129 }
130
131 /* This also forces the mapping of COW pages, so our page list
132 * will be valid. Please don't remove it...
133 */
134 memset( entry->virtual, 0, pages << PAGE_SHIFT );
135
136 entry->handle = (unsigned long)entry->virtual;
137
138 DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
139 DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
140
141 for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
142 entry->pagelist[j] = vmalloc_to_page((void *)i);
143 if (!entry->pagelist[j])
144 goto failed;
145 SetPageReserved(entry->pagelist[j]);
146 }
147
148 request.handle = entry->handle;
149
150 if ( copy_to_user( argp, &request, sizeof(request) ) ) {
151 drm_sg_cleanup( entry );
152 return -EFAULT;
153 }
154
155 dev->sg = entry;
156
157#if DEBUG_SCATTER
158 /* Verify that each page points to its virtual address, and vice
159 * versa.
160 */
161 {
162 int error = 0;
163
164 for ( i = 0 ; i < pages ; i++ ) {
165 unsigned long *tmp;
166
167 tmp = page_address( entry->pagelist[i] );
168 for ( j = 0 ;
169 j < PAGE_SIZE / sizeof(unsigned long) ;
170 j++, tmp++ ) {
171 *tmp = 0xcafebabe;
172 }
173 tmp = (unsigned long *)((u8 *)entry->virtual +
174 (PAGE_SIZE * i));
175 for( j = 0 ;
176 j < PAGE_SIZE / sizeof(unsigned long) ;
177 j++, tmp++ ) {
178 if ( *tmp != 0xcafebabe && error == 0 ) {
179 error = 1;
180 DRM_ERROR( "Scatter allocation error, "
181 "pagelist does not match "
182 "virtual mapping\n" );
183 }
184 }
185 tmp = page_address( entry->pagelist[i] );
186 for(j = 0 ;
187 j < PAGE_SIZE / sizeof(unsigned long) ;
188 j++, tmp++) {
189 *tmp = 0;
190 }
191 }
192 if (error == 0)
193 DRM_ERROR( "Scatter allocation matches pagelist\n" );
194 }
195#endif
196
197 return 0;
198
199 failed:
200 drm_sg_cleanup( entry );
201 return -ENOMEM;
202}
203
204int drm_sg_free( struct inode *inode, struct file *filp,
205 unsigned int cmd, unsigned long arg )
206{
207 drm_file_t *priv = filp->private_data;
208 drm_device_t *dev = priv->head->dev;
209 drm_scatter_gather_t request;
210 drm_sg_mem_t *entry;
211
212 if (!drm_core_check_feature(dev, DRIVER_SG))
213 return -EINVAL;
214
215 if ( copy_from_user( &request,
216 (drm_scatter_gather_t __user *)arg,
217 sizeof(request) ) )
218 return -EFAULT;
219
220 entry = dev->sg;
221 dev->sg = NULL;
222
223 if ( !entry || entry->handle != request.handle )
224 return -EINVAL;
225
226 DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );
227
228 drm_sg_cleanup( entry );
229
230 return 0;
231}
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
new file mode 100644
index 000000000000..8ccbdef7bb3e
--- /dev/null
+++ b/drivers/char/drm/drm_stub.c
@@ -0,0 +1,319 @@
1/**
2 * \file drm_stub.h
3 * Stub support
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 */
7
8/*
9 * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
10 *
11 * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
12 * All Rights Reserved.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31 * DEALINGS IN THE SOFTWARE.
32 */
33
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include "drmP.h"
37#include "drm_core.h"
38
39unsigned int drm_cards_limit = 16; /* Enough for one machine */
40unsigned int drm_debug = 0; /* 1 to enable debug output */
41EXPORT_SYMBOL(drm_debug);
42
43MODULE_AUTHOR( CORE_AUTHOR );
44MODULE_DESCRIPTION( CORE_DESC );
45MODULE_LICENSE("GPL and additional rights");
46MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards");
47MODULE_PARM_DESC(debug, "Enable debug output");
48
49module_param_named(cards_limit, drm_cards_limit, int, 0444);
50module_param_named(debug, drm_debug, int, 0666);
51
52drm_head_t **drm_heads;
53struct drm_sysfs_class *drm_class;
54struct proc_dir_entry *drm_proc_root;
55
56static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver)
57{
58 int retcode;
59
60 spin_lock_init(&dev->count_lock);
61 init_timer( &dev->timer );
62 sema_init( &dev->struct_sem, 1 );
63 sema_init( &dev->ctxlist_sem, 1 );
64
65 dev->pdev = pdev;
66
67#ifdef __alpha__
68 dev->hose = pdev->sysdata;
69 dev->pci_domain = dev->hose->bus->number;
70#else
71 dev->pci_domain = 0;
72#endif
73 dev->pci_bus = pdev->bus->number;
74 dev->pci_slot = PCI_SLOT(pdev->devfn);
75 dev->pci_func = PCI_FUNC(pdev->devfn);
76 dev->irq = pdev->irq;
77
78 /* the DRM has 6 basic counters */
79 dev->counters = 6;
80 dev->types[0] = _DRM_STAT_LOCK;
81 dev->types[1] = _DRM_STAT_OPENS;
82 dev->types[2] = _DRM_STAT_CLOSES;
83 dev->types[3] = _DRM_STAT_IOCTLS;
84 dev->types[4] = _DRM_STAT_LOCKS;
85 dev->types[5] = _DRM_STAT_UNLOCKS;
86
87 dev->driver = driver;
88
89 if (dev->driver->preinit)
90 if ((retcode = dev->driver->preinit(dev, ent->driver_data)))
91 goto error_out_unreg;
92
93 if (drm_core_has_AGP(dev)) {
94 dev->agp = drm_agp_init(dev);
95 if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
96 DRM_ERROR( "Cannot initialize the agpgart module.\n" );
97 retcode = -EINVAL;
98 goto error_out_unreg;
99 }
100 if (drm_core_has_MTRR(dev)) {
101 if (dev->agp)
102 dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
103 dev->agp->agp_info.aper_size*1024*1024,
104 MTRR_TYPE_WRCOMB,
105 1 );
106 }
107 }
108
109 retcode = drm_ctxbitmap_init( dev );
110 if( retcode ) {
111 DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
112 goto error_out_unreg;
113 }
114
115 return 0;
116
117error_out_unreg:
118 drm_takedown(dev);
119 return retcode;
120}
121
122/**
123 * File \c open operation.
124 *
125 * \param inode device inode.
126 * \param filp file pointer.
127 *
128 * Puts the dev->fops corresponding to the device minor number into
129 * \p filp, call the \c open method, and restore the file operations.
130 */
131int drm_stub_open(struct inode *inode, struct file *filp)
132{
133 drm_device_t *dev = NULL;
134 int minor = iminor(inode);
135 int err = -ENODEV;
136 struct file_operations *old_fops;
137
138 DRM_DEBUG("\n");
139
140 if (!((minor >= 0) && (minor < drm_cards_limit)))
141 return -ENODEV;
142
143 if (!drm_heads[minor])
144 return -ENODEV;
145
146 if (!(dev = drm_heads[minor]->dev))
147 return -ENODEV;
148
149 old_fops = filp->f_op;
150 filp->f_op = fops_get(&dev->driver->fops);
151 if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
152 fops_put(filp->f_op);
153 filp->f_op = fops_get(old_fops);
154 }
155 fops_put(old_fops);
156
157 return err;
158}
159
160
161/**
162 * Register.
163 *
164 * \param pdev - PCI device structure
165 * \param ent entry from the PCI ID table with device type flags
166 * \return zero on success or a negative number on failure.
167 *
168 * Attempt to gets inter module "drm" information. If we are first
169 * then register the character device and inter module information.
170 * Try and register, if we fail to register, backout previous work.
171 */
172int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
173 struct drm_driver *driver)
174{
175 drm_device_t *dev;
176 int ret;
177
178 DRM_DEBUG("\n");
179
180 dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
181 if (!dev)
182 return -ENOMEM;
183
184 pci_enable_device(pdev);
185
186 if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
187 printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
188 goto err_g1;
189 }
190 if ((ret = drm_get_head(dev, &dev->primary)))
191 goto err_g1;
192
193 /* postinit is a required function to display the signon banner */
194 /* drivers add secondary heads here if needed */
195 if ((ret = dev->driver->postinit(dev, ent->driver_data)))
196 goto err_g1;
197
198 return 0;
199
200err_g1:
201 drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
202 return ret;
203}
204EXPORT_SYMBOL(drm_get_dev);
205
206/**
207 * Get a secondary minor number.
208 *
209 * \param dev device data structure
210 * \param sec-minor structure to hold the assigned minor
211 * \return negative number on failure.
212 *
213 * Search an empty entry and initialize it to the given parameters, and
214 * create the proc init entry via proc_init(). This routines assigns
215 * minor numbers to secondary heads of multi-headed cards
216 */
217int drm_get_head(drm_device_t *dev, drm_head_t *head)
218{
219 drm_head_t **heads = drm_heads;
220 int ret;
221 int minor;
222
223 DRM_DEBUG("\n");
224
225 for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
226 if (!*heads) {
227
228 *head = (drm_head_t) {
229 .dev = dev,
230 .device = MKDEV(DRM_MAJOR, minor),
231 .minor = minor,
232 };
233
234 if ((ret = drm_proc_init(dev, minor, drm_proc_root, &head->dev_root))) {
235 printk (KERN_ERR "DRM: Failed to initialize /proc/dri.\n");
236 goto err_g1;
237 }
238
239
240 head->dev_class = drm_sysfs_device_add(drm_class,
241 MKDEV(DRM_MAJOR,
242 minor),
243 &dev->pdev->dev,
244 "card%d", minor);
245 if (IS_ERR(head->dev_class)) {
246 printk(KERN_ERR "DRM: Error sysfs_device_add.\n");
247 ret = PTR_ERR(head->dev_class);
248 goto err_g2;
249 }
250 *heads = head;
251
252 DRM_DEBUG("new minor assigned %d\n", minor);
253 return 0;
254 }
255 }
256 DRM_ERROR("out of minors\n");
257 return -ENOMEM;
258err_g2:
259 drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
260err_g1:
261 *head = (drm_head_t) {.dev = NULL};
262 return ret;
263}
264
265
266/**
267 * Put a device minor number.
268 *
269 * \param dev device data structure
270 * \return always zero
271 *
272 * Cleans up the proc resources. If it is the last minor then release the foreign
273 * "drm" data, otherwise unregisters the "drm" data, frees the dev list and
274 * unregisters the character device.
275 */
276int drm_put_dev(drm_device_t * dev)
277{
278 DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
279
280 if (dev->unique) {
281 drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
282 dev->unique = NULL;
283 dev->unique_len = 0;
284 }
285 if (dev->devname) {
286 drm_free(dev->devname, strlen(dev->devname) + 1,
287 DRM_MEM_DRIVER);
288 dev->devname = NULL;
289 }
290 drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
291 return 0;
292}
293
294/**
295 * Put a secondary minor number.
296 *
297 * \param sec_minor - structure to be released
298 * \return always zero
299 *
300 * Cleans up the proc resources. Not legal for this to be the
301 * last minor released.
302 *
303 */
304int drm_put_head(drm_head_t *head)
305{
306 int minor = head->minor;
307
308 DRM_DEBUG("release secondary minor %d\n", minor);
309
310 drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
311 drm_sysfs_device_remove(MKDEV(DRM_MAJOR, head->minor));
312
313 *head = (drm_head_t){.dev = NULL};
314
315 drm_heads[minor] = NULL;
316
317 return 0;
318}
319
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
new file mode 100644
index 000000000000..2fc10c4bbcdf
--- /dev/null
+++ b/drivers/char/drm/drm_sysfs.c
@@ -0,0 +1,208 @@
1/*
2 * drm_sysfs.c - Modifications to drm_sysfs_class.c to support
3 * extra sysfs attribute from DRM. Normal drm_sysfs_class
4 * does not allow adding attributes.
5 *
6 * Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com>
7 * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
8 * Copyright (c) 2003-2004 IBM Corp.
9 *
10 * This file is released under the GPLv2
11 *
12 */
13
14#include <linux/config.h>
15#include <linux/device.h>
16#include <linux/kdev_t.h>
17#include <linux/err.h>
18
19#include "drm_core.h"
20
21struct drm_sysfs_class {
22 struct class_device_attribute attr;
23 struct class class;
24};
25#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)
26
27struct simple_dev {
28 struct list_head node;
29 dev_t dev;
30 struct class_device class_dev;
31};
32#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
33
34static LIST_HEAD(simple_dev_list);
35static DEFINE_SPINLOCK(simple_dev_list_lock);
36
37static void release_simple_dev(struct class_device *class_dev)
38{
39 struct simple_dev *s_dev = to_simple_dev(class_dev);
40 kfree(s_dev);
41}
42
43static ssize_t show_dev(struct class_device *class_dev, char *buf)
44{
45 struct simple_dev *s_dev = to_simple_dev(class_dev);
46 return print_dev_t(buf, s_dev->dev);
47}
48
49static void drm_sysfs_class_release(struct class *class)
50{
51 struct drm_sysfs_class *cs = to_drm_sysfs_class(class);
52 kfree(cs);
53}
54
55/* Display the version of drm_core. This doesn't work right in current design */
56static ssize_t version_show(struct class *dev, char *buf)
57{
58 return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR,
59 CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
60}
61
62static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
63
64/**
65 * drm_sysfs_create - create a struct drm_sysfs_class structure
66 * @owner: pointer to the module that is to "own" this struct drm_sysfs_class
67 * @name: pointer to a string for the name of this class.
68 *
69 * This is used to create a struct drm_sysfs_class pointer that can then be used
70 * in calls to drm_sysfs_device_add().
71 *
72 * Note, the pointer created here is to be destroyed when finished by making a
73 * call to drm_sysfs_destroy().
74 */
75struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
76{
77 struct drm_sysfs_class *cs;
78 int retval;
79
80 cs = kmalloc(sizeof(*cs), GFP_KERNEL);
81 if (!cs) {
82 retval = -ENOMEM;
83 goto error;
84 }
85 memset(cs, 0x00, sizeof(*cs));
86
87 cs->class.name = name;
88 cs->class.class_release = drm_sysfs_class_release;
89 cs->class.release = release_simple_dev;
90
91 cs->attr.attr.name = "dev";
92 cs->attr.attr.mode = S_IRUGO;
93 cs->attr.attr.owner = owner;
94 cs->attr.show = show_dev;
95 cs->attr.store = NULL;
96
97 retval = class_register(&cs->class);
98 if (retval)
99 goto error;
100 class_create_file(&cs->class, &class_attr_version);
101
102 return cs;
103
104 error:
105 kfree(cs);
106 return ERR_PTR(retval);
107}
108
109/**
110 * drm_sysfs_destroy - destroys a struct drm_sysfs_class structure
111 * @cs: pointer to the struct drm_sysfs_class that is to be destroyed
112 *
113 * Note, the pointer to be destroyed must have been created with a call to
114 * drm_sysfs_create().
115 */
116void drm_sysfs_destroy(struct drm_sysfs_class *cs)
117{
118 if ((cs == NULL) || (IS_ERR(cs)))
119 return;
120
121 class_unregister(&cs->class);
122}
123
124/**
125 * drm_sysfs_device_add - adds a class device to sysfs for a character driver
126 * @cs: pointer to the struct drm_sysfs_class that this device should be registered to.
127 * @dev: the dev_t for the device to be added.
128 * @device: a pointer to a struct device that is assiociated with this class device.
129 * @fmt: string for the class device's name
130 *
131 * A struct class_device will be created in sysfs, registered to the specified
132 * class. A "dev" file will be created, showing the dev_t for the device. The
133 * pointer to the struct class_device will be returned from the call. Any further
134 * sysfs files that might be required can be created using this pointer.
135 * Note: the struct drm_sysfs_class passed to this function must have previously been
136 * created with a call to drm_sysfs_create().
137 */
138struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev,
139 struct device *device,
140 const char *fmt, ...)
141{
142 va_list args;
143 struct simple_dev *s_dev = NULL;
144 int retval;
145
146 if ((cs == NULL) || (IS_ERR(cs))) {
147 retval = -ENODEV;
148 goto error;
149 }
150
151 s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
152 if (!s_dev) {
153 retval = -ENOMEM;
154 goto error;
155 }
156 memset(s_dev, 0x00, sizeof(*s_dev));
157
158 s_dev->dev = dev;
159 s_dev->class_dev.dev = device;
160 s_dev->class_dev.class = &cs->class;
161
162 va_start(args, fmt);
163 vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
164 va_end(args);
165 retval = class_device_register(&s_dev->class_dev);
166 if (retval)
167 goto error;
168
169 class_device_create_file(&s_dev->class_dev, &cs->attr);
170
171 spin_lock(&simple_dev_list_lock);
172 list_add(&s_dev->node, &simple_dev_list);
173 spin_unlock(&simple_dev_list_lock);
174
175 return &s_dev->class_dev;
176
177 error:
178 kfree(s_dev);
179 return ERR_PTR(retval);
180}
181
182/**
183 * drm_sysfs_device_remove - removes a class device that was created with drm_sysfs_device_add()
184 * @dev: the dev_t of the device that was previously registered.
185 *
186 * This call unregisters and cleans up a class device that was created with a
187 * call to drm_sysfs_device_add()
188 */
189void drm_sysfs_device_remove(dev_t dev)
190{
191 struct simple_dev *s_dev = NULL;
192 int found = 0;
193
194 spin_lock(&simple_dev_list_lock);
195 list_for_each_entry(s_dev, &simple_dev_list, node) {
196 if (s_dev->dev == dev) {
197 found = 1;
198 break;
199 }
200 }
201 if (found) {
202 list_del(&s_dev->node);
203 spin_unlock(&simple_dev_list_lock);
204 class_device_unregister(&s_dev->class_dev);
205 } else {
206 spin_unlock(&simple_dev_list_lock);
207 }
208}
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
new file mode 100644
index 000000000000..fc72f30f312b
--- /dev/null
+++ b/drivers/char/drm/drm_vm.c
@@ -0,0 +1,678 @@
1/**
2 * \file drm_vm.h
3 * Memory mapping for DRM
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
7 */
8
9/*
10 * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
11 *
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include "drmP.h"
37#if defined(__ia64__)
38#include <linux/efi.h>
39#endif
40
41
42/**
43 * \c nopage method for AGP virtual memory.
44 *
45 * \param vma virtual memory area.
46 * \param address access address.
47 * \return pointer to the page structure.
48 *
49 * Find the right map and if it's AGP memory find the real physical page to
50 * map, get the page, increment the use count and return it.
51 */
52#if __OS_HAS_AGP
53static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
54 unsigned long address)
55{
56 drm_file_t *priv = vma->vm_file->private_data;
57 drm_device_t *dev = priv->head->dev;
58 drm_map_t *map = NULL;
59 drm_map_list_t *r_list;
60 struct list_head *list;
61
62 /*
63 * Find the right map
64 */
65 if (!drm_core_has_AGP(dev))
66 goto vm_nopage_error;
67
68 if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error;
69
70 list_for_each(list, &dev->maplist->head) {
71 r_list = list_entry(list, drm_map_list_t, head);
72 map = r_list->map;
73 if (!map) continue;
74 if (map->offset == VM_OFFSET(vma)) break;
75 }
76
77 if (map && map->type == _DRM_AGP) {
78 unsigned long offset = address - vma->vm_start;
79 unsigned long baddr = VM_OFFSET(vma) + offset;
80 struct drm_agp_mem *agpmem;
81 struct page *page;
82
83#ifdef __alpha__
84 /*
85 * Adjust to a bus-relative address
86 */
87 baddr -= dev->hose->mem_space->start;
88#endif
89
90 /*
91 * It's AGP memory - find the real physical page to map
92 */
93 for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
94 if (agpmem->bound <= baddr &&
95 agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
96 break;
97 }
98
99 if (!agpmem) goto vm_nopage_error;
100
101 /*
102 * Get the page, inc the use count, and return it
103 */
104 offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
105 page = virt_to_page(__va(agpmem->memory->memory[offset]));
106 get_page(page);
107
108 DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
109 baddr, __va(agpmem->memory->memory[offset]), offset,
110 page_count(page));
111
112 return page;
113 }
114vm_nopage_error:
115 return NOPAGE_SIGBUS; /* Disallow mremap */
116}
117#else /* __OS_HAS_AGP */
118static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
119 unsigned long address)
120{
121 return NOPAGE_SIGBUS;
122}
123#endif /* __OS_HAS_AGP */
124
125/**
126 * \c nopage method for shared virtual memory.
127 *
128 * \param vma virtual memory area.
129 * \param address access address.
130 * \return pointer to the page structure.
131 *
132 * Get the the mapping, find the real physical page to map, get the page, and
133 * return it.
134 */
135static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
136 unsigned long address)
137{
138 drm_map_t *map = (drm_map_t *)vma->vm_private_data;
139 unsigned long offset;
140 unsigned long i;
141 struct page *page;
142
143 if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
144 if (!map) return NOPAGE_OOM; /* Nothing allocated */
145
146 offset = address - vma->vm_start;
147 i = (unsigned long)map->handle + offset;
148 page = vmalloc_to_page((void *)i);
149 if (!page)
150 return NOPAGE_OOM;
151 get_page(page);
152
153 DRM_DEBUG("shm_nopage 0x%lx\n", address);
154 return page;
155}
156
157
158/**
159 * \c close method for shared virtual memory.
160 *
161 * \param vma virtual memory area.
162 *
163 * Deletes map information if we are the last
164 * person to close a mapping and it's not in the global maplist.
165 */
166void drm_vm_shm_close(struct vm_area_struct *vma)
167{
168 drm_file_t *priv = vma->vm_file->private_data;
169 drm_device_t *dev = priv->head->dev;
170 drm_vma_entry_t *pt, *prev, *next;
171 drm_map_t *map;
172 drm_map_list_t *r_list;
173 struct list_head *list;
174 int found_maps = 0;
175
176 DRM_DEBUG("0x%08lx,0x%08lx\n",
177 vma->vm_start, vma->vm_end - vma->vm_start);
178 atomic_dec(&dev->vma_count);
179
180 map = vma->vm_private_data;
181
182 down(&dev->struct_sem);
183 for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
184 next = pt->next;
185 if (pt->vma->vm_private_data == map) found_maps++;
186 if (pt->vma == vma) {
187 if (prev) {
188 prev->next = pt->next;
189 } else {
190 dev->vmalist = pt->next;
191 }
192 drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
193 } else {
194 prev = pt;
195 }
196 }
197 /* We were the only map that was found */
198 if(found_maps == 1 &&
199 map->flags & _DRM_REMOVABLE) {
200 /* Check to see if we are in the maplist, if we are not, then
201 * we delete this mappings information.
202 */
203 found_maps = 0;
204 list = &dev->maplist->head;
205 list_for_each(list, &dev->maplist->head) {
206 r_list = list_entry(list, drm_map_list_t, head);
207 if (r_list->map == map) found_maps++;
208 }
209
210 if(!found_maps) {
211 switch (map->type) {
212 case _DRM_REGISTERS:
213 case _DRM_FRAME_BUFFER:
214 if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
215 int retcode;
216 retcode = mtrr_del(map->mtrr,
217 map->offset,
218 map->size);
219 DRM_DEBUG("mtrr_del = %d\n", retcode);
220 }
221 drm_ioremapfree(map->handle, map->size, dev);
222 break;
223 case _DRM_SHM:
224 vfree(map->handle);
225 break;
226 case _DRM_AGP:
227 case _DRM_SCATTER_GATHER:
228 break;
229 }
230 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
231 }
232 }
233 up(&dev->struct_sem);
234}
235
236/**
237 * \c nopage method for DMA virtual memory.
238 *
239 * \param vma virtual memory area.
240 * \param address access address.
241 * \return pointer to the page structure.
242 *
243 * Determine the page number from the page offset and get it from drm_device_dma::pagelist.
244 */
245static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
246 unsigned long address)
247{
248 drm_file_t *priv = vma->vm_file->private_data;
249 drm_device_t *dev = priv->head->dev;
250 drm_device_dma_t *dma = dev->dma;
251 unsigned long offset;
252 unsigned long page_nr;
253 struct page *page;
254
255 if (!dma) return NOPAGE_SIGBUS; /* Error */
256 if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
257 if (!dma->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
258
259 offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
260 page_nr = offset >> PAGE_SHIFT;
261 page = virt_to_page((dma->pagelist[page_nr] +
262 (offset & (~PAGE_MASK))));
263
264 get_page(page);
265
266 DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr);
267 return page;
268}
269
270/**
271 * \c nopage method for scatter-gather virtual memory.
272 *
273 * \param vma virtual memory area.
274 * \param address access address.
275 * \return pointer to the page structure.
276 *
277 * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
278 */
279static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
280 unsigned long address)
281{
282 drm_map_t *map = (drm_map_t *)vma->vm_private_data;
283 drm_file_t *priv = vma->vm_file->private_data;
284 drm_device_t *dev = priv->head->dev;
285 drm_sg_mem_t *entry = dev->sg;
286 unsigned long offset;
287 unsigned long map_offset;
288 unsigned long page_offset;
289 struct page *page;
290
291 if (!entry) return NOPAGE_SIGBUS; /* Error */
292 if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
293 if (!entry->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
294
295
296 offset = address - vma->vm_start;
297 map_offset = map->offset - dev->sg->handle;
298 page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
299 page = entry->pagelist[page_offset];
300 get_page(page);
301
302 return page;
303}
304
305
306#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
307
308static struct page *drm_vm_nopage(struct vm_area_struct *vma,
309 unsigned long address,
310 int *type) {
311 if (type) *type = VM_FAULT_MINOR;
312 return drm_do_vm_nopage(vma, address);
313}
314
315static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
316 unsigned long address,
317 int *type) {
318 if (type) *type = VM_FAULT_MINOR;
319 return drm_do_vm_shm_nopage(vma, address);
320}
321
322static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
323 unsigned long address,
324 int *type) {
325 if (type) *type = VM_FAULT_MINOR;
326 return drm_do_vm_dma_nopage(vma, address);
327}
328
329static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
330 unsigned long address,
331 int *type) {
332 if (type) *type = VM_FAULT_MINOR;
333 return drm_do_vm_sg_nopage(vma, address);
334}
335
336#else /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) */
337
338static struct page *drm_vm_nopage(struct vm_area_struct *vma,
339 unsigned long address,
340 int unused) {
341 return drm_do_vm_nopage(vma, address);
342}
343
344static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
345 unsigned long address,
346 int unused) {
347 return drm_do_vm_shm_nopage(vma, address);
348}
349
350static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
351 unsigned long address,
352 int unused) {
353 return drm_do_vm_dma_nopage(vma, address);
354}
355
356static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
357 unsigned long address,
358 int unused) {
359 return drm_do_vm_sg_nopage(vma, address);
360}
361
362#endif
363
364
365/** AGP virtual memory operations */
366static struct vm_operations_struct drm_vm_ops = {
367 .nopage = drm_vm_nopage,
368 .open = drm_vm_open,
369 .close = drm_vm_close,
370};
371
372/** Shared virtual memory operations */
373static struct vm_operations_struct drm_vm_shm_ops = {
374 .nopage = drm_vm_shm_nopage,
375 .open = drm_vm_open,
376 .close = drm_vm_shm_close,
377};
378
379/** DMA virtual memory operations */
380static struct vm_operations_struct drm_vm_dma_ops = {
381 .nopage = drm_vm_dma_nopage,
382 .open = drm_vm_open,
383 .close = drm_vm_close,
384};
385
386/** Scatter-gather virtual memory operations */
387static struct vm_operations_struct drm_vm_sg_ops = {
388 .nopage = drm_vm_sg_nopage,
389 .open = drm_vm_open,
390 .close = drm_vm_close,
391};
392
393
394/**
395 * \c open method for shared virtual memory.
396 *
397 * \param vma virtual memory area.
398 *
399 * Create a new drm_vma_entry structure as the \p vma private data entry and
400 * add it to drm_device::vmalist.
401 */
402void drm_vm_open(struct vm_area_struct *vma)
403{
404 drm_file_t *priv = vma->vm_file->private_data;
405 drm_device_t *dev = priv->head->dev;
406 drm_vma_entry_t *vma_entry;
407
408 DRM_DEBUG("0x%08lx,0x%08lx\n",
409 vma->vm_start, vma->vm_end - vma->vm_start);
410 atomic_inc(&dev->vma_count);
411
412 vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
413 if (vma_entry) {
414 down(&dev->struct_sem);
415 vma_entry->vma = vma;
416 vma_entry->next = dev->vmalist;
417 vma_entry->pid = current->pid;
418 dev->vmalist = vma_entry;
419 up(&dev->struct_sem);
420 }
421}
422
423/**
424 * \c close method for all virtual memory types.
425 *
426 * \param vma virtual memory area.
427 *
428 * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
429 * free it.
430 */
431void drm_vm_close(struct vm_area_struct *vma)
432{
433 drm_file_t *priv = vma->vm_file->private_data;
434 drm_device_t *dev = priv->head->dev;
435 drm_vma_entry_t *pt, *prev;
436
437 DRM_DEBUG("0x%08lx,0x%08lx\n",
438 vma->vm_start, vma->vm_end - vma->vm_start);
439 atomic_dec(&dev->vma_count);
440
441 down(&dev->struct_sem);
442 for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
443 if (pt->vma == vma) {
444 if (prev) {
445 prev->next = pt->next;
446 } else {
447 dev->vmalist = pt->next;
448 }
449 drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
450 break;
451 }
452 }
453 up(&dev->struct_sem);
454}
455
456/**
457 * mmap DMA memory.
458 *
459 * \param filp file pointer.
460 * \param vma virtual memory area.
461 * \return zero on success or a negative number on failure.
462 *
463 * Sets the virtual memory area operations structure to vm_dma_ops, the file
464 * pointer, and calls vm_open().
465 */
466int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
467{
468 drm_file_t *priv = filp->private_data;
469 drm_device_t *dev;
470 drm_device_dma_t *dma;
471 unsigned long length = vma->vm_end - vma->vm_start;
472
473 lock_kernel();
474 dev = priv->head->dev;
475 dma = dev->dma;
476 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
477 vma->vm_start, vma->vm_end, VM_OFFSET(vma));
478
479 /* Length must match exact page count */
480 if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
481 unlock_kernel();
482 return -EINVAL;
483 }
484 unlock_kernel();
485
486 vma->vm_ops = &drm_vm_dma_ops;
487
488#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
489 vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
490#else
491 vma->vm_flags |= VM_RESERVED; /* Don't swap */
492#endif
493
494 vma->vm_file = filp; /* Needed for drm_vm_open() */
495 drm_vm_open(vma);
496 return 0;
497}
498
499unsigned long drm_core_get_map_ofs(drm_map_t *map)
500{
501 return map->offset;
502}
503EXPORT_SYMBOL(drm_core_get_map_ofs);
504
505unsigned long drm_core_get_reg_ofs(struct drm_device *dev)
506{
507#ifdef __alpha__
508 return dev->hose->dense_mem_base - dev->hose->mem_space->start;
509#else
510 return 0;
511#endif
512}
513EXPORT_SYMBOL(drm_core_get_reg_ofs);
514
515/**
516 * mmap DMA memory.
517 *
518 * \param filp file pointer.
519 * \param vma virtual memory area.
520 * \return zero on success or a negative number on failure.
521 *
522 * If the virtual memory area has no offset associated with it then it's a DMA
523 * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist,
524 * checks that the restricted flag is not set, sets the virtual memory operations
525 * according to the mapping type and remaps the pages. Finally sets the file
526 * pointer and calls vm_open().
527 */
528int drm_mmap(struct file *filp, struct vm_area_struct *vma)
529{
530 drm_file_t *priv = filp->private_data;
531 drm_device_t *dev = priv->head->dev;
532 drm_map_t *map = NULL;
533 drm_map_list_t *r_list;
534 unsigned long offset = 0;
535 struct list_head *list;
536
537 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
538 vma->vm_start, vma->vm_end, VM_OFFSET(vma));
539
540 if ( !priv->authenticated ) return -EACCES;
541
542 /* We check for "dma". On Apple's UniNorth, it's valid to have
543 * the AGP mapped at physical address 0
544 * --BenH.
545 */
546 if (!VM_OFFSET(vma)
547#if __OS_HAS_AGP
548 && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
549#endif
550 )
551 return drm_mmap_dma(filp, vma);
552
553 /* A sequential search of a linked list is
554 fine here because: 1) there will only be
555 about 5-10 entries in the list and, 2) a
556 DRI client only has to do this mapping
557 once, so it doesn't have to be optimized
558 for performance, even if the list was a
559 bit longer. */
560 list_for_each(list, &dev->maplist->head) {
561 unsigned long off;
562
563 r_list = list_entry(list, drm_map_list_t, head);
564 map = r_list->map;
565 if (!map) continue;
566 off = dev->driver->get_map_ofs(map);
567 if (off == VM_OFFSET(vma)) break;
568 }
569
570 if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
571 return -EPERM;
572
573 /* Check for valid size. */
574 if (map->size != vma->vm_end - vma->vm_start) return -EINVAL;
575
576 if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
577 vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
578#if defined(__i386__) || defined(__x86_64__)
579 pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
580#else
581 /* Ye gads this is ugly. With more thought
582 we could move this up higher and use
583 `protection_map' instead. */
584 vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
585 __pte(pgprot_val(vma->vm_page_prot)))));
586#endif
587 }
588
589 switch (map->type) {
590 case _DRM_AGP:
591 if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
592 /*
593 * On some platforms we can't talk to bus dma address from the CPU, so for
594 * memory of type DRM_AGP, we'll deal with sorting out the real physical
595 * pages and mappings in nopage()
596 */
597#if defined(__powerpc__)
598 pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
599#endif
600 vma->vm_ops = &drm_vm_ops;
601 break;
602 }
603 /* fall through to _DRM_FRAME_BUFFER... */
604 case _DRM_FRAME_BUFFER:
605 case _DRM_REGISTERS:
606 if (VM_OFFSET(vma) >= __pa(high_memory)) {
607#if defined(__i386__) || defined(__x86_64__)
608 if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
609 pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
610 pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
611 }
612#elif defined(__powerpc__)
613 pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED;
614#endif
615 vma->vm_flags |= VM_IO; /* not in core dump */
616 }
617#if defined(__ia64__)
618 if (efi_range_is_wc(vma->vm_start, vma->vm_end -
619 vma->vm_start))
620 vma->vm_page_prot =
621 pgprot_writecombine(vma->vm_page_prot);
622 else
623 vma->vm_page_prot =
624 pgprot_noncached(vma->vm_page_prot);
625#endif
626 offset = dev->driver->get_reg_ofs(dev);
627#ifdef __sparc__
628 if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
629 (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
630 vma->vm_end - vma->vm_start,
631 vma->vm_page_prot))
632#else
633 if (io_remap_pfn_range(vma, vma->vm_start,
634 (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
635 vma->vm_end - vma->vm_start,
636 vma->vm_page_prot))
637#endif
638 return -EAGAIN;
639 DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
640 " offset = 0x%lx\n",
641 map->type,
642 vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset);
643 vma->vm_ops = &drm_vm_ops;
644 break;
645 case _DRM_SHM:
646 vma->vm_ops = &drm_vm_shm_ops;
647 vma->vm_private_data = (void *)map;
648 /* Don't let this area swap. Change when
649 DRM_KERNEL advisory is supported. */
650#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
651 vma->vm_flags |= VM_LOCKED;
652#else
653 vma->vm_flags |= VM_RESERVED;
654#endif
655 break;
656 case _DRM_SCATTER_GATHER:
657 vma->vm_ops = &drm_vm_sg_ops;
658 vma->vm_private_data = (void *)map;
659#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
660 vma->vm_flags |= VM_LOCKED;
661#else
662 vma->vm_flags |= VM_RESERVED;
663#endif
664 break;
665 default:
666 return -EINVAL; /* This should never happen. */
667 }
668#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
669 vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
670#else
671 vma->vm_flags |= VM_RESERVED; /* Don't swap */
672#endif
673
674 vma->vm_file = filp; /* Needed for drm_vm_open() */
675 drm_vm_open(vma);
676 return 0;
677}
678EXPORT_SYMBOL(drm_mmap);
diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c
new file mode 100644
index 000000000000..f51812078010
--- /dev/null
+++ b/drivers/char/drm/ffb_context.c
@@ -0,0 +1,551 @@
1/* $Id: ffb_context.c,v 1.5 2001/08/09 17:47:51 davem Exp $
2 * ffb_context.c: Creator/Creator3D DRI/DRM context switching.
3 *
4 * Copyright (C) 2000 David S. Miller (davem@redhat.com)
5 *
6 * Almost entirely stolen from tdfx_context.c, see there
7 * for authors.
8 */
9
10#include <linux/sched.h>
11#include <asm/upa.h>
12
13#include "ffb.h"
14#include "drmP.h"
15
16#include "ffb_drv.h"
17
18static int DRM(alloc_queue)(drm_device_t *dev, int is_2d_only)
19{
20 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
21 int i;
22
23 for (i = 0; i < FFB_MAX_CTXS; i++) {
24 if (fpriv->hw_state[i] == NULL)
25 break;
26 }
27 if (i == FFB_MAX_CTXS)
28 return -1;
29
30 fpriv->hw_state[i] = kmalloc(sizeof(struct ffb_hw_context), GFP_KERNEL);
31 if (fpriv->hw_state[i] == NULL)
32 return -1;
33
34 fpriv->hw_state[i]->is_2d_only = is_2d_only;
35
36 /* Plus one because 0 is the special DRM_KERNEL_CONTEXT. */
37 return i + 1;
38}
39
40static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
41{
42 ffb_fbcPtr ffb = fpriv->regs;
43 struct ffb_hw_context *ctx;
44 int i;
45
46 ctx = fpriv->hw_state[idx - 1];
47 if (idx == 0 || ctx == NULL)
48 return;
49
50 if (ctx->is_2d_only) {
51 /* 2D applications only care about certain pieces
52 * of state.
53 */
54 ctx->drawop = upa_readl(&ffb->drawop);
55 ctx->ppc = upa_readl(&ffb->ppc);
56 ctx->wid = upa_readl(&ffb->wid);
57 ctx->fg = upa_readl(&ffb->fg);
58 ctx->bg = upa_readl(&ffb->bg);
59 ctx->xclip = upa_readl(&ffb->xclip);
60 ctx->fbc = upa_readl(&ffb->fbc);
61 ctx->rop = upa_readl(&ffb->rop);
62 ctx->cmp = upa_readl(&ffb->cmp);
63 ctx->matchab = upa_readl(&ffb->matchab);
64 ctx->magnab = upa_readl(&ffb->magnab);
65 ctx->pmask = upa_readl(&ffb->pmask);
66 ctx->xpmask = upa_readl(&ffb->xpmask);
67 ctx->lpat = upa_readl(&ffb->lpat);
68 ctx->fontxy = upa_readl(&ffb->fontxy);
69 ctx->fontw = upa_readl(&ffb->fontw);
70 ctx->fontinc = upa_readl(&ffb->fontinc);
71
72 /* stencil/stencilctl only exists on FFB2+ and later
73 * due to the introduction of 3DRAM-III.
74 */
75 if (fpriv->ffb_type == ffb2_vertical_plus ||
76 fpriv->ffb_type == ffb2_horizontal_plus) {
77 ctx->stencil = upa_readl(&ffb->stencil);
78 ctx->stencilctl = upa_readl(&ffb->stencilctl);
79 }
80
81 for (i = 0; i < 32; i++)
82 ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]);
83 ctx->ucsr = upa_readl(&ffb->ucsr);
84 return;
85 }
86
87 /* Fetch drawop. */
88 ctx->drawop = upa_readl(&ffb->drawop);
89
90 /* If we were saving the vertex registers, this is where
91 * we would do it. We would save 32 32-bit words starting
92 * at ffb->suvtx.
93 */
94
95 /* Capture rendering attributes. */
96
97 ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */
98 ctx->wid = upa_readl(&ffb->wid); /* Current WID */
99 ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */
100 ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */
101 ctx->consty = upa_readl(&ffb->consty); /* Constant Y */
102 ctx->constz = upa_readl(&ffb->constz); /* Constant Z */
103 ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */
104 ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */
105 ctx->vclipmin = upa_readl(&ffb->vclipmin); /* Primary XY clip, minimum */
106 ctx->vclipmax = upa_readl(&ffb->vclipmax); /* Primary XY clip, maximum */
107 ctx->vclipzmin = upa_readl(&ffb->vclipzmin); /* Primary Z clip, minimum */
108 ctx->vclipzmax = upa_readl(&ffb->vclipzmax); /* Primary Z clip, maximum */
109 ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */
110 ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */
111 ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */
112 ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */
113 ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */
114 ctx->blendc1 = upa_readl(&ffb->blendc1); /* Alpha Blend Color 1 */
115 ctx->blendc2 = upa_readl(&ffb->blendc2); /* Alpha Blend Color 2 */
116 ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */
117 ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */
118 ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */
119 ctx->matchab = upa_readl(&ffb->matchab); /* Buffer A/B Match Ops */
120 ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */
121 ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */
122 ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */
123 ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */
124 ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */
125 ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */
126 ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */
127
128 /* Auxiliary Clips. */
129 ctx->auxclip0min = upa_readl(&ffb->auxclip[0].min);
130 ctx->auxclip0max = upa_readl(&ffb->auxclip[0].max);
131 ctx->auxclip1min = upa_readl(&ffb->auxclip[1].min);
132 ctx->auxclip1max = upa_readl(&ffb->auxclip[1].max);
133 ctx->auxclip2min = upa_readl(&ffb->auxclip[2].min);
134 ctx->auxclip2max = upa_readl(&ffb->auxclip[2].max);
135 ctx->auxclip3min = upa_readl(&ffb->auxclip[3].min);
136 ctx->auxclip3max = upa_readl(&ffb->auxclip[3].max);
137
138 ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */
139 ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */
140 ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */
141 ctx->fontinc = upa_readl(&ffb->fontinc); /* Font X/Y Increment */
142
143 /* These registers/features only exist on FFB2 and later chips. */
144 if (fpriv->ffb_type >= ffb2_prototype) {
145 ctx->dcss1 = upa_readl(&ffb->dcss1); /* Depth Cue Scale Slope 1 */
146 ctx->dcss2 = upa_readl(&ffb->dcss2); /* Depth Cue Scale Slope 2 */
147 ctx->dcss2 = upa_readl(&ffb->dcss3); /* Depth Cue Scale Slope 3 */
148 ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */
149 ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */
150 ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */
151 ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */
152 ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */
153 ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */
154
155 /* And stencil/stencilctl only exists on FFB2+ and later
156 * due to the introduction of 3DRAM-III.
157 */
158 if (fpriv->ffb_type == ffb2_vertical_plus ||
159 fpriv->ffb_type == ffb2_horizontal_plus) {
160 ctx->stencil = upa_readl(&ffb->stencil);
161 ctx->stencilctl = upa_readl(&ffb->stencilctl);
162 }
163 }
164
165 /* Save the 32x32 area pattern. */
166 for (i = 0; i < 32; i++)
167 ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]);
168
169 /* Finally, stash away the User Constol/Status Register. */
170 ctx->ucsr = upa_readl(&ffb->ucsr);
171}
172
173static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
174{
175 ffb_fbcPtr ffb = fpriv->regs;
176 struct ffb_hw_context *ctx;
177 int i;
178
179 ctx = fpriv->hw_state[idx - 1];
180 if (idx == 0 || ctx == NULL)
181 return;
182
183 if (ctx->is_2d_only) {
184 /* 2D applications only care about certain pieces
185 * of state.
186 */
187 upa_writel(ctx->drawop, &ffb->drawop);
188
189 /* If we were restoring the vertex registers, this is where
190 * we would do it. We would restore 32 32-bit words starting
191 * at ffb->suvtx.
192 */
193
194 upa_writel(ctx->ppc, &ffb->ppc);
195 upa_writel(ctx->wid, &ffb->wid);
196 upa_writel(ctx->fg, &ffb->fg);
197 upa_writel(ctx->bg, &ffb->bg);
198 upa_writel(ctx->xclip, &ffb->xclip);
199 upa_writel(ctx->fbc, &ffb->fbc);
200 upa_writel(ctx->rop, &ffb->rop);
201 upa_writel(ctx->cmp, &ffb->cmp);
202 upa_writel(ctx->matchab, &ffb->matchab);
203 upa_writel(ctx->magnab, &ffb->magnab);
204 upa_writel(ctx->pmask, &ffb->pmask);
205 upa_writel(ctx->xpmask, &ffb->xpmask);
206 upa_writel(ctx->lpat, &ffb->lpat);
207 upa_writel(ctx->fontxy, &ffb->fontxy);
208 upa_writel(ctx->fontw, &ffb->fontw);
209 upa_writel(ctx->fontinc, &ffb->fontinc);
210
211 /* stencil/stencilctl only exists on FFB2+ and later
212 * due to the introduction of 3DRAM-III.
213 */
214 if (fpriv->ffb_type == ffb2_vertical_plus ||
215 fpriv->ffb_type == ffb2_horizontal_plus) {
216 upa_writel(ctx->stencil, &ffb->stencil);
217 upa_writel(ctx->stencilctl, &ffb->stencilctl);
218 upa_writel(0x80000000, &ffb->fbc);
219 upa_writel((ctx->stencilctl | 0x80000),
220 &ffb->rawstencilctl);
221 upa_writel(ctx->fbc, &ffb->fbc);
222 }
223
224 for (i = 0; i < 32; i++)
225 upa_writel(ctx->area_pattern[i], &ffb->pattern[i]);
226 upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr);
227 return;
228 }
229
230 /* Restore drawop. */
231 upa_writel(ctx->drawop, &ffb->drawop);
232
233 /* If we were restoring the vertex registers, this is where
234 * we would do it. We would restore 32 32-bit words starting
235 * at ffb->suvtx.
236 */
237
238 /* Restore rendering attributes. */
239
240 upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */
241 upa_writel(ctx->wid, &ffb->wid); /* Current WID */
242 upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */
243 upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */
244 upa_writel(ctx->consty, &ffb->consty); /* Constant Y */
245 upa_writel(ctx->constz, &ffb->constz); /* Constant Z */
246 upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */
247 upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */
248 upa_writel(ctx->vclipmin, &ffb->vclipmin); /* Primary XY clip, minimum */
249 upa_writel(ctx->vclipmax, &ffb->vclipmax); /* Primary XY clip, maximum */
250 upa_writel(ctx->vclipzmin, &ffb->vclipzmin); /* Primary Z clip, minimum */
251 upa_writel(ctx->vclipzmax, &ffb->vclipzmax); /* Primary Z clip, maximum */
252 upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */
253 upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */
254 upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */
255 upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */
256 upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */
257 upa_writel(ctx->blendc1, &ffb->blendc1); /* Alpha Blend Color 1 */
258 upa_writel(ctx->blendc2, &ffb->blendc2); /* Alpha Blend Color 2 */
259 upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */
260 upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */
261 upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */
262 upa_writel(ctx->matchab, &ffb->matchab); /* Buffer A/B Match Ops */
263 upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */
264 upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */
265 upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */
266 upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */
267 upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */
268 upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */
269 upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */
270
271 /* Auxiliary Clips. */
272 upa_writel(ctx->auxclip0min, &ffb->auxclip[0].min);
273 upa_writel(ctx->auxclip0max, &ffb->auxclip[0].max);
274 upa_writel(ctx->auxclip1min, &ffb->auxclip[1].min);
275 upa_writel(ctx->auxclip1max, &ffb->auxclip[1].max);
276 upa_writel(ctx->auxclip2min, &ffb->auxclip[2].min);
277 upa_writel(ctx->auxclip2max, &ffb->auxclip[2].max);
278 upa_writel(ctx->auxclip3min, &ffb->auxclip[3].min);
279 upa_writel(ctx->auxclip3max, &ffb->auxclip[3].max);
280
281 upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */
282 upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */
283 upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */
284 upa_writel(ctx->fontinc, &ffb->fontinc); /* Font X/Y Increment */
285
286 /* These registers/features only exist on FFB2 and later chips. */
287 if (fpriv->ffb_type >= ffb2_prototype) {
288 upa_writel(ctx->dcss1, &ffb->dcss1); /* Depth Cue Scale Slope 1 */
289 upa_writel(ctx->dcss2, &ffb->dcss2); /* Depth Cue Scale Slope 2 */
290 upa_writel(ctx->dcss3, &ffb->dcss2); /* Depth Cue Scale Slope 3 */
291 upa_writel(ctx->dcs2, &ffb->dcs2); /* Depth Cue Scale 2 */
292 upa_writel(ctx->dcs3, &ffb->dcs3); /* Depth Cue Scale 3 */
293 upa_writel(ctx->dcs4, &ffb->dcs4); /* Depth Cue Scale 4 */
294 upa_writel(ctx->dcd2, &ffb->dcd2); /* Depth Cue Depth 2 */
295 upa_writel(ctx->dcd3, &ffb->dcd3); /* Depth Cue Depth 3 */
296 upa_writel(ctx->dcd4, &ffb->dcd4); /* Depth Cue Depth 4 */
297
298 /* And stencil/stencilctl only exists on FFB2+ and later
299 * due to the introduction of 3DRAM-III.
300 */
301 if (fpriv->ffb_type == ffb2_vertical_plus ||
302 fpriv->ffb_type == ffb2_horizontal_plus) {
303 /* Unfortunately, there is a hardware bug on
304 * the FFB2+ chips which prevents a normal write
305 * to the stencil control register from working
306 * as it should.
307 *
308 * The state controlled by the FFB stencilctl register
309 * really gets transferred to the per-buffer instances
310 * of the stencilctl register in the 3DRAM chips.
311 *
312 * The bug is that FFB does not update buffer C correctly,
313 * so we have to do it by hand for them.
314 */
315
316 /* This will update buffers A and B. */
317 upa_writel(ctx->stencil, &ffb->stencil);
318 upa_writel(ctx->stencilctl, &ffb->stencilctl);
319
320 /* Force FFB to use buffer C 3dram regs. */
321 upa_writel(0x80000000, &ffb->fbc);
322 upa_writel((ctx->stencilctl | 0x80000),
323 &ffb->rawstencilctl);
324
325 /* Now restore the correct FBC controls. */
326 upa_writel(ctx->fbc, &ffb->fbc);
327 }
328 }
329
330 /* Restore the 32x32 area pattern. */
331 for (i = 0; i < 32; i++)
332 upa_writel(ctx->area_pattern[i], &ffb->pattern[i]);
333
334 /* Finally, stash away the User Constol/Status Register.
335 * The only state we really preserve here is the picking
336 * control.
337 */
338 upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr);
339}
340
341#define FFB_UCSR_FB_BUSY 0x01000000
342#define FFB_UCSR_RP_BUSY 0x02000000
343#define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
344
345static void FFBWait(ffb_fbcPtr ffb)
346{
347 int limit = 100000;
348
349 do {
350 u32 regval = upa_readl(&ffb->ucsr);
351
352 if ((regval & FFB_UCSR_ALL_BUSY) == 0)
353 break;
354 } while (--limit);
355}
356
357int ffb_driver_context_switch(drm_device_t *dev, int old, int new)
358{
359 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
360
361#ifdef DRM_DMA_HISTOGRAM
362 dev->ctx_start = get_cycles();
363#endif
364
365 DRM_DEBUG("Context switch from %d to %d\n", old, new);
366
367 if (new == dev->last_context ||
368 dev->last_context == 0) {
369 dev->last_context = new;
370 return 0;
371 }
372
373 FFBWait(fpriv->regs);
374 ffb_save_context(fpriv, old);
375 ffb_restore_context(fpriv, old, new);
376 FFBWait(fpriv->regs);
377
378 dev->last_context = new;
379
380 return 0;
381}
382
383int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
384 unsigned long arg)
385{
386 drm_ctx_res_t res;
387 drm_ctx_t ctx;
388 int i;
389
390 DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
391 if (copy_from_user(&res, (drm_ctx_res_t __user *)arg, sizeof(res)))
392 return -EFAULT;
393 if (res.count >= DRM_RESERVED_CONTEXTS) {
394 memset(&ctx, 0, sizeof(ctx));
395 for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
396 ctx.handle = i;
397 if (copy_to_user(&res.contexts[i],
398 &i,
399 sizeof(i)))
400 return -EFAULT;
401 }
402 }
403 res.count = DRM_RESERVED_CONTEXTS;
404 if (copy_to_user((drm_ctx_res_t __user *)arg, &res, sizeof(res)))
405 return -EFAULT;
406 return 0;
407}
408
409
410int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
411 unsigned long arg)
412{
413 drm_file_t *priv = filp->private_data;
414 drm_device_t *dev = priv->dev;
415 drm_ctx_t ctx;
416 int idx;
417
418 if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
419 return -EFAULT;
420 idx = DRM(alloc_queue)(dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
421 if (idx < 0)
422 return -ENFILE;
423
424 DRM_DEBUG("%d\n", ctx.handle);
425 ctx.handle = idx;
426 if (copy_to_user((drm_ctx_t __user *)arg, &ctx, sizeof(ctx)))
427 return -EFAULT;
428 return 0;
429}
430
431int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
432 unsigned long arg)
433{
434 drm_file_t *priv = filp->private_data;
435 drm_device_t *dev = priv->dev;
436 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
437 struct ffb_hw_context *hwctx;
438 drm_ctx_t ctx;
439 int idx;
440
441 if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
442 return -EFAULT;
443
444 idx = ctx.handle;
445 if (idx <= 0 || idx >= FFB_MAX_CTXS)
446 return -EINVAL;
447
448 hwctx = fpriv->hw_state[idx - 1];
449 if (hwctx == NULL)
450 return -EINVAL;
451
452 if ((ctx.flags & _DRM_CONTEXT_2DONLY) == 0)
453 hwctx->is_2d_only = 0;
454 else
455 hwctx->is_2d_only = 1;
456
457 return 0;
458}
459
460int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
461 unsigned long arg)
462{
463 drm_file_t *priv = filp->private_data;
464 drm_device_t *dev = priv->dev;
465 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
466 struct ffb_hw_context *hwctx;
467 drm_ctx_t ctx;
468 int idx;
469
470 if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
471 return -EFAULT;
472
473 idx = ctx.handle;
474 if (idx <= 0 || idx >= FFB_MAX_CTXS)
475 return -EINVAL;
476
477 hwctx = fpriv->hw_state[idx - 1];
478 if (hwctx == NULL)
479 return -EINVAL;
480
481 if (hwctx->is_2d_only != 0)
482 ctx.flags = _DRM_CONTEXT_2DONLY;
483 else
484 ctx.flags = 0;
485
486 if (copy_to_user((drm_ctx_t __user *)arg, &ctx, sizeof(ctx)))
487 return -EFAULT;
488
489 return 0;
490}
491
492int ffb_driver_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
493 unsigned long arg)
494{
495 drm_file_t *priv = filp->private_data;
496 drm_device_t *dev = priv->dev;
497 drm_ctx_t ctx;
498
499 if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
500 return -EFAULT;
501 DRM_DEBUG("%d\n", ctx.handle);
502 return ffb_driver_context_switch(dev, dev->last_context, ctx.handle);
503}
504
505int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
506 unsigned long arg)
507{
508 drm_ctx_t ctx;
509
510 if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
511 return -EFAULT;
512 DRM_DEBUG("%d\n", ctx.handle);
513
514 return 0;
515}
516
517int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
518 unsigned long arg)
519{
520 drm_ctx_t ctx;
521 drm_file_t *priv = filp->private_data;
522 drm_device_t *dev = priv->dev;
523 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
524 int idx;
525
526 if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
527 return -EFAULT;
528 DRM_DEBUG("%d\n", ctx.handle);
529
530 idx = ctx.handle - 1;
531 if (idx < 0 || idx >= FFB_MAX_CTXS)
532 return -EINVAL;
533
534 if (fpriv->hw_state[idx] != NULL) {
535 kfree(fpriv->hw_state[idx]);
536 fpriv->hw_state[idx] = NULL;
537 }
538 return 0;
539}
540
541void ffb_set_context_ioctls(void)
542{
543 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)].func = ffb_driver_addctx;
544 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx;
545 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx;
546 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx;
547 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func = ffb_driver_switchctx;
548 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx;
549 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx;
550
551}
diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
new file mode 100644
index 000000000000..ec614fff8f04
--- /dev/null
+++ b/drivers/char/drm/ffb_drv.c
@@ -0,0 +1,365 @@
1/* $Id: ffb_drv.c,v 1.16 2001/10/18 16:00:24 davem Exp $
2 * ffb_drv.c: Creator/Creator3D direct rendering driver.
3 *
4 * Copyright (C) 2000 David S. Miller (davem@redhat.com)
5 */
6
7#include <linux/config.h>
8#include "ffb.h"
9#include "drmP.h"
10
11#include "ffb_drv.h"
12
13#include <linux/sched.h>
14#include <linux/smp_lock.h>
15#include <asm/shmparam.h>
16#include <asm/oplib.h>
17#include <asm/upa.h>
18
19#define DRIVER_AUTHOR "David S. Miller"
20
21#define DRIVER_NAME "ffb"
22#define DRIVER_DESC "Creator/Creator3D"
23#define DRIVER_DATE "20000517"
24
25#define DRIVER_MAJOR 0
26#define DRIVER_MINOR 0
27#define DRIVER_PATCHLEVEL 1
28
29typedef struct _ffb_position_t {
30 int node;
31 int root;
32} ffb_position_t;
33
34static ffb_position_t *ffb_position;
35
36static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance)
37{
38 volatile unsigned char *strap_bits;
39 unsigned char val;
40
41 strap_bits = (volatile unsigned char *)
42 (ffb_priv->card_phys_base + 0x00200000UL);
43
44 /* Don't ask, you have to read the value twice for whatever
45 * reason to get correct contents.
46 */
47 val = upa_readb(strap_bits);
48 val = upa_readb(strap_bits);
49 switch (val & 0x78) {
50 case (0x0 << 5) | (0x0 << 3):
51 ffb_priv->ffb_type = ffb1_prototype;
52 printk("ffb%d: Detected FFB1 pre-FCS prototype\n", instance);
53 break;
54 case (0x0 << 5) | (0x1 << 3):
55 ffb_priv->ffb_type = ffb1_standard;
56 printk("ffb%d: Detected FFB1\n", instance);
57 break;
58 case (0x0 << 5) | (0x3 << 3):
59 ffb_priv->ffb_type = ffb1_speedsort;
60 printk("ffb%d: Detected FFB1-SpeedSort\n", instance);
61 break;
62 case (0x1 << 5) | (0x0 << 3):
63 ffb_priv->ffb_type = ffb2_prototype;
64 printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n", instance);
65 break;
66 case (0x1 << 5) | (0x1 << 3):
67 ffb_priv->ffb_type = ffb2_vertical;
68 printk("ffb%d: Detected FFB2/vertical\n", instance);
69 break;
70 case (0x1 << 5) | (0x2 << 3):
71 ffb_priv->ffb_type = ffb2_vertical_plus;
72 printk("ffb%d: Detected FFB2+/vertical\n", instance);
73 break;
74 case (0x2 << 5) | (0x0 << 3):
75 ffb_priv->ffb_type = ffb2_horizontal;
76 printk("ffb%d: Detected FFB2/horizontal\n", instance);
77 break;
78 case (0x2 << 5) | (0x2 << 3):
79 ffb_priv->ffb_type = ffb2_horizontal;
80 printk("ffb%d: Detected FFB2+/horizontal\n", instance);
81 break;
82 default:
83 ffb_priv->ffb_type = ffb2_vertical;
84 printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n", instance, val);
85 break;
86 };
87}
88
89static void ffb_apply_upa_parent_ranges(int parent,
90 struct linux_prom64_registers *regs)
91{
92 struct linux_prom64_ranges ranges[PROMREG_MAX];
93 char name[128];
94 int len, i;
95
96 prom_getproperty(parent, "name", name, sizeof(name));
97 if (strcmp(name, "upa") != 0)
98 return;
99
100 len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
101 if (len <= 0)
102 return;
103
104 len /= sizeof(struct linux_prom64_ranges);
105 for (i = 0; i < len; i++) {
106 struct linux_prom64_ranges *rng = &ranges[i];
107 u64 phys_addr = regs->phys_addr;
108
109 if (phys_addr >= rng->ot_child_base &&
110 phys_addr < (rng->ot_child_base + rng->or_size)) {
111 regs->phys_addr -= rng->ot_child_base;
112 regs->phys_addr += rng->ot_parent_base;
113 return;
114 }
115 }
116
117 return;
118}
119
120static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node,
121 int instance)
122{
123 struct linux_prom64_registers regs[2*PROMREG_MAX];
124 ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
125 int i;
126
127 ffb_priv->prom_node = prom_node;
128 if (prom_getproperty(ffb_priv->prom_node, "reg",
129 (void *)regs, sizeof(regs)) <= 0) {
130 return -EINVAL;
131 }
132 ffb_apply_upa_parent_ranges(parent_node, &regs[0]);
133 ffb_priv->card_phys_base = regs[0].phys_addr;
134 ffb_priv->regs = (ffb_fbcPtr)
135 (regs[0].phys_addr + 0x00600000UL);
136 get_ffb_type(ffb_priv, instance);
137 for (i = 0; i < FFB_MAX_CTXS; i++)
138 ffb_priv->hw_state[i] = NULL;
139
140 return 0;
141}
142
143static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
144{
145 drm_file_t *priv = filp->private_data;
146 drm_device_t *dev;
147 drm_map_list_t *r_list;
148 struct list_head *list;
149 drm_map_t *map;
150
151 if (!priv || (dev = priv->dev) == NULL)
152 return NULL;
153
154 list_for_each(list, &dev->maplist->head) {
155 unsigned long uoff;
156
157 r_list = (drm_map_list_t *)list;
158 map = r_list->map;
159 if (!map)
160 continue;
161 uoff = (map->offset & 0xffffffff);
162 if (uoff == off)
163 return map;
164 }
165
166 return NULL;
167}
168
169unsigned long ffb_get_unmapped_area(struct file *filp,
170 unsigned long hint,
171 unsigned long len,
172 unsigned long pgoff,
173 unsigned long flags)
174{
175 drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT);
176 unsigned long addr = -ENOMEM;
177
178 if (!map)
179 return get_unmapped_area(NULL, hint, len, pgoff, flags);
180
181 if (map->type == _DRM_FRAME_BUFFER ||
182 map->type == _DRM_REGISTERS) {
183#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
184 addr = get_fb_unmapped_area(filp, hint, len, pgoff, flags);
185#else
186 addr = get_unmapped_area(NULL, hint, len, pgoff, flags);
187#endif
188 } else if (map->type == _DRM_SHM && SHMLBA > PAGE_SIZE) {
189 unsigned long slack = SHMLBA - PAGE_SIZE;
190
191 addr = get_unmapped_area(NULL, hint, len + slack, pgoff, flags);
192 if (!(addr & ~PAGE_MASK)) {
193 unsigned long kvirt = (unsigned long) map->handle;
194
195 if ((kvirt & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
196 unsigned long koff, aoff;
197
198 koff = kvirt & (SHMLBA - 1);
199 aoff = addr & (SHMLBA - 1);
200 if (koff < aoff)
201 koff += SHMLBA;
202
203 addr += (koff - aoff);
204 }
205 }
206 } else {
207 addr = get_unmapped_area(NULL, hint, len, pgoff, flags);
208 }
209
210 return addr;
211}
212
213static int ffb_presetup(drm_device_t *dev)
214{
215 ffb_dev_priv_t *ffb_priv;
216 int ret = 0;
217 int i = 0;
218
219 /* Check for the case where no device was found. */
220 if (ffb_position == NULL)
221 return -ENODEV;
222
223 /* code used to use numdevs no numdevs anymore */
224 ffb_priv = kmalloc(sizeof(ffb_dev_priv_t), GFP_KERNEL);
225 if (!ffb_priv)
226 return -ENOMEM;
227 memset(ffb_priv, 0, sizeof(*ffb_priv));
228 dev->dev_private = ffb_priv;
229
230 ret = ffb_init_one(dev,
231 ffb_position[i].node,
232 ffb_position[i].root,
233 i);
234 return ret;
235}
236
237static void ffb_driver_release(drm_device_t *dev, struct file *filp)
238{
239 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
240 int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);
241 int idx;
242
243 idx = context - 1;
244 if (fpriv &&
245 context != DRM_KERNEL_CONTEXT &&
246 fpriv->hw_state[idx] != NULL) {
247 kfree(fpriv->hw_state[idx]);
248 fpriv->hw_state[idx] = NULL;
249 }
250}
251
252static void ffb_driver_pretakedown(drm_device_t *dev)
253{
254 if (dev->dev_private) kfree(dev->dev_private);
255}
256
257static int ffb_driver_postcleanup(drm_device_t *dev)
258{
259 if (ffb_position != NULL) kfree(ffb_position);
260 return 0;
261}
262
263static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev, drm_lock_t *lock)
264{
265 dev->lock.filp = 0;
266 {
267 __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
268 unsigned int old, new, prev, ctx;
269
270 ctx = lock->context;
271 do {
272 old = *plock;
273 new = ctx;
274 prev = cmpxchg(plock, old, new);
275 } while (prev != old);
276 }
277 wake_up_interruptible(&dev->lock.lock_queue);
278}
279
280static unsigned long ffb_driver_get_map_ofs(drm_map_t *map)
281{
282 return (map->offset & 0xffffffff);
283}
284
285static unsigned long ffb_driver_get_reg_ofs(drm_device_t *dev)
286{
287 ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
288
289 if (ffb_priv)
290 return ffb_priv->card_phys_base;
291
292 return 0;
293}
294
295static int postinit( struct drm_device *dev, unsigned long flags )
296{
297 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
298 DRIVER_NAME,
299 DRIVER_MAJOR,
300 DRIVER_MINOR,
301 DRIVER_PATCHLEVEL,
302 DRIVER_DATE,
303 dev->minor
304 );
305 return 0;
306}
307
308static int version( drm_version_t *version )
309{
310 int len;
311
312 version->version_major = DRIVER_MAJOR;
313 version->version_minor = DRIVER_MINOR;
314 version->version_patchlevel = DRIVER_PATCHLEVEL;
315 DRM_COPY( version->name, DRIVER_NAME );
316 DRM_COPY( version->date, DRIVER_DATE );
317 DRM_COPY( version->desc, DRIVER_DESC );
318 return 0;
319}
320
321static drm_ioctl_desc_t ioctls[] = {
322
323};
324
325static struct drm_driver driver = {
326 .driver_features = 0,
327 .dev_priv_size = sizeof(u32),
328 .release = ffb_driver_release,
329 .presetup = ffb_presetup,
330 .pretakedown = ffb_driver_pretakedown,
331 .postcleanup = ffb_driver_postcleanup,
332 .kernel_context_switch = ffb_driver_context_switch,
333 .kernel_context_switch_unlock = ffb_driver_kernel_context_switch_unlock,
334 .get_map_ofs = ffb_driver_get_map_ofs,
335 .get_reg_ofs = ffb_driver_get_reg_ofs,
336 .postinit = postinit,
337 .version = version,
338 .ioctls = ioctls,
339 .num_ioctls = DRM_ARRAY_SIZE(ioctls),
340 .fops = {
341 .owner = THIS_MODULE,
342 .open = drm_open,
343 .release = drm_release,
344 .ioctl = drm_ioctl,
345 .mmap = drm_mmap,
346 .poll = drm_poll,
347 .fasync = drm_fasync,
348 },
349};
350
351static int __init ffb_init(void)
352{
353 return -ENODEV;
354}
355
356static void __exit ffb_exit(void)
357{
358}
359
360module_init(ffb_init);
361module_exit(ffb_exit);
362
363MODULE_AUTHOR( DRIVER_AUTHOR );
364MODULE_DESCRIPTION( DRIVER_DESC );
365MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/ffb_drv.h b/drivers/char/drm/ffb_drv.h
new file mode 100644
index 000000000000..8bf7f1e143f1
--- /dev/null
+++ b/drivers/char/drm/ffb_drv.h
@@ -0,0 +1,286 @@
1/* $Id: ffb_drv.h,v 1.1 2000/06/01 04:24:39 davem Exp $
2 * ffb_drv.h: Creator/Creator3D direct rendering driver.
3 *
4 * Copyright (C) 2000 David S. Miller (davem@redhat.com)
5 */
6
7/* Auxilliary clips. */
8typedef struct {
9 volatile unsigned int min;
10 volatile unsigned int max;
11} ffb_auxclip, *ffb_auxclipPtr;
12
13/* FFB register set. */
14typedef struct _ffb_fbc {
15 /* Next vertex registers, on the right we list which drawops
16 * use said register and the logical name the register has in
17 * that context.
18 */ /* DESCRIPTION DRAWOP(NAME) */
19/*0x00*/unsigned int pad1[3]; /* Reserved */
20/*0x0c*/volatile unsigned int alpha; /* ALPHA Transparency */
21/*0x10*/volatile unsigned int red; /* RED */
22/*0x14*/volatile unsigned int green; /* GREEN */
23/*0x18*/volatile unsigned int blue; /* BLUE */
24/*0x1c*/volatile unsigned int z; /* DEPTH */
25/*0x20*/volatile unsigned int y; /* Y triangle(DOYF) */
26 /* aadot(DYF) */
27 /* ddline(DYF) */
28 /* aaline(DYF) */
29/*0x24*/volatile unsigned int x; /* X triangle(DOXF) */
30 /* aadot(DXF) */
31 /* ddline(DXF) */
32 /* aaline(DXF) */
33/*0x28*/unsigned int pad2[2]; /* Reserved */
34/*0x30*/volatile unsigned int ryf; /* Y (alias to DOYF) ddline(RYF) */
35 /* aaline(RYF) */
36 /* triangle(RYF) */
37/*0x34*/volatile unsigned int rxf; /* X ddline(RXF) */
38 /* aaline(RXF) */
39 /* triangle(RXF) */
40/*0x38*/unsigned int pad3[2]; /* Reserved */
41/*0x40*/volatile unsigned int dmyf; /* Y (alias to DOYF) triangle(DMYF) */
42/*0x44*/volatile unsigned int dmxf; /* X triangle(DMXF) */
43/*0x48*/unsigned int pad4[2]; /* Reserved */
44/*0x50*/volatile unsigned int ebyi; /* Y (alias to RYI) polygon(EBYI) */
45/*0x54*/volatile unsigned int ebxi; /* X polygon(EBXI) */
46/*0x58*/unsigned int pad5[2]; /* Reserved */
47/*0x60*/volatile unsigned int by; /* Y brline(RYI) */
48 /* fastfill(OP) */
49 /* polygon(YI) */
50 /* rectangle(YI) */
51 /* bcopy(SRCY) */
52 /* vscroll(SRCY) */
53/*0x64*/volatile unsigned int bx; /* X brline(RXI) */
54 /* polygon(XI) */
55 /* rectangle(XI) */
56 /* bcopy(SRCX) */
57 /* vscroll(SRCX) */
58 /* fastfill(GO) */
59/*0x68*/volatile unsigned int dy; /* destination Y fastfill(DSTY) */
60 /* bcopy(DSRY) */
61 /* vscroll(DSRY) */
62/*0x6c*/volatile unsigned int dx; /* destination X fastfill(DSTX) */
63 /* bcopy(DSTX) */
64 /* vscroll(DSTX) */
65/*0x70*/volatile unsigned int bh; /* Y (alias to RYI) brline(DYI) */
66 /* dot(DYI) */
67 /* polygon(ETYI) */
68 /* Height fastfill(H) */
69 /* bcopy(H) */
70 /* vscroll(H) */
71 /* Y count fastfill(NY) */
72/*0x74*/volatile unsigned int bw; /* X dot(DXI) */
73 /* brline(DXI) */
74 /* polygon(ETXI) */
75 /* fastfill(W) */
76 /* bcopy(W) */
77 /* vscroll(W) */
78 /* fastfill(NX) */
79/*0x78*/unsigned int pad6[2]; /* Reserved */
80/*0x80*/unsigned int pad7[32]; /* Reserved */
81
82 /* Setup Unit's vertex state register */
83/*100*/ volatile unsigned int suvtx;
84/*104*/ unsigned int pad8[63]; /* Reserved */
85
86 /* Frame Buffer Control Registers */
87/*200*/ volatile unsigned int ppc; /* Pixel Processor Control */
88/*204*/ volatile unsigned int wid; /* Current WID */
89/*208*/ volatile unsigned int fg; /* FG data */
90/*20c*/ volatile unsigned int bg; /* BG data */
91/*210*/ volatile unsigned int consty; /* Constant Y */
92/*214*/ volatile unsigned int constz; /* Constant Z */
93/*218*/ volatile unsigned int xclip; /* X Clip */
94/*21c*/ volatile unsigned int dcss; /* Depth Cue Scale Slope */
95/*220*/ volatile unsigned int vclipmin; /* Viewclip XY Min Bounds */
96/*224*/ volatile unsigned int vclipmax; /* Viewclip XY Max Bounds */
97/*228*/ volatile unsigned int vclipzmin; /* Viewclip Z Min Bounds */
98/*22c*/ volatile unsigned int vclipzmax; /* Viewclip Z Max Bounds */
99/*230*/ volatile unsigned int dcsf; /* Depth Cue Scale Front Bound */
100/*234*/ volatile unsigned int dcsb; /* Depth Cue Scale Back Bound */
101/*238*/ volatile unsigned int dczf; /* Depth Cue Z Front */
102/*23c*/ volatile unsigned int dczb; /* Depth Cue Z Back */
103/*240*/ unsigned int pad9; /* Reserved */
104/*244*/ volatile unsigned int blendc; /* Alpha Blend Control */
105/*248*/ volatile unsigned int blendc1; /* Alpha Blend Color 1 */
106/*24c*/ volatile unsigned int blendc2; /* Alpha Blend Color 2 */
107/*250*/ volatile unsigned int fbramitc; /* FB RAM Interleave Test Control */
108/*254*/ volatile unsigned int fbc; /* Frame Buffer Control */
109/*258*/ volatile unsigned int rop; /* Raster OPeration */
110/*25c*/ volatile unsigned int cmp; /* Frame Buffer Compare */
111/*260*/ volatile unsigned int matchab; /* Buffer AB Match Mask */
112/*264*/ volatile unsigned int matchc; /* Buffer C(YZ) Match Mask */
113/*268*/ volatile unsigned int magnab; /* Buffer AB Magnitude Mask */
114/*26c*/ volatile unsigned int magnc; /* Buffer C(YZ) Magnitude Mask */
115/*270*/ volatile unsigned int fbcfg0; /* Frame Buffer Config 0 */
116/*274*/ volatile unsigned int fbcfg1; /* Frame Buffer Config 1 */
117/*278*/ volatile unsigned int fbcfg2; /* Frame Buffer Config 2 */
118/*27c*/ volatile unsigned int fbcfg3; /* Frame Buffer Config 3 */
119/*280*/ volatile unsigned int ppcfg; /* Pixel Processor Config */
120/*284*/ volatile unsigned int pick; /* Picking Control */
121/*288*/ volatile unsigned int fillmode; /* FillMode */
122/*28c*/ volatile unsigned int fbramwac; /* FB RAM Write Address Control */
123/*290*/ volatile unsigned int pmask; /* RGB PlaneMask */
124/*294*/ volatile unsigned int xpmask; /* X PlaneMask */
125/*298*/ volatile unsigned int ypmask; /* Y PlaneMask */
126/*29c*/ volatile unsigned int zpmask; /* Z PlaneMask */
127/*2a0*/ ffb_auxclip auxclip[4]; /* Auxilliary Viewport Clip */
128
129 /* New 3dRAM III support regs */
130/*2c0*/ volatile unsigned int rawblend2;
131/*2c4*/ volatile unsigned int rawpreblend;
132/*2c8*/ volatile unsigned int rawstencil;
133/*2cc*/ volatile unsigned int rawstencilctl;
134/*2d0*/ volatile unsigned int threedram1;
135/*2d4*/ volatile unsigned int threedram2;
136/*2d8*/ volatile unsigned int passin;
137/*2dc*/ volatile unsigned int rawclrdepth;
138/*2e0*/ volatile unsigned int rawpmask;
139/*2e4*/ volatile unsigned int rawcsrc;
140/*2e8*/ volatile unsigned int rawmatch;
141/*2ec*/ volatile unsigned int rawmagn;
142/*2f0*/ volatile unsigned int rawropblend;
143/*2f4*/ volatile unsigned int rawcmp;
144/*2f8*/ volatile unsigned int rawwac;
145/*2fc*/ volatile unsigned int fbramid;
146
147/*300*/ volatile unsigned int drawop; /* Draw OPeration */
148/*304*/ unsigned int pad10[2]; /* Reserved */
149/*30c*/ volatile unsigned int lpat; /* Line Pattern control */
150/*310*/ unsigned int pad11; /* Reserved */
151/*314*/ volatile unsigned int fontxy; /* XY Font coordinate */
152/*318*/ volatile unsigned int fontw; /* Font Width */
153/*31c*/ volatile unsigned int fontinc; /* Font Increment */
154/*320*/ volatile unsigned int font; /* Font bits */
155/*324*/ unsigned int pad12[3]; /* Reserved */
156/*330*/ volatile unsigned int blend2;
157/*334*/ volatile unsigned int preblend;
158/*338*/ volatile unsigned int stencil;
159/*33c*/ volatile unsigned int stencilctl;
160
161/*340*/ unsigned int pad13[4]; /* Reserved */
162/*350*/ volatile unsigned int dcss1; /* Depth Cue Scale Slope 1 */
163/*354*/ volatile unsigned int dcss2; /* Depth Cue Scale Slope 2 */
164/*358*/ volatile unsigned int dcss3; /* Depth Cue Scale Slope 3 */
165/*35c*/ volatile unsigned int widpmask;
166/*360*/ volatile unsigned int dcs2;
167/*364*/ volatile unsigned int dcs3;
168/*368*/ volatile unsigned int dcs4;
169/*36c*/ unsigned int pad14; /* Reserved */
170/*370*/ volatile unsigned int dcd2;
171/*374*/ volatile unsigned int dcd3;
172/*378*/ volatile unsigned int dcd4;
173/*37c*/ unsigned int pad15; /* Reserved */
174/*380*/ volatile unsigned int pattern[32]; /* area Pattern */
175/*400*/ unsigned int pad16[8]; /* Reserved */
176/*420*/ volatile unsigned int reset; /* chip RESET */
177/*424*/ unsigned int pad17[247]; /* Reserved */
178/*800*/ volatile unsigned int devid; /* Device ID */
179/*804*/ unsigned int pad18[63]; /* Reserved */
180/*900*/ volatile unsigned int ucsr; /* User Control & Status Register */
181/*904*/ unsigned int pad19[31]; /* Reserved */
182/*980*/ volatile unsigned int mer; /* Mode Enable Register */
183/*984*/ unsigned int pad20[1439]; /* Reserved */
184} ffb_fbc, *ffb_fbcPtr;
185
186struct ffb_hw_context {
187 int is_2d_only;
188
189 unsigned int ppc;
190 unsigned int wid;
191 unsigned int fg;
192 unsigned int bg;
193 unsigned int consty;
194 unsigned int constz;
195 unsigned int xclip;
196 unsigned int dcss;
197 unsigned int vclipmin;
198 unsigned int vclipmax;
199 unsigned int vclipzmin;
200 unsigned int vclipzmax;
201 unsigned int dcsf;
202 unsigned int dcsb;
203 unsigned int dczf;
204 unsigned int dczb;
205 unsigned int blendc;
206 unsigned int blendc1;
207 unsigned int blendc2;
208 unsigned int fbc;
209 unsigned int rop;
210 unsigned int cmp;
211 unsigned int matchab;
212 unsigned int matchc;
213 unsigned int magnab;
214 unsigned int magnc;
215 unsigned int pmask;
216 unsigned int xpmask;
217 unsigned int ypmask;
218 unsigned int zpmask;
219 unsigned int auxclip0min;
220 unsigned int auxclip0max;
221 unsigned int auxclip1min;
222 unsigned int auxclip1max;
223 unsigned int auxclip2min;
224 unsigned int auxclip2max;
225 unsigned int auxclip3min;
226 unsigned int auxclip3max;
227 unsigned int drawop;
228 unsigned int lpat;
229 unsigned int fontxy;
230 unsigned int fontw;
231 unsigned int fontinc;
232 unsigned int area_pattern[32];
233 unsigned int ucsr;
234 unsigned int stencil;
235 unsigned int stencilctl;
236 unsigned int dcss1;
237 unsigned int dcss2;
238 unsigned int dcss3;
239 unsigned int dcs2;
240 unsigned int dcs3;
241 unsigned int dcs4;
242 unsigned int dcd2;
243 unsigned int dcd3;
244 unsigned int dcd4;
245 unsigned int mer;
246};
247
248#define FFB_MAX_CTXS 32
249
250enum ffb_chip_type {
251 ffb1_prototype = 0, /* Early pre-FCS FFB */
252 ffb1_standard, /* First FCS FFB, 100Mhz UPA, 66MHz gclk */
253 ffb1_speedsort, /* Second FCS FFB, 100Mhz UPA, 75MHz gclk */
254 ffb2_prototype, /* Early pre-FCS vertical FFB2 */
255 ffb2_vertical, /* First FCS FFB2/vertical, 100Mhz UPA, 100MHZ gclk,
256 75(SingleBuffer)/83(DoubleBuffer) MHz fclk */
257 ffb2_vertical_plus, /* Second FCS FFB2/vertical, same timings */
258 ffb2_horizontal, /* First FCS FFB2/horizontal, same timings as FFB2/vert */
259 ffb2_horizontal_plus, /* Second FCS FFB2/horizontal, same timings */
260 afb_m3, /* FCS Elite3D, 3 float chips */
261 afb_m6 /* FCS Elite3D, 6 float chips */
262};
263
264typedef struct ffb_dev_priv {
265 /* Misc software state. */
266 int prom_node;
267 enum ffb_chip_type ffb_type;
268 u64 card_phys_base;
269 struct miscdevice miscdev;
270
271 /* Controller registers. */
272 ffb_fbcPtr regs;
273
274 /* Context table. */
275 struct ffb_hw_context *hw_state[FFB_MAX_CTXS];
276} ffb_dev_priv_t;
277
278extern unsigned long ffb_get_unmapped_area(struct file *filp,
279 unsigned long hint,
280 unsigned long len,
281 unsigned long pgoff,
282 unsigned long flags);
283extern void ffb_set_context_ioctls(void);
284extern drm_ioctl_desc_t DRM(ioctls)[];
285
286extern int ffb_driver_context_switch(drm_device_t *dev, int old, int new);
diff --git a/drivers/char/drm/gamma_context.h b/drivers/char/drm/gamma_context.h
new file mode 100644
index 000000000000..d11b507f87ee
--- /dev/null
+++ b/drivers/char/drm/gamma_context.h
@@ -0,0 +1,492 @@
1/* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
2 * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
3 *
4 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 * ChangeLog:
31 * 2001-11-16 Torsten Duwe <duwe@caldera.de>
32 * added context constructor/destructor hooks,
33 * needed by SiS driver's memory management.
34 */
35
36/* ================================================================
37 * Old-style context support -- only used by gamma.
38 */
39
40
41/* The drm_read and drm_write_string code (especially that which manages
42 the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
43 DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
44
45ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
46{
47 drm_file_t *priv = filp->private_data;
48 drm_device_t *dev = priv->dev;
49 int left;
50 int avail;
51 int send;
52 int cur;
53
54 DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
55
56 while (dev->buf_rp == dev->buf_wp) {
57 DRM_DEBUG(" sleeping\n");
58 if (filp->f_flags & O_NONBLOCK) {
59 return -EAGAIN;
60 }
61 interruptible_sleep_on(&dev->buf_readers);
62 if (signal_pending(current)) {
63 DRM_DEBUG(" interrupted\n");
64 return -ERESTARTSYS;
65 }
66 DRM_DEBUG(" awake\n");
67 }
68
69 left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
70 avail = DRM_BSZ - left;
71 send = DRM_MIN(avail, count);
72
73 while (send) {
74 if (dev->buf_wp > dev->buf_rp) {
75 cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
76 } else {
77 cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
78 }
79 if (copy_to_user(buf, dev->buf_rp, cur))
80 return -EFAULT;
81 dev->buf_rp += cur;
82 if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
83 send -= cur;
84 }
85
86 wake_up_interruptible(&dev->buf_writers);
87 return DRM_MIN(avail, count);
88}
89
90
91/* In an incredibly convoluted setup, the kernel module actually calls
92 * back into the X server to perform context switches on behalf of the
93 * 3d clients.
94 */
95int DRM(write_string)(drm_device_t *dev, const char *s)
96{
97 int left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
98 int send = strlen(s);
99 int count;
100
101 DRM_DEBUG("%d left, %d to send (%p, %p)\n",
102 left, send, dev->buf_rp, dev->buf_wp);
103
104 if (left == 1 || dev->buf_wp != dev->buf_rp) {
105 DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
106 left,
107 dev->buf_wp,
108 dev->buf_rp);
109 }
110
111 while (send) {
112 if (dev->buf_wp >= dev->buf_rp) {
113 count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
114 if (count == left) --count; /* Leave a hole */
115 } else {
116 count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
117 }
118 strncpy(dev->buf_wp, s, count);
119 dev->buf_wp += count;
120 if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
121 send -= count;
122 }
123
124 if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
125
126 DRM_DEBUG("waking\n");
127 wake_up_interruptible(&dev->buf_readers);
128 return 0;
129}
130
131unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait)
132{
133 drm_file_t *priv = filp->private_data;
134 drm_device_t *dev = priv->dev;
135
136 poll_wait(filp, &dev->buf_readers, wait);
137 if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
138 return 0;
139}
140
141int DRM(context_switch)(drm_device_t *dev, int old, int new)
142{
143 char buf[64];
144 drm_queue_t *q;
145
146 if (test_and_set_bit(0, &dev->context_flag)) {
147 DRM_ERROR("Reentering -- FIXME\n");
148 return -EBUSY;
149 }
150
151 DRM_DEBUG("Context switch from %d to %d\n", old, new);
152
153 if (new >= dev->queue_count) {
154 clear_bit(0, &dev->context_flag);
155 return -EINVAL;
156 }
157
158 if (new == dev->last_context) {
159 clear_bit(0, &dev->context_flag);
160 return 0;
161 }
162
163 q = dev->queuelist[new];
164 atomic_inc(&q->use_count);
165 if (atomic_read(&q->use_count) == 1) {
166 atomic_dec(&q->use_count);
167 clear_bit(0, &dev->context_flag);
168 return -EINVAL;
169 }
170
171 /* This causes the X server to wake up & do a bunch of hardware
172 * interaction to actually effect the context switch.
173 */
174 sprintf(buf, "C %d %d\n", old, new);
175 DRM(write_string)(dev, buf);
176
177 atomic_dec(&q->use_count);
178
179 return 0;
180}
181
182int DRM(context_switch_complete)(drm_device_t *dev, int new)
183{
184 drm_device_dma_t *dma = dev->dma;
185
186 dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
187 dev->last_switch = jiffies;
188
189 if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
190 DRM_ERROR("Lock isn't held after context switch\n");
191 }
192
193 if (!dma || !(dma->next_buffer && dma->next_buffer->while_locked)) {
194 if (DRM(lock_free)(dev, &dev->lock.hw_lock->lock,
195 DRM_KERNEL_CONTEXT)) {
196 DRM_ERROR("Cannot free lock\n");
197 }
198 }
199
200 clear_bit(0, &dev->context_flag);
201 wake_up_interruptible(&dev->context_wait);
202
203 return 0;
204}
205
206static int DRM(init_queue)(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx)
207{
208 DRM_DEBUG("\n");
209
210 if (atomic_read(&q->use_count) != 1
211 || atomic_read(&q->finalization)
212 || atomic_read(&q->block_count)) {
213 DRM_ERROR("New queue is already in use: u%d f%d b%d\n",
214 atomic_read(&q->use_count),
215 atomic_read(&q->finalization),
216 atomic_read(&q->block_count));
217 }
218
219 atomic_set(&q->finalization, 0);
220 atomic_set(&q->block_count, 0);
221 atomic_set(&q->block_read, 0);
222 atomic_set(&q->block_write, 0);
223 atomic_set(&q->total_queued, 0);
224 atomic_set(&q->total_flushed, 0);
225 atomic_set(&q->total_locks, 0);
226
227 init_waitqueue_head(&q->write_queue);
228 init_waitqueue_head(&q->read_queue);
229 init_waitqueue_head(&q->flush_queue);
230
231 q->flags = ctx->flags;
232
233 DRM(waitlist_create)(&q->waitlist, dev->dma->buf_count);
234
235 return 0;
236}
237
238
239/* drm_alloc_queue:
240PRE: 1) dev->queuelist[0..dev->queue_count] is allocated and will not
241 disappear (so all deallocation must be done after IOCTLs are off)
242 2) dev->queue_count < dev->queue_slots
243 3) dev->queuelist[i].use_count == 0 and
244 dev->queuelist[i].finalization == 0 if i not in use
245POST: 1) dev->queuelist[i].use_count == 1
246 2) dev->queue_count < dev->queue_slots */
247
248static int DRM(alloc_queue)(drm_device_t *dev)
249{
250 int i;
251 drm_queue_t *queue;
252 int oldslots;
253 int newslots;
254 /* Check for a free queue */
255 for (i = 0; i < dev->queue_count; i++) {
256 atomic_inc(&dev->queuelist[i]->use_count);
257 if (atomic_read(&dev->queuelist[i]->use_count) == 1
258 && !atomic_read(&dev->queuelist[i]->finalization)) {
259 DRM_DEBUG("%d (free)\n", i);
260 return i;
261 }
262 atomic_dec(&dev->queuelist[i]->use_count);
263 }
264 /* Allocate a new queue */
265 down(&dev->struct_sem);
266
267 queue = DRM(alloc)(sizeof(*queue), DRM_MEM_QUEUES);
268 memset(queue, 0, sizeof(*queue));
269 atomic_set(&queue->use_count, 1);
270
271 ++dev->queue_count;
272 if (dev->queue_count >= dev->queue_slots) {
273 oldslots = dev->queue_slots * sizeof(*dev->queuelist);
274 if (!dev->queue_slots) dev->queue_slots = 1;
275 dev->queue_slots *= 2;
276 newslots = dev->queue_slots * sizeof(*dev->queuelist);
277
278 dev->queuelist = DRM(realloc)(dev->queuelist,
279 oldslots,
280 newslots,
281 DRM_MEM_QUEUES);
282 if (!dev->queuelist) {
283 up(&dev->struct_sem);
284 DRM_DEBUG("out of memory\n");
285 return -ENOMEM;
286 }
287 }
288 dev->queuelist[dev->queue_count-1] = queue;
289
290 up(&dev->struct_sem);
291 DRM_DEBUG("%d (new)\n", dev->queue_count - 1);
292 return dev->queue_count - 1;
293}
294
295int DRM(resctx)(struct inode *inode, struct file *filp,
296 unsigned int cmd, unsigned long arg)
297{
298 drm_ctx_res_t __user *argp = (void __user *)arg;
299 drm_ctx_res_t res;
300 drm_ctx_t ctx;
301 int i;
302
303 DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
304 if (copy_from_user(&res, argp, sizeof(res)))
305 return -EFAULT;
306 if (res.count >= DRM_RESERVED_CONTEXTS) {
307 memset(&ctx, 0, sizeof(ctx));
308 for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
309 ctx.handle = i;
310 if (copy_to_user(&res.contexts[i],
311 &i,
312 sizeof(i)))
313 return -EFAULT;
314 }
315 }
316 res.count = DRM_RESERVED_CONTEXTS;
317 if (copy_to_user(argp, &res, sizeof(res)))
318 return -EFAULT;
319 return 0;
320}
321
322int DRM(addctx)(struct inode *inode, struct file *filp,
323 unsigned int cmd, unsigned long arg)
324{
325 drm_file_t *priv = filp->private_data;
326 drm_device_t *dev = priv->dev;
327 drm_ctx_t ctx;
328 drm_ctx_t __user *argp = (void __user *)arg;
329
330 if (copy_from_user(&ctx, argp, sizeof(ctx)))
331 return -EFAULT;
332 if ((ctx.handle = DRM(alloc_queue)(dev)) == DRM_KERNEL_CONTEXT) {
333 /* Init kernel's context and get a new one. */
334 DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
335 ctx.handle = DRM(alloc_queue)(dev);
336 }
337 DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
338 DRM_DEBUG("%d\n", ctx.handle);
339 if (copy_to_user(argp, &ctx, sizeof(ctx)))
340 return -EFAULT;
341 return 0;
342}
343
344int DRM(modctx)(struct inode *inode, struct file *filp,
345 unsigned int cmd, unsigned long arg)
346{
347 drm_file_t *priv = filp->private_data;
348 drm_device_t *dev = priv->dev;
349 drm_ctx_t ctx;
350 drm_queue_t *q;
351
352 if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
353 return -EFAULT;
354
355 DRM_DEBUG("%d\n", ctx.handle);
356
357 if (ctx.handle < 0 || ctx.handle >= dev->queue_count) return -EINVAL;
358 q = dev->queuelist[ctx.handle];
359
360 atomic_inc(&q->use_count);
361 if (atomic_read(&q->use_count) == 1) {
362 /* No longer in use */
363 atomic_dec(&q->use_count);
364 return -EINVAL;
365 }
366
367 if (DRM_BUFCOUNT(&q->waitlist)) {
368 atomic_dec(&q->use_count);
369 return -EBUSY;
370 }
371
372 q->flags = ctx.flags;
373
374 atomic_dec(&q->use_count);
375 return 0;
376}
377
378int DRM(getctx)(struct inode *inode, struct file *filp,
379 unsigned int cmd, unsigned long arg)
380{
381 drm_file_t *priv = filp->private_data;
382 drm_device_t *dev = priv->dev;
383 drm_ctx_t __user *argp = (void __user *)arg;
384 drm_ctx_t ctx;
385 drm_queue_t *q;
386
387 if (copy_from_user(&ctx, argp, sizeof(ctx)))
388 return -EFAULT;
389
390 DRM_DEBUG("%d\n", ctx.handle);
391
392 if (ctx.handle >= dev->queue_count) return -EINVAL;
393 q = dev->queuelist[ctx.handle];
394
395 atomic_inc(&q->use_count);
396 if (atomic_read(&q->use_count) == 1) {
397 /* No longer in use */
398 atomic_dec(&q->use_count);
399 return -EINVAL;
400 }
401
402 ctx.flags = q->flags;
403 atomic_dec(&q->use_count);
404
405 if (copy_to_user(argp, &ctx, sizeof(ctx)))
406 return -EFAULT;
407
408 return 0;
409}
410
411int DRM(switchctx)(struct inode *inode, struct file *filp,
412 unsigned int cmd, unsigned long arg)
413{
414 drm_file_t *priv = filp->private_data;
415 drm_device_t *dev = priv->dev;
416 drm_ctx_t ctx;
417
418 if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
419 return -EFAULT;
420 DRM_DEBUG("%d\n", ctx.handle);
421 return DRM(context_switch)(dev, dev->last_context, ctx.handle);
422}
423
424int DRM(newctx)(struct inode *inode, struct file *filp,
425 unsigned int cmd, unsigned long arg)
426{
427 drm_file_t *priv = filp->private_data;
428 drm_device_t *dev = priv->dev;
429 drm_ctx_t ctx;
430
431 if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
432 return -EFAULT;
433 DRM_DEBUG("%d\n", ctx.handle);
434 DRM(context_switch_complete)(dev, ctx.handle);
435
436 return 0;
437}
438
439int DRM(rmctx)(struct inode *inode, struct file *filp,
440 unsigned int cmd, unsigned long arg)
441{
442 drm_file_t *priv = filp->private_data;
443 drm_device_t *dev = priv->dev;
444 drm_ctx_t ctx;
445 drm_queue_t *q;
446 drm_buf_t *buf;
447
448 if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
449 return -EFAULT;
450 DRM_DEBUG("%d\n", ctx.handle);
451
452 if (ctx.handle >= dev->queue_count) return -EINVAL;
453 q = dev->queuelist[ctx.handle];
454
455 atomic_inc(&q->use_count);
456 if (atomic_read(&q->use_count) == 1) {
457 /* No longer in use */
458 atomic_dec(&q->use_count);
459 return -EINVAL;
460 }
461
462 atomic_inc(&q->finalization); /* Mark queue in finalization state */
463 atomic_sub(2, &q->use_count); /* Mark queue as unused (pending
464 finalization) */
465
466 while (test_and_set_bit(0, &dev->interrupt_flag)) {
467 schedule();
468 if (signal_pending(current)) {
469 clear_bit(0, &dev->interrupt_flag);
470 return -EINTR;
471 }
472 }
473 /* Remove queued buffers */
474 while ((buf = DRM(waitlist_get)(&q->waitlist))) {
475 DRM(free_buffer)(dev, buf);
476 }
477 clear_bit(0, &dev->interrupt_flag);
478
479 /* Wakeup blocked processes */
480 wake_up_interruptible(&q->read_queue);
481 wake_up_interruptible(&q->write_queue);
482 wake_up_interruptible(&q->flush_queue);
483
484 /* Finalization over. Queue is made
485 available when both use_count and
486 finalization become 0, which won't
487 happen until all the waiting processes
488 stop waiting. */
489 atomic_dec(&q->finalization);
490 return 0;
491}
492
diff --git a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c
new file mode 100644
index 000000000000..e486fb8d31e9
--- /dev/null
+++ b/drivers/char/drm/gamma_dma.c
@@ -0,0 +1,946 @@
1/* gamma_dma.c -- DMA support for GMX 2000 -*- linux-c -*-
2 * Created: Fri Mar 19 14:30:16 1999 by faith@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 *
30 */
31
32#include "gamma.h"
33#include "drmP.h"
34#include "drm.h"
35#include "gamma_drm.h"
36#include "gamma_drv.h"
37
38#include <linux/interrupt.h> /* For task queue support */
39#include <linux/delay.h>
40
41static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address,
42 unsigned long length)
43{
44 drm_gamma_private_t *dev_priv =
45 (drm_gamma_private_t *)dev->dev_private;
46 mb();
47 while ( GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
48 cpu_relax();
49
50 GAMMA_WRITE(GAMMA_DMAADDRESS, address);
51
52 while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4)
53 cpu_relax();
54
55 GAMMA_WRITE(GAMMA_DMACOUNT, length / 4);
56}
57
58void gamma_dma_quiescent_single(drm_device_t *dev)
59{
60 drm_gamma_private_t *dev_priv =
61 (drm_gamma_private_t *)dev->dev_private;
62 while (GAMMA_READ(GAMMA_DMACOUNT))
63 cpu_relax();
64
65 while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
66 cpu_relax();
67
68 GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
69 GAMMA_WRITE(GAMMA_SYNC, 0);
70
71 do {
72 while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
73 cpu_relax();
74 } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
75}
76
77void gamma_dma_quiescent_dual(drm_device_t *dev)
78{
79 drm_gamma_private_t *dev_priv =
80 (drm_gamma_private_t *)dev->dev_private;
81 while (GAMMA_READ(GAMMA_DMACOUNT))
82 cpu_relax();
83
84 while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
85 cpu_relax();
86
87 GAMMA_WRITE(GAMMA_BROADCASTMASK, 3);
88 GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
89 GAMMA_WRITE(GAMMA_SYNC, 0);
90
91 /* Read from first MX */
92 do {
93 while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
94 cpu_relax();
95 } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
96
97 /* Read from second MX */
98 do {
99 while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000))
100 cpu_relax();
101 } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG);
102}
103
104void gamma_dma_ready(drm_device_t *dev)
105{
106 drm_gamma_private_t *dev_priv =
107 (drm_gamma_private_t *)dev->dev_private;
108 while (GAMMA_READ(GAMMA_DMACOUNT))
109 cpu_relax();
110}
111
112static inline int gamma_dma_is_ready(drm_device_t *dev)
113{
114 drm_gamma_private_t *dev_priv =
115 (drm_gamma_private_t *)dev->dev_private;
116 return (!GAMMA_READ(GAMMA_DMACOUNT));
117}
118
119irqreturn_t gamma_driver_irq_handler( DRM_IRQ_ARGS )
120{
121 drm_device_t *dev = (drm_device_t *)arg;
122 drm_device_dma_t *dma = dev->dma;
123 drm_gamma_private_t *dev_priv =
124 (drm_gamma_private_t *)dev->dev_private;
125
126 /* FIXME: should check whether we're actually interested in the interrupt? */
127 atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */
128
129 while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
130 cpu_relax();
131
132 GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */
133 GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8);
134 GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001);
135 if (gamma_dma_is_ready(dev)) {
136 /* Free previous buffer */
137 if (test_and_set_bit(0, &dev->dma_flag))
138 return IRQ_HANDLED;
139 if (dma->this_buffer) {
140 gamma_free_buffer(dev, dma->this_buffer);
141 dma->this_buffer = NULL;
142 }
143 clear_bit(0, &dev->dma_flag);
144
145 /* Dispatch new buffer */
146 schedule_work(&dev->work);
147 }
148 return IRQ_HANDLED;
149}
150
151/* Only called by gamma_dma_schedule. */
152static int gamma_do_dma(drm_device_t *dev, int locked)
153{
154 unsigned long address;
155 unsigned long length;
156 drm_buf_t *buf;
157 int retcode = 0;
158 drm_device_dma_t *dma = dev->dma;
159
160 if (test_and_set_bit(0, &dev->dma_flag)) return -EBUSY;
161
162
163 if (!dma->next_buffer) {
164 DRM_ERROR("No next_buffer\n");
165 clear_bit(0, &dev->dma_flag);
166 return -EINVAL;
167 }
168
169 buf = dma->next_buffer;
170 /* WE NOW ARE ON LOGICAL PAGES!! - using page table setup in dma_init */
171 /* So we pass the buffer index value into the physical page offset */
172 address = buf->idx << 12;
173 length = buf->used;
174
175 DRM_DEBUG("context %d, buffer %d (%ld bytes)\n",
176 buf->context, buf->idx, length);
177
178 if (buf->list == DRM_LIST_RECLAIM) {
179 gamma_clear_next_buffer(dev);
180 gamma_free_buffer(dev, buf);
181 clear_bit(0, &dev->dma_flag);
182 return -EINVAL;
183 }
184
185 if (!length) {
186 DRM_ERROR("0 length buffer\n");
187 gamma_clear_next_buffer(dev);
188 gamma_free_buffer(dev, buf);
189 clear_bit(0, &dev->dma_flag);
190 return 0;
191 }
192
193 if (!gamma_dma_is_ready(dev)) {
194 clear_bit(0, &dev->dma_flag);
195 return -EBUSY;
196 }
197
198 if (buf->while_locked) {
199 if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
200 DRM_ERROR("Dispatching buffer %d from pid %d"
201 " \"while locked\", but no lock held\n",
202 buf->idx, current->pid);
203 }
204 } else {
205 if (!locked && !gamma_lock_take(&dev->lock.hw_lock->lock,
206 DRM_KERNEL_CONTEXT)) {
207 clear_bit(0, &dev->dma_flag);
208 return -EBUSY;
209 }
210 }
211
212 if (dev->last_context != buf->context
213 && !(dev->queuelist[buf->context]->flags
214 & _DRM_CONTEXT_PRESERVED)) {
215 /* PRE: dev->last_context != buf->context */
216 if (DRM(context_switch)(dev, dev->last_context,
217 buf->context)) {
218 DRM(clear_next_buffer)(dev);
219 DRM(free_buffer)(dev, buf);
220 }
221 retcode = -EBUSY;
222 goto cleanup;
223
224 /* POST: we will wait for the context
225 switch and will dispatch on a later call
226 when dev->last_context == buf->context.
227 NOTE WE HOLD THE LOCK THROUGHOUT THIS
228 TIME! */
229 }
230
231 gamma_clear_next_buffer(dev);
232 buf->pending = 1;
233 buf->waiting = 0;
234 buf->list = DRM_LIST_PEND;
235
236 /* WE NOW ARE ON LOGICAL PAGES!!! - overriding address */
237 address = buf->idx << 12;
238
239 gamma_dma_dispatch(dev, address, length);
240 gamma_free_buffer(dev, dma->this_buffer);
241 dma->this_buffer = buf;
242
243 atomic_inc(&dev->counts[7]); /* _DRM_STAT_DMA */
244 atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
245
246 if (!buf->while_locked && !dev->context_flag && !locked) {
247 if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
248 DRM_KERNEL_CONTEXT)) {
249 DRM_ERROR("\n");
250 }
251 }
252cleanup:
253
254 clear_bit(0, &dev->dma_flag);
255
256
257 return retcode;
258}
259
260static void gamma_dma_timer_bh(unsigned long dev)
261{
262 gamma_dma_schedule((drm_device_t *)dev, 0);
263}
264
265void gamma_irq_immediate_bh(void *dev)
266{
267 gamma_dma_schedule(dev, 0);
268}
269
270int gamma_dma_schedule(drm_device_t *dev, int locked)
271{
272 int next;
273 drm_queue_t *q;
274 drm_buf_t *buf;
275 int retcode = 0;
276 int processed = 0;
277 int missed;
278 int expire = 20;
279 drm_device_dma_t *dma = dev->dma;
280
281 if (test_and_set_bit(0, &dev->interrupt_flag)) {
282 /* Not reentrant */
283 atomic_inc(&dev->counts[10]); /* _DRM_STAT_MISSED */
284 return -EBUSY;
285 }
286 missed = atomic_read(&dev->counts[10]);
287
288
289again:
290 if (dev->context_flag) {
291 clear_bit(0, &dev->interrupt_flag);
292 return -EBUSY;
293 }
294 if (dma->next_buffer) {
295 /* Unsent buffer that was previously
296 selected, but that couldn't be sent
297 because the lock could not be obtained
298 or the DMA engine wasn't ready. Try
299 again. */
300 if (!(retcode = gamma_do_dma(dev, locked))) ++processed;
301 } else {
302 do {
303 next = gamma_select_queue(dev, gamma_dma_timer_bh);
304 if (next >= 0) {
305 q = dev->queuelist[next];
306 buf = gamma_waitlist_get(&q->waitlist);
307 dma->next_buffer = buf;
308 dma->next_queue = q;
309 if (buf && buf->list == DRM_LIST_RECLAIM) {
310 gamma_clear_next_buffer(dev);
311 gamma_free_buffer(dev, buf);
312 }
313 }
314 } while (next >= 0 && !dma->next_buffer);
315 if (dma->next_buffer) {
316 if (!(retcode = gamma_do_dma(dev, locked))) {
317 ++processed;
318 }
319 }
320 }
321
322 if (--expire) {
323 if (missed != atomic_read(&dev->counts[10])) {
324 if (gamma_dma_is_ready(dev)) goto again;
325 }
326 if (processed && gamma_dma_is_ready(dev)) {
327 processed = 0;
328 goto again;
329 }
330 }
331
332 clear_bit(0, &dev->interrupt_flag);
333
334 return retcode;
335}
336
337static int gamma_dma_priority(struct file *filp,
338 drm_device_t *dev, drm_dma_t *d)
339{
340 unsigned long address;
341 unsigned long length;
342 int must_free = 0;
343 int retcode = 0;
344 int i;
345 int idx;
346 drm_buf_t *buf;
347 drm_buf_t *last_buf = NULL;
348 drm_device_dma_t *dma = dev->dma;
349 int *send_indices = NULL;
350 int *send_sizes = NULL;
351
352 DECLARE_WAITQUEUE(entry, current);
353
354 /* Turn off interrupt handling */
355 while (test_and_set_bit(0, &dev->interrupt_flag)) {
356 schedule();
357 if (signal_pending(current)) return -EINTR;
358 }
359 if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) {
360 while (!gamma_lock_take(&dev->lock.hw_lock->lock,
361 DRM_KERNEL_CONTEXT)) {
362 schedule();
363 if (signal_pending(current)) {
364 clear_bit(0, &dev->interrupt_flag);
365 return -EINTR;
366 }
367 }
368 ++must_free;
369 }
370
371 send_indices = DRM(alloc)(d->send_count * sizeof(*send_indices),
372 DRM_MEM_DRIVER);
373 if (send_indices == NULL)
374 return -ENOMEM;
375 if (copy_from_user(send_indices, d->send_indices,
376 d->send_count * sizeof(*send_indices))) {
377 retcode = -EFAULT;
378 goto cleanup;
379 }
380
381 send_sizes = DRM(alloc)(d->send_count * sizeof(*send_sizes),
382 DRM_MEM_DRIVER);
383 if (send_sizes == NULL)
384 return -ENOMEM;
385 if (copy_from_user(send_sizes, d->send_sizes,
386 d->send_count * sizeof(*send_sizes))) {
387 retcode = -EFAULT;
388 goto cleanup;
389 }
390
391 for (i = 0; i < d->send_count; i++) {
392 idx = send_indices[i];
393 if (idx < 0 || idx >= dma->buf_count) {
394 DRM_ERROR("Index %d (of %d max)\n",
395 send_indices[i], dma->buf_count - 1);
396 continue;
397 }
398 buf = dma->buflist[ idx ];
399 if (buf->filp != filp) {
400 DRM_ERROR("Process %d using buffer not owned\n",
401 current->pid);
402 retcode = -EINVAL;
403 goto cleanup;
404 }
405 if (buf->list != DRM_LIST_NONE) {
406 DRM_ERROR("Process %d using buffer on list %d\n",
407 current->pid, buf->list);
408 retcode = -EINVAL;
409 goto cleanup;
410 }
411 /* This isn't a race condition on
412 buf->list, since our concern is the
413 buffer reclaim during the time the
414 process closes the /dev/drm? handle, so
415 it can't also be doing DMA. */
416 buf->list = DRM_LIST_PRIO;
417 buf->used = send_sizes[i];
418 buf->context = d->context;
419 buf->while_locked = d->flags & _DRM_DMA_WHILE_LOCKED;
420 address = (unsigned long)buf->address;
421 length = buf->used;
422 if (!length) {
423 DRM_ERROR("0 length buffer\n");
424 }
425 if (buf->pending) {
426 DRM_ERROR("Sending pending buffer:"
427 " buffer %d, offset %d\n",
428 send_indices[i], i);
429 retcode = -EINVAL;
430 goto cleanup;
431 }
432 if (buf->waiting) {
433 DRM_ERROR("Sending waiting buffer:"
434 " buffer %d, offset %d\n",
435 send_indices[i], i);
436 retcode = -EINVAL;
437 goto cleanup;
438 }
439 buf->pending = 1;
440
441 if (dev->last_context != buf->context
442 && !(dev->queuelist[buf->context]->flags
443 & _DRM_CONTEXT_PRESERVED)) {
444 add_wait_queue(&dev->context_wait, &entry);
445 current->state = TASK_INTERRUPTIBLE;
446 /* PRE: dev->last_context != buf->context */
447 DRM(context_switch)(dev, dev->last_context,
448 buf->context);
449 /* POST: we will wait for the context
450 switch and will dispatch on a later call
451 when dev->last_context == buf->context.
452 NOTE WE HOLD THE LOCK THROUGHOUT THIS
453 TIME! */
454 schedule();
455 current->state = TASK_RUNNING;
456 remove_wait_queue(&dev->context_wait, &entry);
457 if (signal_pending(current)) {
458 retcode = -EINTR;
459 goto cleanup;
460 }
461 if (dev->last_context != buf->context) {
462 DRM_ERROR("Context mismatch: %d %d\n",
463 dev->last_context,
464 buf->context);
465 }
466 }
467
468 gamma_dma_dispatch(dev, address, length);
469 atomic_inc(&dev->counts[9]); /* _DRM_STAT_SPECIAL */
470 atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
471
472 if (last_buf) {
473 gamma_free_buffer(dev, last_buf);
474 }
475 last_buf = buf;
476 }
477
478
479cleanup:
480 if (last_buf) {
481 gamma_dma_ready(dev);
482 gamma_free_buffer(dev, last_buf);
483 }
484 if (send_indices)
485 DRM(free)(send_indices, d->send_count * sizeof(*send_indices),
486 DRM_MEM_DRIVER);
487 if (send_sizes)
488 DRM(free)(send_sizes, d->send_count * sizeof(*send_sizes),
489 DRM_MEM_DRIVER);
490
491 if (must_free && !dev->context_flag) {
492 if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
493 DRM_KERNEL_CONTEXT)) {
494 DRM_ERROR("\n");
495 }
496 }
497 clear_bit(0, &dev->interrupt_flag);
498 return retcode;
499}
500
501static int gamma_dma_send_buffers(struct file *filp,
502 drm_device_t *dev, drm_dma_t *d)
503{
504 DECLARE_WAITQUEUE(entry, current);
505 drm_buf_t *last_buf = NULL;
506 int retcode = 0;
507 drm_device_dma_t *dma = dev->dma;
508 int send_index;
509
510 if (get_user(send_index, &d->send_indices[d->send_count-1]))
511 return -EFAULT;
512
513 if (d->flags & _DRM_DMA_BLOCK) {
514 last_buf = dma->buflist[send_index];
515 add_wait_queue(&last_buf->dma_wait, &entry);
516 }
517
518 if ((retcode = gamma_dma_enqueue(filp, d))) {
519 if (d->flags & _DRM_DMA_BLOCK)
520 remove_wait_queue(&last_buf->dma_wait, &entry);
521 return retcode;
522 }
523
524 gamma_dma_schedule(dev, 0);
525
526 if (d->flags & _DRM_DMA_BLOCK) {
527 DRM_DEBUG("%d waiting\n", current->pid);
528 for (;;) {
529 current->state = TASK_INTERRUPTIBLE;
530 if (!last_buf->waiting && !last_buf->pending)
531 break; /* finished */
532 schedule();
533 if (signal_pending(current)) {
534 retcode = -EINTR; /* Can't restart */
535 break;
536 }
537 }
538 current->state = TASK_RUNNING;
539 DRM_DEBUG("%d running\n", current->pid);
540 remove_wait_queue(&last_buf->dma_wait, &entry);
541 if (!retcode
542 || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) {
543 if (!waitqueue_active(&last_buf->dma_wait)) {
544 gamma_free_buffer(dev, last_buf);
545 }
546 }
547 if (retcode) {
548 DRM_ERROR("ctx%d w%d p%d c%ld i%d l%d pid:%d\n",
549 d->context,
550 last_buf->waiting,
551 last_buf->pending,
552 (long)DRM_WAITCOUNT(dev, d->context),
553 last_buf->idx,
554 last_buf->list,
555 current->pid);
556 }
557 }
558 return retcode;
559}
560
561int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd,
562 unsigned long arg)
563{
564 drm_file_t *priv = filp->private_data;
565 drm_device_t *dev = priv->dev;
566 drm_device_dma_t *dma = dev->dma;
567 int retcode = 0;
568 drm_dma_t __user *argp = (void __user *)arg;
569 drm_dma_t d;
570
571 if (copy_from_user(&d, argp, sizeof(d)))
572 return -EFAULT;
573
574 if (d.send_count < 0 || d.send_count > dma->buf_count) {
575 DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
576 current->pid, d.send_count, dma->buf_count);
577 return -EINVAL;
578 }
579
580 if (d.request_count < 0 || d.request_count > dma->buf_count) {
581 DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
582 current->pid, d.request_count, dma->buf_count);
583 return -EINVAL;
584 }
585
586 if (d.send_count) {
587 if (d.flags & _DRM_DMA_PRIORITY)
588 retcode = gamma_dma_priority(filp, dev, &d);
589 else
590 retcode = gamma_dma_send_buffers(filp, dev, &d);
591 }
592
593 d.granted_count = 0;
594
595 if (!retcode && d.request_count) {
596 retcode = gamma_dma_get_buffers(filp, &d);
597 }
598
599 DRM_DEBUG("%d returning, granted = %d\n",
600 current->pid, d.granted_count);
601 if (copy_to_user(argp, &d, sizeof(d)))
602 return -EFAULT;
603
604 return retcode;
605}
606
607/* =============================================================
608 * DMA initialization, cleanup
609 */
610
611static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
612{
613 drm_gamma_private_t *dev_priv;
614 drm_device_dma_t *dma = dev->dma;
615 drm_buf_t *buf;
616 int i;
617 struct list_head *list;
618 unsigned long *pgt;
619
620 DRM_DEBUG( "%s\n", __FUNCTION__ );
621
622 dev_priv = DRM(alloc)( sizeof(drm_gamma_private_t),
623 DRM_MEM_DRIVER );
624 if ( !dev_priv )
625 return -ENOMEM;
626
627 dev->dev_private = (void *)dev_priv;
628
629 memset( dev_priv, 0, sizeof(drm_gamma_private_t) );
630
631 dev_priv->num_rast = init->num_rast;
632
633 list_for_each(list, &dev->maplist->head) {
634 drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
635 if( r_list->map &&
636 r_list->map->type == _DRM_SHM &&
637 r_list->map->flags & _DRM_CONTAINS_LOCK ) {
638 dev_priv->sarea = r_list->map;
639 break;
640 }
641 }
642
643 dev_priv->mmio0 = drm_core_findmap(dev, init->mmio0);
644 dev_priv->mmio1 = drm_core_findmap(dev, init->mmio1);
645 dev_priv->mmio2 = drm_core_findmap(dev, init->mmio2);
646 dev_priv->mmio3 = drm_core_findmap(dev, init->mmio3);
647
648 dev_priv->sarea_priv = (drm_gamma_sarea_t *)
649 ((u8 *)dev_priv->sarea->handle +
650 init->sarea_priv_offset);
651
652 if (init->pcimode) {
653 buf = dma->buflist[GLINT_DRI_BUF_COUNT];
654 pgt = buf->address;
655
656 for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
657 buf = dma->buflist[i];
658 *pgt = virt_to_phys((void*)buf->address) | 0x07;
659 pgt++;
660 }
661
662 buf = dma->buflist[GLINT_DRI_BUF_COUNT];
663 } else {
664 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
665 drm_core_ioremap( dev->agp_buffer_map, dev);
666
667 buf = dma->buflist[GLINT_DRI_BUF_COUNT];
668 pgt = buf->address;
669
670 for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
671 buf = dma->buflist[i];
672 *pgt = (unsigned long)buf->address + 0x07;
673 pgt++;
674 }
675
676 buf = dma->buflist[GLINT_DRI_BUF_COUNT];
677
678 while (GAMMA_READ(GAMMA_INFIFOSPACE) < 1);
679 GAMMA_WRITE( GAMMA_GDMACONTROL, 0xe);
680 }
681 while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
682 GAMMA_WRITE( GAMMA_PAGETABLEADDR, virt_to_phys((void*)buf->address) );
683 GAMMA_WRITE( GAMMA_PAGETABLELENGTH, 2 );
684
685 return 0;
686}
687
688int gamma_do_cleanup_dma( drm_device_t *dev )
689{
690 DRM_DEBUG( "%s\n", __FUNCTION__ );
691
692 /* Make sure interrupts are disabled here because the uninstall ioctl
693 * may not have been called from userspace and after dev_private
694 * is freed, it's too late.
695 */
696 if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
697 if ( dev->irq_enabled )
698 DRM(irq_uninstall)(dev);
699
700 if ( dev->dev_private ) {
701
702 if ( dev->agp_buffer_map != NULL )
703 drm_core_ioremapfree( dev->agp_buffer_map, dev );
704
705 DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),
706 DRM_MEM_DRIVER );
707 dev->dev_private = NULL;
708 }
709
710 return 0;
711}
712
713int gamma_dma_init( struct inode *inode, struct file *filp,
714 unsigned int cmd, unsigned long arg )
715{
716 drm_file_t *priv = filp->private_data;
717 drm_device_t *dev = priv->dev;
718 drm_gamma_init_t init;
719
720 LOCK_TEST_WITH_RETURN( dev, filp );
721
722 if ( copy_from_user( &init, (drm_gamma_init_t __user *)arg, sizeof(init) ) )
723 return -EFAULT;
724
725 switch ( init.func ) {
726 case GAMMA_INIT_DMA:
727 return gamma_do_init_dma( dev, &init );
728 case GAMMA_CLEANUP_DMA:
729 return gamma_do_cleanup_dma( dev );
730 }
731
732 return -EINVAL;
733}
734
735static int gamma_do_copy_dma( drm_device_t *dev, drm_gamma_copy_t *copy )
736{
737 drm_device_dma_t *dma = dev->dma;
738 unsigned int *screenbuf;
739
740 DRM_DEBUG( "%s\n", __FUNCTION__ );
741
742 /* We've DRM_RESTRICTED this DMA buffer */
743
744 screenbuf = dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ]->address;
745
746#if 0
747 *buffer++ = 0x180; /* Tag (FilterMode) */
748 *buffer++ = 0x200; /* Allow FBColor through */
749 *buffer++ = 0x53B; /* Tag */
750 *buffer++ = copy->Pitch;
751 *buffer++ = 0x53A; /* Tag */
752 *buffer++ = copy->SrcAddress;
753 *buffer++ = 0x539; /* Tag */
754 *buffer++ = copy->WidthHeight; /* Initiates transfer */
755 *buffer++ = 0x53C; /* Tag - DMAOutputAddress */
756 *buffer++ = virt_to_phys((void*)screenbuf);
757 *buffer++ = 0x53D; /* Tag - DMAOutputCount */
758 *buffer++ = copy->Count; /* Reads HostOutFifo BLOCKS until ..*/
759
760 /* Data now sitting in dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ] */
761 /* Now put it back to the screen */
762
763 *buffer++ = 0x180; /* Tag (FilterMode) */
764 *buffer++ = 0x400; /* Allow Sync through */
765 *buffer++ = 0x538; /* Tag - DMARectangleReadTarget */
766 *buffer++ = 0x155; /* FBSourceData | count */
767 *buffer++ = 0x537; /* Tag */
768 *buffer++ = copy->Pitch;
769 *buffer++ = 0x536; /* Tag */
770 *buffer++ = copy->DstAddress;
771 *buffer++ = 0x535; /* Tag */
772 *buffer++ = copy->WidthHeight; /* Initiates transfer */
773 *buffer++ = 0x530; /* Tag - DMAAddr */
774 *buffer++ = virt_to_phys((void*)screenbuf);
775 *buffer++ = 0x531;
776 *buffer++ = copy->Count; /* initiates DMA transfer of color data */
777#endif
778
779 /* need to dispatch it now */
780
781 return 0;
782}
783
784int gamma_dma_copy( struct inode *inode, struct file *filp,
785 unsigned int cmd, unsigned long arg )
786{
787 drm_file_t *priv = filp->private_data;
788 drm_device_t *dev = priv->dev;
789 drm_gamma_copy_t copy;
790
791 if ( copy_from_user( &copy, (drm_gamma_copy_t __user *)arg, sizeof(copy) ) )
792 return -EFAULT;
793
794 return gamma_do_copy_dma( dev, &copy );
795}
796
797/* =============================================================
798 * Per Context SAREA Support
799 */
800
801int gamma_getsareactx(struct inode *inode, struct file *filp,
802 unsigned int cmd, unsigned long arg)
803{
804 drm_file_t *priv = filp->private_data;
805 drm_device_t *dev = priv->dev;
806 drm_ctx_priv_map_t __user *argp = (void __user *)arg;
807 drm_ctx_priv_map_t request;
808 drm_map_t *map;
809
810 if (copy_from_user(&request, argp, sizeof(request)))
811 return -EFAULT;
812
813 down(&dev->struct_sem);
814 if ((int)request.ctx_id >= dev->max_context) {
815 up(&dev->struct_sem);
816 return -EINVAL;
817 }
818
819 map = dev->context_sareas[request.ctx_id];
820 up(&dev->struct_sem);
821
822 request.handle = map->handle;
823 if (copy_to_user(argp, &request, sizeof(request)))
824 return -EFAULT;
825 return 0;
826}
827
828int gamma_setsareactx(struct inode *inode, struct file *filp,
829 unsigned int cmd, unsigned long arg)
830{
831 drm_file_t *priv = filp->private_data;
832 drm_device_t *dev = priv->dev;
833 drm_ctx_priv_map_t request;
834 drm_map_t *map = NULL;
835 drm_map_list_t *r_list;
836 struct list_head *list;
837
838 if (copy_from_user(&request,
839 (drm_ctx_priv_map_t __user *)arg,
840 sizeof(request)))
841 return -EFAULT;
842
843 down(&dev->struct_sem);
844 r_list = NULL;
845 list_for_each(list, &dev->maplist->head) {
846 r_list = list_entry(list, drm_map_list_t, head);
847 if(r_list->map &&
848 r_list->map->handle == request.handle) break;
849 }
850 if (list == &(dev->maplist->head)) {
851 up(&dev->struct_sem);
852 return -EINVAL;
853 }
854 map = r_list->map;
855 up(&dev->struct_sem);
856
857 if (!map) return -EINVAL;
858
859 down(&dev->struct_sem);
860 if ((int)request.ctx_id >= dev->max_context) {
861 up(&dev->struct_sem);
862 return -EINVAL;
863 }
864 dev->context_sareas[request.ctx_id] = map;
865 up(&dev->struct_sem);
866 return 0;
867}
868
869void gamma_driver_irq_preinstall( drm_device_t *dev ) {
870 drm_gamma_private_t *dev_priv =
871 (drm_gamma_private_t *)dev->dev_private;
872
873 while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
874 cpu_relax();
875
876 GAMMA_WRITE( GAMMA_GCOMMANDMODE, 0x00000004 );
877 GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 );
878}
879
880void gamma_driver_irq_postinstall( drm_device_t *dev ) {
881 drm_gamma_private_t *dev_priv =
882 (drm_gamma_private_t *)dev->dev_private;
883
884 while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
885 cpu_relax();
886
887 GAMMA_WRITE( GAMMA_GINTENABLE, 0x00002001 );
888 GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000008 );
889 GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00039090 );
890}
891
892void gamma_driver_irq_uninstall( drm_device_t *dev ) {
893 drm_gamma_private_t *dev_priv =
894 (drm_gamma_private_t *)dev->dev_private;
895 if (!dev_priv)
896 return;
897
898 while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
899 cpu_relax();
900
901 GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00000000 );
902 GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000000 );
903 GAMMA_WRITE( GAMMA_GINTENABLE, 0x00000000 );
904}
905
906extern drm_ioctl_desc_t DRM(ioctls)[];
907
908static int gamma_driver_preinit(drm_device_t *dev)
909{
910 /* reset the finish ioctl */
911 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_FINISH)].func = DRM(finish);
912 return 0;
913}
914
915static void gamma_driver_pretakedown(drm_device_t *dev)
916{
917 gamma_do_cleanup_dma(dev);
918}
919
920static void gamma_driver_dma_ready(drm_device_t *dev)
921{
922 gamma_dma_ready(dev);
923}
924
925static int gamma_driver_dma_quiescent(drm_device_t *dev)
926{
927 drm_gamma_private_t *dev_priv = (
928 drm_gamma_private_t *)dev->dev_private;
929 if (dev_priv->num_rast == 2)
930 gamma_dma_quiescent_dual(dev);
931 else gamma_dma_quiescent_single(dev);
932 return 0;
933}
934
935void gamma_driver_register_fns(drm_device_t *dev)
936{
937 dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
938 DRM(fops).read = gamma_fops_read;
939 DRM(fops).poll = gamma_fops_poll;
940 dev->driver.preinit = gamma_driver_preinit;
941 dev->driver.pretakedown = gamma_driver_pretakedown;
942 dev->driver.dma_ready = gamma_driver_dma_ready;
943 dev->driver.dma_quiescent = gamma_driver_dma_quiescent;
944 dev->driver.dma_flush_block_and_flush = gamma_flush_block_and_flush;
945 dev->driver.dma_flush_unblock = gamma_flush_unblock;
946}
diff --git a/drivers/char/drm/gamma_drm.h b/drivers/char/drm/gamma_drm.h
new file mode 100644
index 000000000000..20819ded0e15
--- /dev/null
+++ b/drivers/char/drm/gamma_drm.h
@@ -0,0 +1,90 @@
1#ifndef _GAMMA_DRM_H_
2#define _GAMMA_DRM_H_
3
4typedef struct _drm_gamma_tex_region {
5 unsigned char next, prev; /* indices to form a circular LRU */
6 unsigned char in_use; /* owned by a client, or free? */
7 int age; /* tracked by clients to update local LRU's */
8} drm_gamma_tex_region_t;
9
10typedef struct {
11 unsigned int GDeltaMode;
12 unsigned int GDepthMode;
13 unsigned int GGeometryMode;
14 unsigned int GTransformMode;
15} drm_gamma_context_regs_t;
16
17typedef struct _drm_gamma_sarea {
18 drm_gamma_context_regs_t context_state;
19
20 unsigned int dirty;
21
22
23 /* Maintain an LRU of contiguous regions of texture space. If
24 * you think you own a region of texture memory, and it has an
25 * age different to the one you set, then you are mistaken and
26 * it has been stolen by another client. If global texAge
27 * hasn't changed, there is no need to walk the list.
28 *
29 * These regions can be used as a proxy for the fine-grained
30 * texture information of other clients - by maintaining them
31 * in the same lru which is used to age their own textures,
32 * clients have an approximate lru for the whole of global
33 * texture space, and can make informed decisions as to which
34 * areas to kick out. There is no need to choose whether to
35 * kick out your own texture or someone else's - simply eject
36 * them all in LRU order.
37 */
38
39#define GAMMA_NR_TEX_REGIONS 64
40 drm_gamma_tex_region_t texList[GAMMA_NR_TEX_REGIONS+1];
41 /* Last elt is sentinal */
42 int texAge; /* last time texture was uploaded */
43 int last_enqueue; /* last time a buffer was enqueued */
44 int last_dispatch; /* age of the most recently dispatched buffer */
45 int last_quiescent; /* */
46 int ctxOwner; /* last context to upload state */
47
48 int vertex_prim;
49} drm_gamma_sarea_t;
50
51/* WARNING: If you change any of these defines, make sure to change the
52 * defines in the Xserver file (xf86drmGamma.h)
53 */
54
55/* Gamma specific ioctls
56 * The device specific ioctl range is 0x40 to 0x79.
57 */
58#define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t)
59#define DRM_IOCTL_GAMMA_COPY DRM_IOW( 0x41, drm_gamma_copy_t)
60
61typedef struct drm_gamma_copy {
62 unsigned int DMAOutputAddress;
63 unsigned int DMAOutputCount;
64 unsigned int DMAReadGLINTSource;
65 unsigned int DMARectangleWriteAddress;
66 unsigned int DMARectangleWriteLinePitch;
67 unsigned int DMARectangleWrite;
68 unsigned int DMARectangleReadAddress;
69 unsigned int DMARectangleReadLinePitch;
70 unsigned int DMARectangleRead;
71 unsigned int DMARectangleReadTarget;
72} drm_gamma_copy_t;
73
74typedef struct drm_gamma_init {
75 enum {
76 GAMMA_INIT_DMA = 0x01,
77 GAMMA_CLEANUP_DMA = 0x02
78 } func;
79
80 int sarea_priv_offset;
81 int pcimode;
82 unsigned int mmio0;
83 unsigned int mmio1;
84 unsigned int mmio2;
85 unsigned int mmio3;
86 unsigned int buffers_offset;
87 int num_rast;
88} drm_gamma_init_t;
89
90#endif /* _GAMMA_DRM_H_ */
diff --git a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c
new file mode 100644
index 000000000000..e7e64b62792a
--- /dev/null
+++ b/drivers/char/drm/gamma_drv.c
@@ -0,0 +1,59 @@
1/* gamma.c -- 3dlabs GMX 2000 driver -*- linux-c -*-
2 * Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 */
31
32#include <linux/config.h>
33#include "gamma.h"
34#include "drmP.h"
35#include "drm.h"
36#include "gamma_drm.h"
37#include "gamma_drv.h"
38
39#include "drm_auth.h"
40#include "drm_agpsupport.h"
41#include "drm_bufs.h"
42#include "gamma_context.h" /* NOTE! */
43#include "drm_dma.h"
44#include "gamma_old_dma.h" /* NOTE */
45#include "drm_drawable.h"
46#include "drm_drv.h"
47
48#include "drm_fops.h"
49#include "drm_init.h"
50#include "drm_ioctl.h"
51#include "drm_irq.h"
52#include "gamma_lists.h" /* NOTE */
53#include "drm_lock.h"
54#include "gamma_lock.h" /* NOTE */
55#include "drm_memory.h"
56#include "drm_proc.h"
57#include "drm_vm.h"
58#include "drm_stub.h"
59#include "drm_scatter.h"
diff --git a/drivers/char/drm/gamma_drv.h b/drivers/char/drm/gamma_drv.h
new file mode 100644
index 000000000000..146fcc6253cd
--- /dev/null
+++ b/drivers/char/drm/gamma_drv.h
@@ -0,0 +1,147 @@
1/* gamma_drv.h -- Private header for 3dlabs GMX 2000 driver -*- linux-c -*-
2 * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 *
30 */
31
32#ifndef _GAMMA_DRV_H_
33#define _GAMMA_DRV_H_
34
35typedef struct drm_gamma_private {
36 drm_gamma_sarea_t *sarea_priv;
37 drm_map_t *sarea;
38 drm_map_t *mmio0;
39 drm_map_t *mmio1;
40 drm_map_t *mmio2;
41 drm_map_t *mmio3;
42 int num_rast;
43} drm_gamma_private_t;
44
45 /* gamma_dma.c */
46extern int gamma_dma_init( struct inode *inode, struct file *filp,
47 unsigned int cmd, unsigned long arg );
48extern int gamma_dma_copy( struct inode *inode, struct file *filp,
49 unsigned int cmd, unsigned long arg );
50
51extern int gamma_do_cleanup_dma( drm_device_t *dev );
52extern void gamma_dma_ready(drm_device_t *dev);
53extern void gamma_dma_quiescent_single(drm_device_t *dev);
54extern void gamma_dma_quiescent_dual(drm_device_t *dev);
55
56 /* gamma_dma.c */
57extern int gamma_dma_schedule(drm_device_t *dev, int locked);
58extern int gamma_dma(struct inode *inode, struct file *filp,
59 unsigned int cmd, unsigned long arg);
60extern int gamma_find_devices(void);
61extern int gamma_found(void);
62
63/* Gamma-specific code pulled from drm_fops.h:
64 */
65extern int DRM(finish)(struct inode *inode, struct file *filp,
66 unsigned int cmd, unsigned long arg);
67extern int DRM(flush_unblock)(drm_device_t *dev, int context,
68 drm_lock_flags_t flags);
69extern int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
70 drm_lock_flags_t flags);
71
72/* Gamma-specific code pulled from drm_dma.h:
73 */
74extern void DRM(clear_next_buffer)(drm_device_t *dev);
75extern int DRM(select_queue)(drm_device_t *dev,
76 void (*wrapper)(unsigned long));
77extern int DRM(dma_enqueue)(struct file *filp, drm_dma_t *dma);
78extern int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma);
79
80
81/* Gamma-specific code pulled from drm_lists.h (now renamed gamma_lists.h):
82 */
83extern int DRM(waitlist_create)(drm_waitlist_t *bl, int count);
84extern int DRM(waitlist_destroy)(drm_waitlist_t *bl);
85extern int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf);
86extern drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl);
87extern int DRM(freelist_create)(drm_freelist_t *bl, int count);
88extern int DRM(freelist_destroy)(drm_freelist_t *bl);
89extern int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl,
90 drm_buf_t *buf);
91extern drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block);
92
93/* externs for gamma changes to the ops */
94extern struct file_operations DRM(fops);
95extern unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait);
96extern ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
97
98
99#define GLINT_DRI_BUF_COUNT 256
100
101#define GAMMA_OFF(reg) \
102 ((reg < 0x1000) \
103 ? reg \
104 : ((reg < 0x10000) \
105 ? (reg - 0x1000) \
106 : ((reg < 0x11000) \
107 ? (reg - 0x10000) \
108 : (reg - 0x11000))))
109
110#define GAMMA_BASE(reg) ((unsigned long) \
111 ((reg < 0x1000) ? dev_priv->mmio0->handle : \
112 ((reg < 0x10000) ? dev_priv->mmio1->handle : \
113 ((reg < 0x11000) ? dev_priv->mmio2->handle : \
114 dev_priv->mmio3->handle))))
115#define GAMMA_ADDR(reg) (GAMMA_BASE(reg) + GAMMA_OFF(reg))
116#define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg)
117#define GAMMA_READ(reg) GAMMA_DEREF(reg)
118#define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0)
119
120#define GAMMA_BROADCASTMASK 0x9378
121#define GAMMA_COMMANDINTENABLE 0x0c48
122#define GAMMA_DMAADDRESS 0x0028
123#define GAMMA_DMACOUNT 0x0030
124#define GAMMA_FILTERMODE 0x8c00
125#define GAMMA_GCOMMANDINTFLAGS 0x0c50
126#define GAMMA_GCOMMANDMODE 0x0c40
127#define GAMMA_QUEUED_DMA_MODE 1<<1
128#define GAMMA_GCOMMANDSTATUS 0x0c60
129#define GAMMA_GDELAYTIMER 0x0c38
130#define GAMMA_GDMACONTROL 0x0060
131#define GAMMA_USE_AGP 1<<1
132#define GAMMA_GINTENABLE 0x0808
133#define GAMMA_GINTFLAGS 0x0810
134#define GAMMA_INFIFOSPACE 0x0018
135#define GAMMA_OUTFIFOWORDS 0x0020
136#define GAMMA_OUTPUTFIFO 0x2000
137#define GAMMA_SYNC 0x8c40
138#define GAMMA_SYNC_TAG 0x0188
139#define GAMMA_PAGETABLEADDR 0x0C00
140#define GAMMA_PAGETABLELENGTH 0x0C08
141
142#define GAMMA_PASSTHROUGH 0x1FE
143#define GAMMA_DMAADDRTAG 0x530
144#define GAMMA_DMACOUNTTAG 0x531
145#define GAMMA_COMMANDINTTAG 0x532
146
147#endif
diff --git a/drivers/char/drm/gamma_lists.h b/drivers/char/drm/gamma_lists.h
new file mode 100644
index 000000000000..2d93f412b96b
--- /dev/null
+++ b/drivers/char/drm/gamma_lists.h
@@ -0,0 +1,215 @@
1/* drm_lists.h -- Buffer list handling routines -*- linux-c -*-
2 * Created: Mon Apr 19 20:54:22 1999 by faith@valinux.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 */
31
32#include "drmP.h"
33
34
35int DRM(waitlist_create)(drm_waitlist_t *bl, int count)
36{
37 if (bl->count) return -EINVAL;
38
39 bl->bufs = DRM(alloc)((bl->count + 2) * sizeof(*bl->bufs),
40 DRM_MEM_BUFLISTS);
41
42 if(!bl->bufs) return -ENOMEM;
43 memset(bl->bufs, 0, sizeof(*bl->bufs));
44 bl->count = count;
45 bl->rp = bl->bufs;
46 bl->wp = bl->bufs;
47 bl->end = &bl->bufs[bl->count+1];
48 spin_lock_init(&bl->write_lock);
49 spin_lock_init(&bl->read_lock);
50 return 0;
51}
52
53int DRM(waitlist_destroy)(drm_waitlist_t *bl)
54{
55 if (bl->rp != bl->wp) return -EINVAL;
56 if (bl->bufs) DRM(free)(bl->bufs,
57 (bl->count + 2) * sizeof(*bl->bufs),
58 DRM_MEM_BUFLISTS);
59 bl->count = 0;
60 bl->bufs = NULL;
61 bl->rp = NULL;
62 bl->wp = NULL;
63 bl->end = NULL;
64 return 0;
65}
66
67int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf)
68{
69 int left;
70 unsigned long flags;
71
72 left = DRM_LEFTCOUNT(bl);
73 if (!left) {
74 DRM_ERROR("Overflow while adding buffer %d from filp %p\n",
75 buf->idx, buf->filp);
76 return -EINVAL;
77 }
78 buf->list = DRM_LIST_WAIT;
79
80 spin_lock_irqsave(&bl->write_lock, flags);
81 *bl->wp = buf;
82 if (++bl->wp >= bl->end) bl->wp = bl->bufs;
83 spin_unlock_irqrestore(&bl->write_lock, flags);
84
85 return 0;
86}
87
88drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl)
89{
90 drm_buf_t *buf;
91 unsigned long flags;
92
93 spin_lock_irqsave(&bl->read_lock, flags);
94 buf = *bl->rp;
95 if (bl->rp == bl->wp) {
96 spin_unlock_irqrestore(&bl->read_lock, flags);
97 return NULL;
98 }
99 if (++bl->rp >= bl->end) bl->rp = bl->bufs;
100 spin_unlock_irqrestore(&bl->read_lock, flags);
101
102 return buf;
103}
104
105int DRM(freelist_create)(drm_freelist_t *bl, int count)
106{
107 atomic_set(&bl->count, 0);
108 bl->next = NULL;
109 init_waitqueue_head(&bl->waiting);
110 bl->low_mark = 0;
111 bl->high_mark = 0;
112 atomic_set(&bl->wfh, 0);
113 spin_lock_init(&bl->lock);
114 ++bl->initialized;
115 return 0;
116}
117
118int DRM(freelist_destroy)(drm_freelist_t *bl)
119{
120 atomic_set(&bl->count, 0);
121 bl->next = NULL;
122 return 0;
123}
124
125int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
126{
127 drm_device_dma_t *dma = dev->dma;
128
129 if (!dma) {
130 DRM_ERROR("No DMA support\n");
131 return 1;
132 }
133
134 if (buf->waiting || buf->pending || buf->list == DRM_LIST_FREE) {
135 DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n",
136 buf->idx, buf->waiting, buf->pending, buf->list);
137 }
138 if (!bl) return 1;
139 buf->list = DRM_LIST_FREE;
140
141 spin_lock(&bl->lock);
142 buf->next = bl->next;
143 bl->next = buf;
144 spin_unlock(&bl->lock);
145
146 atomic_inc(&bl->count);
147 if (atomic_read(&bl->count) > dma->buf_count) {
148 DRM_ERROR("%d of %d buffers free after addition of %d\n",
149 atomic_read(&bl->count), dma->buf_count, buf->idx);
150 return 1;
151 }
152 /* Check for high water mark */
153 if (atomic_read(&bl->wfh) && atomic_read(&bl->count)>=bl->high_mark) {
154 atomic_set(&bl->wfh, 0);
155 wake_up_interruptible(&bl->waiting);
156 }
157 return 0;
158}
159
160static drm_buf_t *DRM(freelist_try)(drm_freelist_t *bl)
161{
162 drm_buf_t *buf;
163
164 if (!bl) return NULL;
165
166 /* Get buffer */
167 spin_lock(&bl->lock);
168 if (!bl->next) {
169 spin_unlock(&bl->lock);
170 return NULL;
171 }
172 buf = bl->next;
173 bl->next = bl->next->next;
174 spin_unlock(&bl->lock);
175
176 atomic_dec(&bl->count);
177 buf->next = NULL;
178 buf->list = DRM_LIST_NONE;
179 if (buf->waiting || buf->pending) {
180 DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n",
181 buf->idx, buf->waiting, buf->pending, buf->list);
182 }
183
184 return buf;
185}
186
187drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block)
188{
189 drm_buf_t *buf = NULL;
190 DECLARE_WAITQUEUE(entry, current);
191
192 if (!bl || !bl->initialized) return NULL;
193
194 /* Check for low water mark */
195 if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */
196 atomic_set(&bl->wfh, 1);
197 if (atomic_read(&bl->wfh)) {
198 if (block) {
199 add_wait_queue(&bl->waiting, &entry);
200 for (;;) {
201 current->state = TASK_INTERRUPTIBLE;
202 if (!atomic_read(&bl->wfh)
203 && (buf = DRM(freelist_try)(bl))) break;
204 schedule();
205 if (signal_pending(current)) break;
206 }
207 current->state = TASK_RUNNING;
208 remove_wait_queue(&bl->waiting, &entry);
209 }
210 return buf;
211 }
212
213 return DRM(freelist_try)(bl);
214}
215
diff --git a/drivers/char/drm/gamma_lock.h b/drivers/char/drm/gamma_lock.h
new file mode 100644
index 000000000000..ddec67e4ed16
--- /dev/null
+++ b/drivers/char/drm/gamma_lock.h
@@ -0,0 +1,140 @@
1/* lock.c -- IOCTLs for locking -*- linux-c -*-
2 * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 */
31
32
33/* Gamma-specific code extracted from drm_lock.h:
34 */
35static int DRM(flush_queue)(drm_device_t *dev, int context)
36{
37 DECLARE_WAITQUEUE(entry, current);
38 int ret = 0;
39 drm_queue_t *q = dev->queuelist[context];
40
41 DRM_DEBUG("\n");
42
43 atomic_inc(&q->use_count);
44 if (atomic_read(&q->use_count) > 1) {
45 atomic_inc(&q->block_write);
46 add_wait_queue(&q->flush_queue, &entry);
47 atomic_inc(&q->block_count);
48 for (;;) {
49 current->state = TASK_INTERRUPTIBLE;
50 if (!DRM_BUFCOUNT(&q->waitlist)) break;
51 schedule();
52 if (signal_pending(current)) {
53 ret = -EINTR; /* Can't restart */
54 break;
55 }
56 }
57 atomic_dec(&q->block_count);
58 current->state = TASK_RUNNING;
59 remove_wait_queue(&q->flush_queue, &entry);
60 }
61 atomic_dec(&q->use_count);
62
63 /* NOTE: block_write is still incremented!
64 Use drm_flush_unlock_queue to decrement. */
65 return ret;
66}
67
68static int DRM(flush_unblock_queue)(drm_device_t *dev, int context)
69{
70 drm_queue_t *q = dev->queuelist[context];
71
72 DRM_DEBUG("\n");
73
74 atomic_inc(&q->use_count);
75 if (atomic_read(&q->use_count) > 1) {
76 if (atomic_read(&q->block_write)) {
77 atomic_dec(&q->block_write);
78 wake_up_interruptible(&q->write_queue);
79 }
80 }
81 atomic_dec(&q->use_count);
82 return 0;
83}
84
85int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
86 drm_lock_flags_t flags)
87{
88 int ret = 0;
89 int i;
90
91 DRM_DEBUG("\n");
92
93 if (flags & _DRM_LOCK_FLUSH) {
94 ret = DRM(flush_queue)(dev, DRM_KERNEL_CONTEXT);
95 if (!ret) ret = DRM(flush_queue)(dev, context);
96 }
97 if (flags & _DRM_LOCK_FLUSH_ALL) {
98 for (i = 0; !ret && i < dev->queue_count; i++) {
99 ret = DRM(flush_queue)(dev, i);
100 }
101 }
102 return ret;
103}
104
105int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags)
106{
107 int ret = 0;
108 int i;
109
110 DRM_DEBUG("\n");
111
112 if (flags & _DRM_LOCK_FLUSH) {
113 ret = DRM(flush_unblock_queue)(dev, DRM_KERNEL_CONTEXT);
114 if (!ret) ret = DRM(flush_unblock_queue)(dev, context);
115 }
116 if (flags & _DRM_LOCK_FLUSH_ALL) {
117 for (i = 0; !ret && i < dev->queue_count; i++) {
118 ret = DRM(flush_unblock_queue)(dev, i);
119 }
120 }
121
122 return ret;
123}
124
125int DRM(finish)(struct inode *inode, struct file *filp, unsigned int cmd,
126 unsigned long arg)
127{
128 drm_file_t *priv = filp->private_data;
129 drm_device_t *dev = priv->dev;
130 int ret = 0;
131 drm_lock_t lock;
132
133 DRM_DEBUG("\n");
134
135 if (copy_from_user(&lock, (drm_lock_t __user *)arg, sizeof(lock)))
136 return -EFAULT;
137 ret = DRM(flush_block_and_flush)(dev, lock.context, lock.flags);
138 DRM(flush_unblock)(dev, lock.context, lock.flags);
139 return ret;
140}
diff --git a/drivers/char/drm/gamma_old_dma.h b/drivers/char/drm/gamma_old_dma.h
new file mode 100644
index 000000000000..abdd454aab9f
--- /dev/null
+++ b/drivers/char/drm/gamma_old_dma.h
@@ -0,0 +1,313 @@
1/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
2 * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
3 *
4 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 */
31
32
33/* Gamma-specific code pulled from drm_dma.h:
34 */
35
36void DRM(clear_next_buffer)(drm_device_t *dev)
37{
38 drm_device_dma_t *dma = dev->dma;
39
40 dma->next_buffer = NULL;
41 if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) {
42 wake_up_interruptible(&dma->next_queue->flush_queue);
43 }
44 dma->next_queue = NULL;
45}
46
47int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long))
48{
49 int i;
50 int candidate = -1;
51 int j = jiffies;
52
53 if (!dev) {
54 DRM_ERROR("No device\n");
55 return -1;
56 }
57 if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) {
58 /* This only happens between the time the
59 interrupt is initialized and the time
60 the queues are initialized. */
61 return -1;
62 }
63
64 /* Doing "while locked" DMA? */
65 if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
66 return DRM_KERNEL_CONTEXT;
67 }
68
69 /* If there are buffers on the last_context
70 queue, and we have not been executing
71 this context very long, continue to
72 execute this context. */
73 if (dev->last_switch <= j
74 && dev->last_switch + DRM_TIME_SLICE > j
75 && DRM_WAITCOUNT(dev, dev->last_context)) {
76 return dev->last_context;
77 }
78
79 /* Otherwise, find a candidate */
80 for (i = dev->last_checked + 1; i < dev->queue_count; i++) {
81 if (DRM_WAITCOUNT(dev, i)) {
82 candidate = dev->last_checked = i;
83 break;
84 }
85 }
86
87 if (candidate < 0) {
88 for (i = 0; i < dev->queue_count; i++) {
89 if (DRM_WAITCOUNT(dev, i)) {
90 candidate = dev->last_checked = i;
91 break;
92 }
93 }
94 }
95
96 if (wrapper
97 && candidate >= 0
98 && candidate != dev->last_context
99 && dev->last_switch <= j
100 && dev->last_switch + DRM_TIME_SLICE > j) {
101 if (dev->timer.expires != dev->last_switch + DRM_TIME_SLICE) {
102 del_timer(&dev->timer);
103 dev->timer.function = wrapper;
104 dev->timer.data = (unsigned long)dev;
105 dev->timer.expires = dev->last_switch+DRM_TIME_SLICE;
106 add_timer(&dev->timer);
107 }
108 return -1;
109 }
110
111 return candidate;
112}
113
114
115int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
116{
117 drm_file_t *priv = filp->private_data;
118 drm_device_t *dev = priv->dev;
119 int i;
120 drm_queue_t *q;
121 drm_buf_t *buf;
122 int idx;
123 int while_locked = 0;
124 drm_device_dma_t *dma = dev->dma;
125 int *ind;
126 int err;
127 DECLARE_WAITQUEUE(entry, current);
128
129 DRM_DEBUG("%d\n", d->send_count);
130
131 if (d->flags & _DRM_DMA_WHILE_LOCKED) {
132 int context = dev->lock.hw_lock->lock;
133
134 if (!_DRM_LOCK_IS_HELD(context)) {
135 DRM_ERROR("No lock held during \"while locked\""
136 " request\n");
137 return -EINVAL;
138 }
139 if (d->context != _DRM_LOCKING_CONTEXT(context)
140 && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) {
141 DRM_ERROR("Lock held by %d while %d makes"
142 " \"while locked\" request\n",
143 _DRM_LOCKING_CONTEXT(context),
144 d->context);
145 return -EINVAL;
146 }
147 q = dev->queuelist[DRM_KERNEL_CONTEXT];
148 while_locked = 1;
149 } else {
150 q = dev->queuelist[d->context];
151 }
152
153
154 atomic_inc(&q->use_count);
155 if (atomic_read(&q->block_write)) {
156 add_wait_queue(&q->write_queue, &entry);
157 atomic_inc(&q->block_count);
158 for (;;) {
159 current->state = TASK_INTERRUPTIBLE;
160 if (!atomic_read(&q->block_write)) break;
161 schedule();
162 if (signal_pending(current)) {
163 atomic_dec(&q->use_count);
164 remove_wait_queue(&q->write_queue, &entry);
165 return -EINTR;
166 }
167 }
168 atomic_dec(&q->block_count);
169 current->state = TASK_RUNNING;
170 remove_wait_queue(&q->write_queue, &entry);
171 }
172
173 ind = DRM(alloc)(d->send_count * sizeof(int), DRM_MEM_DRIVER);
174 if (!ind)
175 return -ENOMEM;
176
177 if (copy_from_user(ind, d->send_indices, d->send_count * sizeof(int))) {
178 err = -EFAULT;
179 goto out;
180 }
181
182 err = -EINVAL;
183 for (i = 0; i < d->send_count; i++) {
184 idx = ind[i];
185 if (idx < 0 || idx >= dma->buf_count) {
186 DRM_ERROR("Index %d (of %d max)\n",
187 ind[i], dma->buf_count - 1);
188 goto out;
189 }
190 buf = dma->buflist[ idx ];
191 if (buf->filp != filp) {
192 DRM_ERROR("Process %d using buffer not owned\n",
193 current->pid);
194 goto out;
195 }
196 if (buf->list != DRM_LIST_NONE) {
197 DRM_ERROR("Process %d using buffer %d on list %d\n",
198 current->pid, buf->idx, buf->list);
199 goto out;
200 }
201 buf->used = ind[i];
202 buf->while_locked = while_locked;
203 buf->context = d->context;
204 if (!buf->used) {
205 DRM_ERROR("Queueing 0 length buffer\n");
206 }
207 if (buf->pending) {
208 DRM_ERROR("Queueing pending buffer:"
209 " buffer %d, offset %d\n",
210 ind[i], i);
211 goto out;
212 }
213 if (buf->waiting) {
214 DRM_ERROR("Queueing waiting buffer:"
215 " buffer %d, offset %d\n",
216 ind[i], i);
217 goto out;
218 }
219 buf->waiting = 1;
220 if (atomic_read(&q->use_count) == 1
221 || atomic_read(&q->finalization)) {
222 DRM(free_buffer)(dev, buf);
223 } else {
224 DRM(waitlist_put)(&q->waitlist, buf);
225 atomic_inc(&q->total_queued);
226 }
227 }
228 atomic_dec(&q->use_count);
229
230 return 0;
231
232out:
233 DRM(free)(ind, d->send_count * sizeof(int), DRM_MEM_DRIVER);
234 atomic_dec(&q->use_count);
235 return err;
236}
237
238static int DRM(dma_get_buffers_of_order)(struct file *filp, drm_dma_t *d,
239 int order)
240{
241 drm_file_t *priv = filp->private_data;
242 drm_device_t *dev = priv->dev;
243 int i;
244 drm_buf_t *buf;
245 drm_device_dma_t *dma = dev->dma;
246
247 for (i = d->granted_count; i < d->request_count; i++) {
248 buf = DRM(freelist_get)(&dma->bufs[order].freelist,
249 d->flags & _DRM_DMA_WAIT);
250 if (!buf) break;
251 if (buf->pending || buf->waiting) {
252 DRM_ERROR("Free buffer %d in use: filp %p (w%d, p%d)\n",
253 buf->idx,
254 buf->filp,
255 buf->waiting,
256 buf->pending);
257 }
258 buf->filp = filp;
259 if (copy_to_user(&d->request_indices[i],
260 &buf->idx,
261 sizeof(buf->idx)))
262 return -EFAULT;
263
264 if (copy_to_user(&d->request_sizes[i],
265 &buf->total,
266 sizeof(buf->total)))
267 return -EFAULT;
268
269 ++d->granted_count;
270 }
271 return 0;
272}
273
274
275int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma)
276{
277 int order;
278 int retcode = 0;
279 int tmp_order;
280
281 order = DRM(order)(dma->request_size);
282
283 dma->granted_count = 0;
284 retcode = DRM(dma_get_buffers_of_order)(filp, dma, order);
285
286 if (dma->granted_count < dma->request_count
287 && (dma->flags & _DRM_DMA_SMALLER_OK)) {
288 for (tmp_order = order - 1;
289 !retcode
290 && dma->granted_count < dma->request_count
291 && tmp_order >= DRM_MIN_ORDER;
292 --tmp_order) {
293
294 retcode = DRM(dma_get_buffers_of_order)(filp, dma,
295 tmp_order);
296 }
297 }
298
299 if (dma->granted_count < dma->request_count
300 && (dma->flags & _DRM_DMA_LARGER_OK)) {
301 for (tmp_order = order + 1;
302 !retcode
303 && dma->granted_count < dma->request_count
304 && tmp_order <= DRM_MAX_ORDER;
305 ++tmp_order) {
306
307 retcode = DRM(dma_get_buffers_of_order)(filp, dma,
308 tmp_order);
309 }
310 }
311 return 0;
312}
313
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
new file mode 100644
index 000000000000..24857cc6c23b
--- /dev/null
+++ b/drivers/char/drm/i810_dma.c
@@ -0,0 +1,1385 @@
1/* i810_dma.c -- DMA support for the i810 -*- linux-c -*-
2 * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
28 * Jeff Hartmann <jhartmann@valinux.com>
29 * Keith Whitwell <keith@tungstengraphics.com>
30 *
31 */
32
33#include "drmP.h"
34#include "drm.h"
35#include "i810_drm.h"
36#include "i810_drv.h"
37#include <linux/interrupt.h> /* For task queue support */
38#include <linux/delay.h>
39#include <linux/pagemap.h>
40
41#define I810_BUF_FREE 2
42#define I810_BUF_CLIENT 1
43#define I810_BUF_HARDWARE 0
44
45#define I810_BUF_UNMAPPED 0
46#define I810_BUF_MAPPED 1
47
48#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
49#define down_write down
50#define up_write up
51#endif
52
53static drm_buf_t *i810_freelist_get(drm_device_t *dev)
54{
55 drm_device_dma_t *dma = dev->dma;
56 int i;
57 int used;
58
59 /* Linear search might not be the best solution */
60
61 for (i = 0; i < dma->buf_count; i++) {
62 drm_buf_t *buf = dma->buflist[ i ];
63 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
64 /* In use is already a pointer */
65 used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
66 I810_BUF_CLIENT);
67 if (used == I810_BUF_FREE) {
68 return buf;
69 }
70 }
71 return NULL;
72}
73
74/* This should only be called if the buffer is not sent to the hardware
75 * yet, the hardware updates in use for us once its on the ring buffer.
76 */
77
78static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
79{
80 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
81 int used;
82
83 /* In use is already a pointer */
84 used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
85 if (used != I810_BUF_CLIENT) {
86 DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
87 return -EINVAL;
88 }
89
90 return 0;
91}
92
93static struct file_operations i810_buffer_fops = {
94 .open = drm_open,
95 .flush = drm_flush,
96 .release = drm_release,
97 .ioctl = drm_ioctl,
98 .mmap = i810_mmap_buffers,
99 .fasync = drm_fasync,
100};
101
102int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
103{
104 drm_file_t *priv = filp->private_data;
105 drm_device_t *dev;
106 drm_i810_private_t *dev_priv;
107 drm_buf_t *buf;
108 drm_i810_buf_priv_t *buf_priv;
109
110 lock_kernel();
111 dev = priv->head->dev;
112 dev_priv = dev->dev_private;
113 buf = dev_priv->mmap_buffer;
114 buf_priv = buf->dev_private;
115
116 vma->vm_flags |= (VM_IO | VM_DONTCOPY);
117 vma->vm_file = filp;
118
119 buf_priv->currently_mapped = I810_BUF_MAPPED;
120 unlock_kernel();
121
122 if (io_remap_pfn_range(vma, vma->vm_start,
123 VM_OFFSET(vma) >> PAGE_SHIFT,
124 vma->vm_end - vma->vm_start,
125 vma->vm_page_prot)) return -EAGAIN;
126 return 0;
127}
128
129static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
130{
131 drm_file_t *priv = filp->private_data;
132 drm_device_t *dev = priv->head->dev;
133 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
134 drm_i810_private_t *dev_priv = dev->dev_private;
135 struct file_operations *old_fops;
136 int retcode = 0;
137
138 if (buf_priv->currently_mapped == I810_BUF_MAPPED)
139 return -EINVAL;
140
141 down_write( &current->mm->mmap_sem );
142 old_fops = filp->f_op;
143 filp->f_op = &i810_buffer_fops;
144 dev_priv->mmap_buffer = buf;
145 buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
146 PROT_READ|PROT_WRITE,
147 MAP_SHARED,
148 buf->bus_address);
149 dev_priv->mmap_buffer = NULL;
150 filp->f_op = old_fops;
151 if ((unsigned long)buf_priv->virtual > -1024UL) {
152 /* Real error */
153 DRM_ERROR("mmap error\n");
154 retcode = (signed int)buf_priv->virtual;
155 buf_priv->virtual = NULL;
156 }
157 up_write( &current->mm->mmap_sem );
158
159 return retcode;
160}
161
162static int i810_unmap_buffer(drm_buf_t *buf)
163{
164 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
165 int retcode = 0;
166
167 if (buf_priv->currently_mapped != I810_BUF_MAPPED)
168 return -EINVAL;
169
170 down_write(&current->mm->mmap_sem);
171 retcode = do_munmap(current->mm,
172 (unsigned long)buf_priv->virtual,
173 (size_t) buf->total);
174 up_write(&current->mm->mmap_sem);
175
176 buf_priv->currently_mapped = I810_BUF_UNMAPPED;
177 buf_priv->virtual = NULL;
178
179 return retcode;
180}
181
182static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
183 struct file *filp)
184{
185 drm_buf_t *buf;
186 drm_i810_buf_priv_t *buf_priv;
187 int retcode = 0;
188
189 buf = i810_freelist_get(dev);
190 if (!buf) {
191 retcode = -ENOMEM;
192 DRM_DEBUG("retcode=%d\n", retcode);
193 return retcode;
194 }
195
196 retcode = i810_map_buffer(buf, filp);
197 if (retcode) {
198 i810_freelist_put(dev, buf);
199 DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
200 return retcode;
201 }
202 buf->filp = filp;
203 buf_priv = buf->dev_private;
204 d->granted = 1;
205 d->request_idx = buf->idx;
206 d->request_size = buf->total;
207 d->virtual = buf_priv->virtual;
208
209 return retcode;
210}
211
212static int i810_dma_cleanup(drm_device_t *dev)
213{
214 drm_device_dma_t *dma = dev->dma;
215
216 /* Make sure interrupts are disabled here because the uninstall ioctl
217 * may not have been called from userspace and after dev_private
218 * is freed, it's too late.
219 */
220 if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled)
221 drm_irq_uninstall(dev);
222
223 if (dev->dev_private) {
224 int i;
225 drm_i810_private_t *dev_priv =
226 (drm_i810_private_t *) dev->dev_private;
227
228 if (dev_priv->ring.virtual_start) {
229 drm_ioremapfree((void *) dev_priv->ring.virtual_start,
230 dev_priv->ring.Size, dev);
231 }
232 if (dev_priv->hw_status_page) {
233 pci_free_consistent(dev->pdev, PAGE_SIZE,
234 dev_priv->hw_status_page,
235 dev_priv->dma_status_page);
236 /* Need to rewrite hardware status page */
237 I810_WRITE(0x02080, 0x1ffff000);
238 }
239 drm_free(dev->dev_private, sizeof(drm_i810_private_t),
240 DRM_MEM_DRIVER);
241 dev->dev_private = NULL;
242
243 for (i = 0; i < dma->buf_count; i++) {
244 drm_buf_t *buf = dma->buflist[ i ];
245 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
246 if ( buf_priv->kernel_virtual && buf->total )
247 drm_ioremapfree(buf_priv->kernel_virtual, buf->total, dev);
248 }
249 }
250 return 0;
251}
252
253static int i810_wait_ring(drm_device_t *dev, int n)
254{
255 drm_i810_private_t *dev_priv = dev->dev_private;
256 drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
257 int iters = 0;
258 unsigned long end;
259 unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
260
261 end = jiffies + (HZ*3);
262 while (ring->space < n) {
263 ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
264 ring->space = ring->head - (ring->tail+8);
265 if (ring->space < 0) ring->space += ring->Size;
266
267 if (ring->head != last_head) {
268 end = jiffies + (HZ*3);
269 last_head = ring->head;
270 }
271
272 iters++;
273 if (time_before(end, jiffies)) {
274 DRM_ERROR("space: %d wanted %d\n", ring->space, n);
275 DRM_ERROR("lockup\n");
276 goto out_wait_ring;
277 }
278 udelay(1);
279 }
280
281out_wait_ring:
282 return iters;
283}
284
285static void i810_kernel_lost_context(drm_device_t *dev)
286{
287 drm_i810_private_t *dev_priv = dev->dev_private;
288 drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
289
290 ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
291 ring->tail = I810_READ(LP_RING + RING_TAIL);
292 ring->space = ring->head - (ring->tail+8);
293 if (ring->space < 0) ring->space += ring->Size;
294}
295
296static int i810_freelist_init(drm_device_t *dev, drm_i810_private_t *dev_priv)
297{
298 drm_device_dma_t *dma = dev->dma;
299 int my_idx = 24;
300 u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
301 int i;
302
303 if (dma->buf_count > 1019) {
304 /* Not enough space in the status page for the freelist */
305 return -EINVAL;
306 }
307
308 for (i = 0; i < dma->buf_count; i++) {
309 drm_buf_t *buf = dma->buflist[ i ];
310 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
311
312 buf_priv->in_use = hw_status++;
313 buf_priv->my_use_idx = my_idx;
314 my_idx += 4;
315
316 *buf_priv->in_use = I810_BUF_FREE;
317
318 buf_priv->kernel_virtual = drm_ioremap(buf->bus_address,
319 buf->total, dev);
320 }
321 return 0;
322}
323
324static int i810_dma_initialize(drm_device_t *dev,
325 drm_i810_private_t *dev_priv,
326 drm_i810_init_t *init)
327{
328 struct list_head *list;
329
330 memset(dev_priv, 0, sizeof(drm_i810_private_t));
331
332 list_for_each(list, &dev->maplist->head) {
333 drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
334 if (r_list->map &&
335 r_list->map->type == _DRM_SHM &&
336 r_list->map->flags & _DRM_CONTAINS_LOCK ) {
337 dev_priv->sarea_map = r_list->map;
338 break;
339 }
340 }
341 if (!dev_priv->sarea_map) {
342 dev->dev_private = (void *)dev_priv;
343 i810_dma_cleanup(dev);
344 DRM_ERROR("can not find sarea!\n");
345 return -EINVAL;
346 }
347 dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
348 if (!dev_priv->mmio_map) {
349 dev->dev_private = (void *)dev_priv;
350 i810_dma_cleanup(dev);
351 DRM_ERROR("can not find mmio map!\n");
352 return -EINVAL;
353 }
354 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
355 if (!dev->agp_buffer_map) {
356 dev->dev_private = (void *)dev_priv;
357 i810_dma_cleanup(dev);
358 DRM_ERROR("can not find dma buffer map!\n");
359 return -EINVAL;
360 }
361
362 dev_priv->sarea_priv = (drm_i810_sarea_t *)
363 ((u8 *)dev_priv->sarea_map->handle +
364 init->sarea_priv_offset);
365
366 dev_priv->ring.Start = init->ring_start;
367 dev_priv->ring.End = init->ring_end;
368 dev_priv->ring.Size = init->ring_size;
369
370 dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
371 init->ring_start,
372 init->ring_size, dev);
373
374 if (dev_priv->ring.virtual_start == NULL) {
375 dev->dev_private = (void *) dev_priv;
376 i810_dma_cleanup(dev);
377 DRM_ERROR("can not ioremap virtual address for"
378 " ring buffer\n");
379 return -ENOMEM;
380 }
381
382 dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
383
384 dev_priv->w = init->w;
385 dev_priv->h = init->h;
386 dev_priv->pitch = init->pitch;
387 dev_priv->back_offset = init->back_offset;
388 dev_priv->depth_offset = init->depth_offset;
389 dev_priv->front_offset = init->front_offset;
390
391 dev_priv->overlay_offset = init->overlay_offset;
392 dev_priv->overlay_physical = init->overlay_physical;
393
394 dev_priv->front_di1 = init->front_offset | init->pitch_bits;
395 dev_priv->back_di1 = init->back_offset | init->pitch_bits;
396 dev_priv->zi1 = init->depth_offset | init->pitch_bits;
397
398 /* Program Hardware Status Page */
399 dev_priv->hw_status_page =
400 pci_alloc_consistent(dev->pdev, PAGE_SIZE,
401 &dev_priv->dma_status_page);
402 if (!dev_priv->hw_status_page) {
403 dev->dev_private = (void *)dev_priv;
404 i810_dma_cleanup(dev);
405 DRM_ERROR("Can not allocate hardware status page\n");
406 return -ENOMEM;
407 }
408 memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
409 DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
410
411 I810_WRITE(0x02080, dev_priv->dma_status_page);
412 DRM_DEBUG("Enabled hardware status page\n");
413
414 /* Now we need to init our freelist */
415 if (i810_freelist_init(dev, dev_priv) != 0) {
416 dev->dev_private = (void *)dev_priv;
417 i810_dma_cleanup(dev);
418 DRM_ERROR("Not enough space in the status page for"
419 " the freelist\n");
420 return -ENOMEM;
421 }
422 dev->dev_private = (void *)dev_priv;
423
424 return 0;
425}
426
427/* i810 DRM version 1.1 used a smaller init structure with different
428 * ordering of values than is currently used (drm >= 1.2). There is
429 * no defined way to detect the XFree version to correct this problem,
430 * however by checking using this procedure we can detect the correct
431 * thing to do.
432 *
433 * #1 Read the Smaller init structure from user-space
434 * #2 Verify the overlay_physical is a valid physical address, or NULL
435 * If it isn't then we have a v1.1 client. Fix up params.
436 * If it is, then we have a 1.2 client... get the rest of the data.
437 */
438static int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
439{
440
441 /* Get v1.1 init data */
442 if (copy_from_user(init, (drm_i810_pre12_init_t __user *)arg,
443 sizeof(drm_i810_pre12_init_t))) {
444 return -EFAULT;
445 }
446
447 if ((!init->overlay_physical) || (init->overlay_physical > 4096)) {
448
449 /* This is a v1.2 client, just get the v1.2 init data */
450 DRM_INFO("Using POST v1.2 init.\n");
451 if (copy_from_user(init, (drm_i810_init_t __user *)arg,
452 sizeof(drm_i810_init_t))) {
453 return -EFAULT;
454 }
455 } else {
456
457 /* This is a v1.1 client, fix the params */
458 DRM_INFO("Using PRE v1.2 init.\n");
459 init->pitch_bits = init->h;
460 init->pitch = init->w;
461 init->h = init->overlay_physical;
462 init->w = init->overlay_offset;
463 init->overlay_physical = 0;
464 init->overlay_offset = 0;
465 }
466
467 return 0;
468}
469
470static int i810_dma_init(struct inode *inode, struct file *filp,
471 unsigned int cmd, unsigned long arg)
472{
473 drm_file_t *priv = filp->private_data;
474 drm_device_t *dev = priv->head->dev;
475 drm_i810_private_t *dev_priv;
476 drm_i810_init_t init;
477 int retcode = 0;
478
479 /* Get only the init func */
480 if (copy_from_user(&init, (void __user *)arg, sizeof(drm_i810_init_func_t)))
481 return -EFAULT;
482
483 switch(init.func) {
484 case I810_INIT_DMA:
485 /* This case is for backward compatibility. It
486 * handles XFree 4.1.0 and 4.2.0, and has to
487 * do some parameter checking as described below.
488 * It will someday go away.
489 */
490 retcode = i810_dma_init_compat(&init, arg);
491 if (retcode)
492 return retcode;
493
494 dev_priv = drm_alloc(sizeof(drm_i810_private_t),
495 DRM_MEM_DRIVER);
496 if (dev_priv == NULL)
497 return -ENOMEM;
498 retcode = i810_dma_initialize(dev, dev_priv, &init);
499 break;
500
501 default:
502 case I810_INIT_DMA_1_4:
503 DRM_INFO("Using v1.4 init.\n");
504 if (copy_from_user(&init, (drm_i810_init_t __user *)arg,
505 sizeof(drm_i810_init_t))) {
506 return -EFAULT;
507 }
508 dev_priv = drm_alloc(sizeof(drm_i810_private_t),
509 DRM_MEM_DRIVER);
510 if (dev_priv == NULL)
511 return -ENOMEM;
512 retcode = i810_dma_initialize(dev, dev_priv, &init);
513 break;
514
515 case I810_CLEANUP_DMA:
516 DRM_INFO("DMA Cleanup\n");
517 retcode = i810_dma_cleanup(dev);
518 break;
519 }
520
521 return retcode;
522}
523
524
525
526/* Most efficient way to verify state for the i810 is as it is
527 * emitted. Non-conformant state is silently dropped.
528 *
529 * Use 'volatile' & local var tmp to force the emitted values to be
530 * identical to the verified ones.
531 */
532static void i810EmitContextVerified( drm_device_t *dev,
533 volatile unsigned int *code )
534{
535 drm_i810_private_t *dev_priv = dev->dev_private;
536 int i, j = 0;
537 unsigned int tmp;
538 RING_LOCALS;
539
540 BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
541
542 OUT_RING( GFX_OP_COLOR_FACTOR );
543 OUT_RING( code[I810_CTXREG_CF1] );
544
545 OUT_RING( GFX_OP_STIPPLE );
546 OUT_RING( code[I810_CTXREG_ST1] );
547
548 for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
549 tmp = code[i];
550
551 if ((tmp & (7<<29)) == (3<<29) &&
552 (tmp & (0x1f<<24)) < (0x1d<<24))
553 {
554 OUT_RING( tmp );
555 j++;
556 }
557 else printk("constext state dropped!!!\n");
558 }
559
560 if (j & 1)
561 OUT_RING( 0 );
562
563 ADVANCE_LP_RING();
564}
565
566static void i810EmitTexVerified( drm_device_t *dev,
567 volatile unsigned int *code )
568{
569 drm_i810_private_t *dev_priv = dev->dev_private;
570 int i, j = 0;
571 unsigned int tmp;
572 RING_LOCALS;
573
574 BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
575
576 OUT_RING( GFX_OP_MAP_INFO );
577 OUT_RING( code[I810_TEXREG_MI1] );
578 OUT_RING( code[I810_TEXREG_MI2] );
579 OUT_RING( code[I810_TEXREG_MI3] );
580
581 for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
582 tmp = code[i];
583
584 if ((tmp & (7<<29)) == (3<<29) &&
585 (tmp & (0x1f<<24)) < (0x1d<<24))
586 {
587 OUT_RING( tmp );
588 j++;
589 }
590 else printk("texture state dropped!!!\n");
591 }
592
593 if (j & 1)
594 OUT_RING( 0 );
595
596 ADVANCE_LP_RING();
597}
598
599
600/* Need to do some additional checking when setting the dest buffer.
601 */
602static void i810EmitDestVerified( drm_device_t *dev,
603 volatile unsigned int *code )
604{
605 drm_i810_private_t *dev_priv = dev->dev_private;
606 unsigned int tmp;
607 RING_LOCALS;
608
609 BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
610
611 tmp = code[I810_DESTREG_DI1];
612 if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
613 OUT_RING( CMD_OP_DESTBUFFER_INFO );
614 OUT_RING( tmp );
615 } else
616 DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
617 tmp, dev_priv->front_di1, dev_priv->back_di1);
618
619 /* invarient:
620 */
621 OUT_RING( CMD_OP_Z_BUFFER_INFO );
622 OUT_RING( dev_priv->zi1 );
623
624 OUT_RING( GFX_OP_DESTBUFFER_VARS );
625 OUT_RING( code[I810_DESTREG_DV1] );
626
627 OUT_RING( GFX_OP_DRAWRECT_INFO );
628 OUT_RING( code[I810_DESTREG_DR1] );
629 OUT_RING( code[I810_DESTREG_DR2] );
630 OUT_RING( code[I810_DESTREG_DR3] );
631 OUT_RING( code[I810_DESTREG_DR4] );
632 OUT_RING( 0 );
633
634 ADVANCE_LP_RING();
635}
636
637
638
639static void i810EmitState( drm_device_t *dev )
640{
641 drm_i810_private_t *dev_priv = dev->dev_private;
642 drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
643 unsigned int dirty = sarea_priv->dirty;
644
645 DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
646
647 if (dirty & I810_UPLOAD_BUFFERS) {
648 i810EmitDestVerified( dev, sarea_priv->BufferState );
649 sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
650 }
651
652 if (dirty & I810_UPLOAD_CTX) {
653 i810EmitContextVerified( dev, sarea_priv->ContextState );
654 sarea_priv->dirty &= ~I810_UPLOAD_CTX;
655 }
656
657 if (dirty & I810_UPLOAD_TEX0) {
658 i810EmitTexVerified( dev, sarea_priv->TexState[0] );
659 sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
660 }
661
662 if (dirty & I810_UPLOAD_TEX1) {
663 i810EmitTexVerified( dev, sarea_priv->TexState[1] );
664 sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
665 }
666}
667
668
669
670/* need to verify
671 */
672static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
673 unsigned int clear_color,
674 unsigned int clear_zval )
675{
676 drm_i810_private_t *dev_priv = dev->dev_private;
677 drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
678 int nbox = sarea_priv->nbox;
679 drm_clip_rect_t *pbox = sarea_priv->boxes;
680 int pitch = dev_priv->pitch;
681 int cpp = 2;
682 int i;
683 RING_LOCALS;
684
685 if ( dev_priv->current_page == 1 ) {
686 unsigned int tmp = flags;
687
688 flags &= ~(I810_FRONT | I810_BACK);
689 if (tmp & I810_FRONT) flags |= I810_BACK;
690 if (tmp & I810_BACK) flags |= I810_FRONT;
691 }
692
693 i810_kernel_lost_context(dev);
694
695 if (nbox > I810_NR_SAREA_CLIPRECTS)
696 nbox = I810_NR_SAREA_CLIPRECTS;
697
698 for (i = 0 ; i < nbox ; i++, pbox++) {
699 unsigned int x = pbox->x1;
700 unsigned int y = pbox->y1;
701 unsigned int width = (pbox->x2 - x) * cpp;
702 unsigned int height = pbox->y2 - y;
703 unsigned int start = y * pitch + x * cpp;
704
705 if (pbox->x1 > pbox->x2 ||
706 pbox->y1 > pbox->y2 ||
707 pbox->x2 > dev_priv->w ||
708 pbox->y2 > dev_priv->h)
709 continue;
710
711 if ( flags & I810_FRONT ) {
712 BEGIN_LP_RING( 6 );
713 OUT_RING( BR00_BITBLT_CLIENT |
714 BR00_OP_COLOR_BLT | 0x3 );
715 OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
716 OUT_RING( (height << 16) | width );
717 OUT_RING( start );
718 OUT_RING( clear_color );
719 OUT_RING( 0 );
720 ADVANCE_LP_RING();
721 }
722
723 if ( flags & I810_BACK ) {
724 BEGIN_LP_RING( 6 );
725 OUT_RING( BR00_BITBLT_CLIENT |
726 BR00_OP_COLOR_BLT | 0x3 );
727 OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
728 OUT_RING( (height << 16) | width );
729 OUT_RING( dev_priv->back_offset + start );
730 OUT_RING( clear_color );
731 OUT_RING( 0 );
732 ADVANCE_LP_RING();
733 }
734
735 if ( flags & I810_DEPTH ) {
736 BEGIN_LP_RING( 6 );
737 OUT_RING( BR00_BITBLT_CLIENT |
738 BR00_OP_COLOR_BLT | 0x3 );
739 OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
740 OUT_RING( (height << 16) | width );
741 OUT_RING( dev_priv->depth_offset + start );
742 OUT_RING( clear_zval );
743 OUT_RING( 0 );
744 ADVANCE_LP_RING();
745 }
746 }
747}
748
749static void i810_dma_dispatch_swap( drm_device_t *dev )
750{
751 drm_i810_private_t *dev_priv = dev->dev_private;
752 drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
753 int nbox = sarea_priv->nbox;
754 drm_clip_rect_t *pbox = sarea_priv->boxes;
755 int pitch = dev_priv->pitch;
756 int cpp = 2;
757 int i;
758 RING_LOCALS;
759
760 DRM_DEBUG("swapbuffers\n");
761
762 i810_kernel_lost_context(dev);
763
764 if (nbox > I810_NR_SAREA_CLIPRECTS)
765 nbox = I810_NR_SAREA_CLIPRECTS;
766
767 for (i = 0 ; i < nbox; i++, pbox++)
768 {
769 unsigned int w = pbox->x2 - pbox->x1;
770 unsigned int h = pbox->y2 - pbox->y1;
771 unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
772 unsigned int start = dst;
773
774 if (pbox->x1 > pbox->x2 ||
775 pbox->y1 > pbox->y2 ||
776 pbox->x2 > dev_priv->w ||
777 pbox->y2 > dev_priv->h)
778 continue;
779
780 BEGIN_LP_RING( 6 );
781 OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
782 OUT_RING( pitch | (0xCC << 16));
783 OUT_RING( (h << 16) | (w * cpp));
784 if (dev_priv->current_page == 0)
785 OUT_RING(dev_priv->front_offset + start);
786 else
787 OUT_RING(dev_priv->back_offset + start);
788 OUT_RING( pitch );
789 if (dev_priv->current_page == 0)
790 OUT_RING(dev_priv->back_offset + start);
791 else
792 OUT_RING(dev_priv->front_offset + start);
793 ADVANCE_LP_RING();
794 }
795}
796
797
798static void i810_dma_dispatch_vertex(drm_device_t *dev,
799 drm_buf_t *buf,
800 int discard,
801 int used)
802{
803 drm_i810_private_t *dev_priv = dev->dev_private;
804 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
805 drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
806 drm_clip_rect_t *box = sarea_priv->boxes;
807 int nbox = sarea_priv->nbox;
808 unsigned long address = (unsigned long)buf->bus_address;
809 unsigned long start = address - dev->agp->base;
810 int i = 0;
811 RING_LOCALS;
812
813 i810_kernel_lost_context(dev);
814
815 if (nbox > I810_NR_SAREA_CLIPRECTS)
816 nbox = I810_NR_SAREA_CLIPRECTS;
817
818 if (used > 4*1024)
819 used = 0;
820
821 if (sarea_priv->dirty)
822 i810EmitState( dev );
823
824 if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
825 unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
826
827 *(u32 *)buf_priv->kernel_virtual = ((GFX_OP_PRIMITIVE | prim | ((used/4)-2)));
828
829 if (used & 4) {
830 *(u32 *)((u32)buf_priv->kernel_virtual + used) = 0;
831 used += 4;
832 }
833
834 i810_unmap_buffer(buf);
835 }
836
837 if (used) {
838 do {
839 if (i < nbox) {
840 BEGIN_LP_RING(4);
841 OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
842 SC_ENABLE );
843 OUT_RING( GFX_OP_SCISSOR_INFO );
844 OUT_RING( box[i].x1 | (box[i].y1<<16) );
845 OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) );
846 ADVANCE_LP_RING();
847 }
848
849 BEGIN_LP_RING(4);
850 OUT_RING( CMD_OP_BATCH_BUFFER );
851 OUT_RING( start | BB1_PROTECTED );
852 OUT_RING( start + used - 4 );
853 OUT_RING( 0 );
854 ADVANCE_LP_RING();
855
856 } while (++i < nbox);
857 }
858
859 if (discard) {
860 dev_priv->counter++;
861
862 (void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
863 I810_BUF_HARDWARE);
864
865 BEGIN_LP_RING(8);
866 OUT_RING( CMD_STORE_DWORD_IDX );
867 OUT_RING( 20 );
868 OUT_RING( dev_priv->counter );
869 OUT_RING( CMD_STORE_DWORD_IDX );
870 OUT_RING( buf_priv->my_use_idx );
871 OUT_RING( I810_BUF_FREE );
872 OUT_RING( CMD_REPORT_HEAD );
873 OUT_RING( 0 );
874 ADVANCE_LP_RING();
875 }
876}
877
878static void i810_dma_dispatch_flip( drm_device_t *dev )
879{
880 drm_i810_private_t *dev_priv = dev->dev_private;
881 int pitch = dev_priv->pitch;
882 RING_LOCALS;
883
884 DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
885 __FUNCTION__,
886 dev_priv->current_page,
887 dev_priv->sarea_priv->pf_current_page);
888
889 i810_kernel_lost_context(dev);
890
891 BEGIN_LP_RING( 2 );
892 OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
893 OUT_RING( 0 );
894 ADVANCE_LP_RING();
895
896 BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
897 /* On i815 at least ASYNC is buggy */
898 /* pitch<<5 is from 11.2.8 p158,
899 its the pitch / 8 then left shifted 8,
900 so (pitch >> 3) << 8 */
901 OUT_RING( CMD_OP_FRONTBUFFER_INFO | (pitch<<5) /*| ASYNC_FLIP */ );
902 if ( dev_priv->current_page == 0 ) {
903 OUT_RING( dev_priv->back_offset );
904 dev_priv->current_page = 1;
905 } else {
906 OUT_RING( dev_priv->front_offset );
907 dev_priv->current_page = 0;
908 }
909 OUT_RING(0);
910 ADVANCE_LP_RING();
911
912 BEGIN_LP_RING(2);
913 OUT_RING( CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP );
914 OUT_RING( 0 );
915 ADVANCE_LP_RING();
916
917 /* Increment the frame counter. The client-side 3D driver must
918 * throttle the framerate by waiting for this value before
919 * performing the swapbuffer ioctl.
920 */
921 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
922
923}
924
925static void i810_dma_quiescent(drm_device_t *dev)
926{
927 drm_i810_private_t *dev_priv = dev->dev_private;
928 RING_LOCALS;
929
930/* printk("%s\n", __FUNCTION__); */
931
932 i810_kernel_lost_context(dev);
933
934 BEGIN_LP_RING(4);
935 OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
936 OUT_RING( CMD_REPORT_HEAD );
937 OUT_RING( 0 );
938 OUT_RING( 0 );
939 ADVANCE_LP_RING();
940
941 i810_wait_ring( dev, dev_priv->ring.Size - 8 );
942}
943
944static int i810_flush_queue(drm_device_t *dev)
945{
946 drm_i810_private_t *dev_priv = dev->dev_private;
947 drm_device_dma_t *dma = dev->dma;
948 int i, ret = 0;
949 RING_LOCALS;
950
951/* printk("%s\n", __FUNCTION__); */
952
953 i810_kernel_lost_context(dev);
954
955 BEGIN_LP_RING(2);
956 OUT_RING( CMD_REPORT_HEAD );
957 OUT_RING( 0 );
958 ADVANCE_LP_RING();
959
960 i810_wait_ring( dev, dev_priv->ring.Size - 8 );
961
962 for (i = 0; i < dma->buf_count; i++) {
963 drm_buf_t *buf = dma->buflist[ i ];
964 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
965
966 int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
967 I810_BUF_FREE);
968
969 if (used == I810_BUF_HARDWARE)
970 DRM_DEBUG("reclaimed from HARDWARE\n");
971 if (used == I810_BUF_CLIENT)
972 DRM_DEBUG("still on client\n");
973 }
974
975 return ret;
976}
977
978/* Must be called with the lock held */
979void i810_reclaim_buffers(drm_device_t *dev, struct file *filp)
980{
981 drm_device_dma_t *dma = dev->dma;
982 int i;
983
984 if (!dma) return;
985 if (!dev->dev_private) return;
986 if (!dma->buflist) return;
987
988 i810_flush_queue(dev);
989
990 for (i = 0; i < dma->buf_count; i++) {
991 drm_buf_t *buf = dma->buflist[ i ];
992 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
993
994 if (buf->filp == filp && buf_priv) {
995 int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
996 I810_BUF_FREE);
997
998 if (used == I810_BUF_CLIENT)
999 DRM_DEBUG("reclaimed from client\n");
1000 if (buf_priv->currently_mapped == I810_BUF_MAPPED)
1001 buf_priv->currently_mapped = I810_BUF_UNMAPPED;
1002 }
1003 }
1004}
1005
1006int i810_flush_ioctl(struct inode *inode, struct file *filp,
1007 unsigned int cmd, unsigned long arg)
1008{
1009 drm_file_t *priv = filp->private_data;
1010 drm_device_t *dev = priv->head->dev;
1011
1012 LOCK_TEST_WITH_RETURN(dev, filp);
1013
1014 i810_flush_queue(dev);
1015 return 0;
1016}
1017
1018
1019static int i810_dma_vertex(struct inode *inode, struct file *filp,
1020 unsigned int cmd, unsigned long arg)
1021{
1022 drm_file_t *priv = filp->private_data;
1023 drm_device_t *dev = priv->head->dev;
1024 drm_device_dma_t *dma = dev->dma;
1025 drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1026 u32 *hw_status = dev_priv->hw_status_page;
1027 drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1028 dev_priv->sarea_priv;
1029 drm_i810_vertex_t vertex;
1030
1031 if (copy_from_user(&vertex, (drm_i810_vertex_t __user *)arg, sizeof(vertex)))
1032 return -EFAULT;
1033
1034 LOCK_TEST_WITH_RETURN(dev, filp);
1035
1036 DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
1037 vertex.idx, vertex.used, vertex.discard);
1038
1039 if (vertex.idx < 0 || vertex.idx > dma->buf_count)
1040 return -EINVAL;
1041
1042 i810_dma_dispatch_vertex( dev,
1043 dma->buflist[ vertex.idx ],
1044 vertex.discard, vertex.used );
1045
1046 atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
1047 atomic_inc(&dev->counts[_DRM_STAT_DMA]);
1048 sarea_priv->last_enqueue = dev_priv->counter-1;
1049 sarea_priv->last_dispatch = (int) hw_status[5];
1050
1051 return 0;
1052}
1053
1054
1055
1056static int i810_clear_bufs(struct inode *inode, struct file *filp,
1057 unsigned int cmd, unsigned long arg)
1058{
1059 drm_file_t *priv = filp->private_data;
1060 drm_device_t *dev = priv->head->dev;
1061 drm_i810_clear_t clear;
1062
1063 if (copy_from_user(&clear, (drm_i810_clear_t __user *)arg, sizeof(clear)))
1064 return -EFAULT;
1065
1066 LOCK_TEST_WITH_RETURN(dev, filp);
1067
1068 /* GH: Someone's doing nasty things... */
1069 if (!dev->dev_private) {
1070 return -EINVAL;
1071 }
1072
1073 i810_dma_dispatch_clear( dev, clear.flags,
1074 clear.clear_color,
1075 clear.clear_depth );
1076 return 0;
1077}
1078
1079static int i810_swap_bufs(struct inode *inode, struct file *filp,
1080 unsigned int cmd, unsigned long arg)
1081{
1082 drm_file_t *priv = filp->private_data;
1083 drm_device_t *dev = priv->head->dev;
1084
1085 DRM_DEBUG("i810_swap_bufs\n");
1086
1087 LOCK_TEST_WITH_RETURN(dev, filp);
1088
1089 i810_dma_dispatch_swap( dev );
1090 return 0;
1091}
1092
1093static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
1094 unsigned long arg)
1095{
1096 drm_file_t *priv = filp->private_data;
1097 drm_device_t *dev = priv->head->dev;
1098 drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1099 u32 *hw_status = dev_priv->hw_status_page;
1100 drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1101 dev_priv->sarea_priv;
1102
1103 sarea_priv->last_dispatch = (int) hw_status[5];
1104 return 0;
1105}
1106
1107static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
1108 unsigned long arg)
1109{
1110 drm_file_t *priv = filp->private_data;
1111 drm_device_t *dev = priv->head->dev;
1112 int retcode = 0;
1113 drm_i810_dma_t d;
1114 drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1115 u32 *hw_status = dev_priv->hw_status_page;
1116 drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1117 dev_priv->sarea_priv;
1118
1119 if (copy_from_user(&d, (drm_i810_dma_t __user *)arg, sizeof(d)))
1120 return -EFAULT;
1121
1122 LOCK_TEST_WITH_RETURN(dev, filp);
1123
1124 d.granted = 0;
1125
1126 retcode = i810_dma_get_buffer(dev, &d, filp);
1127
1128 DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
1129 current->pid, retcode, d.granted);
1130
1131 if (copy_to_user((drm_dma_t __user *)arg, &d, sizeof(d)))
1132 return -EFAULT;
1133 sarea_priv->last_dispatch = (int) hw_status[5];
1134
1135 return retcode;
1136}
1137
1138static int i810_copybuf(struct inode *inode,
1139 struct file *filp, unsigned int cmd, unsigned long arg)
1140{
1141 /* Never copy - 2.4.x doesn't need it */
1142 return 0;
1143}
1144
1145static int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
1146 unsigned long arg)
1147{
1148 /* Never copy - 2.4.x doesn't need it */
1149 return 0;
1150}
1151
1152static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used,
1153 unsigned int last_render)
1154{
1155 drm_i810_private_t *dev_priv = dev->dev_private;
1156 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
1157 drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
1158 unsigned long address = (unsigned long)buf->bus_address;
1159 unsigned long start = address - dev->agp->base;
1160 int u;
1161 RING_LOCALS;
1162
1163 i810_kernel_lost_context(dev);
1164
1165 u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
1166 I810_BUF_HARDWARE);
1167 if (u != I810_BUF_CLIENT) {
1168 DRM_DEBUG("MC found buffer that isn't mine!\n");
1169 }
1170
1171 if (used > 4*1024)
1172 used = 0;
1173
1174 sarea_priv->dirty = 0x7f;
1175
1176 DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n",
1177 address, used);
1178
1179 dev_priv->counter++;
1180 DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
1181 DRM_DEBUG("i810_dma_dispatch_mc\n");
1182 DRM_DEBUG("start : %lx\n", start);
1183 DRM_DEBUG("used : %d\n", used);
1184 DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
1185
1186 if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
1187 if (used & 4) {
1188 *(u32 *)((u32)buf_priv->virtual + used) = 0;
1189 used += 4;
1190 }
1191
1192 i810_unmap_buffer(buf);
1193 }
1194 BEGIN_LP_RING(4);
1195 OUT_RING( CMD_OP_BATCH_BUFFER );
1196 OUT_RING( start | BB1_PROTECTED );
1197 OUT_RING( start + used - 4 );
1198 OUT_RING( 0 );
1199 ADVANCE_LP_RING();
1200
1201
1202 BEGIN_LP_RING(8);
1203 OUT_RING( CMD_STORE_DWORD_IDX );
1204 OUT_RING( buf_priv->my_use_idx );
1205 OUT_RING( I810_BUF_FREE );
1206 OUT_RING( 0 );
1207
1208 OUT_RING( CMD_STORE_DWORD_IDX );
1209 OUT_RING( 16 );
1210 OUT_RING( last_render );
1211 OUT_RING( 0 );
1212 ADVANCE_LP_RING();
1213}
1214
1215static int i810_dma_mc(struct inode *inode, struct file *filp,
1216 unsigned int cmd, unsigned long arg)
1217{
1218 drm_file_t *priv = filp->private_data;
1219 drm_device_t *dev = priv->head->dev;
1220 drm_device_dma_t *dma = dev->dma;
1221 drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1222 u32 *hw_status = dev_priv->hw_status_page;
1223 drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1224 dev_priv->sarea_priv;
1225 drm_i810_mc_t mc;
1226
1227 if (copy_from_user(&mc, (drm_i810_mc_t __user *)arg, sizeof(mc)))
1228 return -EFAULT;
1229
1230 LOCK_TEST_WITH_RETURN(dev, filp);
1231
1232 if (mc.idx >= dma->buf_count || mc.idx < 0)
1233 return -EINVAL;
1234
1235 i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used,
1236 mc.last_render );
1237
1238 atomic_add(mc.used, &dev->counts[_DRM_STAT_SECONDARY]);
1239 atomic_inc(&dev->counts[_DRM_STAT_DMA]);
1240 sarea_priv->last_enqueue = dev_priv->counter-1;
1241 sarea_priv->last_dispatch = (int) hw_status[5];
1242
1243 return 0;
1244}
1245
1246static int i810_rstatus(struct inode *inode, struct file *filp,
1247 unsigned int cmd, unsigned long arg)
1248{
1249 drm_file_t *priv = filp->private_data;
1250 drm_device_t *dev = priv->head->dev;
1251 drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1252
1253 return (int)(((u32 *)(dev_priv->hw_status_page))[4]);
1254}
1255
1256static int i810_ov0_info(struct inode *inode, struct file *filp,
1257 unsigned int cmd, unsigned long arg)
1258{
1259 drm_file_t *priv = filp->private_data;
1260 drm_device_t *dev = priv->head->dev;
1261 drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1262 drm_i810_overlay_t data;
1263
1264 data.offset = dev_priv->overlay_offset;
1265 data.physical = dev_priv->overlay_physical;
1266 if (copy_to_user((drm_i810_overlay_t __user *)arg,&data,sizeof(data)))
1267 return -EFAULT;
1268 return 0;
1269}
1270
1271static int i810_fstatus(struct inode *inode, struct file *filp,
1272 unsigned int cmd, unsigned long arg)
1273{
1274 drm_file_t *priv = filp->private_data;
1275 drm_device_t *dev = priv->head->dev;
1276 drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1277
1278 LOCK_TEST_WITH_RETURN(dev, filp);
1279
1280 return I810_READ(0x30008);
1281}
1282
1283static int i810_ov0_flip(struct inode *inode, struct file *filp,
1284 unsigned int cmd, unsigned long arg)
1285{
1286 drm_file_t *priv = filp->private_data;
1287 drm_device_t *dev = priv->head->dev;
1288 drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1289
1290 LOCK_TEST_WITH_RETURN(dev, filp);
1291
1292 //Tell the overlay to update
1293 I810_WRITE(0x30000,dev_priv->overlay_physical | 0x80000000);
1294
1295 return 0;
1296}
1297
1298
1299/* Not sure why this isn't set all the time:
1300 */
1301static void i810_do_init_pageflip( drm_device_t *dev )
1302{
1303 drm_i810_private_t *dev_priv = dev->dev_private;
1304
1305 DRM_DEBUG("%s\n", __FUNCTION__);
1306 dev_priv->page_flipping = 1;
1307 dev_priv->current_page = 0;
1308 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
1309}
1310
1311static int i810_do_cleanup_pageflip( drm_device_t *dev )
1312{
1313 drm_i810_private_t *dev_priv = dev->dev_private;
1314
1315 DRM_DEBUG("%s\n", __FUNCTION__);
1316 if (dev_priv->current_page != 0)
1317 i810_dma_dispatch_flip( dev );
1318
1319 dev_priv->page_flipping = 0;
1320 return 0;
1321}
1322
1323static int i810_flip_bufs(struct inode *inode, struct file *filp,
1324 unsigned int cmd, unsigned long arg)
1325{
1326 drm_file_t *priv = filp->private_data;
1327 drm_device_t *dev = priv->head->dev;
1328 drm_i810_private_t *dev_priv = dev->dev_private;
1329
1330 DRM_DEBUG("%s\n", __FUNCTION__);
1331
1332 LOCK_TEST_WITH_RETURN(dev, filp);
1333
1334 if (!dev_priv->page_flipping)
1335 i810_do_init_pageflip( dev );
1336
1337 i810_dma_dispatch_flip( dev );
1338 return 0;
1339}
1340
1341void i810_driver_pretakedown(drm_device_t *dev)
1342{
1343 i810_dma_cleanup( dev );
1344}
1345
1346void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp)
1347{
1348 if (dev->dev_private) {
1349 drm_i810_private_t *dev_priv = dev->dev_private;
1350 if (dev_priv->page_flipping) {
1351 i810_do_cleanup_pageflip(dev);
1352 }
1353 }
1354}
1355
1356void i810_driver_release(drm_device_t *dev, struct file *filp)
1357{
1358 i810_reclaim_buffers(dev, filp);
1359}
1360
1361int i810_driver_dma_quiescent(drm_device_t *dev)
1362{
1363 i810_dma_quiescent( dev );
1364 return 0;
1365}
1366
1367drm_ioctl_desc_t i810_ioctls[] = {
1368 [DRM_IOCTL_NR(DRM_I810_INIT)] = { i810_dma_init, 1, 1 },
1369 [DRM_IOCTL_NR(DRM_I810_VERTEX)] = { i810_dma_vertex, 1, 0 },
1370 [DRM_IOCTL_NR(DRM_I810_CLEAR)] = { i810_clear_bufs, 1, 0 },
1371 [DRM_IOCTL_NR(DRM_I810_FLUSH)] = { i810_flush_ioctl, 1, 0 },
1372 [DRM_IOCTL_NR(DRM_I810_GETAGE)] = { i810_getage, 1, 0 },
1373 [DRM_IOCTL_NR(DRM_I810_GETBUF)] = { i810_getbuf, 1, 0 },
1374 [DRM_IOCTL_NR(DRM_I810_SWAP)] = { i810_swap_bufs, 1, 0 },
1375 [DRM_IOCTL_NR(DRM_I810_COPY)] = { i810_copybuf, 1, 0 },
1376 [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = { i810_docopy, 1, 0 },
1377 [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = { i810_ov0_info, 1, 0 },
1378 [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = { i810_fstatus, 1, 0 },
1379 [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = { i810_ov0_flip, 1, 0 },
1380 [DRM_IOCTL_NR(DRM_I810_MC)] = { i810_dma_mc, 1, 1 },
1381 [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = { i810_rstatus, 1, 0 },
1382 [DRM_IOCTL_NR(DRM_I810_FLIP)] = { i810_flip_bufs, 1, 0 }
1383};
1384
1385int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
diff --git a/drivers/char/drm/i810_drm.h b/drivers/char/drm/i810_drm.h
new file mode 100644
index 000000000000..73ac40563b1d
--- /dev/null
+++ b/drivers/char/drm/i810_drm.h
@@ -0,0 +1,289 @@
1#ifndef _I810_DRM_H_
2#define _I810_DRM_H_
3
4/* WARNING: These defines must be the same as what the Xserver uses.
5 * if you change them, you must change the defines in the Xserver.
6 */
7
8#ifndef _I810_DEFINES_
9#define _I810_DEFINES_
10
11#define I810_DMA_BUF_ORDER 12
12#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER)
13#define I810_DMA_BUF_NR 256
14#define I810_NR_SAREA_CLIPRECTS 8
15
16/* Each region is a minimum of 64k, and there are at most 64 of them.
17 */
18#define I810_NR_TEX_REGIONS 64
19#define I810_LOG_MIN_TEX_REGION_SIZE 16
20#endif
21
22#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
23#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
24#define I810_UPLOAD_CTX 0x4
25#define I810_UPLOAD_BUFFERS 0x8
26#define I810_UPLOAD_TEX0 0x10
27#define I810_UPLOAD_TEX1 0x20
28#define I810_UPLOAD_CLIPRECTS 0x40
29
30
31/* Indices into buf.Setup where various bits of state are mirrored per
32 * context and per buffer. These can be fired at the card as a unit,
33 * or in a piecewise fashion as required.
34 */
35
36/* Destbuffer state
37 * - backbuffer linear offset and pitch -- invarient in the current dri
38 * - zbuffer linear offset and pitch -- also invarient
39 * - drawing origin in back and depth buffers.
40 *
41 * Keep the depth/back buffer state here to accommodate private buffers
42 * in the future.
43 */
44#define I810_DESTREG_DI0 0 /* CMD_OP_DESTBUFFER_INFO (2 dwords) */
45#define I810_DESTREG_DI1 1
46#define I810_DESTREG_DV0 2 /* GFX_OP_DESTBUFFER_VARS (2 dwords) */
47#define I810_DESTREG_DV1 3
48#define I810_DESTREG_DR0 4 /* GFX_OP_DRAWRECT_INFO (4 dwords) */
49#define I810_DESTREG_DR1 5
50#define I810_DESTREG_DR2 6
51#define I810_DESTREG_DR3 7
52#define I810_DESTREG_DR4 8
53#define I810_DEST_SETUP_SIZE 10
54
55/* Context state
56 */
57#define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */
58#define I810_CTXREG_CF1 1
59#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
60#define I810_CTXREG_ST1 3
61#define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */
62#define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */
63#define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
64#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
65#define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
66#define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
67#define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
68#define I810_CTXREG_MA2 11 /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */
69#define I810_CTXREG_SDM 12 /* GFX_OP_SRC_DEST_MONO */
70#define I810_CTXREG_FOG 13 /* GFX_OP_FOG_COLOR */
71#define I810_CTXREG_B1 14 /* GFX_OP_BOOL_1 */
72#define I810_CTXREG_B2 15 /* GFX_OP_BOOL_2 */
73#define I810_CTXREG_LCS 16 /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */
74#define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */
75#define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */
76#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */
77#define I810_CTX_SETUP_SIZE 20
78
79/* Texture state (per tex unit)
80 */
81#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */
82#define I810_TEXREG_MI1 1
83#define I810_TEXREG_MI2 2
84#define I810_TEXREG_MI3 3
85#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */
86#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */
87#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */
88#define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */
89#define I810_TEX_SETUP_SIZE 8
90
91/* Flags for clear ioctl
92 */
93#define I810_FRONT 0x1
94#define I810_BACK 0x2
95#define I810_DEPTH 0x4
96
97typedef enum _drm_i810_init_func {
98 I810_INIT_DMA = 0x01,
99 I810_CLEANUP_DMA = 0x02,
100 I810_INIT_DMA_1_4 = 0x03
101 } drm_i810_init_func_t;
102
103/* This is the init structure after v1.2 */
104typedef struct _drm_i810_init {
105 drm_i810_init_func_t func;
106#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
107 int ring_map_idx;
108 int buffer_map_idx;
109#else
110 unsigned int mmio_offset;
111 unsigned int buffers_offset;
112#endif
113 int sarea_priv_offset;
114 unsigned int ring_start;
115 unsigned int ring_end;
116 unsigned int ring_size;
117 unsigned int front_offset;
118 unsigned int back_offset;
119 unsigned int depth_offset;
120 unsigned int overlay_offset;
121 unsigned int overlay_physical;
122 unsigned int w;
123 unsigned int h;
124 unsigned int pitch;
125 unsigned int pitch_bits;
126} drm_i810_init_t;
127
128/* This is the init structure prior to v1.2 */
129typedef struct _drm_i810_pre12_init {
130 drm_i810_init_func_t func;
131 unsigned int mmio_offset;
132 unsigned int buffers_offset;
133 int sarea_priv_offset;
134 unsigned int ring_start;
135 unsigned int ring_end;
136 unsigned int ring_size;
137 unsigned int front_offset;
138 unsigned int back_offset;
139 unsigned int depth_offset;
140 unsigned int w;
141 unsigned int h;
142 unsigned int pitch;
143 unsigned int pitch_bits;
144} drm_i810_pre12_init_t;
145
146/* Warning: If you change the SAREA structure you must change the Xserver
147 * structure as well */
148
149typedef struct _drm_i810_tex_region {
150 unsigned char next, prev; /* indices to form a circular LRU */
151 unsigned char in_use; /* owned by a client, or free? */
152 int age; /* tracked by clients to update local LRU's */
153} drm_i810_tex_region_t;
154
155typedef struct _drm_i810_sarea {
156 unsigned int ContextState[I810_CTX_SETUP_SIZE];
157 unsigned int BufferState[I810_DEST_SETUP_SIZE];
158 unsigned int TexState[2][I810_TEX_SETUP_SIZE];
159 unsigned int dirty;
160
161 unsigned int nbox;
162 drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
163
164 /* Maintain an LRU of contiguous regions of texture space. If
165 * you think you own a region of texture memory, and it has an
166 * age different to the one you set, then you are mistaken and
167 * it has been stolen by another client. If global texAge
168 * hasn't changed, there is no need to walk the list.
169 *
170 * These regions can be used as a proxy for the fine-grained
171 * texture information of other clients - by maintaining them
172 * in the same lru which is used to age their own textures,
173 * clients have an approximate lru for the whole of global
174 * texture space, and can make informed decisions as to which
175 * areas to kick out. There is no need to choose whether to
176 * kick out your own texture or someone else's - simply eject
177 * them all in LRU order.
178 */
179
180 drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS+1];
181 /* Last elt is sentinal */
182 int texAge; /* last time texture was uploaded */
183 int last_enqueue; /* last time a buffer was enqueued */
184 int last_dispatch; /* age of the most recently dispatched buffer */
185 int last_quiescent; /* */
186 int ctxOwner; /* last context to upload state */
187
188 int vertex_prim;
189
190 int pf_enabled; /* is pageflipping allowed? */
191 int pf_active;
192 int pf_current_page; /* which buffer is being displayed? */
193} drm_i810_sarea_t;
194
195/* WARNING: If you change any of these defines, make sure to change the
196 * defines in the Xserver file (xf86drmMga.h)
197 */
198
199/* i810 specific ioctls
200 * The device specific ioctl range is 0x40 to 0x79.
201 */
202#define DRM_I810_INIT 0x00
203#define DRM_I810_VERTEX 0x01
204#define DRM_I810_CLEAR 0x02
205#define DRM_I810_FLUSH 0x03
206#define DRM_I810_GETAGE 0x04
207#define DRM_I810_GETBUF 0x05
208#define DRM_I810_SWAP 0x06
209#define DRM_I810_COPY 0x07
210#define DRM_I810_DOCOPY 0x08
211#define DRM_I810_OV0INFO 0x09
212#define DRM_I810_FSTATUS 0x0a
213#define DRM_I810_OV0FLIP 0x0b
214#define DRM_I810_MC 0x0c
215#define DRM_I810_RSTATUS 0x0d
216#define DRM_I810_FLIP 0x0e
217
218#define DRM_IOCTL_I810_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I810_INIT, drm_i810_init_t)
219#define DRM_IOCTL_I810_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_I810_VERTEX, drm_i810_vertex_t)
220#define DRM_IOCTL_I810_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_I810_CLEAR, drm_i810_clear_t)
221#define DRM_IOCTL_I810_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_I810_FLUSH)
222#define DRM_IOCTL_I810_GETAGE DRM_IO( DRM_COMMAND_BASE + DRM_I810_GETAGE)
223#define DRM_IOCTL_I810_GETBUF DRM_IOWR(DRM_COMMAND_BASE + DRM_I810_GETBUF, drm_i810_dma_t)
224#define DRM_IOCTL_I810_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_I810_SWAP)
225#define DRM_IOCTL_I810_COPY DRM_IOW( DRM_COMMAND_BASE + DRM_I810_COPY, drm_i810_copy_t)
226#define DRM_IOCTL_I810_DOCOPY DRM_IO( DRM_COMMAND_BASE + DRM_I810_DOCOPY)
227#define DRM_IOCTL_I810_OV0INFO DRM_IOR( DRM_COMMAND_BASE + DRM_I810_OV0INFO, drm_i810_overlay_t)
228#define DRM_IOCTL_I810_FSTATUS DRM_IO ( DRM_COMMAND_BASE + DRM_I810_FSTATUS)
229#define DRM_IOCTL_I810_OV0FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I810_OV0FLIP)
230#define DRM_IOCTL_I810_MC DRM_IOW( DRM_COMMAND_BASE + DRM_I810_MC, drm_i810_mc_t)
231#define DRM_IOCTL_I810_RSTATUS DRM_IO ( DRM_COMMAND_BASE + DRM_I810_RSTATUS)
232#define DRM_IOCTL_I810_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I810_FLIP)
233
234typedef struct _drm_i810_clear {
235 int clear_color;
236 int clear_depth;
237 int flags;
238} drm_i810_clear_t;
239
240/* These may be placeholders if we have more cliprects than
241 * I810_NR_SAREA_CLIPRECTS. In that case, the client sets discard to
242 * false, indicating that the buffer will be dispatched again with a
243 * new set of cliprects.
244 */
245typedef struct _drm_i810_vertex {
246 int idx; /* buffer index */
247 int used; /* nr bytes in use */
248 int discard; /* client is finished with the buffer? */
249} drm_i810_vertex_t;
250
251typedef struct _drm_i810_copy_t {
252 int idx; /* buffer index */
253 int used; /* nr bytes in use */
254 void *address; /* Address to copy from */
255} drm_i810_copy_t;
256
257#define PR_TRIANGLES (0x0<<18)
258#define PR_TRISTRIP_0 (0x1<<18)
259#define PR_TRISTRIP_1 (0x2<<18)
260#define PR_TRIFAN (0x3<<18)
261#define PR_POLYGON (0x4<<18)
262#define PR_LINES (0x5<<18)
263#define PR_LINESTRIP (0x6<<18)
264#define PR_RECTS (0x7<<18)
265#define PR_MASK (0x7<<18)
266
267
268typedef struct drm_i810_dma {
269 void *virtual;
270 int request_idx;
271 int request_size;
272 int granted;
273} drm_i810_dma_t;
274
275typedef struct _drm_i810_overlay_t {
276 unsigned int offset; /* Address of the Overlay Regs */
277 unsigned int physical;
278} drm_i810_overlay_t;
279
280typedef struct _drm_i810_mc {
281 int idx; /* buffer index */
282 int used; /* nr bytes in use */
283 int num_blocks; /* number of GFXBlocks */
284 int *length; /* List of lengths for GFXBlocks (FUTURE)*/
285 unsigned int last_render; /* Last Render Request */
286} drm_i810_mc_t;
287
288
289#endif /* _I810_DRM_H_ */
diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c
new file mode 100644
index 000000000000..ff51b3259af9
--- /dev/null
+++ b/drivers/char/drm/i810_drv.c
@@ -0,0 +1,126 @@
1/* i810_drv.c -- I810 driver -*- linux-c -*-
2 * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Jeff Hartmann <jhartmann@valinux.com>
30 * Gareth Hughes <gareth@valinux.com>
31 */
32
33#include <linux/config.h>
34#include "drmP.h"
35#include "drm.h"
36#include "i810_drm.h"
37#include "i810_drv.h"
38
39#include "drm_pciids.h"
40
41static int postinit( struct drm_device *dev, unsigned long flags )
42{
43 /* i810 has 4 more counters */
44 dev->counters += 4;
45 dev->types[6] = _DRM_STAT_IRQ;
46 dev->types[7] = _DRM_STAT_PRIMARY;
47 dev->types[8] = _DRM_STAT_SECONDARY;
48 dev->types[9] = _DRM_STAT_DMA;
49
50 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
51 DRIVER_NAME,
52 DRIVER_MAJOR,
53 DRIVER_MINOR,
54 DRIVER_PATCHLEVEL,
55 DRIVER_DATE,
56 dev->primary.minor,
57 pci_pretty_name(dev->pdev)
58 );
59 return 0;
60}
61
62static int version( drm_version_t *version )
63{
64 int len;
65
66 version->version_major = DRIVER_MAJOR;
67 version->version_minor = DRIVER_MINOR;
68 version->version_patchlevel = DRIVER_PATCHLEVEL;
69 DRM_COPY( version->name, DRIVER_NAME );
70 DRM_COPY( version->date, DRIVER_DATE );
71 DRM_COPY( version->desc, DRIVER_DESC );
72 return 0;
73}
74
75static struct pci_device_id pciidlist[] = {
76 i810_PCI_IDS
77};
78
79extern drm_ioctl_desc_t i810_ioctls[];
80extern int i810_max_ioctl;
81
82static struct drm_driver driver = {
83 .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
84 .dev_priv_size = sizeof(drm_i810_buf_priv_t),
85 .pretakedown = i810_driver_pretakedown,
86 .prerelease = i810_driver_prerelease,
87 .release = i810_driver_release,
88 .dma_quiescent = i810_driver_dma_quiescent,
89 .reclaim_buffers = i810_reclaim_buffers,
90 .get_map_ofs = drm_core_get_map_ofs,
91 .get_reg_ofs = drm_core_get_reg_ofs,
92 .postinit = postinit,
93 .version = version,
94 .ioctls = i810_ioctls,
95 .fops = {
96 .owner = THIS_MODULE,
97 .open = drm_open,
98 .release = drm_release,
99 .ioctl = drm_ioctl,
100 .mmap = drm_mmap,
101 .poll = drm_poll,
102 .fasync = drm_fasync,
103 },
104 .pci_driver = {
105 .name = DRIVER_NAME,
106 .id_table = pciidlist,
107 },
108};
109
110static int __init i810_init(void)
111{
112 driver.num_ioctls = i810_max_ioctl;
113 return drm_init(&driver);
114}
115
116static void __exit i810_exit(void)
117{
118 drm_exit(&driver);
119}
120
121module_init(i810_init);
122module_exit(i810_exit);
123
124MODULE_AUTHOR( DRIVER_AUTHOR );
125MODULE_DESCRIPTION( DRIVER_DESC );
126MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
new file mode 100644
index 000000000000..fa23ca454e57
--- /dev/null
+++ b/drivers/char/drm/i810_drv.h
@@ -0,0 +1,236 @@
1/* i810_drv.h -- Private header for the Matrox g200/g400 driver -*- linux-c -*-
2 * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
28 * Jeff Hartmann <jhartmann@valinux.com>
29 *
30 */
31
32#ifndef _I810_DRV_H_
33#define _I810_DRV_H_
34
35/* General customization:
36 */
37
38#define DRIVER_AUTHOR "VA Linux Systems Inc."
39
40#define DRIVER_NAME "i810"
41#define DRIVER_DESC "Intel i810"
42#define DRIVER_DATE "20030605"
43
44/* Interface history
45 *
46 * 1.1 - XFree86 4.1
47 * 1.2 - XvMC interfaces
48 * - XFree86 4.2
49 * 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility)
50 * - Remove requirement for interrupt (leave stubs again)
51 * 1.3 - Add page flipping.
52 * 1.4 - fix DRM interface
53 */
54#define DRIVER_MAJOR 1
55#define DRIVER_MINOR 4
56#define DRIVER_PATCHLEVEL 0
57
58typedef struct drm_i810_buf_priv {
59 u32 *in_use;
60 int my_use_idx;
61 int currently_mapped;
62 void *virtual;
63 void *kernel_virtual;
64} drm_i810_buf_priv_t;
65
66typedef struct _drm_i810_ring_buffer{
67 int tail_mask;
68 unsigned long Start;
69 unsigned long End;
70 unsigned long Size;
71 u8 *virtual_start;
72 int head;
73 int tail;
74 int space;
75} drm_i810_ring_buffer_t;
76
77typedef struct drm_i810_private {
78 drm_map_t *sarea_map;
79 drm_map_t *mmio_map;
80
81 drm_i810_sarea_t *sarea_priv;
82 drm_i810_ring_buffer_t ring;
83
84 void *hw_status_page;
85 unsigned long counter;
86
87 dma_addr_t dma_status_page;
88
89 drm_buf_t *mmap_buffer;
90
91
92 u32 front_di1, back_di1, zi1;
93
94 int back_offset;
95 int depth_offset;
96 int overlay_offset;
97 int overlay_physical;
98 int w, h;
99 int pitch;
100 int back_pitch;
101 int depth_pitch;
102
103 int do_boxes;
104 int dma_used;
105
106 int current_page;
107 int page_flipping;
108
109 wait_queue_head_t irq_queue;
110 atomic_t irq_received;
111 atomic_t irq_emitted;
112
113 int front_offset;
114} drm_i810_private_t;
115
116 /* i810_dma.c */
117extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp);
118extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
119
120extern int i810_driver_dma_quiescent(drm_device_t *dev);
121extern void i810_driver_release(drm_device_t *dev, struct file *filp);
122extern void i810_driver_pretakedown(drm_device_t *dev);
123extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp);
124
125#define I810_BASE(reg) ((unsigned long) \
126 dev_priv->mmio_map->handle)
127#define I810_ADDR(reg) (I810_BASE(reg) + reg)
128#define I810_DEREF(reg) *(__volatile__ int *)I810_ADDR(reg)
129#define I810_READ(reg) I810_DEREF(reg)
130#define I810_WRITE(reg,val) do { I810_DEREF(reg) = val; } while (0)
131#define I810_DEREF16(reg) *(__volatile__ u16 *)I810_ADDR(reg)
132#define I810_READ16(reg) I810_DEREF16(reg)
133#define I810_WRITE16(reg,val) do { I810_DEREF16(reg) = val; } while (0)
134
135#define I810_VERBOSE 0
136#define RING_LOCALS unsigned int outring, ringmask; \
137 volatile char *virt;
138
139#define BEGIN_LP_RING(n) do { \
140 if (I810_VERBOSE) \
141 DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \
142 if (dev_priv->ring.space < n*4) \
143 i810_wait_ring(dev, n*4); \
144 dev_priv->ring.space -= n*4; \
145 outring = dev_priv->ring.tail; \
146 ringmask = dev_priv->ring.tail_mask; \
147 virt = dev_priv->ring.virtual_start; \
148} while (0)
149
150#define ADVANCE_LP_RING() do { \
151 if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \
152 dev_priv->ring.tail = outring; \
153 I810_WRITE(LP_RING + RING_TAIL, outring); \
154} while(0)
155
156#define OUT_RING(n) do { \
157 if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
158 *(volatile unsigned int *)(virt + outring) = n; \
159 outring += 4; \
160 outring &= ringmask; \
161} while (0)
162
163#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
164#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
165#define CMD_REPORT_HEAD (7<<23)
166#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1)
167#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1)
168
169#define INST_PARSER_CLIENT 0x00000000
170#define INST_OP_FLUSH 0x02000000
171#define INST_FLUSH_MAP_CACHE 0x00000001
172
173
174#define BB1_START_ADDR_MASK (~0x7)
175#define BB1_PROTECTED (1<<0)
176#define BB1_UNPROTECTED (0<<0)
177#define BB2_END_ADDR_MASK (~0x7)
178
179#define I810REG_HWSTAM 0x02098
180#define I810REG_INT_IDENTITY_R 0x020a4
181#define I810REG_INT_MASK_R 0x020a8
182#define I810REG_INT_ENABLE_R 0x020a0
183
184#define LP_RING 0x2030
185#define HP_RING 0x2040
186#define RING_TAIL 0x00
187#define TAIL_ADDR 0x000FFFF8
188#define RING_HEAD 0x04
189#define HEAD_WRAP_COUNT 0xFFE00000
190#define HEAD_WRAP_ONE 0x00200000
191#define HEAD_ADDR 0x001FFFFC
192#define RING_START 0x08
193#define START_ADDR 0x00FFFFF8
194#define RING_LEN 0x0C
195#define RING_NR_PAGES 0x000FF000
196#define RING_REPORT_MASK 0x00000006
197#define RING_REPORT_64K 0x00000002
198#define RING_REPORT_128K 0x00000004
199#define RING_NO_REPORT 0x00000000
200#define RING_VALID_MASK 0x00000001
201#define RING_VALID 0x00000001
202#define RING_INVALID 0x00000000
203
204#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19))
205#define SC_UPDATE_SCISSOR (0x1<<1)
206#define SC_ENABLE_MASK (0x1<<0)
207#define SC_ENABLE (0x1<<0)
208
209#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
210#define SCI_YMIN_MASK (0xffff<<16)
211#define SCI_XMIN_MASK (0xffff<<0)
212#define SCI_YMAX_MASK (0xffff<<16)
213#define SCI_XMAX_MASK (0xffff<<0)
214
215#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
216#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
217#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x2)
218#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
219#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
220#define GFX_OP_PRIMITIVE ((0x3<<29)|(0x1f<<24))
221
222#define CMD_OP_Z_BUFFER_INFO ((0x0<<29)|(0x16<<23))
223#define CMD_OP_DESTBUFFER_INFO ((0x0<<29)|(0x15<<23))
224#define CMD_OP_FRONTBUFFER_INFO ((0x0<<29)|(0x14<<23))
225#define CMD_OP_WAIT_FOR_EVENT ((0x0<<29)|(0x03<<23))
226
227#define BR00_BITBLT_CLIENT 0x40000000
228#define BR00_OP_COLOR_BLT 0x10000000
229#define BR00_OP_SRC_COPY_BLT 0x10C00000
230#define BR13_SOLID_PATTERN 0x80000000
231
232#define WAIT_FOR_PLANE_A_SCANLINES (1<<1)
233#define WAIT_FOR_PLANE_A_FLIP (1<<2)
234#define WAIT_FOR_VBLANK (1<<3)
235
236#endif
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
new file mode 100644
index 000000000000..98adccf8e434
--- /dev/null
+++ b/drivers/char/drm/i830_dma.c
@@ -0,0 +1,1588 @@
1/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
2 * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
28 * Jeff Hartmann <jhartmann@valinux.com>
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Abraham vd Merwe <abraham@2d3d.co.za>
31 *
32 */
33
34#include "drmP.h"
35#include "drm.h"
36#include "i830_drm.h"
37#include "i830_drv.h"
38#include <linux/interrupt.h> /* For task queue support */
39#include <linux/pagemap.h> /* For FASTCALL on unlock_page() */
40#include <linux/delay.h>
41#include <asm/uaccess.h>
42
43#define I830_BUF_FREE 2
44#define I830_BUF_CLIENT 1
45#define I830_BUF_HARDWARE 0
46
47#define I830_BUF_UNMAPPED 0
48#define I830_BUF_MAPPED 1
49
50#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
51#define down_write down
52#define up_write up
53#endif
54
55static drm_buf_t *i830_freelist_get(drm_device_t *dev)
56{
57 drm_device_dma_t *dma = dev->dma;
58 int i;
59 int used;
60
61 /* Linear search might not be the best solution */
62
63 for (i = 0; i < dma->buf_count; i++) {
64 drm_buf_t *buf = dma->buflist[ i ];
65 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
66 /* In use is already a pointer */
67 used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
68 I830_BUF_CLIENT);
69 if(used == I830_BUF_FREE) {
70 return buf;
71 }
72 }
73 return NULL;
74}
75
76/* This should only be called if the buffer is not sent to the hardware
77 * yet, the hardware updates in use for us once its on the ring buffer.
78 */
79
80static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf)
81{
82 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
83 int used;
84
85 /* In use is already a pointer */
86 used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
87 if(used != I830_BUF_CLIENT) {
88 DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
89 return -EINVAL;
90 }
91
92 return 0;
93}
94
95static struct file_operations i830_buffer_fops = {
96 .open = drm_open,
97 .flush = drm_flush,
98 .release = drm_release,
99 .ioctl = drm_ioctl,
100 .mmap = i830_mmap_buffers,
101 .fasync = drm_fasync,
102};
103
104int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
105{
106 drm_file_t *priv = filp->private_data;
107 drm_device_t *dev;
108 drm_i830_private_t *dev_priv;
109 drm_buf_t *buf;
110 drm_i830_buf_priv_t *buf_priv;
111
112 lock_kernel();
113 dev = priv->head->dev;
114 dev_priv = dev->dev_private;
115 buf = dev_priv->mmap_buffer;
116 buf_priv = buf->dev_private;
117
118 vma->vm_flags |= (VM_IO | VM_DONTCOPY);
119 vma->vm_file = filp;
120
121 buf_priv->currently_mapped = I830_BUF_MAPPED;
122 unlock_kernel();
123
124 if (io_remap_pfn_range(vma, vma->vm_start,
125 VM_OFFSET(vma) >> PAGE_SHIFT,
126 vma->vm_end - vma->vm_start,
127 vma->vm_page_prot)) return -EAGAIN;
128 return 0;
129}
130
131static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
132{
133 drm_file_t *priv = filp->private_data;
134 drm_device_t *dev = priv->head->dev;
135 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
136 drm_i830_private_t *dev_priv = dev->dev_private;
137 struct file_operations *old_fops;
138 unsigned long virtual;
139 int retcode = 0;
140
141 if(buf_priv->currently_mapped == I830_BUF_MAPPED) return -EINVAL;
142
143 down_write( &current->mm->mmap_sem );
144 old_fops = filp->f_op;
145 filp->f_op = &i830_buffer_fops;
146 dev_priv->mmap_buffer = buf;
147 virtual = do_mmap(filp, 0, buf->total, PROT_READ|PROT_WRITE,
148 MAP_SHARED, buf->bus_address);
149 dev_priv->mmap_buffer = NULL;
150 filp->f_op = old_fops;
151 if (IS_ERR((void *)virtual)) { /* ugh */
152 /* Real error */
153 DRM_ERROR("mmap error\n");
154 retcode = virtual;
155 buf_priv->virtual = NULL;
156 } else {
157 buf_priv->virtual = (void __user *)virtual;
158 }
159 up_write( &current->mm->mmap_sem );
160
161 return retcode;
162}
163
164static int i830_unmap_buffer(drm_buf_t *buf)
165{
166 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
167 int retcode = 0;
168
169 if(buf_priv->currently_mapped != I830_BUF_MAPPED)
170 return -EINVAL;
171
172 down_write(&current->mm->mmap_sem);
173 retcode = do_munmap(current->mm,
174 (unsigned long)buf_priv->virtual,
175 (size_t) buf->total);
176 up_write(&current->mm->mmap_sem);
177
178 buf_priv->currently_mapped = I830_BUF_UNMAPPED;
179 buf_priv->virtual = NULL;
180
181 return retcode;
182}
183
184static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d,
185 struct file *filp)
186{
187 drm_buf_t *buf;
188 drm_i830_buf_priv_t *buf_priv;
189 int retcode = 0;
190
191 buf = i830_freelist_get(dev);
192 if (!buf) {
193 retcode = -ENOMEM;
194 DRM_DEBUG("retcode=%d\n", retcode);
195 return retcode;
196 }
197
198 retcode = i830_map_buffer(buf, filp);
199 if(retcode) {
200 i830_freelist_put(dev, buf);
201 DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
202 return retcode;
203 }
204 buf->filp = filp;
205 buf_priv = buf->dev_private;
206 d->granted = 1;
207 d->request_idx = buf->idx;
208 d->request_size = buf->total;
209 d->virtual = buf_priv->virtual;
210
211 return retcode;
212}
213
214static int i830_dma_cleanup(drm_device_t *dev)
215{
216 drm_device_dma_t *dma = dev->dma;
217
218 /* Make sure interrupts are disabled here because the uninstall ioctl
219 * may not have been called from userspace and after dev_private
220 * is freed, it's too late.
221 */
222 if ( dev->irq_enabled ) drm_irq_uninstall(dev);
223
224 if (dev->dev_private) {
225 int i;
226 drm_i830_private_t *dev_priv =
227 (drm_i830_private_t *) dev->dev_private;
228
229 if (dev_priv->ring.virtual_start) {
230 drm_ioremapfree((void *) dev_priv->ring.virtual_start,
231 dev_priv->ring.Size, dev);
232 }
233 if (dev_priv->hw_status_page) {
234 pci_free_consistent(dev->pdev, PAGE_SIZE,
235 dev_priv->hw_status_page,
236 dev_priv->dma_status_page);
237 /* Need to rewrite hardware status page */
238 I830_WRITE(0x02080, 0x1ffff000);
239 }
240
241 drm_free(dev->dev_private, sizeof(drm_i830_private_t),
242 DRM_MEM_DRIVER);
243 dev->dev_private = NULL;
244
245 for (i = 0; i < dma->buf_count; i++) {
246 drm_buf_t *buf = dma->buflist[ i ];
247 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
248 if ( buf_priv->kernel_virtual && buf->total )
249 drm_ioremapfree(buf_priv->kernel_virtual, buf->total, dev);
250 }
251 }
252 return 0;
253}
254
255int i830_wait_ring(drm_device_t *dev, int n, const char *caller)
256{
257 drm_i830_private_t *dev_priv = dev->dev_private;
258 drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
259 int iters = 0;
260 unsigned long end;
261 unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
262
263 end = jiffies + (HZ*3);
264 while (ring->space < n) {
265 ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
266 ring->space = ring->head - (ring->tail+8);
267 if (ring->space < 0) ring->space += ring->Size;
268
269 if (ring->head != last_head) {
270 end = jiffies + (HZ*3);
271 last_head = ring->head;
272 }
273
274 iters++;
275 if(time_before(end, jiffies)) {
276 DRM_ERROR("space: %d wanted %d\n", ring->space, n);
277 DRM_ERROR("lockup\n");
278 goto out_wait_ring;
279 }
280 udelay(1);
281 dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
282 }
283
284out_wait_ring:
285 return iters;
286}
287
288static void i830_kernel_lost_context(drm_device_t *dev)
289{
290 drm_i830_private_t *dev_priv = dev->dev_private;
291 drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
292
293 ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
294 ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
295 ring->space = ring->head - (ring->tail+8);
296 if (ring->space < 0) ring->space += ring->Size;
297
298 if (ring->head == ring->tail)
299 dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
300}
301
302static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv)
303{
304 drm_device_dma_t *dma = dev->dma;
305 int my_idx = 36;
306 u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
307 int i;
308
309 if(dma->buf_count > 1019) {
310 /* Not enough space in the status page for the freelist */
311 return -EINVAL;
312 }
313
314 for (i = 0; i < dma->buf_count; i++) {
315 drm_buf_t *buf = dma->buflist[ i ];
316 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
317
318 buf_priv->in_use = hw_status++;
319 buf_priv->my_use_idx = my_idx;
320 my_idx += 4;
321
322 *buf_priv->in_use = I830_BUF_FREE;
323
324 buf_priv->kernel_virtual = drm_ioremap(buf->bus_address,
325 buf->total, dev);
326 }
327 return 0;
328}
329
330static int i830_dma_initialize(drm_device_t *dev,
331 drm_i830_private_t *dev_priv,
332 drm_i830_init_t *init)
333{
334 struct list_head *list;
335
336 memset(dev_priv, 0, sizeof(drm_i830_private_t));
337
338 list_for_each(list, &dev->maplist->head) {
339 drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
340 if( r_list->map &&
341 r_list->map->type == _DRM_SHM &&
342 r_list->map->flags & _DRM_CONTAINS_LOCK ) {
343 dev_priv->sarea_map = r_list->map;
344 break;
345 }
346 }
347
348 if(!dev_priv->sarea_map) {
349 dev->dev_private = (void *)dev_priv;
350 i830_dma_cleanup(dev);
351 DRM_ERROR("can not find sarea!\n");
352 return -EINVAL;
353 }
354 dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
355 if(!dev_priv->mmio_map) {
356 dev->dev_private = (void *)dev_priv;
357 i830_dma_cleanup(dev);
358 DRM_ERROR("can not find mmio map!\n");
359 return -EINVAL;
360 }
361 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
362 if(!dev->agp_buffer_map) {
363 dev->dev_private = (void *)dev_priv;
364 i830_dma_cleanup(dev);
365 DRM_ERROR("can not find dma buffer map!\n");
366 return -EINVAL;
367 }
368
369 dev_priv->sarea_priv = (drm_i830_sarea_t *)
370 ((u8 *)dev_priv->sarea_map->handle +
371 init->sarea_priv_offset);
372
373 dev_priv->ring.Start = init->ring_start;
374 dev_priv->ring.End = init->ring_end;
375 dev_priv->ring.Size = init->ring_size;
376
377 dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
378 init->ring_start,
379 init->ring_size, dev);
380
381 if (dev_priv->ring.virtual_start == NULL) {
382 dev->dev_private = (void *) dev_priv;
383 i830_dma_cleanup(dev);
384 DRM_ERROR("can not ioremap virtual address for"
385 " ring buffer\n");
386 return -ENOMEM;
387 }
388
389 dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
390
391 dev_priv->w = init->w;
392 dev_priv->h = init->h;
393 dev_priv->pitch = init->pitch;
394 dev_priv->back_offset = init->back_offset;
395 dev_priv->depth_offset = init->depth_offset;
396 dev_priv->front_offset = init->front_offset;
397
398 dev_priv->front_di1 = init->front_offset | init->pitch_bits;
399 dev_priv->back_di1 = init->back_offset | init->pitch_bits;
400 dev_priv->zi1 = init->depth_offset | init->pitch_bits;
401
402 DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1);
403 DRM_DEBUG("back_offset %x\n", dev_priv->back_offset);
404 DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1);
405 DRM_DEBUG("pitch_bits %x\n", init->pitch_bits);
406
407 dev_priv->cpp = init->cpp;
408 /* We are using separate values as placeholders for mechanisms for
409 * private backbuffer/depthbuffer usage.
410 */
411
412 dev_priv->back_pitch = init->back_pitch;
413 dev_priv->depth_pitch = init->depth_pitch;
414 dev_priv->do_boxes = 0;
415 dev_priv->use_mi_batchbuffer_start = 0;
416
417 /* Program Hardware Status Page */
418 dev_priv->hw_status_page =
419 pci_alloc_consistent(dev->pdev, PAGE_SIZE,
420 &dev_priv->dma_status_page);
421 if (!dev_priv->hw_status_page) {
422 dev->dev_private = (void *)dev_priv;
423 i830_dma_cleanup(dev);
424 DRM_ERROR("Can not allocate hardware status page\n");
425 return -ENOMEM;
426 }
427 memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
428 DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
429
430 I830_WRITE(0x02080, dev_priv->dma_status_page);
431 DRM_DEBUG("Enabled hardware status page\n");
432
433 /* Now we need to init our freelist */
434 if(i830_freelist_init(dev, dev_priv) != 0) {
435 dev->dev_private = (void *)dev_priv;
436 i830_dma_cleanup(dev);
437 DRM_ERROR("Not enough space in the status page for"
438 " the freelist\n");
439 return -ENOMEM;
440 }
441 dev->dev_private = (void *)dev_priv;
442
443 return 0;
444}
445
446static int i830_dma_init(struct inode *inode, struct file *filp,
447 unsigned int cmd, unsigned long arg)
448{
449 drm_file_t *priv = filp->private_data;
450 drm_device_t *dev = priv->head->dev;
451 drm_i830_private_t *dev_priv;
452 drm_i830_init_t init;
453 int retcode = 0;
454
455 if (copy_from_user(&init, (void * __user) arg, sizeof(init)))
456 return -EFAULT;
457
458 switch(init.func) {
459 case I830_INIT_DMA:
460 dev_priv = drm_alloc(sizeof(drm_i830_private_t),
461 DRM_MEM_DRIVER);
462 if(dev_priv == NULL) return -ENOMEM;
463 retcode = i830_dma_initialize(dev, dev_priv, &init);
464 break;
465 case I830_CLEANUP_DMA:
466 retcode = i830_dma_cleanup(dev);
467 break;
468 default:
469 retcode = -EINVAL;
470 break;
471 }
472
473 return retcode;
474}
475
476#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
477#define ST1_ENABLE (1<<16)
478#define ST1_MASK (0xffff)
479
480/* Most efficient way to verify state for the i830 is as it is
481 * emitted. Non-conformant state is silently dropped.
482 */
483static void i830EmitContextVerified( drm_device_t *dev,
484 unsigned int *code )
485{
486 drm_i830_private_t *dev_priv = dev->dev_private;
487 int i, j = 0;
488 unsigned int tmp;
489 RING_LOCALS;
490
491 BEGIN_LP_RING( I830_CTX_SETUP_SIZE + 4 );
492
493 for ( i = 0 ; i < I830_CTXREG_BLENDCOLR0 ; i++ ) {
494 tmp = code[i];
495 if ((tmp & (7<<29)) == CMD_3D &&
496 (tmp & (0x1f<<24)) < (0x1d<<24)) {
497 OUT_RING( tmp );
498 j++;
499 } else {
500 DRM_ERROR("Skipping %d\n", i);
501 }
502 }
503
504 OUT_RING( STATE3D_CONST_BLEND_COLOR_CMD );
505 OUT_RING( code[I830_CTXREG_BLENDCOLR] );
506 j += 2;
507
508 for ( i = I830_CTXREG_VF ; i < I830_CTXREG_MCSB0 ; i++ ) {
509 tmp = code[i];
510 if ((tmp & (7<<29)) == CMD_3D &&
511 (tmp & (0x1f<<24)) < (0x1d<<24)) {
512 OUT_RING( tmp );
513 j++;
514 } else {
515 DRM_ERROR("Skipping %d\n", i);
516 }
517 }
518
519 OUT_RING( STATE3D_MAP_COORD_SETBIND_CMD );
520 OUT_RING( code[I830_CTXREG_MCSB1] );
521 j += 2;
522
523 if (j & 1)
524 OUT_RING( 0 );
525
526 ADVANCE_LP_RING();
527}
528
529static void i830EmitTexVerified( drm_device_t *dev, unsigned int *code )
530{
531 drm_i830_private_t *dev_priv = dev->dev_private;
532 int i, j = 0;
533 unsigned int tmp;
534 RING_LOCALS;
535
536 if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO ||
537 (code[I830_TEXREG_MI0] & ~(0xf*LOAD_TEXTURE_MAP0)) ==
538 (STATE3D_LOAD_STATE_IMMEDIATE_2|4)) {
539
540 BEGIN_LP_RING( I830_TEX_SETUP_SIZE );
541
542 OUT_RING( code[I830_TEXREG_MI0] ); /* TM0LI */
543 OUT_RING( code[I830_TEXREG_MI1] ); /* TM0S0 */
544 OUT_RING( code[I830_TEXREG_MI2] ); /* TM0S1 */
545 OUT_RING( code[I830_TEXREG_MI3] ); /* TM0S2 */
546 OUT_RING( code[I830_TEXREG_MI4] ); /* TM0S3 */
547 OUT_RING( code[I830_TEXREG_MI5] ); /* TM0S4 */
548
549 for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) {
550 tmp = code[i];
551 OUT_RING( tmp );
552 j++;
553 }
554
555 if (j & 1)
556 OUT_RING( 0 );
557
558 ADVANCE_LP_RING();
559 }
560 else
561 printk("rejected packet %x\n", code[0]);
562}
563
564static void i830EmitTexBlendVerified( drm_device_t *dev,
565 unsigned int *code,
566 unsigned int num)
567{
568 drm_i830_private_t *dev_priv = dev->dev_private;
569 int i, j = 0;
570 unsigned int tmp;
571 RING_LOCALS;
572
573 if (!num)
574 return;
575
576 BEGIN_LP_RING( num + 1 );
577
578 for ( i = 0 ; i < num ; i++ ) {
579 tmp = code[i];
580 OUT_RING( tmp );
581 j++;
582 }
583
584 if (j & 1)
585 OUT_RING( 0 );
586
587 ADVANCE_LP_RING();
588}
589
590static void i830EmitTexPalette( drm_device_t *dev,
591 unsigned int *palette,
592 int number,
593 int is_shared )
594{
595 drm_i830_private_t *dev_priv = dev->dev_private;
596 int i;
597 RING_LOCALS;
598
599 return;
600
601 BEGIN_LP_RING( 258 );
602
603 if(is_shared == 1) {
604 OUT_RING(CMD_OP_MAP_PALETTE_LOAD |
605 MAP_PALETTE_NUM(0) |
606 MAP_PALETTE_BOTH);
607 } else {
608 OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
609 }
610 for(i = 0; i < 256; i++) {
611 OUT_RING(palette[i]);
612 }
613 OUT_RING(0);
614 /* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop!
615 */
616}
617
618/* Need to do some additional checking when setting the dest buffer.
619 */
620static void i830EmitDestVerified( drm_device_t *dev,
621 unsigned int *code )
622{
623 drm_i830_private_t *dev_priv = dev->dev_private;
624 unsigned int tmp;
625 RING_LOCALS;
626
627 BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 10 );
628
629
630 tmp = code[I830_DESTREG_CBUFADDR];
631 if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
632 if (((int)outring) & 8) {
633 OUT_RING(0);
634 OUT_RING(0);
635 }
636
637 OUT_RING( CMD_OP_DESTBUFFER_INFO );
638 OUT_RING( BUF_3D_ID_COLOR_BACK |
639 BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
640 BUF_3D_USE_FENCE);
641 OUT_RING( tmp );
642 OUT_RING( 0 );
643
644 OUT_RING( CMD_OP_DESTBUFFER_INFO );
645 OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE |
646 BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
647 OUT_RING( dev_priv->zi1 );
648 OUT_RING( 0 );
649 } else {
650 DRM_ERROR("bad di1 %x (allow %x or %x)\n",
651 tmp, dev_priv->front_di1, dev_priv->back_di1);
652 }
653
654 /* invarient:
655 */
656
657
658 OUT_RING( GFX_OP_DESTBUFFER_VARS );
659 OUT_RING( code[I830_DESTREG_DV1] );
660
661 OUT_RING( GFX_OP_DRAWRECT_INFO );
662 OUT_RING( code[I830_DESTREG_DR1] );
663 OUT_RING( code[I830_DESTREG_DR2] );
664 OUT_RING( code[I830_DESTREG_DR3] );
665 OUT_RING( code[I830_DESTREG_DR4] );
666
667 /* Need to verify this */
668 tmp = code[I830_DESTREG_SENABLE];
669 if((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
670 OUT_RING( tmp );
671 } else {
672 DRM_ERROR("bad scissor enable\n");
673 OUT_RING( 0 );
674 }
675
676 OUT_RING( GFX_OP_SCISSOR_RECT );
677 OUT_RING( code[I830_DESTREG_SR1] );
678 OUT_RING( code[I830_DESTREG_SR2] );
679 OUT_RING( 0 );
680
681 ADVANCE_LP_RING();
682}
683
684static void i830EmitStippleVerified( drm_device_t *dev,
685 unsigned int *code )
686{
687 drm_i830_private_t *dev_priv = dev->dev_private;
688 RING_LOCALS;
689
690 BEGIN_LP_RING( 2 );
691 OUT_RING( GFX_OP_STIPPLE );
692 OUT_RING( code[1] );
693 ADVANCE_LP_RING();
694}
695
696
697static void i830EmitState( drm_device_t *dev )
698{
699 drm_i830_private_t *dev_priv = dev->dev_private;
700 drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
701 unsigned int dirty = sarea_priv->dirty;
702
703 DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
704
705 if (dirty & I830_UPLOAD_BUFFERS) {
706 i830EmitDestVerified( dev, sarea_priv->BufferState );
707 sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
708 }
709
710 if (dirty & I830_UPLOAD_CTX) {
711 i830EmitContextVerified( dev, sarea_priv->ContextState );
712 sarea_priv->dirty &= ~I830_UPLOAD_CTX;
713 }
714
715 if (dirty & I830_UPLOAD_TEX0) {
716 i830EmitTexVerified( dev, sarea_priv->TexState[0] );
717 sarea_priv->dirty &= ~I830_UPLOAD_TEX0;
718 }
719
720 if (dirty & I830_UPLOAD_TEX1) {
721 i830EmitTexVerified( dev, sarea_priv->TexState[1] );
722 sarea_priv->dirty &= ~I830_UPLOAD_TEX1;
723 }
724
725 if (dirty & I830_UPLOAD_TEXBLEND0) {
726 i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[0],
727 sarea_priv->TexBlendStateWordsUsed[0]);
728 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0;
729 }
730
731 if (dirty & I830_UPLOAD_TEXBLEND1) {
732 i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[1],
733 sarea_priv->TexBlendStateWordsUsed[1]);
734 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1;
735 }
736
737 if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
738 i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
739 } else {
740 if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
741 i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
742 sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
743 }
744 if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
745 i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
746 sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
747 }
748
749 /* 1.3:
750 */
751#if 0
752 if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) {
753 i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0);
754 sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
755 }
756 if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) {
757 i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0);
758 sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
759 }
760#endif
761 }
762
763 /* 1.3:
764 */
765 if (dirty & I830_UPLOAD_STIPPLE) {
766 i830EmitStippleVerified( dev,
767 sarea_priv->StippleState);
768 sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE;
769 }
770
771 if (dirty & I830_UPLOAD_TEX2) {
772 i830EmitTexVerified( dev, sarea_priv->TexState2 );
773 sarea_priv->dirty &= ~I830_UPLOAD_TEX2;
774 }
775
776 if (dirty & I830_UPLOAD_TEX3) {
777 i830EmitTexVerified( dev, sarea_priv->TexState3 );
778 sarea_priv->dirty &= ~I830_UPLOAD_TEX3;
779 }
780
781
782 if (dirty & I830_UPLOAD_TEXBLEND2) {
783 i830EmitTexBlendVerified(
784 dev,
785 sarea_priv->TexBlendState2,
786 sarea_priv->TexBlendStateWordsUsed2);
787
788 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2;
789 }
790
791 if (dirty & I830_UPLOAD_TEXBLEND3) {
792 i830EmitTexBlendVerified(
793 dev,
794 sarea_priv->TexBlendState3,
795 sarea_priv->TexBlendStateWordsUsed3);
796 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3;
797 }
798}
799
800/* ================================================================
801 * Performance monitoring functions
802 */
803
804static void i830_fill_box( drm_device_t *dev,
805 int x, int y, int w, int h,
806 int r, int g, int b )
807{
808 drm_i830_private_t *dev_priv = dev->dev_private;
809 u32 color;
810 unsigned int BR13, CMD;
811 RING_LOCALS;
812
813 BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1<<24);
814 CMD = XY_COLOR_BLT_CMD;
815 x += dev_priv->sarea_priv->boxes[0].x1;
816 y += dev_priv->sarea_priv->boxes[0].y1;
817
818 if (dev_priv->cpp == 4) {
819 BR13 |= (1<<25);
820 CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
821 color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
822 } else {
823 color = (((r & 0xf8) << 8) |
824 ((g & 0xfc) << 3) |
825 ((b & 0xf8) >> 3));
826 }
827
828 BEGIN_LP_RING( 6 );
829 OUT_RING( CMD );
830 OUT_RING( BR13 );
831 OUT_RING( (y << 16) | x );
832 OUT_RING( ((y+h) << 16) | (x+w) );
833
834 if ( dev_priv->current_page == 1 ) {
835 OUT_RING( dev_priv->front_offset );
836 } else {
837 OUT_RING( dev_priv->back_offset );
838 }
839
840 OUT_RING( color );
841 ADVANCE_LP_RING();
842}
843
844static void i830_cp_performance_boxes( drm_device_t *dev )
845{
846 drm_i830_private_t *dev_priv = dev->dev_private;
847
848 /* Purple box for page flipping
849 */
850 if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP )
851 i830_fill_box( dev, 4, 4, 8, 8, 255, 0, 255 );
852
853 /* Red box if we have to wait for idle at any point
854 */
855 if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT )
856 i830_fill_box( dev, 16, 4, 8, 8, 255, 0, 0 );
857
858 /* Blue box: lost context?
859 */
860 if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT )
861 i830_fill_box( dev, 28, 4, 8, 8, 0, 0, 255 );
862
863 /* Yellow box for texture swaps
864 */
865 if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD )
866 i830_fill_box( dev, 40, 4, 8, 8, 255, 255, 0 );
867
868 /* Green box if hardware never idles (as far as we can tell)
869 */
870 if ( !(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY) )
871 i830_fill_box( dev, 64, 4, 8, 8, 0, 255, 0 );
872
873
874 /* Draw bars indicating number of buffers allocated
875 * (not a great measure, easily confused)
876 */
877 if (dev_priv->dma_used) {
878 int bar = dev_priv->dma_used / 10240;
879 if (bar > 100) bar = 100;
880 if (bar < 1) bar = 1;
881 i830_fill_box( dev, 4, 16, bar, 4, 196, 128, 128 );
882 dev_priv->dma_used = 0;
883 }
884
885 dev_priv->sarea_priv->perf_boxes = 0;
886}
887
888static void i830_dma_dispatch_clear( drm_device_t *dev, int flags,
889 unsigned int clear_color,
890 unsigned int clear_zval,
891 unsigned int clear_depthmask)
892{
893 drm_i830_private_t *dev_priv = dev->dev_private;
894 drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
895 int nbox = sarea_priv->nbox;
896 drm_clip_rect_t *pbox = sarea_priv->boxes;
897 int pitch = dev_priv->pitch;
898 int cpp = dev_priv->cpp;
899 int i;
900 unsigned int BR13, CMD, D_CMD;
901 RING_LOCALS;
902
903
904 if ( dev_priv->current_page == 1 ) {
905 unsigned int tmp = flags;
906
907 flags &= ~(I830_FRONT | I830_BACK);
908 if ( tmp & I830_FRONT ) flags |= I830_BACK;
909 if ( tmp & I830_BACK ) flags |= I830_FRONT;
910 }
911
912 i830_kernel_lost_context(dev);
913
914 switch(cpp) {
915 case 2:
916 BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
917 D_CMD = CMD = XY_COLOR_BLT_CMD;
918 break;
919 case 4:
920 BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
921 CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
922 XY_COLOR_BLT_WRITE_RGB);
923 D_CMD = XY_COLOR_BLT_CMD;
924 if(clear_depthmask & 0x00ffffff)
925 D_CMD |= XY_COLOR_BLT_WRITE_RGB;
926 if(clear_depthmask & 0xff000000)
927 D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
928 break;
929 default:
930 BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
931 D_CMD = CMD = XY_COLOR_BLT_CMD;
932 break;
933 }
934
935 if (nbox > I830_NR_SAREA_CLIPRECTS)
936 nbox = I830_NR_SAREA_CLIPRECTS;
937
938 for (i = 0 ; i < nbox ; i++, pbox++) {
939 if (pbox->x1 > pbox->x2 ||
940 pbox->y1 > pbox->y2 ||
941 pbox->x2 > dev_priv->w ||
942 pbox->y2 > dev_priv->h)
943 continue;
944
945 if ( flags & I830_FRONT ) {
946 DRM_DEBUG("clear front\n");
947 BEGIN_LP_RING( 6 );
948 OUT_RING( CMD );
949 OUT_RING( BR13 );
950 OUT_RING( (pbox->y1 << 16) | pbox->x1 );
951 OUT_RING( (pbox->y2 << 16) | pbox->x2 );
952 OUT_RING( dev_priv->front_offset );
953 OUT_RING( clear_color );
954 ADVANCE_LP_RING();
955 }
956
957 if ( flags & I830_BACK ) {
958 DRM_DEBUG("clear back\n");
959 BEGIN_LP_RING( 6 );
960 OUT_RING( CMD );
961 OUT_RING( BR13 );
962 OUT_RING( (pbox->y1 << 16) | pbox->x1 );
963 OUT_RING( (pbox->y2 << 16) | pbox->x2 );
964 OUT_RING( dev_priv->back_offset );
965 OUT_RING( clear_color );
966 ADVANCE_LP_RING();
967 }
968
969 if ( flags & I830_DEPTH ) {
970 DRM_DEBUG("clear depth\n");
971 BEGIN_LP_RING( 6 );
972 OUT_RING( D_CMD );
973 OUT_RING( BR13 );
974 OUT_RING( (pbox->y1 << 16) | pbox->x1 );
975 OUT_RING( (pbox->y2 << 16) | pbox->x2 );
976 OUT_RING( dev_priv->depth_offset );
977 OUT_RING( clear_zval );
978 ADVANCE_LP_RING();
979 }
980 }
981}
982
983static void i830_dma_dispatch_swap( drm_device_t *dev )
984{
985 drm_i830_private_t *dev_priv = dev->dev_private;
986 drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
987 int nbox = sarea_priv->nbox;
988 drm_clip_rect_t *pbox = sarea_priv->boxes;
989 int pitch = dev_priv->pitch;
990 int cpp = dev_priv->cpp;
991 int i;
992 unsigned int CMD, BR13;
993 RING_LOCALS;
994
995 DRM_DEBUG("swapbuffers\n");
996
997 i830_kernel_lost_context(dev);
998
999 if (dev_priv->do_boxes)
1000 i830_cp_performance_boxes( dev );
1001
1002 switch(cpp) {
1003 case 2:
1004 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
1005 CMD = XY_SRC_COPY_BLT_CMD;
1006 break;
1007 case 4:
1008 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
1009 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
1010 XY_SRC_COPY_BLT_WRITE_RGB);
1011 break;
1012 default:
1013 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
1014 CMD = XY_SRC_COPY_BLT_CMD;
1015 break;
1016 }
1017
1018
1019 if (nbox > I830_NR_SAREA_CLIPRECTS)
1020 nbox = I830_NR_SAREA_CLIPRECTS;
1021
1022 for (i = 0 ; i < nbox; i++, pbox++)
1023 {
1024 if (pbox->x1 > pbox->x2 ||
1025 pbox->y1 > pbox->y2 ||
1026 pbox->x2 > dev_priv->w ||
1027 pbox->y2 > dev_priv->h)
1028 continue;
1029
1030 DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
1031 pbox->x1, pbox->y1,
1032 pbox->x2, pbox->y2);
1033
1034 BEGIN_LP_RING( 8 );
1035 OUT_RING( CMD );
1036 OUT_RING( BR13 );
1037 OUT_RING( (pbox->y1 << 16) | pbox->x1 );
1038 OUT_RING( (pbox->y2 << 16) | pbox->x2 );
1039
1040 if (dev_priv->current_page == 0)
1041 OUT_RING( dev_priv->front_offset );
1042 else
1043 OUT_RING( dev_priv->back_offset );
1044
1045 OUT_RING( (pbox->y1 << 16) | pbox->x1 );
1046 OUT_RING( BR13 & 0xffff );
1047
1048 if (dev_priv->current_page == 0)
1049 OUT_RING( dev_priv->back_offset );
1050 else
1051 OUT_RING( dev_priv->front_offset );
1052
1053 ADVANCE_LP_RING();
1054 }
1055}
1056
1057static void i830_dma_dispatch_flip( drm_device_t *dev )
1058{
1059 drm_i830_private_t *dev_priv = dev->dev_private;
1060 RING_LOCALS;
1061
1062 DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
1063 __FUNCTION__,
1064 dev_priv->current_page,
1065 dev_priv->sarea_priv->pf_current_page);
1066
1067 i830_kernel_lost_context(dev);
1068
1069 if (dev_priv->do_boxes) {
1070 dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;
1071 i830_cp_performance_boxes( dev );
1072 }
1073
1074
1075 BEGIN_LP_RING( 2 );
1076 OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
1077 OUT_RING( 0 );
1078 ADVANCE_LP_RING();
1079
1080 BEGIN_LP_RING( 6 );
1081 OUT_RING( CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP );
1082 OUT_RING( 0 );
1083 if ( dev_priv->current_page == 0 ) {
1084 OUT_RING( dev_priv->back_offset );
1085 dev_priv->current_page = 1;
1086 } else {
1087 OUT_RING( dev_priv->front_offset );
1088 dev_priv->current_page = 0;
1089 }
1090 OUT_RING(0);
1091 ADVANCE_LP_RING();
1092
1093
1094 BEGIN_LP_RING( 2 );
1095 OUT_RING( MI_WAIT_FOR_EVENT |
1096 MI_WAIT_FOR_PLANE_A_FLIP );
1097 OUT_RING( 0 );
1098 ADVANCE_LP_RING();
1099
1100
1101 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
1102}
1103
1104static void i830_dma_dispatch_vertex(drm_device_t *dev,
1105 drm_buf_t *buf,
1106 int discard,
1107 int used)
1108{
1109 drm_i830_private_t *dev_priv = dev->dev_private;
1110 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
1111 drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
1112 drm_clip_rect_t *box = sarea_priv->boxes;
1113 int nbox = sarea_priv->nbox;
1114 unsigned long address = (unsigned long)buf->bus_address;
1115 unsigned long start = address - dev->agp->base;
1116 int i = 0, u;
1117 RING_LOCALS;
1118
1119 i830_kernel_lost_context(dev);
1120
1121 if (nbox > I830_NR_SAREA_CLIPRECTS)
1122 nbox = I830_NR_SAREA_CLIPRECTS;
1123
1124 if (discard) {
1125 u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
1126 I830_BUF_HARDWARE);
1127 if(u != I830_BUF_CLIENT) {
1128 DRM_DEBUG("xxxx 2\n");
1129 }
1130 }
1131
1132 if (used > 4*1023)
1133 used = 0;
1134
1135 if (sarea_priv->dirty)
1136 i830EmitState( dev );
1137
1138 DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
1139 address, used, nbox);
1140
1141 dev_priv->counter++;
1142 DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter);
1143 DRM_DEBUG( "i830_dma_dispatch\n");
1144 DRM_DEBUG( "start : %lx\n", start);
1145 DRM_DEBUG( "used : %d\n", used);
1146 DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4);
1147
1148 if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
1149 u32 *vp = buf_priv->kernel_virtual;
1150
1151 vp[0] = (GFX_OP_PRIMITIVE |
1152 sarea_priv->vertex_prim |
1153 ((used/4)-2));
1154
1155 if (dev_priv->use_mi_batchbuffer_start) {
1156 vp[used/4] = MI_BATCH_BUFFER_END;
1157 used += 4;
1158 }
1159
1160 if (used & 4) {
1161 vp[used/4] = 0;
1162 used += 4;
1163 }
1164
1165 i830_unmap_buffer(buf);
1166 }
1167
1168 if (used) {
1169 do {
1170 if (i < nbox) {
1171 BEGIN_LP_RING(6);
1172 OUT_RING( GFX_OP_DRAWRECT_INFO );
1173 OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR1] );
1174 OUT_RING( box[i].x1 | (box[i].y1<<16) );
1175 OUT_RING( box[i].x2 | (box[i].y2<<16) );
1176 OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR4] );
1177 OUT_RING( 0 );
1178 ADVANCE_LP_RING();
1179 }
1180
1181 if (dev_priv->use_mi_batchbuffer_start) {
1182 BEGIN_LP_RING(2);
1183 OUT_RING( MI_BATCH_BUFFER_START | (2<<6) );
1184 OUT_RING( start | MI_BATCH_NON_SECURE );
1185 ADVANCE_LP_RING();
1186 }
1187 else {
1188 BEGIN_LP_RING(4);
1189 OUT_RING( MI_BATCH_BUFFER );
1190 OUT_RING( start | MI_BATCH_NON_SECURE );
1191 OUT_RING( start + used - 4 );
1192 OUT_RING( 0 );
1193 ADVANCE_LP_RING();
1194 }
1195
1196 } while (++i < nbox);
1197 }
1198
1199 if (discard) {
1200 dev_priv->counter++;
1201
1202 (void) cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
1203 I830_BUF_HARDWARE);
1204
1205 BEGIN_LP_RING(8);
1206 OUT_RING( CMD_STORE_DWORD_IDX );
1207 OUT_RING( 20 );
1208 OUT_RING( dev_priv->counter );
1209 OUT_RING( CMD_STORE_DWORD_IDX );
1210 OUT_RING( buf_priv->my_use_idx );
1211 OUT_RING( I830_BUF_FREE );
1212 OUT_RING( CMD_REPORT_HEAD );
1213 OUT_RING( 0 );
1214 ADVANCE_LP_RING();
1215 }
1216}
1217
1218
1219static void i830_dma_quiescent(drm_device_t *dev)
1220{
1221 drm_i830_private_t *dev_priv = dev->dev_private;
1222 RING_LOCALS;
1223
1224 i830_kernel_lost_context(dev);
1225
1226 BEGIN_LP_RING(4);
1227 OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
1228 OUT_RING( CMD_REPORT_HEAD );
1229 OUT_RING( 0 );
1230 OUT_RING( 0 );
1231 ADVANCE_LP_RING();
1232
1233 i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
1234}
1235
1236static int i830_flush_queue(drm_device_t *dev)
1237{
1238 drm_i830_private_t *dev_priv = dev->dev_private;
1239 drm_device_dma_t *dma = dev->dma;
1240 int i, ret = 0;
1241 RING_LOCALS;
1242
1243 i830_kernel_lost_context(dev);
1244
1245 BEGIN_LP_RING(2);
1246 OUT_RING( CMD_REPORT_HEAD );
1247 OUT_RING( 0 );
1248 ADVANCE_LP_RING();
1249
1250 i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
1251
1252 for (i = 0; i < dma->buf_count; i++) {
1253 drm_buf_t *buf = dma->buflist[ i ];
1254 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
1255
1256 int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
1257 I830_BUF_FREE);
1258
1259 if (used == I830_BUF_HARDWARE)
1260 DRM_DEBUG("reclaimed from HARDWARE\n");
1261 if (used == I830_BUF_CLIENT)
1262 DRM_DEBUG("still on client\n");
1263 }
1264
1265 return ret;
1266}
1267
1268/* Must be called with the lock held */
1269void i830_reclaim_buffers(drm_device_t *dev, struct file *filp)
1270{
1271 drm_device_dma_t *dma = dev->dma;
1272 int i;
1273
1274 if (!dma) return;
1275 if (!dev->dev_private) return;
1276 if (!dma->buflist) return;
1277
1278 i830_flush_queue(dev);
1279
1280 for (i = 0; i < dma->buf_count; i++) {
1281 drm_buf_t *buf = dma->buflist[ i ];
1282 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
1283
1284 if (buf->filp == filp && buf_priv) {
1285 int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
1286 I830_BUF_FREE);
1287
1288 if (used == I830_BUF_CLIENT)
1289 DRM_DEBUG("reclaimed from client\n");
1290 if(buf_priv->currently_mapped == I830_BUF_MAPPED)
1291 buf_priv->currently_mapped = I830_BUF_UNMAPPED;
1292 }
1293 }
1294}
1295
1296static int i830_flush_ioctl(struct inode *inode, struct file *filp,
1297 unsigned int cmd, unsigned long arg)
1298{
1299 drm_file_t *priv = filp->private_data;
1300 drm_device_t *dev = priv->head->dev;
1301
1302 LOCK_TEST_WITH_RETURN(dev, filp);
1303
1304 i830_flush_queue(dev);
1305 return 0;
1306}
1307
1308static int i830_dma_vertex(struct inode *inode, struct file *filp,
1309 unsigned int cmd, unsigned long arg)
1310{
1311 drm_file_t *priv = filp->private_data;
1312 drm_device_t *dev = priv->head->dev;
1313 drm_device_dma_t *dma = dev->dma;
1314 drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
1315 u32 *hw_status = dev_priv->hw_status_page;
1316 drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
1317 dev_priv->sarea_priv;
1318 drm_i830_vertex_t vertex;
1319
1320 if (copy_from_user(&vertex, (drm_i830_vertex_t __user *)arg, sizeof(vertex)))
1321 return -EFAULT;
1322
1323 LOCK_TEST_WITH_RETURN(dev, filp);
1324
1325 DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n",
1326 vertex.idx, vertex.used, vertex.discard);
1327
1328 if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
1329
1330 i830_dma_dispatch_vertex( dev,
1331 dma->buflist[ vertex.idx ],
1332 vertex.discard, vertex.used );
1333
1334 sarea_priv->last_enqueue = dev_priv->counter-1;
1335 sarea_priv->last_dispatch = (int) hw_status[5];
1336
1337 return 0;
1338}
1339
1340static int i830_clear_bufs(struct inode *inode, struct file *filp,
1341 unsigned int cmd, unsigned long arg)
1342{
1343 drm_file_t *priv = filp->private_data;
1344 drm_device_t *dev = priv->head->dev;
1345 drm_i830_clear_t clear;
1346
1347 if (copy_from_user(&clear, (drm_i830_clear_t __user *)arg, sizeof(clear)))
1348 return -EFAULT;
1349
1350 LOCK_TEST_WITH_RETURN(dev, filp);
1351
1352 /* GH: Someone's doing nasty things... */
1353 if (!dev->dev_private) {
1354 return -EINVAL;
1355 }
1356
1357 i830_dma_dispatch_clear( dev, clear.flags,
1358 clear.clear_color,
1359 clear.clear_depth,
1360 clear.clear_depthmask);
1361 return 0;
1362}
1363
1364static int i830_swap_bufs(struct inode *inode, struct file *filp,
1365 unsigned int cmd, unsigned long arg)
1366{
1367 drm_file_t *priv = filp->private_data;
1368 drm_device_t *dev = priv->head->dev;
1369
1370 DRM_DEBUG("i830_swap_bufs\n");
1371
1372 LOCK_TEST_WITH_RETURN(dev, filp);
1373
1374 i830_dma_dispatch_swap( dev );
1375 return 0;
1376}
1377
1378
1379
1380/* Not sure why this isn't set all the time:
1381 */
1382static void i830_do_init_pageflip( drm_device_t *dev )
1383{
1384 drm_i830_private_t *dev_priv = dev->dev_private;
1385
1386 DRM_DEBUG("%s\n", __FUNCTION__);
1387 dev_priv->page_flipping = 1;
1388 dev_priv->current_page = 0;
1389 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
1390}
1391
1392static int i830_do_cleanup_pageflip( drm_device_t *dev )
1393{
1394 drm_i830_private_t *dev_priv = dev->dev_private;
1395
1396 DRM_DEBUG("%s\n", __FUNCTION__);
1397 if (dev_priv->current_page != 0)
1398 i830_dma_dispatch_flip( dev );
1399
1400 dev_priv->page_flipping = 0;
1401 return 0;
1402}
1403
1404static int i830_flip_bufs(struct inode *inode, struct file *filp,
1405 unsigned int cmd, unsigned long arg)
1406{
1407 drm_file_t *priv = filp->private_data;
1408 drm_device_t *dev = priv->head->dev;
1409 drm_i830_private_t *dev_priv = dev->dev_private;
1410
1411 DRM_DEBUG("%s\n", __FUNCTION__);
1412
1413 LOCK_TEST_WITH_RETURN(dev, filp);
1414
1415 if (!dev_priv->page_flipping)
1416 i830_do_init_pageflip( dev );
1417
1418 i830_dma_dispatch_flip( dev );
1419 return 0;
1420}
1421
1422static int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
1423 unsigned long arg)
1424{
1425 drm_file_t *priv = filp->private_data;
1426 drm_device_t *dev = priv->head->dev;
1427 drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
1428 u32 *hw_status = dev_priv->hw_status_page;
1429 drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
1430 dev_priv->sarea_priv;
1431
1432 sarea_priv->last_dispatch = (int) hw_status[5];
1433 return 0;
1434}
1435
1436static int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
1437 unsigned long arg)
1438{
1439 drm_file_t *priv = filp->private_data;
1440 drm_device_t *dev = priv->head->dev;
1441 int retcode = 0;
1442 drm_i830_dma_t d;
1443 drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
1444 u32 *hw_status = dev_priv->hw_status_page;
1445 drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
1446 dev_priv->sarea_priv;
1447
1448 DRM_DEBUG("getbuf\n");
1449 if (copy_from_user(&d, (drm_i830_dma_t __user *)arg, sizeof(d)))
1450 return -EFAULT;
1451
1452 LOCK_TEST_WITH_RETURN(dev, filp);
1453
1454 d.granted = 0;
1455
1456 retcode = i830_dma_get_buffer(dev, &d, filp);
1457
1458 DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
1459 current->pid, retcode, d.granted);
1460
1461 if (copy_to_user((drm_dma_t __user *)arg, &d, sizeof(d)))
1462 return -EFAULT;
1463 sarea_priv->last_dispatch = (int) hw_status[5];
1464
1465 return retcode;
1466}
1467
1468static int i830_copybuf(struct inode *inode,
1469 struct file *filp, unsigned int cmd, unsigned long arg)
1470{
1471 /* Never copy - 2.4.x doesn't need it */
1472 return 0;
1473}
1474
1475static int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
1476 unsigned long arg)
1477{
1478 return 0;
1479}
1480
1481
1482
1483static int i830_getparam( struct inode *inode, struct file *filp,
1484 unsigned int cmd, unsigned long arg )
1485{
1486 drm_file_t *priv = filp->private_data;
1487 drm_device_t *dev = priv->head->dev;
1488 drm_i830_private_t *dev_priv = dev->dev_private;
1489 drm_i830_getparam_t param;
1490 int value;
1491
1492 if ( !dev_priv ) {
1493 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1494 return -EINVAL;
1495 }
1496
1497 if (copy_from_user(&param, (drm_i830_getparam_t __user *)arg, sizeof(param) ))
1498 return -EFAULT;
1499
1500 switch( param.param ) {
1501 case I830_PARAM_IRQ_ACTIVE:
1502 value = dev->irq_enabled;
1503 break;
1504 default:
1505 return -EINVAL;
1506 }
1507
1508 if ( copy_to_user( param.value, &value, sizeof(int) ) ) {
1509 DRM_ERROR( "copy_to_user\n" );
1510 return -EFAULT;
1511 }
1512
1513 return 0;
1514}
1515
1516
1517static int i830_setparam( struct inode *inode, struct file *filp,
1518 unsigned int cmd, unsigned long arg )
1519{
1520 drm_file_t *priv = filp->private_data;
1521 drm_device_t *dev = priv->head->dev;
1522 drm_i830_private_t *dev_priv = dev->dev_private;
1523 drm_i830_setparam_t param;
1524
1525 if ( !dev_priv ) {
1526 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1527 return -EINVAL;
1528 }
1529
1530 if (copy_from_user(&param, (drm_i830_setparam_t __user *)arg, sizeof(param) ))
1531 return -EFAULT;
1532
1533 switch( param.param ) {
1534 case I830_SETPARAM_USE_MI_BATCHBUFFER_START:
1535 dev_priv->use_mi_batchbuffer_start = param.value;
1536 break;
1537 default:
1538 return -EINVAL;
1539 }
1540
1541 return 0;
1542}
1543
1544
1545void i830_driver_pretakedown(drm_device_t *dev)
1546{
1547 i830_dma_cleanup( dev );
1548}
1549
1550void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp)
1551{
1552 if (dev->dev_private) {
1553 drm_i830_private_t *dev_priv = dev->dev_private;
1554 if (dev_priv->page_flipping) {
1555 i830_do_cleanup_pageflip(dev);
1556 }
1557 }
1558}
1559
1560void i830_driver_release(drm_device_t *dev, struct file *filp)
1561{
1562 i830_reclaim_buffers(dev, filp);
1563}
1564
1565int i830_driver_dma_quiescent(drm_device_t *dev)
1566{
1567 i830_dma_quiescent( dev );
1568 return 0;
1569}
1570
1571drm_ioctl_desc_t i830_ioctls[] = {
1572 [DRM_IOCTL_NR(DRM_I830_INIT)] = { i830_dma_init, 1, 1 },
1573 [DRM_IOCTL_NR(DRM_I830_VERTEX)] = { i830_dma_vertex, 1, 0 },
1574 [DRM_IOCTL_NR(DRM_I830_CLEAR)] = { i830_clear_bufs, 1, 0 },
1575 [DRM_IOCTL_NR(DRM_I830_FLUSH)] = { i830_flush_ioctl, 1, 0 },
1576 [DRM_IOCTL_NR(DRM_I830_GETAGE)] = { i830_getage, 1, 0 },
1577 [DRM_IOCTL_NR(DRM_I830_GETBUF)] = { i830_getbuf, 1, 0 },
1578 [DRM_IOCTL_NR(DRM_I830_SWAP)] = { i830_swap_bufs, 1, 0 },
1579 [DRM_IOCTL_NR(DRM_I830_COPY)] = { i830_copybuf, 1, 0 },
1580 [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = { i830_docopy, 1, 0 },
1581 [DRM_IOCTL_NR(DRM_I830_FLIP)] = { i830_flip_bufs, 1, 0 },
1582 [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = { i830_irq_emit, 1, 0 },
1583 [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = { i830_irq_wait, 1, 0 },
1584 [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = { i830_getparam, 1, 0 },
1585 [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = { i830_setparam, 1, 0 }
1586};
1587
1588int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
diff --git a/drivers/char/drm/i830_drm.h b/drivers/char/drm/i830_drm.h
new file mode 100644
index 000000000000..03382c0beee3
--- /dev/null
+++ b/drivers/char/drm/i830_drm.h
@@ -0,0 +1,350 @@
1#ifndef _I830_DRM_H_
2#define _I830_DRM_H_
3
4/* WARNING: These defines must be the same as what the Xserver uses.
5 * if you change them, you must change the defines in the Xserver.
6 *
7 * KW: Actually, you can't ever change them because doing so would
8 * break backwards compatibility.
9 */
10
11#ifndef _I830_DEFINES_
12#define _I830_DEFINES_
13
14#define I830_DMA_BUF_ORDER 12
15#define I830_DMA_BUF_SZ (1<<I830_DMA_BUF_ORDER)
16#define I830_DMA_BUF_NR 256
17#define I830_NR_SAREA_CLIPRECTS 8
18
19/* Each region is a minimum of 64k, and there are at most 64 of them.
20 */
21#define I830_NR_TEX_REGIONS 64
22#define I830_LOG_MIN_TEX_REGION_SIZE 16
23
24/* KW: These aren't correct but someone set them to two and then
25 * released the module. Now we can't change them as doing so would
26 * break backwards compatibility.
27 */
28#define I830_TEXTURE_COUNT 2
29#define I830_TEXBLEND_COUNT I830_TEXTURE_COUNT
30
31#define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */
32
33#define I830_UPLOAD_CTX 0x1
34#define I830_UPLOAD_BUFFERS 0x2
35#define I830_UPLOAD_CLIPRECTS 0x4
36#define I830_UPLOAD_TEX0_IMAGE 0x100 /* handled clientside */
37#define I830_UPLOAD_TEX0_CUBE 0x200 /* handled clientside */
38#define I830_UPLOAD_TEX1_IMAGE 0x400 /* handled clientside */
39#define I830_UPLOAD_TEX1_CUBE 0x800 /* handled clientside */
40#define I830_UPLOAD_TEX2_IMAGE 0x1000 /* handled clientside */
41#define I830_UPLOAD_TEX2_CUBE 0x2000 /* handled clientside */
42#define I830_UPLOAD_TEX3_IMAGE 0x4000 /* handled clientside */
43#define I830_UPLOAD_TEX3_CUBE 0x8000 /* handled clientside */
44#define I830_UPLOAD_TEX_N_IMAGE(n) (0x100 << (n * 2))
45#define I830_UPLOAD_TEX_N_CUBE(n) (0x200 << (n * 2))
46#define I830_UPLOAD_TEXIMAGE_MASK 0xff00
47#define I830_UPLOAD_TEX0 0x10000
48#define I830_UPLOAD_TEX1 0x20000
49#define I830_UPLOAD_TEX2 0x40000
50#define I830_UPLOAD_TEX3 0x80000
51#define I830_UPLOAD_TEX_N(n) (0x10000 << (n))
52#define I830_UPLOAD_TEX_MASK 0xf0000
53#define I830_UPLOAD_TEXBLEND0 0x100000
54#define I830_UPLOAD_TEXBLEND1 0x200000
55#define I830_UPLOAD_TEXBLEND2 0x400000
56#define I830_UPLOAD_TEXBLEND3 0x800000
57#define I830_UPLOAD_TEXBLEND_N(n) (0x100000 << (n))
58#define I830_UPLOAD_TEXBLEND_MASK 0xf00000
59#define I830_UPLOAD_TEX_PALETTE_N(n) (0x1000000 << (n))
60#define I830_UPLOAD_TEX_PALETTE_SHARED 0x4000000
61#define I830_UPLOAD_STIPPLE 0x8000000
62
63/* Indices into buf.Setup where various bits of state are mirrored per
64 * context and per buffer. These can be fired at the card as a unit,
65 * or in a piecewise fashion as required.
66 */
67
68/* Destbuffer state
69 * - backbuffer linear offset and pitch -- invarient in the current dri
70 * - zbuffer linear offset and pitch -- also invarient
71 * - drawing origin in back and depth buffers.
72 *
73 * Keep the depth/back buffer state here to accommodate private buffers
74 * in the future.
75 */
76
77#define I830_DESTREG_CBUFADDR 0
78#define I830_DESTREG_DBUFADDR 1
79#define I830_DESTREG_DV0 2
80#define I830_DESTREG_DV1 3
81#define I830_DESTREG_SENABLE 4
82#define I830_DESTREG_SR0 5
83#define I830_DESTREG_SR1 6
84#define I830_DESTREG_SR2 7
85#define I830_DESTREG_DR0 8
86#define I830_DESTREG_DR1 9
87#define I830_DESTREG_DR2 10
88#define I830_DESTREG_DR3 11
89#define I830_DESTREG_DR4 12
90#define I830_DEST_SETUP_SIZE 13
91
92/* Context state
93 */
94#define I830_CTXREG_STATE1 0
95#define I830_CTXREG_STATE2 1
96#define I830_CTXREG_STATE3 2
97#define I830_CTXREG_STATE4 3
98#define I830_CTXREG_STATE5 4
99#define I830_CTXREG_IALPHAB 5
100#define I830_CTXREG_STENCILTST 6
101#define I830_CTXREG_ENABLES_1 7
102#define I830_CTXREG_ENABLES_2 8
103#define I830_CTXREG_AA 9
104#define I830_CTXREG_FOGCOLOR 10
105#define I830_CTXREG_BLENDCOLR0 11
106#define I830_CTXREG_BLENDCOLR 12 /* Dword 1 of 2 dword command */
107#define I830_CTXREG_VF 13
108#define I830_CTXREG_VF2 14
109#define I830_CTXREG_MCSB0 15
110#define I830_CTXREG_MCSB1 16
111#define I830_CTX_SETUP_SIZE 17
112
113/* 1.3: Stipple state
114 */
115#define I830_STPREG_ST0 0
116#define I830_STPREG_ST1 1
117#define I830_STP_SETUP_SIZE 2
118
119
120/* Texture state (per tex unit)
121 */
122
123#define I830_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (6 dwords) */
124#define I830_TEXREG_MI1 1
125#define I830_TEXREG_MI2 2
126#define I830_TEXREG_MI3 3
127#define I830_TEXREG_MI4 4
128#define I830_TEXREG_MI5 5
129#define I830_TEXREG_MF 6 /* GFX_OP_MAP_FILTER */
130#define I830_TEXREG_MLC 7 /* GFX_OP_MAP_LOD_CTL */
131#define I830_TEXREG_MLL 8 /* GFX_OP_MAP_LOD_LIMITS */
132#define I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS */
133#define I830_TEX_SETUP_SIZE 10
134
135#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
136#define I830_TEXREG_TM0S0 1
137#define I830_TEXREG_TM0S1 2
138#define I830_TEXREG_TM0S2 3
139#define I830_TEXREG_TM0S3 4
140#define I830_TEXREG_TM0S4 5
141#define I830_TEXREG_NOP0 6 /* noop */
142#define I830_TEXREG_NOP1 7 /* noop */
143#define I830_TEXREG_NOP2 8 /* noop */
144#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */
145#define __I830_TEX_SETUP_SIZE 10
146
147#define I830_FRONT 0x1
148#define I830_BACK 0x2
149#define I830_DEPTH 0x4
150
151#endif /* _I830_DEFINES_ */
152
153typedef struct _drm_i830_init {
154 enum {
155 I830_INIT_DMA = 0x01,
156 I830_CLEANUP_DMA = 0x02
157 } func;
158 unsigned int mmio_offset;
159 unsigned int buffers_offset;
160 int sarea_priv_offset;
161 unsigned int ring_start;
162 unsigned int ring_end;
163 unsigned int ring_size;
164 unsigned int front_offset;
165 unsigned int back_offset;
166 unsigned int depth_offset;
167 unsigned int w;
168 unsigned int h;
169 unsigned int pitch;
170 unsigned int pitch_bits;
171 unsigned int back_pitch;
172 unsigned int depth_pitch;
173 unsigned int cpp;
174} drm_i830_init_t;
175
176/* Warning: If you change the SAREA structure you must change the Xserver
177 * structure as well */
178
179typedef struct _drm_i830_tex_region {
180 unsigned char next, prev; /* indices to form a circular LRU */
181 unsigned char in_use; /* owned by a client, or free? */
182 int age; /* tracked by clients to update local LRU's */
183} drm_i830_tex_region_t;
184
185typedef struct _drm_i830_sarea {
186 unsigned int ContextState[I830_CTX_SETUP_SIZE];
187 unsigned int BufferState[I830_DEST_SETUP_SIZE];
188 unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE];
189 unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
190 unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT];
191 unsigned int Palette[2][256];
192 unsigned int dirty;
193
194 unsigned int nbox;
195 drm_clip_rect_t boxes[I830_NR_SAREA_CLIPRECTS];
196
197 /* Maintain an LRU of contiguous regions of texture space. If
198 * you think you own a region of texture memory, and it has an
199 * age different to the one you set, then you are mistaken and
200 * it has been stolen by another client. If global texAge
201 * hasn't changed, there is no need to walk the list.
202 *
203 * These regions can be used as a proxy for the fine-grained
204 * texture information of other clients - by maintaining them
205 * in the same lru which is used to age their own textures,
206 * clients have an approximate lru for the whole of global
207 * texture space, and can make informed decisions as to which
208 * areas to kick out. There is no need to choose whether to
209 * kick out your own texture or someone else's - simply eject
210 * them all in LRU order.
211 */
212
213 drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS+1];
214 /* Last elt is sentinal */
215 int texAge; /* last time texture was uploaded */
216 int last_enqueue; /* last time a buffer was enqueued */
217 int last_dispatch; /* age of the most recently dispatched buffer */
218 int last_quiescent; /* */
219 int ctxOwner; /* last context to upload state */
220
221 int vertex_prim;
222
223 int pf_enabled; /* is pageflipping allowed? */
224 int pf_active;
225 int pf_current_page; /* which buffer is being displayed? */
226
227 int perf_boxes; /* performance boxes to be displayed */
228
229 /* Here's the state for texunits 2,3:
230 */
231 unsigned int TexState2[I830_TEX_SETUP_SIZE];
232 unsigned int TexBlendState2[I830_TEXBLEND_SIZE];
233 unsigned int TexBlendStateWordsUsed2;
234
235 unsigned int TexState3[I830_TEX_SETUP_SIZE];
236 unsigned int TexBlendState3[I830_TEXBLEND_SIZE];
237 unsigned int TexBlendStateWordsUsed3;
238
239 unsigned int StippleState[I830_STP_SETUP_SIZE];
240} drm_i830_sarea_t;
241
242/* Flags for perf_boxes
243 */
244#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */
245#define I830_BOX_FLIP 0x2 /* populated by kernel */
246#define I830_BOX_WAIT 0x4 /* populated by kernel & client */
247#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */
248#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */
249
250
251/* I830 specific ioctls
252 * The device specific ioctl range is 0x40 to 0x79.
253 */
254#define DRM_I830_INIT 0x00
255#define DRM_I830_VERTEX 0x01
256#define DRM_I830_CLEAR 0x02
257#define DRM_I830_FLUSH 0x03
258#define DRM_I830_GETAGE 0x04
259#define DRM_I830_GETBUF 0x05
260#define DRM_I830_SWAP 0x06
261#define DRM_I830_COPY 0x07
262#define DRM_I830_DOCOPY 0x08
263#define DRM_I830_FLIP 0x09
264#define DRM_I830_IRQ_EMIT 0x0a
265#define DRM_I830_IRQ_WAIT 0x0b
266#define DRM_I830_GETPARAM 0x0c
267#define DRM_I830_SETPARAM 0x0d
268
269#define DRM_IOCTL_I830_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_INIT, drm_i830_init_t)
270#define DRM_IOCTL_I830_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_VERTEX, drm_i830_vertex_t)
271#define DRM_IOCTL_I830_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_CLEAR, drm_i830_clear_t)
272#define DRM_IOCTL_I830_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_FLUSH)
273#define DRM_IOCTL_I830_GETAGE DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_GETAGE)
274#define DRM_IOCTL_I830_GETBUF DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_GETBUF, drm_i830_dma_t)
275#define DRM_IOCTL_I830_SWAP DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_SWAP)
276#define DRM_IOCTL_I830_COPY DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_COPY, drm_i830_copy_t)
277#define DRM_IOCTL_I830_DOCOPY DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_DOCOPY)
278#define DRM_IOCTL_I830_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_FLIP)
279#define DRM_IOCTL_I830_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_IRQ_EMIT, drm_i830_irq_emit_t)
280#define DRM_IOCTL_I830_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_IRQ_WAIT, drm_i830_irq_wait_t)
281#define DRM_IOCTL_I830_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_GETPARAM, drm_i830_getparam_t)
282#define DRM_IOCTL_I830_SETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_SETPARAM, drm_i830_setparam_t)
283
284typedef struct _drm_i830_clear {
285 int clear_color;
286 int clear_depth;
287 int flags;
288 unsigned int clear_colormask;
289 unsigned int clear_depthmask;
290} drm_i830_clear_t;
291
292
293
294/* These may be placeholders if we have more cliprects than
295 * I830_NR_SAREA_CLIPRECTS. In that case, the client sets discard to
296 * false, indicating that the buffer will be dispatched again with a
297 * new set of cliprects.
298 */
299typedef struct _drm_i830_vertex {
300 int idx; /* buffer index */
301 int used; /* nr bytes in use */
302 int discard; /* client is finished with the buffer? */
303} drm_i830_vertex_t;
304
305typedef struct _drm_i830_copy_t {
306 int idx; /* buffer index */
307 int used; /* nr bytes in use */
308 void __user *address; /* Address to copy from */
309} drm_i830_copy_t;
310
311typedef struct drm_i830_dma {
312 void __user *virtual;
313 int request_idx;
314 int request_size;
315 int granted;
316} drm_i830_dma_t;
317
318
319/* 1.3: Userspace can request & wait on irq's:
320 */
321typedef struct drm_i830_irq_emit {
322 int __user *irq_seq;
323} drm_i830_irq_emit_t;
324
325typedef struct drm_i830_irq_wait {
326 int irq_seq;
327} drm_i830_irq_wait_t;
328
329
330/* 1.3: New ioctl to query kernel params:
331 */
332#define I830_PARAM_IRQ_ACTIVE 1
333
334typedef struct drm_i830_getparam {
335 int param;
336 int __user *value;
337} drm_i830_getparam_t;
338
339
340/* 1.3: New ioctl to set kernel params:
341 */
342#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1
343
344typedef struct drm_i830_setparam {
345 int param;
346 int value;
347} drm_i830_setparam_t;
348
349
350#endif /* _I830_DRM_H_ */
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
new file mode 100644
index 000000000000..aa80ad6a5ee0
--- /dev/null
+++ b/drivers/char/drm/i830_drv.c
@@ -0,0 +1,137 @@
1/* i830_drv.c -- I810 driver -*- linux-c -*-
2 * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Jeff Hartmann <jhartmann@valinux.com>
30 * Gareth Hughes <gareth@valinux.com>
31 * Abraham vd Merwe <abraham@2d3d.co.za>
32 * Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35#include <linux/config.h>
36#include "drmP.h"
37#include "drm.h"
38#include "i830_drm.h"
39#include "i830_drv.h"
40
41#include "drm_pciids.h"
42
43int postinit( struct drm_device *dev, unsigned long flags )
44{
45 dev->counters += 4;
46 dev->types[6] = _DRM_STAT_IRQ;
47 dev->types[7] = _DRM_STAT_PRIMARY;
48 dev->types[8] = _DRM_STAT_SECONDARY;
49 dev->types[9] = _DRM_STAT_DMA;
50
51 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
52 DRIVER_NAME,
53 DRIVER_MAJOR,
54 DRIVER_MINOR,
55 DRIVER_PATCHLEVEL,
56 DRIVER_DATE,
57 dev->primary.minor,
58 pci_pretty_name(dev->pdev)
59 );
60 return 0;
61}
62
63static int version( drm_version_t *version )
64{
65 int len;
66
67 version->version_major = DRIVER_MAJOR;
68 version->version_minor = DRIVER_MINOR;
69 version->version_patchlevel = DRIVER_PATCHLEVEL;
70 DRM_COPY( version->name, DRIVER_NAME );
71 DRM_COPY( version->date, DRIVER_DATE );
72 DRM_COPY( version->desc, DRIVER_DESC );
73 return 0;
74}
75
76static struct pci_device_id pciidlist[] = {
77 i830_PCI_IDS
78};
79
80extern drm_ioctl_desc_t i830_ioctls[];
81extern int i830_max_ioctl;
82
83static struct drm_driver driver = {
84 .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
85#if USE_IRQS
86 .driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ,
87#endif
88 .dev_priv_size = sizeof(drm_i830_buf_priv_t),
89 .pretakedown = i830_driver_pretakedown,
90 .prerelease = i830_driver_prerelease,
91 .release = i830_driver_release,
92 .dma_quiescent = i830_driver_dma_quiescent,
93 .reclaim_buffers = i830_reclaim_buffers,
94 .get_map_ofs = drm_core_get_map_ofs,
95 .get_reg_ofs = drm_core_get_reg_ofs,
96#if USE_IRQS
97 .irq_preinstall = i830_driver_irq_preinstall,
98 .irq_postinstall = i830_driver_irq_postinstall,
99 .irq_uninstall = i830_driver_irq_uninstall,
100 .irq_handler = i830_driver_irq_handler,
101#endif
102 .postinit = postinit,
103 .version = version,
104 .ioctls = i830_ioctls,
105 .fops = {
106 .owner = THIS_MODULE,
107 .open = drm_open,
108 .release = drm_release,
109 .ioctl = drm_ioctl,
110 .mmap = drm_mmap,
111 .poll = drm_poll,
112 .fasync = drm_fasync,
113 },
114 .pci_driver = {
115 .name = DRIVER_NAME,
116 .id_table = pciidlist,
117 }
118
119};
120
121static int __init i830_init(void)
122{
123 driver.num_ioctls = i830_max_ioctl;
124 return drm_init(&driver);
125}
126
127static void __exit i830_exit(void)
128{
129 drm_exit(&driver);
130}
131
132module_init(i830_init);
133module_exit(i830_exit);
134
135MODULE_AUTHOR( DRIVER_AUTHOR );
136MODULE_DESCRIPTION( DRIVER_DESC );
137MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
new file mode 100644
index 000000000000..d4b2d093d6ab
--- /dev/null
+++ b/drivers/char/drm/i830_drv.h
@@ -0,0 +1,301 @@
1/* i830_drv.h -- Private header for the I830 driver -*- linux-c -*-
2 * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
28 * Jeff Hartmann <jhartmann@valinux.com>
29 *
30 */
31
32#ifndef _I830_DRV_H_
33#define _I830_DRV_H_
34
35/* General customization:
36 */
37
38#define DRIVER_AUTHOR "VA Linux Systems Inc."
39
40#define DRIVER_NAME "i830"
41#define DRIVER_DESC "Intel 830M"
42#define DRIVER_DATE "20021108"
43
44/* Interface history:
45 *
46 * 1.1: Original.
47 * 1.2: ?
48 * 1.3: New irq emit/wait ioctls.
49 * New pageflip ioctl.
50 * New getparam ioctl.
51 * State for texunits 3&4 in sarea.
52 * New (alternative) layout for texture state.
53 */
54#define DRIVER_MAJOR 1
55#define DRIVER_MINOR 3
56#define DRIVER_PATCHLEVEL 2
57
58/* Driver will work either way: IRQ's save cpu time when waiting for
59 * the card, but are subject to subtle interactions between bios,
60 * hardware and the driver.
61 */
62/* XXX: Add vblank support? */
63#define USE_IRQS 0
64
65typedef struct drm_i830_buf_priv {
66 u32 *in_use;
67 int my_use_idx;
68 int currently_mapped;
69 void __user *virtual;
70 void *kernel_virtual;
71} drm_i830_buf_priv_t;
72
73typedef struct _drm_i830_ring_buffer{
74 int tail_mask;
75 unsigned long Start;
76 unsigned long End;
77 unsigned long Size;
78 u8 *virtual_start;
79 int head;
80 int tail;
81 int space;
82} drm_i830_ring_buffer_t;
83
84typedef struct drm_i830_private {
85 drm_map_t *sarea_map;
86 drm_map_t *mmio_map;
87
88 drm_i830_sarea_t *sarea_priv;
89 drm_i830_ring_buffer_t ring;
90
91 void * hw_status_page;
92 unsigned long counter;
93
94 dma_addr_t dma_status_page;
95
96 drm_buf_t *mmap_buffer;
97
98 u32 front_di1, back_di1, zi1;
99
100 int back_offset;
101 int depth_offset;
102 int front_offset;
103 int w, h;
104 int pitch;
105 int back_pitch;
106 int depth_pitch;
107 unsigned int cpp;
108
109 int do_boxes;
110 int dma_used;
111
112 int current_page;
113 int page_flipping;
114
115 wait_queue_head_t irq_queue;
116 atomic_t irq_received;
117 atomic_t irq_emitted;
118
119 int use_mi_batchbuffer_start;
120
121} drm_i830_private_t;
122
123/* i830_dma.c */
124extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp);
125
126extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
127
128/* i830_irq.c */
129extern int i830_irq_emit( struct inode *inode, struct file *filp,
130 unsigned int cmd, unsigned long arg );
131extern int i830_irq_wait( struct inode *inode, struct file *filp,
132 unsigned int cmd, unsigned long arg );
133
134extern irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS );
135extern void i830_driver_irq_preinstall( drm_device_t *dev );
136extern void i830_driver_irq_postinstall( drm_device_t *dev );
137extern void i830_driver_irq_uninstall( drm_device_t *dev );
138extern void i830_driver_pretakedown(drm_device_t *dev);
139extern void i830_driver_release(drm_device_t *dev, struct file *filp);
140extern int i830_driver_dma_quiescent(drm_device_t *dev);
141extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp);
142
143#define I830_BASE(reg) ((unsigned long) \
144 dev_priv->mmio_map->handle)
145#define I830_ADDR(reg) (I830_BASE(reg) + reg)
146#define I830_DEREF(reg) *(__volatile__ unsigned int *)I830_ADDR(reg)
147#define I830_READ(reg) readl((volatile u32 *)I830_ADDR(reg))
148#define I830_WRITE(reg,val) writel(val, (volatile u32 *)I830_ADDR(reg))
149#define I830_DEREF16(reg) *(__volatile__ u16 *)I830_ADDR(reg)
150#define I830_READ16(reg) I830_DEREF16(reg)
151#define I830_WRITE16(reg,val) do { I830_DEREF16(reg) = val; } while (0)
152
153
154
155#define I830_VERBOSE 0
156
157#define RING_LOCALS unsigned int outring, ringmask, outcount; \
158 volatile char *virt;
159
160#define BEGIN_LP_RING(n) do { \
161 if (I830_VERBOSE) \
162 printk("BEGIN_LP_RING(%d) in %s\n", \
163 n, __FUNCTION__); \
164 if (dev_priv->ring.space < n*4) \
165 i830_wait_ring(dev, n*4, __FUNCTION__); \
166 outcount = 0; \
167 outring = dev_priv->ring.tail; \
168 ringmask = dev_priv->ring.tail_mask; \
169 virt = dev_priv->ring.virtual_start; \
170} while (0)
171
172
173#define OUT_RING(n) do { \
174 if (I830_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \
175 *(volatile unsigned int *)(virt + outring) = n; \
176 outcount++; \
177 outring += 4; \
178 outring &= ringmask; \
179} while (0)
180
181#define ADVANCE_LP_RING() do { \
182 if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring); \
183 dev_priv->ring.tail = outring; \
184 dev_priv->ring.space -= outcount * 4; \
185 I830_WRITE(LP_RING + RING_TAIL, outring); \
186} while(0)
187
188extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
189
190
191#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
192#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
193#define CMD_REPORT_HEAD (7<<23)
194#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1)
195#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1)
196
197#define STATE3D_LOAD_STATE_IMMEDIATE_2 ((0x3<<29)|(0x1d<<24)|(0x03<<16))
198#define LOAD_TEXTURE_MAP0 (1<<11)
199
200#define INST_PARSER_CLIENT 0x00000000
201#define INST_OP_FLUSH 0x02000000
202#define INST_FLUSH_MAP_CACHE 0x00000001
203
204
205#define BB1_START_ADDR_MASK (~0x7)
206#define BB1_PROTECTED (1<<0)
207#define BB1_UNPROTECTED (0<<0)
208#define BB2_END_ADDR_MASK (~0x7)
209
210#define I830REG_HWSTAM 0x02098
211#define I830REG_INT_IDENTITY_R 0x020a4
212#define I830REG_INT_MASK_R 0x020a8
213#define I830REG_INT_ENABLE_R 0x020a0
214
215#define I830_IRQ_RESERVED ((1<<13)|(3<<2))
216
217
218#define LP_RING 0x2030
219#define HP_RING 0x2040
220#define RING_TAIL 0x00
221#define TAIL_ADDR 0x001FFFF8
222#define RING_HEAD 0x04
223#define HEAD_WRAP_COUNT 0xFFE00000
224#define HEAD_WRAP_ONE 0x00200000
225#define HEAD_ADDR 0x001FFFFC
226#define RING_START 0x08
227#define START_ADDR 0x0xFFFFF000
228#define RING_LEN 0x0C
229#define RING_NR_PAGES 0x001FF000
230#define RING_REPORT_MASK 0x00000006
231#define RING_REPORT_64K 0x00000002
232#define RING_REPORT_128K 0x00000004
233#define RING_NO_REPORT 0x00000000
234#define RING_VALID_MASK 0x00000001
235#define RING_VALID 0x00000001
236#define RING_INVALID 0x00000000
237
238#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19))
239#define SC_UPDATE_SCISSOR (0x1<<1)
240#define SC_ENABLE_MASK (0x1<<0)
241#define SC_ENABLE (0x1<<0)
242
243#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
244#define SCI_YMIN_MASK (0xffff<<16)
245#define SCI_XMIN_MASK (0xffff<<0)
246#define SCI_YMAX_MASK (0xffff<<16)
247#define SCI_XMAX_MASK (0xffff<<0)
248
249#define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19))
250#define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
251#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
252#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
253#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4)
254#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
255#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
256#define GFX_OP_PRIMITIVE ((0x3<<29)|(0x1f<<24))
257
258#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
259
260#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
261#define ASYNC_FLIP (1<<22)
262
263#define CMD_3D (0x3<<29)
264#define STATE3D_CONST_BLEND_COLOR_CMD (CMD_3D|(0x1d<<24)|(0x88<<16))
265#define STATE3D_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16))
266
267#define BR00_BITBLT_CLIENT 0x40000000
268#define BR00_OP_COLOR_BLT 0x10000000
269#define BR00_OP_SRC_COPY_BLT 0x10C00000
270#define BR13_SOLID_PATTERN 0x80000000
271
272#define BUF_3D_ID_COLOR_BACK (0x3<<24)
273#define BUF_3D_ID_DEPTH (0x7<<24)
274#define BUF_3D_USE_FENCE (1<<23)
275#define BUF_3D_PITCH(x) (((x)/4)<<2)
276
277#define CMD_OP_MAP_PALETTE_LOAD ((3<<29)|(0x1d<<24)|(0x82<<16)|255)
278#define MAP_PALETTE_NUM(x) ((x<<8) & (1<<8))
279#define MAP_PALETTE_BOTH (1<<11)
280
281#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|0x4)
282#define XY_COLOR_BLT_WRITE_ALPHA (1<<21)
283#define XY_COLOR_BLT_WRITE_RGB (1<<20)
284
285#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
286#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
287#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
288
289#define MI_BATCH_BUFFER ((0x30<<23)|1)
290#define MI_BATCH_BUFFER_START (0x31<<23)
291#define MI_BATCH_BUFFER_END (0xA<<23)
292#define MI_BATCH_NON_SECURE (1)
293
294#define MI_WAIT_FOR_EVENT ((0x3<<23))
295#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
296#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
297
298#define MI_LOAD_SCAN_LINES_INCL ((0x12<<23))
299
300#endif
301
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
new file mode 100644
index 000000000000..6d7729ffe2dc
--- /dev/null
+++ b/drivers/char/drm/i830_irq.c
@@ -0,0 +1,204 @@
1/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
2 *
3 * Copyright 2002 Tungsten Graphics, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 *
25 * Authors: Keith Whitwell <keith@tungstengraphics.com>
26 *
27 */
28
29#include "drmP.h"
30#include "drm.h"
31#include "i830_drm.h"
32#include "i830_drv.h"
33#include <linux/interrupt.h> /* For task queue support */
34#include <linux/delay.h>
35
36
37irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS )
38{
39 drm_device_t *dev = (drm_device_t *)arg;
40 drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
41 u16 temp;
42
43 temp = I830_READ16(I830REG_INT_IDENTITY_R);
44 DRM_DEBUG("%x\n", temp);
45
46 if ( !( temp & 2 ) )
47 return IRQ_NONE;
48
49 I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
50
51 atomic_inc(&dev_priv->irq_received);
52 wake_up_interruptible(&dev_priv->irq_queue);
53
54 return IRQ_HANDLED;
55}
56
57
58int i830_emit_irq(drm_device_t *dev)
59{
60 drm_i830_private_t *dev_priv = dev->dev_private;
61 RING_LOCALS;
62
63 DRM_DEBUG("%s\n", __FUNCTION__);
64
65 atomic_inc(&dev_priv->irq_emitted);
66
67 BEGIN_LP_RING(2);
68 OUT_RING( 0 );
69 OUT_RING( GFX_OP_USER_INTERRUPT );
70 ADVANCE_LP_RING();
71
72 return atomic_read(&dev_priv->irq_emitted);
73}
74
75
76int i830_wait_irq(drm_device_t *dev, int irq_nr)
77{
78 drm_i830_private_t *dev_priv =
79 (drm_i830_private_t *)dev->dev_private;
80 DECLARE_WAITQUEUE(entry, current);
81 unsigned long end = jiffies + HZ*3;
82 int ret = 0;
83
84 DRM_DEBUG("%s\n", __FUNCTION__);
85
86 if (atomic_read(&dev_priv->irq_received) >= irq_nr)
87 return 0;
88
89 dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
90
91 add_wait_queue(&dev_priv->irq_queue, &entry);
92
93 for (;;) {
94 __set_current_state(TASK_INTERRUPTIBLE);
95 if (atomic_read(&dev_priv->irq_received) >= irq_nr)
96 break;
97 if((signed)(end - jiffies) <= 0) {
98 DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
99 I830_READ16( I830REG_INT_IDENTITY_R ),
100 I830_READ16( I830REG_INT_MASK_R ),
101 I830_READ16( I830REG_INT_ENABLE_R ),
102 I830_READ16( I830REG_HWSTAM ));
103
104 ret = -EBUSY; /* Lockup? Missed irq? */
105 break;
106 }
107 schedule_timeout(HZ*3);
108 if (signal_pending(current)) {
109 ret = -EINTR;
110 break;
111 }
112 }
113
114 __set_current_state(TASK_RUNNING);
115 remove_wait_queue(&dev_priv->irq_queue, &entry);
116 return ret;
117}
118
119
120/* Needs the lock as it touches the ring.
121 */
122int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd,
123 unsigned long arg )
124{
125 drm_file_t *priv = filp->private_data;
126 drm_device_t *dev = priv->head->dev;
127 drm_i830_private_t *dev_priv = dev->dev_private;
128 drm_i830_irq_emit_t emit;
129 int result;
130
131 LOCK_TEST_WITH_RETURN(dev, filp);
132
133 if ( !dev_priv ) {
134 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
135 return -EINVAL;
136 }
137
138 if (copy_from_user( &emit, (drm_i830_irq_emit_t __user *)arg, sizeof(emit) ))
139 return -EFAULT;
140
141 result = i830_emit_irq( dev );
142
143 if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) {
144 DRM_ERROR( "copy_to_user\n" );
145 return -EFAULT;
146 }
147
148 return 0;
149}
150
151
152/* Doesn't need the hardware lock.
153 */
154int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd,
155 unsigned long arg )
156{
157 drm_file_t *priv = filp->private_data;
158 drm_device_t *dev = priv->head->dev;
159 drm_i830_private_t *dev_priv = dev->dev_private;
160 drm_i830_irq_wait_t irqwait;
161
162 if ( !dev_priv ) {
163 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
164 return -EINVAL;
165 }
166
167 if (copy_from_user( &irqwait, (drm_i830_irq_wait_t __user *)arg,
168 sizeof(irqwait) ))
169 return -EFAULT;
170
171 return i830_wait_irq( dev, irqwait.irq_seq );
172}
173
174
175/* drm_dma.h hooks
176*/
177void i830_driver_irq_preinstall( drm_device_t *dev ) {
178 drm_i830_private_t *dev_priv =
179 (drm_i830_private_t *)dev->dev_private;
180
181 I830_WRITE16( I830REG_HWSTAM, 0xffff );
182 I830_WRITE16( I830REG_INT_MASK_R, 0x0 );
183 I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
184 atomic_set(&dev_priv->irq_received, 0);
185 atomic_set(&dev_priv->irq_emitted, 0);
186 init_waitqueue_head(&dev_priv->irq_queue);
187}
188
189void i830_driver_irq_postinstall( drm_device_t *dev ) {
190 drm_i830_private_t *dev_priv =
191 (drm_i830_private_t *)dev->dev_private;
192
193 I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );
194}
195
196void i830_driver_irq_uninstall( drm_device_t *dev ) {
197 drm_i830_private_t *dev_priv =
198 (drm_i830_private_t *)dev->dev_private;
199 if (!dev_priv)
200 return;
201
202 I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
203 I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
204}
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
new file mode 100644
index 000000000000..7300a09dbd5c
--- /dev/null
+++ b/drivers/char/drm/i915_dma.c
@@ -0,0 +1,725 @@
1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
2 */
3/**************************************************************************
4 *
5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * All Rights Reserved.
7 *
8 **************************************************************************/
9
10#include "drmP.h"
11#include "drm.h"
12#include "i915_drm.h"
13#include "i915_drv.h"
14
15drm_ioctl_desc_t i915_ioctls[] = {
16 [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1},
17 [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0},
18 [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0},
19 [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0},
20 [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0},
21 [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0},
22 [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0},
23 [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1},
24 [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0},
25 [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0},
26 [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1},
27 [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0}
28};
29
30int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
31
32/* Really want an OS-independent resettable timer. Would like to have
33 * this loop run for (eg) 3 sec, but have the timer reset every time
34 * the head pointer changes, so that EBUSY only happens if the ring
35 * actually stalls for (eg) 3 seconds.
36 */
37int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
38{
39 drm_i915_private_t *dev_priv = dev->dev_private;
40 drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
41 u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
42 int i;
43
44 for (i = 0; i < 10000; i++) {
45 ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
46 ring->space = ring->head - (ring->tail + 8);
47 if (ring->space < 0)
48 ring->space += ring->Size;
49 if (ring->space >= n)
50 return 0;
51
52 dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
53
54 if (ring->head != last_head)
55 i = 0;
56
57 last_head = ring->head;
58 }
59
60 return DRM_ERR(EBUSY);
61}
62
63void i915_kernel_lost_context(drm_device_t * dev)
64{
65 drm_i915_private_t *dev_priv = dev->dev_private;
66 drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
67
68 ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
69 ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
70 ring->space = ring->head - (ring->tail + 8);
71 if (ring->space < 0)
72 ring->space += ring->Size;
73
74 if (ring->head == ring->tail)
75 dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
76}
77
78int i915_dma_cleanup(drm_device_t * dev)
79{
80 /* Make sure interrupts are disabled here because the uninstall ioctl
81 * may not have been called from userspace and after dev_private
82 * is freed, it's too late.
83 */
84 if (dev->irq)
85 drm_irq_uninstall (dev);
86
87 if (dev->dev_private) {
88 drm_i915_private_t *dev_priv =
89 (drm_i915_private_t *) dev->dev_private;
90
91 if (dev_priv->ring.virtual_start) {
92 drm_core_ioremapfree( &dev_priv->ring.map, dev);
93 }
94
95 if (dev_priv->hw_status_page) {
96 drm_pci_free(dev, PAGE_SIZE, dev_priv->hw_status_page,
97 dev_priv->dma_status_page);
98 /* Need to rewrite hardware status page */
99 I915_WRITE(0x02080, 0x1ffff000);
100 }
101
102 drm_free (dev->dev_private, sizeof(drm_i915_private_t),
103 DRM_MEM_DRIVER);
104
105 dev->dev_private = NULL;
106 }
107
108 return 0;
109}
110
111static int i915_initialize(drm_device_t * dev,
112 drm_i915_private_t * dev_priv,
113 drm_i915_init_t * init)
114{
115 memset(dev_priv, 0, sizeof(drm_i915_private_t));
116
117 DRM_GETSAREA();
118 if (!dev_priv->sarea) {
119 DRM_ERROR("can not find sarea!\n");
120 dev->dev_private = (void *)dev_priv;
121 i915_dma_cleanup(dev);
122 return DRM_ERR(EINVAL);
123 }
124
125 dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
126 if (!dev_priv->mmio_map) {
127 dev->dev_private = (void *)dev_priv;
128 i915_dma_cleanup(dev);
129 DRM_ERROR("can not find mmio map!\n");
130 return DRM_ERR(EINVAL);
131 }
132
133 dev_priv->sarea_priv = (drm_i915_sarea_t *)
134 ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
135
136 dev_priv->ring.Start = init->ring_start;
137 dev_priv->ring.End = init->ring_end;
138 dev_priv->ring.Size = init->ring_size;
139 dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
140
141 dev_priv->ring.map.offset = init->ring_start;
142 dev_priv->ring.map.size = init->ring_size;
143 dev_priv->ring.map.type = 0;
144 dev_priv->ring.map.flags = 0;
145 dev_priv->ring.map.mtrr = 0;
146
147 drm_core_ioremap( &dev_priv->ring.map, dev );
148
149 if (dev_priv->ring.map.handle == NULL) {
150 dev->dev_private = (void *)dev_priv;
151 i915_dma_cleanup(dev);
152 DRM_ERROR("can not ioremap virtual address for"
153 " ring buffer\n");
154 return DRM_ERR(ENOMEM);
155 }
156
157 dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
158
159 dev_priv->back_offset = init->back_offset;
160 dev_priv->front_offset = init->front_offset;
161 dev_priv->current_page = 0;
162 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
163
164 /* We are using separate values as placeholders for mechanisms for
165 * private backbuffer/depthbuffer usage.
166 */
167 dev_priv->use_mi_batchbuffer_start = 0;
168
169 /* Allow hardware batchbuffers unless told otherwise.
170 */
171 dev_priv->allow_batchbuffer = 1;
172
173 /* Program Hardware Status Page */
174 dev_priv->hw_status_page = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
175 0xffffffff,
176 &dev_priv->dma_status_page);
177
178 if (!dev_priv->hw_status_page) {
179 dev->dev_private = (void *)dev_priv;
180 i915_dma_cleanup(dev);
181 DRM_ERROR("Can not allocate hardware status page\n");
182 return DRM_ERR(ENOMEM);
183 }
184 memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
185 DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
186
187 I915_WRITE(0x02080, dev_priv->dma_status_page);
188 DRM_DEBUG("Enabled hardware status page\n");
189
190 dev->dev_private = (void *)dev_priv;
191
192 return 0;
193}
194
195static int i915_resume(drm_device_t * dev)
196{
197 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
198
199 DRM_DEBUG("%s\n", __FUNCTION__);
200
201 if (!dev_priv->sarea) {
202 DRM_ERROR("can not find sarea!\n");
203 return DRM_ERR(EINVAL);
204 }
205
206 if (!dev_priv->mmio_map) {
207 DRM_ERROR("can not find mmio map!\n");
208 return DRM_ERR(EINVAL);
209 }
210
211 if (dev_priv->ring.map.handle == NULL) {
212 DRM_ERROR("can not ioremap virtual address for"
213 " ring buffer\n");
214 return DRM_ERR(ENOMEM);
215 }
216
217 /* Program Hardware Status Page */
218 if (!dev_priv->hw_status_page) {
219 DRM_ERROR("Can not find hardware status page\n");
220 return DRM_ERR(EINVAL);
221 }
222 DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
223
224 I915_WRITE(0x02080, dev_priv->dma_status_page);
225 DRM_DEBUG("Enabled hardware status page\n");
226
227 return 0;
228}
229
230int i915_dma_init(DRM_IOCTL_ARGS)
231{
232 DRM_DEVICE;
233 drm_i915_private_t *dev_priv;
234 drm_i915_init_t init;
235 int retcode = 0;
236
237 DRM_COPY_FROM_USER_IOCTL(init, (drm_i915_init_t __user *) data,
238 sizeof(init));
239
240 switch (init.func) {
241 case I915_INIT_DMA:
242 dev_priv = drm_alloc (sizeof(drm_i915_private_t),
243 DRM_MEM_DRIVER);
244 if (dev_priv == NULL)
245 return DRM_ERR(ENOMEM);
246 retcode = i915_initialize(dev, dev_priv, &init);
247 break;
248 case I915_CLEANUP_DMA:
249 retcode = i915_dma_cleanup(dev);
250 break;
251 case I915_RESUME_DMA:
252 retcode = i915_resume(dev);
253 break;
254 default:
255 retcode = -EINVAL;
256 break;
257 }
258
259 return retcode;
260}
261
262/* Implement basically the same security restrictions as hardware does
263 * for MI_BATCH_NON_SECURE. These can be made stricter at any time.
264 *
265 * Most of the calculations below involve calculating the size of a
266 * particular instruction. It's important to get the size right as
267 * that tells us where the next instruction to check is. Any illegal
268 * instruction detected will be given a size of zero, which is a
269 * signal to abort the rest of the buffer.
270 */
271static int do_validate_cmd(int cmd)
272{
273 switch (((cmd >> 29) & 0x7)) {
274 case 0x0:
275 switch ((cmd >> 23) & 0x3f) {
276 case 0x0:
277 return 1; /* MI_NOOP */
278 case 0x4:
279 return 1; /* MI_FLUSH */
280 default:
281 return 0; /* disallow everything else */
282 }
283 break;
284 case 0x1:
285 return 0; /* reserved */
286 case 0x2:
287 return (cmd & 0xff) + 2; /* 2d commands */
288 case 0x3:
289 if (((cmd >> 24) & 0x1f) <= 0x18)
290 return 1;
291
292 switch ((cmd >> 24) & 0x1f) {
293 case 0x1c:
294 return 1;
295 case 0x1d:
296 switch ((cmd>>16)&0xff) {
297 case 0x3:
298 return (cmd & 0x1f) + 2;
299 case 0x4:
300 return (cmd & 0xf) + 2;
301 default:
302 return (cmd & 0xffff) + 2;
303 }
304 case 0x1e:
305 if (cmd & (1 << 23))
306 return (cmd & 0xffff) + 1;
307 else
308 return 1;
309 case 0x1f:
310 if ((cmd & (1 << 23)) == 0) /* inline vertices */
311 return (cmd & 0x1ffff) + 2;
312 else if (cmd & (1 << 17)) /* indirect random */
313 if ((cmd & 0xffff) == 0)
314 return 0; /* unknown length, too hard */
315 else
316 return (((cmd & 0xffff) + 1) / 2) + 1;
317 else
318 return 2; /* indirect sequential */
319 default:
320 return 0;
321 }
322 default:
323 return 0;
324 }
325
326 return 0;
327}
328
329static int validate_cmd(int cmd)
330{
331 int ret = do_validate_cmd(cmd);
332
333/* printk("validate_cmd( %x ): %d\n", cmd, ret); */
334
335 return ret;
336}
337
338static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
339{
340 drm_i915_private_t *dev_priv = dev->dev_private;
341 int i;
342 RING_LOCALS;
343
344 for (i = 0; i < dwords;) {
345 int cmd, sz;
346
347 if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
348 return DRM_ERR(EINVAL);
349
350/* printk("%d/%d ", i, dwords); */
351
352 if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
353 return DRM_ERR(EINVAL);
354
355 BEGIN_LP_RING(sz);
356 OUT_RING(cmd);
357
358 while (++i, --sz) {
359 if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
360 sizeof(cmd))) {
361 return DRM_ERR(EINVAL);
362 }
363 OUT_RING(cmd);
364 }
365 ADVANCE_LP_RING();
366 }
367
368 return 0;
369}
370
371static int i915_emit_box(drm_device_t * dev,
372 drm_clip_rect_t __user * boxes,
373 int i, int DR1, int DR4)
374{
375 drm_i915_private_t *dev_priv = dev->dev_private;
376 drm_clip_rect_t box;
377 RING_LOCALS;
378
379 if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
380 return EFAULT;
381 }
382
383 if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
384 DRM_ERROR("Bad box %d,%d..%d,%d\n",
385 box.x1, box.y1, box.x2, box.y2);
386 return DRM_ERR(EINVAL);
387 }
388
389 BEGIN_LP_RING(6);
390 OUT_RING(GFX_OP_DRAWRECT_INFO);
391 OUT_RING(DR1);
392 OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
393 OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
394 OUT_RING(DR4);
395 OUT_RING(0);
396 ADVANCE_LP_RING();
397
398 return 0;
399}
400
401static int i915_dispatch_cmdbuffer(drm_device_t * dev,
402 drm_i915_cmdbuffer_t * cmd)
403{
404 int nbox = cmd->num_cliprects;
405 int i = 0, count, ret;
406
407 if (cmd->sz & 0x3) {
408 DRM_ERROR("alignment");
409 return DRM_ERR(EINVAL);
410 }
411
412 i915_kernel_lost_context(dev);
413
414 count = nbox ? nbox : 1;
415
416 for (i = 0; i < count; i++) {
417 if (i < nbox) {
418 ret = i915_emit_box(dev, cmd->cliprects, i,
419 cmd->DR1, cmd->DR4);
420 if (ret)
421 return ret;
422 }
423
424 ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
425 if (ret)
426 return ret;
427 }
428
429 return 0;
430}
431
432static int i915_dispatch_batchbuffer(drm_device_t * dev,
433 drm_i915_batchbuffer_t * batch)
434{
435 drm_i915_private_t *dev_priv = dev->dev_private;
436 drm_clip_rect_t __user *boxes = batch->cliprects;
437 int nbox = batch->num_cliprects;
438 int i = 0, count;
439 RING_LOCALS;
440
441 if ((batch->start | batch->used) & 0x7) {
442 DRM_ERROR("alignment");
443 return DRM_ERR(EINVAL);
444 }
445
446 i915_kernel_lost_context(dev);
447
448 count = nbox ? nbox : 1;
449
450 for (i = 0; i < count; i++) {
451 if (i < nbox) {
452 int ret = i915_emit_box(dev, boxes, i,
453 batch->DR1, batch->DR4);
454 if (ret)
455 return ret;
456 }
457
458 if (dev_priv->use_mi_batchbuffer_start) {
459 BEGIN_LP_RING(2);
460 OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
461 OUT_RING(batch->start | MI_BATCH_NON_SECURE);
462 ADVANCE_LP_RING();
463 } else {
464 BEGIN_LP_RING(4);
465 OUT_RING(MI_BATCH_BUFFER);
466 OUT_RING(batch->start | MI_BATCH_NON_SECURE);
467 OUT_RING(batch->start + batch->used - 4);
468 OUT_RING(0);
469 ADVANCE_LP_RING();
470 }
471 }
472
473 dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
474
475 BEGIN_LP_RING(4);
476 OUT_RING(CMD_STORE_DWORD_IDX);
477 OUT_RING(20);
478 OUT_RING(dev_priv->counter);
479 OUT_RING(0);
480 ADVANCE_LP_RING();
481
482 return 0;
483}
484
485static int i915_dispatch_flip(drm_device_t * dev)
486{
487 drm_i915_private_t *dev_priv = dev->dev_private;
488 RING_LOCALS;
489
490 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
491 __FUNCTION__,
492 dev_priv->current_page,
493 dev_priv->sarea_priv->pf_current_page);
494
495 i915_kernel_lost_context(dev);
496
497 BEGIN_LP_RING(2);
498 OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
499 OUT_RING(0);
500 ADVANCE_LP_RING();
501
502 BEGIN_LP_RING(6);
503 OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
504 OUT_RING(0);
505 if (dev_priv->current_page == 0) {
506 OUT_RING(dev_priv->back_offset);
507 dev_priv->current_page = 1;
508 } else {
509 OUT_RING(dev_priv->front_offset);
510 dev_priv->current_page = 0;
511 }
512 OUT_RING(0);
513 ADVANCE_LP_RING();
514
515 BEGIN_LP_RING(2);
516 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
517 OUT_RING(0);
518 ADVANCE_LP_RING();
519
520 dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
521
522 BEGIN_LP_RING(4);
523 OUT_RING(CMD_STORE_DWORD_IDX);
524 OUT_RING(20);
525 OUT_RING(dev_priv->counter);
526 OUT_RING(0);
527 ADVANCE_LP_RING();
528
529 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
530 return 0;
531}
532
533static int i915_quiescent(drm_device_t * dev)
534{
535 drm_i915_private_t *dev_priv = dev->dev_private;
536
537 i915_kernel_lost_context(dev);
538 return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
539}
540
541int i915_flush_ioctl(DRM_IOCTL_ARGS)
542{
543 DRM_DEVICE;
544
545 LOCK_TEST_WITH_RETURN(dev, filp);
546
547 return i915_quiescent(dev);
548}
549
550int i915_batchbuffer(DRM_IOCTL_ARGS)
551{
552 DRM_DEVICE;
553 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
554 u32 *hw_status = dev_priv->hw_status_page;
555 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
556 dev_priv->sarea_priv;
557 drm_i915_batchbuffer_t batch;
558 int ret;
559
560 if (!dev_priv->allow_batchbuffer) {
561 DRM_ERROR("Batchbuffer ioctl disabled\n");
562 return DRM_ERR(EINVAL);
563 }
564
565 DRM_COPY_FROM_USER_IOCTL(batch, (drm_i915_batchbuffer_t __user *) data,
566 sizeof(batch));
567
568 DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
569 batch.start, batch.used, batch.num_cliprects);
570
571 LOCK_TEST_WITH_RETURN(dev, filp);
572
573 if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
574 batch.num_cliprects *
575 sizeof(drm_clip_rect_t)))
576 return DRM_ERR(EFAULT);
577
578 ret = i915_dispatch_batchbuffer(dev, &batch);
579
580 sarea_priv->last_dispatch = (int)hw_status[5];
581 return ret;
582}
583
584int i915_cmdbuffer(DRM_IOCTL_ARGS)
585{
586 DRM_DEVICE;
587 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
588 u32 *hw_status = dev_priv->hw_status_page;
589 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
590 dev_priv->sarea_priv;
591 drm_i915_cmdbuffer_t cmdbuf;
592 int ret;
593
594 DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_i915_cmdbuffer_t __user *) data,
595 sizeof(cmdbuf));
596
597 DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
598 cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects);
599
600 LOCK_TEST_WITH_RETURN(dev, filp);
601
602 if (cmdbuf.num_cliprects &&
603 DRM_VERIFYAREA_READ(cmdbuf.cliprects,
604 cmdbuf.num_cliprects *
605 sizeof(drm_clip_rect_t))) {
606 DRM_ERROR("Fault accessing cliprects\n");
607 return DRM_ERR(EFAULT);
608 }
609
610 ret = i915_dispatch_cmdbuffer(dev, &cmdbuf);
611 if (ret) {
612 DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
613 return ret;
614 }
615
616 sarea_priv->last_dispatch = (int)hw_status[5];
617 return 0;
618}
619
620int i915_do_cleanup_pageflip(drm_device_t * dev)
621{
622 drm_i915_private_t *dev_priv = dev->dev_private;
623
624 DRM_DEBUG("%s\n", __FUNCTION__);
625 if (dev_priv->current_page != 0)
626 i915_dispatch_flip(dev);
627
628 return 0;
629}
630
631int i915_flip_bufs(DRM_IOCTL_ARGS)
632{
633 DRM_DEVICE;
634
635 DRM_DEBUG("%s\n", __FUNCTION__);
636
637 LOCK_TEST_WITH_RETURN(dev, filp);
638
639 return i915_dispatch_flip(dev);
640}
641
642int i915_getparam(DRM_IOCTL_ARGS)
643{
644 DRM_DEVICE;
645 drm_i915_private_t *dev_priv = dev->dev_private;
646 drm_i915_getparam_t param;
647 int value;
648
649 if (!dev_priv) {
650 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
651 return DRM_ERR(EINVAL);
652 }
653
654 DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_getparam_t __user *) data,
655 sizeof(param));
656
657 switch (param.param) {
658 case I915_PARAM_IRQ_ACTIVE:
659 value = dev->irq ? 1 : 0;
660 break;
661 case I915_PARAM_ALLOW_BATCHBUFFER:
662 value = dev_priv->allow_batchbuffer ? 1 : 0;
663 break;
664 default:
665 DRM_ERROR("Unkown parameter %d\n", param.param);
666 return DRM_ERR(EINVAL);
667 }
668
669 if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
670 DRM_ERROR("DRM_COPY_TO_USER failed\n");
671 return DRM_ERR(EFAULT);
672 }
673
674 return 0;
675}
676
677int i915_setparam(DRM_IOCTL_ARGS)
678{
679 DRM_DEVICE;
680 drm_i915_private_t *dev_priv = dev->dev_private;
681 drm_i915_setparam_t param;
682
683 if (!dev_priv) {
684 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
685 return DRM_ERR(EINVAL);
686 }
687
688 DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_setparam_t __user *) data,
689 sizeof(param));
690
691 switch (param.param) {
692 case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
693 dev_priv->use_mi_batchbuffer_start = param.value;
694 break;
695 case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
696 dev_priv->tex_lru_log_granularity = param.value;
697 break;
698 case I915_SETPARAM_ALLOW_BATCHBUFFER:
699 dev_priv->allow_batchbuffer = param.value;
700 break;
701 default:
702 DRM_ERROR("unknown parameter %d\n", param.param);
703 return DRM_ERR(EINVAL);
704 }
705
706 return 0;
707}
708
709void i915_driver_pretakedown(drm_device_t *dev)
710{
711 if ( dev->dev_private ) {
712 drm_i915_private_t *dev_priv = dev->dev_private;
713 i915_mem_takedown( &(dev_priv->agp_heap) );
714 }
715 i915_dma_cleanup( dev );
716}
717
718void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp)
719{
720 if ( dev->dev_private ) {
721 drm_i915_private_t *dev_priv = dev->dev_private;
722 i915_mem_release( dev, filp, dev_priv->agp_heap );
723 }
724}
725
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
new file mode 100644
index 000000000000..7e55edf45c4f
--- /dev/null
+++ b/drivers/char/drm/i915_drm.h
@@ -0,0 +1,167 @@
1#ifndef _I915_DRM_H_
2#define _I915_DRM_H_
3
4/* Please note that modifications to all structs defined here are
5 * subject to backwards-compatibility constraints.
6 */
7
8#include "drm.h"
9
10/* Each region is a minimum of 16k, and there are at most 255 of them.
11 */
12#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
13 * of chars for next/prev indices */
14#define I915_LOG_MIN_TEX_REGION_SIZE 14
15
16typedef struct _drm_i915_init {
17 enum {
18 I915_INIT_DMA = 0x01,
19 I915_CLEANUP_DMA = 0x02,
20 I915_RESUME_DMA = 0x03
21 } func;
22 unsigned int mmio_offset;
23 int sarea_priv_offset;
24 unsigned int ring_start;
25 unsigned int ring_end;
26 unsigned int ring_size;
27 unsigned int front_offset;
28 unsigned int back_offset;
29 unsigned int depth_offset;
30 unsigned int w;
31 unsigned int h;
32 unsigned int pitch;
33 unsigned int pitch_bits;
34 unsigned int back_pitch;
35 unsigned int depth_pitch;
36 unsigned int cpp;
37 unsigned int chipset;
38} drm_i915_init_t;
39
40typedef struct _drm_i915_sarea {
41 drm_tex_region_t texList[I915_NR_TEX_REGIONS + 1];
42 int last_upload; /* last time texture was uploaded */
43 int last_enqueue; /* last time a buffer was enqueued */
44 int last_dispatch; /* age of the most recently dispatched buffer */
45 int ctxOwner; /* last context to upload state */
46 int texAge;
47 int pf_enabled; /* is pageflipping allowed? */
48 int pf_active;
49 int pf_current_page; /* which buffer is being displayed? */
50 int perf_boxes; /* performance boxes to be displayed */
51} drm_i915_sarea_t;
52
53/* Flags for perf_boxes
54 */
55#define I915_BOX_RING_EMPTY 0x1
56#define I915_BOX_FLIP 0x2
57#define I915_BOX_WAIT 0x4
58#define I915_BOX_TEXTURE_LOAD 0x8
59#define I915_BOX_LOST_CONTEXT 0x10
60
61/* I915 specific ioctls
62 * The device specific ioctl range is 0x40 to 0x79.
63 */
64#define DRM_I915_INIT 0x00
65#define DRM_I915_FLUSH 0x01
66#define DRM_I915_FLIP 0x02
67#define DRM_I915_BATCHBUFFER 0x03
68#define DRM_I915_IRQ_EMIT 0x04
69#define DRM_I915_IRQ_WAIT 0x05
70#define DRM_I915_GETPARAM 0x06
71#define DRM_I915_SETPARAM 0x07
72#define DRM_I915_ALLOC 0x08
73#define DRM_I915_FREE 0x09
74#define DRM_I915_INIT_HEAP 0x0a
75#define DRM_I915_CMDBUFFER 0x0b
76
77#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
78#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
79#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
80#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
81#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
82#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
83#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t)
84#define DRM_IOCTL_I915_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t)
85#define DRM_IOCTL_I915_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t)
86#define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t)
87#define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
88#define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
89
90/* Allow drivers to submit batchbuffers directly to hardware, relying
91 * on the security mechanisms provided by hardware.
92 */
93typedef struct _drm_i915_batchbuffer {
94 int start; /* agp offset */
95 int used; /* nr bytes in use */
96 int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
97 int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
98 int num_cliprects; /* mulitpass with multiple cliprects? */
99 drm_clip_rect_t __user *cliprects; /* pointer to userspace cliprects */
100} drm_i915_batchbuffer_t;
101
102/* As above, but pass a pointer to userspace buffer which can be
103 * validated by the kernel prior to sending to hardware.
104 */
105typedef struct _drm_i915_cmdbuffer {
106 char __user *buf; /* pointer to userspace command buffer */
107 int sz; /* nr bytes in buf */
108 int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
109 int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
110 int num_cliprects; /* mulitpass with multiple cliprects? */
111 drm_clip_rect_t __user *cliprects; /* pointer to userspace cliprects */
112} drm_i915_cmdbuffer_t;
113
114/* Userspace can request & wait on irq's:
115 */
116typedef struct drm_i915_irq_emit {
117 int __user *irq_seq;
118} drm_i915_irq_emit_t;
119
120typedef struct drm_i915_irq_wait {
121 int irq_seq;
122} drm_i915_irq_wait_t;
123
124/* Ioctl to query kernel params:
125 */
126#define I915_PARAM_IRQ_ACTIVE 1
127#define I915_PARAM_ALLOW_BATCHBUFFER 2
128
129typedef struct drm_i915_getparam {
130 int param;
131 int __user *value;
132} drm_i915_getparam_t;
133
134/* Ioctl to set kernel params:
135 */
136#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1
137#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2
138#define I915_SETPARAM_ALLOW_BATCHBUFFER 3
139
140typedef struct drm_i915_setparam {
141 int param;
142 int value;
143} drm_i915_setparam_t;
144
145/* A memory manager for regions of shared memory:
146 */
147#define I915_MEM_REGION_AGP 1
148
149typedef struct drm_i915_mem_alloc {
150 int region;
151 int alignment;
152 int size;
153 int __user *region_offset; /* offset from start of fb or agp */
154} drm_i915_mem_alloc_t;
155
156typedef struct drm_i915_mem_free {
157 int region;
158 int region_offset;
159} drm_i915_mem_free_t;
160
161typedef struct drm_i915_mem_init_heap {
162 int region;
163 int size;
164 int start;
165} drm_i915_mem_init_heap_t;
166
167#endif /* _I915_DRM_H_ */
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
new file mode 100644
index 000000000000..002b7082e21b
--- /dev/null
+++ b/drivers/char/drm/i915_drv.c
@@ -0,0 +1,104 @@
1/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
2 */
3
4/**************************************************************************
5 *
6 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
7 * All Rights Reserved.
8 *
9 **************************************************************************/
10
11#include "drmP.h"
12#include "drm.h"
13#include "i915_drm.h"
14#include "i915_drv.h"
15
16#include "drm_pciids.h"
17
18int postinit( struct drm_device *dev, unsigned long flags )
19{
20 dev->counters += 4;
21 dev->types[6] = _DRM_STAT_IRQ;
22 dev->types[7] = _DRM_STAT_PRIMARY;
23 dev->types[8] = _DRM_STAT_SECONDARY;
24 dev->types[9] = _DRM_STAT_DMA;
25
26 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
27 DRIVER_NAME,
28 DRIVER_MAJOR,
29 DRIVER_MINOR,
30 DRIVER_PATCHLEVEL,
31 DRIVER_DATE,
32 dev->primary.minor,
33 pci_pretty_name(dev->pdev)
34 );
35 return 0;
36}
37
38static int version( drm_version_t *version )
39{
40 int len;
41
42 version->version_major = DRIVER_MAJOR;
43 version->version_minor = DRIVER_MINOR;
44 version->version_patchlevel = DRIVER_PATCHLEVEL;
45 DRM_COPY( version->name, DRIVER_NAME );
46 DRM_COPY( version->date, DRIVER_DATE );
47 DRM_COPY( version->desc, DRIVER_DESC );
48 return 0;
49}
50
51static struct pci_device_id pciidlist[] = {
52 i915_PCI_IDS
53};
54
55extern drm_ioctl_desc_t i915_ioctls[];
56extern int i915_max_ioctl;
57
58static struct drm_driver driver = {
59 .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
60 DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
61 .pretakedown = i915_driver_pretakedown,
62 .prerelease = i915_driver_prerelease,
63 .irq_preinstall = i915_driver_irq_preinstall,
64 .irq_postinstall = i915_driver_irq_postinstall,
65 .irq_uninstall = i915_driver_irq_uninstall,
66 .irq_handler = i915_driver_irq_handler,
67 .reclaim_buffers = drm_core_reclaim_buffers,
68 .get_map_ofs = drm_core_get_map_ofs,
69 .get_reg_ofs = drm_core_get_reg_ofs,
70 .postinit = postinit,
71 .version = version,
72 .ioctls = i915_ioctls,
73 .fops = {
74 .owner = THIS_MODULE,
75 .open = drm_open,
76 .release = drm_release,
77 .ioctl = drm_ioctl,
78 .mmap = drm_mmap,
79 .poll = drm_poll,
80 .fasync = drm_fasync,
81 },
82 .pci_driver = {
83 .name = DRIVER_NAME,
84 .id_table = pciidlist,
85 }
86};
87
88static int __init i915_init(void)
89{
90 driver.num_ioctls = i915_max_ioctl;
91 return drm_init(&driver);
92}
93
94static void __exit i915_exit(void)
95{
96 drm_exit(&driver);
97}
98
99module_init(i915_init);
100module_exit(i915_exit);
101
102MODULE_AUTHOR( DRIVER_AUTHOR );
103MODULE_DESCRIPTION( DRIVER_DESC );
104MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
new file mode 100644
index 000000000000..f6ca92a565db
--- /dev/null
+++ b/drivers/char/drm/i915_drv.h
@@ -0,0 +1,243 @@
1/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
2 */
3/**************************************************************************
4 *
5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * All Rights Reserved.
7 *
8 **************************************************************************/
9
10#ifndef _I915_DRV_H_
11#define _I915_DRV_H_
12
13/* General customization:
14 */
15
16#define DRIVER_AUTHOR "Tungsten Graphics, Inc."
17
18#define DRIVER_NAME "i915"
19#define DRIVER_DESC "Intel Graphics"
20#define DRIVER_DATE "20040405"
21
22/* Interface history:
23 *
24 * 1.1: Original.
25 */
26#define DRIVER_MAJOR 1
27#define DRIVER_MINOR 1
28#define DRIVER_PATCHLEVEL 0
29
30/* We use our own dma mechanisms, not the drm template code. However,
31 * the shared IRQ code is useful to us:
32 */
33#define __HAVE_PM 1
34
35typedef struct _drm_i915_ring_buffer {
36 int tail_mask;
37 unsigned long Start;
38 unsigned long End;
39 unsigned long Size;
40 u8 *virtual_start;
41 int head;
42 int tail;
43 int space;
44 drm_local_map_t map;
45} drm_i915_ring_buffer_t;
46
47struct mem_block {
48 struct mem_block *next;
49 struct mem_block *prev;
50 int start;
51 int size;
52 DRMFILE filp; /* 0: free, -1: heap, other: real files */
53};
54
55typedef struct drm_i915_private {
56 drm_local_map_t *sarea;
57 drm_local_map_t *mmio_map;
58
59 drm_i915_sarea_t *sarea_priv;
60 drm_i915_ring_buffer_t ring;
61
62 void *hw_status_page;
63 unsigned long counter;
64 dma_addr_t dma_status_page;
65
66 int back_offset;
67 int front_offset;
68 int current_page;
69 int page_flipping;
70 int use_mi_batchbuffer_start;
71
72 wait_queue_head_t irq_queue;
73 atomic_t irq_received;
74 atomic_t irq_emitted;
75
76 int tex_lru_log_granularity;
77 int allow_batchbuffer;
78 struct mem_block *agp_heap;
79} drm_i915_private_t;
80
81 /* i915_dma.c */
82extern int i915_dma_init(DRM_IOCTL_ARGS);
83extern int i915_dma_cleanup(drm_device_t * dev);
84extern int i915_flush_ioctl(DRM_IOCTL_ARGS);
85extern int i915_batchbuffer(DRM_IOCTL_ARGS);
86extern int i915_flip_bufs(DRM_IOCTL_ARGS);
87extern int i915_getparam(DRM_IOCTL_ARGS);
88extern int i915_setparam(DRM_IOCTL_ARGS);
89extern int i915_cmdbuffer(DRM_IOCTL_ARGS);
90extern void i915_kernel_lost_context(drm_device_t * dev);
91extern void i915_driver_pretakedown(drm_device_t *dev);
92extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp);
93
94/* i915_irq.c */
95extern int i915_irq_emit(DRM_IOCTL_ARGS);
96extern int i915_irq_wait(DRM_IOCTL_ARGS);
97extern int i915_wait_irq(drm_device_t * dev, int irq_nr);
98extern int i915_emit_irq(drm_device_t * dev);
99
100extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
101extern void i915_driver_irq_preinstall(drm_device_t *dev);
102extern void i915_driver_irq_postinstall(drm_device_t *dev);
103extern void i915_driver_irq_uninstall(drm_device_t *dev);
104
105/* i915_mem.c */
106extern int i915_mem_alloc(DRM_IOCTL_ARGS);
107extern int i915_mem_free(DRM_IOCTL_ARGS);
108extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
109extern void i915_mem_takedown(struct mem_block **heap);
110extern void i915_mem_release(drm_device_t * dev,
111 DRMFILE filp, struct mem_block *heap);
112
113#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
114#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
115#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
116#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, reg, val)
117
118#define I915_VERBOSE 0
119
120#define RING_LOCALS unsigned int outring, ringmask, outcount; \
121 volatile char *virt;
122
123#define BEGIN_LP_RING(n) do { \
124 if (I915_VERBOSE) \
125 DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \
126 n, __FUNCTION__); \
127 if (dev_priv->ring.space < n*4) \
128 i915_wait_ring(dev, n*4, __FUNCTION__); \
129 outcount = 0; \
130 outring = dev_priv->ring.tail; \
131 ringmask = dev_priv->ring.tail_mask; \
132 virt = dev_priv->ring.virtual_start; \
133} while (0)
134
135#define OUT_RING(n) do { \
136 if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
137 *(volatile unsigned int *)(virt + outring) = n; \
138 outcount++; \
139 outring += 4; \
140 outring &= ringmask; \
141} while (0)
142
143#define ADVANCE_LP_RING() do { \
144 if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring); \
145 dev_priv->ring.tail = outring; \
146 dev_priv->ring.space -= outcount * 4; \
147 I915_WRITE(LP_RING + RING_TAIL, outring); \
148} while(0)
149
150extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
151
152#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
153#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
154#define CMD_REPORT_HEAD (7<<23)
155#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1)
156#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1)
157
158#define INST_PARSER_CLIENT 0x00000000
159#define INST_OP_FLUSH 0x02000000
160#define INST_FLUSH_MAP_CACHE 0x00000001
161
162#define BB1_START_ADDR_MASK (~0x7)
163#define BB1_PROTECTED (1<<0)
164#define BB1_UNPROTECTED (0<<0)
165#define BB2_END_ADDR_MASK (~0x7)
166
167#define I915REG_HWSTAM 0x02098
168#define I915REG_INT_IDENTITY_R 0x020a4
169#define I915REG_INT_MASK_R 0x020a8
170#define I915REG_INT_ENABLE_R 0x020a0
171
172#define SRX_INDEX 0x3c4
173#define SRX_DATA 0x3c5
174#define SR01 1
175#define SR01_SCREEN_OFF (1<<5)
176
177#define PPCR 0x61204
178#define PPCR_ON (1<<0)
179
180#define ADPA 0x61100
181#define ADPA_DPMS_MASK (~(3<<10))
182#define ADPA_DPMS_ON (0<<10)
183#define ADPA_DPMS_SUSPEND (1<<10)
184#define ADPA_DPMS_STANDBY (2<<10)
185#define ADPA_DPMS_OFF (3<<10)
186
187#define NOPID 0x2094
188#define LP_RING 0x2030
189#define HP_RING 0x2040
190#define RING_TAIL 0x00
191#define TAIL_ADDR 0x001FFFF8
192#define RING_HEAD 0x04
193#define HEAD_WRAP_COUNT 0xFFE00000
194#define HEAD_WRAP_ONE 0x00200000
195#define HEAD_ADDR 0x001FFFFC
196#define RING_START 0x08
197#define START_ADDR 0x0xFFFFF000
198#define RING_LEN 0x0C
199#define RING_NR_PAGES 0x001FF000
200#define RING_REPORT_MASK 0x00000006
201#define RING_REPORT_64K 0x00000002
202#define RING_REPORT_128K 0x00000004
203#define RING_NO_REPORT 0x00000000
204#define RING_VALID_MASK 0x00000001
205#define RING_VALID 0x00000001
206#define RING_INVALID 0x00000000
207
208#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19))
209#define SC_UPDATE_SCISSOR (0x1<<1)
210#define SC_ENABLE_MASK (0x1<<0)
211#define SC_ENABLE (0x1<<0)
212
213#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
214#define SCI_YMIN_MASK (0xffff<<16)
215#define SCI_XMIN_MASK (0xffff<<0)
216#define SCI_YMAX_MASK (0xffff<<16)
217#define SCI_XMAX_MASK (0xffff<<0)
218
219#define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19))
220#define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
221#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
222#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
223#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4)
224#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
225#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
226
227#define MI_BATCH_BUFFER ((0x30<<23)|1)
228#define MI_BATCH_BUFFER_START (0x31<<23)
229#define MI_BATCH_BUFFER_END (0xA<<23)
230#define MI_BATCH_NON_SECURE (1)
231
232#define MI_WAIT_FOR_EVENT ((0x3<<23))
233#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
234#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
235
236#define MI_LOAD_SCAN_LINES_INCL ((0x12<<23))
237
238#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
239#define ASYNC_FLIP (1<<22)
240
241#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
242
243#endif
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
new file mode 100644
index 000000000000..b0239262a84a
--- /dev/null
+++ b/drivers/char/drm/i915_irq.c
@@ -0,0 +1,161 @@
1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
2 */
3/**************************************************************************
4 *
5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * All Rights Reserved.
7 *
8 **************************************************************************/
9
10#include "drmP.h"
11#include "drm.h"
12#include "i915_drm.h"
13#include "i915_drv.h"
14
15#define USER_INT_FLAG 0x2
16#define MAX_NOPID ((u32)~0)
17#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5])
18
19irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
20{
21 drm_device_t *dev = (drm_device_t *) arg;
22 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
23 u16 temp;
24
25 temp = I915_READ16(I915REG_INT_IDENTITY_R);
26 temp &= USER_INT_FLAG;
27
28 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
29
30 if (temp == 0)
31 return IRQ_NONE;
32
33 I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
34 DRM_WAKEUP(&dev_priv->irq_queue);
35
36 return IRQ_HANDLED;
37}
38
39int i915_emit_irq(drm_device_t * dev)
40{
41 drm_i915_private_t *dev_priv = dev->dev_private;
42 u32 ret;
43 RING_LOCALS;
44
45 i915_kernel_lost_context(dev);
46
47 DRM_DEBUG("%s\n", __FUNCTION__);
48
49 ret = dev_priv->counter;
50
51 BEGIN_LP_RING(2);
52 OUT_RING(0);
53 OUT_RING(GFX_OP_USER_INTERRUPT);
54 ADVANCE_LP_RING();
55
56 return ret;
57}
58
59int i915_wait_irq(drm_device_t * dev, int irq_nr)
60{
61 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
62 int ret = 0;
63
64 DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
65 READ_BREADCRUMB(dev_priv));
66
67 if (READ_BREADCRUMB(dev_priv) >= irq_nr)
68 return 0;
69
70 dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
71
72 DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
73 READ_BREADCRUMB(dev_priv) >= irq_nr);
74
75 if (ret == DRM_ERR(EBUSY)) {
76 DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
77 __FUNCTION__,
78 READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
79 }
80
81 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
82 return ret;
83}
84
85/* Needs the lock as it touches the ring.
86 */
87int i915_irq_emit(DRM_IOCTL_ARGS)
88{
89 DRM_DEVICE;
90 drm_i915_private_t *dev_priv = dev->dev_private;
91 drm_i915_irq_emit_t emit;
92 int result;
93
94 LOCK_TEST_WITH_RETURN(dev, filp);
95
96 if (!dev_priv) {
97 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
98 return DRM_ERR(EINVAL);
99 }
100
101 DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data,
102 sizeof(emit));
103
104 result = i915_emit_irq(dev);
105
106 if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
107 DRM_ERROR("copy_to_user\n");
108 return DRM_ERR(EFAULT);
109 }
110
111 return 0;
112}
113
114/* Doesn't need the hardware lock.
115 */
116int i915_irq_wait(DRM_IOCTL_ARGS)
117{
118 DRM_DEVICE;
119 drm_i915_private_t *dev_priv = dev->dev_private;
120 drm_i915_irq_wait_t irqwait;
121
122 if (!dev_priv) {
123 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
124 return DRM_ERR(EINVAL);
125 }
126
127 DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data,
128 sizeof(irqwait));
129
130 return i915_wait_irq(dev, irqwait.irq_seq);
131}
132
133/* drm_dma.h hooks
134*/
135void i915_driver_irq_preinstall(drm_device_t * dev)
136{
137 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
138
139 I915_WRITE16(I915REG_HWSTAM, 0xfffe);
140 I915_WRITE16(I915REG_INT_MASK_R, 0x0);
141 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
142}
143
144void i915_driver_irq_postinstall(drm_device_t * dev)
145{
146 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
147
148 I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);
149 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
150}
151
152void i915_driver_irq_uninstall(drm_device_t * dev)
153{
154 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
155 if (!dev_priv)
156 return;
157
158 I915_WRITE16(I915REG_HWSTAM, 0xffff);
159 I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
160 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
161}
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
new file mode 100644
index 000000000000..d54a3005946b
--- /dev/null
+++ b/drivers/char/drm/i915_mem.c
@@ -0,0 +1,346 @@
1/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
2 */
3/**************************************************************************
4 *
5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * All Rights Reserved.
7 *
8 **************************************************************************/
9
10#include "drmP.h"
11#include "drm.h"
12#include "i915_drm.h"
13#include "i915_drv.h"
14
15/* This memory manager is integrated into the global/local lru
16 * mechanisms used by the clients. Specifically, it operates by
17 * setting the 'in_use' fields of the global LRU to indicate whether
18 * this region is privately allocated to a client.
19 *
20 * This does require the client to actually respect that field.
21 *
22 * Currently no effort is made to allocate 'private' memory in any
23 * clever way - the LRU information isn't used to determine which
24 * block to allocate, and the ring is drained prior to allocations --
25 * in other words allocation is expensive.
26 */
27static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
28{
29 drm_i915_private_t *dev_priv = dev->dev_private;
30 drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
31 drm_tex_region_t *list;
32 unsigned shift, nr;
33 unsigned start;
34 unsigned end;
35 unsigned i;
36 int age;
37
38 shift = dev_priv->tex_lru_log_granularity;
39 nr = I915_NR_TEX_REGIONS;
40
41 start = p->start >> shift;
42 end = (p->start + p->size - 1) >> shift;
43
44 age = ++sarea_priv->texAge;
45 list = sarea_priv->texList;
46
47 /* Mark the regions with the new flag and update their age. Move
48 * them to head of list to preserve LRU semantics.
49 */
50 for (i = start; i <= end; i++) {
51 list[i].in_use = in_use;
52 list[i].age = age;
53
54 /* remove_from_list(i)
55 */
56 list[(unsigned)list[i].next].prev = list[i].prev;
57 list[(unsigned)list[i].prev].next = list[i].next;
58
59 /* insert_at_head(list, i)
60 */
61 list[i].prev = nr;
62 list[i].next = list[nr].next;
63 list[(unsigned)list[nr].next].prev = i;
64 list[nr].next = i;
65 }
66}
67
68/* Very simple allocator for agp memory, working on a static range
69 * already mapped into each client's address space.
70 */
71
72static struct mem_block *split_block(struct mem_block *p, int start, int size,
73 DRMFILE filp)
74{
75 /* Maybe cut off the start of an existing block */
76 if (start > p->start) {
77 struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
78 if (!newblock)
79 goto out;
80 newblock->start = start;
81 newblock->size = p->size - (start - p->start);
82 newblock->filp = NULL;
83 newblock->next = p->next;
84 newblock->prev = p;
85 p->next->prev = newblock;
86 p->next = newblock;
87 p->size -= newblock->size;
88 p = newblock;
89 }
90
91 /* Maybe cut off the end of an existing block */
92 if (size < p->size) {
93 struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
94 if (!newblock)
95 goto out;
96 newblock->start = start + size;
97 newblock->size = p->size - size;
98 newblock->filp = NULL;
99 newblock->next = p->next;
100 newblock->prev = p;
101 p->next->prev = newblock;
102 p->next = newblock;
103 p->size = size;
104 }
105
106 out:
107 /* Our block is in the middle */
108 p->filp = filp;
109 return p;
110}
111
112static struct mem_block *alloc_block(struct mem_block *heap, int size,
113 int align2, DRMFILE filp)
114{
115 struct mem_block *p;
116 int mask = (1 << align2) - 1;
117
118 for (p = heap->next; p != heap; p = p->next) {
119 int start = (p->start + mask) & ~mask;
120 if (p->filp == NULL && start + size <= p->start + p->size)
121 return split_block(p, start, size, filp);
122 }
123
124 return NULL;
125}
126
127static struct mem_block *find_block(struct mem_block *heap, int start)
128{
129 struct mem_block *p;
130
131 for (p = heap->next; p != heap; p = p->next)
132 if (p->start == start)
133 return p;
134
135 return NULL;
136}
137
138static void free_block(struct mem_block *p)
139{
140 p->filp = NULL;
141
142 /* Assumes a single contiguous range. Needs a special filp in
143 * 'heap' to stop it being subsumed.
144 */
145 if (p->next->filp == NULL) {
146 struct mem_block *q = p->next;
147 p->size += q->size;
148 p->next = q->next;
149 p->next->prev = p;
150 drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
151 }
152
153 if (p->prev->filp == NULL) {
154 struct mem_block *q = p->prev;
155 q->size += p->size;
156 q->next = p->next;
157 q->next->prev = q;
158 drm_free(p, sizeof(*q), DRM_MEM_BUFLISTS);
159 }
160}
161
162/* Initialize. How to check for an uninitialized heap?
163 */
164static int init_heap(struct mem_block **heap, int start, int size)
165{
166 struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFLISTS);
167
168 if (!blocks)
169 return -ENOMEM;
170
171 *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFLISTS);
172 if (!*heap) {
173 drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFLISTS);
174 return -ENOMEM;
175 }
176
177 blocks->start = start;
178 blocks->size = size;
179 blocks->filp = NULL;
180 blocks->next = blocks->prev = *heap;
181
182 memset(*heap, 0, sizeof(**heap));
183 (*heap)->filp = (DRMFILE) - 1;
184 (*heap)->next = (*heap)->prev = blocks;
185 return 0;
186}
187
188/* Free all blocks associated with the releasing file.
189 */
190void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap)
191{
192 struct mem_block *p;
193
194 if (!heap || !heap->next)
195 return;
196
197 for (p = heap->next; p != heap; p = p->next) {
198 if (p->filp == filp) {
199 p->filp = NULL;
200 mark_block(dev, p, 0);
201 }
202 }
203
204 /* Assumes a single contiguous range. Needs a special filp in
205 * 'heap' to stop it being subsumed.
206 */
207 for (p = heap->next; p != heap; p = p->next) {
208 while (p->filp == NULL && p->next->filp == NULL) {
209 struct mem_block *q = p->next;
210 p->size += q->size;
211 p->next = q->next;
212 p->next->prev = p;
213 drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
214 }
215 }
216}
217
218/* Shutdown.
219 */
220void i915_mem_takedown(struct mem_block **heap)
221{
222 struct mem_block *p;
223
224 if (!*heap)
225 return;
226
227 for (p = (*heap)->next; p != *heap;) {
228 struct mem_block *q = p;
229 p = p->next;
230 drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
231 }
232
233 drm_free(*heap, sizeof(**heap), DRM_MEM_BUFLISTS);
234 *heap = NULL;
235}
236
237static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
238{
239 switch (region) {
240 case I915_MEM_REGION_AGP:
241 return &dev_priv->agp_heap;
242 default:
243 return NULL;
244 }
245}
246
247/* IOCTL HANDLERS */
248
249int i915_mem_alloc(DRM_IOCTL_ARGS)
250{
251 DRM_DEVICE;
252 drm_i915_private_t *dev_priv = dev->dev_private;
253 drm_i915_mem_alloc_t alloc;
254 struct mem_block *block, **heap;
255
256 if (!dev_priv) {
257 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
258 return DRM_ERR(EINVAL);
259 }
260
261 DRM_COPY_FROM_USER_IOCTL(alloc, (drm_i915_mem_alloc_t __user *) data,
262 sizeof(alloc));
263
264 heap = get_heap(dev_priv, alloc.region);
265 if (!heap || !*heap)
266 return DRM_ERR(EFAULT);
267
268 /* Make things easier on ourselves: all allocations at least
269 * 4k aligned.
270 */
271 if (alloc.alignment < 12)
272 alloc.alignment = 12;
273
274 block = alloc_block(*heap, alloc.size, alloc.alignment, filp);
275
276 if (!block)
277 return DRM_ERR(ENOMEM);
278
279 mark_block(dev, block, 1);
280
281 if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) {
282 DRM_ERROR("copy_to_user\n");
283 return DRM_ERR(EFAULT);
284 }
285
286 return 0;
287}
288
289int i915_mem_free(DRM_IOCTL_ARGS)
290{
291 DRM_DEVICE;
292 drm_i915_private_t *dev_priv = dev->dev_private;
293 drm_i915_mem_free_t memfree;
294 struct mem_block *block, **heap;
295
296 if (!dev_priv) {
297 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
298 return DRM_ERR(EINVAL);
299 }
300
301 DRM_COPY_FROM_USER_IOCTL(memfree, (drm_i915_mem_free_t __user *) data,
302 sizeof(memfree));
303
304 heap = get_heap(dev_priv, memfree.region);
305 if (!heap || !*heap)
306 return DRM_ERR(EFAULT);
307
308 block = find_block(*heap, memfree.region_offset);
309 if (!block)
310 return DRM_ERR(EFAULT);
311
312 if (block->filp != filp)
313 return DRM_ERR(EPERM);
314
315 mark_block(dev, block, 0);
316 free_block(block);
317 return 0;
318}
319
320int i915_mem_init_heap(DRM_IOCTL_ARGS)
321{
322 DRM_DEVICE;
323 drm_i915_private_t *dev_priv = dev->dev_private;
324 drm_i915_mem_init_heap_t initheap;
325 struct mem_block **heap;
326
327 if (!dev_priv) {
328 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
329 return DRM_ERR(EINVAL);
330 }
331
332 DRM_COPY_FROM_USER_IOCTL(initheap,
333 (drm_i915_mem_init_heap_t __user *) data,
334 sizeof(initheap));
335
336 heap = get_heap(dev_priv, initheap.region);
337 if (!heap)
338 return DRM_ERR(EFAULT);
339
340 if (*heap) {
341 DRM_ERROR("heap already initialized?");
342 return DRM_ERR(EFAULT);
343 }
344
345 return init_heap(heap, initheap.start, initheap.size);
346}
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
new file mode 100644
index 000000000000..832eaf8a5068
--- /dev/null
+++ b/drivers/char/drm/mga_dma.c
@@ -0,0 +1,754 @@
1/* mga_dma.c -- DMA support for mga g200/g400 -*- linux-c -*-
2 * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Jeff Hartmann <jhartmann@valinux.com>
30 * Keith Whitwell <keith@tungstengraphics.com>
31 *
32 * Rewritten by:
33 * Gareth Hughes <gareth@valinux.com>
34 */
35
36#include "drmP.h"
37#include "drm.h"
38#include "mga_drm.h"
39#include "mga_drv.h"
40
41#define MGA_DEFAULT_USEC_TIMEOUT 10000
42#define MGA_FREELIST_DEBUG 0
43
44static int mga_do_cleanup_dma( drm_device_t *dev );
45
46/* ================================================================
47 * Engine control
48 */
49
50int mga_do_wait_for_idle( drm_mga_private_t *dev_priv )
51{
52 u32 status = 0;
53 int i;
54 DRM_DEBUG( "\n" );
55
56 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
57 status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
58 if ( status == MGA_ENDPRDMASTS ) {
59 MGA_WRITE8( MGA_CRTC_INDEX, 0 );
60 return 0;
61 }
62 DRM_UDELAY( 1 );
63 }
64
65#if MGA_DMA_DEBUG
66 DRM_ERROR( "failed!\n" );
67 DRM_INFO( " status=0x%08x\n", status );
68#endif
69 return DRM_ERR(EBUSY);
70}
71
72static int mga_do_dma_reset( drm_mga_private_t *dev_priv )
73{
74 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
75 drm_mga_primary_buffer_t *primary = &dev_priv->prim;
76
77 DRM_DEBUG( "\n" );
78
79 /* The primary DMA stream should look like new right about now.
80 */
81 primary->tail = 0;
82 primary->space = primary->size;
83 primary->last_flush = 0;
84
85 sarea_priv->last_wrap = 0;
86
87 /* FIXME: Reset counters, buffer ages etc...
88 */
89
90 /* FIXME: What else do we need to reinitialize? WARP stuff?
91 */
92
93 return 0;
94}
95
96/* ================================================================
97 * Primary DMA stream
98 */
99
100void mga_do_dma_flush( drm_mga_private_t *dev_priv )
101{
102 drm_mga_primary_buffer_t *primary = &dev_priv->prim;
103 u32 head, tail;
104 u32 status = 0;
105 int i;
106 DMA_LOCALS;
107 DRM_DEBUG( "\n" );
108
109 /* We need to wait so that we can do an safe flush */
110 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
111 status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
112 if ( status == MGA_ENDPRDMASTS ) break;
113 DRM_UDELAY( 1 );
114 }
115
116 if ( primary->tail == primary->last_flush ) {
117 DRM_DEBUG( " bailing out...\n" );
118 return;
119 }
120
121 tail = primary->tail + dev_priv->primary->offset;
122
123 /* We need to pad the stream between flushes, as the card
124 * actually (partially?) reads the first of these commands.
125 * See page 4-16 in the G400 manual, middle of the page or so.
126 */
127 BEGIN_DMA( 1 );
128
129 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
130 MGA_DMAPAD, 0x00000000,
131 MGA_DMAPAD, 0x00000000,
132 MGA_DMAPAD, 0x00000000 );
133
134 ADVANCE_DMA();
135
136 primary->last_flush = primary->tail;
137
138 head = MGA_READ( MGA_PRIMADDRESS );
139
140 if ( head <= tail ) {
141 primary->space = primary->size - primary->tail;
142 } else {
143 primary->space = head - tail;
144 }
145
146 DRM_DEBUG( " head = 0x%06lx\n", head - dev_priv->primary->offset );
147 DRM_DEBUG( " tail = 0x%06lx\n", tail - dev_priv->primary->offset );
148 DRM_DEBUG( " space = 0x%06x\n", primary->space );
149
150 mga_flush_write_combine();
151 MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
152
153 DRM_DEBUG( "done.\n" );
154}
155
156void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
157{
158 drm_mga_primary_buffer_t *primary = &dev_priv->prim;
159 u32 head, tail;
160 DMA_LOCALS;
161 DRM_DEBUG( "\n" );
162
163 BEGIN_DMA_WRAP();
164
165 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
166 MGA_DMAPAD, 0x00000000,
167 MGA_DMAPAD, 0x00000000,
168 MGA_DMAPAD, 0x00000000 );
169
170 ADVANCE_DMA();
171
172 tail = primary->tail + dev_priv->primary->offset;
173
174 primary->tail = 0;
175 primary->last_flush = 0;
176 primary->last_wrap++;
177
178 head = MGA_READ( MGA_PRIMADDRESS );
179
180 if ( head == dev_priv->primary->offset ) {
181 primary->space = primary->size;
182 } else {
183 primary->space = head - dev_priv->primary->offset;
184 }
185
186 DRM_DEBUG( " head = 0x%06lx\n",
187 head - dev_priv->primary->offset );
188 DRM_DEBUG( " tail = 0x%06x\n", primary->tail );
189 DRM_DEBUG( " wrap = %d\n", primary->last_wrap );
190 DRM_DEBUG( " space = 0x%06x\n", primary->space );
191
192 mga_flush_write_combine();
193 MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
194
195 set_bit( 0, &primary->wrapped );
196 DRM_DEBUG( "done.\n" );
197}
198
199void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
200{
201 drm_mga_primary_buffer_t *primary = &dev_priv->prim;
202 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
203 u32 head = dev_priv->primary->offset;
204 DRM_DEBUG( "\n" );
205
206 sarea_priv->last_wrap++;
207 DRM_DEBUG( " wrap = %d\n", sarea_priv->last_wrap );
208
209 mga_flush_write_combine();
210 MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL );
211
212 clear_bit( 0, &primary->wrapped );
213 DRM_DEBUG( "done.\n" );
214}
215
216
217/* ================================================================
218 * Freelist management
219 */
220
221#define MGA_BUFFER_USED ~0
222#define MGA_BUFFER_FREE 0
223
224#if MGA_FREELIST_DEBUG
225static void mga_freelist_print( drm_device_t *dev )
226{
227 drm_mga_private_t *dev_priv = dev->dev_private;
228 drm_mga_freelist_t *entry;
229
230 DRM_INFO( "\n" );
231 DRM_INFO( "current dispatch: last=0x%x done=0x%x\n",
232 dev_priv->sarea_priv->last_dispatch,
233 (unsigned int)(MGA_READ( MGA_PRIMADDRESS ) -
234 dev_priv->primary->offset) );
235 DRM_INFO( "current freelist:\n" );
236
237 for ( entry = dev_priv->head->next ; entry ; entry = entry->next ) {
238 DRM_INFO( " %p idx=%2d age=0x%x 0x%06lx\n",
239 entry, entry->buf->idx, entry->age.head,
240 entry->age.head - dev_priv->primary->offset );
241 }
242 DRM_INFO( "\n" );
243}
244#endif
245
246static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv )
247{
248 drm_device_dma_t *dma = dev->dma;
249 drm_buf_t *buf;
250 drm_mga_buf_priv_t *buf_priv;
251 drm_mga_freelist_t *entry;
252 int i;
253 DRM_DEBUG( "count=%d\n", dma->buf_count );
254
255 dev_priv->head = drm_alloc( sizeof(drm_mga_freelist_t),
256 DRM_MEM_DRIVER );
257 if ( dev_priv->head == NULL )
258 return DRM_ERR(ENOMEM);
259
260 memset( dev_priv->head, 0, sizeof(drm_mga_freelist_t) );
261 SET_AGE( &dev_priv->head->age, MGA_BUFFER_USED, 0 );
262
263 for ( i = 0 ; i < dma->buf_count ; i++ ) {
264 buf = dma->buflist[i];
265 buf_priv = buf->dev_private;
266
267 entry = drm_alloc( sizeof(drm_mga_freelist_t),
268 DRM_MEM_DRIVER );
269 if ( entry == NULL )
270 return DRM_ERR(ENOMEM);
271
272 memset( entry, 0, sizeof(drm_mga_freelist_t) );
273
274 entry->next = dev_priv->head->next;
275 entry->prev = dev_priv->head;
276 SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
277 entry->buf = buf;
278
279 if ( dev_priv->head->next != NULL )
280 dev_priv->head->next->prev = entry;
281 if ( entry->next == NULL )
282 dev_priv->tail = entry;
283
284 buf_priv->list_entry = entry;
285 buf_priv->discard = 0;
286 buf_priv->dispatched = 0;
287
288 dev_priv->head->next = entry;
289 }
290
291 return 0;
292}
293
294static void mga_freelist_cleanup( drm_device_t *dev )
295{
296 drm_mga_private_t *dev_priv = dev->dev_private;
297 drm_mga_freelist_t *entry;
298 drm_mga_freelist_t *next;
299 DRM_DEBUG( "\n" );
300
301 entry = dev_priv->head;
302 while ( entry ) {
303 next = entry->next;
304 drm_free( entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER );
305 entry = next;
306 }
307
308 dev_priv->head = dev_priv->tail = NULL;
309}
310
311#if 0
312/* FIXME: Still needed?
313 */
314static void mga_freelist_reset( drm_device_t *dev )
315{
316 drm_device_dma_t *dma = dev->dma;
317 drm_buf_t *buf;
318 drm_mga_buf_priv_t *buf_priv;
319 int i;
320
321 for ( i = 0 ; i < dma->buf_count ; i++ ) {
322 buf = dma->buflist[i];
323 buf_priv = buf->dev_private;
324 SET_AGE( &buf_priv->list_entry->age,
325 MGA_BUFFER_FREE, 0 );
326 }
327}
328#endif
329
330static drm_buf_t *mga_freelist_get( drm_device_t *dev )
331{
332 drm_mga_private_t *dev_priv = dev->dev_private;
333 drm_mga_freelist_t *next;
334 drm_mga_freelist_t *prev;
335 drm_mga_freelist_t *tail = dev_priv->tail;
336 u32 head, wrap;
337 DRM_DEBUG( "\n" );
338
339 head = MGA_READ( MGA_PRIMADDRESS );
340 wrap = dev_priv->sarea_priv->last_wrap;
341
342 DRM_DEBUG( " tail=0x%06lx %d\n",
343 tail->age.head ?
344 tail->age.head - dev_priv->primary->offset : 0,
345 tail->age.wrap );
346 DRM_DEBUG( " head=0x%06lx %d\n",
347 head - dev_priv->primary->offset, wrap );
348
349 if ( TEST_AGE( &tail->age, head, wrap ) ) {
350 prev = dev_priv->tail->prev;
351 next = dev_priv->tail;
352 prev->next = NULL;
353 next->prev = next->next = NULL;
354 dev_priv->tail = prev;
355 SET_AGE( &next->age, MGA_BUFFER_USED, 0 );
356 return next->buf;
357 }
358
359 DRM_DEBUG( "returning NULL!\n" );
360 return NULL;
361}
362
363int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
364{
365 drm_mga_private_t *dev_priv = dev->dev_private;
366 drm_mga_buf_priv_t *buf_priv = buf->dev_private;
367 drm_mga_freelist_t *head, *entry, *prev;
368
369 DRM_DEBUG( "age=0x%06lx wrap=%d\n",
370 buf_priv->list_entry->age.head -
371 dev_priv->primary->offset,
372 buf_priv->list_entry->age.wrap );
373
374 entry = buf_priv->list_entry;
375 head = dev_priv->head;
376
377 if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) {
378 SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
379 prev = dev_priv->tail;
380 prev->next = entry;
381 entry->prev = prev;
382 entry->next = NULL;
383 } else {
384 prev = head->next;
385 head->next = entry;
386 prev->prev = entry;
387 entry->prev = head;
388 entry->next = prev;
389 }
390
391 return 0;
392}
393
394
395/* ================================================================
396 * DMA initialization, cleanup
397 */
398
399static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
400{
401 drm_mga_private_t *dev_priv;
402 int ret;
403 DRM_DEBUG( "\n" );
404
405 dev_priv = drm_alloc( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
406 if ( !dev_priv )
407 return DRM_ERR(ENOMEM);
408
409 memset( dev_priv, 0, sizeof(drm_mga_private_t) );
410
411 dev_priv->chipset = init->chipset;
412
413 dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
414
415 if ( init->sgram ) {
416 dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
417 } else {
418 dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
419 }
420 dev_priv->maccess = init->maccess;
421
422 dev_priv->fb_cpp = init->fb_cpp;
423 dev_priv->front_offset = init->front_offset;
424 dev_priv->front_pitch = init->front_pitch;
425 dev_priv->back_offset = init->back_offset;
426 dev_priv->back_pitch = init->back_pitch;
427
428 dev_priv->depth_cpp = init->depth_cpp;
429 dev_priv->depth_offset = init->depth_offset;
430 dev_priv->depth_pitch = init->depth_pitch;
431
432 /* FIXME: Need to support AGP textures...
433 */
434 dev_priv->texture_offset = init->texture_offset[0];
435 dev_priv->texture_size = init->texture_size[0];
436
437 DRM_GETSAREA();
438
439 if(!dev_priv->sarea) {
440 DRM_ERROR( "failed to find sarea!\n" );
441 /* Assign dev_private so we can do cleanup. */
442 dev->dev_private = (void *)dev_priv;
443 mga_do_cleanup_dma( dev );
444 return DRM_ERR(EINVAL);
445 }
446
447 dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
448 if(!dev_priv->mmio) {
449 DRM_ERROR( "failed to find mmio region!\n" );
450 /* Assign dev_private so we can do cleanup. */
451 dev->dev_private = (void *)dev_priv;
452 mga_do_cleanup_dma( dev );
453 return DRM_ERR(EINVAL);
454 }
455 dev_priv->status = drm_core_findmap(dev, init->status_offset);
456 if(!dev_priv->status) {
457 DRM_ERROR( "failed to find status page!\n" );
458 /* Assign dev_private so we can do cleanup. */
459 dev->dev_private = (void *)dev_priv;
460 mga_do_cleanup_dma( dev );
461 return DRM_ERR(EINVAL);
462 }
463 dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
464 if(!dev_priv->warp) {
465 DRM_ERROR( "failed to find warp microcode region!\n" );
466 /* Assign dev_private so we can do cleanup. */
467 dev->dev_private = (void *)dev_priv;
468 mga_do_cleanup_dma( dev );
469 return DRM_ERR(EINVAL);
470 }
471 dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
472 if(!dev_priv->primary) {
473 DRM_ERROR( "failed to find primary dma region!\n" );
474 /* Assign dev_private so we can do cleanup. */
475 dev->dev_private = (void *)dev_priv;
476 mga_do_cleanup_dma( dev );
477 return DRM_ERR(EINVAL);
478 }
479 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
480 if(!dev->agp_buffer_map) {
481 DRM_ERROR( "failed to find dma buffer region!\n" );
482 /* Assign dev_private so we can do cleanup. */
483 dev->dev_private = (void *)dev_priv;
484 mga_do_cleanup_dma( dev );
485 return DRM_ERR(EINVAL);
486 }
487
488 dev_priv->sarea_priv =
489 (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
490 init->sarea_priv_offset);
491
492 drm_core_ioremap( dev_priv->warp, dev );
493 drm_core_ioremap( dev_priv->primary, dev );
494 drm_core_ioremap( dev->agp_buffer_map, dev );
495
496 if(!dev_priv->warp->handle ||
497 !dev_priv->primary->handle ||
498 !dev->agp_buffer_map->handle ) {
499 DRM_ERROR( "failed to ioremap agp regions!\n" );
500 /* Assign dev_private so we can do cleanup. */
501 dev->dev_private = (void *)dev_priv;
502 mga_do_cleanup_dma( dev );
503 return DRM_ERR(ENOMEM);
504 }
505
506 ret = mga_warp_install_microcode( dev_priv );
507 if ( ret < 0 ) {
508 DRM_ERROR( "failed to install WARP ucode!\n" );
509 /* Assign dev_private so we can do cleanup. */
510 dev->dev_private = (void *)dev_priv;
511 mga_do_cleanup_dma( dev );
512 return ret;
513 }
514
515 ret = mga_warp_init( dev_priv );
516 if ( ret < 0 ) {
517 DRM_ERROR( "failed to init WARP engine!\n" );
518 /* Assign dev_private so we can do cleanup. */
519 dev->dev_private = (void *)dev_priv;
520 mga_do_cleanup_dma( dev );
521 return ret;
522 }
523
524 dev_priv->prim.status = (u32 *)dev_priv->status->handle;
525
526 mga_do_wait_for_idle( dev_priv );
527
528 /* Init the primary DMA registers.
529 */
530 MGA_WRITE( MGA_PRIMADDRESS,
531 dev_priv->primary->offset | MGA_DMA_GENERAL );
532#if 0
533 MGA_WRITE( MGA_PRIMPTR,
534 virt_to_bus((void *)dev_priv->prim.status) |
535 MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */
536 MGA_PRIMPTREN1 ); /* DWGSYNC */
537#endif
538
539 dev_priv->prim.start = (u8 *)dev_priv->primary->handle;
540 dev_priv->prim.end = ((u8 *)dev_priv->primary->handle
541 + dev_priv->primary->size);
542 dev_priv->prim.size = dev_priv->primary->size;
543
544 dev_priv->prim.tail = 0;
545 dev_priv->prim.space = dev_priv->prim.size;
546 dev_priv->prim.wrapped = 0;
547
548 dev_priv->prim.last_flush = 0;
549 dev_priv->prim.last_wrap = 0;
550
551 dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
552
553 dev_priv->prim.status[0] = dev_priv->primary->offset;
554 dev_priv->prim.status[1] = 0;
555
556 dev_priv->sarea_priv->last_wrap = 0;
557 dev_priv->sarea_priv->last_frame.head = 0;
558 dev_priv->sarea_priv->last_frame.wrap = 0;
559
560 if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
561 DRM_ERROR( "could not initialize freelist\n" );
562 /* Assign dev_private so we can do cleanup. */
563 dev->dev_private = (void *)dev_priv;
564 mga_do_cleanup_dma( dev );
565 return DRM_ERR(ENOMEM);
566 }
567
568 /* Make dev_private visable to others. */
569 dev->dev_private = (void *)dev_priv;
570 return 0;
571}
572
573static int mga_do_cleanup_dma( drm_device_t *dev )
574{
575 DRM_DEBUG( "\n" );
576
577 /* Make sure interrupts are disabled here because the uninstall ioctl
578 * may not have been called from userspace and after dev_private
579 * is freed, it's too late.
580 */
581 if ( dev->irq_enabled ) drm_irq_uninstall(dev);
582
583 if ( dev->dev_private ) {
584 drm_mga_private_t *dev_priv = dev->dev_private;
585
586 if ( dev_priv->warp != NULL )
587 drm_core_ioremapfree( dev_priv->warp, dev );
588 if ( dev_priv->primary != NULL )
589 drm_core_ioremapfree( dev_priv->primary, dev );
590 if ( dev->agp_buffer_map != NULL )
591 drm_core_ioremapfree( dev->agp_buffer_map, dev );
592
593 if ( dev_priv->head != NULL ) {
594 mga_freelist_cleanup( dev );
595 }
596
597 drm_free( dev->dev_private, sizeof(drm_mga_private_t),
598 DRM_MEM_DRIVER );
599 dev->dev_private = NULL;
600 }
601
602 return 0;
603}
604
605int mga_dma_init( DRM_IOCTL_ARGS )
606{
607 DRM_DEVICE;
608 drm_mga_init_t init;
609
610 LOCK_TEST_WITH_RETURN( dev, filp );
611
612 DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t __user *)data, sizeof(init) );
613
614 switch ( init.func ) {
615 case MGA_INIT_DMA:
616 return mga_do_init_dma( dev, &init );
617 case MGA_CLEANUP_DMA:
618 return mga_do_cleanup_dma( dev );
619 }
620
621 return DRM_ERR(EINVAL);
622}
623
624
625/* ================================================================
626 * Primary DMA stream management
627 */
628
629int mga_dma_flush( DRM_IOCTL_ARGS )
630{
631 DRM_DEVICE;
632 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
633 drm_lock_t lock;
634
635 LOCK_TEST_WITH_RETURN( dev, filp );
636
637 DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t __user *)data, sizeof(lock) );
638
639 DRM_DEBUG( "%s%s%s\n",
640 (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
641 (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
642 (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "" );
643
644 WRAP_WAIT_WITH_RETURN( dev_priv );
645
646 if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) {
647 mga_do_dma_flush( dev_priv );
648 }
649
650 if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
651#if MGA_DMA_DEBUG
652 int ret = mga_do_wait_for_idle( dev_priv );
653 if ( ret < 0 )
654 DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ );
655 return ret;
656#else
657 return mga_do_wait_for_idle( dev_priv );
658#endif
659 } else {
660 return 0;
661 }
662}
663
664int mga_dma_reset( DRM_IOCTL_ARGS )
665{
666 DRM_DEVICE;
667 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
668
669 LOCK_TEST_WITH_RETURN( dev, filp );
670
671 return mga_do_dma_reset( dev_priv );
672}
673
674
675/* ================================================================
676 * DMA buffer management
677 */
678
679static int mga_dma_get_buffers( DRMFILE filp,
680 drm_device_t *dev, drm_dma_t *d )
681{
682 drm_buf_t *buf;
683 int i;
684
685 for ( i = d->granted_count ; i < d->request_count ; i++ ) {
686 buf = mga_freelist_get( dev );
687 if ( !buf ) return DRM_ERR(EAGAIN);
688
689 buf->filp = filp;
690
691 if ( DRM_COPY_TO_USER( &d->request_indices[i],
692 &buf->idx, sizeof(buf->idx) ) )
693 return DRM_ERR(EFAULT);
694 if ( DRM_COPY_TO_USER( &d->request_sizes[i],
695 &buf->total, sizeof(buf->total) ) )
696 return DRM_ERR(EFAULT);
697
698 d->granted_count++;
699 }
700 return 0;
701}
702
703int mga_dma_buffers( DRM_IOCTL_ARGS )
704{
705 DRM_DEVICE;
706 drm_device_dma_t *dma = dev->dma;
707 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
708 drm_dma_t __user *argp = (void __user *)data;
709 drm_dma_t d;
710 int ret = 0;
711
712 LOCK_TEST_WITH_RETURN( dev, filp );
713
714 DRM_COPY_FROM_USER_IOCTL( d, argp, sizeof(d) );
715
716 /* Please don't send us buffers.
717 */
718 if ( d.send_count != 0 ) {
719 DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
720 DRM_CURRENTPID, d.send_count );
721 return DRM_ERR(EINVAL);
722 }
723
724 /* We'll send you buffers.
725 */
726 if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
727 DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
728 DRM_CURRENTPID, d.request_count, dma->buf_count );
729 return DRM_ERR(EINVAL);
730 }
731
732 WRAP_TEST_WITH_RETURN( dev_priv );
733
734 d.granted_count = 0;
735
736 if ( d.request_count ) {
737 ret = mga_dma_get_buffers( filp, dev, &d );
738 }
739
740 DRM_COPY_TO_USER_IOCTL( argp, d, sizeof(d) );
741
742 return ret;
743}
744
745void mga_driver_pretakedown(drm_device_t *dev)
746{
747 mga_do_cleanup_dma( dev );
748}
749
750int mga_driver_dma_quiescent(drm_device_t *dev)
751{
752 drm_mga_private_t *dev_priv = dev->dev_private;
753 return mga_do_wait_for_idle( dev_priv );
754}
diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
new file mode 100644
index 000000000000..521d4451d012
--- /dev/null
+++ b/drivers/char/drm/mga_drm.h
@@ -0,0 +1,349 @@
1/* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*-
2 * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Jeff Hartmann <jhartmann@valinux.com>
29 * Keith Whitwell <keith@tungstengraphics.com>
30 *
31 * Rewritten by:
32 * Gareth Hughes <gareth@valinux.com>
33 */
34
35#ifndef __MGA_DRM_H__
36#define __MGA_DRM_H__
37
38/* WARNING: If you change any of these defines, make sure to change the
39 * defines in the Xserver file (mga_sarea.h)
40 */
41
42#ifndef __MGA_SAREA_DEFINES__
43#define __MGA_SAREA_DEFINES__
44
45/* WARP pipe flags
46 */
47#define MGA_F 0x1 /* fog */
48#define MGA_A 0x2 /* alpha */
49#define MGA_S 0x4 /* specular */
50#define MGA_T2 0x8 /* multitexture */
51
52#define MGA_WARP_TGZ 0
53#define MGA_WARP_TGZF (MGA_F)
54#define MGA_WARP_TGZA (MGA_A)
55#define MGA_WARP_TGZAF (MGA_F|MGA_A)
56#define MGA_WARP_TGZS (MGA_S)
57#define MGA_WARP_TGZSF (MGA_S|MGA_F)
58#define MGA_WARP_TGZSA (MGA_S|MGA_A)
59#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A)
60#define MGA_WARP_T2GZ (MGA_T2)
61#define MGA_WARP_T2GZF (MGA_T2|MGA_F)
62#define MGA_WARP_T2GZA (MGA_T2|MGA_A)
63#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F)
64#define MGA_WARP_T2GZS (MGA_T2|MGA_S)
65#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F)
66#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A)
67#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A)
68
69#define MGA_MAX_G200_PIPES 8 /* no multitex */
70#define MGA_MAX_G400_PIPES 16
71#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES
72#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */
73
74#define MGA_CARD_TYPE_G200 1
75#define MGA_CARD_TYPE_G400 2
76
77
78#define MGA_FRONT 0x1
79#define MGA_BACK 0x2
80#define MGA_DEPTH 0x4
81
82/* What needs to be changed for the current vertex dma buffer?
83 */
84#define MGA_UPLOAD_CONTEXT 0x1
85#define MGA_UPLOAD_TEX0 0x2
86#define MGA_UPLOAD_TEX1 0x4
87#define MGA_UPLOAD_PIPE 0x8
88#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */
89#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */
90#define MGA_UPLOAD_2D 0x40
91#define MGA_WAIT_AGE 0x80 /* handled client-side */
92#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */
93#if 0
94#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock
95 quiescent */
96#endif
97
98/* 32 buffers of 64k each, total 2 meg.
99 */
100#define MGA_BUFFER_SIZE (1 << 16)
101#define MGA_NUM_BUFFERS 128
102
103/* Keep these small for testing.
104 */
105#define MGA_NR_SAREA_CLIPRECTS 8
106
107/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
108 * regions, subject to a minimum region size of (1<<16) == 64k.
109 *
110 * Clients may subdivide regions internally, but when sharing between
111 * clients, the region size is the minimum granularity.
112 */
113
114#define MGA_CARD_HEAP 0
115#define MGA_AGP_HEAP 1
116#define MGA_NR_TEX_HEAPS 2
117#define MGA_NR_TEX_REGIONS 16
118#define MGA_LOG_MIN_TEX_REGION_SIZE 16
119
120#define DRM_MGA_IDLE_RETRY 2048
121
122#endif /* __MGA_SAREA_DEFINES__ */
123
124
125/* Setup registers for 3D context
126 */
127typedef struct {
128 unsigned int dstorg;
129 unsigned int maccess;
130 unsigned int plnwt;
131 unsigned int dwgctl;
132 unsigned int alphactrl;
133 unsigned int fogcolor;
134 unsigned int wflag;
135 unsigned int tdualstage0;
136 unsigned int tdualstage1;
137 unsigned int fcol;
138 unsigned int stencil;
139 unsigned int stencilctl;
140} drm_mga_context_regs_t;
141
142/* Setup registers for 2D, X server
143 */
144typedef struct {
145 unsigned int pitch;
146} drm_mga_server_regs_t;
147
148/* Setup registers for each texture unit
149 */
150typedef struct {
151 unsigned int texctl;
152 unsigned int texctl2;
153 unsigned int texfilter;
154 unsigned int texbordercol;
155 unsigned int texorg;
156 unsigned int texwidth;
157 unsigned int texheight;
158 unsigned int texorg1;
159 unsigned int texorg2;
160 unsigned int texorg3;
161 unsigned int texorg4;
162} drm_mga_texture_regs_t;
163
164/* General aging mechanism
165 */
166typedef struct {
167 unsigned int head; /* Position of head pointer */
168 unsigned int wrap; /* Primary DMA wrap count */
169} drm_mga_age_t;
170
171typedef struct _drm_mga_sarea {
172 /* The channel for communication of state information to the kernel
173 * on firing a vertex dma buffer.
174 */
175 drm_mga_context_regs_t context_state;
176 drm_mga_server_regs_t server_state;
177 drm_mga_texture_regs_t tex_state[2];
178 unsigned int warp_pipe;
179 unsigned int dirty;
180 unsigned int vertsize;
181
182 /* The current cliprects, or a subset thereof.
183 */
184 drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
185 unsigned int nbox;
186
187 /* Information about the most recently used 3d drawable. The
188 * client fills in the req_* fields, the server fills in the
189 * exported_ fields and puts the cliprects into boxes, above.
190 *
191 * The client clears the exported_drawable field before
192 * clobbering the boxes data.
193 */
194 unsigned int req_drawable; /* the X drawable id */
195 unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */
196
197 unsigned int exported_drawable;
198 unsigned int exported_index;
199 unsigned int exported_stamp;
200 unsigned int exported_buffers;
201 unsigned int exported_nfront;
202 unsigned int exported_nback;
203 int exported_back_x, exported_front_x, exported_w;
204 int exported_back_y, exported_front_y, exported_h;
205 drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
206
207 /* Counters for aging textures and for client-side throttling.
208 */
209 unsigned int status[4];
210 unsigned int last_wrap;
211
212 drm_mga_age_t last_frame;
213 unsigned int last_enqueue; /* last time a buffer was enqueued */
214 unsigned int last_dispatch; /* age of the most recently dispatched buffer */
215 unsigned int last_quiescent; /* */
216
217 /* LRU lists for texture memory in agp space and on the card.
218 */
219 drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS+1];
220 unsigned int texAge[MGA_NR_TEX_HEAPS];
221
222 /* Mechanism to validate card state.
223 */
224 int ctxOwner;
225} drm_mga_sarea_t;
226
227
228/* WARNING: If you change any of these defines, make sure to change the
229 * defines in the Xserver file (xf86drmMga.h)
230 */
231
232/* MGA specific ioctls
233 * The device specific ioctl range is 0x40 to 0x79.
234 */
235#define DRM_MGA_INIT 0x00
236#define DRM_MGA_FLUSH 0x01
237#define DRM_MGA_RESET 0x02
238#define DRM_MGA_SWAP 0x03
239#define DRM_MGA_CLEAR 0x04
240#define DRM_MGA_VERTEX 0x05
241#define DRM_MGA_INDICES 0x06
242#define DRM_MGA_ILOAD 0x07
243#define DRM_MGA_BLIT 0x08
244#define DRM_MGA_GETPARAM 0x09
245
246#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
247#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
248#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET)
249#define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP)
250#define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t)
251#define DRM_IOCTL_MGA_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t)
252#define DRM_IOCTL_MGA_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t)
253#define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t)
254#define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t)
255#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t)
256
257typedef struct _drm_mga_warp_index {
258 int installed;
259 unsigned long phys_addr;
260 int size;
261} drm_mga_warp_index_t;
262
263typedef struct drm_mga_init {
264 enum {
265 MGA_INIT_DMA = 0x01,
266 MGA_CLEANUP_DMA = 0x02
267 } func;
268
269 unsigned long sarea_priv_offset;
270
271 int chipset;
272 int sgram;
273
274 unsigned int maccess;
275
276 unsigned int fb_cpp;
277 unsigned int front_offset, front_pitch;
278 unsigned int back_offset, back_pitch;
279
280 unsigned int depth_cpp;
281 unsigned int depth_offset, depth_pitch;
282
283 unsigned int texture_offset[MGA_NR_TEX_HEAPS];
284 unsigned int texture_size[MGA_NR_TEX_HEAPS];
285
286 unsigned long fb_offset;
287 unsigned long mmio_offset;
288 unsigned long status_offset;
289 unsigned long warp_offset;
290 unsigned long primary_offset;
291 unsigned long buffers_offset;
292} drm_mga_init_t;
293
294typedef struct drm_mga_fullscreen {
295 enum {
296 MGA_INIT_FULLSCREEN = 0x01,
297 MGA_CLEANUP_FULLSCREEN = 0x02
298 } func;
299} drm_mga_fullscreen_t;
300
301typedef struct drm_mga_clear {
302 unsigned int flags;
303 unsigned int clear_color;
304 unsigned int clear_depth;
305 unsigned int color_mask;
306 unsigned int depth_mask;
307} drm_mga_clear_t;
308
309typedef struct drm_mga_vertex {
310 int idx; /* buffer to queue */
311 int used; /* bytes in use */
312 int discard; /* client finished with buffer? */
313} drm_mga_vertex_t;
314
315typedef struct drm_mga_indices {
316 int idx; /* buffer to queue */
317 unsigned int start;
318 unsigned int end;
319 int discard; /* client finished with buffer? */
320} drm_mga_indices_t;
321
322typedef struct drm_mga_iload {
323 int idx;
324 unsigned int dstorg;
325 unsigned int length;
326} drm_mga_iload_t;
327
328typedef struct _drm_mga_blit {
329 unsigned int planemask;
330 unsigned int srcorg;
331 unsigned int dstorg;
332 int src_pitch, dst_pitch;
333 int delta_sx, delta_sy;
334 int delta_dx, delta_dy;
335 int height, ydir; /* flip image vertically */
336 int source_pitch, dest_pitch;
337} drm_mga_blit_t;
338
339/* 3.1: An ioctl to get parameters that aren't available to the 3d
340 * client any other way.
341 */
342#define MGA_PARAM_IRQ_NR 1
343
344typedef struct drm_mga_getparam {
345 int param;
346 void __user *value;
347} drm_mga_getparam_t;
348
349#endif
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
new file mode 100644
index 000000000000..22dab3e9d92a
--- /dev/null
+++ b/drivers/char/drm/mga_drv.c
@@ -0,0 +1,127 @@
1/* mga_drv.c -- Matrox G200/G400 driver -*- linux-c -*-
2 * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 */
31
32#include <linux/config.h>
33#include "drmP.h"
34#include "drm.h"
35#include "mga_drm.h"
36#include "mga_drv.h"
37
38
39#include "drm_pciids.h"
40
41static int postinit( struct drm_device *dev, unsigned long flags )
42{
43 dev->counters += 3;
44 dev->types[6] = _DRM_STAT_IRQ;
45 dev->types[7] = _DRM_STAT_PRIMARY;
46 dev->types[8] = _DRM_STAT_SECONDARY;
47
48 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
49 DRIVER_NAME,
50 DRIVER_MAJOR,
51 DRIVER_MINOR,
52 DRIVER_PATCHLEVEL,
53 DRIVER_DATE,
54 dev->primary.minor,
55 pci_pretty_name(dev->pdev)
56 );
57 return 0;
58}
59
60static int version( drm_version_t *version )
61{
62 int len;
63
64 version->version_major = DRIVER_MAJOR;
65 version->version_minor = DRIVER_MINOR;
66 version->version_patchlevel = DRIVER_PATCHLEVEL;
67 DRM_COPY( version->name, DRIVER_NAME );
68 DRM_COPY( version->date, DRIVER_DATE );
69 DRM_COPY( version->desc, DRIVER_DESC );
70 return 0;
71}
72
73static struct pci_device_id pciidlist[] = {
74 mga_PCI_IDS
75};
76
77extern drm_ioctl_desc_t mga_ioctls[];
78extern int mga_max_ioctl;
79
80static struct drm_driver driver = {
81 .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
82 .pretakedown = mga_driver_pretakedown,
83 .dma_quiescent = mga_driver_dma_quiescent,
84 .vblank_wait = mga_driver_vblank_wait,
85 .irq_preinstall = mga_driver_irq_preinstall,
86 .irq_postinstall = mga_driver_irq_postinstall,
87 .irq_uninstall = mga_driver_irq_uninstall,
88 .irq_handler = mga_driver_irq_handler,
89 .reclaim_buffers = drm_core_reclaim_buffers,
90 .get_map_ofs = drm_core_get_map_ofs,
91 .get_reg_ofs = drm_core_get_reg_ofs,
92 .postinit = postinit,
93 .version = version,
94 .ioctls = mga_ioctls,
95 .dma_ioctl = mga_dma_buffers,
96 .fops = {
97 .owner = THIS_MODULE,
98 .open = drm_open,
99 .release = drm_release,
100 .ioctl = drm_ioctl,
101 .mmap = drm_mmap,
102 .poll = drm_poll,
103 .fasync = drm_fasync,
104 },
105 .pci_driver = {
106 .name = DRIVER_NAME,
107 .id_table = pciidlist,
108 }
109};
110
111static int __init mga_init(void)
112{
113 driver.num_ioctls = mga_max_ioctl;
114 return drm_init(&driver);
115}
116
117static void __exit mga_exit(void)
118{
119 drm_exit(&driver);
120}
121
122module_init(mga_init);
123module_exit(mga_exit);
124
125MODULE_AUTHOR( DRIVER_AUTHOR );
126MODULE_DESCRIPTION( DRIVER_DESC );
127MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
new file mode 100644
index 000000000000..1d84a1eb34db
--- /dev/null
+++ b/drivers/char/drm/mga_drv.h
@@ -0,0 +1,638 @@
1/* mga_drv.h -- Private header for the Matrox G200/G400 driver -*- linux-c -*-
2 * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Gareth Hughes <gareth@valinux.com>
29 */
30
31#ifndef __MGA_DRV_H__
32#define __MGA_DRV_H__
33
34/* General customization:
35 */
36
37#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
38
39#define DRIVER_NAME "mga"
40#define DRIVER_DESC "Matrox G200/G400"
41#define DRIVER_DATE "20021029"
42
43#define DRIVER_MAJOR 3
44#define DRIVER_MINOR 1
45#define DRIVER_PATCHLEVEL 0
46
47typedef struct drm_mga_primary_buffer {
48 u8 *start;
49 u8 *end;
50 int size;
51
52 u32 tail;
53 int space;
54 volatile long wrapped;
55
56 volatile u32 *status;
57
58 u32 last_flush;
59 u32 last_wrap;
60
61 u32 high_mark;
62} drm_mga_primary_buffer_t;
63
64typedef struct drm_mga_freelist {
65 struct drm_mga_freelist *next;
66 struct drm_mga_freelist *prev;
67 drm_mga_age_t age;
68 drm_buf_t *buf;
69} drm_mga_freelist_t;
70
71typedef struct {
72 drm_mga_freelist_t *list_entry;
73 int discard;
74 int dispatched;
75} drm_mga_buf_priv_t;
76
77typedef struct drm_mga_private {
78 drm_mga_primary_buffer_t prim;
79 drm_mga_sarea_t *sarea_priv;
80
81 drm_mga_freelist_t *head;
82 drm_mga_freelist_t *tail;
83
84 unsigned int warp_pipe;
85 unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES];
86
87 int chipset;
88 int usec_timeout;
89
90 u32 clear_cmd;
91 u32 maccess;
92
93 unsigned int fb_cpp;
94 unsigned int front_offset;
95 unsigned int front_pitch;
96 unsigned int back_offset;
97 unsigned int back_pitch;
98
99 unsigned int depth_cpp;
100 unsigned int depth_offset;
101 unsigned int depth_pitch;
102
103 unsigned int texture_offset;
104 unsigned int texture_size;
105
106 drm_local_map_t *sarea;
107 drm_local_map_t *mmio;
108 drm_local_map_t *status;
109 drm_local_map_t *warp;
110 drm_local_map_t *primary;
111 drm_local_map_t *buffers;
112 drm_local_map_t *agp_textures;
113} drm_mga_private_t;
114
115 /* mga_dma.c */
116extern int mga_dma_init( DRM_IOCTL_ARGS );
117extern int mga_dma_flush( DRM_IOCTL_ARGS );
118extern int mga_dma_reset( DRM_IOCTL_ARGS );
119extern int mga_dma_buffers( DRM_IOCTL_ARGS );
120extern void mga_driver_pretakedown(drm_device_t *dev);
121extern int mga_driver_dma_quiescent(drm_device_t *dev);
122
123extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv );
124
125extern void mga_do_dma_flush( drm_mga_private_t *dev_priv );
126extern void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv );
127extern void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv );
128
129extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf );
130
131 /* mga_warp.c */
132extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
133extern int mga_warp_init( drm_mga_private_t *dev_priv );
134
135extern int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
136extern irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS );
137extern void mga_driver_irq_preinstall( drm_device_t *dev );
138extern void mga_driver_irq_postinstall( drm_device_t *dev );
139extern void mga_driver_irq_uninstall( drm_device_t *dev );
140
141#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER()
142
143#if defined(__linux__) && defined(__alpha__)
144#define MGA_BASE( reg ) ((unsigned long)(dev_priv->mmio->handle))
145#define MGA_ADDR( reg ) (MGA_BASE(reg) + reg)
146
147#define MGA_DEREF( reg ) *(volatile u32 *)MGA_ADDR( reg )
148#define MGA_DEREF8( reg ) *(volatile u8 *)MGA_ADDR( reg )
149
150#define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg)))
151#define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg)))
152#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
153#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
154
155static inline u32 _MGA_READ(u32 *addr)
156{
157 DRM_MEMORYBARRIER();
158 return *(volatile u32 *)addr;
159}
160#else
161#define MGA_READ8( reg ) DRM_READ8(dev_priv->mmio, (reg))
162#define MGA_READ( reg ) DRM_READ32(dev_priv->mmio, (reg))
163#define MGA_WRITE8( reg, val ) DRM_WRITE8(dev_priv->mmio, (reg), (val))
164#define MGA_WRITE( reg, val ) DRM_WRITE32(dev_priv->mmio, (reg), (val))
165#endif
166
167#define DWGREG0 0x1c00
168#define DWGREG0_END 0x1dff
169#define DWGREG1 0x2c00
170#define DWGREG1_END 0x2dff
171
172#define ISREG0(r) (r >= DWGREG0 && r <= DWGREG0_END)
173#define DMAREG0(r) (u8)((r - DWGREG0) >> 2)
174#define DMAREG1(r) (u8)(((r - DWGREG1) >> 2) | 0x80)
175#define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
176
177
178
179/* ================================================================
180 * Helper macross...
181 */
182
183#define MGA_EMIT_STATE( dev_priv, dirty ) \
184do { \
185 if ( (dirty) & ~MGA_UPLOAD_CLIPRECTS ) { \
186 if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) { \
187 mga_g400_emit_state( dev_priv ); \
188 } else { \
189 mga_g200_emit_state( dev_priv ); \
190 } \
191 } \
192} while (0)
193
194#define WRAP_TEST_WITH_RETURN( dev_priv ) \
195do { \
196 if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \
197 if ( mga_is_idle( dev_priv ) ) { \
198 mga_do_dma_wrap_end( dev_priv ); \
199 } else if ( dev_priv->prim.space < \
200 dev_priv->prim.high_mark ) { \
201 if ( MGA_DMA_DEBUG ) \
202 DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \
203 return DRM_ERR(EBUSY); \
204 } \
205 } \
206} while (0)
207
208#define WRAP_WAIT_WITH_RETURN( dev_priv ) \
209do { \
210 if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \
211 if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { \
212 if ( MGA_DMA_DEBUG ) \
213 DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \
214 return DRM_ERR(EBUSY); \
215 } \
216 mga_do_dma_wrap_end( dev_priv ); \
217 } \
218} while (0)
219
220
221/* ================================================================
222 * Primary DMA command stream
223 */
224
225#define MGA_VERBOSE 0
226
227#define DMA_LOCALS unsigned int write; volatile u8 *prim;
228
229#define DMA_BLOCK_SIZE (5 * sizeof(u32))
230
231#define BEGIN_DMA( n ) \
232do { \
233 if ( MGA_VERBOSE ) { \
234 DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \
235 (n), __FUNCTION__ ); \
236 DRM_INFO( " space=0x%x req=0x%Zx\n", \
237 dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \
238 } \
239 prim = dev_priv->prim.start; \
240 write = dev_priv->prim.tail; \
241} while (0)
242
243#define BEGIN_DMA_WRAP() \
244do { \
245 if ( MGA_VERBOSE ) { \
246 DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ ); \
247 DRM_INFO( " space=0x%x\n", dev_priv->prim.space ); \
248 } \
249 prim = dev_priv->prim.start; \
250 write = dev_priv->prim.tail; \
251} while (0)
252
253#define ADVANCE_DMA() \
254do { \
255 dev_priv->prim.tail = write; \
256 if ( MGA_VERBOSE ) { \
257 DRM_INFO( "ADVANCE_DMA() tail=0x%05x sp=0x%x\n", \
258 write, dev_priv->prim.space ); \
259 } \
260} while (0)
261
262#define FLUSH_DMA() \
263do { \
264 if ( 0 ) { \
265 DRM_INFO( "%s:\n", __FUNCTION__ ); \
266 DRM_INFO( " tail=0x%06x head=0x%06lx\n", \
267 dev_priv->prim.tail, \
268 MGA_READ( MGA_PRIMADDRESS ) - \
269 dev_priv->primary->offset ); \
270 } \
271 if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) { \
272 if ( dev_priv->prim.space < \
273 dev_priv->prim.high_mark ) { \
274 mga_do_dma_wrap_start( dev_priv ); \
275 } else { \
276 mga_do_dma_flush( dev_priv ); \
277 } \
278 } \
279} while (0)
280
281/* Never use this, always use DMA_BLOCK(...) for primary DMA output.
282 */
283#define DMA_WRITE( offset, val ) \
284do { \
285 if ( MGA_VERBOSE ) { \
286 DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04Zx\n", \
287 (u32)(val), write + (offset) * sizeof(u32) ); \
288 } \
289 *(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \
290} while (0)
291
292#define DMA_BLOCK( reg0, val0, reg1, val1, reg2, val2, reg3, val3 ) \
293do { \
294 DMA_WRITE( 0, ((DMAREG( reg0 ) << 0) | \
295 (DMAREG( reg1 ) << 8) | \
296 (DMAREG( reg2 ) << 16) | \
297 (DMAREG( reg3 ) << 24)) ); \
298 DMA_WRITE( 1, val0 ); \
299 DMA_WRITE( 2, val1 ); \
300 DMA_WRITE( 3, val2 ); \
301 DMA_WRITE( 4, val3 ); \
302 write += DMA_BLOCK_SIZE; \
303} while (0)
304
305
306/* Buffer aging via primary DMA stream head pointer.
307 */
308
309#define SET_AGE( age, h, w ) \
310do { \
311 (age)->head = h; \
312 (age)->wrap = w; \
313} while (0)
314
315#define TEST_AGE( age, h, w ) ( (age)->wrap < w || \
316 ( (age)->wrap == w && \
317 (age)->head < h ) )
318
319#define AGE_BUFFER( buf_priv ) \
320do { \
321 drm_mga_freelist_t *entry = (buf_priv)->list_entry; \
322 if ( (buf_priv)->dispatched ) { \
323 entry->age.head = (dev_priv->prim.tail + \
324 dev_priv->primary->offset); \
325 entry->age.wrap = dev_priv->sarea_priv->last_wrap; \
326 } else { \
327 entry->age.head = 0; \
328 entry->age.wrap = 0; \
329 } \
330} while (0)
331
332
333#define MGA_ENGINE_IDLE_MASK (MGA_SOFTRAPEN | \
334 MGA_DWGENGSTS | \
335 MGA_ENDPRDMASTS)
336#define MGA_DMA_IDLE_MASK (MGA_SOFTRAPEN | \
337 MGA_ENDPRDMASTS)
338
339#define MGA_DMA_DEBUG 0
340
341
342
343/* A reduced set of the mga registers.
344 */
345#define MGA_CRTC_INDEX 0x1fd4
346#define MGA_CRTC_DATA 0x1fd5
347
348/* CRTC11 */
349#define MGA_VINTCLR (1 << 4)
350#define MGA_VINTEN (1 << 5)
351
352#define MGA_ALPHACTRL 0x2c7c
353#define MGA_AR0 0x1c60
354#define MGA_AR1 0x1c64
355#define MGA_AR2 0x1c68
356#define MGA_AR3 0x1c6c
357#define MGA_AR4 0x1c70
358#define MGA_AR5 0x1c74
359#define MGA_AR6 0x1c78
360
361#define MGA_CXBNDRY 0x1c80
362#define MGA_CXLEFT 0x1ca0
363#define MGA_CXRIGHT 0x1ca4
364
365#define MGA_DMAPAD 0x1c54
366#define MGA_DSTORG 0x2cb8
367#define MGA_DWGCTL 0x1c00
368# define MGA_OPCOD_MASK (15 << 0)
369# define MGA_OPCOD_TRAP (4 << 0)
370# define MGA_OPCOD_TEXTURE_TRAP (6 << 0)
371# define MGA_OPCOD_BITBLT (8 << 0)
372# define MGA_OPCOD_ILOAD (9 << 0)
373# define MGA_ATYPE_MASK (7 << 4)
374# define MGA_ATYPE_RPL (0 << 4)
375# define MGA_ATYPE_RSTR (1 << 4)
376# define MGA_ATYPE_ZI (3 << 4)
377# define MGA_ATYPE_BLK (4 << 4)
378# define MGA_ATYPE_I (7 << 4)
379# define MGA_LINEAR (1 << 7)
380# define MGA_ZMODE_MASK (7 << 8)
381# define MGA_ZMODE_NOZCMP (0 << 8)
382# define MGA_ZMODE_ZE (2 << 8)
383# define MGA_ZMODE_ZNE (3 << 8)
384# define MGA_ZMODE_ZLT (4 << 8)
385# define MGA_ZMODE_ZLTE (5 << 8)
386# define MGA_ZMODE_ZGT (6 << 8)
387# define MGA_ZMODE_ZGTE (7 << 8)
388# define MGA_SOLID (1 << 11)
389# define MGA_ARZERO (1 << 12)
390# define MGA_SGNZERO (1 << 13)
391# define MGA_SHIFTZERO (1 << 14)
392# define MGA_BOP_MASK (15 << 16)
393# define MGA_BOP_ZERO (0 << 16)
394# define MGA_BOP_DST (10 << 16)
395# define MGA_BOP_SRC (12 << 16)
396# define MGA_BOP_ONE (15 << 16)
397# define MGA_TRANS_SHIFT 20
398# define MGA_TRANS_MASK (15 << 20)
399# define MGA_BLTMOD_MASK (15 << 25)
400# define MGA_BLTMOD_BMONOLEF (0 << 25)
401# define MGA_BLTMOD_BMONOWF (4 << 25)
402# define MGA_BLTMOD_PLAN (1 << 25)
403# define MGA_BLTMOD_BFCOL (2 << 25)
404# define MGA_BLTMOD_BU32BGR (3 << 25)
405# define MGA_BLTMOD_BU32RGB (7 << 25)
406# define MGA_BLTMOD_BU24BGR (11 << 25)
407# define MGA_BLTMOD_BU24RGB (15 << 25)
408# define MGA_PATTERN (1 << 29)
409# define MGA_TRANSC (1 << 30)
410# define MGA_CLIPDIS (1 << 31)
411#define MGA_DWGSYNC 0x2c4c
412
413#define MGA_FCOL 0x1c24
414#define MGA_FIFOSTATUS 0x1e10
415#define MGA_FOGCOL 0x1cf4
416#define MGA_FXBNDRY 0x1c84
417#define MGA_FXLEFT 0x1ca8
418#define MGA_FXRIGHT 0x1cac
419
420#define MGA_ICLEAR 0x1e18
421# define MGA_SOFTRAPICLR (1 << 0)
422# define MGA_VLINEICLR (1 << 5)
423#define MGA_IEN 0x1e1c
424# define MGA_SOFTRAPIEN (1 << 0)
425# define MGA_VLINEIEN (1 << 5)
426
427#define MGA_LEN 0x1c5c
428
429#define MGA_MACCESS 0x1c04
430
431#define MGA_PITCH 0x1c8c
432#define MGA_PLNWT 0x1c1c
433#define MGA_PRIMADDRESS 0x1e58
434# define MGA_DMA_GENERAL (0 << 0)
435# define MGA_DMA_BLIT (1 << 0)
436# define MGA_DMA_VECTOR (2 << 0)
437# define MGA_DMA_VERTEX (3 << 0)
438#define MGA_PRIMEND 0x1e5c
439# define MGA_PRIMNOSTART (1 << 0)
440# define MGA_PAGPXFER (1 << 1)
441#define MGA_PRIMPTR 0x1e50
442# define MGA_PRIMPTREN0 (1 << 0)
443# define MGA_PRIMPTREN1 (1 << 1)
444
445#define MGA_RST 0x1e40
446# define MGA_SOFTRESET (1 << 0)
447# define MGA_SOFTEXTRST (1 << 1)
448
449#define MGA_SECADDRESS 0x2c40
450#define MGA_SECEND 0x2c44
451#define MGA_SETUPADDRESS 0x2cd0
452#define MGA_SETUPEND 0x2cd4
453#define MGA_SGN 0x1c58
454#define MGA_SOFTRAP 0x2c48
455#define MGA_SRCORG 0x2cb4
456# define MGA_SRMMAP_MASK (1 << 0)
457# define MGA_SRCMAP_FB (0 << 0)
458# define MGA_SRCMAP_SYSMEM (1 << 0)
459# define MGA_SRCACC_MASK (1 << 1)
460# define MGA_SRCACC_PCI (0 << 1)
461# define MGA_SRCACC_AGP (1 << 1)
462#define MGA_STATUS 0x1e14
463# define MGA_SOFTRAPEN (1 << 0)
464# define MGA_VSYNCPEN (1 << 4)
465# define MGA_VLINEPEN (1 << 5)
466# define MGA_DWGENGSTS (1 << 16)
467# define MGA_ENDPRDMASTS (1 << 17)
468#define MGA_STENCIL 0x2cc8
469#define MGA_STENCILCTL 0x2ccc
470
471#define MGA_TDUALSTAGE0 0x2cf8
472#define MGA_TDUALSTAGE1 0x2cfc
473#define MGA_TEXBORDERCOL 0x2c5c
474#define MGA_TEXCTL 0x2c30
475#define MGA_TEXCTL2 0x2c3c
476# define MGA_DUALTEX (1 << 7)
477# define MGA_G400_TC2_MAGIC (1 << 15)
478# define MGA_MAP1_ENABLE (1 << 31)
479#define MGA_TEXFILTER 0x2c58
480#define MGA_TEXHEIGHT 0x2c2c
481#define MGA_TEXORG 0x2c24
482# define MGA_TEXORGMAP_MASK (1 << 0)
483# define MGA_TEXORGMAP_FB (0 << 0)
484# define MGA_TEXORGMAP_SYSMEM (1 << 0)
485# define MGA_TEXORGACC_MASK (1 << 1)
486# define MGA_TEXORGACC_PCI (0 << 1)
487# define MGA_TEXORGACC_AGP (1 << 1)
488#define MGA_TEXORG1 0x2ca4
489#define MGA_TEXORG2 0x2ca8
490#define MGA_TEXORG3 0x2cac
491#define MGA_TEXORG4 0x2cb0
492#define MGA_TEXTRANS 0x2c34
493#define MGA_TEXTRANSHIGH 0x2c38
494#define MGA_TEXWIDTH 0x2c28
495
496#define MGA_WACCEPTSEQ 0x1dd4
497#define MGA_WCODEADDR 0x1e6c
498#define MGA_WFLAG 0x1dc4
499#define MGA_WFLAG1 0x1de0
500#define MGA_WFLAGNB 0x1e64
501#define MGA_WFLAGNB1 0x1e08
502#define MGA_WGETMSB 0x1dc8
503#define MGA_WIADDR 0x1dc0
504#define MGA_WIADDR2 0x1dd8
505# define MGA_WMODE_SUSPEND (0 << 0)
506# define MGA_WMODE_RESUME (1 << 0)
507# define MGA_WMODE_JUMP (2 << 0)
508# define MGA_WMODE_START (3 << 0)
509# define MGA_WAGP_ENABLE (1 << 2)
510#define MGA_WMISC 0x1e70
511# define MGA_WUCODECACHE_ENABLE (1 << 0)
512# define MGA_WMASTER_ENABLE (1 << 1)
513# define MGA_WCACHEFLUSH_ENABLE (1 << 3)
514#define MGA_WVRTXSZ 0x1dcc
515
516#define MGA_YBOT 0x1c9c
517#define MGA_YDST 0x1c90
518#define MGA_YDSTLEN 0x1c88
519#define MGA_YDSTORG 0x1c94
520#define MGA_YTOP 0x1c98
521
522#define MGA_ZORG 0x1c0c
523
524/* This finishes the current batch of commands
525 */
526#define MGA_EXEC 0x0100
527
528/* Warp registers
529 */
530#define MGA_WR0 0x2d00
531#define MGA_WR1 0x2d04
532#define MGA_WR2 0x2d08
533#define MGA_WR3 0x2d0c
534#define MGA_WR4 0x2d10
535#define MGA_WR5 0x2d14
536#define MGA_WR6 0x2d18
537#define MGA_WR7 0x2d1c
538#define MGA_WR8 0x2d20
539#define MGA_WR9 0x2d24
540#define MGA_WR10 0x2d28
541#define MGA_WR11 0x2d2c
542#define MGA_WR12 0x2d30
543#define MGA_WR13 0x2d34
544#define MGA_WR14 0x2d38
545#define MGA_WR15 0x2d3c
546#define MGA_WR16 0x2d40
547#define MGA_WR17 0x2d44
548#define MGA_WR18 0x2d48
549#define MGA_WR19 0x2d4c
550#define MGA_WR20 0x2d50
551#define MGA_WR21 0x2d54
552#define MGA_WR22 0x2d58
553#define MGA_WR23 0x2d5c
554#define MGA_WR24 0x2d60
555#define MGA_WR25 0x2d64
556#define MGA_WR26 0x2d68
557#define MGA_WR27 0x2d6c
558#define MGA_WR28 0x2d70
559#define MGA_WR29 0x2d74
560#define MGA_WR30 0x2d78
561#define MGA_WR31 0x2d7c
562#define MGA_WR32 0x2d80
563#define MGA_WR33 0x2d84
564#define MGA_WR34 0x2d88
565#define MGA_WR35 0x2d8c
566#define MGA_WR36 0x2d90
567#define MGA_WR37 0x2d94
568#define MGA_WR38 0x2d98
569#define MGA_WR39 0x2d9c
570#define MGA_WR40 0x2da0
571#define MGA_WR41 0x2da4
572#define MGA_WR42 0x2da8
573#define MGA_WR43 0x2dac
574#define MGA_WR44 0x2db0
575#define MGA_WR45 0x2db4
576#define MGA_WR46 0x2db8
577#define MGA_WR47 0x2dbc
578#define MGA_WR48 0x2dc0
579#define MGA_WR49 0x2dc4
580#define MGA_WR50 0x2dc8
581#define MGA_WR51 0x2dcc
582#define MGA_WR52 0x2dd0
583#define MGA_WR53 0x2dd4
584#define MGA_WR54 0x2dd8
585#define MGA_WR55 0x2ddc
586#define MGA_WR56 0x2de0
587#define MGA_WR57 0x2de4
588#define MGA_WR58 0x2de8
589#define MGA_WR59 0x2dec
590#define MGA_WR60 0x2df0
591#define MGA_WR61 0x2df4
592#define MGA_WR62 0x2df8
593#define MGA_WR63 0x2dfc
594# define MGA_G400_WR_MAGIC (1 << 6)
595# define MGA_G400_WR56_MAGIC 0x46480000 /* 12800.0f */
596
597
598#define MGA_ILOAD_ALIGN 64
599#define MGA_ILOAD_MASK (MGA_ILOAD_ALIGN - 1)
600
601#define MGA_DWGCTL_FLUSH (MGA_OPCOD_TEXTURE_TRAP | \
602 MGA_ATYPE_I | \
603 MGA_ZMODE_NOZCMP | \
604 MGA_ARZERO | \
605 MGA_SGNZERO | \
606 MGA_BOP_SRC | \
607 (15 << MGA_TRANS_SHIFT))
608
609#define MGA_DWGCTL_CLEAR (MGA_OPCOD_TRAP | \
610 MGA_ZMODE_NOZCMP | \
611 MGA_SOLID | \
612 MGA_ARZERO | \
613 MGA_SGNZERO | \
614 MGA_SHIFTZERO | \
615 MGA_BOP_SRC | \
616 (0 << MGA_TRANS_SHIFT) | \
617 MGA_BLTMOD_BMONOLEF | \
618 MGA_TRANSC | \
619 MGA_CLIPDIS)
620
621#define MGA_DWGCTL_COPY (MGA_OPCOD_BITBLT | \
622 MGA_ATYPE_RPL | \
623 MGA_SGNZERO | \
624 MGA_SHIFTZERO | \
625 MGA_BOP_SRC | \
626 (0 << MGA_TRANS_SHIFT) | \
627 MGA_BLTMOD_BFCOL | \
628 MGA_CLIPDIS)
629
630/* Simple idle test.
631 */
632static __inline__ int mga_is_idle( drm_mga_private_t *dev_priv )
633{
634 u32 status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
635 return ( status == MGA_ENDPRDMASTS );
636}
637
638#endif
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
new file mode 100644
index 000000000000..bc0b6b5d43a6
--- /dev/null
+++ b/drivers/char/drm/mga_irq.c
@@ -0,0 +1,102 @@
1/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*-
2 *
3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 *
5 * The Weather Channel (TM) funded Tungsten Graphics to develop the
6 * initial release of the Radeon 8500 driver under the XFree86 license.
7 * This notice must be preserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Eric Anholt <anholt@FreeBSD.org>
31 */
32
33#include "drmP.h"
34#include "drm.h"
35#include "mga_drm.h"
36#include "mga_drv.h"
37
38irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS )
39{
40 drm_device_t *dev = (drm_device_t *) arg;
41 drm_mga_private_t *dev_priv =
42 (drm_mga_private_t *)dev->dev_private;
43 int status;
44
45 status = MGA_READ( MGA_STATUS );
46
47 /* VBLANK interrupt */
48 if ( status & MGA_VLINEPEN ) {
49 MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR );
50 atomic_inc(&dev->vbl_received);
51 DRM_WAKEUP(&dev->vbl_queue);
52 drm_vbl_send_signals( dev );
53 return IRQ_HANDLED;
54 }
55 return IRQ_NONE;
56}
57
58int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
59{
60 unsigned int cur_vblank;
61 int ret = 0;
62
63 /* Assume that the user has missed the current sequence number
64 * by about a day rather than she wants to wait for years
65 * using vertical blanks...
66 */
67 DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ,
68 ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
69 - *sequence ) <= (1<<23) ) );
70
71 *sequence = cur_vblank;
72
73 return ret;
74}
75
76void mga_driver_irq_preinstall( drm_device_t *dev ) {
77 drm_mga_private_t *dev_priv =
78 (drm_mga_private_t *)dev->dev_private;
79
80 /* Disable *all* interrupts */
81 MGA_WRITE( MGA_IEN, 0 );
82 /* Clear bits if they're already high */
83 MGA_WRITE( MGA_ICLEAR, ~0 );
84}
85
86void mga_driver_irq_postinstall( drm_device_t *dev ) {
87 drm_mga_private_t *dev_priv =
88 (drm_mga_private_t *)dev->dev_private;
89
90 /* Turn on VBL interrupt */
91 MGA_WRITE( MGA_IEN, MGA_VLINEIEN );
92}
93
94void mga_driver_irq_uninstall( drm_device_t *dev ) {
95 drm_mga_private_t *dev_priv =
96 (drm_mga_private_t *)dev->dev_private;
97 if (!dev_priv)
98 return;
99
100 /* Disable *all* interrupts */
101 MGA_WRITE( MGA_IEN, 0 );
102}
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
new file mode 100644
index 000000000000..3c7a8f5ba501
--- /dev/null
+++ b/drivers/char/drm/mga_state.c
@@ -0,0 +1,1123 @@
1/* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*-
2 * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Jeff Hartmann <jhartmann@valinux.com>
29 * Keith Whitwell <keith@tungstengraphics.com>
30 *
31 * Rewritten by:
32 * Gareth Hughes <gareth@valinux.com>
33 */
34
35#include "drmP.h"
36#include "drm.h"
37#include "mga_drm.h"
38#include "mga_drv.h"
39
40/* ================================================================
41 * DMA hardware state programming functions
42 */
43
44static void mga_emit_clip_rect( drm_mga_private_t *dev_priv,
45 drm_clip_rect_t *box )
46{
47 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
48 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
49 unsigned int pitch = dev_priv->front_pitch;
50 DMA_LOCALS;
51
52 BEGIN_DMA( 2 );
53
54 /* Force reset of DWGCTL on G400 (eliminates clip disable bit).
55 */
56 if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
57 DMA_BLOCK( MGA_DWGCTL, ctx->dwgctl,
58 MGA_LEN + MGA_EXEC, 0x80000000,
59 MGA_DWGCTL, ctx->dwgctl,
60 MGA_LEN + MGA_EXEC, 0x80000000 );
61 }
62 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
63 MGA_CXBNDRY, (box->x2 << 16) | box->x1,
64 MGA_YTOP, box->y1 * pitch,
65 MGA_YBOT, box->y2 * pitch );
66
67 ADVANCE_DMA();
68}
69
70static __inline__ void mga_g200_emit_context( drm_mga_private_t *dev_priv )
71{
72 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
73 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
74 DMA_LOCALS;
75
76 BEGIN_DMA( 3 );
77
78 DMA_BLOCK( MGA_DSTORG, ctx->dstorg,
79 MGA_MACCESS, ctx->maccess,
80 MGA_PLNWT, ctx->plnwt,
81 MGA_DWGCTL, ctx->dwgctl );
82
83 DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl,
84 MGA_FOGCOL, ctx->fogcolor,
85 MGA_WFLAG, ctx->wflag,
86 MGA_ZORG, dev_priv->depth_offset );
87
88 DMA_BLOCK( MGA_FCOL, ctx->fcol,
89 MGA_DMAPAD, 0x00000000,
90 MGA_DMAPAD, 0x00000000,
91 MGA_DMAPAD, 0x00000000 );
92
93 ADVANCE_DMA();
94}
95
96static __inline__ void mga_g400_emit_context( drm_mga_private_t *dev_priv )
97{
98 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
99 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
100 DMA_LOCALS;
101
102 BEGIN_DMA( 4 );
103
104 DMA_BLOCK( MGA_DSTORG, ctx->dstorg,
105 MGA_MACCESS, ctx->maccess,
106 MGA_PLNWT, ctx->plnwt,
107 MGA_DWGCTL, ctx->dwgctl );
108
109 DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl,
110 MGA_FOGCOL, ctx->fogcolor,
111 MGA_WFLAG, ctx->wflag,
112 MGA_ZORG, dev_priv->depth_offset );
113
114 DMA_BLOCK( MGA_WFLAG1, ctx->wflag,
115 MGA_TDUALSTAGE0, ctx->tdualstage0,
116 MGA_TDUALSTAGE1, ctx->tdualstage1,
117 MGA_FCOL, ctx->fcol );
118
119 DMA_BLOCK( MGA_STENCIL, ctx->stencil,
120 MGA_STENCILCTL, ctx->stencilctl,
121 MGA_DMAPAD, 0x00000000,
122 MGA_DMAPAD, 0x00000000 );
123
124 ADVANCE_DMA();
125}
126
127static __inline__ void mga_g200_emit_tex0( drm_mga_private_t *dev_priv )
128{
129 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
130 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
131 DMA_LOCALS;
132
133 BEGIN_DMA( 4 );
134
135 DMA_BLOCK( MGA_TEXCTL2, tex->texctl2,
136 MGA_TEXCTL, tex->texctl,
137 MGA_TEXFILTER, tex->texfilter,
138 MGA_TEXBORDERCOL, tex->texbordercol );
139
140 DMA_BLOCK( MGA_TEXORG, tex->texorg,
141 MGA_TEXORG1, tex->texorg1,
142 MGA_TEXORG2, tex->texorg2,
143 MGA_TEXORG3, tex->texorg3 );
144
145 DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
146 MGA_TEXWIDTH, tex->texwidth,
147 MGA_TEXHEIGHT, tex->texheight,
148 MGA_WR24, tex->texwidth );
149
150 DMA_BLOCK( MGA_WR34, tex->texheight,
151 MGA_TEXTRANS, 0x0000ffff,
152 MGA_TEXTRANSHIGH, 0x0000ffff,
153 MGA_DMAPAD, 0x00000000 );
154
155 ADVANCE_DMA();
156}
157
158static __inline__ void mga_g400_emit_tex0( drm_mga_private_t *dev_priv )
159{
160 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
161 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
162 DMA_LOCALS;
163
164/* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */
165/* tex->texctl, tex->texctl2); */
166
167 BEGIN_DMA( 6 );
168
169 DMA_BLOCK( MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
170 MGA_TEXCTL, tex->texctl,
171 MGA_TEXFILTER, tex->texfilter,
172 MGA_TEXBORDERCOL, tex->texbordercol );
173
174 DMA_BLOCK( MGA_TEXORG, tex->texorg,
175 MGA_TEXORG1, tex->texorg1,
176 MGA_TEXORG2, tex->texorg2,
177 MGA_TEXORG3, tex->texorg3 );
178
179 DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
180 MGA_TEXWIDTH, tex->texwidth,
181 MGA_TEXHEIGHT, tex->texheight,
182 MGA_WR49, 0x00000000 );
183
184 DMA_BLOCK( MGA_WR57, 0x00000000,
185 MGA_WR53, 0x00000000,
186 MGA_WR61, 0x00000000,
187 MGA_WR52, MGA_G400_WR_MAGIC );
188
189 DMA_BLOCK( MGA_WR60, MGA_G400_WR_MAGIC,
190 MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
191 MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
192 MGA_DMAPAD, 0x00000000 );
193
194 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
195 MGA_DMAPAD, 0x00000000,
196 MGA_TEXTRANS, 0x0000ffff,
197 MGA_TEXTRANSHIGH, 0x0000ffff );
198
199 ADVANCE_DMA();
200}
201
202static __inline__ void mga_g400_emit_tex1( drm_mga_private_t *dev_priv )
203{
204 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
205 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
206 DMA_LOCALS;
207
208/* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */
209/* tex->texctl, tex->texctl2); */
210
211 BEGIN_DMA( 5 );
212
213 DMA_BLOCK( MGA_TEXCTL2, (tex->texctl2 |
214 MGA_MAP1_ENABLE |
215 MGA_G400_TC2_MAGIC),
216 MGA_TEXCTL, tex->texctl,
217 MGA_TEXFILTER, tex->texfilter,
218 MGA_TEXBORDERCOL, tex->texbordercol );
219
220 DMA_BLOCK( MGA_TEXORG, tex->texorg,
221 MGA_TEXORG1, tex->texorg1,
222 MGA_TEXORG2, tex->texorg2,
223 MGA_TEXORG3, tex->texorg3 );
224
225 DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
226 MGA_TEXWIDTH, tex->texwidth,
227 MGA_TEXHEIGHT, tex->texheight,
228 MGA_WR49, 0x00000000 );
229
230 DMA_BLOCK( MGA_WR57, 0x00000000,
231 MGA_WR53, 0x00000000,
232 MGA_WR61, 0x00000000,
233 MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC );
234
235 DMA_BLOCK( MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
236 MGA_TEXTRANS, 0x0000ffff,
237 MGA_TEXTRANSHIGH, 0x0000ffff,
238 MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC );
239
240 ADVANCE_DMA();
241}
242
243static __inline__ void mga_g200_emit_pipe( drm_mga_private_t *dev_priv )
244{
245 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
246 unsigned int pipe = sarea_priv->warp_pipe;
247 DMA_LOCALS;
248
249 BEGIN_DMA( 3 );
250
251 DMA_BLOCK( MGA_WIADDR, MGA_WMODE_SUSPEND,
252 MGA_WVRTXSZ, 0x00000007,
253 MGA_WFLAG, 0x00000000,
254 MGA_WR24, 0x00000000 );
255
256 DMA_BLOCK( MGA_WR25, 0x00000100,
257 MGA_WR34, 0x00000000,
258 MGA_WR42, 0x0000ffff,
259 MGA_WR60, 0x0000ffff );
260
261 /* Padding required to to hardware bug.
262 */
263 DMA_BLOCK( MGA_DMAPAD, 0xffffffff,
264 MGA_DMAPAD, 0xffffffff,
265 MGA_DMAPAD, 0xffffffff,
266 MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
267 MGA_WMODE_START |
268 MGA_WAGP_ENABLE) );
269
270 ADVANCE_DMA();
271}
272
273static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
274{
275 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
276 unsigned int pipe = sarea_priv->warp_pipe;
277 DMA_LOCALS;
278
279/* printk("mga_g400_emit_pipe %x\n", pipe); */
280
281 BEGIN_DMA( 10 );
282
283 DMA_BLOCK( MGA_WIADDR2, MGA_WMODE_SUSPEND,
284 MGA_DMAPAD, 0x00000000,
285 MGA_DMAPAD, 0x00000000,
286 MGA_DMAPAD, 0x00000000 );
287
288 if ( pipe & MGA_T2 ) {
289 DMA_BLOCK( MGA_WVRTXSZ, 0x00001e09,
290 MGA_DMAPAD, 0x00000000,
291 MGA_DMAPAD, 0x00000000,
292 MGA_DMAPAD, 0x00000000 );
293
294 DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000,
295 MGA_WACCEPTSEQ, 0x00000000,
296 MGA_WACCEPTSEQ, 0x00000000,
297 MGA_WACCEPTSEQ, 0x1e000000 );
298 } else {
299 if ( dev_priv->warp_pipe & MGA_T2 ) {
300 /* Flush the WARP pipe */
301 DMA_BLOCK( MGA_YDST, 0x00000000,
302 MGA_FXLEFT, 0x00000000,
303 MGA_FXRIGHT, 0x00000001,
304 MGA_DWGCTL, MGA_DWGCTL_FLUSH );
305
306 DMA_BLOCK( MGA_LEN + MGA_EXEC, 0x00000001,
307 MGA_DWGSYNC, 0x00007000,
308 MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
309 MGA_LEN + MGA_EXEC, 0x00000000 );
310
311 DMA_BLOCK( MGA_TEXCTL2, (MGA_DUALTEX |
312 MGA_G400_TC2_MAGIC),
313 MGA_LEN + MGA_EXEC, 0x00000000,
314 MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
315 MGA_DMAPAD, 0x00000000 );
316 }
317
318 DMA_BLOCK( MGA_WVRTXSZ, 0x00001807,
319 MGA_DMAPAD, 0x00000000,
320 MGA_DMAPAD, 0x00000000,
321 MGA_DMAPAD, 0x00000000 );
322
323 DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000,
324 MGA_WACCEPTSEQ, 0x00000000,
325 MGA_WACCEPTSEQ, 0x00000000,
326 MGA_WACCEPTSEQ, 0x18000000 );
327 }
328
329 DMA_BLOCK( MGA_WFLAG, 0x00000000,
330 MGA_WFLAG1, 0x00000000,
331 MGA_WR56, MGA_G400_WR56_MAGIC,
332 MGA_DMAPAD, 0x00000000 );
333
334 DMA_BLOCK( MGA_WR49, 0x00000000, /* tex0 */
335 MGA_WR57, 0x00000000, /* tex0 */
336 MGA_WR53, 0x00000000, /* tex1 */
337 MGA_WR61, 0x00000000 ); /* tex1 */
338
339 DMA_BLOCK( MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */
340 MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */
341 MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */
342 MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */
343
344 /* Padding required to to hardware bug */
345 DMA_BLOCK( MGA_DMAPAD, 0xffffffff,
346 MGA_DMAPAD, 0xffffffff,
347 MGA_DMAPAD, 0xffffffff,
348 MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
349 MGA_WMODE_START |
350 MGA_WAGP_ENABLE) );
351
352 ADVANCE_DMA();
353}
354
355static void mga_g200_emit_state( drm_mga_private_t *dev_priv )
356{
357 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
358 unsigned int dirty = sarea_priv->dirty;
359
360 if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
361 mga_g200_emit_pipe( dev_priv );
362 dev_priv->warp_pipe = sarea_priv->warp_pipe;
363 }
364
365 if ( dirty & MGA_UPLOAD_CONTEXT ) {
366 mga_g200_emit_context( dev_priv );
367 sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
368 }
369
370 if ( dirty & MGA_UPLOAD_TEX0 ) {
371 mga_g200_emit_tex0( dev_priv );
372 sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
373 }
374}
375
376static void mga_g400_emit_state( drm_mga_private_t *dev_priv )
377{
378 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
379 unsigned int dirty = sarea_priv->dirty;
380 int multitex = sarea_priv->warp_pipe & MGA_T2;
381
382 if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
383 mga_g400_emit_pipe( dev_priv );
384 dev_priv->warp_pipe = sarea_priv->warp_pipe;
385 }
386
387 if ( dirty & MGA_UPLOAD_CONTEXT ) {
388 mga_g400_emit_context( dev_priv );
389 sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
390 }
391
392 if ( dirty & MGA_UPLOAD_TEX0 ) {
393 mga_g400_emit_tex0( dev_priv );
394 sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
395 }
396
397 if ( (dirty & MGA_UPLOAD_TEX1) && multitex ) {
398 mga_g400_emit_tex1( dev_priv );
399 sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
400 }
401}
402
403
404/* ================================================================
405 * SAREA state verification
406 */
407
408/* Disallow all write destinations except the front and backbuffer.
409 */
410static int mga_verify_context( drm_mga_private_t *dev_priv )
411{
412 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
413 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
414
415 if ( ctx->dstorg != dev_priv->front_offset &&
416 ctx->dstorg != dev_priv->back_offset ) {
417 DRM_ERROR( "*** bad DSTORG: %x (front %x, back %x)\n\n",
418 ctx->dstorg, dev_priv->front_offset,
419 dev_priv->back_offset );
420 ctx->dstorg = 0;
421 return DRM_ERR(EINVAL);
422 }
423
424 return 0;
425}
426
427/* Disallow texture reads from PCI space.
428 */
429static int mga_verify_tex( drm_mga_private_t *dev_priv, int unit )
430{
431 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
432 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
433 unsigned int org;
434
435 org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
436
437 if ( org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI) ) {
438 DRM_ERROR( "*** bad TEXORG: 0x%x, unit %d\n",
439 tex->texorg, unit );
440 tex->texorg = 0;
441 return DRM_ERR(EINVAL);
442 }
443
444 return 0;
445}
446
447static int mga_verify_state( drm_mga_private_t *dev_priv )
448{
449 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
450 unsigned int dirty = sarea_priv->dirty;
451 int ret = 0;
452
453 if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
454 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
455
456 if ( dirty & MGA_UPLOAD_CONTEXT )
457 ret |= mga_verify_context( dev_priv );
458
459 if ( dirty & MGA_UPLOAD_TEX0 )
460 ret |= mga_verify_tex( dev_priv, 0 );
461
462 if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
463 if ( dirty & MGA_UPLOAD_TEX1 )
464 ret |= mga_verify_tex( dev_priv, 1 );
465
466 if ( dirty & MGA_UPLOAD_PIPE )
467 ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES );
468 } else {
469 if ( dirty & MGA_UPLOAD_PIPE )
470 ret |= ( sarea_priv->warp_pipe > MGA_MAX_G200_PIPES );
471 }
472
473 return ( ret == 0 );
474}
475
476static int mga_verify_iload( drm_mga_private_t *dev_priv,
477 unsigned int dstorg, unsigned int length )
478{
479 if ( dstorg < dev_priv->texture_offset ||
480 dstorg + length > (dev_priv->texture_offset +
481 dev_priv->texture_size) ) {
482 DRM_ERROR( "*** bad iload DSTORG: 0x%x\n", dstorg );
483 return DRM_ERR(EINVAL);
484 }
485
486 if ( length & MGA_ILOAD_MASK ) {
487 DRM_ERROR( "*** bad iload length: 0x%x\n",
488 length & MGA_ILOAD_MASK );
489 return DRM_ERR(EINVAL);
490 }
491
492 return 0;
493}
494
495static int mga_verify_blit( drm_mga_private_t *dev_priv,
496 unsigned int srcorg, unsigned int dstorg )
497{
498 if ( (srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
499 (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ) {
500 DRM_ERROR( "*** bad blit: src=0x%x dst=0x%x\n",
501 srcorg, dstorg );
502 return DRM_ERR(EINVAL);
503 }
504 return 0;
505}
506
507
508/* ================================================================
509 *
510 */
511
512static void mga_dma_dispatch_clear( drm_device_t *dev,
513 drm_mga_clear_t *clear )
514{
515 drm_mga_private_t *dev_priv = dev->dev_private;
516 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
517 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
518 drm_clip_rect_t *pbox = sarea_priv->boxes;
519 int nbox = sarea_priv->nbox;
520 int i;
521 DMA_LOCALS;
522 DRM_DEBUG( "\n" );
523
524 BEGIN_DMA( 1 );
525
526 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
527 MGA_DMAPAD, 0x00000000,
528 MGA_DWGSYNC, 0x00007100,
529 MGA_DWGSYNC, 0x00007000 );
530
531 ADVANCE_DMA();
532
533 for ( i = 0 ; i < nbox ; i++ ) {
534 drm_clip_rect_t *box = &pbox[i];
535 u32 height = box->y2 - box->y1;
536
537 DRM_DEBUG( " from=%d,%d to=%d,%d\n",
538 box->x1, box->y1, box->x2, box->y2 );
539
540 if ( clear->flags & MGA_FRONT ) {
541 BEGIN_DMA( 2 );
542
543 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
544 MGA_PLNWT, clear->color_mask,
545 MGA_YDSTLEN, (box->y1 << 16) | height,
546 MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
547
548 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
549 MGA_FCOL, clear->clear_color,
550 MGA_DSTORG, dev_priv->front_offset,
551 MGA_DWGCTL + MGA_EXEC,
552 dev_priv->clear_cmd );
553
554 ADVANCE_DMA();
555 }
556
557
558 if ( clear->flags & MGA_BACK ) {
559 BEGIN_DMA( 2 );
560
561 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
562 MGA_PLNWT, clear->color_mask,
563 MGA_YDSTLEN, (box->y1 << 16) | height,
564 MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
565
566 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
567 MGA_FCOL, clear->clear_color,
568 MGA_DSTORG, dev_priv->back_offset,
569 MGA_DWGCTL + MGA_EXEC,
570 dev_priv->clear_cmd );
571
572 ADVANCE_DMA();
573 }
574
575 if ( clear->flags & MGA_DEPTH ) {
576 BEGIN_DMA( 2 );
577
578 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
579 MGA_PLNWT, clear->depth_mask,
580 MGA_YDSTLEN, (box->y1 << 16) | height,
581 MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
582
583 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
584 MGA_FCOL, clear->clear_depth,
585 MGA_DSTORG, dev_priv->depth_offset,
586 MGA_DWGCTL + MGA_EXEC,
587 dev_priv->clear_cmd );
588
589 ADVANCE_DMA();
590 }
591
592 }
593
594 BEGIN_DMA( 1 );
595
596 /* Force reset of DWGCTL */
597 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
598 MGA_DMAPAD, 0x00000000,
599 MGA_PLNWT, ctx->plnwt,
600 MGA_DWGCTL, ctx->dwgctl );
601
602 ADVANCE_DMA();
603
604 FLUSH_DMA();
605}
606
607static void mga_dma_dispatch_swap( drm_device_t *dev )
608{
609 drm_mga_private_t *dev_priv = dev->dev_private;
610 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
611 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
612 drm_clip_rect_t *pbox = sarea_priv->boxes;
613 int nbox = sarea_priv->nbox;
614 int i;
615 DMA_LOCALS;
616 DRM_DEBUG( "\n" );
617
618 sarea_priv->last_frame.head = dev_priv->prim.tail;
619 sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
620
621 BEGIN_DMA( 4 + nbox );
622
623 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
624 MGA_DMAPAD, 0x00000000,
625 MGA_DWGSYNC, 0x00007100,
626 MGA_DWGSYNC, 0x00007000 );
627
628 DMA_BLOCK( MGA_DSTORG, dev_priv->front_offset,
629 MGA_MACCESS, dev_priv->maccess,
630 MGA_SRCORG, dev_priv->back_offset,
631 MGA_AR5, dev_priv->front_pitch );
632
633 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
634 MGA_DMAPAD, 0x00000000,
635 MGA_PLNWT, 0xffffffff,
636 MGA_DWGCTL, MGA_DWGCTL_COPY );
637
638 for ( i = 0 ; i < nbox ; i++ ) {
639 drm_clip_rect_t *box = &pbox[i];
640 u32 height = box->y2 - box->y1;
641 u32 start = box->y1 * dev_priv->front_pitch;
642
643 DRM_DEBUG( " from=%d,%d to=%d,%d\n",
644 box->x1, box->y1, box->x2, box->y2 );
645
646 DMA_BLOCK( MGA_AR0, start + box->x2 - 1,
647 MGA_AR3, start + box->x1,
648 MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
649 MGA_YDSTLEN + MGA_EXEC,
650 (box->y1 << 16) | height );
651 }
652
653 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
654 MGA_PLNWT, ctx->plnwt,
655 MGA_SRCORG, dev_priv->front_offset,
656 MGA_DWGCTL, ctx->dwgctl );
657
658 ADVANCE_DMA();
659
660 FLUSH_DMA();
661
662 DRM_DEBUG( "%s... done.\n", __FUNCTION__ );
663}
664
665static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf )
666{
667 drm_mga_private_t *dev_priv = dev->dev_private;
668 drm_mga_buf_priv_t *buf_priv = buf->dev_private;
669 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
670 u32 address = (u32) buf->bus_address;
671 u32 length = (u32) buf->used;
672 int i = 0;
673 DMA_LOCALS;
674 DRM_DEBUG( "vertex: buf=%d used=%d\n", buf->idx, buf->used );
675
676 if ( buf->used ) {
677 buf_priv->dispatched = 1;
678
679 MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
680
681 do {
682 if ( i < sarea_priv->nbox ) {
683 mga_emit_clip_rect( dev_priv,
684 &sarea_priv->boxes[i] );
685 }
686
687 BEGIN_DMA( 1 );
688
689 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
690 MGA_DMAPAD, 0x00000000,
691 MGA_SECADDRESS, (address |
692 MGA_DMA_VERTEX),
693 MGA_SECEND, ((address + length) |
694 MGA_PAGPXFER) );
695
696 ADVANCE_DMA();
697 } while ( ++i < sarea_priv->nbox );
698 }
699
700 if ( buf_priv->discard ) {
701 AGE_BUFFER( buf_priv );
702 buf->pending = 0;
703 buf->used = 0;
704 buf_priv->dispatched = 0;
705
706 mga_freelist_put( dev, buf );
707 }
708
709 FLUSH_DMA();
710}
711
712static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf,
713 unsigned int start, unsigned int end )
714{
715 drm_mga_private_t *dev_priv = dev->dev_private;
716 drm_mga_buf_priv_t *buf_priv = buf->dev_private;
717 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
718 u32 address = (u32) buf->bus_address;
719 int i = 0;
720 DMA_LOCALS;
721 DRM_DEBUG( "indices: buf=%d start=%d end=%d\n", buf->idx, start, end );
722
723 if ( start != end ) {
724 buf_priv->dispatched = 1;
725
726 MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
727
728 do {
729 if ( i < sarea_priv->nbox ) {
730 mga_emit_clip_rect( dev_priv,
731 &sarea_priv->boxes[i] );
732 }
733
734 BEGIN_DMA( 1 );
735
736 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
737 MGA_DMAPAD, 0x00000000,
738 MGA_SETUPADDRESS, address + start,
739 MGA_SETUPEND, ((address + end) |
740 MGA_PAGPXFER) );
741
742 ADVANCE_DMA();
743 } while ( ++i < sarea_priv->nbox );
744 }
745
746 if ( buf_priv->discard ) {
747 AGE_BUFFER( buf_priv );
748 buf->pending = 0;
749 buf->used = 0;
750 buf_priv->dispatched = 0;
751
752 mga_freelist_put( dev, buf );
753 }
754
755 FLUSH_DMA();
756}
757
758/* This copies a 64 byte aligned agp region to the frambuffer with a
759 * standard blit, the ioctl needs to do checking.
760 */
761static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf,
762 unsigned int dstorg, unsigned int length )
763{
764 drm_mga_private_t *dev_priv = dev->dev_private;
765 drm_mga_buf_priv_t *buf_priv = buf->dev_private;
766 drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
767 u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM;
768 u32 y2;
769 DMA_LOCALS;
770 DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used );
771
772 y2 = length / 64;
773
774 BEGIN_DMA( 5 );
775
776 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
777 MGA_DMAPAD, 0x00000000,
778 MGA_DWGSYNC, 0x00007100,
779 MGA_DWGSYNC, 0x00007000 );
780
781 DMA_BLOCK( MGA_DSTORG, dstorg,
782 MGA_MACCESS, 0x00000000,
783 MGA_SRCORG, srcorg,
784 MGA_AR5, 64 );
785
786 DMA_BLOCK( MGA_PITCH, 64,
787 MGA_PLNWT, 0xffffffff,
788 MGA_DMAPAD, 0x00000000,
789 MGA_DWGCTL, MGA_DWGCTL_COPY );
790
791 DMA_BLOCK( MGA_AR0, 63,
792 MGA_AR3, 0,
793 MGA_FXBNDRY, (63 << 16) | 0,
794 MGA_YDSTLEN + MGA_EXEC, y2 );
795
796 DMA_BLOCK( MGA_PLNWT, ctx->plnwt,
797 MGA_SRCORG, dev_priv->front_offset,
798 MGA_PITCH, dev_priv->front_pitch,
799 MGA_DWGSYNC, 0x00007000 );
800
801 ADVANCE_DMA();
802
803 AGE_BUFFER( buf_priv );
804
805 buf->pending = 0;
806 buf->used = 0;
807 buf_priv->dispatched = 0;
808
809 mga_freelist_put( dev, buf );
810
811 FLUSH_DMA();
812}
813
814static void mga_dma_dispatch_blit( drm_device_t *dev,
815 drm_mga_blit_t *blit )
816{
817 drm_mga_private_t *dev_priv = dev->dev_private;
818 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
819 drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
820 drm_clip_rect_t *pbox = sarea_priv->boxes;
821 int nbox = sarea_priv->nbox;
822 u32 scandir = 0, i;
823 DMA_LOCALS;
824 DRM_DEBUG( "\n" );
825
826 BEGIN_DMA( 4 + nbox );
827
828 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
829 MGA_DMAPAD, 0x00000000,
830 MGA_DWGSYNC, 0x00007100,
831 MGA_DWGSYNC, 0x00007000 );
832
833 DMA_BLOCK( MGA_DWGCTL, MGA_DWGCTL_COPY,
834 MGA_PLNWT, blit->planemask,
835 MGA_SRCORG, blit->srcorg,
836 MGA_DSTORG, blit->dstorg );
837
838 DMA_BLOCK( MGA_SGN, scandir,
839 MGA_MACCESS, dev_priv->maccess,
840 MGA_AR5, blit->ydir * blit->src_pitch,
841 MGA_PITCH, blit->dst_pitch );
842
843 for ( i = 0 ; i < nbox ; i++ ) {
844 int srcx = pbox[i].x1 + blit->delta_sx;
845 int srcy = pbox[i].y1 + blit->delta_sy;
846 int dstx = pbox[i].x1 + blit->delta_dx;
847 int dsty = pbox[i].y1 + blit->delta_dy;
848 int h = pbox[i].y2 - pbox[i].y1;
849 int w = pbox[i].x2 - pbox[i].x1 - 1;
850 int start;
851
852 if ( blit->ydir == -1 ) {
853 srcy = blit->height - srcy - 1;
854 }
855
856 start = srcy * blit->src_pitch + srcx;
857
858 DMA_BLOCK( MGA_AR0, start + w,
859 MGA_AR3, start,
860 MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
861 MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h );
862 }
863
864 /* Do something to flush AGP?
865 */
866
867 /* Force reset of DWGCTL */
868 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
869 MGA_PLNWT, ctx->plnwt,
870 MGA_PITCH, dev_priv->front_pitch,
871 MGA_DWGCTL, ctx->dwgctl );
872
873 ADVANCE_DMA();
874}
875
876
877/* ================================================================
878 *
879 */
880
881static int mga_dma_clear( DRM_IOCTL_ARGS )
882{
883 DRM_DEVICE;
884 drm_mga_private_t *dev_priv = dev->dev_private;
885 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
886 drm_mga_clear_t clear;
887
888 LOCK_TEST_WITH_RETURN( dev, filp );
889
890 DRM_COPY_FROM_USER_IOCTL( clear, (drm_mga_clear_t __user *)data, sizeof(clear) );
891
892 if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
893 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
894
895 WRAP_TEST_WITH_RETURN( dev_priv );
896
897 mga_dma_dispatch_clear( dev, &clear );
898
899 /* Make sure we restore the 3D state next time.
900 */
901 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
902
903 return 0;
904}
905
906static int mga_dma_swap( DRM_IOCTL_ARGS )
907{
908 DRM_DEVICE;
909 drm_mga_private_t *dev_priv = dev->dev_private;
910 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
911
912 LOCK_TEST_WITH_RETURN( dev, filp );
913
914 if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
915 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
916
917 WRAP_TEST_WITH_RETURN( dev_priv );
918
919 mga_dma_dispatch_swap( dev );
920
921 /* Make sure we restore the 3D state next time.
922 */
923 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
924
925 return 0;
926}
927
928static int mga_dma_vertex( DRM_IOCTL_ARGS )
929{
930 DRM_DEVICE;
931 drm_mga_private_t *dev_priv = dev->dev_private;
932 drm_device_dma_t *dma = dev->dma;
933 drm_buf_t *buf;
934 drm_mga_buf_priv_t *buf_priv;
935 drm_mga_vertex_t vertex;
936
937 LOCK_TEST_WITH_RETURN( dev, filp );
938
939 DRM_COPY_FROM_USER_IOCTL( vertex,
940 (drm_mga_vertex_t __user *)data,
941 sizeof(vertex) );
942
943 if(vertex.idx < 0 || vertex.idx > dma->buf_count) return DRM_ERR(EINVAL);
944 buf = dma->buflist[vertex.idx];
945 buf_priv = buf->dev_private;
946
947 buf->used = vertex.used;
948 buf_priv->discard = vertex.discard;
949
950 if ( !mga_verify_state( dev_priv ) ) {
951 if ( vertex.discard ) {
952 if ( buf_priv->dispatched == 1 )
953 AGE_BUFFER( buf_priv );
954 buf_priv->dispatched = 0;
955 mga_freelist_put( dev, buf );
956 }
957 return DRM_ERR(EINVAL);
958 }
959
960 WRAP_TEST_WITH_RETURN( dev_priv );
961
962 mga_dma_dispatch_vertex( dev, buf );
963
964 return 0;
965}
966
967static int mga_dma_indices( DRM_IOCTL_ARGS )
968{
969 DRM_DEVICE;
970 drm_mga_private_t *dev_priv = dev->dev_private;
971 drm_device_dma_t *dma = dev->dma;
972 drm_buf_t *buf;
973 drm_mga_buf_priv_t *buf_priv;
974 drm_mga_indices_t indices;
975
976 LOCK_TEST_WITH_RETURN( dev, filp );
977
978 DRM_COPY_FROM_USER_IOCTL( indices,
979 (drm_mga_indices_t __user *)data,
980 sizeof(indices) );
981
982 if(indices.idx < 0 || indices.idx > dma->buf_count) return DRM_ERR(EINVAL);
983
984 buf = dma->buflist[indices.idx];
985 buf_priv = buf->dev_private;
986
987 buf_priv->discard = indices.discard;
988
989 if ( !mga_verify_state( dev_priv ) ) {
990 if ( indices.discard ) {
991 if ( buf_priv->dispatched == 1 )
992 AGE_BUFFER( buf_priv );
993 buf_priv->dispatched = 0;
994 mga_freelist_put( dev, buf );
995 }
996 return DRM_ERR(EINVAL);
997 }
998
999 WRAP_TEST_WITH_RETURN( dev_priv );
1000
1001 mga_dma_dispatch_indices( dev, buf, indices.start, indices.end );
1002
1003 return 0;
1004}
1005
1006static int mga_dma_iload( DRM_IOCTL_ARGS )
1007{
1008 DRM_DEVICE;
1009 drm_device_dma_t *dma = dev->dma;
1010 drm_mga_private_t *dev_priv = dev->dev_private;
1011 drm_buf_t *buf;
1012 drm_mga_buf_priv_t *buf_priv;
1013 drm_mga_iload_t iload;
1014 DRM_DEBUG( "\n" );
1015
1016 LOCK_TEST_WITH_RETURN( dev, filp );
1017
1018 DRM_COPY_FROM_USER_IOCTL( iload, (drm_mga_iload_t __user *)data, sizeof(iload) );
1019
1020#if 0
1021 if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {
1022 if ( MGA_DMA_DEBUG )
1023 DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ );
1024 return DRM_ERR(EBUSY);
1025 }
1026#endif
1027 if(iload.idx < 0 || iload.idx > dma->buf_count) return DRM_ERR(EINVAL);
1028
1029 buf = dma->buflist[iload.idx];
1030 buf_priv = buf->dev_private;
1031
1032 if ( mga_verify_iload( dev_priv, iload.dstorg, iload.length ) ) {
1033 mga_freelist_put( dev, buf );
1034 return DRM_ERR(EINVAL);
1035 }
1036
1037 WRAP_TEST_WITH_RETURN( dev_priv );
1038
1039 mga_dma_dispatch_iload( dev, buf, iload.dstorg, iload.length );
1040
1041 /* Make sure we restore the 3D state next time.
1042 */
1043 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
1044
1045 return 0;
1046}
1047
1048static int mga_dma_blit( DRM_IOCTL_ARGS )
1049{
1050 DRM_DEVICE;
1051 drm_mga_private_t *dev_priv = dev->dev_private;
1052 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
1053 drm_mga_blit_t blit;
1054 DRM_DEBUG( "\n" );
1055
1056 LOCK_TEST_WITH_RETURN( dev, filp );
1057
1058 DRM_COPY_FROM_USER_IOCTL( blit, (drm_mga_blit_t __user *)data, sizeof(blit) );
1059
1060 if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
1061 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
1062
1063 if ( mga_verify_blit( dev_priv, blit.srcorg, blit.dstorg ) )
1064 return DRM_ERR(EINVAL);
1065
1066 WRAP_TEST_WITH_RETURN( dev_priv );
1067
1068 mga_dma_dispatch_blit( dev, &blit );
1069
1070 /* Make sure we restore the 3D state next time.
1071 */
1072 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
1073
1074 return 0;
1075}
1076
1077static int mga_getparam( DRM_IOCTL_ARGS )
1078{
1079 DRM_DEVICE;
1080 drm_mga_private_t *dev_priv = dev->dev_private;
1081 drm_mga_getparam_t param;
1082 int value;
1083
1084 if ( !dev_priv ) {
1085 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1086 return DRM_ERR(EINVAL);
1087 }
1088
1089 DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t __user *)data,
1090 sizeof(param) );
1091
1092 DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
1093
1094 switch( param.param ) {
1095 case MGA_PARAM_IRQ_NR:
1096 value = dev->irq;
1097 break;
1098 default:
1099 return DRM_ERR(EINVAL);
1100 }
1101
1102 if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
1103 DRM_ERROR( "copy_to_user\n" );
1104 return DRM_ERR(EFAULT);
1105 }
1106
1107 return 0;
1108}
1109
1110drm_ioctl_desc_t mga_ioctls[] = {
1111 [DRM_IOCTL_NR(DRM_MGA_INIT)] = { mga_dma_init, 1, 1 },
1112 [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = { mga_dma_flush, 1, 0 },
1113 [DRM_IOCTL_NR(DRM_MGA_RESET)] = { mga_dma_reset, 1, 0 },
1114 [DRM_IOCTL_NR(DRM_MGA_SWAP)] = { mga_dma_swap, 1, 0 },
1115 [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = { mga_dma_clear, 1, 0 },
1116 [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 },
1117 [DRM_IOCTL_NR(DRM_MGA_INDICES)] = { mga_dma_indices, 1, 0 },
1118 [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = { mga_dma_iload, 1, 0 },
1119 [DRM_IOCTL_NR(DRM_MGA_BLIT)] = { mga_dma_blit, 1, 0 },
1120 [DRM_IOCTL_NR(DRM_MGA_GETPARAM)]= { mga_getparam, 1, 0 },
1121};
1122
1123int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
diff --git a/drivers/char/drm/mga_ucode.h b/drivers/char/drm/mga_ucode.h
new file mode 100644
index 000000000000..fa0f82ec9fa0
--- /dev/null
+++ b/drivers/char/drm/mga_ucode.h
@@ -0,0 +1,11645 @@
1/* mga_ucode.h -- Matrox G200/G400 WARP engine microcode -*- linux-c -*-
2 * Created: Thu Jan 11 21:20:43 2001 by gareth@valinux.com
3 *
4 * Copyright 1999 Matrox Graphics Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * MATROX GRAPHICS INC., OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
23 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Kernel-based WARP engine management:
26 * Gareth Hughes <gareth@valinux.com>
27 */
28
29/*
30 * WARP pipes are named according to the functions they perform, where:
31 *
32 * - T stands for computation of texture stage 0
33 * - T2 stands for computation of both texture stage 0 and texture stage 1
34 * - G stands for computation of triangle intensity (Gouraud interpolation)
35 * - Z stands for computation of Z buffer interpolation
36 * - S stands for computation of specular highlight
37 * - A stands for computation of the alpha channel
38 * - F stands for computation of vertex fog interpolation
39 */
40
41static unsigned char warp_g200_tgz[] = {
42
430x00, 0x80, 0x00, 0xE8,
440x00, 0x80, 0x00, 0xE8,
45
460x00, 0x80, 0x00, 0xE8,
470x00, 0x80, 0x00, 0xE8,
48
490x00, 0x80, 0x00, 0xE8,
500x00, 0x80, 0x00, 0xE8,
51
520x00, 0x80, 0x00, 0xE8,
530x00, 0x80, 0x00, 0xE8,
54
550x00, 0x80, 0x00, 0xE8,
560x00, 0x80, 0x00, 0xE8,
57
580x00, 0x98, 0xA0, 0xE9,
590x40, 0x40, 0xD8, 0xEC,
60
610xFF, 0x80, 0xC0, 0xE9,
620x00, 0x80, 0x00, 0xE8,
63
640x1F, 0xD7, 0x18, 0xBD,
650x3F, 0xD7, 0x22, 0xBD,
66
670x81, 0x04,
680x89, 0x04,
690x01, 0x04,
700x09, 0x04,
71
720xC9, 0x41, 0xC0, 0xEC,
730x11, 0x04,
740x00, 0xE0,
75
760x41, 0xCC, 0x41, 0xCD,
770x49, 0xCC, 0x49, 0xCD,
78
790xD1, 0x41, 0xC0, 0xEC,
800x51, 0xCC, 0x51, 0xCD,
81
820x80, 0x04,
830x10, 0x04,
840x08, 0x04,
850x00, 0xE0,
86
870x00, 0xCC, 0xC0, 0xCD,
880xD1, 0x49, 0xC0, 0xEC,
89
900x8A, 0x1F, 0x20, 0xE9,
910x8B, 0x3F, 0x20, 0xE9,
92
930x41, 0x3C, 0x41, 0xAD,
940x49, 0x3C, 0x49, 0xAD,
95
960x10, 0xCC, 0x10, 0xCD,
970x08, 0xCC, 0x08, 0xCD,
98
990xB9, 0x41, 0x49, 0xBB,
1000x1F, 0xF0, 0x41, 0xCD,
101
1020x51, 0x3C, 0x51, 0xAD,
1030x00, 0x98, 0x80, 0xE9,
104
1050x72, 0x80, 0x07, 0xEA,
1060x24, 0x1F, 0x20, 0xE9,
107
1080x15, 0x41, 0x49, 0xBD,
1090x1D, 0x41, 0x51, 0xBD,
110
1110x2E, 0x41, 0x2A, 0xB8,
1120x34, 0x53, 0xA0, 0xE8,
113
1140x15, 0x30,
1150x1D, 0x30,
1160x58, 0xE3,
1170x00, 0xE0,
118
1190xB5, 0x40, 0x48, 0xBD,
1200x3D, 0x40, 0x50, 0xBD,
121
1220x24, 0x43, 0xA0, 0xE8,
1230x2C, 0x4B, 0xA0, 0xE8,
124
1250x15, 0x72,
1260x09, 0xE3,
1270x00, 0xE0,
1280x1D, 0x72,
129
1300x35, 0x30,
1310xB5, 0x30,
1320xBD, 0x30,
1330x3D, 0x30,
134
1350x9C, 0x97, 0x57, 0x9F,
1360x00, 0x80, 0x00, 0xE8,
137
1380x6C, 0x64, 0xC8, 0xEC,
1390x98, 0xE1,
1400xB5, 0x05,
141
1420xBD, 0x05,
1430x2E, 0x30,
1440x32, 0xC0, 0xA0, 0xE8,
145
1460x33, 0xC0, 0xA0, 0xE8,
1470x74, 0x64, 0xC8, 0xEC,
148
1490x40, 0x3C, 0x40, 0xAD,
1500x32, 0x6A,
1510x2A, 0x30,
152
1530x20, 0x73,
1540x33, 0x6A,
1550x00, 0xE0,
1560x28, 0x73,
157
1580x1C, 0x72,
1590x83, 0xE2,
1600x60, 0x80, 0x15, 0xEA,
161
1620xB8, 0x3D, 0x28, 0xDF,
1630x30, 0x35, 0x20, 0xDF,
164
1650x40, 0x30,
1660x00, 0xE0,
1670xCC, 0xE2,
1680x64, 0x72,
169
1700x25, 0x42, 0x52, 0xBF,
1710x2D, 0x42, 0x4A, 0xBF,
172
1730x30, 0x2E, 0x30, 0xDF,
1740x38, 0x2E, 0x38, 0xDF,
175
1760x18, 0x1D, 0x45, 0xE9,
1770x1E, 0x15, 0x45, 0xE9,
178
1790x2B, 0x49, 0x51, 0xBD,
1800x00, 0xE0,
1810x1F, 0x73,
182
1830x38, 0x38, 0x40, 0xAF,
1840x30, 0x30, 0x40, 0xAF,
185
1860x24, 0x1F, 0x24, 0xDF,
1870x1D, 0x32, 0x20, 0xE9,
188
1890x2C, 0x1F, 0x2C, 0xDF,
1900x1A, 0x33, 0x20, 0xE9,
191
1920xB0, 0x10,
1930x08, 0xE3,
1940x40, 0x10,
1950xB8, 0x10,
196
1970x26, 0xF0, 0x30, 0xCD,
1980x2F, 0xF0, 0x38, 0xCD,
199
2000x2B, 0x80, 0x20, 0xE9,
2010x2A, 0x80, 0x20, 0xE9,
202
2030xA6, 0x20,
2040x88, 0xE2,
2050x00, 0xE0,
2060xAF, 0x20,
207
2080x28, 0x2A, 0x26, 0xAF,
2090x20, 0x2A, 0xC0, 0xAF,
210
2110x34, 0x1F, 0x34, 0xDF,
2120x46, 0x24, 0x46, 0xDF,
213
2140x28, 0x30, 0x80, 0xBF,
2150x20, 0x38, 0x80, 0xBF,
216
2170x47, 0x24, 0x47, 0xDF,
2180x4E, 0x2C, 0x4E, 0xDF,
219
2200x4F, 0x2C, 0x4F, 0xDF,
2210x56, 0x34, 0x56, 0xDF,
222
2230x28, 0x15, 0x28, 0xDF,
2240x20, 0x1D, 0x20, 0xDF,
225
2260x57, 0x34, 0x57, 0xDF,
2270x00, 0xE0,
2280x1D, 0x05,
229
2300x04, 0x80, 0x10, 0xEA,
2310x89, 0xE2,
2320x2B, 0x30,
233
2340x3F, 0xC1, 0x1D, 0xBD,
2350x00, 0x80, 0x00, 0xE8,
236
2370x00, 0x80, 0x00, 0xE8,
2380x00, 0x80, 0x00, 0xE8,
239
2400xA0, 0x68,
2410xBF, 0x25,
2420x00, 0x80, 0x00, 0xE8,
243
2440x20, 0xC0, 0x20, 0xAF,
2450x28, 0x05,
2460x97, 0x74,
247
2480x00, 0xE0,
2490x2A, 0x10,
2500x16, 0xC0, 0x20, 0xE9,
251
2520x04, 0x80, 0x10, 0xEA,
2530x8C, 0xE2,
2540x95, 0x05,
255
2560x28, 0xC1, 0x28, 0xAD,
2570x1F, 0xC1, 0x15, 0xBD,
258
2590x00, 0x80, 0x00, 0xE8,
2600x00, 0x80, 0x00, 0xE8,
261
2620xA8, 0x67,
2630x9F, 0x6B,
2640x00, 0x80, 0x00, 0xE8,
265
2660x28, 0xC0, 0x28, 0xAD,
2670x1D, 0x25,
2680x20, 0x05,
269
2700x28, 0x32, 0x80, 0xAD,
2710x40, 0x2A, 0x40, 0xBD,
272
2730x1C, 0x80, 0x20, 0xE9,
2740x20, 0x33, 0x20, 0xAD,
275
2760x20, 0x73,
2770x00, 0xE0,
2780xB6, 0x49, 0x51, 0xBB,
279
2800x26, 0x2F, 0xB0, 0xE8,
2810x19, 0x20, 0x20, 0xE9,
282
2830x35, 0x20, 0x35, 0xDF,
2840x3D, 0x20, 0x3D, 0xDF,
285
2860x15, 0x20, 0x15, 0xDF,
2870x1D, 0x20, 0x1D, 0xDF,
288
2890x26, 0xD0, 0x26, 0xCD,
2900x29, 0x49, 0x2A, 0xB8,
291
2920x26, 0x40, 0x80, 0xBD,
2930x3B, 0x48, 0x50, 0xBD,
294
2950x3E, 0x54, 0x57, 0x9F,
2960x00, 0xE0,
2970x82, 0xE1,
298
2990x1E, 0xAF, 0x59, 0x9F,
3000x00, 0x80, 0x00, 0xE8,
301
3020x26, 0x30,
3030x29, 0x30,
3040x48, 0x3C, 0x48, 0xAD,
305
3060x2B, 0x72,
3070xC2, 0xE1,
3080x2C, 0xC0, 0x44, 0xC2,
309
3100x05, 0x24, 0x34, 0xBF,
3110x0D, 0x24, 0x2C, 0xBF,
312
3130x2D, 0x46, 0x4E, 0xBF,
3140x25, 0x46, 0x56, 0xBF,
315
3160x20, 0x1D, 0x6F, 0x8F,
3170x32, 0x3E, 0x5F, 0xE9,
318
3190x3E, 0x50, 0x56, 0x9F,
3200x00, 0xE0,
3210x3B, 0x30,
322
3230x1E, 0x8F, 0x51, 0x9F,
3240x33, 0x1E, 0x5F, 0xE9,
325
3260x05, 0x44, 0x54, 0xB2,
3270x0D, 0x44, 0x4C, 0xB2,
328
3290x19, 0xC0, 0xB0, 0xE8,
3300x34, 0xC0, 0x44, 0xC4,
331
3320x33, 0x73,
3330x00, 0xE0,
3340x3E, 0x62, 0x57, 0x9F,
335
3360x1E, 0xAF, 0x59, 0x9F,
3370x00, 0xE0,
3380x0D, 0x20,
339
3400x84, 0x3E, 0x58, 0xE9,
3410x28, 0x1D, 0x6F, 0x8F,
342
3430x05, 0x20,
3440x00, 0xE0,
3450x85, 0x1E, 0x58, 0xE9,
346
3470x9B, 0x3B, 0x33, 0xDF,
3480x20, 0x20, 0x42, 0xAF,
349
3500x30, 0x42, 0x56, 0x9F,
3510x80, 0x3E, 0x57, 0xE9,
352
3530x3F, 0x8F, 0x51, 0x9F,
3540x30, 0x80, 0x5F, 0xE9,
355
3560x28, 0x28, 0x24, 0xAF,
3570x81, 0x1E, 0x57, 0xE9,
358
3590x05, 0x47, 0x57, 0xBF,
3600x0D, 0x47, 0x4F, 0xBF,
361
3620x88, 0x80, 0x58, 0xE9,
3630x1B, 0x29, 0x1B, 0xDF,
364
3650x30, 0x1D, 0x6F, 0x8F,
3660x3A, 0x30, 0x4F, 0xE9,
367
3680x1C, 0x30, 0x26, 0xDF,
3690x09, 0xE3,
3700x3B, 0x05,
371
3720x3E, 0x50, 0x56, 0x9F,
3730x3B, 0x3F, 0x4F, 0xE9,
374
3750x1E, 0x8F, 0x51, 0x9F,
3760x00, 0xE0,
3770xAC, 0x20,
378
3790x2D, 0x44, 0x4C, 0xB4,
3800x2C, 0x1C, 0xC0, 0xAF,
381
3820x25, 0x44, 0x54, 0xB4,
3830x00, 0xE0,
3840xC8, 0x30,
385
3860x30, 0x46, 0x30, 0xAF,
3870x1B, 0x1B, 0x48, 0xAF,
388
3890x00, 0xE0,
3900x25, 0x20,
3910x38, 0x2C, 0x4F, 0xE9,
392
3930x86, 0x80, 0x57, 0xE9,
3940x38, 0x1D, 0x6F, 0x8F,
395
3960x28, 0x74,
3970x00, 0xE0,
3980x0D, 0x44, 0x4C, 0xB0,
399
4000x05, 0x44, 0x54, 0xB0,
4010x2D, 0x20,
4020x9B, 0x10,
403
4040x82, 0x3E, 0x57, 0xE9,
4050x32, 0xF0, 0x1B, 0xCD,
406
4070x1E, 0xBD, 0x59, 0x9F,
4080x83, 0x1E, 0x57, 0xE9,
409
4100x38, 0x47, 0x38, 0xAF,
4110x34, 0x20,
4120x2A, 0x30,
413
4140x00, 0xE0,
4150x0D, 0x20,
4160x32, 0x20,
4170x05, 0x20,
418
4190x87, 0x80, 0x57, 0xE9,
4200x1F, 0x54, 0x57, 0x9F,
421
4220x17, 0x42, 0x56, 0x9F,
4230x00, 0xE0,
4240x3B, 0x6A,
425
4260x3F, 0x8F, 0x51, 0x9F,
4270x37, 0x1E, 0x4F, 0xE9,
428
4290x37, 0x32, 0x2A, 0xAF,
4300x00, 0xE0,
4310x32, 0x00,
432
4330x00, 0x80, 0x00, 0xE8,
4340x27, 0xC0, 0x44, 0xC0,
435
4360x36, 0x1F, 0x4F, 0xE9,
4370x1F, 0x1F, 0x26, 0xDF,
438
4390x37, 0x1B, 0x37, 0xBF,
4400x17, 0x26, 0x17, 0xDF,
441
4420x3E, 0x17, 0x4F, 0xE9,
4430x3F, 0x3F, 0x4F, 0xE9,
444
4450x34, 0x1F, 0x34, 0xAF,
4460x2B, 0x05,
4470xA7, 0x20,
448
4490x33, 0x2B, 0x37, 0xDF,
4500x27, 0x17, 0xC0, 0xAF,
451
4520x34, 0x80, 0x4F, 0xE9,
4530x00, 0x80, 0x00, 0xE8,
454
4550x03, 0x80, 0x0A, 0xEA,
4560x17, 0xC1, 0x2B, 0xBD,
457
4580x00, 0x80, 0x00, 0xE8,
4590x00, 0x80, 0x00, 0xE8,
460
4610xB3, 0x68,
4620x97, 0x25,
4630x00, 0x80, 0x00, 0xE8,
464
4650x33, 0xC0, 0x33, 0xAF,
4660x3C, 0x27, 0x4F, 0xE9,
467
4680x57, 0x39, 0x20, 0xE9,
4690x28, 0x19, 0x60, 0xEC,
470
4710x2B, 0x32, 0x20, 0xE9,
4720x1D, 0x3B, 0x20, 0xE9,
473
4740xB3, 0x05,
4750x00, 0xE0,
4760x16, 0x28, 0x20, 0xE9,
477
4780x23, 0x3B, 0x33, 0xAD,
4790x1E, 0x2B, 0x20, 0xE9,
480
4810x1C, 0x80, 0x20, 0xE9,
4820x57, 0x36, 0x20, 0xE9,
483
4840x00, 0x80, 0xA0, 0xE9,
4850x40, 0x40, 0xD8, 0xEC,
486
4870xFF, 0x80, 0xC0, 0xE9,
4880x90, 0xE2,
4890x00, 0xE0,
490
4910x85, 0xFF, 0x20, 0xEA,
4920x19, 0xC8, 0xC1, 0xCD,
493
4940x1F, 0xD7, 0x18, 0xBD,
4950x3F, 0xD7, 0x22, 0xBD,
496
4970x9F, 0x41, 0x49, 0xBD,
4980x00, 0x80, 0x00, 0xE8,
499
5000x25, 0x41, 0x49, 0xBD,
5010x2D, 0x41, 0x51, 0xBD,
502
5030x0D, 0x80, 0x07, 0xEA,
5040x00, 0x80, 0x00, 0xE8,
505
5060x35, 0x40, 0x48, 0xBD,
5070x3D, 0x40, 0x50, 0xBD,
508
5090x00, 0x80, 0x00, 0xE8,
5100x25, 0x30,
5110x2D, 0x30,
512
5130x35, 0x30,
5140xB5, 0x30,
5150xBD, 0x30,
5160x3D, 0x30,
517
5180x9C, 0xA7, 0x5B, 0x9F,
5190x00, 0x80, 0x00, 0xE8,
520
5210x00, 0x80, 0x00, 0xE8,
5220x00, 0x80, 0x00, 0xE8,
523
5240x00, 0x80, 0x00, 0xE8,
5250x00, 0x80, 0x00, 0xE8,
526
5270x00, 0x80, 0x00, 0xE8,
5280x00, 0x80, 0x00, 0xE8,
529
5300x00, 0x80, 0x00, 0xE8,
5310x00, 0x80, 0x00, 0xE8,
532
5330x84, 0xFF, 0x0A, 0xEA,
5340x00, 0x80, 0x00, 0xE8,
535
5360xC9, 0x41, 0xC8, 0xEC,
5370x42, 0xE1,
5380x00, 0xE0,
539
5400x82, 0xFF, 0x20, 0xEA,
5410x00, 0x80, 0x00, 0xE8,
542
5430x00, 0x80, 0x00, 0xE8,
5440x00, 0x80, 0x00, 0xE8,
545
5460xC8, 0x40, 0xC0, 0xEC,
5470x00, 0x80, 0x00, 0xE8,
548
5490x7F, 0xFF, 0x20, 0xEA,
5500x00, 0x80, 0x00, 0xE8,
551
5520x00, 0x80, 0x00, 0xE8,
5530x00, 0x80, 0x00, 0xE8,
554
555};
556
557static unsigned char warp_g200_tgza[] = {
558
5590x00, 0x98, 0xA0, 0xE9,
5600x40, 0x40, 0xD8, 0xEC,
561
5620xFF, 0x80, 0xC0, 0xE9,
5630x00, 0x80, 0x00, 0xE8,
564
5650x1F, 0xD7, 0x18, 0xBD,
5660x3F, 0xD7, 0x22, 0xBD,
567
5680x81, 0x04,
5690x89, 0x04,
5700x01, 0x04,
5710x09, 0x04,
572
5730xC9, 0x41, 0xC0, 0xEC,
5740x11, 0x04,
5750x00, 0xE0,
576
5770x41, 0xCC, 0x41, 0xCD,
5780x49, 0xCC, 0x49, 0xCD,
579
5800xD1, 0x41, 0xC0, 0xEC,
5810x51, 0xCC, 0x51, 0xCD,
582
5830x80, 0x04,
5840x10, 0x04,
5850x08, 0x04,
5860x00, 0xE0,
587
5880x00, 0xCC, 0xC0, 0xCD,
5890xD1, 0x49, 0xC0, 0xEC,
590
5910x8A, 0x1F, 0x20, 0xE9,
5920x8B, 0x3F, 0x20, 0xE9,
593
5940x41, 0x3C, 0x41, 0xAD,
5950x49, 0x3C, 0x49, 0xAD,
596
5970x10, 0xCC, 0x10, 0xCD,
5980x08, 0xCC, 0x08, 0xCD,
599
6000xB9, 0x41, 0x49, 0xBB,
6010x1F, 0xF0, 0x41, 0xCD,
602
6030x51, 0x3C, 0x51, 0xAD,
6040x00, 0x98, 0x80, 0xE9,
605
6060x7D, 0x80, 0x07, 0xEA,
6070x24, 0x1F, 0x20, 0xE9,
608
6090x15, 0x41, 0x49, 0xBD,
6100x1D, 0x41, 0x51, 0xBD,
611
6120x2E, 0x41, 0x2A, 0xB8,
6130x34, 0x53, 0xA0, 0xE8,
614
6150x15, 0x30,
6160x1D, 0x30,
6170x58, 0xE3,
6180x00, 0xE0,
619
6200xB5, 0x40, 0x48, 0xBD,
6210x3D, 0x40, 0x50, 0xBD,
622
6230x24, 0x43, 0xA0, 0xE8,
6240x2C, 0x4B, 0xA0, 0xE8,
625
6260x15, 0x72,
6270x09, 0xE3,
6280x00, 0xE0,
6290x1D, 0x72,
630
6310x35, 0x30,
6320xB5, 0x30,
6330xBD, 0x30,
6340x3D, 0x30,
635
6360x9C, 0x97, 0x57, 0x9F,
6370x00, 0x80, 0x00, 0xE8,
638
6390x6C, 0x64, 0xC8, 0xEC,
6400x98, 0xE1,
6410xB5, 0x05,
642
6430xBD, 0x05,
6440x2E, 0x30,
6450x32, 0xC0, 0xA0, 0xE8,
646
6470x33, 0xC0, 0xA0, 0xE8,
6480x74, 0x64, 0xC8, 0xEC,
649
6500x40, 0x3C, 0x40, 0xAD,
6510x32, 0x6A,
6520x2A, 0x30,
653
6540x20, 0x73,
6550x33, 0x6A,
6560x00, 0xE0,
6570x28, 0x73,
658
6590x1C, 0x72,
6600x83, 0xE2,
6610x6B, 0x80, 0x15, 0xEA,
662
6630xB8, 0x3D, 0x28, 0xDF,
6640x30, 0x35, 0x20, 0xDF,
665
6660x40, 0x30,
6670x00, 0xE0,
6680xCC, 0xE2,
6690x64, 0x72,
670
6710x25, 0x42, 0x52, 0xBF,
6720x2D, 0x42, 0x4A, 0xBF,
673
6740x30, 0x2E, 0x30, 0xDF,
6750x38, 0x2E, 0x38, 0xDF,
676
6770x18, 0x1D, 0x45, 0xE9,
6780x1E, 0x15, 0x45, 0xE9,
679
6800x2B, 0x49, 0x51, 0xBD,
6810x00, 0xE0,
6820x1F, 0x73,
683
6840x38, 0x38, 0x40, 0xAF,
6850x30, 0x30, 0x40, 0xAF,
686
6870x24, 0x1F, 0x24, 0xDF,
6880x1D, 0x32, 0x20, 0xE9,
689
6900x2C, 0x1F, 0x2C, 0xDF,
6910x1A, 0x33, 0x20, 0xE9,
692
6930xB0, 0x10,
6940x08, 0xE3,
6950x40, 0x10,
6960xB8, 0x10,
697
6980x26, 0xF0, 0x30, 0xCD,
6990x2F, 0xF0, 0x38, 0xCD,
700
7010x2B, 0x80, 0x20, 0xE9,
7020x2A, 0x80, 0x20, 0xE9,
703
7040xA6, 0x20,
7050x88, 0xE2,
7060x00, 0xE0,
7070xAF, 0x20,
708
7090x28, 0x2A, 0x26, 0xAF,
7100x20, 0x2A, 0xC0, 0xAF,
711
7120x34, 0x1F, 0x34, 0xDF,
7130x46, 0x24, 0x46, 0xDF,
714
7150x28, 0x30, 0x80, 0xBF,
7160x20, 0x38, 0x80, 0xBF,
717
7180x47, 0x24, 0x47, 0xDF,
7190x4E, 0x2C, 0x4E, 0xDF,
720
7210x4F, 0x2C, 0x4F, 0xDF,
7220x56, 0x34, 0x56, 0xDF,
723
7240x28, 0x15, 0x28, 0xDF,
7250x20, 0x1D, 0x20, 0xDF,
726
7270x57, 0x34, 0x57, 0xDF,
7280x00, 0xE0,
7290x1D, 0x05,
730
7310x04, 0x80, 0x10, 0xEA,
7320x89, 0xE2,
7330x2B, 0x30,
734
7350x3F, 0xC1, 0x1D, 0xBD,
7360x00, 0x80, 0x00, 0xE8,
737
7380x00, 0x80, 0x00, 0xE8,
7390x00, 0x80, 0x00, 0xE8,
740
7410xA0, 0x68,
7420xBF, 0x25,
7430x00, 0x80, 0x00, 0xE8,
744
7450x20, 0xC0, 0x20, 0xAF,
7460x28, 0x05,
7470x97, 0x74,
748
7490x00, 0xE0,
7500x2A, 0x10,
7510x16, 0xC0, 0x20, 0xE9,
752
7530x04, 0x80, 0x10, 0xEA,
7540x8C, 0xE2,
7550x95, 0x05,
756
7570x28, 0xC1, 0x28, 0xAD,
7580x1F, 0xC1, 0x15, 0xBD,
759
7600x00, 0x80, 0x00, 0xE8,
7610x00, 0x80, 0x00, 0xE8,
762
7630xA8, 0x67,
7640x9F, 0x6B,
7650x00, 0x80, 0x00, 0xE8,
766
7670x28, 0xC0, 0x28, 0xAD,
7680x1D, 0x25,
7690x20, 0x05,
770
7710x28, 0x32, 0x80, 0xAD,
7720x40, 0x2A, 0x40, 0xBD,
773
7740x1C, 0x80, 0x20, 0xE9,
7750x20, 0x33, 0x20, 0xAD,
776
7770x20, 0x73,
7780x00, 0xE0,
7790xB6, 0x49, 0x51, 0xBB,
780
7810x26, 0x2F, 0xB0, 0xE8,
7820x19, 0x20, 0x20, 0xE9,
783
7840x35, 0x20, 0x35, 0xDF,
7850x3D, 0x20, 0x3D, 0xDF,
786
7870x15, 0x20, 0x15, 0xDF,
7880x1D, 0x20, 0x1D, 0xDF,
789
7900x26, 0xD0, 0x26, 0xCD,
7910x29, 0x49, 0x2A, 0xB8,
792
7930x26, 0x40, 0x80, 0xBD,
7940x3B, 0x48, 0x50, 0xBD,
795
7960x3E, 0x54, 0x57, 0x9F,
7970x00, 0xE0,
7980x82, 0xE1,
799
8000x1E, 0xAF, 0x59, 0x9F,
8010x00, 0x80, 0x00, 0xE8,
802
8030x26, 0x30,
8040x29, 0x30,
8050x48, 0x3C, 0x48, 0xAD,
806
8070x2B, 0x72,
8080xC2, 0xE1,
8090x2C, 0xC0, 0x44, 0xC2,
810
8110x05, 0x24, 0x34, 0xBF,
8120x0D, 0x24, 0x2C, 0xBF,
813
8140x2D, 0x46, 0x4E, 0xBF,
8150x25, 0x46, 0x56, 0xBF,
816
8170x20, 0x1D, 0x6F, 0x8F,
8180x32, 0x3E, 0x5F, 0xE9,
819
8200x3E, 0x50, 0x56, 0x9F,
8210x00, 0xE0,
8220x3B, 0x30,
823
8240x1E, 0x8F, 0x51, 0x9F,
8250x33, 0x1E, 0x5F, 0xE9,
826
8270x05, 0x44, 0x54, 0xB2,
8280x0D, 0x44, 0x4C, 0xB2,
829
8300x19, 0xC0, 0xB0, 0xE8,
8310x34, 0xC0, 0x44, 0xC4,
832
8330x33, 0x73,
8340x00, 0xE0,
8350x3E, 0x62, 0x57, 0x9F,
836
8370x1E, 0xAF, 0x59, 0x9F,
8380x00, 0xE0,
8390x0D, 0x20,
840
8410x84, 0x3E, 0x58, 0xE9,
8420x28, 0x1D, 0x6F, 0x8F,
843
8440x05, 0x20,
8450x00, 0xE0,
8460x85, 0x1E, 0x58, 0xE9,
847
8480x9B, 0x3B, 0x33, 0xDF,
8490x20, 0x20, 0x42, 0xAF,
850
8510x30, 0x42, 0x56, 0x9F,
8520x80, 0x3E, 0x57, 0xE9,
853
8540x3F, 0x8F, 0x51, 0x9F,
8550x30, 0x80, 0x5F, 0xE9,
856
8570x28, 0x28, 0x24, 0xAF,
8580x81, 0x1E, 0x57, 0xE9,
859
8600x05, 0x47, 0x57, 0xBF,
8610x0D, 0x47, 0x4F, 0xBF,
862
8630x88, 0x80, 0x58, 0xE9,
8640x1B, 0x29, 0x1B, 0xDF,
865
8660x30, 0x1D, 0x6F, 0x8F,
8670x3A, 0x30, 0x4F, 0xE9,
868
8690x1C, 0x30, 0x26, 0xDF,
8700x09, 0xE3,
8710x3B, 0x05,
872
8730x3E, 0x50, 0x56, 0x9F,
8740x3B, 0x3F, 0x4F, 0xE9,
875
8760x1E, 0x8F, 0x51, 0x9F,
8770x00, 0xE0,
8780xAC, 0x20,
879
8800x2D, 0x44, 0x4C, 0xB4,
8810x2C, 0x1C, 0xC0, 0xAF,
882
8830x25, 0x44, 0x54, 0xB4,
8840x00, 0xE0,
8850xC8, 0x30,
886
8870x30, 0x46, 0x30, 0xAF,
8880x1B, 0x1B, 0x48, 0xAF,
889
8900x00, 0xE0,
8910x25, 0x20,
8920x38, 0x2C, 0x4F, 0xE9,
893
8940x86, 0x80, 0x57, 0xE9,
8950x38, 0x1D, 0x6F, 0x8F,
896
8970x28, 0x74,
8980x00, 0xE0,
8990x0D, 0x44, 0x4C, 0xB0,
900
9010x05, 0x44, 0x54, 0xB0,
9020x2D, 0x20,
9030x9B, 0x10,
904
9050x82, 0x3E, 0x57, 0xE9,
9060x32, 0xF0, 0x1B, 0xCD,
907
9080x1E, 0xBD, 0x59, 0x9F,
9090x83, 0x1E, 0x57, 0xE9,
910
9110x38, 0x47, 0x38, 0xAF,
9120x34, 0x20,
9130x2A, 0x30,
914
9150x00, 0xE0,
9160x0D, 0x20,
9170x32, 0x20,
9180x05, 0x20,
919
9200x87, 0x80, 0x57, 0xE9,
9210x1F, 0x54, 0x57, 0x9F,
922
9230x17, 0x42, 0x56, 0x9F,
9240x00, 0xE0,
9250x3B, 0x6A,
926
9270x3F, 0x8F, 0x51, 0x9F,
9280x37, 0x1E, 0x4F, 0xE9,
929
9300x37, 0x32, 0x2A, 0xAF,
9310x00, 0xE0,
9320x32, 0x00,
933
9340x00, 0x80, 0x00, 0xE8,
9350x27, 0xC0, 0x44, 0xC0,
936
9370x36, 0x1F, 0x4F, 0xE9,
9380x1F, 0x1F, 0x26, 0xDF,
939
9400x37, 0x1B, 0x37, 0xBF,
9410x17, 0x26, 0x17, 0xDF,
942
9430x3E, 0x17, 0x4F, 0xE9,
9440x3F, 0x3F, 0x4F, 0xE9,
945
9460x34, 0x1F, 0x34, 0xAF,
9470x2B, 0x05,
9480xA7, 0x20,
949
9500x33, 0x2B, 0x37, 0xDF,
9510x27, 0x17, 0xC0, 0xAF,
952
9530x34, 0x80, 0x4F, 0xE9,
9540x00, 0x80, 0x00, 0xE8,
955
9560x2D, 0x44, 0x4C, 0xB6,
9570x25, 0x44, 0x54, 0xB6,
958
9590x03, 0x80, 0x2A, 0xEA,
9600x17, 0xC1, 0x2B, 0xBD,
961
9620x2D, 0x20,
9630x25, 0x20,
9640x07, 0xC0, 0x44, 0xC6,
965
9660xB3, 0x68,
9670x97, 0x25,
9680x00, 0x80, 0x00, 0xE8,
969
9700x33, 0xC0, 0x33, 0xAF,
9710x3C, 0x27, 0x4F, 0xE9,
972
9730x1F, 0x62, 0x57, 0x9F,
9740x00, 0x80, 0x00, 0xE8,
975
9760x3F, 0x3D, 0x5D, 0x9F,
9770x00, 0xE0,
9780x07, 0x20,
979
9800x00, 0x80, 0x00, 0xE8,
9810x28, 0x19, 0x60, 0xEC,
982
9830xB3, 0x05,
9840x00, 0xE0,
9850x00, 0x80, 0x00, 0xE8,
986
9870x23, 0x3B, 0x33, 0xAD,
9880x00, 0x80, 0x00, 0xE8,
989
9900x1F, 0x26, 0x1F, 0xDF,
9910x9D, 0x1F, 0x4F, 0xE9,
992
9930x00, 0x80, 0x00, 0xE8,
9940x00, 0x80, 0x00, 0xE8,
995
9960x00, 0x80, 0x00, 0xE8,
9970x9E, 0x3F, 0x4F, 0xE9,
998
9990x07, 0x07, 0x1F, 0xAF,
10000x00, 0x80, 0x00, 0xE8,
1001
10020x00, 0x80, 0x00, 0xE8,
10030x00, 0x80, 0x00, 0xE8,
1004
10050x9C, 0x80, 0x4F, 0xE9,
10060x00, 0x80, 0x00, 0xE8,
1007
10080x00, 0x80, 0x00, 0xE8,
10090x57, 0x39, 0x20, 0xE9,
1010
10110x16, 0x28, 0x20, 0xE9,
10120x1D, 0x3B, 0x20, 0xE9,
1013
10140x1E, 0x2B, 0x20, 0xE9,
10150x2B, 0x32, 0x20, 0xE9,
1016
10170x1C, 0x23, 0x20, 0xE9,
10180x57, 0x36, 0x20, 0xE9,
1019
10200x00, 0x80, 0xA0, 0xE9,
10210x40, 0x40, 0xD8, 0xEC,
1022
10230xFF, 0x80, 0xC0, 0xE9,
10240x90, 0xE2,
10250x00, 0xE0,
1026
10270x7A, 0xFF, 0x20, 0xEA,
10280x19, 0xC8, 0xC1, 0xCD,
1029
10300x1F, 0xD7, 0x18, 0xBD,
10310x3F, 0xD7, 0x22, 0xBD,
1032
10330x9F, 0x41, 0x49, 0xBD,
10340x00, 0x80, 0x00, 0xE8,
1035
10360x25, 0x41, 0x49, 0xBD,
10370x2D, 0x41, 0x51, 0xBD,
1038
10390x0D, 0x80, 0x07, 0xEA,
10400x00, 0x80, 0x00, 0xE8,
1041
10420x35, 0x40, 0x48, 0xBD,
10430x3D, 0x40, 0x50, 0xBD,
1044
10450x00, 0x80, 0x00, 0xE8,
10460x25, 0x30,
10470x2D, 0x30,
1048
10490x35, 0x30,
10500xB5, 0x30,
10510xBD, 0x30,
10520x3D, 0x30,
1053
10540x9C, 0xA7, 0x5B, 0x9F,
10550x00, 0x80, 0x00, 0xE8,
1056
10570x00, 0x80, 0x00, 0xE8,
10580x00, 0x80, 0x00, 0xE8,
1059
10600x00, 0x80, 0x00, 0xE8,
10610x00, 0x80, 0x00, 0xE8,
1062
10630x00, 0x80, 0x00, 0xE8,
10640x00, 0x80, 0x00, 0xE8,
1065
10660x00, 0x80, 0x00, 0xE8,
10670x00, 0x80, 0x00, 0xE8,
1068
10690x79, 0xFF, 0x0A, 0xEA,
10700x00, 0x80, 0x00, 0xE8,
1071
10720xC9, 0x41, 0xC8, 0xEC,
10730x42, 0xE1,
10740x00, 0xE0,
1075
10760x77, 0xFF, 0x20, 0xEA,
10770x00, 0x80, 0x00, 0xE8,
1078
10790x00, 0x80, 0x00, 0xE8,
10800x00, 0x80, 0x00, 0xE8,
1081
10820xC8, 0x40, 0xC0, 0xEC,
10830x00, 0x80, 0x00, 0xE8,
1084
10850x74, 0xFF, 0x20, 0xEA,
10860x00, 0x80, 0x00, 0xE8,
1087
10880x00, 0x80, 0x00, 0xE8,
10890x00, 0x80, 0x00, 0xE8,
1090
1091};
1092
1093static unsigned char warp_g200_tgzaf[] = {
1094
10950x00, 0x80, 0x00, 0xE8,
10960x00, 0x80, 0x00, 0xE8,
1097
10980x00, 0x80, 0x00, 0xE8,
10990x00, 0x80, 0x00, 0xE8,
1100
11010x00, 0x80, 0x00, 0xE8,
11020x00, 0x80, 0x00, 0xE8,
1103
11040x00, 0x80, 0x00, 0xE8,
11050x00, 0x80, 0x00, 0xE8,
1106
11070x00, 0x80, 0x00, 0xE8,
11080x00, 0x80, 0x00, 0xE8,
1109
11100x00, 0x80, 0x00, 0xE8,
11110x00, 0x80, 0x00, 0xE8,
1112
11130x00, 0x80, 0x00, 0xE8,
11140x00, 0x80, 0x00, 0xE8,
1115
11160x00, 0x80, 0x00, 0xE8,
11170x00, 0x80, 0x00, 0xE8,
1118
11190x00, 0x80, 0x00, 0xE8,
11200x00, 0x80, 0x00, 0xE8,
1121
11220x00, 0x80, 0x00, 0xE8,
11230x00, 0x80, 0x00, 0xE8,
1124
11250x00, 0x98, 0xA0, 0xE9,
11260x40, 0x40, 0xD8, 0xEC,
1127
11280xFF, 0x80, 0xC0, 0xE9,
11290x00, 0x80, 0x00, 0xE8,
1130
11310x1F, 0xD7, 0x18, 0xBD,
11320x3F, 0xD7, 0x22, 0xBD,
1133
11340x81, 0x04,
11350x89, 0x04,
11360x01, 0x04,
11370x09, 0x04,
1138
11390xC9, 0x41, 0xC0, 0xEC,
11400x11, 0x04,
11410x00, 0xE0,
1142
11430x41, 0xCC, 0x41, 0xCD,
11440x49, 0xCC, 0x49, 0xCD,
1145
11460xD1, 0x41, 0xC0, 0xEC,
11470x51, 0xCC, 0x51, 0xCD,
1148
11490x80, 0x04,
11500x10, 0x04,
11510x08, 0x04,
11520x00, 0xE0,
1153
11540x00, 0xCC, 0xC0, 0xCD,
11550xD1, 0x49, 0xC0, 0xEC,
1156
11570x8A, 0x1F, 0x20, 0xE9,
11580x8B, 0x3F, 0x20, 0xE9,
1159
11600x41, 0x3C, 0x41, 0xAD,
11610x49, 0x3C, 0x49, 0xAD,
1162
11630x10, 0xCC, 0x10, 0xCD,
11640x08, 0xCC, 0x08, 0xCD,
1165
11660xB9, 0x41, 0x49, 0xBB,
11670x1F, 0xF0, 0x41, 0xCD,
1168
11690x51, 0x3C, 0x51, 0xAD,
11700x00, 0x98, 0x80, 0xE9,
1171
11720x83, 0x80, 0x07, 0xEA,
11730x24, 0x1F, 0x20, 0xE9,
1174
11750x21, 0x45, 0x80, 0xE8,
11760x1A, 0x4D, 0x80, 0xE8,
1177
11780x31, 0x55, 0x80, 0xE8,
11790x00, 0x80, 0x00, 0xE8,
1180
11810x15, 0x41, 0x49, 0xBD,
11820x1D, 0x41, 0x51, 0xBD,
1183
11840x2E, 0x41, 0x2A, 0xB8,
11850x34, 0x53, 0xA0, 0xE8,
1186
11870x15, 0x30,
11880x1D, 0x30,
11890x58, 0xE3,
11900x00, 0xE0,
1191
11920xB5, 0x40, 0x48, 0xBD,
11930x3D, 0x40, 0x50, 0xBD,
1194
11950x24, 0x43, 0xA0, 0xE8,
11960x2C, 0x4B, 0xA0, 0xE8,
1197
11980x15, 0x72,
11990x09, 0xE3,
12000x00, 0xE0,
12010x1D, 0x72,
1202
12030x35, 0x30,
12040xB5, 0x30,
12050xBD, 0x30,
12060x3D, 0x30,
1207
12080x9C, 0x97, 0x57, 0x9F,
12090x00, 0x80, 0x00, 0xE8,
1210
12110x6C, 0x64, 0xC8, 0xEC,
12120x98, 0xE1,
12130xB5, 0x05,
1214
12150xBD, 0x05,
12160x2E, 0x30,
12170x32, 0xC0, 0xA0, 0xE8,
1218
12190x33, 0xC0, 0xA0, 0xE8,
12200x74, 0x64, 0xC8, 0xEC,
1221
12220x40, 0x3C, 0x40, 0xAD,
12230x32, 0x6A,
12240x2A, 0x30,
1225
12260x20, 0x73,
12270x33, 0x6A,
12280x00, 0xE0,
12290x28, 0x73,
1230
12310x1C, 0x72,
12320x83, 0xE2,
12330x6F, 0x80, 0x15, 0xEA,
1234
12350xB8, 0x3D, 0x28, 0xDF,
12360x30, 0x35, 0x20, 0xDF,
1237
12380x40, 0x30,
12390x00, 0xE0,
12400xCC, 0xE2,
12410x64, 0x72,
1242
12430x25, 0x42, 0x52, 0xBF,
12440x2D, 0x42, 0x4A, 0xBF,
1245
12460x30, 0x2E, 0x30, 0xDF,
12470x38, 0x2E, 0x38, 0xDF,
1248
12490x18, 0x1D, 0x45, 0xE9,
12500x1E, 0x15, 0x45, 0xE9,
1251
12520x2B, 0x49, 0x51, 0xBD,
12530x00, 0xE0,
12540x1F, 0x73,
1255
12560x38, 0x38, 0x40, 0xAF,
12570x30, 0x30, 0x40, 0xAF,
1258
12590x24, 0x1F, 0x24, 0xDF,
12600x1D, 0x32, 0x20, 0xE9,
1261
12620x2C, 0x1F, 0x2C, 0xDF,
12630x1A, 0x33, 0x20, 0xE9,
1264
12650xB0, 0x10,
12660x08, 0xE3,
12670x40, 0x10,
12680xB8, 0x10,
1269
12700x26, 0xF0, 0x30, 0xCD,
12710x2F, 0xF0, 0x38, 0xCD,
1272
12730x2B, 0x80, 0x20, 0xE9,
12740x2A, 0x80, 0x20, 0xE9,
1275
12760xA6, 0x20,
12770x88, 0xE2,
12780x00, 0xE0,
12790xAF, 0x20,
1280
12810x28, 0x2A, 0x26, 0xAF,
12820x20, 0x2A, 0xC0, 0xAF,
1283
12840x34, 0x1F, 0x34, 0xDF,
12850x46, 0x24, 0x46, 0xDF,
1286
12870x28, 0x30, 0x80, 0xBF,
12880x20, 0x38, 0x80, 0xBF,
1289
12900x47, 0x24, 0x47, 0xDF,
12910x4E, 0x2C, 0x4E, 0xDF,
1292
12930x4F, 0x2C, 0x4F, 0xDF,
12940x56, 0x34, 0x56, 0xDF,
1295
12960x28, 0x15, 0x28, 0xDF,
12970x20, 0x1D, 0x20, 0xDF,
1298
12990x57, 0x34, 0x57, 0xDF,
13000x00, 0xE0,
13010x1D, 0x05,
1302
13030x04, 0x80, 0x10, 0xEA,
13040x89, 0xE2,
13050x2B, 0x30,
1306
13070x3F, 0xC1, 0x1D, 0xBD,
13080x00, 0x80, 0x00, 0xE8,
1309
13100x00, 0x80, 0x00, 0xE8,
13110x00, 0x80, 0x00, 0xE8,
1312
13130xA0, 0x68,
13140xBF, 0x25,
13150x00, 0x80, 0x00, 0xE8,
1316
13170x20, 0xC0, 0x20, 0xAF,
13180x28, 0x05,
13190x97, 0x74,
1320
13210x00, 0xE0,
13220x2A, 0x10,
13230x16, 0xC0, 0x20, 0xE9,
1324
13250x04, 0x80, 0x10, 0xEA,
13260x8C, 0xE2,
13270x95, 0x05,
1328
13290x28, 0xC1, 0x28, 0xAD,
13300x1F, 0xC1, 0x15, 0xBD,
1331
13320x00, 0x80, 0x00, 0xE8,
13330x00, 0x80, 0x00, 0xE8,
1334
13350xA8, 0x67,
13360x9F, 0x6B,
13370x00, 0x80, 0x00, 0xE8,
1338
13390x28, 0xC0, 0x28, 0xAD,
13400x1D, 0x25,
13410x20, 0x05,
1342
13430x28, 0x32, 0x80, 0xAD,
13440x40, 0x2A, 0x40, 0xBD,
1345
13460x1C, 0x80, 0x20, 0xE9,
13470x20, 0x33, 0x20, 0xAD,
1348
13490x20, 0x73,
13500x00, 0xE0,
13510xB6, 0x49, 0x51, 0xBB,
1352
13530x26, 0x2F, 0xB0, 0xE8,
13540x19, 0x20, 0x20, 0xE9,
1355
13560x35, 0x20, 0x35, 0xDF,
13570x3D, 0x20, 0x3D, 0xDF,
1358
13590x15, 0x20, 0x15, 0xDF,
13600x1D, 0x20, 0x1D, 0xDF,
1361
13620x26, 0xD0, 0x26, 0xCD,
13630x29, 0x49, 0x2A, 0xB8,
1364
13650x26, 0x40, 0x80, 0xBD,
13660x3B, 0x48, 0x50, 0xBD,
1367
13680x3E, 0x54, 0x57, 0x9F,
13690x00, 0xE0,
13700x82, 0xE1,
1371
13720x1E, 0xAF, 0x59, 0x9F,
13730x00, 0x80, 0x00, 0xE8,
1374
13750x26, 0x30,
13760x29, 0x30,
13770x48, 0x3C, 0x48, 0xAD,
1378
13790x2B, 0x72,
13800xC2, 0xE1,
13810x2C, 0xC0, 0x44, 0xC2,
1382
13830x05, 0x24, 0x34, 0xBF,
13840x0D, 0x24, 0x2C, 0xBF,
1385
13860x2D, 0x46, 0x4E, 0xBF,
13870x25, 0x46, 0x56, 0xBF,
1388
13890x20, 0x1D, 0x6F, 0x8F,
13900x32, 0x3E, 0x5F, 0xE9,
1391
13920x3E, 0x50, 0x56, 0x9F,
13930x00, 0xE0,
13940x3B, 0x30,
1395
13960x1E, 0x8F, 0x51, 0x9F,
13970x33, 0x1E, 0x5F, 0xE9,
1398
13990x05, 0x44, 0x54, 0xB2,
14000x0D, 0x44, 0x4C, 0xB2,
1401
14020x19, 0xC0, 0xB0, 0xE8,
14030x34, 0xC0, 0x44, 0xC4,
1404
14050x33, 0x73,
14060x00, 0xE0,
14070x3E, 0x62, 0x57, 0x9F,
1408
14090x1E, 0xAF, 0x59, 0x9F,
14100x00, 0xE0,
14110x0D, 0x20,
1412
14130x84, 0x3E, 0x58, 0xE9,
14140x28, 0x1D, 0x6F, 0x8F,
1415
14160x05, 0x20,
14170x00, 0xE0,
14180x85, 0x1E, 0x58, 0xE9,
1419
14200x9B, 0x3B, 0x33, 0xDF,
14210x20, 0x20, 0x42, 0xAF,
1422
14230x30, 0x42, 0x56, 0x9F,
14240x80, 0x3E, 0x57, 0xE9,
1425
14260x3F, 0x8F, 0x51, 0x9F,
14270x30, 0x80, 0x5F, 0xE9,
1428
14290x28, 0x28, 0x24, 0xAF,
14300x81, 0x1E, 0x57, 0xE9,
1431
14320x05, 0x47, 0x57, 0xBF,
14330x0D, 0x47, 0x4F, 0xBF,
1434
14350x88, 0x80, 0x58, 0xE9,
14360x1B, 0x29, 0x1B, 0xDF,
1437
14380x30, 0x1D, 0x6F, 0x8F,
14390x3A, 0x30, 0x4F, 0xE9,
1440
14410x1C, 0x30, 0x26, 0xDF,
14420x09, 0xE3,
14430x3B, 0x05,
1444
14450x3E, 0x50, 0x56, 0x9F,
14460x3B, 0x3F, 0x4F, 0xE9,
1447
14480x1E, 0x8F, 0x51, 0x9F,
14490x00, 0xE0,
14500xAC, 0x20,
1451
14520x2D, 0x44, 0x4C, 0xB4,
14530x2C, 0x1C, 0xC0, 0xAF,
1454
14550x25, 0x44, 0x54, 0xB4,
14560x00, 0xE0,
14570xC8, 0x30,
1458
14590x30, 0x46, 0x30, 0xAF,
14600x1B, 0x1B, 0x48, 0xAF,
1461
14620x00, 0xE0,
14630x25, 0x20,
14640x38, 0x2C, 0x4F, 0xE9,
1465
14660x86, 0x80, 0x57, 0xE9,
14670x38, 0x1D, 0x6F, 0x8F,
1468
14690x28, 0x74,
14700x00, 0xE0,
14710x0D, 0x44, 0x4C, 0xB0,
1472
14730x05, 0x44, 0x54, 0xB0,
14740x2D, 0x20,
14750x9B, 0x10,
1476
14770x82, 0x3E, 0x57, 0xE9,
14780x32, 0xF0, 0x1B, 0xCD,
1479
14800x1E, 0xBD, 0x59, 0x9F,
14810x83, 0x1E, 0x57, 0xE9,
1482
14830x38, 0x47, 0x38, 0xAF,
14840x34, 0x20,
14850x2A, 0x30,
1486
14870x00, 0xE0,
14880x0D, 0x20,
14890x32, 0x20,
14900x05, 0x20,
1491
14920x87, 0x80, 0x57, 0xE9,
14930x1F, 0x54, 0x57, 0x9F,
1494
14950x17, 0x42, 0x56, 0x9F,
14960x00, 0xE0,
14970x3B, 0x6A,
1498
14990x3F, 0x8F, 0x51, 0x9F,
15000x37, 0x1E, 0x4F, 0xE9,
1501
15020x37, 0x32, 0x2A, 0xAF,
15030x00, 0xE0,
15040x32, 0x00,
1505
15060x00, 0x80, 0x00, 0xE8,
15070x27, 0xC0, 0x44, 0xC0,
1508
15090x36, 0x1F, 0x4F, 0xE9,
15100x1F, 0x1F, 0x26, 0xDF,
1511
15120x37, 0x1B, 0x37, 0xBF,
15130x17, 0x26, 0x17, 0xDF,
1514
15150x3E, 0x17, 0x4F, 0xE9,
15160x3F, 0x3F, 0x4F, 0xE9,
1517
15180x34, 0x1F, 0x34, 0xAF,
15190x2B, 0x05,
15200xA7, 0x20,
1521
15220x33, 0x2B, 0x37, 0xDF,
15230x27, 0x17, 0xC0, 0xAF,
1524
15250x34, 0x80, 0x4F, 0xE9,
15260x00, 0x80, 0x00, 0xE8,
1527
15280x0D, 0x21, 0x1A, 0xB6,
15290x05, 0x21, 0x31, 0xB6,
1530
15310x2D, 0x44, 0x4C, 0xB6,
15320x25, 0x44, 0x54, 0xB6,
1533
15340x03, 0x80, 0x2A, 0xEA,
15350x17, 0xC1, 0x2B, 0xBD,
1536
15370x0D, 0x20,
15380x05, 0x20,
15390x2F, 0xC0, 0x21, 0xC6,
1540
15410xB3, 0x68,
15420x97, 0x25,
15430x00, 0x80, 0x00, 0xE8,
1544
15450x33, 0xC0, 0x33, 0xAF,
15460x3C, 0x27, 0x4F, 0xE9,
1547
15480x00, 0xE0,
15490x25, 0x20,
15500x07, 0xC0, 0x44, 0xC6,
1551
15520x17, 0x50, 0x56, 0x9F,
15530x00, 0xE0,
15540x2D, 0x20,
1555
15560x37, 0x0F, 0x5C, 0x9F,
15570x00, 0xE0,
15580x2F, 0x20,
1559
15600x1F, 0x62, 0x57, 0x9F,
15610x00, 0xE0,
15620x07, 0x20,
1563
15640x3F, 0x3D, 0x5D, 0x9F,
15650x00, 0x80, 0x00, 0xE8,
1566
15670x00, 0x80, 0x00, 0xE8,
15680x28, 0x19, 0x60, 0xEC,
1569
15700xB3, 0x05,
15710x00, 0xE0,
15720x17, 0x26, 0x17, 0xDF,
1573
15740x23, 0x3B, 0x33, 0xAD,
15750x35, 0x17, 0x4F, 0xE9,
1576
15770x1F, 0x26, 0x1F, 0xDF,
15780x9D, 0x1F, 0x4F, 0xE9,
1579
15800x9E, 0x3F, 0x4F, 0xE9,
15810x39, 0x37, 0x4F, 0xE9,
1582
15830x2F, 0x2F, 0x17, 0xAF,
15840x00, 0x80, 0x00, 0xE8,
1585
15860x07, 0x07, 0x1F, 0xAF,
15870x00, 0x80, 0x00, 0xE8,
1588
15890x31, 0x80, 0x4F, 0xE9,
15900x00, 0x80, 0x00, 0xE8,
1591
15920x9C, 0x80, 0x4F, 0xE9,
15930x00, 0x80, 0x00, 0xE8,
1594
15950x00, 0x80, 0x00, 0xE8,
15960x57, 0x39, 0x20, 0xE9,
1597
15980x16, 0x28, 0x20, 0xE9,
15990x1D, 0x3B, 0x20, 0xE9,
1600
16010x1E, 0x2B, 0x20, 0xE9,
16020x2B, 0x32, 0x20, 0xE9,
1603
16040x1C, 0x23, 0x20, 0xE9,
16050x57, 0x36, 0x20, 0xE9,
1606
16070x00, 0x80, 0xA0, 0xE9,
16080x40, 0x40, 0xD8, 0xEC,
1609
16100xFF, 0x80, 0xC0, 0xE9,
16110x90, 0xE2,
16120x00, 0xE0,
1613
16140x74, 0xFF, 0x20, 0xEA,
16150x19, 0xC8, 0xC1, 0xCD,
1616
16170x1F, 0xD7, 0x18, 0xBD,
16180x3F, 0xD7, 0x22, 0xBD,
1619
16200x9F, 0x41, 0x49, 0xBD,
16210x00, 0x80, 0x00, 0xE8,
1622
16230x25, 0x41, 0x49, 0xBD,
16240x2D, 0x41, 0x51, 0xBD,
1625
16260x0D, 0x80, 0x07, 0xEA,
16270x00, 0x80, 0x00, 0xE8,
1628
16290x35, 0x40, 0x48, 0xBD,
16300x3D, 0x40, 0x50, 0xBD,
1631
16320x00, 0x80, 0x00, 0xE8,
16330x25, 0x30,
16340x2D, 0x30,
1635
16360x35, 0x30,
16370xB5, 0x30,
16380xBD, 0x30,
16390x3D, 0x30,
1640
16410x9C, 0xA7, 0x5B, 0x9F,
16420x00, 0x80, 0x00, 0xE8,
1643
16440x00, 0x80, 0x00, 0xE8,
16450x00, 0x80, 0x00, 0xE8,
1646
16470x00, 0x80, 0x00, 0xE8,
16480x00, 0x80, 0x00, 0xE8,
1649
16500x00, 0x80, 0x00, 0xE8,
16510x00, 0x80, 0x00, 0xE8,
1652
16530x00, 0x80, 0x00, 0xE8,
16540x00, 0x80, 0x00, 0xE8,
1655
16560x73, 0xFF, 0x0A, 0xEA,
16570x00, 0x80, 0x00, 0xE8,
1658
16590xC9, 0x41, 0xC8, 0xEC,
16600x42, 0xE1,
16610x00, 0xE0,
1662
16630x71, 0xFF, 0x20, 0xEA,
16640x00, 0x80, 0x00, 0xE8,
1665
16660x00, 0x80, 0x00, 0xE8,
16670x00, 0x80, 0x00, 0xE8,
1668
16690xC8, 0x40, 0xC0, 0xEC,
16700x00, 0x80, 0x00, 0xE8,
1671
16720x6E, 0xFF, 0x20, 0xEA,
16730x00, 0x80, 0x00, 0xE8,
1674
16750x00, 0x80, 0x00, 0xE8,
16760x00, 0x80, 0x00, 0xE8,
1677
1678};
1679
1680static unsigned char warp_g200_tgzf[] = {
1681
16820x00, 0x80, 0x00, 0xE8,
16830x00, 0x80, 0x00, 0xE8,
1684
16850x00, 0x80, 0x00, 0xE8,
16860x00, 0x80, 0x00, 0xE8,
1687
16880x00, 0x80, 0x00, 0xE8,
16890x00, 0x80, 0x00, 0xE8,
1690
16910x00, 0x80, 0x00, 0xE8,
16920x00, 0x80, 0x00, 0xE8,
1693
16940x00, 0x80, 0x00, 0xE8,
16950x00, 0x80, 0x00, 0xE8,
1696
16970x00, 0x80, 0x00, 0xE8,
16980x00, 0x80, 0x00, 0xE8,
1699
17000x00, 0x80, 0x00, 0xE8,
17010x00, 0x80, 0x00, 0xE8,
1702
17030x00, 0x80, 0x00, 0xE8,
17040x00, 0x80, 0x00, 0xE8,
1705
17060x00, 0x80, 0x00, 0xE8,
17070x00, 0x80, 0x00, 0xE8,
1708
17090x00, 0x80, 0x00, 0xE8,
17100x00, 0x80, 0x00, 0xE8,
1711
17120x00, 0x98, 0xA0, 0xE9,
17130x40, 0x40, 0xD8, 0xEC,
1714
17150xFF, 0x80, 0xC0, 0xE9,
17160x00, 0x80, 0x00, 0xE8,
1717
17180x1F, 0xD7, 0x18, 0xBD,
17190x3F, 0xD7, 0x22, 0xBD,
1720
17210x81, 0x04,
17220x89, 0x04,
17230x01, 0x04,
17240x09, 0x04,
1725
17260xC9, 0x41, 0xC0, 0xEC,
17270x11, 0x04,
17280x00, 0xE0,
1729
17300x41, 0xCC, 0x41, 0xCD,
17310x49, 0xCC, 0x49, 0xCD,
1732
17330xD1, 0x41, 0xC0, 0xEC,
17340x51, 0xCC, 0x51, 0xCD,
1735
17360x80, 0x04,
17370x10, 0x04,
17380x08, 0x04,
17390x00, 0xE0,
1740
17410x00, 0xCC, 0xC0, 0xCD,
17420xD1, 0x49, 0xC0, 0xEC,
1743
17440x8A, 0x1F, 0x20, 0xE9,
17450x8B, 0x3F, 0x20, 0xE9,
1746
17470x41, 0x3C, 0x41, 0xAD,
17480x49, 0x3C, 0x49, 0xAD,
1749
17500x10, 0xCC, 0x10, 0xCD,
17510x08, 0xCC, 0x08, 0xCD,
1752
17530xB9, 0x41, 0x49, 0xBB,
17540x1F, 0xF0, 0x41, 0xCD,
1755
17560x51, 0x3C, 0x51, 0xAD,
17570x00, 0x98, 0x80, 0xE9,
1758
17590x7F, 0x80, 0x07, 0xEA,
17600x24, 0x1F, 0x20, 0xE9,
1761
17620x21, 0x45, 0x80, 0xE8,
17630x1A, 0x4D, 0x80, 0xE8,
1764
17650x31, 0x55, 0x80, 0xE8,
17660x00, 0x80, 0x00, 0xE8,
1767
17680x15, 0x41, 0x49, 0xBD,
17690x1D, 0x41, 0x51, 0xBD,
1770
17710x2E, 0x41, 0x2A, 0xB8,
17720x34, 0x53, 0xA0, 0xE8,
1773
17740x15, 0x30,
17750x1D, 0x30,
17760x58, 0xE3,
17770x00, 0xE0,
1778
17790xB5, 0x40, 0x48, 0xBD,
17800x3D, 0x40, 0x50, 0xBD,
1781
17820x24, 0x43, 0xA0, 0xE8,
17830x2C, 0x4B, 0xA0, 0xE8,
1784
17850x15, 0x72,
17860x09, 0xE3,
17870x00, 0xE0,
17880x1D, 0x72,
1789
17900x35, 0x30,
17910xB5, 0x30,
17920xBD, 0x30,
17930x3D, 0x30,
1794
17950x9C, 0x97, 0x57, 0x9F,
17960x00, 0x80, 0x00, 0xE8,
1797
17980x6C, 0x64, 0xC8, 0xEC,
17990x98, 0xE1,
18000xB5, 0x05,
1801
18020xBD, 0x05,
18030x2E, 0x30,
18040x32, 0xC0, 0xA0, 0xE8,
1805
18060x33, 0xC0, 0xA0, 0xE8,
18070x74, 0x64, 0xC8, 0xEC,
1808
18090x40, 0x3C, 0x40, 0xAD,
18100x32, 0x6A,
18110x2A, 0x30,
1812
18130x20, 0x73,
18140x33, 0x6A,
18150x00, 0xE0,
18160x28, 0x73,
1817
18180x1C, 0x72,
18190x83, 0xE2,
18200x6B, 0x80, 0x15, 0xEA,
1821
18220xB8, 0x3D, 0x28, 0xDF,
18230x30, 0x35, 0x20, 0xDF,
1824
18250x40, 0x30,
18260x00, 0xE0,
18270xCC, 0xE2,
18280x64, 0x72,
1829
18300x25, 0x42, 0x52, 0xBF,
18310x2D, 0x42, 0x4A, 0xBF,
1832
18330x30, 0x2E, 0x30, 0xDF,
18340x38, 0x2E, 0x38, 0xDF,
1835
18360x18, 0x1D, 0x45, 0xE9,
18370x1E, 0x15, 0x45, 0xE9,
1838
18390x2B, 0x49, 0x51, 0xBD,
18400x00, 0xE0,
18410x1F, 0x73,
1842
18430x38, 0x38, 0x40, 0xAF,
18440x30, 0x30, 0x40, 0xAF,
1845
18460x24, 0x1F, 0x24, 0xDF,
18470x1D, 0x32, 0x20, 0xE9,
1848
18490x2C, 0x1F, 0x2C, 0xDF,
18500x1A, 0x33, 0x20, 0xE9,
1851
18520xB0, 0x10,
18530x08, 0xE3,
18540x40, 0x10,
18550xB8, 0x10,
1856
18570x26, 0xF0, 0x30, 0xCD,
18580x2F, 0xF0, 0x38, 0xCD,
1859
18600x2B, 0x80, 0x20, 0xE9,
18610x2A, 0x80, 0x20, 0xE9,
1862
18630xA6, 0x20,
18640x88, 0xE2,
18650x00, 0xE0,
18660xAF, 0x20,
1867
18680x28, 0x2A, 0x26, 0xAF,
18690x20, 0x2A, 0xC0, 0xAF,
1870
18710x34, 0x1F, 0x34, 0xDF,
18720x46, 0x24, 0x46, 0xDF,
1873
18740x28, 0x30, 0x80, 0xBF,
18750x20, 0x38, 0x80, 0xBF,
1876
18770x47, 0x24, 0x47, 0xDF,
18780x4E, 0x2C, 0x4E, 0xDF,
1879
18800x4F, 0x2C, 0x4F, 0xDF,
18810x56, 0x34, 0x56, 0xDF,
1882
18830x28, 0x15, 0x28, 0xDF,
18840x20, 0x1D, 0x20, 0xDF,
1885
18860x57, 0x34, 0x57, 0xDF,
18870x00, 0xE0,
18880x1D, 0x05,
1889
18900x04, 0x80, 0x10, 0xEA,
18910x89, 0xE2,
18920x2B, 0x30,
1893
18940x3F, 0xC1, 0x1D, 0xBD,
18950x00, 0x80, 0x00, 0xE8,
1896
18970x00, 0x80, 0x00, 0xE8,
18980x00, 0x80, 0x00, 0xE8,
1899
19000xA0, 0x68,
19010xBF, 0x25,
19020x00, 0x80, 0x00, 0xE8,
1903
19040x20, 0xC0, 0x20, 0xAF,
19050x28, 0x05,
19060x97, 0x74,
1907
19080x00, 0xE0,
19090x2A, 0x10,
19100x16, 0xC0, 0x20, 0xE9,
1911
19120x04, 0x80, 0x10, 0xEA,
19130x8C, 0xE2,
19140x95, 0x05,
1915
19160x28, 0xC1, 0x28, 0xAD,
19170x1F, 0xC1, 0x15, 0xBD,
1918
19190x00, 0x80, 0x00, 0xE8,
19200x00, 0x80, 0x00, 0xE8,
1921
19220xA8, 0x67,
19230x9F, 0x6B,
19240x00, 0x80, 0x00, 0xE8,
1925
19260x28, 0xC0, 0x28, 0xAD,
19270x1D, 0x25,
19280x20, 0x05,
1929
19300x28, 0x32, 0x80, 0xAD,
19310x40, 0x2A, 0x40, 0xBD,
1932
19330x1C, 0x80, 0x20, 0xE9,
19340x20, 0x33, 0x20, 0xAD,
1935
19360x20, 0x73,
19370x00, 0xE0,
19380xB6, 0x49, 0x51, 0xBB,
1939
19400x26, 0x2F, 0xB0, 0xE8,
19410x19, 0x20, 0x20, 0xE9,
1942
19430x35, 0x20, 0x35, 0xDF,
19440x3D, 0x20, 0x3D, 0xDF,
1945
19460x15, 0x20, 0x15, 0xDF,
19470x1D, 0x20, 0x1D, 0xDF,
1948
19490x26, 0xD0, 0x26, 0xCD,
19500x29, 0x49, 0x2A, 0xB8,
1951
19520x26, 0x40, 0x80, 0xBD,
19530x3B, 0x48, 0x50, 0xBD,
1954
19550x3E, 0x54, 0x57, 0x9F,
19560x00, 0xE0,
19570x82, 0xE1,
1958
19590x1E, 0xAF, 0x59, 0x9F,
19600x00, 0x80, 0x00, 0xE8,
1961
19620x26, 0x30,
19630x29, 0x30,
19640x48, 0x3C, 0x48, 0xAD,
1965
19660x2B, 0x72,
19670xC2, 0xE1,
19680x2C, 0xC0, 0x44, 0xC2,
1969
19700x05, 0x24, 0x34, 0xBF,
19710x0D, 0x24, 0x2C, 0xBF,
1972
19730x2D, 0x46, 0x4E, 0xBF,
19740x25, 0x46, 0x56, 0xBF,
1975
19760x20, 0x1D, 0x6F, 0x8F,
19770x32, 0x3E, 0x5F, 0xE9,
1978
19790x3E, 0x50, 0x56, 0x9F,
19800x00, 0xE0,
19810x3B, 0x30,
1982
19830x1E, 0x8F, 0x51, 0x9F,
19840x33, 0x1E, 0x5F, 0xE9,
1985
19860x05, 0x44, 0x54, 0xB2,
19870x0D, 0x44, 0x4C, 0xB2,
1988
19890x19, 0xC0, 0xB0, 0xE8,
19900x34, 0xC0, 0x44, 0xC4,
1991
19920x33, 0x73,
19930x00, 0xE0,
19940x3E, 0x62, 0x57, 0x9F,
1995
19960x1E, 0xAF, 0x59, 0x9F,
19970x00, 0xE0,
19980x0D, 0x20,
1999
20000x84, 0x3E, 0x58, 0xE9,
20010x28, 0x1D, 0x6F, 0x8F,
2002
20030x05, 0x20,
20040x00, 0xE0,
20050x85, 0x1E, 0x58, 0xE9,
2006
20070x9B, 0x3B, 0x33, 0xDF,
20080x20, 0x20, 0x42, 0xAF,
2009
20100x30, 0x42, 0x56, 0x9F,
20110x80, 0x3E, 0x57, 0xE9,
2012
20130x3F, 0x8F, 0x51, 0x9F,
20140x30, 0x80, 0x5F, 0xE9,
2015
20160x28, 0x28, 0x24, 0xAF,
20170x81, 0x1E, 0x57, 0xE9,
2018
20190x05, 0x47, 0x57, 0xBF,
20200x0D, 0x47, 0x4F, 0xBF,
2021
20220x88, 0x80, 0x58, 0xE9,
20230x1B, 0x29, 0x1B, 0xDF,
2024
20250x30, 0x1D, 0x6F, 0x8F,
20260x3A, 0x30, 0x4F, 0xE9,
2027
20280x1C, 0x30, 0x26, 0xDF,
20290x09, 0xE3,
20300x3B, 0x05,
2031
20320x3E, 0x50, 0x56, 0x9F,
20330x3B, 0x3F, 0x4F, 0xE9,
2034
20350x1E, 0x8F, 0x51, 0x9F,
20360x00, 0xE0,
20370xAC, 0x20,
2038
20390x2D, 0x44, 0x4C, 0xB4,
20400x2C, 0x1C, 0xC0, 0xAF,
2041
20420x25, 0x44, 0x54, 0xB4,
20430x00, 0xE0,
20440xC8, 0x30,
2045
20460x30, 0x46, 0x30, 0xAF,
20470x1B, 0x1B, 0x48, 0xAF,
2048
20490x00, 0xE0,
20500x25, 0x20,
20510x38, 0x2C, 0x4F, 0xE9,
2052
20530x86, 0x80, 0x57, 0xE9,
20540x38, 0x1D, 0x6F, 0x8F,
2055
20560x28, 0x74,
20570x00, 0xE0,
20580x0D, 0x44, 0x4C, 0xB0,
2059
20600x05, 0x44, 0x54, 0xB0,
20610x2D, 0x20,
20620x9B, 0x10,
2063
20640x82, 0x3E, 0x57, 0xE9,
20650x32, 0xF0, 0x1B, 0xCD,
2066
20670x1E, 0xBD, 0x59, 0x9F,
20680x83, 0x1E, 0x57, 0xE9,
2069
20700x38, 0x47, 0x38, 0xAF,
20710x34, 0x20,
20720x2A, 0x30,
2073
20740x00, 0xE0,
20750x0D, 0x20,
20760x32, 0x20,
20770x05, 0x20,
2078
20790x87, 0x80, 0x57, 0xE9,
20800x1F, 0x54, 0x57, 0x9F,
2081
20820x17, 0x42, 0x56, 0x9F,
20830x00, 0xE0,
20840x3B, 0x6A,
2085
20860x3F, 0x8F, 0x51, 0x9F,
20870x37, 0x1E, 0x4F, 0xE9,
2088
20890x37, 0x32, 0x2A, 0xAF,
20900x00, 0xE0,
20910x32, 0x00,
2092
20930x00, 0x80, 0x00, 0xE8,
20940x27, 0xC0, 0x44, 0xC0,
2095
20960x36, 0x1F, 0x4F, 0xE9,
20970x1F, 0x1F, 0x26, 0xDF,
2098
20990x37, 0x1B, 0x37, 0xBF,
21000x17, 0x26, 0x17, 0xDF,
2101
21020x3E, 0x17, 0x4F, 0xE9,
21030x3F, 0x3F, 0x4F, 0xE9,
2104
21050x34, 0x1F, 0x34, 0xAF,
21060x2B, 0x05,
21070xA7, 0x20,
2108
21090x33, 0x2B, 0x37, 0xDF,
21100x27, 0x17, 0xC0, 0xAF,
2111
21120x34, 0x80, 0x4F, 0xE9,
21130x00, 0x80, 0x00, 0xE8,
2114
21150x0D, 0x21, 0x1A, 0xB6,
21160x05, 0x21, 0x31, 0xB6,
2117
21180x03, 0x80, 0x2A, 0xEA,
21190x17, 0xC1, 0x2B, 0xBD,
2120
21210x0D, 0x20,
21220x05, 0x20,
21230x2F, 0xC0, 0x21, 0xC6,
2124
21250xB3, 0x68,
21260x97, 0x25,
21270x00, 0x80, 0x00, 0xE8,
2128
21290x33, 0xC0, 0x33, 0xAF,
21300x3C, 0x27, 0x4F, 0xE9,
2131
21320x17, 0x50, 0x56, 0x9F,
21330x00, 0x80, 0x00, 0xE8,
2134
21350x37, 0x0F, 0x5C, 0x9F,
21360x00, 0xE0,
21370x2F, 0x20,
2138
21390x00, 0x80, 0x00, 0xE8,
21400x28, 0x19, 0x60, 0xEC,
2141
21420xB3, 0x05,
21430x00, 0xE0,
21440x00, 0x80, 0x00, 0xE8,
2145
21460x23, 0x3B, 0x33, 0xAD,
21470x00, 0x80, 0x00, 0xE8,
2148
21490x17, 0x26, 0x17, 0xDF,
21500x35, 0x17, 0x4F, 0xE9,
2151
21520x00, 0x80, 0x00, 0xE8,
21530x00, 0x80, 0x00, 0xE8,
2154
21550x00, 0x80, 0x00, 0xE8,
21560x39, 0x37, 0x4F, 0xE9,
2157
21580x2F, 0x2F, 0x17, 0xAF,
21590x00, 0x80, 0x00, 0xE8,
2160
21610x00, 0x80, 0x00, 0xE8,
21620x00, 0x80, 0x00, 0xE8,
2163
21640x31, 0x80, 0x4F, 0xE9,
21650x00, 0x80, 0x00, 0xE8,
2166
21670x00, 0x80, 0x00, 0xE8,
21680x57, 0x39, 0x20, 0xE9,
2169
21700x16, 0x28, 0x20, 0xE9,
21710x1D, 0x3B, 0x20, 0xE9,
2172
21730x1E, 0x2B, 0x20, 0xE9,
21740x2B, 0x32, 0x20, 0xE9,
2175
21760x1C, 0x23, 0x20, 0xE9,
21770x57, 0x36, 0x20, 0xE9,
2178
21790x00, 0x80, 0xA0, 0xE9,
21800x40, 0x40, 0xD8, 0xEC,
2181
21820xFF, 0x80, 0xC0, 0xE9,
21830x90, 0xE2,
21840x00, 0xE0,
2185
21860x78, 0xFF, 0x20, 0xEA,
21870x19, 0xC8, 0xC1, 0xCD,
2188
21890x1F, 0xD7, 0x18, 0xBD,
21900x3F, 0xD7, 0x22, 0xBD,
2191
21920x9F, 0x41, 0x49, 0xBD,
21930x00, 0x80, 0x00, 0xE8,
2194
21950x25, 0x41, 0x49, 0xBD,
21960x2D, 0x41, 0x51, 0xBD,
2197
21980x0D, 0x80, 0x07, 0xEA,
21990x00, 0x80, 0x00, 0xE8,
2200
22010x35, 0x40, 0x48, 0xBD,
22020x3D, 0x40, 0x50, 0xBD,
2203
22040x00, 0x80, 0x00, 0xE8,
22050x25, 0x30,
22060x2D, 0x30,
2207
22080x35, 0x30,
22090xB5, 0x30,
22100xBD, 0x30,
22110x3D, 0x30,
2212
22130x9C, 0xA7, 0x5B, 0x9F,
22140x00, 0x80, 0x00, 0xE8,
2215
22160x00, 0x80, 0x00, 0xE8,
22170x00, 0x80, 0x00, 0xE8,
2218
22190x00, 0x80, 0x00, 0xE8,
22200x00, 0x80, 0x00, 0xE8,
2221
22220x00, 0x80, 0x00, 0xE8,
22230x00, 0x80, 0x00, 0xE8,
2224
22250x00, 0x80, 0x00, 0xE8,
22260x00, 0x80, 0x00, 0xE8,
2227
22280x77, 0xFF, 0x0A, 0xEA,
22290x00, 0x80, 0x00, 0xE8,
2230
22310xC9, 0x41, 0xC8, 0xEC,
22320x42, 0xE1,
22330x00, 0xE0,
2234
22350x75, 0xFF, 0x20, 0xEA,
22360x00, 0x80, 0x00, 0xE8,
2237
22380x00, 0x80, 0x00, 0xE8,
22390x00, 0x80, 0x00, 0xE8,
2240
22410xC8, 0x40, 0xC0, 0xEC,
22420x00, 0x80, 0x00, 0xE8,
2243
22440x72, 0xFF, 0x20, 0xEA,
22450x00, 0x80, 0x00, 0xE8,
2246
22470x00, 0x80, 0x00, 0xE8,
22480x00, 0x80, 0x00, 0xE8,
2249
2250};
2251
2252static unsigned char warp_g200_tgzs[] = {
2253
22540x00, 0x80, 0x00, 0xE8,
22550x00, 0x80, 0x00, 0xE8,
2256
22570x00, 0x80, 0x00, 0xE8,
22580x00, 0x80, 0x00, 0xE8,
2259
22600x00, 0x80, 0x00, 0xE8,
22610x00, 0x80, 0x00, 0xE8,
2262
22630x00, 0x80, 0x00, 0xE8,
22640x00, 0x80, 0x00, 0xE8,
2265
22660x00, 0x80, 0x00, 0xE8,
22670x00, 0x80, 0x00, 0xE8,
2268
22690x00, 0x80, 0x00, 0xE8,
22700x00, 0x80, 0x00, 0xE8,
2271
22720x00, 0x80, 0x00, 0xE8,
22730x00, 0x80, 0x00, 0xE8,
2274
22750x00, 0x80, 0x00, 0xE8,
22760x00, 0x80, 0x00, 0xE8,
2277
22780x00, 0x80, 0x00, 0xE8,
22790x00, 0x80, 0x00, 0xE8,
2280
22810x00, 0x80, 0x00, 0xE8,
22820x00, 0x80, 0x00, 0xE8,
2283
22840x00, 0x80, 0x00, 0xE8,
22850x00, 0x80, 0x00, 0xE8,
2286
22870x00, 0x80, 0x00, 0xE8,
22880x00, 0x80, 0x00, 0xE8,
2289
22900x00, 0x80, 0x00, 0xE8,
22910x00, 0x80, 0x00, 0xE8,
2292
22930x00, 0x98, 0xA0, 0xE9,
22940x40, 0x40, 0xD8, 0xEC,
2295
22960xFF, 0x80, 0xC0, 0xE9,
22970x00, 0x80, 0x00, 0xE8,
2298
22990x1F, 0xD7, 0x18, 0xBD,
23000x3F, 0xD7, 0x22, 0xBD,
2301
23020x81, 0x04,
23030x89, 0x04,
23040x01, 0x04,
23050x09, 0x04,
2306
23070xC9, 0x41, 0xC0, 0xEC,
23080x11, 0x04,
23090x00, 0xE0,
2310
23110x41, 0xCC, 0x41, 0xCD,
23120x49, 0xCC, 0x49, 0xCD,
2313
23140xD1, 0x41, 0xC0, 0xEC,
23150x51, 0xCC, 0x51, 0xCD,
2316
23170x80, 0x04,
23180x10, 0x04,
23190x08, 0x04,
23200x00, 0xE0,
2321
23220x00, 0xCC, 0xC0, 0xCD,
23230xD1, 0x49, 0xC0, 0xEC,
2324
23250x8A, 0x1F, 0x20, 0xE9,
23260x8B, 0x3F, 0x20, 0xE9,
2327
23280x41, 0x3C, 0x41, 0xAD,
23290x49, 0x3C, 0x49, 0xAD,
2330
23310x10, 0xCC, 0x10, 0xCD,
23320x08, 0xCC, 0x08, 0xCD,
2333
23340xB9, 0x41, 0x49, 0xBB,
23350x1F, 0xF0, 0x41, 0xCD,
2336
23370x51, 0x3C, 0x51, 0xAD,
23380x00, 0x98, 0x80, 0xE9,
2339
23400x8B, 0x80, 0x07, 0xEA,
23410x24, 0x1F, 0x20, 0xE9,
2342
23430x21, 0x45, 0x80, 0xE8,
23440x1A, 0x4D, 0x80, 0xE8,
2345
23460x31, 0x55, 0x80, 0xE8,
23470x00, 0x80, 0x00, 0xE8,
2348
23490x15, 0x41, 0x49, 0xBD,
23500x1D, 0x41, 0x51, 0xBD,
2351
23520x2E, 0x41, 0x2A, 0xB8,
23530x34, 0x53, 0xA0, 0xE8,
2354
23550x15, 0x30,
23560x1D, 0x30,
23570x58, 0xE3,
23580x00, 0xE0,
2359
23600xB5, 0x40, 0x48, 0xBD,
23610x3D, 0x40, 0x50, 0xBD,
2362
23630x24, 0x43, 0xA0, 0xE8,
23640x2C, 0x4B, 0xA0, 0xE8,
2365
23660x15, 0x72,
23670x09, 0xE3,
23680x00, 0xE0,
23690x1D, 0x72,
2370
23710x35, 0x30,
23720xB5, 0x30,
23730xBD, 0x30,
23740x3D, 0x30,
2375
23760x9C, 0x97, 0x57, 0x9F,
23770x00, 0x80, 0x00, 0xE8,
2378
23790x6C, 0x64, 0xC8, 0xEC,
23800x98, 0xE1,
23810xB5, 0x05,
2382
23830xBD, 0x05,
23840x2E, 0x30,
23850x32, 0xC0, 0xA0, 0xE8,
2386
23870x33, 0xC0, 0xA0, 0xE8,
23880x74, 0x64, 0xC8, 0xEC,
2389
23900x40, 0x3C, 0x40, 0xAD,
23910x32, 0x6A,
23920x2A, 0x30,
2393
23940x20, 0x73,
23950x33, 0x6A,
23960x00, 0xE0,
23970x28, 0x73,
2398
23990x1C, 0x72,
24000x83, 0xE2,
24010x77, 0x80, 0x15, 0xEA,
2402
24030xB8, 0x3D, 0x28, 0xDF,
24040x30, 0x35, 0x20, 0xDF,
2405
24060x40, 0x30,
24070x00, 0xE0,
24080xCC, 0xE2,
24090x64, 0x72,
2410
24110x25, 0x42, 0x52, 0xBF,
24120x2D, 0x42, 0x4A, 0xBF,
2413
24140x30, 0x2E, 0x30, 0xDF,
24150x38, 0x2E, 0x38, 0xDF,
2416
24170x18, 0x1D, 0x45, 0xE9,
24180x1E, 0x15, 0x45, 0xE9,
2419
24200x2B, 0x49, 0x51, 0xBD,
24210x00, 0xE0,
24220x1F, 0x73,
2423
24240x38, 0x38, 0x40, 0xAF,
24250x30, 0x30, 0x40, 0xAF,
2426
24270x24, 0x1F, 0x24, 0xDF,
24280x1D, 0x32, 0x20, 0xE9,
2429
24300x2C, 0x1F, 0x2C, 0xDF,
24310x1A, 0x33, 0x20, 0xE9,
2432
24330xB0, 0x10,
24340x08, 0xE3,
24350x40, 0x10,
24360xB8, 0x10,
2437
24380x26, 0xF0, 0x30, 0xCD,
24390x2F, 0xF0, 0x38, 0xCD,
2440
24410x2B, 0x80, 0x20, 0xE9,
24420x2A, 0x80, 0x20, 0xE9,
2443
24440xA6, 0x20,
24450x88, 0xE2,
24460x00, 0xE0,
24470xAF, 0x20,
2448
24490x28, 0x2A, 0x26, 0xAF,
24500x20, 0x2A, 0xC0, 0xAF,
2451
24520x34, 0x1F, 0x34, 0xDF,
24530x46, 0x24, 0x46, 0xDF,
2454
24550x28, 0x30, 0x80, 0xBF,
24560x20, 0x38, 0x80, 0xBF,
2457
24580x47, 0x24, 0x47, 0xDF,
24590x4E, 0x2C, 0x4E, 0xDF,
2460
24610x4F, 0x2C, 0x4F, 0xDF,
24620x56, 0x34, 0x56, 0xDF,
2463
24640x28, 0x15, 0x28, 0xDF,
24650x20, 0x1D, 0x20, 0xDF,
2466
24670x57, 0x34, 0x57, 0xDF,
24680x00, 0xE0,
24690x1D, 0x05,
2470
24710x04, 0x80, 0x10, 0xEA,
24720x89, 0xE2,
24730x2B, 0x30,
2474
24750x3F, 0xC1, 0x1D, 0xBD,
24760x00, 0x80, 0x00, 0xE8,
2477
24780x00, 0x80, 0x00, 0xE8,
24790x00, 0x80, 0x00, 0xE8,
2480
24810xA0, 0x68,
24820xBF, 0x25,
24830x00, 0x80, 0x00, 0xE8,
2484
24850x20, 0xC0, 0x20, 0xAF,
24860x28, 0x05,
24870x97, 0x74,
2488
24890x00, 0xE0,
24900x2A, 0x10,
24910x16, 0xC0, 0x20, 0xE9,
2492
24930x04, 0x80, 0x10, 0xEA,
24940x8C, 0xE2,
24950x95, 0x05,
2496
24970x28, 0xC1, 0x28, 0xAD,
24980x1F, 0xC1, 0x15, 0xBD,
2499
25000x00, 0x80, 0x00, 0xE8,
25010x00, 0x80, 0x00, 0xE8,
2502
25030xA8, 0x67,
25040x9F, 0x6B,
25050x00, 0x80, 0x00, 0xE8,
2506
25070x28, 0xC0, 0x28, 0xAD,
25080x1D, 0x25,
25090x20, 0x05,
2510
25110x28, 0x32, 0x80, 0xAD,
25120x40, 0x2A, 0x40, 0xBD,
2513
25140x1C, 0x80, 0x20, 0xE9,
25150x20, 0x33, 0x20, 0xAD,
2516
25170x20, 0x73,
25180x00, 0xE0,
25190xB6, 0x49, 0x51, 0xBB,
2520
25210x26, 0x2F, 0xB0, 0xE8,
25220x19, 0x20, 0x20, 0xE9,
2523
25240x35, 0x20, 0x35, 0xDF,
25250x3D, 0x20, 0x3D, 0xDF,
2526
25270x15, 0x20, 0x15, 0xDF,
25280x1D, 0x20, 0x1D, 0xDF,
2529
25300x26, 0xD0, 0x26, 0xCD,
25310x29, 0x49, 0x2A, 0xB8,
2532
25330x26, 0x40, 0x80, 0xBD,
25340x3B, 0x48, 0x50, 0xBD,
2535
25360x3E, 0x54, 0x57, 0x9F,
25370x00, 0xE0,
25380x82, 0xE1,
2539
25400x1E, 0xAF, 0x59, 0x9F,
25410x00, 0x80, 0x00, 0xE8,
2542
25430x26, 0x30,
25440x29, 0x30,
25450x48, 0x3C, 0x48, 0xAD,
2546
25470x2B, 0x72,
25480xC2, 0xE1,
25490x2C, 0xC0, 0x44, 0xC2,
2550
25510x05, 0x24, 0x34, 0xBF,
25520x0D, 0x24, 0x2C, 0xBF,
2553
25540x2D, 0x46, 0x4E, 0xBF,
25550x25, 0x46, 0x56, 0xBF,
2556
25570x20, 0x1D, 0x6F, 0x8F,
25580x32, 0x3E, 0x5F, 0xE9,
2559
25600x3E, 0x50, 0x56, 0x9F,
25610x00, 0xE0,
25620x3B, 0x30,
2563
25640x1E, 0x8F, 0x51, 0x9F,
25650x33, 0x1E, 0x5F, 0xE9,
2566
25670x05, 0x44, 0x54, 0xB2,
25680x0D, 0x44, 0x4C, 0xB2,
2569
25700x19, 0xC0, 0xB0, 0xE8,
25710x34, 0xC0, 0x44, 0xC4,
2572
25730x33, 0x73,
25740x00, 0xE0,
25750x3E, 0x62, 0x57, 0x9F,
2576
25770x1E, 0xAF, 0x59, 0x9F,
25780x00, 0xE0,
25790x0D, 0x20,
2580
25810x84, 0x3E, 0x58, 0xE9,
25820x28, 0x1D, 0x6F, 0x8F,
2583
25840x05, 0x20,
25850x00, 0xE0,
25860x85, 0x1E, 0x58, 0xE9,
2587
25880x9B, 0x3B, 0x33, 0xDF,
25890x20, 0x20, 0x42, 0xAF,
2590
25910x30, 0x42, 0x56, 0x9F,
25920x80, 0x3E, 0x57, 0xE9,
2593
25940x3F, 0x8F, 0x51, 0x9F,
25950x30, 0x80, 0x5F, 0xE9,
2596
25970x28, 0x28, 0x24, 0xAF,
25980x81, 0x1E, 0x57, 0xE9,
2599
26000x05, 0x47, 0x57, 0xBF,
26010x0D, 0x47, 0x4F, 0xBF,
2602
26030x88, 0x80, 0x58, 0xE9,
26040x1B, 0x29, 0x1B, 0xDF,
2605
26060x30, 0x1D, 0x6F, 0x8F,
26070x3A, 0x30, 0x4F, 0xE9,
2608
26090x1C, 0x30, 0x26, 0xDF,
26100x09, 0xE3,
26110x3B, 0x05,
2612
26130x3E, 0x50, 0x56, 0x9F,
26140x3B, 0x3F, 0x4F, 0xE9,
2615
26160x1E, 0x8F, 0x51, 0x9F,
26170x00, 0xE0,
26180xAC, 0x20,
2619
26200x2D, 0x44, 0x4C, 0xB4,
26210x2C, 0x1C, 0xC0, 0xAF,
2622
26230x25, 0x44, 0x54, 0xB4,
26240x00, 0xE0,
26250xC8, 0x30,
2626
26270x30, 0x46, 0x30, 0xAF,
26280x1B, 0x1B, 0x48, 0xAF,
2629
26300x00, 0xE0,
26310x25, 0x20,
26320x38, 0x2C, 0x4F, 0xE9,
2633
26340x86, 0x80, 0x57, 0xE9,
26350x38, 0x1D, 0x6F, 0x8F,
2636
26370x28, 0x74,
26380x00, 0xE0,
26390x0D, 0x44, 0x4C, 0xB0,
2640
26410x05, 0x44, 0x54, 0xB0,
26420x2D, 0x20,
26430x9B, 0x10,
2644
26450x82, 0x3E, 0x57, 0xE9,
26460x32, 0xF0, 0x1B, 0xCD,
2647
26480x1E, 0xBD, 0x59, 0x9F,
26490x83, 0x1E, 0x57, 0xE9,
2650
26510x38, 0x47, 0x38, 0xAF,
26520x34, 0x20,
26530x2A, 0x30,
2654
26550x00, 0xE0,
26560x0D, 0x20,
26570x32, 0x20,
26580x05, 0x20,
2659
26600x87, 0x80, 0x57, 0xE9,
26610x1F, 0x54, 0x57, 0x9F,
2662
26630x17, 0x42, 0x56, 0x9F,
26640x00, 0xE0,
26650x3B, 0x6A,
2666
26670x3F, 0x8F, 0x51, 0x9F,
26680x37, 0x1E, 0x4F, 0xE9,
2669
26700x37, 0x32, 0x2A, 0xAF,
26710x00, 0xE0,
26720x32, 0x00,
2673
26740x00, 0x80, 0x00, 0xE8,
26750x27, 0xC0, 0x44, 0xC0,
2676
26770x36, 0x1F, 0x4F, 0xE9,
26780x1F, 0x1F, 0x26, 0xDF,
2679
26800x37, 0x1B, 0x37, 0xBF,
26810x17, 0x26, 0x17, 0xDF,
2682
26830x3E, 0x17, 0x4F, 0xE9,
26840x3F, 0x3F, 0x4F, 0xE9,
2685
26860x34, 0x1F, 0x34, 0xAF,
26870x2B, 0x05,
26880xA7, 0x20,
2689
26900x33, 0x2B, 0x37, 0xDF,
26910x27, 0x17, 0xC0, 0xAF,
2692
26930x34, 0x80, 0x4F, 0xE9,
26940x00, 0x80, 0x00, 0xE8,
2695
26960x2D, 0x21, 0x1A, 0xB0,
26970x25, 0x21, 0x31, 0xB0,
2698
26990x0D, 0x21, 0x1A, 0xB2,
27000x05, 0x21, 0x31, 0xB2,
2701
27020x03, 0x80, 0x2A, 0xEA,
27030x17, 0xC1, 0x2B, 0xBD,
2704
27050x2D, 0x20,
27060x25, 0x20,
27070x05, 0x20,
27080x0D, 0x20,
2709
27100xB3, 0x68,
27110x97, 0x25,
27120x00, 0x80, 0x00, 0xE8,
2713
27140x33, 0xC0, 0x33, 0xAF,
27150x2F, 0xC0, 0x21, 0xC0,
2716
27170x16, 0x42, 0x56, 0x9F,
27180x3C, 0x27, 0x4F, 0xE9,
2719
27200x1E, 0x62, 0x57, 0x9F,
27210x00, 0x80, 0x00, 0xE8,
2722
27230x25, 0x21, 0x31, 0xB4,
27240x2D, 0x21, 0x1A, 0xB4,
2725
27260x3F, 0x2F, 0x5D, 0x9F,
27270x00, 0x80, 0x00, 0xE8,
2728
27290x33, 0x05,
27300x00, 0xE0,
27310x28, 0x19, 0x60, 0xEC,
2732
27330x37, 0x0F, 0x5C, 0x9F,
27340x00, 0xE0,
27350x2F, 0x20,
2736
27370x23, 0x3B, 0x33, 0xAD,
27380x1E, 0x26, 0x1E, 0xDF,
2739
27400xA7, 0x1E, 0x4F, 0xE9,
27410x17, 0x26, 0x16, 0xDF,
2742
27430x2D, 0x20,
27440x00, 0xE0,
27450xA8, 0x3F, 0x4F, 0xE9,
2746
27470x2F, 0x2F, 0x1E, 0xAF,
27480x25, 0x20,
27490x00, 0xE0,
2750
27510xA4, 0x16, 0x4F, 0xE9,
27520x0F, 0xC0, 0x21, 0xC2,
2753
27540xA6, 0x80, 0x4F, 0xE9,
27550x1F, 0x62, 0x57, 0x9F,
2756
27570x3F, 0x2F, 0x5D, 0x9F,
27580x00, 0xE0,
27590x8F, 0x20,
2760
27610xA5, 0x37, 0x4F, 0xE9,
27620x0F, 0x17, 0x0F, 0xAF,
2763
27640x06, 0xC0, 0x21, 0xC4,
27650x00, 0x80, 0x00, 0xE8,
2766
27670x00, 0x80, 0x00, 0xE8,
27680xA3, 0x80, 0x4F, 0xE9,
2769
27700x06, 0x20,
27710x00, 0xE0,
27720x1F, 0x26, 0x1F, 0xDF,
2773
27740xA1, 0x1F, 0x4F, 0xE9,
27750xA2, 0x3F, 0x4F, 0xE9,
2776
27770x00, 0x80, 0x00, 0xE8,
27780x00, 0x80, 0x00, 0xE8,
2779
27800x06, 0x06, 0x1F, 0xAF,
27810x00, 0x80, 0x00, 0xE8,
2782
27830x00, 0x80, 0x00, 0xE8,
27840x00, 0x80, 0x00, 0xE8,
2785
27860xA0, 0x80, 0x4F, 0xE9,
27870x00, 0x80, 0x00, 0xE8,
2788
27890x00, 0x80, 0x00, 0xE8,
27900x57, 0x39, 0x20, 0xE9,
2791
27920x16, 0x28, 0x20, 0xE9,
27930x1D, 0x3B, 0x20, 0xE9,
2794
27950x1E, 0x2B, 0x20, 0xE9,
27960x2B, 0x32, 0x20, 0xE9,
2797
27980x1C, 0x23, 0x20, 0xE9,
27990x57, 0x36, 0x20, 0xE9,
2800
28010x00, 0x80, 0xA0, 0xE9,
28020x40, 0x40, 0xD8, 0xEC,
2803
28040xFF, 0x80, 0xC0, 0xE9,
28050x90, 0xE2,
28060x00, 0xE0,
2807
28080x6C, 0xFF, 0x20, 0xEA,
28090x19, 0xC8, 0xC1, 0xCD,
2810
28110x1F, 0xD7, 0x18, 0xBD,
28120x3F, 0xD7, 0x22, 0xBD,
2813
28140x9F, 0x41, 0x49, 0xBD,
28150x00, 0x80, 0x00, 0xE8,
2816
28170x25, 0x41, 0x49, 0xBD,
28180x2D, 0x41, 0x51, 0xBD,
2819
28200x0D, 0x80, 0x07, 0xEA,
28210x00, 0x80, 0x00, 0xE8,
2822
28230x35, 0x40, 0x48, 0xBD,
28240x3D, 0x40, 0x50, 0xBD,
2825
28260x00, 0x80, 0x00, 0xE8,
28270x25, 0x30,
28280x2D, 0x30,
2829
28300x35, 0x30,
28310xB5, 0x30,
28320xBD, 0x30,
28330x3D, 0x30,
2834
28350x9C, 0xA7, 0x5B, 0x9F,
28360x00, 0x80, 0x00, 0xE8,
2837
28380x00, 0x80, 0x00, 0xE8,
28390x00, 0x80, 0x00, 0xE8,
2840
28410x00, 0x80, 0x00, 0xE8,
28420x00, 0x80, 0x00, 0xE8,
2843
28440x00, 0x80, 0x00, 0xE8,
28450x00, 0x80, 0x00, 0xE8,
2846
28470x00, 0x80, 0x00, 0xE8,
28480x00, 0x80, 0x00, 0xE8,
2849
28500x6B, 0xFF, 0x0A, 0xEA,
28510x00, 0x80, 0x00, 0xE8,
2852
28530xC9, 0x41, 0xC8, 0xEC,
28540x42, 0xE1,
28550x00, 0xE0,
2856
28570x69, 0xFF, 0x20, 0xEA,
28580x00, 0x80, 0x00, 0xE8,
2859
28600x00, 0x80, 0x00, 0xE8,
28610x00, 0x80, 0x00, 0xE8,
2862
28630xC8, 0x40, 0xC0, 0xEC,
28640x00, 0x80, 0x00, 0xE8,
2865
28660x66, 0xFF, 0x20, 0xEA,
28670x00, 0x80, 0x00, 0xE8,
2868
28690x00, 0x80, 0x00, 0xE8,
28700x00, 0x80, 0x00, 0xE8,
2871
2872};
2873
2874static unsigned char warp_g200_tgzsa[] = {
2875
28760x00, 0x80, 0x00, 0xE8,
28770x00, 0x80, 0x00, 0xE8,
2878
28790x00, 0x80, 0x00, 0xE8,
28800x00, 0x80, 0x00, 0xE8,
2881
28820x00, 0x80, 0x00, 0xE8,
28830x00, 0x80, 0x00, 0xE8,
2884
28850x00, 0x80, 0x00, 0xE8,
28860x00, 0x80, 0x00, 0xE8,
2887
28880x00, 0x80, 0x00, 0xE8,
28890x00, 0x80, 0x00, 0xE8,
2890
28910x00, 0x80, 0x00, 0xE8,
28920x00, 0x80, 0x00, 0xE8,
2893
28940x00, 0x80, 0x00, 0xE8,
28950x00, 0x80, 0x00, 0xE8,
2896
28970x00, 0x80, 0x00, 0xE8,
28980x00, 0x80, 0x00, 0xE8,
2899
29000x00, 0x80, 0x00, 0xE8,
29010x00, 0x80, 0x00, 0xE8,
2902
29030x00, 0x80, 0x00, 0xE8,
29040x00, 0x80, 0x00, 0xE8,
2905
29060x00, 0x80, 0x00, 0xE8,
29070x00, 0x80, 0x00, 0xE8,
2908
29090x00, 0x80, 0x00, 0xE8,
29100x00, 0x80, 0x00, 0xE8,
2911
29120x00, 0x80, 0x00, 0xE8,
29130x00, 0x80, 0x00, 0xE8,
2914
29150x00, 0x98, 0xA0, 0xE9,
29160x40, 0x40, 0xD8, 0xEC,
2917
29180xFF, 0x80, 0xC0, 0xE9,
29190x00, 0x80, 0x00, 0xE8,
2920
29210x1F, 0xD7, 0x18, 0xBD,
29220x3F, 0xD7, 0x22, 0xBD,
2923
29240x81, 0x04,
29250x89, 0x04,
29260x01, 0x04,
29270x09, 0x04,
2928
29290xC9, 0x41, 0xC0, 0xEC,
29300x11, 0x04,
29310x00, 0xE0,
2932
29330x41, 0xCC, 0x41, 0xCD,
29340x49, 0xCC, 0x49, 0xCD,
2935
29360xD1, 0x41, 0xC0, 0xEC,
29370x51, 0xCC, 0x51, 0xCD,
2938
29390x80, 0x04,
29400x10, 0x04,
29410x08, 0x04,
29420x00, 0xE0,
2943
29440x00, 0xCC, 0xC0, 0xCD,
29450xD1, 0x49, 0xC0, 0xEC,
2946
29470x8A, 0x1F, 0x20, 0xE9,
29480x8B, 0x3F, 0x20, 0xE9,
2949
29500x41, 0x3C, 0x41, 0xAD,
29510x49, 0x3C, 0x49, 0xAD,
2952
29530x10, 0xCC, 0x10, 0xCD,
29540x08, 0xCC, 0x08, 0xCD,
2955
29560xB9, 0x41, 0x49, 0xBB,
29570x1F, 0xF0, 0x41, 0xCD,
2958
29590x51, 0x3C, 0x51, 0xAD,
29600x00, 0x98, 0x80, 0xE9,
2961
29620x8F, 0x80, 0x07, 0xEA,
29630x24, 0x1F, 0x20, 0xE9,
2964
29650x21, 0x45, 0x80, 0xE8,
29660x1A, 0x4D, 0x80, 0xE8,
2967
29680x31, 0x55, 0x80, 0xE8,
29690x00, 0x80, 0x00, 0xE8,
2970
29710x15, 0x41, 0x49, 0xBD,
29720x1D, 0x41, 0x51, 0xBD,
2973
29740x2E, 0x41, 0x2A, 0xB8,
29750x34, 0x53, 0xA0, 0xE8,
2976
29770x15, 0x30,
29780x1D, 0x30,
29790x58, 0xE3,
29800x00, 0xE0,
2981
29820xB5, 0x40, 0x48, 0xBD,
29830x3D, 0x40, 0x50, 0xBD,
2984
29850x24, 0x43, 0xA0, 0xE8,
29860x2C, 0x4B, 0xA0, 0xE8,
2987
29880x15, 0x72,
29890x09, 0xE3,
29900x00, 0xE0,
29910x1D, 0x72,
2992
29930x35, 0x30,
29940xB5, 0x30,
29950xBD, 0x30,
29960x3D, 0x30,
2997
29980x9C, 0x97, 0x57, 0x9F,
29990x00, 0x80, 0x00, 0xE8,
3000
30010x6C, 0x64, 0xC8, 0xEC,
30020x98, 0xE1,
30030xB5, 0x05,
3004
30050xBD, 0x05,
30060x2E, 0x30,
30070x32, 0xC0, 0xA0, 0xE8,
3008
30090x33, 0xC0, 0xA0, 0xE8,
30100x74, 0x64, 0xC8, 0xEC,
3011
30120x40, 0x3C, 0x40, 0xAD,
30130x32, 0x6A,
30140x2A, 0x30,
3015
30160x20, 0x73,
30170x33, 0x6A,
30180x00, 0xE0,
30190x28, 0x73,
3020
30210x1C, 0x72,
30220x83, 0xE2,
30230x7B, 0x80, 0x15, 0xEA,
3024
30250xB8, 0x3D, 0x28, 0xDF,
30260x30, 0x35, 0x20, 0xDF,
3027
30280x40, 0x30,
30290x00, 0xE0,
30300xCC, 0xE2,
30310x64, 0x72,
3032
30330x25, 0x42, 0x52, 0xBF,
30340x2D, 0x42, 0x4A, 0xBF,
3035
30360x30, 0x2E, 0x30, 0xDF,
30370x38, 0x2E, 0x38, 0xDF,
3038
30390x18, 0x1D, 0x45, 0xE9,
30400x1E, 0x15, 0x45, 0xE9,
3041
30420x2B, 0x49, 0x51, 0xBD,
30430x00, 0xE0,
30440x1F, 0x73,
3045
30460x38, 0x38, 0x40, 0xAF,
30470x30, 0x30, 0x40, 0xAF,
3048
30490x24, 0x1F, 0x24, 0xDF,
30500x1D, 0x32, 0x20, 0xE9,
3051
30520x2C, 0x1F, 0x2C, 0xDF,
30530x1A, 0x33, 0x20, 0xE9,
3054
30550xB0, 0x10,
30560x08, 0xE3,
30570x40, 0x10,
30580xB8, 0x10,
3059
30600x26, 0xF0, 0x30, 0xCD,
30610x2F, 0xF0, 0x38, 0xCD,
3062
30630x2B, 0x80, 0x20, 0xE9,
30640x2A, 0x80, 0x20, 0xE9,
3065
30660xA6, 0x20,
30670x88, 0xE2,
30680x00, 0xE0,
30690xAF, 0x20,
3070
30710x28, 0x2A, 0x26, 0xAF,
30720x20, 0x2A, 0xC0, 0xAF,
3073
30740x34, 0x1F, 0x34, 0xDF,
30750x46, 0x24, 0x46, 0xDF,
3076
30770x28, 0x30, 0x80, 0xBF,
30780x20, 0x38, 0x80, 0xBF,
3079
30800x47, 0x24, 0x47, 0xDF,
30810x4E, 0x2C, 0x4E, 0xDF,
3082
30830x4F, 0x2C, 0x4F, 0xDF,
30840x56, 0x34, 0x56, 0xDF,
3085
30860x28, 0x15, 0x28, 0xDF,
30870x20, 0x1D, 0x20, 0xDF,
3088
30890x57, 0x34, 0x57, 0xDF,
30900x00, 0xE0,
30910x1D, 0x05,
3092
30930x04, 0x80, 0x10, 0xEA,
30940x89, 0xE2,
30950x2B, 0x30,
3096
30970x3F, 0xC1, 0x1D, 0xBD,
30980x00, 0x80, 0x00, 0xE8,
3099
31000x00, 0x80, 0x00, 0xE8,
31010x00, 0x80, 0x00, 0xE8,
3102
31030xA0, 0x68,
31040xBF, 0x25,
31050x00, 0x80, 0x00, 0xE8,
3106
31070x20, 0xC0, 0x20, 0xAF,
31080x28, 0x05,
31090x97, 0x74,
3110
31110x00, 0xE0,
31120x2A, 0x10,
31130x16, 0xC0, 0x20, 0xE9,
3114
31150x04, 0x80, 0x10, 0xEA,
31160x8C, 0xE2,
31170x95, 0x05,
3118
31190x28, 0xC1, 0x28, 0xAD,
31200x1F, 0xC1, 0x15, 0xBD,
3121
31220x00, 0x80, 0x00, 0xE8,
31230x00, 0x80, 0x00, 0xE8,
3124
31250xA8, 0x67,
31260x9F, 0x6B,
31270x00, 0x80, 0x00, 0xE8,
3128
31290x28, 0xC0, 0x28, 0xAD,
31300x1D, 0x25,
31310x20, 0x05,
3132
31330x28, 0x32, 0x80, 0xAD,
31340x40, 0x2A, 0x40, 0xBD,
3135
31360x1C, 0x80, 0x20, 0xE9,
31370x20, 0x33, 0x20, 0xAD,
3138
31390x20, 0x73,
31400x00, 0xE0,
31410xB6, 0x49, 0x51, 0xBB,
3142
31430x26, 0x2F, 0xB0, 0xE8,
31440x19, 0x20, 0x20, 0xE9,
3145
31460x35, 0x20, 0x35, 0xDF,
31470x3D, 0x20, 0x3D, 0xDF,
3148
31490x15, 0x20, 0x15, 0xDF,
31500x1D, 0x20, 0x1D, 0xDF,
3151
31520x26, 0xD0, 0x26, 0xCD,
31530x29, 0x49, 0x2A, 0xB8,
3154
31550x26, 0x40, 0x80, 0xBD,
31560x3B, 0x48, 0x50, 0xBD,
3157
31580x3E, 0x54, 0x57, 0x9F,
31590x00, 0xE0,
31600x82, 0xE1,
3161
31620x1E, 0xAF, 0x59, 0x9F,
31630x00, 0x80, 0x00, 0xE8,
3164
31650x26, 0x30,
31660x29, 0x30,
31670x48, 0x3C, 0x48, 0xAD,
3168
31690x2B, 0x72,
31700xC2, 0xE1,
31710x2C, 0xC0, 0x44, 0xC2,
3172
31730x05, 0x24, 0x34, 0xBF,
31740x0D, 0x24, 0x2C, 0xBF,
3175
31760x2D, 0x46, 0x4E, 0xBF,
31770x25, 0x46, 0x56, 0xBF,
3178
31790x20, 0x1D, 0x6F, 0x8F,
31800x32, 0x3E, 0x5F, 0xE9,
3181
31820x3E, 0x50, 0x56, 0x9F,
31830x00, 0xE0,
31840x3B, 0x30,
3185
31860x1E, 0x8F, 0x51, 0x9F,
31870x33, 0x1E, 0x5F, 0xE9,
3188
31890x05, 0x44, 0x54, 0xB2,
31900x0D, 0x44, 0x4C, 0xB2,
3191
31920x19, 0xC0, 0xB0, 0xE8,
31930x34, 0xC0, 0x44, 0xC4,
3194
31950x33, 0x73,
31960x00, 0xE0,
31970x3E, 0x62, 0x57, 0x9F,
3198
31990x1E, 0xAF, 0x59, 0x9F,
32000x00, 0xE0,
32010x0D, 0x20,
3202
32030x84, 0x3E, 0x58, 0xE9,
32040x28, 0x1D, 0x6F, 0x8F,
3205
32060x05, 0x20,
32070x00, 0xE0,
32080x85, 0x1E, 0x58, 0xE9,
3209
32100x9B, 0x3B, 0x33, 0xDF,
32110x20, 0x20, 0x42, 0xAF,
3212
32130x30, 0x42, 0x56, 0x9F,
32140x80, 0x3E, 0x57, 0xE9,
3215
32160x3F, 0x8F, 0x51, 0x9F,
32170x30, 0x80, 0x5F, 0xE9,
3218
32190x28, 0x28, 0x24, 0xAF,
32200x81, 0x1E, 0x57, 0xE9,
3221
32220x05, 0x47, 0x57, 0xBF,
32230x0D, 0x47, 0x4F, 0xBF,
3224
32250x88, 0x80, 0x58, 0xE9,
32260x1B, 0x29, 0x1B, 0xDF,
3227
32280x30, 0x1D, 0x6F, 0x8F,
32290x3A, 0x30, 0x4F, 0xE9,
3230
32310x1C, 0x30, 0x26, 0xDF,
32320x09, 0xE3,
32330x3B, 0x05,
3234
32350x3E, 0x50, 0x56, 0x9F,
32360x3B, 0x3F, 0x4F, 0xE9,
3237
32380x1E, 0x8F, 0x51, 0x9F,
32390x00, 0xE0,
32400xAC, 0x20,
3241
32420x2D, 0x44, 0x4C, 0xB4,
32430x2C, 0x1C, 0xC0, 0xAF,
3244
32450x25, 0x44, 0x54, 0xB4,
32460x00, 0xE0,
32470xC8, 0x30,
3248
32490x30, 0x46, 0x30, 0xAF,
32500x1B, 0x1B, 0x48, 0xAF,
3251
32520x00, 0xE0,
32530x25, 0x20,
32540x38, 0x2C, 0x4F, 0xE9,
3255
32560x86, 0x80, 0x57, 0xE9,
32570x38, 0x1D, 0x6F, 0x8F,
3258
32590x28, 0x74,
32600x00, 0xE0,
32610x0D, 0x44, 0x4C, 0xB0,
3262
32630x05, 0x44, 0x54, 0xB0,
32640x2D, 0x20,
32650x9B, 0x10,
3266
32670x82, 0x3E, 0x57, 0xE9,
32680x32, 0xF0, 0x1B, 0xCD,
3269
32700x1E, 0xBD, 0x59, 0x9F,
32710x83, 0x1E, 0x57, 0xE9,
3272
32730x38, 0x47, 0x38, 0xAF,
32740x34, 0x20,
32750x2A, 0x30,
3276
32770x00, 0xE0,
32780x0D, 0x20,
32790x32, 0x20,
32800x05, 0x20,
3281
32820x87, 0x80, 0x57, 0xE9,
32830x1F, 0x54, 0x57, 0x9F,
3284
32850x17, 0x42, 0x56, 0x9F,
32860x00, 0xE0,
32870x3B, 0x6A,
3288
32890x3F, 0x8F, 0x51, 0x9F,
32900x37, 0x1E, 0x4F, 0xE9,
3291
32920x37, 0x32, 0x2A, 0xAF,
32930x00, 0xE0,
32940x32, 0x00,
3295
32960x00, 0x80, 0x00, 0xE8,
32970x27, 0xC0, 0x44, 0xC0,
3298
32990x36, 0x1F, 0x4F, 0xE9,
33000x1F, 0x1F, 0x26, 0xDF,
3301
33020x37, 0x1B, 0x37, 0xBF,
33030x17, 0x26, 0x17, 0xDF,
3304
33050x3E, 0x17, 0x4F, 0xE9,
33060x3F, 0x3F, 0x4F, 0xE9,
3307
33080x34, 0x1F, 0x34, 0xAF,
33090x2B, 0x05,
33100xA7, 0x20,
3311
33120x33, 0x2B, 0x37, 0xDF,
33130x27, 0x17, 0xC0, 0xAF,
3314
33150x34, 0x80, 0x4F, 0xE9,
33160x00, 0x80, 0x00, 0xE8,
3317
33180x2D, 0x21, 0x1A, 0xB0,
33190x25, 0x21, 0x31, 0xB0,
3320
33210x0D, 0x21, 0x1A, 0xB2,
33220x05, 0x21, 0x31, 0xB2,
3323
33240x03, 0x80, 0x2A, 0xEA,
33250x17, 0xC1, 0x2B, 0xBD,
3326
33270x2D, 0x20,
33280x25, 0x20,
33290x05, 0x20,
33300x0D, 0x20,
3331
33320xB3, 0x68,
33330x97, 0x25,
33340x00, 0x80, 0x00, 0xE8,
3335
33360x33, 0xC0, 0x33, 0xAF,
33370x2F, 0xC0, 0x21, 0xC0,
3338
33390x16, 0x42, 0x56, 0x9F,
33400x3C, 0x27, 0x4F, 0xE9,
3341
33420x1E, 0x62, 0x57, 0x9F,
33430x00, 0x80, 0x00, 0xE8,
3344
33450x25, 0x21, 0x31, 0xB4,
33460x2D, 0x21, 0x1A, 0xB4,
3347
33480x3F, 0x2F, 0x5D, 0x9F,
33490x00, 0x80, 0x00, 0xE8,
3350
33510x33, 0x05,
33520x00, 0xE0,
33530x28, 0x19, 0x60, 0xEC,
3354
33550x0D, 0x44, 0x4C, 0xB6,
33560x05, 0x44, 0x54, 0xB6,
3357
33580x37, 0x0F, 0x5C, 0x9F,
33590x00, 0xE0,
33600x2F, 0x20,
3361
33620x23, 0x3B, 0x33, 0xAD,
33630x1E, 0x26, 0x1E, 0xDF,
3364
33650xA7, 0x1E, 0x4F, 0xE9,
33660x17, 0x26, 0x16, 0xDF,
3367
33680x2D, 0x20,
33690x00, 0xE0,
33700xA8, 0x3F, 0x4F, 0xE9,
3371
33720x2F, 0x2F, 0x1E, 0xAF,
33730x25, 0x20,
33740x00, 0xE0,
3375
33760xA4, 0x16, 0x4F, 0xE9,
33770x0F, 0xC0, 0x21, 0xC2,
3378
33790xA6, 0x80, 0x4F, 0xE9,
33800x1F, 0x62, 0x57, 0x9F,
3381
33820x0D, 0x20,
33830x05, 0x20,
33840x00, 0x80, 0x00, 0xE8,
3385
33860x3F, 0x2F, 0x5D, 0x9F,
33870x00, 0xE0,
33880x0F, 0x20,
3389
33900x17, 0x50, 0x56, 0x9F,
33910xA5, 0x37, 0x4F, 0xE9,
3392
33930x06, 0xC0, 0x21, 0xC4,
33940x0F, 0x17, 0x0F, 0xAF,
3395
33960x37, 0x0F, 0x5C, 0x9F,
33970x00, 0x80, 0x00, 0xE8,
3398
33990x2F, 0xC0, 0x44, 0xC6,
34000xA3, 0x80, 0x4F, 0xE9,
3401
34020x06, 0x20,
34030x00, 0xE0,
34040x1F, 0x26, 0x1F, 0xDF,
3405
34060x17, 0x26, 0x17, 0xDF,
34070x9D, 0x17, 0x4F, 0xE9,
3408
34090xA1, 0x1F, 0x4F, 0xE9,
34100xA2, 0x3F, 0x4F, 0xE9,
3411
34120x06, 0x06, 0x1F, 0xAF,
34130x00, 0xE0,
34140xAF, 0x20,
3415
34160x9E, 0x37, 0x4F, 0xE9,
34170x2F, 0x17, 0x2F, 0xAF,
3418
34190xA0, 0x80, 0x4F, 0xE9,
34200x00, 0x80, 0x00, 0xE8,
3421
34220x00, 0x80, 0x00, 0xE8,
34230x9C, 0x80, 0x4F, 0xE9,
3424
34250x00, 0x80, 0x00, 0xE8,
34260x57, 0x39, 0x20, 0xE9,
3427
34280x16, 0x28, 0x20, 0xE9,
34290x1D, 0x3B, 0x20, 0xE9,
3430
34310x1E, 0x2B, 0x20, 0xE9,
34320x2B, 0x32, 0x20, 0xE9,
3433
34340x1C, 0x23, 0x20, 0xE9,
34350x57, 0x36, 0x20, 0xE9,
3436
34370x00, 0x80, 0xA0, 0xE9,
34380x40, 0x40, 0xD8, 0xEC,
3439
34400xFF, 0x80, 0xC0, 0xE9,
34410x90, 0xE2,
34420x00, 0xE0,
3443
34440x68, 0xFF, 0x20, 0xEA,
34450x19, 0xC8, 0xC1, 0xCD,
3446
34470x1F, 0xD7, 0x18, 0xBD,
34480x3F, 0xD7, 0x22, 0xBD,
3449
34500x9F, 0x41, 0x49, 0xBD,
34510x00, 0x80, 0x00, 0xE8,
3452
34530x25, 0x41, 0x49, 0xBD,
34540x2D, 0x41, 0x51, 0xBD,
3455
34560x0D, 0x80, 0x07, 0xEA,
34570x00, 0x80, 0x00, 0xE8,
3458
34590x35, 0x40, 0x48, 0xBD,
34600x3D, 0x40, 0x50, 0xBD,
3461
34620x00, 0x80, 0x00, 0xE8,
34630x25, 0x30,
34640x2D, 0x30,
3465
34660x35, 0x30,
34670xB5, 0x30,
34680xBD, 0x30,
34690x3D, 0x30,
3470
34710x9C, 0xA7, 0x5B, 0x9F,
34720x00, 0x80, 0x00, 0xE8,
3473
34740x00, 0x80, 0x00, 0xE8,
34750x00, 0x80, 0x00, 0xE8,
3476
34770x00, 0x80, 0x00, 0xE8,
34780x00, 0x80, 0x00, 0xE8,
3479
34800x00, 0x80, 0x00, 0xE8,
34810x00, 0x80, 0x00, 0xE8,
3482
34830x00, 0x80, 0x00, 0xE8,
34840x00, 0x80, 0x00, 0xE8,
3485
34860x67, 0xFF, 0x0A, 0xEA,
34870x00, 0x80, 0x00, 0xE8,
3488
34890xC9, 0x41, 0xC8, 0xEC,
34900x42, 0xE1,
34910x00, 0xE0,
3492
34930x65, 0xFF, 0x20, 0xEA,
34940x00, 0x80, 0x00, 0xE8,
3495
34960x00, 0x80, 0x00, 0xE8,
34970x00, 0x80, 0x00, 0xE8,
3498
34990xC8, 0x40, 0xC0, 0xEC,
35000x00, 0x80, 0x00, 0xE8,
3501
35020x62, 0xFF, 0x20, 0xEA,
35030x00, 0x80, 0x00, 0xE8,
3504
35050x00, 0x80, 0x00, 0xE8,
35060x00, 0x80, 0x00, 0xE8,
3507
3508};
3509
3510static unsigned char warp_g200_tgzsaf[] = {
3511
35120x00, 0x80, 0x00, 0xE8,
35130x00, 0x80, 0x00, 0xE8,
3514
35150x00, 0x80, 0x00, 0xE8,
35160x00, 0x80, 0x00, 0xE8,
3517
35180x00, 0x80, 0x00, 0xE8,
35190x00, 0x80, 0x00, 0xE8,
3520
35210x00, 0x98, 0xA0, 0xE9,
35220x40, 0x40, 0xD8, 0xEC,
3523
35240xFF, 0x80, 0xC0, 0xE9,
35250x00, 0x80, 0x00, 0xE8,
3526
35270x1F, 0xD7, 0x18, 0xBD,
35280x3F, 0xD7, 0x22, 0xBD,
3529
35300x81, 0x04,
35310x89, 0x04,
35320x01, 0x04,
35330x09, 0x04,
3534
35350xC9, 0x41, 0xC0, 0xEC,
35360x11, 0x04,
35370x00, 0xE0,
3538
35390x41, 0xCC, 0x41, 0xCD,
35400x49, 0xCC, 0x49, 0xCD,
3541
35420xD1, 0x41, 0xC0, 0xEC,
35430x51, 0xCC, 0x51, 0xCD,
3544
35450x80, 0x04,
35460x10, 0x04,
35470x08, 0x04,
35480x00, 0xE0,
3549
35500x00, 0xCC, 0xC0, 0xCD,
35510xD1, 0x49, 0xC0, 0xEC,
3552
35530x8A, 0x1F, 0x20, 0xE9,
35540x8B, 0x3F, 0x20, 0xE9,
3555
35560x41, 0x3C, 0x41, 0xAD,
35570x49, 0x3C, 0x49, 0xAD,
3558
35590x10, 0xCC, 0x10, 0xCD,
35600x08, 0xCC, 0x08, 0xCD,
3561
35620xB9, 0x41, 0x49, 0xBB,
35630x1F, 0xF0, 0x41, 0xCD,
3564
35650x51, 0x3C, 0x51, 0xAD,
35660x00, 0x98, 0x80, 0xE9,
3567
35680x94, 0x80, 0x07, 0xEA,
35690x24, 0x1F, 0x20, 0xE9,
3570
35710x21, 0x45, 0x80, 0xE8,
35720x1A, 0x4D, 0x80, 0xE8,
3573
35740x31, 0x55, 0x80, 0xE8,
35750x00, 0x80, 0x00, 0xE8,
3576
35770x15, 0x41, 0x49, 0xBD,
35780x1D, 0x41, 0x51, 0xBD,
3579
35800x2E, 0x41, 0x2A, 0xB8,
35810x34, 0x53, 0xA0, 0xE8,
3582
35830x15, 0x30,
35840x1D, 0x30,
35850x58, 0xE3,
35860x00, 0xE0,
3587
35880xB5, 0x40, 0x48, 0xBD,
35890x3D, 0x40, 0x50, 0xBD,
3590
35910x24, 0x43, 0xA0, 0xE8,
35920x2C, 0x4B, 0xA0, 0xE8,
3593
35940x15, 0x72,
35950x09, 0xE3,
35960x00, 0xE0,
35970x1D, 0x72,
3598
35990x35, 0x30,
36000xB5, 0x30,
36010xBD, 0x30,
36020x3D, 0x30,
3603
36040x9C, 0x97, 0x57, 0x9F,
36050x00, 0x80, 0x00, 0xE8,
3606
36070x6C, 0x64, 0xC8, 0xEC,
36080x98, 0xE1,
36090xB5, 0x05,
3610
36110xBD, 0x05,
36120x2E, 0x30,
36130x32, 0xC0, 0xA0, 0xE8,
3614
36150x33, 0xC0, 0xA0, 0xE8,
36160x74, 0x64, 0xC8, 0xEC,
3617
36180x40, 0x3C, 0x40, 0xAD,
36190x32, 0x6A,
36200x2A, 0x30,
3621
36220x20, 0x73,
36230x33, 0x6A,
36240x00, 0xE0,
36250x28, 0x73,
3626
36270x1C, 0x72,
36280x83, 0xE2,
36290x80, 0x80, 0x15, 0xEA,
3630
36310xB8, 0x3D, 0x28, 0xDF,
36320x30, 0x35, 0x20, 0xDF,
3633
36340x40, 0x30,
36350x00, 0xE0,
36360xCC, 0xE2,
36370x64, 0x72,
3638
36390x25, 0x42, 0x52, 0xBF,
36400x2D, 0x42, 0x4A, 0xBF,
3641
36420x30, 0x2E, 0x30, 0xDF,
36430x38, 0x2E, 0x38, 0xDF,
3644
36450x18, 0x1D, 0x45, 0xE9,
36460x1E, 0x15, 0x45, 0xE9,
3647
36480x2B, 0x49, 0x51, 0xBD,
36490x00, 0xE0,
36500x1F, 0x73,
3651
36520x38, 0x38, 0x40, 0xAF,
36530x30, 0x30, 0x40, 0xAF,
3654
36550x24, 0x1F, 0x24, 0xDF,
36560x1D, 0x32, 0x20, 0xE9,
3657
36580x2C, 0x1F, 0x2C, 0xDF,
36590x1A, 0x33, 0x20, 0xE9,
3660
36610xB0, 0x10,
36620x08, 0xE3,
36630x40, 0x10,
36640xB8, 0x10,
3665
36660x26, 0xF0, 0x30, 0xCD,
36670x2F, 0xF0, 0x38, 0xCD,
3668
36690x2B, 0x80, 0x20, 0xE9,
36700x2A, 0x80, 0x20, 0xE9,
3671
36720xA6, 0x20,
36730x88, 0xE2,
36740x00, 0xE0,
36750xAF, 0x20,
3676
36770x28, 0x2A, 0x26, 0xAF,
36780x20, 0x2A, 0xC0, 0xAF,
3679
36800x34, 0x1F, 0x34, 0xDF,
36810x46, 0x24, 0x46, 0xDF,
3682
36830x28, 0x30, 0x80, 0xBF,
36840x20, 0x38, 0x80, 0xBF,
3685
36860x47, 0x24, 0x47, 0xDF,
36870x4E, 0x2C, 0x4E, 0xDF,
3688
36890x4F, 0x2C, 0x4F, 0xDF,
36900x56, 0x34, 0x56, 0xDF,
3691
36920x28, 0x15, 0x28, 0xDF,
36930x20, 0x1D, 0x20, 0xDF,
3694
36950x57, 0x34, 0x57, 0xDF,
36960x00, 0xE0,
36970x1D, 0x05,
3698
36990x04, 0x80, 0x10, 0xEA,
37000x89, 0xE2,
37010x2B, 0x30,
3702
37030x3F, 0xC1, 0x1D, 0xBD,
37040x00, 0x80, 0x00, 0xE8,
3705
37060x00, 0x80, 0x00, 0xE8,
37070x00, 0x80, 0x00, 0xE8,
3708
37090xA0, 0x68,
37100xBF, 0x25,
37110x00, 0x80, 0x00, 0xE8,
3712
37130x20, 0xC0, 0x20, 0xAF,
37140x28, 0x05,
37150x97, 0x74,
3716
37170x00, 0xE0,
37180x2A, 0x10,
37190x16, 0xC0, 0x20, 0xE9,
3720
37210x04, 0x80, 0x10, 0xEA,
37220x8C, 0xE2,
37230x95, 0x05,
3724
37250x28, 0xC1, 0x28, 0xAD,
37260x1F, 0xC1, 0x15, 0xBD,
3727
37280x00, 0x80, 0x00, 0xE8,
37290x00, 0x80, 0x00, 0xE8,
3730
37310xA8, 0x67,
37320x9F, 0x6B,
37330x00, 0x80, 0x00, 0xE8,
3734
37350x28, 0xC0, 0x28, 0xAD,
37360x1D, 0x25,
37370x20, 0x05,
3738
37390x28, 0x32, 0x80, 0xAD,
37400x40, 0x2A, 0x40, 0xBD,
3741
37420x1C, 0x80, 0x20, 0xE9,
37430x20, 0x33, 0x20, 0xAD,
3744
37450x20, 0x73,
37460x00, 0xE0,
37470xB6, 0x49, 0x51, 0xBB,
3748
37490x26, 0x2F, 0xB0, 0xE8,
37500x19, 0x20, 0x20, 0xE9,
3751
37520x35, 0x20, 0x35, 0xDF,
37530x3D, 0x20, 0x3D, 0xDF,
3754
37550x15, 0x20, 0x15, 0xDF,
37560x1D, 0x20, 0x1D, 0xDF,
3757
37580x26, 0xD0, 0x26, 0xCD,
37590x29, 0x49, 0x2A, 0xB8,
3760
37610x26, 0x40, 0x80, 0xBD,
37620x3B, 0x48, 0x50, 0xBD,
3763
37640x3E, 0x54, 0x57, 0x9F,
37650x00, 0xE0,
37660x82, 0xE1,
3767
37680x1E, 0xAF, 0x59, 0x9F,
37690x00, 0x80, 0x00, 0xE8,
3770
37710x26, 0x30,
37720x29, 0x30,
37730x48, 0x3C, 0x48, 0xAD,
3774
37750x2B, 0x72,
37760xC2, 0xE1,
37770x2C, 0xC0, 0x44, 0xC2,
3778
37790x05, 0x24, 0x34, 0xBF,
37800x0D, 0x24, 0x2C, 0xBF,
3781
37820x2D, 0x46, 0x4E, 0xBF,
37830x25, 0x46, 0x56, 0xBF,
3784
37850x20, 0x1D, 0x6F, 0x8F,
37860x32, 0x3E, 0x5F, 0xE9,
3787
37880x3E, 0x50, 0x56, 0x9F,
37890x00, 0xE0,
37900x3B, 0x30,
3791
37920x1E, 0x8F, 0x51, 0x9F,
37930x33, 0x1E, 0x5F, 0xE9,
3794
37950x05, 0x44, 0x54, 0xB2,
37960x0D, 0x44, 0x4C, 0xB2,
3797
37980x19, 0xC0, 0xB0, 0xE8,
37990x34, 0xC0, 0x44, 0xC4,
3800
38010x33, 0x73,
38020x00, 0xE0,
38030x3E, 0x62, 0x57, 0x9F,
3804
38050x1E, 0xAF, 0x59, 0x9F,
38060x00, 0xE0,
38070x0D, 0x20,
3808
38090x84, 0x3E, 0x58, 0xE9,
38100x28, 0x1D, 0x6F, 0x8F,
3811
38120x05, 0x20,
38130x00, 0xE0,
38140x85, 0x1E, 0x58, 0xE9,
3815
38160x9B, 0x3B, 0x33, 0xDF,
38170x20, 0x20, 0x42, 0xAF,
3818
38190x30, 0x42, 0x56, 0x9F,
38200x80, 0x3E, 0x57, 0xE9,
3821
38220x3F, 0x8F, 0x51, 0x9F,
38230x30, 0x80, 0x5F, 0xE9,
3824
38250x28, 0x28, 0x24, 0xAF,
38260x81, 0x1E, 0x57, 0xE9,
3827
38280x05, 0x47, 0x57, 0xBF,
38290x0D, 0x47, 0x4F, 0xBF,
3830
38310x88, 0x80, 0x58, 0xE9,
38320x1B, 0x29, 0x1B, 0xDF,
3833
38340x30, 0x1D, 0x6F, 0x8F,
38350x3A, 0x30, 0x4F, 0xE9,
3836
38370x1C, 0x30, 0x26, 0xDF,
38380x09, 0xE3,
38390x3B, 0x05,
3840
38410x3E, 0x50, 0x56, 0x9F,
38420x3B, 0x3F, 0x4F, 0xE9,
3843
38440x1E, 0x8F, 0x51, 0x9F,
38450x00, 0xE0,
38460xAC, 0x20,
3847
38480x2D, 0x44, 0x4C, 0xB4,
38490x2C, 0x1C, 0xC0, 0xAF,
3850
38510x25, 0x44, 0x54, 0xB4,
38520x00, 0xE0,
38530xC8, 0x30,
3854
38550x30, 0x46, 0x30, 0xAF,
38560x1B, 0x1B, 0x48, 0xAF,
3857
38580x00, 0xE0,
38590x25, 0x20,
38600x38, 0x2C, 0x4F, 0xE9,
3861
38620x86, 0x80, 0x57, 0xE9,
38630x38, 0x1D, 0x6F, 0x8F,
3864
38650x28, 0x74,
38660x00, 0xE0,
38670x0D, 0x44, 0x4C, 0xB0,
3868
38690x05, 0x44, 0x54, 0xB0,
38700x2D, 0x20,
38710x9B, 0x10,
3872
38730x82, 0x3E, 0x57, 0xE9,
38740x32, 0xF0, 0x1B, 0xCD,
3875
38760x1E, 0xBD, 0x59, 0x9F,
38770x83, 0x1E, 0x57, 0xE9,
3878
38790x38, 0x47, 0x38, 0xAF,
38800x34, 0x20,
38810x2A, 0x30,
3882
38830x00, 0xE0,
38840x0D, 0x20,
38850x32, 0x20,
38860x05, 0x20,
3887
38880x87, 0x80, 0x57, 0xE9,
38890x1F, 0x54, 0x57, 0x9F,
3890
38910x17, 0x42, 0x56, 0x9F,
38920x00, 0xE0,
38930x3B, 0x6A,
3894
38950x3F, 0x8F, 0x51, 0x9F,
38960x37, 0x1E, 0x4F, 0xE9,
3897
38980x37, 0x32, 0x2A, 0xAF,
38990x00, 0xE0,
39000x32, 0x00,
3901
39020x00, 0x80, 0x00, 0xE8,
39030x27, 0xC0, 0x44, 0xC0,
3904
39050x36, 0x1F, 0x4F, 0xE9,
39060x1F, 0x1F, 0x26, 0xDF,
3907
39080x37, 0x1B, 0x37, 0xBF,
39090x17, 0x26, 0x17, 0xDF,
3910
39110x3E, 0x17, 0x4F, 0xE9,
39120x3F, 0x3F, 0x4F, 0xE9,
3913
39140x34, 0x1F, 0x34, 0xAF,
39150x2B, 0x05,
39160xA7, 0x20,
3917
39180x33, 0x2B, 0x37, 0xDF,
39190x27, 0x17, 0xC0, 0xAF,
3920
39210x34, 0x80, 0x4F, 0xE9,
39220x00, 0x80, 0x00, 0xE8,
3923
39240x2D, 0x21, 0x1A, 0xB0,
39250x25, 0x21, 0x31, 0xB0,
3926
39270x0D, 0x21, 0x1A, 0xB2,
39280x05, 0x21, 0x31, 0xB2,
3929
39300x03, 0x80, 0x2A, 0xEA,
39310x17, 0xC1, 0x2B, 0xBD,
3932
39330x2D, 0x20,
39340x25, 0x20,
39350x05, 0x20,
39360x0D, 0x20,
3937
39380xB3, 0x68,
39390x97, 0x25,
39400x00, 0x80, 0x00, 0xE8,
3941
39420x33, 0xC0, 0x33, 0xAF,
39430x2F, 0xC0, 0x21, 0xC0,
3944
39450x16, 0x42, 0x56, 0x9F,
39460x3C, 0x27, 0x4F, 0xE9,
3947
39480x1E, 0x62, 0x57, 0x9F,
39490x00, 0x80, 0x00, 0xE8,
3950
39510x25, 0x21, 0x31, 0xB4,
39520x2D, 0x21, 0x1A, 0xB4,
3953
39540x3F, 0x2F, 0x5D, 0x9F,
39550x00, 0x80, 0x00, 0xE8,
3956
39570x33, 0x05,
39580x00, 0xE0,
39590x28, 0x19, 0x60, 0xEC,
3960
39610x0D, 0x21, 0x1A, 0xB6,
39620x05, 0x21, 0x31, 0xB6,
3963
39640x37, 0x0F, 0x5C, 0x9F,
39650x00, 0xE0,
39660x2F, 0x20,
3967
39680x23, 0x3B, 0x33, 0xAD,
39690x1E, 0x26, 0x1E, 0xDF,
3970
39710xA7, 0x1E, 0x4F, 0xE9,
39720x17, 0x26, 0x16, 0xDF,
3973
39740x2D, 0x20,
39750x00, 0xE0,
39760xA8, 0x3F, 0x4F, 0xE9,
3977
39780x2F, 0x2F, 0x1E, 0xAF,
39790x25, 0x20,
39800x00, 0xE0,
3981
39820xA4, 0x16, 0x4F, 0xE9,
39830x0F, 0xC0, 0x21, 0xC2,
3984
39850xA6, 0x80, 0x4F, 0xE9,
39860x1F, 0x62, 0x57, 0x9F,
3987
39880x0D, 0x20,
39890x05, 0x20,
39900x2F, 0xC0, 0x21, 0xC6,
3991
39920x2D, 0x44, 0x4C, 0xB6,
39930x25, 0x44, 0x54, 0xB6,
3994
39950x3F, 0x2F, 0x5D, 0x9F,
39960x00, 0xE0,
39970x0F, 0x20,
3998
39990x2D, 0x20,
40000x25, 0x20,
40010x07, 0xC0, 0x44, 0xC6,
4002
40030x17, 0x50, 0x56, 0x9F,
40040xA5, 0x37, 0x4F, 0xE9,
4005
40060x06, 0xC0, 0x21, 0xC4,
40070x0F, 0x17, 0x0F, 0xAF,
4008
40090x37, 0x0F, 0x5C, 0x9F,
40100x00, 0x80, 0x00, 0xE8,
4011
40120x1E, 0x62, 0x57, 0x9F,
40130x00, 0x80, 0x00, 0xE8,
4014
40150x3E, 0x3D, 0x5D, 0x9F,
40160x00, 0xE0,
40170x07, 0x20,
4018
40190x2F, 0x20,
40200x00, 0xE0,
40210xA3, 0x0F, 0x4F, 0xE9,
4022
40230x06, 0x20,
40240x00, 0xE0,
40250x1F, 0x26, 0x1F, 0xDF,
4026
40270x17, 0x26, 0x17, 0xDF,
40280xA1, 0x1F, 0x4F, 0xE9,
4029
40300x1E, 0x26, 0x1E, 0xDF,
40310x9D, 0x1E, 0x4F, 0xE9,
4032
40330x35, 0x17, 0x4F, 0xE9,
40340xA2, 0x3F, 0x4F, 0xE9,
4035
40360x06, 0x06, 0x1F, 0xAF,
40370x39, 0x37, 0x4F, 0xE9,
4038
40390x2F, 0x2F, 0x17, 0xAF,
40400x07, 0x07, 0x1E, 0xAF,
4041
40420xA0, 0x80, 0x4F, 0xE9,
40430x9E, 0x3E, 0x4F, 0xE9,
4044
40450x31, 0x80, 0x4F, 0xE9,
40460x9C, 0x80, 0x4F, 0xE9,
4047
40480x00, 0x80, 0x00, 0xE8,
40490x57, 0x39, 0x20, 0xE9,
4050
40510x16, 0x28, 0x20, 0xE9,
40520x1D, 0x3B, 0x20, 0xE9,
4053
40540x1E, 0x2B, 0x20, 0xE9,
40550x2B, 0x32, 0x20, 0xE9,
4056
40570x1C, 0x23, 0x20, 0xE9,
40580x57, 0x36, 0x20, 0xE9,
4059
40600x00, 0x80, 0xA0, 0xE9,
40610x40, 0x40, 0xD8, 0xEC,
4062
40630xFF, 0x80, 0xC0, 0xE9,
40640x90, 0xE2,
40650x00, 0xE0,
4066
40670x63, 0xFF, 0x20, 0xEA,
40680x19, 0xC8, 0xC1, 0xCD,
4069
40700x1F, 0xD7, 0x18, 0xBD,
40710x3F, 0xD7, 0x22, 0xBD,
4072
40730x9F, 0x41, 0x49, 0xBD,
40740x00, 0x80, 0x00, 0xE8,
4075
40760x25, 0x41, 0x49, 0xBD,
40770x2D, 0x41, 0x51, 0xBD,
4078
40790x0D, 0x80, 0x07, 0xEA,
40800x00, 0x80, 0x00, 0xE8,
4081
40820x35, 0x40, 0x48, 0xBD,
40830x3D, 0x40, 0x50, 0xBD,
4084
40850x00, 0x80, 0x00, 0xE8,
40860x25, 0x30,
40870x2D, 0x30,
4088
40890x35, 0x30,
40900xB5, 0x30,
40910xBD, 0x30,
40920x3D, 0x30,
4093
40940x9C, 0xA7, 0x5B, 0x9F,
40950x00, 0x80, 0x00, 0xE8,
4096
40970x00, 0x80, 0x00, 0xE8,
40980x00, 0x80, 0x00, 0xE8,
4099
41000x00, 0x80, 0x00, 0xE8,
41010x00, 0x80, 0x00, 0xE8,
4102
41030x00, 0x80, 0x00, 0xE8,
41040x00, 0x80, 0x00, 0xE8,
4105
41060x00, 0x80, 0x00, 0xE8,
41070x00, 0x80, 0x00, 0xE8,
4108
41090x62, 0xFF, 0x0A, 0xEA,
41100x00, 0x80, 0x00, 0xE8,
4111
41120xC9, 0x41, 0xC8, 0xEC,
41130x42, 0xE1,
41140x00, 0xE0,
4115
41160x60, 0xFF, 0x20, 0xEA,
41170x00, 0x80, 0x00, 0xE8,
4118
41190x00, 0x80, 0x00, 0xE8,
41200x00, 0x80, 0x00, 0xE8,
4121
41220xC8, 0x40, 0xC0, 0xEC,
41230x00, 0x80, 0x00, 0xE8,
4124
41250x5D, 0xFF, 0x20, 0xEA,
41260x00, 0x80, 0x00, 0xE8,
4127
41280x00, 0x80, 0x00, 0xE8,
41290x00, 0x80, 0x00, 0xE8,
4130
4131};
4132
4133static unsigned char warp_g200_tgzsf[] = {
4134
41350x00, 0x80, 0x00, 0xE8,
41360x00, 0x80, 0x00, 0xE8,
4137
41380x00, 0x80, 0x00, 0xE8,
41390x00, 0x80, 0x00, 0xE8,
4140
41410x00, 0x80, 0x00, 0xE8,
41420x00, 0x80, 0x00, 0xE8,
4143
41440x00, 0x80, 0x00, 0xE8,
41450x00, 0x80, 0x00, 0xE8,
4146
41470x00, 0x80, 0x00, 0xE8,
41480x00, 0x80, 0x00, 0xE8,
4149
41500x00, 0x80, 0x00, 0xE8,
41510x00, 0x80, 0x00, 0xE8,
4152
41530x00, 0x80, 0x00, 0xE8,
41540x00, 0x80, 0x00, 0xE8,
4155
41560x00, 0x80, 0x00, 0xE8,
41570x00, 0x80, 0x00, 0xE8,
4158
41590x00, 0x80, 0x00, 0xE8,
41600x00, 0x80, 0x00, 0xE8,
4161
41620x00, 0x80, 0x00, 0xE8,
41630x00, 0x80, 0x00, 0xE8,
4164
41650x00, 0x80, 0x00, 0xE8,
41660x00, 0x80, 0x00, 0xE8,
4167
41680x00, 0x80, 0x00, 0xE8,
41690x00, 0x80, 0x00, 0xE8,
4170
41710x00, 0x80, 0x00, 0xE8,
41720x00, 0x80, 0x00, 0xE8,
4173
41740x00, 0x98, 0xA0, 0xE9,
41750x40, 0x40, 0xD8, 0xEC,
4176
41770xFF, 0x80, 0xC0, 0xE9,
41780x00, 0x80, 0x00, 0xE8,
4179
41800x1F, 0xD7, 0x18, 0xBD,
41810x3F, 0xD7, 0x22, 0xBD,
4182
41830x81, 0x04,
41840x89, 0x04,
41850x01, 0x04,
41860x09, 0x04,
4187
41880xC9, 0x41, 0xC0, 0xEC,
41890x11, 0x04,
41900x00, 0xE0,
4191
41920x41, 0xCC, 0x41, 0xCD,
41930x49, 0xCC, 0x49, 0xCD,
4194
41950xD1, 0x41, 0xC0, 0xEC,
41960x51, 0xCC, 0x51, 0xCD,
4197
41980x80, 0x04,
41990x10, 0x04,
42000x08, 0x04,
42010x00, 0xE0,
4202
42030x00, 0xCC, 0xC0, 0xCD,
42040xD1, 0x49, 0xC0, 0xEC,
4205
42060x8A, 0x1F, 0x20, 0xE9,
42070x8B, 0x3F, 0x20, 0xE9,
4208
42090x41, 0x3C, 0x41, 0xAD,
42100x49, 0x3C, 0x49, 0xAD,
4211
42120x10, 0xCC, 0x10, 0xCD,
42130x08, 0xCC, 0x08, 0xCD,
4214
42150xB9, 0x41, 0x49, 0xBB,
42160x1F, 0xF0, 0x41, 0xCD,
4217
42180x51, 0x3C, 0x51, 0xAD,
42190x00, 0x98, 0x80, 0xE9,
4220
42210x8F, 0x80, 0x07, 0xEA,
42220x24, 0x1F, 0x20, 0xE9,
4223
42240x21, 0x45, 0x80, 0xE8,
42250x1A, 0x4D, 0x80, 0xE8,
4226
42270x31, 0x55, 0x80, 0xE8,
42280x00, 0x80, 0x00, 0xE8,
4229
42300x15, 0x41, 0x49, 0xBD,
42310x1D, 0x41, 0x51, 0xBD,
4232
42330x2E, 0x41, 0x2A, 0xB8,
42340x34, 0x53, 0xA0, 0xE8,
4235
42360x15, 0x30,
42370x1D, 0x30,
42380x58, 0xE3,
42390x00, 0xE0,
4240
42410xB5, 0x40, 0x48, 0xBD,
42420x3D, 0x40, 0x50, 0xBD,
4243
42440x24, 0x43, 0xA0, 0xE8,
42450x2C, 0x4B, 0xA0, 0xE8,
4246
42470x15, 0x72,
42480x09, 0xE3,
42490x00, 0xE0,
42500x1D, 0x72,
4251
42520x35, 0x30,
42530xB5, 0x30,
42540xBD, 0x30,
42550x3D, 0x30,
4256
42570x9C, 0x97, 0x57, 0x9F,
42580x00, 0x80, 0x00, 0xE8,
4259
42600x6C, 0x64, 0xC8, 0xEC,
42610x98, 0xE1,
42620xB5, 0x05,
4263
42640xBD, 0x05,
42650x2E, 0x30,
42660x32, 0xC0, 0xA0, 0xE8,
4267
42680x33, 0xC0, 0xA0, 0xE8,
42690x74, 0x64, 0xC8, 0xEC,
4270
42710x40, 0x3C, 0x40, 0xAD,
42720x32, 0x6A,
42730x2A, 0x30,
4274
42750x20, 0x73,
42760x33, 0x6A,
42770x00, 0xE0,
42780x28, 0x73,
4279
42800x1C, 0x72,
42810x83, 0xE2,
42820x7B, 0x80, 0x15, 0xEA,
4283
42840xB8, 0x3D, 0x28, 0xDF,
42850x30, 0x35, 0x20, 0xDF,
4286
42870x40, 0x30,
42880x00, 0xE0,
42890xCC, 0xE2,
42900x64, 0x72,
4291
42920x25, 0x42, 0x52, 0xBF,
42930x2D, 0x42, 0x4A, 0xBF,
4294
42950x30, 0x2E, 0x30, 0xDF,
42960x38, 0x2E, 0x38, 0xDF,
4297
42980x18, 0x1D, 0x45, 0xE9,
42990x1E, 0x15, 0x45, 0xE9,
4300
43010x2B, 0x49, 0x51, 0xBD,
43020x00, 0xE0,
43030x1F, 0x73,
4304
43050x38, 0x38, 0x40, 0xAF,
43060x30, 0x30, 0x40, 0xAF,
4307
43080x24, 0x1F, 0x24, 0xDF,
43090x1D, 0x32, 0x20, 0xE9,
4310
43110x2C, 0x1F, 0x2C, 0xDF,
43120x1A, 0x33, 0x20, 0xE9,
4313
43140xB0, 0x10,
43150x08, 0xE3,
43160x40, 0x10,
43170xB8, 0x10,
4318
43190x26, 0xF0, 0x30, 0xCD,
43200x2F, 0xF0, 0x38, 0xCD,
4321
43220x2B, 0x80, 0x20, 0xE9,
43230x2A, 0x80, 0x20, 0xE9,
4324
43250xA6, 0x20,
43260x88, 0xE2,
43270x00, 0xE0,
43280xAF, 0x20,
4329
43300x28, 0x2A, 0x26, 0xAF,
43310x20, 0x2A, 0xC0, 0xAF,
4332
43330x34, 0x1F, 0x34, 0xDF,
43340x46, 0x24, 0x46, 0xDF,
4335
43360x28, 0x30, 0x80, 0xBF,
43370x20, 0x38, 0x80, 0xBF,
4338
43390x47, 0x24, 0x47, 0xDF,
43400x4E, 0x2C, 0x4E, 0xDF,
4341
43420x4F, 0x2C, 0x4F, 0xDF,
43430x56, 0x34, 0x56, 0xDF,
4344
43450x28, 0x15, 0x28, 0xDF,
43460x20, 0x1D, 0x20, 0xDF,
4347
43480x57, 0x34, 0x57, 0xDF,
43490x00, 0xE0,
43500x1D, 0x05,
4351
43520x04, 0x80, 0x10, 0xEA,
43530x89, 0xE2,
43540x2B, 0x30,
4355
43560x3F, 0xC1, 0x1D, 0xBD,
43570x00, 0x80, 0x00, 0xE8,
4358
43590x00, 0x80, 0x00, 0xE8,
43600x00, 0x80, 0x00, 0xE8,
4361
43620xA0, 0x68,
43630xBF, 0x25,
43640x00, 0x80, 0x00, 0xE8,
4365
43660x20, 0xC0, 0x20, 0xAF,
43670x28, 0x05,
43680x97, 0x74,
4369
43700x00, 0xE0,
43710x2A, 0x10,
43720x16, 0xC0, 0x20, 0xE9,
4373
43740x04, 0x80, 0x10, 0xEA,
43750x8C, 0xE2,
43760x95, 0x05,
4377
43780x28, 0xC1, 0x28, 0xAD,
43790x1F, 0xC1, 0x15, 0xBD,
4380
43810x00, 0x80, 0x00, 0xE8,
43820x00, 0x80, 0x00, 0xE8,
4383
43840xA8, 0x67,
43850x9F, 0x6B,
43860x00, 0x80, 0x00, 0xE8,
4387
43880x28, 0xC0, 0x28, 0xAD,
43890x1D, 0x25,
43900x20, 0x05,
4391
43920x28, 0x32, 0x80, 0xAD,
43930x40, 0x2A, 0x40, 0xBD,
4394
43950x1C, 0x80, 0x20, 0xE9,
43960x20, 0x33, 0x20, 0xAD,
4397
43980x20, 0x73,
43990x00, 0xE0,
44000xB6, 0x49, 0x51, 0xBB,
4401
44020x26, 0x2F, 0xB0, 0xE8,
44030x19, 0x20, 0x20, 0xE9,
4404
44050x35, 0x20, 0x35, 0xDF,
44060x3D, 0x20, 0x3D, 0xDF,
4407
44080x15, 0x20, 0x15, 0xDF,
44090x1D, 0x20, 0x1D, 0xDF,
4410
44110x26, 0xD0, 0x26, 0xCD,
44120x29, 0x49, 0x2A, 0xB8,
4413
44140x26, 0x40, 0x80, 0xBD,
44150x3B, 0x48, 0x50, 0xBD,
4416
44170x3E, 0x54, 0x57, 0x9F,
44180x00, 0xE0,
44190x82, 0xE1,
4420
44210x1E, 0xAF, 0x59, 0x9F,
44220x00, 0x80, 0x00, 0xE8,
4423
44240x26, 0x30,
44250x29, 0x30,
44260x48, 0x3C, 0x48, 0xAD,
4427
44280x2B, 0x72,
44290xC2, 0xE1,
44300x2C, 0xC0, 0x44, 0xC2,
4431
44320x05, 0x24, 0x34, 0xBF,
44330x0D, 0x24, 0x2C, 0xBF,
4434
44350x2D, 0x46, 0x4E, 0xBF,
44360x25, 0x46, 0x56, 0xBF,
4437
44380x20, 0x1D, 0x6F, 0x8F,
44390x32, 0x3E, 0x5F, 0xE9,
4440
44410x3E, 0x50, 0x56, 0x9F,
44420x00, 0xE0,
44430x3B, 0x30,
4444
44450x1E, 0x8F, 0x51, 0x9F,
44460x33, 0x1E, 0x5F, 0xE9,
4447
44480x05, 0x44, 0x54, 0xB2,
44490x0D, 0x44, 0x4C, 0xB2,
4450
44510x19, 0xC0, 0xB0, 0xE8,
44520x34, 0xC0, 0x44, 0xC4,
4453
44540x33, 0x73,
44550x00, 0xE0,
44560x3E, 0x62, 0x57, 0x9F,
4457
44580x1E, 0xAF, 0x59, 0x9F,
44590x00, 0xE0,
44600x0D, 0x20,
4461
44620x84, 0x3E, 0x58, 0xE9,
44630x28, 0x1D, 0x6F, 0x8F,
4464
44650x05, 0x20,
44660x00, 0xE0,
44670x85, 0x1E, 0x58, 0xE9,
4468
44690x9B, 0x3B, 0x33, 0xDF,
44700x20, 0x20, 0x42, 0xAF,
4471
44720x30, 0x42, 0x56, 0x9F,
44730x80, 0x3E, 0x57, 0xE9,
4474
44750x3F, 0x8F, 0x51, 0x9F,
44760x30, 0x80, 0x5F, 0xE9,
4477
44780x28, 0x28, 0x24, 0xAF,
44790x81, 0x1E, 0x57, 0xE9,
4480
44810x05, 0x47, 0x57, 0xBF,
44820x0D, 0x47, 0x4F, 0xBF,
4483
44840x88, 0x80, 0x58, 0xE9,
44850x1B, 0x29, 0x1B, 0xDF,
4486
44870x30, 0x1D, 0x6F, 0x8F,
44880x3A, 0x30, 0x4F, 0xE9,
4489
44900x1C, 0x30, 0x26, 0xDF,
44910x09, 0xE3,
44920x3B, 0x05,
4493
44940x3E, 0x50, 0x56, 0x9F,
44950x3B, 0x3F, 0x4F, 0xE9,
4496
44970x1E, 0x8F, 0x51, 0x9F,
44980x00, 0xE0,
44990xAC, 0x20,
4500
45010x2D, 0x44, 0x4C, 0xB4,
45020x2C, 0x1C, 0xC0, 0xAF,
4503
45040x25, 0x44, 0x54, 0xB4,
45050x00, 0xE0,
45060xC8, 0x30,
4507
45080x30, 0x46, 0x30, 0xAF,
45090x1B, 0x1B, 0x48, 0xAF,
4510
45110x00, 0xE0,
45120x25, 0x20,
45130x38, 0x2C, 0x4F, 0xE9,
4514
45150x86, 0x80, 0x57, 0xE9,
45160x38, 0x1D, 0x6F, 0x8F,
4517
45180x28, 0x74,
45190x00, 0xE0,
45200x0D, 0x44, 0x4C, 0xB0,
4521
45220x05, 0x44, 0x54, 0xB0,
45230x2D, 0x20,
45240x9B, 0x10,
4525
45260x82, 0x3E, 0x57, 0xE9,
45270x32, 0xF0, 0x1B, 0xCD,
4528
45290x1E, 0xBD, 0x59, 0x9F,
45300x83, 0x1E, 0x57, 0xE9,
4531
45320x38, 0x47, 0x38, 0xAF,
45330x34, 0x20,
45340x2A, 0x30,
4535
45360x00, 0xE0,
45370x0D, 0x20,
45380x32, 0x20,
45390x05, 0x20,
4540
45410x87, 0x80, 0x57, 0xE9,
45420x1F, 0x54, 0x57, 0x9F,
4543
45440x17, 0x42, 0x56, 0x9F,
45450x00, 0xE0,
45460x3B, 0x6A,
4547
45480x3F, 0x8F, 0x51, 0x9F,
45490x37, 0x1E, 0x4F, 0xE9,
4550
45510x37, 0x32, 0x2A, 0xAF,
45520x00, 0xE0,
45530x32, 0x00,
4554
45550x00, 0x80, 0x00, 0xE8,
45560x27, 0xC0, 0x44, 0xC0,
4557
45580x36, 0x1F, 0x4F, 0xE9,
45590x1F, 0x1F, 0x26, 0xDF,
4560
45610x37, 0x1B, 0x37, 0xBF,
45620x17, 0x26, 0x17, 0xDF,
4563
45640x3E, 0x17, 0x4F, 0xE9,
45650x3F, 0x3F, 0x4F, 0xE9,
4566
45670x34, 0x1F, 0x34, 0xAF,
45680x2B, 0x05,
45690xA7, 0x20,
4570
45710x33, 0x2B, 0x37, 0xDF,
45720x27, 0x17, 0xC0, 0xAF,
4573
45740x34, 0x80, 0x4F, 0xE9,
45750x00, 0x80, 0x00, 0xE8,
4576
45770x2D, 0x21, 0x1A, 0xB0,
45780x25, 0x21, 0x31, 0xB0,
4579
45800x0D, 0x21, 0x1A, 0xB2,
45810x05, 0x21, 0x31, 0xB2,
4582
45830x03, 0x80, 0x2A, 0xEA,
45840x17, 0xC1, 0x2B, 0xBD,
4585
45860x2D, 0x20,
45870x25, 0x20,
45880x05, 0x20,
45890x0D, 0x20,
4590
45910xB3, 0x68,
45920x97, 0x25,
45930x00, 0x80, 0x00, 0xE8,
4594
45950x33, 0xC0, 0x33, 0xAF,
45960x2F, 0xC0, 0x21, 0xC0,
4597
45980x16, 0x42, 0x56, 0x9F,
45990x3C, 0x27, 0x4F, 0xE9,
4600
46010x1E, 0x62, 0x57, 0x9F,
46020x00, 0x80, 0x00, 0xE8,
4603
46040x25, 0x21, 0x31, 0xB4,
46050x2D, 0x21, 0x1A, 0xB4,
4606
46070x3F, 0x2F, 0x5D, 0x9F,
46080x00, 0x80, 0x00, 0xE8,
4609
46100x33, 0x05,
46110x00, 0xE0,
46120x28, 0x19, 0x60, 0xEC,
4613
46140x0D, 0x21, 0x1A, 0xB6,
46150x05, 0x21, 0x31, 0xB6,
4616
46170x37, 0x0F, 0x5C, 0x9F,
46180x00, 0xE0,
46190x2F, 0x20,
4620
46210x23, 0x3B, 0x33, 0xAD,
46220x1E, 0x26, 0x1E, 0xDF,
4623
46240xA7, 0x1E, 0x4F, 0xE9,
46250x17, 0x26, 0x16, 0xDF,
4626
46270x2D, 0x20,
46280x00, 0xE0,
46290xA8, 0x3F, 0x4F, 0xE9,
4630
46310x2F, 0x2F, 0x1E, 0xAF,
46320x25, 0x20,
46330x00, 0xE0,
4634
46350xA4, 0x16, 0x4F, 0xE9,
46360x0F, 0xC0, 0x21, 0xC2,
4637
46380xA6, 0x80, 0x4F, 0xE9,
46390x1F, 0x62, 0x57, 0x9F,
4640
46410x0D, 0x20,
46420x05, 0x20,
46430x2F, 0xC0, 0x21, 0xC6,
4644
46450x3F, 0x2F, 0x5D, 0x9F,
46460x00, 0xE0,
46470x0F, 0x20,
4648
46490x17, 0x50, 0x56, 0x9F,
46500xA5, 0x37, 0x4F, 0xE9,
4651
46520x06, 0xC0, 0x21, 0xC4,
46530x0F, 0x17, 0x0F, 0xAF,
4654
46550x37, 0x0F, 0x5C, 0x9F,
46560x00, 0x80, 0x00, 0xE8,
4657
46580x2F, 0x20,
46590x00, 0xE0,
46600xA3, 0x80, 0x4F, 0xE9,
4661
46620x06, 0x20,
46630x00, 0xE0,
46640x1F, 0x26, 0x1F, 0xDF,
4665
46660x17, 0x26, 0x17, 0xDF,
46670x35, 0x17, 0x4F, 0xE9,
4668
46690xA1, 0x1F, 0x4F, 0xE9,
46700xA2, 0x3F, 0x4F, 0xE9,
4671
46720x06, 0x06, 0x1F, 0xAF,
46730x39, 0x37, 0x4F, 0xE9,
4674
46750x2F, 0x2F, 0x17, 0xAF,
46760x00, 0x80, 0x00, 0xE8,
4677
46780xA0, 0x80, 0x4F, 0xE9,
46790x00, 0x80, 0x00, 0xE8,
4680
46810x31, 0x80, 0x4F, 0xE9,
46820x00, 0x80, 0x00, 0xE8,
4683
46840x00, 0x80, 0x00, 0xE8,
46850x57, 0x39, 0x20, 0xE9,
4686
46870x16, 0x28, 0x20, 0xE9,
46880x1D, 0x3B, 0x20, 0xE9,
4689
46900x1E, 0x2B, 0x20, 0xE9,
46910x2B, 0x32, 0x20, 0xE9,
4692
46930x1C, 0x23, 0x20, 0xE9,
46940x57, 0x36, 0x20, 0xE9,
4695
46960x00, 0x80, 0xA0, 0xE9,
46970x40, 0x40, 0xD8, 0xEC,
4698
46990xFF, 0x80, 0xC0, 0xE9,
47000x90, 0xE2,
47010x00, 0xE0,
4702
47030x68, 0xFF, 0x20, 0xEA,
47040x19, 0xC8, 0xC1, 0xCD,
4705
47060x1F, 0xD7, 0x18, 0xBD,
47070x3F, 0xD7, 0x22, 0xBD,
4708
47090x9F, 0x41, 0x49, 0xBD,
47100x00, 0x80, 0x00, 0xE8,
4711
47120x25, 0x41, 0x49, 0xBD,
47130x2D, 0x41, 0x51, 0xBD,
4714
47150x0D, 0x80, 0x07, 0xEA,
47160x00, 0x80, 0x00, 0xE8,
4717
47180x35, 0x40, 0x48, 0xBD,
47190x3D, 0x40, 0x50, 0xBD,
4720
47210x00, 0x80, 0x00, 0xE8,
47220x25, 0x30,
47230x2D, 0x30,
4724
47250x35, 0x30,
47260xB5, 0x30,
47270xBD, 0x30,
47280x3D, 0x30,
4729
47300x9C, 0xA7, 0x5B, 0x9F,
47310x00, 0x80, 0x00, 0xE8,
4732
47330x00, 0x80, 0x00, 0xE8,
47340x00, 0x80, 0x00, 0xE8,
4735
47360x00, 0x80, 0x00, 0xE8,
47370x00, 0x80, 0x00, 0xE8,
4738
47390x00, 0x80, 0x00, 0xE8,
47400x00, 0x80, 0x00, 0xE8,
4741
47420x00, 0x80, 0x00, 0xE8,
47430x00, 0x80, 0x00, 0xE8,
4744
47450x67, 0xFF, 0x0A, 0xEA,
47460x00, 0x80, 0x00, 0xE8,
4747
47480xC9, 0x41, 0xC8, 0xEC,
47490x42, 0xE1,
47500x00, 0xE0,
4751
47520x65, 0xFF, 0x20, 0xEA,
47530x00, 0x80, 0x00, 0xE8,
4754
47550x00, 0x80, 0x00, 0xE8,
47560x00, 0x80, 0x00, 0xE8,
4757
47580xC8, 0x40, 0xC0, 0xEC,
47590x00, 0x80, 0x00, 0xE8,
4760
47610x62, 0xFF, 0x20, 0xEA,
47620x00, 0x80, 0x00, 0xE8,
4763
47640x00, 0x80, 0x00, 0xE8,
47650x00, 0x80, 0x00, 0xE8,
4766
4767};
4768
4769static unsigned char warp_g400_t2gz[] = {
4770
47710x00, 0x8A, 0x98, 0xE9,
47720x00, 0x80, 0x00, 0xE8,
4773
47740x00, 0x80, 0xA0, 0xE9,
47750x00, 0x00, 0xD8, 0xEC,
4776
47770xFF, 0x80, 0xC0, 0xE9,
47780x00, 0x80, 0x00, 0xE8,
4779
47800x0A, 0x40, 0x50, 0xBF,
47810x2A, 0x40, 0x60, 0xBF,
4782
47830x32, 0x41, 0x51, 0xBF,
47840x3A, 0x41, 0x61, 0xBF,
4785
47860xC3, 0x6B,
47870xD3, 0x6B,
47880x00, 0x8A, 0x98, 0xE9,
4789
47900x73, 0x7B, 0xC8, 0xEC,
47910x96, 0xE2,
47920x41, 0x04,
4793
47940x7B, 0x43, 0xA0, 0xE8,
47950x73, 0x53, 0xA0, 0xE8,
4796
47970xAD, 0xEE, 0x23, 0x9F,
47980x00, 0xE0,
47990x51, 0x04,
4800
48010x90, 0xE2,
48020x61, 0x04,
48030x31, 0x46, 0xB1, 0xE8,
4804
48050x51, 0x41, 0xE0, 0xEC,
48060x39, 0x67, 0xB1, 0xE8,
4807
48080x00, 0x04,
48090x46, 0xE2,
48100x73, 0x63, 0xA0, 0xE8,
4811
48120x61, 0x41, 0xE0, 0xEC,
48130x31, 0x00,
48140x39, 0x00,
4815
48160x78, 0x80, 0x15, 0xEA,
48170x10, 0x04,
48180x20, 0x04,
4819
48200x61, 0x51, 0xE0, 0xEC,
48210x2F, 0x41, 0x60, 0xEA,
4822
48230x31, 0x20,
48240x39, 0x20,
48250x1F, 0x42, 0xA0, 0xE8,
4826
48270x2A, 0x42, 0x52, 0xBF,
48280x0F, 0x52, 0xA0, 0xE8,
4829
48300x1A, 0x42, 0x62, 0xBF,
48310x1E, 0x51, 0x60, 0xEA,
4832
48330x73, 0x7B, 0xC8, 0xEC,
48340x0E, 0x61, 0x60, 0xEA,
4835
48360x32, 0x40, 0x50, 0xBD,
48370x22, 0x40, 0x60, 0xBD,
4838
48390x12, 0x41, 0x51, 0xBD,
48400x3A, 0x41, 0x61, 0xBD,
4841
48420xBF, 0x2F, 0x0E, 0xBD,
48430x97, 0xE2,
48440x7B, 0x72,
4845
48460x32, 0x20,
48470x22, 0x20,
48480x12, 0x20,
48490x3A, 0x20,
4850
48510x35, 0x48, 0xB1, 0xE8,
48520x3D, 0x59, 0xB1, 0xE8,
4853
48540x46, 0x31, 0x46, 0xBF,
48550x56, 0x31, 0x56, 0xBF,
4856
48570xB3, 0xE2, 0x2D, 0x9F,
48580x00, 0x80, 0x00, 0xE8,
4859
48600x66, 0x31, 0x66, 0xBF,
48610x47, 0x39, 0x47, 0xBF,
4862
48630x57, 0x39, 0x57, 0xBF,
48640x67, 0x39, 0x67, 0xBF,
4865
48660x69, 0x80, 0x07, 0xEA,
48670x24, 0x41, 0x20, 0xE9,
4868
48690x35, 0x00,
48700x3D, 0x00,
48710x00, 0xE0,
48720x2D, 0x73,
4873
48740x33, 0x72,
48750x0C, 0xE3,
48760x8D, 0x2F, 0x1E, 0xBD,
4877
48780x43, 0x75, 0xF8, 0xEC,
48790x35, 0x20,
48800x3D, 0x20,
4881
48820x43, 0x43, 0x2D, 0xDF,
48830x53, 0x53, 0x2D, 0xDF,
4884
48850xAE, 0x1E, 0x0E, 0xBD,
48860x58, 0xE3,
48870x33, 0x66,
4888
48890x48, 0x35, 0x48, 0xBF,
48900x58, 0x35, 0x58, 0xBF,
4891
48920x68, 0x35, 0x68, 0xBF,
48930x49, 0x3D, 0x49, 0xBF,
4894
48950x59, 0x3D, 0x59, 0xBF,
48960x69, 0x3D, 0x69, 0xBF,
4897
48980x63, 0x63, 0x2D, 0xDF,
48990x4D, 0x7D, 0xF8, 0xEC,
4900
49010x59, 0xE3,
49020x00, 0xE0,
49030xB8, 0x38, 0x33, 0xBF,
4904
49050x2D, 0x73,
49060x30, 0x76,
49070x18, 0x3A, 0x41, 0xE9,
4908
49090x3F, 0x53, 0xA0, 0xE8,
49100x05, 0x80, 0x3D, 0xEA,
4911
49120x37, 0x43, 0xA0, 0xE8,
49130x3D, 0x63, 0xA0, 0xE8,
4914
49150x50, 0x70, 0xF8, 0xEC,
49160x2B, 0x50, 0x3C, 0xE9,
4917
49180x1F, 0x0F, 0xBC, 0xE8,
49190x00, 0x80, 0x00, 0xE8,
4920
49210x59, 0x78, 0xF8, 0xEC,
49220x00, 0x80, 0x00, 0xE8,
4923
49240x15, 0xC0, 0x20, 0xE9,
49250x15, 0xC0, 0x20, 0xE9,
4926
49270x15, 0xC0, 0x20, 0xE9,
49280x15, 0xC0, 0x20, 0xE9,
4929
49300x1E, 0x12, 0x41, 0xE9,
49310x1A, 0x22, 0x41, 0xE9,
4932
49330x46, 0x37, 0x46, 0xDF,
49340x56, 0x3F, 0x56, 0xDF,
4935
49360x2B, 0x40, 0x3D, 0xE9,
49370x66, 0x3D, 0x66, 0xDF,
4938
49390x1D, 0x32, 0x41, 0xE9,
49400x67, 0x3D, 0x67, 0xDF,
4941
49420x47, 0x37, 0x47, 0xDF,
49430x57, 0x3F, 0x57, 0xDF,
4944
49450x2A, 0x40, 0x20, 0xE9,
49460x59, 0x3F, 0x59, 0xDF,
4947
49480x16, 0x30, 0x20, 0xE9,
49490x69, 0x3D, 0x69, 0xDF,
4950
49510x48, 0x37, 0x48, 0xDF,
49520x58, 0x3F, 0x58, 0xDF,
4953
49540x12, 0x12, 0x2D, 0xDF,
49550x22, 0x22, 0x2D, 0xDF,
4956
49570x32, 0x32, 0x2D, 0xDF,
49580x3A, 0x3A, 0x2D, 0xDF,
4959
49600x68, 0x3D, 0x68, 0xDF,
49610x49, 0x37, 0x49, 0xDF,
4962
49630x3D, 0xCF, 0x74, 0xC0,
49640x37, 0xCF, 0x74, 0xC4,
4965
49660x31, 0x53, 0x2F, 0x9F,
49670x34, 0x80, 0x20, 0xE9,
4968
49690x39, 0xE5, 0x2C, 0x9F,
49700x3C, 0x3D, 0x20, 0xE9,
4971
49720x0A, 0x44, 0x54, 0xB0,
49730x02, 0x44, 0x64, 0xB0,
4974
49750x2A, 0x44, 0x54, 0xB2,
49760x1A, 0x44, 0x64, 0xB2,
4977
49780x25, 0x80, 0x3A, 0xEA,
49790x0A, 0x20,
49800x02, 0x20,
4981
49820x3D, 0xCF, 0x74, 0xC2,
49830x2A, 0x20,
49840x1A, 0x20,
4985
49860x30, 0x50, 0x2E, 0x9F,
49870x32, 0x31, 0x5F, 0xE9,
4988
49890x38, 0x21, 0x2C, 0x9F,
49900x33, 0x39, 0x5F, 0xE9,
4991
49920x31, 0x53, 0x2F, 0x9F,
49930x00, 0x80, 0x00, 0xE8,
4994
49950x2A, 0x44, 0x54, 0xB4,
49960x1A, 0x44, 0x64, 0xB4,
4997
49980x39, 0xE5, 0x2C, 0x9F,
49990x38, 0x3D, 0x20, 0xE9,
5000
50010x88, 0x73, 0x5E, 0xE9,
50020x2A, 0x20,
50030x1A, 0x20,
5004
50050x2A, 0x46, 0x56, 0xBF,
50060x1A, 0x46, 0x66, 0xBF,
5007
50080x31, 0x53, 0x2F, 0x9F,
50090x3E, 0x30, 0x4F, 0xE9,
5010
50110x39, 0xE5, 0x2C, 0x9F,
50120x3F, 0x38, 0x4F, 0xE9,
5013
50140x0A, 0x47, 0x57, 0xBF,
50150x02, 0x47, 0x67, 0xBF,
5016
50170x31, 0x53, 0x2F, 0x9F,
50180x3A, 0x31, 0x4F, 0xE9,
5019
50200x39, 0xE5, 0x2C, 0x9F,
50210x3B, 0x39, 0x4F, 0xE9,
5022
50230x2A, 0x43, 0x53, 0xBF,
50240x1A, 0x43, 0x63, 0xBF,
5025
50260x30, 0x50, 0x2E, 0x9F,
50270x36, 0x31, 0x4F, 0xE9,
5028
50290x38, 0x21, 0x2C, 0x9F,
50300x37, 0x39, 0x4F, 0xE9,
5031
50320x0A, 0x48, 0x58, 0xBF,
50330x02, 0x48, 0x68, 0xBF,
5034
50350x31, 0x53, 0x2F, 0x9F,
50360x80, 0x31, 0x57, 0xE9,
5037
50380x39, 0xE5, 0x2C, 0x9F,
50390x81, 0x39, 0x57, 0xE9,
5040
50410x2A, 0x49, 0x59, 0xBF,
50420x1A, 0x49, 0x69, 0xBF,
5043
50440x30, 0x50, 0x2E, 0x9F,
50450x82, 0x30, 0x57, 0xE9,
5046
50470x38, 0x21, 0x2C, 0x9F,
50480x83, 0x38, 0x57, 0xE9,
5049
50500x31, 0x53, 0x2F, 0x9F,
50510x84, 0x31, 0x5E, 0xE9,
5052
50530x39, 0xE5, 0x2C, 0x9F,
50540x85, 0x39, 0x5E, 0xE9,
5055
50560x86, 0x76, 0x57, 0xE9,
50570x8A, 0x36, 0x20, 0xE9,
5058
50590x87, 0x77, 0x57, 0xE9,
50600x8B, 0x3E, 0xBF, 0xEA,
5061
50620x80, 0x30, 0x57, 0xE9,
50630x81, 0x38, 0x57, 0xE9,
5064
50650x82, 0x31, 0x57, 0xE9,
50660x86, 0x78, 0x57, 0xE9,
5067
50680x83, 0x39, 0x57, 0xE9,
50690x87, 0x79, 0x57, 0xE9,
5070
50710x30, 0x1F, 0x5F, 0xE9,
50720x8A, 0x34, 0x20, 0xE9,
5073
50740x8B, 0x3C, 0x20, 0xE9,
50750x37, 0x50, 0x60, 0xBD,
5076
50770x57, 0x0D, 0x20, 0xE9,
50780x35, 0x51, 0x61, 0xBD,
5079
50800x2B, 0x50, 0x20, 0xE9,
50810x1D, 0x37, 0xE1, 0xEA,
5082
50830x1E, 0x35, 0xE1, 0xEA,
50840x00, 0xE0,
50850x0E, 0x77,
5086
50870x24, 0x51, 0x20, 0xE9,
50880x9F, 0xFF, 0x20, 0xEA,
5089
50900x16, 0x0E, 0x20, 0xE9,
50910x57, 0x2E, 0xBF, 0xEA,
5092
50930x0B, 0x46, 0xA0, 0xE8,
50940x1B, 0x56, 0xA0, 0xE8,
5095
50960x2B, 0x66, 0xA0, 0xE8,
50970x0C, 0x47, 0xA0, 0xE8,
5098
50990x1C, 0x57, 0xA0, 0xE8,
51000x2C, 0x67, 0xA0, 0xE8,
5101
51020x0B, 0x00,
51030x1B, 0x00,
51040x2B, 0x00,
51050x00, 0xE0,
5106
51070x0C, 0x00,
51080x1C, 0x00,
51090x2C, 0x00,
51100x00, 0xE0,
5111
51120x0B, 0x65,
51130x1B, 0x65,
51140x2B, 0x65,
51150x00, 0xE0,
5116
51170x0C, 0x65,
51180x1C, 0x65,
51190x2C, 0x65,
51200x00, 0xE0,
5121
51220x0B, 0x1B, 0x60, 0xEC,
51230x36, 0xD7, 0x36, 0xAD,
5124
51250x2B, 0x80, 0x60, 0xEC,
51260x0C, 0x1C, 0x60, 0xEC,
5127
51280x3E, 0xD7, 0x3E, 0xAD,
51290x2C, 0x80, 0x60, 0xEC,
5130
51310x0B, 0x2B, 0xDE, 0xE8,
51320x1B, 0x80, 0xDE, 0xE8,
5133
51340x36, 0x80, 0x36, 0xBD,
51350x3E, 0x80, 0x3E, 0xBD,
5136
51370x33, 0xD7, 0x0B, 0xBD,
51380x3B, 0xD7, 0x1B, 0xBD,
5139
51400x46, 0x80, 0x46, 0xCF,
51410x57, 0x80, 0x57, 0xCF,
5142
51430x66, 0x33, 0x66, 0xCF,
51440x47, 0x3B, 0x47, 0xCF,
5145
51460x56, 0x33, 0x56, 0xCF,
51470x67, 0x3B, 0x67, 0xCF,
5148
51490x0B, 0x48, 0xA0, 0xE8,
51500x1B, 0x58, 0xA0, 0xE8,
5151
51520x2B, 0x68, 0xA0, 0xE8,
51530x0C, 0x49, 0xA0, 0xE8,
5154
51550x1C, 0x59, 0xA0, 0xE8,
51560x2C, 0x69, 0xA0, 0xE8,
5157
51580x0B, 0x00,
51590x1B, 0x00,
51600x2B, 0x00,
51610x00, 0xE0,
5162
51630x0C, 0x00,
51640x1C, 0x00,
51650x2C, 0x00,
51660x00, 0xE0,
5167
51680x0B, 0x65,
51690x1B, 0x65,
51700x2B, 0x65,
51710x00, 0xE0,
5172
51730x0C, 0x65,
51740x1C, 0x65,
51750x2C, 0x65,
51760x00, 0xE0,
5177
51780x0B, 0x1B, 0x60, 0xEC,
51790x34, 0xD7, 0x34, 0xAD,
5180
51810x2B, 0x80, 0x60, 0xEC,
51820x0C, 0x1C, 0x60, 0xEC,
5183
51840x3C, 0xD7, 0x3C, 0xAD,
51850x2C, 0x80, 0x60, 0xEC,
5186
51870x0B, 0x2B, 0xDE, 0xE8,
51880x1B, 0x80, 0xDE, 0xE8,
5189
51900x34, 0x80, 0x34, 0xBD,
51910x3C, 0x80, 0x3C, 0xBD,
5192
51930x33, 0xD7, 0x0B, 0xBD,
51940x3B, 0xD7, 0x1B, 0xBD,
5195
51960x48, 0x80, 0x48, 0xCF,
51970x59, 0x80, 0x59, 0xCF,
5198
51990x68, 0x33, 0x68, 0xCF,
52000x49, 0x3B, 0x49, 0xCF,
5201
52020xBE, 0xFF, 0x20, 0xEA,
52030x00, 0x80, 0x00, 0xE8,
5204
52050x58, 0x33, 0x58, 0xCF,
52060x69, 0x3B, 0x69, 0xCF,
5207
52080x7D, 0xFF, 0x20, 0xEA,
52090x57, 0xC0, 0xBF, 0xEA,
5210
52110x00, 0x80, 0xA0, 0xE9,
52120x00, 0x00, 0xD8, 0xEC,
5213
5214};
5215
5216static unsigned char warp_g400_t2gza[] = {
5217
52180x00, 0x8A, 0x98, 0xE9,
52190x00, 0x80, 0x00, 0xE8,
5220
52210x00, 0x80, 0xA0, 0xE9,
52220x00, 0x00, 0xD8, 0xEC,
5223
52240xFF, 0x80, 0xC0, 0xE9,
52250x00, 0x80, 0x00, 0xE8,
5226
52270x0A, 0x40, 0x50, 0xBF,
52280x2A, 0x40, 0x60, 0xBF,
5229
52300x32, 0x41, 0x51, 0xBF,
52310x3A, 0x41, 0x61, 0xBF,
5232
52330xC3, 0x6B,
52340xD3, 0x6B,
52350x00, 0x8A, 0x98, 0xE9,
5236
52370x73, 0x7B, 0xC8, 0xEC,
52380x96, 0xE2,
52390x41, 0x04,
5240
52410x7B, 0x43, 0xA0, 0xE8,
52420x73, 0x53, 0xA0, 0xE8,
5243
52440xAD, 0xEE, 0x23, 0x9F,
52450x00, 0xE0,
52460x51, 0x04,
5247
52480x90, 0xE2,
52490x61, 0x04,
52500x31, 0x46, 0xB1, 0xE8,
5251
52520x51, 0x41, 0xE0, 0xEC,
52530x39, 0x67, 0xB1, 0xE8,
5254
52550x00, 0x04,
52560x46, 0xE2,
52570x73, 0x63, 0xA0, 0xE8,
5258
52590x61, 0x41, 0xE0, 0xEC,
52600x31, 0x00,
52610x39, 0x00,
5262
52630x7C, 0x80, 0x15, 0xEA,
52640x10, 0x04,
52650x20, 0x04,
5266
52670x61, 0x51, 0xE0, 0xEC,
52680x2F, 0x41, 0x60, 0xEA,
5269
52700x31, 0x20,
52710x39, 0x20,
52720x1F, 0x42, 0xA0, 0xE8,
5273
52740x2A, 0x42, 0x52, 0xBF,
52750x0F, 0x52, 0xA0, 0xE8,
5276
52770x1A, 0x42, 0x62, 0xBF,
52780x1E, 0x51, 0x60, 0xEA,
5279
52800x73, 0x7B, 0xC8, 0xEC,
52810x0E, 0x61, 0x60, 0xEA,
5282
52830x32, 0x40, 0x50, 0xBD,
52840x22, 0x40, 0x60, 0xBD,
5285
52860x12, 0x41, 0x51, 0xBD,
52870x3A, 0x41, 0x61, 0xBD,
5288
52890xBF, 0x2F, 0x0E, 0xBD,
52900x97, 0xE2,
52910x7B, 0x72,
5292
52930x32, 0x20,
52940x22, 0x20,
52950x12, 0x20,
52960x3A, 0x20,
5297
52980x35, 0x48, 0xB1, 0xE8,
52990x3D, 0x59, 0xB1, 0xE8,
5300
53010x46, 0x31, 0x46, 0xBF,
53020x56, 0x31, 0x56, 0xBF,
5303
53040xB3, 0xE2, 0x2D, 0x9F,
53050x00, 0x80, 0x00, 0xE8,
5306
53070x66, 0x31, 0x66, 0xBF,
53080x47, 0x39, 0x47, 0xBF,
5309
53100x57, 0x39, 0x57, 0xBF,
53110x67, 0x39, 0x67, 0xBF,
5312
53130x6D, 0x80, 0x07, 0xEA,
53140x24, 0x41, 0x20, 0xE9,
5315
53160x35, 0x00,
53170x3D, 0x00,
53180x00, 0xE0,
53190x2D, 0x73,
5320
53210x33, 0x72,
53220x0C, 0xE3,
53230x8D, 0x2F, 0x1E, 0xBD,
5324
53250x43, 0x75, 0xF8, 0xEC,
53260x35, 0x20,
53270x3D, 0x20,
5328
53290x43, 0x43, 0x2D, 0xDF,
53300x53, 0x53, 0x2D, 0xDF,
5331
53320xAE, 0x1E, 0x0E, 0xBD,
53330x58, 0xE3,
53340x33, 0x66,
5335
53360x48, 0x35, 0x48, 0xBF,
53370x58, 0x35, 0x58, 0xBF,
5338
53390x68, 0x35, 0x68, 0xBF,
53400x49, 0x3D, 0x49, 0xBF,
5341
53420x59, 0x3D, 0x59, 0xBF,
53430x69, 0x3D, 0x69, 0xBF,
5344
53450x63, 0x63, 0x2D, 0xDF,
53460x4D, 0x7D, 0xF8, 0xEC,
5347
53480x59, 0xE3,
53490x00, 0xE0,
53500xB8, 0x38, 0x33, 0xBF,
5351
53520x2D, 0x73,
53530x30, 0x76,
53540x18, 0x3A, 0x41, 0xE9,
5355
53560x3F, 0x53, 0xA0, 0xE8,
53570x05, 0x80, 0x3D, 0xEA,
5358
53590x37, 0x43, 0xA0, 0xE8,
53600x3D, 0x63, 0xA0, 0xE8,
5361
53620x50, 0x70, 0xF8, 0xEC,
53630x2B, 0x50, 0x3C, 0xE9,
5364
53650x1F, 0x0F, 0xBC, 0xE8,
53660x00, 0x80, 0x00, 0xE8,
5367
53680x59, 0x78, 0xF8, 0xEC,
53690x00, 0x80, 0x00, 0xE8,
5370
53710x15, 0xC0, 0x20, 0xE9,
53720x15, 0xC0, 0x20, 0xE9,
5373
53740x15, 0xC0, 0x20, 0xE9,
53750x15, 0xC0, 0x20, 0xE9,
5376
53770x1E, 0x12, 0x41, 0xE9,
53780x1A, 0x22, 0x41, 0xE9,
5379
53800x46, 0x37, 0x46, 0xDF,
53810x56, 0x3F, 0x56, 0xDF,
5382
53830x2B, 0x40, 0x3D, 0xE9,
53840x66, 0x3D, 0x66, 0xDF,
5385
53860x1D, 0x32, 0x41, 0xE9,
53870x67, 0x3D, 0x67, 0xDF,
5388
53890x47, 0x37, 0x47, 0xDF,
53900x57, 0x3F, 0x57, 0xDF,
5391
53920x2A, 0x40, 0x20, 0xE9,
53930x59, 0x3F, 0x59, 0xDF,
5394
53950x16, 0x30, 0x20, 0xE9,
53960x69, 0x3D, 0x69, 0xDF,
5397
53980x48, 0x37, 0x48, 0xDF,
53990x58, 0x3F, 0x58, 0xDF,
5400
54010x12, 0x12, 0x2D, 0xDF,
54020x22, 0x22, 0x2D, 0xDF,
5403
54040x32, 0x32, 0x2D, 0xDF,
54050x3A, 0x3A, 0x2D, 0xDF,
5406
54070x68, 0x3D, 0x68, 0xDF,
54080x49, 0x37, 0x49, 0xDF,
5409
54100x3D, 0xCF, 0x74, 0xC0,
54110x37, 0xCF, 0x74, 0xC4,
5412
54130x31, 0x53, 0x2F, 0x9F,
54140x34, 0x80, 0x20, 0xE9,
5415
54160x39, 0xE5, 0x2C, 0x9F,
54170x3C, 0x3D, 0x20, 0xE9,
5418
54190x0A, 0x44, 0x54, 0xB0,
54200x02, 0x44, 0x64, 0xB0,
5421
54220x2A, 0x44, 0x54, 0xB2,
54230x1A, 0x44, 0x64, 0xB2,
5424
54250x29, 0x80, 0x3A, 0xEA,
54260x0A, 0x20,
54270x02, 0x20,
5428
54290x0F, 0xCF, 0x74, 0xC6,
54300x3D, 0xCF, 0x74, 0xC2,
5431
54320x88, 0x73, 0x5E, 0xE9,
54330x2A, 0x20,
54340x1A, 0x20,
5435
54360x30, 0x50, 0x2E, 0x9F,
54370x32, 0x31, 0x5F, 0xE9,
5438
54390x38, 0x21, 0x2C, 0x9F,
54400x33, 0x39, 0x5F, 0xE9,
5441
54420x31, 0x53, 0x2F, 0x9F,
54430x9C, 0x0F, 0x20, 0xE9,
5444
54450x0A, 0x44, 0x54, 0xB4,
54460x02, 0x44, 0x64, 0xB4,
5447
54480x2A, 0x44, 0x54, 0xB6,
54490x1A, 0x44, 0x64, 0xB6,
5450
54510x39, 0xE5, 0x2C, 0x9F,
54520x38, 0x3D, 0x20, 0xE9,
5453
54540x0A, 0x20,
54550x02, 0x20,
54560x2A, 0x20,
54570x1A, 0x20,
5458
54590x0A, 0x47, 0x57, 0xBF,
54600x02, 0x47, 0x67, 0xBF,
5461
54620x30, 0x50, 0x2E, 0x9F,
54630x3E, 0x30, 0x4F, 0xE9,
5464
54650x38, 0x21, 0x2C, 0x9F,
54660x3F, 0x38, 0x4F, 0xE9,
5467
54680x2A, 0x46, 0x56, 0xBF,
54690x1A, 0x46, 0x66, 0xBF,
5470
54710x31, 0x53, 0x2F, 0x9F,
54720x3A, 0x31, 0x4F, 0xE9,
5473
54740x39, 0xE5, 0x2C, 0x9F,
54750x3B, 0x39, 0x4F, 0xE9,
5476
54770x31, 0x53, 0x2F, 0x9F,
54780x36, 0x30, 0x4F, 0xE9,
5479
54800x39, 0xE5, 0x2C, 0x9F,
54810x37, 0x38, 0x4F, 0xE9,
5482
54830x2A, 0x43, 0x53, 0xBF,
54840x1A, 0x43, 0x63, 0xBF,
5485
54860x30, 0x50, 0x2E, 0x9F,
54870x9D, 0x31, 0x4F, 0xE9,
5488
54890x38, 0x21, 0x2C, 0x9F,
54900x9E, 0x39, 0x4F, 0xE9,
5491
54920x0A, 0x48, 0x58, 0xBF,
54930x02, 0x48, 0x68, 0xBF,
5494
54950x31, 0x53, 0x2F, 0x9F,
54960x80, 0x31, 0x57, 0xE9,
5497
54980x39, 0xE5, 0x2C, 0x9F,
54990x81, 0x39, 0x57, 0xE9,
5500
55010x2A, 0x49, 0x59, 0xBF,
55020x1A, 0x49, 0x69, 0xBF,
5503
55040x30, 0x50, 0x2E, 0x9F,
55050x82, 0x30, 0x57, 0xE9,
5506
55070x38, 0x21, 0x2C, 0x9F,
55080x83, 0x38, 0x57, 0xE9,
5509
55100x31, 0x53, 0x2F, 0x9F,
55110x84, 0x31, 0x5E, 0xE9,
5512
55130x39, 0xE5, 0x2C, 0x9F,
55140x85, 0x39, 0x5E, 0xE9,
5515
55160x86, 0x76, 0x57, 0xE9,
55170x8A, 0x36, 0x20, 0xE9,
5518
55190x87, 0x77, 0x57, 0xE9,
55200x8B, 0x3E, 0xBF, 0xEA,
5521
55220x80, 0x30, 0x57, 0xE9,
55230x81, 0x38, 0x57, 0xE9,
5524
55250x82, 0x31, 0x57, 0xE9,
55260x86, 0x78, 0x57, 0xE9,
5527
55280x83, 0x39, 0x57, 0xE9,
55290x87, 0x79, 0x57, 0xE9,
5530
55310x30, 0x1F, 0x5F, 0xE9,
55320x8A, 0x34, 0x20, 0xE9,
5533
55340x8B, 0x3C, 0x20, 0xE9,
55350x37, 0x50, 0x60, 0xBD,
5536
55370x57, 0x0D, 0x20, 0xE9,
55380x35, 0x51, 0x61, 0xBD,
5539
55400x2B, 0x50, 0x20, 0xE9,
55410x1D, 0x37, 0xE1, 0xEA,
5542
55430x1E, 0x35, 0xE1, 0xEA,
55440x00, 0xE0,
55450x0E, 0x77,
5546
55470x24, 0x51, 0x20, 0xE9,
55480x9B, 0xFF, 0x20, 0xEA,
5549
55500x16, 0x0E, 0x20, 0xE9,
55510x57, 0x2E, 0xBF, 0xEA,
5552
55530x0B, 0x46, 0xA0, 0xE8,
55540x1B, 0x56, 0xA0, 0xE8,
5555
55560x2B, 0x66, 0xA0, 0xE8,
55570x0C, 0x47, 0xA0, 0xE8,
5558
55590x1C, 0x57, 0xA0, 0xE8,
55600x2C, 0x67, 0xA0, 0xE8,
5561
55620x0B, 0x00,
55630x1B, 0x00,
55640x2B, 0x00,
55650x00, 0xE0,
5566
55670x0C, 0x00,
55680x1C, 0x00,
55690x2C, 0x00,
55700x00, 0xE0,
5571
55720x0B, 0x65,
55730x1B, 0x65,
55740x2B, 0x65,
55750x00, 0xE0,
5576
55770x0C, 0x65,
55780x1C, 0x65,
55790x2C, 0x65,
55800x00, 0xE0,
5581
55820x0B, 0x1B, 0x60, 0xEC,
55830x36, 0xD7, 0x36, 0xAD,
5584
55850x2B, 0x80, 0x60, 0xEC,
55860x0C, 0x1C, 0x60, 0xEC,
5587
55880x3E, 0xD7, 0x3E, 0xAD,
55890x2C, 0x80, 0x60, 0xEC,
5590
55910x0B, 0x2B, 0xDE, 0xE8,
55920x1B, 0x80, 0xDE, 0xE8,
5593
55940x36, 0x80, 0x36, 0xBD,
55950x3E, 0x80, 0x3E, 0xBD,
5596
55970x33, 0xD7, 0x0B, 0xBD,
55980x3B, 0xD7, 0x1B, 0xBD,
5599
56000x46, 0x80, 0x46, 0xCF,
56010x57, 0x80, 0x57, 0xCF,
5602
56030x66, 0x33, 0x66, 0xCF,
56040x47, 0x3B, 0x47, 0xCF,
5605
56060x56, 0x33, 0x56, 0xCF,
56070x67, 0x3B, 0x67, 0xCF,
5608
56090x0B, 0x48, 0xA0, 0xE8,
56100x1B, 0x58, 0xA0, 0xE8,
5611
56120x2B, 0x68, 0xA0, 0xE8,
56130x0C, 0x49, 0xA0, 0xE8,
5614
56150x1C, 0x59, 0xA0, 0xE8,
56160x2C, 0x69, 0xA0, 0xE8,
5617
56180x0B, 0x00,
56190x1B, 0x00,
56200x2B, 0x00,
56210x00, 0xE0,
5622
56230x0C, 0x00,
56240x1C, 0x00,
56250x2C, 0x00,
56260x00, 0xE0,
5627
56280x0B, 0x65,
56290x1B, 0x65,
56300x2B, 0x65,
56310x00, 0xE0,
5632
56330x0C, 0x65,
56340x1C, 0x65,
56350x2C, 0x65,
56360x00, 0xE0,
5637
56380x0B, 0x1B, 0x60, 0xEC,
56390x34, 0xD7, 0x34, 0xAD,
5640
56410x2B, 0x80, 0x60, 0xEC,
56420x0C, 0x1C, 0x60, 0xEC,
5643
56440x3C, 0xD7, 0x3C, 0xAD,
56450x2C, 0x80, 0x60, 0xEC,
5646
56470x0B, 0x2B, 0xDE, 0xE8,
56480x1B, 0x80, 0xDE, 0xE8,
5649
56500x34, 0x80, 0x34, 0xBD,
56510x3C, 0x80, 0x3C, 0xBD,
5652
56530x33, 0xD7, 0x0B, 0xBD,
56540x3B, 0xD7, 0x1B, 0xBD,
5655
56560x48, 0x80, 0x48, 0xCF,
56570x59, 0x80, 0x59, 0xCF,
5658
56590x68, 0x33, 0x68, 0xCF,
56600x49, 0x3B, 0x49, 0xCF,
5661
56620xBA, 0xFF, 0x20, 0xEA,
56630x00, 0x80, 0x00, 0xE8,
5664
56650x58, 0x33, 0x58, 0xCF,
56660x69, 0x3B, 0x69, 0xCF,
5667
56680x79, 0xFF, 0x20, 0xEA,
56690x57, 0xC0, 0xBF, 0xEA,
5670
56710x00, 0x80, 0xA0, 0xE9,
56720x00, 0x00, 0xD8, 0xEC,
5673
5674};
5675
5676static unsigned char warp_g400_t2gzaf[] = {
5677
56780x00, 0x8A, 0x98, 0xE9,
56790x00, 0x80, 0x00, 0xE8,
5680
56810x00, 0x80, 0xA0, 0xE9,
56820x00, 0x00, 0xD8, 0xEC,
5683
56840xFF, 0x80, 0xC0, 0xE9,
56850x00, 0x80, 0x00, 0xE8,
5686
56870x0A, 0x40, 0x50, 0xBF,
56880x2A, 0x40, 0x60, 0xBF,
5689
56900x32, 0x41, 0x51, 0xBF,
56910x3A, 0x41, 0x61, 0xBF,
5692
56930xC3, 0x6B,
56940xD3, 0x6B,
56950x00, 0x8A, 0x98, 0xE9,
5696
56970x73, 0x7B, 0xC8, 0xEC,
56980x96, 0xE2,
56990x41, 0x04,
5700
57010x7B, 0x43, 0xA0, 0xE8,
57020x73, 0x53, 0xA0, 0xE8,
5703
57040xAD, 0xEE, 0x23, 0x9F,
57050x00, 0xE0,
57060x51, 0x04,
5707
57080x90, 0xE2,
57090x61, 0x04,
57100x31, 0x46, 0xB1, 0xE8,
5711
57120x51, 0x41, 0xE0, 0xEC,
57130x39, 0x67, 0xB1, 0xE8,
5714
57150x00, 0x04,
57160x46, 0xE2,
57170x73, 0x63, 0xA0, 0xE8,
5718
57190x61, 0x41, 0xE0, 0xEC,
57200x31, 0x00,
57210x39, 0x00,
5722
57230x81, 0x80, 0x15, 0xEA,
57240x10, 0x04,
57250x20, 0x04,
5726
57270x61, 0x51, 0xE0, 0xEC,
57280x2F, 0x41, 0x60, 0xEA,
5729
57300x31, 0x20,
57310x39, 0x20,
57320x1F, 0x42, 0xA0, 0xE8,
5733
57340x2A, 0x42, 0x52, 0xBF,
57350x0F, 0x52, 0xA0, 0xE8,
5736
57370x1A, 0x42, 0x62, 0xBF,
57380x1E, 0x51, 0x60, 0xEA,
5739
57400x73, 0x7B, 0xC8, 0xEC,
57410x0E, 0x61, 0x60, 0xEA,
5742
57430x32, 0x40, 0x50, 0xBD,
57440x22, 0x40, 0x60, 0xBD,
5745
57460x12, 0x41, 0x51, 0xBD,
57470x3A, 0x41, 0x61, 0xBD,
5748
57490xBF, 0x2F, 0x0E, 0xBD,
57500x97, 0xE2,
57510x7B, 0x72,
5752
57530x32, 0x20,
57540x22, 0x20,
57550x12, 0x20,
57560x3A, 0x20,
5757
57580x35, 0x48, 0xB1, 0xE8,
57590x3D, 0x59, 0xB1, 0xE8,
5760
57610x46, 0x31, 0x46, 0xBF,
57620x56, 0x31, 0x56, 0xBF,
5763
57640xB3, 0xE2, 0x2D, 0x9F,
57650x00, 0x80, 0x00, 0xE8,
5766
57670x66, 0x31, 0x66, 0xBF,
57680x47, 0x39, 0x47, 0xBF,
5769
57700x57, 0x39, 0x57, 0xBF,
57710x67, 0x39, 0x67, 0xBF,
5772
57730x72, 0x80, 0x07, 0xEA,
57740x24, 0x41, 0x20, 0xE9,
5775
57760x35, 0x00,
57770x3D, 0x00,
57780x00, 0xE0,
57790x2D, 0x73,
5780
57810x33, 0x72,
57820x0C, 0xE3,
57830x8D, 0x2F, 0x1E, 0xBD,
5784
57850x43, 0x75, 0xF8, 0xEC,
57860x35, 0x20,
57870x3D, 0x20,
5788
57890x43, 0x43, 0x2D, 0xDF,
57900x53, 0x53, 0x2D, 0xDF,
5791
57920xAE, 0x1E, 0x0E, 0xBD,
57930x58, 0xE3,
57940x33, 0x66,
5795
57960x48, 0x35, 0x48, 0xBF,
57970x58, 0x35, 0x58, 0xBF,
5798
57990x68, 0x35, 0x68, 0xBF,
58000x49, 0x3D, 0x49, 0xBF,
5801
58020x59, 0x3D, 0x59, 0xBF,
58030x69, 0x3D, 0x69, 0xBF,
5804
58050x63, 0x63, 0x2D, 0xDF,
58060x4D, 0x7D, 0xF8, 0xEC,
5807
58080x59, 0xE3,
58090x00, 0xE0,
58100xB8, 0x38, 0x33, 0xBF,
5811
58120x2D, 0x73,
58130x30, 0x76,
58140x18, 0x3A, 0x41, 0xE9,
5815
58160x3F, 0x53, 0xA0, 0xE8,
58170x05, 0x80, 0x3D, 0xEA,
5818
58190x37, 0x43, 0xA0, 0xE8,
58200x3D, 0x63, 0xA0, 0xE8,
5821
58220x50, 0x70, 0xF8, 0xEC,
58230x2B, 0x50, 0x3C, 0xE9,
5824
58250x1F, 0x0F, 0xBC, 0xE8,
58260x00, 0x80, 0x00, 0xE8,
5827
58280x59, 0x78, 0xF8, 0xEC,
58290x00, 0x80, 0x00, 0xE8,
5830
58310x15, 0xC0, 0x20, 0xE9,
58320x15, 0xC0, 0x20, 0xE9,
5833
58340x15, 0xC0, 0x20, 0xE9,
58350x15, 0xC0, 0x20, 0xE9,
5836
58370x1E, 0x12, 0x41, 0xE9,
58380x1A, 0x22, 0x41, 0xE9,
5839
58400x46, 0x37, 0x46, 0xDF,
58410x56, 0x3F, 0x56, 0xDF,
5842
58430x2B, 0x40, 0x3D, 0xE9,
58440x66, 0x3D, 0x66, 0xDF,
5845
58460x1D, 0x32, 0x41, 0xE9,
58470x67, 0x3D, 0x67, 0xDF,
5848
58490x47, 0x37, 0x47, 0xDF,
58500x57, 0x3F, 0x57, 0xDF,
5851
58520x2A, 0x40, 0x20, 0xE9,
58530x59, 0x3F, 0x59, 0xDF,
5854
58550x16, 0x30, 0x20, 0xE9,
58560x69, 0x3D, 0x69, 0xDF,
5857
58580x48, 0x37, 0x48, 0xDF,
58590x58, 0x3F, 0x58, 0xDF,
5860
58610x12, 0x12, 0x2D, 0xDF,
58620x22, 0x22, 0x2D, 0xDF,
5863
58640x32, 0x32, 0x2D, 0xDF,
58650x3A, 0x3A, 0x2D, 0xDF,
5866
58670x68, 0x3D, 0x68, 0xDF,
58680x49, 0x37, 0x49, 0xDF,
5869
58700x3D, 0xCF, 0x74, 0xC0,
58710x37, 0xCF, 0x74, 0xC4,
5872
58730x0A, 0x44, 0x54, 0xB0,
58740x02, 0x44, 0x64, 0xB0,
5875
58760x31, 0x53, 0x2F, 0x9F,
58770x34, 0x37, 0x20, 0xE9,
5878
58790x39, 0xE5, 0x2C, 0x9F,
58800x3C, 0x3D, 0x20, 0xE9,
5881
58820x2A, 0x44, 0x54, 0xB2,
58830x1A, 0x44, 0x64, 0xB2,
5884
58850x2E, 0x80, 0x3A, 0xEA,
58860x0A, 0x20,
58870x02, 0x20,
5888
58890x88, 0x73, 0x5E, 0xE9,
58900x2A, 0x20,
58910x1A, 0x20,
5892
58930x3D, 0xCF, 0x74, 0xC2,
58940x0F, 0xCF, 0x74, 0xC6,
5895
58960x30, 0x50, 0x2E, 0x9F,
58970x32, 0x31, 0x5F, 0xE9,
5898
58990x38, 0x21, 0x2C, 0x9F,
59000x33, 0x39, 0x5F, 0xE9,
5901
59020x31, 0x53, 0x2F, 0x9F,
59030x9C, 0x0F, 0x20, 0xE9,
5904
59050x0A, 0x44, 0x54, 0xB4,
59060x02, 0x44, 0x64, 0xB4,
5907
59080x2A, 0x44, 0x54, 0xB6,
59090x1A, 0x44, 0x64, 0xB6,
5910
59110x39, 0xE5, 0x2C, 0x9F,
59120x38, 0x3D, 0x20, 0xE9,
5913
59140x0A, 0x20,
59150x02, 0x20,
59160x2A, 0x20,
59170x1A, 0x20,
5918
59190x3D, 0xCF, 0x75, 0xC6,
59200x00, 0x80, 0x00, 0xE8,
5921
59220x30, 0x50, 0x2E, 0x9F,
59230x3E, 0x30, 0x4F, 0xE9,
5924
59250x38, 0x21, 0x2C, 0x9F,
59260x3F, 0x38, 0x4F, 0xE9,
5927
59280x0A, 0x45, 0x55, 0xB6,
59290x02, 0x45, 0x65, 0xB6,
5930
59310x31, 0x53, 0x2F, 0x9F,
59320x3A, 0x31, 0x4F, 0xE9,
5933
59340x39, 0xE5, 0x2C, 0x9F,
59350x3B, 0x39, 0x4F, 0xE9,
5936
59370x31, 0x3D, 0x20, 0xE9,
59380x0A, 0x20,
59390x02, 0x20,
5940
59410x2A, 0x46, 0x56, 0xBF,
59420x1A, 0x46, 0x66, 0xBF,
5943
59440x0A, 0x47, 0x57, 0xBF,
59450x02, 0x47, 0x67, 0xBF,
5946
59470x30, 0x50, 0x2E, 0x9F,
59480x36, 0x30, 0x4F, 0xE9,
5949
59500x38, 0x21, 0x2C, 0x9F,
59510x37, 0x38, 0x4F, 0xE9,
5952
59530x31, 0x53, 0x2F, 0x9F,
59540x9D, 0x31, 0x4F, 0xE9,
5955
59560x39, 0xE5, 0x2C, 0x9F,
59570x9E, 0x39, 0x4F, 0xE9,
5958
59590x2A, 0x43, 0x53, 0xBF,
59600x1A, 0x43, 0x63, 0xBF,
5961
59620x30, 0x50, 0x2E, 0x9F,
59630x35, 0x30, 0x4F, 0xE9,
5964
59650x38, 0x21, 0x2C, 0x9F,
59660x39, 0x38, 0x4F, 0xE9,
5967
59680x0A, 0x48, 0x58, 0xBF,
59690x02, 0x48, 0x68, 0xBF,
5970
59710x31, 0x53, 0x2F, 0x9F,
59720x80, 0x31, 0x57, 0xE9,
5973
59740x39, 0xE5, 0x2C, 0x9F,
59750x81, 0x39, 0x57, 0xE9,
5976
59770x2A, 0x49, 0x59, 0xBF,
59780x1A, 0x49, 0x69, 0xBF,
5979
59800x30, 0x50, 0x2E, 0x9F,
59810x82, 0x30, 0x57, 0xE9,
5982
59830x38, 0x21, 0x2C, 0x9F,
59840x83, 0x38, 0x57, 0xE9,
5985
59860x31, 0x53, 0x2F, 0x9F,
59870x84, 0x31, 0x5E, 0xE9,
5988
59890x39, 0xE5, 0x2C, 0x9F,
59900x85, 0x39, 0x5E, 0xE9,
5991
59920x86, 0x76, 0x57, 0xE9,
59930x8A, 0x36, 0x20, 0xE9,
5994
59950x87, 0x77, 0x57, 0xE9,
59960x8B, 0x3E, 0xBF, 0xEA,
5997
59980x80, 0x30, 0x57, 0xE9,
59990x81, 0x38, 0x57, 0xE9,
6000
60010x82, 0x31, 0x57, 0xE9,
60020x86, 0x78, 0x57, 0xE9,
6003
60040x83, 0x39, 0x57, 0xE9,
60050x87, 0x79, 0x57, 0xE9,
6006
60070x30, 0x1F, 0x5F, 0xE9,
60080x8A, 0x34, 0x20, 0xE9,
6009
60100x8B, 0x3C, 0x20, 0xE9,
60110x37, 0x50, 0x60, 0xBD,
6012
60130x57, 0x0D, 0x20, 0xE9,
60140x35, 0x51, 0x61, 0xBD,
6015
60160x2B, 0x50, 0x20, 0xE9,
60170x1D, 0x37, 0xE1, 0xEA,
6018
60190x1E, 0x35, 0xE1, 0xEA,
60200x00, 0xE0,
60210x0E, 0x77,
6022
60230x24, 0x51, 0x20, 0xE9,
60240x96, 0xFF, 0x20, 0xEA,
6025
60260x16, 0x0E, 0x20, 0xE9,
60270x57, 0x2E, 0xBF, 0xEA,
6028
60290x0B, 0x46, 0xA0, 0xE8,
60300x1B, 0x56, 0xA0, 0xE8,
6031
60320x2B, 0x66, 0xA0, 0xE8,
60330x0C, 0x47, 0xA0, 0xE8,
6034
60350x1C, 0x57, 0xA0, 0xE8,
60360x2C, 0x67, 0xA0, 0xE8,
6037
60380x0B, 0x00,
60390x1B, 0x00,
60400x2B, 0x00,
60410x00, 0xE0,
6042
60430x0C, 0x00,
60440x1C, 0x00,
60450x2C, 0x00,
60460x00, 0xE0,
6047
60480x0B, 0x65,
60490x1B, 0x65,
60500x2B, 0x65,
60510x00, 0xE0,
6052
60530x0C, 0x65,
60540x1C, 0x65,
60550x2C, 0x65,
60560x00, 0xE0,
6057
60580x0B, 0x1B, 0x60, 0xEC,
60590x36, 0xD7, 0x36, 0xAD,
6060
60610x2B, 0x80, 0x60, 0xEC,
60620x0C, 0x1C, 0x60, 0xEC,
6063
60640x3E, 0xD7, 0x3E, 0xAD,
60650x2C, 0x80, 0x60, 0xEC,
6066
60670x0B, 0x2B, 0xDE, 0xE8,
60680x1B, 0x80, 0xDE, 0xE8,
6069
60700x36, 0x80, 0x36, 0xBD,
60710x3E, 0x80, 0x3E, 0xBD,
6072
60730x33, 0xD7, 0x0B, 0xBD,
60740x3B, 0xD7, 0x1B, 0xBD,
6075
60760x46, 0x80, 0x46, 0xCF,
60770x57, 0x80, 0x57, 0xCF,
6078
60790x66, 0x33, 0x66, 0xCF,
60800x47, 0x3B, 0x47, 0xCF,
6081
60820x56, 0x33, 0x56, 0xCF,
60830x67, 0x3B, 0x67, 0xCF,
6084
60850x0B, 0x48, 0xA0, 0xE8,
60860x1B, 0x58, 0xA0, 0xE8,
6087
60880x2B, 0x68, 0xA0, 0xE8,
60890x0C, 0x49, 0xA0, 0xE8,
6090
60910x1C, 0x59, 0xA0, 0xE8,
60920x2C, 0x69, 0xA0, 0xE8,
6093
60940x0B, 0x00,
60950x1B, 0x00,
60960x2B, 0x00,
60970x00, 0xE0,
6098
60990x0C, 0x00,
61000x1C, 0x00,
61010x2C, 0x00,
61020x00, 0xE0,
6103
61040x0B, 0x65,
61050x1B, 0x65,
61060x2B, 0x65,
61070x00, 0xE0,
6108
61090x0C, 0x65,
61100x1C, 0x65,
61110x2C, 0x65,
61120x00, 0xE0,
6113
61140x0B, 0x1B, 0x60, 0xEC,
61150x34, 0xD7, 0x34, 0xAD,
6116
61170x2B, 0x80, 0x60, 0xEC,
61180x0C, 0x1C, 0x60, 0xEC,
6119
61200x3C, 0xD7, 0x3C, 0xAD,
61210x2C, 0x80, 0x60, 0xEC,
6122
61230x0B, 0x2B, 0xDE, 0xE8,
61240x1B, 0x80, 0xDE, 0xE8,
6125
61260x34, 0x80, 0x34, 0xBD,
61270x3C, 0x80, 0x3C, 0xBD,
6128
61290x33, 0xD7, 0x0B, 0xBD,
61300x3B, 0xD7, 0x1B, 0xBD,
6131
61320x48, 0x80, 0x48, 0xCF,
61330x59, 0x80, 0x59, 0xCF,
6134
61350x68, 0x33, 0x68, 0xCF,
61360x49, 0x3B, 0x49, 0xCF,
6137
61380xB5, 0xFF, 0x20, 0xEA,
61390x00, 0x80, 0x00, 0xE8,
6140
61410x58, 0x33, 0x58, 0xCF,
61420x69, 0x3B, 0x69, 0xCF,
6143
61440x74, 0xFF, 0x20, 0xEA,
61450x57, 0xC0, 0xBF, 0xEA,
6146
61470x00, 0x80, 0xA0, 0xE9,
61480x00, 0x00, 0xD8, 0xEC,
6149
6150};
6151
6152static unsigned char warp_g400_t2gzf[] = {
6153
61540x00, 0x8A, 0x98, 0xE9,
61550x00, 0x80, 0x00, 0xE8,
6156
61570x00, 0x80, 0xA0, 0xE9,
61580x00, 0x00, 0xD8, 0xEC,
6159
61600xFF, 0x80, 0xC0, 0xE9,
61610x00, 0x80, 0x00, 0xE8,
6162
61630x0A, 0x40, 0x50, 0xBF,
61640x2A, 0x40, 0x60, 0xBF,
6165
61660x32, 0x41, 0x51, 0xBF,
61670x3A, 0x41, 0x61, 0xBF,
6168
61690xC3, 0x6B,
61700xD3, 0x6B,
61710x00, 0x8A, 0x98, 0xE9,
6172
61730x73, 0x7B, 0xC8, 0xEC,
61740x96, 0xE2,
61750x41, 0x04,
6176
61770x7B, 0x43, 0xA0, 0xE8,
61780x73, 0x53, 0xA0, 0xE8,
6179
61800xAD, 0xEE, 0x23, 0x9F,
61810x00, 0xE0,
61820x51, 0x04,
6183
61840x90, 0xE2,
61850x61, 0x04,
61860x31, 0x46, 0xB1, 0xE8,
6187
61880x51, 0x41, 0xE0, 0xEC,
61890x39, 0x67, 0xB1, 0xE8,
6190
61910x00, 0x04,
61920x46, 0xE2,
61930x73, 0x63, 0xA0, 0xE8,
6194
61950x61, 0x41, 0xE0, 0xEC,
61960x31, 0x00,
61970x39, 0x00,
6198
61990x7D, 0x80, 0x15, 0xEA,
62000x10, 0x04,
62010x20, 0x04,
6202
62030x61, 0x51, 0xE0, 0xEC,
62040x2F, 0x41, 0x60, 0xEA,
6205
62060x31, 0x20,
62070x39, 0x20,
62080x1F, 0x42, 0xA0, 0xE8,
6209
62100x2A, 0x42, 0x52, 0xBF,
62110x0F, 0x52, 0xA0, 0xE8,
6212
62130x1A, 0x42, 0x62, 0xBF,
62140x1E, 0x51, 0x60, 0xEA,
6215
62160x73, 0x7B, 0xC8, 0xEC,
62170x0E, 0x61, 0x60, 0xEA,
6218
62190x32, 0x40, 0x50, 0xBD,
62200x22, 0x40, 0x60, 0xBD,
6221
62220x12, 0x41, 0x51, 0xBD,
62230x3A, 0x41, 0x61, 0xBD,
6224
62250xBF, 0x2F, 0x0E, 0xBD,
62260x97, 0xE2,
62270x7B, 0x72,
6228
62290x32, 0x20,
62300x22, 0x20,
62310x12, 0x20,
62320x3A, 0x20,
6233
62340x35, 0x48, 0xB1, 0xE8,
62350x3D, 0x59, 0xB1, 0xE8,
6236
62370x46, 0x31, 0x46, 0xBF,
62380x56, 0x31, 0x56, 0xBF,
6239
62400xB3, 0xE2, 0x2D, 0x9F,
62410x00, 0x80, 0x00, 0xE8,
6242
62430x66, 0x31, 0x66, 0xBF,
62440x47, 0x39, 0x47, 0xBF,
6245
62460x57, 0x39, 0x57, 0xBF,
62470x67, 0x39, 0x67, 0xBF,
6248
62490x6E, 0x80, 0x07, 0xEA,
62500x24, 0x41, 0x20, 0xE9,
6251
62520x35, 0x00,
62530x3D, 0x00,
62540x00, 0xE0,
62550x2D, 0x73,
6256
62570x33, 0x72,
62580x0C, 0xE3,
62590x8D, 0x2F, 0x1E, 0xBD,
6260
62610x43, 0x75, 0xF8, 0xEC,
62620x35, 0x20,
62630x3D, 0x20,
6264
62650x43, 0x43, 0x2D, 0xDF,
62660x53, 0x53, 0x2D, 0xDF,
6267
62680xAE, 0x1E, 0x0E, 0xBD,
62690x58, 0xE3,
62700x33, 0x66,
6271
62720x48, 0x35, 0x48, 0xBF,
62730x58, 0x35, 0x58, 0xBF,
6274
62750x68, 0x35, 0x68, 0xBF,
62760x49, 0x3D, 0x49, 0xBF,
6277
62780x59, 0x3D, 0x59, 0xBF,
62790x69, 0x3D, 0x69, 0xBF,
6280
62810x63, 0x63, 0x2D, 0xDF,
62820x4D, 0x7D, 0xF8, 0xEC,
6283
62840x59, 0xE3,
62850x00, 0xE0,
62860xB8, 0x38, 0x33, 0xBF,
6287
62880x2D, 0x73,
62890x30, 0x76,
62900x18, 0x3A, 0x41, 0xE9,
6291
62920x3F, 0x53, 0xA0, 0xE8,
62930x05, 0x80, 0x3D, 0xEA,
6294
62950x37, 0x43, 0xA0, 0xE8,
62960x3D, 0x63, 0xA0, 0xE8,
6297
62980x50, 0x70, 0xF8, 0xEC,
62990x2B, 0x50, 0x3C, 0xE9,
6300
63010x1F, 0x0F, 0xBC, 0xE8,
63020x00, 0x80, 0x00, 0xE8,
6303
63040x59, 0x78, 0xF8, 0xEC,
63050x00, 0x80, 0x00, 0xE8,
6306
63070x15, 0xC0, 0x20, 0xE9,
63080x15, 0xC0, 0x20, 0xE9,
6309
63100x15, 0xC0, 0x20, 0xE9,
63110x15, 0xC0, 0x20, 0xE9,
6312
63130x1E, 0x12, 0x41, 0xE9,
63140x1A, 0x22, 0x41, 0xE9,
6315
63160x46, 0x37, 0x46, 0xDF,
63170x56, 0x3F, 0x56, 0xDF,
6318
63190x2B, 0x40, 0x3D, 0xE9,
63200x66, 0x3D, 0x66, 0xDF,
6321
63220x1D, 0x32, 0x41, 0xE9,
63230x67, 0x3D, 0x67, 0xDF,
6324
63250x47, 0x37, 0x47, 0xDF,
63260x57, 0x3F, 0x57, 0xDF,
6327
63280x2A, 0x40, 0x20, 0xE9,
63290x59, 0x3F, 0x59, 0xDF,
6330
63310x16, 0x30, 0x20, 0xE9,
63320x69, 0x3D, 0x69, 0xDF,
6333
63340x48, 0x37, 0x48, 0xDF,
63350x58, 0x3F, 0x58, 0xDF,
6336
63370x12, 0x12, 0x2D, 0xDF,
63380x22, 0x22, 0x2D, 0xDF,
6339
63400x32, 0x32, 0x2D, 0xDF,
63410x3A, 0x3A, 0x2D, 0xDF,
6342
63430x68, 0x3D, 0x68, 0xDF,
63440x49, 0x37, 0x49, 0xDF,
6345
63460x3D, 0xCF, 0x74, 0xC0,
63470x37, 0xCF, 0x74, 0xC4,
6348
63490x39, 0xE5, 0x2C, 0x9F,
63500x34, 0x80, 0x20, 0xE9,
6351
63520x31, 0x53, 0x2F, 0x9F,
63530x00, 0x80, 0x00, 0xE8,
6354
63550x88, 0x73, 0x5E, 0xE9,
63560x00, 0x80, 0x00, 0xE8,
6357
63580x0F, 0xCF, 0x75, 0xC6,
63590x3C, 0x3D, 0x20, 0xE9,
6360
63610x0A, 0x44, 0x54, 0xB0,
63620x02, 0x44, 0x64, 0xB0,
6363
63640x2A, 0x44, 0x54, 0xB2,
63650x1A, 0x44, 0x64, 0xB2,
6366
63670x28, 0x80, 0x3A, 0xEA,
63680x0A, 0x20,
63690x02, 0x20,
6370
63710x3D, 0xCF, 0x74, 0xC2,
63720x2A, 0x20,
63730x1A, 0x20,
6374
63750x30, 0x50, 0x2E, 0x9F,
63760x32, 0x31, 0x5F, 0xE9,
6377
63780x38, 0x21, 0x2C, 0x9F,
63790x33, 0x39, 0x5F, 0xE9,
6380
63810x31, 0x53, 0x2F, 0x9F,
63820x31, 0x0F, 0x20, 0xE9,
6383
63840x0A, 0x44, 0x54, 0xB4,
63850x02, 0x44, 0x64, 0xB4,
6386
63870x2A, 0x45, 0x55, 0xB6,
63880x1A, 0x45, 0x65, 0xB6,
6389
63900x39, 0xE5, 0x2C, 0x9F,
63910x38, 0x3D, 0x20, 0xE9,
6392
63930x0A, 0x20,
63940x02, 0x20,
63950x2A, 0x20,
63960x1A, 0x20,
6397
63980x0A, 0x47, 0x57, 0xBF,
63990x02, 0x47, 0x67, 0xBF,
6400
64010x30, 0x50, 0x2E, 0x9F,
64020x3E, 0x30, 0x4F, 0xE9,
6403
64040x38, 0x21, 0x2C, 0x9F,
64050x3F, 0x38, 0x4F, 0xE9,
6406
64070x2A, 0x46, 0x56, 0xBF,
64080x1A, 0x46, 0x66, 0xBF,
6409
64100x31, 0x53, 0x2F, 0x9F,
64110x3A, 0x31, 0x4F, 0xE9,
6412
64130x39, 0xE5, 0x2C, 0x9F,
64140x3B, 0x39, 0x4F, 0xE9,
6415
64160x31, 0x53, 0x2F, 0x9F,
64170x36, 0x30, 0x4F, 0xE9,
6418
64190x39, 0xE5, 0x2C, 0x9F,
64200x37, 0x38, 0x4F, 0xE9,
6421
64220x2A, 0x43, 0x53, 0xBF,
64230x1A, 0x43, 0x63, 0xBF,
6424
64250x30, 0x50, 0x2E, 0x9F,
64260x35, 0x31, 0x4F, 0xE9,
6427
64280x38, 0x21, 0x2C, 0x9F,
64290x39, 0x39, 0x4F, 0xE9,
6430
64310x0A, 0x48, 0x58, 0xBF,
64320x02, 0x48, 0x68, 0xBF,
6433
64340x31, 0x53, 0x2F, 0x9F,
64350x80, 0x31, 0x57, 0xE9,
6436
64370x39, 0xE5, 0x2C, 0x9F,
64380x81, 0x39, 0x57, 0xE9,
6439
64400x2A, 0x49, 0x59, 0xBF,
64410x1A, 0x49, 0x69, 0xBF,
6442
64430x30, 0x50, 0x2E, 0x9F,
64440x82, 0x30, 0x57, 0xE9,
6445
64460x38, 0x21, 0x2C, 0x9F,
64470x83, 0x38, 0x57, 0xE9,
6448
64490x31, 0x53, 0x2F, 0x9F,
64500x84, 0x31, 0x5E, 0xE9,
6451
64520x39, 0xE5, 0x2C, 0x9F,
64530x85, 0x39, 0x5E, 0xE9,
6454
64550x86, 0x76, 0x57, 0xE9,
64560x8A, 0x36, 0x20, 0xE9,
6457
64580x87, 0x77, 0x57, 0xE9,
64590x8B, 0x3E, 0xBF, 0xEA,
6460
64610x80, 0x30, 0x57, 0xE9,
64620x81, 0x38, 0x57, 0xE9,
6463
64640x82, 0x31, 0x57, 0xE9,
64650x86, 0x78, 0x57, 0xE9,
6466
64670x83, 0x39, 0x57, 0xE9,
64680x87, 0x79, 0x57, 0xE9,
6469
64700x30, 0x1F, 0x5F, 0xE9,
64710x8A, 0x34, 0x20, 0xE9,
6472
64730x8B, 0x3C, 0x20, 0xE9,
64740x37, 0x50, 0x60, 0xBD,
6475
64760x57, 0x0D, 0x20, 0xE9,
64770x35, 0x51, 0x61, 0xBD,
6478
64790x2B, 0x50, 0x20, 0xE9,
64800x1D, 0x37, 0xE1, 0xEA,
6481
64820x1E, 0x35, 0xE1, 0xEA,
64830x00, 0xE0,
64840x0E, 0x77,
6485
64860x24, 0x51, 0x20, 0xE9,
64870x9A, 0xFF, 0x20, 0xEA,
6488
64890x16, 0x0E, 0x20, 0xE9,
64900x57, 0x2E, 0xBF, 0xEA,
6491
64920x0B, 0x46, 0xA0, 0xE8,
64930x1B, 0x56, 0xA0, 0xE8,
6494
64950x2B, 0x66, 0xA0, 0xE8,
64960x0C, 0x47, 0xA0, 0xE8,
6497
64980x1C, 0x57, 0xA0, 0xE8,
64990x2C, 0x67, 0xA0, 0xE8,
6500
65010x0B, 0x00,
65020x1B, 0x00,
65030x2B, 0x00,
65040x00, 0xE0,
6505
65060x0C, 0x00,
65070x1C, 0x00,
65080x2C, 0x00,
65090x00, 0xE0,
6510
65110x0B, 0x65,
65120x1B, 0x65,
65130x2B, 0x65,
65140x00, 0xE0,
6515
65160x0C, 0x65,
65170x1C, 0x65,
65180x2C, 0x65,
65190x00, 0xE0,
6520
65210x0B, 0x1B, 0x60, 0xEC,
65220x36, 0xD7, 0x36, 0xAD,
6523
65240x2B, 0x80, 0x60, 0xEC,
65250x0C, 0x1C, 0x60, 0xEC,
6526
65270x3E, 0xD7, 0x3E, 0xAD,
65280x2C, 0x80, 0x60, 0xEC,
6529
65300x0B, 0x2B, 0xDE, 0xE8,
65310x1B, 0x80, 0xDE, 0xE8,
6532
65330x36, 0x80, 0x36, 0xBD,
65340x3E, 0x80, 0x3E, 0xBD,
6535
65360x33, 0xD7, 0x0B, 0xBD,
65370x3B, 0xD7, 0x1B, 0xBD,
6538
65390x46, 0x80, 0x46, 0xCF,
65400x57, 0x80, 0x57, 0xCF,
6541
65420x66, 0x33, 0x66, 0xCF,
65430x47, 0x3B, 0x47, 0xCF,
6544
65450x56, 0x33, 0x56, 0xCF,
65460x67, 0x3B, 0x67, 0xCF,
6547
65480x0B, 0x48, 0xA0, 0xE8,
65490x1B, 0x58, 0xA0, 0xE8,
6550
65510x2B, 0x68, 0xA0, 0xE8,
65520x0C, 0x49, 0xA0, 0xE8,
6553
65540x1C, 0x59, 0xA0, 0xE8,
65550x2C, 0x69, 0xA0, 0xE8,
6556
65570x0B, 0x00,
65580x1B, 0x00,
65590x2B, 0x00,
65600x00, 0xE0,
6561
65620x0C, 0x00,
65630x1C, 0x00,
65640x2C, 0x00,
65650x00, 0xE0,
6566
65670x0B, 0x65,
65680x1B, 0x65,
65690x2B, 0x65,
65700x00, 0xE0,
6571
65720x0C, 0x65,
65730x1C, 0x65,
65740x2C, 0x65,
65750x00, 0xE0,
6576
65770x0B, 0x1B, 0x60, 0xEC,
65780x34, 0xD7, 0x34, 0xAD,
6579
65800x2B, 0x80, 0x60, 0xEC,
65810x0C, 0x1C, 0x60, 0xEC,
6582
65830x3C, 0xD7, 0x3C, 0xAD,
65840x2C, 0x80, 0x60, 0xEC,
6585
65860x0B, 0x2B, 0xDE, 0xE8,
65870x1B, 0x80, 0xDE, 0xE8,
6588
65890x34, 0x80, 0x34, 0xBD,
65900x3C, 0x80, 0x3C, 0xBD,
6591
65920x33, 0xD7, 0x0B, 0xBD,
65930x3B, 0xD7, 0x1B, 0xBD,
6594
65950x48, 0x80, 0x48, 0xCF,
65960x59, 0x80, 0x59, 0xCF,
6597
65980x68, 0x33, 0x68, 0xCF,
65990x49, 0x3B, 0x49, 0xCF,
6600
66010xBB, 0xFF, 0x20, 0xEA,
66020x00, 0x80, 0x00, 0xE8,
6603
66040x58, 0x33, 0x58, 0xCF,
66050x69, 0x3B, 0x69, 0xCF,
6606
66070x78, 0xFF, 0x20, 0xEA,
66080x57, 0xC0, 0xBF, 0xEA,
6609
66100x00, 0x80, 0xA0, 0xE9,
66110x00, 0x00, 0xD8, 0xEC,
6612
6613};
6614
6615static unsigned char warp_g400_t2gzs[] = {
6616
66170x00, 0x8A, 0x98, 0xE9,
66180x00, 0x80, 0x00, 0xE8,
6619
66200x00, 0x80, 0xA0, 0xE9,
66210x00, 0x00, 0xD8, 0xEC,
6622
66230xFF, 0x80, 0xC0, 0xE9,
66240x00, 0x80, 0x00, 0xE8,
6625
66260x0A, 0x40, 0x50, 0xBF,
66270x2A, 0x40, 0x60, 0xBF,
6628
66290x32, 0x41, 0x51, 0xBF,
66300x3A, 0x41, 0x61, 0xBF,
6631
66320xC3, 0x6B,
66330xD3, 0x6B,
66340x00, 0x8A, 0x98, 0xE9,
6635
66360x73, 0x7B, 0xC8, 0xEC,
66370x96, 0xE2,
66380x41, 0x04,
6639
66400x7B, 0x43, 0xA0, 0xE8,
66410x73, 0x53, 0xA0, 0xE8,
6642
66430xAD, 0xEE, 0x23, 0x9F,
66440x00, 0xE0,
66450x51, 0x04,
6646
66470x90, 0xE2,
66480x61, 0x04,
66490x31, 0x46, 0xB1, 0xE8,
6650
66510x51, 0x41, 0xE0, 0xEC,
66520x39, 0x67, 0xB1, 0xE8,
6653
66540x00, 0x04,
66550x46, 0xE2,
66560x73, 0x63, 0xA0, 0xE8,
6657
66580x61, 0x41, 0xE0, 0xEC,
66590x31, 0x00,
66600x39, 0x00,
6661
66620x85, 0x80, 0x15, 0xEA,
66630x10, 0x04,
66640x20, 0x04,
6665
66660x61, 0x51, 0xE0, 0xEC,
66670x2F, 0x41, 0x60, 0xEA,
6668
66690x31, 0x20,
66700x39, 0x20,
66710x1F, 0x42, 0xA0, 0xE8,
6672
66730x2A, 0x42, 0x52, 0xBF,
66740x0F, 0x52, 0xA0, 0xE8,
6675
66760x1A, 0x42, 0x62, 0xBF,
66770x1E, 0x51, 0x60, 0xEA,
6678
66790x73, 0x7B, 0xC8, 0xEC,
66800x0E, 0x61, 0x60, 0xEA,
6681
66820x32, 0x40, 0x50, 0xBD,
66830x22, 0x40, 0x60, 0xBD,
6684
66850x12, 0x41, 0x51, 0xBD,
66860x3A, 0x41, 0x61, 0xBD,
6687
66880xBF, 0x2F, 0x0E, 0xBD,
66890x97, 0xE2,
66900x7B, 0x72,
6691
66920x32, 0x20,
66930x22, 0x20,
66940x12, 0x20,
66950x3A, 0x20,
6696
66970x35, 0x48, 0xB1, 0xE8,
66980x3D, 0x59, 0xB1, 0xE8,
6699
67000x46, 0x31, 0x46, 0xBF,
67010x56, 0x31, 0x56, 0xBF,
6702
67030xB3, 0xE2, 0x2D, 0x9F,
67040x00, 0x80, 0x00, 0xE8,
6705
67060x66, 0x31, 0x66, 0xBF,
67070x47, 0x39, 0x47, 0xBF,
6708
67090x57, 0x39, 0x57, 0xBF,
67100x67, 0x39, 0x67, 0xBF,
6711
67120x76, 0x80, 0x07, 0xEA,
67130x24, 0x41, 0x20, 0xE9,
6714
67150x35, 0x00,
67160x3D, 0x00,
67170x00, 0xE0,
67180x2D, 0x73,
6719
67200x33, 0x72,
67210x0C, 0xE3,
67220x8D, 0x2F, 0x1E, 0xBD,
6723
67240x43, 0x75, 0xF8, 0xEC,
67250x35, 0x20,
67260x3D, 0x20,
6727
67280x43, 0x43, 0x2D, 0xDF,
67290x53, 0x53, 0x2D, 0xDF,
6730
67310xAE, 0x1E, 0x0E, 0xBD,
67320x58, 0xE3,
67330x33, 0x66,
6734
67350x48, 0x35, 0x48, 0xBF,
67360x58, 0x35, 0x58, 0xBF,
6737
67380x68, 0x35, 0x68, 0xBF,
67390x49, 0x3D, 0x49, 0xBF,
6740
67410x59, 0x3D, 0x59, 0xBF,
67420x69, 0x3D, 0x69, 0xBF,
6743
67440x63, 0x63, 0x2D, 0xDF,
67450x4D, 0x7D, 0xF8, 0xEC,
6746
67470x59, 0xE3,
67480x00, 0xE0,
67490xB8, 0x38, 0x33, 0xBF,
6750
67510x2D, 0x73,
67520x30, 0x76,
67530x18, 0x3A, 0x41, 0xE9,
6754
67550x3F, 0x53, 0xA0, 0xE8,
67560x05, 0x80, 0x3D, 0xEA,
6757
67580x37, 0x43, 0xA0, 0xE8,
67590x3D, 0x63, 0xA0, 0xE8,
6760
67610x50, 0x70, 0xF8, 0xEC,
67620x2B, 0x50, 0x3C, 0xE9,
6763
67640x1F, 0x0F, 0xBC, 0xE8,
67650x00, 0x80, 0x00, 0xE8,
6766
67670x59, 0x78, 0xF8, 0xEC,
67680x00, 0x80, 0x00, 0xE8,
6769
67700x15, 0xC0, 0x20, 0xE9,
67710x15, 0xC0, 0x20, 0xE9,
6772
67730x15, 0xC0, 0x20, 0xE9,
67740x15, 0xC0, 0x20, 0xE9,
6775
67760x1E, 0x12, 0x41, 0xE9,
67770x1A, 0x22, 0x41, 0xE9,
6778
67790x46, 0x37, 0x46, 0xDF,
67800x56, 0x3F, 0x56, 0xDF,
6781
67820x2B, 0x40, 0x3D, 0xE9,
67830x66, 0x3D, 0x66, 0xDF,
6784
67850x1D, 0x32, 0x41, 0xE9,
67860x67, 0x3D, 0x67, 0xDF,
6787
67880x47, 0x37, 0x47, 0xDF,
67890x57, 0x3F, 0x57, 0xDF,
6790
67910x2A, 0x40, 0x20, 0xE9,
67920x59, 0x3F, 0x59, 0xDF,
6793
67940x16, 0x30, 0x20, 0xE9,
67950x69, 0x3D, 0x69, 0xDF,
6796
67970x48, 0x37, 0x48, 0xDF,
67980x58, 0x3F, 0x58, 0xDF,
6799
68000x68, 0x3D, 0x68, 0xDF,
68010x49, 0x37, 0x49, 0xDF,
6802
68030x32, 0x32, 0x2D, 0xDF,
68040x22, 0x22, 0x2D, 0xDF,
6805
68060x12, 0x12, 0x2D, 0xDF,
68070x3A, 0x3A, 0x2D, 0xDF,
6808
68090x0F, 0xCF, 0x74, 0xC2,
68100x37, 0xCF, 0x74, 0xC4,
6811
68120x0A, 0x44, 0x54, 0xB0,
68130x02, 0x44, 0x64, 0xB0,
6814
68150x3D, 0xCF, 0x74, 0xC0,
68160x34, 0x37, 0x20, 0xE9,
6817
68180x31, 0x53, 0x2F, 0x9F,
68190x38, 0x0F, 0x20, 0xE9,
6820
68210x39, 0xE5, 0x2C, 0x9F,
68220x3C, 0x3D, 0x20, 0xE9,
6823
68240x2A, 0x44, 0x54, 0xB2,
68250x1A, 0x44, 0x64, 0xB2,
6826
68270x31, 0x80, 0x3A, 0xEA,
68280x0A, 0x20,
68290x02, 0x20,
6830
68310x0F, 0xCF, 0x75, 0xC0,
68320x2A, 0x20,
68330x1A, 0x20,
6834
68350x30, 0x50, 0x2E, 0x9F,
68360x32, 0x31, 0x5F, 0xE9,
6837
68380x38, 0x21, 0x2C, 0x9F,
68390x33, 0x39, 0x5F, 0xE9,
6840
68410x3D, 0xCF, 0x75, 0xC2,
68420x37, 0xCF, 0x75, 0xC4,
6843
68440x31, 0x53, 0x2F, 0x9F,
68450xA6, 0x0F, 0x20, 0xE9,
6846
68470x39, 0xE5, 0x2C, 0x9F,
68480xA3, 0x3D, 0x20, 0xE9,
6849
68500x2A, 0x44, 0x54, 0xB4,
68510x1A, 0x44, 0x64, 0xB4,
6852
68530x0A, 0x45, 0x55, 0xB0,
68540x02, 0x45, 0x65, 0xB0,
6855
68560x88, 0x73, 0x5E, 0xE9,
68570x2A, 0x20,
68580x1A, 0x20,
6859
68600xA0, 0x37, 0x20, 0xE9,
68610x0A, 0x20,
68620x02, 0x20,
6863
68640x31, 0x53, 0x2F, 0x9F,
68650x3E, 0x30, 0x4F, 0xE9,
6866
68670x39, 0xE5, 0x2C, 0x9F,
68680x3F, 0x38, 0x4F, 0xE9,
6869
68700x30, 0x50, 0x2E, 0x9F,
68710x3A, 0x31, 0x4F, 0xE9,
6872
68730x2A, 0x45, 0x55, 0xB2,
68740x1A, 0x45, 0x65, 0xB2,
6875
68760x0A, 0x45, 0x55, 0xB4,
68770x02, 0x45, 0x65, 0xB4,
6878
68790x38, 0x21, 0x2C, 0x9F,
68800x3B, 0x39, 0x4F, 0xE9,
6881
68820x2A, 0x20,
68830x1A, 0x20,
68840x0A, 0x20,
68850x02, 0x20,
6886
68870x2A, 0x46, 0x56, 0xBF,
68880x1A, 0x46, 0x66, 0xBF,
6889
68900x31, 0x53, 0x2F, 0x9F,
68910x36, 0x31, 0x4F, 0xE9,
6892
68930x39, 0xE5, 0x2C, 0x9F,
68940x37, 0x39, 0x4F, 0xE9,
6895
68960x30, 0x50, 0x2E, 0x9F,
68970xA7, 0x30, 0x4F, 0xE9,
6898
68990x38, 0x21, 0x2C, 0x9F,
69000xA8, 0x38, 0x4F, 0xE9,
6901
69020x0A, 0x47, 0x57, 0xBF,
69030x02, 0x47, 0x67, 0xBF,
6904
69050x31, 0x53, 0x2F, 0x9F,
69060xA4, 0x31, 0x4F, 0xE9,
6907
69080x39, 0xE5, 0x2C, 0x9F,
69090xA5, 0x39, 0x4F, 0xE9,
6910
69110x2A, 0x43, 0x53, 0xBF,
69120x1A, 0x43, 0x63, 0xBF,
6913
69140x30, 0x50, 0x2E, 0x9F,
69150xA1, 0x30, 0x4F, 0xE9,
6916
69170x38, 0x21, 0x2C, 0x9F,
69180xA2, 0x38, 0x4F, 0xE9,
6919
69200x0A, 0x48, 0x58, 0xBF,
69210x02, 0x48, 0x68, 0xBF,
6922
69230x31, 0x53, 0x2F, 0x9F,
69240x80, 0x31, 0x57, 0xE9,
6925
69260x39, 0xE5, 0x2C, 0x9F,
69270x81, 0x39, 0x57, 0xE9,
6928
69290x2A, 0x49, 0x59, 0xBF,
69300x1A, 0x49, 0x69, 0xBF,
6931
69320x30, 0x50, 0x2E, 0x9F,
69330x82, 0x30, 0x57, 0xE9,
6934
69350x38, 0x21, 0x2C, 0x9F,
69360x83, 0x38, 0x57, 0xE9,
6937
69380x31, 0x53, 0x2F, 0x9F,
69390x84, 0x31, 0x5E, 0xE9,
6940
69410x39, 0xE5, 0x2C, 0x9F,
69420x85, 0x39, 0x5E, 0xE9,
6943
69440x86, 0x76, 0x57, 0xE9,
69450x8A, 0x36, 0x20, 0xE9,
6946
69470x87, 0x77, 0x57, 0xE9,
69480x8B, 0x3E, 0xBF, 0xEA,
6949
69500x80, 0x30, 0x57, 0xE9,
69510x81, 0x38, 0x57, 0xE9,
6952
69530x82, 0x31, 0x57, 0xE9,
69540x86, 0x78, 0x57, 0xE9,
6955
69560x83, 0x39, 0x57, 0xE9,
69570x87, 0x79, 0x57, 0xE9,
6958
69590x30, 0x1F, 0x5F, 0xE9,
69600x8A, 0x34, 0x20, 0xE9,
6961
69620x8B, 0x3C, 0x20, 0xE9,
69630x37, 0x50, 0x60, 0xBD,
6964
69650x57, 0x0D, 0x20, 0xE9,
69660x35, 0x51, 0x61, 0xBD,
6967
69680x2B, 0x50, 0x20, 0xE9,
69690x1D, 0x37, 0xE1, 0xEA,
6970
69710x1E, 0x35, 0xE1, 0xEA,
69720x00, 0xE0,
69730x0E, 0x77,
6974
69750x24, 0x51, 0x20, 0xE9,
69760x92, 0xFF, 0x20, 0xEA,
6977
69780x16, 0x0E, 0x20, 0xE9,
69790x57, 0x2E, 0xBF, 0xEA,
6980
69810x0B, 0x46, 0xA0, 0xE8,
69820x1B, 0x56, 0xA0, 0xE8,
6983
69840x2B, 0x66, 0xA0, 0xE8,
69850x0C, 0x47, 0xA0, 0xE8,
6986
69870x1C, 0x57, 0xA0, 0xE8,
69880x2C, 0x67, 0xA0, 0xE8,
6989
69900x0B, 0x00,
69910x1B, 0x00,
69920x2B, 0x00,
69930x00, 0xE0,
6994
69950x0C, 0x00,
69960x1C, 0x00,
69970x2C, 0x00,
69980x00, 0xE0,
6999
70000x0B, 0x65,
70010x1B, 0x65,
70020x2B, 0x65,
70030x00, 0xE0,
7004
70050x0C, 0x65,
70060x1C, 0x65,
70070x2C, 0x65,
70080x00, 0xE0,
7009
70100x0B, 0x1B, 0x60, 0xEC,
70110x36, 0xD7, 0x36, 0xAD,
7012
70130x2B, 0x80, 0x60, 0xEC,
70140x0C, 0x1C, 0x60, 0xEC,
7015
70160x3E, 0xD7, 0x3E, 0xAD,
70170x2C, 0x80, 0x60, 0xEC,
7018
70190x0B, 0x2B, 0xDE, 0xE8,
70200x1B, 0x80, 0xDE, 0xE8,
7021
70220x36, 0x80, 0x36, 0xBD,
70230x3E, 0x80, 0x3E, 0xBD,
7024
70250x33, 0xD7, 0x0B, 0xBD,
70260x3B, 0xD7, 0x1B, 0xBD,
7027
70280x46, 0x80, 0x46, 0xCF,
70290x57, 0x80, 0x57, 0xCF,
7030
70310x66, 0x33, 0x66, 0xCF,
70320x47, 0x3B, 0x47, 0xCF,
7033
70340x56, 0x33, 0x56, 0xCF,
70350x67, 0x3B, 0x67, 0xCF,
7036
70370x0B, 0x48, 0xA0, 0xE8,
70380x1B, 0x58, 0xA0, 0xE8,
7039
70400x2B, 0x68, 0xA0, 0xE8,
70410x0C, 0x49, 0xA0, 0xE8,
7042
70430x1C, 0x59, 0xA0, 0xE8,
70440x2C, 0x69, 0xA0, 0xE8,
7045
70460x0B, 0x00,
70470x1B, 0x00,
70480x2B, 0x00,
70490x00, 0xE0,
7050
70510x0C, 0x00,
70520x1C, 0x00,
70530x2C, 0x00,
70540x00, 0xE0,
7055
70560x0B, 0x65,
70570x1B, 0x65,
70580x2B, 0x65,
70590x00, 0xE0,
7060
70610x0C, 0x65,
70620x1C, 0x65,
70630x2C, 0x65,
70640x00, 0xE0,
7065
70660x0B, 0x1B, 0x60, 0xEC,
70670x34, 0xD7, 0x34, 0xAD,
7068
70690x2B, 0x80, 0x60, 0xEC,
70700x0C, 0x1C, 0x60, 0xEC,
7071
70720x3C, 0xD7, 0x3C, 0xAD,
70730x2C, 0x80, 0x60, 0xEC,
7074
70750x0B, 0x2B, 0xDE, 0xE8,
70760x1B, 0x80, 0xDE, 0xE8,
7077
70780x34, 0x80, 0x34, 0xBD,
70790x3C, 0x80, 0x3C, 0xBD,
7080
70810x33, 0xD7, 0x0B, 0xBD,
70820x3B, 0xD7, 0x1B, 0xBD,
7083
70840x48, 0x80, 0x48, 0xCF,
70850x59, 0x80, 0x59, 0xCF,
7086
70870x68, 0x33, 0x68, 0xCF,
70880x49, 0x3B, 0x49, 0xCF,
7089
70900xB2, 0xFF, 0x20, 0xEA,
70910x00, 0x80, 0x00, 0xE8,
7092
70930x58, 0x33, 0x58, 0xCF,
70940x69, 0x3B, 0x69, 0xCF,
7095
70960x70, 0xFF, 0x20, 0xEA,
70970x57, 0xC0, 0xBF, 0xEA,
7098
70990x00, 0x80, 0xA0, 0xE9,
71000x00, 0x00, 0xD8, 0xEC,
7101
7102};
7103
7104static unsigned char warp_g400_t2gzsa[] = {
7105
71060x00, 0x8A, 0x98, 0xE9,
71070x00, 0x80, 0x00, 0xE8,
7108
71090x00, 0x80, 0xA0, 0xE9,
71100x00, 0x00, 0xD8, 0xEC,
7111
71120xFF, 0x80, 0xC0, 0xE9,
71130x00, 0x80, 0x00, 0xE8,
7114
71150x0A, 0x40, 0x50, 0xBF,
71160x2A, 0x40, 0x60, 0xBF,
7117
71180x32, 0x41, 0x51, 0xBF,
71190x3A, 0x41, 0x61, 0xBF,
7120
71210xC3, 0x6B,
71220xD3, 0x6B,
71230x00, 0x8A, 0x98, 0xE9,
7124
71250x73, 0x7B, 0xC8, 0xEC,
71260x96, 0xE2,
71270x41, 0x04,
7128
71290x7B, 0x43, 0xA0, 0xE8,
71300x73, 0x53, 0xA0, 0xE8,
7131
71320xAD, 0xEE, 0x23, 0x9F,
71330x00, 0xE0,
71340x51, 0x04,
7135
71360x90, 0xE2,
71370x61, 0x04,
71380x31, 0x46, 0xB1, 0xE8,
7139
71400x51, 0x41, 0xE0, 0xEC,
71410x39, 0x67, 0xB1, 0xE8,
7142
71430x00, 0x04,
71440x46, 0xE2,
71450x73, 0x63, 0xA0, 0xE8,
7146
71470x61, 0x41, 0xE0, 0xEC,
71480x31, 0x00,
71490x39, 0x00,
7150
71510x8A, 0x80, 0x15, 0xEA,
71520x10, 0x04,
71530x20, 0x04,
7154
71550x61, 0x51, 0xE0, 0xEC,
71560x2F, 0x41, 0x60, 0xEA,
7157
71580x31, 0x20,
71590x39, 0x20,
71600x1F, 0x42, 0xA0, 0xE8,
7161
71620x2A, 0x42, 0x52, 0xBF,
71630x0F, 0x52, 0xA0, 0xE8,
7164
71650x1A, 0x42, 0x62, 0xBF,
71660x1E, 0x51, 0x60, 0xEA,
7167
71680x73, 0x7B, 0xC8, 0xEC,
71690x0E, 0x61, 0x60, 0xEA,
7170
71710x32, 0x40, 0x50, 0xBD,
71720x22, 0x40, 0x60, 0xBD,
7173
71740x12, 0x41, 0x51, 0xBD,
71750x3A, 0x41, 0x61, 0xBD,
7176
71770xBF, 0x2F, 0x0E, 0xBD,
71780x97, 0xE2,
71790x7B, 0x72,
7180
71810x32, 0x20,
71820x22, 0x20,
71830x12, 0x20,
71840x3A, 0x20,
7185
71860x35, 0x48, 0xB1, 0xE8,
71870x3D, 0x59, 0xB1, 0xE8,
7188
71890x46, 0x31, 0x46, 0xBF,
71900x56, 0x31, 0x56, 0xBF,
7191
71920xB3, 0xE2, 0x2D, 0x9F,
71930x00, 0x80, 0x00, 0xE8,
7194
71950x66, 0x31, 0x66, 0xBF,
71960x47, 0x39, 0x47, 0xBF,
7197
71980x57, 0x39, 0x57, 0xBF,
71990x67, 0x39, 0x67, 0xBF,
7200
72010x7B, 0x80, 0x07, 0xEA,
72020x24, 0x41, 0x20, 0xE9,
7203
72040x35, 0x00,
72050x3D, 0x00,
72060x00, 0xE0,
72070x2D, 0x73,
7208
72090x33, 0x72,
72100x0C, 0xE3,
72110x8D, 0x2F, 0x1E, 0xBD,
7212
72130x43, 0x75, 0xF8, 0xEC,
72140x35, 0x20,
72150x3D, 0x20,
7216
72170x43, 0x43, 0x2D, 0xDF,
72180x53, 0x53, 0x2D, 0xDF,
7219
72200xAE, 0x1E, 0x0E, 0xBD,
72210x58, 0xE3,
72220x33, 0x66,
7223
72240x48, 0x35, 0x48, 0xBF,
72250x58, 0x35, 0x58, 0xBF,
7226
72270x68, 0x35, 0x68, 0xBF,
72280x49, 0x3D, 0x49, 0xBF,
7229
72300x59, 0x3D, 0x59, 0xBF,
72310x69, 0x3D, 0x69, 0xBF,
7232
72330x63, 0x63, 0x2D, 0xDF,
72340x4D, 0x7D, 0xF8, 0xEC,
7235
72360x59, 0xE3,
72370x00, 0xE0,
72380xB8, 0x38, 0x33, 0xBF,
7239
72400x2D, 0x73,
72410x30, 0x76,
72420x18, 0x3A, 0x41, 0xE9,
7243
72440x3F, 0x53, 0xA0, 0xE8,
72450x05, 0x80, 0x3D, 0xEA,
7246
72470x37, 0x43, 0xA0, 0xE8,
72480x3D, 0x63, 0xA0, 0xE8,
7249
72500x50, 0x70, 0xF8, 0xEC,
72510x2B, 0x50, 0x3C, 0xE9,
7252
72530x1F, 0x0F, 0xBC, 0xE8,
72540x00, 0x80, 0x00, 0xE8,
7255
72560x59, 0x78, 0xF8, 0xEC,
72570x00, 0x80, 0x00, 0xE8,
7258
72590x15, 0xC0, 0x20, 0xE9,
72600x15, 0xC0, 0x20, 0xE9,
7261
72620x15, 0xC0, 0x20, 0xE9,
72630x15, 0xC0, 0x20, 0xE9,
7264
72650x1E, 0x12, 0x41, 0xE9,
72660x1A, 0x22, 0x41, 0xE9,
7267
72680x46, 0x37, 0x46, 0xDF,
72690x56, 0x3F, 0x56, 0xDF,
7270
72710x2B, 0x40, 0x3D, 0xE9,
72720x66, 0x3D, 0x66, 0xDF,
7273
72740x1D, 0x32, 0x41, 0xE9,
72750x67, 0x3D, 0x67, 0xDF,
7276
72770x47, 0x37, 0x47, 0xDF,
72780x57, 0x3F, 0x57, 0xDF,
7279
72800x2A, 0x40, 0x20, 0xE9,
72810x59, 0x3F, 0x59, 0xDF,
7282
72830x16, 0x30, 0x20, 0xE9,
72840x69, 0x3D, 0x69, 0xDF,
7285
72860x48, 0x37, 0x48, 0xDF,
72870x58, 0x3F, 0x58, 0xDF,
7288
72890x68, 0x3D, 0x68, 0xDF,
72900x49, 0x37, 0x49, 0xDF,
7291
72920x32, 0x32, 0x2D, 0xDF,
72930x22, 0x22, 0x2D, 0xDF,
7294
72950x12, 0x12, 0x2D, 0xDF,
72960x3A, 0x3A, 0x2D, 0xDF,
7297
72980x0F, 0xCF, 0x74, 0xC2,
72990x37, 0xCF, 0x74, 0xC4,
7300
73010x0A, 0x44, 0x54, 0xB0,
73020x02, 0x44, 0x64, 0xB0,
7303
73040x3D, 0xCF, 0x74, 0xC0,
73050x34, 0x37, 0x20, 0xE9,
7306
73070x31, 0x53, 0x2F, 0x9F,
73080x38, 0x0F, 0x20, 0xE9,
7309
73100x39, 0xE5, 0x2C, 0x9F,
73110x3C, 0x3D, 0x20, 0xE9,
7312
73130x2A, 0x44, 0x54, 0xB2,
73140x1A, 0x44, 0x64, 0xB2,
7315
73160x36, 0x80, 0x3A, 0xEA,
73170x0A, 0x20,
73180x02, 0x20,
7319
73200x0F, 0xCF, 0x75, 0xC0,
73210x2A, 0x20,
73220x1A, 0x20,
7323
73240x30, 0x50, 0x2E, 0x9F,
73250x32, 0x31, 0x5F, 0xE9,
7326
73270x38, 0x21, 0x2C, 0x9F,
73280x33, 0x39, 0x5F, 0xE9,
7329
73300x3D, 0xCF, 0x75, 0xC2,
73310x37, 0xCF, 0x75, 0xC4,
7332
73330x31, 0x53, 0x2F, 0x9F,
73340xA6, 0x0F, 0x20, 0xE9,
7335
73360x39, 0xE5, 0x2C, 0x9F,
73370xA3, 0x3D, 0x20, 0xE9,
7338
73390x2A, 0x44, 0x54, 0xB4,
73400x1A, 0x44, 0x64, 0xB4,
7341
73420x0A, 0x45, 0x55, 0xB0,
73430x02, 0x45, 0x65, 0xB0,
7344
73450x88, 0x73, 0x5E, 0xE9,
73460x2A, 0x20,
73470x1A, 0x20,
7348
73490xA0, 0x37, 0x20, 0xE9,
73500x0A, 0x20,
73510x02, 0x20,
7352
73530x31, 0x53, 0x2F, 0x9F,
73540x3E, 0x30, 0x4F, 0xE9,
7355
73560x39, 0xE5, 0x2C, 0x9F,
73570x3F, 0x38, 0x4F, 0xE9,
7358
73590x30, 0x50, 0x2E, 0x9F,
73600x3A, 0x31, 0x4F, 0xE9,
7361
73620x38, 0x21, 0x2C, 0x9F,
73630x3B, 0x39, 0x4F, 0xE9,
7364
73650x2A, 0x45, 0x55, 0xB2,
73660x1A, 0x45, 0x65, 0xB2,
7367
73680x0A, 0x45, 0x55, 0xB4,
73690x02, 0x45, 0x65, 0xB4,
7370
73710x0F, 0xCF, 0x74, 0xC6,
73720x2A, 0x20,
73730x1A, 0x20,
7374
73750xA7, 0x30, 0x4F, 0xE9,
73760x0A, 0x20,
73770x02, 0x20,
7378
73790x31, 0x53, 0x2F, 0x9F,
73800x9C, 0x0F, 0x20, 0xE9,
7381
73820x39, 0xE5, 0x2C, 0x9F,
73830xA8, 0x38, 0x4F, 0xE9,
7384
73850x2A, 0x44, 0x54, 0xB6,
73860x1A, 0x44, 0x64, 0xB6,
7387
73880x30, 0x50, 0x2E, 0x9F,
73890x36, 0x31, 0x4F, 0xE9,
7390
73910x38, 0x21, 0x2C, 0x9F,
73920x37, 0x39, 0x4F, 0xE9,
7393
73940x00, 0x80, 0x00, 0xE8,
73950x2A, 0x20,
73960x1A, 0x20,
7397
73980x2A, 0x46, 0x56, 0xBF,
73990x1A, 0x46, 0x66, 0xBF,
7400
74010x31, 0x53, 0x2F, 0x9F,
74020xA4, 0x31, 0x4F, 0xE9,
7403
74040x39, 0xE5, 0x2C, 0x9F,
74050xA5, 0x39, 0x4F, 0xE9,
7406
74070x0A, 0x47, 0x57, 0xBF,
74080x02, 0x47, 0x67, 0xBF,
7409
74100x31, 0x53, 0x2F, 0x9F,
74110xA1, 0x30, 0x4F, 0xE9,
7412
74130x39, 0xE5, 0x2C, 0x9F,
74140xA2, 0x38, 0x4F, 0xE9,
7415
74160x2A, 0x43, 0x53, 0xBF,
74170x1A, 0x43, 0x63, 0xBF,
7418
74190x30, 0x50, 0x2E, 0x9F,
74200x9D, 0x31, 0x4F, 0xE9,
7421
74220x38, 0x21, 0x2C, 0x9F,
74230x9E, 0x39, 0x4F, 0xE9,
7424
74250x0A, 0x48, 0x58, 0xBF,
74260x02, 0x48, 0x68, 0xBF,
7427
74280x31, 0x53, 0x2F, 0x9F,
74290x80, 0x31, 0x57, 0xE9,
7430
74310x39, 0xE5, 0x2C, 0x9F,
74320x81, 0x39, 0x57, 0xE9,
7433
74340x2A, 0x49, 0x59, 0xBF,
74350x1A, 0x49, 0x69, 0xBF,
7436
74370x30, 0x50, 0x2E, 0x9F,
74380x82, 0x30, 0x57, 0xE9,
7439
74400x38, 0x21, 0x2C, 0x9F,
74410x83, 0x38, 0x57, 0xE9,
7442
74430x31, 0x53, 0x2F, 0x9F,
74440x84, 0x31, 0x5E, 0xE9,
7445
74460x39, 0xE5, 0x2C, 0x9F,
74470x85, 0x39, 0x5E, 0xE9,
7448
74490x86, 0x76, 0x57, 0xE9,
74500x8A, 0x36, 0x20, 0xE9,
7451
74520x87, 0x77, 0x57, 0xE9,
74530x8B, 0x3E, 0xBF, 0xEA,
7454
74550x80, 0x30, 0x57, 0xE9,
74560x81, 0x38, 0x57, 0xE9,
7457
74580x82, 0x31, 0x57, 0xE9,
74590x86, 0x78, 0x57, 0xE9,
7460
74610x83, 0x39, 0x57, 0xE9,
74620x87, 0x79, 0x57, 0xE9,
7463
74640x30, 0x1F, 0x5F, 0xE9,
74650x8A, 0x34, 0x20, 0xE9,
7466
74670x8B, 0x3C, 0x20, 0xE9,
74680x37, 0x50, 0x60, 0xBD,
7469
74700x57, 0x0D, 0x20, 0xE9,
74710x35, 0x51, 0x61, 0xBD,
7472
74730x2B, 0x50, 0x20, 0xE9,
74740x1D, 0x37, 0xE1, 0xEA,
7475
74760x1E, 0x35, 0xE1, 0xEA,
74770x00, 0xE0,
74780x0E, 0x77,
7479
74800x24, 0x51, 0x20, 0xE9,
74810x8D, 0xFF, 0x20, 0xEA,
7482
74830x16, 0x0E, 0x20, 0xE9,
74840x57, 0x2E, 0xBF, 0xEA,
7485
74860x0B, 0x46, 0xA0, 0xE8,
74870x1B, 0x56, 0xA0, 0xE8,
7488
74890x2B, 0x66, 0xA0, 0xE8,
74900x0C, 0x47, 0xA0, 0xE8,
7491
74920x1C, 0x57, 0xA0, 0xE8,
74930x2C, 0x67, 0xA0, 0xE8,
7494
74950x0B, 0x00,
74960x1B, 0x00,
74970x2B, 0x00,
74980x00, 0xE0,
7499
75000x0C, 0x00,
75010x1C, 0x00,
75020x2C, 0x00,
75030x00, 0xE0,
7504
75050x0B, 0x65,
75060x1B, 0x65,
75070x2B, 0x65,
75080x00, 0xE0,
7509
75100x0C, 0x65,
75110x1C, 0x65,
75120x2C, 0x65,
75130x00, 0xE0,
7514
75150x0B, 0x1B, 0x60, 0xEC,
75160x36, 0xD7, 0x36, 0xAD,
7517
75180x2B, 0x80, 0x60, 0xEC,
75190x0C, 0x1C, 0x60, 0xEC,
7520
75210x3E, 0xD7, 0x3E, 0xAD,
75220x2C, 0x80, 0x60, 0xEC,
7523
75240x0B, 0x2B, 0xDE, 0xE8,
75250x1B, 0x80, 0xDE, 0xE8,
7526
75270x36, 0x80, 0x36, 0xBD,
75280x3E, 0x80, 0x3E, 0xBD,
7529
75300x33, 0xD7, 0x0B, 0xBD,
75310x3B, 0xD7, 0x1B, 0xBD,
7532
75330x46, 0x80, 0x46, 0xCF,
75340x57, 0x80, 0x57, 0xCF,
7535
75360x66, 0x33, 0x66, 0xCF,
75370x47, 0x3B, 0x47, 0xCF,
7538
75390x56, 0x33, 0x56, 0xCF,
75400x67, 0x3B, 0x67, 0xCF,
7541
75420x0B, 0x48, 0xA0, 0xE8,
75430x1B, 0x58, 0xA0, 0xE8,
7544
75450x2B, 0x68, 0xA0, 0xE8,
75460x0C, 0x49, 0xA0, 0xE8,
7547
75480x1C, 0x59, 0xA0, 0xE8,
75490x2C, 0x69, 0xA0, 0xE8,
7550
75510x0B, 0x00,
75520x1B, 0x00,
75530x2B, 0x00,
75540x00, 0xE0,
7555
75560x0C, 0x00,
75570x1C, 0x00,
75580x2C, 0x00,
75590x00, 0xE0,
7560
75610x0B, 0x65,
75620x1B, 0x65,
75630x2B, 0x65,
75640x00, 0xE0,
7565
75660x0C, 0x65,
75670x1C, 0x65,
75680x2C, 0x65,
75690x00, 0xE0,
7570
75710x0B, 0x1B, 0x60, 0xEC,
75720x34, 0xD7, 0x34, 0xAD,
7573
75740x2B, 0x80, 0x60, 0xEC,
75750x0C, 0x1C, 0x60, 0xEC,
7576
75770x3C, 0xD7, 0x3C, 0xAD,
75780x2C, 0x80, 0x60, 0xEC,
7579
75800x0B, 0x2B, 0xDE, 0xE8,
75810x1B, 0x80, 0xDE, 0xE8,
7582
75830x34, 0x80, 0x34, 0xBD,
75840x3C, 0x80, 0x3C, 0xBD,
7585
75860x33, 0xD7, 0x0B, 0xBD,
75870x3B, 0xD7, 0x1B, 0xBD,
7588
75890x48, 0x80, 0x48, 0xCF,
75900x59, 0x80, 0x59, 0xCF,
7591
75920x68, 0x33, 0x68, 0xCF,
75930x49, 0x3B, 0x49, 0xCF,
7594
75950xAD, 0xFF, 0x20, 0xEA,
75960x00, 0x80, 0x00, 0xE8,
7597
75980x58, 0x33, 0x58, 0xCF,
75990x69, 0x3B, 0x69, 0xCF,
7600
76010x6B, 0xFF, 0x20, 0xEA,
76020x57, 0xC0, 0xBF, 0xEA,
7603
76040x00, 0x80, 0xA0, 0xE9,
76050x00, 0x00, 0xD8, 0xEC,
7606
7607};
7608
7609static unsigned char warp_g400_t2gzsaf[] = {
7610
76110x00, 0x8A, 0x98, 0xE9,
76120x00, 0x80, 0x00, 0xE8,
7613
76140x00, 0x80, 0xA0, 0xE9,
76150x00, 0x00, 0xD8, 0xEC,
7616
76170xFF, 0x80, 0xC0, 0xE9,
76180x00, 0x80, 0x00, 0xE8,
7619
76200x0A, 0x40, 0x50, 0xBF,
76210x2A, 0x40, 0x60, 0xBF,
7622
76230x32, 0x41, 0x51, 0xBF,
76240x3A, 0x41, 0x61, 0xBF,
7625
76260xC3, 0x6B,
76270xD3, 0x6B,
76280x00, 0x8A, 0x98, 0xE9,
7629
76300x73, 0x7B, 0xC8, 0xEC,
76310x96, 0xE2,
76320x41, 0x04,
7633
76340x7B, 0x43, 0xA0, 0xE8,
76350x73, 0x53, 0xA0, 0xE8,
7636
76370xAD, 0xEE, 0x23, 0x9F,
76380x00, 0xE0,
76390x51, 0x04,
7640
76410x90, 0xE2,
76420x61, 0x04,
76430x31, 0x46, 0xB1, 0xE8,
7644
76450x51, 0x41, 0xE0, 0xEC,
76460x39, 0x67, 0xB1, 0xE8,
7647
76480x00, 0x04,
76490x46, 0xE2,
76500x73, 0x63, 0xA0, 0xE8,
7651
76520x61, 0x41, 0xE0, 0xEC,
76530x31, 0x00,
76540x39, 0x00,
7655
76560x8E, 0x80, 0x15, 0xEA,
76570x10, 0x04,
76580x20, 0x04,
7659
76600x61, 0x51, 0xE0, 0xEC,
76610x2F, 0x41, 0x60, 0xEA,
7662
76630x31, 0x20,
76640x39, 0x20,
76650x1F, 0x42, 0xA0, 0xE8,
7666
76670x2A, 0x42, 0x52, 0xBF,
76680x0F, 0x52, 0xA0, 0xE8,
7669
76700x1A, 0x42, 0x62, 0xBF,
76710x1E, 0x51, 0x60, 0xEA,
7672
76730x73, 0x7B, 0xC8, 0xEC,
76740x0E, 0x61, 0x60, 0xEA,
7675
76760x32, 0x40, 0x50, 0xBD,
76770x22, 0x40, 0x60, 0xBD,
7678
76790x12, 0x41, 0x51, 0xBD,
76800x3A, 0x41, 0x61, 0xBD,
7681
76820xBF, 0x2F, 0x0E, 0xBD,
76830x97, 0xE2,
76840x7B, 0x72,
7685
76860x32, 0x20,
76870x22, 0x20,
76880x12, 0x20,
76890x3A, 0x20,
7690
76910x35, 0x48, 0xB1, 0xE8,
76920x3D, 0x59, 0xB1, 0xE8,
7693
76940x46, 0x31, 0x46, 0xBF,
76950x56, 0x31, 0x56, 0xBF,
7696
76970xB3, 0xE2, 0x2D, 0x9F,
76980x00, 0x80, 0x00, 0xE8,
7699
77000x66, 0x31, 0x66, 0xBF,
77010x47, 0x39, 0x47, 0xBF,
7702
77030x57, 0x39, 0x57, 0xBF,
77040x67, 0x39, 0x67, 0xBF,
7705
77060x7F, 0x80, 0x07, 0xEA,
77070x24, 0x41, 0x20, 0xE9,
7708
77090x35, 0x00,
77100x3D, 0x00,
77110x00, 0xE0,
77120x2D, 0x73,
7713
77140x33, 0x72,
77150x0C, 0xE3,
77160x8D, 0x2F, 0x1E, 0xBD,
7717
77180x43, 0x75, 0xF8, 0xEC,
77190x35, 0x20,
77200x3D, 0x20,
7721
77220x43, 0x43, 0x2D, 0xDF,
77230x53, 0x53, 0x2D, 0xDF,
7724
77250xAE, 0x1E, 0x0E, 0xBD,
77260x58, 0xE3,
77270x33, 0x66,
7728
77290x48, 0x35, 0x48, 0xBF,
77300x58, 0x35, 0x58, 0xBF,
7731
77320x68, 0x35, 0x68, 0xBF,
77330x49, 0x3D, 0x49, 0xBF,
7734
77350x59, 0x3D, 0x59, 0xBF,
77360x69, 0x3D, 0x69, 0xBF,
7737
77380x63, 0x63, 0x2D, 0xDF,
77390x4D, 0x7D, 0xF8, 0xEC,
7740
77410x59, 0xE3,
77420x00, 0xE0,
77430xB8, 0x38, 0x33, 0xBF,
7744
77450x2D, 0x73,
77460x30, 0x76,
77470x18, 0x3A, 0x41, 0xE9,
7748
77490x3F, 0x53, 0xA0, 0xE8,
77500x05, 0x80, 0x3D, 0xEA,
7751
77520x37, 0x43, 0xA0, 0xE8,
77530x3D, 0x63, 0xA0, 0xE8,
7754
77550x50, 0x70, 0xF8, 0xEC,
77560x2B, 0x50, 0x3C, 0xE9,
7757
77580x1F, 0x0F, 0xBC, 0xE8,
77590x00, 0x80, 0x00, 0xE8,
7760
77610x59, 0x78, 0xF8, 0xEC,
77620x00, 0x80, 0x00, 0xE8,
7763
77640x15, 0xC0, 0x20, 0xE9,
77650x15, 0xC0, 0x20, 0xE9,
7766
77670x15, 0xC0, 0x20, 0xE9,
77680x15, 0xC0, 0x20, 0xE9,
7769
77700x1E, 0x12, 0x41, 0xE9,
77710x1A, 0x22, 0x41, 0xE9,
7772
77730x46, 0x37, 0x46, 0xDF,
77740x56, 0x3F, 0x56, 0xDF,
7775
77760x2B, 0x40, 0x3D, 0xE9,
77770x66, 0x3D, 0x66, 0xDF,
7778
77790x1D, 0x32, 0x41, 0xE9,
77800x67, 0x3D, 0x67, 0xDF,
7781
77820x47, 0x37, 0x47, 0xDF,
77830x57, 0x3F, 0x57, 0xDF,
7784
77850x2A, 0x40, 0x20, 0xE9,
77860x59, 0x3F, 0x59, 0xDF,
7787
77880x16, 0x30, 0x20, 0xE9,
77890x69, 0x3D, 0x69, 0xDF,
7790
77910x48, 0x37, 0x48, 0xDF,
77920x58, 0x3F, 0x58, 0xDF,
7793
77940x68, 0x3D, 0x68, 0xDF,
77950x49, 0x37, 0x49, 0xDF,
7796
77970x32, 0x32, 0x2D, 0xDF,
77980x22, 0x22, 0x2D, 0xDF,
7799
78000x12, 0x12, 0x2D, 0xDF,
78010x3A, 0x3A, 0x2D, 0xDF,
7802
78030x0F, 0xCF, 0x74, 0xC2,
78040x37, 0xCF, 0x74, 0xC4,
7805
78060x0A, 0x44, 0x54, 0xB0,
78070x02, 0x44, 0x64, 0xB0,
7808
78090x3D, 0xCF, 0x74, 0xC0,
78100x34, 0x37, 0x20, 0xE9,
7811
78120x31, 0x53, 0x2F, 0x9F,
78130x38, 0x0F, 0x20, 0xE9,
7814
78150x39, 0xE5, 0x2C, 0x9F,
78160x3C, 0x3D, 0x20, 0xE9,
7817
78180x2A, 0x44, 0x54, 0xB2,
78190x1A, 0x44, 0x64, 0xB2,
7820
78210x3A, 0x80, 0x3A, 0xEA,
78220x0A, 0x20,
78230x02, 0x20,
7824
78250x0F, 0xCF, 0x75, 0xC0,
78260x2A, 0x20,
78270x1A, 0x20,
7828
78290x30, 0x50, 0x2E, 0x9F,
78300x32, 0x31, 0x5F, 0xE9,
7831
78320x38, 0x21, 0x2C, 0x9F,
78330x33, 0x39, 0x5F, 0xE9,
7834
78350x3D, 0xCF, 0x75, 0xC2,
78360x37, 0xCF, 0x75, 0xC4,
7837
78380x31, 0x53, 0x2F, 0x9F,
78390xA6, 0x0F, 0x20, 0xE9,
7840
78410x39, 0xE5, 0x2C, 0x9F,
78420xA3, 0x3D, 0x20, 0xE9,
7843
78440x2A, 0x44, 0x54, 0xB4,
78450x1A, 0x44, 0x64, 0xB4,
7846
78470x0A, 0x45, 0x55, 0xB0,
78480x02, 0x45, 0x65, 0xB0,
7849
78500x88, 0x73, 0x5E, 0xE9,
78510x2A, 0x20,
78520x1A, 0x20,
7853
78540xA0, 0x37, 0x20, 0xE9,
78550x0A, 0x20,
78560x02, 0x20,
7857
78580x31, 0x53, 0x2F, 0x9F,
78590x3E, 0x30, 0x4F, 0xE9,
7860
78610x39, 0xE5, 0x2C, 0x9F,
78620x3F, 0x38, 0x4F, 0xE9,
7863
78640x30, 0x50, 0x2E, 0x9F,
78650x3A, 0x31, 0x4F, 0xE9,
7866
78670x38, 0x21, 0x2C, 0x9F,
78680x3B, 0x39, 0x4F, 0xE9,
7869
78700x2A, 0x45, 0x55, 0xB2,
78710x1A, 0x45, 0x65, 0xB2,
7872
78730x0A, 0x45, 0x55, 0xB4,
78740x02, 0x45, 0x65, 0xB4,
7875
78760x0F, 0xCF, 0x74, 0xC6,
78770x2A, 0x20,
78780x1A, 0x20,
7879
78800xA7, 0x30, 0x4F, 0xE9,
78810x0A, 0x20,
78820x02, 0x20,
7883
78840x31, 0x53, 0x2F, 0x9F,
78850x9C, 0x0F, 0x20, 0xE9,
7886
78870x39, 0xE5, 0x2C, 0x9F,
78880xA8, 0x38, 0x4F, 0xE9,
7889
78900x2A, 0x44, 0x54, 0xB6,
78910x1A, 0x44, 0x64, 0xB6,
7892
78930x30, 0x50, 0x2E, 0x9F,
78940x36, 0x31, 0x4F, 0xE9,
7895
78960x38, 0x21, 0x2C, 0x9F,
78970x37, 0x39, 0x4F, 0xE9,
7898
78990x0A, 0x45, 0x55, 0xB6,
79000x02, 0x45, 0x65, 0xB6,
7901
79020x3D, 0xCF, 0x75, 0xC6,
79030x2A, 0x20,
79040x1A, 0x20,
7905
79060x2A, 0x46, 0x56, 0xBF,
79070x1A, 0x46, 0x66, 0xBF,
7908
79090x31, 0x53, 0x2F, 0x9F,
79100xA4, 0x31, 0x4F, 0xE9,
7911
79120x39, 0xE5, 0x2C, 0x9F,
79130xA5, 0x39, 0x4F, 0xE9,
7914
79150x31, 0x3D, 0x20, 0xE9,
79160x0A, 0x20,
79170x02, 0x20,
7918
79190x0A, 0x47, 0x57, 0xBF,
79200x02, 0x47, 0x67, 0xBF,
7921
79220x30, 0x50, 0x2E, 0x9F,
79230xA1, 0x30, 0x4F, 0xE9,
7924
79250x38, 0x21, 0x2C, 0x9F,
79260xA2, 0x38, 0x4F, 0xE9,
7927
79280x31, 0x53, 0x2F, 0x9F,
79290x9D, 0x31, 0x4F, 0xE9,
7930
79310x39, 0xE5, 0x2C, 0x9F,
79320x9E, 0x39, 0x4F, 0xE9,
7933
79340x2A, 0x43, 0x53, 0xBF,
79350x1A, 0x43, 0x63, 0xBF,
7936
79370x30, 0x50, 0x2E, 0x9F,
79380x35, 0x30, 0x4F, 0xE9,
7939
79400x38, 0x21, 0x2C, 0x9F,
79410x39, 0x38, 0x4F, 0xE9,
7942
79430x0A, 0x48, 0x58, 0xBF,
79440x02, 0x48, 0x68, 0xBF,
7945
79460x31, 0x53, 0x2F, 0x9F,
79470x80, 0x31, 0x57, 0xE9,
7948
79490x39, 0xE5, 0x2C, 0x9F,
79500x81, 0x39, 0x57, 0xE9,
7951
79520x2A, 0x49, 0x59, 0xBF,
79530x1A, 0x49, 0x69, 0xBF,
7954
79550x30, 0x50, 0x2E, 0x9F,
79560x82, 0x30, 0x57, 0xE9,
7957
79580x38, 0x21, 0x2C, 0x9F,
79590x83, 0x38, 0x57, 0xE9,
7960
79610x31, 0x53, 0x2F, 0x9F,
79620x84, 0x31, 0x5E, 0xE9,
7963
79640x39, 0xE5, 0x2C, 0x9F,
79650x85, 0x39, 0x5E, 0xE9,
7966
79670x86, 0x76, 0x57, 0xE9,
79680x8A, 0x36, 0x20, 0xE9,
7969
79700x87, 0x77, 0x57, 0xE9,
79710x8B, 0x3E, 0xBF, 0xEA,
7972
79730x80, 0x30, 0x57, 0xE9,
79740x81, 0x38, 0x57, 0xE9,
7975
79760x82, 0x31, 0x57, 0xE9,
79770x86, 0x78, 0x57, 0xE9,
7978
79790x83, 0x39, 0x57, 0xE9,
79800x87, 0x79, 0x57, 0xE9,
7981
79820x30, 0x1F, 0x5F, 0xE9,
79830x8A, 0x34, 0x20, 0xE9,
7984
79850x8B, 0x3C, 0x20, 0xE9,
79860x37, 0x50, 0x60, 0xBD,
7987
79880x57, 0x0D, 0x20, 0xE9,
79890x35, 0x51, 0x61, 0xBD,
7990
79910x2B, 0x50, 0x20, 0xE9,
79920x1D, 0x37, 0xE1, 0xEA,
7993
79940x1E, 0x35, 0xE1, 0xEA,
79950x00, 0xE0,
79960x0E, 0x77,
7997
79980x24, 0x51, 0x20, 0xE9,
79990x89, 0xFF, 0x20, 0xEA,
8000
80010x16, 0x0E, 0x20, 0xE9,
80020x57, 0x2E, 0xBF, 0xEA,
8003
80040x0B, 0x46, 0xA0, 0xE8,
80050x1B, 0x56, 0xA0, 0xE8,
8006
80070x2B, 0x66, 0xA0, 0xE8,
80080x0C, 0x47, 0xA0, 0xE8,
8009
80100x1C, 0x57, 0xA0, 0xE8,
80110x2C, 0x67, 0xA0, 0xE8,
8012
80130x0B, 0x00,
80140x1B, 0x00,
80150x2B, 0x00,
80160x00, 0xE0,
8017
80180x0C, 0x00,
80190x1C, 0x00,
80200x2C, 0x00,
80210x00, 0xE0,
8022
80230x0B, 0x65,
80240x1B, 0x65,
80250x2B, 0x65,
80260x00, 0xE0,
8027
80280x0C, 0x65,
80290x1C, 0x65,
80300x2C, 0x65,
80310x00, 0xE0,
8032
80330x0B, 0x1B, 0x60, 0xEC,
80340x36, 0xD7, 0x36, 0xAD,
8035
80360x2B, 0x80, 0x60, 0xEC,
80370x0C, 0x1C, 0x60, 0xEC,
8038
80390x3E, 0xD7, 0x3E, 0xAD,
80400x2C, 0x80, 0x60, 0xEC,
8041
80420x0B, 0x2B, 0xDE, 0xE8,
80430x1B, 0x80, 0xDE, 0xE8,
8044
80450x36, 0x80, 0x36, 0xBD,
80460x3E, 0x80, 0x3E, 0xBD,
8047
80480x33, 0xD7, 0x0B, 0xBD,
80490x3B, 0xD7, 0x1B, 0xBD,
8050
80510x46, 0x80, 0x46, 0xCF,
80520x57, 0x80, 0x57, 0xCF,
8053
80540x66, 0x33, 0x66, 0xCF,
80550x47, 0x3B, 0x47, 0xCF,
8056
80570x56, 0x33, 0x56, 0xCF,
80580x67, 0x3B, 0x67, 0xCF,
8059
80600x0B, 0x48, 0xA0, 0xE8,
80610x1B, 0x58, 0xA0, 0xE8,
8062
80630x2B, 0x68, 0xA0, 0xE8,
80640x0C, 0x49, 0xA0, 0xE8,
8065
80660x1C, 0x59, 0xA0, 0xE8,
80670x2C, 0x69, 0xA0, 0xE8,
8068
80690x0B, 0x00,
80700x1B, 0x00,
80710x2B, 0x00,
80720x00, 0xE0,
8073
80740x0C, 0x00,
80750x1C, 0x00,
80760x2C, 0x00,
80770x00, 0xE0,
8078
80790x0B, 0x65,
80800x1B, 0x65,
80810x2B, 0x65,
80820x00, 0xE0,
8083
80840x0C, 0x65,
80850x1C, 0x65,
80860x2C, 0x65,
80870x00, 0xE0,
8088
80890x0B, 0x1B, 0x60, 0xEC,
80900x34, 0xD7, 0x34, 0xAD,
8091
80920x2B, 0x80, 0x60, 0xEC,
80930x0C, 0x1C, 0x60, 0xEC,
8094
80950x3C, 0xD7, 0x3C, 0xAD,
80960x2C, 0x80, 0x60, 0xEC,
8097
80980x0B, 0x2B, 0xDE, 0xE8,
80990x1B, 0x80, 0xDE, 0xE8,
8100
81010x34, 0x80, 0x34, 0xBD,
81020x3C, 0x80, 0x3C, 0xBD,
8103
81040x33, 0xD7, 0x0B, 0xBD,
81050x3B, 0xD7, 0x1B, 0xBD,
8106
81070x48, 0x80, 0x48, 0xCF,
81080x59, 0x80, 0x59, 0xCF,
8109
81100x68, 0x33, 0x68, 0xCF,
81110x49, 0x3B, 0x49, 0xCF,
8112
81130xA9, 0xFF, 0x20, 0xEA,
81140x00, 0x80, 0x00, 0xE8,
8115
81160x58, 0x33, 0x58, 0xCF,
81170x69, 0x3B, 0x69, 0xCF,
8118
81190x67, 0xFF, 0x20, 0xEA,
81200x57, 0xC0, 0xBF, 0xEA,
8121
81220x00, 0x80, 0xA0, 0xE9,
81230x00, 0x00, 0xD8, 0xEC,
8124
8125};
8126
8127static unsigned char warp_g400_t2gzsf[] = {
8128
81290x00, 0x8A, 0x98, 0xE9,
81300x00, 0x80, 0x00, 0xE8,
8131
81320x00, 0x80, 0xA0, 0xE9,
81330x00, 0x00, 0xD8, 0xEC,
8134
81350xFF, 0x80, 0xC0, 0xE9,
81360x00, 0x80, 0x00, 0xE8,
8137
81380x0A, 0x40, 0x50, 0xBF,
81390x2A, 0x40, 0x60, 0xBF,
8140
81410x32, 0x41, 0x51, 0xBF,
81420x3A, 0x41, 0x61, 0xBF,
8143
81440xC3, 0x6B,
81450xD3, 0x6B,
81460x00, 0x8A, 0x98, 0xE9,
8147
81480x73, 0x7B, 0xC8, 0xEC,
81490x96, 0xE2,
81500x41, 0x04,
8151
81520x7B, 0x43, 0xA0, 0xE8,
81530x73, 0x53, 0xA0, 0xE8,
8154
81550xAD, 0xEE, 0x23, 0x9F,
81560x00, 0xE0,
81570x51, 0x04,
8158
81590x90, 0xE2,
81600x61, 0x04,
81610x31, 0x46, 0xB1, 0xE8,
8162
81630x51, 0x41, 0xE0, 0xEC,
81640x39, 0x67, 0xB1, 0xE8,
8165
81660x00, 0x04,
81670x46, 0xE2,
81680x73, 0x63, 0xA0, 0xE8,
8169
81700x61, 0x41, 0xE0, 0xEC,
81710x31, 0x00,
81720x39, 0x00,
8173
81740x8A, 0x80, 0x15, 0xEA,
81750x10, 0x04,
81760x20, 0x04,
8177
81780x61, 0x51, 0xE0, 0xEC,
81790x2F, 0x41, 0x60, 0xEA,
8180
81810x31, 0x20,
81820x39, 0x20,
81830x1F, 0x42, 0xA0, 0xE8,
8184
81850x2A, 0x42, 0x52, 0xBF,
81860x0F, 0x52, 0xA0, 0xE8,
8187
81880x1A, 0x42, 0x62, 0xBF,
81890x1E, 0x51, 0x60, 0xEA,
8190
81910x73, 0x7B, 0xC8, 0xEC,
81920x0E, 0x61, 0x60, 0xEA,
8193
81940x32, 0x40, 0x50, 0xBD,
81950x22, 0x40, 0x60, 0xBD,
8196
81970x12, 0x41, 0x51, 0xBD,
81980x3A, 0x41, 0x61, 0xBD,
8199
82000xBF, 0x2F, 0x0E, 0xBD,
82010x97, 0xE2,
82020x7B, 0x72,
8203
82040x32, 0x20,
82050x22, 0x20,
82060x12, 0x20,
82070x3A, 0x20,
8208
82090x35, 0x48, 0xB1, 0xE8,
82100x3D, 0x59, 0xB1, 0xE8,
8211
82120x46, 0x31, 0x46, 0xBF,
82130x56, 0x31, 0x56, 0xBF,
8214
82150xB3, 0xE2, 0x2D, 0x9F,
82160x00, 0x80, 0x00, 0xE8,
8217
82180x66, 0x31, 0x66, 0xBF,
82190x47, 0x39, 0x47, 0xBF,
8220
82210x57, 0x39, 0x57, 0xBF,
82220x67, 0x39, 0x67, 0xBF,
8223
82240x7B, 0x80, 0x07, 0xEA,
82250x24, 0x41, 0x20, 0xE9,
8226
82270x35, 0x00,
82280x3D, 0x00,
82290x00, 0xE0,
82300x2D, 0x73,
8231
82320x33, 0x72,
82330x0C, 0xE3,
82340x8D, 0x2F, 0x1E, 0xBD,
8235
82360x43, 0x75, 0xF8, 0xEC,
82370x35, 0x20,
82380x3D, 0x20,
8239
82400x43, 0x43, 0x2D, 0xDF,
82410x53, 0x53, 0x2D, 0xDF,
8242
82430xAE, 0x1E, 0x0E, 0xBD,
82440x58, 0xE3,
82450x33, 0x66,
8246
82470x48, 0x35, 0x48, 0xBF,
82480x58, 0x35, 0x58, 0xBF,
8249
82500x68, 0x35, 0x68, 0xBF,
82510x49, 0x3D, 0x49, 0xBF,
8252
82530x59, 0x3D, 0x59, 0xBF,
82540x69, 0x3D, 0x69, 0xBF,
8255
82560x63, 0x63, 0x2D, 0xDF,
82570x4D, 0x7D, 0xF8, 0xEC,
8258
82590x59, 0xE3,
82600x00, 0xE0,
82610xB8, 0x38, 0x33, 0xBF,
8262
82630x2D, 0x73,
82640x30, 0x76,
82650x18, 0x3A, 0x41, 0xE9,
8266
82670x3F, 0x53, 0xA0, 0xE8,
82680x05, 0x80, 0x3D, 0xEA,
8269
82700x37, 0x43, 0xA0, 0xE8,
82710x3D, 0x63, 0xA0, 0xE8,
8272
82730x50, 0x70, 0xF8, 0xEC,
82740x2B, 0x50, 0x3C, 0xE9,
8275
82760x1F, 0x0F, 0xBC, 0xE8,
82770x00, 0x80, 0x00, 0xE8,
8278
82790x59, 0x78, 0xF8, 0xEC,
82800x00, 0x80, 0x00, 0xE8,
8281
82820x15, 0xC0, 0x20, 0xE9,
82830x15, 0xC0, 0x20, 0xE9,
8284
82850x15, 0xC0, 0x20, 0xE9,
82860x15, 0xC0, 0x20, 0xE9,
8287
82880x1E, 0x12, 0x41, 0xE9,
82890x1A, 0x22, 0x41, 0xE9,
8290
82910x46, 0x37, 0x46, 0xDF,
82920x56, 0x3F, 0x56, 0xDF,
8293
82940x2B, 0x40, 0x3D, 0xE9,
82950x66, 0x3D, 0x66, 0xDF,
8296
82970x1D, 0x32, 0x41, 0xE9,
82980x67, 0x3D, 0x67, 0xDF,
8299
83000x47, 0x37, 0x47, 0xDF,
83010x57, 0x3F, 0x57, 0xDF,
8302
83030x2A, 0x40, 0x20, 0xE9,
83040x59, 0x3F, 0x59, 0xDF,
8305
83060x16, 0x30, 0x20, 0xE9,
83070x69, 0x3D, 0x69, 0xDF,
8308
83090x48, 0x37, 0x48, 0xDF,
83100x58, 0x3F, 0x58, 0xDF,
8311
83120x68, 0x3D, 0x68, 0xDF,
83130x49, 0x37, 0x49, 0xDF,
8314
83150x32, 0x32, 0x2D, 0xDF,
83160x22, 0x22, 0x2D, 0xDF,
8317
83180x12, 0x12, 0x2D, 0xDF,
83190x3A, 0x3A, 0x2D, 0xDF,
8320
83210x0F, 0xCF, 0x74, 0xC2,
83220x37, 0xCF, 0x74, 0xC4,
8323
83240x0A, 0x44, 0x54, 0xB0,
83250x02, 0x44, 0x64, 0xB0,
8326
83270x3D, 0xCF, 0x74, 0xC0,
83280x34, 0x37, 0x20, 0xE9,
8329
83300x31, 0x53, 0x2F, 0x9F,
83310x38, 0x0F, 0x20, 0xE9,
8332
83330x39, 0xE5, 0x2C, 0x9F,
83340x3C, 0x3D, 0x20, 0xE9,
8335
83360x2A, 0x44, 0x54, 0xB2,
83370x1A, 0x44, 0x64, 0xB2,
8338
83390x36, 0x80, 0x3A, 0xEA,
83400x0A, 0x20,
83410x02, 0x20,
8342
83430x0F, 0xCF, 0x75, 0xC0,
83440x2A, 0x20,
83450x1A, 0x20,
8346
83470x30, 0x50, 0x2E, 0x9F,
83480x32, 0x31, 0x5F, 0xE9,
8349
83500x38, 0x21, 0x2C, 0x9F,
83510x33, 0x39, 0x5F, 0xE9,
8352
83530x3D, 0xCF, 0x75, 0xC2,
83540x37, 0xCF, 0x75, 0xC4,
8355
83560x31, 0x53, 0x2F, 0x9F,
83570xA6, 0x0F, 0x20, 0xE9,
8358
83590x39, 0xE5, 0x2C, 0x9F,
83600xA3, 0x3D, 0x20, 0xE9,
8361
83620x2A, 0x44, 0x54, 0xB4,
83630x1A, 0x44, 0x64, 0xB4,
8364
83650x0A, 0x45, 0x55, 0xB0,
83660x02, 0x45, 0x65, 0xB0,
8367
83680x88, 0x73, 0x5E, 0xE9,
83690x2A, 0x20,
83700x1A, 0x20,
8371
83720xA0, 0x37, 0x20, 0xE9,
83730x0A, 0x20,
83740x02, 0x20,
8375
83760x31, 0x53, 0x2F, 0x9F,
83770x3E, 0x30, 0x4F, 0xE9,
8378
83790x39, 0xE5, 0x2C, 0x9F,
83800x3F, 0x38, 0x4F, 0xE9,
8381
83820x30, 0x50, 0x2E, 0x9F,
83830x3A, 0x31, 0x4F, 0xE9,
8384
83850x38, 0x21, 0x2C, 0x9F,
83860x3B, 0x39, 0x4F, 0xE9,
8387
83880x2A, 0x45, 0x55, 0xB2,
83890x1A, 0x45, 0x65, 0xB2,
8390
83910x0A, 0x45, 0x55, 0xB4,
83920x02, 0x45, 0x65, 0xB4,
8393
83940x0F, 0xCF, 0x75, 0xC6,
83950x2A, 0x20,
83960x1A, 0x20,
8397
83980xA7, 0x30, 0x4F, 0xE9,
83990x0A, 0x20,
84000x02, 0x20,
8401
84020x31, 0x53, 0x2F, 0x9F,
84030x31, 0x0F, 0x20, 0xE9,
8404
84050x39, 0xE5, 0x2C, 0x9F,
84060xA8, 0x38, 0x4F, 0xE9,
8407
84080x2A, 0x45, 0x55, 0xB6,
84090x1A, 0x45, 0x65, 0xB6,
8410
84110x30, 0x50, 0x2E, 0x9F,
84120x36, 0x31, 0x4F, 0xE9,
8413
84140x38, 0x21, 0x2C, 0x9F,
84150x37, 0x39, 0x4F, 0xE9,
8416
84170x00, 0x80, 0x00, 0xE8,
84180x2A, 0x20,
84190x1A, 0x20,
8420
84210x2A, 0x46, 0x56, 0xBF,
84220x1A, 0x46, 0x66, 0xBF,
8423
84240x31, 0x53, 0x2F, 0x9F,
84250xA4, 0x31, 0x4F, 0xE9,
8426
84270x39, 0xE5, 0x2C, 0x9F,
84280xA5, 0x39, 0x4F, 0xE9,
8429
84300x0A, 0x47, 0x57, 0xBF,
84310x02, 0x47, 0x67, 0xBF,
8432
84330x31, 0x53, 0x2F, 0x9F,
84340xA1, 0x30, 0x4F, 0xE9,
8435
84360x39, 0xE5, 0x2C, 0x9F,
84370xA2, 0x38, 0x4F, 0xE9,
8438
84390x2A, 0x43, 0x53, 0xBF,
84400x1A, 0x43, 0x63, 0xBF,
8441
84420x30, 0x50, 0x2E, 0x9F,
84430x35, 0x31, 0x4F, 0xE9,
8444
84450x38, 0x21, 0x2C, 0x9F,
84460x39, 0x39, 0x4F, 0xE9,
8447
84480x0A, 0x48, 0x58, 0xBF,
84490x02, 0x48, 0x68, 0xBF,
8450
84510x31, 0x53, 0x2F, 0x9F,
84520x80, 0x31, 0x57, 0xE9,
8453
84540x39, 0xE5, 0x2C, 0x9F,
84550x81, 0x39, 0x57, 0xE9,
8456
84570x2A, 0x49, 0x59, 0xBF,
84580x1A, 0x49, 0x69, 0xBF,
8459
84600x30, 0x50, 0x2E, 0x9F,
84610x82, 0x30, 0x57, 0xE9,
8462
84630x38, 0x21, 0x2C, 0x9F,
84640x83, 0x38, 0x57, 0xE9,
8465
84660x31, 0x53, 0x2F, 0x9F,
84670x84, 0x31, 0x5E, 0xE9,
8468
84690x39, 0xE5, 0x2C, 0x9F,
84700x85, 0x39, 0x5E, 0xE9,
8471
84720x86, 0x76, 0x57, 0xE9,
84730x8A, 0x36, 0x20, 0xE9,
8474
84750x87, 0x77, 0x57, 0xE9,
84760x8B, 0x3E, 0xBF, 0xEA,
8477
84780x80, 0x30, 0x57, 0xE9,
84790x81, 0x38, 0x57, 0xE9,
8480
84810x82, 0x31, 0x57, 0xE9,
84820x86, 0x78, 0x57, 0xE9,
8483
84840x83, 0x39, 0x57, 0xE9,
84850x87, 0x79, 0x57, 0xE9,
8486
84870x30, 0x1F, 0x5F, 0xE9,
84880x8A, 0x34, 0x20, 0xE9,
8489
84900x8B, 0x3C, 0x20, 0xE9,
84910x37, 0x50, 0x60, 0xBD,
8492
84930x57, 0x0D, 0x20, 0xE9,
84940x35, 0x51, 0x61, 0xBD,
8495
84960x2B, 0x50, 0x20, 0xE9,
84970x1D, 0x37, 0xE1, 0xEA,
8498
84990x1E, 0x35, 0xE1, 0xEA,
85000x00, 0xE0,
85010x0E, 0x77,
8502
85030x24, 0x51, 0x20, 0xE9,
85040x8D, 0xFF, 0x20, 0xEA,
8505
85060x16, 0x0E, 0x20, 0xE9,
85070x57, 0x2E, 0xBF, 0xEA,
8508
85090x0B, 0x46, 0xA0, 0xE8,
85100x1B, 0x56, 0xA0, 0xE8,
8511
85120x2B, 0x66, 0xA0, 0xE8,
85130x0C, 0x47, 0xA0, 0xE8,
8514
85150x1C, 0x57, 0xA0, 0xE8,
85160x2C, 0x67, 0xA0, 0xE8,
8517
85180x0B, 0x00,
85190x1B, 0x00,
85200x2B, 0x00,
85210x00, 0xE0,
8522
85230x0C, 0x00,
85240x1C, 0x00,
85250x2C, 0x00,
85260x00, 0xE0,
8527
85280x0B, 0x65,
85290x1B, 0x65,
85300x2B, 0x65,
85310x00, 0xE0,
8532
85330x0C, 0x65,
85340x1C, 0x65,
85350x2C, 0x65,
85360x00, 0xE0,
8537
85380x0B, 0x1B, 0x60, 0xEC,
85390x36, 0xD7, 0x36, 0xAD,
8540
85410x2B, 0x80, 0x60, 0xEC,
85420x0C, 0x1C, 0x60, 0xEC,
8543
85440x3E, 0xD7, 0x3E, 0xAD,
85450x2C, 0x80, 0x60, 0xEC,
8546
85470x0B, 0x2B, 0xDE, 0xE8,
85480x1B, 0x80, 0xDE, 0xE8,
8549
85500x36, 0x80, 0x36, 0xBD,
85510x3E, 0x80, 0x3E, 0xBD,
8552
85530x33, 0xD7, 0x0B, 0xBD,
85540x3B, 0xD7, 0x1B, 0xBD,
8555
85560x46, 0x80, 0x46, 0xCF,
85570x57, 0x80, 0x57, 0xCF,
8558
85590x66, 0x33, 0x66, 0xCF,
85600x47, 0x3B, 0x47, 0xCF,
8561
85620x56, 0x33, 0x56, 0xCF,
85630x67, 0x3B, 0x67, 0xCF,
8564
85650x0B, 0x48, 0xA0, 0xE8,
85660x1B, 0x58, 0xA0, 0xE8,
8567
85680x2B, 0x68, 0xA0, 0xE8,
85690x0C, 0x49, 0xA0, 0xE8,
8570
85710x1C, 0x59, 0xA0, 0xE8,
85720x2C, 0x69, 0xA0, 0xE8,
8573
85740x0B, 0x00,
85750x1B, 0x00,
85760x2B, 0x00,
85770x00, 0xE0,
8578
85790x0C, 0x00,
85800x1C, 0x00,
85810x2C, 0x00,
85820x00, 0xE0,
8583
85840x0B, 0x65,
85850x1B, 0x65,
85860x2B, 0x65,
85870x00, 0xE0,
8588
85890x0C, 0x65,
85900x1C, 0x65,
85910x2C, 0x65,
85920x00, 0xE0,
8593
85940x0B, 0x1B, 0x60, 0xEC,
85950x34, 0xD7, 0x34, 0xAD,
8596
85970x2B, 0x80, 0x60, 0xEC,
85980x0C, 0x1C, 0x60, 0xEC,
8599
86000x3C, 0xD7, 0x3C, 0xAD,
86010x2C, 0x80, 0x60, 0xEC,
8602
86030x0B, 0x2B, 0xDE, 0xE8,
86040x1B, 0x80, 0xDE, 0xE8,
8605
86060x34, 0x80, 0x34, 0xBD,
86070x3C, 0x80, 0x3C, 0xBD,
8608
86090x33, 0xD7, 0x0B, 0xBD,
86100x3B, 0xD7, 0x1B, 0xBD,
8611
86120x48, 0x80, 0x48, 0xCF,
86130x59, 0x80, 0x59, 0xCF,
8614
86150x68, 0x33, 0x68, 0xCF,
86160x49, 0x3B, 0x49, 0xCF,
8617
86180xAD, 0xFF, 0x20, 0xEA,
86190x00, 0x80, 0x00, 0xE8,
8620
86210x58, 0x33, 0x58, 0xCF,
86220x69, 0x3B, 0x69, 0xCF,
8623
86240x6B, 0xFF, 0x20, 0xEA,
86250x57, 0xC0, 0xBF, 0xEA,
8626
86270x00, 0x80, 0xA0, 0xE9,
86280x00, 0x00, 0xD8, 0xEC,
8629
8630};
8631
8632static unsigned char warp_g400_tgz[] = {
8633
86340x00, 0x88, 0x98, 0xE9,
86350x00, 0x80, 0x00, 0xE8,
8636
86370x00, 0x80, 0xA0, 0xE9,
86380x00, 0x00, 0xD8, 0xEC,
8639
86400xFF, 0x80, 0xC0, 0xE9,
86410x00, 0x80, 0x00, 0xE8,
8642
86430x22, 0x40, 0x48, 0xBF,
86440x2A, 0x40, 0x50, 0xBF,
8645
86460x32, 0x41, 0x49, 0xBF,
86470x3A, 0x41, 0x51, 0xBF,
8648
86490xC3, 0x6B,
86500xCB, 0x6B,
86510x00, 0x88, 0x98, 0xE9,
8652
86530x73, 0x7B, 0xC8, 0xEC,
86540x96, 0xE2,
86550x41, 0x04,
8656
86570x7B, 0x43, 0xA0, 0xE8,
86580x73, 0x4B, 0xA0, 0xE8,
8659
86600xAD, 0xEE, 0x29, 0x9F,
86610x00, 0xE0,
86620x49, 0x04,
8663
86640x90, 0xE2,
86650x51, 0x04,
86660x31, 0x46, 0xB1, 0xE8,
8667
86680x49, 0x41, 0xC0, 0xEC,
86690x39, 0x57, 0xB1, 0xE8,
8670
86710x00, 0x04,
86720x46, 0xE2,
86730x73, 0x53, 0xA0, 0xE8,
8674
86750x51, 0x41, 0xC0, 0xEC,
86760x31, 0x00,
86770x39, 0x00,
8678
86790x58, 0x80, 0x15, 0xEA,
86800x08, 0x04,
86810x10, 0x04,
8682
86830x51, 0x49, 0xC0, 0xEC,
86840x2F, 0x41, 0x60, 0xEA,
8685
86860x31, 0x20,
86870x39, 0x20,
86880x1F, 0x42, 0xA0, 0xE8,
8689
86900x2A, 0x42, 0x4A, 0xBF,
86910x27, 0x4A, 0xA0, 0xE8,
8692
86930x1A, 0x42, 0x52, 0xBF,
86940x1E, 0x49, 0x60, 0xEA,
8695
86960x73, 0x7B, 0xC8, 0xEC,
86970x26, 0x51, 0x60, 0xEA,
8698
86990x32, 0x40, 0x48, 0xBD,
87000x22, 0x40, 0x50, 0xBD,
8701
87020x12, 0x41, 0x49, 0xBD,
87030x3A, 0x41, 0x51, 0xBD,
8704
87050xBF, 0x2F, 0x26, 0xBD,
87060x00, 0xE0,
87070x7B, 0x72,
8708
87090x32, 0x20,
87100x22, 0x20,
87110x12, 0x20,
87120x3A, 0x20,
8713
87140x46, 0x31, 0x46, 0xBF,
87150x4E, 0x31, 0x4E, 0xBF,
8716
87170xB3, 0xE2, 0x2D, 0x9F,
87180x00, 0x80, 0x00, 0xE8,
8719
87200x56, 0x31, 0x56, 0xBF,
87210x47, 0x39, 0x47, 0xBF,
8722
87230x4F, 0x39, 0x4F, 0xBF,
87240x57, 0x39, 0x57, 0xBF,
8725
87260x4A, 0x80, 0x07, 0xEA,
87270x24, 0x41, 0x20, 0xE9,
8728
87290x42, 0x73, 0xF8, 0xEC,
87300x00, 0xE0,
87310x2D, 0x73,
8732
87330x33, 0x72,
87340x0C, 0xE3,
87350xA5, 0x2F, 0x1E, 0xBD,
8736
87370x43, 0x43, 0x2D, 0xDF,
87380x4B, 0x4B, 0x2D, 0xDF,
8739
87400xAE, 0x1E, 0x26, 0xBD,
87410x58, 0xE3,
87420x33, 0x66,
8743
87440x53, 0x53, 0x2D, 0xDF,
87450x00, 0x80, 0x00, 0xE8,
8746
87470xB8, 0x38, 0x33, 0xBF,
87480x00, 0xE0,
87490x59, 0xE3,
8750
87510x1E, 0x12, 0x41, 0xE9,
87520x1A, 0x22, 0x41, 0xE9,
8753
87540x2B, 0x40, 0x3D, 0xE9,
87550x3F, 0x4B, 0xA0, 0xE8,
8756
87570x2D, 0x73,
87580x30, 0x76,
87590x05, 0x80, 0x3D, 0xEA,
8760
87610x37, 0x43, 0xA0, 0xE8,
87620x3D, 0x53, 0xA0, 0xE8,
8763
87640x48, 0x70, 0xF8, 0xEC,
87650x2B, 0x48, 0x3C, 0xE9,
8766
87670x1F, 0x27, 0xBC, 0xE8,
87680x00, 0x80, 0x00, 0xE8,
8769
87700x00, 0x80, 0x00, 0xE8,
87710x00, 0x80, 0x00, 0xE8,
8772
87730x15, 0xC0, 0x20, 0xE9,
87740x15, 0xC0, 0x20, 0xE9,
8775
87760x15, 0xC0, 0x20, 0xE9,
87770x15, 0xC0, 0x20, 0xE9,
8778
87790x18, 0x3A, 0x41, 0xE9,
87800x1D, 0x32, 0x41, 0xE9,
8781
87820x2A, 0x40, 0x20, 0xE9,
87830x56, 0x3D, 0x56, 0xDF,
8784
87850x46, 0x37, 0x46, 0xDF,
87860x4E, 0x3F, 0x4E, 0xDF,
8787
87880x16, 0x30, 0x20, 0xE9,
87890x4F, 0x3F, 0x4F, 0xDF,
8790
87910x32, 0x32, 0x2D, 0xDF,
87920x22, 0x22, 0x2D, 0xDF,
8793
87940x12, 0x12, 0x2D, 0xDF,
87950x3A, 0x3A, 0x2D, 0xDF,
8796
87970x47, 0x37, 0x47, 0xDF,
87980x57, 0x3D, 0x57, 0xDF,
8799
88000x3D, 0xCF, 0x74, 0xC0,
88010x37, 0xCF, 0x74, 0xC4,
8802
88030x31, 0x53, 0x2F, 0x9F,
88040x34, 0x80, 0x20, 0xE9,
8805
88060x39, 0xE5, 0x2C, 0x9F,
88070x3C, 0x3D, 0x20, 0xE9,
8808
88090x0A, 0x44, 0x4C, 0xB0,
88100x02, 0x44, 0x54, 0xB0,
8811
88120x2A, 0x44, 0x4C, 0xB2,
88130x1A, 0x44, 0x54, 0xB2,
8814
88150x1D, 0x80, 0x3A, 0xEA,
88160x0A, 0x20,
88170x02, 0x20,
8818
88190x3D, 0xCF, 0x74, 0xC2,
88200x2A, 0x20,
88210x1A, 0x20,
8822
88230x30, 0x50, 0x2E, 0x9F,
88240x32, 0x31, 0x5F, 0xE9,
8825
88260x38, 0x21, 0x2C, 0x9F,
88270x33, 0x39, 0x5F, 0xE9,
8828
88290x31, 0x53, 0x2F, 0x9F,
88300x00, 0x80, 0x00, 0xE8,
8831
88320x2A, 0x44, 0x4C, 0xB4,
88330x1A, 0x44, 0x54, 0xB4,
8834
88350x39, 0xE5, 0x2C, 0x9F,
88360x38, 0x3D, 0x20, 0xE9,
8837
88380x88, 0x73, 0x5E, 0xE9,
88390x2A, 0x20,
88400x1A, 0x20,
8841
88420x2A, 0x46, 0x4E, 0xBF,
88430x1A, 0x46, 0x56, 0xBF,
8844
88450x31, 0x53, 0x2F, 0x9F,
88460x3E, 0x30, 0x4F, 0xE9,
8847
88480x39, 0xE5, 0x2C, 0x9F,
88490x3F, 0x38, 0x4F, 0xE9,
8850
88510x0A, 0x47, 0x4F, 0xBF,
88520x02, 0x47, 0x57, 0xBF,
8853
88540x31, 0x53, 0x2F, 0x9F,
88550x3A, 0x31, 0x4F, 0xE9,
8856
88570x39, 0xE5, 0x2C, 0x9F,
88580x3B, 0x39, 0x4F, 0xE9,
8859
88600x2A, 0x43, 0x4B, 0xBF,
88610x1A, 0x43, 0x53, 0xBF,
8862
88630x30, 0x50, 0x2E, 0x9F,
88640x36, 0x31, 0x4F, 0xE9,
8865
88660x38, 0x21, 0x2C, 0x9F,
88670x37, 0x39, 0x4F, 0xE9,
8868
88690x31, 0x53, 0x2F, 0x9F,
88700x80, 0x31, 0x57, 0xE9,
8871
88720x39, 0xE5, 0x2C, 0x9F,
88730x81, 0x39, 0x57, 0xE9,
8874
88750x37, 0x48, 0x50, 0xBD,
88760x8A, 0x36, 0x20, 0xE9,
8877
88780x86, 0x76, 0x57, 0xE9,
88790x8B, 0x3E, 0x20, 0xE9,
8880
88810x82, 0x30, 0x57, 0xE9,
88820x87, 0x77, 0x57, 0xE9,
8883
88840x83, 0x38, 0x57, 0xE9,
88850x35, 0x49, 0x51, 0xBD,
8886
88870x84, 0x31, 0x5E, 0xE9,
88880x30, 0x1F, 0x5F, 0xE9,
8889
88900x85, 0x39, 0x5E, 0xE9,
88910x57, 0x25, 0x20, 0xE9,
8892
88930x2B, 0x48, 0x20, 0xE9,
88940x1D, 0x37, 0xE1, 0xEA,
8895
88960x1E, 0x35, 0xE1, 0xEA,
88970x00, 0xE0,
88980x26, 0x77,
8899
89000x24, 0x49, 0x20, 0xE9,
89010xAF, 0xFF, 0x20, 0xEA,
8902
89030x16, 0x26, 0x20, 0xE9,
89040x57, 0x2E, 0xBF, 0xEA,
8905
89060x1C, 0x46, 0xA0, 0xE8,
89070x23, 0x4E, 0xA0, 0xE8,
8908
89090x2B, 0x56, 0xA0, 0xE8,
89100x1D, 0x47, 0xA0, 0xE8,
8911
89120x24, 0x4F, 0xA0, 0xE8,
89130x2C, 0x57, 0xA0, 0xE8,
8914
89150x1C, 0x00,
89160x23, 0x00,
89170x2B, 0x00,
89180x00, 0xE0,
8919
89200x1D, 0x00,
89210x24, 0x00,
89220x2C, 0x00,
89230x00, 0xE0,
8924
89250x1C, 0x65,
89260x23, 0x65,
89270x2B, 0x65,
89280x00, 0xE0,
8929
89300x1D, 0x65,
89310x24, 0x65,
89320x2C, 0x65,
89330x00, 0xE0,
8934
89350x1C, 0x23, 0x60, 0xEC,
89360x36, 0xD7, 0x36, 0xAD,
8937
89380x2B, 0x80, 0x60, 0xEC,
89390x1D, 0x24, 0x60, 0xEC,
8940
89410x3E, 0xD7, 0x3E, 0xAD,
89420x2C, 0x80, 0x60, 0xEC,
8943
89440x1C, 0x2B, 0xDE, 0xE8,
89450x23, 0x80, 0xDE, 0xE8,
8946
89470x36, 0x80, 0x36, 0xBD,
89480x3E, 0x80, 0x3E, 0xBD,
8949
89500x33, 0xD7, 0x1C, 0xBD,
89510x3B, 0xD7, 0x23, 0xBD,
8952
89530x46, 0x80, 0x46, 0xCF,
89540x4F, 0x80, 0x4F, 0xCF,
8955
89560x56, 0x33, 0x56, 0xCF,
89570x47, 0x3B, 0x47, 0xCF,
8958
89590xD6, 0xFF, 0x20, 0xEA,
89600x00, 0x80, 0x00, 0xE8,
8961
89620x4E, 0x33, 0x4E, 0xCF,
89630x57, 0x3B, 0x57, 0xCF,
8964
89650x9D, 0xFF, 0x20, 0xEA,
89660x57, 0xC0, 0xBF, 0xEA,
8967
89680x00, 0x80, 0xA0, 0xE9,
89690x00, 0x00, 0xD8, 0xEC,
8970
8971};
8972
8973static unsigned char warp_g400_tgza[] = {
8974
89750x00, 0x88, 0x98, 0xE9,
89760x00, 0x80, 0x00, 0xE8,
8977
89780x00, 0x80, 0xA0, 0xE9,
89790x00, 0x00, 0xD8, 0xEC,
8980
89810xFF, 0x80, 0xC0, 0xE9,
89820x00, 0x80, 0x00, 0xE8,
8983
89840x22, 0x40, 0x48, 0xBF,
89850x2A, 0x40, 0x50, 0xBF,
8986
89870x32, 0x41, 0x49, 0xBF,
89880x3A, 0x41, 0x51, 0xBF,
8989
89900xC3, 0x6B,
89910xCB, 0x6B,
89920x00, 0x88, 0x98, 0xE9,
8993
89940x73, 0x7B, 0xC8, 0xEC,
89950x96, 0xE2,
89960x41, 0x04,
8997
89980x7B, 0x43, 0xA0, 0xE8,
89990x73, 0x4B, 0xA0, 0xE8,
9000
90010xAD, 0xEE, 0x29, 0x9F,
90020x00, 0xE0,
90030x49, 0x04,
9004
90050x90, 0xE2,
90060x51, 0x04,
90070x31, 0x46, 0xB1, 0xE8,
9008
90090x49, 0x41, 0xC0, 0xEC,
90100x39, 0x57, 0xB1, 0xE8,
9011
90120x00, 0x04,
90130x46, 0xE2,
90140x73, 0x53, 0xA0, 0xE8,
9015
90160x51, 0x41, 0xC0, 0xEC,
90170x31, 0x00,
90180x39, 0x00,
9019
90200x5C, 0x80, 0x15, 0xEA,
90210x08, 0x04,
90220x10, 0x04,
9023
90240x51, 0x49, 0xC0, 0xEC,
90250x2F, 0x41, 0x60, 0xEA,
9026
90270x31, 0x20,
90280x39, 0x20,
90290x1F, 0x42, 0xA0, 0xE8,
9030
90310x2A, 0x42, 0x4A, 0xBF,
90320x27, 0x4A, 0xA0, 0xE8,
9033
90340x1A, 0x42, 0x52, 0xBF,
90350x1E, 0x49, 0x60, 0xEA,
9036
90370x73, 0x7B, 0xC8, 0xEC,
90380x26, 0x51, 0x60, 0xEA,
9039
90400x32, 0x40, 0x48, 0xBD,
90410x22, 0x40, 0x50, 0xBD,
9042
90430x12, 0x41, 0x49, 0xBD,
90440x3A, 0x41, 0x51, 0xBD,
9045
90460xBF, 0x2F, 0x26, 0xBD,
90470x00, 0xE0,
90480x7B, 0x72,
9049
90500x32, 0x20,
90510x22, 0x20,
90520x12, 0x20,
90530x3A, 0x20,
9054
90550x46, 0x31, 0x46, 0xBF,
90560x4E, 0x31, 0x4E, 0xBF,
9057
90580xB3, 0xE2, 0x2D, 0x9F,
90590x00, 0x80, 0x00, 0xE8,
9060
90610x56, 0x31, 0x56, 0xBF,
90620x47, 0x39, 0x47, 0xBF,
9063
90640x4F, 0x39, 0x4F, 0xBF,
90650x57, 0x39, 0x57, 0xBF,
9066
90670x4E, 0x80, 0x07, 0xEA,
90680x24, 0x41, 0x20, 0xE9,
9069
90700x42, 0x73, 0xF8, 0xEC,
90710x00, 0xE0,
90720x2D, 0x73,
9073
90740x33, 0x72,
90750x0C, 0xE3,
90760xA5, 0x2F, 0x1E, 0xBD,
9077
90780x43, 0x43, 0x2D, 0xDF,
90790x4B, 0x4B, 0x2D, 0xDF,
9080
90810xAE, 0x1E, 0x26, 0xBD,
90820x58, 0xE3,
90830x33, 0x66,
9084
90850x53, 0x53, 0x2D, 0xDF,
90860x00, 0x80, 0x00, 0xE8,
9087
90880xB8, 0x38, 0x33, 0xBF,
90890x00, 0xE0,
90900x59, 0xE3,
9091
90920x1E, 0x12, 0x41, 0xE9,
90930x1A, 0x22, 0x41, 0xE9,
9094
90950x2B, 0x40, 0x3D, 0xE9,
90960x3F, 0x4B, 0xA0, 0xE8,
9097
90980x2D, 0x73,
90990x30, 0x76,
91000x05, 0x80, 0x3D, 0xEA,
9101
91020x37, 0x43, 0xA0, 0xE8,
91030x3D, 0x53, 0xA0, 0xE8,
9104
91050x48, 0x70, 0xF8, 0xEC,
91060x2B, 0x48, 0x3C, 0xE9,
9107
91080x1F, 0x27, 0xBC, 0xE8,
91090x00, 0x80, 0x00, 0xE8,
9110
91110x00, 0x80, 0x00, 0xE8,
91120x00, 0x80, 0x00, 0xE8,
9113
91140x15, 0xC0, 0x20, 0xE9,
91150x15, 0xC0, 0x20, 0xE9,
9116
91170x15, 0xC0, 0x20, 0xE9,
91180x15, 0xC0, 0x20, 0xE9,
9119
91200x18, 0x3A, 0x41, 0xE9,
91210x1D, 0x32, 0x41, 0xE9,
9122
91230x2A, 0x40, 0x20, 0xE9,
91240x56, 0x3D, 0x56, 0xDF,
9125
91260x46, 0x37, 0x46, 0xDF,
91270x4E, 0x3F, 0x4E, 0xDF,
9128
91290x16, 0x30, 0x20, 0xE9,
91300x4F, 0x3F, 0x4F, 0xDF,
9131
91320x32, 0x32, 0x2D, 0xDF,
91330x22, 0x22, 0x2D, 0xDF,
9134
91350x12, 0x12, 0x2D, 0xDF,
91360x3A, 0x3A, 0x2D, 0xDF,
9137
91380x47, 0x37, 0x47, 0xDF,
91390x57, 0x3D, 0x57, 0xDF,
9140
91410x3D, 0xCF, 0x74, 0xC0,
91420x37, 0xCF, 0x74, 0xC4,
9143
91440x31, 0x53, 0x2F, 0x9F,
91450x34, 0x80, 0x20, 0xE9,
9146
91470x39, 0xE5, 0x2C, 0x9F,
91480x3C, 0x3D, 0x20, 0xE9,
9149
91500x27, 0xCF, 0x74, 0xC6,
91510x3D, 0xCF, 0x74, 0xC2,
9152
91530x0A, 0x44, 0x4C, 0xB0,
91540x02, 0x44, 0x54, 0xB0,
9155
91560x2A, 0x44, 0x4C, 0xB2,
91570x1A, 0x44, 0x54, 0xB2,
9158
91590x20, 0x80, 0x3A, 0xEA,
91600x0A, 0x20,
91610x02, 0x20,
9162
91630x88, 0x73, 0x5E, 0xE9,
91640x2A, 0x20,
91650x1A, 0x20,
9166
91670x30, 0x50, 0x2E, 0x9F,
91680x32, 0x31, 0x5F, 0xE9,
9169
91700x38, 0x21, 0x2C, 0x9F,
91710x33, 0x39, 0x5F, 0xE9,
9172
91730x31, 0x53, 0x2F, 0x9F,
91740x9C, 0x27, 0x20, 0xE9,
9175
91760x0A, 0x44, 0x4C, 0xB4,
91770x02, 0x44, 0x54, 0xB4,
9178
91790x2A, 0x44, 0x4C, 0xB6,
91800x1A, 0x44, 0x54, 0xB6,
9181
91820x39, 0xE5, 0x2C, 0x9F,
91830x38, 0x3D, 0x20, 0xE9,
9184
91850x0A, 0x20,
91860x02, 0x20,
91870x2A, 0x20,
91880x1A, 0x20,
9189
91900x0A, 0x47, 0x4F, 0xBF,
91910x02, 0x47, 0x57, 0xBF,
9192
91930x30, 0x50, 0x2E, 0x9F,
91940x3E, 0x30, 0x4F, 0xE9,
9195
91960x38, 0x21, 0x2C, 0x9F,
91970x3F, 0x38, 0x4F, 0xE9,
9198
91990x2A, 0x46, 0x4E, 0xBF,
92000x1A, 0x46, 0x56, 0xBF,
9201
92020x31, 0x53, 0x2F, 0x9F,
92030x3A, 0x31, 0x4F, 0xE9,
9204
92050x39, 0xE5, 0x2C, 0x9F,
92060x3B, 0x39, 0x4F, 0xE9,
9207
92080x31, 0x53, 0x2F, 0x9F,
92090x36, 0x30, 0x4F, 0xE9,
9210
92110x39, 0xE5, 0x2C, 0x9F,
92120x37, 0x38, 0x4F, 0xE9,
9213
92140x2A, 0x43, 0x4B, 0xBF,
92150x1A, 0x43, 0x53, 0xBF,
9216
92170x30, 0x50, 0x2E, 0x9F,
92180x9D, 0x31, 0x4F, 0xE9,
9219
92200x38, 0x21, 0x2C, 0x9F,
92210x9E, 0x39, 0x4F, 0xE9,
9222
92230x31, 0x53, 0x2F, 0x9F,
92240x80, 0x31, 0x57, 0xE9,
9225
92260x39, 0xE5, 0x2C, 0x9F,
92270x81, 0x39, 0x57, 0xE9,
9228
92290x37, 0x48, 0x50, 0xBD,
92300x8A, 0x36, 0x20, 0xE9,
9231
92320x86, 0x76, 0x57, 0xE9,
92330x8B, 0x3E, 0x20, 0xE9,
9234
92350x82, 0x30, 0x57, 0xE9,
92360x87, 0x77, 0x57, 0xE9,
9237
92380x83, 0x38, 0x57, 0xE9,
92390x35, 0x49, 0x51, 0xBD,
9240
92410x84, 0x31, 0x5E, 0xE9,
92420x30, 0x1F, 0x5F, 0xE9,
9243
92440x85, 0x39, 0x5E, 0xE9,
92450x57, 0x25, 0x20, 0xE9,
9246
92470x2B, 0x48, 0x20, 0xE9,
92480x1D, 0x37, 0xE1, 0xEA,
9249
92500x1E, 0x35, 0xE1, 0xEA,
92510x00, 0xE0,
92520x26, 0x77,
9253
92540x24, 0x49, 0x20, 0xE9,
92550xAB, 0xFF, 0x20, 0xEA,
9256
92570x16, 0x26, 0x20, 0xE9,
92580x57, 0x2E, 0xBF, 0xEA,
9259
92600x1C, 0x46, 0xA0, 0xE8,
92610x23, 0x4E, 0xA0, 0xE8,
9262
92630x2B, 0x56, 0xA0, 0xE8,
92640x1D, 0x47, 0xA0, 0xE8,
9265
92660x24, 0x4F, 0xA0, 0xE8,
92670x2C, 0x57, 0xA0, 0xE8,
9268
92690x1C, 0x00,
92700x23, 0x00,
92710x2B, 0x00,
92720x00, 0xE0,
9273
92740x1D, 0x00,
92750x24, 0x00,
92760x2C, 0x00,
92770x00, 0xE0,
9278
92790x1C, 0x65,
92800x23, 0x65,
92810x2B, 0x65,
92820x00, 0xE0,
9283
92840x1D, 0x65,
92850x24, 0x65,
92860x2C, 0x65,
92870x00, 0xE0,
9288
92890x1C, 0x23, 0x60, 0xEC,
92900x36, 0xD7, 0x36, 0xAD,
9291
92920x2B, 0x80, 0x60, 0xEC,
92930x1D, 0x24, 0x60, 0xEC,
9294
92950x3E, 0xD7, 0x3E, 0xAD,
92960x2C, 0x80, 0x60, 0xEC,
9297
92980x1C, 0x2B, 0xDE, 0xE8,
92990x23, 0x80, 0xDE, 0xE8,
9300
93010x36, 0x80, 0x36, 0xBD,
93020x3E, 0x80, 0x3E, 0xBD,
9303
93040x33, 0xD7, 0x1C, 0xBD,
93050x3B, 0xD7, 0x23, 0xBD,
9306
93070x46, 0x80, 0x46, 0xCF,
93080x4F, 0x80, 0x4F, 0xCF,
9309
93100x56, 0x33, 0x56, 0xCF,
93110x47, 0x3B, 0x47, 0xCF,
9312
93130xD3, 0xFF, 0x20, 0xEA,
93140x00, 0x80, 0x00, 0xE8,
9315
93160x4E, 0x33, 0x4E, 0xCF,
93170x57, 0x3B, 0x57, 0xCF,
9318
93190x99, 0xFF, 0x20, 0xEA,
93200x57, 0xC0, 0xBF, 0xEA,
9321
93220x00, 0x80, 0xA0, 0xE9,
93230x00, 0x00, 0xD8, 0xEC,
9324
9325};
9326
9327static unsigned char warp_g400_tgzaf[] = {
9328
93290x00, 0x88, 0x98, 0xE9,
93300x00, 0x80, 0x00, 0xE8,
9331
93320x00, 0x80, 0xA0, 0xE9,
93330x00, 0x00, 0xD8, 0xEC,
9334
93350xFF, 0x80, 0xC0, 0xE9,
93360x00, 0x80, 0x00, 0xE8,
9337
93380x22, 0x40, 0x48, 0xBF,
93390x2A, 0x40, 0x50, 0xBF,
9340
93410x32, 0x41, 0x49, 0xBF,
93420x3A, 0x41, 0x51, 0xBF,
9343
93440xC3, 0x6B,
93450xCB, 0x6B,
93460x00, 0x88, 0x98, 0xE9,
9347
93480x73, 0x7B, 0xC8, 0xEC,
93490x96, 0xE2,
93500x41, 0x04,
9351
93520x7B, 0x43, 0xA0, 0xE8,
93530x73, 0x4B, 0xA0, 0xE8,
9354
93550xAD, 0xEE, 0x29, 0x9F,
93560x00, 0xE0,
93570x49, 0x04,
9358
93590x90, 0xE2,
93600x51, 0x04,
93610x31, 0x46, 0xB1, 0xE8,
9362
93630x49, 0x41, 0xC0, 0xEC,
93640x39, 0x57, 0xB1, 0xE8,
9365
93660x00, 0x04,
93670x46, 0xE2,
93680x73, 0x53, 0xA0, 0xE8,
9369
93700x51, 0x41, 0xC0, 0xEC,
93710x31, 0x00,
93720x39, 0x00,
9373
93740x61, 0x80, 0x15, 0xEA,
93750x08, 0x04,
93760x10, 0x04,
9377
93780x51, 0x49, 0xC0, 0xEC,
93790x2F, 0x41, 0x60, 0xEA,
9380
93810x31, 0x20,
93820x39, 0x20,
93830x1F, 0x42, 0xA0, 0xE8,
9384
93850x2A, 0x42, 0x4A, 0xBF,
93860x27, 0x4A, 0xA0, 0xE8,
9387
93880x1A, 0x42, 0x52, 0xBF,
93890x1E, 0x49, 0x60, 0xEA,
9390
93910x73, 0x7B, 0xC8, 0xEC,
93920x26, 0x51, 0x60, 0xEA,
9393
93940x32, 0x40, 0x48, 0xBD,
93950x22, 0x40, 0x50, 0xBD,
9396
93970x12, 0x41, 0x49, 0xBD,
93980x3A, 0x41, 0x51, 0xBD,
9399
94000xBF, 0x2F, 0x26, 0xBD,
94010x00, 0xE0,
94020x7B, 0x72,
9403
94040x32, 0x20,
94050x22, 0x20,
94060x12, 0x20,
94070x3A, 0x20,
9408
94090x46, 0x31, 0x46, 0xBF,
94100x4E, 0x31, 0x4E, 0xBF,
9411
94120xB3, 0xE2, 0x2D, 0x9F,
94130x00, 0x80, 0x00, 0xE8,
9414
94150x56, 0x31, 0x56, 0xBF,
94160x47, 0x39, 0x47, 0xBF,
9417
94180x4F, 0x39, 0x4F, 0xBF,
94190x57, 0x39, 0x57, 0xBF,
9420
94210x53, 0x80, 0x07, 0xEA,
94220x24, 0x41, 0x20, 0xE9,
9423
94240x42, 0x73, 0xF8, 0xEC,
94250x00, 0xE0,
94260x2D, 0x73,
9427
94280x33, 0x72,
94290x0C, 0xE3,
94300xA5, 0x2F, 0x1E, 0xBD,
9431
94320x43, 0x43, 0x2D, 0xDF,
94330x4B, 0x4B, 0x2D, 0xDF,
9434
94350xAE, 0x1E, 0x26, 0xBD,
94360x58, 0xE3,
94370x33, 0x66,
9438
94390x53, 0x53, 0x2D, 0xDF,
94400x00, 0x80, 0x00, 0xE8,
9441
94420xB8, 0x38, 0x33, 0xBF,
94430x00, 0xE0,
94440x59, 0xE3,
9445
94460x1E, 0x12, 0x41, 0xE9,
94470x1A, 0x22, 0x41, 0xE9,
9448
94490x2B, 0x40, 0x3D, 0xE9,
94500x3F, 0x4B, 0xA0, 0xE8,
9451
94520x2D, 0x73,
94530x30, 0x76,
94540x05, 0x80, 0x3D, 0xEA,
9455
94560x37, 0x43, 0xA0, 0xE8,
94570x3D, 0x53, 0xA0, 0xE8,
9458
94590x48, 0x70, 0xF8, 0xEC,
94600x2B, 0x48, 0x3C, 0xE9,
9461
94620x1F, 0x27, 0xBC, 0xE8,
94630x00, 0x80, 0x00, 0xE8,
9464
94650x00, 0x80, 0x00, 0xE8,
94660x00, 0x80, 0x00, 0xE8,
9467
94680x15, 0xC0, 0x20, 0xE9,
94690x15, 0xC0, 0x20, 0xE9,
9470
94710x15, 0xC0, 0x20, 0xE9,
94720x15, 0xC0, 0x20, 0xE9,
9473
94740x18, 0x3A, 0x41, 0xE9,
94750x1D, 0x32, 0x41, 0xE9,
9476
94770x2A, 0x40, 0x20, 0xE9,
94780x56, 0x3D, 0x56, 0xDF,
9479
94800x46, 0x37, 0x46, 0xDF,
94810x4E, 0x3F, 0x4E, 0xDF,
9482
94830x16, 0x30, 0x20, 0xE9,
94840x4F, 0x3F, 0x4F, 0xDF,
9485
94860x32, 0x32, 0x2D, 0xDF,
94870x22, 0x22, 0x2D, 0xDF,
9488
94890x12, 0x12, 0x2D, 0xDF,
94900x3A, 0x3A, 0x2D, 0xDF,
9491
94920x47, 0x37, 0x47, 0xDF,
94930x57, 0x3D, 0x57, 0xDF,
9494
94950x3D, 0xCF, 0x74, 0xC0,
94960x37, 0xCF, 0x74, 0xC4,
9497
94980x0A, 0x44, 0x4C, 0xB0,
94990x02, 0x44, 0x54, 0xB0,
9500
95010x31, 0x53, 0x2F, 0x9F,
95020x34, 0x37, 0x20, 0xE9,
9503
95040x39, 0xE5, 0x2C, 0x9F,
95050x3C, 0x3D, 0x20, 0xE9,
9506
95070x2A, 0x44, 0x4C, 0xB2,
95080x1A, 0x44, 0x54, 0xB2,
9509
95100x26, 0x80, 0x3A, 0xEA,
95110x0A, 0x20,
95120x02, 0x20,
9513
95140x88, 0x73, 0x5E, 0xE9,
95150x2A, 0x20,
95160x1A, 0x20,
9517
95180x3D, 0xCF, 0x74, 0xC2,
95190x27, 0xCF, 0x74, 0xC6,
9520
95210x30, 0x50, 0x2E, 0x9F,
95220x32, 0x31, 0x5F, 0xE9,
9523
95240x38, 0x21, 0x2C, 0x9F,
95250x33, 0x39, 0x5F, 0xE9,
9526
95270x31, 0x53, 0x2F, 0x9F,
95280x9C, 0x27, 0x20, 0xE9,
9529
95300x0A, 0x44, 0x4C, 0xB4,
95310x02, 0x44, 0x54, 0xB4,
9532
95330x2A, 0x44, 0x4C, 0xB6,
95340x1A, 0x44, 0x54, 0xB6,
9535
95360x39, 0xE5, 0x2C, 0x9F,
95370x38, 0x3D, 0x20, 0xE9,
9538
95390x0A, 0x20,
95400x02, 0x20,
95410x2A, 0x20,
95420x1A, 0x20,
9543
95440x3D, 0xCF, 0x75, 0xC6,
95450x00, 0x80, 0x00, 0xE8,
9546
95470x30, 0x50, 0x2E, 0x9F,
95480x3E, 0x30, 0x4F, 0xE9,
9549
95500x38, 0x21, 0x2C, 0x9F,
95510x3F, 0x38, 0x4F, 0xE9,
9552
95530x0A, 0x45, 0x4D, 0xB6,
95540x02, 0x45, 0x55, 0xB6,
9555
95560x31, 0x53, 0x2F, 0x9F,
95570x3A, 0x31, 0x4F, 0xE9,
9558
95590x39, 0xE5, 0x2C, 0x9F,
95600x3B, 0x39, 0x4F, 0xE9,
9561
95620x31, 0x3D, 0x20, 0xE9,
95630x0A, 0x20,
95640x02, 0x20,
9565
95660x2A, 0x46, 0x4E, 0xBF,
95670x1A, 0x46, 0x56, 0xBF,
9568
95690x0A, 0x47, 0x4F, 0xBF,
95700x02, 0x47, 0x57, 0xBF,
9571
95720x30, 0x50, 0x2E, 0x9F,
95730x36, 0x30, 0x4F, 0xE9,
9574
95750x38, 0x21, 0x2C, 0x9F,
95760x37, 0x38, 0x4F, 0xE9,
9577
95780x31, 0x53, 0x2F, 0x9F,
95790x9D, 0x31, 0x4F, 0xE9,
9580
95810x39, 0xE5, 0x2C, 0x9F,
95820x9E, 0x39, 0x4F, 0xE9,
9583
95840x2A, 0x43, 0x4B, 0xBF,
95850x1A, 0x43, 0x53, 0xBF,
9586
95870x30, 0x50, 0x2E, 0x9F,
95880x35, 0x30, 0x4F, 0xE9,
9589
95900x38, 0x21, 0x2C, 0x9F,
95910x39, 0x38, 0x4F, 0xE9,
9592
95930x31, 0x53, 0x2F, 0x9F,
95940x80, 0x31, 0x57, 0xE9,
9595
95960x39, 0xE5, 0x2C, 0x9F,
95970x81, 0x39, 0x57, 0xE9,
9598
95990x37, 0x48, 0x50, 0xBD,
96000x8A, 0x36, 0x20, 0xE9,
9601
96020x86, 0x76, 0x57, 0xE9,
96030x8B, 0x3E, 0x20, 0xE9,
9604
96050x82, 0x30, 0x57, 0xE9,
96060x87, 0x77, 0x57, 0xE9,
9607
96080x83, 0x38, 0x57, 0xE9,
96090x35, 0x49, 0x51, 0xBD,
9610
96110x84, 0x31, 0x5E, 0xE9,
96120x30, 0x1F, 0x5F, 0xE9,
9613
96140x85, 0x39, 0x5E, 0xE9,
96150x57, 0x25, 0x20, 0xE9,
9616
96170x2B, 0x48, 0x20, 0xE9,
96180x1D, 0x37, 0xE1, 0xEA,
9619
96200x1E, 0x35, 0xE1, 0xEA,
96210x00, 0xE0,
96220x26, 0x77,
9623
96240x24, 0x49, 0x20, 0xE9,
96250xA6, 0xFF, 0x20, 0xEA,
9626
96270x16, 0x26, 0x20, 0xE9,
96280x57, 0x2E, 0xBF, 0xEA,
9629
96300x1C, 0x46, 0xA0, 0xE8,
96310x23, 0x4E, 0xA0, 0xE8,
9632
96330x2B, 0x56, 0xA0, 0xE8,
96340x1D, 0x47, 0xA0, 0xE8,
9635
96360x24, 0x4F, 0xA0, 0xE8,
96370x2C, 0x57, 0xA0, 0xE8,
9638
96390x1C, 0x00,
96400x23, 0x00,
96410x2B, 0x00,
96420x00, 0xE0,
9643
96440x1D, 0x00,
96450x24, 0x00,
96460x2C, 0x00,
96470x00, 0xE0,
9648
96490x1C, 0x65,
96500x23, 0x65,
96510x2B, 0x65,
96520x00, 0xE0,
9653
96540x1D, 0x65,
96550x24, 0x65,
96560x2C, 0x65,
96570x00, 0xE0,
9658
96590x1C, 0x23, 0x60, 0xEC,
96600x36, 0xD7, 0x36, 0xAD,
9661
96620x2B, 0x80, 0x60, 0xEC,
96630x1D, 0x24, 0x60, 0xEC,
9664
96650x3E, 0xD7, 0x3E, 0xAD,
96660x2C, 0x80, 0x60, 0xEC,
9667
96680x1C, 0x2B, 0xDE, 0xE8,
96690x23, 0x80, 0xDE, 0xE8,
9670
96710x36, 0x80, 0x36, 0xBD,
96720x3E, 0x80, 0x3E, 0xBD,
9673
96740x33, 0xD7, 0x1C, 0xBD,
96750x3B, 0xD7, 0x23, 0xBD,
9676
96770x46, 0x80, 0x46, 0xCF,
96780x4F, 0x80, 0x4F, 0xCF,
9679
96800x56, 0x33, 0x56, 0xCF,
96810x47, 0x3B, 0x47, 0xCF,
9682
96830xCD, 0xFF, 0x20, 0xEA,
96840x00, 0x80, 0x00, 0xE8,
9685
96860x4E, 0x33, 0x4E, 0xCF,
96870x57, 0x3B, 0x57, 0xCF,
9688
96890x94, 0xFF, 0x20, 0xEA,
96900x57, 0xC0, 0xBF, 0xEA,
9691
96920x00, 0x80, 0xA0, 0xE9,
96930x00, 0x00, 0xD8, 0xEC,
9694
9695};
9696
9697static unsigned char warp_g400_tgzf[] = {
9698
96990x00, 0x88, 0x98, 0xE9,
97000x00, 0x80, 0x00, 0xE8,
9701
97020x00, 0x80, 0xA0, 0xE9,
97030x00, 0x00, 0xD8, 0xEC,
9704
97050xFF, 0x80, 0xC0, 0xE9,
97060x00, 0x80, 0x00, 0xE8,
9707
97080x22, 0x40, 0x48, 0xBF,
97090x2A, 0x40, 0x50, 0xBF,
9710
97110x32, 0x41, 0x49, 0xBF,
97120x3A, 0x41, 0x51, 0xBF,
9713
97140xC3, 0x6B,
97150xCB, 0x6B,
97160x00, 0x88, 0x98, 0xE9,
9717
97180x73, 0x7B, 0xC8, 0xEC,
97190x96, 0xE2,
97200x41, 0x04,
9721
97220x7B, 0x43, 0xA0, 0xE8,
97230x73, 0x4B, 0xA0, 0xE8,
9724
97250xAD, 0xEE, 0x29, 0x9F,
97260x00, 0xE0,
97270x49, 0x04,
9728
97290x90, 0xE2,
97300x51, 0x04,
97310x31, 0x46, 0xB1, 0xE8,
9732
97330x49, 0x41, 0xC0, 0xEC,
97340x39, 0x57, 0xB1, 0xE8,
9735
97360x00, 0x04,
97370x46, 0xE2,
97380x73, 0x53, 0xA0, 0xE8,
9739
97400x51, 0x41, 0xC0, 0xEC,
97410x31, 0x00,
97420x39, 0x00,
9743
97440x5D, 0x80, 0x15, 0xEA,
97450x08, 0x04,
97460x10, 0x04,
9747
97480x51, 0x49, 0xC0, 0xEC,
97490x2F, 0x41, 0x60, 0xEA,
9750
97510x31, 0x20,
97520x39, 0x20,
97530x1F, 0x42, 0xA0, 0xE8,
9754
97550x2A, 0x42, 0x4A, 0xBF,
97560x27, 0x4A, 0xA0, 0xE8,
9757
97580x1A, 0x42, 0x52, 0xBF,
97590x1E, 0x49, 0x60, 0xEA,
9760
97610x73, 0x7B, 0xC8, 0xEC,
97620x26, 0x51, 0x60, 0xEA,
9763
97640x32, 0x40, 0x48, 0xBD,
97650x22, 0x40, 0x50, 0xBD,
9766
97670x12, 0x41, 0x49, 0xBD,
97680x3A, 0x41, 0x51, 0xBD,
9769
97700xBF, 0x2F, 0x26, 0xBD,
97710x00, 0xE0,
97720x7B, 0x72,
9773
97740x32, 0x20,
97750x22, 0x20,
97760x12, 0x20,
97770x3A, 0x20,
9778
97790x46, 0x31, 0x46, 0xBF,
97800x4E, 0x31, 0x4E, 0xBF,
9781
97820xB3, 0xE2, 0x2D, 0x9F,
97830x00, 0x80, 0x00, 0xE8,
9784
97850x56, 0x31, 0x56, 0xBF,
97860x47, 0x39, 0x47, 0xBF,
9787
97880x4F, 0x39, 0x4F, 0xBF,
97890x57, 0x39, 0x57, 0xBF,
9790
97910x4F, 0x80, 0x07, 0xEA,
97920x24, 0x41, 0x20, 0xE9,
9793
97940x42, 0x73, 0xF8, 0xEC,
97950x00, 0xE0,
97960x2D, 0x73,
9797
97980x33, 0x72,
97990x0C, 0xE3,
98000xA5, 0x2F, 0x1E, 0xBD,
9801
98020x43, 0x43, 0x2D, 0xDF,
98030x4B, 0x4B, 0x2D, 0xDF,
9804
98050xAE, 0x1E, 0x26, 0xBD,
98060x58, 0xE3,
98070x33, 0x66,
9808
98090x53, 0x53, 0x2D, 0xDF,
98100x00, 0x80, 0x00, 0xE8,
9811
98120xB8, 0x38, 0x33, 0xBF,
98130x00, 0xE0,
98140x59, 0xE3,
9815
98160x1E, 0x12, 0x41, 0xE9,
98170x1A, 0x22, 0x41, 0xE9,
9818
98190x2B, 0x40, 0x3D, 0xE9,
98200x3F, 0x4B, 0xA0, 0xE8,
9821
98220x2D, 0x73,
98230x30, 0x76,
98240x05, 0x80, 0x3D, 0xEA,
9825
98260x37, 0x43, 0xA0, 0xE8,
98270x3D, 0x53, 0xA0, 0xE8,
9828
98290x48, 0x70, 0xF8, 0xEC,
98300x2B, 0x48, 0x3C, 0xE9,
9831
98320x1F, 0x27, 0xBC, 0xE8,
98330x00, 0x80, 0x00, 0xE8,
9834
98350x00, 0x80, 0x00, 0xE8,
98360x00, 0x80, 0x00, 0xE8,
9837
98380x15, 0xC0, 0x20, 0xE9,
98390x15, 0xC0, 0x20, 0xE9,
9840
98410x15, 0xC0, 0x20, 0xE9,
98420x15, 0xC0, 0x20, 0xE9,
9843
98440x18, 0x3A, 0x41, 0xE9,
98450x1D, 0x32, 0x41, 0xE9,
9846
98470x2A, 0x40, 0x20, 0xE9,
98480x56, 0x3D, 0x56, 0xDF,
9849
98500x46, 0x37, 0x46, 0xDF,
98510x4E, 0x3F, 0x4E, 0xDF,
9852
98530x16, 0x30, 0x20, 0xE9,
98540x4F, 0x3F, 0x4F, 0xDF,
9855
98560x32, 0x32, 0x2D, 0xDF,
98570x22, 0x22, 0x2D, 0xDF,
9858
98590x12, 0x12, 0x2D, 0xDF,
98600x3A, 0x3A, 0x2D, 0xDF,
9861
98620x47, 0x37, 0x47, 0xDF,
98630x57, 0x3D, 0x57, 0xDF,
9864
98650x3D, 0xCF, 0x74, 0xC0,
98660x37, 0xCF, 0x74, 0xC4,
9867
98680x39, 0xE5, 0x2C, 0x9F,
98690x34, 0x80, 0x20, 0xE9,
9870
98710x31, 0x53, 0x2F, 0x9F,
98720x00, 0x80, 0x00, 0xE8,
9873
98740x88, 0x73, 0x5E, 0xE9,
98750x00, 0x80, 0x00, 0xE8,
9876
98770x27, 0xCF, 0x75, 0xC6,
98780x3C, 0x3D, 0x20, 0xE9,
9879
98800x0A, 0x44, 0x4C, 0xB0,
98810x02, 0x44, 0x54, 0xB0,
9882
98830x2A, 0x44, 0x4C, 0xB2,
98840x1A, 0x44, 0x54, 0xB2,
9885
98860x20, 0x80, 0x3A, 0xEA,
98870x0A, 0x20,
98880x02, 0x20,
9889
98900x3D, 0xCF, 0x74, 0xC2,
98910x2A, 0x20,
98920x1A, 0x20,
9893
98940x30, 0x50, 0x2E, 0x9F,
98950x32, 0x31, 0x5F, 0xE9,
9896
98970x38, 0x21, 0x2C, 0x9F,
98980x33, 0x39, 0x5F, 0xE9,
9899
99000x31, 0x53, 0x2F, 0x9F,
99010x31, 0x27, 0x20, 0xE9,
9902
99030x0A, 0x44, 0x4C, 0xB4,
99040x02, 0x44, 0x54, 0xB4,
9905
99060x2A, 0x45, 0x4D, 0xB6,
99070x1A, 0x45, 0x55, 0xB6,
9908
99090x39, 0xE5, 0x2C, 0x9F,
99100x38, 0x3D, 0x20, 0xE9,
9911
99120x0A, 0x20,
99130x02, 0x20,
99140x2A, 0x20,
99150x1A, 0x20,
9916
99170x0A, 0x47, 0x4F, 0xBF,
99180x02, 0x47, 0x57, 0xBF,
9919
99200x30, 0x50, 0x2E, 0x9F,
99210x3E, 0x30, 0x4F, 0xE9,
9922
99230x38, 0x21, 0x2C, 0x9F,
99240x3F, 0x38, 0x4F, 0xE9,
9925
99260x2A, 0x46, 0x4E, 0xBF,
99270x1A, 0x46, 0x56, 0xBF,
9928
99290x31, 0x53, 0x2F, 0x9F,
99300x3A, 0x31, 0x4F, 0xE9,
9931
99320x39, 0xE5, 0x2C, 0x9F,
99330x3B, 0x39, 0x4F, 0xE9,
9934
99350x31, 0x53, 0x2F, 0x9F,
99360x36, 0x30, 0x4F, 0xE9,
9937
99380x39, 0xE5, 0x2C, 0x9F,
99390x37, 0x38, 0x4F, 0xE9,
9940
99410x2A, 0x43, 0x4B, 0xBF,
99420x1A, 0x43, 0x53, 0xBF,
9943
99440x30, 0x50, 0x2E, 0x9F,
99450x35, 0x31, 0x4F, 0xE9,
9946
99470x38, 0x21, 0x2C, 0x9F,
99480x39, 0x39, 0x4F, 0xE9,
9949
99500x31, 0x53, 0x2F, 0x9F,
99510x80, 0x31, 0x57, 0xE9,
9952
99530x39, 0xE5, 0x2C, 0x9F,
99540x81, 0x39, 0x57, 0xE9,
9955
99560x37, 0x48, 0x50, 0xBD,
99570x8A, 0x36, 0x20, 0xE9,
9958
99590x86, 0x76, 0x57, 0xE9,
99600x8B, 0x3E, 0x20, 0xE9,
9961
99620x82, 0x30, 0x57, 0xE9,
99630x87, 0x77, 0x57, 0xE9,
9964
99650x83, 0x38, 0x57, 0xE9,
99660x35, 0x49, 0x51, 0xBD,
9967
99680x84, 0x31, 0x5E, 0xE9,
99690x30, 0x1F, 0x5F, 0xE9,
9970
99710x85, 0x39, 0x5E, 0xE9,
99720x57, 0x25, 0x20, 0xE9,
9973
99740x2B, 0x48, 0x20, 0xE9,
99750x1D, 0x37, 0xE1, 0xEA,
9976
99770x1E, 0x35, 0xE1, 0xEA,
99780x00, 0xE0,
99790x26, 0x77,
9980
99810x24, 0x49, 0x20, 0xE9,
99820xAA, 0xFF, 0x20, 0xEA,
9983
99840x16, 0x26, 0x20, 0xE9,
99850x57, 0x2E, 0xBF, 0xEA,
9986
99870x1C, 0x46, 0xA0, 0xE8,
99880x23, 0x4E, 0xA0, 0xE8,
9989
99900x2B, 0x56, 0xA0, 0xE8,
99910x1D, 0x47, 0xA0, 0xE8,
9992
99930x24, 0x4F, 0xA0, 0xE8,
99940x2C, 0x57, 0xA0, 0xE8,
9995
99960x1C, 0x00,
99970x23, 0x00,
99980x2B, 0x00,
99990x00, 0xE0,
10000
100010x1D, 0x00,
100020x24, 0x00,
100030x2C, 0x00,
100040x00, 0xE0,
10005
100060x1C, 0x65,
100070x23, 0x65,
100080x2B, 0x65,
100090x00, 0xE0,
10010
100110x1D, 0x65,
100120x24, 0x65,
100130x2C, 0x65,
100140x00, 0xE0,
10015
100160x1C, 0x23, 0x60, 0xEC,
100170x36, 0xD7, 0x36, 0xAD,
10018
100190x2B, 0x80, 0x60, 0xEC,
100200x1D, 0x24, 0x60, 0xEC,
10021
100220x3E, 0xD7, 0x3E, 0xAD,
100230x2C, 0x80, 0x60, 0xEC,
10024
100250x1C, 0x2B, 0xDE, 0xE8,
100260x23, 0x80, 0xDE, 0xE8,
10027
100280x36, 0x80, 0x36, 0xBD,
100290x3E, 0x80, 0x3E, 0xBD,
10030
100310x33, 0xD7, 0x1C, 0xBD,
100320x3B, 0xD7, 0x23, 0xBD,
10033
100340x46, 0x80, 0x46, 0xCF,
100350x4F, 0x80, 0x4F, 0xCF,
10036
100370x56, 0x33, 0x56, 0xCF,
100380x47, 0x3B, 0x47, 0xCF,
10039
100400xD3, 0xFF, 0x20, 0xEA,
100410x00, 0x80, 0x00, 0xE8,
10042
100430x4E, 0x33, 0x4E, 0xCF,
100440x57, 0x3B, 0x57, 0xCF,
10045
100460x98, 0xFF, 0x20, 0xEA,
100470x57, 0xC0, 0xBF, 0xEA,
10048
100490x00, 0x80, 0xA0, 0xE9,
100500x00, 0x00, 0xD8, 0xEC,
10051
10052};
10053
10054static unsigned char warp_g400_tgzs[] = {
10055
100560x00, 0x88, 0x98, 0xE9,
100570x00, 0x80, 0x00, 0xE8,
10058
100590x00, 0x80, 0xA0, 0xE9,
100600x00, 0x00, 0xD8, 0xEC,
10061
100620xFF, 0x80, 0xC0, 0xE9,
100630x00, 0x80, 0x00, 0xE8,
10064
100650x22, 0x40, 0x48, 0xBF,
100660x2A, 0x40, 0x50, 0xBF,
10067
100680x32, 0x41, 0x49, 0xBF,
100690x3A, 0x41, 0x51, 0xBF,
10070
100710xC3, 0x6B,
100720xCB, 0x6B,
100730x00, 0x88, 0x98, 0xE9,
10074
100750x73, 0x7B, 0xC8, 0xEC,
100760x96, 0xE2,
100770x41, 0x04,
10078
100790x7B, 0x43, 0xA0, 0xE8,
100800x73, 0x4B, 0xA0, 0xE8,
10081
100820xAD, 0xEE, 0x29, 0x9F,
100830x00, 0xE0,
100840x49, 0x04,
10085
100860x90, 0xE2,
100870x51, 0x04,
100880x31, 0x46, 0xB1, 0xE8,
10089
100900x49, 0x41, 0xC0, 0xEC,
100910x39, 0x57, 0xB1, 0xE8,
10092
100930x00, 0x04,
100940x46, 0xE2,
100950x73, 0x53, 0xA0, 0xE8,
10096
100970x51, 0x41, 0xC0, 0xEC,
100980x31, 0x00,
100990x39, 0x00,
10100
101010x65, 0x80, 0x15, 0xEA,
101020x08, 0x04,
101030x10, 0x04,
10104
101050x51, 0x49, 0xC0, 0xEC,
101060x2F, 0x41, 0x60, 0xEA,
10107
101080x31, 0x20,
101090x39, 0x20,
101100x1F, 0x42, 0xA0, 0xE8,
10111
101120x2A, 0x42, 0x4A, 0xBF,
101130x27, 0x4A, 0xA0, 0xE8,
10114
101150x1A, 0x42, 0x52, 0xBF,
101160x1E, 0x49, 0x60, 0xEA,
10117
101180x73, 0x7B, 0xC8, 0xEC,
101190x26, 0x51, 0x60, 0xEA,
10120
101210x32, 0x40, 0x48, 0xBD,
101220x22, 0x40, 0x50, 0xBD,
10123
101240x12, 0x41, 0x49, 0xBD,
101250x3A, 0x41, 0x51, 0xBD,
10126
101270xBF, 0x2F, 0x26, 0xBD,
101280x00, 0xE0,
101290x7B, 0x72,
10130
101310x32, 0x20,
101320x22, 0x20,
101330x12, 0x20,
101340x3A, 0x20,
10135
101360x46, 0x31, 0x46, 0xBF,
101370x4E, 0x31, 0x4E, 0xBF,
10138
101390xB3, 0xE2, 0x2D, 0x9F,
101400x00, 0x80, 0x00, 0xE8,
10141
101420x56, 0x31, 0x56, 0xBF,
101430x47, 0x39, 0x47, 0xBF,
10144
101450x4F, 0x39, 0x4F, 0xBF,
101460x57, 0x39, 0x57, 0xBF,
10147
101480x57, 0x80, 0x07, 0xEA,
101490x24, 0x41, 0x20, 0xE9,
10150
101510x42, 0x73, 0xF8, 0xEC,
101520x00, 0xE0,
101530x2D, 0x73,
10154
101550x33, 0x72,
101560x0C, 0xE3,
101570xA5, 0x2F, 0x1E, 0xBD,
10158
101590x43, 0x43, 0x2D, 0xDF,
101600x4B, 0x4B, 0x2D, 0xDF,
10161
101620xAE, 0x1E, 0x26, 0xBD,
101630x58, 0xE3,
101640x33, 0x66,
10165
101660x53, 0x53, 0x2D, 0xDF,
101670x00, 0x80, 0x00, 0xE8,
10168
101690xB8, 0x38, 0x33, 0xBF,
101700x00, 0xE0,
101710x59, 0xE3,
10172
101730x1E, 0x12, 0x41, 0xE9,
101740x1A, 0x22, 0x41, 0xE9,
10175
101760x2B, 0x40, 0x3D, 0xE9,
101770x3F, 0x4B, 0xA0, 0xE8,
10178
101790x2D, 0x73,
101800x30, 0x76,
101810x05, 0x80, 0x3D, 0xEA,
10182
101830x37, 0x43, 0xA0, 0xE8,
101840x3D, 0x53, 0xA0, 0xE8,
10185
101860x48, 0x70, 0xF8, 0xEC,
101870x2B, 0x48, 0x3C, 0xE9,
10188
101890x1F, 0x27, 0xBC, 0xE8,
101900x00, 0x80, 0x00, 0xE8,
10191
101920x00, 0x80, 0x00, 0xE8,
101930x00, 0x80, 0x00, 0xE8,
10194
101950x15, 0xC0, 0x20, 0xE9,
101960x15, 0xC0, 0x20, 0xE9,
10197
101980x15, 0xC0, 0x20, 0xE9,
101990x15, 0xC0, 0x20, 0xE9,
10200
102010x18, 0x3A, 0x41, 0xE9,
102020x1D, 0x32, 0x41, 0xE9,
10203
102040x2A, 0x40, 0x20, 0xE9,
102050x56, 0x3D, 0x56, 0xDF,
10206
102070x46, 0x37, 0x46, 0xDF,
102080x4E, 0x3F, 0x4E, 0xDF,
10209
102100x16, 0x30, 0x20, 0xE9,
102110x4F, 0x3F, 0x4F, 0xDF,
10212
102130x47, 0x37, 0x47, 0xDF,
102140x57, 0x3D, 0x57, 0xDF,
10215
102160x32, 0x32, 0x2D, 0xDF,
102170x22, 0x22, 0x2D, 0xDF,
10218
102190x12, 0x12, 0x2D, 0xDF,
102200x3A, 0x3A, 0x2D, 0xDF,
10221
102220x27, 0xCF, 0x74, 0xC2,
102230x37, 0xCF, 0x74, 0xC4,
10224
102250x0A, 0x44, 0x4C, 0xB0,
102260x02, 0x44, 0x54, 0xB0,
10227
102280x3D, 0xCF, 0x74, 0xC0,
102290x34, 0x37, 0x20, 0xE9,
10230
102310x31, 0x53, 0x2F, 0x9F,
102320x38, 0x27, 0x20, 0xE9,
10233
102340x39, 0xE5, 0x2C, 0x9F,
102350x3C, 0x3D, 0x20, 0xE9,
10236
102370x2A, 0x44, 0x4C, 0xB2,
102380x1A, 0x44, 0x54, 0xB2,
10239
102400x29, 0x80, 0x3A, 0xEA,
102410x0A, 0x20,
102420x02, 0x20,
10243
102440x27, 0xCF, 0x75, 0xC0,
102450x2A, 0x20,
102460x1A, 0x20,
10247
102480x30, 0x50, 0x2E, 0x9F,
102490x32, 0x31, 0x5F, 0xE9,
10250
102510x38, 0x21, 0x2C, 0x9F,
102520x33, 0x39, 0x5F, 0xE9,
10253
102540x3D, 0xCF, 0x75, 0xC2,
102550x37, 0xCF, 0x75, 0xC4,
10256
102570x31, 0x53, 0x2F, 0x9F,
102580xA6, 0x27, 0x20, 0xE9,
10259
102600x39, 0xE5, 0x2C, 0x9F,
102610xA3, 0x3D, 0x20, 0xE9,
10262
102630x2A, 0x44, 0x4C, 0xB4,
102640x1A, 0x44, 0x54, 0xB4,
10265
102660x0A, 0x45, 0x4D, 0xB0,
102670x02, 0x45, 0x55, 0xB0,
10268
102690x88, 0x73, 0x5E, 0xE9,
102700x2A, 0x20,
102710x1A, 0x20,
10272
102730xA0, 0x37, 0x20, 0xE9,
102740x0A, 0x20,
102750x02, 0x20,
10276
102770x31, 0x53, 0x2F, 0x9F,
102780x3E, 0x30, 0x4F, 0xE9,
10279
102800x39, 0xE5, 0x2C, 0x9F,
102810x3F, 0x38, 0x4F, 0xE9,
10282
102830x30, 0x50, 0x2E, 0x9F,
102840x3A, 0x31, 0x4F, 0xE9,
10285
102860x2A, 0x45, 0x4D, 0xB2,
102870x1A, 0x45, 0x55, 0xB2,
10288
102890x0A, 0x45, 0x4D, 0xB4,
102900x02, 0x45, 0x55, 0xB4,
10291
102920x38, 0x21, 0x2C, 0x9F,
102930x3B, 0x39, 0x4F, 0xE9,
10294
102950x0A, 0x20,
102960x02, 0x20,
102970x2A, 0x20,
102980x1A, 0x20,
10299
103000x2A, 0x46, 0x4E, 0xBF,
103010x1A, 0x46, 0x56, 0xBF,
10302
103030x31, 0x53, 0x2F, 0x9F,
103040x36, 0x31, 0x4F, 0xE9,
10305
103060x39, 0xE5, 0x2C, 0x9F,
103070x37, 0x39, 0x4F, 0xE9,
10308
103090x30, 0x50, 0x2E, 0x9F,
103100xA7, 0x30, 0x4F, 0xE9,
10311
103120x38, 0x21, 0x2C, 0x9F,
103130xA8, 0x38, 0x4F, 0xE9,
10314
103150x0A, 0x47, 0x4F, 0xBF,
103160x02, 0x47, 0x57, 0xBF,
10317
103180x31, 0x53, 0x2F, 0x9F,
103190xA4, 0x31, 0x4F, 0xE9,
10320
103210x39, 0xE5, 0x2C, 0x9F,
103220xA5, 0x39, 0x4F, 0xE9,
10323
103240x2A, 0x43, 0x4B, 0xBF,
103250x1A, 0x43, 0x53, 0xBF,
10326
103270x30, 0x50, 0x2E, 0x9F,
103280xA1, 0x30, 0x4F, 0xE9,
10329
103300x38, 0x21, 0x2C, 0x9F,
103310xA2, 0x38, 0x4F, 0xE9,
10332
103330x31, 0x53, 0x2F, 0x9F,
103340x80, 0x31, 0x57, 0xE9,
10335
103360x39, 0xE5, 0x2C, 0x9F,
103370x81, 0x39, 0x57, 0xE9,
10338
103390x37, 0x48, 0x50, 0xBD,
103400x8A, 0x36, 0x20, 0xE9,
10341
103420x86, 0x76, 0x57, 0xE9,
103430x8B, 0x3E, 0x20, 0xE9,
10344
103450x82, 0x30, 0x57, 0xE9,
103460x87, 0x77, 0x57, 0xE9,
10347
103480x83, 0x38, 0x57, 0xE9,
103490x35, 0x49, 0x51, 0xBD,
10350
103510x84, 0x31, 0x5E, 0xE9,
103520x30, 0x1F, 0x5F, 0xE9,
10353
103540x85, 0x39, 0x5E, 0xE9,
103550x57, 0x25, 0x20, 0xE9,
10356
103570x2B, 0x48, 0x20, 0xE9,
103580x1D, 0x37, 0xE1, 0xEA,
10359
103600x1E, 0x35, 0xE1, 0xEA,
103610x00, 0xE0,
103620x26, 0x77,
10363
103640x24, 0x49, 0x20, 0xE9,
103650xA2, 0xFF, 0x20, 0xEA,
10366
103670x16, 0x26, 0x20, 0xE9,
103680x57, 0x2E, 0xBF, 0xEA,
10369
103700x1C, 0x46, 0xA0, 0xE8,
103710x23, 0x4E, 0xA0, 0xE8,
10372
103730x2B, 0x56, 0xA0, 0xE8,
103740x1D, 0x47, 0xA0, 0xE8,
10375
103760x24, 0x4F, 0xA0, 0xE8,
103770x2C, 0x57, 0xA0, 0xE8,
10378
103790x1C, 0x00,
103800x23, 0x00,
103810x2B, 0x00,
103820x00, 0xE0,
10383
103840x1D, 0x00,
103850x24, 0x00,
103860x2C, 0x00,
103870x00, 0xE0,
10388
103890x1C, 0x65,
103900x23, 0x65,
103910x2B, 0x65,
103920x00, 0xE0,
10393
103940x1D, 0x65,
103950x24, 0x65,
103960x2C, 0x65,
103970x00, 0xE0,
10398
103990x1C, 0x23, 0x60, 0xEC,
104000x36, 0xD7, 0x36, 0xAD,
10401
104020x2B, 0x80, 0x60, 0xEC,
104030x1D, 0x24, 0x60, 0xEC,
10404
104050x3E, 0xD7, 0x3E, 0xAD,
104060x2C, 0x80, 0x60, 0xEC,
10407
104080x1C, 0x2B, 0xDE, 0xE8,
104090x23, 0x80, 0xDE, 0xE8,
10410
104110x36, 0x80, 0x36, 0xBD,
104120x3E, 0x80, 0x3E, 0xBD,
10413
104140x33, 0xD7, 0x1C, 0xBD,
104150x3B, 0xD7, 0x23, 0xBD,
10416
104170x46, 0x80, 0x46, 0xCF,
104180x4F, 0x80, 0x4F, 0xCF,
10419
104200x56, 0x33, 0x56, 0xCF,
104210x47, 0x3B, 0x47, 0xCF,
10422
104230xCA, 0xFF, 0x20, 0xEA,
104240x00, 0x80, 0x00, 0xE8,
10425
104260x4E, 0x33, 0x4E, 0xCF,
104270x57, 0x3B, 0x57, 0xCF,
10428
104290x90, 0xFF, 0x20, 0xEA,
104300x57, 0xC0, 0xBF, 0xEA,
10431
104320x00, 0x80, 0xA0, 0xE9,
104330x00, 0x00, 0xD8, 0xEC,
10434
10435};
10436
10437static unsigned char warp_g400_tgzsa[] = {
10438
104390x00, 0x88, 0x98, 0xE9,
104400x00, 0x80, 0x00, 0xE8,
10441
104420x00, 0x80, 0xA0, 0xE9,
104430x00, 0x00, 0xD8, 0xEC,
10444
104450xFF, 0x80, 0xC0, 0xE9,
104460x00, 0x80, 0x00, 0xE8,
10447
104480x22, 0x40, 0x48, 0xBF,
104490x2A, 0x40, 0x50, 0xBF,
10450
104510x32, 0x41, 0x49, 0xBF,
104520x3A, 0x41, 0x51, 0xBF,
10453
104540xC3, 0x6B,
104550xCB, 0x6B,
104560x00, 0x88, 0x98, 0xE9,
10457
104580x73, 0x7B, 0xC8, 0xEC,
104590x96, 0xE2,
104600x41, 0x04,
10461
104620x7B, 0x43, 0xA0, 0xE8,
104630x73, 0x4B, 0xA0, 0xE8,
10464
104650xAD, 0xEE, 0x29, 0x9F,
104660x00, 0xE0,
104670x49, 0x04,
10468
104690x90, 0xE2,
104700x51, 0x04,
104710x31, 0x46, 0xB1, 0xE8,
10472
104730x49, 0x41, 0xC0, 0xEC,
104740x39, 0x57, 0xB1, 0xE8,
10475
104760x00, 0x04,
104770x46, 0xE2,
104780x73, 0x53, 0xA0, 0xE8,
10479
104800x51, 0x41, 0xC0, 0xEC,
104810x31, 0x00,
104820x39, 0x00,
10483
104840x6A, 0x80, 0x15, 0xEA,
104850x08, 0x04,
104860x10, 0x04,
10487
104880x51, 0x49, 0xC0, 0xEC,
104890x2F, 0x41, 0x60, 0xEA,
10490
104910x31, 0x20,
104920x39, 0x20,
104930x1F, 0x42, 0xA0, 0xE8,
10494
104950x2A, 0x42, 0x4A, 0xBF,
104960x27, 0x4A, 0xA0, 0xE8,
10497
104980x1A, 0x42, 0x52, 0xBF,
104990x1E, 0x49, 0x60, 0xEA,
10500
105010x73, 0x7B, 0xC8, 0xEC,
105020x26, 0x51, 0x60, 0xEA,
10503
105040x32, 0x40, 0x48, 0xBD,
105050x22, 0x40, 0x50, 0xBD,
10506
105070x12, 0x41, 0x49, 0xBD,
105080x3A, 0x41, 0x51, 0xBD,
10509
105100xBF, 0x2F, 0x26, 0xBD,
105110x00, 0xE0,
105120x7B, 0x72,
10513
105140x32, 0x20,
105150x22, 0x20,
105160x12, 0x20,
105170x3A, 0x20,
10518
105190x46, 0x31, 0x46, 0xBF,
105200x4E, 0x31, 0x4E, 0xBF,
10521
105220xB3, 0xE2, 0x2D, 0x9F,
105230x00, 0x80, 0x00, 0xE8,
10524
105250x56, 0x31, 0x56, 0xBF,
105260x47, 0x39, 0x47, 0xBF,
10527
105280x4F, 0x39, 0x4F, 0xBF,
105290x57, 0x39, 0x57, 0xBF,
10530
105310x5C, 0x80, 0x07, 0xEA,
105320x24, 0x41, 0x20, 0xE9,
10533
105340x42, 0x73, 0xF8, 0xEC,
105350x00, 0xE0,
105360x2D, 0x73,
10537
105380x33, 0x72,
105390x0C, 0xE3,
105400xA5, 0x2F, 0x1E, 0xBD,
10541
105420x43, 0x43, 0x2D, 0xDF,
105430x4B, 0x4B, 0x2D, 0xDF,
10544
105450xAE, 0x1E, 0x26, 0xBD,
105460x58, 0xE3,
105470x33, 0x66,
10548
105490x53, 0x53, 0x2D, 0xDF,
105500x00, 0x80, 0x00, 0xE8,
10551
105520xB8, 0x38, 0x33, 0xBF,
105530x00, 0xE0,
105540x59, 0xE3,
10555
105560x1E, 0x12, 0x41, 0xE9,
105570x1A, 0x22, 0x41, 0xE9,
10558
105590x2B, 0x40, 0x3D, 0xE9,
105600x3F, 0x4B, 0xA0, 0xE8,
10561
105620x2D, 0x73,
105630x30, 0x76,
105640x05, 0x80, 0x3D, 0xEA,
10565
105660x37, 0x43, 0xA0, 0xE8,
105670x3D, 0x53, 0xA0, 0xE8,
10568
105690x48, 0x70, 0xF8, 0xEC,
105700x2B, 0x48, 0x3C, 0xE9,
10571
105720x1F, 0x27, 0xBC, 0xE8,
105730x00, 0x80, 0x00, 0xE8,
10574
105750x00, 0x80, 0x00, 0xE8,
105760x00, 0x80, 0x00, 0xE8,
10577
105780x15, 0xC0, 0x20, 0xE9,
105790x15, 0xC0, 0x20, 0xE9,
10580
105810x15, 0xC0, 0x20, 0xE9,
105820x15, 0xC0, 0x20, 0xE9,
10583
105840x18, 0x3A, 0x41, 0xE9,
105850x1D, 0x32, 0x41, 0xE9,
10586
105870x2A, 0x40, 0x20, 0xE9,
105880x56, 0x3D, 0x56, 0xDF,
10589
105900x46, 0x37, 0x46, 0xDF,
105910x4E, 0x3F, 0x4E, 0xDF,
10592
105930x16, 0x30, 0x20, 0xE9,
105940x4F, 0x3F, 0x4F, 0xDF,
10595
105960x47, 0x37, 0x47, 0xDF,
105970x57, 0x3D, 0x57, 0xDF,
10598
105990x32, 0x32, 0x2D, 0xDF,
106000x22, 0x22, 0x2D, 0xDF,
10601
106020x12, 0x12, 0x2D, 0xDF,
106030x3A, 0x3A, 0x2D, 0xDF,
10604
106050x27, 0xCF, 0x74, 0xC2,
106060x37, 0xCF, 0x74, 0xC4,
10607
106080x0A, 0x44, 0x4C, 0xB0,
106090x02, 0x44, 0x54, 0xB0,
10610
106110x3D, 0xCF, 0x74, 0xC0,
106120x34, 0x37, 0x20, 0xE9,
10613
106140x31, 0x53, 0x2F, 0x9F,
106150x38, 0x27, 0x20, 0xE9,
10616
106170x39, 0xE5, 0x2C, 0x9F,
106180x3C, 0x3D, 0x20, 0xE9,
10619
106200x2A, 0x44, 0x4C, 0xB2,
106210x1A, 0x44, 0x54, 0xB2,
10622
106230x2E, 0x80, 0x3A, 0xEA,
106240x0A, 0x20,
106250x02, 0x20,
10626
106270x27, 0xCF, 0x75, 0xC0,
106280x2A, 0x20,
106290x1A, 0x20,
10630
106310x30, 0x50, 0x2E, 0x9F,
106320x32, 0x31, 0x5F, 0xE9,
10633
106340x38, 0x21, 0x2C, 0x9F,
106350x33, 0x39, 0x5F, 0xE9,
10636
106370x3D, 0xCF, 0x75, 0xC2,
106380x37, 0xCF, 0x75, 0xC4,
10639
106400x31, 0x53, 0x2F, 0x9F,
106410xA6, 0x27, 0x20, 0xE9,
10642
106430x39, 0xE5, 0x2C, 0x9F,
106440xA3, 0x3D, 0x20, 0xE9,
10645
106460x2A, 0x44, 0x4C, 0xB4,
106470x1A, 0x44, 0x54, 0xB4,
10648
106490x0A, 0x45, 0x4D, 0xB0,
106500x02, 0x45, 0x55, 0xB0,
10651
106520x88, 0x73, 0x5E, 0xE9,
106530x2A, 0x20,
106540x1A, 0x20,
10655
106560xA0, 0x37, 0x20, 0xE9,
106570x0A, 0x20,
106580x02, 0x20,
10659
106600x31, 0x53, 0x2F, 0x9F,
106610x3E, 0x30, 0x4F, 0xE9,
10662
106630x39, 0xE5, 0x2C, 0x9F,
106640x3F, 0x38, 0x4F, 0xE9,
10665
106660x30, 0x50, 0x2E, 0x9F,
106670x3A, 0x31, 0x4F, 0xE9,
10668
106690x38, 0x21, 0x2C, 0x9F,
106700x3B, 0x39, 0x4F, 0xE9,
10671
106720x2A, 0x45, 0x4D, 0xB2,
106730x1A, 0x45, 0x55, 0xB2,
10674
106750x0A, 0x45, 0x4D, 0xB4,
106760x02, 0x45, 0x55, 0xB4,
10677
106780x27, 0xCF, 0x74, 0xC6,
106790x2A, 0x20,
106800x1A, 0x20,
10681
106820xA7, 0x30, 0x4F, 0xE9,
106830x0A, 0x20,
106840x02, 0x20,
10685
106860x31, 0x53, 0x2F, 0x9F,
106870x9C, 0x27, 0x20, 0xE9,
10688
106890x39, 0xE5, 0x2C, 0x9F,
106900xA8, 0x38, 0x4F, 0xE9,
10691
106920x2A, 0x44, 0x4C, 0xB6,
106930x1A, 0x44, 0x54, 0xB6,
10694
106950x30, 0x50, 0x2E, 0x9F,
106960x36, 0x31, 0x4F, 0xE9,
10697
106980x38, 0x21, 0x2C, 0x9F,
106990x37, 0x39, 0x4F, 0xE9,
10700
107010x00, 0x80, 0x00, 0xE8,
107020x2A, 0x20,
107030x1A, 0x20,
10704
107050x2A, 0x46, 0x4E, 0xBF,
107060x1A, 0x46, 0x56, 0xBF,
10707
107080x31, 0x53, 0x2F, 0x9F,
107090xA4, 0x31, 0x4F, 0xE9,
10710
107110x39, 0xE5, 0x2C, 0x9F,
107120xA5, 0x39, 0x4F, 0xE9,
10713
107140x0A, 0x47, 0x4F, 0xBF,
107150x02, 0x47, 0x57, 0xBF,
10716
107170x31, 0x53, 0x2F, 0x9F,
107180xA1, 0x30, 0x4F, 0xE9,
10719
107200x39, 0xE5, 0x2C, 0x9F,
107210xA2, 0x38, 0x4F, 0xE9,
10722
107230x2A, 0x43, 0x4B, 0xBF,
107240x1A, 0x43, 0x53, 0xBF,
10725
107260x30, 0x50, 0x2E, 0x9F,
107270x9D, 0x31, 0x4F, 0xE9,
10728
107290x38, 0x21, 0x2C, 0x9F,
107300x9E, 0x39, 0x4F, 0xE9,
10731
107320x31, 0x53, 0x2F, 0x9F,
107330x80, 0x31, 0x57, 0xE9,
10734
107350x39, 0xE5, 0x2C, 0x9F,
107360x81, 0x39, 0x57, 0xE9,
10737
107380x37, 0x48, 0x50, 0xBD,
107390x8A, 0x36, 0x20, 0xE9,
10740
107410x86, 0x76, 0x57, 0xE9,
107420x8B, 0x3E, 0x20, 0xE9,
10743
107440x82, 0x30, 0x57, 0xE9,
107450x87, 0x77, 0x57, 0xE9,
10746
107470x83, 0x38, 0x57, 0xE9,
107480x35, 0x49, 0x51, 0xBD,
10749
107500x84, 0x31, 0x5E, 0xE9,
107510x30, 0x1F, 0x5F, 0xE9,
10752
107530x85, 0x39, 0x5E, 0xE9,
107540x57, 0x25, 0x20, 0xE9,
10755
107560x2B, 0x48, 0x20, 0xE9,
107570x1D, 0x37, 0xE1, 0xEA,
10758
107590x1E, 0x35, 0xE1, 0xEA,
107600x00, 0xE0,
107610x26, 0x77,
10762
107630x24, 0x49, 0x20, 0xE9,
107640x9D, 0xFF, 0x20, 0xEA,
10765
107660x16, 0x26, 0x20, 0xE9,
107670x57, 0x2E, 0xBF, 0xEA,
10768
107690x1C, 0x46, 0xA0, 0xE8,
107700x23, 0x4E, 0xA0, 0xE8,
10771
107720x2B, 0x56, 0xA0, 0xE8,
107730x1D, 0x47, 0xA0, 0xE8,
10774
107750x24, 0x4F, 0xA0, 0xE8,
107760x2C, 0x57, 0xA0, 0xE8,
10777
107780x1C, 0x00,
107790x23, 0x00,
107800x2B, 0x00,
107810x00, 0xE0,
10782
107830x1D, 0x00,
107840x24, 0x00,
107850x2C, 0x00,
107860x00, 0xE0,
10787
107880x1C, 0x65,
107890x23, 0x65,
107900x2B, 0x65,
107910x00, 0xE0,
10792
107930x1D, 0x65,
107940x24, 0x65,
107950x2C, 0x65,
107960x00, 0xE0,
10797
107980x1C, 0x23, 0x60, 0xEC,
107990x36, 0xD7, 0x36, 0xAD,
10800
108010x2B, 0x80, 0x60, 0xEC,
108020x1D, 0x24, 0x60, 0xEC,
10803
108040x3E, 0xD7, 0x3E, 0xAD,
108050x2C, 0x80, 0x60, 0xEC,
10806
108070x1C, 0x2B, 0xDE, 0xE8,
108080x23, 0x80, 0xDE, 0xE8,
10809
108100x36, 0x80, 0x36, 0xBD,
108110x3E, 0x80, 0x3E, 0xBD,
10812
108130x33, 0xD7, 0x1C, 0xBD,
108140x3B, 0xD7, 0x23, 0xBD,
10815
108160x46, 0x80, 0x46, 0xCF,
108170x4F, 0x80, 0x4F, 0xCF,
10818
108190x56, 0x33, 0x56, 0xCF,
108200x47, 0x3B, 0x47, 0xCF,
10821
108220xC5, 0xFF, 0x20, 0xEA,
108230x00, 0x80, 0x00, 0xE8,
10824
108250x4E, 0x33, 0x4E, 0xCF,
108260x57, 0x3B, 0x57, 0xCF,
10827
108280x8B, 0xFF, 0x20, 0xEA,
108290x57, 0xC0, 0xBF, 0xEA,
10830
108310x00, 0x80, 0xA0, 0xE9,
108320x00, 0x00, 0xD8, 0xEC,
10833
10834};
10835
10836static unsigned char warp_g400_tgzsaf[] = {
10837
108380x00, 0x88, 0x98, 0xE9,
108390x00, 0x80, 0x00, 0xE8,
10840
108410x00, 0x80, 0xA0, 0xE9,
108420x00, 0x00, 0xD8, 0xEC,
10843
108440xFF, 0x80, 0xC0, 0xE9,
108450x00, 0x80, 0x00, 0xE8,
10846
108470x22, 0x40, 0x48, 0xBF,
108480x2A, 0x40, 0x50, 0xBF,
10849
108500x32, 0x41, 0x49, 0xBF,
108510x3A, 0x41, 0x51, 0xBF,
10852
108530xC3, 0x6B,
108540xCB, 0x6B,
108550x00, 0x88, 0x98, 0xE9,
10856
108570x73, 0x7B, 0xC8, 0xEC,
108580x96, 0xE2,
108590x41, 0x04,
10860
108610x7B, 0x43, 0xA0, 0xE8,
108620x73, 0x4B, 0xA0, 0xE8,
10863
108640xAD, 0xEE, 0x29, 0x9F,
108650x00, 0xE0,
108660x49, 0x04,
10867
108680x90, 0xE2,
108690x51, 0x04,
108700x31, 0x46, 0xB1, 0xE8,
10871
108720x49, 0x41, 0xC0, 0xEC,
108730x39, 0x57, 0xB1, 0xE8,
10874
108750x00, 0x04,
108760x46, 0xE2,
108770x73, 0x53, 0xA0, 0xE8,
10878
108790x51, 0x41, 0xC0, 0xEC,
108800x31, 0x00,
108810x39, 0x00,
10882
108830x6E, 0x80, 0x15, 0xEA,
108840x08, 0x04,
108850x10, 0x04,
10886
108870x51, 0x49, 0xC0, 0xEC,
108880x2F, 0x41, 0x60, 0xEA,
10889
108900x31, 0x20,
108910x39, 0x20,
108920x1F, 0x42, 0xA0, 0xE8,
10893
108940x2A, 0x42, 0x4A, 0xBF,
108950x27, 0x4A, 0xA0, 0xE8,
10896
108970x1A, 0x42, 0x52, 0xBF,
108980x1E, 0x49, 0x60, 0xEA,
10899
109000x73, 0x7B, 0xC8, 0xEC,
109010x26, 0x51, 0x60, 0xEA,
10902
109030x32, 0x40, 0x48, 0xBD,
109040x22, 0x40, 0x50, 0xBD,
10905
109060x12, 0x41, 0x49, 0xBD,
109070x3A, 0x41, 0x51, 0xBD,
10908
109090xBF, 0x2F, 0x26, 0xBD,
109100x00, 0xE0,
109110x7B, 0x72,
10912
109130x32, 0x20,
109140x22, 0x20,
109150x12, 0x20,
109160x3A, 0x20,
10917
109180x46, 0x31, 0x46, 0xBF,
109190x4E, 0x31, 0x4E, 0xBF,
10920
109210xB3, 0xE2, 0x2D, 0x9F,
109220x00, 0x80, 0x00, 0xE8,
10923
109240x56, 0x31, 0x56, 0xBF,
109250x47, 0x39, 0x47, 0xBF,
10926
109270x4F, 0x39, 0x4F, 0xBF,
109280x57, 0x39, 0x57, 0xBF,
10929
109300x60, 0x80, 0x07, 0xEA,
109310x24, 0x41, 0x20, 0xE9,
10932
109330x42, 0x73, 0xF8, 0xEC,
109340x00, 0xE0,
109350x2D, 0x73,
10936
109370x33, 0x72,
109380x0C, 0xE3,
109390xA5, 0x2F, 0x1E, 0xBD,
10940
109410x43, 0x43, 0x2D, 0xDF,
109420x4B, 0x4B, 0x2D, 0xDF,
10943
109440xAE, 0x1E, 0x26, 0xBD,
109450x58, 0xE3,
109460x33, 0x66,
10947
109480x53, 0x53, 0x2D, 0xDF,
109490x00, 0x80, 0x00, 0xE8,
10950
109510xB8, 0x38, 0x33, 0xBF,
109520x00, 0xE0,
109530x59, 0xE3,
10954
109550x1E, 0x12, 0x41, 0xE9,
109560x1A, 0x22, 0x41, 0xE9,
10957
109580x2B, 0x40, 0x3D, 0xE9,
109590x3F, 0x4B, 0xA0, 0xE8,
10960
109610x2D, 0x73,
109620x30, 0x76,
109630x05, 0x80, 0x3D, 0xEA,
10964
109650x37, 0x43, 0xA0, 0xE8,
109660x3D, 0x53, 0xA0, 0xE8,
10967
109680x48, 0x70, 0xF8, 0xEC,
109690x2B, 0x48, 0x3C, 0xE9,
10970
109710x1F, 0x27, 0xBC, 0xE8,
109720x00, 0x80, 0x00, 0xE8,
10973
109740x00, 0x80, 0x00, 0xE8,
109750x00, 0x80, 0x00, 0xE8,
10976
109770x15, 0xC0, 0x20, 0xE9,
109780x15, 0xC0, 0x20, 0xE9,
10979
109800x15, 0xC0, 0x20, 0xE9,
109810x15, 0xC0, 0x20, 0xE9,
10982
109830x18, 0x3A, 0x41, 0xE9,
109840x1D, 0x32, 0x41, 0xE9,
10985
109860x2A, 0x40, 0x20, 0xE9,
109870x56, 0x3D, 0x56, 0xDF,
10988
109890x46, 0x37, 0x46, 0xDF,
109900x4E, 0x3F, 0x4E, 0xDF,
10991
109920x16, 0x30, 0x20, 0xE9,
109930x4F, 0x3F, 0x4F, 0xDF,
10994
109950x47, 0x37, 0x47, 0xDF,
109960x57, 0x3D, 0x57, 0xDF,
10997
109980x32, 0x32, 0x2D, 0xDF,
109990x22, 0x22, 0x2D, 0xDF,
11000
110010x12, 0x12, 0x2D, 0xDF,
110020x3A, 0x3A, 0x2D, 0xDF,
11003
110040x27, 0xCF, 0x74, 0xC2,
110050x37, 0xCF, 0x74, 0xC4,
11006
110070x0A, 0x44, 0x4C, 0xB0,
110080x02, 0x44, 0x54, 0xB0,
11009
110100x3D, 0xCF, 0x74, 0xC0,
110110x34, 0x37, 0x20, 0xE9,
11012
110130x31, 0x53, 0x2F, 0x9F,
110140x38, 0x27, 0x20, 0xE9,
11015
110160x39, 0xE5, 0x2C, 0x9F,
110170x3C, 0x3D, 0x20, 0xE9,
11018
110190x2A, 0x44, 0x4C, 0xB2,
110200x1A, 0x44, 0x54, 0xB2,
11021
110220x32, 0x80, 0x3A, 0xEA,
110230x0A, 0x20,
110240x02, 0x20,
11025
110260x27, 0xCF, 0x75, 0xC0,
110270x2A, 0x20,
110280x1A, 0x20,
11029
110300x30, 0x50, 0x2E, 0x9F,
110310x32, 0x31, 0x5F, 0xE9,
11032
110330x38, 0x21, 0x2C, 0x9F,
110340x33, 0x39, 0x5F, 0xE9,
11035
110360x3D, 0xCF, 0x75, 0xC2,
110370x37, 0xCF, 0x75, 0xC4,
11038
110390x31, 0x53, 0x2F, 0x9F,
110400xA6, 0x27, 0x20, 0xE9,
11041
110420x39, 0xE5, 0x2C, 0x9F,
110430xA3, 0x3D, 0x20, 0xE9,
11044
110450x2A, 0x44, 0x4C, 0xB4,
110460x1A, 0x44, 0x54, 0xB4,
11047
110480x0A, 0x45, 0x4D, 0xB0,
110490x02, 0x45, 0x55, 0xB0,
11050
110510x88, 0x73, 0x5E, 0xE9,
110520x2A, 0x20,
110530x1A, 0x20,
11054
110550xA0, 0x37, 0x20, 0xE9,
110560x0A, 0x20,
110570x02, 0x20,
11058
110590x31, 0x53, 0x2F, 0x9F,
110600x3E, 0x30, 0x4F, 0xE9,
11061
110620x39, 0xE5, 0x2C, 0x9F,
110630x3F, 0x38, 0x4F, 0xE9,
11064
110650x30, 0x50, 0x2E, 0x9F,
110660x3A, 0x31, 0x4F, 0xE9,
11067
110680x38, 0x21, 0x2C, 0x9F,
110690x3B, 0x39, 0x4F, 0xE9,
11070
110710x2A, 0x45, 0x4D, 0xB2,
110720x1A, 0x45, 0x55, 0xB2,
11073
110740x0A, 0x45, 0x4D, 0xB4,
110750x02, 0x45, 0x55, 0xB4,
11076
110770x27, 0xCF, 0x74, 0xC6,
110780x2A, 0x20,
110790x1A, 0x20,
11080
110810xA7, 0x30, 0x4F, 0xE9,
110820x0A, 0x20,
110830x02, 0x20,
11084
110850x31, 0x53, 0x2F, 0x9F,
110860x9C, 0x27, 0x20, 0xE9,
11087
110880x39, 0xE5, 0x2C, 0x9F,
110890xA8, 0x38, 0x4F, 0xE9,
11090
110910x2A, 0x44, 0x4C, 0xB6,
110920x1A, 0x44, 0x54, 0xB6,
11093
110940x30, 0x50, 0x2E, 0x9F,
110950x36, 0x31, 0x4F, 0xE9,
11096
110970x38, 0x21, 0x2C, 0x9F,
110980x37, 0x39, 0x4F, 0xE9,
11099
111000x0A, 0x45, 0x4D, 0xB6,
111010x02, 0x45, 0x55, 0xB6,
11102
111030x3D, 0xCF, 0x75, 0xC6,
111040x2A, 0x20,
111050x1A, 0x20,
11106
111070x2A, 0x46, 0x4E, 0xBF,
111080x1A, 0x46, 0x56, 0xBF,
11109
111100x31, 0x53, 0x2F, 0x9F,
111110xA4, 0x31, 0x4F, 0xE9,
11112
111130x39, 0xE5, 0x2C, 0x9F,
111140xA5, 0x39, 0x4F, 0xE9,
11115
111160x31, 0x3D, 0x20, 0xE9,
111170x0A, 0x20,
111180x02, 0x20,
11119
111200x0A, 0x47, 0x4F, 0xBF,
111210x02, 0x47, 0x57, 0xBF,
11122
111230x30, 0x50, 0x2E, 0x9F,
111240xA1, 0x30, 0x4F, 0xE9,
11125
111260x38, 0x21, 0x2C, 0x9F,
111270xA2, 0x38, 0x4F, 0xE9,
11128
111290x31, 0x53, 0x2F, 0x9F,
111300x9D, 0x31, 0x4F, 0xE9,
11131
111320x39, 0xE5, 0x2C, 0x9F,
111330x9E, 0x39, 0x4F, 0xE9,
11134
111350x2A, 0x43, 0x4B, 0xBF,
111360x1A, 0x43, 0x53, 0xBF,
11137
111380x30, 0x50, 0x2E, 0x9F,
111390x35, 0x30, 0x4F, 0xE9,
11140
111410x38, 0x21, 0x2C, 0x9F,
111420x39, 0x38, 0x4F, 0xE9,
11143
111440x31, 0x53, 0x2F, 0x9F,
111450x80, 0x31, 0x57, 0xE9,
11146
111470x39, 0xE5, 0x2C, 0x9F,
111480x81, 0x39, 0x57, 0xE9,
11149
111500x37, 0x48, 0x50, 0xBD,
111510x8A, 0x36, 0x20, 0xE9,
11152
111530x86, 0x76, 0x57, 0xE9,
111540x8B, 0x3E, 0x20, 0xE9,
11155
111560x82, 0x30, 0x57, 0xE9,
111570x87, 0x77, 0x57, 0xE9,
11158
111590x83, 0x38, 0x57, 0xE9,
111600x35, 0x49, 0x51, 0xBD,
11161
111620x84, 0x31, 0x5E, 0xE9,
111630x30, 0x1F, 0x5F, 0xE9,
11164
111650x85, 0x39, 0x5E, 0xE9,
111660x57, 0x25, 0x20, 0xE9,
11167
111680x2B, 0x48, 0x20, 0xE9,
111690x1D, 0x37, 0xE1, 0xEA,
11170
111710x1E, 0x35, 0xE1, 0xEA,
111720x00, 0xE0,
111730x26, 0x77,
11174
111750x24, 0x49, 0x20, 0xE9,
111760x99, 0xFF, 0x20, 0xEA,
11177
111780x16, 0x26, 0x20, 0xE9,
111790x57, 0x2E, 0xBF, 0xEA,
11180
111810x1C, 0x46, 0xA0, 0xE8,
111820x23, 0x4E, 0xA0, 0xE8,
11183
111840x2B, 0x56, 0xA0, 0xE8,
111850x1D, 0x47, 0xA0, 0xE8,
11186
111870x24, 0x4F, 0xA0, 0xE8,
111880x2C, 0x57, 0xA0, 0xE8,
11189
111900x1C, 0x00,
111910x23, 0x00,
111920x2B, 0x00,
111930x00, 0xE0,
11194
111950x1D, 0x00,
111960x24, 0x00,
111970x2C, 0x00,
111980x00, 0xE0,
11199
112000x1C, 0x65,
112010x23, 0x65,
112020x2B, 0x65,
112030x00, 0xE0,
11204
112050x1D, 0x65,
112060x24, 0x65,
112070x2C, 0x65,
112080x00, 0xE0,
11209
112100x1C, 0x23, 0x60, 0xEC,
112110x36, 0xD7, 0x36, 0xAD,
11212
112130x2B, 0x80, 0x60, 0xEC,
112140x1D, 0x24, 0x60, 0xEC,
11215
112160x3E, 0xD7, 0x3E, 0xAD,
112170x2C, 0x80, 0x60, 0xEC,
11218
112190x1C, 0x2B, 0xDE, 0xE8,
112200x23, 0x80, 0xDE, 0xE8,
11221
112220x36, 0x80, 0x36, 0xBD,
112230x3E, 0x80, 0x3E, 0xBD,
11224
112250x33, 0xD7, 0x1C, 0xBD,
112260x3B, 0xD7, 0x23, 0xBD,
11227
112280x46, 0x80, 0x46, 0xCF,
112290x4F, 0x80, 0x4F, 0xCF,
11230
112310x56, 0x33, 0x56, 0xCF,
112320x47, 0x3B, 0x47, 0xCF,
11233
112340xC1, 0xFF, 0x20, 0xEA,
112350x00, 0x80, 0x00, 0xE8,
11236
112370x4E, 0x33, 0x4E, 0xCF,
112380x57, 0x3B, 0x57, 0xCF,
11239
112400x87, 0xFF, 0x20, 0xEA,
112410x57, 0xC0, 0xBF, 0xEA,
11242
112430x00, 0x80, 0xA0, 0xE9,
112440x00, 0x00, 0xD8, 0xEC,
11245
11246};
11247
11248static unsigned char warp_g400_tgzsf[] = {
11249
112500x00, 0x88, 0x98, 0xE9,
112510x00, 0x80, 0x00, 0xE8,
11252
112530x00, 0x80, 0xA0, 0xE9,
112540x00, 0x00, 0xD8, 0xEC,
11255
112560xFF, 0x80, 0xC0, 0xE9,
112570x00, 0x80, 0x00, 0xE8,
11258
112590x22, 0x40, 0x48, 0xBF,
112600x2A, 0x40, 0x50, 0xBF,
11261
112620x32, 0x41, 0x49, 0xBF,
112630x3A, 0x41, 0x51, 0xBF,
11264
112650xC3, 0x6B,
112660xCB, 0x6B,
112670x00, 0x88, 0x98, 0xE9,
11268
112690x73, 0x7B, 0xC8, 0xEC,
112700x96, 0xE2,
112710x41, 0x04,
11272
112730x7B, 0x43, 0xA0, 0xE8,
112740x73, 0x4B, 0xA0, 0xE8,
11275
112760xAD, 0xEE, 0x29, 0x9F,
112770x00, 0xE0,
112780x49, 0x04,
11279
112800x90, 0xE2,
112810x51, 0x04,
112820x31, 0x46, 0xB1, 0xE8,
11283
112840x49, 0x41, 0xC0, 0xEC,
112850x39, 0x57, 0xB1, 0xE8,
11286
112870x00, 0x04,
112880x46, 0xE2,
112890x73, 0x53, 0xA0, 0xE8,
11290
112910x51, 0x41, 0xC0, 0xEC,
112920x31, 0x00,
112930x39, 0x00,
11294
112950x6A, 0x80, 0x15, 0xEA,
112960x08, 0x04,
112970x10, 0x04,
11298
112990x51, 0x49, 0xC0, 0xEC,
113000x2F, 0x41, 0x60, 0xEA,
11301
113020x31, 0x20,
113030x39, 0x20,
113040x1F, 0x42, 0xA0, 0xE8,
11305
113060x2A, 0x42, 0x4A, 0xBF,
113070x27, 0x4A, 0xA0, 0xE8,
11308
113090x1A, 0x42, 0x52, 0xBF,
113100x1E, 0x49, 0x60, 0xEA,
11311
113120x73, 0x7B, 0xC8, 0xEC,
113130x26, 0x51, 0x60, 0xEA,
11314
113150x32, 0x40, 0x48, 0xBD,
113160x22, 0x40, 0x50, 0xBD,
11317
113180x12, 0x41, 0x49, 0xBD,
113190x3A, 0x41, 0x51, 0xBD,
11320
113210xBF, 0x2F, 0x26, 0xBD,
113220x00, 0xE0,
113230x7B, 0x72,
11324
113250x32, 0x20,
113260x22, 0x20,
113270x12, 0x20,
113280x3A, 0x20,
11329
113300x46, 0x31, 0x46, 0xBF,
113310x4E, 0x31, 0x4E, 0xBF,
11332
113330xB3, 0xE2, 0x2D, 0x9F,
113340x00, 0x80, 0x00, 0xE8,
11335
113360x56, 0x31, 0x56, 0xBF,
113370x47, 0x39, 0x47, 0xBF,
11338
113390x4F, 0x39, 0x4F, 0xBF,
113400x57, 0x39, 0x57, 0xBF,
11341
113420x5C, 0x80, 0x07, 0xEA,
113430x24, 0x41, 0x20, 0xE9,
11344
113450x42, 0x73, 0xF8, 0xEC,
113460x00, 0xE0,
113470x2D, 0x73,
11348
113490x33, 0x72,
113500x0C, 0xE3,
113510xA5, 0x2F, 0x1E, 0xBD,
11352
113530x43, 0x43, 0x2D, 0xDF,
113540x4B, 0x4B, 0x2D, 0xDF,
11355
113560xAE, 0x1E, 0x26, 0xBD,
113570x58, 0xE3,
113580x33, 0x66,
11359
113600x53, 0x53, 0x2D, 0xDF,
113610x00, 0x80, 0x00, 0xE8,
11362
113630xB8, 0x38, 0x33, 0xBF,
113640x00, 0xE0,
113650x59, 0xE3,
11366
113670x1E, 0x12, 0x41, 0xE9,
113680x1A, 0x22, 0x41, 0xE9,
11369
113700x2B, 0x40, 0x3D, 0xE9,
113710x3F, 0x4B, 0xA0, 0xE8,
11372
113730x2D, 0x73,
113740x30, 0x76,
113750x05, 0x80, 0x3D, 0xEA,
11376
113770x37, 0x43, 0xA0, 0xE8,
113780x3D, 0x53, 0xA0, 0xE8,
11379
113800x48, 0x70, 0xF8, 0xEC,
113810x2B, 0x48, 0x3C, 0xE9,
11382
113830x1F, 0x27, 0xBC, 0xE8,
113840x00, 0x80, 0x00, 0xE8,
11385
113860x00, 0x80, 0x00, 0xE8,
113870x00, 0x80, 0x00, 0xE8,
11388
113890x15, 0xC0, 0x20, 0xE9,
113900x15, 0xC0, 0x20, 0xE9,
11391
113920x15, 0xC0, 0x20, 0xE9,
113930x15, 0xC0, 0x20, 0xE9,
11394
113950x18, 0x3A, 0x41, 0xE9,
113960x1D, 0x32, 0x41, 0xE9,
11397
113980x2A, 0x40, 0x20, 0xE9,
113990x56, 0x3D, 0x56, 0xDF,
11400
114010x46, 0x37, 0x46, 0xDF,
114020x4E, 0x3F, 0x4E, 0xDF,
11403
114040x16, 0x30, 0x20, 0xE9,
114050x4F, 0x3F, 0x4F, 0xDF,
11406
114070x47, 0x37, 0x47, 0xDF,
114080x57, 0x3D, 0x57, 0xDF,
11409
114100x32, 0x32, 0x2D, 0xDF,
114110x22, 0x22, 0x2D, 0xDF,
11412
114130x12, 0x12, 0x2D, 0xDF,
114140x3A, 0x3A, 0x2D, 0xDF,
11415
114160x27, 0xCF, 0x74, 0xC2,
114170x37, 0xCF, 0x74, 0xC4,
11418
114190x0A, 0x44, 0x4C, 0xB0,
114200x02, 0x44, 0x54, 0xB0,
11421
114220x3D, 0xCF, 0x74, 0xC0,
114230x34, 0x37, 0x20, 0xE9,
11424
114250x31, 0x53, 0x2F, 0x9F,
114260x38, 0x27, 0x20, 0xE9,
11427
114280x39, 0xE5, 0x2C, 0x9F,
114290x3C, 0x3D, 0x20, 0xE9,
11430
114310x2A, 0x44, 0x4C, 0xB2,
114320x1A, 0x44, 0x54, 0xB2,
11433
114340x2E, 0x80, 0x3A, 0xEA,
114350x0A, 0x20,
114360x02, 0x20,
11437
114380x27, 0xCF, 0x75, 0xC0,
114390x2A, 0x20,
114400x1A, 0x20,
11441
114420x30, 0x50, 0x2E, 0x9F,
114430x32, 0x31, 0x5F, 0xE9,
11444
114450x38, 0x21, 0x2C, 0x9F,
114460x33, 0x39, 0x5F, 0xE9,
11447
114480x3D, 0xCF, 0x75, 0xC2,
114490x37, 0xCF, 0x75, 0xC4,
11450
114510x31, 0x53, 0x2F, 0x9F,
114520xA6, 0x27, 0x20, 0xE9,
11453
114540x39, 0xE5, 0x2C, 0x9F,
114550xA3, 0x3D, 0x20, 0xE9,
11456
114570x2A, 0x44, 0x4C, 0xB4,
114580x1A, 0x44, 0x54, 0xB4,
11459
114600x0A, 0x45, 0x4D, 0xB0,
114610x02, 0x45, 0x55, 0xB0,
11462
114630x88, 0x73, 0x5E, 0xE9,
114640x2A, 0x20,
114650x1A, 0x20,
11466
114670xA0, 0x37, 0x20, 0xE9,
114680x0A, 0x20,
114690x02, 0x20,
11470
114710x31, 0x53, 0x2F, 0x9F,
114720x3E, 0x30, 0x4F, 0xE9,
11473
114740x39, 0xE5, 0x2C, 0x9F,
114750x3F, 0x38, 0x4F, 0xE9,
11476
114770x30, 0x50, 0x2E, 0x9F,
114780x3A, 0x31, 0x4F, 0xE9,
11479
114800x38, 0x21, 0x2C, 0x9F,
114810x3B, 0x39, 0x4F, 0xE9,
11482
114830x2A, 0x45, 0x4D, 0xB2,
114840x1A, 0x45, 0x55, 0xB2,
11485
114860x0A, 0x45, 0x4D, 0xB4,
114870x02, 0x45, 0x55, 0xB4,
11488
114890x27, 0xCF, 0x75, 0xC6,
114900x2A, 0x20,
114910x1A, 0x20,
11492
114930xA7, 0x30, 0x4F, 0xE9,
114940x0A, 0x20,
114950x02, 0x20,
11496
114970x31, 0x53, 0x2F, 0x9F,
114980x31, 0x27, 0x20, 0xE9,
11499
115000x39, 0xE5, 0x2C, 0x9F,
115010xA8, 0x38, 0x4F, 0xE9,
11502
115030x2A, 0x45, 0x4D, 0xB6,
115040x1A, 0x45, 0x55, 0xB6,
11505
115060x30, 0x50, 0x2E, 0x9F,
115070x36, 0x31, 0x4F, 0xE9,
11508
115090x38, 0x21, 0x2C, 0x9F,
115100x37, 0x39, 0x4F, 0xE9,
11511
115120x00, 0x80, 0x00, 0xE8,
115130x2A, 0x20,
115140x1A, 0x20,
11515
115160x2A, 0x46, 0x4E, 0xBF,
115170x1A, 0x46, 0x56, 0xBF,
11518
115190x31, 0x53, 0x2F, 0x9F,
115200xA4, 0x31, 0x4F, 0xE9,
11521
115220x39, 0xE5, 0x2C, 0x9F,
115230xA5, 0x39, 0x4F, 0xE9,
11524
115250x0A, 0x47, 0x4F, 0xBF,
115260x02, 0x47, 0x57, 0xBF,
11527
115280x31, 0x53, 0x2F, 0x9F,
115290xA1, 0x30, 0x4F, 0xE9,
11530
115310x39, 0xE5, 0x2C, 0x9F,
115320xA2, 0x38, 0x4F, 0xE9,
11533
115340x2A, 0x43, 0x4B, 0xBF,
115350x1A, 0x43, 0x53, 0xBF,
11536
115370x30, 0x50, 0x2E, 0x9F,
115380x35, 0x31, 0x4F, 0xE9,
11539
115400x38, 0x21, 0x2C, 0x9F,
115410x39, 0x39, 0x4F, 0xE9,
11542
115430x31, 0x53, 0x2F, 0x9F,
115440x80, 0x31, 0x57, 0xE9,
11545
115460x39, 0xE5, 0x2C, 0x9F,
115470x81, 0x39, 0x57, 0xE9,
11548
115490x37, 0x48, 0x50, 0xBD,
115500x8A, 0x36, 0x20, 0xE9,
11551
115520x86, 0x76, 0x57, 0xE9,
115530x8B, 0x3E, 0x20, 0xE9,
11554
115550x82, 0x30, 0x57, 0xE9,
115560x87, 0x77, 0x57, 0xE9,
11557
115580x83, 0x38, 0x57, 0xE9,
115590x35, 0x49, 0x51, 0xBD,
11560
115610x84, 0x31, 0x5E, 0xE9,
115620x30, 0x1F, 0x5F, 0xE9,
11563
115640x85, 0x39, 0x5E, 0xE9,
115650x57, 0x25, 0x20, 0xE9,
11566
115670x2B, 0x48, 0x20, 0xE9,
115680x1D, 0x37, 0xE1, 0xEA,
11569
115700x1E, 0x35, 0xE1, 0xEA,
115710x00, 0xE0,
115720x26, 0x77,
11573
115740x24, 0x49, 0x20, 0xE9,
115750x9D, 0xFF, 0x20, 0xEA,
11576
115770x16, 0x26, 0x20, 0xE9,
115780x57, 0x2E, 0xBF, 0xEA,
11579
115800x1C, 0x46, 0xA0, 0xE8,
115810x23, 0x4E, 0xA0, 0xE8,
11582
115830x2B, 0x56, 0xA0, 0xE8,
115840x1D, 0x47, 0xA0, 0xE8,
11585
115860x24, 0x4F, 0xA0, 0xE8,
115870x2C, 0x57, 0xA0, 0xE8,
11588
115890x1C, 0x00,
115900x23, 0x00,
115910x2B, 0x00,
115920x00, 0xE0,
11593
115940x1D, 0x00,
115950x24, 0x00,
115960x2C, 0x00,
115970x00, 0xE0,
11598
115990x1C, 0x65,
116000x23, 0x65,
116010x2B, 0x65,
116020x00, 0xE0,
11603
116040x1D, 0x65,
116050x24, 0x65,
116060x2C, 0x65,
116070x00, 0xE0,
11608
116090x1C, 0x23, 0x60, 0xEC,
116100x36, 0xD7, 0x36, 0xAD,
11611
116120x2B, 0x80, 0x60, 0xEC,
116130x1D, 0x24, 0x60, 0xEC,
11614
116150x3E, 0xD7, 0x3E, 0xAD,
116160x2C, 0x80, 0x60, 0xEC,
11617
116180x1C, 0x2B, 0xDE, 0xE8,
116190x23, 0x80, 0xDE, 0xE8,
11620
116210x36, 0x80, 0x36, 0xBD,
116220x3E, 0x80, 0x3E, 0xBD,
11623
116240x33, 0xD7, 0x1C, 0xBD,
116250x3B, 0xD7, 0x23, 0xBD,
11626
116270x46, 0x80, 0x46, 0xCF,
116280x4F, 0x80, 0x4F, 0xCF,
11629
116300x56, 0x33, 0x56, 0xCF,
116310x47, 0x3B, 0x47, 0xCF,
11632
116330xC5, 0xFF, 0x20, 0xEA,
116340x00, 0x80, 0x00, 0xE8,
11635
116360x4E, 0x33, 0x4E, 0xCF,
116370x57, 0x3B, 0x57, 0xCF,
11638
116390x8B, 0xFF, 0x20, 0xEA,
116400x57, 0xC0, 0xBF, 0xEA,
11641
116420x00, 0x80, 0xA0, 0xE9,
116430x00, 0x00, 0xD8, 0xEC,
11644
11645};
diff --git a/drivers/char/drm/mga_warp.c b/drivers/char/drm/mga_warp.c
new file mode 100644
index 000000000000..0a3a0cc700dc
--- /dev/null
+++ b/drivers/char/drm/mga_warp.c
@@ -0,0 +1,210 @@
1/* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*-
2 * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com
3 *
4 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Gareth Hughes <gareth@valinux.com>
28 */
29
30#include "drmP.h"
31#include "drm.h"
32#include "mga_drm.h"
33#include "mga_drv.h"
34#include "mga_ucode.h"
35
36
37#define MGA_WARP_CODE_ALIGN 256 /* in bytes */
38
39#define WARP_UCODE_SIZE( which ) \
40 ((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
41
42#define WARP_UCODE_INSTALL( which, where ) \
43do { \
44 DRM_DEBUG( " pcbase = 0x%08lx vcbase = %p\n", pcbase, vcbase );\
45 dev_priv->warp_pipe_phys[where] = pcbase; \
46 memcpy( vcbase, which, sizeof(which) ); \
47 pcbase += WARP_UCODE_SIZE( which ); \
48 vcbase += WARP_UCODE_SIZE( which ); \
49} while (0)
50
51
52static unsigned int mga_warp_g400_microcode_size( drm_mga_private_t *dev_priv )
53{
54 unsigned int size;
55
56 size = ( WARP_UCODE_SIZE( warp_g400_tgz ) +
57 WARP_UCODE_SIZE( warp_g400_tgza ) +
58 WARP_UCODE_SIZE( warp_g400_tgzaf ) +
59 WARP_UCODE_SIZE( warp_g400_tgzf ) +
60 WARP_UCODE_SIZE( warp_g400_tgzs ) +
61 WARP_UCODE_SIZE( warp_g400_tgzsa ) +
62 WARP_UCODE_SIZE( warp_g400_tgzsaf ) +
63 WARP_UCODE_SIZE( warp_g400_tgzsf ) +
64 WARP_UCODE_SIZE( warp_g400_t2gz ) +
65 WARP_UCODE_SIZE( warp_g400_t2gza ) +
66 WARP_UCODE_SIZE( warp_g400_t2gzaf ) +
67 WARP_UCODE_SIZE( warp_g400_t2gzf ) +
68 WARP_UCODE_SIZE( warp_g400_t2gzs ) +
69 WARP_UCODE_SIZE( warp_g400_t2gzsa ) +
70 WARP_UCODE_SIZE( warp_g400_t2gzsaf ) +
71 WARP_UCODE_SIZE( warp_g400_t2gzsf ) );
72
73 size = PAGE_ALIGN( size );
74
75 DRM_DEBUG( "G400 ucode size = %d bytes\n", size );
76 return size;
77}
78
79static unsigned int mga_warp_g200_microcode_size( drm_mga_private_t *dev_priv )
80{
81 unsigned int size;
82
83 size = ( WARP_UCODE_SIZE( warp_g200_tgz ) +
84 WARP_UCODE_SIZE( warp_g200_tgza ) +
85 WARP_UCODE_SIZE( warp_g200_tgzaf ) +
86 WARP_UCODE_SIZE( warp_g200_tgzf ) +
87 WARP_UCODE_SIZE( warp_g200_tgzs ) +
88 WARP_UCODE_SIZE( warp_g200_tgzsa ) +
89 WARP_UCODE_SIZE( warp_g200_tgzsaf ) +
90 WARP_UCODE_SIZE( warp_g200_tgzsf ) );
91
92 size = PAGE_ALIGN( size );
93
94 DRM_DEBUG( "G200 ucode size = %d bytes\n", size );
95 return size;
96}
97
98static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv )
99{
100 unsigned char *vcbase = dev_priv->warp->handle;
101 unsigned long pcbase = dev_priv->warp->offset;
102 unsigned int size;
103
104 size = mga_warp_g400_microcode_size( dev_priv );
105 if ( size > dev_priv->warp->size ) {
106 DRM_ERROR( "microcode too large! (%u > %lu)\n",
107 size, dev_priv->warp->size );
108 return DRM_ERR(ENOMEM);
109 }
110
111 memset( dev_priv->warp_pipe_phys, 0,
112 sizeof(dev_priv->warp_pipe_phys) );
113
114 WARP_UCODE_INSTALL( warp_g400_tgz, MGA_WARP_TGZ );
115 WARP_UCODE_INSTALL( warp_g400_tgzf, MGA_WARP_TGZF );
116 WARP_UCODE_INSTALL( warp_g400_tgza, MGA_WARP_TGZA );
117 WARP_UCODE_INSTALL( warp_g400_tgzaf, MGA_WARP_TGZAF );
118 WARP_UCODE_INSTALL( warp_g400_tgzs, MGA_WARP_TGZS );
119 WARP_UCODE_INSTALL( warp_g400_tgzsf, MGA_WARP_TGZSF );
120 WARP_UCODE_INSTALL( warp_g400_tgzsa, MGA_WARP_TGZSA );
121 WARP_UCODE_INSTALL( warp_g400_tgzsaf, MGA_WARP_TGZSAF );
122
123 WARP_UCODE_INSTALL( warp_g400_t2gz, MGA_WARP_T2GZ );
124 WARP_UCODE_INSTALL( warp_g400_t2gzf, MGA_WARP_T2GZF );
125 WARP_UCODE_INSTALL( warp_g400_t2gza, MGA_WARP_T2GZA );
126 WARP_UCODE_INSTALL( warp_g400_t2gzaf, MGA_WARP_T2GZAF );
127 WARP_UCODE_INSTALL( warp_g400_t2gzs, MGA_WARP_T2GZS );
128 WARP_UCODE_INSTALL( warp_g400_t2gzsf, MGA_WARP_T2GZSF );
129 WARP_UCODE_INSTALL( warp_g400_t2gzsa, MGA_WARP_T2GZSA );
130 WARP_UCODE_INSTALL( warp_g400_t2gzsaf, MGA_WARP_T2GZSAF );
131
132 return 0;
133}
134
135static int mga_warp_install_g200_microcode( drm_mga_private_t *dev_priv )
136{
137 unsigned char *vcbase = dev_priv->warp->handle;
138 unsigned long pcbase = dev_priv->warp->offset;
139 unsigned int size;
140
141 size = mga_warp_g200_microcode_size( dev_priv );
142 if ( size > dev_priv->warp->size ) {
143 DRM_ERROR( "microcode too large! (%u > %lu)\n",
144 size, dev_priv->warp->size );
145 return DRM_ERR(ENOMEM);
146 }
147
148 memset( dev_priv->warp_pipe_phys, 0,
149 sizeof(dev_priv->warp_pipe_phys) );
150
151 WARP_UCODE_INSTALL( warp_g200_tgz, MGA_WARP_TGZ );
152 WARP_UCODE_INSTALL( warp_g200_tgzf, MGA_WARP_TGZF );
153 WARP_UCODE_INSTALL( warp_g200_tgza, MGA_WARP_TGZA );
154 WARP_UCODE_INSTALL( warp_g200_tgzaf, MGA_WARP_TGZAF );
155 WARP_UCODE_INSTALL( warp_g200_tgzs, MGA_WARP_TGZS );
156 WARP_UCODE_INSTALL( warp_g200_tgzsf, MGA_WARP_TGZSF );
157 WARP_UCODE_INSTALL( warp_g200_tgzsa, MGA_WARP_TGZSA );
158 WARP_UCODE_INSTALL( warp_g200_tgzsaf, MGA_WARP_TGZSAF );
159
160 return 0;
161}
162
163int mga_warp_install_microcode( drm_mga_private_t *dev_priv )
164{
165 switch ( dev_priv->chipset ) {
166 case MGA_CARD_TYPE_G400:
167 return mga_warp_install_g400_microcode( dev_priv );
168 case MGA_CARD_TYPE_G200:
169 return mga_warp_install_g200_microcode( dev_priv );
170 default:
171 return DRM_ERR(EINVAL);
172 }
173}
174
175#define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
176
177int mga_warp_init( drm_mga_private_t *dev_priv )
178{
179 u32 wmisc;
180
181 /* FIXME: Get rid of these damned magic numbers...
182 */
183 switch ( dev_priv->chipset ) {
184 case MGA_CARD_TYPE_G400:
185 MGA_WRITE( MGA_WIADDR2, MGA_WMODE_SUSPEND );
186 MGA_WRITE( MGA_WGETMSB, 0x00000E00 );
187 MGA_WRITE( MGA_WVRTXSZ, 0x00001807 );
188 MGA_WRITE( MGA_WACCEPTSEQ, 0x18000000 );
189 break;
190 case MGA_CARD_TYPE_G200:
191 MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND );
192 MGA_WRITE( MGA_WGETMSB, 0x1606 );
193 MGA_WRITE( MGA_WVRTXSZ, 7 );
194 break;
195 default:
196 return DRM_ERR(EINVAL);
197 }
198
199 MGA_WRITE( MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
200 MGA_WMASTER_ENABLE |
201 MGA_WCACHEFLUSH_ENABLE) );
202 wmisc = MGA_READ( MGA_WMISC );
203 if ( wmisc != WMISC_EXPECTED ) {
204 DRM_ERROR( "WARP engine config failed! 0x%x != 0x%x\n",
205 wmisc, WMISC_EXPECTED );
206 return DRM_ERR(EINVAL);
207 }
208
209 return 0;
210}
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
new file mode 100644
index 000000000000..08ed8d01d9d9
--- /dev/null
+++ b/drivers/char/drm/r128_cce.c
@@ -0,0 +1,943 @@
1/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
2 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
3 *
4 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Gareth Hughes <gareth@valinux.com>
29 */
30
31#include "drmP.h"
32#include "drm.h"
33#include "r128_drm.h"
34#include "r128_drv.h"
35
36#define R128_FIFO_DEBUG 0
37
38/* CCE microcode (from ATI) */
39static u32 r128_cce_microcode[] = {
40 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
41 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0,
42 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1,
43 11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11,
44 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28,
45 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9,
46 30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656,
47 1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1,
48 15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071,
49 12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2,
50 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1,
51 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
52 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1,
53 15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2,
54 268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1,
55 15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82,
56 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729,
57 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008,
58 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
59 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1,
60 180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1,
61 114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0,
62 33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370,
63 1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1,
64 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793,
65 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
66 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1,
67 114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1,
68 1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1,
69 1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894,
70 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14,
71 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1,
72 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1,
73 33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1,
74 409611, 9, 188, 0, 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
81};
82
83static int R128_READ_PLL(drm_device_t *dev, int addr)
84{
85 drm_r128_private_t *dev_priv = dev->dev_private;
86
87 R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
88 return R128_READ(R128_CLOCK_CNTL_DATA);
89}
90
91#if R128_FIFO_DEBUG
92static void r128_status( drm_r128_private_t *dev_priv )
93{
94 printk( "GUI_STAT = 0x%08x\n",
95 (unsigned int)R128_READ( R128_GUI_STAT ) );
96 printk( "PM4_STAT = 0x%08x\n",
97 (unsigned int)R128_READ( R128_PM4_STAT ) );
98 printk( "PM4_BUFFER_DL_WPTR = 0x%08x\n",
99 (unsigned int)R128_READ( R128_PM4_BUFFER_DL_WPTR ) );
100 printk( "PM4_BUFFER_DL_RPTR = 0x%08x\n",
101 (unsigned int)R128_READ( R128_PM4_BUFFER_DL_RPTR ) );
102 printk( "PM4_MICRO_CNTL = 0x%08x\n",
103 (unsigned int)R128_READ( R128_PM4_MICRO_CNTL ) );
104 printk( "PM4_BUFFER_CNTL = 0x%08x\n",
105 (unsigned int)R128_READ( R128_PM4_BUFFER_CNTL ) );
106}
107#endif
108
109
110/* ================================================================
111 * Engine, FIFO control
112 */
113
114static int r128_do_pixcache_flush( drm_r128_private_t *dev_priv )
115{
116 u32 tmp;
117 int i;
118
119 tmp = R128_READ( R128_PC_NGUI_CTLSTAT ) | R128_PC_FLUSH_ALL;
120 R128_WRITE( R128_PC_NGUI_CTLSTAT, tmp );
121
122 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
123 if ( !(R128_READ( R128_PC_NGUI_CTLSTAT ) & R128_PC_BUSY) ) {
124 return 0;
125 }
126 DRM_UDELAY( 1 );
127 }
128
129#if R128_FIFO_DEBUG
130 DRM_ERROR( "failed!\n" );
131#endif
132 return DRM_ERR(EBUSY);
133}
134
135static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries )
136{
137 int i;
138
139 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
140 int slots = R128_READ( R128_GUI_STAT ) & R128_GUI_FIFOCNT_MASK;
141 if ( slots >= entries ) return 0;
142 DRM_UDELAY( 1 );
143 }
144
145#if R128_FIFO_DEBUG
146 DRM_ERROR( "failed!\n" );
147#endif
148 return DRM_ERR(EBUSY);
149}
150
151static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
152{
153 int i, ret;
154
155 ret = r128_do_wait_for_fifo( dev_priv, 64 );
156 if ( ret ) return ret;
157
158 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
159 if ( !(R128_READ( R128_GUI_STAT ) & R128_GUI_ACTIVE) ) {
160 r128_do_pixcache_flush( dev_priv );
161 return 0;
162 }
163 DRM_UDELAY( 1 );
164 }
165
166#if R128_FIFO_DEBUG
167 DRM_ERROR( "failed!\n" );
168#endif
169 return DRM_ERR(EBUSY);
170}
171
172
173/* ================================================================
174 * CCE control, initialization
175 */
176
177/* Load the microcode for the CCE */
178static void r128_cce_load_microcode( drm_r128_private_t *dev_priv )
179{
180 int i;
181
182 DRM_DEBUG( "\n" );
183
184 r128_do_wait_for_idle( dev_priv );
185
186 R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 );
187 for ( i = 0 ; i < 256 ; i++ ) {
188 R128_WRITE( R128_PM4_MICROCODE_DATAH,
189 r128_cce_microcode[i * 2] );
190 R128_WRITE( R128_PM4_MICROCODE_DATAL,
191 r128_cce_microcode[i * 2 + 1] );
192 }
193}
194
195/* Flush any pending commands to the CCE. This should only be used just
196 * prior to a wait for idle, as it informs the engine that the command
197 * stream is ending.
198 */
199static void r128_do_cce_flush( drm_r128_private_t *dev_priv )
200{
201 u32 tmp;
202
203 tmp = R128_READ( R128_PM4_BUFFER_DL_WPTR ) | R128_PM4_BUFFER_DL_DONE;
204 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, tmp );
205}
206
207/* Wait for the CCE to go idle.
208 */
209int r128_do_cce_idle( drm_r128_private_t *dev_priv )
210{
211 int i;
212
213 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
214 if ( GET_RING_HEAD( dev_priv ) == dev_priv->ring.tail ) {
215 int pm4stat = R128_READ( R128_PM4_STAT );
216 if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
217 dev_priv->cce_fifo_size ) &&
218 !(pm4stat & (R128_PM4_BUSY |
219 R128_PM4_GUI_ACTIVE)) ) {
220 return r128_do_pixcache_flush( dev_priv );
221 }
222 }
223 DRM_UDELAY( 1 );
224 }
225
226#if R128_FIFO_DEBUG
227 DRM_ERROR( "failed!\n" );
228 r128_status( dev_priv );
229#endif
230 return DRM_ERR(EBUSY);
231}
232
233/* Start the Concurrent Command Engine.
234 */
235static void r128_do_cce_start( drm_r128_private_t *dev_priv )
236{
237 r128_do_wait_for_idle( dev_priv );
238
239 R128_WRITE( R128_PM4_BUFFER_CNTL,
240 dev_priv->cce_mode | dev_priv->ring.size_l2qw
241 | R128_PM4_BUFFER_CNTL_NOUPDATE );
242 R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */
243 R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN );
244
245 dev_priv->cce_running = 1;
246}
247
248/* Reset the Concurrent Command Engine. This will not flush any pending
249 * commands, so you must wait for the CCE command stream to complete
250 * before calling this routine.
251 */
252static void r128_do_cce_reset( drm_r128_private_t *dev_priv )
253{
254 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
255 R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
256 dev_priv->ring.tail = 0;
257}
258
259/* Stop the Concurrent Command Engine. This will not flush any pending
260 * commands, so you must flush the command stream and wait for the CCE
261 * to go idle before calling this routine.
262 */
263static void r128_do_cce_stop( drm_r128_private_t *dev_priv )
264{
265 R128_WRITE( R128_PM4_MICRO_CNTL, 0 );
266 R128_WRITE( R128_PM4_BUFFER_CNTL,
267 R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE );
268
269 dev_priv->cce_running = 0;
270}
271
272/* Reset the engine. This will stop the CCE if it is running.
273 */
274static int r128_do_engine_reset( drm_device_t *dev )
275{
276 drm_r128_private_t *dev_priv = dev->dev_private;
277 u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
278
279 r128_do_pixcache_flush( dev_priv );
280
281 clock_cntl_index = R128_READ( R128_CLOCK_CNTL_INDEX );
282 mclk_cntl = R128_READ_PLL( dev, R128_MCLK_CNTL );
283
284 R128_WRITE_PLL( R128_MCLK_CNTL,
285 mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP );
286
287 gen_reset_cntl = R128_READ( R128_GEN_RESET_CNTL );
288
289 /* Taken from the sample code - do not change */
290 R128_WRITE( R128_GEN_RESET_CNTL,
291 gen_reset_cntl | R128_SOFT_RESET_GUI );
292 R128_READ( R128_GEN_RESET_CNTL );
293 R128_WRITE( R128_GEN_RESET_CNTL,
294 gen_reset_cntl & ~R128_SOFT_RESET_GUI );
295 R128_READ( R128_GEN_RESET_CNTL );
296
297 R128_WRITE_PLL( R128_MCLK_CNTL, mclk_cntl );
298 R128_WRITE( R128_CLOCK_CNTL_INDEX, clock_cntl_index );
299 R128_WRITE( R128_GEN_RESET_CNTL, gen_reset_cntl );
300
301 /* Reset the CCE ring */
302 r128_do_cce_reset( dev_priv );
303
304 /* The CCE is no longer running after an engine reset */
305 dev_priv->cce_running = 0;
306
307 /* Reset any pending vertex, indirect buffers */
308 r128_freelist_reset( dev );
309
310 return 0;
311}
312
313static void r128_cce_init_ring_buffer( drm_device_t *dev,
314 drm_r128_private_t *dev_priv )
315{
316 u32 ring_start;
317 u32 tmp;
318
319 DRM_DEBUG( "\n" );
320
321 /* The manual (p. 2) says this address is in "VM space". This
322 * means it's an offset from the start of AGP space.
323 */
324#if __OS_HAS_AGP
325 if ( !dev_priv->is_pci )
326 ring_start = dev_priv->cce_ring->offset - dev->agp->base;
327 else
328#endif
329 ring_start = dev_priv->cce_ring->offset - dev->sg->handle;
330
331 R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
332
333 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
334 R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
335
336 /* Set watermark control */
337 R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
338 ((R128_WATERMARK_L/4) << R128_WMA_SHIFT)
339 | ((R128_WATERMARK_M/4) << R128_WMB_SHIFT)
340 | ((R128_WATERMARK_N/4) << R128_WMC_SHIFT)
341 | ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT) );
342
343 /* Force read. Why? Because it's in the examples... */
344 R128_READ( R128_PM4_BUFFER_ADDR );
345
346 /* Turn on bus mastering */
347 tmp = R128_READ( R128_BUS_CNTL ) & ~R128_BUS_MASTER_DIS;
348 R128_WRITE( R128_BUS_CNTL, tmp );
349}
350
351static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
352{
353 drm_r128_private_t *dev_priv;
354
355 DRM_DEBUG( "\n" );
356
357 dev_priv = drm_alloc( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
358 if ( dev_priv == NULL )
359 return DRM_ERR(ENOMEM);
360
361 memset( dev_priv, 0, sizeof(drm_r128_private_t) );
362
363 dev_priv->is_pci = init->is_pci;
364
365 if ( dev_priv->is_pci && !dev->sg ) {
366 DRM_ERROR( "PCI GART memory not allocated!\n" );
367 dev->dev_private = (void *)dev_priv;
368 r128_do_cleanup_cce( dev );
369 return DRM_ERR(EINVAL);
370 }
371
372 dev_priv->usec_timeout = init->usec_timeout;
373 if ( dev_priv->usec_timeout < 1 ||
374 dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
375 DRM_DEBUG( "TIMEOUT problem!\n" );
376 dev->dev_private = (void *)dev_priv;
377 r128_do_cleanup_cce( dev );
378 return DRM_ERR(EINVAL);
379 }
380
381 dev_priv->cce_mode = init->cce_mode;
382
383 /* GH: Simple idle check.
384 */
385 atomic_set( &dev_priv->idle_count, 0 );
386
387 /* We don't support anything other than bus-mastering ring mode,
388 * but the ring can be in either AGP or PCI space for the ring
389 * read pointer.
390 */
391 if ( ( init->cce_mode != R128_PM4_192BM ) &&
392 ( init->cce_mode != R128_PM4_128BM_64INDBM ) &&
393 ( init->cce_mode != R128_PM4_64BM_128INDBM ) &&
394 ( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
395 DRM_DEBUG( "Bad cce_mode!\n" );
396 dev->dev_private = (void *)dev_priv;
397 r128_do_cleanup_cce( dev );
398 return DRM_ERR(EINVAL);
399 }
400
401 switch ( init->cce_mode ) {
402 case R128_PM4_NONPM4:
403 dev_priv->cce_fifo_size = 0;
404 break;
405 case R128_PM4_192PIO:
406 case R128_PM4_192BM:
407 dev_priv->cce_fifo_size = 192;
408 break;
409 case R128_PM4_128PIO_64INDBM:
410 case R128_PM4_128BM_64INDBM:
411 dev_priv->cce_fifo_size = 128;
412 break;
413 case R128_PM4_64PIO_128INDBM:
414 case R128_PM4_64BM_128INDBM:
415 case R128_PM4_64PIO_64VCBM_64INDBM:
416 case R128_PM4_64BM_64VCBM_64INDBM:
417 case R128_PM4_64PIO_64VCPIO_64INDPIO:
418 dev_priv->cce_fifo_size = 64;
419 break;
420 }
421
422 switch ( init->fb_bpp ) {
423 case 16:
424 dev_priv->color_fmt = R128_DATATYPE_RGB565;
425 break;
426 case 32:
427 default:
428 dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
429 break;
430 }
431 dev_priv->front_offset = init->front_offset;
432 dev_priv->front_pitch = init->front_pitch;
433 dev_priv->back_offset = init->back_offset;
434 dev_priv->back_pitch = init->back_pitch;
435
436 switch ( init->depth_bpp ) {
437 case 16:
438 dev_priv->depth_fmt = R128_DATATYPE_RGB565;
439 break;
440 case 24:
441 case 32:
442 default:
443 dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
444 break;
445 }
446 dev_priv->depth_offset = init->depth_offset;
447 dev_priv->depth_pitch = init->depth_pitch;
448 dev_priv->span_offset = init->span_offset;
449
450 dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch/8) << 21) |
451 (dev_priv->front_offset >> 5));
452 dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch/8) << 21) |
453 (dev_priv->back_offset >> 5));
454 dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) |
455 (dev_priv->depth_offset >> 5) |
456 R128_DST_TILE);
457 dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) |
458 (dev_priv->span_offset >> 5));
459
460 DRM_GETSAREA();
461
462 if(!dev_priv->sarea) {
463 DRM_ERROR("could not find sarea!\n");
464 dev->dev_private = (void *)dev_priv;
465 r128_do_cleanup_cce( dev );
466 return DRM_ERR(EINVAL);
467 }
468
469 dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
470 if(!dev_priv->mmio) {
471 DRM_ERROR("could not find mmio region!\n");
472 dev->dev_private = (void *)dev_priv;
473 r128_do_cleanup_cce( dev );
474 return DRM_ERR(EINVAL);
475 }
476 dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
477 if(!dev_priv->cce_ring) {
478 DRM_ERROR("could not find cce ring region!\n");
479 dev->dev_private = (void *)dev_priv;
480 r128_do_cleanup_cce( dev );
481 return DRM_ERR(EINVAL);
482 }
483 dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
484 if(!dev_priv->ring_rptr) {
485 DRM_ERROR("could not find ring read pointer!\n");
486 dev->dev_private = (void *)dev_priv;
487 r128_do_cleanup_cce( dev );
488 return DRM_ERR(EINVAL);
489 }
490 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
491 if(!dev->agp_buffer_map) {
492 DRM_ERROR("could not find dma buffer region!\n");
493 dev->dev_private = (void *)dev_priv;
494 r128_do_cleanup_cce( dev );
495 return DRM_ERR(EINVAL);
496 }
497
498 if ( !dev_priv->is_pci ) {
499 dev_priv->agp_textures = drm_core_findmap(dev, init->agp_textures_offset);
500 if(!dev_priv->agp_textures) {
501 DRM_ERROR("could not find agp texture region!\n");
502 dev->dev_private = (void *)dev_priv;
503 r128_do_cleanup_cce( dev );
504 return DRM_ERR(EINVAL);
505 }
506 }
507
508 dev_priv->sarea_priv =
509 (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
510 init->sarea_priv_offset);
511
512#if __OS_HAS_AGP
513 if ( !dev_priv->is_pci ) {
514 drm_core_ioremap( dev_priv->cce_ring, dev );
515 drm_core_ioremap( dev_priv->ring_rptr, dev );
516 drm_core_ioremap( dev->agp_buffer_map, dev );
517 if(!dev_priv->cce_ring->handle ||
518 !dev_priv->ring_rptr->handle ||
519 !dev->agp_buffer_map->handle) {
520 DRM_ERROR("Could not ioremap agp regions!\n");
521 dev->dev_private = (void *)dev_priv;
522 r128_do_cleanup_cce( dev );
523 return DRM_ERR(ENOMEM);
524 }
525 } else
526#endif
527 {
528 dev_priv->cce_ring->handle =
529 (void *)dev_priv->cce_ring->offset;
530 dev_priv->ring_rptr->handle =
531 (void *)dev_priv->ring_rptr->offset;
532 dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset;
533 }
534
535#if __OS_HAS_AGP
536 if ( !dev_priv->is_pci )
537 dev_priv->cce_buffers_offset = dev->agp->base;
538 else
539#endif
540 dev_priv->cce_buffers_offset = dev->sg->handle;
541
542 dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle;
543 dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle
544 + init->ring_size / sizeof(u32));
545 dev_priv->ring.size = init->ring_size;
546 dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
547
548 dev_priv->ring.tail_mask =
549 (dev_priv->ring.size / sizeof(u32)) - 1;
550
551 dev_priv->ring.high_mark = 128;
552
553 dev_priv->sarea_priv->last_frame = 0;
554 R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame );
555
556 dev_priv->sarea_priv->last_dispatch = 0;
557 R128_WRITE( R128_LAST_DISPATCH_REG,
558 dev_priv->sarea_priv->last_dispatch );
559
560#if __OS_HAS_AGP
561 if ( dev_priv->is_pci ) {
562#endif
563 if (!drm_ati_pcigart_init( dev, &dev_priv->phys_pci_gart,
564 &dev_priv->bus_pci_gart) ) {
565 DRM_ERROR( "failed to init PCI GART!\n" );
566 dev->dev_private = (void *)dev_priv;
567 r128_do_cleanup_cce( dev );
568 return DRM_ERR(ENOMEM);
569 }
570 R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart );
571#if __OS_HAS_AGP
572 }
573#endif
574
575 r128_cce_init_ring_buffer( dev, dev_priv );
576 r128_cce_load_microcode( dev_priv );
577
578 dev->dev_private = (void *)dev_priv;
579
580 r128_do_engine_reset( dev );
581
582 return 0;
583}
584
585int r128_do_cleanup_cce( drm_device_t *dev )
586{
587
588 /* Make sure interrupts are disabled here because the uninstall ioctl
589 * may not have been called from userspace and after dev_private
590 * is freed, it's too late.
591 */
592 if ( dev->irq_enabled ) drm_irq_uninstall(dev);
593
594 if ( dev->dev_private ) {
595 drm_r128_private_t *dev_priv = dev->dev_private;
596
597#if __OS_HAS_AGP
598 if ( !dev_priv->is_pci ) {
599 if ( dev_priv->cce_ring != NULL )
600 drm_core_ioremapfree( dev_priv->cce_ring, dev );
601 if ( dev_priv->ring_rptr != NULL )
602 drm_core_ioremapfree( dev_priv->ring_rptr, dev );
603 if ( dev->agp_buffer_map != NULL )
604 drm_core_ioremapfree( dev->agp_buffer_map, dev );
605 } else
606#endif
607 {
608 if (!drm_ati_pcigart_cleanup( dev,
609 dev_priv->phys_pci_gart,
610 dev_priv->bus_pci_gart ))
611 DRM_ERROR( "failed to cleanup PCI GART!\n" );
612 }
613
614 drm_free( dev->dev_private, sizeof(drm_r128_private_t),
615 DRM_MEM_DRIVER );
616 dev->dev_private = NULL;
617 }
618
619 return 0;
620}
621
622int r128_cce_init( DRM_IOCTL_ARGS )
623{
624 DRM_DEVICE;
625 drm_r128_init_t init;
626
627 DRM_DEBUG( "\n" );
628
629 LOCK_TEST_WITH_RETURN( dev, filp );
630
631 DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t __user *)data, sizeof(init) );
632
633 switch ( init.func ) {
634 case R128_INIT_CCE:
635 return r128_do_init_cce( dev, &init );
636 case R128_CLEANUP_CCE:
637 return r128_do_cleanup_cce( dev );
638 }
639
640 return DRM_ERR(EINVAL);
641}
642
643int r128_cce_start( DRM_IOCTL_ARGS )
644{
645 DRM_DEVICE;
646 drm_r128_private_t *dev_priv = dev->dev_private;
647 DRM_DEBUG( "\n" );
648
649 LOCK_TEST_WITH_RETURN( dev, filp );
650
651 if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) {
652 DRM_DEBUG( "%s while CCE running\n", __FUNCTION__ );
653 return 0;
654 }
655
656 r128_do_cce_start( dev_priv );
657
658 return 0;
659}
660
661/* Stop the CCE. The engine must have been idled before calling this
662 * routine.
663 */
664int r128_cce_stop( DRM_IOCTL_ARGS )
665{
666 DRM_DEVICE;
667 drm_r128_private_t *dev_priv = dev->dev_private;
668 drm_r128_cce_stop_t stop;
669 int ret;
670 DRM_DEBUG( "\n" );
671
672 LOCK_TEST_WITH_RETURN( dev, filp );
673
674 DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *)data, sizeof(stop) );
675
676 /* Flush any pending CCE commands. This ensures any outstanding
677 * commands are exectuted by the engine before we turn it off.
678 */
679 if ( stop.flush ) {
680 r128_do_cce_flush( dev_priv );
681 }
682
683 /* If we fail to make the engine go idle, we return an error
684 * code so that the DRM ioctl wrapper can try again.
685 */
686 if ( stop.idle ) {
687 ret = r128_do_cce_idle( dev_priv );
688 if ( ret ) return ret;
689 }
690
691 /* Finally, we can turn off the CCE. If the engine isn't idle,
692 * we will get some dropped triangles as they won't be fully
693 * rendered before the CCE is shut down.
694 */
695 r128_do_cce_stop( dev_priv );
696
697 /* Reset the engine */
698 r128_do_engine_reset( dev );
699
700 return 0;
701}
702
703/* Just reset the CCE ring. Called as part of an X Server engine reset.
704 */
705int r128_cce_reset( DRM_IOCTL_ARGS )
706{
707 DRM_DEVICE;
708 drm_r128_private_t *dev_priv = dev->dev_private;
709 DRM_DEBUG( "\n" );
710
711 LOCK_TEST_WITH_RETURN( dev, filp );
712
713 if ( !dev_priv ) {
714 DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
715 return DRM_ERR(EINVAL);
716 }
717
718 r128_do_cce_reset( dev_priv );
719
720 /* The CCE is no longer running after an engine reset */
721 dev_priv->cce_running = 0;
722
723 return 0;
724}
725
726int r128_cce_idle( DRM_IOCTL_ARGS )
727{
728 DRM_DEVICE;
729 drm_r128_private_t *dev_priv = dev->dev_private;
730 DRM_DEBUG( "\n" );
731
732 LOCK_TEST_WITH_RETURN( dev, filp );
733
734 if ( dev_priv->cce_running ) {
735 r128_do_cce_flush( dev_priv );
736 }
737
738 return r128_do_cce_idle( dev_priv );
739}
740
741int r128_engine_reset( DRM_IOCTL_ARGS )
742{
743 DRM_DEVICE;
744 DRM_DEBUG( "\n" );
745
746 LOCK_TEST_WITH_RETURN( dev, filp );
747
748 return r128_do_engine_reset( dev );
749}
750
751int r128_fullscreen( DRM_IOCTL_ARGS )
752{
753 return DRM_ERR(EINVAL);
754}
755
756
757/* ================================================================
758 * Freelist management
759 */
760#define R128_BUFFER_USED 0xffffffff
761#define R128_BUFFER_FREE 0
762
763#if 0
764static int r128_freelist_init( drm_device_t *dev )
765{
766 drm_device_dma_t *dma = dev->dma;
767 drm_r128_private_t *dev_priv = dev->dev_private;
768 drm_buf_t *buf;
769 drm_r128_buf_priv_t *buf_priv;
770 drm_r128_freelist_t *entry;
771 int i;
772
773 dev_priv->head = drm_alloc( sizeof(drm_r128_freelist_t),
774 DRM_MEM_DRIVER );
775 if ( dev_priv->head == NULL )
776 return DRM_ERR(ENOMEM);
777
778 memset( dev_priv->head, 0, sizeof(drm_r128_freelist_t) );
779 dev_priv->head->age = R128_BUFFER_USED;
780
781 for ( i = 0 ; i < dma->buf_count ; i++ ) {
782 buf = dma->buflist[i];
783 buf_priv = buf->dev_private;
784
785 entry = drm_alloc( sizeof(drm_r128_freelist_t),
786 DRM_MEM_DRIVER );
787 if ( !entry ) return DRM_ERR(ENOMEM);
788
789 entry->age = R128_BUFFER_FREE;
790 entry->buf = buf;
791 entry->prev = dev_priv->head;
792 entry->next = dev_priv->head->next;
793 if ( !entry->next )
794 dev_priv->tail = entry;
795
796 buf_priv->discard = 0;
797 buf_priv->dispatched = 0;
798 buf_priv->list_entry = entry;
799
800 dev_priv->head->next = entry;
801
802 if ( dev_priv->head->next )
803 dev_priv->head->next->prev = entry;
804 }
805
806 return 0;
807
808}
809#endif
810
811static drm_buf_t *r128_freelist_get( drm_device_t *dev )
812{
813 drm_device_dma_t *dma = dev->dma;
814 drm_r128_private_t *dev_priv = dev->dev_private;
815 drm_r128_buf_priv_t *buf_priv;
816 drm_buf_t *buf;
817 int i, t;
818
819 /* FIXME: Optimize -- use freelist code */
820
821 for ( i = 0 ; i < dma->buf_count ; i++ ) {
822 buf = dma->buflist[i];
823 buf_priv = buf->dev_private;
824 if ( buf->filp == 0 )
825 return buf;
826 }
827
828 for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
829 u32 done_age = R128_READ( R128_LAST_DISPATCH_REG );
830
831 for ( i = 0 ; i < dma->buf_count ; i++ ) {
832 buf = dma->buflist[i];
833 buf_priv = buf->dev_private;
834 if ( buf->pending && buf_priv->age <= done_age ) {
835 /* The buffer has been processed, so it
836 * can now be used.
837 */
838 buf->pending = 0;
839 return buf;
840 }
841 }
842 DRM_UDELAY( 1 );
843 }
844
845 DRM_DEBUG( "returning NULL!\n" );
846 return NULL;
847}
848
849void r128_freelist_reset( drm_device_t *dev )
850{
851 drm_device_dma_t *dma = dev->dma;
852 int i;
853
854 for ( i = 0 ; i < dma->buf_count ; i++ ) {
855 drm_buf_t *buf = dma->buflist[i];
856 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
857 buf_priv->age = 0;
858 }
859}
860
861
862/* ================================================================
863 * CCE command submission
864 */
865
866int r128_wait_ring( drm_r128_private_t *dev_priv, int n )
867{
868 drm_r128_ring_buffer_t *ring = &dev_priv->ring;
869 int i;
870
871 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
872 r128_update_ring_snapshot( dev_priv );
873 if ( ring->space >= n )
874 return 0;
875 DRM_UDELAY( 1 );
876 }
877
878 /* FIXME: This is being ignored... */
879 DRM_ERROR( "failed!\n" );
880 return DRM_ERR(EBUSY);
881}
882
883static int r128_cce_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d )
884{
885 int i;
886 drm_buf_t *buf;
887
888 for ( i = d->granted_count ; i < d->request_count ; i++ ) {
889 buf = r128_freelist_get( dev );
890 if ( !buf ) return DRM_ERR(EAGAIN);
891
892 buf->filp = filp;
893
894 if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
895 sizeof(buf->idx) ) )
896 return DRM_ERR(EFAULT);
897 if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
898 sizeof(buf->total) ) )
899 return DRM_ERR(EFAULT);
900
901 d->granted_count++;
902 }
903 return 0;
904}
905
906int r128_cce_buffers( DRM_IOCTL_ARGS )
907{
908 DRM_DEVICE;
909 drm_device_dma_t *dma = dev->dma;
910 int ret = 0;
911 drm_dma_t __user *argp = (void __user *)data;
912 drm_dma_t d;
913
914 LOCK_TEST_WITH_RETURN( dev, filp );
915
916 DRM_COPY_FROM_USER_IOCTL( d, argp, sizeof(d) );
917
918 /* Please don't send us buffers.
919 */
920 if ( d.send_count != 0 ) {
921 DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
922 DRM_CURRENTPID, d.send_count );
923 return DRM_ERR(EINVAL);
924 }
925
926 /* We'll send you buffers.
927 */
928 if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
929 DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
930 DRM_CURRENTPID, d.request_count, dma->buf_count );
931 return DRM_ERR(EINVAL);
932 }
933
934 d.granted_count = 0;
935
936 if ( d.request_count ) {
937 ret = r128_cce_get_buffers( filp, dev, &d );
938 }
939
940 DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d) );
941
942 return ret;
943}
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
new file mode 100644
index 000000000000..0cba17d1e0ff
--- /dev/null
+++ b/drivers/char/drm/r128_drm.h
@@ -0,0 +1,345 @@
1/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-
2 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
3 *
4 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Gareth Hughes <gareth@valinux.com>
29 * Kevin E. Martin <martin@valinux.com>
30 */
31
32#ifndef __R128_DRM_H__
33#define __R128_DRM_H__
34
35/* WARNING: If you change any of these defines, make sure to change the
36 * defines in the X server file (r128_sarea.h)
37 */
38#ifndef __R128_SAREA_DEFINES__
39#define __R128_SAREA_DEFINES__
40
41/* What needs to be changed for the current vertex buffer?
42 */
43#define R128_UPLOAD_CONTEXT 0x001
44#define R128_UPLOAD_SETUP 0x002
45#define R128_UPLOAD_TEX0 0x004
46#define R128_UPLOAD_TEX1 0x008
47#define R128_UPLOAD_TEX0IMAGES 0x010
48#define R128_UPLOAD_TEX1IMAGES 0x020
49#define R128_UPLOAD_CORE 0x040
50#define R128_UPLOAD_MASKS 0x080
51#define R128_UPLOAD_WINDOW 0x100
52#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */
53#define R128_REQUIRE_QUIESCENCE 0x400
54#define R128_UPLOAD_ALL 0x7ff
55
56#define R128_FRONT 0x1
57#define R128_BACK 0x2
58#define R128_DEPTH 0x4
59
60/* Primitive types
61 */
62#define R128_POINTS 0x1
63#define R128_LINES 0x2
64#define R128_LINE_STRIP 0x3
65#define R128_TRIANGLES 0x4
66#define R128_TRIANGLE_FAN 0x5
67#define R128_TRIANGLE_STRIP 0x6
68
69/* Vertex/indirect buffer size
70 */
71#define R128_BUFFER_SIZE 16384
72
73/* Byte offsets for indirect buffer data
74 */
75#define R128_INDEX_PRIM_OFFSET 20
76#define R128_HOSTDATA_BLIT_OFFSET 32
77
78/* Keep these small for testing.
79 */
80#define R128_NR_SAREA_CLIPRECTS 12
81
82/* There are 2 heaps (local/AGP). Each region within a heap is a
83 * minimum of 64k, and there are at most 64 of them per heap.
84 */
85#define R128_LOCAL_TEX_HEAP 0
86#define R128_AGP_TEX_HEAP 1
87#define R128_NR_TEX_HEAPS 2
88#define R128_NR_TEX_REGIONS 64
89#define R128_LOG_TEX_GRANULARITY 16
90
91#define R128_NR_CONTEXT_REGS 12
92
93#define R128_MAX_TEXTURE_LEVELS 11
94#define R128_MAX_TEXTURE_UNITS 2
95
96#endif /* __R128_SAREA_DEFINES__ */
97
98typedef struct {
99 /* Context state - can be written in one large chunk */
100 unsigned int dst_pitch_offset_c;
101 unsigned int dp_gui_master_cntl_c;
102 unsigned int sc_top_left_c;
103 unsigned int sc_bottom_right_c;
104 unsigned int z_offset_c;
105 unsigned int z_pitch_c;
106 unsigned int z_sten_cntl_c;
107 unsigned int tex_cntl_c;
108 unsigned int misc_3d_state_cntl_reg;
109 unsigned int texture_clr_cmp_clr_c;
110 unsigned int texture_clr_cmp_msk_c;
111 unsigned int fog_color_c;
112
113 /* Texture state */
114 unsigned int tex_size_pitch_c;
115 unsigned int constant_color_c;
116
117 /* Setup state */
118 unsigned int pm4_vc_fpu_setup;
119 unsigned int setup_cntl;
120
121 /* Mask state */
122 unsigned int dp_write_mask;
123 unsigned int sten_ref_mask_c;
124 unsigned int plane_3d_mask_c;
125
126 /* Window state */
127 unsigned int window_xy_offset;
128
129 /* Core state */
130 unsigned int scale_3d_cntl;
131} drm_r128_context_regs_t;
132
133/* Setup registers for each texture unit
134 */
135typedef struct {
136 unsigned int tex_cntl;
137 unsigned int tex_combine_cntl;
138 unsigned int tex_size_pitch;
139 unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS];
140 unsigned int tex_border_color;
141} drm_r128_texture_regs_t;
142
143
144typedef struct drm_r128_sarea {
145 /* The channel for communication of state information to the kernel
146 * on firing a vertex buffer.
147 */
148 drm_r128_context_regs_t context_state;
149 drm_r128_texture_regs_t tex_state[R128_MAX_TEXTURE_UNITS];
150 unsigned int dirty;
151 unsigned int vertsize;
152 unsigned int vc_format;
153
154 /* The current cliprects, or a subset thereof.
155 */
156 drm_clip_rect_t boxes[R128_NR_SAREA_CLIPRECTS];
157 unsigned int nbox;
158
159 /* Counters for client-side throttling of rendering clients.
160 */
161 unsigned int last_frame;
162 unsigned int last_dispatch;
163
164 drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
165 unsigned int tex_age[R128_NR_TEX_HEAPS];
166 int ctx_owner;
167 int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */
168 int pfCurrentPage; /* which buffer is being displayed? */
169} drm_r128_sarea_t;
170
171
172/* WARNING: If you change any of these defines, make sure to change the
173 * defines in the Xserver file (xf86drmR128.h)
174 */
175
176/* Rage 128 specific ioctls
177 * The device specific ioctl range is 0x40 to 0x79.
178 */
179#define DRM_R128_INIT 0x00
180#define DRM_R128_CCE_START 0x01
181#define DRM_R128_CCE_STOP 0x02
182#define DRM_R128_CCE_RESET 0x03
183#define DRM_R128_CCE_IDLE 0x04
184/* 0x05 not used */
185#define DRM_R128_RESET 0x06
186#define DRM_R128_SWAP 0x07
187#define DRM_R128_CLEAR 0x08
188#define DRM_R128_VERTEX 0x09
189#define DRM_R128_INDICES 0x0a
190#define DRM_R128_BLIT 0x0b
191#define DRM_R128_DEPTH 0x0c
192#define DRM_R128_STIPPLE 0x0d
193/* 0x0e not used */
194#define DRM_R128_INDIRECT 0x0f
195#define DRM_R128_FULLSCREEN 0x10
196#define DRM_R128_CLEAR2 0x11
197#define DRM_R128_GETPARAM 0x12
198#define DRM_R128_FLIP 0x13
199
200#define DRM_IOCTL_R128_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t)
201#define DRM_IOCTL_R128_CCE_START DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_START)
202#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t)
203#define DRM_IOCTL_R128_CCE_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_RESET)
204#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_IDLE)
205/* 0x05 not used */
206#define DRM_IOCTL_R128_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_RESET)
207#define DRM_IOCTL_R128_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_R128_SWAP)
208#define DRM_IOCTL_R128_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t)
209#define DRM_IOCTL_R128_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t)
210#define DRM_IOCTL_R128_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t)
211#define DRM_IOCTL_R128_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t)
212#define DRM_IOCTL_R128_DEPTH DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t)
213#define DRM_IOCTL_R128_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t)
214/* 0x0e not used */
215#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t)
216#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t)
217#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t)
218#define DRM_IOCTL_R128_GETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t)
219#define DRM_IOCTL_R128_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_R128_FLIP)
220
221typedef struct drm_r128_init {
222 enum {
223 R128_INIT_CCE = 0x01,
224 R128_CLEANUP_CCE = 0x02
225 } func;
226#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
227 int sarea_priv_offset;
228#else
229 unsigned long sarea_priv_offset;
230#endif
231 int is_pci;
232 int cce_mode;
233 int cce_secure;
234 int ring_size;
235 int usec_timeout;
236
237 unsigned int fb_bpp;
238 unsigned int front_offset, front_pitch;
239 unsigned int back_offset, back_pitch;
240 unsigned int depth_bpp;
241 unsigned int depth_offset, depth_pitch;
242 unsigned int span_offset;
243
244#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
245 unsigned int fb_offset;
246 unsigned int mmio_offset;
247 unsigned int ring_offset;
248 unsigned int ring_rptr_offset;
249 unsigned int buffers_offset;
250 unsigned int agp_textures_offset;
251#else
252 unsigned long fb_offset;
253 unsigned long mmio_offset;
254 unsigned long ring_offset;
255 unsigned long ring_rptr_offset;
256 unsigned long buffers_offset;
257 unsigned long agp_textures_offset;
258#endif
259} drm_r128_init_t;
260
261typedef struct drm_r128_cce_stop {
262 int flush;
263 int idle;
264} drm_r128_cce_stop_t;
265
266typedef struct drm_r128_clear {
267 unsigned int flags;
268#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
269 int x, y, w, h;
270#endif
271 unsigned int clear_color;
272 unsigned int clear_depth;
273#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
274 unsigned int color_mask;
275 unsigned int depth_mask;
276#endif
277} drm_r128_clear_t;
278
279typedef struct drm_r128_vertex {
280 int prim;
281 int idx; /* Index of vertex buffer */
282 int count; /* Number of vertices in buffer */
283 int discard; /* Client finished with buffer? */
284} drm_r128_vertex_t;
285
286typedef struct drm_r128_indices {
287 int prim;
288 int idx;
289 int start;
290 int end;
291 int discard; /* Client finished with buffer? */
292} drm_r128_indices_t;
293
294typedef struct drm_r128_blit {
295 int idx;
296 int pitch;
297 int offset;
298 int format;
299 unsigned short x, y;
300 unsigned short width, height;
301} drm_r128_blit_t;
302
303typedef struct drm_r128_depth {
304 enum {
305 R128_WRITE_SPAN = 0x01,
306 R128_WRITE_PIXELS = 0x02,
307 R128_READ_SPAN = 0x03,
308 R128_READ_PIXELS = 0x04
309 } func;
310 int n;
311 int __user *x;
312 int __user *y;
313 unsigned int __user *buffer;
314 unsigned char __user *mask;
315} drm_r128_depth_t;
316
317typedef struct drm_r128_stipple {
318 unsigned int __user *mask;
319} drm_r128_stipple_t;
320
321typedef struct drm_r128_indirect {
322 int idx;
323 int start;
324 int end;
325 int discard;
326} drm_r128_indirect_t;
327
328typedef struct drm_r128_fullscreen {
329 enum {
330 R128_INIT_FULLSCREEN = 0x01,
331 R128_CLEANUP_FULLSCREEN = 0x02
332 } func;
333} drm_r128_fullscreen_t;
334
335/* 2.3: An ioctl to get parameters that aren't available to the 3d
336 * client any other way.
337 */
338#define R128_PARAM_IRQ_NR 1
339
340typedef struct drm_r128_getparam {
341 int param;
342 void __user *value;
343} drm_r128_getparam_t;
344
345#endif
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
new file mode 100644
index 000000000000..ced63810237b
--- /dev/null
+++ b/drivers/char/drm/r128_drv.c
@@ -0,0 +1,122 @@
1/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
2 * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 */
31
32#include <linux/config.h>
33#include "drmP.h"
34#include "drm.h"
35#include "r128_drm.h"
36#include "r128_drv.h"
37
38#include "drm_pciids.h"
39
40static int postinit( struct drm_device *dev, unsigned long flags )
41{
42 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
43 DRIVER_NAME,
44 DRIVER_MAJOR,
45 DRIVER_MINOR,
46 DRIVER_PATCHLEVEL,
47 DRIVER_DATE,
48 dev->primary.minor,
49 pci_pretty_name(dev->pdev)
50 );
51 return 0;
52}
53
54static int version( drm_version_t *version )
55{
56 int len;
57
58 version->version_major = DRIVER_MAJOR;
59 version->version_minor = DRIVER_MINOR;
60 version->version_patchlevel = DRIVER_PATCHLEVEL;
61 DRM_COPY( version->name, DRIVER_NAME );
62 DRM_COPY( version->date, DRIVER_DATE );
63 DRM_COPY( version->desc, DRIVER_DESC );
64 return 0;
65}
66
67static struct pci_device_id pciidlist[] = {
68 r128_PCI_IDS
69};
70
71extern drm_ioctl_desc_t r128_ioctls[];
72extern int r128_max_ioctl;
73
74static struct drm_driver driver = {
75 .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
76 .dev_priv_size = sizeof(drm_r128_buf_priv_t),
77 .prerelease = r128_driver_prerelease,
78 .pretakedown = r128_driver_pretakedown,
79 .vblank_wait = r128_driver_vblank_wait,
80 .irq_preinstall = r128_driver_irq_preinstall,
81 .irq_postinstall = r128_driver_irq_postinstall,
82 .irq_uninstall = r128_driver_irq_uninstall,
83 .irq_handler = r128_driver_irq_handler,
84 .reclaim_buffers = drm_core_reclaim_buffers,
85 .get_map_ofs = drm_core_get_map_ofs,
86 .get_reg_ofs = drm_core_get_reg_ofs,
87 .postinit = postinit,
88 .version = version,
89 .ioctls = r128_ioctls,
90 .dma_ioctl = r128_cce_buffers,
91 .fops = {
92 .owner = THIS_MODULE,
93 .open = drm_open,
94 .release = drm_release,
95 .ioctl = drm_ioctl,
96 .mmap = drm_mmap,
97 .poll = drm_poll,
98 .fasync = drm_fasync,
99 },
100 .pci_driver = {
101 .name = DRIVER_NAME,
102 .id_table = pciidlist,
103 }
104};
105
106static int __init r128_init(void)
107{
108 driver.num_ioctls = r128_max_ioctl;
109 return drm_init(&driver);
110}
111
112static void __exit r128_exit(void)
113{
114 drm_exit(&driver);
115}
116
117module_init(r128_init);
118module_exit(r128_exit);
119
120MODULE_AUTHOR( DRIVER_AUTHOR );
121MODULE_DESCRIPTION( DRIVER_DESC );
122MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
new file mode 100644
index 000000000000..cf1aa5df459e
--- /dev/null
+++ b/drivers/char/drm/r128_drv.h
@@ -0,0 +1,521 @@
1/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
2 * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Kevin E. Martin <martin@valinux.com>
30 * Gareth Hughes <gareth@valinux.com>
31 * Michel D�zer <daenzerm@student.ethz.ch>
32 */
33
34#ifndef __R128_DRV_H__
35#define __R128_DRV_H__
36
37/* General customization:
38 */
39#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
40
41#define DRIVER_NAME "r128"
42#define DRIVER_DESC "ATI Rage 128"
43#define DRIVER_DATE "20030725"
44
45/* Interface history:
46 *
47 * ?? - ??
48 * 2.4 - Add support for ycbcr textures (no new ioctls)
49 * 2.5 - Add FLIP ioctl, disable FULLSCREEN.
50 */
51#define DRIVER_MAJOR 2
52#define DRIVER_MINOR 5
53#define DRIVER_PATCHLEVEL 0
54
55
56#define GET_RING_HEAD(dev_priv) R128_READ( R128_PM4_BUFFER_DL_RPTR )
57
58typedef struct drm_r128_freelist {
59 unsigned int age;
60 drm_buf_t *buf;
61 struct drm_r128_freelist *next;
62 struct drm_r128_freelist *prev;
63} drm_r128_freelist_t;
64
65typedef struct drm_r128_ring_buffer {
66 u32 *start;
67 u32 *end;
68 int size;
69 int size_l2qw;
70
71 u32 tail;
72 u32 tail_mask;
73 int space;
74
75 int high_mark;
76} drm_r128_ring_buffer_t;
77
78typedef struct drm_r128_private {
79 drm_r128_ring_buffer_t ring;
80 drm_r128_sarea_t *sarea_priv;
81
82 int cce_mode;
83 int cce_fifo_size;
84 int cce_running;
85
86 drm_r128_freelist_t *head;
87 drm_r128_freelist_t *tail;
88
89 int usec_timeout;
90 int is_pci;
91 unsigned long phys_pci_gart;
92 dma_addr_t bus_pci_gart;
93 unsigned long cce_buffers_offset;
94
95 atomic_t idle_count;
96
97 int page_flipping;
98 int current_page;
99 u32 crtc_offset;
100 u32 crtc_offset_cntl;
101
102 u32 color_fmt;
103 unsigned int front_offset;
104 unsigned int front_pitch;
105 unsigned int back_offset;
106 unsigned int back_pitch;
107
108 u32 depth_fmt;
109 unsigned int depth_offset;
110 unsigned int depth_pitch;
111 unsigned int span_offset;
112
113 u32 front_pitch_offset_c;
114 u32 back_pitch_offset_c;
115 u32 depth_pitch_offset_c;
116 u32 span_pitch_offset_c;
117
118 drm_local_map_t *sarea;
119 drm_local_map_t *mmio;
120 drm_local_map_t *cce_ring;
121 drm_local_map_t *ring_rptr;
122 drm_local_map_t *agp_textures;
123} drm_r128_private_t;
124
125typedef struct drm_r128_buf_priv {
126 u32 age;
127 int prim;
128 int discard;
129 int dispatched;
130 drm_r128_freelist_t *list_entry;
131} drm_r128_buf_priv_t;
132
133 /* r128_cce.c */
134extern int r128_cce_init( DRM_IOCTL_ARGS );
135extern int r128_cce_start( DRM_IOCTL_ARGS );
136extern int r128_cce_stop( DRM_IOCTL_ARGS );
137extern int r128_cce_reset( DRM_IOCTL_ARGS );
138extern int r128_cce_idle( DRM_IOCTL_ARGS );
139extern int r128_engine_reset( DRM_IOCTL_ARGS );
140extern int r128_fullscreen( DRM_IOCTL_ARGS );
141extern int r128_cce_buffers( DRM_IOCTL_ARGS );
142
143extern void r128_freelist_reset( drm_device_t *dev );
144
145extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
146
147extern int r128_do_cce_idle( drm_r128_private_t *dev_priv );
148extern int r128_do_cleanup_cce( drm_device_t *dev );
149
150extern int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
151
152extern irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS );
153extern void r128_driver_irq_preinstall( drm_device_t *dev );
154extern void r128_driver_irq_postinstall( drm_device_t *dev );
155extern void r128_driver_irq_uninstall( drm_device_t *dev );
156extern void r128_driver_pretakedown(drm_device_t *dev);
157extern void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp);
158
159/* Register definitions, register access macros and drmAddMap constants
160 * for Rage 128 kernel driver.
161 */
162
163#define R128_AUX_SC_CNTL 0x1660
164# define R128_AUX1_SC_EN (1 << 0)
165# define R128_AUX1_SC_MODE_OR (0 << 1)
166# define R128_AUX1_SC_MODE_NAND (1 << 1)
167# define R128_AUX2_SC_EN (1 << 2)
168# define R128_AUX2_SC_MODE_OR (0 << 3)
169# define R128_AUX2_SC_MODE_NAND (1 << 3)
170# define R128_AUX3_SC_EN (1 << 4)
171# define R128_AUX3_SC_MODE_OR (0 << 5)
172# define R128_AUX3_SC_MODE_NAND (1 << 5)
173#define R128_AUX1_SC_LEFT 0x1664
174#define R128_AUX1_SC_RIGHT 0x1668
175#define R128_AUX1_SC_TOP 0x166c
176#define R128_AUX1_SC_BOTTOM 0x1670
177#define R128_AUX2_SC_LEFT 0x1674
178#define R128_AUX2_SC_RIGHT 0x1678
179#define R128_AUX2_SC_TOP 0x167c
180#define R128_AUX2_SC_BOTTOM 0x1680
181#define R128_AUX3_SC_LEFT 0x1684
182#define R128_AUX3_SC_RIGHT 0x1688
183#define R128_AUX3_SC_TOP 0x168c
184#define R128_AUX3_SC_BOTTOM 0x1690
185
186#define R128_BRUSH_DATA0 0x1480
187#define R128_BUS_CNTL 0x0030
188# define R128_BUS_MASTER_DIS (1 << 6)
189
190#define R128_CLOCK_CNTL_INDEX 0x0008
191#define R128_CLOCK_CNTL_DATA 0x000c
192# define R128_PLL_WR_EN (1 << 7)
193#define R128_CONSTANT_COLOR_C 0x1d34
194#define R128_CRTC_OFFSET 0x0224
195#define R128_CRTC_OFFSET_CNTL 0x0228
196# define R128_CRTC_OFFSET_FLIP_CNTL (1 << 16)
197
198#define R128_DP_GUI_MASTER_CNTL 0x146c
199# define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
200# define R128_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
201# define R128_GMC_BRUSH_SOLID_COLOR (13 << 4)
202# define R128_GMC_BRUSH_NONE (15 << 4)
203# define R128_GMC_DST_16BPP (4 << 8)
204# define R128_GMC_DST_24BPP (5 << 8)
205# define R128_GMC_DST_32BPP (6 << 8)
206# define R128_GMC_DST_DATATYPE_SHIFT 8
207# define R128_GMC_SRC_DATATYPE_COLOR (3 << 12)
208# define R128_DP_SRC_SOURCE_MEMORY (2 << 24)
209# define R128_DP_SRC_SOURCE_HOST_DATA (3 << 24)
210# define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28)
211# define R128_GMC_AUX_CLIP_DIS (1 << 29)
212# define R128_GMC_WR_MSK_DIS (1 << 30)
213# define R128_ROP3_S 0x00cc0000
214# define R128_ROP3_P 0x00f00000
215#define R128_DP_WRITE_MASK 0x16cc
216#define R128_DST_PITCH_OFFSET_C 0x1c80
217# define R128_DST_TILE (1 << 31)
218
219#define R128_GEN_INT_CNTL 0x0040
220# define R128_CRTC_VBLANK_INT_EN (1 << 0)
221#define R128_GEN_INT_STATUS 0x0044
222# define R128_CRTC_VBLANK_INT (1 << 0)
223# define R128_CRTC_VBLANK_INT_AK (1 << 0)
224#define R128_GEN_RESET_CNTL 0x00f0
225# define R128_SOFT_RESET_GUI (1 << 0)
226
227#define R128_GUI_SCRATCH_REG0 0x15e0
228#define R128_GUI_SCRATCH_REG1 0x15e4
229#define R128_GUI_SCRATCH_REG2 0x15e8
230#define R128_GUI_SCRATCH_REG3 0x15ec
231#define R128_GUI_SCRATCH_REG4 0x15f0
232#define R128_GUI_SCRATCH_REG5 0x15f4
233
234#define R128_GUI_STAT 0x1740
235# define R128_GUI_FIFOCNT_MASK 0x0fff
236# define R128_GUI_ACTIVE (1 << 31)
237
238#define R128_MCLK_CNTL 0x000f
239# define R128_FORCE_GCP (1 << 16)
240# define R128_FORCE_PIPE3D_CP (1 << 17)
241# define R128_FORCE_RCP (1 << 18)
242
243#define R128_PC_GUI_CTLSTAT 0x1748
244#define R128_PC_NGUI_CTLSTAT 0x0184
245# define R128_PC_FLUSH_GUI (3 << 0)
246# define R128_PC_RI_GUI (1 << 2)
247# define R128_PC_FLUSH_ALL 0x00ff
248# define R128_PC_BUSY (1 << 31)
249
250#define R128_PCI_GART_PAGE 0x017c
251#define R128_PRIM_TEX_CNTL_C 0x1cb0
252
253#define R128_SCALE_3D_CNTL 0x1a00
254#define R128_SEC_TEX_CNTL_C 0x1d00
255#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c
256#define R128_SETUP_CNTL 0x1bc4
257#define R128_STEN_REF_MASK_C 0x1d40
258
259#define R128_TEX_CNTL_C 0x1c9c
260# define R128_TEX_CACHE_FLUSH (1 << 23)
261
262#define R128_WAIT_UNTIL 0x1720
263# define R128_EVENT_CRTC_OFFSET (1 << 0)
264#define R128_WINDOW_XY_OFFSET 0x1bcc
265
266
267/* CCE registers
268 */
269#define R128_PM4_BUFFER_OFFSET 0x0700
270#define R128_PM4_BUFFER_CNTL 0x0704
271# define R128_PM4_MASK (15 << 28)
272# define R128_PM4_NONPM4 (0 << 28)
273# define R128_PM4_192PIO (1 << 28)
274# define R128_PM4_192BM (2 << 28)
275# define R128_PM4_128PIO_64INDBM (3 << 28)
276# define R128_PM4_128BM_64INDBM (4 << 28)
277# define R128_PM4_64PIO_128INDBM (5 << 28)
278# define R128_PM4_64BM_128INDBM (6 << 28)
279# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28)
280# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28)
281# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
282# define R128_PM4_BUFFER_CNTL_NOUPDATE (1 << 27)
283
284#define R128_PM4_BUFFER_WM_CNTL 0x0708
285# define R128_WMA_SHIFT 0
286# define R128_WMB_SHIFT 8
287# define R128_WMC_SHIFT 16
288# define R128_WB_WM_SHIFT 24
289
290#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c
291#define R128_PM4_BUFFER_DL_RPTR 0x0710
292#define R128_PM4_BUFFER_DL_WPTR 0x0714
293# define R128_PM4_BUFFER_DL_DONE (1 << 31)
294
295#define R128_PM4_VC_FPU_SETUP 0x071c
296
297#define R128_PM4_IW_INDOFF 0x0738
298#define R128_PM4_IW_INDSIZE 0x073c
299
300#define R128_PM4_STAT 0x07b8
301# define R128_PM4_FIFOCNT_MASK 0x0fff
302# define R128_PM4_BUSY (1 << 16)
303# define R128_PM4_GUI_ACTIVE (1 << 31)
304
305#define R128_PM4_MICROCODE_ADDR 0x07d4
306#define R128_PM4_MICROCODE_RADDR 0x07d8
307#define R128_PM4_MICROCODE_DATAH 0x07dc
308#define R128_PM4_MICROCODE_DATAL 0x07e0
309
310#define R128_PM4_BUFFER_ADDR 0x07f0
311#define R128_PM4_MICRO_CNTL 0x07fc
312# define R128_PM4_MICRO_FREERUN (1 << 30)
313
314#define R128_PM4_FIFO_DATA_EVEN 0x1000
315#define R128_PM4_FIFO_DATA_ODD 0x1004
316
317
318/* CCE command packets
319 */
320#define R128_CCE_PACKET0 0x00000000
321#define R128_CCE_PACKET1 0x40000000
322#define R128_CCE_PACKET2 0x80000000
323#define R128_CCE_PACKET3 0xC0000000
324# define R128_CNTL_HOSTDATA_BLT 0x00009400
325# define R128_CNTL_PAINT_MULTI 0x00009A00
326# define R128_CNTL_BITBLT_MULTI 0x00009B00
327# define R128_3D_RNDR_GEN_INDX_PRIM 0x00002300
328
329#define R128_CCE_PACKET_MASK 0xC0000000
330#define R128_CCE_PACKET_COUNT_MASK 0x3fff0000
331#define R128_CCE_PACKET0_REG_MASK 0x000007ff
332#define R128_CCE_PACKET1_REG0_MASK 0x000007ff
333#define R128_CCE_PACKET1_REG1_MASK 0x003ff800
334
335#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000
336#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001
337#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002
338#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003
339#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004
340#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005
341#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006
342#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007
343#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010
344#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020
345#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030
346#define R128_CCE_VC_CNTL_NUM_SHIFT 16
347
348#define R128_DATATYPE_VQ 0
349#define R128_DATATYPE_CI4 1
350#define R128_DATATYPE_CI8 2
351#define R128_DATATYPE_ARGB1555 3
352#define R128_DATATYPE_RGB565 4
353#define R128_DATATYPE_RGB888 5
354#define R128_DATATYPE_ARGB8888 6
355#define R128_DATATYPE_RGB332 7
356#define R128_DATATYPE_Y8 8
357#define R128_DATATYPE_RGB8 9
358#define R128_DATATYPE_CI16 10
359#define R128_DATATYPE_YVYU422 11
360#define R128_DATATYPE_VYUY422 12
361#define R128_DATATYPE_AYUV444 14
362#define R128_DATATYPE_ARGB4444 15
363
364/* Constants */
365#define R128_AGP_OFFSET 0x02000000
366
367#define R128_WATERMARK_L 16
368#define R128_WATERMARK_M 8
369#define R128_WATERMARK_N 8
370#define R128_WATERMARK_K 128
371
372#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */
373
374#define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0
375#define R128_LAST_DISPATCH_REG R128_GUI_SCRATCH_REG1
376#define R128_MAX_VB_AGE 0x7fffffff
377#define R128_MAX_VB_VERTS (0xffff)
378
379#define R128_RING_HIGH_MARK 128
380
381#define R128_PERFORMANCE_BOXES 0
382
383#define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
384#define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
385#define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) )
386#define R128_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) )
387
388#define R128_WRITE_PLL(addr,val) \
389do { \
390 R128_WRITE8(R128_CLOCK_CNTL_INDEX, \
391 ((addr) & 0x1f) | R128_PLL_WR_EN); \
392 R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \
393} while (0)
394
395
396#define CCE_PACKET0( reg, n ) (R128_CCE_PACKET0 | \
397 ((n) << 16) | ((reg) >> 2))
398#define CCE_PACKET1( reg0, reg1 ) (R128_CCE_PACKET1 | \
399 (((reg1) >> 2) << 11) | ((reg0) >> 2))
400#define CCE_PACKET2() (R128_CCE_PACKET2)
401#define CCE_PACKET3( pkt, n ) (R128_CCE_PACKET3 | \
402 (pkt) | ((n) << 16))
403
404
405static __inline__ void
406r128_update_ring_snapshot( drm_r128_private_t *dev_priv )
407{
408 drm_r128_ring_buffer_t *ring = &dev_priv->ring;
409 ring->space = (GET_RING_HEAD( dev_priv ) - ring->tail) * sizeof(u32);
410 if ( ring->space <= 0 )
411 ring->space += ring->size;
412}
413
414/* ================================================================
415 * Misc helper macros
416 */
417
418#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
419do { \
420 drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \
421 if ( ring->space < ring->high_mark ) { \
422 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { \
423 r128_update_ring_snapshot( dev_priv ); \
424 if ( ring->space >= ring->high_mark ) \
425 goto __ring_space_done; \
426 DRM_UDELAY(1); \
427 } \
428 DRM_ERROR( "ring space check failed!\n" ); \
429 return DRM_ERR(EBUSY); \
430 } \
431 __ring_space_done: \
432 ; \
433} while (0)
434
435#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \
436do { \
437 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; \
438 if ( sarea_priv->last_dispatch >= R128_MAX_VB_AGE ) { \
439 int __ret = r128_do_cce_idle( dev_priv ); \
440 if ( __ret ) return __ret; \
441 sarea_priv->last_dispatch = 0; \
442 r128_freelist_reset( dev ); \
443 } \
444} while (0)
445
446#define R128_WAIT_UNTIL_PAGE_FLIPPED() do { \
447 OUT_RING( CCE_PACKET0( R128_WAIT_UNTIL, 0 ) ); \
448 OUT_RING( R128_EVENT_CRTC_OFFSET ); \
449} while (0)
450
451
452/* ================================================================
453 * Ring control
454 */
455
456#define R128_VERBOSE 0
457
458#define RING_LOCALS \
459 int write, _nr; unsigned int tail_mask; volatile u32 *ring;
460
461#define BEGIN_RING( n ) do { \
462 if ( R128_VERBOSE ) { \
463 DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
464 (n), __FUNCTION__ ); \
465 } \
466 if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
467 COMMIT_RING(); \
468 r128_wait_ring( dev_priv, (n) * sizeof(u32) ); \
469 } \
470 _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \
471 ring = dev_priv->ring.start; \
472 write = dev_priv->ring.tail; \
473 tail_mask = dev_priv->ring.tail_mask; \
474} while (0)
475
476/* You can set this to zero if you want. If the card locks up, you'll
477 * need to keep this set. It works around a bug in early revs of the
478 * Rage 128 chipset, where the CCE would read 32 dwords past the end of
479 * the ring buffer before wrapping around.
480 */
481#define R128_BROKEN_CCE 1
482
483#define ADVANCE_RING() do { \
484 if ( R128_VERBOSE ) { \
485 DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \
486 write, dev_priv->ring.tail ); \
487 } \
488 if ( R128_BROKEN_CCE && write < 32 ) { \
489 memcpy( dev_priv->ring.end, \
490 dev_priv->ring.start, \
491 write * sizeof(u32) ); \
492 } \
493 if (((dev_priv->ring.tail + _nr) & tail_mask) != write) { \
494 DRM_ERROR( \
495 "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \
496 ((dev_priv->ring.tail + _nr) & tail_mask), \
497 write, __LINE__); \
498 } else \
499 dev_priv->ring.tail = write; \
500} while (0)
501
502#define COMMIT_RING() do { \
503 if ( R128_VERBOSE ) { \
504 DRM_INFO( "COMMIT_RING() tail=0x%06x\n", \
505 dev_priv->ring.tail ); \
506 } \
507 DRM_MEMORYBARRIER(); \
508 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail ); \
509 R128_READ( R128_PM4_BUFFER_DL_WPTR ); \
510} while (0)
511
512#define OUT_RING( x ) do { \
513 if ( R128_VERBOSE ) { \
514 DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \
515 (unsigned int)(x), write ); \
516 } \
517 ring[write++] = cpu_to_le32( x ); \
518 write &= tail_mask; \
519} while (0)
520
521#endif /* __R128_DRV_H__ */
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
new file mode 100644
index 000000000000..643a30785fe5
--- /dev/null
+++ b/drivers/char/drm/r128_irq.c
@@ -0,0 +1,102 @@
1/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*-
2 *
3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 *
5 * The Weather Channel (TM) funded Tungsten Graphics to develop the
6 * initial release of the Radeon 8500 driver under the XFree86 license.
7 * This notice must be preserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Eric Anholt <anholt@FreeBSD.org>
31 */
32
33#include "drmP.h"
34#include "drm.h"
35#include "r128_drm.h"
36#include "r128_drv.h"
37
38irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS )
39{
40 drm_device_t *dev = (drm_device_t *) arg;
41 drm_r128_private_t *dev_priv =
42 (drm_r128_private_t *)dev->dev_private;
43 int status;
44
45 status = R128_READ( R128_GEN_INT_STATUS );
46
47 /* VBLANK interrupt */
48 if ( status & R128_CRTC_VBLANK_INT ) {
49 R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK );
50 atomic_inc(&dev->vbl_received);
51 DRM_WAKEUP(&dev->vbl_queue);
52 drm_vbl_send_signals( dev );
53 return IRQ_HANDLED;
54 }
55 return IRQ_NONE;
56}
57
58int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
59{
60 unsigned int cur_vblank;
61 int ret = 0;
62
63 /* Assume that the user has missed the current sequence number
64 * by about a day rather than she wants to wait for years
65 * using vertical blanks...
66 */
67 DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ,
68 ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
69 - *sequence ) <= (1<<23) ) );
70
71 *sequence = cur_vblank;
72
73 return ret;
74}
75
76void r128_driver_irq_preinstall( drm_device_t *dev ) {
77 drm_r128_private_t *dev_priv =
78 (drm_r128_private_t *)dev->dev_private;
79
80 /* Disable *all* interrupts */
81 R128_WRITE( R128_GEN_INT_CNTL, 0 );
82 /* Clear vblank bit if it's already high */
83 R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK );
84}
85
86void r128_driver_irq_postinstall( drm_device_t *dev ) {
87 drm_r128_private_t *dev_priv =
88 (drm_r128_private_t *)dev->dev_private;
89
90 /* Turn on VBL interrupt */
91 R128_WRITE( R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN );
92}
93
94void r128_driver_irq_uninstall( drm_device_t *dev ) {
95 drm_r128_private_t *dev_priv =
96 (drm_r128_private_t *)dev->dev_private;
97 if (!dev_priv)
98 return;
99
100 /* Disable *all* interrupts */
101 R128_WRITE( R128_GEN_INT_CNTL, 0 );
102}
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
new file mode 100644
index 000000000000..38b3cbd0bbba
--- /dev/null
+++ b/drivers/char/drm/r128_state.c
@@ -0,0 +1,1732 @@
1/* r128_state.c -- State support for r128 -*- linux-c -*-
2 * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
3 *
4 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Gareth Hughes <gareth@valinux.com>
28 */
29
30#include "drmP.h"
31#include "drm.h"
32#include "r128_drm.h"
33#include "r128_drv.h"
34
35
36/* ================================================================
37 * CCE hardware state programming functions
38 */
39
40static void r128_emit_clip_rects( drm_r128_private_t *dev_priv,
41 drm_clip_rect_t *boxes, int count )
42{
43 u32 aux_sc_cntl = 0x00000000;
44 RING_LOCALS;
45 DRM_DEBUG( " %s\n", __FUNCTION__ );
46
47 BEGIN_RING( (count < 3? count: 3) * 5 + 2 );
48
49 if ( count >= 1 ) {
50 OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
51 OUT_RING( boxes[0].x1 );
52 OUT_RING( boxes[0].x2 - 1 );
53 OUT_RING( boxes[0].y1 );
54 OUT_RING( boxes[0].y2 - 1 );
55
56 aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
57 }
58 if ( count >= 2 ) {
59 OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT, 3 ) );
60 OUT_RING( boxes[1].x1 );
61 OUT_RING( boxes[1].x2 - 1 );
62 OUT_RING( boxes[1].y1 );
63 OUT_RING( boxes[1].y2 - 1 );
64
65 aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
66 }
67 if ( count >= 3 ) {
68 OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT, 3 ) );
69 OUT_RING( boxes[2].x1 );
70 OUT_RING( boxes[2].x2 - 1 );
71 OUT_RING( boxes[2].y1 );
72 OUT_RING( boxes[2].y2 - 1 );
73
74 aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
75 }
76
77 OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL, 0 ) );
78 OUT_RING( aux_sc_cntl );
79
80 ADVANCE_RING();
81}
82
83static __inline__ void r128_emit_core( drm_r128_private_t *dev_priv )
84{
85 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
86 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
87 RING_LOCALS;
88 DRM_DEBUG( " %s\n", __FUNCTION__ );
89
90 BEGIN_RING( 2 );
91
92 OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL, 0 ) );
93 OUT_RING( ctx->scale_3d_cntl );
94
95 ADVANCE_RING();
96}
97
98static __inline__ void r128_emit_context( drm_r128_private_t *dev_priv )
99{
100 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
101 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
102 RING_LOCALS;
103 DRM_DEBUG( " %s\n", __FUNCTION__ );
104
105 BEGIN_RING( 13 );
106
107 OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C, 11 ) );
108 OUT_RING( ctx->dst_pitch_offset_c );
109 OUT_RING( ctx->dp_gui_master_cntl_c );
110 OUT_RING( ctx->sc_top_left_c );
111 OUT_RING( ctx->sc_bottom_right_c );
112 OUT_RING( ctx->z_offset_c );
113 OUT_RING( ctx->z_pitch_c );
114 OUT_RING( ctx->z_sten_cntl_c );
115 OUT_RING( ctx->tex_cntl_c );
116 OUT_RING( ctx->misc_3d_state_cntl_reg );
117 OUT_RING( ctx->texture_clr_cmp_clr_c );
118 OUT_RING( ctx->texture_clr_cmp_msk_c );
119 OUT_RING( ctx->fog_color_c );
120
121 ADVANCE_RING();
122}
123
124static __inline__ void r128_emit_setup( drm_r128_private_t *dev_priv )
125{
126 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
127 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
128 RING_LOCALS;
129 DRM_DEBUG( " %s\n", __FUNCTION__ );
130
131 BEGIN_RING( 3 );
132
133 OUT_RING( CCE_PACKET1( R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP ) );
134 OUT_RING( ctx->setup_cntl );
135 OUT_RING( ctx->pm4_vc_fpu_setup );
136
137 ADVANCE_RING();
138}
139
140static __inline__ void r128_emit_masks( drm_r128_private_t *dev_priv )
141{
142 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
143 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
144 RING_LOCALS;
145 DRM_DEBUG( " %s\n", __FUNCTION__ );
146
147 BEGIN_RING( 5 );
148
149 OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
150 OUT_RING( ctx->dp_write_mask );
151
152 OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C, 1 ) );
153 OUT_RING( ctx->sten_ref_mask_c );
154 OUT_RING( ctx->plane_3d_mask_c );
155
156 ADVANCE_RING();
157}
158
159static __inline__ void r128_emit_window( drm_r128_private_t *dev_priv )
160{
161 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
162 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
163 RING_LOCALS;
164 DRM_DEBUG( " %s\n", __FUNCTION__ );
165
166 BEGIN_RING( 2 );
167
168 OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET, 0 ) );
169 OUT_RING( ctx->window_xy_offset );
170
171 ADVANCE_RING();
172}
173
174static __inline__ void r128_emit_tex0( drm_r128_private_t *dev_priv )
175{
176 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
177 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
178 drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
179 int i;
180 RING_LOCALS;
181 DRM_DEBUG( " %s\n", __FUNCTION__ );
182
183 BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS );
184
185 OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C,
186 2 + R128_MAX_TEXTURE_LEVELS ) );
187 OUT_RING( tex->tex_cntl );
188 OUT_RING( tex->tex_combine_cntl );
189 OUT_RING( ctx->tex_size_pitch_c );
190 for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
191 OUT_RING( tex->tex_offset[i] );
192 }
193
194 OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C, 1 ) );
195 OUT_RING( ctx->constant_color_c );
196 OUT_RING( tex->tex_border_color );
197
198 ADVANCE_RING();
199}
200
201static __inline__ void r128_emit_tex1( drm_r128_private_t *dev_priv )
202{
203 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
204 drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
205 int i;
206 RING_LOCALS;
207 DRM_DEBUG( " %s\n", __FUNCTION__ );
208
209 BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS );
210
211 OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C,
212 1 + R128_MAX_TEXTURE_LEVELS ) );
213 OUT_RING( tex->tex_cntl );
214 OUT_RING( tex->tex_combine_cntl );
215 for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
216 OUT_RING( tex->tex_offset[i] );
217 }
218
219 OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C, 0 ) );
220 OUT_RING( tex->tex_border_color );
221
222 ADVANCE_RING();
223}
224
225static __inline__ void r128_emit_state( drm_r128_private_t *dev_priv )
226{
227 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
228 unsigned int dirty = sarea_priv->dirty;
229
230 DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
231
232 if ( dirty & R128_UPLOAD_CORE ) {
233 r128_emit_core( dev_priv );
234 sarea_priv->dirty &= ~R128_UPLOAD_CORE;
235 }
236
237 if ( dirty & R128_UPLOAD_CONTEXT ) {
238 r128_emit_context( dev_priv );
239 sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
240 }
241
242 if ( dirty & R128_UPLOAD_SETUP ) {
243 r128_emit_setup( dev_priv );
244 sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
245 }
246
247 if ( dirty & R128_UPLOAD_MASKS ) {
248 r128_emit_masks( dev_priv );
249 sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
250 }
251
252 if ( dirty & R128_UPLOAD_WINDOW ) {
253 r128_emit_window( dev_priv );
254 sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
255 }
256
257 if ( dirty & R128_UPLOAD_TEX0 ) {
258 r128_emit_tex0( dev_priv );
259 sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
260 }
261
262 if ( dirty & R128_UPLOAD_TEX1 ) {
263 r128_emit_tex1( dev_priv );
264 sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
265 }
266
267 /* Turn off the texture cache flushing */
268 sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
269
270 sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
271}
272
273
274#if R128_PERFORMANCE_BOXES
275/* ================================================================
276 * Performance monitoring functions
277 */
278
279static void r128_clear_box( drm_r128_private_t *dev_priv,
280 int x, int y, int w, int h,
281 int r, int g, int b )
282{
283 u32 pitch, offset;
284 u32 fb_bpp, color;
285 RING_LOCALS;
286
287 switch ( dev_priv->fb_bpp ) {
288 case 16:
289 fb_bpp = R128_GMC_DST_16BPP;
290 color = (((r & 0xf8) << 8) |
291 ((g & 0xfc) << 3) |
292 ((b & 0xf8) >> 3));
293 break;
294 case 24:
295 fb_bpp = R128_GMC_DST_24BPP;
296 color = ((r << 16) | (g << 8) | b);
297 break;
298 case 32:
299 fb_bpp = R128_GMC_DST_32BPP;
300 color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
301 break;
302 default:
303 return;
304 }
305
306 offset = dev_priv->back_offset;
307 pitch = dev_priv->back_pitch >> 3;
308
309 BEGIN_RING( 6 );
310
311 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
312 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
313 R128_GMC_BRUSH_SOLID_COLOR |
314 fb_bpp |
315 R128_GMC_SRC_DATATYPE_COLOR |
316 R128_ROP3_P |
317 R128_GMC_CLR_CMP_CNTL_DIS |
318 R128_GMC_AUX_CLIP_DIS );
319
320 OUT_RING( (pitch << 21) | (offset >> 5) );
321 OUT_RING( color );
322
323 OUT_RING( (x << 16) | y );
324 OUT_RING( (w << 16) | h );
325
326 ADVANCE_RING();
327}
328
329static void r128_cce_performance_boxes( drm_r128_private_t *dev_priv )
330{
331 if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
332 r128_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
333 } else {
334 atomic_set( &dev_priv->idle_count, 0 );
335 }
336}
337
338#endif
339
340
341/* ================================================================
342 * CCE command dispatch functions
343 */
344
345static void r128_print_dirty( const char *msg, unsigned int flags )
346{
347 DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
348 msg,
349 flags,
350 (flags & R128_UPLOAD_CORE) ? "core, " : "",
351 (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
352 (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
353 (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
354 (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
355 (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
356 (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
357 (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
358 (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
359}
360
361static void r128_cce_dispatch_clear( drm_device_t *dev,
362 drm_r128_clear_t *clear )
363{
364 drm_r128_private_t *dev_priv = dev->dev_private;
365 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
366 int nbox = sarea_priv->nbox;
367 drm_clip_rect_t *pbox = sarea_priv->boxes;
368 unsigned int flags = clear->flags;
369 int i;
370 RING_LOCALS;
371 DRM_DEBUG( "%s\n", __FUNCTION__ );
372
373 if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
374 unsigned int tmp = flags;
375
376 flags &= ~(R128_FRONT | R128_BACK);
377 if ( tmp & R128_FRONT ) flags |= R128_BACK;
378 if ( tmp & R128_BACK ) flags |= R128_FRONT;
379 }
380
381 for ( i = 0 ; i < nbox ; i++ ) {
382 int x = pbox[i].x1;
383 int y = pbox[i].y1;
384 int w = pbox[i].x2 - x;
385 int h = pbox[i].y2 - y;
386
387 DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
388 pbox[i].x1, pbox[i].y1, pbox[i].x2,
389 pbox[i].y2, flags );
390
391 if ( flags & (R128_FRONT | R128_BACK) ) {
392 BEGIN_RING( 2 );
393
394 OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
395 OUT_RING( clear->color_mask );
396
397 ADVANCE_RING();
398 }
399
400 if ( flags & R128_FRONT ) {
401 BEGIN_RING( 6 );
402
403 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
404 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
405 R128_GMC_BRUSH_SOLID_COLOR |
406 (dev_priv->color_fmt << 8) |
407 R128_GMC_SRC_DATATYPE_COLOR |
408 R128_ROP3_P |
409 R128_GMC_CLR_CMP_CNTL_DIS |
410 R128_GMC_AUX_CLIP_DIS );
411
412 OUT_RING( dev_priv->front_pitch_offset_c );
413 OUT_RING( clear->clear_color );
414
415 OUT_RING( (x << 16) | y );
416 OUT_RING( (w << 16) | h );
417
418 ADVANCE_RING();
419 }
420
421 if ( flags & R128_BACK ) {
422 BEGIN_RING( 6 );
423
424 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
425 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
426 R128_GMC_BRUSH_SOLID_COLOR |
427 (dev_priv->color_fmt << 8) |
428 R128_GMC_SRC_DATATYPE_COLOR |
429 R128_ROP3_P |
430 R128_GMC_CLR_CMP_CNTL_DIS |
431 R128_GMC_AUX_CLIP_DIS );
432
433 OUT_RING( dev_priv->back_pitch_offset_c );
434 OUT_RING( clear->clear_color );
435
436 OUT_RING( (x << 16) | y );
437 OUT_RING( (w << 16) | h );
438
439 ADVANCE_RING();
440 }
441
442 if ( flags & R128_DEPTH ) {
443 BEGIN_RING( 6 );
444
445 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
446 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
447 R128_GMC_BRUSH_SOLID_COLOR |
448 (dev_priv->depth_fmt << 8) |
449 R128_GMC_SRC_DATATYPE_COLOR |
450 R128_ROP3_P |
451 R128_GMC_CLR_CMP_CNTL_DIS |
452 R128_GMC_AUX_CLIP_DIS |
453 R128_GMC_WR_MSK_DIS );
454
455 OUT_RING( dev_priv->depth_pitch_offset_c );
456 OUT_RING( clear->clear_depth );
457
458 OUT_RING( (x << 16) | y );
459 OUT_RING( (w << 16) | h );
460
461 ADVANCE_RING();
462 }
463 }
464}
465
466static void r128_cce_dispatch_swap( drm_device_t *dev )
467{
468 drm_r128_private_t *dev_priv = dev->dev_private;
469 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
470 int nbox = sarea_priv->nbox;
471 drm_clip_rect_t *pbox = sarea_priv->boxes;
472 int i;
473 RING_LOCALS;
474 DRM_DEBUG( "%s\n", __FUNCTION__ );
475
476#if R128_PERFORMANCE_BOXES
477 /* Do some trivial performance monitoring...
478 */
479 r128_cce_performance_boxes( dev_priv );
480#endif
481
482 for ( i = 0 ; i < nbox ; i++ ) {
483 int x = pbox[i].x1;
484 int y = pbox[i].y1;
485 int w = pbox[i].x2 - x;
486 int h = pbox[i].y2 - y;
487
488 BEGIN_RING( 7 );
489
490 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
491 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
492 R128_GMC_DST_PITCH_OFFSET_CNTL |
493 R128_GMC_BRUSH_NONE |
494 (dev_priv->color_fmt << 8) |
495 R128_GMC_SRC_DATATYPE_COLOR |
496 R128_ROP3_S |
497 R128_DP_SRC_SOURCE_MEMORY |
498 R128_GMC_CLR_CMP_CNTL_DIS |
499 R128_GMC_AUX_CLIP_DIS |
500 R128_GMC_WR_MSK_DIS );
501
502 /* Make this work even if front & back are flipped:
503 */
504 if (dev_priv->current_page == 0) {
505 OUT_RING( dev_priv->back_pitch_offset_c );
506 OUT_RING( dev_priv->front_pitch_offset_c );
507 }
508 else {
509 OUT_RING( dev_priv->front_pitch_offset_c );
510 OUT_RING( dev_priv->back_pitch_offset_c );
511 }
512
513 OUT_RING( (x << 16) | y );
514 OUT_RING( (x << 16) | y );
515 OUT_RING( (w << 16) | h );
516
517 ADVANCE_RING();
518 }
519
520 /* Increment the frame counter. The client-side 3D driver must
521 * throttle the framerate by waiting for this value before
522 * performing the swapbuffer ioctl.
523 */
524 dev_priv->sarea_priv->last_frame++;
525
526 BEGIN_RING( 2 );
527
528 OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
529 OUT_RING( dev_priv->sarea_priv->last_frame );
530
531 ADVANCE_RING();
532}
533
534static void r128_cce_dispatch_flip( drm_device_t *dev )
535{
536 drm_r128_private_t *dev_priv = dev->dev_private;
537 RING_LOCALS;
538 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
539 __FUNCTION__,
540 dev_priv->current_page,
541 dev_priv->sarea_priv->pfCurrentPage);
542
543#if R128_PERFORMANCE_BOXES
544 /* Do some trivial performance monitoring...
545 */
546 r128_cce_performance_boxes( dev_priv );
547#endif
548
549 BEGIN_RING( 4 );
550
551 R128_WAIT_UNTIL_PAGE_FLIPPED();
552 OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 0 ) );
553
554 if ( dev_priv->current_page == 0 ) {
555 OUT_RING( dev_priv->back_offset );
556 } else {
557 OUT_RING( dev_priv->front_offset );
558 }
559
560 ADVANCE_RING();
561
562 /* Increment the frame counter. The client-side 3D driver must
563 * throttle the framerate by waiting for this value before
564 * performing the swapbuffer ioctl.
565 */
566 dev_priv->sarea_priv->last_frame++;
567 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
568 1 - dev_priv->current_page;
569
570 BEGIN_RING( 2 );
571
572 OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
573 OUT_RING( dev_priv->sarea_priv->last_frame );
574
575 ADVANCE_RING();
576}
577
578static void r128_cce_dispatch_vertex( drm_device_t *dev,
579 drm_buf_t *buf )
580{
581 drm_r128_private_t *dev_priv = dev->dev_private;
582 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
583 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
584 int format = sarea_priv->vc_format;
585 int offset = buf->bus_address;
586 int size = buf->used;
587 int prim = buf_priv->prim;
588 int i = 0;
589 RING_LOCALS;
590 DRM_DEBUG( "buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox );
591
592 if ( 0 )
593 r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
594
595 if ( buf->used ) {
596 buf_priv->dispatched = 1;
597
598 if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
599 r128_emit_state( dev_priv );
600 }
601
602 do {
603 /* Emit the next set of up to three cliprects */
604 if ( i < sarea_priv->nbox ) {
605 r128_emit_clip_rects( dev_priv,
606 &sarea_priv->boxes[i],
607 sarea_priv->nbox - i );
608 }
609
610 /* Emit the vertex buffer rendering commands */
611 BEGIN_RING( 5 );
612
613 OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) );
614 OUT_RING( offset );
615 OUT_RING( size );
616 OUT_RING( format );
617 OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
618 (size << R128_CCE_VC_CNTL_NUM_SHIFT) );
619
620 ADVANCE_RING();
621
622 i += 3;
623 } while ( i < sarea_priv->nbox );
624 }
625
626 if ( buf_priv->discard ) {
627 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
628
629 /* Emit the vertex buffer age */
630 BEGIN_RING( 2 );
631
632 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
633 OUT_RING( buf_priv->age );
634
635 ADVANCE_RING();
636
637 buf->pending = 1;
638 buf->used = 0;
639 /* FIXME: Check dispatched field */
640 buf_priv->dispatched = 0;
641 }
642
643 dev_priv->sarea_priv->last_dispatch++;
644
645 sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
646 sarea_priv->nbox = 0;
647}
648
649static void r128_cce_dispatch_indirect( drm_device_t *dev,
650 drm_buf_t *buf,
651 int start, int end )
652{
653 drm_r128_private_t *dev_priv = dev->dev_private;
654 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
655 RING_LOCALS;
656 DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
657 buf->idx, start, end );
658
659 if ( start != end ) {
660 int offset = buf->bus_address + start;
661 int dwords = (end - start + 3) / sizeof(u32);
662
663 /* Indirect buffer data must be an even number of
664 * dwords, so if we've been given an odd number we must
665 * pad the data with a Type-2 CCE packet.
666 */
667 if ( dwords & 1 ) {
668 u32 *data = (u32 *)
669 ((char *)dev->agp_buffer_map->handle
670 + buf->offset + start);
671 data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
672 }
673
674 buf_priv->dispatched = 1;
675
676 /* Fire off the indirect buffer */
677 BEGIN_RING( 3 );
678
679 OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) );
680 OUT_RING( offset );
681 OUT_RING( dwords );
682
683 ADVANCE_RING();
684 }
685
686 if ( buf_priv->discard ) {
687 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
688
689 /* Emit the indirect buffer age */
690 BEGIN_RING( 2 );
691
692 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
693 OUT_RING( buf_priv->age );
694
695 ADVANCE_RING();
696
697 buf->pending = 1;
698 buf->used = 0;
699 /* FIXME: Check dispatched field */
700 buf_priv->dispatched = 0;
701 }
702
703 dev_priv->sarea_priv->last_dispatch++;
704}
705
706static void r128_cce_dispatch_indices( drm_device_t *dev,
707 drm_buf_t *buf,
708 int start, int end,
709 int count )
710{
711 drm_r128_private_t *dev_priv = dev->dev_private;
712 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
713 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
714 int format = sarea_priv->vc_format;
715 int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;
716 int prim = buf_priv->prim;
717 u32 *data;
718 int dwords;
719 int i = 0;
720 RING_LOCALS;
721 DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
722
723 if ( 0 )
724 r128_print_dirty( "dispatch_indices", sarea_priv->dirty );
725
726 if ( start != end ) {
727 buf_priv->dispatched = 1;
728
729 if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
730 r128_emit_state( dev_priv );
731 }
732
733 dwords = (end - start + 3) / sizeof(u32);
734
735 data = (u32 *)((char *)dev->agp_buffer_map->handle
736 + buf->offset + start);
737
738 data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
739 dwords-2 ) );
740
741 data[1] = cpu_to_le32( offset );
742 data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
743 data[3] = cpu_to_le32( format );
744 data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
745 (count << 16)) );
746
747 if ( count & 0x1 ) {
748#ifdef __LITTLE_ENDIAN
749 data[dwords-1] &= 0x0000ffff;
750#else
751 data[dwords-1] &= 0xffff0000;
752#endif
753 }
754
755 do {
756 /* Emit the next set of up to three cliprects */
757 if ( i < sarea_priv->nbox ) {
758 r128_emit_clip_rects( dev_priv,
759 &sarea_priv->boxes[i],
760 sarea_priv->nbox - i );
761 }
762
763 r128_cce_dispatch_indirect( dev, buf, start, end );
764
765 i += 3;
766 } while ( i < sarea_priv->nbox );
767 }
768
769 if ( buf_priv->discard ) {
770 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
771
772 /* Emit the vertex buffer age */
773 BEGIN_RING( 2 );
774
775 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
776 OUT_RING( buf_priv->age );
777
778 ADVANCE_RING();
779
780 buf->pending = 1;
781 /* FIXME: Check dispatched field */
782 buf_priv->dispatched = 0;
783 }
784
785 dev_priv->sarea_priv->last_dispatch++;
786
787 sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
788 sarea_priv->nbox = 0;
789}
790
791static int r128_cce_dispatch_blit( DRMFILE filp,
792 drm_device_t *dev,
793 drm_r128_blit_t *blit )
794{
795 drm_r128_private_t *dev_priv = dev->dev_private;
796 drm_device_dma_t *dma = dev->dma;
797 drm_buf_t *buf;
798 drm_r128_buf_priv_t *buf_priv;
799 u32 *data;
800 int dword_shift, dwords;
801 RING_LOCALS;
802 DRM_DEBUG( "\n" );
803
804 /* The compiler won't optimize away a division by a variable,
805 * even if the only legal values are powers of two. Thus, we'll
806 * use a shift instead.
807 */
808 switch ( blit->format ) {
809 case R128_DATATYPE_ARGB8888:
810 dword_shift = 0;
811 break;
812 case R128_DATATYPE_ARGB1555:
813 case R128_DATATYPE_RGB565:
814 case R128_DATATYPE_ARGB4444:
815 case R128_DATATYPE_YVYU422:
816 case R128_DATATYPE_VYUY422:
817 dword_shift = 1;
818 break;
819 case R128_DATATYPE_CI8:
820 case R128_DATATYPE_RGB8:
821 dword_shift = 2;
822 break;
823 default:
824 DRM_ERROR( "invalid blit format %d\n", blit->format );
825 return DRM_ERR(EINVAL);
826 }
827
828 /* Flush the pixel cache, and mark the contents as Read Invalid.
829 * This ensures no pixel data gets mixed up with the texture
830 * data from the host data blit, otherwise part of the texture
831 * image may be corrupted.
832 */
833 BEGIN_RING( 2 );
834
835 OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
836 OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI );
837
838 ADVANCE_RING();
839
840 /* Dispatch the indirect buffer.
841 */
842 buf = dma->buflist[blit->idx];
843 buf_priv = buf->dev_private;
844
845 if ( buf->filp != filp ) {
846 DRM_ERROR( "process %d using buffer owned by %p\n",
847 DRM_CURRENTPID, buf->filp );
848 return DRM_ERR(EINVAL);
849 }
850 if ( buf->pending ) {
851 DRM_ERROR( "sending pending buffer %d\n", blit->idx );
852 return DRM_ERR(EINVAL);
853 }
854
855 buf_priv->discard = 1;
856
857 dwords = (blit->width * blit->height) >> dword_shift;
858
859 data = (u32 *)((char *)dev->agp_buffer_map->handle + buf->offset);
860
861 data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
862 data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
863 R128_GMC_BRUSH_NONE |
864 (blit->format << 8) |
865 R128_GMC_SRC_DATATYPE_COLOR |
866 R128_ROP3_S |
867 R128_DP_SRC_SOURCE_HOST_DATA |
868 R128_GMC_CLR_CMP_CNTL_DIS |
869 R128_GMC_AUX_CLIP_DIS |
870 R128_GMC_WR_MSK_DIS) );
871
872 data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
873 data[3] = cpu_to_le32( 0xffffffff );
874 data[4] = cpu_to_le32( 0xffffffff );
875 data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
876 data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
877 data[7] = cpu_to_le32( dwords );
878
879 buf->used = (dwords + 8) * sizeof(u32);
880
881 r128_cce_dispatch_indirect( dev, buf, 0, buf->used );
882
883 /* Flush the pixel cache after the blit completes. This ensures
884 * the texture data is written out to memory before rendering
885 * continues.
886 */
887 BEGIN_RING( 2 );
888
889 OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
890 OUT_RING( R128_PC_FLUSH_GUI );
891
892 ADVANCE_RING();
893
894 return 0;
895}
896
897
898/* ================================================================
899 * Tiled depth buffer management
900 *
901 * FIXME: These should all set the destination write mask for when we
902 * have hardware stencil support.
903 */
904
905static int r128_cce_dispatch_write_span( drm_device_t *dev,
906 drm_r128_depth_t *depth )
907{
908 drm_r128_private_t *dev_priv = dev->dev_private;
909 int count, x, y;
910 u32 *buffer;
911 u8 *mask;
912 int i, buffer_size, mask_size;
913 RING_LOCALS;
914 DRM_DEBUG( "\n" );
915
916 count = depth->n;
917 if (count > 4096 || count <= 0)
918 return DRM_ERR(EMSGSIZE);
919
920 if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
921 return DRM_ERR(EFAULT);
922 }
923 if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
924 return DRM_ERR(EFAULT);
925 }
926
927 buffer_size = depth->n * sizeof(u32);
928 buffer = drm_alloc( buffer_size, DRM_MEM_BUFS );
929 if ( buffer == NULL )
930 return DRM_ERR(ENOMEM);
931 if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
932 drm_free( buffer, buffer_size, DRM_MEM_BUFS);
933 return DRM_ERR(EFAULT);
934 }
935
936 mask_size = depth->n * sizeof(u8);
937 if ( depth->mask ) {
938 mask = drm_alloc( mask_size, DRM_MEM_BUFS );
939 if ( mask == NULL ) {
940 drm_free( buffer, buffer_size, DRM_MEM_BUFS );
941 return DRM_ERR(ENOMEM);
942 }
943 if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
944 drm_free( buffer, buffer_size, DRM_MEM_BUFS );
945 drm_free( mask, mask_size, DRM_MEM_BUFS );
946 return DRM_ERR(EFAULT);
947 }
948
949 for ( i = 0 ; i < count ; i++, x++ ) {
950 if ( mask[i] ) {
951 BEGIN_RING( 6 );
952
953 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
954 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
955 R128_GMC_BRUSH_SOLID_COLOR |
956 (dev_priv->depth_fmt << 8) |
957 R128_GMC_SRC_DATATYPE_COLOR |
958 R128_ROP3_P |
959 R128_GMC_CLR_CMP_CNTL_DIS |
960 R128_GMC_WR_MSK_DIS );
961
962 OUT_RING( dev_priv->depth_pitch_offset_c );
963 OUT_RING( buffer[i] );
964
965 OUT_RING( (x << 16) | y );
966 OUT_RING( (1 << 16) | 1 );
967
968 ADVANCE_RING();
969 }
970 }
971
972 drm_free( mask, mask_size, DRM_MEM_BUFS );
973 } else {
974 for ( i = 0 ; i < count ; i++, x++ ) {
975 BEGIN_RING( 6 );
976
977 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
978 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
979 R128_GMC_BRUSH_SOLID_COLOR |
980 (dev_priv->depth_fmt << 8) |
981 R128_GMC_SRC_DATATYPE_COLOR |
982 R128_ROP3_P |
983 R128_GMC_CLR_CMP_CNTL_DIS |
984 R128_GMC_WR_MSK_DIS );
985
986 OUT_RING( dev_priv->depth_pitch_offset_c );
987 OUT_RING( buffer[i] );
988
989 OUT_RING( (x << 16) | y );
990 OUT_RING( (1 << 16) | 1 );
991
992 ADVANCE_RING();
993 }
994 }
995
996 drm_free( buffer, buffer_size, DRM_MEM_BUFS );
997
998 return 0;
999}
1000
1001static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
1002 drm_r128_depth_t *depth )
1003{
1004 drm_r128_private_t *dev_priv = dev->dev_private;
1005 int count, *x, *y;
1006 u32 *buffer;
1007 u8 *mask;
1008 int i, xbuf_size, ybuf_size, buffer_size, mask_size;
1009 RING_LOCALS;
1010 DRM_DEBUG( "\n" );
1011
1012 count = depth->n;
1013 if (count > 4096 || count <= 0)
1014 return DRM_ERR(EMSGSIZE);
1015
1016 xbuf_size = count * sizeof(*x);
1017 ybuf_size = count * sizeof(*y);
1018 x = drm_alloc( xbuf_size, DRM_MEM_BUFS );
1019 if ( x == NULL ) {
1020 return DRM_ERR(ENOMEM);
1021 }
1022 y = drm_alloc( ybuf_size, DRM_MEM_BUFS );
1023 if ( y == NULL ) {
1024 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1025 return DRM_ERR(ENOMEM);
1026 }
1027 if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
1028 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1029 drm_free( y, ybuf_size, DRM_MEM_BUFS );
1030 return DRM_ERR(EFAULT);
1031 }
1032 if ( DRM_COPY_FROM_USER( y, depth->y, xbuf_size ) ) {
1033 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1034 drm_free( y, ybuf_size, DRM_MEM_BUFS );
1035 return DRM_ERR(EFAULT);
1036 }
1037
1038 buffer_size = depth->n * sizeof(u32);
1039 buffer = drm_alloc( buffer_size, DRM_MEM_BUFS );
1040 if ( buffer == NULL ) {
1041 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1042 drm_free( y, ybuf_size, DRM_MEM_BUFS );
1043 return DRM_ERR(ENOMEM);
1044 }
1045 if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
1046 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1047 drm_free( y, ybuf_size, DRM_MEM_BUFS );
1048 drm_free( buffer, buffer_size, DRM_MEM_BUFS );
1049 return DRM_ERR(EFAULT);
1050 }
1051
1052 if ( depth->mask ) {
1053 mask_size = depth->n * sizeof(u8);
1054 mask = drm_alloc( mask_size, DRM_MEM_BUFS );
1055 if ( mask == NULL ) {
1056 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1057 drm_free( y, ybuf_size, DRM_MEM_BUFS );
1058 drm_free( buffer, buffer_size, DRM_MEM_BUFS );
1059 return DRM_ERR(ENOMEM);
1060 }
1061 if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
1062 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1063 drm_free( y, ybuf_size, DRM_MEM_BUFS );
1064 drm_free( buffer, buffer_size, DRM_MEM_BUFS );
1065 drm_free( mask, mask_size, DRM_MEM_BUFS );
1066 return DRM_ERR(EFAULT);
1067 }
1068
1069 for ( i = 0 ; i < count ; i++ ) {
1070 if ( mask[i] ) {
1071 BEGIN_RING( 6 );
1072
1073 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
1074 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
1075 R128_GMC_BRUSH_SOLID_COLOR |
1076 (dev_priv->depth_fmt << 8) |
1077 R128_GMC_SRC_DATATYPE_COLOR |
1078 R128_ROP3_P |
1079 R128_GMC_CLR_CMP_CNTL_DIS |
1080 R128_GMC_WR_MSK_DIS );
1081
1082 OUT_RING( dev_priv->depth_pitch_offset_c );
1083 OUT_RING( buffer[i] );
1084
1085 OUT_RING( (x[i] << 16) | y[i] );
1086 OUT_RING( (1 << 16) | 1 );
1087
1088 ADVANCE_RING();
1089 }
1090 }
1091
1092 drm_free( mask, mask_size, DRM_MEM_BUFS );
1093 } else {
1094 for ( i = 0 ; i < count ; i++ ) {
1095 BEGIN_RING( 6 );
1096
1097 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
1098 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
1099 R128_GMC_BRUSH_SOLID_COLOR |
1100 (dev_priv->depth_fmt << 8) |
1101 R128_GMC_SRC_DATATYPE_COLOR |
1102 R128_ROP3_P |
1103 R128_GMC_CLR_CMP_CNTL_DIS |
1104 R128_GMC_WR_MSK_DIS );
1105
1106 OUT_RING( dev_priv->depth_pitch_offset_c );
1107 OUT_RING( buffer[i] );
1108
1109 OUT_RING( (x[i] << 16) | y[i] );
1110 OUT_RING( (1 << 16) | 1 );
1111
1112 ADVANCE_RING();
1113 }
1114 }
1115
1116 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1117 drm_free( y, ybuf_size, DRM_MEM_BUFS );
1118 drm_free( buffer, buffer_size, DRM_MEM_BUFS );
1119
1120 return 0;
1121}
1122
1123static int r128_cce_dispatch_read_span( drm_device_t *dev,
1124 drm_r128_depth_t *depth )
1125{
1126 drm_r128_private_t *dev_priv = dev->dev_private;
1127 int count, x, y;
1128 RING_LOCALS;
1129 DRM_DEBUG( "\n" );
1130
1131 count = depth->n;
1132 if (count > 4096 || count <= 0)
1133 return DRM_ERR(EMSGSIZE);
1134
1135 if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
1136 return DRM_ERR(EFAULT);
1137 }
1138 if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
1139 return DRM_ERR(EFAULT);
1140 }
1141
1142 BEGIN_RING( 7 );
1143
1144 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
1145 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
1146 R128_GMC_DST_PITCH_OFFSET_CNTL |
1147 R128_GMC_BRUSH_NONE |
1148 (dev_priv->depth_fmt << 8) |
1149 R128_GMC_SRC_DATATYPE_COLOR |
1150 R128_ROP3_S |
1151 R128_DP_SRC_SOURCE_MEMORY |
1152 R128_GMC_CLR_CMP_CNTL_DIS |
1153 R128_GMC_WR_MSK_DIS );
1154
1155 OUT_RING( dev_priv->depth_pitch_offset_c );
1156 OUT_RING( dev_priv->span_pitch_offset_c );
1157
1158 OUT_RING( (x << 16) | y );
1159 OUT_RING( (0 << 16) | 0 );
1160 OUT_RING( (count << 16) | 1 );
1161
1162 ADVANCE_RING();
1163
1164 return 0;
1165}
1166
1167static int r128_cce_dispatch_read_pixels( drm_device_t *dev,
1168 drm_r128_depth_t *depth )
1169{
1170 drm_r128_private_t *dev_priv = dev->dev_private;
1171 int count, *x, *y;
1172 int i, xbuf_size, ybuf_size;
1173 RING_LOCALS;
1174 DRM_DEBUG( "%s\n", __FUNCTION__ );
1175
1176 count = depth->n;
1177 if (count > 4096 || count <= 0)
1178 return DRM_ERR(EMSGSIZE);
1179
1180 if ( count > dev_priv->depth_pitch ) {
1181 count = dev_priv->depth_pitch;
1182 }
1183
1184 xbuf_size = count * sizeof(*x);
1185 ybuf_size = count * sizeof(*y);
1186 x = drm_alloc( xbuf_size, DRM_MEM_BUFS );
1187 if ( x == NULL ) {
1188 return DRM_ERR(ENOMEM);
1189 }
1190 y = drm_alloc( ybuf_size, DRM_MEM_BUFS );
1191 if ( y == NULL ) {
1192 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1193 return DRM_ERR(ENOMEM);
1194 }
1195 if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
1196 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1197 drm_free( y, ybuf_size, DRM_MEM_BUFS );
1198 return DRM_ERR(EFAULT);
1199 }
1200 if ( DRM_COPY_FROM_USER( y, depth->y, ybuf_size ) ) {
1201 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1202 drm_free( y, ybuf_size, DRM_MEM_BUFS );
1203 return DRM_ERR(EFAULT);
1204 }
1205
1206 for ( i = 0 ; i < count ; i++ ) {
1207 BEGIN_RING( 7 );
1208
1209 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
1210 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
1211 R128_GMC_DST_PITCH_OFFSET_CNTL |
1212 R128_GMC_BRUSH_NONE |
1213 (dev_priv->depth_fmt << 8) |
1214 R128_GMC_SRC_DATATYPE_COLOR |
1215 R128_ROP3_S |
1216 R128_DP_SRC_SOURCE_MEMORY |
1217 R128_GMC_CLR_CMP_CNTL_DIS |
1218 R128_GMC_WR_MSK_DIS );
1219
1220 OUT_RING( dev_priv->depth_pitch_offset_c );
1221 OUT_RING( dev_priv->span_pitch_offset_c );
1222
1223 OUT_RING( (x[i] << 16) | y[i] );
1224 OUT_RING( (i << 16) | 0 );
1225 OUT_RING( (1 << 16) | 1 );
1226
1227 ADVANCE_RING();
1228 }
1229
1230 drm_free( x, xbuf_size, DRM_MEM_BUFS );
1231 drm_free( y, ybuf_size, DRM_MEM_BUFS );
1232
1233 return 0;
1234}
1235
1236
1237/* ================================================================
1238 * Polygon stipple
1239 */
1240
1241static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple )
1242{
1243 drm_r128_private_t *dev_priv = dev->dev_private;
1244 int i;
1245 RING_LOCALS;
1246 DRM_DEBUG( "%s\n", __FUNCTION__ );
1247
1248 BEGIN_RING( 33 );
1249
1250 OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
1251 for ( i = 0 ; i < 32 ; i++ ) {
1252 OUT_RING( stipple[i] );
1253 }
1254
1255 ADVANCE_RING();
1256}
1257
1258
1259/* ================================================================
1260 * IOCTL functions
1261 */
1262
1263static int r128_cce_clear( DRM_IOCTL_ARGS )
1264{
1265 DRM_DEVICE;
1266 drm_r128_private_t *dev_priv = dev->dev_private;
1267 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1268 drm_r128_clear_t clear;
1269 DRM_DEBUG( "\n" );
1270
1271 LOCK_TEST_WITH_RETURN( dev, filp );
1272
1273 DRM_COPY_FROM_USER_IOCTL( clear, (drm_r128_clear_t __user *) data,
1274 sizeof(clear) );
1275
1276 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1277
1278 if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
1279 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1280
1281 r128_cce_dispatch_clear( dev, &clear );
1282 COMMIT_RING();
1283
1284 /* Make sure we restore the 3D state next time.
1285 */
1286 dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
1287
1288 return 0;
1289}
1290
1291static int r128_do_init_pageflip( drm_device_t *dev )
1292{
1293 drm_r128_private_t *dev_priv = dev->dev_private;
1294 DRM_DEBUG( "\n" );
1295
1296 dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET );
1297 dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL );
1298
1299 R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset );
1300 R128_WRITE( R128_CRTC_OFFSET_CNTL,
1301 dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL );
1302
1303 dev_priv->page_flipping = 1;
1304 dev_priv->current_page = 0;
1305 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
1306
1307 return 0;
1308}
1309
1310int r128_do_cleanup_pageflip( drm_device_t *dev )
1311{
1312 drm_r128_private_t *dev_priv = dev->dev_private;
1313 DRM_DEBUG( "\n" );
1314
1315 R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset );
1316 R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
1317
1318 if (dev_priv->current_page != 0) {
1319 r128_cce_dispatch_flip( dev );
1320 COMMIT_RING();
1321 }
1322
1323 dev_priv->page_flipping = 0;
1324 return 0;
1325}
1326
1327/* Swapping and flipping are different operations, need different ioctls.
1328 * They can & should be intermixed to support multiple 3d windows.
1329 */
1330
1331static int r128_cce_flip( DRM_IOCTL_ARGS )
1332{
1333 DRM_DEVICE;
1334 drm_r128_private_t *dev_priv = dev->dev_private;
1335 DRM_DEBUG( "%s\n", __FUNCTION__ );
1336
1337 LOCK_TEST_WITH_RETURN( dev, filp );
1338
1339 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1340
1341 if (!dev_priv->page_flipping)
1342 r128_do_init_pageflip( dev );
1343
1344 r128_cce_dispatch_flip( dev );
1345
1346 COMMIT_RING();
1347 return 0;
1348}
1349
1350static int r128_cce_swap( DRM_IOCTL_ARGS )
1351{
1352 DRM_DEVICE;
1353 drm_r128_private_t *dev_priv = dev->dev_private;
1354 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1355 DRM_DEBUG( "%s\n", __FUNCTION__ );
1356
1357 LOCK_TEST_WITH_RETURN( dev, filp );
1358
1359 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1360
1361 if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
1362 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1363
1364 r128_cce_dispatch_swap( dev );
1365 dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
1366 R128_UPLOAD_MASKS);
1367
1368 COMMIT_RING();
1369 return 0;
1370}
1371
1372static int r128_cce_vertex( DRM_IOCTL_ARGS )
1373{
1374 DRM_DEVICE;
1375 drm_r128_private_t *dev_priv = dev->dev_private;
1376 drm_device_dma_t *dma = dev->dma;
1377 drm_buf_t *buf;
1378 drm_r128_buf_priv_t *buf_priv;
1379 drm_r128_vertex_t vertex;
1380
1381 LOCK_TEST_WITH_RETURN( dev, filp );
1382
1383 if ( !dev_priv ) {
1384 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1385 return DRM_ERR(EINVAL);
1386 }
1387
1388 DRM_COPY_FROM_USER_IOCTL( vertex, (drm_r128_vertex_t __user *) data,
1389 sizeof(vertex) );
1390
1391 DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
1392 DRM_CURRENTPID,
1393 vertex.idx, vertex.count, vertex.discard );
1394
1395 if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
1396 DRM_ERROR( "buffer index %d (of %d max)\n",
1397 vertex.idx, dma->buf_count - 1 );
1398 return DRM_ERR(EINVAL);
1399 }
1400 if ( vertex.prim < 0 ||
1401 vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
1402 DRM_ERROR( "buffer prim %d\n", vertex.prim );
1403 return DRM_ERR(EINVAL);
1404 }
1405
1406 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1407 VB_AGE_TEST_WITH_RETURN( dev_priv );
1408
1409 buf = dma->buflist[vertex.idx];
1410 buf_priv = buf->dev_private;
1411
1412 if ( buf->filp != filp ) {
1413 DRM_ERROR( "process %d using buffer owned by %p\n",
1414 DRM_CURRENTPID, buf->filp );
1415 return DRM_ERR(EINVAL);
1416 }
1417 if ( buf->pending ) {
1418 DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
1419 return DRM_ERR(EINVAL);
1420 }
1421
1422 buf->used = vertex.count;
1423 buf_priv->prim = vertex.prim;
1424 buf_priv->discard = vertex.discard;
1425
1426 r128_cce_dispatch_vertex( dev, buf );
1427
1428 COMMIT_RING();
1429 return 0;
1430}
1431
1432static int r128_cce_indices( DRM_IOCTL_ARGS )
1433{
1434 DRM_DEVICE;
1435 drm_r128_private_t *dev_priv = dev->dev_private;
1436 drm_device_dma_t *dma = dev->dma;
1437 drm_buf_t *buf;
1438 drm_r128_buf_priv_t *buf_priv;
1439 drm_r128_indices_t elts;
1440 int count;
1441
1442 LOCK_TEST_WITH_RETURN( dev, filp );
1443
1444 if ( !dev_priv ) {
1445 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1446 return DRM_ERR(EINVAL);
1447 }
1448
1449 DRM_COPY_FROM_USER_IOCTL( elts, (drm_r128_indices_t __user *) data,
1450 sizeof(elts) );
1451
1452 DRM_DEBUG( "pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
1453 elts.idx, elts.start, elts.end, elts.discard );
1454
1455 if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
1456 DRM_ERROR( "buffer index %d (of %d max)\n",
1457 elts.idx, dma->buf_count - 1 );
1458 return DRM_ERR(EINVAL);
1459 }
1460 if ( elts.prim < 0 ||
1461 elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
1462 DRM_ERROR( "buffer prim %d\n", elts.prim );
1463 return DRM_ERR(EINVAL);
1464 }
1465
1466 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1467 VB_AGE_TEST_WITH_RETURN( dev_priv );
1468
1469 buf = dma->buflist[elts.idx];
1470 buf_priv = buf->dev_private;
1471
1472 if ( buf->filp != filp ) {
1473 DRM_ERROR( "process %d using buffer owned by %p\n",
1474 DRM_CURRENTPID, buf->filp );
1475 return DRM_ERR(EINVAL);
1476 }
1477 if ( buf->pending ) {
1478 DRM_ERROR( "sending pending buffer %d\n", elts.idx );
1479 return DRM_ERR(EINVAL);
1480 }
1481
1482 count = (elts.end - elts.start) / sizeof(u16);
1483 elts.start -= R128_INDEX_PRIM_OFFSET;
1484
1485 if ( elts.start & 0x7 ) {
1486 DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
1487 return DRM_ERR(EINVAL);
1488 }
1489 if ( elts.start < buf->used ) {
1490 DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
1491 return DRM_ERR(EINVAL);
1492 }
1493
1494 buf->used = elts.end;
1495 buf_priv->prim = elts.prim;
1496 buf_priv->discard = elts.discard;
1497
1498 r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
1499
1500 COMMIT_RING();
1501 return 0;
1502}
1503
1504static int r128_cce_blit( DRM_IOCTL_ARGS )
1505{
1506 DRM_DEVICE;
1507 drm_device_dma_t *dma = dev->dma;
1508 drm_r128_private_t *dev_priv = dev->dev_private;
1509 drm_r128_blit_t blit;
1510 int ret;
1511
1512 LOCK_TEST_WITH_RETURN( dev, filp );
1513
1514 DRM_COPY_FROM_USER_IOCTL( blit, (drm_r128_blit_t __user *) data,
1515 sizeof(blit) );
1516
1517 DRM_DEBUG( "pid=%d index=%d\n", DRM_CURRENTPID, blit.idx );
1518
1519 if ( blit.idx < 0 || blit.idx >= dma->buf_count ) {
1520 DRM_ERROR( "buffer index %d (of %d max)\n",
1521 blit.idx, dma->buf_count - 1 );
1522 return DRM_ERR(EINVAL);
1523 }
1524
1525 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1526 VB_AGE_TEST_WITH_RETURN( dev_priv );
1527
1528 ret = r128_cce_dispatch_blit( filp, dev, &blit );
1529
1530 COMMIT_RING();
1531 return ret;
1532}
1533
1534static int r128_cce_depth( DRM_IOCTL_ARGS )
1535{
1536 DRM_DEVICE;
1537 drm_r128_private_t *dev_priv = dev->dev_private;
1538 drm_r128_depth_t depth;
1539 int ret;
1540
1541 LOCK_TEST_WITH_RETURN( dev, filp );
1542
1543 DRM_COPY_FROM_USER_IOCTL( depth, (drm_r128_depth_t __user *) data,
1544 sizeof(depth) );
1545
1546 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1547
1548 ret = DRM_ERR(EINVAL);
1549 switch ( depth.func ) {
1550 case R128_WRITE_SPAN:
1551 ret = r128_cce_dispatch_write_span( dev, &depth );
1552 case R128_WRITE_PIXELS:
1553 ret = r128_cce_dispatch_write_pixels( dev, &depth );
1554 case R128_READ_SPAN:
1555 ret = r128_cce_dispatch_read_span( dev, &depth );
1556 case R128_READ_PIXELS:
1557 ret = r128_cce_dispatch_read_pixels( dev, &depth );
1558 }
1559
1560 COMMIT_RING();
1561 return ret;
1562}
1563
1564static int r128_cce_stipple( DRM_IOCTL_ARGS )
1565{
1566 DRM_DEVICE;
1567 drm_r128_private_t *dev_priv = dev->dev_private;
1568 drm_r128_stipple_t stipple;
1569 u32 mask[32];
1570
1571 LOCK_TEST_WITH_RETURN( dev, filp );
1572
1573 DRM_COPY_FROM_USER_IOCTL( stipple, (drm_r128_stipple_t __user *) data,
1574 sizeof(stipple) );
1575
1576 if ( DRM_COPY_FROM_USER( &mask, stipple.mask,
1577 32 * sizeof(u32) ) )
1578 return DRM_ERR( EFAULT );
1579
1580 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1581
1582 r128_cce_dispatch_stipple( dev, mask );
1583
1584 COMMIT_RING();
1585 return 0;
1586}
1587
1588static int r128_cce_indirect( DRM_IOCTL_ARGS )
1589{
1590 DRM_DEVICE;
1591 drm_r128_private_t *dev_priv = dev->dev_private;
1592 drm_device_dma_t *dma = dev->dma;
1593 drm_buf_t *buf;
1594 drm_r128_buf_priv_t *buf_priv;
1595 drm_r128_indirect_t indirect;
1596#if 0
1597 RING_LOCALS;
1598#endif
1599
1600 LOCK_TEST_WITH_RETURN( dev, filp );
1601
1602 if ( !dev_priv ) {
1603 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1604 return DRM_ERR(EINVAL);
1605 }
1606
1607 DRM_COPY_FROM_USER_IOCTL( indirect, (drm_r128_indirect_t __user *) data,
1608 sizeof(indirect) );
1609
1610 DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
1611 indirect.idx, indirect.start,
1612 indirect.end, indirect.discard );
1613
1614 if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
1615 DRM_ERROR( "buffer index %d (of %d max)\n",
1616 indirect.idx, dma->buf_count - 1 );
1617 return DRM_ERR(EINVAL);
1618 }
1619
1620 buf = dma->buflist[indirect.idx];
1621 buf_priv = buf->dev_private;
1622
1623 if ( buf->filp != filp ) {
1624 DRM_ERROR( "process %d using buffer owned by %p\n",
1625 DRM_CURRENTPID, buf->filp );
1626 return DRM_ERR(EINVAL);
1627 }
1628 if ( buf->pending ) {
1629 DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
1630 return DRM_ERR(EINVAL);
1631 }
1632
1633 if ( indirect.start < buf->used ) {
1634 DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
1635 indirect.start, buf->used );
1636 return DRM_ERR(EINVAL);
1637 }
1638
1639 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1640 VB_AGE_TEST_WITH_RETURN( dev_priv );
1641
1642 buf->used = indirect.end;
1643 buf_priv->discard = indirect.discard;
1644
1645#if 0
1646 /* Wait for the 3D stream to idle before the indirect buffer
1647 * containing 2D acceleration commands is processed.
1648 */
1649 BEGIN_RING( 2 );
1650 RADEON_WAIT_UNTIL_3D_IDLE();
1651 ADVANCE_RING();
1652#endif
1653
1654 /* Dispatch the indirect buffer full of commands from the
1655 * X server. This is insecure and is thus only available to
1656 * privileged clients.
1657 */
1658 r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
1659
1660 COMMIT_RING();
1661 return 0;
1662}
1663
1664static int r128_getparam( DRM_IOCTL_ARGS )
1665{
1666 DRM_DEVICE;
1667 drm_r128_private_t *dev_priv = dev->dev_private;
1668 drm_r128_getparam_t param;
1669 int value;
1670
1671 if ( !dev_priv ) {
1672 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1673 return DRM_ERR(EINVAL);
1674 }
1675
1676 DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t __user *)data,
1677 sizeof(param) );
1678
1679 DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
1680
1681 switch( param.param ) {
1682 case R128_PARAM_IRQ_NR:
1683 value = dev->irq;
1684 break;
1685 default:
1686 return DRM_ERR(EINVAL);
1687 }
1688
1689 if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
1690 DRM_ERROR( "copy_to_user\n" );
1691 return DRM_ERR(EFAULT);
1692 }
1693
1694 return 0;
1695}
1696
1697void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp)
1698{
1699 if ( dev->dev_private ) {
1700 drm_r128_private_t *dev_priv = dev->dev_private;
1701 if ( dev_priv->page_flipping ) {
1702 r128_do_cleanup_pageflip( dev );
1703 }
1704 }
1705}
1706
1707void r128_driver_pretakedown(drm_device_t *dev)
1708{
1709 r128_do_cleanup_cce( dev );
1710}
1711
1712drm_ioctl_desc_t r128_ioctls[] = {
1713 [DRM_IOCTL_NR(DRM_R128_INIT)] = { r128_cce_init, 1, 1 },
1714 [DRM_IOCTL_NR(DRM_R128_CCE_START)] = { r128_cce_start, 1, 1 },
1715 [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 },
1716 [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 },
1717 [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 },
1718 [DRM_IOCTL_NR(DRM_R128_RESET)] = { r128_engine_reset, 1, 0 },
1719 [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = { r128_fullscreen, 1, 0 },
1720 [DRM_IOCTL_NR(DRM_R128_SWAP)] = { r128_cce_swap, 1, 0 },
1721 [DRM_IOCTL_NR(DRM_R128_FLIP)] = { r128_cce_flip, 1, 0 },
1722 [DRM_IOCTL_NR(DRM_R128_CLEAR)] = { r128_cce_clear, 1, 0 },
1723 [DRM_IOCTL_NR(DRM_R128_VERTEX)] = { r128_cce_vertex, 1, 0 },
1724 [DRM_IOCTL_NR(DRM_R128_INDICES)] = { r128_cce_indices, 1, 0 },
1725 [DRM_IOCTL_NR(DRM_R128_BLIT)] = { r128_cce_blit, 1, 0 },
1726 [DRM_IOCTL_NR(DRM_R128_DEPTH)] = { r128_cce_depth, 1, 0 },
1727 [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 },
1728 [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 },
1729 [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = { r128_getparam, 1, 0 },
1730};
1731
1732int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
new file mode 100644
index 000000000000..20bcf872b348
--- /dev/null
+++ b/drivers/char/drm/radeon_cp.c
@@ -0,0 +1,2061 @@
1/* radeon_cp.c -- CP support for Radeon -*- linux-c -*-
2 *
3 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
4 * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Kevin E. Martin <martin@valinux.com>
28 * Gareth Hughes <gareth@valinux.com>
29 */
30
31#include "drmP.h"
32#include "drm.h"
33#include "radeon_drm.h"
34#include "radeon_drv.h"
35
36#define RADEON_FIFO_DEBUG 0
37
38static int radeon_do_cleanup_cp( drm_device_t *dev );
39
40/* CP microcode (from ATI) */
41static u32 R200_cp_microcode[][2] = {
42 { 0x21007000, 0000000000 },
43 { 0x20007000, 0000000000 },
44 { 0x000000ab, 0x00000004 },
45 { 0x000000af, 0x00000004 },
46 { 0x66544a49, 0000000000 },
47 { 0x49494174, 0000000000 },
48 { 0x54517d83, 0000000000 },
49 { 0x498d8b64, 0000000000 },
50 { 0x49494949, 0000000000 },
51 { 0x49da493c, 0000000000 },
52 { 0x49989898, 0000000000 },
53 { 0xd34949d5, 0000000000 },
54 { 0x9dc90e11, 0000000000 },
55 { 0xce9b9b9b, 0000000000 },
56 { 0x000f0000, 0x00000016 },
57 { 0x352e232c, 0000000000 },
58 { 0x00000013, 0x00000004 },
59 { 0x000f0000, 0x00000016 },
60 { 0x352e272c, 0000000000 },
61 { 0x000f0001, 0x00000016 },
62 { 0x3239362f, 0000000000 },
63 { 0x000077ef, 0x00000002 },
64 { 0x00061000, 0x00000002 },
65 { 0x00000020, 0x0000001a },
66 { 0x00004000, 0x0000001e },
67 { 0x00061000, 0x00000002 },
68 { 0x00000020, 0x0000001a },
69 { 0x00004000, 0x0000001e },
70 { 0x00061000, 0x00000002 },
71 { 0x00000020, 0x0000001a },
72 { 0x00004000, 0x0000001e },
73 { 0x00000016, 0x00000004 },
74 { 0x0003802a, 0x00000002 },
75 { 0x040067e0, 0x00000002 },
76 { 0x00000016, 0x00000004 },
77 { 0x000077e0, 0x00000002 },
78 { 0x00065000, 0x00000002 },
79 { 0x000037e1, 0x00000002 },
80 { 0x040067e1, 0x00000006 },
81 { 0x000077e0, 0x00000002 },
82 { 0x000077e1, 0x00000002 },
83 { 0x000077e1, 0x00000006 },
84 { 0xffffffff, 0000000000 },
85 { 0x10000000, 0000000000 },
86 { 0x0003802a, 0x00000002 },
87 { 0x040067e0, 0x00000006 },
88 { 0x00007675, 0x00000002 },
89 { 0x00007676, 0x00000002 },
90 { 0x00007677, 0x00000002 },
91 { 0x00007678, 0x00000006 },
92 { 0x0003802b, 0x00000002 },
93 { 0x04002676, 0x00000002 },
94 { 0x00007677, 0x00000002 },
95 { 0x00007678, 0x00000006 },
96 { 0x0000002e, 0x00000018 },
97 { 0x0000002e, 0x00000018 },
98 { 0000000000, 0x00000006 },
99 { 0x0000002f, 0x00000018 },
100 { 0x0000002f, 0x00000018 },
101 { 0000000000, 0x00000006 },
102 { 0x01605000, 0x00000002 },
103 { 0x00065000, 0x00000002 },
104 { 0x00098000, 0x00000002 },
105 { 0x00061000, 0x00000002 },
106 { 0x64c0603d, 0x00000004 },
107 { 0x00080000, 0x00000016 },
108 { 0000000000, 0000000000 },
109 { 0x0400251d, 0x00000002 },
110 { 0x00007580, 0x00000002 },
111 { 0x00067581, 0x00000002 },
112 { 0x04002580, 0x00000002 },
113 { 0x00067581, 0x00000002 },
114 { 0x00000046, 0x00000004 },
115 { 0x00005000, 0000000000 },
116 { 0x00061000, 0x00000002 },
117 { 0x0000750e, 0x00000002 },
118 { 0x00019000, 0x00000002 },
119 { 0x00011055, 0x00000014 },
120 { 0x00000055, 0x00000012 },
121 { 0x0400250f, 0x00000002 },
122 { 0x0000504a, 0x00000004 },
123 { 0x00007565, 0x00000002 },
124 { 0x00007566, 0x00000002 },
125 { 0x00000051, 0x00000004 },
126 { 0x01e655b4, 0x00000002 },
127 { 0x4401b0dc, 0x00000002 },
128 { 0x01c110dc, 0x00000002 },
129 { 0x2666705d, 0x00000018 },
130 { 0x040c2565, 0x00000002 },
131 { 0x0000005d, 0x00000018 },
132 { 0x04002564, 0x00000002 },
133 { 0x00007566, 0x00000002 },
134 { 0x00000054, 0x00000004 },
135 { 0x00401060, 0x00000008 },
136 { 0x00101000, 0x00000002 },
137 { 0x000d80ff, 0x00000002 },
138 { 0x00800063, 0x00000008 },
139 { 0x000f9000, 0x00000002 },
140 { 0x000e00ff, 0x00000002 },
141 { 0000000000, 0x00000006 },
142 { 0x00000080, 0x00000018 },
143 { 0x00000054, 0x00000004 },
144 { 0x00007576, 0x00000002 },
145 { 0x00065000, 0x00000002 },
146 { 0x00009000, 0x00000002 },
147 { 0x00041000, 0x00000002 },
148 { 0x0c00350e, 0x00000002 },
149 { 0x00049000, 0x00000002 },
150 { 0x00051000, 0x00000002 },
151 { 0x01e785f8, 0x00000002 },
152 { 0x00200000, 0x00000002 },
153 { 0x00600073, 0x0000000c },
154 { 0x00007563, 0x00000002 },
155 { 0x006075f0, 0x00000021 },
156 { 0x20007068, 0x00000004 },
157 { 0x00005068, 0x00000004 },
158 { 0x00007576, 0x00000002 },
159 { 0x00007577, 0x00000002 },
160 { 0x0000750e, 0x00000002 },
161 { 0x0000750f, 0x00000002 },
162 { 0x00a05000, 0x00000002 },
163 { 0x00600076, 0x0000000c },
164 { 0x006075f0, 0x00000021 },
165 { 0x000075f8, 0x00000002 },
166 { 0x00000076, 0x00000004 },
167 { 0x000a750e, 0x00000002 },
168 { 0x0020750f, 0x00000002 },
169 { 0x00600079, 0x00000004 },
170 { 0x00007570, 0x00000002 },
171 { 0x00007571, 0x00000002 },
172 { 0x00007572, 0x00000006 },
173 { 0x00005000, 0x00000002 },
174 { 0x00a05000, 0x00000002 },
175 { 0x00007568, 0x00000002 },
176 { 0x00061000, 0x00000002 },
177 { 0x00000084, 0x0000000c },
178 { 0x00058000, 0x00000002 },
179 { 0x0c607562, 0x00000002 },
180 { 0x00000086, 0x00000004 },
181 { 0x00600085, 0x00000004 },
182 { 0x400070dd, 0000000000 },
183 { 0x000380dd, 0x00000002 },
184 { 0x00000093, 0x0000001c },
185 { 0x00065095, 0x00000018 },
186 { 0x040025bb, 0x00000002 },
187 { 0x00061096, 0x00000018 },
188 { 0x040075bc, 0000000000 },
189 { 0x000075bb, 0x00000002 },
190 { 0x000075bc, 0000000000 },
191 { 0x00090000, 0x00000006 },
192 { 0x00090000, 0x00000002 },
193 { 0x000d8002, 0x00000006 },
194 { 0x00005000, 0x00000002 },
195 { 0x00007821, 0x00000002 },
196 { 0x00007800, 0000000000 },
197 { 0x00007821, 0x00000002 },
198 { 0x00007800, 0000000000 },
199 { 0x01665000, 0x00000002 },
200 { 0x000a0000, 0x00000002 },
201 { 0x000671cc, 0x00000002 },
202 { 0x0286f1cd, 0x00000002 },
203 { 0x000000a3, 0x00000010 },
204 { 0x21007000, 0000000000 },
205 { 0x000000aa, 0x0000001c },
206 { 0x00065000, 0x00000002 },
207 { 0x000a0000, 0x00000002 },
208 { 0x00061000, 0x00000002 },
209 { 0x000b0000, 0x00000002 },
210 { 0x38067000, 0x00000002 },
211 { 0x000a00a6, 0x00000004 },
212 { 0x20007000, 0000000000 },
213 { 0x01200000, 0x00000002 },
214 { 0x20077000, 0x00000002 },
215 { 0x01200000, 0x00000002 },
216 { 0x20007000, 0000000000 },
217 { 0x00061000, 0x00000002 },
218 { 0x0120751b, 0x00000002 },
219 { 0x8040750a, 0x00000002 },
220 { 0x8040750b, 0x00000002 },
221 { 0x00110000, 0x00000002 },
222 { 0x000380dd, 0x00000002 },
223 { 0x000000bd, 0x0000001c },
224 { 0x00061096, 0x00000018 },
225 { 0x844075bd, 0x00000002 },
226 { 0x00061095, 0x00000018 },
227 { 0x840075bb, 0x00000002 },
228 { 0x00061096, 0x00000018 },
229 { 0x844075bc, 0x00000002 },
230 { 0x000000c0, 0x00000004 },
231 { 0x804075bd, 0x00000002 },
232 { 0x800075bb, 0x00000002 },
233 { 0x804075bc, 0x00000002 },
234 { 0x00108000, 0x00000002 },
235 { 0x01400000, 0x00000002 },
236 { 0x006000c4, 0x0000000c },
237 { 0x20c07000, 0x00000020 },
238 { 0x000000c6, 0x00000012 },
239 { 0x00800000, 0x00000006 },
240 { 0x0080751d, 0x00000006 },
241 { 0x000025bb, 0x00000002 },
242 { 0x000040c0, 0x00000004 },
243 { 0x0000775c, 0x00000002 },
244 { 0x00a05000, 0x00000002 },
245 { 0x00661000, 0x00000002 },
246 { 0x0460275d, 0x00000020 },
247 { 0x00004000, 0000000000 },
248 { 0x00007999, 0x00000002 },
249 { 0x00a05000, 0x00000002 },
250 { 0x00661000, 0x00000002 },
251 { 0x0460299b, 0x00000020 },
252 { 0x00004000, 0000000000 },
253 { 0x01e00830, 0x00000002 },
254 { 0x21007000, 0000000000 },
255 { 0x00005000, 0x00000002 },
256 { 0x00038042, 0x00000002 },
257 { 0x040025e0, 0x00000002 },
258 { 0x000075e1, 0000000000 },
259 { 0x00000001, 0000000000 },
260 { 0x000380d9, 0x00000002 },
261 { 0x04007394, 0000000000 },
262 { 0000000000, 0000000000 },
263 { 0000000000, 0000000000 },
264 { 0000000000, 0000000000 },
265 { 0000000000, 0000000000 },
266 { 0000000000, 0000000000 },
267 { 0000000000, 0000000000 },
268 { 0000000000, 0000000000 },
269 { 0000000000, 0000000000 },
270 { 0000000000, 0000000000 },
271 { 0000000000, 0000000000 },
272 { 0000000000, 0000000000 },
273 { 0000000000, 0000000000 },
274 { 0000000000, 0000000000 },
275 { 0000000000, 0000000000 },
276 { 0000000000, 0000000000 },
277 { 0000000000, 0000000000 },
278 { 0000000000, 0000000000 },
279 { 0000000000, 0000000000 },
280 { 0000000000, 0000000000 },
281 { 0000000000, 0000000000 },
282 { 0000000000, 0000000000 },
283 { 0000000000, 0000000000 },
284 { 0000000000, 0000000000 },
285 { 0000000000, 0000000000 },
286 { 0000000000, 0000000000 },
287 { 0000000000, 0000000000 },
288 { 0000000000, 0000000000 },
289 { 0000000000, 0000000000 },
290 { 0000000000, 0000000000 },
291 { 0000000000, 0000000000 },
292 { 0000000000, 0000000000 },
293 { 0000000000, 0000000000 },
294 { 0000000000, 0000000000 },
295 { 0000000000, 0000000000 },
296 { 0000000000, 0000000000 },
297 { 0000000000, 0000000000 },
298};
299
300
301static u32 radeon_cp_microcode[][2] = {
302 { 0x21007000, 0000000000 },
303 { 0x20007000, 0000000000 },
304 { 0x000000b4, 0x00000004 },
305 { 0x000000b8, 0x00000004 },
306 { 0x6f5b4d4c, 0000000000 },
307 { 0x4c4c427f, 0000000000 },
308 { 0x5b568a92, 0000000000 },
309 { 0x4ca09c6d, 0000000000 },
310 { 0xad4c4c4c, 0000000000 },
311 { 0x4ce1af3d, 0000000000 },
312 { 0xd8afafaf, 0000000000 },
313 { 0xd64c4cdc, 0000000000 },
314 { 0x4cd10d10, 0000000000 },
315 { 0x000f0000, 0x00000016 },
316 { 0x362f242d, 0000000000 },
317 { 0x00000012, 0x00000004 },
318 { 0x000f0000, 0x00000016 },
319 { 0x362f282d, 0000000000 },
320 { 0x000380e7, 0x00000002 },
321 { 0x04002c97, 0x00000002 },
322 { 0x000f0001, 0x00000016 },
323 { 0x333a3730, 0000000000 },
324 { 0x000077ef, 0x00000002 },
325 { 0x00061000, 0x00000002 },
326 { 0x00000021, 0x0000001a },
327 { 0x00004000, 0x0000001e },
328 { 0x00061000, 0x00000002 },
329 { 0x00000021, 0x0000001a },
330 { 0x00004000, 0x0000001e },
331 { 0x00061000, 0x00000002 },
332 { 0x00000021, 0x0000001a },
333 { 0x00004000, 0x0000001e },
334 { 0x00000017, 0x00000004 },
335 { 0x0003802b, 0x00000002 },
336 { 0x040067e0, 0x00000002 },
337 { 0x00000017, 0x00000004 },
338 { 0x000077e0, 0x00000002 },
339 { 0x00065000, 0x00000002 },
340 { 0x000037e1, 0x00000002 },
341 { 0x040067e1, 0x00000006 },
342 { 0x000077e0, 0x00000002 },
343 { 0x000077e1, 0x00000002 },
344 { 0x000077e1, 0x00000006 },
345 { 0xffffffff, 0000000000 },
346 { 0x10000000, 0000000000 },
347 { 0x0003802b, 0x00000002 },
348 { 0x040067e0, 0x00000006 },
349 { 0x00007675, 0x00000002 },
350 { 0x00007676, 0x00000002 },
351 { 0x00007677, 0x00000002 },
352 { 0x00007678, 0x00000006 },
353 { 0x0003802c, 0x00000002 },
354 { 0x04002676, 0x00000002 },
355 { 0x00007677, 0x00000002 },
356 { 0x00007678, 0x00000006 },
357 { 0x0000002f, 0x00000018 },
358 { 0x0000002f, 0x00000018 },
359 { 0000000000, 0x00000006 },
360 { 0x00000030, 0x00000018 },
361 { 0x00000030, 0x00000018 },
362 { 0000000000, 0x00000006 },
363 { 0x01605000, 0x00000002 },
364 { 0x00065000, 0x00000002 },
365 { 0x00098000, 0x00000002 },
366 { 0x00061000, 0x00000002 },
367 { 0x64c0603e, 0x00000004 },
368 { 0x000380e6, 0x00000002 },
369 { 0x040025c5, 0x00000002 },
370 { 0x00080000, 0x00000016 },
371 { 0000000000, 0000000000 },
372 { 0x0400251d, 0x00000002 },
373 { 0x00007580, 0x00000002 },
374 { 0x00067581, 0x00000002 },
375 { 0x04002580, 0x00000002 },
376 { 0x00067581, 0x00000002 },
377 { 0x00000049, 0x00000004 },
378 { 0x00005000, 0000000000 },
379 { 0x000380e6, 0x00000002 },
380 { 0x040025c5, 0x00000002 },
381 { 0x00061000, 0x00000002 },
382 { 0x0000750e, 0x00000002 },
383 { 0x00019000, 0x00000002 },
384 { 0x00011055, 0x00000014 },
385 { 0x00000055, 0x00000012 },
386 { 0x0400250f, 0x00000002 },
387 { 0x0000504f, 0x00000004 },
388 { 0x000380e6, 0x00000002 },
389 { 0x040025c5, 0x00000002 },
390 { 0x00007565, 0x00000002 },
391 { 0x00007566, 0x00000002 },
392 { 0x00000058, 0x00000004 },
393 { 0x000380e6, 0x00000002 },
394 { 0x040025c5, 0x00000002 },
395 { 0x01e655b4, 0x00000002 },
396 { 0x4401b0e4, 0x00000002 },
397 { 0x01c110e4, 0x00000002 },
398 { 0x26667066, 0x00000018 },
399 { 0x040c2565, 0x00000002 },
400 { 0x00000066, 0x00000018 },
401 { 0x04002564, 0x00000002 },
402 { 0x00007566, 0x00000002 },
403 { 0x0000005d, 0x00000004 },
404 { 0x00401069, 0x00000008 },
405 { 0x00101000, 0x00000002 },
406 { 0x000d80ff, 0x00000002 },
407 { 0x0080006c, 0x00000008 },
408 { 0x000f9000, 0x00000002 },
409 { 0x000e00ff, 0x00000002 },
410 { 0000000000, 0x00000006 },
411 { 0x0000008f, 0x00000018 },
412 { 0x0000005b, 0x00000004 },
413 { 0x000380e6, 0x00000002 },
414 { 0x040025c5, 0x00000002 },
415 { 0x00007576, 0x00000002 },
416 { 0x00065000, 0x00000002 },
417 { 0x00009000, 0x00000002 },
418 { 0x00041000, 0x00000002 },
419 { 0x0c00350e, 0x00000002 },
420 { 0x00049000, 0x00000002 },
421 { 0x00051000, 0x00000002 },
422 { 0x01e785f8, 0x00000002 },
423 { 0x00200000, 0x00000002 },
424 { 0x0060007e, 0x0000000c },
425 { 0x00007563, 0x00000002 },
426 { 0x006075f0, 0x00000021 },
427 { 0x20007073, 0x00000004 },
428 { 0x00005073, 0x00000004 },
429 { 0x000380e6, 0x00000002 },
430 { 0x040025c5, 0x00000002 },
431 { 0x00007576, 0x00000002 },
432 { 0x00007577, 0x00000002 },
433 { 0x0000750e, 0x00000002 },
434 { 0x0000750f, 0x00000002 },
435 { 0x00a05000, 0x00000002 },
436 { 0x00600083, 0x0000000c },
437 { 0x006075f0, 0x00000021 },
438 { 0x000075f8, 0x00000002 },
439 { 0x00000083, 0x00000004 },
440 { 0x000a750e, 0x00000002 },
441 { 0x000380e6, 0x00000002 },
442 { 0x040025c5, 0x00000002 },
443 { 0x0020750f, 0x00000002 },
444 { 0x00600086, 0x00000004 },
445 { 0x00007570, 0x00000002 },
446 { 0x00007571, 0x00000002 },
447 { 0x00007572, 0x00000006 },
448 { 0x000380e6, 0x00000002 },
449 { 0x040025c5, 0x00000002 },
450 { 0x00005000, 0x00000002 },
451 { 0x00a05000, 0x00000002 },
452 { 0x00007568, 0x00000002 },
453 { 0x00061000, 0x00000002 },
454 { 0x00000095, 0x0000000c },
455 { 0x00058000, 0x00000002 },
456 { 0x0c607562, 0x00000002 },
457 { 0x00000097, 0x00000004 },
458 { 0x000380e6, 0x00000002 },
459 { 0x040025c5, 0x00000002 },
460 { 0x00600096, 0x00000004 },
461 { 0x400070e5, 0000000000 },
462 { 0x000380e6, 0x00000002 },
463 { 0x040025c5, 0x00000002 },
464 { 0x000380e5, 0x00000002 },
465 { 0x000000a8, 0x0000001c },
466 { 0x000650aa, 0x00000018 },
467 { 0x040025bb, 0x00000002 },
468 { 0x000610ab, 0x00000018 },
469 { 0x040075bc, 0000000000 },
470 { 0x000075bb, 0x00000002 },
471 { 0x000075bc, 0000000000 },
472 { 0x00090000, 0x00000006 },
473 { 0x00090000, 0x00000002 },
474 { 0x000d8002, 0x00000006 },
475 { 0x00007832, 0x00000002 },
476 { 0x00005000, 0x00000002 },
477 { 0x000380e7, 0x00000002 },
478 { 0x04002c97, 0x00000002 },
479 { 0x00007820, 0x00000002 },
480 { 0x00007821, 0x00000002 },
481 { 0x00007800, 0000000000 },
482 { 0x01200000, 0x00000002 },
483 { 0x20077000, 0x00000002 },
484 { 0x01200000, 0x00000002 },
485 { 0x20007000, 0x00000002 },
486 { 0x00061000, 0x00000002 },
487 { 0x0120751b, 0x00000002 },
488 { 0x8040750a, 0x00000002 },
489 { 0x8040750b, 0x00000002 },
490 { 0x00110000, 0x00000002 },
491 { 0x000380e5, 0x00000002 },
492 { 0x000000c6, 0x0000001c },
493 { 0x000610ab, 0x00000018 },
494 { 0x844075bd, 0x00000002 },
495 { 0x000610aa, 0x00000018 },
496 { 0x840075bb, 0x00000002 },
497 { 0x000610ab, 0x00000018 },
498 { 0x844075bc, 0x00000002 },
499 { 0x000000c9, 0x00000004 },
500 { 0x804075bd, 0x00000002 },
501 { 0x800075bb, 0x00000002 },
502 { 0x804075bc, 0x00000002 },
503 { 0x00108000, 0x00000002 },
504 { 0x01400000, 0x00000002 },
505 { 0x006000cd, 0x0000000c },
506 { 0x20c07000, 0x00000020 },
507 { 0x000000cf, 0x00000012 },
508 { 0x00800000, 0x00000006 },
509 { 0x0080751d, 0x00000006 },
510 { 0000000000, 0000000000 },
511 { 0x0000775c, 0x00000002 },
512 { 0x00a05000, 0x00000002 },
513 { 0x00661000, 0x00000002 },
514 { 0x0460275d, 0x00000020 },
515 { 0x00004000, 0000000000 },
516 { 0x01e00830, 0x00000002 },
517 { 0x21007000, 0000000000 },
518 { 0x6464614d, 0000000000 },
519 { 0x69687420, 0000000000 },
520 { 0x00000073, 0000000000 },
521 { 0000000000, 0000000000 },
522 { 0x00005000, 0x00000002 },
523 { 0x000380d0, 0x00000002 },
524 { 0x040025e0, 0x00000002 },
525 { 0x000075e1, 0000000000 },
526 { 0x00000001, 0000000000 },
527 { 0x000380e0, 0x00000002 },
528 { 0x04002394, 0x00000002 },
529 { 0x00005000, 0000000000 },
530 { 0000000000, 0000000000 },
531 { 0000000000, 0000000000 },
532 { 0x00000008, 0000000000 },
533 { 0x00000004, 0000000000 },
534 { 0000000000, 0000000000 },
535 { 0000000000, 0000000000 },
536 { 0000000000, 0000000000 },
537 { 0000000000, 0000000000 },
538 { 0000000000, 0000000000 },
539 { 0000000000, 0000000000 },
540 { 0000000000, 0000000000 },
541 { 0000000000, 0000000000 },
542 { 0000000000, 0000000000 },
543 { 0000000000, 0000000000 },
544 { 0000000000, 0000000000 },
545 { 0000000000, 0000000000 },
546 { 0000000000, 0000000000 },
547 { 0000000000, 0000000000 },
548 { 0000000000, 0000000000 },
549 { 0000000000, 0000000000 },
550 { 0000000000, 0000000000 },
551 { 0000000000, 0000000000 },
552 { 0000000000, 0000000000 },
553 { 0000000000, 0000000000 },
554 { 0000000000, 0000000000 },
555 { 0000000000, 0000000000 },
556 { 0000000000, 0000000000 },
557 { 0000000000, 0000000000 },
558};
559
560static u32 R300_cp_microcode[][2] = {
561 { 0x4200e000, 0000000000 },
562 { 0x4000e000, 0000000000 },
563 { 0x000000af, 0x00000008 },
564 { 0x000000b3, 0x00000008 },
565 { 0x6c5a504f, 0000000000 },
566 { 0x4f4f497a, 0000000000 },
567 { 0x5a578288, 0000000000 },
568 { 0x4f91906a, 0000000000 },
569 { 0x4f4f4f4f, 0000000000 },
570 { 0x4fe24f44, 0000000000 },
571 { 0x4f9c9c9c, 0000000000 },
572 { 0xdc4f4fde, 0000000000 },
573 { 0xa1cd4f4f, 0000000000 },
574 { 0xd29d9d9d, 0000000000 },
575 { 0x4f0f9fd7, 0000000000 },
576 { 0x000ca000, 0x00000004 },
577 { 0x000d0012, 0x00000038 },
578 { 0x0000e8b4, 0x00000004 },
579 { 0x000d0014, 0x00000038 },
580 { 0x0000e8b6, 0x00000004 },
581 { 0x000d0016, 0x00000038 },
582 { 0x0000e854, 0x00000004 },
583 { 0x000d0018, 0x00000038 },
584 { 0x0000e855, 0x00000004 },
585 { 0x000d001a, 0x00000038 },
586 { 0x0000e856, 0x00000004 },
587 { 0x000d001c, 0x00000038 },
588 { 0x0000e857, 0x00000004 },
589 { 0x000d001e, 0x00000038 },
590 { 0x0000e824, 0x00000004 },
591 { 0x000d0020, 0x00000038 },
592 { 0x0000e825, 0x00000004 },
593 { 0x000d0022, 0x00000038 },
594 { 0x0000e830, 0x00000004 },
595 { 0x000d0024, 0x00000038 },
596 { 0x0000f0c0, 0x00000004 },
597 { 0x000d0026, 0x00000038 },
598 { 0x0000f0c1, 0x00000004 },
599 { 0x000d0028, 0x00000038 },
600 { 0x0000f041, 0x00000004 },
601 { 0x000d002a, 0x00000038 },
602 { 0x0000f184, 0x00000004 },
603 { 0x000d002c, 0x00000038 },
604 { 0x0000f185, 0x00000004 },
605 { 0x000d002e, 0x00000038 },
606 { 0x0000f186, 0x00000004 },
607 { 0x000d0030, 0x00000038 },
608 { 0x0000f187, 0x00000004 },
609 { 0x000d0032, 0x00000038 },
610 { 0x0000f180, 0x00000004 },
611 { 0x000d0034, 0x00000038 },
612 { 0x0000f393, 0x00000004 },
613 { 0x000d0036, 0x00000038 },
614 { 0x0000f38a, 0x00000004 },
615 { 0x000d0038, 0x00000038 },
616 { 0x0000f38e, 0x00000004 },
617 { 0x0000e821, 0x00000004 },
618 { 0x0140a000, 0x00000004 },
619 { 0x00000043, 0x00000018 },
620 { 0x00cce800, 0x00000004 },
621 { 0x001b0001, 0x00000004 },
622 { 0x08004800, 0x00000004 },
623 { 0x001b0001, 0x00000004 },
624 { 0x08004800, 0x00000004 },
625 { 0x001b0001, 0x00000004 },
626 { 0x08004800, 0x00000004 },
627 { 0x0000003a, 0x00000008 },
628 { 0x0000a000, 0000000000 },
629 { 0x02c0a000, 0x00000004 },
630 { 0x000ca000, 0x00000004 },
631 { 0x00130000, 0x00000004 },
632 { 0x000c2000, 0x00000004 },
633 { 0xc980c045, 0x00000008 },
634 { 0x2000451d, 0x00000004 },
635 { 0x0000e580, 0x00000004 },
636 { 0x000ce581, 0x00000004 },
637 { 0x08004580, 0x00000004 },
638 { 0x000ce581, 0x00000004 },
639 { 0x0000004c, 0x00000008 },
640 { 0x0000a000, 0000000000 },
641 { 0x000c2000, 0x00000004 },
642 { 0x0000e50e, 0x00000004 },
643 { 0x00032000, 0x00000004 },
644 { 0x00022056, 0x00000028 },
645 { 0x00000056, 0x00000024 },
646 { 0x0800450f, 0x00000004 },
647 { 0x0000a050, 0x00000008 },
648 { 0x0000e565, 0x00000004 },
649 { 0x0000e566, 0x00000004 },
650 { 0x00000057, 0x00000008 },
651 { 0x03cca5b4, 0x00000004 },
652 { 0x05432000, 0x00000004 },
653 { 0x00022000, 0x00000004 },
654 { 0x4ccce063, 0x00000030 },
655 { 0x08274565, 0x00000004 },
656 { 0x00000063, 0x00000030 },
657 { 0x08004564, 0x00000004 },
658 { 0x0000e566, 0x00000004 },
659 { 0x0000005a, 0x00000008 },
660 { 0x00802066, 0x00000010 },
661 { 0x00202000, 0x00000004 },
662 { 0x001b00ff, 0x00000004 },
663 { 0x01000069, 0x00000010 },
664 { 0x001f2000, 0x00000004 },
665 { 0x001c00ff, 0x00000004 },
666 { 0000000000, 0x0000000c },
667 { 0x00000085, 0x00000030 },
668 { 0x0000005a, 0x00000008 },
669 { 0x0000e576, 0x00000004 },
670 { 0x000ca000, 0x00000004 },
671 { 0x00012000, 0x00000004 },
672 { 0x00082000, 0x00000004 },
673 { 0x1800650e, 0x00000004 },
674 { 0x00092000, 0x00000004 },
675 { 0x000a2000, 0x00000004 },
676 { 0x000f0000, 0x00000004 },
677 { 0x00400000, 0x00000004 },
678 { 0x00000079, 0x00000018 },
679 { 0x0000e563, 0x00000004 },
680 { 0x00c0e5f9, 0x000000c2 },
681 { 0x0000006e, 0x00000008 },
682 { 0x0000a06e, 0x00000008 },
683 { 0x0000e576, 0x00000004 },
684 { 0x0000e577, 0x00000004 },
685 { 0x0000e50e, 0x00000004 },
686 { 0x0000e50f, 0x00000004 },
687 { 0x0140a000, 0x00000004 },
688 { 0x0000007c, 0x00000018 },
689 { 0x00c0e5f9, 0x000000c2 },
690 { 0x0000007c, 0x00000008 },
691 { 0x0014e50e, 0x00000004 },
692 { 0x0040e50f, 0x00000004 },
693 { 0x00c0007f, 0x00000008 },
694 { 0x0000e570, 0x00000004 },
695 { 0x0000e571, 0x00000004 },
696 { 0x0000e572, 0x0000000c },
697 { 0x0000a000, 0x00000004 },
698 { 0x0140a000, 0x00000004 },
699 { 0x0000e568, 0x00000004 },
700 { 0x000c2000, 0x00000004 },
701 { 0x00000089, 0x00000018 },
702 { 0x000b0000, 0x00000004 },
703 { 0x18c0e562, 0x00000004 },
704 { 0x0000008b, 0x00000008 },
705 { 0x00c0008a, 0x00000008 },
706 { 0x000700e4, 0x00000004 },
707 { 0x00000097, 0x00000038 },
708 { 0x000ca099, 0x00000030 },
709 { 0x080045bb, 0x00000004 },
710 { 0x000c209a, 0x00000030 },
711 { 0x0800e5bc, 0000000000 },
712 { 0x0000e5bb, 0x00000004 },
713 { 0x0000e5bc, 0000000000 },
714 { 0x00120000, 0x0000000c },
715 { 0x00120000, 0x00000004 },
716 { 0x001b0002, 0x0000000c },
717 { 0x0000a000, 0x00000004 },
718 { 0x0000e821, 0x00000004 },
719 { 0x0000e800, 0000000000 },
720 { 0x0000e821, 0x00000004 },
721 { 0x0000e82e, 0000000000 },
722 { 0x02cca000, 0x00000004 },
723 { 0x00140000, 0x00000004 },
724 { 0x000ce1cc, 0x00000004 },
725 { 0x050de1cd, 0x00000004 },
726 { 0x000000a7, 0x00000020 },
727 { 0x4200e000, 0000000000 },
728 { 0x000000ae, 0x00000038 },
729 { 0x000ca000, 0x00000004 },
730 { 0x00140000, 0x00000004 },
731 { 0x000c2000, 0x00000004 },
732 { 0x00160000, 0x00000004 },
733 { 0x700ce000, 0x00000004 },
734 { 0x001400aa, 0x00000008 },
735 { 0x4000e000, 0000000000 },
736 { 0x02400000, 0x00000004 },
737 { 0x400ee000, 0x00000004 },
738 { 0x02400000, 0x00000004 },
739 { 0x4000e000, 0000000000 },
740 { 0x000c2000, 0x00000004 },
741 { 0x0240e51b, 0x00000004 },
742 { 0x0080e50a, 0x00000005 },
743 { 0x0080e50b, 0x00000005 },
744 { 0x00220000, 0x00000004 },
745 { 0x000700e4, 0x00000004 },
746 { 0x000000c1, 0x00000038 },
747 { 0x000c209a, 0x00000030 },
748 { 0x0880e5bd, 0x00000005 },
749 { 0x000c2099, 0x00000030 },
750 { 0x0800e5bb, 0x00000005 },
751 { 0x000c209a, 0x00000030 },
752 { 0x0880e5bc, 0x00000005 },
753 { 0x000000c4, 0x00000008 },
754 { 0x0080e5bd, 0x00000005 },
755 { 0x0000e5bb, 0x00000005 },
756 { 0x0080e5bc, 0x00000005 },
757 { 0x00210000, 0x00000004 },
758 { 0x02800000, 0x00000004 },
759 { 0x00c000c8, 0x00000018 },
760 { 0x4180e000, 0x00000040 },
761 { 0x000000ca, 0x00000024 },
762 { 0x01000000, 0x0000000c },
763 { 0x0100e51d, 0x0000000c },
764 { 0x000045bb, 0x00000004 },
765 { 0x000080c4, 0x00000008 },
766 { 0x0000f3ce, 0x00000004 },
767 { 0x0140a000, 0x00000004 },
768 { 0x00cc2000, 0x00000004 },
769 { 0x08c053cf, 0x00000040 },
770 { 0x00008000, 0000000000 },
771 { 0x0000f3d2, 0x00000004 },
772 { 0x0140a000, 0x00000004 },
773 { 0x00cc2000, 0x00000004 },
774 { 0x08c053d3, 0x00000040 },
775 { 0x00008000, 0000000000 },
776 { 0x0000f39d, 0x00000004 },
777 { 0x0140a000, 0x00000004 },
778 { 0x00cc2000, 0x00000004 },
779 { 0x08c0539e, 0x00000040 },
780 { 0x00008000, 0000000000 },
781 { 0x03c00830, 0x00000004 },
782 { 0x4200e000, 0000000000 },
783 { 0x0000a000, 0x00000004 },
784 { 0x200045e0, 0x00000004 },
785 { 0x0000e5e1, 0000000000 },
786 { 0x00000001, 0000000000 },
787 { 0x000700e1, 0x00000004 },
788 { 0x0800e394, 0000000000 },
789 { 0000000000, 0000000000 },
790 { 0000000000, 0000000000 },
791 { 0000000000, 0000000000 },
792 { 0000000000, 0000000000 },
793 { 0000000000, 0000000000 },
794 { 0000000000, 0000000000 },
795 { 0000000000, 0000000000 },
796 { 0000000000, 0000000000 },
797 { 0000000000, 0000000000 },
798 { 0000000000, 0000000000 },
799 { 0000000000, 0000000000 },
800 { 0000000000, 0000000000 },
801 { 0000000000, 0000000000 },
802 { 0000000000, 0000000000 },
803 { 0000000000, 0000000000 },
804 { 0000000000, 0000000000 },
805 { 0000000000, 0000000000 },
806 { 0000000000, 0000000000 },
807 { 0000000000, 0000000000 },
808 { 0000000000, 0000000000 },
809 { 0000000000, 0000000000 },
810 { 0000000000, 0000000000 },
811 { 0000000000, 0000000000 },
812 { 0000000000, 0000000000 },
813 { 0000000000, 0000000000 },
814 { 0000000000, 0000000000 },
815 { 0000000000, 0000000000 },
816 { 0000000000, 0000000000 },
817};
818
819static int RADEON_READ_PLL(drm_device_t *dev, int addr)
820{
821 drm_radeon_private_t *dev_priv = dev->dev_private;
822
823 RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
824 return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
825}
826
827#if RADEON_FIFO_DEBUG
828static void radeon_status( drm_radeon_private_t *dev_priv )
829{
830 printk( "%s:\n", __FUNCTION__ );
831 printk( "RBBM_STATUS = 0x%08x\n",
832 (unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) );
833 printk( "CP_RB_RTPR = 0x%08x\n",
834 (unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
835 printk( "CP_RB_WTPR = 0x%08x\n",
836 (unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
837 printk( "AIC_CNTL = 0x%08x\n",
838 (unsigned int)RADEON_READ( RADEON_AIC_CNTL ) );
839 printk( "AIC_STAT = 0x%08x\n",
840 (unsigned int)RADEON_READ( RADEON_AIC_STAT ) );
841 printk( "AIC_PT_BASE = 0x%08x\n",
842 (unsigned int)RADEON_READ( RADEON_AIC_PT_BASE ) );
843 printk( "TLB_ADDR = 0x%08x\n",
844 (unsigned int)RADEON_READ( RADEON_AIC_TLB_ADDR ) );
845 printk( "TLB_DATA = 0x%08x\n",
846 (unsigned int)RADEON_READ( RADEON_AIC_TLB_DATA ) );
847}
848#endif
849
850
851/* ================================================================
852 * Engine, FIFO control
853 */
854
855static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv )
856{
857 u32 tmp;
858 int i;
859
860 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
861
862 tmp = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
863 tmp |= RADEON_RB2D_DC_FLUSH_ALL;
864 RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
865
866 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
867 if ( !(RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT )
868 & RADEON_RB2D_DC_BUSY) ) {
869 return 0;
870 }
871 DRM_UDELAY( 1 );
872 }
873
874#if RADEON_FIFO_DEBUG
875 DRM_ERROR( "failed!\n" );
876 radeon_status( dev_priv );
877#endif
878 return DRM_ERR(EBUSY);
879}
880
881static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
882 int entries )
883{
884 int i;
885
886 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
887
888 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
889 int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
890 & RADEON_RBBM_FIFOCNT_MASK );
891 if ( slots >= entries ) return 0;
892 DRM_UDELAY( 1 );
893 }
894
895#if RADEON_FIFO_DEBUG
896 DRM_ERROR( "failed!\n" );
897 radeon_status( dev_priv );
898#endif
899 return DRM_ERR(EBUSY);
900}
901
902static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
903{
904 int i, ret;
905
906 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
907
908 ret = radeon_do_wait_for_fifo( dev_priv, 64 );
909 if ( ret ) return ret;
910
911 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
912 if ( !(RADEON_READ( RADEON_RBBM_STATUS )
913 & RADEON_RBBM_ACTIVE) ) {
914 radeon_do_pixcache_flush( dev_priv );
915 return 0;
916 }
917 DRM_UDELAY( 1 );
918 }
919
920#if RADEON_FIFO_DEBUG
921 DRM_ERROR( "failed!\n" );
922 radeon_status( dev_priv );
923#endif
924 return DRM_ERR(EBUSY);
925}
926
927
928/* ================================================================
929 * CP control, initialization
930 */
931
932/* Load the microcode for the CP */
933static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
934{
935 int i;
936 DRM_DEBUG( "\n" );
937
938 radeon_do_wait_for_idle( dev_priv );
939
940 RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 );
941
942 if (dev_priv->microcode_version==UCODE_R200) {
943 DRM_INFO("Loading R200 Microcode\n");
944 for ( i = 0 ; i < 256 ; i++ )
945 {
946 RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
947 R200_cp_microcode[i][1] );
948 RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
949 R200_cp_microcode[i][0] );
950 }
951 } else if (dev_priv->microcode_version==UCODE_R300) {
952 DRM_INFO("Loading R300 Microcode\n");
953 for ( i = 0 ; i < 256 ; i++ )
954 {
955 RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
956 R300_cp_microcode[i][1] );
957 RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
958 R300_cp_microcode[i][0] );
959 }
960 } else {
961 for ( i = 0 ; i < 256 ; i++ ) {
962 RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
963 radeon_cp_microcode[i][1] );
964 RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
965 radeon_cp_microcode[i][0] );
966 }
967 }
968}
969
970/* Flush any pending commands to the CP. This should only be used just
971 * prior to a wait for idle, as it informs the engine that the command
972 * stream is ending.
973 */
974static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
975{
976 DRM_DEBUG( "\n" );
977#if 0
978 u32 tmp;
979
980 tmp = RADEON_READ( RADEON_CP_RB_WPTR ) | (1 << 31);
981 RADEON_WRITE( RADEON_CP_RB_WPTR, tmp );
982#endif
983}
984
985/* Wait for the CP to go idle.
986 */
987int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
988{
989 RING_LOCALS;
990 DRM_DEBUG( "\n" );
991
992 BEGIN_RING( 6 );
993
994 RADEON_PURGE_CACHE();
995 RADEON_PURGE_ZCACHE();
996 RADEON_WAIT_UNTIL_IDLE();
997
998 ADVANCE_RING();
999 COMMIT_RING();
1000
1001 return radeon_do_wait_for_idle( dev_priv );
1002}
1003
1004/* Start the Command Processor.
1005 */
1006static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
1007{
1008 RING_LOCALS;
1009 DRM_DEBUG( "\n" );
1010
1011 radeon_do_wait_for_idle( dev_priv );
1012
1013 RADEON_WRITE( RADEON_CP_CSQ_CNTL, dev_priv->cp_mode );
1014
1015 dev_priv->cp_running = 1;
1016
1017 BEGIN_RING( 6 );
1018
1019 RADEON_PURGE_CACHE();
1020 RADEON_PURGE_ZCACHE();
1021 RADEON_WAIT_UNTIL_IDLE();
1022
1023 ADVANCE_RING();
1024 COMMIT_RING();
1025}
1026
1027/* Reset the Command Processor. This will not flush any pending
1028 * commands, so you must wait for the CP command stream to complete
1029 * before calling this routine.
1030 */
1031static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
1032{
1033 u32 cur_read_ptr;
1034 DRM_DEBUG( "\n" );
1035
1036 cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
1037 RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
1038 SET_RING_HEAD( dev_priv, cur_read_ptr );
1039 dev_priv->ring.tail = cur_read_ptr;
1040}
1041
1042/* Stop the Command Processor. This will not flush any pending
1043 * commands, so you must flush the command stream and wait for the CP
1044 * to go idle before calling this routine.
1045 */
1046static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
1047{
1048 DRM_DEBUG( "\n" );
1049
1050 RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
1051
1052 dev_priv->cp_running = 0;
1053}
1054
1055/* Reset the engine. This will stop the CP if it is running.
1056 */
1057static int radeon_do_engine_reset( drm_device_t *dev )
1058{
1059 drm_radeon_private_t *dev_priv = dev->dev_private;
1060 u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
1061 DRM_DEBUG( "\n" );
1062
1063 radeon_do_pixcache_flush( dev_priv );
1064
1065 clock_cntl_index = RADEON_READ( RADEON_CLOCK_CNTL_INDEX );
1066 mclk_cntl = RADEON_READ_PLL( dev, RADEON_MCLK_CNTL );
1067
1068 RADEON_WRITE_PLL( RADEON_MCLK_CNTL, ( mclk_cntl |
1069 RADEON_FORCEON_MCLKA |
1070 RADEON_FORCEON_MCLKB |
1071 RADEON_FORCEON_YCLKA |
1072 RADEON_FORCEON_YCLKB |
1073 RADEON_FORCEON_MC |
1074 RADEON_FORCEON_AIC ) );
1075
1076 rbbm_soft_reset = RADEON_READ( RADEON_RBBM_SOFT_RESET );
1077
1078 RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset |
1079 RADEON_SOFT_RESET_CP |
1080 RADEON_SOFT_RESET_HI |
1081 RADEON_SOFT_RESET_SE |
1082 RADEON_SOFT_RESET_RE |
1083 RADEON_SOFT_RESET_PP |
1084 RADEON_SOFT_RESET_E2 |
1085 RADEON_SOFT_RESET_RB ) );
1086 RADEON_READ( RADEON_RBBM_SOFT_RESET );
1087 RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset &
1088 ~( RADEON_SOFT_RESET_CP |
1089 RADEON_SOFT_RESET_HI |
1090 RADEON_SOFT_RESET_SE |
1091 RADEON_SOFT_RESET_RE |
1092 RADEON_SOFT_RESET_PP |
1093 RADEON_SOFT_RESET_E2 |
1094 RADEON_SOFT_RESET_RB ) ) );
1095 RADEON_READ( RADEON_RBBM_SOFT_RESET );
1096
1097
1098 RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl );
1099 RADEON_WRITE( RADEON_CLOCK_CNTL_INDEX, clock_cntl_index );
1100 RADEON_WRITE( RADEON_RBBM_SOFT_RESET, rbbm_soft_reset );
1101
1102 /* Reset the CP ring */
1103 radeon_do_cp_reset( dev_priv );
1104
1105 /* The CP is no longer running after an engine reset */
1106 dev_priv->cp_running = 0;
1107
1108 /* Reset any pending vertex, indirect buffers */
1109 radeon_freelist_reset( dev );
1110
1111 return 0;
1112}
1113
1114static void radeon_cp_init_ring_buffer( drm_device_t *dev,
1115 drm_radeon_private_t *dev_priv )
1116{
1117 u32 ring_start, cur_read_ptr;
1118 u32 tmp;
1119
1120 /* Initialize the memory controller */
1121 RADEON_WRITE( RADEON_MC_FB_LOCATION,
1122 ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 )
1123 | ( dev_priv->fb_location >> 16 ) );
1124
1125#if __OS_HAS_AGP
1126 if ( !dev_priv->is_pci ) {
1127 RADEON_WRITE( RADEON_MC_AGP_LOCATION,
1128 (((dev_priv->gart_vm_start - 1 +
1129 dev_priv->gart_size) & 0xffff0000) |
1130 (dev_priv->gart_vm_start >> 16)) );
1131
1132 ring_start = (dev_priv->cp_ring->offset
1133 - dev->agp->base
1134 + dev_priv->gart_vm_start);
1135 } else
1136#endif
1137 ring_start = (dev_priv->cp_ring->offset
1138 - dev->sg->handle
1139 + dev_priv->gart_vm_start);
1140
1141 RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
1142
1143 /* Set the write pointer delay */
1144 RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 );
1145
1146 /* Initialize the ring buffer's read and write pointers */
1147 cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
1148 RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
1149 SET_RING_HEAD( dev_priv, cur_read_ptr );
1150 dev_priv->ring.tail = cur_read_ptr;
1151
1152#if __OS_HAS_AGP
1153 if ( !dev_priv->is_pci ) {
1154 RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
1155 dev_priv->ring_rptr->offset
1156 - dev->agp->base
1157 + dev_priv->gart_vm_start);
1158 } else
1159#endif
1160 {
1161 drm_sg_mem_t *entry = dev->sg;
1162 unsigned long tmp_ofs, page_ofs;
1163
1164 tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
1165 page_ofs = tmp_ofs >> PAGE_SHIFT;
1166
1167 RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
1168 entry->busaddr[page_ofs]);
1169 DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
1170 (unsigned long) entry->busaddr[page_ofs],
1171 entry->handle + tmp_ofs );
1172 }
1173
1174 /* Initialize the scratch register pointer. This will cause
1175 * the scratch register values to be written out to memory
1176 * whenever they are updated.
1177 *
1178 * We simply put this behind the ring read pointer, this works
1179 * with PCI GART as well as (whatever kind of) AGP GART
1180 */
1181 RADEON_WRITE( RADEON_SCRATCH_ADDR, RADEON_READ( RADEON_CP_RB_RPTR_ADDR )
1182 + RADEON_SCRATCH_REG_OFFSET );
1183
1184 dev_priv->scratch = ((__volatile__ u32 *)
1185 dev_priv->ring_rptr->handle +
1186 (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
1187
1188 RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
1189
1190 /* Writeback doesn't seem to work everywhere, test it first */
1191 DRM_WRITE32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0 );
1192 RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
1193
1194 for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
1195 if ( DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1) ) == 0xdeadbeef )
1196 break;
1197 DRM_UDELAY( 1 );
1198 }
1199
1200 if ( tmp < dev_priv->usec_timeout ) {
1201 dev_priv->writeback_works = 1;
1202 DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
1203 } else {
1204 dev_priv->writeback_works = 0;
1205 DRM_DEBUG( "writeback test failed\n" );
1206 }
1207
1208 dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
1209 RADEON_WRITE( RADEON_LAST_FRAME_REG,
1210 dev_priv->sarea_priv->last_frame );
1211
1212 dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
1213 RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
1214 dev_priv->sarea_priv->last_dispatch );
1215
1216 dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
1217 RADEON_WRITE( RADEON_LAST_CLEAR_REG,
1218 dev_priv->sarea_priv->last_clear );
1219
1220 /* Set ring buffer size */
1221#ifdef __BIG_ENDIAN
1222 RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT );
1223#else
1224 RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
1225#endif
1226
1227 radeon_do_wait_for_idle( dev_priv );
1228
1229 /* Turn on bus mastering */
1230 tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
1231 RADEON_WRITE( RADEON_BUS_CNTL, tmp );
1232
1233 /* Sync everything up */
1234 RADEON_WRITE( RADEON_ISYNC_CNTL,
1235 (RADEON_ISYNC_ANY2D_IDLE3D |
1236 RADEON_ISYNC_ANY3D_IDLE2D |
1237 RADEON_ISYNC_WAIT_IDLEGUI |
1238 RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
1239}
1240
1241/* Enable or disable PCI GART on the chip */
1242static void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on )
1243{
1244 u32 tmp = RADEON_READ( RADEON_AIC_CNTL );
1245
1246 if ( on ) {
1247 RADEON_WRITE( RADEON_AIC_CNTL, tmp | RADEON_PCIGART_TRANSLATE_EN );
1248
1249 /* set PCI GART page-table base address
1250 */
1251 RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );
1252
1253 /* set address range for PCI address translate
1254 */
1255 RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start );
1256 RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
1257 + dev_priv->gart_size - 1);
1258
1259 /* Turn off AGP aperture -- is this required for PCI GART?
1260 */
1261 RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
1262 RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
1263 } else {
1264 RADEON_WRITE( RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN );
1265 }
1266}
1267
1268static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
1269{
1270 drm_radeon_private_t *dev_priv = dev->dev_private;;
1271 DRM_DEBUG( "\n" );
1272
1273 dev_priv->is_pci = init->is_pci;
1274
1275 if ( dev_priv->is_pci && !dev->sg ) {
1276 DRM_ERROR( "PCI GART memory not allocated!\n" );
1277 dev->dev_private = (void *)dev_priv;
1278 radeon_do_cleanup_cp(dev);
1279 return DRM_ERR(EINVAL);
1280 }
1281
1282 dev_priv->usec_timeout = init->usec_timeout;
1283 if ( dev_priv->usec_timeout < 1 ||
1284 dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
1285 DRM_DEBUG( "TIMEOUT problem!\n" );
1286 dev->dev_private = (void *)dev_priv;
1287 radeon_do_cleanup_cp(dev);
1288 return DRM_ERR(EINVAL);
1289 }
1290
1291 switch(init->func) {
1292 case RADEON_INIT_R200_CP:
1293 dev_priv->microcode_version=UCODE_R200;
1294 break;
1295 case RADEON_INIT_R300_CP:
1296 dev_priv->microcode_version=UCODE_R300;
1297 break;
1298 default:
1299 dev_priv->microcode_version=UCODE_R100;
1300 }
1301
1302 dev_priv->do_boxes = 0;
1303 dev_priv->cp_mode = init->cp_mode;
1304
1305 /* We don't support anything other than bus-mastering ring mode,
1306 * but the ring can be in either AGP or PCI space for the ring
1307 * read pointer.
1308 */
1309 if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
1310 ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
1311 DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
1312 dev->dev_private = (void *)dev_priv;
1313 radeon_do_cleanup_cp(dev);
1314 return DRM_ERR(EINVAL);
1315 }
1316
1317 switch ( init->fb_bpp ) {
1318 case 16:
1319 dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
1320 break;
1321 case 32:
1322 default:
1323 dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
1324 break;
1325 }
1326 dev_priv->front_offset = init->front_offset;
1327 dev_priv->front_pitch = init->front_pitch;
1328 dev_priv->back_offset = init->back_offset;
1329 dev_priv->back_pitch = init->back_pitch;
1330
1331 switch ( init->depth_bpp ) {
1332 case 16:
1333 dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
1334 break;
1335 case 32:
1336 default:
1337 dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
1338 break;
1339 }
1340 dev_priv->depth_offset = init->depth_offset;
1341 dev_priv->depth_pitch = init->depth_pitch;
1342
1343 /* Hardware state for depth clears. Remove this if/when we no
1344 * longer clear the depth buffer with a 3D rectangle. Hard-code
1345 * all values to prevent unwanted 3D state from slipping through
1346 * and screwing with the clear operation.
1347 */
1348 dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
1349 (dev_priv->color_fmt << 10) |
1350 (dev_priv->microcode_version == UCODE_R100 ? RADEON_ZBLOCK16 : 0));
1351
1352 dev_priv->depth_clear.rb3d_zstencilcntl =
1353 (dev_priv->depth_fmt |
1354 RADEON_Z_TEST_ALWAYS |
1355 RADEON_STENCIL_TEST_ALWAYS |
1356 RADEON_STENCIL_S_FAIL_REPLACE |
1357 RADEON_STENCIL_ZPASS_REPLACE |
1358 RADEON_STENCIL_ZFAIL_REPLACE |
1359 RADEON_Z_WRITE_ENABLE);
1360
1361 dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
1362 RADEON_BFACE_SOLID |
1363 RADEON_FFACE_SOLID |
1364 RADEON_FLAT_SHADE_VTX_LAST |
1365 RADEON_DIFFUSE_SHADE_FLAT |
1366 RADEON_ALPHA_SHADE_FLAT |
1367 RADEON_SPECULAR_SHADE_FLAT |
1368 RADEON_FOG_SHADE_FLAT |
1369 RADEON_VTX_PIX_CENTER_OGL |
1370 RADEON_ROUND_MODE_TRUNC |
1371 RADEON_ROUND_PREC_8TH_PIX);
1372
1373 DRM_GETSAREA();
1374
1375 dev_priv->fb_offset = init->fb_offset;
1376 dev_priv->mmio_offset = init->mmio_offset;
1377 dev_priv->ring_offset = init->ring_offset;
1378 dev_priv->ring_rptr_offset = init->ring_rptr_offset;
1379 dev_priv->buffers_offset = init->buffers_offset;
1380 dev_priv->gart_textures_offset = init->gart_textures_offset;
1381
1382 if(!dev_priv->sarea) {
1383 DRM_ERROR("could not find sarea!\n");
1384 dev->dev_private = (void *)dev_priv;
1385 radeon_do_cleanup_cp(dev);
1386 return DRM_ERR(EINVAL);
1387 }
1388
1389 dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
1390 if(!dev_priv->mmio) {
1391 DRM_ERROR("could not find mmio region!\n");
1392 dev->dev_private = (void *)dev_priv;
1393 radeon_do_cleanup_cp(dev);
1394 return DRM_ERR(EINVAL);
1395 }
1396 dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
1397 if(!dev_priv->cp_ring) {
1398 DRM_ERROR("could not find cp ring region!\n");
1399 dev->dev_private = (void *)dev_priv;
1400 radeon_do_cleanup_cp(dev);
1401 return DRM_ERR(EINVAL);
1402 }
1403 dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
1404 if(!dev_priv->ring_rptr) {
1405 DRM_ERROR("could not find ring read pointer!\n");
1406 dev->dev_private = (void *)dev_priv;
1407 radeon_do_cleanup_cp(dev);
1408 return DRM_ERR(EINVAL);
1409 }
1410 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
1411 if(!dev->agp_buffer_map) {
1412 DRM_ERROR("could not find dma buffer region!\n");
1413 dev->dev_private = (void *)dev_priv;
1414 radeon_do_cleanup_cp(dev);
1415 return DRM_ERR(EINVAL);
1416 }
1417
1418 if ( init->gart_textures_offset ) {
1419 dev_priv->gart_textures = drm_core_findmap(dev, init->gart_textures_offset);
1420 if ( !dev_priv->gart_textures ) {
1421 DRM_ERROR("could not find GART texture region!\n");
1422 dev->dev_private = (void *)dev_priv;
1423 radeon_do_cleanup_cp(dev);
1424 return DRM_ERR(EINVAL);
1425 }
1426 }
1427
1428 dev_priv->sarea_priv =
1429 (drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
1430 init->sarea_priv_offset);
1431
1432#if __OS_HAS_AGP
1433 if ( !dev_priv->is_pci ) {
1434 drm_core_ioremap( dev_priv->cp_ring, dev );
1435 drm_core_ioremap( dev_priv->ring_rptr, dev );
1436 drm_core_ioremap( dev->agp_buffer_map, dev );
1437 if(!dev_priv->cp_ring->handle ||
1438 !dev_priv->ring_rptr->handle ||
1439 !dev->agp_buffer_map->handle) {
1440 DRM_ERROR("could not find ioremap agp regions!\n");
1441 dev->dev_private = (void *)dev_priv;
1442 radeon_do_cleanup_cp(dev);
1443 return DRM_ERR(EINVAL);
1444 }
1445 } else
1446#endif
1447 {
1448 dev_priv->cp_ring->handle =
1449 (void *)dev_priv->cp_ring->offset;
1450 dev_priv->ring_rptr->handle =
1451 (void *)dev_priv->ring_rptr->offset;
1452 dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset;
1453
1454 DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
1455 dev_priv->cp_ring->handle );
1456 DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
1457 dev_priv->ring_rptr->handle );
1458 DRM_DEBUG( "dev->agp_buffer_map->handle %p\n",
1459 dev->agp_buffer_map->handle );
1460 }
1461
1462 dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION )
1463 & 0xffff ) << 16;
1464
1465 dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
1466 ( ( dev_priv->front_offset
1467 + dev_priv->fb_location ) >> 10 ) );
1468
1469 dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
1470 ( ( dev_priv->back_offset
1471 + dev_priv->fb_location ) >> 10 ) );
1472
1473 dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
1474 ( ( dev_priv->depth_offset
1475 + dev_priv->fb_location ) >> 10 ) );
1476
1477
1478 dev_priv->gart_size = init->gart_size;
1479 dev_priv->gart_vm_start = dev_priv->fb_location
1480 + RADEON_READ( RADEON_CONFIG_APER_SIZE );
1481
1482#if __OS_HAS_AGP
1483 if ( !dev_priv->is_pci )
1484 dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
1485 - dev->agp->base
1486 + dev_priv->gart_vm_start);
1487 else
1488#endif
1489 dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
1490 - dev->sg->handle
1491 + dev_priv->gart_vm_start);
1492
1493 DRM_DEBUG( "dev_priv->gart_size %d\n",
1494 dev_priv->gart_size );
1495 DRM_DEBUG( "dev_priv->gart_vm_start 0x%x\n",
1496 dev_priv->gart_vm_start );
1497 DRM_DEBUG( "dev_priv->gart_buffers_offset 0x%lx\n",
1498 dev_priv->gart_buffers_offset );
1499
1500 dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle;
1501 dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
1502 + init->ring_size / sizeof(u32));
1503 dev_priv->ring.size = init->ring_size;
1504 dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
1505
1506 dev_priv->ring.tail_mask =
1507 (dev_priv->ring.size / sizeof(u32)) - 1;
1508
1509 dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
1510
1511#if __OS_HAS_AGP
1512 if ( !dev_priv->is_pci ) {
1513 /* Turn off PCI GART */
1514 radeon_set_pcigart( dev_priv, 0 );
1515 } else
1516#endif
1517 {
1518 if (!drm_ati_pcigart_init( dev, &dev_priv->phys_pci_gart,
1519 &dev_priv->bus_pci_gart)) {
1520 DRM_ERROR( "failed to init PCI GART!\n" );
1521 dev->dev_private = (void *)dev_priv;
1522 radeon_do_cleanup_cp(dev);
1523 return DRM_ERR(ENOMEM);
1524 }
1525
1526 /* Turn on PCI GART */
1527 radeon_set_pcigart( dev_priv, 1 );
1528 }
1529
1530 radeon_cp_load_microcode( dev_priv );
1531 radeon_cp_init_ring_buffer( dev, dev_priv );
1532
1533 dev_priv->last_buf = 0;
1534
1535 dev->dev_private = (void *)dev_priv;
1536
1537 radeon_do_engine_reset( dev );
1538
1539 return 0;
1540}
1541
1542static int radeon_do_cleanup_cp( drm_device_t *dev )
1543{
1544 drm_radeon_private_t *dev_priv = dev->dev_private;
1545 DRM_DEBUG( "\n" );
1546
1547 /* Make sure interrupts are disabled here because the uninstall ioctl
1548 * may not have been called from userspace and after dev_private
1549 * is freed, it's too late.
1550 */
1551 if ( dev->irq_enabled ) drm_irq_uninstall(dev);
1552
1553#if __OS_HAS_AGP
1554 if ( !dev_priv->is_pci ) {
1555 if ( dev_priv->cp_ring != NULL )
1556 drm_core_ioremapfree( dev_priv->cp_ring, dev );
1557 if ( dev_priv->ring_rptr != NULL )
1558 drm_core_ioremapfree( dev_priv->ring_rptr, dev );
1559 if ( dev->agp_buffer_map != NULL )
1560 {
1561 drm_core_ioremapfree( dev->agp_buffer_map, dev );
1562 dev->agp_buffer_map = NULL;
1563 }
1564 } else
1565#endif
1566 {
1567 if (!drm_ati_pcigart_cleanup( dev,
1568 dev_priv->phys_pci_gart,
1569 dev_priv->bus_pci_gart ))
1570 DRM_ERROR( "failed to cleanup PCI GART!\n" );
1571 }
1572
1573 /* only clear to the start of flags */
1574 memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
1575
1576 return 0;
1577}
1578
1579/* This code will reinit the Radeon CP hardware after a resume from disc.
1580 * AFAIK, it would be very difficult to pickle the state at suspend time, so
1581 * here we make sure that all Radeon hardware initialisation is re-done without
1582 * affecting running applications.
1583 *
1584 * Charl P. Botha <http://cpbotha.net>
1585 */
1586static int radeon_do_resume_cp( drm_device_t *dev )
1587{
1588 drm_radeon_private_t *dev_priv = dev->dev_private;
1589
1590 if ( !dev_priv ) {
1591 DRM_ERROR( "Called with no initialization\n" );
1592 return DRM_ERR( EINVAL );
1593 }
1594
1595 DRM_DEBUG("Starting radeon_do_resume_cp()\n");
1596
1597#if __OS_HAS_AGP
1598 if ( !dev_priv->is_pci ) {
1599 /* Turn off PCI GART */
1600 radeon_set_pcigart( dev_priv, 0 );
1601 } else
1602#endif
1603 {
1604 /* Turn on PCI GART */
1605 radeon_set_pcigart( dev_priv, 1 );
1606 }
1607
1608 radeon_cp_load_microcode( dev_priv );
1609 radeon_cp_init_ring_buffer( dev, dev_priv );
1610
1611 radeon_do_engine_reset( dev );
1612
1613 DRM_DEBUG("radeon_do_resume_cp() complete\n");
1614
1615 return 0;
1616}
1617
1618
1619int radeon_cp_init( DRM_IOCTL_ARGS )
1620{
1621 DRM_DEVICE;
1622 drm_radeon_init_t init;
1623
1624 LOCK_TEST_WITH_RETURN( dev, filp );
1625
1626 DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t __user *)data, sizeof(init) );
1627
1628 switch ( init.func ) {
1629 case RADEON_INIT_CP:
1630 case RADEON_INIT_R200_CP:
1631 case RADEON_INIT_R300_CP:
1632 return radeon_do_init_cp( dev, &init );
1633 case RADEON_CLEANUP_CP:
1634 return radeon_do_cleanup_cp( dev );
1635 }
1636
1637 return DRM_ERR(EINVAL);
1638}
1639
1640int radeon_cp_start( DRM_IOCTL_ARGS )
1641{
1642 DRM_DEVICE;
1643 drm_radeon_private_t *dev_priv = dev->dev_private;
1644 DRM_DEBUG( "\n" );
1645
1646 LOCK_TEST_WITH_RETURN( dev, filp );
1647
1648 if ( dev_priv->cp_running ) {
1649 DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
1650 return 0;
1651 }
1652 if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) {
1653 DRM_DEBUG( "%s called with bogus CP mode (%d)\n",
1654 __FUNCTION__, dev_priv->cp_mode );
1655 return 0;
1656 }
1657
1658 radeon_do_cp_start( dev_priv );
1659
1660 return 0;
1661}
1662
1663/* Stop the CP. The engine must have been idled before calling this
1664 * routine.
1665 */
1666int radeon_cp_stop( DRM_IOCTL_ARGS )
1667{
1668 DRM_DEVICE;
1669 drm_radeon_private_t *dev_priv = dev->dev_private;
1670 drm_radeon_cp_stop_t stop;
1671 int ret;
1672 DRM_DEBUG( "\n" );
1673
1674 LOCK_TEST_WITH_RETURN( dev, filp );
1675
1676 DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t __user *)data, sizeof(stop) );
1677
1678 if (!dev_priv->cp_running)
1679 return 0;
1680
1681 /* Flush any pending CP commands. This ensures any outstanding
1682 * commands are exectuted by the engine before we turn it off.
1683 */
1684 if ( stop.flush ) {
1685 radeon_do_cp_flush( dev_priv );
1686 }
1687
1688 /* If we fail to make the engine go idle, we return an error
1689 * code so that the DRM ioctl wrapper can try again.
1690 */
1691 if ( stop.idle ) {
1692 ret = radeon_do_cp_idle( dev_priv );
1693 if ( ret ) return ret;
1694 }
1695
1696 /* Finally, we can turn off the CP. If the engine isn't idle,
1697 * we will get some dropped triangles as they won't be fully
1698 * rendered before the CP is shut down.
1699 */
1700 radeon_do_cp_stop( dev_priv );
1701
1702 /* Reset the engine */
1703 radeon_do_engine_reset( dev );
1704
1705 return 0;
1706}
1707
1708
1709void radeon_do_release( drm_device_t *dev )
1710{
1711 drm_radeon_private_t *dev_priv = dev->dev_private;
1712 int i, ret;
1713
1714 if (dev_priv) {
1715 if (dev_priv->cp_running) {
1716 /* Stop the cp */
1717 while ((ret = radeon_do_cp_idle( dev_priv )) != 0) {
1718 DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
1719#ifdef __linux__
1720 schedule();
1721#else
1722 tsleep(&ret, PZERO, "rdnrel", 1);
1723#endif
1724 }
1725 radeon_do_cp_stop( dev_priv );
1726 radeon_do_engine_reset( dev );
1727 }
1728
1729 /* Disable *all* interrupts */
1730 if (dev_priv->mmio) /* remove this after permanent addmaps */
1731 RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
1732
1733 if (dev_priv->mmio) {/* remove all surfaces */
1734 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1735 RADEON_WRITE(RADEON_SURFACE0_INFO + 16*i, 0);
1736 RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16*i, 0);
1737 RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16*i, 0);
1738 }
1739 }
1740
1741 /* Free memory heap structures */
1742 radeon_mem_takedown( &(dev_priv->gart_heap) );
1743 radeon_mem_takedown( &(dev_priv->fb_heap) );
1744
1745 /* deallocate kernel resources */
1746 radeon_do_cleanup_cp( dev );
1747 }
1748}
1749
1750/* Just reset the CP ring. Called as part of an X Server engine reset.
1751 */
1752int radeon_cp_reset( DRM_IOCTL_ARGS )
1753{
1754 DRM_DEVICE;
1755 drm_radeon_private_t *dev_priv = dev->dev_private;
1756 DRM_DEBUG( "\n" );
1757
1758 LOCK_TEST_WITH_RETURN( dev, filp );
1759
1760 if ( !dev_priv ) {
1761 DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
1762 return DRM_ERR(EINVAL);
1763 }
1764
1765 radeon_do_cp_reset( dev_priv );
1766
1767 /* The CP is no longer running after an engine reset */
1768 dev_priv->cp_running = 0;
1769
1770 return 0;
1771}
1772
1773int radeon_cp_idle( DRM_IOCTL_ARGS )
1774{
1775 DRM_DEVICE;
1776 drm_radeon_private_t *dev_priv = dev->dev_private;
1777 DRM_DEBUG( "\n" );
1778
1779 LOCK_TEST_WITH_RETURN( dev, filp );
1780
1781 return radeon_do_cp_idle( dev_priv );
1782}
1783
1784/* Added by Charl P. Botha to call radeon_do_resume_cp().
1785 */
1786int radeon_cp_resume( DRM_IOCTL_ARGS )
1787{
1788 DRM_DEVICE;
1789
1790 return radeon_do_resume_cp(dev);
1791}
1792
1793
1794int radeon_engine_reset( DRM_IOCTL_ARGS )
1795{
1796 DRM_DEVICE;
1797 DRM_DEBUG( "\n" );
1798
1799 LOCK_TEST_WITH_RETURN( dev, filp );
1800
1801 return radeon_do_engine_reset( dev );
1802}
1803
1804
1805/* ================================================================
1806 * Fullscreen mode
1807 */
1808
1809/* KW: Deprecated to say the least:
1810 */
1811int radeon_fullscreen( DRM_IOCTL_ARGS )
1812{
1813 return 0;
1814}
1815
1816
1817/* ================================================================
1818 * Freelist management
1819 */
1820
1821/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
1822 * bufs until freelist code is used. Note this hides a problem with
1823 * the scratch register * (used to keep track of last buffer
1824 * completed) being written to before * the last buffer has actually
1825 * completed rendering.
1826 *
1827 * KW: It's also a good way to find free buffers quickly.
1828 *
1829 * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
1830 * sleep. However, bugs in older versions of radeon_accel.c mean that
1831 * we essentially have to do this, else old clients will break.
1832 *
1833 * However, it does leave open a potential deadlock where all the
1834 * buffers are held by other clients, which can't release them because
1835 * they can't get the lock.
1836 */
1837
1838drm_buf_t *radeon_freelist_get( drm_device_t *dev )
1839{
1840 drm_device_dma_t *dma = dev->dma;
1841 drm_radeon_private_t *dev_priv = dev->dev_private;
1842 drm_radeon_buf_priv_t *buf_priv;
1843 drm_buf_t *buf;
1844 int i, t;
1845 int start;
1846
1847 if ( ++dev_priv->last_buf >= dma->buf_count )
1848 dev_priv->last_buf = 0;
1849
1850 start = dev_priv->last_buf;
1851
1852 for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
1853 u32 done_age = GET_SCRATCH( 1 );
1854 DRM_DEBUG("done_age = %d\n",done_age);
1855 for ( i = start ; i < dma->buf_count ; i++ ) {
1856 buf = dma->buflist[i];
1857 buf_priv = buf->dev_private;
1858 if ( buf->filp == 0 || (buf->pending &&
1859 buf_priv->age <= done_age) ) {
1860 dev_priv->stats.requested_bufs++;
1861 buf->pending = 0;
1862 return buf;
1863 }
1864 start = 0;
1865 }
1866
1867 if (t) {
1868 DRM_UDELAY( 1 );
1869 dev_priv->stats.freelist_loops++;
1870 }
1871 }
1872
1873 DRM_DEBUG( "returning NULL!\n" );
1874 return NULL;
1875}
1876#if 0
1877drm_buf_t *radeon_freelist_get( drm_device_t *dev )
1878{
1879 drm_device_dma_t *dma = dev->dma;
1880 drm_radeon_private_t *dev_priv = dev->dev_private;
1881 drm_radeon_buf_priv_t *buf_priv;
1882 drm_buf_t *buf;
1883 int i, t;
1884 int start;
1885 u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
1886
1887 if ( ++dev_priv->last_buf >= dma->buf_count )
1888 dev_priv->last_buf = 0;
1889
1890 start = dev_priv->last_buf;
1891 dev_priv->stats.freelist_loops++;
1892
1893 for ( t = 0 ; t < 2 ; t++ ) {
1894 for ( i = start ; i < dma->buf_count ; i++ ) {
1895 buf = dma->buflist[i];
1896 buf_priv = buf->dev_private;
1897 if ( buf->filp == 0 || (buf->pending &&
1898 buf_priv->age <= done_age) ) {
1899 dev_priv->stats.requested_bufs++;
1900 buf->pending = 0;
1901 return buf;
1902 }
1903 }
1904 start = 0;
1905 }
1906
1907 return NULL;
1908}
1909#endif
1910
1911void radeon_freelist_reset( drm_device_t *dev )
1912{
1913 drm_device_dma_t *dma = dev->dma;
1914 drm_radeon_private_t *dev_priv = dev->dev_private;
1915 int i;
1916
1917 dev_priv->last_buf = 0;
1918 for ( i = 0 ; i < dma->buf_count ; i++ ) {
1919 drm_buf_t *buf = dma->buflist[i];
1920 drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
1921 buf_priv->age = 0;
1922 }
1923}
1924
1925
1926/* ================================================================
1927 * CP command submission
1928 */
1929
1930int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
1931{
1932 drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
1933 int i;
1934 u32 last_head = GET_RING_HEAD( dev_priv );
1935
1936 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
1937 u32 head = GET_RING_HEAD( dev_priv );
1938
1939 ring->space = (head - ring->tail) * sizeof(u32);
1940 if ( ring->space <= 0 )
1941 ring->space += ring->size;
1942 if ( ring->space > n )
1943 return 0;
1944
1945 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
1946
1947 if (head != last_head)
1948 i = 0;
1949 last_head = head;
1950
1951 DRM_UDELAY( 1 );
1952 }
1953
1954 /* FIXME: This return value is ignored in the BEGIN_RING macro! */
1955#if RADEON_FIFO_DEBUG
1956 radeon_status( dev_priv );
1957 DRM_ERROR( "failed!\n" );
1958#endif
1959 return DRM_ERR(EBUSY);
1960}
1961
1962static int radeon_cp_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d )
1963{
1964 int i;
1965 drm_buf_t *buf;
1966
1967 for ( i = d->granted_count ; i < d->request_count ; i++ ) {
1968 buf = radeon_freelist_get( dev );
1969 if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */
1970
1971 buf->filp = filp;
1972
1973 if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
1974 sizeof(buf->idx) ) )
1975 return DRM_ERR(EFAULT);
1976 if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
1977 sizeof(buf->total) ) )
1978 return DRM_ERR(EFAULT);
1979
1980 d->granted_count++;
1981 }
1982 return 0;
1983}
1984
1985int radeon_cp_buffers( DRM_IOCTL_ARGS )
1986{
1987 DRM_DEVICE;
1988 drm_device_dma_t *dma = dev->dma;
1989 int ret = 0;
1990 drm_dma_t __user *argp = (void __user *)data;
1991 drm_dma_t d;
1992
1993 LOCK_TEST_WITH_RETURN( dev, filp );
1994
1995 DRM_COPY_FROM_USER_IOCTL( d, argp, sizeof(d) );
1996
1997 /* Please don't send us buffers.
1998 */
1999 if ( d.send_count != 0 ) {
2000 DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
2001 DRM_CURRENTPID, d.send_count );
2002 return DRM_ERR(EINVAL);
2003 }
2004
2005 /* We'll send you buffers.
2006 */
2007 if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
2008 DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
2009 DRM_CURRENTPID, d.request_count, dma->buf_count );
2010 return DRM_ERR(EINVAL);
2011 }
2012
2013 d.granted_count = 0;
2014
2015 if ( d.request_count ) {
2016 ret = radeon_cp_get_buffers( filp, dev, &d );
2017 }
2018
2019 DRM_COPY_TO_USER_IOCTL( argp, d, sizeof(d) );
2020
2021 return ret;
2022}
2023
2024int radeon_driver_preinit(struct drm_device *dev, unsigned long flags)
2025{
2026 drm_radeon_private_t *dev_priv;
2027 int ret = 0;
2028
2029 dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER);
2030 if (dev_priv == NULL)
2031 return DRM_ERR(ENOMEM);
2032
2033 memset(dev_priv, 0, sizeof(drm_radeon_private_t));
2034 dev->dev_private = (void *)dev_priv;
2035 dev_priv->flags = flags;
2036
2037 switch (flags & CHIP_FAMILY_MASK) {
2038 case CHIP_R100:
2039 case CHIP_RV200:
2040 case CHIP_R200:
2041 case CHIP_R300:
2042 dev_priv->flags |= CHIP_HAS_HIERZ;
2043 break;
2044 default:
2045 /* all other chips have no hierarchical z buffer */
2046 break;
2047 }
2048 return ret;
2049}
2050
2051int radeon_driver_postcleanup(struct drm_device *dev)
2052{
2053 drm_radeon_private_t *dev_priv = dev->dev_private;
2054
2055 DRM_DEBUG("\n");
2056
2057 drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
2058
2059 dev->dev_private = NULL;
2060 return 0;
2061}
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
new file mode 100644
index 000000000000..c1e62d047989
--- /dev/null
+++ b/drivers/char/drm/radeon_drm.h
@@ -0,0 +1,659 @@
1/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*-
2 *
3 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
4 * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
5 * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Kevin E. Martin <martin@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 * Keith Whitwell <keith@tungstengraphics.com>
31 */
32
33#ifndef __RADEON_DRM_H__
34#define __RADEON_DRM_H__
35
36/* WARNING: If you change any of these defines, make sure to change the
37 * defines in the X server file (radeon_sarea.h)
38 */
39#ifndef __RADEON_SAREA_DEFINES__
40#define __RADEON_SAREA_DEFINES__
41
42/* Old style state flags, required for sarea interface (1.1 and 1.2
43 * clears) and 1.2 drm_vertex2 ioctl.
44 */
45#define RADEON_UPLOAD_CONTEXT 0x00000001
46#define RADEON_UPLOAD_VERTFMT 0x00000002
47#define RADEON_UPLOAD_LINE 0x00000004
48#define RADEON_UPLOAD_BUMPMAP 0x00000008
49#define RADEON_UPLOAD_MASKS 0x00000010
50#define RADEON_UPLOAD_VIEWPORT 0x00000020
51#define RADEON_UPLOAD_SETUP 0x00000040
52#define RADEON_UPLOAD_TCL 0x00000080
53#define RADEON_UPLOAD_MISC 0x00000100
54#define RADEON_UPLOAD_TEX0 0x00000200
55#define RADEON_UPLOAD_TEX1 0x00000400
56#define RADEON_UPLOAD_TEX2 0x00000800
57#define RADEON_UPLOAD_TEX0IMAGES 0x00001000
58#define RADEON_UPLOAD_TEX1IMAGES 0x00002000
59#define RADEON_UPLOAD_TEX2IMAGES 0x00004000
60#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */
61#define RADEON_REQUIRE_QUIESCENCE 0x00010000
62#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */
63#define RADEON_UPLOAD_ALL 0x003effff
64#define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff
65
66
67/* New style per-packet identifiers for use in cmd_buffer ioctl with
68 * the RADEON_EMIT_PACKET command. Comments relate new packets to old
69 * state bits and the packet size:
70 */
71#define RADEON_EMIT_PP_MISC 0 /* context/7 */
72#define RADEON_EMIT_PP_CNTL 1 /* context/3 */
73#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */
74#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */
75#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */
76#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */
77#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */
78#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */
79#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */
80#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */
81#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */
82#define RADEON_EMIT_RE_MISC 11 /* misc/1 */
83#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */
84#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */
85#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */
86#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */
87#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */
88#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */
89#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */
90#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */
91#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */
92#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */
93#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */
94#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */
95#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */
96#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */
97#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */
98#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */
99#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */
100#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */
101#define R200_EMIT_TFACTOR_0 30 /* tf/7 */
102#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */
103#define R200_EMIT_VAP_CTL 32 /* vap/1 */
104#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */
105#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */
106#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */
107#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */
108#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */
109#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */
110#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */
111#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */
112#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */
113#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */
114#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */
115#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */
116#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */
117#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */
118#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */
119#define R200_EMIT_VTE_CNTL 48 /* vte/1 */
120#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */
121#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */
122#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */
123#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */
124#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */
125#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */
126#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */
127#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */
128#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */
129#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */
130#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */
131#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */
132#define R200_EMIT_PP_CUBIC_FACES_0 61
133#define R200_EMIT_PP_CUBIC_OFFSETS_0 62
134#define R200_EMIT_PP_CUBIC_FACES_1 63
135#define R200_EMIT_PP_CUBIC_OFFSETS_1 64
136#define R200_EMIT_PP_CUBIC_FACES_2 65
137#define R200_EMIT_PP_CUBIC_OFFSETS_2 66
138#define R200_EMIT_PP_CUBIC_FACES_3 67
139#define R200_EMIT_PP_CUBIC_OFFSETS_3 68
140#define R200_EMIT_PP_CUBIC_FACES_4 69
141#define R200_EMIT_PP_CUBIC_OFFSETS_4 70
142#define R200_EMIT_PP_CUBIC_FACES_5 71
143#define R200_EMIT_PP_CUBIC_OFFSETS_5 72
144#define RADEON_EMIT_PP_TEX_SIZE_0 73
145#define RADEON_EMIT_PP_TEX_SIZE_1 74
146#define RADEON_EMIT_PP_TEX_SIZE_2 75
147#define R200_EMIT_RB3D_BLENDCOLOR 76
148#define R200_EMIT_TCL_POINT_SPRITE_CNTL 77
149#define RADEON_EMIT_PP_CUBIC_FACES_0 78
150#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0 79
151#define RADEON_EMIT_PP_CUBIC_FACES_1 80
152#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1 81
153#define RADEON_EMIT_PP_CUBIC_FACES_2 82
154#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2 83
155#define R200_EMIT_PP_TRI_PERF_CNTL 84
156#define RADEON_MAX_STATE_PACKETS 85
157
158/* Commands understood by cmd_buffer ioctl. More can be added but
159 * obviously these can't be removed or changed:
160 */
161#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */
162#define RADEON_CMD_SCALARS 2 /* emit scalar data */
163#define RADEON_CMD_VECTORS 3 /* emit vector data */
164#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
165#define RADEON_CMD_PACKET3 5 /* emit hw packet */
166#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
167#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */
168#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note:
169 * doesn't make the cpu wait, just
170 * the graphics hardware */
171
172
173typedef union {
174 int i;
175 struct {
176 unsigned char cmd_type, pad0, pad1, pad2;
177 } header;
178 struct {
179 unsigned char cmd_type, packet_id, pad0, pad1;
180 } packet;
181 struct {
182 unsigned char cmd_type, offset, stride, count;
183 } scalars;
184 struct {
185 unsigned char cmd_type, offset, stride, count;
186 } vectors;
187 struct {
188 unsigned char cmd_type, buf_idx, pad0, pad1;
189 } dma;
190 struct {
191 unsigned char cmd_type, flags, pad0, pad1;
192 } wait;
193} drm_radeon_cmd_header_t;
194
195#define RADEON_WAIT_2D 0x1
196#define RADEON_WAIT_3D 0x2
197
198
199#define RADEON_FRONT 0x1
200#define RADEON_BACK 0x2
201#define RADEON_DEPTH 0x4
202#define RADEON_STENCIL 0x8
203#define RADEON_CLEAR_FASTZ 0x80000000
204#define RADEON_USE_HIERZ 0x40000000
205#define RADEON_USE_COMP_ZBUF 0x20000000
206
207/* Primitive types
208 */
209#define RADEON_POINTS 0x1
210#define RADEON_LINES 0x2
211#define RADEON_LINE_STRIP 0x3
212#define RADEON_TRIANGLES 0x4
213#define RADEON_TRIANGLE_FAN 0x5
214#define RADEON_TRIANGLE_STRIP 0x6
215
216/* Vertex/indirect buffer size
217 */
218#define RADEON_BUFFER_SIZE 65536
219
220/* Byte offsets for indirect buffer data
221 */
222#define RADEON_INDEX_PRIM_OFFSET 20
223
224#define RADEON_SCRATCH_REG_OFFSET 32
225
226#define RADEON_NR_SAREA_CLIPRECTS 12
227
228/* There are 2 heaps (local/GART). Each region within a heap is a
229 * minimum of 64k, and there are at most 64 of them per heap.
230 */
231#define RADEON_LOCAL_TEX_HEAP 0
232#define RADEON_GART_TEX_HEAP 1
233#define RADEON_NR_TEX_HEAPS 2
234#define RADEON_NR_TEX_REGIONS 64
235#define RADEON_LOG_TEX_GRANULARITY 16
236
237#define RADEON_MAX_TEXTURE_LEVELS 12
238#define RADEON_MAX_TEXTURE_UNITS 3
239
240#define RADEON_MAX_SURFACES 8
241
242/* Blits have strict offset rules. All blit offset must be aligned on
243 * a 1K-byte boundary.
244 */
245#define RADEON_OFFSET_SHIFT 10
246#define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT)
247#define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1)
248
249#endif /* __RADEON_SAREA_DEFINES__ */
250
251typedef struct {
252 unsigned int red;
253 unsigned int green;
254 unsigned int blue;
255 unsigned int alpha;
256} radeon_color_regs_t;
257
258typedef struct {
259 /* Context state */
260 unsigned int pp_misc; /* 0x1c14 */
261 unsigned int pp_fog_color;
262 unsigned int re_solid_color;
263 unsigned int rb3d_blendcntl;
264 unsigned int rb3d_depthoffset;
265 unsigned int rb3d_depthpitch;
266 unsigned int rb3d_zstencilcntl;
267
268 unsigned int pp_cntl; /* 0x1c38 */
269 unsigned int rb3d_cntl;
270 unsigned int rb3d_coloroffset;
271 unsigned int re_width_height;
272 unsigned int rb3d_colorpitch;
273 unsigned int se_cntl;
274
275 /* Vertex format state */
276 unsigned int se_coord_fmt; /* 0x1c50 */
277
278 /* Line state */
279 unsigned int re_line_pattern; /* 0x1cd0 */
280 unsigned int re_line_state;
281
282 unsigned int se_line_width; /* 0x1db8 */
283
284 /* Bumpmap state */
285 unsigned int pp_lum_matrix; /* 0x1d00 */
286
287 unsigned int pp_rot_matrix_0; /* 0x1d58 */
288 unsigned int pp_rot_matrix_1;
289
290 /* Mask state */
291 unsigned int rb3d_stencilrefmask; /* 0x1d7c */
292 unsigned int rb3d_ropcntl;
293 unsigned int rb3d_planemask;
294
295 /* Viewport state */
296 unsigned int se_vport_xscale; /* 0x1d98 */
297 unsigned int se_vport_xoffset;
298 unsigned int se_vport_yscale;
299 unsigned int se_vport_yoffset;
300 unsigned int se_vport_zscale;
301 unsigned int se_vport_zoffset;
302
303 /* Setup state */
304 unsigned int se_cntl_status; /* 0x2140 */
305
306 /* Misc state */
307 unsigned int re_top_left; /* 0x26c0 */
308 unsigned int re_misc;
309} drm_radeon_context_regs_t;
310
311typedef struct {
312 /* Zbias state */
313 unsigned int se_zbias_factor; /* 0x1dac */
314 unsigned int se_zbias_constant;
315} drm_radeon_context2_regs_t;
316
317
318/* Setup registers for each texture unit
319 */
320typedef struct {
321 unsigned int pp_txfilter;
322 unsigned int pp_txformat;
323 unsigned int pp_txoffset;
324 unsigned int pp_txcblend;
325 unsigned int pp_txablend;
326 unsigned int pp_tfactor;
327 unsigned int pp_border_color;
328} drm_radeon_texture_regs_t;
329
330typedef struct {
331 unsigned int start;
332 unsigned int finish;
333 unsigned int prim:8;
334 unsigned int stateidx:8;
335 unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
336 unsigned int vc_format; /* vertex format */
337} drm_radeon_prim_t;
338
339
340typedef struct {
341 drm_radeon_context_regs_t context;
342 drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS];
343 drm_radeon_context2_regs_t context2;
344 unsigned int dirty;
345} drm_radeon_state_t;
346
347
348typedef struct {
349 /* The channel for communication of state information to the
350 * kernel on firing a vertex buffer with either of the
351 * obsoleted vertex/index ioctls.
352 */
353 drm_radeon_context_regs_t context_state;
354 drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS];
355 unsigned int dirty;
356 unsigned int vertsize;
357 unsigned int vc_format;
358
359 /* The current cliprects, or a subset thereof.
360 */
361 drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS];
362 unsigned int nbox;
363
364 /* Counters for client-side throttling of rendering clients.
365 */
366 unsigned int last_frame;
367 unsigned int last_dispatch;
368 unsigned int last_clear;
369
370 drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
371 unsigned int tex_age[RADEON_NR_TEX_HEAPS];
372 int ctx_owner;
373 int pfState; /* number of 3d windows (0,1,2ormore) */
374 int pfCurrentPage; /* which buffer is being displayed? */
375 int crtc2_base; /* CRTC2 frame offset */
376 int tiling_enabled; /* set by drm, read by 2d + 3d clients */
377} drm_radeon_sarea_t;
378
379
380/* WARNING: If you change any of these defines, make sure to change the
381 * defines in the Xserver file (xf86drmRadeon.h)
382 *
383 * KW: actually it's illegal to change any of this (backwards compatibility).
384 */
385
386/* Radeon specific ioctls
387 * The device specific ioctl range is 0x40 to 0x79.
388 */
389#define DRM_RADEON_CP_INIT 0x00
390#define DRM_RADEON_CP_START 0x01
391#define DRM_RADEON_CP_STOP 0x02
392#define DRM_RADEON_CP_RESET 0x03
393#define DRM_RADEON_CP_IDLE 0x04
394#define DRM_RADEON_RESET 0x05
395#define DRM_RADEON_FULLSCREEN 0x06
396#define DRM_RADEON_SWAP 0x07
397#define DRM_RADEON_CLEAR 0x08
398#define DRM_RADEON_VERTEX 0x09
399#define DRM_RADEON_INDICES 0x0A
400#define DRM_RADEON_NOT_USED
401#define DRM_RADEON_STIPPLE 0x0C
402#define DRM_RADEON_INDIRECT 0x0D
403#define DRM_RADEON_TEXTURE 0x0E
404#define DRM_RADEON_VERTEX2 0x0F
405#define DRM_RADEON_CMDBUF 0x10
406#define DRM_RADEON_GETPARAM 0x11
407#define DRM_RADEON_FLIP 0x12
408#define DRM_RADEON_ALLOC 0x13
409#define DRM_RADEON_FREE 0x14
410#define DRM_RADEON_INIT_HEAP 0x15
411#define DRM_RADEON_IRQ_EMIT 0x16
412#define DRM_RADEON_IRQ_WAIT 0x17
413#define DRM_RADEON_CP_RESUME 0x18
414#define DRM_RADEON_SETPARAM 0x19
415#define DRM_RADEON_SURF_ALLOC 0x1a
416#define DRM_RADEON_SURF_FREE 0x1b
417
418#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
419#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START)
420#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t)
421#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESET)
422#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE)
423#define DRM_IOCTL_RADEON_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_RESET)
424#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t)
425#define DRM_IOCTL_RADEON_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_SWAP)
426#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t)
427#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t)
428#define DRM_IOCTL_RADEON_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t)
429#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t)
430#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t)
431#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t)
432#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t)
433#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t)
434#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t)
435#define DRM_IOCTL_RADEON_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_FLIP)
436#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t)
437#define DRM_IOCTL_RADEON_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t)
438#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t)
439#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t)
440#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t)
441#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME)
442#define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t)
443#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t)
444#define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t)
445
446typedef struct drm_radeon_init {
447 enum {
448 RADEON_INIT_CP = 0x01,
449 RADEON_CLEANUP_CP = 0x02,
450 RADEON_INIT_R200_CP = 0x03,
451 RADEON_INIT_R300_CP = 0x04
452 } func;
453 unsigned long sarea_priv_offset;
454 int is_pci;
455 int cp_mode;
456 int gart_size;
457 int ring_size;
458 int usec_timeout;
459
460 unsigned int fb_bpp;
461 unsigned int front_offset, front_pitch;
462 unsigned int back_offset, back_pitch;
463 unsigned int depth_bpp;
464 unsigned int depth_offset, depth_pitch;
465
466 unsigned long fb_offset;
467 unsigned long mmio_offset;
468 unsigned long ring_offset;
469 unsigned long ring_rptr_offset;
470 unsigned long buffers_offset;
471 unsigned long gart_textures_offset;
472} drm_radeon_init_t;
473
474typedef struct drm_radeon_cp_stop {
475 int flush;
476 int idle;
477} drm_radeon_cp_stop_t;
478
479typedef struct drm_radeon_fullscreen {
480 enum {
481 RADEON_INIT_FULLSCREEN = 0x01,
482 RADEON_CLEANUP_FULLSCREEN = 0x02
483 } func;
484} drm_radeon_fullscreen_t;
485
486#define CLEAR_X1 0
487#define CLEAR_Y1 1
488#define CLEAR_X2 2
489#define CLEAR_Y2 3
490#define CLEAR_DEPTH 4
491
492typedef union drm_radeon_clear_rect {
493 float f[5];
494 unsigned int ui[5];
495} drm_radeon_clear_rect_t;
496
497typedef struct drm_radeon_clear {
498 unsigned int flags;
499 unsigned int clear_color;
500 unsigned int clear_depth;
501 unsigned int color_mask;
502 unsigned int depth_mask; /* misnamed field: should be stencil */
503 drm_radeon_clear_rect_t __user *depth_boxes;
504} drm_radeon_clear_t;
505
506typedef struct drm_radeon_vertex {
507 int prim;
508 int idx; /* Index of vertex buffer */
509 int count; /* Number of vertices in buffer */
510 int discard; /* Client finished with buffer? */
511} drm_radeon_vertex_t;
512
513typedef struct drm_radeon_indices {
514 int prim;
515 int idx;
516 int start;
517 int end;
518 int discard; /* Client finished with buffer? */
519} drm_radeon_indices_t;
520
521/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices
522 * - allows multiple primitives and state changes in a single ioctl
523 * - supports driver change to emit native primitives
524 */
525typedef struct drm_radeon_vertex2 {
526 int idx; /* Index of vertex buffer */
527 int discard; /* Client finished with buffer? */
528 int nr_states;
529 drm_radeon_state_t __user *state;
530 int nr_prims;
531 drm_radeon_prim_t __user *prim;
532} drm_radeon_vertex2_t;
533
534/* v1.3 - obsoletes drm_radeon_vertex2
535 * - allows arbitarily large cliprect list
536 * - allows updating of tcl packet, vector and scalar state
537 * - allows memory-efficient description of state updates
538 * - allows state to be emitted without a primitive
539 * (for clears, ctx switches)
540 * - allows more than one dma buffer to be referenced per ioctl
541 * - supports tcl driver
542 * - may be extended in future versions with new cmd types, packets
543 */
544typedef struct drm_radeon_cmd_buffer {
545 int bufsz;
546 char __user *buf;
547 int nbox;
548 drm_clip_rect_t __user *boxes;
549} drm_radeon_cmd_buffer_t;
550
551typedef struct drm_radeon_tex_image {
552 unsigned int x, y; /* Blit coordinates */
553 unsigned int width, height;
554 const void __user *data;
555} drm_radeon_tex_image_t;
556
557typedef struct drm_radeon_texture {
558 unsigned int offset;
559 int pitch;
560 int format;
561 int width; /* Texture image coordinates */
562 int height;
563 drm_radeon_tex_image_t __user *image;
564} drm_radeon_texture_t;
565
566typedef struct drm_radeon_stipple {
567 unsigned int __user *mask;
568} drm_radeon_stipple_t;
569
570typedef struct drm_radeon_indirect {
571 int idx;
572 int start;
573 int end;
574 int discard;
575} drm_radeon_indirect_t;
576
577
578/* 1.3: An ioctl to get parameters that aren't available to the 3d
579 * client any other way.
580 */
581#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */
582#define RADEON_PARAM_LAST_FRAME 2
583#define RADEON_PARAM_LAST_DISPATCH 3
584#define RADEON_PARAM_LAST_CLEAR 4
585/* Added with DRM version 1.6. */
586#define RADEON_PARAM_IRQ_NR 5
587#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */
588/* Added with DRM version 1.8. */
589#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */
590#define RADEON_PARAM_STATUS_HANDLE 8
591#define RADEON_PARAM_SAREA_HANDLE 9
592#define RADEON_PARAM_GART_TEX_HANDLE 10
593#define RADEON_PARAM_SCRATCH_OFFSET 11
594
595typedef struct drm_radeon_getparam {
596 int param;
597 void __user *value;
598} drm_radeon_getparam_t;
599
600/* 1.6: Set up a memory manager for regions of shared memory:
601 */
602#define RADEON_MEM_REGION_GART 1
603#define RADEON_MEM_REGION_FB 2
604
605typedef struct drm_radeon_mem_alloc {
606 int region;
607 int alignment;
608 int size;
609 int __user *region_offset; /* offset from start of fb or GART */
610} drm_radeon_mem_alloc_t;
611
612typedef struct drm_radeon_mem_free {
613 int region;
614 int region_offset;
615} drm_radeon_mem_free_t;
616
617typedef struct drm_radeon_mem_init_heap {
618 int region;
619 int size;
620 int start;
621} drm_radeon_mem_init_heap_t;
622
623
624/* 1.6: Userspace can request & wait on irq's:
625 */
626typedef struct drm_radeon_irq_emit {
627 int __user *irq_seq;
628} drm_radeon_irq_emit_t;
629
630typedef struct drm_radeon_irq_wait {
631 int irq_seq;
632} drm_radeon_irq_wait_t;
633
634
635/* 1.10: Clients tell the DRM where they think the framebuffer is located in
636 * the card's address space, via a new generic ioctl to set parameters
637 */
638
639typedef struct drm_radeon_setparam {
640 unsigned int param;
641 int64_t value;
642} drm_radeon_setparam_t;
643
644#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
645#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
646
647/* 1.14: Clients can allocate/free a surface
648 */
649typedef struct drm_radeon_surface_alloc {
650 unsigned int address;
651 unsigned int size;
652 unsigned int flags;
653} drm_radeon_surface_alloc_t;
654
655typedef struct drm_radeon_surface_free {
656 unsigned int address;
657} drm_radeon_surface_free_t;
658
659#endif
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
new file mode 100644
index 000000000000..7b983d96e53b
--- /dev/null
+++ b/drivers/char/drm/radeon_drv.c
@@ -0,0 +1,127 @@
1/**
2 * \file radeon_drv.c
3 * ATI Radeon driver
4 *
5 * \author Gareth Hughes <gareth@valinux.com>
6 */
7
8/*
9 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
10 * All Rights Reserved.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice (including the next
20 * paragraph) shall be included in all copies or substantial portions of the
21 * Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
27 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29 * OTHER DEALINGS IN THE SOFTWARE.
30 */
31
32
33#include <linux/config.h>
34#include "drmP.h"
35#include "drm.h"
36#include "radeon_drm.h"
37#include "radeon_drv.h"
38
39#include "drm_pciids.h"
40
41static int postinit( struct drm_device *dev, unsigned long flags )
42{
43 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
44 DRIVER_NAME,
45 DRIVER_MAJOR,
46 DRIVER_MINOR,
47 DRIVER_PATCHLEVEL,
48 DRIVER_DATE,
49 dev->primary.minor,
50 pci_pretty_name(dev->pdev)
51 );
52 return 0;
53}
54
55static int version( drm_version_t *version )
56{
57 int len;
58
59 version->version_major = DRIVER_MAJOR;
60 version->version_minor = DRIVER_MINOR;
61 version->version_patchlevel = DRIVER_PATCHLEVEL;
62 DRM_COPY( version->name, DRIVER_NAME );
63 DRM_COPY( version->date, DRIVER_DATE );
64 DRM_COPY( version->desc, DRIVER_DESC );
65 return 0;
66}
67
68static struct pci_device_id pciidlist[] = {
69 radeon_PCI_IDS
70};
71
72extern drm_ioctl_desc_t radeon_ioctls[];
73extern int radeon_max_ioctl;
74
75static struct drm_driver driver = {
76 .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
77 .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
78 .preinit = radeon_driver_preinit,
79 .postcleanup = radeon_driver_postcleanup,
80 .prerelease = radeon_driver_prerelease,
81 .pretakedown = radeon_driver_pretakedown,
82 .open_helper = radeon_driver_open_helper,
83 .vblank_wait = radeon_driver_vblank_wait,
84 .irq_preinstall = radeon_driver_irq_preinstall,
85 .irq_postinstall = radeon_driver_irq_postinstall,
86 .irq_uninstall = radeon_driver_irq_uninstall,
87 .irq_handler = radeon_driver_irq_handler,
88 .free_filp_priv = radeon_driver_free_filp_priv,
89 .reclaim_buffers = drm_core_reclaim_buffers,
90 .get_map_ofs = drm_core_get_map_ofs,
91 .get_reg_ofs = drm_core_get_reg_ofs,
92 .postinit = postinit,
93 .version = version,
94 .ioctls = radeon_ioctls,
95 .dma_ioctl = radeon_cp_buffers,
96 .fops = {
97 .owner = THIS_MODULE,
98 .open = drm_open,
99 .release = drm_release,
100 .ioctl = drm_ioctl,
101 .mmap = drm_mmap,
102 .poll = drm_poll,
103 .fasync = drm_fasync,
104 },
105 .pci_driver = {
106 .name = DRIVER_NAME,
107 .id_table = pciidlist,
108 }
109};
110
111static int __init radeon_init(void)
112{
113 driver.num_ioctls = radeon_max_ioctl;
114 return drm_init(&driver);
115}
116
117static void __exit radeon_exit(void)
118{
119 drm_exit(&driver);
120}
121
122module_init(radeon_init);
123module_exit(radeon_exit);
124
125MODULE_AUTHOR( DRIVER_AUTHOR );
126MODULE_DESCRIPTION( DRIVER_DESC );
127MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
new file mode 100644
index 000000000000..5837098afae8
--- /dev/null
+++ b/drivers/char/drm/radeon_drv.h
@@ -0,0 +1,1044 @@
1/* radeon_drv.h -- Private header for radeon driver -*- linux-c -*-
2 *
3 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
4 * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Kevin E. Martin <martin@valinux.com>
28 * Gareth Hughes <gareth@valinux.com>
29 */
30
31#ifndef __RADEON_DRV_H__
32#define __RADEON_DRV_H__
33
34/* General customization:
35 */
36
37#define DRIVER_AUTHOR "Gareth Hughes, Keith Whitwell, others."
38
39#define DRIVER_NAME "radeon"
40#define DRIVER_DESC "ATI Radeon"
41#define DRIVER_DATE "20050311"
42
43/* Interface history:
44 *
45 * 1.1 - ??
46 * 1.2 - Add vertex2 ioctl (keith)
47 * - Add stencil capability to clear ioctl (gareth, keith)
48 * - Increase MAX_TEXTURE_LEVELS (brian)
49 * 1.3 - Add cmdbuf ioctl (keith)
50 * - Add support for new radeon packets (keith)
51 * - Add getparam ioctl (keith)
52 * - Add flip-buffers ioctl, deprecate fullscreen foo (keith).
53 * 1.4 - Add scratch registers to get_param ioctl.
54 * 1.5 - Add r200 packets to cmdbuf ioctl
55 * - Add r200 function to init ioctl
56 * - Add 'scalar2' instruction to cmdbuf
57 * 1.6 - Add static GART memory manager
58 * Add irq handler (won't be turned on unless X server knows to)
59 * Add irq ioctls and irq_active getparam.
60 * Add wait command for cmdbuf ioctl
61 * Add GART offset query for getparam
62 * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5]
63 * and R200_PP_CUBIC_OFFSET_F1_[0..5].
64 * Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and
65 * R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian)
66 * 1.8 - Remove need to call cleanup ioctls on last client exit (keith)
67 * Add 'GET' queries for starting additional clients on different VT's.
68 * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
69 * Add texture rectangle support for r100.
70 * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which
71 * clients use to tell the DRM where they think the framebuffer is
72 * located in the card's address space
73 * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color
74 * and GL_EXT_blend_[func|equation]_separate on r200
75 * 1.12- Add R300 CP microcode support - this just loads the CP on r300
76 * (No 3D support yet - just microcode loading)
77 * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters
78 * - Add hyperz support, add hyperz flags to clear ioctl.
79 * 1.14- Add support for color tiling
80 * - Add R100/R200 surface allocation/free support
81 * 1.15- Add support for texture micro tiling
82 * - Add support for r100 cube maps
83 * 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear
84 * texture filtering on r200
85 */
86#define DRIVER_MAJOR 1
87#define DRIVER_MINOR 16
88#define DRIVER_PATCHLEVEL 0
89
90#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
91#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
92
93/*
94 * Radeon chip families
95 */
96enum radeon_family {
97 CHIP_R100,
98 CHIP_RS100,
99 CHIP_RV100,
100 CHIP_R200,
101 CHIP_RV200,
102 CHIP_RS200,
103 CHIP_R250,
104 CHIP_RS250,
105 CHIP_RV250,
106 CHIP_RV280,
107 CHIP_R300,
108 CHIP_RS300,
109 CHIP_RV350,
110 CHIP_LAST,
111};
112
113enum radeon_cp_microcode_version {
114 UCODE_R100,
115 UCODE_R200,
116 UCODE_R300,
117};
118
119/*
120 * Chip flags
121 */
122enum radeon_chip_flags {
123 CHIP_FAMILY_MASK = 0x0000ffffUL,
124 CHIP_FLAGS_MASK = 0xffff0000UL,
125 CHIP_IS_MOBILITY = 0x00010000UL,
126 CHIP_IS_IGP = 0x00020000UL,
127 CHIP_SINGLE_CRTC = 0x00040000UL,
128 CHIP_IS_AGP = 0x00080000UL,
129 CHIP_HAS_HIERZ = 0x00100000UL,
130};
131
132typedef struct drm_radeon_freelist {
133 unsigned int age;
134 drm_buf_t *buf;
135 struct drm_radeon_freelist *next;
136 struct drm_radeon_freelist *prev;
137} drm_radeon_freelist_t;
138
139typedef struct drm_radeon_ring_buffer {
140 u32 *start;
141 u32 *end;
142 int size;
143 int size_l2qw;
144
145 u32 tail;
146 u32 tail_mask;
147 int space;
148
149 int high_mark;
150} drm_radeon_ring_buffer_t;
151
152typedef struct drm_radeon_depth_clear_t {
153 u32 rb3d_cntl;
154 u32 rb3d_zstencilcntl;
155 u32 se_cntl;
156} drm_radeon_depth_clear_t;
157
158struct drm_radeon_driver_file_fields {
159 int64_t radeon_fb_delta;
160};
161
162struct mem_block {
163 struct mem_block *next;
164 struct mem_block *prev;
165 int start;
166 int size;
167 DRMFILE filp; /* 0: free, -1: heap, other: real files */
168};
169
170struct radeon_surface {
171 int refcount;
172 u32 lower;
173 u32 upper;
174 u32 flags;
175};
176
177struct radeon_virt_surface {
178 int surface_index;
179 u32 lower;
180 u32 upper;
181 u32 flags;
182 DRMFILE filp;
183};
184
185typedef struct drm_radeon_private {
186 drm_radeon_ring_buffer_t ring;
187 drm_radeon_sarea_t *sarea_priv;
188
189 u32 fb_location;
190
191 int gart_size;
192 u32 gart_vm_start;
193 unsigned long gart_buffers_offset;
194
195 int cp_mode;
196 int cp_running;
197
198 drm_radeon_freelist_t *head;
199 drm_radeon_freelist_t *tail;
200 int last_buf;
201 volatile u32 *scratch;
202 int writeback_works;
203
204 int usec_timeout;
205
206 int microcode_version;
207
208 int is_pci;
209 unsigned long phys_pci_gart;
210 dma_addr_t bus_pci_gart;
211
212 struct {
213 u32 boxes;
214 int freelist_timeouts;
215 int freelist_loops;
216 int requested_bufs;
217 int last_frame_reads;
218 int last_clear_reads;
219 int clears;
220 int texture_uploads;
221 } stats;
222
223 int do_boxes;
224 int page_flipping;
225 int current_page;
226
227 u32 color_fmt;
228 unsigned int front_offset;
229 unsigned int front_pitch;
230 unsigned int back_offset;
231 unsigned int back_pitch;
232
233 u32 depth_fmt;
234 unsigned int depth_offset;
235 unsigned int depth_pitch;
236
237 u32 front_pitch_offset;
238 u32 back_pitch_offset;
239 u32 depth_pitch_offset;
240
241 drm_radeon_depth_clear_t depth_clear;
242
243 unsigned long fb_offset;
244 unsigned long mmio_offset;
245 unsigned long ring_offset;
246 unsigned long ring_rptr_offset;
247 unsigned long buffers_offset;
248 unsigned long gart_textures_offset;
249
250 drm_local_map_t *sarea;
251 drm_local_map_t *mmio;
252 drm_local_map_t *cp_ring;
253 drm_local_map_t *ring_rptr;
254 drm_local_map_t *gart_textures;
255
256 struct mem_block *gart_heap;
257 struct mem_block *fb_heap;
258
259 /* SW interrupt */
260 wait_queue_head_t swi_queue;
261 atomic_t swi_emitted;
262
263 struct radeon_surface surfaces[RADEON_MAX_SURFACES];
264 struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES];
265
266 /* starting from here on, data is preserved accross an open */
267 uint32_t flags; /* see radeon_chip_flags */
268} drm_radeon_private_t;
269
270typedef struct drm_radeon_buf_priv {
271 u32 age;
272} drm_radeon_buf_priv_t;
273
274 /* radeon_cp.c */
275extern int radeon_cp_init( DRM_IOCTL_ARGS );
276extern int radeon_cp_start( DRM_IOCTL_ARGS );
277extern int radeon_cp_stop( DRM_IOCTL_ARGS );
278extern int radeon_cp_reset( DRM_IOCTL_ARGS );
279extern int radeon_cp_idle( DRM_IOCTL_ARGS );
280extern int radeon_cp_resume( DRM_IOCTL_ARGS );
281extern int radeon_engine_reset( DRM_IOCTL_ARGS );
282extern int radeon_fullscreen( DRM_IOCTL_ARGS );
283extern int radeon_cp_buffers( DRM_IOCTL_ARGS );
284
285extern void radeon_freelist_reset( drm_device_t *dev );
286extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
287
288extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
289
290extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
291
292extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags);
293extern int radeon_driver_postcleanup(struct drm_device *dev);
294
295extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
296extern int radeon_mem_free( DRM_IOCTL_ARGS );
297extern int radeon_mem_init_heap( DRM_IOCTL_ARGS );
298extern void radeon_mem_takedown( struct mem_block **heap );
299extern void radeon_mem_release( DRMFILE filp, struct mem_block *heap );
300
301 /* radeon_irq.c */
302extern int radeon_irq_emit( DRM_IOCTL_ARGS );
303extern int radeon_irq_wait( DRM_IOCTL_ARGS );
304
305extern void radeon_do_release(drm_device_t *dev);
306extern int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
307extern irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS );
308extern void radeon_driver_irq_preinstall( drm_device_t *dev );
309extern void radeon_driver_irq_postinstall( drm_device_t *dev );
310extern void radeon_driver_irq_uninstall( drm_device_t *dev );
311extern void radeon_driver_prerelease(drm_device_t *dev, DRMFILE filp);
312extern void radeon_driver_pretakedown(drm_device_t *dev);
313extern int radeon_driver_open_helper(drm_device_t *dev, drm_file_t *filp_priv);
314extern void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv);
315
316extern int radeon_preinit( struct drm_device *dev, unsigned long flags );
317extern int radeon_postinit( struct drm_device *dev, unsigned long flags );
318extern int radeon_postcleanup( struct drm_device *dev );
319
320/* Flags for stats.boxes
321 */
322#define RADEON_BOX_DMA_IDLE 0x1
323#define RADEON_BOX_RING_FULL 0x2
324#define RADEON_BOX_FLIP 0x4
325#define RADEON_BOX_WAIT_IDLE 0x8
326#define RADEON_BOX_TEXTURE_LOAD 0x10
327
328
329
330/* Register definitions, register access macros and drmAddMap constants
331 * for Radeon kernel driver.
332 */
333
334#define RADEON_AGP_COMMAND 0x0f60
335#define RADEON_AUX_SCISSOR_CNTL 0x26f0
336# define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24)
337# define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25)
338# define RADEON_EXCLUSIVE_SCISSOR_2 (1 << 26)
339# define RADEON_SCISSOR_0_ENABLE (1 << 28)
340# define RADEON_SCISSOR_1_ENABLE (1 << 29)
341# define RADEON_SCISSOR_2_ENABLE (1 << 30)
342
343#define RADEON_BUS_CNTL 0x0030
344# define RADEON_BUS_MASTER_DIS (1 << 6)
345
346#define RADEON_CLOCK_CNTL_DATA 0x000c
347# define RADEON_PLL_WR_EN (1 << 7)
348#define RADEON_CLOCK_CNTL_INDEX 0x0008
349#define RADEON_CONFIG_APER_SIZE 0x0108
350#define RADEON_CRTC_OFFSET 0x0224
351#define RADEON_CRTC_OFFSET_CNTL 0x0228
352# define RADEON_CRTC_TILE_EN (1 << 15)
353# define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16)
354#define RADEON_CRTC2_OFFSET 0x0324
355#define RADEON_CRTC2_OFFSET_CNTL 0x0328
356
357#define RADEON_RB3D_COLOROFFSET 0x1c40
358#define RADEON_RB3D_COLORPITCH 0x1c48
359
360#define RADEON_DP_GUI_MASTER_CNTL 0x146c
361# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
362# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
363# define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4)
364# define RADEON_GMC_BRUSH_NONE (15 << 4)
365# define RADEON_GMC_DST_16BPP (4 << 8)
366# define RADEON_GMC_DST_24BPP (5 << 8)
367# define RADEON_GMC_DST_32BPP (6 << 8)
368# define RADEON_GMC_DST_DATATYPE_SHIFT 8
369# define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12)
370# define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24)
371# define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24)
372# define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28)
373# define RADEON_GMC_WR_MSK_DIS (1 << 30)
374# define RADEON_ROP3_S 0x00cc0000
375# define RADEON_ROP3_P 0x00f00000
376#define RADEON_DP_WRITE_MASK 0x16cc
377#define RADEON_DST_PITCH_OFFSET 0x142c
378#define RADEON_DST_PITCH_OFFSET_C 0x1c80
379# define RADEON_DST_TILE_LINEAR (0 << 30)
380# define RADEON_DST_TILE_MACRO (1 << 30)
381# define RADEON_DST_TILE_MICRO (2 << 30)
382# define RADEON_DST_TILE_BOTH (3 << 30)
383
384#define RADEON_SCRATCH_REG0 0x15e0
385#define RADEON_SCRATCH_REG1 0x15e4
386#define RADEON_SCRATCH_REG2 0x15e8
387#define RADEON_SCRATCH_REG3 0x15ec
388#define RADEON_SCRATCH_REG4 0x15f0
389#define RADEON_SCRATCH_REG5 0x15f4
390#define RADEON_SCRATCH_UMSK 0x0770
391#define RADEON_SCRATCH_ADDR 0x0774
392
393#define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x))
394
395#define GET_SCRATCH( x ) (dev_priv->writeback_works \
396 ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
397 : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
398
399
400#define RADEON_GEN_INT_CNTL 0x0040
401# define RADEON_CRTC_VBLANK_MASK (1 << 0)
402# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19)
403# define RADEON_SW_INT_ENABLE (1 << 25)
404
405#define RADEON_GEN_INT_STATUS 0x0044
406# define RADEON_CRTC_VBLANK_STAT (1 << 0)
407# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0)
408# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19)
409# define RADEON_SW_INT_TEST (1 << 25)
410# define RADEON_SW_INT_TEST_ACK (1 << 25)
411# define RADEON_SW_INT_FIRE (1 << 26)
412
413#define RADEON_HOST_PATH_CNTL 0x0130
414# define RADEON_HDP_SOFT_RESET (1 << 26)
415# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28)
416# define RADEON_HDP_WC_TIMEOUT_28BCLK (7 << 28)
417
418#define RADEON_ISYNC_CNTL 0x1724
419# define RADEON_ISYNC_ANY2D_IDLE3D (1 << 0)
420# define RADEON_ISYNC_ANY3D_IDLE2D (1 << 1)
421# define RADEON_ISYNC_TRIG2D_IDLE3D (1 << 2)
422# define RADEON_ISYNC_TRIG3D_IDLE2D (1 << 3)
423# define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4)
424# define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5)
425
426#define RADEON_RBBM_GUICNTL 0x172c
427# define RADEON_HOST_DATA_SWAP_NONE (0 << 0)
428# define RADEON_HOST_DATA_SWAP_16BIT (1 << 0)
429# define RADEON_HOST_DATA_SWAP_32BIT (2 << 0)
430# define RADEON_HOST_DATA_SWAP_HDW (3 << 0)
431
432#define RADEON_MC_AGP_LOCATION 0x014c
433#define RADEON_MC_FB_LOCATION 0x0148
434#define RADEON_MCLK_CNTL 0x0012
435# define RADEON_FORCEON_MCLKA (1 << 16)
436# define RADEON_FORCEON_MCLKB (1 << 17)
437# define RADEON_FORCEON_YCLKA (1 << 18)
438# define RADEON_FORCEON_YCLKB (1 << 19)
439# define RADEON_FORCEON_MC (1 << 20)
440# define RADEON_FORCEON_AIC (1 << 21)
441
442#define RADEON_PP_BORDER_COLOR_0 0x1d40
443#define RADEON_PP_BORDER_COLOR_1 0x1d44
444#define RADEON_PP_BORDER_COLOR_2 0x1d48
445#define RADEON_PP_CNTL 0x1c38
446# define RADEON_SCISSOR_ENABLE (1 << 1)
447#define RADEON_PP_LUM_MATRIX 0x1d00
448#define RADEON_PP_MISC 0x1c14
449#define RADEON_PP_ROT_MATRIX_0 0x1d58
450#define RADEON_PP_TXFILTER_0 0x1c54
451#define RADEON_PP_TXOFFSET_0 0x1c5c
452#define RADEON_PP_TXFILTER_1 0x1c6c
453#define RADEON_PP_TXFILTER_2 0x1c84
454
455#define RADEON_RB2D_DSTCACHE_CTLSTAT 0x342c
456# define RADEON_RB2D_DC_FLUSH (3 << 0)
457# define RADEON_RB2D_DC_FREE (3 << 2)
458# define RADEON_RB2D_DC_FLUSH_ALL 0xf
459# define RADEON_RB2D_DC_BUSY (1 << 31)
460#define RADEON_RB3D_CNTL 0x1c3c
461# define RADEON_ALPHA_BLEND_ENABLE (1 << 0)
462# define RADEON_PLANE_MASK_ENABLE (1 << 1)
463# define RADEON_DITHER_ENABLE (1 << 2)
464# define RADEON_ROUND_ENABLE (1 << 3)
465# define RADEON_SCALE_DITHER_ENABLE (1 << 4)
466# define RADEON_DITHER_INIT (1 << 5)
467# define RADEON_ROP_ENABLE (1 << 6)
468# define RADEON_STENCIL_ENABLE (1 << 7)
469# define RADEON_Z_ENABLE (1 << 8)
470# define RADEON_ZBLOCK16 (1 << 15)
471#define RADEON_RB3D_DEPTHOFFSET 0x1c24
472#define RADEON_RB3D_DEPTHCLEARVALUE 0x3230
473#define RADEON_RB3D_DEPTHPITCH 0x1c28
474#define RADEON_RB3D_PLANEMASK 0x1d84
475#define RADEON_RB3D_STENCILREFMASK 0x1d7c
476#define RADEON_RB3D_ZCACHE_MODE 0x3250
477#define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254
478# define RADEON_RB3D_ZC_FLUSH (1 << 0)
479# define RADEON_RB3D_ZC_FREE (1 << 2)
480# define RADEON_RB3D_ZC_FLUSH_ALL 0x5
481# define RADEON_RB3D_ZC_BUSY (1 << 31)
482#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
483# define RADEON_Z_TEST_MASK (7 << 4)
484# define RADEON_Z_TEST_ALWAYS (7 << 4)
485# define RADEON_Z_HIERARCHY_ENABLE (1 << 8)
486# define RADEON_STENCIL_TEST_ALWAYS (7 << 12)
487# define RADEON_STENCIL_S_FAIL_REPLACE (2 << 16)
488# define RADEON_STENCIL_ZPASS_REPLACE (2 << 20)
489# define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24)
490# define RADEON_Z_COMPRESSION_ENABLE (1 << 28)
491# define RADEON_FORCE_Z_DIRTY (1 << 29)
492# define RADEON_Z_WRITE_ENABLE (1 << 30)
493# define RADEON_Z_DECOMPRESSION_ENABLE (1 << 31)
494#define RADEON_RBBM_SOFT_RESET 0x00f0
495# define RADEON_SOFT_RESET_CP (1 << 0)
496# define RADEON_SOFT_RESET_HI (1 << 1)
497# define RADEON_SOFT_RESET_SE (1 << 2)
498# define RADEON_SOFT_RESET_RE (1 << 3)
499# define RADEON_SOFT_RESET_PP (1 << 4)
500# define RADEON_SOFT_RESET_E2 (1 << 5)
501# define RADEON_SOFT_RESET_RB (1 << 6)
502# define RADEON_SOFT_RESET_HDP (1 << 7)
503#define RADEON_RBBM_STATUS 0x0e40
504# define RADEON_RBBM_FIFOCNT_MASK 0x007f
505# define RADEON_RBBM_ACTIVE (1 << 31)
506#define RADEON_RE_LINE_PATTERN 0x1cd0
507#define RADEON_RE_MISC 0x26c4
508#define RADEON_RE_TOP_LEFT 0x26c0
509#define RADEON_RE_WIDTH_HEIGHT 0x1c44
510#define RADEON_RE_STIPPLE_ADDR 0x1cc8
511#define RADEON_RE_STIPPLE_DATA 0x1ccc
512
513#define RADEON_SCISSOR_TL_0 0x1cd8
514#define RADEON_SCISSOR_BR_0 0x1cdc
515#define RADEON_SCISSOR_TL_1 0x1ce0
516#define RADEON_SCISSOR_BR_1 0x1ce4
517#define RADEON_SCISSOR_TL_2 0x1ce8
518#define RADEON_SCISSOR_BR_2 0x1cec
519#define RADEON_SE_COORD_FMT 0x1c50
520#define RADEON_SE_CNTL 0x1c4c
521# define RADEON_FFACE_CULL_CW (0 << 0)
522# define RADEON_BFACE_SOLID (3 << 1)
523# define RADEON_FFACE_SOLID (3 << 3)
524# define RADEON_FLAT_SHADE_VTX_LAST (3 << 6)
525# define RADEON_DIFFUSE_SHADE_FLAT (1 << 8)
526# define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8)
527# define RADEON_ALPHA_SHADE_FLAT (1 << 10)
528# define RADEON_ALPHA_SHADE_GOURAUD (2 << 10)
529# define RADEON_SPECULAR_SHADE_FLAT (1 << 12)
530# define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12)
531# define RADEON_FOG_SHADE_FLAT (1 << 14)
532# define RADEON_FOG_SHADE_GOURAUD (2 << 14)
533# define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24)
534# define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25)
535# define RADEON_VTX_PIX_CENTER_OGL (1 << 27)
536# define RADEON_ROUND_MODE_TRUNC (0 << 28)
537# define RADEON_ROUND_PREC_8TH_PIX (1 << 30)
538#define RADEON_SE_CNTL_STATUS 0x2140
539#define RADEON_SE_LINE_WIDTH 0x1db8
540#define RADEON_SE_VPORT_XSCALE 0x1d98
541#define RADEON_SE_ZBIAS_FACTOR 0x1db0
542#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210
543#define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254
544#define RADEON_SE_TCL_VECTOR_INDX_REG 0x2200
545# define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT 16
546# define RADEON_VEC_INDX_DWORD_COUNT_SHIFT 28
547#define RADEON_SE_TCL_VECTOR_DATA_REG 0x2204
548#define RADEON_SE_TCL_SCALAR_INDX_REG 0x2208
549# define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT 16
550#define RADEON_SE_TCL_SCALAR_DATA_REG 0x220C
551#define RADEON_SURFACE_ACCESS_FLAGS 0x0bf8
552#define RADEON_SURFACE_ACCESS_CLR 0x0bfc
553#define RADEON_SURFACE_CNTL 0x0b00
554# define RADEON_SURF_TRANSLATION_DIS (1 << 8)
555# define RADEON_NONSURF_AP0_SWP_MASK (3 << 20)
556# define RADEON_NONSURF_AP0_SWP_LITTLE (0 << 20)
557# define RADEON_NONSURF_AP0_SWP_BIG16 (1 << 20)
558# define RADEON_NONSURF_AP0_SWP_BIG32 (2 << 20)
559# define RADEON_NONSURF_AP1_SWP_MASK (3 << 22)
560# define RADEON_NONSURF_AP1_SWP_LITTLE (0 << 22)
561# define RADEON_NONSURF_AP1_SWP_BIG16 (1 << 22)
562# define RADEON_NONSURF_AP1_SWP_BIG32 (2 << 22)
563#define RADEON_SURFACE0_INFO 0x0b0c
564# define RADEON_SURF_PITCHSEL_MASK (0x1ff << 0)
565# define RADEON_SURF_TILE_MODE_MASK (3 << 16)
566# define RADEON_SURF_TILE_MODE_MACRO (0 << 16)
567# define RADEON_SURF_TILE_MODE_MICRO (1 << 16)
568# define RADEON_SURF_TILE_MODE_32BIT_Z (2 << 16)
569# define RADEON_SURF_TILE_MODE_16BIT_Z (3 << 16)
570#define RADEON_SURFACE0_LOWER_BOUND 0x0b04
571#define RADEON_SURFACE0_UPPER_BOUND 0x0b08
572# define RADEON_SURF_ADDRESS_FIXED_MASK (0x3ff << 0)
573#define RADEON_SURFACE1_INFO 0x0b1c
574#define RADEON_SURFACE1_LOWER_BOUND 0x0b14
575#define RADEON_SURFACE1_UPPER_BOUND 0x0b18
576#define RADEON_SURFACE2_INFO 0x0b2c
577#define RADEON_SURFACE2_LOWER_BOUND 0x0b24
578#define RADEON_SURFACE2_UPPER_BOUND 0x0b28
579#define RADEON_SURFACE3_INFO 0x0b3c
580#define RADEON_SURFACE3_LOWER_BOUND 0x0b34
581#define RADEON_SURFACE3_UPPER_BOUND 0x0b38
582#define RADEON_SURFACE4_INFO 0x0b4c
583#define RADEON_SURFACE4_LOWER_BOUND 0x0b44
584#define RADEON_SURFACE4_UPPER_BOUND 0x0b48
585#define RADEON_SURFACE5_INFO 0x0b5c
586#define RADEON_SURFACE5_LOWER_BOUND 0x0b54
587#define RADEON_SURFACE5_UPPER_BOUND 0x0b58
588#define RADEON_SURFACE6_INFO 0x0b6c
589#define RADEON_SURFACE6_LOWER_BOUND 0x0b64
590#define RADEON_SURFACE6_UPPER_BOUND 0x0b68
591#define RADEON_SURFACE7_INFO 0x0b7c
592#define RADEON_SURFACE7_LOWER_BOUND 0x0b74
593#define RADEON_SURFACE7_UPPER_BOUND 0x0b78
594#define RADEON_SW_SEMAPHORE 0x013c
595
596#define RADEON_WAIT_UNTIL 0x1720
597# define RADEON_WAIT_CRTC_PFLIP (1 << 0)
598# define RADEON_WAIT_2D_IDLECLEAN (1 << 16)
599# define RADEON_WAIT_3D_IDLECLEAN (1 << 17)
600# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18)
601
602#define RADEON_RB3D_ZMASKOFFSET 0x3234
603#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
604# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
605# define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0)
606
607
608/* CP registers */
609#define RADEON_CP_ME_RAM_ADDR 0x07d4
610#define RADEON_CP_ME_RAM_RADDR 0x07d8
611#define RADEON_CP_ME_RAM_DATAH 0x07dc
612#define RADEON_CP_ME_RAM_DATAL 0x07e0
613
614#define RADEON_CP_RB_BASE 0x0700
615#define RADEON_CP_RB_CNTL 0x0704
616# define RADEON_BUF_SWAP_32BIT (2 << 16)
617#define RADEON_CP_RB_RPTR_ADDR 0x070c
618#define RADEON_CP_RB_RPTR 0x0710
619#define RADEON_CP_RB_WPTR 0x0714
620
621#define RADEON_CP_RB_WPTR_DELAY 0x0718
622# define RADEON_PRE_WRITE_TIMER_SHIFT 0
623# define RADEON_PRE_WRITE_LIMIT_SHIFT 23
624
625#define RADEON_CP_IB_BASE 0x0738
626
627#define RADEON_CP_CSQ_CNTL 0x0740
628# define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0)
629# define RADEON_CSQ_PRIDIS_INDDIS (0 << 28)
630# define RADEON_CSQ_PRIPIO_INDDIS (1 << 28)
631# define RADEON_CSQ_PRIBM_INDDIS (2 << 28)
632# define RADEON_CSQ_PRIPIO_INDBM (3 << 28)
633# define RADEON_CSQ_PRIBM_INDBM (4 << 28)
634# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28)
635
636#define RADEON_AIC_CNTL 0x01d0
637# define RADEON_PCIGART_TRANSLATE_EN (1 << 0)
638#define RADEON_AIC_STAT 0x01d4
639#define RADEON_AIC_PT_BASE 0x01d8
640#define RADEON_AIC_LO_ADDR 0x01dc
641#define RADEON_AIC_HI_ADDR 0x01e0
642#define RADEON_AIC_TLB_ADDR 0x01e4
643#define RADEON_AIC_TLB_DATA 0x01e8
644
645/* CP command packets */
646#define RADEON_CP_PACKET0 0x00000000
647# define RADEON_ONE_REG_WR (1 << 15)
648#define RADEON_CP_PACKET1 0x40000000
649#define RADEON_CP_PACKET2 0x80000000
650#define RADEON_CP_PACKET3 0xC0000000
651# define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300
652# define RADEON_WAIT_FOR_IDLE 0x00002600
653# define RADEON_3D_DRAW_VBUF 0x00002800
654# define RADEON_3D_DRAW_IMMD 0x00002900
655# define RADEON_3D_DRAW_INDX 0x00002A00
656# define RADEON_3D_LOAD_VBPNTR 0x00002F00
657# define RADEON_MPEG_IDCT_MACROBLOCK 0x00003000
658# define RADEON_MPEG_IDCT_MACROBLOCK_REV 0x00003100
659# define RADEON_3D_CLEAR_ZMASK 0x00003200
660# define RADEON_3D_CLEAR_HIZ 0x00003700
661# define RADEON_CNTL_HOSTDATA_BLT 0x00009400
662# define RADEON_CNTL_PAINT_MULTI 0x00009A00
663# define RADEON_CNTL_BITBLT_MULTI 0x00009B00
664# define RADEON_CNTL_SET_SCISSORS 0xC0001E00
665
666#define RADEON_CP_PACKET_MASK 0xC0000000
667#define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000
668#define RADEON_CP_PACKET0_REG_MASK 0x000007ff
669#define RADEON_CP_PACKET1_REG0_MASK 0x000007ff
670#define RADEON_CP_PACKET1_REG1_MASK 0x003ff800
671
672#define RADEON_VTX_Z_PRESENT (1 << 31)
673#define RADEON_VTX_PKCOLOR_PRESENT (1 << 3)
674
675#define RADEON_PRIM_TYPE_NONE (0 << 0)
676#define RADEON_PRIM_TYPE_POINT (1 << 0)
677#define RADEON_PRIM_TYPE_LINE (2 << 0)
678#define RADEON_PRIM_TYPE_LINE_STRIP (3 << 0)
679#define RADEON_PRIM_TYPE_TRI_LIST (4 << 0)
680#define RADEON_PRIM_TYPE_TRI_FAN (5 << 0)
681#define RADEON_PRIM_TYPE_TRI_STRIP (6 << 0)
682#define RADEON_PRIM_TYPE_TRI_TYPE2 (7 << 0)
683#define RADEON_PRIM_TYPE_RECT_LIST (8 << 0)
684#define RADEON_PRIM_TYPE_3VRT_POINT_LIST (9 << 0)
685#define RADEON_PRIM_TYPE_3VRT_LINE_LIST (10 << 0)
686#define RADEON_PRIM_TYPE_MASK 0xf
687#define RADEON_PRIM_WALK_IND (1 << 4)
688#define RADEON_PRIM_WALK_LIST (2 << 4)
689#define RADEON_PRIM_WALK_RING (3 << 4)
690#define RADEON_COLOR_ORDER_BGRA (0 << 6)
691#define RADEON_COLOR_ORDER_RGBA (1 << 6)
692#define RADEON_MAOS_ENABLE (1 << 7)
693#define RADEON_VTX_FMT_R128_MODE (0 << 8)
694#define RADEON_VTX_FMT_RADEON_MODE (1 << 8)
695#define RADEON_NUM_VERTICES_SHIFT 16
696
697#define RADEON_COLOR_FORMAT_CI8 2
698#define RADEON_COLOR_FORMAT_ARGB1555 3
699#define RADEON_COLOR_FORMAT_RGB565 4
700#define RADEON_COLOR_FORMAT_ARGB8888 6
701#define RADEON_COLOR_FORMAT_RGB332 7
702#define RADEON_COLOR_FORMAT_RGB8 9
703#define RADEON_COLOR_FORMAT_ARGB4444 15
704
705#define RADEON_TXFORMAT_I8 0
706#define RADEON_TXFORMAT_AI88 1
707#define RADEON_TXFORMAT_RGB332 2
708#define RADEON_TXFORMAT_ARGB1555 3
709#define RADEON_TXFORMAT_RGB565 4
710#define RADEON_TXFORMAT_ARGB4444 5
711#define RADEON_TXFORMAT_ARGB8888 6
712#define RADEON_TXFORMAT_RGBA8888 7
713#define RADEON_TXFORMAT_Y8 8
714#define RADEON_TXFORMAT_VYUY422 10
715#define RADEON_TXFORMAT_YVYU422 11
716#define RADEON_TXFORMAT_DXT1 12
717#define RADEON_TXFORMAT_DXT23 14
718#define RADEON_TXFORMAT_DXT45 15
719
720#define R200_PP_TXCBLEND_0 0x2f00
721#define R200_PP_TXCBLEND_1 0x2f10
722#define R200_PP_TXCBLEND_2 0x2f20
723#define R200_PP_TXCBLEND_3 0x2f30
724#define R200_PP_TXCBLEND_4 0x2f40
725#define R200_PP_TXCBLEND_5 0x2f50
726#define R200_PP_TXCBLEND_6 0x2f60
727#define R200_PP_TXCBLEND_7 0x2f70
728#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268
729#define R200_PP_TFACTOR_0 0x2ee0
730#define R200_SE_VTX_FMT_0 0x2088
731#define R200_SE_VAP_CNTL 0x2080
732#define R200_SE_TCL_MATRIX_SEL_0 0x2230
733#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8
734#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0
735#define R200_PP_TXFILTER_5 0x2ca0
736#define R200_PP_TXFILTER_4 0x2c80
737#define R200_PP_TXFILTER_3 0x2c60
738#define R200_PP_TXFILTER_2 0x2c40
739#define R200_PP_TXFILTER_1 0x2c20
740#define R200_PP_TXFILTER_0 0x2c00
741#define R200_PP_TXOFFSET_5 0x2d78
742#define R200_PP_TXOFFSET_4 0x2d60
743#define R200_PP_TXOFFSET_3 0x2d48
744#define R200_PP_TXOFFSET_2 0x2d30
745#define R200_PP_TXOFFSET_1 0x2d18
746#define R200_PP_TXOFFSET_0 0x2d00
747
748#define R200_PP_CUBIC_FACES_0 0x2c18
749#define R200_PP_CUBIC_FACES_1 0x2c38
750#define R200_PP_CUBIC_FACES_2 0x2c58
751#define R200_PP_CUBIC_FACES_3 0x2c78
752#define R200_PP_CUBIC_FACES_4 0x2c98
753#define R200_PP_CUBIC_FACES_5 0x2cb8
754#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04
755#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08
756#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c
757#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10
758#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14
759#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c
760#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20
761#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24
762#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28
763#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c
764#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34
765#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38
766#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c
767#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40
768#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44
769#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c
770#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50
771#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54
772#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58
773#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c
774#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64
775#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68
776#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c
777#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70
778#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74
779#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c
780#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80
781#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84
782#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88
783#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c
784
785#define R200_RE_AUX_SCISSOR_CNTL 0x26f0
786#define R200_SE_VTE_CNTL 0x20b0
787#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250
788#define R200_PP_TAM_DEBUG3 0x2d9c
789#define R200_PP_CNTL_X 0x2cc4
790#define R200_SE_VAP_CNTL_STATUS 0x2140
791#define R200_RE_SCISSOR_TL_0 0x1cd8
792#define R200_RE_SCISSOR_TL_1 0x1ce0
793#define R200_RE_SCISSOR_TL_2 0x1ce8
794#define R200_RB3D_DEPTHXY_OFFSET 0x1d60
795#define R200_RE_AUX_SCISSOR_CNTL 0x26f0
796#define R200_SE_VTX_STATE_CNTL 0x2180
797#define R200_RE_POINTSIZE 0x2648
798#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
799
800#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */
801#define RADEON_PP_TEX_SIZE_1 0x1d0c
802#define RADEON_PP_TEX_SIZE_2 0x1d14
803
804#define RADEON_PP_CUBIC_FACES_0 0x1d24
805#define RADEON_PP_CUBIC_FACES_1 0x1d28
806#define RADEON_PP_CUBIC_FACES_2 0x1d2c
807#define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */
808#define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00
809#define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14
810
811#define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001
812#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000
813#define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT 0x00000012
814#define SE_VTE_CNTL__VTX_XY_FMT_MASK 0x00000100
815#define SE_VTE_CNTL__VTX_Z_FMT_MASK 0x00000200
816#define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK 0x00000001
817#define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK 0x00000002
818#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT 0x0000000b
819#define R200_3D_DRAW_IMMD_2 0xC0003500
820#define R200_SE_VTX_FMT_1 0x208c
821#define R200_RE_CNTL 0x1c50
822
823#define R200_RB3D_BLENDCOLOR 0x3218
824
825#define R200_SE_TCL_POINT_SPRITE_CNTL 0x22c4
826
827#define R200_PP_TRI_PERF 0x2cf8
828
829/* Constants */
830#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
831
832#define RADEON_LAST_FRAME_REG RADEON_SCRATCH_REG0
833#define RADEON_LAST_DISPATCH_REG RADEON_SCRATCH_REG1
834#define RADEON_LAST_CLEAR_REG RADEON_SCRATCH_REG2
835#define RADEON_LAST_SWI_REG RADEON_SCRATCH_REG3
836#define RADEON_LAST_DISPATCH 1
837
838#define RADEON_MAX_VB_AGE 0x7fffffff
839#define RADEON_MAX_VB_VERTS (0xffff)
840
841#define RADEON_RING_HIGH_MARK 128
842
843#define RADEON_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
844#define RADEON_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
845#define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) )
846#define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) )
847
848#define RADEON_WRITE_PLL( addr, val ) \
849do { \
850 RADEON_WRITE8( RADEON_CLOCK_CNTL_INDEX, \
851 ((addr) & 0x1f) | RADEON_PLL_WR_EN ); \
852 RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \
853} while (0)
854
855#define CP_PACKET0( reg, n ) \
856 (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
857#define CP_PACKET0_TABLE( reg, n ) \
858 (RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2))
859#define CP_PACKET1( reg0, reg1 ) \
860 (RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2))
861#define CP_PACKET2() \
862 (RADEON_CP_PACKET2)
863#define CP_PACKET3( pkt, n ) \
864 (RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
865
866
867/* ================================================================
868 * Engine control helper macros
869 */
870
871#define RADEON_WAIT_UNTIL_2D_IDLE() do { \
872 OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
873 OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \
874 RADEON_WAIT_HOST_IDLECLEAN) ); \
875} while (0)
876
877#define RADEON_WAIT_UNTIL_3D_IDLE() do { \
878 OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
879 OUT_RING( (RADEON_WAIT_3D_IDLECLEAN | \
880 RADEON_WAIT_HOST_IDLECLEAN) ); \
881} while (0)
882
883#define RADEON_WAIT_UNTIL_IDLE() do { \
884 OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
885 OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \
886 RADEON_WAIT_3D_IDLECLEAN | \
887 RADEON_WAIT_HOST_IDLECLEAN) ); \
888} while (0)
889
890#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do { \
891 OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
892 OUT_RING( RADEON_WAIT_CRTC_PFLIP ); \
893} while (0)
894
895#define RADEON_FLUSH_CACHE() do { \
896 OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \
897 OUT_RING( RADEON_RB2D_DC_FLUSH ); \
898} while (0)
899
900#define RADEON_PURGE_CACHE() do { \
901 OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \
902 OUT_RING( RADEON_RB2D_DC_FLUSH_ALL ); \
903} while (0)
904
905#define RADEON_FLUSH_ZCACHE() do { \
906 OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
907 OUT_RING( RADEON_RB3D_ZC_FLUSH ); \
908} while (0)
909
910#define RADEON_PURGE_ZCACHE() do { \
911 OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
912 OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \
913} while (0)
914
915
916/* ================================================================
917 * Misc helper macros
918 */
919
920/* Perfbox functionality only.
921 */
922#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
923do { \
924 if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) { \
925 u32 head = GET_RING_HEAD( dev_priv ); \
926 if (head == dev_priv->ring.tail) \
927 dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE; \
928 } \
929} while (0)
930
931#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \
932do { \
933 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \
934 if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \
935 int __ret = radeon_do_cp_idle( dev_priv ); \
936 if ( __ret ) return __ret; \
937 sarea_priv->last_dispatch = 0; \
938 radeon_freelist_reset( dev ); \
939 } \
940} while (0)
941
942#define RADEON_DISPATCH_AGE( age ) do { \
943 OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) ); \
944 OUT_RING( age ); \
945} while (0)
946
947#define RADEON_FRAME_AGE( age ) do { \
948 OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) ); \
949 OUT_RING( age ); \
950} while (0)
951
952#define RADEON_CLEAR_AGE( age ) do { \
953 OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) ); \
954 OUT_RING( age ); \
955} while (0)
956
957
958/* ================================================================
959 * Ring control
960 */
961
962#define RADEON_VERBOSE 0
963
964#define RING_LOCALS int write, _nr; unsigned int mask; u32 *ring;
965
966#define BEGIN_RING( n ) do { \
967 if ( RADEON_VERBOSE ) { \
968 DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
969 n, __FUNCTION__ ); \
970 } \
971 if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
972 COMMIT_RING(); \
973 radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \
974 } \
975 _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \
976 ring = dev_priv->ring.start; \
977 write = dev_priv->ring.tail; \
978 mask = dev_priv->ring.tail_mask; \
979} while (0)
980
981#define ADVANCE_RING() do { \
982 if ( RADEON_VERBOSE ) { \
983 DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \
984 write, dev_priv->ring.tail ); \
985 } \
986 if (((dev_priv->ring.tail + _nr) & mask) != write) { \
987 DRM_ERROR( \
988 "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \
989 ((dev_priv->ring.tail + _nr) & mask), \
990 write, __LINE__); \
991 } else \
992 dev_priv->ring.tail = write; \
993} while (0)
994
995#define COMMIT_RING() do { \
996 /* Flush writes to ring */ \
997 DRM_MEMORYBARRIER(); \
998 GET_RING_HEAD( dev_priv ); \
999 RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail ); \
1000 /* read from PCI bus to ensure correct posting */ \
1001 RADEON_READ( RADEON_CP_RB_RPTR ); \
1002} while (0)
1003
1004#define OUT_RING( x ) do { \
1005 if ( RADEON_VERBOSE ) { \
1006 DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \
1007 (unsigned int)(x), write ); \
1008 } \
1009 ring[write++] = (x); \
1010 write &= mask; \
1011} while (0)
1012
1013#define OUT_RING_REG( reg, val ) do { \
1014 OUT_RING( CP_PACKET0( reg, 0 ) ); \
1015 OUT_RING( val ); \
1016} while (0)
1017
1018
1019#define OUT_RING_TABLE( tab, sz ) do { \
1020 int _size = (sz); \
1021 int *_tab = (int *)(tab); \
1022 \
1023 if (write + _size > mask) { \
1024 int _i = (mask+1) - write; \
1025 _size -= _i; \
1026 while (_i > 0 ) { \
1027 *(int *)(ring + write) = *_tab++; \
1028 write++; \
1029 _i--; \
1030 } \
1031 write = 0; \
1032 _tab += _i; \
1033 } \
1034 \
1035 while (_size > 0) { \
1036 *(ring + write) = *_tab++; \
1037 write++; \
1038 _size--; \
1039 } \
1040 write &= mask; \
1041} while (0)
1042
1043
1044#endif /* __RADEON_DRV_H__ */
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
new file mode 100644
index 000000000000..5b18bee6492e
--- /dev/null
+++ b/drivers/char/drm/radeon_irq.c
@@ -0,0 +1,251 @@
1/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*-
2 *
3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 *
5 * The Weather Channel (TM) funded Tungsten Graphics to develop the
6 * initial release of the Radeon 8500 driver under the XFree86 license.
7 * This notice must be preserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Michel D�zer <michel@daenzer.net>
31 */
32
33#include "drmP.h"
34#include "drm.h"
35#include "radeon_drm.h"
36#include "radeon_drv.h"
37
38/* Interrupts - Used for device synchronization and flushing in the
39 * following circumstances:
40 *
41 * - Exclusive FB access with hw idle:
42 * - Wait for GUI Idle (?) interrupt, then do normal flush.
43 *
44 * - Frame throttling, NV_fence:
45 * - Drop marker irq's into command stream ahead of time.
46 * - Wait on irq's with lock *not held*
47 * - Check each for termination condition
48 *
49 * - Internally in cp_getbuffer, etc:
50 * - as above, but wait with lock held???
51 *
52 * NOTE: These functions are misleadingly named -- the irq's aren't
53 * tied to dma at all, this is just a hangover from dri prehistory.
54 */
55
56irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS )
57{
58 drm_device_t *dev = (drm_device_t *) arg;
59 drm_radeon_private_t *dev_priv =
60 (drm_radeon_private_t *)dev->dev_private;
61 u32 stat;
62
63 /* Only consider the bits we're interested in - others could be used
64 * outside the DRM
65 */
66 stat = RADEON_READ(RADEON_GEN_INT_STATUS)
67 & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT);
68 if (!stat)
69 return IRQ_NONE;
70
71 /* SW interrupt */
72 if (stat & RADEON_SW_INT_TEST) {
73 DRM_WAKEUP( &dev_priv->swi_queue );
74 }
75
76 /* VBLANK interrupt */
77 if (stat & RADEON_CRTC_VBLANK_STAT) {
78 atomic_inc(&dev->vbl_received);
79 DRM_WAKEUP(&dev->vbl_queue);
80 drm_vbl_send_signals( dev );
81 }
82
83 /* Acknowledge interrupts we handle */
84 RADEON_WRITE(RADEON_GEN_INT_STATUS, stat);
85 return IRQ_HANDLED;
86}
87
88static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv)
89{
90 u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS )
91 & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT);
92 if (tmp)
93 RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp );
94}
95
96static int radeon_emit_irq(drm_device_t *dev)
97{
98 drm_radeon_private_t *dev_priv = dev->dev_private;
99 unsigned int ret;
100 RING_LOCALS;
101
102 atomic_inc(&dev_priv->swi_emitted);
103 ret = atomic_read(&dev_priv->swi_emitted);
104
105 BEGIN_RING( 4 );
106 OUT_RING_REG( RADEON_LAST_SWI_REG, ret );
107 OUT_RING_REG( RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE );
108 ADVANCE_RING();
109 COMMIT_RING();
110
111 return ret;
112}
113
114
115static int radeon_wait_irq(drm_device_t *dev, int swi_nr)
116{
117 drm_radeon_private_t *dev_priv =
118 (drm_radeon_private_t *)dev->dev_private;
119 int ret = 0;
120
121 if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr)
122 return 0;
123
124 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
125
126 /* This is a hack to work around mysterious freezes on certain
127 * systems:
128 */
129 radeon_acknowledge_irqs( dev_priv );
130
131 DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ,
132 RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr );
133
134 return ret;
135}
136
137int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
138{
139 drm_radeon_private_t *dev_priv =
140 (drm_radeon_private_t *)dev->dev_private;
141 unsigned int cur_vblank;
142 int ret = 0;
143
144 if ( !dev_priv ) {
145 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
146 return DRM_ERR(EINVAL);
147 }
148
149 radeon_acknowledge_irqs( dev_priv );
150
151 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
152
153 /* Assume that the user has missed the current sequence number
154 * by about a day rather than she wants to wait for years
155 * using vertical blanks...
156 */
157 DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ,
158 ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
159 - *sequence ) <= (1<<23) ) );
160
161 *sequence = cur_vblank;
162
163 return ret;
164}
165
166
167/* Needs the lock as it touches the ring.
168 */
169int radeon_irq_emit( DRM_IOCTL_ARGS )
170{
171 DRM_DEVICE;
172 drm_radeon_private_t *dev_priv = dev->dev_private;
173 drm_radeon_irq_emit_t emit;
174 int result;
175
176 LOCK_TEST_WITH_RETURN( dev, filp );
177
178 if ( !dev_priv ) {
179 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
180 return DRM_ERR(EINVAL);
181 }
182
183 DRM_COPY_FROM_USER_IOCTL( emit, (drm_radeon_irq_emit_t __user *)data,
184 sizeof(emit) );
185
186 result = radeon_emit_irq( dev );
187
188 if ( DRM_COPY_TO_USER( emit.irq_seq, &result, sizeof(int) ) ) {
189 DRM_ERROR( "copy_to_user\n" );
190 return DRM_ERR(EFAULT);
191 }
192
193 return 0;
194}
195
196
197/* Doesn't need the hardware lock.
198 */
199int radeon_irq_wait( DRM_IOCTL_ARGS )
200{
201 DRM_DEVICE;
202 drm_radeon_private_t *dev_priv = dev->dev_private;
203 drm_radeon_irq_wait_t irqwait;
204
205 if ( !dev_priv ) {
206 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
207 return DRM_ERR(EINVAL);
208 }
209
210 DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_radeon_irq_wait_t __user*)data,
211 sizeof(irqwait) );
212
213 return radeon_wait_irq( dev, irqwait.irq_seq );
214}
215
216
217/* drm_dma.h hooks
218*/
219void radeon_driver_irq_preinstall( drm_device_t *dev ) {
220 drm_radeon_private_t *dev_priv =
221 (drm_radeon_private_t *)dev->dev_private;
222
223 /* Disable *all* interrupts */
224 RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
225
226 /* Clear bits if they're already high */
227 radeon_acknowledge_irqs( dev_priv );
228}
229
230void radeon_driver_irq_postinstall( drm_device_t *dev ) {
231 drm_radeon_private_t *dev_priv =
232 (drm_radeon_private_t *)dev->dev_private;
233
234 atomic_set(&dev_priv->swi_emitted, 0);
235 DRM_INIT_WAITQUEUE( &dev_priv->swi_queue );
236
237 /* Turn on SW and VBL ints */
238 RADEON_WRITE( RADEON_GEN_INT_CNTL,
239 RADEON_CRTC_VBLANK_MASK |
240 RADEON_SW_INT_ENABLE );
241}
242
243void radeon_driver_irq_uninstall( drm_device_t *dev ) {
244 drm_radeon_private_t *dev_priv =
245 (drm_radeon_private_t *)dev->dev_private;
246 if (!dev_priv)
247 return;
248
249 /* Disable *all* interrupts */
250 RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
251}
diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c
new file mode 100644
index 000000000000..134f894e6e4b
--- /dev/null
+++ b/drivers/char/drm/radeon_mem.c
@@ -0,0 +1,322 @@
1/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*-
2 *
3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 *
5 * The Weather Channel (TM) funded Tungsten Graphics to develop the
6 * initial release of the Radeon 8500 driver under the XFree86 license.
7 * This notice must be preserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 */
31
32#include "drmP.h"
33#include "drm.h"
34#include "radeon_drm.h"
35#include "radeon_drv.h"
36
37/* Very simple allocator for GART memory, working on a static range
38 * already mapped into each client's address space.
39 */
40
41static struct mem_block *split_block(struct mem_block *p, int start, int size,
42 DRMFILE filp )
43{
44 /* Maybe cut off the start of an existing block */
45 if (start > p->start) {
46 struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFS );
47 if (!newblock)
48 goto out;
49 newblock->start = start;
50 newblock->size = p->size - (start - p->start);
51 newblock->filp = NULL;
52 newblock->next = p->next;
53 newblock->prev = p;
54 p->next->prev = newblock;
55 p->next = newblock;
56 p->size -= newblock->size;
57 p = newblock;
58 }
59
60 /* Maybe cut off the end of an existing block */
61 if (size < p->size) {
62 struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFS );
63 if (!newblock)
64 goto out;
65 newblock->start = start + size;
66 newblock->size = p->size - size;
67 newblock->filp = NULL;
68 newblock->next = p->next;
69 newblock->prev = p;
70 p->next->prev = newblock;
71 p->next = newblock;
72 p->size = size;
73 }
74
75 out:
76 /* Our block is in the middle */
77 p->filp = filp;
78 return p;
79}
80
81static struct mem_block *alloc_block( struct mem_block *heap, int size,
82 int align2, DRMFILE filp )
83{
84 struct mem_block *p;
85 int mask = (1 << align2)-1;
86
87 list_for_each(p, heap) {
88 int start = (p->start + mask) & ~mask;
89 if (p->filp == 0 && start + size <= p->start + p->size)
90 return split_block( p, start, size, filp );
91 }
92
93 return NULL;
94}
95
96static struct mem_block *find_block( struct mem_block *heap, int start )
97{
98 struct mem_block *p;
99
100 list_for_each(p, heap)
101 if (p->start == start)
102 return p;
103
104 return NULL;
105}
106
107
108static void free_block( struct mem_block *p )
109{
110 p->filp = NULL;
111
112 /* Assumes a single contiguous range. Needs a special filp in
113 * 'heap' to stop it being subsumed.
114 */
115 if (p->next->filp == 0) {
116 struct mem_block *q = p->next;
117 p->size += q->size;
118 p->next = q->next;
119 p->next->prev = p;
120 drm_free(q, sizeof(*q), DRM_MEM_BUFS );
121 }
122
123 if (p->prev->filp == 0) {
124 struct mem_block *q = p->prev;
125 q->size += p->size;
126 q->next = p->next;
127 q->next->prev = q;
128 drm_free(p, sizeof(*q), DRM_MEM_BUFS );
129 }
130}
131
132/* Initialize. How to check for an uninitialized heap?
133 */
134static int init_heap(struct mem_block **heap, int start, int size)
135{
136 struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS );
137
138 if (!blocks)
139 return DRM_ERR(ENOMEM);
140
141 *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS );
142 if (!*heap) {
143 drm_free( blocks, sizeof(*blocks), DRM_MEM_BUFS );
144 return DRM_ERR(ENOMEM);
145 }
146
147 blocks->start = start;
148 blocks->size = size;
149 blocks->filp = NULL;
150 blocks->next = blocks->prev = *heap;
151
152 memset( *heap, 0, sizeof(**heap) );
153 (*heap)->filp = (DRMFILE) -1;
154 (*heap)->next = (*heap)->prev = blocks;
155 return 0;
156}
157
158
159/* Free all blocks associated with the releasing file.
160 */
161void radeon_mem_release( DRMFILE filp, struct mem_block *heap )
162{
163 struct mem_block *p;
164
165 if (!heap || !heap->next)
166 return;
167
168 list_for_each(p, heap) {
169 if (p->filp == filp)
170 p->filp = NULL;
171 }
172
173 /* Assumes a single contiguous range. Needs a special filp in
174 * 'heap' to stop it being subsumed.
175 */
176 list_for_each(p, heap) {
177 while (p->filp == 0 && p->next->filp == 0) {
178 struct mem_block *q = p->next;
179 p->size += q->size;
180 p->next = q->next;
181 p->next->prev = p;
182 drm_free(q, sizeof(*q),DRM_MEM_DRIVER);
183 }
184 }
185}
186
187/* Shutdown.
188 */
189void radeon_mem_takedown( struct mem_block **heap )
190{
191 struct mem_block *p;
192
193 if (!*heap)
194 return;
195
196 for (p = (*heap)->next ; p != *heap ; ) {
197 struct mem_block *q = p;
198 p = p->next;
199 drm_free(q, sizeof(*q),DRM_MEM_DRIVER);
200 }
201
202 drm_free( *heap, sizeof(**heap),DRM_MEM_DRIVER );
203 *heap = NULL;
204}
205
206
207
208/* IOCTL HANDLERS */
209
210static struct mem_block **get_heap( drm_radeon_private_t *dev_priv,
211 int region )
212{
213 switch( region ) {
214 case RADEON_MEM_REGION_GART:
215 return &dev_priv->gart_heap;
216 case RADEON_MEM_REGION_FB:
217 return &dev_priv->fb_heap;
218 default:
219 return NULL;
220 }
221}
222
223int radeon_mem_alloc( DRM_IOCTL_ARGS )
224{
225 DRM_DEVICE;
226 drm_radeon_private_t *dev_priv = dev->dev_private;
227 drm_radeon_mem_alloc_t alloc;
228 struct mem_block *block, **heap;
229
230 if ( !dev_priv ) {
231 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
232 return DRM_ERR(EINVAL);
233 }
234
235 DRM_COPY_FROM_USER_IOCTL( alloc, (drm_radeon_mem_alloc_t __user *)data,
236 sizeof(alloc) );
237
238 heap = get_heap( dev_priv, alloc.region );
239 if (!heap || !*heap)
240 return DRM_ERR(EFAULT);
241
242 /* Make things easier on ourselves: all allocations at least
243 * 4k aligned.
244 */
245 if (alloc.alignment < 12)
246 alloc.alignment = 12;
247
248 block = alloc_block( *heap, alloc.size, alloc.alignment,
249 filp );
250
251 if (!block)
252 return DRM_ERR(ENOMEM);
253
254 if ( DRM_COPY_TO_USER( alloc.region_offset, &block->start,
255 sizeof(int) ) ) {
256 DRM_ERROR( "copy_to_user\n" );
257 return DRM_ERR(EFAULT);
258 }
259
260 return 0;
261}
262
263
264
265int radeon_mem_free( DRM_IOCTL_ARGS )
266{
267 DRM_DEVICE;
268 drm_radeon_private_t *dev_priv = dev->dev_private;
269 drm_radeon_mem_free_t memfree;
270 struct mem_block *block, **heap;
271
272 if ( !dev_priv ) {
273 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
274 return DRM_ERR(EINVAL);
275 }
276
277 DRM_COPY_FROM_USER_IOCTL( memfree, (drm_radeon_mem_free_t __user *)data,
278 sizeof(memfree) );
279
280 heap = get_heap( dev_priv, memfree.region );
281 if (!heap || !*heap)
282 return DRM_ERR(EFAULT);
283
284 block = find_block( *heap, memfree.region_offset );
285 if (!block)
286 return DRM_ERR(EFAULT);
287
288 if (block->filp != filp)
289 return DRM_ERR(EPERM);
290
291 free_block( block );
292 return 0;
293}
294
295int radeon_mem_init_heap( DRM_IOCTL_ARGS )
296{
297 DRM_DEVICE;
298 drm_radeon_private_t *dev_priv = dev->dev_private;
299 drm_radeon_mem_init_heap_t initheap;
300 struct mem_block **heap;
301
302 if ( !dev_priv ) {
303 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
304 return DRM_ERR(EINVAL);
305 }
306
307 DRM_COPY_FROM_USER_IOCTL( initheap, (drm_radeon_mem_init_heap_t __user *)data,
308 sizeof(initheap) );
309
310 heap = get_heap( dev_priv, initheap.region );
311 if (!heap)
312 return DRM_ERR(EFAULT);
313
314 if (*heap) {
315 DRM_ERROR("heap already initialized?");
316 return DRM_ERR(EFAULT);
317 }
318
319 return init_heap( heap, initheap.start, initheap.size );
320}
321
322
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
new file mode 100644
index 000000000000..1f79e249146c
--- /dev/null
+++ b/drivers/char/drm/radeon_state.c
@@ -0,0 +1,3102 @@
1/* radeon_state.c -- State support for Radeon -*- linux-c -*-
2 *
3 * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 * Gareth Hughes <gareth@valinux.com>
27 * Kevin E. Martin <martin@valinux.com>
28 */
29
30#include "drmP.h"
31#include "drm.h"
32#include "drm_sarea.h"
33#include "radeon_drm.h"
34#include "radeon_drv.h"
35
36/* ================================================================
37 * Helper functions for client state checking and fixup
38 */
39
40static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_priv,
41 drm_file_t *filp_priv,
42 u32 *offset ) {
43 u32 off = *offset;
44 struct drm_radeon_driver_file_fields *radeon_priv;
45
46 if ( off >= dev_priv->fb_location &&
47 off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
48 return 0;
49
50 radeon_priv = filp_priv->driver_priv;
51 off += radeon_priv->radeon_fb_delta;
52
53 DRM_DEBUG( "offset fixed up to 0x%x\n", off );
54
55 if ( off < dev_priv->fb_location ||
56 off >= ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
57 return DRM_ERR( EINVAL );
58
59 *offset = off;
60
61 return 0;
62}
63
64static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv,
65 drm_file_t *filp_priv,
66 int id,
67 u32 __user *data ) {
68 switch ( id ) {
69
70 case RADEON_EMIT_PP_MISC:
71 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
72 &data[( RADEON_RB3D_DEPTHOFFSET
73 - RADEON_PP_MISC ) / 4] ) ) {
74 DRM_ERROR( "Invalid depth buffer offset\n" );
75 return DRM_ERR( EINVAL );
76 }
77 break;
78
79 case RADEON_EMIT_PP_CNTL:
80 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
81 &data[( RADEON_RB3D_COLOROFFSET
82 - RADEON_PP_CNTL ) / 4] ) ) {
83 DRM_ERROR( "Invalid colour buffer offset\n" );
84 return DRM_ERR( EINVAL );
85 }
86 break;
87
88 case R200_EMIT_PP_TXOFFSET_0:
89 case R200_EMIT_PP_TXOFFSET_1:
90 case R200_EMIT_PP_TXOFFSET_2:
91 case R200_EMIT_PP_TXOFFSET_3:
92 case R200_EMIT_PP_TXOFFSET_4:
93 case R200_EMIT_PP_TXOFFSET_5:
94 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
95 &data[0] ) ) {
96 DRM_ERROR( "Invalid R200 texture offset\n" );
97 return DRM_ERR( EINVAL );
98 }
99 break;
100
101 case RADEON_EMIT_PP_TXFILTER_0:
102 case RADEON_EMIT_PP_TXFILTER_1:
103 case RADEON_EMIT_PP_TXFILTER_2:
104 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
105 &data[( RADEON_PP_TXOFFSET_0
106 - RADEON_PP_TXFILTER_0 ) / 4] ) ) {
107 DRM_ERROR( "Invalid R100 texture offset\n" );
108 return DRM_ERR( EINVAL );
109 }
110 break;
111
112 case R200_EMIT_PP_CUBIC_OFFSETS_0:
113 case R200_EMIT_PP_CUBIC_OFFSETS_1:
114 case R200_EMIT_PP_CUBIC_OFFSETS_2:
115 case R200_EMIT_PP_CUBIC_OFFSETS_3:
116 case R200_EMIT_PP_CUBIC_OFFSETS_4:
117 case R200_EMIT_PP_CUBIC_OFFSETS_5: {
118 int i;
119 for ( i = 0; i < 5; i++ ) {
120 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
121 &data[i] ) ) {
122 DRM_ERROR( "Invalid R200 cubic texture offset\n" );
123 return DRM_ERR( EINVAL );
124 }
125 }
126 break;
127 }
128
129 case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
130 case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
131 case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
132 int i;
133 for (i = 0; i < 5; i++) {
134 if (radeon_check_and_fixup_offset(dev_priv,
135 filp_priv,
136 &data[i])) {
137 DRM_ERROR
138 ("Invalid R100 cubic texture offset\n");
139 return DRM_ERR(EINVAL);
140 }
141 }
142 }
143 break;
144
145 case RADEON_EMIT_RB3D_COLORPITCH:
146 case RADEON_EMIT_RE_LINE_PATTERN:
147 case RADEON_EMIT_SE_LINE_WIDTH:
148 case RADEON_EMIT_PP_LUM_MATRIX:
149 case RADEON_EMIT_PP_ROT_MATRIX_0:
150 case RADEON_EMIT_RB3D_STENCILREFMASK:
151 case RADEON_EMIT_SE_VPORT_XSCALE:
152 case RADEON_EMIT_SE_CNTL:
153 case RADEON_EMIT_SE_CNTL_STATUS:
154 case RADEON_EMIT_RE_MISC:
155 case RADEON_EMIT_PP_BORDER_COLOR_0:
156 case RADEON_EMIT_PP_BORDER_COLOR_1:
157 case RADEON_EMIT_PP_BORDER_COLOR_2:
158 case RADEON_EMIT_SE_ZBIAS_FACTOR:
159 case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
160 case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
161 case R200_EMIT_PP_TXCBLEND_0:
162 case R200_EMIT_PP_TXCBLEND_1:
163 case R200_EMIT_PP_TXCBLEND_2:
164 case R200_EMIT_PP_TXCBLEND_3:
165 case R200_EMIT_PP_TXCBLEND_4:
166 case R200_EMIT_PP_TXCBLEND_5:
167 case R200_EMIT_PP_TXCBLEND_6:
168 case R200_EMIT_PP_TXCBLEND_7:
169 case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
170 case R200_EMIT_TFACTOR_0:
171 case R200_EMIT_VTX_FMT_0:
172 case R200_EMIT_VAP_CTL:
173 case R200_EMIT_MATRIX_SELECT_0:
174 case R200_EMIT_TEX_PROC_CTL_2:
175 case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
176 case R200_EMIT_PP_TXFILTER_0:
177 case R200_EMIT_PP_TXFILTER_1:
178 case R200_EMIT_PP_TXFILTER_2:
179 case R200_EMIT_PP_TXFILTER_3:
180 case R200_EMIT_PP_TXFILTER_4:
181 case R200_EMIT_PP_TXFILTER_5:
182 case R200_EMIT_VTE_CNTL:
183 case R200_EMIT_OUTPUT_VTX_COMP_SEL:
184 case R200_EMIT_PP_TAM_DEBUG3:
185 case R200_EMIT_PP_CNTL_X:
186 case R200_EMIT_RB3D_DEPTHXY_OFFSET:
187 case R200_EMIT_RE_AUX_SCISSOR_CNTL:
188 case R200_EMIT_RE_SCISSOR_TL_0:
189 case R200_EMIT_RE_SCISSOR_TL_1:
190 case R200_EMIT_RE_SCISSOR_TL_2:
191 case R200_EMIT_SE_VAP_CNTL_STATUS:
192 case R200_EMIT_SE_VTX_STATE_CNTL:
193 case R200_EMIT_RE_POINTSIZE:
194 case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0:
195 case R200_EMIT_PP_CUBIC_FACES_0:
196 case R200_EMIT_PP_CUBIC_FACES_1:
197 case R200_EMIT_PP_CUBIC_FACES_2:
198 case R200_EMIT_PP_CUBIC_FACES_3:
199 case R200_EMIT_PP_CUBIC_FACES_4:
200 case R200_EMIT_PP_CUBIC_FACES_5:
201 case RADEON_EMIT_PP_TEX_SIZE_0:
202 case RADEON_EMIT_PP_TEX_SIZE_1:
203 case RADEON_EMIT_PP_TEX_SIZE_2:
204 case R200_EMIT_RB3D_BLENDCOLOR:
205 case R200_EMIT_TCL_POINT_SPRITE_CNTL:
206 case RADEON_EMIT_PP_CUBIC_FACES_0:
207 case RADEON_EMIT_PP_CUBIC_FACES_1:
208 case RADEON_EMIT_PP_CUBIC_FACES_2:
209 case R200_EMIT_PP_TRI_PERF_CNTL:
210 /* These packets don't contain memory offsets */
211 break;
212
213 default:
214 DRM_ERROR( "Unknown state packet ID %d\n", id );
215 return DRM_ERR( EINVAL );
216 }
217
218 return 0;
219}
220
221static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_priv,
222 drm_file_t *filp_priv,
223 drm_radeon_cmd_buffer_t *cmdbuf,
224 unsigned int *cmdsz ) {
225 u32 *cmd = (u32 *) cmdbuf->buf;
226
227 *cmdsz = 2 + ( ( cmd[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 );
228
229 if ( ( cmd[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) {
230 DRM_ERROR( "Not a type 3 packet\n" );
231 return DRM_ERR( EINVAL );
232 }
233
234 if ( 4 * *cmdsz > cmdbuf->bufsz ) {
235 DRM_ERROR( "Packet size larger than size of data provided\n" );
236 return DRM_ERR( EINVAL );
237 }
238
239 /* Check client state and fix it up if necessary */
240 if ( cmd[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */
241 u32 offset;
242
243 if ( cmd[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL
244 | RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
245 offset = cmd[2] << 10;
246 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
247 DRM_ERROR( "Invalid first packet offset\n" );
248 return DRM_ERR( EINVAL );
249 }
250 cmd[2] = ( cmd[2] & 0xffc00000 ) | offset >> 10;
251 }
252
253 if ( ( cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) &&
254 ( cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
255 offset = cmd[3] << 10;
256 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
257 DRM_ERROR( "Invalid second packet offset\n" );
258 return DRM_ERR( EINVAL );
259 }
260 cmd[3] = ( cmd[3] & 0xffc00000 ) | offset >> 10;
261 }
262 }
263
264 return 0;
265}
266
267
268/* ================================================================
269 * CP hardware state programming functions
270 */
271
272static __inline__ void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
273 drm_clip_rect_t *box )
274{
275 RING_LOCALS;
276
277 DRM_DEBUG( " box: x1=%d y1=%d x2=%d y2=%d\n",
278 box->x1, box->y1, box->x2, box->y2 );
279
280 BEGIN_RING( 4 );
281 OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
282 OUT_RING( (box->y1 << 16) | box->x1 );
283 OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
284 OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
285 ADVANCE_RING();
286}
287
288/* Emit 1.1 state
289 */
290static int radeon_emit_state( drm_radeon_private_t *dev_priv,
291 drm_file_t *filp_priv,
292 drm_radeon_context_regs_t *ctx,
293 drm_radeon_texture_regs_t *tex,
294 unsigned int dirty )
295{
296 RING_LOCALS;
297 DRM_DEBUG( "dirty=0x%08x\n", dirty );
298
299 if ( dirty & RADEON_UPLOAD_CONTEXT ) {
300 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
301 &ctx->rb3d_depthoffset ) ) {
302 DRM_ERROR( "Invalid depth buffer offset\n" );
303 return DRM_ERR( EINVAL );
304 }
305
306 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
307 &ctx->rb3d_coloroffset ) ) {
308 DRM_ERROR( "Invalid depth buffer offset\n" );
309 return DRM_ERR( EINVAL );
310 }
311
312 BEGIN_RING( 14 );
313 OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
314 OUT_RING( ctx->pp_misc );
315 OUT_RING( ctx->pp_fog_color );
316 OUT_RING( ctx->re_solid_color );
317 OUT_RING( ctx->rb3d_blendcntl );
318 OUT_RING( ctx->rb3d_depthoffset );
319 OUT_RING( ctx->rb3d_depthpitch );
320 OUT_RING( ctx->rb3d_zstencilcntl );
321 OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
322 OUT_RING( ctx->pp_cntl );
323 OUT_RING( ctx->rb3d_cntl );
324 OUT_RING( ctx->rb3d_coloroffset );
325 OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
326 OUT_RING( ctx->rb3d_colorpitch );
327 ADVANCE_RING();
328 }
329
330 if ( dirty & RADEON_UPLOAD_VERTFMT ) {
331 BEGIN_RING( 2 );
332 OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
333 OUT_RING( ctx->se_coord_fmt );
334 ADVANCE_RING();
335 }
336
337 if ( dirty & RADEON_UPLOAD_LINE ) {
338 BEGIN_RING( 5 );
339 OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
340 OUT_RING( ctx->re_line_pattern );
341 OUT_RING( ctx->re_line_state );
342 OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
343 OUT_RING( ctx->se_line_width );
344 ADVANCE_RING();
345 }
346
347 if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
348 BEGIN_RING( 5 );
349 OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
350 OUT_RING( ctx->pp_lum_matrix );
351 OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
352 OUT_RING( ctx->pp_rot_matrix_0 );
353 OUT_RING( ctx->pp_rot_matrix_1 );
354 ADVANCE_RING();
355 }
356
357 if ( dirty & RADEON_UPLOAD_MASKS ) {
358 BEGIN_RING( 4 );
359 OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
360 OUT_RING( ctx->rb3d_stencilrefmask );
361 OUT_RING( ctx->rb3d_ropcntl );
362 OUT_RING( ctx->rb3d_planemask );
363 ADVANCE_RING();
364 }
365
366 if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
367 BEGIN_RING( 7 );
368 OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
369 OUT_RING( ctx->se_vport_xscale );
370 OUT_RING( ctx->se_vport_xoffset );
371 OUT_RING( ctx->se_vport_yscale );
372 OUT_RING( ctx->se_vport_yoffset );
373 OUT_RING( ctx->se_vport_zscale );
374 OUT_RING( ctx->se_vport_zoffset );
375 ADVANCE_RING();
376 }
377
378 if ( dirty & RADEON_UPLOAD_SETUP ) {
379 BEGIN_RING( 4 );
380 OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
381 OUT_RING( ctx->se_cntl );
382 OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
383 OUT_RING( ctx->se_cntl_status );
384 ADVANCE_RING();
385 }
386
387 if ( dirty & RADEON_UPLOAD_MISC ) {
388 BEGIN_RING( 2 );
389 OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
390 OUT_RING( ctx->re_misc );
391 ADVANCE_RING();
392 }
393
394 if ( dirty & RADEON_UPLOAD_TEX0 ) {
395 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
396 &tex[0].pp_txoffset ) ) {
397 DRM_ERROR( "Invalid texture offset for unit 0\n" );
398 return DRM_ERR( EINVAL );
399 }
400
401 BEGIN_RING( 9 );
402 OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
403 OUT_RING( tex[0].pp_txfilter );
404 OUT_RING( tex[0].pp_txformat );
405 OUT_RING( tex[0].pp_txoffset );
406 OUT_RING( tex[0].pp_txcblend );
407 OUT_RING( tex[0].pp_txablend );
408 OUT_RING( tex[0].pp_tfactor );
409 OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
410 OUT_RING( tex[0].pp_border_color );
411 ADVANCE_RING();
412 }
413
414 if ( dirty & RADEON_UPLOAD_TEX1 ) {
415 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
416 &tex[1].pp_txoffset ) ) {
417 DRM_ERROR( "Invalid texture offset for unit 1\n" );
418 return DRM_ERR( EINVAL );
419 }
420
421 BEGIN_RING( 9 );
422 OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
423 OUT_RING( tex[1].pp_txfilter );
424 OUT_RING( tex[1].pp_txformat );
425 OUT_RING( tex[1].pp_txoffset );
426 OUT_RING( tex[1].pp_txcblend );
427 OUT_RING( tex[1].pp_txablend );
428 OUT_RING( tex[1].pp_tfactor );
429 OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
430 OUT_RING( tex[1].pp_border_color );
431 ADVANCE_RING();
432 }
433
434 if ( dirty & RADEON_UPLOAD_TEX2 ) {
435 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
436 &tex[2].pp_txoffset ) ) {
437 DRM_ERROR( "Invalid texture offset for unit 2\n" );
438 return DRM_ERR( EINVAL );
439 }
440
441 BEGIN_RING( 9 );
442 OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
443 OUT_RING( tex[2].pp_txfilter );
444 OUT_RING( tex[2].pp_txformat );
445 OUT_RING( tex[2].pp_txoffset );
446 OUT_RING( tex[2].pp_txcblend );
447 OUT_RING( tex[2].pp_txablend );
448 OUT_RING( tex[2].pp_tfactor );
449 OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
450 OUT_RING( tex[2].pp_border_color );
451 ADVANCE_RING();
452 }
453
454 return 0;
455}
456
457/* Emit 1.2 state
458 */
459static int radeon_emit_state2( drm_radeon_private_t *dev_priv,
460 drm_file_t *filp_priv,
461 drm_radeon_state_t *state )
462{
463 RING_LOCALS;
464
465 if (state->dirty & RADEON_UPLOAD_ZBIAS) {
466 BEGIN_RING( 3 );
467 OUT_RING( CP_PACKET0( RADEON_SE_ZBIAS_FACTOR, 1 ) );
468 OUT_RING( state->context2.se_zbias_factor );
469 OUT_RING( state->context2.se_zbias_constant );
470 ADVANCE_RING();
471 }
472
473 return radeon_emit_state( dev_priv, filp_priv, &state->context,
474 state->tex, state->dirty );
475}
476
477/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
478 * 1.3 cmdbuffers allow all previous state to be updated as well as
479 * the tcl scalar and vector areas.
480 */
481static struct {
482 int start;
483 int len;
484 const char *name;
485} packet[RADEON_MAX_STATE_PACKETS] = {
486 { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
487 { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
488 { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
489 { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
490 { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
491 { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
492 { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
493 { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
494 { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
495 { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
496 { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
497 { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
498 { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
499 { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
500 { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
501 { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
502 { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
503 { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
504 { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
505 { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
506 { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
507 { R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0" },
508 { R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1" },
509 { R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2" },
510 { R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3" },
511 { R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4" },
512 { R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5" },
513 { R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6" },
514 { R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7" },
515 { R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" },
516 { R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0" },
517 { R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0" },
518 { R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL" },
519 { R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0" },
520 { R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2" },
521 { R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" },
522 { R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0" },
523 { R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1" },
524 { R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2" },
525 { R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3" },
526 { R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4" },
527 { R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5" },
528 { R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0" },
529 { R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1" },
530 { R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2" },
531 { R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3" },
532 { R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4" },
533 { R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5" },
534 { R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL" },
535 { R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" },
536 { R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3" },
537 { R200_PP_CNTL_X, 1, "R200_PP_CNTL_X" },
538 { R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET" },
539 { R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL" },
540 { R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0" },
541 { R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1" },
542 { R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2" },
543 { R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS" },
544 { R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL" },
545 { R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE" },
546 { R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" },
547 { R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */
548 { R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */
549 { R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1" },
550 { R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1" },
551 { R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2" },
552 { R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2" },
553 { R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3" },
554 { R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3" },
555 { R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4" },
556 { R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
557 { R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" },
558 { R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
559 { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
560 { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
561 { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2" },
562 { R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR" },
563 { R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL" },
564 { RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
565 { RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
566 { RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
567 { RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
568 { RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
569 { RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
570 { R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
571};
572
573
574
575/* ================================================================
576 * Performance monitoring functions
577 */
578
579static void radeon_clear_box( drm_radeon_private_t *dev_priv,
580 int x, int y, int w, int h,
581 int r, int g, int b )
582{
583 u32 color;
584 RING_LOCALS;
585
586 x += dev_priv->sarea_priv->boxes[0].x1;
587 y += dev_priv->sarea_priv->boxes[0].y1;
588
589 switch ( dev_priv->color_fmt ) {
590 case RADEON_COLOR_FORMAT_RGB565:
591 color = (((r & 0xf8) << 8) |
592 ((g & 0xfc) << 3) |
593 ((b & 0xf8) >> 3));
594 break;
595 case RADEON_COLOR_FORMAT_ARGB8888:
596 default:
597 color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
598 break;
599 }
600
601 BEGIN_RING( 4 );
602 RADEON_WAIT_UNTIL_3D_IDLE();
603 OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
604 OUT_RING( 0xffffffff );
605 ADVANCE_RING();
606
607 BEGIN_RING( 6 );
608
609 OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
610 OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
611 RADEON_GMC_BRUSH_SOLID_COLOR |
612 (dev_priv->color_fmt << 8) |
613 RADEON_GMC_SRC_DATATYPE_COLOR |
614 RADEON_ROP3_P |
615 RADEON_GMC_CLR_CMP_CNTL_DIS );
616
617 if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
618 OUT_RING( dev_priv->front_pitch_offset );
619 } else {
620 OUT_RING( dev_priv->back_pitch_offset );
621 }
622
623 OUT_RING( color );
624
625 OUT_RING( (x << 16) | y );
626 OUT_RING( (w << 16) | h );
627
628 ADVANCE_RING();
629}
630
631static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
632{
633 /* Collapse various things into a wait flag -- trying to
634 * guess if userspase slept -- better just to have them tell us.
635 */
636 if (dev_priv->stats.last_frame_reads > 1 ||
637 dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
638 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
639 }
640
641 if (dev_priv->stats.freelist_loops) {
642 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
643 }
644
645 /* Purple box for page flipping
646 */
647 if ( dev_priv->stats.boxes & RADEON_BOX_FLIP )
648 radeon_clear_box( dev_priv, 4, 4, 8, 8, 255, 0, 255 );
649
650 /* Red box if we have to wait for idle at any point
651 */
652 if ( dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE )
653 radeon_clear_box( dev_priv, 16, 4, 8, 8, 255, 0, 0 );
654
655 /* Blue box: lost context?
656 */
657
658 /* Yellow box for texture swaps
659 */
660 if ( dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD )
661 radeon_clear_box( dev_priv, 40, 4, 8, 8, 255, 255, 0 );
662
663 /* Green box if hardware never idles (as far as we can tell)
664 */
665 if ( !(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE) )
666 radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
667
668
669 /* Draw bars indicating number of buffers allocated
670 * (not a great measure, easily confused)
671 */
672 if (dev_priv->stats.requested_bufs) {
673 if (dev_priv->stats.requested_bufs > 100)
674 dev_priv->stats.requested_bufs = 100;
675
676 radeon_clear_box( dev_priv, 4, 16,
677 dev_priv->stats.requested_bufs, 4,
678 196, 128, 128 );
679 }
680
681 memset( &dev_priv->stats, 0, sizeof(dev_priv->stats) );
682
683}
684/* ================================================================
685 * CP command dispatch functions
686 */
687
688static void radeon_cp_dispatch_clear( drm_device_t *dev,
689 drm_radeon_clear_t *clear,
690 drm_radeon_clear_rect_t *depth_boxes )
691{
692 drm_radeon_private_t *dev_priv = dev->dev_private;
693 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
694 drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
695 int nbox = sarea_priv->nbox;
696 drm_clip_rect_t *pbox = sarea_priv->boxes;
697 unsigned int flags = clear->flags;
698 u32 rb3d_cntl = 0, rb3d_stencilrefmask= 0;
699 int i;
700 RING_LOCALS;
701 DRM_DEBUG( "flags = 0x%x\n", flags );
702
703 dev_priv->stats.clears++;
704
705 if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
706 unsigned int tmp = flags;
707
708 flags &= ~(RADEON_FRONT | RADEON_BACK);
709 if ( tmp & RADEON_FRONT ) flags |= RADEON_BACK;
710 if ( tmp & RADEON_BACK ) flags |= RADEON_FRONT;
711 }
712
713 if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
714
715 BEGIN_RING( 4 );
716
717 /* Ensure the 3D stream is idle before doing a
718 * 2D fill to clear the front or back buffer.
719 */
720 RADEON_WAIT_UNTIL_3D_IDLE();
721
722 OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
723 OUT_RING( clear->color_mask );
724
725 ADVANCE_RING();
726
727 /* Make sure we restore the 3D state next time.
728 */
729 dev_priv->sarea_priv->ctx_owner = 0;
730
731 for ( i = 0 ; i < nbox ; i++ ) {
732 int x = pbox[i].x1;
733 int y = pbox[i].y1;
734 int w = pbox[i].x2 - x;
735 int h = pbox[i].y2 - y;
736
737 DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
738 x, y, w, h, flags );
739
740 if ( flags & RADEON_FRONT ) {
741 BEGIN_RING( 6 );
742
743 OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
744 OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
745 RADEON_GMC_BRUSH_SOLID_COLOR |
746 (dev_priv->color_fmt << 8) |
747 RADEON_GMC_SRC_DATATYPE_COLOR |
748 RADEON_ROP3_P |
749 RADEON_GMC_CLR_CMP_CNTL_DIS );
750
751 OUT_RING( dev_priv->front_pitch_offset );
752 OUT_RING( clear->clear_color );
753
754 OUT_RING( (x << 16) | y );
755 OUT_RING( (w << 16) | h );
756
757 ADVANCE_RING();
758 }
759
760 if ( flags & RADEON_BACK ) {
761 BEGIN_RING( 6 );
762
763 OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
764 OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
765 RADEON_GMC_BRUSH_SOLID_COLOR |
766 (dev_priv->color_fmt << 8) |
767 RADEON_GMC_SRC_DATATYPE_COLOR |
768 RADEON_ROP3_P |
769 RADEON_GMC_CLR_CMP_CNTL_DIS );
770
771 OUT_RING( dev_priv->back_pitch_offset );
772 OUT_RING( clear->clear_color );
773
774 OUT_RING( (x << 16) | y );
775 OUT_RING( (w << 16) | h );
776
777 ADVANCE_RING();
778 }
779 }
780 }
781
782 /* hyper z clear */
783 /* no docs available, based on reverse engeneering by Stephane Marchesin */
784 if ((flags & (RADEON_DEPTH | RADEON_STENCIL)) && (flags & RADEON_CLEAR_FASTZ)) {
785
786 int i;
787 int depthpixperline = dev_priv->depth_fmt==RADEON_DEPTH_FORMAT_16BIT_INT_Z?
788 (dev_priv->depth_pitch / 2): (dev_priv->depth_pitch / 4);
789
790 u32 clearmask;
791
792 u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth |
793 ((clear->depth_mask & 0xff) << 24);
794
795
796 /* Make sure we restore the 3D state next time.
797 * we haven't touched any "normal" state - still need this?
798 */
799 dev_priv->sarea_priv->ctx_owner = 0;
800
801 if ((dev_priv->flags & CHIP_HAS_HIERZ) && (flags & RADEON_USE_HIERZ)) {
802 /* FIXME : reverse engineer that for Rx00 cards */
803 /* FIXME : the mask supposedly contains low-res z values. So can't set
804 just to the max (0xff? or actually 0x3fff?), need to take z clear
805 value into account? */
806 /* pattern seems to work for r100, though get slight
807 rendering errors with glxgears. If hierz is not enabled for r100,
808 only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
809 other ones are ignored, and the same clear mask can be used. That's
810 very different behaviour than R200 which needs different clear mask
811 and different number of tiles to clear if hierz is enabled or not !?!
812 */
813 clearmask = (0xff<<22)|(0xff<<6)| 0x003f003f;
814 }
815 else {
816 /* clear mask : chooses the clearing pattern.
817 rv250: could be used to clear only parts of macrotiles
818 (but that would get really complicated...)?
819 bit 0 and 1 (either or both of them ?!?!) are used to
820 not clear tile (or maybe one of the bits indicates if the tile is
821 compressed or not), bit 2 and 3 to not clear tile 1,...,.
822 Pattern is as follows:
823 | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
824 bits -------------------------------------------------
825 | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
826 rv100: clearmask covers 2x8 4x1 tiles, but one clear still
827 covers 256 pixels ?!?
828 */
829 clearmask = 0x0;
830 }
831
832 BEGIN_RING( 8 );
833 RADEON_WAIT_UNTIL_2D_IDLE();
834 OUT_RING_REG( RADEON_RB3D_DEPTHCLEARVALUE,
835 tempRB3D_DEPTHCLEARVALUE);
836 /* what offset is this exactly ? */
837 OUT_RING_REG( RADEON_RB3D_ZMASKOFFSET, 0 );
838 /* need ctlstat, otherwise get some strange black flickering */
839 OUT_RING_REG( RADEON_RB3D_ZCACHE_CTLSTAT, RADEON_RB3D_ZC_FLUSH_ALL );
840 ADVANCE_RING();
841
842 for (i = 0; i < nbox; i++) {
843 int tileoffset, nrtilesx, nrtilesy, j;
844 /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
845 if ((dev_priv->flags&CHIP_HAS_HIERZ) && !(dev_priv->microcode_version==UCODE_R200)) {
846 /* FIXME : figure this out for r200 (when hierz is enabled). Or
847 maybe r200 actually doesn't need to put the low-res z value into
848 the tile cache like r100, but just needs to clear the hi-level z-buffer?
849 Works for R100, both with hierz and without.
850 R100 seems to operate on 2x1 8x8 tiles, but...
851 odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially
852 problematic with resolutions which are not 64 pix aligned? */
853 tileoffset = ((pbox[i].y1 >> 3) * depthpixperline + pbox[i].x1) >> 6;
854 nrtilesx = ((pbox[i].x2 & ~63) - (pbox[i].x1 & ~63)) >> 4;
855 nrtilesy = (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
856 for (j = 0; j <= nrtilesy; j++) {
857 BEGIN_RING( 4 );
858 OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) );
859 /* first tile */
860 OUT_RING( tileoffset * 8 );
861 /* the number of tiles to clear */
862 OUT_RING( nrtilesx + 4 );
863 /* clear mask : chooses the clearing pattern. */
864 OUT_RING( clearmask );
865 ADVANCE_RING();
866 tileoffset += depthpixperline >> 6;
867 }
868 }
869 else if (dev_priv->microcode_version==UCODE_R200) {
870 /* works for rv250. */
871 /* find first macro tile (8x2 4x4 z-pixels on rv250) */
872 tileoffset = ((pbox[i].y1 >> 3) * depthpixperline + pbox[i].x1) >> 5;
873 nrtilesx = (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
874 nrtilesy = (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
875 for (j = 0; j <= nrtilesy; j++) {
876 BEGIN_RING( 4 );
877 OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) );
878 /* first tile */
879 /* judging by the first tile offset needed, could possibly
880 directly address/clear 4x4 tiles instead of 8x2 * 4x4
881 macro tiles, though would still need clear mask for
882 right/bottom if truely 4x4 granularity is desired ? */
883 OUT_RING( tileoffset * 16 );
884 /* the number of tiles to clear */
885 OUT_RING( nrtilesx + 1 );
886 /* clear mask : chooses the clearing pattern. */
887 OUT_RING( clearmask );
888 ADVANCE_RING();
889 tileoffset += depthpixperline >> 5;
890 }
891 }
892 else { /* rv 100 */
893 /* rv100 might not need 64 pix alignment, who knows */
894 /* offsets are, hmm, weird */
895 tileoffset = ((pbox[i].y1 >> 4) * depthpixperline + pbox[i].x1) >> 6;
896 nrtilesx = ((pbox[i].x2 & ~63) - (pbox[i].x1 & ~63)) >> 4;
897 nrtilesy = (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
898 for (j = 0; j <= nrtilesy; j++) {
899 BEGIN_RING( 4 );
900 OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) );
901 OUT_RING( tileoffset * 128 );
902 /* the number of tiles to clear */
903 OUT_RING( nrtilesx + 4 );
904 /* clear mask : chooses the clearing pattern. */
905 OUT_RING( clearmask );
906 ADVANCE_RING();
907 tileoffset += depthpixperline >> 6;
908 }
909 }
910 }
911
912 /* TODO don't always clear all hi-level z tiles */
913 if ((dev_priv->flags & CHIP_HAS_HIERZ) && (dev_priv->microcode_version==UCODE_R200)
914 && (flags & RADEON_USE_HIERZ))
915 /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
916 /* FIXME : the mask supposedly contains low-res z values. So can't set
917 just to the max (0xff? or actually 0x3fff?), need to take z clear
918 value into account? */
919 {
920 BEGIN_RING( 4 );
921 OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_HIZ, 2 ) );
922 OUT_RING( 0x0 ); /* First tile */
923 OUT_RING( 0x3cc0 );
924 OUT_RING( (0xff<<22)|(0xff<<6)| 0x003f003f);
925 ADVANCE_RING();
926 }
927 }
928
929 /* We have to clear the depth and/or stencil buffers by
930 * rendering a quad into just those buffers. Thus, we have to
931 * make sure the 3D engine is configured correctly.
932 */
933 if ((dev_priv->microcode_version == UCODE_R200) &&
934 (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
935
936 int tempPP_CNTL;
937 int tempRE_CNTL;
938 int tempRB3D_CNTL;
939 int tempRB3D_ZSTENCILCNTL;
940 int tempRB3D_STENCILREFMASK;
941 int tempRB3D_PLANEMASK;
942 int tempSE_CNTL;
943 int tempSE_VTE_CNTL;
944 int tempSE_VTX_FMT_0;
945 int tempSE_VTX_FMT_1;
946 int tempSE_VAP_CNTL;
947 int tempRE_AUX_SCISSOR_CNTL;
948
949 tempPP_CNTL = 0;
950 tempRE_CNTL = 0;
951
952 tempRB3D_CNTL = depth_clear->rb3d_cntl;
953
954 tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
955 tempRB3D_STENCILREFMASK = 0x0;
956
957 tempSE_CNTL = depth_clear->se_cntl;
958
959
960
961 /* Disable TCL */
962
963 tempSE_VAP_CNTL = (/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */
964 (0x9 << SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
965
966 tempRB3D_PLANEMASK = 0x0;
967
968 tempRE_AUX_SCISSOR_CNTL = 0x0;
969
970 tempSE_VTE_CNTL =
971 SE_VTE_CNTL__VTX_XY_FMT_MASK |
972 SE_VTE_CNTL__VTX_Z_FMT_MASK;
973
974 /* Vertex format (X, Y, Z, W)*/
975 tempSE_VTX_FMT_0 =
976 SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
977 SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
978 tempSE_VTX_FMT_1 = 0x0;
979
980
981 /*
982 * Depth buffer specific enables
983 */
984 if (flags & RADEON_DEPTH) {
985 /* Enable depth buffer */
986 tempRB3D_CNTL |= RADEON_Z_ENABLE;
987 } else {
988 /* Disable depth buffer */
989 tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
990 }
991
992 /*
993 * Stencil buffer specific enables
994 */
995 if ( flags & RADEON_STENCIL ) {
996 tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
997 tempRB3D_STENCILREFMASK = clear->depth_mask;
998 } else {
999 tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
1000 tempRB3D_STENCILREFMASK = 0x00000000;
1001 }
1002
1003 if (flags & RADEON_USE_COMP_ZBUF) {
1004 tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
1005 RADEON_Z_DECOMPRESSION_ENABLE;
1006 }
1007 if (flags & RADEON_USE_HIERZ) {
1008 tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
1009 }
1010
1011 BEGIN_RING( 26 );
1012 RADEON_WAIT_UNTIL_2D_IDLE();
1013
1014 OUT_RING_REG( RADEON_PP_CNTL, tempPP_CNTL );
1015 OUT_RING_REG( R200_RE_CNTL, tempRE_CNTL );
1016 OUT_RING_REG( RADEON_RB3D_CNTL, tempRB3D_CNTL );
1017 OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL,
1018 tempRB3D_ZSTENCILCNTL );
1019 OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
1020 tempRB3D_STENCILREFMASK );
1021 OUT_RING_REG( RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK );
1022 OUT_RING_REG( RADEON_SE_CNTL, tempSE_CNTL );
1023 OUT_RING_REG( R200_SE_VTE_CNTL, tempSE_VTE_CNTL );
1024 OUT_RING_REG( R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0 );
1025 OUT_RING_REG( R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1 );
1026 OUT_RING_REG( R200_SE_VAP_CNTL, tempSE_VAP_CNTL );
1027 OUT_RING_REG( R200_RE_AUX_SCISSOR_CNTL,
1028 tempRE_AUX_SCISSOR_CNTL );
1029 ADVANCE_RING();
1030
1031 /* Make sure we restore the 3D state next time.
1032 */
1033 dev_priv->sarea_priv->ctx_owner = 0;
1034
1035 for ( i = 0 ; i < nbox ; i++ ) {
1036
1037 /* Funny that this should be required --
1038 * sets top-left?
1039 */
1040 radeon_emit_clip_rect( dev_priv,
1041 &sarea_priv->boxes[i] );
1042
1043 BEGIN_RING( 14 );
1044 OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 12 ) );
1045 OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
1046 RADEON_PRIM_WALK_RING |
1047 (3 << RADEON_NUM_VERTICES_SHIFT)) );
1048 OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
1049 OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
1050 OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
1051 OUT_RING( 0x3f800000 );
1052 OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
1053 OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
1054 OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
1055 OUT_RING( 0x3f800000 );
1056 OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
1057 OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
1058 OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
1059 OUT_RING( 0x3f800000 );
1060 ADVANCE_RING();
1061 }
1062 }
1063 else if ( (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) {
1064
1065 int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
1066
1067 rb3d_cntl = depth_clear->rb3d_cntl;
1068
1069 if ( flags & RADEON_DEPTH ) {
1070 rb3d_cntl |= RADEON_Z_ENABLE;
1071 } else {
1072 rb3d_cntl &= ~RADEON_Z_ENABLE;
1073 }
1074
1075 if ( flags & RADEON_STENCIL ) {
1076 rb3d_cntl |= RADEON_STENCIL_ENABLE;
1077 rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
1078 } else {
1079 rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
1080 rb3d_stencilrefmask = 0x00000000;
1081 }
1082
1083 if (flags & RADEON_USE_COMP_ZBUF) {
1084 tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
1085 RADEON_Z_DECOMPRESSION_ENABLE;
1086 }
1087 if (flags & RADEON_USE_HIERZ) {
1088 tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
1089 }
1090
1091 BEGIN_RING( 13 );
1092 RADEON_WAIT_UNTIL_2D_IDLE();
1093
1094 OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
1095 OUT_RING( 0x00000000 );
1096 OUT_RING( rb3d_cntl );
1097
1098 OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL );
1099 OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
1100 rb3d_stencilrefmask );
1101 OUT_RING_REG( RADEON_RB3D_PLANEMASK,
1102 0x00000000 );
1103 OUT_RING_REG( RADEON_SE_CNTL,
1104 depth_clear->se_cntl );
1105 ADVANCE_RING();
1106
1107 /* Make sure we restore the 3D state next time.
1108 */
1109 dev_priv->sarea_priv->ctx_owner = 0;
1110
1111 for ( i = 0 ; i < nbox ; i++ ) {
1112
1113 /* Funny that this should be required --
1114 * sets top-left?
1115 */
1116 radeon_emit_clip_rect( dev_priv,
1117 &sarea_priv->boxes[i] );
1118
1119 BEGIN_RING( 15 );
1120
1121 OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 13 ) );
1122 OUT_RING( RADEON_VTX_Z_PRESENT |
1123 RADEON_VTX_PKCOLOR_PRESENT);
1124 OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
1125 RADEON_PRIM_WALK_RING |
1126 RADEON_MAOS_ENABLE |
1127 RADEON_VTX_FMT_RADEON_MODE |
1128 (3 << RADEON_NUM_VERTICES_SHIFT)) );
1129
1130
1131 OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
1132 OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
1133 OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
1134 OUT_RING( 0x0 );
1135
1136 OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
1137 OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
1138 OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
1139 OUT_RING( 0x0 );
1140
1141 OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
1142 OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
1143 OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
1144 OUT_RING( 0x0 );
1145
1146 ADVANCE_RING();
1147 }
1148 }
1149
1150 /* Increment the clear counter. The client-side 3D driver must
1151 * wait on this value before performing the clear ioctl. We
1152 * need this because the card's so damned fast...
1153 */
1154 dev_priv->sarea_priv->last_clear++;
1155
1156 BEGIN_RING( 4 );
1157
1158 RADEON_CLEAR_AGE( dev_priv->sarea_priv->last_clear );
1159 RADEON_WAIT_UNTIL_IDLE();
1160
1161 ADVANCE_RING();
1162}
1163
1164static void radeon_cp_dispatch_swap( drm_device_t *dev )
1165{
1166 drm_radeon_private_t *dev_priv = dev->dev_private;
1167 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1168 int nbox = sarea_priv->nbox;
1169 drm_clip_rect_t *pbox = sarea_priv->boxes;
1170 int i;
1171 RING_LOCALS;
1172 DRM_DEBUG( "\n" );
1173
1174 /* Do some trivial performance monitoring...
1175 */
1176 if (dev_priv->do_boxes)
1177 radeon_cp_performance_boxes( dev_priv );
1178
1179
1180 /* Wait for the 3D stream to idle before dispatching the bitblt.
1181 * This will prevent data corruption between the two streams.
1182 */
1183 BEGIN_RING( 2 );
1184
1185 RADEON_WAIT_UNTIL_3D_IDLE();
1186
1187 ADVANCE_RING();
1188
1189 for ( i = 0 ; i < nbox ; i++ ) {
1190 int x = pbox[i].x1;
1191 int y = pbox[i].y1;
1192 int w = pbox[i].x2 - x;
1193 int h = pbox[i].y2 - y;
1194
1195 DRM_DEBUG( "dispatch swap %d,%d-%d,%d\n",
1196 x, y, w, h );
1197
1198 BEGIN_RING( 7 );
1199
1200 OUT_RING( CP_PACKET3( RADEON_CNTL_BITBLT_MULTI, 5 ) );
1201 OUT_RING( RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
1202 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
1203 RADEON_GMC_BRUSH_NONE |
1204 (dev_priv->color_fmt << 8) |
1205 RADEON_GMC_SRC_DATATYPE_COLOR |
1206 RADEON_ROP3_S |
1207 RADEON_DP_SRC_SOURCE_MEMORY |
1208 RADEON_GMC_CLR_CMP_CNTL_DIS |
1209 RADEON_GMC_WR_MSK_DIS );
1210
1211 /* Make this work even if front & back are flipped:
1212 */
1213 if (dev_priv->current_page == 0) {
1214 OUT_RING( dev_priv->back_pitch_offset );
1215 OUT_RING( dev_priv->front_pitch_offset );
1216 }
1217 else {
1218 OUT_RING( dev_priv->front_pitch_offset );
1219 OUT_RING( dev_priv->back_pitch_offset );
1220 }
1221
1222 OUT_RING( (x << 16) | y );
1223 OUT_RING( (x << 16) | y );
1224 OUT_RING( (w << 16) | h );
1225
1226 ADVANCE_RING();
1227 }
1228
1229 /* Increment the frame counter. The client-side 3D driver must
1230 * throttle the framerate by waiting for this value before
1231 * performing the swapbuffer ioctl.
1232 */
1233 dev_priv->sarea_priv->last_frame++;
1234
1235 BEGIN_RING( 4 );
1236
1237 RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
1238 RADEON_WAIT_UNTIL_2D_IDLE();
1239
1240 ADVANCE_RING();
1241}
1242
1243static void radeon_cp_dispatch_flip( drm_device_t *dev )
1244{
1245 drm_radeon_private_t *dev_priv = dev->dev_private;
1246 drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle;
1247 int offset = (dev_priv->current_page == 1)
1248 ? dev_priv->front_offset : dev_priv->back_offset;
1249 RING_LOCALS;
1250 DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
1251 __FUNCTION__,
1252 dev_priv->current_page,
1253 dev_priv->sarea_priv->pfCurrentPage);
1254
1255 /* Do some trivial performance monitoring...
1256 */
1257 if (dev_priv->do_boxes) {
1258 dev_priv->stats.boxes |= RADEON_BOX_FLIP;
1259 radeon_cp_performance_boxes( dev_priv );
1260 }
1261
1262 /* Update the frame offsets for both CRTCs
1263 */
1264 BEGIN_RING( 6 );
1265
1266 RADEON_WAIT_UNTIL_3D_IDLE();
1267 OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch
1268 + sarea->frame.x
1269 * ( dev_priv->color_fmt - 2 ) ) & ~7 )
1270 + offset );
1271 OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
1272 + offset );
1273
1274 ADVANCE_RING();
1275
1276 /* Increment the frame counter. The client-side 3D driver must
1277 * throttle the framerate by waiting for this value before
1278 * performing the swapbuffer ioctl.
1279 */
1280 dev_priv->sarea_priv->last_frame++;
1281 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
1282 1 - dev_priv->current_page;
1283
1284 BEGIN_RING( 2 );
1285
1286 RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
1287
1288 ADVANCE_RING();
1289}
1290
1291static int bad_prim_vertex_nr( int primitive, int nr )
1292{
1293 switch (primitive & RADEON_PRIM_TYPE_MASK) {
1294 case RADEON_PRIM_TYPE_NONE:
1295 case RADEON_PRIM_TYPE_POINT:
1296 return nr < 1;
1297 case RADEON_PRIM_TYPE_LINE:
1298 return (nr & 1) || nr == 0;
1299 case RADEON_PRIM_TYPE_LINE_STRIP:
1300 return nr < 2;
1301 case RADEON_PRIM_TYPE_TRI_LIST:
1302 case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
1303 case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
1304 case RADEON_PRIM_TYPE_RECT_LIST:
1305 return nr % 3 || nr == 0;
1306 case RADEON_PRIM_TYPE_TRI_FAN:
1307 case RADEON_PRIM_TYPE_TRI_STRIP:
1308 return nr < 3;
1309 default:
1310 return 1;
1311 }
1312}
1313
1314
1315
1316typedef struct {
1317 unsigned int start;
1318 unsigned int finish;
1319 unsigned int prim;
1320 unsigned int numverts;
1321 unsigned int offset;
1322 unsigned int vc_format;
1323} drm_radeon_tcl_prim_t;
1324
1325static void radeon_cp_dispatch_vertex( drm_device_t *dev,
1326 drm_buf_t *buf,
1327 drm_radeon_tcl_prim_t *prim )
1328
1329{
1330 drm_radeon_private_t *dev_priv = dev->dev_private;
1331 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1332 int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
1333 int numverts = (int)prim->numverts;
1334 int nbox = sarea_priv->nbox;
1335 int i = 0;
1336 RING_LOCALS;
1337
1338 DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
1339 prim->prim,
1340 prim->vc_format,
1341 prim->start,
1342 prim->finish,
1343 prim->numverts);
1344
1345 if (bad_prim_vertex_nr( prim->prim, prim->numverts )) {
1346 DRM_ERROR( "bad prim %x numverts %d\n",
1347 prim->prim, prim->numverts );
1348 return;
1349 }
1350
1351 do {
1352 /* Emit the next cliprect */
1353 if ( i < nbox ) {
1354 radeon_emit_clip_rect( dev_priv,
1355 &sarea_priv->boxes[i] );
1356 }
1357
1358 /* Emit the vertex buffer rendering commands */
1359 BEGIN_RING( 5 );
1360
1361 OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
1362 OUT_RING( offset );
1363 OUT_RING( numverts );
1364 OUT_RING( prim->vc_format );
1365 OUT_RING( prim->prim | RADEON_PRIM_WALK_LIST |
1366 RADEON_COLOR_ORDER_RGBA |
1367 RADEON_VTX_FMT_RADEON_MODE |
1368 (numverts << RADEON_NUM_VERTICES_SHIFT) );
1369
1370 ADVANCE_RING();
1371
1372 i++;
1373 } while ( i < nbox );
1374}
1375
1376
1377
1378static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf )
1379{
1380 drm_radeon_private_t *dev_priv = dev->dev_private;
1381 drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
1382 RING_LOCALS;
1383
1384 buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
1385
1386 /* Emit the vertex buffer age */
1387 BEGIN_RING( 2 );
1388 RADEON_DISPATCH_AGE( buf_priv->age );
1389 ADVANCE_RING();
1390
1391 buf->pending = 1;
1392 buf->used = 0;
1393}
1394
1395static void radeon_cp_dispatch_indirect( drm_device_t *dev,
1396 drm_buf_t *buf,
1397 int start, int end )
1398{
1399 drm_radeon_private_t *dev_priv = dev->dev_private;
1400 RING_LOCALS;
1401 DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
1402 buf->idx, start, end );
1403
1404 if ( start != end ) {
1405 int offset = (dev_priv->gart_buffers_offset
1406 + buf->offset + start);
1407 int dwords = (end - start + 3) / sizeof(u32);
1408
1409 /* Indirect buffer data must be an even number of
1410 * dwords, so if we've been given an odd number we must
1411 * pad the data with a Type-2 CP packet.
1412 */
1413 if ( dwords & 1 ) {
1414 u32 *data = (u32 *)
1415 ((char *)dev->agp_buffer_map->handle
1416 + buf->offset + start);
1417 data[dwords++] = RADEON_CP_PACKET2;
1418 }
1419
1420 /* Fire off the indirect buffer */
1421 BEGIN_RING( 3 );
1422
1423 OUT_RING( CP_PACKET0( RADEON_CP_IB_BASE, 1 ) );
1424 OUT_RING( offset );
1425 OUT_RING( dwords );
1426
1427 ADVANCE_RING();
1428 }
1429}
1430
1431
1432static void radeon_cp_dispatch_indices( drm_device_t *dev,
1433 drm_buf_t *elt_buf,
1434 drm_radeon_tcl_prim_t *prim )
1435{
1436 drm_radeon_private_t *dev_priv = dev->dev_private;
1437 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1438 int offset = dev_priv->gart_buffers_offset + prim->offset;
1439 u32 *data;
1440 int dwords;
1441 int i = 0;
1442 int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
1443 int count = (prim->finish - start) / sizeof(u16);
1444 int nbox = sarea_priv->nbox;
1445
1446 DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
1447 prim->prim,
1448 prim->vc_format,
1449 prim->start,
1450 prim->finish,
1451 prim->offset,
1452 prim->numverts);
1453
1454 if (bad_prim_vertex_nr( prim->prim, count )) {
1455 DRM_ERROR( "bad prim %x count %d\n",
1456 prim->prim, count );
1457 return;
1458 }
1459
1460
1461 if ( start >= prim->finish ||
1462 (prim->start & 0x7) ) {
1463 DRM_ERROR( "buffer prim %d\n", prim->prim );
1464 return;
1465 }
1466
1467 dwords = (prim->finish - prim->start + 3) / sizeof(u32);
1468
1469 data = (u32 *)((char *)dev->agp_buffer_map->handle +
1470 elt_buf->offset + prim->start);
1471
1472 data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
1473 data[1] = offset;
1474 data[2] = prim->numverts;
1475 data[3] = prim->vc_format;
1476 data[4] = (prim->prim |
1477 RADEON_PRIM_WALK_IND |
1478 RADEON_COLOR_ORDER_RGBA |
1479 RADEON_VTX_FMT_RADEON_MODE |
1480 (count << RADEON_NUM_VERTICES_SHIFT) );
1481
1482 do {
1483 if ( i < nbox )
1484 radeon_emit_clip_rect( dev_priv,
1485 &sarea_priv->boxes[i] );
1486
1487 radeon_cp_dispatch_indirect( dev, elt_buf,
1488 prim->start,
1489 prim->finish );
1490
1491 i++;
1492 } while ( i < nbox );
1493
1494}
1495
1496#define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
1497
1498static int radeon_cp_dispatch_texture( DRMFILE filp,
1499 drm_device_t *dev,
1500 drm_radeon_texture_t *tex,
1501 drm_radeon_tex_image_t *image )
1502{
1503 drm_radeon_private_t *dev_priv = dev->dev_private;
1504 drm_file_t *filp_priv;
1505 drm_buf_t *buf;
1506 u32 format;
1507 u32 *buffer;
1508 const u8 __user *data;
1509 int size, dwords, tex_width, blit_width;
1510 u32 height;
1511 int i;
1512 u32 texpitch, microtile;
1513 RING_LOCALS;
1514
1515 DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
1516
1517 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &tex->offset ) ) {
1518 DRM_ERROR( "Invalid destination offset\n" );
1519 return DRM_ERR( EINVAL );
1520 }
1521
1522 dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
1523
1524 /* Flush the pixel cache. This ensures no pixel data gets mixed
1525 * up with the texture data from the host data blit, otherwise
1526 * part of the texture image may be corrupted.
1527 */
1528 BEGIN_RING( 4 );
1529 RADEON_FLUSH_CACHE();
1530 RADEON_WAIT_UNTIL_IDLE();
1531 ADVANCE_RING();
1532
1533#ifdef __BIG_ENDIAN
1534 /* The Mesa texture functions provide the data in little endian as the
1535 * chip wants it, but we need to compensate for the fact that the CP
1536 * ring gets byte-swapped
1537 */
1538 BEGIN_RING( 2 );
1539 OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT );
1540 ADVANCE_RING();
1541#endif
1542
1543
1544 /* The compiler won't optimize away a division by a variable,
1545 * even if the only legal values are powers of two. Thus, we'll
1546 * use a shift instead.
1547 */
1548 switch ( tex->format ) {
1549 case RADEON_TXFORMAT_ARGB8888:
1550 case RADEON_TXFORMAT_RGBA8888:
1551 format = RADEON_COLOR_FORMAT_ARGB8888;
1552 tex_width = tex->width * 4;
1553 blit_width = image->width * 4;
1554 break;
1555 case RADEON_TXFORMAT_AI88:
1556 case RADEON_TXFORMAT_ARGB1555:
1557 case RADEON_TXFORMAT_RGB565:
1558 case RADEON_TXFORMAT_ARGB4444:
1559 case RADEON_TXFORMAT_VYUY422:
1560 case RADEON_TXFORMAT_YVYU422:
1561 format = RADEON_COLOR_FORMAT_RGB565;
1562 tex_width = tex->width * 2;
1563 blit_width = image->width * 2;
1564 break;
1565 case RADEON_TXFORMAT_I8:
1566 case RADEON_TXFORMAT_RGB332:
1567 format = RADEON_COLOR_FORMAT_CI8;
1568 tex_width = tex->width * 1;
1569 blit_width = image->width * 1;
1570 break;
1571 default:
1572 DRM_ERROR( "invalid texture format %d\n", tex->format );
1573 return DRM_ERR(EINVAL);
1574 }
1575 texpitch = tex->pitch;
1576 if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
1577 microtile = 1;
1578 if (tex_width < 64) {
1579 texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
1580 /* we got tiled coordinates, untile them */
1581 image->x *= 2;
1582 }
1583 }
1584 else microtile = 0;
1585
1586 DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width );
1587
1588 do {
1589 DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
1590 tex->offset >> 10, tex->pitch, tex->format,
1591 image->x, image->y, image->width, image->height );
1592
1593 /* Make a copy of some parameters in case we have to
1594 * update them for a multi-pass texture blit.
1595 */
1596 height = image->height;
1597 data = (const u8 __user *)image->data;
1598
1599 size = height * blit_width;
1600
1601 if ( size > RADEON_MAX_TEXTURE_SIZE ) {
1602 height = RADEON_MAX_TEXTURE_SIZE / blit_width;
1603 size = height * blit_width;
1604 } else if ( size < 4 && size > 0 ) {
1605 size = 4;
1606 } else if ( size == 0 ) {
1607 return 0;
1608 }
1609
1610 buf = radeon_freelist_get( dev );
1611 if ( 0 && !buf ) {
1612 radeon_do_cp_idle( dev_priv );
1613 buf = radeon_freelist_get( dev );
1614 }
1615 if ( !buf ) {
1616 DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
1617 if (DRM_COPY_TO_USER( tex->image, image, sizeof(*image) ))
1618 return DRM_ERR(EFAULT);
1619 return DRM_ERR(EAGAIN);
1620 }
1621
1622
1623 /* Dispatch the indirect buffer.
1624 */
1625 buffer = (u32*)((char*)dev->agp_buffer_map->handle + buf->offset);
1626 dwords = size / 4;
1627 buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
1628 buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
1629 RADEON_GMC_BRUSH_NONE |
1630 (format << 8) |
1631 RADEON_GMC_SRC_DATATYPE_COLOR |
1632 RADEON_ROP3_S |
1633 RADEON_DP_SRC_SOURCE_HOST_DATA |
1634 RADEON_GMC_CLR_CMP_CNTL_DIS |
1635 RADEON_GMC_WR_MSK_DIS);
1636
1637 buffer[2] = (texpitch << 22) | (tex->offset >> 10);
1638 buffer[3] = 0xffffffff;
1639 buffer[4] = 0xffffffff;
1640 buffer[5] = (image->y << 16) | image->x;
1641 buffer[6] = (height << 16) | image->width;
1642 buffer[7] = dwords;
1643 buffer += 8;
1644
1645
1646
1647 if (microtile) {
1648 /* texture micro tiling in use, minimum texture width is thus 16 bytes.
1649 however, we cannot use blitter directly for texture width < 64 bytes,
1650 since minimum tex pitch is 64 bytes and we need this to match
1651 the texture width, otherwise the blitter will tile it wrong.
1652 Thus, tiling manually in this case. Additionally, need to special
1653 case tex height = 1, since our actual image will have height 2
1654 and we need to ensure we don't read beyond the texture size
1655 from user space. */
1656 if (tex->height == 1) {
1657 if (tex_width >= 64 || tex_width <= 16) {
1658 if (DRM_COPY_FROM_USER(buffer, data,
1659 tex_width * sizeof(u32))) {
1660 DRM_ERROR("EFAULT on pad, %d bytes\n",
1661 tex_width);
1662 return DRM_ERR(EFAULT);
1663 }
1664 } else if (tex_width == 32) {
1665 if (DRM_COPY_FROM_USER(buffer, data, 16)) {
1666 DRM_ERROR("EFAULT on pad, %d bytes\n",
1667 tex_width);
1668 return DRM_ERR(EFAULT);
1669 }
1670 if (DRM_COPY_FROM_USER(buffer + 8, data + 16, 16)) {
1671 DRM_ERROR("EFAULT on pad, %d bytes\n",
1672 tex_width);
1673 return DRM_ERR(EFAULT);
1674 }
1675 }
1676 } else if (tex_width >= 64 || tex_width == 16) {
1677 if (DRM_COPY_FROM_USER(buffer, data,
1678 dwords * sizeof(u32))) {
1679 DRM_ERROR("EFAULT on data, %d dwords\n",
1680 dwords);
1681 return DRM_ERR(EFAULT);
1682 }
1683 } else if (tex_width < 16) {
1684 for (i = 0; i < tex->height; i++) {
1685 if (DRM_COPY_FROM_USER(buffer, data, tex_width)) {
1686 DRM_ERROR("EFAULT on pad, %d bytes\n",
1687 tex_width);
1688 return DRM_ERR(EFAULT);
1689 }
1690 buffer += 4;
1691 data += tex_width;
1692 }
1693 } else if (tex_width == 32) {
1694 /* TODO: make sure this works when not fitting in one buffer
1695 (i.e. 32bytes x 2048...) */
1696 for (i = 0; i < tex->height; i += 2) {
1697 if (DRM_COPY_FROM_USER(buffer, data, 16)) {
1698 DRM_ERROR("EFAULT on pad, %d bytes\n",
1699 tex_width);
1700 return DRM_ERR(EFAULT);
1701 }
1702 data += 16;
1703 if (DRM_COPY_FROM_USER(buffer + 8, data, 16)) {
1704 DRM_ERROR("EFAULT on pad, %d bytes\n",
1705 tex_width);
1706 return DRM_ERR(EFAULT);
1707 }
1708 data += 16;
1709 if (DRM_COPY_FROM_USER(buffer + 4, data, 16)) {
1710 DRM_ERROR("EFAULT on pad, %d bytes\n",
1711 tex_width);
1712 return DRM_ERR(EFAULT);
1713 }
1714 data += 16;
1715 if (DRM_COPY_FROM_USER(buffer + 12, data, 16)) {
1716 DRM_ERROR("EFAULT on pad, %d bytes\n",
1717 tex_width);
1718 return DRM_ERR(EFAULT);
1719 }
1720 data += 16;
1721 buffer += 16;
1722 }
1723 }
1724 }
1725 else {
1726 if (tex_width >= 32) {
1727 /* Texture image width is larger than the minimum, so we
1728 * can upload it directly.
1729 */
1730 if (DRM_COPY_FROM_USER(buffer, data,
1731 dwords * sizeof(u32))) {
1732 DRM_ERROR("EFAULT on data, %d dwords\n",
1733 dwords);
1734 return DRM_ERR(EFAULT);
1735 }
1736 } else {
1737 /* Texture image width is less than the minimum, so we
1738 * need to pad out each image scanline to the minimum
1739 * width.
1740 */
1741 for (i = 0 ; i < tex->height ; i++) {
1742 if (DRM_COPY_FROM_USER(buffer, data, tex_width )) {
1743 DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width);
1744 return DRM_ERR(EFAULT);
1745 }
1746 buffer += 8;
1747 data += tex_width;
1748 }
1749 }
1750 }
1751
1752 buf->filp = filp;
1753 buf->used = (dwords + 8) * sizeof(u32);
1754 radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
1755 radeon_cp_discard_buffer( dev, buf );
1756
1757 /* Update the input parameters for next time */
1758 image->y += height;
1759 image->height -= height;
1760 image->data = (const u8 __user *)image->data + size;
1761 } while (image->height > 0);
1762
1763 /* Flush the pixel cache after the blit completes. This ensures
1764 * the texture data is written out to memory before rendering
1765 * continues.
1766 */
1767 BEGIN_RING( 4 );
1768 RADEON_FLUSH_CACHE();
1769 RADEON_WAIT_UNTIL_2D_IDLE();
1770 ADVANCE_RING();
1771 return 0;
1772}
1773
1774
1775static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
1776{
1777 drm_radeon_private_t *dev_priv = dev->dev_private;
1778 int i;
1779 RING_LOCALS;
1780 DRM_DEBUG( "\n" );
1781
1782 BEGIN_RING( 35 );
1783
1784 OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
1785 OUT_RING( 0x00000000 );
1786
1787 OUT_RING( CP_PACKET0_TABLE( RADEON_RE_STIPPLE_DATA, 31 ) );
1788 for ( i = 0 ; i < 32 ; i++ ) {
1789 OUT_RING( stipple[i] );
1790 }
1791
1792 ADVANCE_RING();
1793}
1794
1795static void radeon_apply_surface_regs(int surf_index, drm_radeon_private_t *dev_priv)
1796{
1797 if (!dev_priv->mmio)
1798 return;
1799
1800 radeon_do_cp_idle(dev_priv);
1801
1802 RADEON_WRITE(RADEON_SURFACE0_INFO + 16*surf_index,
1803 dev_priv->surfaces[surf_index].flags);
1804 RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16*surf_index,
1805 dev_priv->surfaces[surf_index].lower);
1806 RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16*surf_index,
1807 dev_priv->surfaces[surf_index].upper);
1808}
1809
1810
1811/* Allocates a virtual surface
1812 * doesn't always allocate a real surface, will stretch an existing
1813 * surface when possible.
1814 *
1815 * Note that refcount can be at most 2, since during a free refcount=3
1816 * might mean we have to allocate a new surface which might not always
1817 * be available.
1818 * For example : we allocate three contigous surfaces ABC. If B is
1819 * freed, we suddenly need two surfaces to store A and C, which might
1820 * not always be available.
1821 */
1822static int alloc_surface(drm_radeon_surface_alloc_t* new, drm_radeon_private_t *dev_priv, DRMFILE filp)
1823{
1824 struct radeon_virt_surface *s;
1825 int i;
1826 int virt_surface_index;
1827 uint32_t new_upper, new_lower;
1828
1829 new_lower = new->address;
1830 new_upper = new_lower + new->size - 1;
1831
1832 /* sanity check */
1833 if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) ||
1834 ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) != RADEON_SURF_ADDRESS_FIXED_MASK) ||
1835 ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
1836 return -1;
1837
1838 /* make sure there is no overlap with existing surfaces */
1839 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1840 if ((dev_priv->surfaces[i].refcount != 0) &&
1841 (( (new_lower >= dev_priv->surfaces[i].lower) &&
1842 (new_lower < dev_priv->surfaces[i].upper) ) ||
1843 ( (new_lower < dev_priv->surfaces[i].lower) &&
1844 (new_upper > dev_priv->surfaces[i].lower) )) ){
1845 return -1;}
1846 }
1847
1848 /* find a virtual surface */
1849 for (i = 0; i < 2*RADEON_MAX_SURFACES; i++)
1850 if (dev_priv->virt_surfaces[i].filp == 0)
1851 break;
1852 if (i == 2*RADEON_MAX_SURFACES) {
1853 return -1;}
1854 virt_surface_index = i;
1855
1856 /* try to reuse an existing surface */
1857 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1858 /* extend before */
1859 if ((dev_priv->surfaces[i].refcount == 1) &&
1860 (new->flags == dev_priv->surfaces[i].flags) &&
1861 (new_upper + 1 == dev_priv->surfaces[i].lower)) {
1862 s = &(dev_priv->virt_surfaces[virt_surface_index]);
1863 s->surface_index = i;
1864 s->lower = new_lower;
1865 s->upper = new_upper;
1866 s->flags = new->flags;
1867 s->filp = filp;
1868 dev_priv->surfaces[i].refcount++;
1869 dev_priv->surfaces[i].lower = s->lower;
1870 radeon_apply_surface_regs(s->surface_index, dev_priv);
1871 return virt_surface_index;
1872 }
1873
1874 /* extend after */
1875 if ((dev_priv->surfaces[i].refcount == 1) &&
1876 (new->flags == dev_priv->surfaces[i].flags) &&
1877 (new_lower == dev_priv->surfaces[i].upper + 1)) {
1878 s = &(dev_priv->virt_surfaces[virt_surface_index]);
1879 s->surface_index = i;
1880 s->lower = new_lower;
1881 s->upper = new_upper;
1882 s->flags = new->flags;
1883 s->filp = filp;
1884 dev_priv->surfaces[i].refcount++;
1885 dev_priv->surfaces[i].upper = s->upper;
1886 radeon_apply_surface_regs(s->surface_index, dev_priv);
1887 return virt_surface_index;
1888 }
1889 }
1890
1891 /* okay, we need a new one */
1892 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1893 if (dev_priv->surfaces[i].refcount == 0) {
1894 s = &(dev_priv->virt_surfaces[virt_surface_index]);
1895 s->surface_index = i;
1896 s->lower = new_lower;
1897 s->upper = new_upper;
1898 s->flags = new->flags;
1899 s->filp = filp;
1900 dev_priv->surfaces[i].refcount = 1;
1901 dev_priv->surfaces[i].lower = s->lower;
1902 dev_priv->surfaces[i].upper = s->upper;
1903 dev_priv->surfaces[i].flags = s->flags;
1904 radeon_apply_surface_regs(s->surface_index, dev_priv);
1905 return virt_surface_index;
1906 }
1907 }
1908
1909 /* we didn't find anything */
1910 return -1;
1911}
1912
1913static int free_surface(DRMFILE filp, drm_radeon_private_t *dev_priv, int lower)
1914{
1915 struct radeon_virt_surface *s;
1916 int i;
1917 /* find the virtual surface */
1918 for(i = 0; i < 2*RADEON_MAX_SURFACES; i++) {
1919 s = &(dev_priv->virt_surfaces[i]);
1920 if (s->filp) {
1921 if ((lower == s->lower) && (filp == s->filp)) {
1922 if (dev_priv->surfaces[s->surface_index].lower == s->lower)
1923 dev_priv->surfaces[s->surface_index].lower = s->upper;
1924
1925 if (dev_priv->surfaces[s->surface_index].upper == s->upper)
1926 dev_priv->surfaces[s->surface_index].upper = s->lower;
1927
1928 dev_priv->surfaces[s->surface_index].refcount--;
1929 if (dev_priv->surfaces[s->surface_index].refcount == 0)
1930 dev_priv->surfaces[s->surface_index].flags = 0;
1931 s->filp = NULL;
1932 radeon_apply_surface_regs(s->surface_index, dev_priv);
1933 return 0;
1934 }
1935 }
1936 }
1937 return 1;
1938}
1939
1940static void radeon_surfaces_release(DRMFILE filp, drm_radeon_private_t *dev_priv)
1941{
1942 int i;
1943 for( i = 0; i < 2*RADEON_MAX_SURFACES; i++)
1944 {
1945 if (dev_priv->virt_surfaces[i].filp == filp)
1946 free_surface(filp, dev_priv, dev_priv->virt_surfaces[i].lower);
1947 }
1948}
1949
1950/* ================================================================
1951 * IOCTL functions
1952 */
1953static int radeon_surface_alloc(DRM_IOCTL_ARGS)
1954{
1955 DRM_DEVICE;
1956 drm_radeon_private_t *dev_priv = dev->dev_private;
1957 drm_radeon_surface_alloc_t alloc;
1958
1959 if (!dev_priv) {
1960 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1961 return DRM_ERR(EINVAL);
1962 }
1963
1964 DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_surface_alloc_t __user *)data,
1965 sizeof(alloc));
1966
1967 if (alloc_surface(&alloc, dev_priv, filp) == -1)
1968 return DRM_ERR(EINVAL);
1969 else
1970 return 0;
1971}
1972
1973static int radeon_surface_free(DRM_IOCTL_ARGS)
1974{
1975 DRM_DEVICE;
1976 drm_radeon_private_t *dev_priv = dev->dev_private;
1977 drm_radeon_surface_free_t memfree;
1978
1979 if (!dev_priv) {
1980 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1981 return DRM_ERR(EINVAL);
1982 }
1983
1984 DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *)data,
1985 sizeof(memfree) );
1986
1987 if (free_surface(filp, dev_priv, memfree.address))
1988 return DRM_ERR(EINVAL);
1989 else
1990 return 0;
1991}
1992
1993static int radeon_cp_clear( DRM_IOCTL_ARGS )
1994{
1995 DRM_DEVICE;
1996 drm_radeon_private_t *dev_priv = dev->dev_private;
1997 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1998 drm_radeon_clear_t clear;
1999 drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
2000 DRM_DEBUG( "\n" );
2001
2002 LOCK_TEST_WITH_RETURN( dev, filp );
2003
2004 DRM_COPY_FROM_USER_IOCTL( clear, (drm_radeon_clear_t __user *)data,
2005 sizeof(clear) );
2006
2007 RING_SPACE_TEST_WITH_RETURN( dev_priv );
2008
2009 if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
2010 sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
2011
2012 if ( DRM_COPY_FROM_USER( &depth_boxes, clear.depth_boxes,
2013 sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
2014 return DRM_ERR(EFAULT);
2015
2016 radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
2017
2018 COMMIT_RING();
2019 return 0;
2020}
2021
2022
2023/* Not sure why this isn't set all the time:
2024 */
2025static int radeon_do_init_pageflip( drm_device_t *dev )
2026{
2027 drm_radeon_private_t *dev_priv = dev->dev_private;
2028 RING_LOCALS;
2029
2030 DRM_DEBUG( "\n" );
2031
2032 BEGIN_RING( 6 );
2033 RADEON_WAIT_UNTIL_3D_IDLE();
2034 OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) );
2035 OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
2036 OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) );
2037 OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
2038 ADVANCE_RING();
2039
2040 dev_priv->page_flipping = 1;
2041 dev_priv->current_page = 0;
2042 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
2043
2044 return 0;
2045}
2046
2047/* Called whenever a client dies, from drm_release.
2048 * NOTE: Lock isn't necessarily held when this is called!
2049 */
2050static int radeon_do_cleanup_pageflip( drm_device_t *dev )
2051{
2052 drm_radeon_private_t *dev_priv = dev->dev_private;
2053 DRM_DEBUG( "\n" );
2054
2055 if (dev_priv->current_page != 0)
2056 radeon_cp_dispatch_flip( dev );
2057
2058 dev_priv->page_flipping = 0;
2059 return 0;
2060}
2061
2062/* Swapping and flipping are different operations, need different ioctls.
2063 * They can & should be intermixed to support multiple 3d windows.
2064 */
2065static int radeon_cp_flip( DRM_IOCTL_ARGS )
2066{
2067 DRM_DEVICE;
2068 drm_radeon_private_t *dev_priv = dev->dev_private;
2069 DRM_DEBUG( "\n" );
2070
2071 LOCK_TEST_WITH_RETURN( dev, filp );
2072
2073 RING_SPACE_TEST_WITH_RETURN( dev_priv );
2074
2075 if (!dev_priv->page_flipping)
2076 radeon_do_init_pageflip( dev );
2077
2078 radeon_cp_dispatch_flip( dev );
2079
2080 COMMIT_RING();
2081 return 0;
2082}
2083
2084static int radeon_cp_swap( DRM_IOCTL_ARGS )
2085{
2086 DRM_DEVICE;
2087 drm_radeon_private_t *dev_priv = dev->dev_private;
2088 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2089 DRM_DEBUG( "\n" );
2090
2091 LOCK_TEST_WITH_RETURN( dev, filp );
2092
2093 RING_SPACE_TEST_WITH_RETURN( dev_priv );
2094
2095 if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
2096 sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
2097
2098 radeon_cp_dispatch_swap( dev );
2099 dev_priv->sarea_priv->ctx_owner = 0;
2100
2101 COMMIT_RING();
2102 return 0;
2103}
2104
2105static int radeon_cp_vertex( DRM_IOCTL_ARGS )
2106{
2107 DRM_DEVICE;
2108 drm_radeon_private_t *dev_priv = dev->dev_private;
2109 drm_file_t *filp_priv;
2110 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2111 drm_device_dma_t *dma = dev->dma;
2112 drm_buf_t *buf;
2113 drm_radeon_vertex_t vertex;
2114 drm_radeon_tcl_prim_t prim;
2115
2116 LOCK_TEST_WITH_RETURN( dev, filp );
2117
2118 DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
2119
2120 DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t __user *)data,
2121 sizeof(vertex) );
2122
2123 DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
2124 DRM_CURRENTPID,
2125 vertex.idx, vertex.count, vertex.discard );
2126
2127 if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
2128 DRM_ERROR( "buffer index %d (of %d max)\n",
2129 vertex.idx, dma->buf_count - 1 );
2130 return DRM_ERR(EINVAL);
2131 }
2132 if ( vertex.prim < 0 ||
2133 vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
2134 DRM_ERROR( "buffer prim %d\n", vertex.prim );
2135 return DRM_ERR(EINVAL);
2136 }
2137
2138 RING_SPACE_TEST_WITH_RETURN( dev_priv );
2139 VB_AGE_TEST_WITH_RETURN( dev_priv );
2140
2141 buf = dma->buflist[vertex.idx];
2142
2143 if ( buf->filp != filp ) {
2144 DRM_ERROR( "process %d using buffer owned by %p\n",
2145 DRM_CURRENTPID, buf->filp );
2146 return DRM_ERR(EINVAL);
2147 }
2148 if ( buf->pending ) {
2149 DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
2150 return DRM_ERR(EINVAL);
2151 }
2152
2153 /* Build up a prim_t record:
2154 */
2155 if (vertex.count) {
2156 buf->used = vertex.count; /* not used? */
2157
2158 if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
2159 if ( radeon_emit_state( dev_priv, filp_priv,
2160 &sarea_priv->context_state,
2161 sarea_priv->tex_state,
2162 sarea_priv->dirty ) ) {
2163 DRM_ERROR( "radeon_emit_state failed\n" );
2164 return DRM_ERR( EINVAL );
2165 }
2166
2167 sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
2168 RADEON_UPLOAD_TEX1IMAGES |
2169 RADEON_UPLOAD_TEX2IMAGES |
2170 RADEON_REQUIRE_QUIESCENCE);
2171 }
2172
2173 prim.start = 0;
2174 prim.finish = vertex.count; /* unused */
2175 prim.prim = vertex.prim;
2176 prim.numverts = vertex.count;
2177 prim.vc_format = dev_priv->sarea_priv->vc_format;
2178
2179 radeon_cp_dispatch_vertex( dev, buf, &prim );
2180 }
2181
2182 if (vertex.discard) {
2183 radeon_cp_discard_buffer( dev, buf );
2184 }
2185
2186 COMMIT_RING();
2187 return 0;
2188}
2189
2190static int radeon_cp_indices( DRM_IOCTL_ARGS )
2191{
2192 DRM_DEVICE;
2193 drm_radeon_private_t *dev_priv = dev->dev_private;
2194 drm_file_t *filp_priv;
2195 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2196 drm_device_dma_t *dma = dev->dma;
2197 drm_buf_t *buf;
2198 drm_radeon_indices_t elts;
2199 drm_radeon_tcl_prim_t prim;
2200 int count;
2201
2202 LOCK_TEST_WITH_RETURN( dev, filp );
2203
2204 if ( !dev_priv ) {
2205 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2206 return DRM_ERR(EINVAL);
2207 }
2208
2209 DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
2210
2211 DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t __user *)data,
2212 sizeof(elts) );
2213
2214 DRM_DEBUG( "pid=%d index=%d start=%d end=%d discard=%d\n",
2215 DRM_CURRENTPID,
2216 elts.idx, elts.start, elts.end, elts.discard );
2217
2218 if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
2219 DRM_ERROR( "buffer index %d (of %d max)\n",
2220 elts.idx, dma->buf_count - 1 );
2221 return DRM_ERR(EINVAL);
2222 }
2223 if ( elts.prim < 0 ||
2224 elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
2225 DRM_ERROR( "buffer prim %d\n", elts.prim );
2226 return DRM_ERR(EINVAL);
2227 }
2228
2229 RING_SPACE_TEST_WITH_RETURN( dev_priv );
2230 VB_AGE_TEST_WITH_RETURN( dev_priv );
2231
2232 buf = dma->buflist[elts.idx];
2233
2234 if ( buf->filp != filp ) {
2235 DRM_ERROR( "process %d using buffer owned by %p\n",
2236 DRM_CURRENTPID, buf->filp );
2237 return DRM_ERR(EINVAL);
2238 }
2239 if ( buf->pending ) {
2240 DRM_ERROR( "sending pending buffer %d\n", elts.idx );
2241 return DRM_ERR(EINVAL);
2242 }
2243
2244 count = (elts.end - elts.start) / sizeof(u16);
2245 elts.start -= RADEON_INDEX_PRIM_OFFSET;
2246
2247 if ( elts.start & 0x7 ) {
2248 DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
2249 return DRM_ERR(EINVAL);
2250 }
2251 if ( elts.start < buf->used ) {
2252 DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
2253 return DRM_ERR(EINVAL);
2254 }
2255
2256 buf->used = elts.end;
2257
2258 if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
2259 if ( radeon_emit_state( dev_priv, filp_priv,
2260 &sarea_priv->context_state,
2261 sarea_priv->tex_state,
2262 sarea_priv->dirty ) ) {
2263 DRM_ERROR( "radeon_emit_state failed\n" );
2264 return DRM_ERR( EINVAL );
2265 }
2266
2267 sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
2268 RADEON_UPLOAD_TEX1IMAGES |
2269 RADEON_UPLOAD_TEX2IMAGES |
2270 RADEON_REQUIRE_QUIESCENCE);
2271 }
2272
2273
2274 /* Build up a prim_t record:
2275 */
2276 prim.start = elts.start;
2277 prim.finish = elts.end;
2278 prim.prim = elts.prim;
2279 prim.offset = 0; /* offset from start of dma buffers */
2280 prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
2281 prim.vc_format = dev_priv->sarea_priv->vc_format;
2282
2283 radeon_cp_dispatch_indices( dev, buf, &prim );
2284 if (elts.discard) {
2285 radeon_cp_discard_buffer( dev, buf );
2286 }
2287
2288 COMMIT_RING();
2289 return 0;
2290}
2291
2292static int radeon_cp_texture( DRM_IOCTL_ARGS )
2293{
2294 DRM_DEVICE;
2295 drm_radeon_private_t *dev_priv = dev->dev_private;
2296 drm_radeon_texture_t tex;
2297 drm_radeon_tex_image_t image;
2298 int ret;
2299
2300 LOCK_TEST_WITH_RETURN( dev, filp );
2301
2302 DRM_COPY_FROM_USER_IOCTL( tex, (drm_radeon_texture_t __user *)data, sizeof(tex) );
2303
2304 if ( tex.image == NULL ) {
2305 DRM_ERROR( "null texture image!\n" );
2306 return DRM_ERR(EINVAL);
2307 }
2308
2309 if ( DRM_COPY_FROM_USER( &image,
2310 (drm_radeon_tex_image_t __user *)tex.image,
2311 sizeof(image) ) )
2312 return DRM_ERR(EFAULT);
2313
2314 RING_SPACE_TEST_WITH_RETURN( dev_priv );
2315 VB_AGE_TEST_WITH_RETURN( dev_priv );
2316
2317 ret = radeon_cp_dispatch_texture( filp, dev, &tex, &image );
2318
2319 COMMIT_RING();
2320 return ret;
2321}
2322
2323static int radeon_cp_stipple( DRM_IOCTL_ARGS )
2324{
2325 DRM_DEVICE;
2326 drm_radeon_private_t *dev_priv = dev->dev_private;
2327 drm_radeon_stipple_t stipple;
2328 u32 mask[32];
2329
2330 LOCK_TEST_WITH_RETURN( dev, filp );
2331
2332 DRM_COPY_FROM_USER_IOCTL( stipple, (drm_radeon_stipple_t __user *)data,
2333 sizeof(stipple) );
2334
2335 if ( DRM_COPY_FROM_USER( &mask, stipple.mask, 32 * sizeof(u32) ) )
2336 return DRM_ERR(EFAULT);
2337
2338 RING_SPACE_TEST_WITH_RETURN( dev_priv );
2339
2340 radeon_cp_dispatch_stipple( dev, mask );
2341
2342 COMMIT_RING();
2343 return 0;
2344}
2345
2346static int radeon_cp_indirect( DRM_IOCTL_ARGS )
2347{
2348 DRM_DEVICE;
2349 drm_radeon_private_t *dev_priv = dev->dev_private;
2350 drm_device_dma_t *dma = dev->dma;
2351 drm_buf_t *buf;
2352 drm_radeon_indirect_t indirect;
2353 RING_LOCALS;
2354
2355 LOCK_TEST_WITH_RETURN( dev, filp );
2356
2357 if ( !dev_priv ) {
2358 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2359 return DRM_ERR(EINVAL);
2360 }
2361
2362 DRM_COPY_FROM_USER_IOCTL( indirect, (drm_radeon_indirect_t __user *)data,
2363 sizeof(indirect) );
2364
2365 DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
2366 indirect.idx, indirect.start,
2367 indirect.end, indirect.discard );
2368
2369 if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
2370 DRM_ERROR( "buffer index %d (of %d max)\n",
2371 indirect.idx, dma->buf_count - 1 );
2372 return DRM_ERR(EINVAL);
2373 }
2374
2375 buf = dma->buflist[indirect.idx];
2376
2377 if ( buf->filp != filp ) {
2378 DRM_ERROR( "process %d using buffer owned by %p\n",
2379 DRM_CURRENTPID, buf->filp );
2380 return DRM_ERR(EINVAL);
2381 }
2382 if ( buf->pending ) {
2383 DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
2384 return DRM_ERR(EINVAL);
2385 }
2386
2387 if ( indirect.start < buf->used ) {
2388 DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
2389 indirect.start, buf->used );
2390 return DRM_ERR(EINVAL);
2391 }
2392
2393 RING_SPACE_TEST_WITH_RETURN( dev_priv );
2394 VB_AGE_TEST_WITH_RETURN( dev_priv );
2395
2396 buf->used = indirect.end;
2397
2398 /* Wait for the 3D stream to idle before the indirect buffer
2399 * containing 2D acceleration commands is processed.
2400 */
2401 BEGIN_RING( 2 );
2402
2403 RADEON_WAIT_UNTIL_3D_IDLE();
2404
2405 ADVANCE_RING();
2406
2407 /* Dispatch the indirect buffer full of commands from the
2408 * X server. This is insecure and is thus only available to
2409 * privileged clients.
2410 */
2411 radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
2412 if (indirect.discard) {
2413 radeon_cp_discard_buffer( dev, buf );
2414 }
2415
2416
2417 COMMIT_RING();
2418 return 0;
2419}
2420
2421static int radeon_cp_vertex2( DRM_IOCTL_ARGS )
2422{
2423 DRM_DEVICE;
2424 drm_radeon_private_t *dev_priv = dev->dev_private;
2425 drm_file_t *filp_priv;
2426 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2427 drm_device_dma_t *dma = dev->dma;
2428 drm_buf_t *buf;
2429 drm_radeon_vertex2_t vertex;
2430 int i;
2431 unsigned char laststate;
2432
2433 LOCK_TEST_WITH_RETURN( dev, filp );
2434
2435 if ( !dev_priv ) {
2436 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2437 return DRM_ERR(EINVAL);
2438 }
2439
2440 DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
2441
2442 DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t __user *)data,
2443 sizeof(vertex) );
2444
2445 DRM_DEBUG( "pid=%d index=%d discard=%d\n",
2446 DRM_CURRENTPID,
2447 vertex.idx, vertex.discard );
2448
2449 if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
2450 DRM_ERROR( "buffer index %d (of %d max)\n",
2451 vertex.idx, dma->buf_count - 1 );
2452 return DRM_ERR(EINVAL);
2453 }
2454
2455 RING_SPACE_TEST_WITH_RETURN( dev_priv );
2456 VB_AGE_TEST_WITH_RETURN( dev_priv );
2457
2458 buf = dma->buflist[vertex.idx];
2459
2460 if ( buf->filp != filp ) {
2461 DRM_ERROR( "process %d using buffer owned by %p\n",
2462 DRM_CURRENTPID, buf->filp );
2463 return DRM_ERR(EINVAL);
2464 }
2465
2466 if ( buf->pending ) {
2467 DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
2468 return DRM_ERR(EINVAL);
2469 }
2470
2471 if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
2472 return DRM_ERR(EINVAL);
2473
2474 for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) {
2475 drm_radeon_prim_t prim;
2476 drm_radeon_tcl_prim_t tclprim;
2477
2478 if ( DRM_COPY_FROM_USER( &prim, &vertex.prim[i], sizeof(prim) ) )
2479 return DRM_ERR(EFAULT);
2480
2481 if ( prim.stateidx != laststate ) {
2482 drm_radeon_state_t state;
2483
2484 if ( DRM_COPY_FROM_USER( &state,
2485 &vertex.state[prim.stateidx],
2486 sizeof(state) ) )
2487 return DRM_ERR(EFAULT);
2488
2489 if ( radeon_emit_state2( dev_priv, filp_priv, &state ) ) {
2490 DRM_ERROR( "radeon_emit_state2 failed\n" );
2491 return DRM_ERR( EINVAL );
2492 }
2493
2494 laststate = prim.stateidx;
2495 }
2496
2497 tclprim.start = prim.start;
2498 tclprim.finish = prim.finish;
2499 tclprim.prim = prim.prim;
2500 tclprim.vc_format = prim.vc_format;
2501
2502 if ( prim.prim & RADEON_PRIM_WALK_IND ) {
2503 tclprim.offset = prim.numverts * 64;
2504 tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
2505
2506 radeon_cp_dispatch_indices( dev, buf, &tclprim );
2507 } else {
2508 tclprim.numverts = prim.numverts;
2509 tclprim.offset = 0; /* not used */
2510
2511 radeon_cp_dispatch_vertex( dev, buf, &tclprim );
2512 }
2513
2514 if (sarea_priv->nbox == 1)
2515 sarea_priv->nbox = 0;
2516 }
2517
2518 if ( vertex.discard ) {
2519 radeon_cp_discard_buffer( dev, buf );
2520 }
2521
2522 COMMIT_RING();
2523 return 0;
2524}
2525
2526
2527static int radeon_emit_packets(
2528 drm_radeon_private_t *dev_priv,
2529 drm_file_t *filp_priv,
2530 drm_radeon_cmd_header_t header,
2531 drm_radeon_cmd_buffer_t *cmdbuf )
2532{
2533 int id = (int)header.packet.packet_id;
2534 int sz, reg;
2535 int *data = (int *)cmdbuf->buf;
2536 RING_LOCALS;
2537
2538 if (id >= RADEON_MAX_STATE_PACKETS)
2539 return DRM_ERR(EINVAL);
2540
2541 sz = packet[id].len;
2542 reg = packet[id].start;
2543
2544 if (sz * sizeof(int) > cmdbuf->bufsz) {
2545 DRM_ERROR( "Packet size provided larger than data provided\n" );
2546 return DRM_ERR(EINVAL);
2547 }
2548
2549 if ( radeon_check_and_fixup_packets( dev_priv, filp_priv, id, data ) ) {
2550 DRM_ERROR( "Packet verification failed\n" );
2551 return DRM_ERR( EINVAL );
2552 }
2553
2554 BEGIN_RING(sz+1);
2555 OUT_RING( CP_PACKET0( reg, (sz-1) ) );
2556 OUT_RING_TABLE( data, sz );
2557 ADVANCE_RING();
2558
2559 cmdbuf->buf += sz * sizeof(int);
2560 cmdbuf->bufsz -= sz * sizeof(int);
2561 return 0;
2562}
2563
2564static __inline__ int radeon_emit_scalars(
2565 drm_radeon_private_t *dev_priv,
2566 drm_radeon_cmd_header_t header,
2567 drm_radeon_cmd_buffer_t *cmdbuf )
2568{
2569 int sz = header.scalars.count;
2570 int start = header.scalars.offset;
2571 int stride = header.scalars.stride;
2572 RING_LOCALS;
2573
2574 BEGIN_RING( 3+sz );
2575 OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
2576 OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2577 OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
2578 OUT_RING_TABLE( cmdbuf->buf, sz );
2579 ADVANCE_RING();
2580 cmdbuf->buf += sz * sizeof(int);
2581 cmdbuf->bufsz -= sz * sizeof(int);
2582 return 0;
2583}
2584
2585/* God this is ugly
2586 */
2587static __inline__ int radeon_emit_scalars2(
2588 drm_radeon_private_t *dev_priv,
2589 drm_radeon_cmd_header_t header,
2590 drm_radeon_cmd_buffer_t *cmdbuf )
2591{
2592 int sz = header.scalars.count;
2593 int start = ((unsigned int)header.scalars.offset) + 0x100;
2594 int stride = header.scalars.stride;
2595 RING_LOCALS;
2596
2597 BEGIN_RING( 3+sz );
2598 OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
2599 OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2600 OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
2601 OUT_RING_TABLE( cmdbuf->buf, sz );
2602 ADVANCE_RING();
2603 cmdbuf->buf += sz * sizeof(int);
2604 cmdbuf->bufsz -= sz * sizeof(int);
2605 return 0;
2606}
2607
2608static __inline__ int radeon_emit_vectors(
2609 drm_radeon_private_t *dev_priv,
2610 drm_radeon_cmd_header_t header,
2611 drm_radeon_cmd_buffer_t *cmdbuf )
2612{
2613 int sz = header.vectors.count;
2614 int start = header.vectors.offset;
2615 int stride = header.vectors.stride;
2616 RING_LOCALS;
2617
2618 BEGIN_RING( 3+sz );
2619 OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) );
2620 OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
2621 OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) );
2622 OUT_RING_TABLE( cmdbuf->buf, sz );
2623 ADVANCE_RING();
2624
2625 cmdbuf->buf += sz * sizeof(int);
2626 cmdbuf->bufsz -= sz * sizeof(int);
2627 return 0;
2628}
2629
2630
2631static int radeon_emit_packet3( drm_device_t *dev,
2632 drm_file_t *filp_priv,
2633 drm_radeon_cmd_buffer_t *cmdbuf )
2634{
2635 drm_radeon_private_t *dev_priv = dev->dev_private;
2636 unsigned int cmdsz;
2637 int ret;
2638 RING_LOCALS;
2639
2640 DRM_DEBUG("\n");
2641
2642 if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
2643 cmdbuf, &cmdsz ) ) ) {
2644 DRM_ERROR( "Packet verification failed\n" );
2645 return ret;
2646 }
2647
2648 BEGIN_RING( cmdsz );
2649 OUT_RING_TABLE( cmdbuf->buf, cmdsz );
2650 ADVANCE_RING();
2651
2652 cmdbuf->buf += cmdsz * 4;
2653 cmdbuf->bufsz -= cmdsz * 4;
2654 return 0;
2655}
2656
2657
2658static int radeon_emit_packet3_cliprect( drm_device_t *dev,
2659 drm_file_t *filp_priv,
2660 drm_radeon_cmd_buffer_t *cmdbuf,
2661 int orig_nbox )
2662{
2663 drm_radeon_private_t *dev_priv = dev->dev_private;
2664 drm_clip_rect_t box;
2665 unsigned int cmdsz;
2666 int ret;
2667 drm_clip_rect_t __user *boxes = cmdbuf->boxes;
2668 int i = 0;
2669 RING_LOCALS;
2670
2671 DRM_DEBUG("\n");
2672
2673 if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
2674 cmdbuf, &cmdsz ) ) ) {
2675 DRM_ERROR( "Packet verification failed\n" );
2676 return ret;
2677 }
2678
2679 if (!orig_nbox)
2680 goto out;
2681
2682 do {
2683 if ( i < cmdbuf->nbox ) {
2684 if (DRM_COPY_FROM_USER( &box, &boxes[i], sizeof(box) ))
2685 return DRM_ERR(EFAULT);
2686 /* FIXME The second and subsequent times round
2687 * this loop, send a WAIT_UNTIL_3D_IDLE before
2688 * calling emit_clip_rect(). This fixes a
2689 * lockup on fast machines when sending
2690 * several cliprects with a cmdbuf, as when
2691 * waving a 2D window over a 3D
2692 * window. Something in the commands from user
2693 * space seems to hang the card when they're
2694 * sent several times in a row. That would be
2695 * the correct place to fix it but this works
2696 * around it until I can figure that out - Tim
2697 * Smith */
2698 if ( i ) {
2699 BEGIN_RING( 2 );
2700 RADEON_WAIT_UNTIL_3D_IDLE();
2701 ADVANCE_RING();
2702 }
2703 radeon_emit_clip_rect( dev_priv, &box );
2704 }
2705
2706 BEGIN_RING( cmdsz );
2707 OUT_RING_TABLE( cmdbuf->buf, cmdsz );
2708 ADVANCE_RING();
2709
2710 } while ( ++i < cmdbuf->nbox );
2711 if (cmdbuf->nbox == 1)
2712 cmdbuf->nbox = 0;
2713
2714 out:
2715 cmdbuf->buf += cmdsz * 4;
2716 cmdbuf->bufsz -= cmdsz * 4;
2717 return 0;
2718}
2719
2720
2721static int radeon_emit_wait( drm_device_t *dev, int flags )
2722{
2723 drm_radeon_private_t *dev_priv = dev->dev_private;
2724 RING_LOCALS;
2725
2726 DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
2727 switch (flags) {
2728 case RADEON_WAIT_2D:
2729 BEGIN_RING( 2 );
2730 RADEON_WAIT_UNTIL_2D_IDLE();
2731 ADVANCE_RING();
2732 break;
2733 case RADEON_WAIT_3D:
2734 BEGIN_RING( 2 );
2735 RADEON_WAIT_UNTIL_3D_IDLE();
2736 ADVANCE_RING();
2737 break;
2738 case RADEON_WAIT_2D|RADEON_WAIT_3D:
2739 BEGIN_RING( 2 );
2740 RADEON_WAIT_UNTIL_IDLE();
2741 ADVANCE_RING();
2742 break;
2743 default:
2744 return DRM_ERR(EINVAL);
2745 }
2746
2747 return 0;
2748}
2749
2750static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
2751{
2752 DRM_DEVICE;
2753 drm_radeon_private_t *dev_priv = dev->dev_private;
2754 drm_file_t *filp_priv;
2755 drm_device_dma_t *dma = dev->dma;
2756 drm_buf_t *buf = NULL;
2757 int idx;
2758 drm_radeon_cmd_buffer_t cmdbuf;
2759 drm_radeon_cmd_header_t header;
2760 int orig_nbox, orig_bufsz;
2761 char *kbuf=NULL;
2762
2763 LOCK_TEST_WITH_RETURN( dev, filp );
2764
2765 if ( !dev_priv ) {
2766 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2767 return DRM_ERR(EINVAL);
2768 }
2769
2770 DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
2771
2772 DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t __user *)data,
2773 sizeof(cmdbuf) );
2774
2775 RING_SPACE_TEST_WITH_RETURN( dev_priv );
2776 VB_AGE_TEST_WITH_RETURN( dev_priv );
2777
2778 if (cmdbuf.bufsz > 64*1024 || cmdbuf.bufsz<0) {
2779 return DRM_ERR(EINVAL);
2780 }
2781
2782 /* Allocate an in-kernel area and copy in the cmdbuf. Do this to avoid
2783 * races between checking values and using those values in other code,
2784 * and simply to avoid a lot of function calls to copy in data.
2785 */
2786 orig_bufsz = cmdbuf.bufsz;
2787 if (orig_bufsz != 0) {
2788 kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
2789 if (kbuf == NULL)
2790 return DRM_ERR(ENOMEM);
2791 if (DRM_COPY_FROM_USER(kbuf, cmdbuf.buf, cmdbuf.bufsz)) {
2792 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
2793 return DRM_ERR(EFAULT);
2794 }
2795 cmdbuf.buf = kbuf;
2796 }
2797
2798 orig_nbox = cmdbuf.nbox;
2799
2800 while ( cmdbuf.bufsz >= sizeof(header) ) {
2801
2802 header.i = *(int *)cmdbuf.buf;
2803 cmdbuf.buf += sizeof(header);
2804 cmdbuf.bufsz -= sizeof(header);
2805
2806 switch (header.header.cmd_type) {
2807 case RADEON_CMD_PACKET:
2808 DRM_DEBUG("RADEON_CMD_PACKET\n");
2809 if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) {
2810 DRM_ERROR("radeon_emit_packets failed\n");
2811 goto err;
2812 }
2813 break;
2814
2815 case RADEON_CMD_SCALARS:
2816 DRM_DEBUG("RADEON_CMD_SCALARS\n");
2817 if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) {
2818 DRM_ERROR("radeon_emit_scalars failed\n");
2819 goto err;
2820 }
2821 break;
2822
2823 case RADEON_CMD_VECTORS:
2824 DRM_DEBUG("RADEON_CMD_VECTORS\n");
2825 if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) {
2826 DRM_ERROR("radeon_emit_vectors failed\n");
2827 goto err;
2828 }
2829 break;
2830
2831 case RADEON_CMD_DMA_DISCARD:
2832 DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
2833 idx = header.dma.buf_idx;
2834 if ( idx < 0 || idx >= dma->buf_count ) {
2835 DRM_ERROR( "buffer index %d (of %d max)\n",
2836 idx, dma->buf_count - 1 );
2837 goto err;
2838 }
2839
2840 buf = dma->buflist[idx];
2841 if ( buf->filp != filp || buf->pending ) {
2842 DRM_ERROR( "bad buffer %p %p %d\n",
2843 buf->filp, filp, buf->pending);
2844 goto err;
2845 }
2846
2847 radeon_cp_discard_buffer( dev, buf );
2848 break;
2849
2850 case RADEON_CMD_PACKET3:
2851 DRM_DEBUG("RADEON_CMD_PACKET3\n");
2852 if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) {
2853 DRM_ERROR("radeon_emit_packet3 failed\n");
2854 goto err;
2855 }
2856 break;
2857
2858 case RADEON_CMD_PACKET3_CLIP:
2859 DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
2860 if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) {
2861 DRM_ERROR("radeon_emit_packet3_clip failed\n");
2862 goto err;
2863 }
2864 break;
2865
2866 case RADEON_CMD_SCALARS2:
2867 DRM_DEBUG("RADEON_CMD_SCALARS2\n");
2868 if (radeon_emit_scalars2( dev_priv, header, &cmdbuf )) {
2869 DRM_ERROR("radeon_emit_scalars2 failed\n");
2870 goto err;
2871 }
2872 break;
2873
2874 case RADEON_CMD_WAIT:
2875 DRM_DEBUG("RADEON_CMD_WAIT\n");
2876 if (radeon_emit_wait( dev, header.wait.flags )) {
2877 DRM_ERROR("radeon_emit_wait failed\n");
2878 goto err;
2879 }
2880 break;
2881 default:
2882 DRM_ERROR("bad cmd_type %d at %p\n",
2883 header.header.cmd_type,
2884 cmdbuf.buf - sizeof(header));
2885 goto err;
2886 }
2887 }
2888
2889 if (orig_bufsz != 0)
2890 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
2891
2892 DRM_DEBUG("DONE\n");
2893 COMMIT_RING();
2894 return 0;
2895
2896err:
2897 if (orig_bufsz != 0)
2898 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
2899 return DRM_ERR(EINVAL);
2900}
2901
2902
2903
2904static int radeon_cp_getparam( DRM_IOCTL_ARGS )
2905{
2906 DRM_DEVICE;
2907 drm_radeon_private_t *dev_priv = dev->dev_private;
2908 drm_radeon_getparam_t param;
2909 int value;
2910
2911 if ( !dev_priv ) {
2912 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2913 return DRM_ERR(EINVAL);
2914 }
2915
2916 DRM_COPY_FROM_USER_IOCTL( param, (drm_radeon_getparam_t __user *)data,
2917 sizeof(param) );
2918
2919 DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
2920
2921 switch( param.param ) {
2922 case RADEON_PARAM_GART_BUFFER_OFFSET:
2923 value = dev_priv->gart_buffers_offset;
2924 break;
2925 case RADEON_PARAM_LAST_FRAME:
2926 dev_priv->stats.last_frame_reads++;
2927 value = GET_SCRATCH( 0 );
2928 break;
2929 case RADEON_PARAM_LAST_DISPATCH:
2930 value = GET_SCRATCH( 1 );
2931 break;
2932 case RADEON_PARAM_LAST_CLEAR:
2933 dev_priv->stats.last_clear_reads++;
2934 value = GET_SCRATCH( 2 );
2935 break;
2936 case RADEON_PARAM_IRQ_NR:
2937 value = dev->irq;
2938 break;
2939 case RADEON_PARAM_GART_BASE:
2940 value = dev_priv->gart_vm_start;
2941 break;
2942 case RADEON_PARAM_REGISTER_HANDLE:
2943 value = dev_priv->mmio_offset;
2944 break;
2945 case RADEON_PARAM_STATUS_HANDLE:
2946 value = dev_priv->ring_rptr_offset;
2947 break;
2948#if BITS_PER_LONG == 32
2949 /*
2950 * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
2951 * pointer which can't fit into an int-sized variable. According to
2952 * Michel Dänzer, the ioctl() is only used on embedded platforms, so
2953 * not supporting it shouldn't be a problem. If the same functionality
2954 * is needed on 64-bit platforms, a new ioctl() would have to be added,
2955 * so backwards-compatibility for the embedded platforms can be
2956 * maintained. --davidm 4-Feb-2004.
2957 */
2958 case RADEON_PARAM_SAREA_HANDLE:
2959 /* The lock is the first dword in the sarea. */
2960 value = (long)dev->lock.hw_lock;
2961 break;
2962#endif
2963 case RADEON_PARAM_GART_TEX_HANDLE:
2964 value = dev_priv->gart_textures_offset;
2965 break;
2966 default:
2967 return DRM_ERR(EINVAL);
2968 }
2969
2970 if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
2971 DRM_ERROR( "copy_to_user\n" );
2972 return DRM_ERR(EFAULT);
2973 }
2974
2975 return 0;
2976}
2977
2978static int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
2979 DRM_DEVICE;
2980 drm_radeon_private_t *dev_priv = dev->dev_private;
2981 drm_file_t *filp_priv;
2982 drm_radeon_setparam_t sp;
2983 struct drm_radeon_driver_file_fields *radeon_priv;
2984
2985 if ( !dev_priv ) {
2986 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2987 return DRM_ERR( EINVAL );
2988 }
2989
2990 DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
2991
2992 DRM_COPY_FROM_USER_IOCTL( sp, ( drm_radeon_setparam_t __user * )data,
2993 sizeof( sp ) );
2994
2995 switch( sp.param ) {
2996 case RADEON_SETPARAM_FB_LOCATION:
2997 radeon_priv = filp_priv->driver_priv;
2998 radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
2999 break;
3000 case RADEON_SETPARAM_SWITCH_TILING:
3001 if (sp.value == 0) {
3002 DRM_DEBUG( "color tiling disabled\n" );
3003 dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
3004 dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
3005 dev_priv->sarea_priv->tiling_enabled = 0;
3006 }
3007 else if (sp.value == 1) {
3008 DRM_DEBUG( "color tiling enabled\n" );
3009 dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
3010 dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
3011 dev_priv->sarea_priv->tiling_enabled = 1;
3012 }
3013 break;
3014 default:
3015 DRM_DEBUG( "Invalid parameter %d\n", sp.param );
3016 return DRM_ERR( EINVAL );
3017 }
3018
3019 return 0;
3020}
3021
3022/* When a client dies:
3023 * - Check for and clean up flipped page state
3024 * - Free any alloced GART memory.
3025 *
3026 * DRM infrastructure takes care of reclaiming dma buffers.
3027 */
3028void radeon_driver_prerelease(drm_device_t *dev, DRMFILE filp)
3029{
3030 if ( dev->dev_private ) {
3031 drm_radeon_private_t *dev_priv = dev->dev_private;
3032 if ( dev_priv->page_flipping ) {
3033 radeon_do_cleanup_pageflip( dev );
3034 }
3035 radeon_mem_release( filp, dev_priv->gart_heap );
3036 radeon_mem_release( filp, dev_priv->fb_heap );
3037 radeon_surfaces_release(filp, dev_priv);
3038 }
3039}
3040
3041void radeon_driver_pretakedown(drm_device_t *dev)
3042{
3043 radeon_do_release(dev);
3044}
3045
3046int radeon_driver_open_helper(drm_device_t *dev, drm_file_t *filp_priv)
3047{
3048 drm_radeon_private_t *dev_priv = dev->dev_private;
3049 struct drm_radeon_driver_file_fields *radeon_priv;
3050
3051 radeon_priv = (struct drm_radeon_driver_file_fields *)drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
3052
3053 if (!radeon_priv)
3054 return -ENOMEM;
3055
3056 filp_priv->driver_priv = radeon_priv;
3057 if ( dev_priv )
3058 radeon_priv->radeon_fb_delta = dev_priv->fb_location;
3059 else
3060 radeon_priv->radeon_fb_delta = 0;
3061 return 0;
3062}
3063
3064
3065void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv)
3066{
3067 struct drm_radeon_driver_file_fields *radeon_priv = filp_priv->driver_priv;
3068
3069 drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
3070}
3071
3072drm_ioctl_desc_t radeon_ioctls[] = {
3073 [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 },
3074 [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = { radeon_cp_start, 1, 1 },
3075 [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 },
3076 [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 },
3077 [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 },
3078 [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = { radeon_cp_resume, 1, 0 },
3079 [DRM_IOCTL_NR(DRM_RADEON_RESET)] = { radeon_engine_reset, 1, 0 },
3080 [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 },
3081 [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 },
3082 [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 },
3083 [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 },
3084 [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 },
3085 [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = { radeon_cp_texture, 1, 0 },
3086 [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 },
3087 [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 },
3088 [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 },
3089 [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 },
3090 [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 },
3091 [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 },
3092 [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 },
3093 [DRM_IOCTL_NR(DRM_RADEON_FREE)] = { radeon_mem_free, 1, 0 },
3094 [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = { radeon_mem_init_heap,1, 1 },
3095 [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 },
3096 [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 },
3097 [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = { radeon_cp_setparam, 1, 0 },
3098 [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = { radeon_surface_alloc,1, 0 },
3099 [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = { radeon_surface_free, 1, 0 }
3100};
3101
3102int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
diff --git a/drivers/char/drm/sis_drm.h b/drivers/char/drm/sis_drm.h
new file mode 100644
index 000000000000..e99c3a43abbc
--- /dev/null
+++ b/drivers/char/drm/sis_drm.h
@@ -0,0 +1,42 @@
1
2#ifndef __SIS_DRM_H__
3#define __SIS_DRM_H__
4
5/* SiS specific ioctls */
6#define NOT_USED_0_3
7#define DRM_SIS_FB_ALLOC 0x04
8#define DRM_SIS_FB_FREE 0x05
9#define NOT_USED_6_12
10#define DRM_SIS_AGP_INIT 0x13
11#define DRM_SIS_AGP_ALLOC 0x14
12#define DRM_SIS_AGP_FREE 0x15
13#define DRM_SIS_FB_INIT 0x16
14
15#define DRM_IOCTL_SIS_FB_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_FB_ALLOC, drm_sis_mem_t)
16#define DRM_IOCTL_SIS_FB_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_FREE, drm_sis_mem_t)
17#define DRM_IOCTL_SIS_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_INIT, drm_sis_agp_t)
18#define DRM_IOCTL_SIS_AGP_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_ALLOC, drm_sis_mem_t)
19#define DRM_IOCTL_SIS_AGP_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_AGP_FREE, drm_sis_mem_t)
20#define DRM_IOCTL_SIS_FB_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_INIT, drm_sis_fb_t)
21/*
22#define DRM_IOCTL_SIS_FLIP DRM_IOW( 0x48, drm_sis_flip_t)
23#define DRM_IOCTL_SIS_FLIP_INIT DRM_IO( 0x49)
24#define DRM_IOCTL_SIS_FLIP_FINAL DRM_IO( 0x50)
25*/
26
27typedef struct {
28 int context;
29 unsigned int offset;
30 unsigned int size;
31 unsigned long free;
32} drm_sis_mem_t;
33
34typedef struct {
35 unsigned int offset, size;
36} drm_sis_agp_t;
37
38typedef struct {
39 unsigned int offset, size;
40} drm_sis_fb_t;
41
42#endif /* __SIS_DRM_H__ */
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
new file mode 100644
index 000000000000..f441714faae3
--- /dev/null
+++ b/drivers/char/drm/sis_drv.c
@@ -0,0 +1,110 @@
1/* sis.c -- sis driver -*- linux-c -*-
2 *
3 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
4 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28#include <linux/config.h>
29#include "drmP.h"
30#include "sis_drm.h"
31#include "sis_drv.h"
32
33#include "drm_pciids.h"
34
35static int postinit( struct drm_device *dev, unsigned long flags )
36{
37 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
38 DRIVER_NAME,
39 DRIVER_MAJOR,
40 DRIVER_MINOR,
41 DRIVER_PATCHLEVEL,
42 DRIVER_DATE,
43 dev->primary.minor,
44 pci_pretty_name(dev->pdev)
45 );
46 return 0;
47}
48
49static int version( drm_version_t *version )
50{
51 int len;
52
53 version->version_major = DRIVER_MAJOR;
54 version->version_minor = DRIVER_MINOR;
55 version->version_patchlevel = DRIVER_PATCHLEVEL;
56 DRM_COPY( version->name, DRIVER_NAME );
57 DRM_COPY( version->date, DRIVER_DATE );
58 DRM_COPY( version->desc, DRIVER_DESC );
59 return 0;
60}
61
62static struct pci_device_id pciidlist[] = {
63 sisdrv_PCI_IDS
64};
65
66extern drm_ioctl_desc_t sis_ioctls[];
67extern int sis_max_ioctl;
68
69static struct drm_driver driver = {
70 .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR,
71 .context_ctor = sis_init_context,
72 .context_dtor = sis_final_context,
73 .reclaim_buffers = drm_core_reclaim_buffers,
74 .get_map_ofs = drm_core_get_map_ofs,
75 .get_reg_ofs = drm_core_get_reg_ofs,
76 .postinit = postinit,
77 .version = version,
78 .ioctls = sis_ioctls,
79 .fops = {
80 .owner = THIS_MODULE,
81 .open = drm_open,
82 .release = drm_release,
83 .ioctl = drm_ioctl,
84 .mmap = drm_mmap,
85 .poll = drm_poll,
86 .fasync = drm_fasync,
87 },
88 .pci_driver = {
89 .name = DRIVER_NAME,
90 .id_table = pciidlist,
91 }
92};
93
94static int __init sis_init(void)
95{
96 driver.num_ioctls = sis_max_ioctl;
97 return drm_init(&driver);
98}
99
100static void __exit sis_exit(void)
101{
102 drm_exit(&driver);
103}
104
105module_init(sis_init);
106module_exit(sis_exit);
107
108MODULE_AUTHOR( DRIVER_AUTHOR );
109MODULE_DESCRIPTION( DRIVER_DESC );
110MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
new file mode 100644
index 000000000000..5be36b5caec9
--- /dev/null
+++ b/drivers/char/drm/sis_drv.h
@@ -0,0 +1,52 @@
1/* sis_drv.h -- Private header for sis driver -*- linux-c -*-
2 *
3 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
4 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28#ifndef _SIS_DRV_H_
29#define _SIS_DRV_H_
30
31/* General customization:
32 */
33
34#define DRIVER_AUTHOR "SIS"
35#define DRIVER_NAME "sis"
36#define DRIVER_DESC "SIS 300/630/540"
37#define DRIVER_DATE "20030826"
38#define DRIVER_MAJOR 1
39#define DRIVER_MINOR 1
40#define DRIVER_PATCHLEVEL 0
41
42#include "sis_ds.h"
43
44typedef struct drm_sis_private {
45 memHeap_t *AGPHeap;
46 memHeap_t *FBHeap;
47} drm_sis_private_t;
48
49extern int sis_init_context(drm_device_t *dev, int context);
50extern int sis_final_context(drm_device_t *dev, int context);
51
52#endif
diff --git a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
new file mode 100644
index 000000000000..e37ed8ce48df
--- /dev/null
+++ b/drivers/char/drm/sis_ds.c
@@ -0,0 +1,301 @@
1/* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*-
2 * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
3 *
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Sung-Ching Lin <sclin@sis.com.tw>
28 *
29 */
30
31#include "drmP.h"
32#include "drm.h"
33#include "sis_ds.h"
34
35/* Set Data Structure, not check repeated value
36 * temporarily used
37 */
38
39set_t *setInit(void)
40{
41 int i;
42 set_t *set;
43
44 set = (set_t *)drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
45 if (set != NULL) {
46 for (i = 0; i < SET_SIZE; i++) {
47 set->list[i].free_next = i + 1;
48 set->list[i].alloc_next = -1;
49 }
50 set->list[SET_SIZE-1].free_next = -1;
51 set->free = 0;
52 set->alloc = -1;
53 set->trace = -1;
54 }
55 return set;
56}
57
58int setAdd(set_t *set, ITEM_TYPE item)
59{
60 int free = set->free;
61
62 if (free != -1) {
63 set->list[free].val = item;
64 set->free = set->list[free].free_next;
65 } else {
66 return 0;
67 }
68
69 set->list[free].alloc_next = set->alloc;
70 set->alloc = free;
71 set->list[free].free_next = -1;
72
73 return 1;
74}
75
76int setDel(set_t *set, ITEM_TYPE item)
77{
78 int alloc = set->alloc;
79 int prev = -1;
80
81 while (alloc != -1) {
82 if (set->list[alloc].val == item) {
83 if (prev != -1)
84 set->list[prev].alloc_next =
85 set->list[alloc].alloc_next;
86 else
87 set->alloc = set->list[alloc].alloc_next;
88 break;
89 }
90 prev = alloc;
91 alloc = set->list[alloc].alloc_next;
92 }
93
94 if (alloc == -1)
95 return 0;
96
97 set->list[alloc].free_next = set->free;
98 set->free = alloc;
99 set->list[alloc].alloc_next = -1;
100
101 return 1;
102}
103
104/* setFirst -> setAdd -> setNext is wrong */
105
106int setFirst(set_t *set, ITEM_TYPE *item)
107{
108 if (set->alloc == -1)
109 return 0;
110
111 *item = set->list[set->alloc].val;
112 set->trace = set->list[set->alloc].alloc_next;
113
114 return 1;
115}
116
117int setNext(set_t *set, ITEM_TYPE *item)
118{
119 if (set->trace == -1)
120 return 0;
121
122 *item = set->list[set->trace].val;
123 set->trace = set->list[set->trace].alloc_next;
124
125 return 1;
126}
127
128int setDestroy(set_t *set)
129{
130 drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
131
132 return 1;
133}
134
135/*
136 * GLX Hardware Device Driver common code
137 * Copyright (C) 1999 Wittawat Yamwong
138 *
139 * Permission is hereby granted, free of charge, to any person obtaining a
140 * copy of this software and associated documentation files (the "Software"),
141 * to deal in the Software without restriction, including without limitation
142 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
143 * and/or sell copies of the Software, and to permit persons to whom the
144 * Software is furnished to do so, subject to the following conditions:
145 *
146 * The above copyright notice and this permission notice shall be included
147 * in all copies or substantial portions of the Software.
148 *
149 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
150 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
151 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
152 * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
153 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
154 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
155 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
156 *
157 */
158
159#define ISFREE(bptr) ((bptr)->free)
160
161memHeap_t *mmInit(int ofs,
162 int size)
163{
164 PMemBlock blocks;
165
166 if (size <= 0)
167 return NULL;
168
169 blocks = (TMemBlock *)drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
170 if (blocks != NULL) {
171 blocks->ofs = ofs;
172 blocks->size = size;
173 blocks->free = 1;
174 return (memHeap_t *)blocks;
175 } else
176 return NULL;
177}
178
179/* Checks if a pointer 'b' is part of the heap 'heap' */
180int mmBlockInHeap(memHeap_t *heap, PMemBlock b)
181{
182 TMemBlock *p;
183
184 if (heap == NULL || b == NULL)
185 return 0;
186
187 p = heap;
188 while (p != NULL && p != b) {
189 p = p->next;
190 }
191 if (p == b)
192 return 1;
193 else
194 return 0;
195}
196
197static TMemBlock* SliceBlock(TMemBlock *p,
198 int startofs, int size,
199 int reserved, int alignment)
200{
201 TMemBlock *newblock;
202
203 /* break left */
204 if (startofs > p->ofs) {
205 newblock = (TMemBlock*) drm_calloc(1, sizeof(TMemBlock),
206 DRM_MEM_DRIVER);
207 newblock->ofs = startofs;
208 newblock->size = p->size - (startofs - p->ofs);
209 newblock->free = 1;
210 newblock->next = p->next;
211 p->size -= newblock->size;
212 p->next = newblock;
213 p = newblock;
214 }
215
216 /* break right */
217 if (size < p->size) {
218 newblock = (TMemBlock*) drm_calloc(1, sizeof(TMemBlock),
219 DRM_MEM_DRIVER);
220 newblock->ofs = startofs + size;
221 newblock->size = p->size - size;
222 newblock->free = 1;
223 newblock->next = p->next;
224 p->size = size;
225 p->next = newblock;
226 }
227
228 /* p = middle block */
229 p->align = alignment;
230 p->free = 0;
231 p->reserved = reserved;
232 return p;
233}
234
235PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch)
236{
237 int mask,startofs, endofs;
238 TMemBlock *p;
239
240 if (heap == NULL || align2 < 0 || size <= 0)
241 return NULL;
242
243 mask = (1 << align2)-1;
244 startofs = 0;
245 p = (TMemBlock *)heap;
246 while (p != NULL) {
247 if (ISFREE(p)) {
248 startofs = (p->ofs + mask) & ~mask;
249 if ( startofs < startSearch ) {
250 startofs = startSearch;
251 }
252 endofs = startofs+size;
253 if (endofs <= (p->ofs+p->size))
254 break;
255 }
256 p = p->next;
257 }
258 if (p == NULL)
259 return NULL;
260 p = SliceBlock(p,startofs,size,0,mask+1);
261 p->heap = heap;
262 return p;
263}
264
265static __inline__ int Join2Blocks(TMemBlock *p)
266{
267 if (p->free && p->next && p->next->free) {
268 TMemBlock *q = p->next;
269 p->size += q->size;
270 p->next = q->next;
271 drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
272 return 1;
273 }
274 return 0;
275}
276
277int mmFreeMem(PMemBlock b)
278{
279 TMemBlock *p, *prev;
280
281 if (b == NULL)
282 return 0;
283 if (b->heap == NULL)
284 return -1;
285
286 p = b->heap;
287 prev = NULL;
288 while (p != NULL && p != b) {
289 prev = p;
290 p = p->next;
291 }
292 if (p == NULL || p->free || p->reserved)
293 return -1;
294
295 p->free = 1;
296 Join2Blocks(p);
297 if (prev)
298 Join2Blocks(prev);
299 return 0;
300}
301
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
new file mode 100644
index 000000000000..171ee75afa57
--- /dev/null
+++ b/drivers/char/drm/sis_ds.h
@@ -0,0 +1,145 @@
1/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
2 * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
3 *
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Sung-Ching Lin <sclin@sis.com.tw>
28 *
29 */
30
31#ifndef __SIS_DS_H__
32#define __SIS_DS_H__
33
34/* Set Data Structure */
35
36#define SET_SIZE 5000
37
38typedef unsigned int ITEM_TYPE;
39
40typedef struct {
41 ITEM_TYPE val;
42 int alloc_next, free_next;
43} list_item_t;
44
45typedef struct {
46 int alloc;
47 int free;
48 int trace;
49 list_item_t list[SET_SIZE];
50} set_t;
51
52set_t *setInit(void);
53int setAdd(set_t *set, ITEM_TYPE item);
54int setDel(set_t *set, ITEM_TYPE item);
55int setFirst(set_t *set, ITEM_TYPE *item);
56int setNext(set_t *set, ITEM_TYPE *item);
57int setDestroy(set_t *set);
58
59/*
60 * GLX Hardware Device Driver common code
61 * Copyright (C) 1999 Wittawat Yamwong
62 *
63 * Permission is hereby granted, free of charge, to any person obtaining a
64 * copy of this software and associated documentation files (the "Software"),
65 * to deal in the Software without restriction, including without limitation
66 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
67 * and/or sell copies of the Software, and to permit persons to whom the
68 * Software is furnished to do so, subject to the following conditions:
69 *
70 * The above copyright notice and this permission notice shall be included
71 * in all copies or substantial portions of the Software.
72 *
73 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
74 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
76 * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
77 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
78 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
79 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
80 *
81 */
82
83struct mem_block_t {
84 struct mem_block_t *next;
85 struct mem_block_t *heap;
86 int ofs,size;
87 int align;
88 unsigned int free:1;
89 unsigned int reserved:1;
90};
91typedef struct mem_block_t TMemBlock;
92typedef struct mem_block_t *PMemBlock;
93
94/* a heap is just the first block in a chain */
95typedef struct mem_block_t memHeap_t;
96
97static __inline__ int mmBlockSize(PMemBlock b)
98{
99 return b->size;
100}
101
102static __inline__ int mmOffset(PMemBlock b)
103{
104 return b->ofs;
105}
106
107static __inline__ void mmMarkReserved(PMemBlock b)
108{
109 b->reserved = 1;
110}
111
112/*
113 * input: total size in bytes
114 * return: a heap pointer if OK, NULL if error
115 */
116memHeap_t *mmInit( int ofs, int size );
117
118/*
119 * Allocate 'size' bytes with 2^align2 bytes alignment,
120 * restrict the search to free memory after 'startSearch'
121 * depth and back buffers should be in different 4mb banks
122 * to get better page hits if possible
123 * input: size = size of block
124 * align2 = 2^align2 bytes alignment
125 * startSearch = linear offset from start of heap to begin search
126 * return: pointer to the allocated block, 0 if error
127 */
128PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch );
129
130/*
131 * Returns 1 if the block 'b' is part of the heap 'heap'
132 */
133int mmBlockInHeap( PMemBlock heap, PMemBlock b );
134
135/*
136 * Free block starts at offset
137 * input: pointer to a block
138 * return: 0 if OK, -1 if error
139 */
140int mmFreeMem( PMemBlock b );
141
142/* For debuging purpose. */
143void mmDumpMemInfo( memHeap_t *mmInit );
144
145#endif /* __SIS_DS_H__ */
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
new file mode 100644
index 000000000000..6610c5576d22
--- /dev/null
+++ b/drivers/char/drm/sis_mm.c
@@ -0,0 +1,417 @@
1/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*-
2 * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
3 *
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Sung-Ching Lin <sclin@sis.com.tw>
28 *
29 */
30
31#include "drmP.h"
32#include "sis_drm.h"
33#include "sis_drv.h"
34#include "sis_ds.h"
35#if defined(__linux__) && defined(CONFIG_FB_SIS)
36#include <video/sisfb.h>
37#endif
38
39#define MAX_CONTEXT 100
40#define VIDEO_TYPE 0
41#define AGP_TYPE 1
42
43typedef struct {
44 int used;
45 int context;
46 set_t *sets[2]; /* 0 for video, 1 for AGP */
47} sis_context_t;
48
49static sis_context_t global_ppriv[MAX_CONTEXT];
50
51
52static int add_alloc_set(int context, int type, unsigned int val)
53{
54 int i, retval = 0;
55
56 for (i = 0; i < MAX_CONTEXT; i++) {
57 if (global_ppriv[i].used && global_ppriv[i].context == context)
58 {
59 retval = setAdd(global_ppriv[i].sets[type], val);
60 break;
61 }
62 }
63 return retval;
64}
65
66static int del_alloc_set(int context, int type, unsigned int val)
67{
68 int i, retval = 0;
69
70 for (i = 0; i < MAX_CONTEXT; i++) {
71 if (global_ppriv[i].used && global_ppriv[i].context == context)
72 {
73 retval = setDel(global_ppriv[i].sets[type], val);
74 break;
75 }
76 }
77 return retval;
78}
79
80/* fb management via fb device */
81#if defined(__linux__) && defined(CONFIG_FB_SIS)
82
83static int sis_fb_init( DRM_IOCTL_ARGS )
84{
85 return 0;
86}
87
88static int sis_fb_alloc( DRM_IOCTL_ARGS )
89{
90 drm_sis_mem_t fb;
91 struct sis_memreq req;
92 drm_sis_mem_t __user *argp = (void __user *)data;
93 int retval = 0;
94
95 DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
96
97 req.size = fb.size;
98 sis_malloc(&req);
99 if (req.offset) {
100 /* TODO */
101 fb.offset = req.offset;
102 fb.free = req.offset;
103 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
104 DRM_DEBUG("adding to allocation set fails\n");
105 sis_free(req.offset);
106 retval = DRM_ERR(EINVAL);
107 }
108 } else {
109 fb.offset = 0;
110 fb.size = 0;
111 fb.free = 0;
112 }
113
114 DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
115
116 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset);
117
118 return retval;
119}
120
121static int sis_fb_free( DRM_IOCTL_ARGS )
122{
123 drm_sis_mem_t fb;
124 int retval = 0;
125
126 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *)data, sizeof(fb));
127
128 if (!fb.free)
129 return DRM_ERR(EINVAL);
130
131 if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
132 retval = DRM_ERR(EINVAL);
133 sis_free((u32)fb.free);
134
135 DRM_DEBUG("free fb, offset = %lu\n", fb.free);
136
137 return retval;
138}
139
140#else
141
142/* Called by the X Server to initialize the FB heap. Allocations will fail
143 * unless this is called. Offset is the beginning of the heap from the
144 * framebuffer offset (MaxXFBMem in XFree86).
145 *
146 * Memory layout according to Thomas Winischofer:
147 * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
148 *
149 * X driver/sisfb HW- Command-
150 * framebuffer memory DRI heap Cursor queue
151 */
152static int sis_fb_init( DRM_IOCTL_ARGS )
153{
154 DRM_DEVICE;
155 drm_sis_private_t *dev_priv = dev->dev_private;
156 drm_sis_fb_t fb;
157
158 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *)data, sizeof(fb));
159
160 if (dev_priv == NULL) {
161 dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
162 DRM_MEM_DRIVER);
163 dev_priv = dev->dev_private;
164 if (dev_priv == NULL)
165 return ENOMEM;
166 }
167
168 if (dev_priv->FBHeap != NULL)
169 return DRM_ERR(EINVAL);
170
171 dev_priv->FBHeap = mmInit(fb.offset, fb.size);
172
173 DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
174
175 return 0;
176}
177
178static int sis_fb_alloc( DRM_IOCTL_ARGS )
179{
180 DRM_DEVICE;
181 drm_sis_private_t *dev_priv = dev->dev_private;
182 drm_sis_mem_t __user *argp = (void __user *)data;
183 drm_sis_mem_t fb;
184 PMemBlock block;
185 int retval = 0;
186
187 if (dev_priv == NULL || dev_priv->FBHeap == NULL)
188 return DRM_ERR(EINVAL);
189
190 DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
191
192 block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
193 if (block) {
194 /* TODO */
195 fb.offset = block->ofs;
196 fb.free = (unsigned long)block;
197 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
198 DRM_DEBUG("adding to allocation set fails\n");
199 mmFreeMem((PMemBlock)fb.free);
200 retval = DRM_ERR(EINVAL);
201 }
202 } else {
203 fb.offset = 0;
204 fb.size = 0;
205 fb.free = 0;
206 }
207
208 DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
209
210 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset);
211
212 return retval;
213}
214
215static int sis_fb_free( DRM_IOCTL_ARGS )
216{
217 DRM_DEVICE;
218 drm_sis_private_t *dev_priv = dev->dev_private;
219 drm_sis_mem_t fb;
220
221 if (dev_priv == NULL || dev_priv->FBHeap == NULL)
222 return DRM_ERR(EINVAL);
223
224 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *)data, sizeof(fb));
225
226 if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock)fb.free))
227 return DRM_ERR(EINVAL);
228
229 if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
230 return DRM_ERR(EINVAL);
231 mmFreeMem((PMemBlock)fb.free);
232
233 DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
234
235 return 0;
236}
237
238#endif
239
240/* agp memory management */
241
242static int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
243{
244 DRM_DEVICE;
245 drm_sis_private_t *dev_priv = dev->dev_private;
246 drm_sis_agp_t agp;
247
248 if (dev_priv == NULL) {
249 dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
250 DRM_MEM_DRIVER);
251 dev_priv = dev->dev_private;
252 if (dev_priv == NULL)
253 return ENOMEM;
254 }
255
256 if (dev_priv->AGPHeap != NULL)
257 return DRM_ERR(EINVAL);
258
259 DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *)data, sizeof(agp));
260
261 dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
262
263 DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
264
265 return 0;
266}
267
268static int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
269{
270 DRM_DEVICE;
271 drm_sis_private_t *dev_priv = dev->dev_private;
272 drm_sis_mem_t __user *argp = (void __user *)data;
273 drm_sis_mem_t agp;
274 PMemBlock block;
275 int retval = 0;
276
277 if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
278 return DRM_ERR(EINVAL);
279
280 DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp));
281
282 block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
283 if (block) {
284 /* TODO */
285 agp.offset = block->ofs;
286 agp.free = (unsigned long)block;
287 if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
288 DRM_DEBUG("adding to allocation set fails\n");
289 mmFreeMem((PMemBlock)agp.free);
290 retval = -1;
291 }
292 } else {
293 agp.offset = 0;
294 agp.size = 0;
295 agp.free = 0;
296 }
297
298 DRM_COPY_TO_USER_IOCTL(argp, agp, sizeof(agp));
299
300 DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
301
302 return retval;
303}
304
305static int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
306{
307 DRM_DEVICE;
308 drm_sis_private_t *dev_priv = dev->dev_private;
309 drm_sis_mem_t agp;
310
311 if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
312 return DRM_ERR(EINVAL);
313
314 DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *)data, sizeof(agp));
315
316 if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock)agp.free))
317 return DRM_ERR(EINVAL);
318
319 mmFreeMem((PMemBlock)agp.free);
320 if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
321 return DRM_ERR(EINVAL);
322
323 DRM_DEBUG("free agp, free = 0x%lx\n", agp.free);
324
325 return 0;
326}
327
328int sis_init_context(struct drm_device *dev, int context)
329{
330 int i;
331
332 for (i = 0; i < MAX_CONTEXT ; i++) {
333 if (global_ppriv[i].used &&
334 (global_ppriv[i].context == context))
335 break;
336 }
337
338 if (i >= MAX_CONTEXT) {
339 for (i = 0; i < MAX_CONTEXT ; i++) {
340 if (!global_ppriv[i].used) {
341 global_ppriv[i].context = context;
342 global_ppriv[i].used = 1;
343 global_ppriv[i].sets[0] = setInit();
344 global_ppriv[i].sets[1] = setInit();
345 DRM_DEBUG("init allocation set, socket=%d, "
346 "context = %d\n", i, context);
347 break;
348 }
349 }
350 if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
351 (global_ppriv[i].sets[1] == NULL))
352 {
353 return 0;
354 }
355 }
356
357 return 1;
358}
359
360int sis_final_context(struct drm_device *dev, int context)
361{
362 int i;
363
364 for (i=0; i<MAX_CONTEXT; i++) {
365 if (global_ppriv[i].used &&
366 (global_ppriv[i].context == context))
367 break;
368 }
369
370 if (i < MAX_CONTEXT) {
371 set_t *set;
372 unsigned int item;
373 int retval;
374
375 DRM_DEBUG("find socket %d, context = %d\n", i, context);
376
377 /* Video Memory */
378 set = global_ppriv[i].sets[0];
379 retval = setFirst(set, &item);
380 while (retval) {
381 DRM_DEBUG("free video memory 0x%x\n", item);
382#if defined(__linux__) && defined(CONFIG_FB_SIS)
383 sis_free(item);
384#else
385 mmFreeMem((PMemBlock)item);
386#endif
387 retval = setNext(set, &item);
388 }
389 setDestroy(set);
390
391 /* AGP Memory */
392 set = global_ppriv[i].sets[1];
393 retval = setFirst(set, &item);
394 while (retval) {
395 DRM_DEBUG("free agp memory 0x%x\n", item);
396 mmFreeMem((PMemBlock)item);
397 retval = setNext(set, &item);
398 }
399 setDestroy(set);
400
401 global_ppriv[i].used = 0;
402 }
403
404 return 1;
405}
406
407drm_ioctl_desc_t sis_ioctls[] = {
408 [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = { sis_fb_alloc, 1, 0 },
409 [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = { sis_fb_free, 1, 0 },
410 [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = { sis_ioctl_agp_init, 1, 1 },
411 [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = { sis_ioctl_agp_alloc, 1, 0 },
412 [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = { sis_ioctl_agp_free, 1, 0 },
413 [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = { sis_fb_init, 1, 1 }
414};
415
416int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
417
diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
new file mode 100644
index 000000000000..0e7943e6efea
--- /dev/null
+++ b/drivers/char/drm/tdfx_drv.c
@@ -0,0 +1,107 @@
1/* tdfx_drv.c -- tdfx driver -*- linux-c -*-
2 * Created: Thu Oct 7 10:38:32 1999 by faith@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Daryll Strauss <daryll@valinux.com>
30 * Gareth Hughes <gareth@valinux.com>
31 */
32
33#include <linux/config.h>
34#include "drmP.h"
35#include "tdfx_drv.h"
36
37#include "drm_pciids.h"
38
39static int postinit( struct drm_device *dev, unsigned long flags )
40{
41 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
42 DRIVER_NAME,
43 DRIVER_MAJOR,
44 DRIVER_MINOR,
45 DRIVER_PATCHLEVEL,
46 DRIVER_DATE,
47 dev->primary.minor,
48 pci_pretty_name(dev->pdev)
49 );
50 return 0;
51}
52
53static int version( drm_version_t *version )
54{
55 int len;
56
57 version->version_major = DRIVER_MAJOR;
58 version->version_minor = DRIVER_MINOR;
59 version->version_patchlevel = DRIVER_PATCHLEVEL;
60 DRM_COPY( version->name, DRIVER_NAME );
61 DRM_COPY( version->date, DRIVER_DATE );
62 DRM_COPY( version->desc, DRIVER_DESC );
63 return 0;
64}
65
66static struct pci_device_id pciidlist[] = {
67 tdfx_PCI_IDS
68};
69
70static struct drm_driver driver = {
71 .driver_features = DRIVER_USE_MTRR,
72 .reclaim_buffers = drm_core_reclaim_buffers,
73 .get_map_ofs = drm_core_get_map_ofs,
74 .get_reg_ofs = drm_core_get_reg_ofs,
75 .postinit = postinit,
76 .version = version,
77 .fops = {
78 .owner = THIS_MODULE,
79 .open = drm_open,
80 .release = drm_release,
81 .ioctl = drm_ioctl,
82 .mmap = drm_mmap,
83 .poll = drm_poll,
84 .fasync = drm_fasync,
85 },
86 .pci_driver = {
87 .name = DRIVER_NAME,
88 .id_table = pciidlist,
89 }
90};
91
92static int __init tdfx_init(void)
93{
94 return drm_init(&driver);
95}
96
97static void __exit tdfx_exit(void)
98{
99 drm_exit(&driver);
100}
101
102module_init(tdfx_init);
103module_exit(tdfx_exit);
104
105MODULE_AUTHOR( DRIVER_AUTHOR );
106MODULE_DESCRIPTION( DRIVER_DESC );
107MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/tdfx_drv.h b/drivers/char/drm/tdfx_drv.h
new file mode 100644
index 000000000000..a582a3db4c75
--- /dev/null
+++ b/drivers/char/drm/tdfx_drv.h
@@ -0,0 +1,50 @@
1/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-
2 * Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com
3 *
4 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Gareth Hughes <gareth@valinux.com>
28 */
29
30#ifndef __TDFX_H__
31#define __TDFX_H__
32
33/* This remains constant for all DRM template files.
34 */
35#define DRM(x) tdfx_##x
36
37/* General customization:
38 */
39
40#define DRIVER_AUTHOR "VA Linux Systems Inc."
41
42#define DRIVER_NAME "tdfx"
43#define DRIVER_DESC "3dfx Banshee/Voodoo3+"
44#define DRIVER_DATE "20010216"
45
46#define DRIVER_MAJOR 1
47#define DRIVER_MINOR 0
48#define DRIVER_PATCHLEVEL 0
49
50#endif