aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/r128
diff options
context:
space:
mode:
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);