aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/r128
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-05-28 20:09:59 -0400
committerDave Airlie <airlied@redhat.com>2008-07-13 20:45:01 -0400
commitc0e09200dc0813972442e550a5905a132768e56c (patch)
treed38e635a30ff8b0a2b98b9d7f97cab1501f8209e /drivers/gpu/drm/r128
parentbce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff)
drm: reorganise drm tree to be more future proof.
With the coming of kernel based modesetting and the memory manager stuff, the everything in one directory approach was getting very ugly and starting to be unmanageable. This restructures the drm along the lines of other kernel components. It creates a drivers/gpu/drm directory and moves the hw drivers into subdirectores. It moves the includes into an include/drm, and sets up the unifdef for the userspace headers we should be exporting. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/r128')
-rw-r--r--drivers/gpu/drm/r128/Makefile10
-rw-r--r--drivers/gpu/drm/r128/r128_cce.c935
-rw-r--r--drivers/gpu/drm/r128/r128_drv.c103
-rw-r--r--drivers/gpu/drm/r128/r128_drv.h522
-rw-r--r--drivers/gpu/drm/r128/r128_ioc32.c221
-rw-r--r--drivers/gpu/drm/r128/r128_irq.c101
-rw-r--r--drivers/gpu/drm/r128/r128_state.c1681
7 files changed, 3573 insertions, 0 deletions
diff --git a/drivers/gpu/drm/r128/Makefile b/drivers/gpu/drm/r128/Makefile
new file mode 100644
index 000000000000..1cc72ae3a880
--- /dev/null
+++ b/drivers/gpu/drm/r128/Makefile
@@ -0,0 +1,10 @@
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
5ccflags-y := -Iinclude/drm
6r128-y := r128_drv.o r128_cce.o r128_state.o r128_irq.o
7
8r128-$(CONFIG_COMPAT) += r128_ioc32.o
9
10obj-$(CONFIG_DRM_R128) += r128.o
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
new file mode 100644
index 000000000000..c31afbde62e7
--- /dev/null
+++ b/drivers/gpu/drm/r128/r128_cce.c
@@ -0,0 +1,935 @@
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/*
5 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
6 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
7 * All Rights Reserved.
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 * Gareth Hughes <gareth@valinux.com>
30 */
31
32#include "drmP.h"
33#include "drm.h"
34#include "r128_drm.h"
35#include "r128_drv.h"
36
37#define R128_FIFO_DEBUG 0
38
39/* CCE microcode (from ATI) */
40static u32 r128_cce_microcode[] = {
41 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
42 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0,
43 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1,
44 11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11,
45 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28,
46 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9,
47 30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656,
48 1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1,
49 15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071,
50 12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2,
51 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1,
52 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
53 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1,
54 15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2,
55 268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1,
56 15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82,
57 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729,
58 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008,
59 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
60 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1,
61 180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1,
62 114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0,
63 33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370,
64 1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1,
65 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793,
66 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
67 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1,
68 114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1,
69 1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1,
70 1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894,
71 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14,
72 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1,
73 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1,
74 33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1,
75 409611, 9, 188, 0, 10240, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
82};
83
84static int R128_READ_PLL(struct drm_device * dev, int addr)
85{
86 drm_r128_private_t *dev_priv = dev->dev_private;
87
88 R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
89 return R128_READ(R128_CLOCK_CNTL_DATA);
90}
91
92#if R128_FIFO_DEBUG
93static void r128_status(drm_r128_private_t * dev_priv)
94{
95 printk("GUI_STAT = 0x%08x\n",
96 (unsigned int)R128_READ(R128_GUI_STAT));
97 printk("PM4_STAT = 0x%08x\n",
98 (unsigned int)R128_READ(R128_PM4_STAT));
99 printk("PM4_BUFFER_DL_WPTR = 0x%08x\n",
100 (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR));
101 printk("PM4_BUFFER_DL_RPTR = 0x%08x\n",
102 (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR));
103 printk("PM4_MICRO_CNTL = 0x%08x\n",
104 (unsigned int)R128_READ(R128_PM4_MICRO_CNTL));
105 printk("PM4_BUFFER_CNTL = 0x%08x\n",
106 (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL));
107}
108#endif
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 -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)
142 return 0;
143 DRM_UDELAY(1);
144 }
145
146#if R128_FIFO_DEBUG
147 DRM_ERROR("failed!\n");
148#endif
149 return -EBUSY;
150}
151
152static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
153{
154 int i, ret;
155
156 ret = r128_do_wait_for_fifo(dev_priv, 64);
157 if (ret)
158 return ret;
159
160 for (i = 0; i < dev_priv->usec_timeout; i++) {
161 if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
162 r128_do_pixcache_flush(dev_priv);
163 return 0;
164 }
165 DRM_UDELAY(1);
166 }
167
168#if R128_FIFO_DEBUG
169 DRM_ERROR("failed!\n");
170#endif
171 return -EBUSY;
172}
173
174/* ================================================================
175 * CCE control, initialization
176 */
177
178/* Load the microcode for the CCE */
179static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
180{
181 int i;
182
183 DRM_DEBUG("\n");
184
185 r128_do_wait_for_idle(dev_priv);
186
187 R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
188 for (i = 0; i < 256; i++) {
189 R128_WRITE(R128_PM4_MICROCODE_DATAH, 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 -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(struct drm_device * 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, gen_reset_cntl | R128_SOFT_RESET_GUI);
291 R128_READ(R128_GEN_RESET_CNTL);
292 R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
293 R128_READ(R128_GEN_RESET_CNTL);
294
295 R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl);
296 R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
297 R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl);
298
299 /* Reset the CCE ring */
300 r128_do_cce_reset(dev_priv);
301
302 /* The CCE is no longer running after an engine reset */
303 dev_priv->cce_running = 0;
304
305 /* Reset any pending vertex, indirect buffers */
306 r128_freelist_reset(dev);
307
308 return 0;
309}
310
311static void r128_cce_init_ring_buffer(struct drm_device * dev,
312 drm_r128_private_t * dev_priv)
313{
314 u32 ring_start;
315 u32 tmp;
316
317 DRM_DEBUG("\n");
318
319 /* The manual (p. 2) says this address is in "VM space". This
320 * means it's an offset from the start of AGP space.
321 */
322#if __OS_HAS_AGP
323 if (!dev_priv->is_pci)
324 ring_start = dev_priv->cce_ring->offset - dev->agp->base;
325 else
326#endif
327 ring_start = dev_priv->cce_ring->offset -
328 (unsigned long)dev->sg->virtual;
329
330 R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET);
331
332 R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
333 R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
334
335 /* Set watermark control */
336 R128_WRITE(R128_PM4_BUFFER_WM_CNTL,
337 ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT)
338 | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT)
339 | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT)
340 | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT));
341
342 /* Force read. Why? Because it's in the examples... */
343 R128_READ(R128_PM4_BUFFER_ADDR);
344
345 /* Turn on bus mastering */
346 tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS;
347 R128_WRITE(R128_BUS_CNTL, tmp);
348}
349
350static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
351{
352 drm_r128_private_t *dev_priv;
353
354 DRM_DEBUG("\n");
355
356 dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
357 if (dev_priv == NULL)
358 return -ENOMEM;
359
360 memset(dev_priv, 0, sizeof(drm_r128_private_t));
361
362 dev_priv->is_pci = init->is_pci;
363
364 if (dev_priv->is_pci && !dev->sg) {
365 DRM_ERROR("PCI GART memory not allocated!\n");
366 dev->dev_private = (void *)dev_priv;
367 r128_do_cleanup_cce(dev);
368 return -EINVAL;
369 }
370
371 dev_priv->usec_timeout = init->usec_timeout;
372 if (dev_priv->usec_timeout < 1 ||
373 dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
374 DRM_DEBUG("TIMEOUT problem!\n");
375 dev->dev_private = (void *)dev_priv;
376 r128_do_cleanup_cce(dev);
377 return -EINVAL;
378 }
379
380 dev_priv->cce_mode = init->cce_mode;
381
382 /* GH: Simple idle check.
383 */
384 atomic_set(&dev_priv->idle_count, 0);
385
386 /* We don't support anything other than bus-mastering ring mode,
387 * but the ring can be in either AGP or PCI space for the ring
388 * read pointer.
389 */
390 if ((init->cce_mode != R128_PM4_192BM) &&
391 (init->cce_mode != R128_PM4_128BM_64INDBM) &&
392 (init->cce_mode != R128_PM4_64BM_128INDBM) &&
393 (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) {
394 DRM_DEBUG("Bad cce_mode!\n");
395 dev->dev_private = (void *)dev_priv;
396 r128_do_cleanup_cce(dev);
397 return -EINVAL;
398 }
399
400 switch (init->cce_mode) {
401 case R128_PM4_NONPM4:
402 dev_priv->cce_fifo_size = 0;
403 break;
404 case R128_PM4_192PIO:
405 case R128_PM4_192BM:
406 dev_priv->cce_fifo_size = 192;
407 break;
408 case R128_PM4_128PIO_64INDBM:
409 case R128_PM4_128BM_64INDBM:
410 dev_priv->cce_fifo_size = 128;
411 break;
412 case R128_PM4_64PIO_128INDBM:
413 case R128_PM4_64BM_128INDBM:
414 case R128_PM4_64PIO_64VCBM_64INDBM:
415 case R128_PM4_64BM_64VCBM_64INDBM:
416 case R128_PM4_64PIO_64VCPIO_64INDPIO:
417 dev_priv->cce_fifo_size = 64;
418 break;
419 }
420
421 switch (init->fb_bpp) {
422 case 16:
423 dev_priv->color_fmt = R128_DATATYPE_RGB565;
424 break;
425 case 32:
426 default:
427 dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
428 break;
429 }
430 dev_priv->front_offset = init->front_offset;
431 dev_priv->front_pitch = init->front_pitch;
432 dev_priv->back_offset = init->back_offset;
433 dev_priv->back_pitch = init->back_pitch;
434
435 switch (init->depth_bpp) {
436 case 16:
437 dev_priv->depth_fmt = R128_DATATYPE_RGB565;
438 break;
439 case 24:
440 case 32:
441 default:
442 dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
443 break;
444 }
445 dev_priv->depth_offset = init->depth_offset;
446 dev_priv->depth_pitch = init->depth_pitch;
447 dev_priv->span_offset = init->span_offset;
448
449 dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) |
450 (dev_priv->front_offset >> 5));
451 dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) |
452 (dev_priv->back_offset >> 5));
453 dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
454 (dev_priv->depth_offset >> 5) |
455 R128_DST_TILE);
456 dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
457 (dev_priv->span_offset >> 5));
458
459 dev_priv->sarea = drm_getsarea(dev);
460 if (!dev_priv->sarea) {
461 DRM_ERROR("could not find sarea!\n");
462 dev->dev_private = (void *)dev_priv;
463 r128_do_cleanup_cce(dev);
464 return -EINVAL;
465 }
466
467 dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
468 if (!dev_priv->mmio) {
469 DRM_ERROR("could not find mmio region!\n");
470 dev->dev_private = (void *)dev_priv;
471 r128_do_cleanup_cce(dev);
472 return -EINVAL;
473 }
474 dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
475 if (!dev_priv->cce_ring) {
476 DRM_ERROR("could not find cce ring region!\n");
477 dev->dev_private = (void *)dev_priv;
478 r128_do_cleanup_cce(dev);
479 return -EINVAL;
480 }
481 dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
482 if (!dev_priv->ring_rptr) {
483 DRM_ERROR("could not find ring read pointer!\n");
484 dev->dev_private = (void *)dev_priv;
485 r128_do_cleanup_cce(dev);
486 return -EINVAL;
487 }
488 dev->agp_buffer_token = init->buffers_offset;
489 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
490 if (!dev->agp_buffer_map) {
491 DRM_ERROR("could not find dma buffer region!\n");
492 dev->dev_private = (void *)dev_priv;
493 r128_do_cleanup_cce(dev);
494 return -EINVAL;
495 }
496
497 if (!dev_priv->is_pci) {
498 dev_priv->agp_textures =
499 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 -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 -ENOMEM;
524 }
525 } else
526#endif
527 {
528 dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset;
529 dev_priv->ring_rptr->handle =
530 (void *)dev_priv->ring_rptr->offset;
531 dev->agp_buffer_map->handle =
532 (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 = (unsigned long)dev->sg->virtual;
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 = (dev_priv->ring.size / sizeof(u32)) - 1;
549
550 dev_priv->ring.high_mark = 128;
551
552 dev_priv->sarea_priv->last_frame = 0;
553 R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
554
555 dev_priv->sarea_priv->last_dispatch = 0;
556 R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch);
557
558#if __OS_HAS_AGP
559 if (dev_priv->is_pci) {
560#endif
561 dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
562 dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
563 dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
564 dev_priv->gart_info.addr = NULL;
565 dev_priv->gart_info.bus_addr = 0;
566 dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
567 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
568 DRM_ERROR("failed to init PCI GART!\n");
569 dev->dev_private = (void *)dev_priv;
570 r128_do_cleanup_cce(dev);
571 return -ENOMEM;
572 }
573 R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
574#if __OS_HAS_AGP
575 }
576#endif
577
578 r128_cce_init_ring_buffer(dev, dev_priv);
579 r128_cce_load_microcode(dev_priv);
580
581 dev->dev_private = (void *)dev_priv;
582
583 r128_do_engine_reset(dev);
584
585 return 0;
586}
587
588int r128_do_cleanup_cce(struct drm_device * dev)
589{
590
591 /* Make sure interrupts are disabled here because the uninstall ioctl
592 * may not have been called from userspace and after dev_private
593 * is freed, it's too late.
594 */
595 if (dev->irq_enabled)
596 drm_irq_uninstall(dev);
597
598 if (dev->dev_private) {
599 drm_r128_private_t *dev_priv = dev->dev_private;
600
601#if __OS_HAS_AGP
602 if (!dev_priv->is_pci) {
603 if (dev_priv->cce_ring != NULL)
604 drm_core_ioremapfree(dev_priv->cce_ring, dev);
605 if (dev_priv->ring_rptr != NULL)
606 drm_core_ioremapfree(dev_priv->ring_rptr, dev);
607 if (dev->agp_buffer_map != NULL) {
608 drm_core_ioremapfree(dev->agp_buffer_map, dev);
609 dev->agp_buffer_map = NULL;
610 }
611 } else
612#endif
613 {
614 if (dev_priv->gart_info.bus_addr)
615 if (!drm_ati_pcigart_cleanup(dev,
616 &dev_priv->gart_info))
617 DRM_ERROR
618 ("failed to cleanup PCI GART!\n");
619 }
620
621 drm_free(dev->dev_private, sizeof(drm_r128_private_t),
622 DRM_MEM_DRIVER);
623 dev->dev_private = NULL;
624 }
625
626 return 0;
627}
628
629int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
630{
631 drm_r128_init_t *init = data;
632
633 DRM_DEBUG("\n");
634
635 LOCK_TEST_WITH_RETURN(dev, file_priv);
636
637 switch (init->func) {
638 case R128_INIT_CCE:
639 return r128_do_init_cce(dev, init);
640 case R128_CLEANUP_CCE:
641 return r128_do_cleanup_cce(dev);
642 }
643
644 return -EINVAL;
645}
646
647int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
648{
649 drm_r128_private_t *dev_priv = dev->dev_private;
650 DRM_DEBUG("\n");
651
652 LOCK_TEST_WITH_RETURN(dev, file_priv);
653
654 if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
655 DRM_DEBUG("while CCE running\n");
656 return 0;
657 }
658
659 r128_do_cce_start(dev_priv);
660
661 return 0;
662}
663
664/* Stop the CCE. The engine must have been idled before calling this
665 * routine.
666 */
667int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv)
668{
669 drm_r128_private_t *dev_priv = dev->dev_private;
670 drm_r128_cce_stop_t *stop = data;
671 int ret;
672 DRM_DEBUG("\n");
673
674 LOCK_TEST_WITH_RETURN(dev, file_priv);
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)
689 return ret;
690 }
691
692 /* Finally, we can turn off the CCE. If the engine isn't idle,
693 * we will get some dropped triangles as they won't be fully
694 * rendered before the CCE is shut down.
695 */
696 r128_do_cce_stop(dev_priv);
697
698 /* Reset the engine */
699 r128_do_engine_reset(dev);
700
701 return 0;
702}
703
704/* Just reset the CCE ring. Called as part of an X Server engine reset.
705 */
706int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
707{
708 drm_r128_private_t *dev_priv = dev->dev_private;
709 DRM_DEBUG("\n");
710
711 LOCK_TEST_WITH_RETURN(dev, file_priv);
712
713 if (!dev_priv) {
714 DRM_DEBUG("called before init done\n");
715 return -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(struct drm_device *dev, void *data, struct drm_file *file_priv)
727{
728 drm_r128_private_t *dev_priv = dev->dev_private;
729 DRM_DEBUG("\n");
730
731 LOCK_TEST_WITH_RETURN(dev, file_priv);
732
733 if (dev_priv->cce_running) {
734 r128_do_cce_flush(dev_priv);
735 }
736
737 return r128_do_cce_idle(dev_priv);
738}
739
740int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
741{
742 DRM_DEBUG("\n");
743
744 LOCK_TEST_WITH_RETURN(dev, file_priv);
745
746 return r128_do_engine_reset(dev);
747}
748
749int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv)
750{
751 return -EINVAL;
752}
753
754/* ================================================================
755 * Freelist management
756 */
757#define R128_BUFFER_USED 0xffffffff
758#define R128_BUFFER_FREE 0
759
760#if 0
761static int r128_freelist_init(struct drm_device * dev)
762{
763 struct drm_device_dma *dma = dev->dma;
764 drm_r128_private_t *dev_priv = dev->dev_private;
765 struct drm_buf *buf;
766 drm_r128_buf_priv_t *buf_priv;
767 drm_r128_freelist_t *entry;
768 int i;
769
770 dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
771 if (dev_priv->head == NULL)
772 return -ENOMEM;
773
774 memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t));
775 dev_priv->head->age = R128_BUFFER_USED;
776
777 for (i = 0; i < dma->buf_count; i++) {
778 buf = dma->buflist[i];
779 buf_priv = buf->dev_private;
780
781 entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
782 if (!entry)
783 return -ENOMEM;
784
785 entry->age = R128_BUFFER_FREE;
786 entry->buf = buf;
787 entry->prev = dev_priv->head;
788 entry->next = dev_priv->head->next;
789 if (!entry->next)
790 dev_priv->tail = entry;
791
792 buf_priv->discard = 0;
793 buf_priv->dispatched = 0;
794 buf_priv->list_entry = entry;
795
796 dev_priv->head->next = entry;
797
798 if (dev_priv->head->next)
799 dev_priv->head->next->prev = entry;
800 }
801
802 return 0;
803
804}
805#endif
806
807static struct drm_buf *r128_freelist_get(struct drm_device * dev)
808{
809 struct drm_device_dma *dma = dev->dma;
810 drm_r128_private_t *dev_priv = dev->dev_private;
811 drm_r128_buf_priv_t *buf_priv;
812 struct drm_buf *buf;
813 int i, t;
814
815 /* FIXME: Optimize -- use freelist code */
816
817 for (i = 0; i < dma->buf_count; i++) {
818 buf = dma->buflist[i];
819 buf_priv = buf->dev_private;
820 if (!buf->file_priv)
821 return buf;
822 }
823
824 for (t = 0; t < dev_priv->usec_timeout; t++) {
825 u32 done_age = R128_READ(R128_LAST_DISPATCH_REG);
826
827 for (i = 0; i < dma->buf_count; i++) {
828 buf = dma->buflist[i];
829 buf_priv = buf->dev_private;
830 if (buf->pending && buf_priv->age <= done_age) {
831 /* The buffer has been processed, so it
832 * can now be used.
833 */
834 buf->pending = 0;
835 return buf;
836 }
837 }
838 DRM_UDELAY(1);
839 }
840
841 DRM_DEBUG("returning NULL!\n");
842 return NULL;
843}
844
845void r128_freelist_reset(struct drm_device * dev)
846{
847 struct drm_device_dma *dma = dev->dma;
848 int i;
849
850 for (i = 0; i < dma->buf_count; i++) {
851 struct drm_buf *buf = dma->buflist[i];
852 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
853 buf_priv->age = 0;
854 }
855}
856
857/* ================================================================
858 * CCE command submission
859 */
860
861int r128_wait_ring(drm_r128_private_t * dev_priv, int n)
862{
863 drm_r128_ring_buffer_t *ring = &dev_priv->ring;
864 int i;
865
866 for (i = 0; i < dev_priv->usec_timeout; i++) {
867 r128_update_ring_snapshot(dev_priv);
868 if (ring->space >= n)
869 return 0;
870 DRM_UDELAY(1);
871 }
872
873 /* FIXME: This is being ignored... */
874 DRM_ERROR("failed!\n");
875 return -EBUSY;
876}
877
878static int r128_cce_get_buffers(struct drm_device * dev,
879 struct drm_file *file_priv,
880 struct drm_dma * d)
881{
882 int i;
883 struct drm_buf *buf;
884
885 for (i = d->granted_count; i < d->request_count; i++) {
886 buf = r128_freelist_get(dev);
887 if (!buf)
888 return -EAGAIN;
889
890 buf->file_priv = file_priv;
891
892 if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
893 sizeof(buf->idx)))
894 return -EFAULT;
895 if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
896 sizeof(buf->total)))
897 return -EFAULT;
898
899 d->granted_count++;
900 }
901 return 0;
902}
903
904int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
905{
906 struct drm_device_dma *dma = dev->dma;
907 int ret = 0;
908 struct drm_dma *d = data;
909
910 LOCK_TEST_WITH_RETURN(dev, file_priv);
911
912 /* Please don't send us buffers.
913 */
914 if (d->send_count != 0) {
915 DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
916 DRM_CURRENTPID, d->send_count);
917 return -EINVAL;
918 }
919
920 /* We'll send you buffers.
921 */
922 if (d->request_count < 0 || d->request_count > dma->buf_count) {
923 DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
924 DRM_CURRENTPID, d->request_count, dma->buf_count);
925 return -EINVAL;
926 }
927
928 d->granted_count = 0;
929
930 if (d->request_count) {
931 ret = r128_cce_get_buffers(dev, file_priv, d);
932 }
933
934 return ret;
935}
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
new file mode 100644
index 000000000000..6108e7587e12
--- /dev/null
+++ b/drivers/gpu/drm/r128/r128_drv.c
@@ -0,0 +1,103 @@
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 "drmP.h"
33#include "drm.h"
34#include "r128_drm.h"
35#include "r128_drv.h"
36
37#include "drm_pciids.h"
38
39static struct pci_device_id pciidlist[] = {
40 r128_PCI_IDS
41};
42
43static struct drm_driver driver = {
44 .driver_features =
45 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
46 DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
47 DRIVER_IRQ_VBL,
48 .dev_priv_size = sizeof(drm_r128_buf_priv_t),
49 .preclose = r128_driver_preclose,
50 .lastclose = r128_driver_lastclose,
51 .vblank_wait = r128_driver_vblank_wait,
52 .irq_preinstall = r128_driver_irq_preinstall,
53 .irq_postinstall = r128_driver_irq_postinstall,
54 .irq_uninstall = r128_driver_irq_uninstall,
55 .irq_handler = r128_driver_irq_handler,
56 .reclaim_buffers = drm_core_reclaim_buffers,
57 .get_map_ofs = drm_core_get_map_ofs,
58 .get_reg_ofs = drm_core_get_reg_ofs,
59 .ioctls = r128_ioctls,
60 .dma_ioctl = r128_cce_buffers,
61 .fops = {
62 .owner = THIS_MODULE,
63 .open = drm_open,
64 .release = drm_release,
65 .ioctl = drm_ioctl,
66 .mmap = drm_mmap,
67 .poll = drm_poll,
68 .fasync = drm_fasync,
69#ifdef CONFIG_COMPAT
70 .compat_ioctl = r128_compat_ioctl,
71#endif
72 },
73
74 .pci_driver = {
75 .name = DRIVER_NAME,
76 .id_table = pciidlist,
77 },
78
79 .name = DRIVER_NAME,
80 .desc = DRIVER_DESC,
81 .date = DRIVER_DATE,
82 .major = DRIVER_MAJOR,
83 .minor = DRIVER_MINOR,
84 .patchlevel = DRIVER_PATCHLEVEL,
85};
86
87static int __init r128_init(void)
88{
89 driver.num_ioctls = r128_max_ioctl;
90 return drm_init(&driver);
91}
92
93static void __exit r128_exit(void)
94{
95 drm_exit(&driver);
96}
97
98module_init(r128_init);
99module_exit(r128_exit);
100
101MODULE_AUTHOR(DRIVER_AUTHOR);
102MODULE_DESCRIPTION(DRIVER_DESC);
103MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
new file mode 100644
index 000000000000..011105e51ac6
--- /dev/null
+++ b/drivers/gpu/drm/r128/r128_drv.h
@@ -0,0 +1,522 @@
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/*
5 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
6 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
7 * All rights reserved.
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 * Rickard E. (Rik) Faith <faith@valinux.com>
30 * Kevin E. Martin <martin@valinux.com>
31 * Gareth Hughes <gareth@valinux.com>
32 * Michel Dänzer <daenzerm@student.ethz.ch>
33 */
34
35#ifndef __R128_DRV_H__
36#define __R128_DRV_H__
37
38/* General customization:
39 */
40#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
41
42#define DRIVER_NAME "r128"
43#define DRIVER_DESC "ATI Rage 128"
44#define DRIVER_DATE "20030725"
45
46/* Interface history:
47 *
48 * ?? - ??
49 * 2.4 - Add support for ycbcr textures (no new ioctls)
50 * 2.5 - Add FLIP ioctl, disable FULLSCREEN.
51 */
52#define DRIVER_MAJOR 2
53#define DRIVER_MINOR 5
54#define DRIVER_PATCHLEVEL 0
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 struct drm_buf *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 cce_buffers_offset;
92
93 atomic_t idle_count;
94
95 int page_flipping;
96 int current_page;
97 u32 crtc_offset;
98 u32 crtc_offset_cntl;
99
100 u32 color_fmt;
101 unsigned int front_offset;
102 unsigned int front_pitch;
103 unsigned int back_offset;
104 unsigned int back_pitch;
105
106 u32 depth_fmt;
107 unsigned int depth_offset;
108 unsigned int depth_pitch;
109 unsigned int span_offset;
110
111 u32 front_pitch_offset_c;
112 u32 back_pitch_offset_c;
113 u32 depth_pitch_offset_c;
114 u32 span_pitch_offset_c;
115
116 drm_local_map_t *sarea;
117 drm_local_map_t *mmio;
118 drm_local_map_t *cce_ring;
119 drm_local_map_t *ring_rptr;
120 drm_local_map_t *agp_textures;
121 struct drm_ati_pcigart_info gart_info;
122} drm_r128_private_t;
123
124typedef struct drm_r128_buf_priv {
125 u32 age;
126 int prim;
127 int discard;
128 int dispatched;
129 drm_r128_freelist_t *list_entry;
130} drm_r128_buf_priv_t;
131
132extern struct drm_ioctl_desc r128_ioctls[];
133extern int r128_max_ioctl;
134
135 /* r128_cce.c */
136extern int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
137extern int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv);
138extern int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv);
139extern int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
140extern int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv);
141extern int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
142extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv);
143extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
144
145extern void r128_freelist_reset(struct drm_device * dev);
146
147extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
148
149extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
150extern int r128_do_cleanup_cce(struct drm_device * dev);
151
152extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
153
154extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
155extern void r128_driver_irq_preinstall(struct drm_device * dev);
156extern void r128_driver_irq_postinstall(struct drm_device * dev);
157extern void r128_driver_irq_uninstall(struct drm_device * dev);
158extern void r128_driver_lastclose(struct drm_device * dev);
159extern void r128_driver_preclose(struct drm_device * dev,
160 struct drm_file *file_priv);
161
162extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
163 unsigned long arg);
164
165/* Register definitions, register access macros and drmAddMap constants
166 * for Rage 128 kernel driver.
167 */
168
169#define R128_AUX_SC_CNTL 0x1660
170# define R128_AUX1_SC_EN (1 << 0)
171# define R128_AUX1_SC_MODE_OR (0 << 1)
172# define R128_AUX1_SC_MODE_NAND (1 << 1)
173# define R128_AUX2_SC_EN (1 << 2)
174# define R128_AUX2_SC_MODE_OR (0 << 3)
175# define R128_AUX2_SC_MODE_NAND (1 << 3)
176# define R128_AUX3_SC_EN (1 << 4)
177# define R128_AUX3_SC_MODE_OR (0 << 5)
178# define R128_AUX3_SC_MODE_NAND (1 << 5)
179#define R128_AUX1_SC_LEFT 0x1664
180#define R128_AUX1_SC_RIGHT 0x1668
181#define R128_AUX1_SC_TOP 0x166c
182#define R128_AUX1_SC_BOTTOM 0x1670
183#define R128_AUX2_SC_LEFT 0x1674
184#define R128_AUX2_SC_RIGHT 0x1678
185#define R128_AUX2_SC_TOP 0x167c
186#define R128_AUX2_SC_BOTTOM 0x1680
187#define R128_AUX3_SC_LEFT 0x1684
188#define R128_AUX3_SC_RIGHT 0x1688
189#define R128_AUX3_SC_TOP 0x168c
190#define R128_AUX3_SC_BOTTOM 0x1690
191
192#define R128_BRUSH_DATA0 0x1480
193#define R128_BUS_CNTL 0x0030
194# define R128_BUS_MASTER_DIS (1 << 6)
195
196#define R128_CLOCK_CNTL_INDEX 0x0008
197#define R128_CLOCK_CNTL_DATA 0x000c
198# define R128_PLL_WR_EN (1 << 7)
199#define R128_CONSTANT_COLOR_C 0x1d34
200#define R128_CRTC_OFFSET 0x0224
201#define R128_CRTC_OFFSET_CNTL 0x0228
202# define R128_CRTC_OFFSET_FLIP_CNTL (1 << 16)
203
204#define R128_DP_GUI_MASTER_CNTL 0x146c
205# define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
206# define R128_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
207# define R128_GMC_BRUSH_SOLID_COLOR (13 << 4)
208# define R128_GMC_BRUSH_NONE (15 << 4)
209# define R128_GMC_DST_16BPP (4 << 8)
210# define R128_GMC_DST_24BPP (5 << 8)
211# define R128_GMC_DST_32BPP (6 << 8)
212# define R128_GMC_DST_DATATYPE_SHIFT 8
213# define R128_GMC_SRC_DATATYPE_COLOR (3 << 12)
214# define R128_DP_SRC_SOURCE_MEMORY (2 << 24)
215# define R128_DP_SRC_SOURCE_HOST_DATA (3 << 24)
216# define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28)
217# define R128_GMC_AUX_CLIP_DIS (1 << 29)
218# define R128_GMC_WR_MSK_DIS (1 << 30)
219# define R128_ROP3_S 0x00cc0000
220# define R128_ROP3_P 0x00f00000
221#define R128_DP_WRITE_MASK 0x16cc
222#define R128_DST_PITCH_OFFSET_C 0x1c80
223# define R128_DST_TILE (1 << 31)
224
225#define R128_GEN_INT_CNTL 0x0040
226# define R128_CRTC_VBLANK_INT_EN (1 << 0)
227#define R128_GEN_INT_STATUS 0x0044
228# define R128_CRTC_VBLANK_INT (1 << 0)
229# define R128_CRTC_VBLANK_INT_AK (1 << 0)
230#define R128_GEN_RESET_CNTL 0x00f0
231# define R128_SOFT_RESET_GUI (1 << 0)
232
233#define R128_GUI_SCRATCH_REG0 0x15e0
234#define R128_GUI_SCRATCH_REG1 0x15e4
235#define R128_GUI_SCRATCH_REG2 0x15e8
236#define R128_GUI_SCRATCH_REG3 0x15ec
237#define R128_GUI_SCRATCH_REG4 0x15f0
238#define R128_GUI_SCRATCH_REG5 0x15f4
239
240#define R128_GUI_STAT 0x1740
241# define R128_GUI_FIFOCNT_MASK 0x0fff
242# define R128_GUI_ACTIVE (1 << 31)
243
244#define R128_MCLK_CNTL 0x000f
245# define R128_FORCE_GCP (1 << 16)
246# define R128_FORCE_PIPE3D_CP (1 << 17)
247# define R128_FORCE_RCP (1 << 18)
248
249#define R128_PC_GUI_CTLSTAT 0x1748
250#define R128_PC_NGUI_CTLSTAT 0x0184
251# define R128_PC_FLUSH_GUI (3 << 0)
252# define R128_PC_RI_GUI (1 << 2)
253# define R128_PC_FLUSH_ALL 0x00ff
254# define R128_PC_BUSY (1 << 31)
255
256#define R128_PCI_GART_PAGE 0x017c
257#define R128_PRIM_TEX_CNTL_C 0x1cb0
258
259#define R128_SCALE_3D_CNTL 0x1a00
260#define R128_SEC_TEX_CNTL_C 0x1d00
261#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c
262#define R128_SETUP_CNTL 0x1bc4
263#define R128_STEN_REF_MASK_C 0x1d40
264
265#define R128_TEX_CNTL_C 0x1c9c
266# define R128_TEX_CACHE_FLUSH (1 << 23)
267
268#define R128_WAIT_UNTIL 0x1720
269# define R128_EVENT_CRTC_OFFSET (1 << 0)
270#define R128_WINDOW_XY_OFFSET 0x1bcc
271
272/* CCE registers
273 */
274#define R128_PM4_BUFFER_OFFSET 0x0700
275#define R128_PM4_BUFFER_CNTL 0x0704
276# define R128_PM4_MASK (15 << 28)
277# define R128_PM4_NONPM4 (0 << 28)
278# define R128_PM4_192PIO (1 << 28)
279# define R128_PM4_192BM (2 << 28)
280# define R128_PM4_128PIO_64INDBM (3 << 28)
281# define R128_PM4_128BM_64INDBM (4 << 28)
282# define R128_PM4_64PIO_128INDBM (5 << 28)
283# define R128_PM4_64BM_128INDBM (6 << 28)
284# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28)
285# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28)
286# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
287# define R128_PM4_BUFFER_CNTL_NOUPDATE (1 << 27)
288
289#define R128_PM4_BUFFER_WM_CNTL 0x0708
290# define R128_WMA_SHIFT 0
291# define R128_WMB_SHIFT 8
292# define R128_WMC_SHIFT 16
293# define R128_WB_WM_SHIFT 24
294
295#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c
296#define R128_PM4_BUFFER_DL_RPTR 0x0710
297#define R128_PM4_BUFFER_DL_WPTR 0x0714
298# define R128_PM4_BUFFER_DL_DONE (1 << 31)
299
300#define R128_PM4_VC_FPU_SETUP 0x071c
301
302#define R128_PM4_IW_INDOFF 0x0738
303#define R128_PM4_IW_INDSIZE 0x073c
304
305#define R128_PM4_STAT 0x07b8
306# define R128_PM4_FIFOCNT_MASK 0x0fff
307# define R128_PM4_BUSY (1 << 16)
308# define R128_PM4_GUI_ACTIVE (1 << 31)
309
310#define R128_PM4_MICROCODE_ADDR 0x07d4
311#define R128_PM4_MICROCODE_RADDR 0x07d8
312#define R128_PM4_MICROCODE_DATAH 0x07dc
313#define R128_PM4_MICROCODE_DATAL 0x07e0
314
315#define R128_PM4_BUFFER_ADDR 0x07f0
316#define R128_PM4_MICRO_CNTL 0x07fc
317# define R128_PM4_MICRO_FREERUN (1 << 30)
318
319#define R128_PM4_FIFO_DATA_EVEN 0x1000
320#define R128_PM4_FIFO_DATA_ODD 0x1004
321
322/* CCE command packets
323 */
324#define R128_CCE_PACKET0 0x00000000
325#define R128_CCE_PACKET1 0x40000000
326#define R128_CCE_PACKET2 0x80000000
327#define R128_CCE_PACKET3 0xC0000000
328# define R128_CNTL_HOSTDATA_BLT 0x00009400
329# define R128_CNTL_PAINT_MULTI 0x00009A00
330# define R128_CNTL_BITBLT_MULTI 0x00009B00
331# define R128_3D_RNDR_GEN_INDX_PRIM 0x00002300
332
333#define R128_CCE_PACKET_MASK 0xC0000000
334#define R128_CCE_PACKET_COUNT_MASK 0x3fff0000
335#define R128_CCE_PACKET0_REG_MASK 0x000007ff
336#define R128_CCE_PACKET1_REG0_MASK 0x000007ff
337#define R128_CCE_PACKET1_REG1_MASK 0x003ff800
338
339#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000
340#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001
341#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002
342#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003
343#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004
344#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005
345#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006
346#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007
347#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010
348#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020
349#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030
350#define R128_CCE_VC_CNTL_NUM_SHIFT 16
351
352#define R128_DATATYPE_VQ 0
353#define R128_DATATYPE_CI4 1
354#define R128_DATATYPE_CI8 2
355#define R128_DATATYPE_ARGB1555 3
356#define R128_DATATYPE_RGB565 4
357#define R128_DATATYPE_RGB888 5
358#define R128_DATATYPE_ARGB8888 6
359#define R128_DATATYPE_RGB332 7
360#define R128_DATATYPE_Y8 8
361#define R128_DATATYPE_RGB8 9
362#define R128_DATATYPE_CI16 10
363#define R128_DATATYPE_YVYU422 11
364#define R128_DATATYPE_VYUY422 12
365#define R128_DATATYPE_AYUV444 14
366#define R128_DATATYPE_ARGB4444 15
367
368/* Constants */
369#define R128_AGP_OFFSET 0x02000000
370
371#define R128_WATERMARK_L 16
372#define R128_WATERMARK_M 8
373#define R128_WATERMARK_N 8
374#define R128_WATERMARK_K 128
375
376#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */
377
378#define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0
379#define R128_LAST_DISPATCH_REG R128_GUI_SCRATCH_REG1
380#define R128_MAX_VB_AGE 0x7fffffff
381#define R128_MAX_VB_VERTS (0xffff)
382
383#define R128_RING_HIGH_MARK 128
384
385#define R128_PERFORMANCE_BOXES 0
386
387#define R128_PCIGART_TABLE_SIZE 32768
388
389#define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
390#define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
391#define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) )
392#define R128_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) )
393
394#define R128_WRITE_PLL(addr,val) \
395do { \
396 R128_WRITE8(R128_CLOCK_CNTL_INDEX, \
397 ((addr) & 0x1f) | R128_PLL_WR_EN); \
398 R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \
399} while (0)
400
401#define CCE_PACKET0( reg, n ) (R128_CCE_PACKET0 | \
402 ((n) << 16) | ((reg) >> 2))
403#define CCE_PACKET1( reg0, reg1 ) (R128_CCE_PACKET1 | \
404 (((reg1) >> 2) << 11) | ((reg0) >> 2))
405#define CCE_PACKET2() (R128_CCE_PACKET2)
406#define CCE_PACKET3( pkt, n ) (R128_CCE_PACKET3 | \
407 (pkt) | ((n) << 16))
408
409static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv)
410{
411 drm_r128_ring_buffer_t *ring = &dev_priv->ring;
412 ring->space = (GET_RING_HEAD(dev_priv) - ring->tail) * sizeof(u32);
413 if (ring->space <= 0)
414 ring->space += ring->size;
415}
416
417/* ================================================================
418 * Misc helper macros
419 */
420
421#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
422do { \
423 drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \
424 if ( ring->space < ring->high_mark ) { \
425 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { \
426 r128_update_ring_snapshot( dev_priv ); \
427 if ( ring->space >= ring->high_mark ) \
428 goto __ring_space_done; \
429 DRM_UDELAY(1); \
430 } \
431 DRM_ERROR( "ring space check failed!\n" ); \
432 return -EBUSY; \
433 } \
434 __ring_space_done: \
435 ; \
436} while (0)
437
438#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \
439do { \
440 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; \
441 if ( sarea_priv->last_dispatch >= R128_MAX_VB_AGE ) { \
442 int __ret = r128_do_cce_idle( dev_priv ); \
443 if ( __ret ) return __ret; \
444 sarea_priv->last_dispatch = 0; \
445 r128_freelist_reset( dev ); \
446 } \
447} while (0)
448
449#define R128_WAIT_UNTIL_PAGE_FLIPPED() do { \
450 OUT_RING( CCE_PACKET0( R128_WAIT_UNTIL, 0 ) ); \
451 OUT_RING( R128_EVENT_CRTC_OFFSET ); \
452} while (0)
453
454/* ================================================================
455 * Ring control
456 */
457
458#define R128_VERBOSE 0
459
460#define RING_LOCALS \
461 int write, _nr; unsigned int tail_mask; volatile u32 *ring;
462
463#define BEGIN_RING( n ) do { \
464 if ( R128_VERBOSE ) { \
465 DRM_INFO( "BEGIN_RING( %d )\n", (n)); \
466 } \
467 if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
468 COMMIT_RING(); \
469 r128_wait_ring( dev_priv, (n) * sizeof(u32) ); \
470 } \
471 _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \
472 ring = dev_priv->ring.start; \
473 write = dev_priv->ring.tail; \
474 tail_mask = dev_priv->ring.tail_mask; \
475} while (0)
476
477/* You can set this to zero if you want. If the card locks up, you'll
478 * need to keep this set. It works around a bug in early revs of the
479 * Rage 128 chipset, where the CCE would read 32 dwords past the end of
480 * the ring buffer before wrapping around.
481 */
482#define R128_BROKEN_CCE 1
483
484#define ADVANCE_RING() do { \
485 if ( R128_VERBOSE ) { \
486 DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \
487 write, dev_priv->ring.tail ); \
488 } \
489 if ( R128_BROKEN_CCE && write < 32 ) { \
490 memcpy( dev_priv->ring.end, \
491 dev_priv->ring.start, \
492 write * sizeof(u32) ); \
493 } \
494 if (((dev_priv->ring.tail + _nr) & tail_mask) != write) { \
495 DRM_ERROR( \
496 "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \
497 ((dev_priv->ring.tail + _nr) & tail_mask), \
498 write, __LINE__); \
499 } else \
500 dev_priv->ring.tail = write; \
501} while (0)
502
503#define COMMIT_RING() do { \
504 if ( R128_VERBOSE ) { \
505 DRM_INFO( "COMMIT_RING() tail=0x%06x\n", \
506 dev_priv->ring.tail ); \
507 } \
508 DRM_MEMORYBARRIER(); \
509 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail ); \
510 R128_READ( R128_PM4_BUFFER_DL_WPTR ); \
511} while (0)
512
513#define OUT_RING( x ) do { \
514 if ( R128_VERBOSE ) { \
515 DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \
516 (unsigned int)(x), write ); \
517 } \
518 ring[write++] = cpu_to_le32( x ); \
519 write &= tail_mask; \
520} while (0)
521
522#endif /* __R128_DRV_H__ */
diff --git a/drivers/gpu/drm/r128/r128_ioc32.c b/drivers/gpu/drm/r128/r128_ioc32.c
new file mode 100644
index 000000000000..d3cb676eee84
--- /dev/null
+++ b/drivers/gpu/drm/r128/r128_ioc32.c
@@ -0,0 +1,221 @@
1/**
2 * \file r128_ioc32.c
3 *
4 * 32-bit ioctl compatibility routines for the R128 DRM.
5 *
6 * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
7 *
8 * Copyright (C) Paul Mackerras 2005
9 * Copyright (C) Egbert Eich 2003,2004
10 * Copyright (C) Dave Airlie 2005
11 * All Rights Reserved.
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice (including the next
21 * paragraph) shall be included in all copies or substantial portions of the
22 * Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30 * IN THE SOFTWARE.
31 */
32#include <linux/compat.h>
33
34#include "drmP.h"
35#include "drm.h"
36#include "r128_drm.h"
37
38typedef struct drm_r128_init32 {
39 int func;
40 unsigned int sarea_priv_offset;
41 int is_pci;
42 int cce_mode;
43 int cce_secure;
44 int ring_size;
45 int usec_timeout;
46
47 unsigned int fb_bpp;
48 unsigned int front_offset, front_pitch;
49 unsigned int back_offset, back_pitch;
50 unsigned int depth_bpp;
51 unsigned int depth_offset, depth_pitch;
52 unsigned int span_offset;
53
54 unsigned int fb_offset;
55 unsigned int mmio_offset;
56 unsigned int ring_offset;
57 unsigned int ring_rptr_offset;
58 unsigned int buffers_offset;
59 unsigned int agp_textures_offset;
60} drm_r128_init32_t;
61
62static int compat_r128_init(struct file *file, unsigned int cmd,
63 unsigned long arg)
64{
65 drm_r128_init32_t init32;
66 drm_r128_init_t __user *init;
67
68 if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
69 return -EFAULT;
70
71 init = compat_alloc_user_space(sizeof(*init));
72 if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
73 || __put_user(init32.func, &init->func)
74 || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
75 || __put_user(init32.is_pci, &init->is_pci)
76 || __put_user(init32.cce_mode, &init->cce_mode)
77 || __put_user(init32.cce_secure, &init->cce_secure)
78 || __put_user(init32.ring_size, &init->ring_size)
79 || __put_user(init32.usec_timeout, &init->usec_timeout)
80 || __put_user(init32.fb_bpp, &init->fb_bpp)
81 || __put_user(init32.front_offset, &init->front_offset)
82 || __put_user(init32.front_pitch, &init->front_pitch)
83 || __put_user(init32.back_offset, &init->back_offset)
84 || __put_user(init32.back_pitch, &init->back_pitch)
85 || __put_user(init32.depth_bpp, &init->depth_bpp)
86 || __put_user(init32.depth_offset, &init->depth_offset)
87 || __put_user(init32.depth_pitch, &init->depth_pitch)
88 || __put_user(init32.span_offset, &init->span_offset)
89 || __put_user(init32.fb_offset, &init->fb_offset)
90 || __put_user(init32.mmio_offset, &init->mmio_offset)
91 || __put_user(init32.ring_offset, &init->ring_offset)
92 || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
93 || __put_user(init32.buffers_offset, &init->buffers_offset)
94 || __put_user(init32.agp_textures_offset,
95 &init->agp_textures_offset))
96 return -EFAULT;
97
98 return drm_ioctl(file->f_path.dentry->d_inode, file,
99 DRM_IOCTL_R128_INIT, (unsigned long)init);
100}
101
102typedef struct drm_r128_depth32 {
103 int func;
104 int n;
105 u32 x;
106 u32 y;
107 u32 buffer;
108 u32 mask;
109} drm_r128_depth32_t;
110
111static int compat_r128_depth(struct file *file, unsigned int cmd,
112 unsigned long arg)
113{
114 drm_r128_depth32_t depth32;
115 drm_r128_depth_t __user *depth;
116
117 if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32)))
118 return -EFAULT;
119
120 depth = compat_alloc_user_space(sizeof(*depth));
121 if (!access_ok(VERIFY_WRITE, depth, sizeof(*depth))
122 || __put_user(depth32.func, &depth->func)
123 || __put_user(depth32.n, &depth->n)
124 || __put_user((int __user *)(unsigned long)depth32.x, &depth->x)
125 || __put_user((int __user *)(unsigned long)depth32.y, &depth->y)
126 || __put_user((unsigned int __user *)(unsigned long)depth32.buffer,
127 &depth->buffer)
128 || __put_user((unsigned char __user *)(unsigned long)depth32.mask,
129 &depth->mask))
130 return -EFAULT;
131
132 return drm_ioctl(file->f_path.dentry->d_inode, file,
133 DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
134
135}
136
137typedef struct drm_r128_stipple32 {
138 u32 mask;
139} drm_r128_stipple32_t;
140
141static int compat_r128_stipple(struct file *file, unsigned int cmd,
142 unsigned long arg)
143{
144 drm_r128_stipple32_t stipple32;
145 drm_r128_stipple_t __user *stipple;
146
147 if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32)))
148 return -EFAULT;
149
150 stipple = compat_alloc_user_space(sizeof(*stipple));
151 if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple))
152 || __put_user((unsigned int __user *)(unsigned long)stipple32.mask,
153 &stipple->mask))
154 return -EFAULT;
155
156 return drm_ioctl(file->f_path.dentry->d_inode, file,
157 DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
158}
159
160typedef struct drm_r128_getparam32 {
161 int param;
162 u32 value;
163} drm_r128_getparam32_t;
164
165static int compat_r128_getparam(struct file *file, unsigned int cmd,
166 unsigned long arg)
167{
168 drm_r128_getparam32_t getparam32;
169 drm_r128_getparam_t __user *getparam;
170
171 if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
172 return -EFAULT;
173
174 getparam = compat_alloc_user_space(sizeof(*getparam));
175 if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
176 || __put_user(getparam32.param, &getparam->param)
177 || __put_user((void __user *)(unsigned long)getparam32.value,
178 &getparam->value))
179 return -EFAULT;
180
181 return drm_ioctl(file->f_path.dentry->d_inode, file,
182 DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
183}
184
185drm_ioctl_compat_t *r128_compat_ioctls[] = {
186 [DRM_R128_INIT] = compat_r128_init,
187 [DRM_R128_DEPTH] = compat_r128_depth,
188 [DRM_R128_STIPPLE] = compat_r128_stipple,
189 [DRM_R128_GETPARAM] = compat_r128_getparam,
190};
191
192/**
193 * Called whenever a 32-bit process running under a 64-bit kernel
194 * performs an ioctl on /dev/dri/card<n>.
195 *
196 * \param filp file pointer.
197 * \param cmd command.
198 * \param arg user argument.
199 * \return zero on success or negative number on failure.
200 */
201long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
202{
203 unsigned int nr = DRM_IOCTL_NR(cmd);
204 drm_ioctl_compat_t *fn = NULL;
205 int ret;
206
207 if (nr < DRM_COMMAND_BASE)
208 return drm_compat_ioctl(filp, cmd, arg);
209
210 if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls))
211 fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE];
212
213 lock_kernel(); /* XXX for now */
214 if (fn != NULL)
215 ret = (*fn) (filp, cmd, arg);
216 else
217 ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
218 unlock_kernel();
219
220 return ret;
221}
diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c
new file mode 100644
index 000000000000..c76fdca7662d
--- /dev/null
+++ b/drivers/gpu/drm/r128/r128_irq.c
@@ -0,0 +1,101 @@
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 struct drm_device *dev = (struct drm_device *) arg;
41 drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
42 int status;
43
44 status = R128_READ(R128_GEN_INT_STATUS);
45
46 /* VBLANK interrupt */
47 if (status & R128_CRTC_VBLANK_INT) {
48 R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
49 atomic_inc(&dev->vbl_received);
50 DRM_WAKEUP(&dev->vbl_queue);
51 drm_vbl_send_signals(dev);
52 return IRQ_HANDLED;
53 }
54 return IRQ_NONE;
55}
56
57int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
58{
59 unsigned int cur_vblank;
60 int ret = 0;
61
62 /* Assume that the user has missed the current sequence number
63 * by about a day rather than she wants to wait for years
64 * using vertical blanks...
65 */
66 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
67 (((cur_vblank = atomic_read(&dev->vbl_received))
68 - *sequence) <= (1 << 23)));
69
70 *sequence = cur_vblank;
71
72 return ret;
73}
74
75void r128_driver_irq_preinstall(struct drm_device * dev)
76{
77 drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
78
79 /* Disable *all* interrupts */
80 R128_WRITE(R128_GEN_INT_CNTL, 0);
81 /* Clear vblank bit if it's already high */
82 R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
83}
84
85void r128_driver_irq_postinstall(struct drm_device * dev)
86{
87 drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
88
89 /* Turn on VBL interrupt */
90 R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
91}
92
93void r128_driver_irq_uninstall(struct drm_device * dev)
94{
95 drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
96 if (!dev_priv)
97 return;
98
99 /* Disable *all* interrupts */
100 R128_WRITE(R128_GEN_INT_CNTL, 0);
101}
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c
new file mode 100644
index 000000000000..51a9afce7b9b
--- /dev/null
+++ b/drivers/gpu/drm/r128/r128_state.c
@@ -0,0 +1,1681 @@
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/*
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/* ================================================================
37 * CCE hardware state programming functions
38 */
39
40static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
41 struct drm_clip_rect * boxes, int count)
42{
43 u32 aux_sc_cntl = 0x00000000;
44 RING_LOCALS;
45 DRM_DEBUG("\n");
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("\n");
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("\n");
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("\n");
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("\n");
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("\n");
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("\n");
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("\n");
208
209 BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);
210
211 OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS));
212 OUT_RING(tex->tex_cntl);
213 OUT_RING(tex->tex_combine_cntl);
214 for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
215 OUT_RING(tex->tex_offset[i]);
216 }
217
218 OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0));
219 OUT_RING(tex->tex_border_color);
220
221 ADVANCE_RING();
222}
223
224static void r128_emit_state(drm_r128_private_t * dev_priv)
225{
226 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
227 unsigned int dirty = sarea_priv->dirty;
228
229 DRM_DEBUG("dirty=0x%08x\n", dirty);
230
231 if (dirty & R128_UPLOAD_CORE) {
232 r128_emit_core(dev_priv);
233 sarea_priv->dirty &= ~R128_UPLOAD_CORE;
234 }
235
236 if (dirty & R128_UPLOAD_CONTEXT) {
237 r128_emit_context(dev_priv);
238 sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
239 }
240
241 if (dirty & R128_UPLOAD_SETUP) {
242 r128_emit_setup(dev_priv);
243 sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
244 }
245
246 if (dirty & R128_UPLOAD_MASKS) {
247 r128_emit_masks(dev_priv);
248 sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
249 }
250
251 if (dirty & R128_UPLOAD_WINDOW) {
252 r128_emit_window(dev_priv);
253 sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
254 }
255
256 if (dirty & R128_UPLOAD_TEX0) {
257 r128_emit_tex0(dev_priv);
258 sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
259 }
260
261 if (dirty & R128_UPLOAD_TEX1) {
262 r128_emit_tex1(dev_priv);
263 sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
264 }
265
266 /* Turn off the texture cache flushing */
267 sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
268
269 sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
270}
271
272#if R128_PERFORMANCE_BOXES
273/* ================================================================
274 * Performance monitoring functions
275 */
276
277static void r128_clear_box(drm_r128_private_t * dev_priv,
278 int x, int y, int w, int h, int r, int g, int b)
279{
280 u32 pitch, offset;
281 u32 fb_bpp, color;
282 RING_LOCALS;
283
284 switch (dev_priv->fb_bpp) {
285 case 16:
286 fb_bpp = R128_GMC_DST_16BPP;
287 color = (((r & 0xf8) << 8) |
288 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
289 break;
290 case 24:
291 fb_bpp = R128_GMC_DST_24BPP;
292 color = ((r << 16) | (g << 8) | b);
293 break;
294 case 32:
295 fb_bpp = R128_GMC_DST_32BPP;
296 color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
297 break;
298 default:
299 return;
300 }
301
302 offset = dev_priv->back_offset;
303 pitch = dev_priv->back_pitch >> 3;
304
305 BEGIN_RING(6);
306
307 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
308 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
309 R128_GMC_BRUSH_SOLID_COLOR |
310 fb_bpp |
311 R128_GMC_SRC_DATATYPE_COLOR |
312 R128_ROP3_P |
313 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS);
314
315 OUT_RING((pitch << 21) | (offset >> 5));
316 OUT_RING(color);
317
318 OUT_RING((x << 16) | y);
319 OUT_RING((w << 16) | h);
320
321 ADVANCE_RING();
322}
323
324static void r128_cce_performance_boxes(drm_r128_private_t * dev_priv)
325{
326 if (atomic_read(&dev_priv->idle_count) == 0) {
327 r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
328 } else {
329 atomic_set(&dev_priv->idle_count, 0);
330 }
331}
332
333#endif
334
335/* ================================================================
336 * CCE command dispatch functions
337 */
338
339static void r128_print_dirty(const char *msg, unsigned int flags)
340{
341 DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
342 msg,
343 flags,
344 (flags & R128_UPLOAD_CORE) ? "core, " : "",
345 (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
346 (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
347 (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
348 (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
349 (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
350 (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
351 (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
352 (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
353}
354
355static void r128_cce_dispatch_clear(struct drm_device * dev,
356 drm_r128_clear_t * clear)
357{
358 drm_r128_private_t *dev_priv = dev->dev_private;
359 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
360 int nbox = sarea_priv->nbox;
361 struct drm_clip_rect *pbox = sarea_priv->boxes;
362 unsigned int flags = clear->flags;
363 int i;
364 RING_LOCALS;
365 DRM_DEBUG("\n");
366
367 if (dev_priv->page_flipping && dev_priv->current_page == 1) {
368 unsigned int tmp = flags;
369
370 flags &= ~(R128_FRONT | R128_BACK);
371 if (tmp & R128_FRONT)
372 flags |= R128_BACK;
373 if (tmp & R128_BACK)
374 flags |= R128_FRONT;
375 }
376
377 for (i = 0; i < nbox; i++) {
378 int x = pbox[i].x1;
379 int y = pbox[i].y1;
380 int w = pbox[i].x2 - x;
381 int h = pbox[i].y2 - y;
382
383 DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
384 pbox[i].x1, pbox[i].y1, pbox[i].x2,
385 pbox[i].y2, flags);
386
387 if (flags & (R128_FRONT | R128_BACK)) {
388 BEGIN_RING(2);
389
390 OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
391 OUT_RING(clear->color_mask);
392
393 ADVANCE_RING();
394 }
395
396 if (flags & R128_FRONT) {
397 BEGIN_RING(6);
398
399 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
400 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
401 R128_GMC_BRUSH_SOLID_COLOR |
402 (dev_priv->color_fmt << 8) |
403 R128_GMC_SRC_DATATYPE_COLOR |
404 R128_ROP3_P |
405 R128_GMC_CLR_CMP_CNTL_DIS |
406 R128_GMC_AUX_CLIP_DIS);
407
408 OUT_RING(dev_priv->front_pitch_offset_c);
409 OUT_RING(clear->clear_color);
410
411 OUT_RING((x << 16) | y);
412 OUT_RING((w << 16) | h);
413
414 ADVANCE_RING();
415 }
416
417 if (flags & R128_BACK) {
418 BEGIN_RING(6);
419
420 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
421 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
422 R128_GMC_BRUSH_SOLID_COLOR |
423 (dev_priv->color_fmt << 8) |
424 R128_GMC_SRC_DATATYPE_COLOR |
425 R128_ROP3_P |
426 R128_GMC_CLR_CMP_CNTL_DIS |
427 R128_GMC_AUX_CLIP_DIS);
428
429 OUT_RING(dev_priv->back_pitch_offset_c);
430 OUT_RING(clear->clear_color);
431
432 OUT_RING((x << 16) | y);
433 OUT_RING((w << 16) | h);
434
435 ADVANCE_RING();
436 }
437
438 if (flags & R128_DEPTH) {
439 BEGIN_RING(6);
440
441 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
442 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
443 R128_GMC_BRUSH_SOLID_COLOR |
444 (dev_priv->depth_fmt << 8) |
445 R128_GMC_SRC_DATATYPE_COLOR |
446 R128_ROP3_P |
447 R128_GMC_CLR_CMP_CNTL_DIS |
448 R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
449
450 OUT_RING(dev_priv->depth_pitch_offset_c);
451 OUT_RING(clear->clear_depth);
452
453 OUT_RING((x << 16) | y);
454 OUT_RING((w << 16) | h);
455
456 ADVANCE_RING();
457 }
458 }
459}
460
461static void r128_cce_dispatch_swap(struct drm_device * dev)
462{
463 drm_r128_private_t *dev_priv = dev->dev_private;
464 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
465 int nbox = sarea_priv->nbox;
466 struct drm_clip_rect *pbox = sarea_priv->boxes;
467 int i;
468 RING_LOCALS;
469 DRM_DEBUG("\n");
470
471#if R128_PERFORMANCE_BOXES
472 /* Do some trivial performance monitoring...
473 */
474 r128_cce_performance_boxes(dev_priv);
475#endif
476
477 for (i = 0; i < nbox; i++) {
478 int x = pbox[i].x1;
479 int y = pbox[i].y1;
480 int w = pbox[i].x2 - x;
481 int h = pbox[i].y2 - y;
482
483 BEGIN_RING(7);
484
485 OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
486 OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
487 R128_GMC_DST_PITCH_OFFSET_CNTL |
488 R128_GMC_BRUSH_NONE |
489 (dev_priv->color_fmt << 8) |
490 R128_GMC_SRC_DATATYPE_COLOR |
491 R128_ROP3_S |
492 R128_DP_SRC_SOURCE_MEMORY |
493 R128_GMC_CLR_CMP_CNTL_DIS |
494 R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
495
496 /* Make this work even if front & back are flipped:
497 */
498 if (dev_priv->current_page == 0) {
499 OUT_RING(dev_priv->back_pitch_offset_c);
500 OUT_RING(dev_priv->front_pitch_offset_c);
501 } else {
502 OUT_RING(dev_priv->front_pitch_offset_c);
503 OUT_RING(dev_priv->back_pitch_offset_c);
504 }
505
506 OUT_RING((x << 16) | y);
507 OUT_RING((x << 16) | y);
508 OUT_RING((w << 16) | h);
509
510 ADVANCE_RING();
511 }
512
513 /* Increment the frame counter. The client-side 3D driver must
514 * throttle the framerate by waiting for this value before
515 * performing the swapbuffer ioctl.
516 */
517 dev_priv->sarea_priv->last_frame++;
518
519 BEGIN_RING(2);
520
521 OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
522 OUT_RING(dev_priv->sarea_priv->last_frame);
523
524 ADVANCE_RING();
525}
526
527static void r128_cce_dispatch_flip(struct drm_device * dev)
528{
529 drm_r128_private_t *dev_priv = dev->dev_private;
530 RING_LOCALS;
531 DRM_DEBUG("page=%d pfCurrentPage=%d\n",
532 dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
533
534#if R128_PERFORMANCE_BOXES
535 /* Do some trivial performance monitoring...
536 */
537 r128_cce_performance_boxes(dev_priv);
538#endif
539
540 BEGIN_RING(4);
541
542 R128_WAIT_UNTIL_PAGE_FLIPPED();
543 OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0));
544
545 if (dev_priv->current_page == 0) {
546 OUT_RING(dev_priv->back_offset);
547 } else {
548 OUT_RING(dev_priv->front_offset);
549 }
550
551 ADVANCE_RING();
552
553 /* Increment the frame counter. The client-side 3D driver must
554 * throttle the framerate by waiting for this value before
555 * performing the swapbuffer ioctl.
556 */
557 dev_priv->sarea_priv->last_frame++;
558 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
559 1 - dev_priv->current_page;
560
561 BEGIN_RING(2);
562
563 OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
564 OUT_RING(dev_priv->sarea_priv->last_frame);
565
566 ADVANCE_RING();
567}
568
569static void r128_cce_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
570{
571 drm_r128_private_t *dev_priv = dev->dev_private;
572 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
573 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
574 int format = sarea_priv->vc_format;
575 int offset = buf->bus_address;
576 int size = buf->used;
577 int prim = buf_priv->prim;
578 int i = 0;
579 RING_LOCALS;
580 DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox);
581
582 if (0)
583 r128_print_dirty("dispatch_vertex", sarea_priv->dirty);
584
585 if (buf->used) {
586 buf_priv->dispatched = 1;
587
588 if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
589 r128_emit_state(dev_priv);
590 }
591
592 do {
593 /* Emit the next set of up to three cliprects */
594 if (i < sarea_priv->nbox) {
595 r128_emit_clip_rects(dev_priv,
596 &sarea_priv->boxes[i],
597 sarea_priv->nbox - i);
598 }
599
600 /* Emit the vertex buffer rendering commands */
601 BEGIN_RING(5);
602
603 OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3));
604 OUT_RING(offset);
605 OUT_RING(size);
606 OUT_RING(format);
607 OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
608 (size << R128_CCE_VC_CNTL_NUM_SHIFT));
609
610 ADVANCE_RING();
611
612 i += 3;
613 } while (i < sarea_priv->nbox);
614 }
615
616 if (buf_priv->discard) {
617 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
618
619 /* Emit the vertex buffer age */
620 BEGIN_RING(2);
621
622 OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
623 OUT_RING(buf_priv->age);
624
625 ADVANCE_RING();
626
627 buf->pending = 1;
628 buf->used = 0;
629 /* FIXME: Check dispatched field */
630 buf_priv->dispatched = 0;
631 }
632
633 dev_priv->sarea_priv->last_dispatch++;
634
635 sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
636 sarea_priv->nbox = 0;
637}
638
639static void r128_cce_dispatch_indirect(struct drm_device * dev,
640 struct drm_buf * buf, int start, int end)
641{
642 drm_r128_private_t *dev_priv = dev->dev_private;
643 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
644 RING_LOCALS;
645 DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
646
647 if (start != end) {
648 int offset = buf->bus_address + start;
649 int dwords = (end - start + 3) / sizeof(u32);
650
651 /* Indirect buffer data must be an even number of
652 * dwords, so if we've been given an odd number we must
653 * pad the data with a Type-2 CCE packet.
654 */
655 if (dwords & 1) {
656 u32 *data = (u32 *)
657 ((char *)dev->agp_buffer_map->handle
658 + buf->offset + start);
659 data[dwords++] = cpu_to_le32(R128_CCE_PACKET2);
660 }
661
662 buf_priv->dispatched = 1;
663
664 /* Fire off the indirect buffer */
665 BEGIN_RING(3);
666
667 OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1));
668 OUT_RING(offset);
669 OUT_RING(dwords);
670
671 ADVANCE_RING();
672 }
673
674 if (buf_priv->discard) {
675 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
676
677 /* Emit the indirect buffer age */
678 BEGIN_RING(2);
679
680 OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
681 OUT_RING(buf_priv->age);
682
683 ADVANCE_RING();
684
685 buf->pending = 1;
686 buf->used = 0;
687 /* FIXME: Check dispatched field */
688 buf_priv->dispatched = 0;
689 }
690
691 dev_priv->sarea_priv->last_dispatch++;
692}
693
694static void r128_cce_dispatch_indices(struct drm_device * dev,
695 struct drm_buf * buf,
696 int start, int end, int count)
697{
698 drm_r128_private_t *dev_priv = dev->dev_private;
699 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
700 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
701 int format = sarea_priv->vc_format;
702 int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;
703 int prim = buf_priv->prim;
704 u32 *data;
705 int dwords;
706 int i = 0;
707 RING_LOCALS;
708 DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count);
709
710 if (0)
711 r128_print_dirty("dispatch_indices", sarea_priv->dirty);
712
713 if (start != end) {
714 buf_priv->dispatched = 1;
715
716 if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
717 r128_emit_state(dev_priv);
718 }
719
720 dwords = (end - start + 3) / sizeof(u32);
721
722 data = (u32 *) ((char *)dev->agp_buffer_map->handle
723 + buf->offset + start);
724
725 data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM,
726 dwords - 2));
727
728 data[1] = cpu_to_le32(offset);
729 data[2] = cpu_to_le32(R128_MAX_VB_VERTS);
730 data[3] = cpu_to_le32(format);
731 data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
732 (count << 16)));
733
734 if (count & 0x1) {
735#ifdef __LITTLE_ENDIAN
736 data[dwords - 1] &= 0x0000ffff;
737#else
738 data[dwords - 1] &= 0xffff0000;
739#endif
740 }
741
742 do {
743 /* Emit the next set of up to three cliprects */
744 if (i < sarea_priv->nbox) {
745 r128_emit_clip_rects(dev_priv,
746 &sarea_priv->boxes[i],
747 sarea_priv->nbox - i);
748 }
749
750 r128_cce_dispatch_indirect(dev, buf, start, end);
751
752 i += 3;
753 } while (i < sarea_priv->nbox);
754 }
755
756 if (buf_priv->discard) {
757 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
758
759 /* Emit the vertex buffer age */
760 BEGIN_RING(2);
761
762 OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
763 OUT_RING(buf_priv->age);
764
765 ADVANCE_RING();
766
767 buf->pending = 1;
768 /* FIXME: Check dispatched field */
769 buf_priv->dispatched = 0;
770 }
771
772 dev_priv->sarea_priv->last_dispatch++;
773
774 sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
775 sarea_priv->nbox = 0;
776}
777
778static int r128_cce_dispatch_blit(struct drm_device * dev,
779 struct drm_file *file_priv,
780 drm_r128_blit_t * blit)
781{
782 drm_r128_private_t *dev_priv = dev->dev_private;
783 struct drm_device_dma *dma = dev->dma;
784 struct drm_buf *buf;
785 drm_r128_buf_priv_t *buf_priv;
786 u32 *data;
787 int dword_shift, dwords;
788 RING_LOCALS;
789 DRM_DEBUG("\n");
790
791 /* The compiler won't optimize away a division by a variable,
792 * even if the only legal values are powers of two. Thus, we'll
793 * use a shift instead.
794 */
795 switch (blit->format) {
796 case R128_DATATYPE_ARGB8888:
797 dword_shift = 0;
798 break;
799 case R128_DATATYPE_ARGB1555:
800 case R128_DATATYPE_RGB565:
801 case R128_DATATYPE_ARGB4444:
802 case R128_DATATYPE_YVYU422:
803 case R128_DATATYPE_VYUY422:
804 dword_shift = 1;
805 break;
806 case R128_DATATYPE_CI8:
807 case R128_DATATYPE_RGB8:
808 dword_shift = 2;
809 break;
810 default:
811 DRM_ERROR("invalid blit format %d\n", blit->format);
812 return -EINVAL;
813 }
814
815 /* Flush the pixel cache, and mark the contents as Read Invalid.
816 * This ensures no pixel data gets mixed up with the texture
817 * data from the host data blit, otherwise part of the texture
818 * image may be corrupted.
819 */
820 BEGIN_RING(2);
821
822 OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
823 OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI);
824
825 ADVANCE_RING();
826
827 /* Dispatch the indirect buffer.
828 */
829 buf = dma->buflist[blit->idx];
830 buf_priv = buf->dev_private;
831
832 if (buf->file_priv != file_priv) {
833 DRM_ERROR("process %d using buffer owned by %p\n",
834 DRM_CURRENTPID, buf->file_priv);
835 return -EINVAL;
836 }
837 if (buf->pending) {
838 DRM_ERROR("sending pending buffer %d\n", blit->idx);
839 return -EINVAL;
840 }
841
842 buf_priv->discard = 1;
843
844 dwords = (blit->width * blit->height) >> dword_shift;
845
846 data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
847
848 data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6));
849 data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL |
850 R128_GMC_BRUSH_NONE |
851 (blit->format << 8) |
852 R128_GMC_SRC_DATATYPE_COLOR |
853 R128_ROP3_S |
854 R128_DP_SRC_SOURCE_HOST_DATA |
855 R128_GMC_CLR_CMP_CNTL_DIS |
856 R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS));
857
858 data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5));
859 data[3] = cpu_to_le32(0xffffffff);
860 data[4] = cpu_to_le32(0xffffffff);
861 data[5] = cpu_to_le32((blit->y << 16) | blit->x);
862 data[6] = cpu_to_le32((blit->height << 16) | blit->width);
863 data[7] = cpu_to_le32(dwords);
864
865 buf->used = (dwords + 8) * sizeof(u32);
866
867 r128_cce_dispatch_indirect(dev, buf, 0, buf->used);
868
869 /* Flush the pixel cache after the blit completes. This ensures
870 * the texture data is written out to memory before rendering
871 * continues.
872 */
873 BEGIN_RING(2);
874
875 OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
876 OUT_RING(R128_PC_FLUSH_GUI);
877
878 ADVANCE_RING();
879
880 return 0;
881}
882
883/* ================================================================
884 * Tiled depth buffer management
885 *
886 * FIXME: These should all set the destination write mask for when we
887 * have hardware stencil support.
888 */
889
890static int r128_cce_dispatch_write_span(struct drm_device * dev,
891 drm_r128_depth_t * depth)
892{
893 drm_r128_private_t *dev_priv = dev->dev_private;
894 int count, x, y;
895 u32 *buffer;
896 u8 *mask;
897 int i, buffer_size, mask_size;
898 RING_LOCALS;
899 DRM_DEBUG("\n");
900
901 count = depth->n;
902 if (count > 4096 || count <= 0)
903 return -EMSGSIZE;
904
905 if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
906 return -EFAULT;
907 }
908 if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
909 return -EFAULT;
910 }
911
912 buffer_size = depth->n * sizeof(u32);
913 buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
914 if (buffer == NULL)
915 return -ENOMEM;
916 if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
917 drm_free(buffer, buffer_size, DRM_MEM_BUFS);
918 return -EFAULT;
919 }
920
921 mask_size = depth->n * sizeof(u8);
922 if (depth->mask) {
923 mask = drm_alloc(mask_size, DRM_MEM_BUFS);
924 if (mask == NULL) {
925 drm_free(buffer, buffer_size, DRM_MEM_BUFS);
926 return -ENOMEM;
927 }
928 if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
929 drm_free(buffer, buffer_size, DRM_MEM_BUFS);
930 drm_free(mask, mask_size, DRM_MEM_BUFS);
931 return -EFAULT;
932 }
933
934 for (i = 0; i < count; i++, x++) {
935 if (mask[i]) {
936 BEGIN_RING(6);
937
938 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
939 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
940 R128_GMC_BRUSH_SOLID_COLOR |
941 (dev_priv->depth_fmt << 8) |
942 R128_GMC_SRC_DATATYPE_COLOR |
943 R128_ROP3_P |
944 R128_GMC_CLR_CMP_CNTL_DIS |
945 R128_GMC_WR_MSK_DIS);
946
947 OUT_RING(dev_priv->depth_pitch_offset_c);
948 OUT_RING(buffer[i]);
949
950 OUT_RING((x << 16) | y);
951 OUT_RING((1 << 16) | 1);
952
953 ADVANCE_RING();
954 }
955 }
956
957 drm_free(mask, mask_size, DRM_MEM_BUFS);
958 } else {
959 for (i = 0; i < count; i++, x++) {
960 BEGIN_RING(6);
961
962 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
963 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
964 R128_GMC_BRUSH_SOLID_COLOR |
965 (dev_priv->depth_fmt << 8) |
966 R128_GMC_SRC_DATATYPE_COLOR |
967 R128_ROP3_P |
968 R128_GMC_CLR_CMP_CNTL_DIS |
969 R128_GMC_WR_MSK_DIS);
970
971 OUT_RING(dev_priv->depth_pitch_offset_c);
972 OUT_RING(buffer[i]);
973
974 OUT_RING((x << 16) | y);
975 OUT_RING((1 << 16) | 1);
976
977 ADVANCE_RING();
978 }
979 }
980
981 drm_free(buffer, buffer_size, DRM_MEM_BUFS);
982
983 return 0;
984}
985
986static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
987 drm_r128_depth_t * depth)
988{
989 drm_r128_private_t *dev_priv = dev->dev_private;
990 int count, *x, *y;
991 u32 *buffer;
992 u8 *mask;
993 int i, xbuf_size, ybuf_size, buffer_size, mask_size;
994 RING_LOCALS;
995 DRM_DEBUG("\n");
996
997 count = depth->n;
998 if (count > 4096 || count <= 0)
999 return -EMSGSIZE;
1000
1001 xbuf_size = count * sizeof(*x);
1002 ybuf_size = count * sizeof(*y);
1003 x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
1004 if (x == NULL) {
1005 return -ENOMEM;
1006 }
1007 y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
1008 if (y == NULL) {
1009 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1010 return -ENOMEM;
1011 }
1012 if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
1013 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1014 drm_free(y, ybuf_size, DRM_MEM_BUFS);
1015 return -EFAULT;
1016 }
1017 if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
1018 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1019 drm_free(y, ybuf_size, DRM_MEM_BUFS);
1020 return -EFAULT;
1021 }
1022
1023 buffer_size = depth->n * sizeof(u32);
1024 buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
1025 if (buffer == NULL) {
1026 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1027 drm_free(y, ybuf_size, DRM_MEM_BUFS);
1028 return -ENOMEM;
1029 }
1030 if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
1031 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1032 drm_free(y, ybuf_size, DRM_MEM_BUFS);
1033 drm_free(buffer, buffer_size, DRM_MEM_BUFS);
1034 return -EFAULT;
1035 }
1036
1037 if (depth->mask) {
1038 mask_size = depth->n * sizeof(u8);
1039 mask = drm_alloc(mask_size, DRM_MEM_BUFS);
1040 if (mask == NULL) {
1041 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1042 drm_free(y, ybuf_size, DRM_MEM_BUFS);
1043 drm_free(buffer, buffer_size, DRM_MEM_BUFS);
1044 return -ENOMEM;
1045 }
1046 if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
1047 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1048 drm_free(y, ybuf_size, DRM_MEM_BUFS);
1049 drm_free(buffer, buffer_size, DRM_MEM_BUFS);
1050 drm_free(mask, mask_size, DRM_MEM_BUFS);
1051 return -EFAULT;
1052 }
1053
1054 for (i = 0; i < count; i++) {
1055 if (mask[i]) {
1056 BEGIN_RING(6);
1057
1058 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
1059 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
1060 R128_GMC_BRUSH_SOLID_COLOR |
1061 (dev_priv->depth_fmt << 8) |
1062 R128_GMC_SRC_DATATYPE_COLOR |
1063 R128_ROP3_P |
1064 R128_GMC_CLR_CMP_CNTL_DIS |
1065 R128_GMC_WR_MSK_DIS);
1066
1067 OUT_RING(dev_priv->depth_pitch_offset_c);
1068 OUT_RING(buffer[i]);
1069
1070 OUT_RING((x[i] << 16) | y[i]);
1071 OUT_RING((1 << 16) | 1);
1072
1073 ADVANCE_RING();
1074 }
1075 }
1076
1077 drm_free(mask, mask_size, DRM_MEM_BUFS);
1078 } else {
1079 for (i = 0; i < count; i++) {
1080 BEGIN_RING(6);
1081
1082 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
1083 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
1084 R128_GMC_BRUSH_SOLID_COLOR |
1085 (dev_priv->depth_fmt << 8) |
1086 R128_GMC_SRC_DATATYPE_COLOR |
1087 R128_ROP3_P |
1088 R128_GMC_CLR_CMP_CNTL_DIS |
1089 R128_GMC_WR_MSK_DIS);
1090
1091 OUT_RING(dev_priv->depth_pitch_offset_c);
1092 OUT_RING(buffer[i]);
1093
1094 OUT_RING((x[i] << 16) | y[i]);
1095 OUT_RING((1 << 16) | 1);
1096
1097 ADVANCE_RING();
1098 }
1099 }
1100
1101 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1102 drm_free(y, ybuf_size, DRM_MEM_BUFS);
1103 drm_free(buffer, buffer_size, DRM_MEM_BUFS);
1104
1105 return 0;
1106}
1107
1108static int r128_cce_dispatch_read_span(struct drm_device * dev,
1109 drm_r128_depth_t * depth)
1110{
1111 drm_r128_private_t *dev_priv = dev->dev_private;
1112 int count, x, y;
1113 RING_LOCALS;
1114 DRM_DEBUG("\n");
1115
1116 count = depth->n;
1117 if (count > 4096 || count <= 0)
1118 return -EMSGSIZE;
1119
1120 if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
1121 return -EFAULT;
1122 }
1123 if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
1124 return -EFAULT;
1125 }
1126
1127 BEGIN_RING(7);
1128
1129 OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
1130 OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
1131 R128_GMC_DST_PITCH_OFFSET_CNTL |
1132 R128_GMC_BRUSH_NONE |
1133 (dev_priv->depth_fmt << 8) |
1134 R128_GMC_SRC_DATATYPE_COLOR |
1135 R128_ROP3_S |
1136 R128_DP_SRC_SOURCE_MEMORY |
1137 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
1138
1139 OUT_RING(dev_priv->depth_pitch_offset_c);
1140 OUT_RING(dev_priv->span_pitch_offset_c);
1141
1142 OUT_RING((x << 16) | y);
1143 OUT_RING((0 << 16) | 0);
1144 OUT_RING((count << 16) | 1);
1145
1146 ADVANCE_RING();
1147
1148 return 0;
1149}
1150
1151static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
1152 drm_r128_depth_t * depth)
1153{
1154 drm_r128_private_t *dev_priv = dev->dev_private;
1155 int count, *x, *y;
1156 int i, xbuf_size, ybuf_size;
1157 RING_LOCALS;
1158 DRM_DEBUG("\n");
1159
1160 count = depth->n;
1161 if (count > 4096 || count <= 0)
1162 return -EMSGSIZE;
1163
1164 if (count > dev_priv->depth_pitch) {
1165 count = dev_priv->depth_pitch;
1166 }
1167
1168 xbuf_size = count * sizeof(*x);
1169 ybuf_size = count * sizeof(*y);
1170 x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
1171 if (x == NULL) {
1172 return -ENOMEM;
1173 }
1174 y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
1175 if (y == NULL) {
1176 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1177 return -ENOMEM;
1178 }
1179 if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
1180 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1181 drm_free(y, ybuf_size, DRM_MEM_BUFS);
1182 return -EFAULT;
1183 }
1184 if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
1185 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1186 drm_free(y, ybuf_size, DRM_MEM_BUFS);
1187 return -EFAULT;
1188 }
1189
1190 for (i = 0; i < count; i++) {
1191 BEGIN_RING(7);
1192
1193 OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
1194 OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
1195 R128_GMC_DST_PITCH_OFFSET_CNTL |
1196 R128_GMC_BRUSH_NONE |
1197 (dev_priv->depth_fmt << 8) |
1198 R128_GMC_SRC_DATATYPE_COLOR |
1199 R128_ROP3_S |
1200 R128_DP_SRC_SOURCE_MEMORY |
1201 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
1202
1203 OUT_RING(dev_priv->depth_pitch_offset_c);
1204 OUT_RING(dev_priv->span_pitch_offset_c);
1205
1206 OUT_RING((x[i] << 16) | y[i]);
1207 OUT_RING((i << 16) | 0);
1208 OUT_RING((1 << 16) | 1);
1209
1210 ADVANCE_RING();
1211 }
1212
1213 drm_free(x, xbuf_size, DRM_MEM_BUFS);
1214 drm_free(y, ybuf_size, DRM_MEM_BUFS);
1215
1216 return 0;
1217}
1218
1219/* ================================================================
1220 * Polygon stipple
1221 */
1222
1223static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
1224{
1225 drm_r128_private_t *dev_priv = dev->dev_private;
1226 int i;
1227 RING_LOCALS;
1228 DRM_DEBUG("\n");
1229
1230 BEGIN_RING(33);
1231
1232 OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31));
1233 for (i = 0; i < 32; i++) {
1234 OUT_RING(stipple[i]);
1235 }
1236
1237 ADVANCE_RING();
1238}
1239
1240/* ================================================================
1241 * IOCTL functions
1242 */
1243
1244static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
1245{
1246 drm_r128_private_t *dev_priv = dev->dev_private;
1247 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1248 drm_r128_clear_t *clear = data;
1249 DRM_DEBUG("\n");
1250
1251 LOCK_TEST_WITH_RETURN(dev, file_priv);
1252
1253 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1254
1255 if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
1256 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1257
1258 r128_cce_dispatch_clear(dev, clear);
1259 COMMIT_RING();
1260
1261 /* Make sure we restore the 3D state next time.
1262 */
1263 dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
1264
1265 return 0;
1266}
1267
1268static int r128_do_init_pageflip(struct drm_device * dev)
1269{
1270 drm_r128_private_t *dev_priv = dev->dev_private;
1271 DRM_DEBUG("\n");
1272
1273 dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET);
1274 dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL);
1275
1276 R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset);
1277 R128_WRITE(R128_CRTC_OFFSET_CNTL,
1278 dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL);
1279
1280 dev_priv->page_flipping = 1;
1281 dev_priv->current_page = 0;
1282 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
1283
1284 return 0;
1285}
1286
1287static int r128_do_cleanup_pageflip(struct drm_device * dev)
1288{
1289 drm_r128_private_t *dev_priv = dev->dev_private;
1290 DRM_DEBUG("\n");
1291
1292 R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset);
1293 R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl);
1294
1295 if (dev_priv->current_page != 0) {
1296 r128_cce_dispatch_flip(dev);
1297 COMMIT_RING();
1298 }
1299
1300 dev_priv->page_flipping = 0;
1301 return 0;
1302}
1303
1304/* Swapping and flipping are different operations, need different ioctls.
1305 * They can & should be intermixed to support multiple 3d windows.
1306 */
1307
1308static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
1309{
1310 drm_r128_private_t *dev_priv = dev->dev_private;
1311 DRM_DEBUG("\n");
1312
1313 LOCK_TEST_WITH_RETURN(dev, file_priv);
1314
1315 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1316
1317 if (!dev_priv->page_flipping)
1318 r128_do_init_pageflip(dev);
1319
1320 r128_cce_dispatch_flip(dev);
1321
1322 COMMIT_RING();
1323 return 0;
1324}
1325
1326static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
1327{
1328 drm_r128_private_t *dev_priv = dev->dev_private;
1329 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1330 DRM_DEBUG("\n");
1331
1332 LOCK_TEST_WITH_RETURN(dev, file_priv);
1333
1334 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1335
1336 if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
1337 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1338
1339 r128_cce_dispatch_swap(dev);
1340 dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
1341 R128_UPLOAD_MASKS);
1342
1343 COMMIT_RING();
1344 return 0;
1345}
1346
1347static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
1348{
1349 drm_r128_private_t *dev_priv = dev->dev_private;
1350 struct drm_device_dma *dma = dev->dma;
1351 struct drm_buf *buf;
1352 drm_r128_buf_priv_t *buf_priv;
1353 drm_r128_vertex_t *vertex = data;
1354
1355 LOCK_TEST_WITH_RETURN(dev, file_priv);
1356
1357 if (!dev_priv) {
1358 DRM_ERROR("called with no initialization\n");
1359 return -EINVAL;
1360 }
1361
1362 DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
1363 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
1364
1365 if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
1366 DRM_ERROR("buffer index %d (of %d max)\n",
1367 vertex->idx, dma->buf_count - 1);
1368 return -EINVAL;
1369 }
1370 if (vertex->prim < 0 ||
1371 vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
1372 DRM_ERROR("buffer prim %d\n", vertex->prim);
1373 return -EINVAL;
1374 }
1375
1376 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1377 VB_AGE_TEST_WITH_RETURN(dev_priv);
1378
1379 buf = dma->buflist[vertex->idx];
1380 buf_priv = buf->dev_private;
1381
1382 if (buf->file_priv != file_priv) {
1383 DRM_ERROR("process %d using buffer owned by %p\n",
1384 DRM_CURRENTPID, buf->file_priv);
1385 return -EINVAL;
1386 }
1387 if (buf->pending) {
1388 DRM_ERROR("sending pending buffer %d\n", vertex->idx);
1389 return -EINVAL;
1390 }
1391
1392 buf->used = vertex->count;
1393 buf_priv->prim = vertex->prim;
1394 buf_priv->discard = vertex->discard;
1395
1396 r128_cce_dispatch_vertex(dev, buf);
1397
1398 COMMIT_RING();
1399 return 0;
1400}
1401
1402static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
1403{
1404 drm_r128_private_t *dev_priv = dev->dev_private;
1405 struct drm_device_dma *dma = dev->dma;
1406 struct drm_buf *buf;
1407 drm_r128_buf_priv_t *buf_priv;
1408 drm_r128_indices_t *elts = data;
1409 int count;
1410
1411 LOCK_TEST_WITH_RETURN(dev, file_priv);
1412
1413 if (!dev_priv) {
1414 DRM_ERROR("called with no initialization\n");
1415 return -EINVAL;
1416 }
1417
1418 DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
1419 elts->idx, elts->start, elts->end, elts->discard);
1420
1421 if (elts->idx < 0 || elts->idx >= dma->buf_count) {
1422 DRM_ERROR("buffer index %d (of %d max)\n",
1423 elts->idx, dma->buf_count - 1);
1424 return -EINVAL;
1425 }
1426 if (elts->prim < 0 ||
1427 elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
1428 DRM_ERROR("buffer prim %d\n", elts->prim);
1429 return -EINVAL;
1430 }
1431
1432 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1433 VB_AGE_TEST_WITH_RETURN(dev_priv);
1434
1435 buf = dma->buflist[elts->idx];
1436 buf_priv = buf->dev_private;
1437
1438 if (buf->file_priv != file_priv) {
1439 DRM_ERROR("process %d using buffer owned by %p\n",
1440 DRM_CURRENTPID, buf->file_priv);
1441 return -EINVAL;
1442 }
1443 if (buf->pending) {
1444 DRM_ERROR("sending pending buffer %d\n", elts->idx);
1445 return -EINVAL;
1446 }
1447
1448 count = (elts->end - elts->start) / sizeof(u16);
1449 elts->start -= R128_INDEX_PRIM_OFFSET;
1450
1451 if (elts->start & 0x7) {
1452 DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
1453 return -EINVAL;
1454 }
1455 if (elts->start < buf->used) {
1456 DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
1457 return -EINVAL;
1458 }
1459
1460 buf->used = elts->end;
1461 buf_priv->prim = elts->prim;
1462 buf_priv->discard = elts->discard;
1463
1464 r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count);
1465
1466 COMMIT_RING();
1467 return 0;
1468}
1469
1470static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
1471{
1472 struct drm_device_dma *dma = dev->dma;
1473 drm_r128_private_t *dev_priv = dev->dev_private;
1474 drm_r128_blit_t *blit = data;
1475 int ret;
1476
1477 LOCK_TEST_WITH_RETURN(dev, file_priv);
1478
1479 DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx);
1480
1481 if (blit->idx < 0 || blit->idx >= dma->buf_count) {
1482 DRM_ERROR("buffer index %d (of %d max)\n",
1483 blit->idx, dma->buf_count - 1);
1484 return -EINVAL;
1485 }
1486
1487 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1488 VB_AGE_TEST_WITH_RETURN(dev_priv);
1489
1490 ret = r128_cce_dispatch_blit(dev, file_priv, blit);
1491
1492 COMMIT_RING();
1493 return ret;
1494}
1495
1496static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv)
1497{
1498 drm_r128_private_t *dev_priv = dev->dev_private;
1499 drm_r128_depth_t *depth = data;
1500 int ret;
1501
1502 LOCK_TEST_WITH_RETURN(dev, file_priv);
1503
1504 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1505
1506 ret = -EINVAL;
1507 switch (depth->func) {
1508 case R128_WRITE_SPAN:
1509 ret = r128_cce_dispatch_write_span(dev, depth);
1510 break;
1511 case R128_WRITE_PIXELS:
1512 ret = r128_cce_dispatch_write_pixels(dev, depth);
1513 break;
1514 case R128_READ_SPAN:
1515 ret = r128_cce_dispatch_read_span(dev, depth);
1516 break;
1517 case R128_READ_PIXELS:
1518 ret = r128_cce_dispatch_read_pixels(dev, depth);
1519 break;
1520 }
1521
1522 COMMIT_RING();
1523 return ret;
1524}
1525
1526static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
1527{
1528 drm_r128_private_t *dev_priv = dev->dev_private;
1529 drm_r128_stipple_t *stipple = data;
1530 u32 mask[32];
1531
1532 LOCK_TEST_WITH_RETURN(dev, file_priv);
1533
1534 if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
1535 return -EFAULT;
1536
1537 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1538
1539 r128_cce_dispatch_stipple(dev, mask);
1540
1541 COMMIT_RING();
1542 return 0;
1543}
1544
1545static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
1546{
1547 drm_r128_private_t *dev_priv = dev->dev_private;
1548 struct drm_device_dma *dma = dev->dma;
1549 struct drm_buf *buf;
1550 drm_r128_buf_priv_t *buf_priv;
1551 drm_r128_indirect_t *indirect = data;
1552#if 0
1553 RING_LOCALS;
1554#endif
1555
1556 LOCK_TEST_WITH_RETURN(dev, file_priv);
1557
1558 if (!dev_priv) {
1559 DRM_ERROR("called with no initialization\n");
1560 return -EINVAL;
1561 }
1562
1563 DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
1564 indirect->idx, indirect->start, indirect->end,
1565 indirect->discard);
1566
1567 if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {
1568 DRM_ERROR("buffer index %d (of %d max)\n",
1569 indirect->idx, dma->buf_count - 1);
1570 return -EINVAL;
1571 }
1572
1573 buf = dma->buflist[indirect->idx];
1574 buf_priv = buf->dev_private;
1575
1576 if (buf->file_priv != file_priv) {
1577 DRM_ERROR("process %d using buffer owned by %p\n",
1578 DRM_CURRENTPID, buf->file_priv);
1579 return -EINVAL;
1580 }
1581 if (buf->pending) {
1582 DRM_ERROR("sending pending buffer %d\n", indirect->idx);
1583 return -EINVAL;
1584 }
1585
1586 if (indirect->start < buf->used) {
1587 DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
1588 indirect->start, buf->used);
1589 return -EINVAL;
1590 }
1591
1592 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1593 VB_AGE_TEST_WITH_RETURN(dev_priv);
1594
1595 buf->used = indirect->end;
1596 buf_priv->discard = indirect->discard;
1597
1598#if 0
1599 /* Wait for the 3D stream to idle before the indirect buffer
1600 * containing 2D acceleration commands is processed.
1601 */
1602 BEGIN_RING(2);
1603 RADEON_WAIT_UNTIL_3D_IDLE();
1604 ADVANCE_RING();
1605#endif
1606
1607 /* Dispatch the indirect buffer full of commands from the
1608 * X server. This is insecure and is thus only available to
1609 * privileged clients.
1610 */
1611 r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end);
1612
1613 COMMIT_RING();
1614 return 0;
1615}
1616
1617static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
1618{
1619 drm_r128_private_t *dev_priv = dev->dev_private;
1620 drm_r128_getparam_t *param = data;
1621 int value;
1622
1623 if (!dev_priv) {
1624 DRM_ERROR("called with no initialization\n");
1625 return -EINVAL;
1626 }
1627
1628 DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
1629
1630 switch (param->param) {
1631 case R128_PARAM_IRQ_NR:
1632 value = dev->irq;
1633 break;
1634 default:
1635 return -EINVAL;
1636 }
1637
1638 if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
1639 DRM_ERROR("copy_to_user\n");
1640 return -EFAULT;
1641 }
1642
1643 return 0;
1644}
1645
1646void r128_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
1647{
1648 if (dev->dev_private) {
1649 drm_r128_private_t *dev_priv = dev->dev_private;
1650 if (dev_priv->page_flipping) {
1651 r128_do_cleanup_pageflip(dev);
1652 }
1653 }
1654}
1655
1656void r128_driver_lastclose(struct drm_device * dev)
1657{
1658 r128_do_cleanup_cce(dev);
1659}
1660
1661struct drm_ioctl_desc r128_ioctls[] = {
1662 DRM_IOCTL_DEF(DRM_R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1663 DRM_IOCTL_DEF(DRM_R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1664 DRM_IOCTL_DEF(DRM_R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1665 DRM_IOCTL_DEF(DRM_R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1666 DRM_IOCTL_DEF(DRM_R128_CCE_IDLE, r128_cce_idle, DRM_AUTH),
1667 DRM_IOCTL_DEF(DRM_R128_RESET, r128_engine_reset, DRM_AUTH),
1668 DRM_IOCTL_DEF(DRM_R128_FULLSCREEN, r128_fullscreen, DRM_AUTH),
1669 DRM_IOCTL_DEF(DRM_R128_SWAP, r128_cce_swap, DRM_AUTH),
1670 DRM_IOCTL_DEF(DRM_R128_FLIP, r128_cce_flip, DRM_AUTH),
1671 DRM_IOCTL_DEF(DRM_R128_CLEAR, r128_cce_clear, DRM_AUTH),
1672 DRM_IOCTL_DEF(DRM_R128_VERTEX, r128_cce_vertex, DRM_AUTH),
1673 DRM_IOCTL_DEF(DRM_R128_INDICES, r128_cce_indices, DRM_AUTH),
1674 DRM_IOCTL_DEF(DRM_R128_BLIT, r128_cce_blit, DRM_AUTH),
1675 DRM_IOCTL_DEF(DRM_R128_DEPTH, r128_cce_depth, DRM_AUTH),
1676 DRM_IOCTL_DEF(DRM_R128_STIPPLE, r128_cce_stipple, DRM_AUTH),
1677 DRM_IOCTL_DEF(DRM_R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1678 DRM_IOCTL_DEF(DRM_R128_GETPARAM, r128_getparam, DRM_AUTH),
1679};
1680
1681int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);