1 /* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
2 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
3 *
4 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Gareth Hughes <gareth@valinux.com>
29 *
30 */
31
32 #define __NO_VERSION__
33 #include "drmP.h"
34 #include "r128_drv.h"
35
36 #include <linux/interrupt.h> /* For task queue support */
37 #include <linux/delay.h>
38
39
40 /* FIXME: Temporary CCE packet buffer */
41 u32 r128_cce_buffer[(1 << 14)] __attribute__ ((aligned (32)));
42
43 /* CCE microcode (from ATI) */
44 static u32 r128_cce_microcode[] = {
45 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
46 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0,
47 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1,
48 11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11,
49 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28,
50 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9,
51 30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656,
52 1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1,
53 15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071,
54 12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2,
55 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1,
56 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
57 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1,
58 15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2,
59 268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1,
60 15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82,
61 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729,
62 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008,
63 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
64 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1,
65 180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1,
66 114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0,
67 33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370,
68 1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1,
69 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793,
70 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
71 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1,
72 114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1,
73 1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1,
74 1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894,
75 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14,
76 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1,
77 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1,
78 33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1,
79 409611, 9, 188, 0, 10240, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
85 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
86 };
87
88
89 #define DO_REMAP(_m, _d) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size, (_d))
90
91 #define DO_REMAPFREE(_m, _d) \
92 do { \
93 if ((_m)->handle && (_m)->size) \
94 drm_ioremapfree((_m)->handle, (_m)->size, (_d)); \
95 } while (0)
96
97 #define DO_FIND_MAP(_m, _o) \
98 do { \
99 int _i; \
100 for (_i = 0; _i < dev->map_count; _i++) { \
101 if (dev->maplist[_i]->offset == _o) { \
102 _m = dev->maplist[_i]; \
103 break; \
104 } \
105 } \
106 } while (0)
107
108
R128_READ_PLL(drm_device_t * dev,int addr)109 int R128_READ_PLL(drm_device_t *dev, int addr)
110 {
111 drm_r128_private_t *dev_priv = dev->dev_private;
112
113 R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
114 return R128_READ(R128_CLOCK_CNTL_DATA);
115 }
116
117 #if 0
118 static void r128_status( drm_r128_private_t *dev_priv )
119 {
120 printk( "GUI_STAT = 0x%08x\n",
121 (unsigned int)R128_READ( R128_GUI_STAT ) );
122 printk( "PM4_STAT = 0x%08x\n",
123 (unsigned int)R128_READ( R128_PM4_STAT ) );
124 printk( "PM4_BUFFER_DL_WPTR = 0x%08x\n",
125 (unsigned int)R128_READ( R128_PM4_BUFFER_DL_WPTR ) );
126 printk( "PM4_BUFFER_DL_RPTR = 0x%08x\n",
127 (unsigned int)R128_READ( R128_PM4_BUFFER_DL_RPTR ) );
128 printk( "PM4_MICRO_CNTL = 0x%08x\n",
129 (unsigned int)R128_READ( R128_PM4_MICRO_CNTL ) );
130 printk( "PM4_BUFFER_CNTL = 0x%08x\n",
131 (unsigned int)R128_READ( R128_PM4_BUFFER_CNTL ) );
132 }
133 #endif
134
135
136 /* ================================================================
137 * Engine, FIFO control
138 */
139
r128_do_pixcache_flush(drm_r128_private_t * dev_priv)140 static int r128_do_pixcache_flush( drm_r128_private_t *dev_priv )
141 {
142 u32 tmp;
143 int i;
144
145 tmp = R128_READ( R128_PC_NGUI_CTLSTAT ) | R128_PC_FLUSH_ALL;
146 R128_WRITE( R128_PC_NGUI_CTLSTAT, tmp );
147
148 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
149 if ( !(R128_READ( R128_PC_NGUI_CTLSTAT ) & R128_PC_BUSY) ) {
150 return 0;
151 }
152 udelay( 1 );
153 }
154
155 DRM_ERROR( "%s failed!\n", __FUNCTION__ );
156 return -EBUSY;
157 }
158
r128_do_wait_for_fifo(drm_r128_private_t * dev_priv,int entries)159 static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries )
160 {
161 int i;
162
163 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
164 int slots = R128_READ( R128_GUI_STAT ) & R128_GUI_FIFOCNT_MASK;
165 if ( slots >= entries ) return 0;
166 udelay( 1 );
167 }
168
169 DRM_ERROR( "%s failed!\n", __FUNCTION__ );
170 return -EBUSY;
171 }
172
r128_do_wait_for_idle(drm_r128_private_t * dev_priv)173 static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
174 {
175 int i, ret;
176
177 ret = r128_do_wait_for_fifo( dev_priv, 64 );
178 if ( !ret ) return ret;
179
180 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
181 if ( !(R128_READ( R128_GUI_STAT ) & R128_GUI_ACTIVE) ) {
182 r128_do_pixcache_flush( dev_priv );
183 return 0;
184 }
185 udelay( 1 );
186 }
187
188 DRM_ERROR( "%s failed!\n", __FUNCTION__ );
189 return -EBUSY;
190 }
191
192
193 /* ================================================================
194 * CCE control, initialization
195 */
196
197 /* Load the microcode for the CCE */
r128_cce_load_microcode(drm_r128_private_t * dev_priv)198 static void r128_cce_load_microcode( drm_r128_private_t *dev_priv )
199 {
200 int i;
201
202 r128_do_wait_for_idle( dev_priv );
203
204 R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 );
205 for ( i = 0 ; i < 256 ; i++ ) {
206 R128_WRITE( R128_PM4_MICROCODE_DATAH,
207 r128_cce_microcode[i * 2] );
208 R128_WRITE( R128_PM4_MICROCODE_DATAL,
209 r128_cce_microcode[i * 2 + 1] );
210 }
211 }
212
213 /* Flush any pending commands to the CCE. This should only be used just
214 * prior to a wait for idle, as it informs the engine that the command
215 * stream is ending.
216 */
r128_do_cce_flush(drm_r128_private_t * dev_priv)217 static void r128_do_cce_flush( drm_r128_private_t *dev_priv )
218 {
219 u32 tmp;
220
221 tmp = R128_READ( R128_PM4_BUFFER_DL_WPTR ) | R128_PM4_BUFFER_DL_DONE;
222 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, tmp );
223 }
224
225 /* Wait for the CCE to go idle.
226 */
r128_do_cce_idle(drm_r128_private_t * dev_priv)227 static int r128_do_cce_idle( drm_r128_private_t *dev_priv )
228 {
229 int i;
230
231 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
232 if ( *dev_priv->ring.head == dev_priv->ring.tail ) {
233 int pm4stat = R128_READ( R128_PM4_STAT );
234 if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
235 dev_priv->cce_fifo_size ) &&
236 !(pm4stat & (R128_PM4_BUSY |
237 R128_PM4_GUI_ACTIVE)) ) {
238 return r128_do_pixcache_flush( dev_priv );
239 }
240 }
241 udelay( 1 );
242 }
243
244 #if 0
245 DRM_ERROR( "failed!\n" );
246 r128_status( dev_priv );
247 #endif
248 return -EBUSY;
249 }
250
251 /* Start the Concurrent Command Engine.
252 */
r128_do_cce_start(drm_r128_private_t * dev_priv)253 static void r128_do_cce_start( drm_r128_private_t *dev_priv )
254 {
255 r128_do_wait_for_idle( dev_priv );
256
257 R128_WRITE( R128_PM4_BUFFER_CNTL,
258 dev_priv->cce_mode | dev_priv->ring.size_l2qw );
259 R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */
260 R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN );
261
262 dev_priv->cce_running = 1;
263 }
264
265 /* Reset the Concurrent Command Engine. This will not flush any pending
266 * commangs, so you must wait for the CCE command stream to complete
267 * before calling this routine.
268 */
r128_do_cce_reset(drm_r128_private_t * dev_priv)269 static void r128_do_cce_reset( drm_r128_private_t *dev_priv )
270 {
271 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
272 R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
273 *dev_priv->ring.head = 0;
274 dev_priv->ring.tail = 0;
275 }
276
277 /* Stop the Concurrent Command Engine. This will not flush any pending
278 * commangs, so you must flush the command stream and wait for the CCE
279 * to go idle before calling this routine.
280 */
r128_do_cce_stop(drm_r128_private_t * dev_priv)281 static void r128_do_cce_stop( drm_r128_private_t *dev_priv )
282 {
283 R128_WRITE( R128_PM4_MICRO_CNTL, 0 );
284 R128_WRITE( R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4 );
285
286 dev_priv->cce_running = 0;
287 }
288
289 /* Reset the engine. This will stop the CCE if it is running.
290 */
r128_do_engine_reset(drm_device_t * dev)291 static int r128_do_engine_reset( drm_device_t *dev )
292 {
293 drm_r128_private_t *dev_priv = dev->dev_private;
294 u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
295
296 r128_do_pixcache_flush( dev_priv );
297
298 clock_cntl_index = R128_READ( R128_CLOCK_CNTL_INDEX );
299 mclk_cntl = R128_READ_PLL( dev, R128_MCLK_CNTL );
300
301 R128_WRITE_PLL( R128_MCLK_CNTL,
302 mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP );
303
304 gen_reset_cntl = R128_READ( R128_GEN_RESET_CNTL );
305
306 /* Taken from the sample code - do not change */
307 R128_WRITE( R128_GEN_RESET_CNTL,
308 gen_reset_cntl | R128_SOFT_RESET_GUI );
309 R128_READ( R128_GEN_RESET_CNTL );
310 R128_WRITE( R128_GEN_RESET_CNTL,
311 gen_reset_cntl & ~R128_SOFT_RESET_GUI );
312 R128_READ( R128_GEN_RESET_CNTL );
313
314 R128_WRITE_PLL( R128_MCLK_CNTL, mclk_cntl );
315 R128_WRITE( R128_CLOCK_CNTL_INDEX, clock_cntl_index );
316 R128_WRITE( R128_GEN_RESET_CNTL, gen_reset_cntl );
317
318 /* Reset the CCE ring */
319 r128_do_cce_reset( dev_priv );
320
321 /* The CCE is no longer running after an engine reset */
322 dev_priv->cce_running = 0;
323
324 /* Reset any pending vertex, indirect buffers */
325 r128_freelist_reset( dev );
326
327 return 0;
328 }
329
r128_cce_init_ring_buffer(drm_device_t * dev)330 static void r128_cce_init_ring_buffer( drm_device_t *dev )
331 {
332 drm_r128_private_t *dev_priv = dev->dev_private;
333 u32 ring_start;
334 u32 tmp;
335
336 /* The manual (p. 2) says this address is in "VM space". This
337 * means it's an offset from the start of AGP space.
338 */
339 ring_start = dev_priv->cce_ring->offset - dev->agp->base;
340 R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
341
342 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
343 R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
344
345 /* DL_RPTR_ADDR is a physical address in AGP space. */
346 *dev_priv->ring.head = 0;
347 R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
348 dev_priv->ring_rptr->offset );
349
350 /* Set watermark control */
351 R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
352 ((R128_WATERMARK_L/4) << R128_WMA_SHIFT)
353 | ((R128_WATERMARK_M/4) << R128_WMB_SHIFT)
354 | ((R128_WATERMARK_N/4) << R128_WMC_SHIFT)
355 | ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT) );
356
357 /* Force read. Why? Because it's in the examples... */
358 R128_READ( R128_PM4_BUFFER_ADDR );
359
360 /* Turn on bus mastering */
361 tmp = R128_READ( R128_BUS_CNTL ) & ~R128_BUS_MASTER_DIS;
362 R128_WRITE( R128_BUS_CNTL, tmp );
363 }
364
r128_do_init_cce(drm_device_t * dev,drm_r128_init_t * init)365 static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
366 {
367 drm_r128_private_t *dev_priv;
368 int i;
369
370 dev_priv = drm_alloc( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
371 if ( dev_priv == NULL )
372 return -ENOMEM;
373 dev->dev_private = (void *)dev_priv;
374
375 memset( dev_priv, 0, sizeof(drm_r128_private_t) );
376
377 dev_priv->is_pci = init->is_pci;
378
379 /* GH: We don't support PCI cards until PCI GART is implemented.
380 * Fail here so we can remove all checks for PCI cards around
381 * the CCE ring code.
382 */
383 if ( dev_priv->is_pci ) {
384 drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
385 dev->dev_private = NULL;
386 return -EINVAL;
387 }
388
389 dev_priv->usec_timeout = init->usec_timeout;
390 if ( dev_priv->usec_timeout < 1 ||
391 dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
392 drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
393 dev->dev_private = NULL;
394 return -EINVAL;
395 }
396
397 dev_priv->cce_mode = init->cce_mode;
398 dev_priv->cce_secure = init->cce_secure;
399
400 /* GH: Simple idle check.
401 */
402 atomic_set( &dev_priv->idle_count, 0 );
403
404 /* We don't support anything other than bus-mastering ring mode,
405 * but the ring can be in either AGP or PCI space for the ring
406 * read pointer.
407 */
408 if ( ( init->cce_mode != R128_PM4_192BM ) &&
409 ( init->cce_mode != R128_PM4_128BM_64INDBM ) &&
410 ( init->cce_mode != R128_PM4_64BM_128INDBM ) &&
411 ( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
412 drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
413 dev->dev_private = NULL;
414 return -EINVAL;
415 }
416
417 switch ( init->cce_mode ) {
418 case R128_PM4_NONPM4:
419 dev_priv->cce_fifo_size = 0;
420 break;
421 case R128_PM4_192PIO:
422 case R128_PM4_192BM:
423 dev_priv->cce_fifo_size = 192;
424 break;
425 case R128_PM4_128PIO_64INDBM:
426 case R128_PM4_128BM_64INDBM:
427 dev_priv->cce_fifo_size = 128;
428 break;
429 case R128_PM4_64PIO_128INDBM:
430 case R128_PM4_64BM_128INDBM:
431 case R128_PM4_64PIO_64VCBM_64INDBM:
432 case R128_PM4_64BM_64VCBM_64INDBM:
433 case R128_PM4_64PIO_64VCPIO_64INDPIO:
434 dev_priv->cce_fifo_size = 64;
435 break;
436 }
437
438 dev_priv->fb_bpp = init->fb_bpp;
439 dev_priv->front_offset = init->front_offset;
440 dev_priv->front_pitch = init->front_pitch;
441 dev_priv->back_offset = init->back_offset;
442 dev_priv->back_pitch = init->back_pitch;
443
444 dev_priv->depth_bpp = init->depth_bpp;
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 /* FIXME: We want multiple shared areas, including one shared
460 * only by the X Server and kernel module.
461 */
462 for ( i = 0 ; i < dev->map_count ; i++ ) {
463 if ( dev->maplist[i]->type == _DRM_SHM ) {
464 dev_priv->sarea = dev->maplist[i];
465 break;
466 }
467 }
468
469 DO_FIND_MAP( dev_priv->fb, init->fb_offset );
470 DO_FIND_MAP( dev_priv->mmio, init->mmio_offset );
471 DO_FIND_MAP( dev_priv->cce_ring, init->ring_offset );
472 DO_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
473 DO_FIND_MAP( dev_priv->buffers, init->buffers_offset );
474
475 if ( !dev_priv->is_pci ) {
476 DO_FIND_MAP( dev_priv->agp_textures,
477 init->agp_textures_offset );
478 }
479
480 dev_priv->sarea_priv =
481 (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
482 init->sarea_priv_offset);
483
484 DO_REMAP( dev_priv->cce_ring, dev );
485 DO_REMAP( dev_priv->ring_rptr, dev );
486 DO_REMAP( dev_priv->buffers, dev );
487 #if 0
488 if ( !dev_priv->is_pci ) {
489 DO_REMAP( dev_priv->agp_textures, dev );
490 }
491 #endif
492
493 dev_priv->ring.head = ((__volatile__ u32 *)
494 dev_priv->ring_rptr->handle);
495
496 dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle;
497 dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle
498 + init->ring_size / sizeof(u32));
499 dev_priv->ring.size = init->ring_size;
500 dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
501
502 dev_priv->ring.tail_mask =
503 (dev_priv->ring.size / sizeof(u32)) - 1;
504
505 dev_priv->sarea_priv->last_frame = 0;
506 R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame );
507
508 dev_priv->sarea_priv->last_dispatch = 0;
509 R128_WRITE( R128_LAST_DISPATCH_REG,
510 dev_priv->sarea_priv->last_dispatch );
511
512 r128_cce_init_ring_buffer( dev );
513 r128_cce_load_microcode( dev_priv );
514 r128_do_engine_reset( dev );
515
516 return 0;
517 }
518
r128_do_cleanup_cce(drm_device_t * dev)519 static int r128_do_cleanup_cce( drm_device_t *dev )
520 {
521 if ( dev->dev_private ) {
522 drm_r128_private_t *dev_priv = dev->dev_private;
523
524 DO_REMAPFREE( dev_priv->cce_ring, dev );
525 DO_REMAPFREE( dev_priv->ring_rptr, dev );
526 DO_REMAPFREE( dev_priv->buffers, dev );
527 #if 0
528 if ( !dev_priv->is_pci ) {
529 DO_REMAPFREE( dev_priv->agp_textures, dev );
530 }
531 #endif
532
533 drm_free( dev->dev_private, sizeof(drm_r128_private_t),
534 DRM_MEM_DRIVER );
535 dev->dev_private = NULL;
536 }
537
538 return 0;
539 }
540
r128_cce_init(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)541 int r128_cce_init( struct inode *inode, struct file *filp,
542 unsigned int cmd, unsigned long arg )
543 {
544 drm_file_t *priv = filp->private_data;
545 drm_device_t *dev = priv->dev;
546 drm_r128_init_t init;
547
548 if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) )
549 return -EFAULT;
550
551 switch ( init.func ) {
552 case R128_INIT_CCE:
553 return r128_do_init_cce( dev, &init );
554 case R128_CLEANUP_CCE:
555 return r128_do_cleanup_cce( dev );
556 }
557
558 return -EINVAL;
559 }
560
r128_cce_start(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)561 int r128_cce_start( struct inode *inode, struct file *filp,
562 unsigned int cmd, unsigned long arg )
563 {
564 drm_file_t *priv = filp->private_data;
565 drm_device_t *dev = priv->dev;
566 drm_r128_private_t *dev_priv = dev->dev_private;
567 DRM_DEBUG( "%s\n", __FUNCTION__ );
568
569 if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
570 dev->lock.pid != current->pid ) {
571 DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
572 return -EINVAL;
573 }
574 if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) {
575 DRM_DEBUG( "%s while CCE running\n", __FUNCTION__ );
576 return 0;
577 }
578
579 r128_do_cce_start( dev_priv );
580
581 return 0;
582 }
583
584 /* Stop the CCE. The engine must have been idled before calling this
585 * routine.
586 */
r128_cce_stop(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)587 int r128_cce_stop( struct inode *inode, struct file *filp,
588 unsigned int cmd, unsigned long arg )
589 {
590 drm_file_t *priv = filp->private_data;
591 drm_device_t *dev = priv->dev;
592 drm_r128_private_t *dev_priv = dev->dev_private;
593 drm_r128_cce_stop_t stop;
594 int ret;
595 DRM_DEBUG( "%s\n", __FUNCTION__ );
596
597 if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
598 dev->lock.pid != current->pid ) {
599 DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
600 return -EINVAL;
601 }
602
603 if ( copy_from_user( &stop, (drm_r128_init_t *)arg, sizeof(stop) ) )
604 return -EFAULT;
605
606 /* Flush any pending CCE commands. This ensures any outstanding
607 * commands are exectuted by the engine before we turn it off.
608 */
609 if ( stop.flush ) {
610 r128_do_cce_flush( dev_priv );
611 }
612
613 /* If we fail to make the engine go idle, we return an error
614 * code so that the DRM ioctl wrapper can try again.
615 */
616 if ( stop.idle ) {
617 ret = r128_do_cce_idle( dev_priv );
618 if ( ret < 0 ) return ret;
619 }
620
621 /* Finally, we can turn off the CCE. If the engine isn't idle,
622 * we will get some dropped triangles as they won't be fully
623 * rendered before the CCE is shut down.
624 */
625 r128_do_cce_stop( dev_priv );
626
627 /* Reset the engine */
628 r128_do_engine_reset( dev );
629
630 return 0;
631 }
632
633 /* Just reset the CCE ring. Called as part of an X Server engine reset.
634 */
r128_cce_reset(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)635 int r128_cce_reset( struct inode *inode, struct file *filp,
636 unsigned int cmd, unsigned long arg )
637 {
638 drm_file_t *priv = filp->private_data;
639 drm_device_t *dev = priv->dev;
640 drm_r128_private_t *dev_priv = dev->dev_private;
641 DRM_DEBUG( "%s\n", __FUNCTION__ );
642
643 if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
644 dev->lock.pid != current->pid ) {
645 DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
646 return -EINVAL;
647 }
648 if ( !dev_priv ) {
649 DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
650 return -EINVAL;
651 }
652
653 r128_do_cce_reset( dev_priv );
654
655 /* The CCE is no longer running after an engine reset */
656 dev_priv->cce_running = 0;
657
658 return 0;
659 }
660
r128_cce_idle(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)661 int r128_cce_idle( struct inode *inode, struct file *filp,
662 unsigned int cmd, unsigned long arg )
663 {
664 drm_file_t *priv = filp->private_data;
665 drm_device_t *dev = priv->dev;
666 drm_r128_private_t *dev_priv = dev->dev_private;
667 DRM_DEBUG( "%s\n", __FUNCTION__ );
668
669 if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
670 dev->lock.pid != current->pid ) {
671 DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
672 return -EINVAL;
673 }
674
675 if ( dev_priv->cce_running ) {
676 r128_do_cce_flush( dev_priv );
677 }
678
679 return r128_do_cce_idle( dev_priv );
680 }
681
r128_engine_reset(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)682 int r128_engine_reset( struct inode *inode, struct file *filp,
683 unsigned int cmd, unsigned long arg )
684 {
685 drm_file_t *priv = filp->private_data;
686 drm_device_t *dev = priv->dev;
687 DRM_DEBUG( "%s\n", __FUNCTION__ );
688
689 if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
690 dev->lock.pid != current->pid ) {
691 DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
692 return -EINVAL;
693 }
694
695 return r128_do_engine_reset( dev );
696 }
697
698
699 /* ================================================================
700 * Freelist management
701 */
702 #define R128_BUFFER_USED 0xffffffff
703 #define R128_BUFFER_FREE 0
704
705 #if 0
706 static int r128_freelist_init( drm_device_t *dev )
707 {
708 drm_device_dma_t *dma = dev->dma;
709 drm_r128_private_t *dev_priv = dev->dev_private;
710 drm_buf_t *buf;
711 drm_r128_buf_priv_t *buf_priv;
712 drm_r128_freelist_t *entry;
713 int i;
714
715 dev_priv->head = drm_alloc( sizeof(drm_r128_freelist_t),
716 DRM_MEM_DRIVER );
717 if ( dev_priv->head == NULL )
718 return -ENOMEM;
719
720 memset( dev_priv->head, 0, sizeof(drm_r128_freelist_t) );
721 dev_priv->head->age = R128_BUFFER_USED;
722
723 for ( i = 0 ; i < dma->buf_count ; i++ ) {
724 buf = dma->buflist[i];
725 buf_priv = buf->dev_private;
726
727 entry = drm_alloc( sizeof(drm_r128_freelist_t),
728 DRM_MEM_DRIVER );
729 if ( !entry ) return -ENOMEM;
730
731 entry->age = R128_BUFFER_FREE;
732 entry->buf = buf;
733 entry->prev = dev_priv->head;
734 entry->next = dev_priv->head->next;
735 if ( !entry->next )
736 dev_priv->tail = entry;
737
738 buf_priv->discard = 0;
739 buf_priv->dispatched = 0;
740 buf_priv->list_entry = entry;
741
742 dev_priv->head->next = entry;
743
744 if ( dev_priv->head->next )
745 dev_priv->head->next->prev = entry;
746 }
747
748 return 0;
749
750 }
751 #endif
752
r128_freelist_get(drm_device_t * dev)753 drm_buf_t *r128_freelist_get( drm_device_t *dev )
754 {
755 drm_device_dma_t *dma = dev->dma;
756 drm_r128_private_t *dev_priv = dev->dev_private;
757 drm_r128_buf_priv_t *buf_priv;
758 drm_buf_t *buf;
759 int i, t;
760
761 /* FIXME: Optimize -- use freelist code */
762
763 for ( i = 0 ; i < dma->buf_count ; i++ ) {
764 buf = dma->buflist[i];
765 buf_priv = buf->dev_private;
766 if ( buf->pid == 0 )
767 return buf;
768 }
769
770 for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
771 u32 done_age = R128_READ( R128_LAST_DISPATCH_REG );
772
773 for ( i = 0 ; i < dma->buf_count ; i++ ) {
774 buf = dma->buflist[i];
775 buf_priv = buf->dev_private;
776 if ( buf->pending && buf_priv->age <= done_age ) {
777 /* The buffer has been processed, so it
778 * can now be used.
779 */
780 buf->pending = 0;
781 return buf;
782 }
783 }
784 udelay( 1 );
785 }
786
787 DRM_ERROR( "returning NULL!\n" );
788 return NULL;
789 }
790
r128_freelist_reset(drm_device_t * dev)791 void r128_freelist_reset( drm_device_t *dev )
792 {
793 drm_device_dma_t *dma = dev->dma;
794 int i;
795
796 for ( i = 0 ; i < dma->buf_count ; i++ ) {
797 drm_buf_t *buf = dma->buflist[i];
798 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
799 buf_priv->age = 0;
800 }
801 }
802
803
804 /* ================================================================
805 * CCE packet submission
806 */
807
r128_wait_ring(drm_r128_private_t * dev_priv,int n)808 int r128_wait_ring( drm_r128_private_t *dev_priv, int n )
809 {
810 drm_r128_ring_buffer_t *ring = &dev_priv->ring;
811 int i;
812
813 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
814 ring->space = *ring->head - ring->tail;
815 if ( ring->space <= 0 )
816 ring->space += ring->size;
817
818 if ( ring->space >= n )
819 return 0;
820
821 udelay( 1 );
822 }
823
824 return -EBUSY;
825 }
826
r128_update_ring_snapshot(drm_r128_private_t * dev_priv)827 void r128_update_ring_snapshot( drm_r128_private_t *dev_priv )
828 {
829 drm_r128_ring_buffer_t *ring = &dev_priv->ring;
830
831 ring->space = *ring->head - ring->tail;
832 #if R128_PERFORMANCE_BOXES
833 if ( ring->space == 0 )
834 atomic_inc( &dev_priv->idle_count );
835 #endif
836 if ( ring->space <= 0 )
837 ring->space += ring->size;
838 }
839
840 #if 0
841 static int r128_verify_command( drm_r128_private_t *dev_priv,
842 u32 cmd, int *size )
843 {
844 int writing = 1;
845
846 *size = 0;
847
848 switch ( cmd & R128_CCE_PACKET_MASK ) {
849 case R128_CCE_PACKET0:
850 if ( (cmd & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2) &&
851 (cmd & R128_CCE_PACKET0_REG_MASK) !=
852 (R128_PM4_VC_FPU_SETUP >> 2) ) {
853 writing = 0;
854 }
855 *size = ((cmd & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
856 break;
857
858 case R128_CCE_PACKET1:
859 if ( (cmd & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2) &&
860 (cmd & R128_CCE_PACKET1_REG0_MASK) !=
861 (R128_PM4_VC_FPU_SETUP >> 2) ) {
862 writing = 0;
863 }
864 if ( (cmd & R128_CCE_PACKET1_REG1_MASK) <= (0x1004 << 9) &&
865 (cmd & R128_CCE_PACKET1_REG1_MASK) !=
866 (R128_PM4_VC_FPU_SETUP << 9) ) {
867 writing = 0;
868 }
869 *size = 3;
870 break;
871
872 case R128_CCE_PACKET2:
873 break;
874
875 case R128_CCE_PACKET3:
876 *size = ((cmd & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
877 break;
878
879 }
880
881 return writing;
882 }
883
884 static int r128_submit_packet_ring_secure( drm_r128_private_t *dev_priv,
885 u32 *commands, int *count )
886 {
887 #if 0
888 int write = dev_priv->sarea_priv->ring_write;
889 int *write_ptr = dev_priv->ring_start + write;
890 int c = *count;
891 u32 tmp = 0;
892 int psize = 0;
893 int writing = 1;
894 int timeout;
895
896 while ( c > 0 ) {
897 tmp = *commands++;
898 if ( !psize ) {
899 writing = r128_verify_command( dev_priv, tmp, &psize );
900 }
901 psize--;
902
903 if ( writing ) {
904 write++;
905 *write_ptr++ = tmp;
906 }
907 if ( write >= dev_priv->ring_entries ) {
908 write = 0;
909 write_ptr = dev_priv->ring_start;
910 }
911 timeout = 0;
912 while ( write == *dev_priv->ring_read_ptr ) {
913 R128_READ( R128_PM4_BUFFER_DL_RPTR );
914 if ( timeout++ >= dev_priv->usec_timeout )
915 return -EBUSY;
916 udelay( 1 );
917 }
918 c--;
919 }
920
921 if ( write < 32 ) {
922 memcpy( dev_priv->ring_end,
923 dev_priv->ring_start,
924 write * sizeof(u32) );
925 }
926
927 /* Make sure WC cache has been flushed */
928 r128_flush_write_combine();
929
930 dev_priv->sarea_priv->ring_write = write;
931 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write );
932
933 *count = 0;
934 #endif
935 return 0;
936 }
937
938 static int r128_submit_packet_ring_insecure( drm_r128_private_t *dev_priv,
939 u32 *commands, int *count )
940 {
941 #if 0
942 int write = dev_priv->sarea_priv->ring_write;
943 int *write_ptr = dev_priv->ring_start + write;
944 int c = *count;
945 int timeout;
946
947 while ( c > 0 ) {
948 write++;
949 *write_ptr++ = *commands++;
950 if ( write >= dev_priv->ring_entries ) {
951 write = 0;
952 write_ptr = dev_priv->ring_start;
953 }
954
955 timeout = 0;
956 while ( write == *dev_priv->ring_read_ptr ) {
957 R128_READ( R128_PM4_BUFFER_DL_RPTR );
958 if ( timeout++ >= dev_priv->usec_timeout )
959 return -EBUSY;
960 udelay( 1 );
961 }
962 c--;
963 }
964
965 if ( write < 32 ) {
966 memcpy( dev_priv->ring_end,
967 dev_priv->ring_start,
968 write * sizeof(u32) );
969 }
970
971 /* Make sure WC cache has been flushed */
972 r128_flush_write_combine();
973
974 dev_priv->sarea_priv->ring_write = write;
975 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write );
976
977 *count = 0;
978 #endif
979 return 0;
980 }
981 #endif
982
983 /* Internal packet submission routine. This uses the insecure versions
984 * of the packet submission functions, and thus should only be used for
985 * packets generated inside the kernel module.
986 */
r128_do_submit_packet(drm_r128_private_t * dev_priv,u32 * buffer,int count)987 int r128_do_submit_packet( drm_r128_private_t *dev_priv,
988 u32 *buffer, int count )
989 {
990 int c = count;
991 int ret = 0;
992
993 #if 0
994 int left = 0;
995
996 if ( c >= dev_priv->ring_entries ) {
997 c = dev_priv->ring_entries - 1;
998 left = count - c;
999 }
1000
1001 /* Since this is only used by the kernel we can use the
1002 * insecure ring buffer submit packet routine.
1003 */
1004 ret = r128_submit_packet_ring_insecure( dev_priv, buffer, &c );
1005 c += left;
1006 #endif
1007
1008 return ( ret < 0 ) ? ret : c;
1009 }
1010
1011 /* External packet submission routine. This uses the secure versions
1012 * by default, and can thus submit packets received from user space.
1013 */
r128_cce_packet(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)1014 int r128_cce_packet( struct inode *inode, struct file *filp,
1015 unsigned int cmd, unsigned long arg )
1016 {
1017 drm_file_t *priv = filp->private_data;
1018 drm_device_t *dev = priv->dev;
1019 drm_r128_private_t *dev_priv = dev->dev_private;
1020 drm_r128_packet_t packet;
1021 u32 *buffer;
1022 int c;
1023 int size;
1024 int ret = 0;
1025
1026 #if 0
1027 /* GH: Disable packet submission for now.
1028 */
1029 return -EINVAL;
1030 #endif
1031
1032 if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
1033 dev->lock.pid != current->pid ) {
1034 DRM_ERROR( "r128_submit_packet called without lock held\n" );
1035 return -EINVAL;
1036 }
1037
1038 if ( copy_from_user( &packet, (drm_r128_packet_t *)arg,
1039 sizeof(packet) ) )
1040 return -EFAULT;
1041
1042 #if 0
1043 c = packet.count;
1044 size = c * sizeof(*buffer);
1045
1046 {
1047 int left = 0;
1048
1049 if ( c >= dev_priv->ring_entries ) {
1050 c = dev_priv->ring_entries - 1;
1051 size = c * sizeof(*buffer);
1052 left = packet.count - c;
1053 }
1054
1055 buffer = kmalloc( size, 0 );
1056 if ( buffer == NULL)
1057 return -ENOMEM;
1058 if ( copy_from_user( buffer, packet.buffer, size ) )
1059 return -EFAULT;
1060
1061 if ( dev_priv->cce_secure ) {
1062 ret = r128_submit_packet_ring_secure( dev_priv,
1063 buffer, &c );
1064 } else {
1065 ret = r128_submit_packet_ring_insecure( dev_priv,
1066 buffer, &c );
1067 }
1068 c += left;
1069 }
1070
1071 kfree( buffer );
1072 #else
1073 c = 0;
1074 #endif
1075
1076 packet.count = c;
1077 if ( copy_to_user( (drm_r128_packet_t *)arg, &packet,
1078 sizeof(packet) ) )
1079 return -EFAULT;
1080
1081 if ( ret ) {
1082 return ret;
1083 } else if ( c > 0 ) {
1084 return -EAGAIN;
1085 }
1086 return 0;
1087 }
1088
1089 #if 0
1090 static int r128_send_vertbufs( drm_device_t *dev, drm_r128_vertex_t *v )
1091 {
1092 drm_device_dma_t *dma = dev->dma;
1093 drm_r128_private_t *dev_priv = dev->dev_private;
1094 drm_r128_buf_priv_t *buf_priv;
1095 drm_buf_t *buf;
1096 int i, ret;
1097 RING_LOCALS;
1098
1099 /* Make sure we have valid data */
1100 for (i = 0; i < v->send_count; i++) {
1101 int idx = v->send_indices[i];
1102
1103 if (idx < 0 || idx >= dma->buf_count) {
1104 DRM_ERROR("Index %d (of %d max)\n",
1105 idx, dma->buf_count - 1);
1106 return -EINVAL;
1107 }
1108 buf = dma->buflist[idx];
1109 if (buf->pid != current->pid) {
1110 DRM_ERROR("Process %d using buffer owned by %d\n",
1111 current->pid, buf->pid);
1112 return -EINVAL;
1113 }
1114 if (buf->pending) {
1115 DRM_ERROR("Sending pending buffer:"
1116 " buffer %d, offset %d\n",
1117 v->send_indices[i], i);
1118 return -EINVAL;
1119 }
1120 }
1121
1122 /* Wait for idle, if we've wrapped to make sure that all pending
1123 buffers have been processed */
1124 if (dev_priv->submit_age == R128_MAX_VBUF_AGE) {
1125 if ((ret = r128_do_cce_idle(dev)) < 0) return ret;
1126 dev_priv->submit_age = 0;
1127 r128_freelist_reset(dev);
1128 }
1129
1130 /* Make sure WC cache has been flushed (if in PIO mode) */
1131 if (!dev_priv->cce_is_bm_mode) r128_flush_write_combine();
1132
1133 /* FIXME: Add support for sending vertex buffer to the CCE here
1134 instead of in client code. The v->prim holds the primitive
1135 type that should be drawn. Loop over the list buffers in
1136 send_indices[] and submit a packet for each VB.
1137
1138 This will require us to loop over the clip rects here as
1139 well, which implies that we extend the kernel driver to allow
1140 cliprects to be stored here. Note that the cliprects could
1141 possibly come from the X server instead of the client, but
1142 this will require additional changes to the DRI to allow for
1143 this optimization. */
1144
1145 /* Submit a CCE packet that writes submit_age to R128_VB_AGE_REG */
1146 #if 0
1147 cce_buffer[0] = R128CCE0(R128_CCE_PACKET0, R128_VB_AGE_REG, 0);
1148 cce_buffer[1] = dev_priv->submit_age;
1149
1150 if ((ret = r128_do_submit_packet(dev, cce_buffer, 2)) < 0) {
1151 /* Until we add support for sending VBs to the CCE in
1152 this routine, we can recover from this error. After
1153 we add that support, we won't be able to easily
1154 recover, so we will probably have to implement
1155 another mechanism for handling timeouts from packets
1156 submitted directly by the kernel. */
1157 return ret;
1158 }
1159 #else
1160 BEGIN_RING( 2 );
1161
1162 OUT_RING( CCE_PACKET0( R128_VB_AGE_REG, 0 ) );
1163 OUT_RING( dev_priv->submit_age );
1164
1165 ADVANCE_RING();
1166 #endif
1167 /* Now that the submit packet request has succeeded, we can mark
1168 the buffers as pending */
1169 for (i = 0; i < v->send_count; i++) {
1170 buf = dma->buflist[v->send_indices[i]];
1171 buf->pending = 1;
1172
1173 buf_priv = buf->dev_private;
1174 buf_priv->age = dev_priv->submit_age;
1175 }
1176
1177 dev_priv->submit_age++;
1178
1179 return 0;
1180 }
1181 #endif
1182
1183
1184
1185
r128_cce_get_buffers(drm_device_t * dev,drm_dma_t * d)1186 static int r128_cce_get_buffers( drm_device_t *dev, drm_dma_t *d )
1187 {
1188 int i;
1189 drm_buf_t *buf;
1190
1191 for ( i = d->granted_count ; i < d->request_count ; i++ ) {
1192 buf = r128_freelist_get( dev );
1193 if ( !buf ) return -EAGAIN;
1194
1195 buf->pid = current->pid;
1196
1197 if ( copy_to_user( &d->request_indices[i], &buf->idx,
1198 sizeof(buf->idx) ) )
1199 return -EFAULT;
1200 if ( copy_to_user( &d->request_sizes[i], &buf->total,
1201 sizeof(buf->total) ) )
1202 return -EFAULT;
1203
1204 d->granted_count++;
1205 }
1206 return 0;
1207 }
1208
r128_cce_buffers(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)1209 int r128_cce_buffers( struct inode *inode, struct file *filp,
1210 unsigned int cmd, unsigned long arg )
1211 {
1212 drm_file_t *priv = filp->private_data;
1213 drm_device_t *dev = priv->dev;
1214 drm_device_dma_t *dma = dev->dma;
1215 int ret = 0;
1216 drm_dma_t d;
1217
1218 if ( copy_from_user( &d, (drm_dma_t *) arg, sizeof(d) ) )
1219 return -EFAULT;
1220
1221 if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
1222 dev->lock.pid != current->pid ) {
1223 DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
1224 return -EINVAL;
1225 }
1226
1227 /* Please don't send us buffers.
1228 */
1229 if ( d.send_count != 0 ) {
1230 DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
1231 current->pid, d.send_count );
1232 return -EINVAL;
1233 }
1234
1235 /* We'll send you buffers.
1236 */
1237 if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
1238 DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
1239 current->pid, d.request_count, dma->buf_count );
1240 return -EINVAL;
1241 }
1242
1243 d.granted_count = 0;
1244
1245 if ( d.request_count ) {
1246 ret = r128_cce_get_buffers( dev, &d );
1247 }
1248
1249 if ( copy_to_user( (drm_dma_t *) arg, &d, sizeof(d) ) )
1250 return -EFAULT;
1251
1252 return ret;
1253 }
1254