FreeBSD/Linux Kernel Cross Reference
sys/dev/drm/r128_cce.c
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 * $FreeBSD$
31 */
32
33 #include "dev/drm/r128.h"
34 #include "dev/drm/drmP.h"
35 #include "dev/drm/drm.h"
36 #include "dev/drm/r128_drm.h"
37 #include "dev/drm/r128_drv.h"
38
39 #define R128_FIFO_DEBUG 0
40
41 /* CCE microcode (from ATI) */
42 static u32 r128_cce_microcode[] = {
43 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
44 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0,
45 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1,
46 11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11,
47 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28,
48 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9,
49 30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656,
50 1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1,
51 15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071,
52 12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2,
53 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1,
54 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
55 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1,
56 15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2,
57 268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1,
58 15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82,
59 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729,
60 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008,
61 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
62 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1,
63 180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1,
64 114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0,
65 33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370,
66 1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1,
67 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793,
68 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
69 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1,
70 114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1,
71 1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1,
72 1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894,
73 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14,
74 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1,
75 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1,
76 33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1,
77 409611, 9, 188, 0, 10240, 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, 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
84 };
85
86 int R128_READ_PLL(drm_device_t *dev, int addr)
87 {
88 drm_r128_private_t *dev_priv = dev->dev_private;
89
90 R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
91 return R128_READ(R128_CLOCK_CNTL_DATA);
92 }
93
94 #if R128_FIFO_DEBUG
95 static void r128_status( drm_r128_private_t *dev_priv )
96 {
97 printk( "GUI_STAT = 0x%08x\n",
98 (unsigned int)R128_READ( R128_GUI_STAT ) );
99 printk( "PM4_STAT = 0x%08x\n",
100 (unsigned int)R128_READ( R128_PM4_STAT ) );
101 printk( "PM4_BUFFER_DL_WPTR = 0x%08x\n",
102 (unsigned int)R128_READ( R128_PM4_BUFFER_DL_WPTR ) );
103 printk( "PM4_BUFFER_DL_RPTR = 0x%08x\n",
104 (unsigned int)R128_READ( R128_PM4_BUFFER_DL_RPTR ) );
105 printk( "PM4_MICRO_CNTL = 0x%08x\n",
106 (unsigned int)R128_READ( R128_PM4_MICRO_CNTL ) );
107 printk( "PM4_BUFFER_CNTL = 0x%08x\n",
108 (unsigned int)R128_READ( R128_PM4_BUFFER_CNTL ) );
109 }
110 #endif
111
112
113 /* ================================================================
114 * Engine, FIFO control
115 */
116
117 static int r128_do_pixcache_flush( drm_r128_private_t *dev_priv )
118 {
119 u32 tmp;
120 int i;
121
122 tmp = R128_READ( R128_PC_NGUI_CTLSTAT ) | R128_PC_FLUSH_ALL;
123 R128_WRITE( R128_PC_NGUI_CTLSTAT, tmp );
124
125 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
126 if ( !(R128_READ( R128_PC_NGUI_CTLSTAT ) & R128_PC_BUSY) ) {
127 return 0;
128 }
129 DRM_UDELAY( 1 );
130 }
131
132 #if R128_FIFO_DEBUG
133 DRM_ERROR( "failed!\n" );
134 #endif
135 return DRM_ERR(EBUSY);
136 }
137
138 static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries )
139 {
140 int i;
141
142 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
143 int slots = R128_READ( R128_GUI_STAT ) & R128_GUI_FIFOCNT_MASK;
144 if ( slots >= entries ) return 0;
145 DRM_UDELAY( 1 );
146 }
147
148 #if R128_FIFO_DEBUG
149 DRM_ERROR( "failed!\n" );
150 #endif
151 return DRM_ERR(EBUSY);
152 }
153
154 static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
155 {
156 int i, ret;
157
158 ret = r128_do_wait_for_fifo( dev_priv, 64 );
159 if ( ret ) return ret;
160
161 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
162 if ( !(R128_READ( R128_GUI_STAT ) & R128_GUI_ACTIVE) ) {
163 r128_do_pixcache_flush( dev_priv );
164 return 0;
165 }
166 DRM_UDELAY( 1 );
167 }
168
169 #if R128_FIFO_DEBUG
170 DRM_ERROR( "failed!\n" );
171 #endif
172 return DRM_ERR(EBUSY);
173 }
174
175
176 /* ================================================================
177 * CCE control, initialization
178 */
179
180 /* Load the microcode for the CCE */
181 static void r128_cce_load_microcode( drm_r128_private_t *dev_priv )
182 {
183 int i;
184
185 DRM_DEBUG( "\n" );
186
187 r128_do_wait_for_idle( dev_priv );
188
189 R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 );
190 for ( i = 0 ; i < 256 ; i++ ) {
191 R128_WRITE( R128_PM4_MICROCODE_DATAH,
192 r128_cce_microcode[i * 2] );
193 R128_WRITE( R128_PM4_MICROCODE_DATAL,
194 r128_cce_microcode[i * 2 + 1] );
195 }
196 }
197
198 /* Flush any pending commands to the CCE. This should only be used just
199 * prior to a wait for idle, as it informs the engine that the command
200 * stream is ending.
201 */
202 static void r128_do_cce_flush( drm_r128_private_t *dev_priv )
203 {
204 u32 tmp;
205
206 tmp = R128_READ( R128_PM4_BUFFER_DL_WPTR ) | R128_PM4_BUFFER_DL_DONE;
207 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, tmp );
208 }
209
210 /* Wait for the CCE to go idle.
211 */
212 int r128_do_cce_idle( drm_r128_private_t *dev_priv )
213 {
214 int i;
215
216 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
217 if ( GET_RING_HEAD( dev_priv ) == dev_priv->ring.tail ) {
218 int pm4stat = R128_READ( R128_PM4_STAT );
219 if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
220 dev_priv->cce_fifo_size ) &&
221 !(pm4stat & (R128_PM4_BUSY |
222 R128_PM4_GUI_ACTIVE)) ) {
223 return r128_do_pixcache_flush( dev_priv );
224 }
225 }
226 DRM_UDELAY( 1 );
227 }
228
229 #if R128_FIFO_DEBUG
230 DRM_ERROR( "failed!\n" );
231 r128_status( dev_priv );
232 #endif
233 return DRM_ERR(EBUSY);
234 }
235
236 /* Start the Concurrent Command Engine.
237 */
238 static void r128_do_cce_start( drm_r128_private_t *dev_priv )
239 {
240 r128_do_wait_for_idle( dev_priv );
241
242 R128_WRITE( R128_PM4_BUFFER_CNTL,
243 dev_priv->cce_mode | dev_priv->ring.size_l2qw
244 | R128_PM4_BUFFER_CNTL_NOUPDATE );
245 R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */
246 R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN );
247
248 dev_priv->cce_running = 1;
249 }
250
251 /* Reset the Concurrent Command Engine. This will not flush any pending
252 * commands, so you must wait for the CCE command stream to complete
253 * before calling this routine.
254 */
255 static void r128_do_cce_reset( drm_r128_private_t *dev_priv )
256 {
257 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
258 R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
259 dev_priv->ring.tail = 0;
260 }
261
262 /* Stop the Concurrent Command Engine. This will not flush any pending
263 * commands, so you must flush the command stream and wait for the CCE
264 * to go idle before calling this routine.
265 */
266 static void r128_do_cce_stop( drm_r128_private_t *dev_priv )
267 {
268 R128_WRITE( R128_PM4_MICRO_CNTL, 0 );
269 R128_WRITE( R128_PM4_BUFFER_CNTL,
270 R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE );
271
272 dev_priv->cce_running = 0;
273 }
274
275 /* Reset the engine. This will stop the CCE if it is running.
276 */
277 static int r128_do_engine_reset( drm_device_t *dev )
278 {
279 drm_r128_private_t *dev_priv = dev->dev_private;
280 u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
281
282 r128_do_pixcache_flush( dev_priv );
283
284 clock_cntl_index = R128_READ( R128_CLOCK_CNTL_INDEX );
285 mclk_cntl = R128_READ_PLL( dev, R128_MCLK_CNTL );
286
287 R128_WRITE_PLL( R128_MCLK_CNTL,
288 mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP );
289
290 gen_reset_cntl = R128_READ( R128_GEN_RESET_CNTL );
291
292 /* Taken from the sample code - do not change */
293 R128_WRITE( R128_GEN_RESET_CNTL,
294 gen_reset_cntl | R128_SOFT_RESET_GUI );
295 R128_READ( R128_GEN_RESET_CNTL );
296 R128_WRITE( R128_GEN_RESET_CNTL,
297 gen_reset_cntl & ~R128_SOFT_RESET_GUI );
298 R128_READ( R128_GEN_RESET_CNTL );
299
300 R128_WRITE_PLL( R128_MCLK_CNTL, mclk_cntl );
301 R128_WRITE( R128_CLOCK_CNTL_INDEX, clock_cntl_index );
302 R128_WRITE( R128_GEN_RESET_CNTL, gen_reset_cntl );
303
304 /* Reset the CCE ring */
305 r128_do_cce_reset( dev_priv );
306
307 /* The CCE is no longer running after an engine reset */
308 dev_priv->cce_running = 0;
309
310 /* Reset any pending vertex, indirect buffers */
311 r128_freelist_reset( dev );
312
313 return 0;
314 }
315
316 static void r128_cce_init_ring_buffer( drm_device_t *dev,
317 drm_r128_private_t *dev_priv )
318 {
319 u32 ring_start;
320 u32 tmp;
321
322 DRM_DEBUG( "\n" );
323
324 /* The manual (p. 2) says this address is in "VM space". This
325 * means it's an offset from the start of AGP space.
326 */
327 #if __REALLY_HAVE_AGP
328 if ( !dev_priv->is_pci )
329 ring_start = dev_priv->cce_ring->offset - dev->agp->base;
330 else
331 #endif
332 ring_start = dev_priv->cce_ring->offset - dev->sg->handle;
333
334 R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
335
336 R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
337 R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
338
339 /* Set watermark control */
340 R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
341 ((R128_WATERMARK_L/4) << R128_WMA_SHIFT)
342 | ((R128_WATERMARK_M/4) << R128_WMB_SHIFT)
343 | ((R128_WATERMARK_N/4) << R128_WMC_SHIFT)
344 | ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT) );
345
346 /* Force read. Why? Because it's in the examples... */
347 R128_READ( R128_PM4_BUFFER_ADDR );
348
349 /* Turn on bus mastering */
350 tmp = R128_READ( R128_BUS_CNTL ) & ~R128_BUS_MASTER_DIS;
351 R128_WRITE( R128_BUS_CNTL, tmp );
352 }
353
354 static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
355 {
356 drm_r128_private_t *dev_priv;
357
358 DRM_DEBUG( "\n" );
359
360 dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
361 if ( dev_priv == NULL )
362 return DRM_ERR(ENOMEM);
363
364 memset( dev_priv, 0, sizeof(drm_r128_private_t) );
365
366 dev_priv->is_pci = init->is_pci;
367
368 if ( dev_priv->is_pci && !dev->sg ) {
369 DRM_ERROR( "PCI GART memory not allocated!\n" );
370 dev->dev_private = (void *)dev_priv;
371 r128_do_cleanup_cce( dev );
372 return DRM_ERR(EINVAL);
373 }
374
375 dev_priv->usec_timeout = init->usec_timeout;
376 if ( dev_priv->usec_timeout < 1 ||
377 dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
378 DRM_DEBUG( "TIMEOUT problem!\n" );
379 dev->dev_private = (void *)dev_priv;
380 r128_do_cleanup_cce( dev );
381 return DRM_ERR(EINVAL);
382 }
383
384 dev_priv->cce_mode = init->cce_mode;
385
386 /* GH: Simple idle check.
387 */
388 atomic_set( &dev_priv->idle_count, 0 );
389
390 /* We don't support anything other than bus-mastering ring mode,
391 * but the ring can be in either AGP or PCI space for the ring
392 * read pointer.
393 */
394 if ( ( init->cce_mode != R128_PM4_192BM ) &&
395 ( init->cce_mode != R128_PM4_128BM_64INDBM ) &&
396 ( init->cce_mode != R128_PM4_64BM_128INDBM ) &&
397 ( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
398 DRM_DEBUG( "Bad cce_mode!\n" );
399 dev->dev_private = (void *)dev_priv;
400 r128_do_cleanup_cce( dev );
401 return DRM_ERR(EINVAL);
402 }
403
404 switch ( init->cce_mode ) {
405 case R128_PM4_NONPM4:
406 dev_priv->cce_fifo_size = 0;
407 break;
408 case R128_PM4_192PIO:
409 case R128_PM4_192BM:
410 dev_priv->cce_fifo_size = 192;
411 break;
412 case R128_PM4_128PIO_64INDBM:
413 case R128_PM4_128BM_64INDBM:
414 dev_priv->cce_fifo_size = 128;
415 break;
416 case R128_PM4_64PIO_128INDBM:
417 case R128_PM4_64BM_128INDBM:
418 case R128_PM4_64PIO_64VCBM_64INDBM:
419 case R128_PM4_64BM_64VCBM_64INDBM:
420 case R128_PM4_64PIO_64VCPIO_64INDPIO:
421 dev_priv->cce_fifo_size = 64;
422 break;
423 }
424
425 switch ( init->fb_bpp ) {
426 case 16:
427 dev_priv->color_fmt = R128_DATATYPE_RGB565;
428 break;
429 case 32:
430 default:
431 dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
432 break;
433 }
434 dev_priv->front_offset = init->front_offset;
435 dev_priv->front_pitch = init->front_pitch;
436 dev_priv->back_offset = init->back_offset;
437 dev_priv->back_pitch = init->back_pitch;
438
439 switch ( init->depth_bpp ) {
440 case 16:
441 dev_priv->depth_fmt = R128_DATATYPE_RGB565;
442 break;
443 case 24:
444 case 32:
445 default:
446 dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
447 break;
448 }
449 dev_priv->depth_offset = init->depth_offset;
450 dev_priv->depth_pitch = init->depth_pitch;
451 dev_priv->span_offset = init->span_offset;
452
453 dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch/8) << 21) |
454 (dev_priv->front_offset >> 5));
455 dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch/8) << 21) |
456 (dev_priv->back_offset >> 5));
457 dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) |
458 (dev_priv->depth_offset >> 5) |
459 R128_DST_TILE);
460 dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) |
461 (dev_priv->span_offset >> 5));
462
463 DRM_GETSAREA();
464
465 if(!dev_priv->sarea) {
466 DRM_ERROR("could not find sarea!\n");
467 dev->dev_private = (void *)dev_priv;
468 r128_do_cleanup_cce( dev );
469 return DRM_ERR(EINVAL);
470 }
471
472 DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
473 if(!dev_priv->mmio) {
474 DRM_ERROR("could not find mmio region!\n");
475 dev->dev_private = (void *)dev_priv;
476 r128_do_cleanup_cce( dev );
477 return DRM_ERR(EINVAL);
478 }
479 DRM_FIND_MAP( dev_priv->cce_ring, init->ring_offset );
480 if(!dev_priv->cce_ring) {
481 DRM_ERROR("could not find cce ring region!\n");
482 dev->dev_private = (void *)dev_priv;
483 r128_do_cleanup_cce( dev );
484 return DRM_ERR(EINVAL);
485 }
486 DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
487 if(!dev_priv->ring_rptr) {
488 DRM_ERROR("could not find ring read pointer!\n");
489 dev->dev_private = (void *)dev_priv;
490 r128_do_cleanup_cce( dev );
491 return DRM_ERR(EINVAL);
492 }
493 DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
494 if(!dev_priv->buffers) {
495 DRM_ERROR("could not find dma buffer region!\n");
496 dev->dev_private = (void *)dev_priv;
497 r128_do_cleanup_cce( dev );
498 return DRM_ERR(EINVAL);
499 }
500
501 if ( !dev_priv->is_pci ) {
502 DRM_FIND_MAP( dev_priv->agp_textures,
503 init->agp_textures_offset );
504 if(!dev_priv->agp_textures) {
505 DRM_ERROR("could not find agp texture region!\n");
506 dev->dev_private = (void *)dev_priv;
507 r128_do_cleanup_cce( dev );
508 return DRM_ERR(EINVAL);
509 }
510 }
511
512 dev_priv->sarea_priv =
513 (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
514 init->sarea_priv_offset);
515
516 #if __REALLY_HAVE_AGP
517 if ( !dev_priv->is_pci ) {
518 DRM_IOREMAP( dev_priv->cce_ring, dev );
519 DRM_IOREMAP( dev_priv->ring_rptr, dev );
520 DRM_IOREMAP( dev_priv->buffers, dev );
521 if(!dev_priv->cce_ring->handle ||
522 !dev_priv->ring_rptr->handle ||
523 !dev_priv->buffers->handle) {
524 DRM_ERROR("Could not ioremap agp regions!\n");
525 dev->dev_private = (void *)dev_priv;
526 r128_do_cleanup_cce( dev );
527 return DRM_ERR(ENOMEM);
528 }
529 } else
530 #endif
531 {
532 dev_priv->cce_ring->handle =
533 (void *)dev_priv->cce_ring->offset;
534 dev_priv->ring_rptr->handle =
535 (void *)dev_priv->ring_rptr->offset;
536 dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
537 }
538
539 #if __REALLY_HAVE_AGP
540 if ( !dev_priv->is_pci )
541 dev_priv->cce_buffers_offset = dev->agp->base;
542 else
543 #endif
544 dev_priv->cce_buffers_offset = dev->sg->handle;
545
546 dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle;
547 dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle
548 + init->ring_size / sizeof(u32));
549 dev_priv->ring.size = init->ring_size;
550 dev_priv->ring.size_l2qw = DRM(order)( init->ring_size / 8 );
551
552 dev_priv->ring.tail_mask =
553 (dev_priv->ring.size / sizeof(u32)) - 1;
554
555 dev_priv->ring.high_mark = 128;
556
557 dev_priv->sarea_priv->last_frame = 0;
558 R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame );
559
560 dev_priv->sarea_priv->last_dispatch = 0;
561 R128_WRITE( R128_LAST_DISPATCH_REG,
562 dev_priv->sarea_priv->last_dispatch );
563
564 #if __REALLY_HAVE_AGP
565 if ( dev_priv->is_pci ) {
566 #endif
567 if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
568 &dev_priv->bus_pci_gart) ) {
569 DRM_ERROR( "failed to init PCI GART!\n" );
570 dev->dev_private = (void *)dev_priv;
571 r128_do_cleanup_cce( dev );
572 return DRM_ERR(ENOMEM);
573 }
574 R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart );
575 #if __REALLY_HAVE_AGP
576 }
577 #endif
578
579 r128_cce_init_ring_buffer( dev, dev_priv );
580 r128_cce_load_microcode( dev_priv );
581
582 dev->dev_private = (void *)dev_priv;
583
584 r128_do_engine_reset( dev );
585
586 return 0;
587 }
588
589 int r128_do_cleanup_cce( drm_device_t *dev )
590 {
591
592 #if __HAVE_IRQ
593 /* Make sure interrupts are disabled here because the uninstall ioctl
594 * may not have been called from userspace and after dev_private
595 * is freed, it's too late.
596 */
597 if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
598 #endif
599
600 if ( dev->dev_private ) {
601 drm_r128_private_t *dev_priv = dev->dev_private;
602
603 #if __REALLY_HAVE_AGP
604 if ( !dev_priv->is_pci ) {
605 if ( dev_priv->cce_ring != NULL )
606 DRM_IOREMAPFREE( dev_priv->cce_ring, dev );
607 if ( dev_priv->ring_rptr != NULL )
608 DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
609 if ( dev_priv->buffers != NULL )
610 DRM_IOREMAPFREE( dev_priv->buffers, dev );
611 } else
612 #endif
613 {
614 if (!DRM(ati_pcigart_cleanup)( dev,
615 dev_priv->phys_pci_gart,
616 dev_priv->bus_pci_gart ))
617 DRM_ERROR( "failed to cleanup PCI GART!\n" );
618 }
619
620 DRM(free)( dev->dev_private, sizeof(drm_r128_private_t),
621 DRM_MEM_DRIVER );
622 dev->dev_private = NULL;
623 }
624
625 return 0;
626 }
627
628 int r128_cce_init( DRM_IOCTL_ARGS )
629 {
630 DRM_DEVICE;
631 drm_r128_init_t init;
632
633 DRM_DEBUG( "\n" );
634
635 LOCK_TEST_WITH_RETURN( dev, filp );
636
637 DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t *)data, sizeof(init) );
638
639 switch ( init.func ) {
640 case R128_INIT_CCE:
641 return r128_do_init_cce( dev, &init );
642 case R128_CLEANUP_CCE:
643 return r128_do_cleanup_cce( dev );
644 }
645
646 return DRM_ERR(EINVAL);
647 }
648
649 int r128_cce_start( DRM_IOCTL_ARGS )
650 {
651 DRM_DEVICE;
652 drm_r128_private_t *dev_priv = dev->dev_private;
653 DRM_DEBUG( "\n" );
654
655 LOCK_TEST_WITH_RETURN( dev, filp );
656
657 if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) {
658 DRM_DEBUG( "%s while CCE running\n", __FUNCTION__ );
659 return 0;
660 }
661
662 r128_do_cce_start( dev_priv );
663
664 return 0;
665 }
666
667 /* Stop the CCE. The engine must have been idled before calling this
668 * routine.
669 */
670 int r128_cce_stop( DRM_IOCTL_ARGS )
671 {
672 DRM_DEVICE;
673 drm_r128_private_t *dev_priv = dev->dev_private;
674 drm_r128_cce_stop_t stop;
675 int ret;
676 DRM_DEBUG( "\n" );
677
678 LOCK_TEST_WITH_RETURN( dev, filp );
679
680 DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t *)data, sizeof(stop) );
681
682 /* Flush any pending CCE commands. This ensures any outstanding
683 * commands are exectuted by the engine before we turn it off.
684 */
685 if ( stop.flush ) {
686 r128_do_cce_flush( dev_priv );
687 }
688
689 /* If we fail to make the engine go idle, we return an error
690 * code so that the DRM ioctl wrapper can try again.
691 */
692 if ( stop.idle ) {
693 ret = r128_do_cce_idle( dev_priv );
694 if ( ret ) return ret;
695 }
696
697 /* Finally, we can turn off the CCE. If the engine isn't idle,
698 * we will get some dropped triangles as they won't be fully
699 * rendered before the CCE is shut down.
700 */
701 r128_do_cce_stop( dev_priv );
702
703 /* Reset the engine */
704 r128_do_engine_reset( dev );
705
706 return 0;
707 }
708
709 /* Just reset the CCE ring. Called as part of an X Server engine reset.
710 */
711 int r128_cce_reset( DRM_IOCTL_ARGS )
712 {
713 DRM_DEVICE;
714 drm_r128_private_t *dev_priv = dev->dev_private;
715 DRM_DEBUG( "\n" );
716
717 LOCK_TEST_WITH_RETURN( dev, filp );
718
719 if ( !dev_priv ) {
720 DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
721 return DRM_ERR(EINVAL);
722 }
723
724 r128_do_cce_reset( dev_priv );
725
726 /* The CCE is no longer running after an engine reset */
727 dev_priv->cce_running = 0;
728
729 return 0;
730 }
731
732 int r128_cce_idle( DRM_IOCTL_ARGS )
733 {
734 DRM_DEVICE;
735 drm_r128_private_t *dev_priv = dev->dev_private;
736 DRM_DEBUG( "\n" );
737
738 LOCK_TEST_WITH_RETURN( dev, filp );
739
740 if ( dev_priv->cce_running ) {
741 r128_do_cce_flush( dev_priv );
742 }
743
744 return r128_do_cce_idle( dev_priv );
745 }
746
747 int r128_engine_reset( DRM_IOCTL_ARGS )
748 {
749 DRM_DEVICE;
750 DRM_DEBUG( "\n" );
751
752 LOCK_TEST_WITH_RETURN( dev, filp );
753
754 return r128_do_engine_reset( dev );
755 }
756
757 int r128_fullscreen( DRM_IOCTL_ARGS )
758 {
759 return DRM_ERR(EINVAL);
760 }
761
762
763 /* ================================================================
764 * Freelist management
765 */
766 #define R128_BUFFER_USED 0xffffffff
767 #define R128_BUFFER_FREE 0
768
769 #if 0
770 static int r128_freelist_init( drm_device_t *dev )
771 {
772 drm_device_dma_t *dma = dev->dma;
773 drm_r128_private_t *dev_priv = dev->dev_private;
774 drm_buf_t *buf;
775 drm_r128_buf_priv_t *buf_priv;
776 drm_r128_freelist_t *entry;
777 int i;
778
779 dev_priv->head = DRM(alloc)( sizeof(drm_r128_freelist_t),
780 DRM_MEM_DRIVER );
781 if ( dev_priv->head == NULL )
782 return DRM_ERR(ENOMEM);
783
784 memset( dev_priv->head, 0, sizeof(drm_r128_freelist_t) );
785 dev_priv->head->age = R128_BUFFER_USED;
786
787 for ( i = 0 ; i < dma->buf_count ; i++ ) {
788 buf = dma->buflist[i];
789 buf_priv = buf->dev_private;
790
791 entry = DRM(alloc)( sizeof(drm_r128_freelist_t),
792 DRM_MEM_DRIVER );
793 if ( !entry ) return DRM_ERR(ENOMEM);
794
795 entry->age = R128_BUFFER_FREE;
796 entry->buf = buf;
797 entry->prev = dev_priv->head;
798 entry->next = dev_priv->head->next;
799 if ( !entry->next )
800 dev_priv->tail = entry;
801
802 buf_priv->discard = 0;
803 buf_priv->dispatched = 0;
804 buf_priv->list_entry = entry;
805
806 dev_priv->head->next = entry;
807
808 if ( dev_priv->head->next )
809 dev_priv->head->next->prev = entry;
810 }
811
812 return 0;
813
814 }
815 #endif
816
817 drm_buf_t *r128_freelist_get( drm_device_t *dev )
818 {
819 drm_device_dma_t *dma = dev->dma;
820 drm_r128_private_t *dev_priv = dev->dev_private;
821 drm_r128_buf_priv_t *buf_priv;
822 drm_buf_t *buf;
823 int i, t;
824
825 /* FIXME: Optimize -- use freelist code */
826
827 for ( i = 0 ; i < dma->buf_count ; i++ ) {
828 buf = dma->buflist[i];
829 buf_priv = buf->dev_private;
830 if ( buf->filp == 0 )
831 return buf;
832 }
833
834 for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
835 u32 done_age = R128_READ( R128_LAST_DISPATCH_REG );
836
837 for ( i = 0 ; i < dma->buf_count ; i++ ) {
838 buf = dma->buflist[i];
839 buf_priv = buf->dev_private;
840 if ( buf->pending && buf_priv->age <= done_age ) {
841 /* The buffer has been processed, so it
842 * can now be used.
843 */
844 buf->pending = 0;
845 return buf;
846 }
847 }
848 DRM_UDELAY( 1 );
849 }
850
851 DRM_DEBUG( "returning NULL!\n" );
852 return NULL;
853 }
854
855 void r128_freelist_reset( drm_device_t *dev )
856 {
857 drm_device_dma_t *dma = dev->dma;
858 int i;
859
860 for ( i = 0 ; i < dma->buf_count ; i++ ) {
861 drm_buf_t *buf = dma->buflist[i];
862 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
863 buf_priv->age = 0;
864 }
865 }
866
867
868 /* ================================================================
869 * CCE command submission
870 */
871
872 int r128_wait_ring( drm_r128_private_t *dev_priv, int n )
873 {
874 drm_r128_ring_buffer_t *ring = &dev_priv->ring;
875 int i;
876
877 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
878 r128_update_ring_snapshot( dev_priv );
879 if ( ring->space >= n )
880 return 0;
881 DRM_UDELAY( 1 );
882 }
883
884 /* FIXME: This is being ignored... */
885 DRM_ERROR( "failed!\n" );
886 return DRM_ERR(EBUSY);
887 }
888
889 static int r128_cce_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d )
890 {
891 int i;
892 drm_buf_t *buf;
893
894 for ( i = d->granted_count ; i < d->request_count ; i++ ) {
895 buf = r128_freelist_get( dev );
896 if ( !buf ) return DRM_ERR(EAGAIN);
897
898 buf->filp = filp;
899
900 if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
901 sizeof(buf->idx) ) )
902 return DRM_ERR(EFAULT);
903 if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
904 sizeof(buf->total) ) )
905 return DRM_ERR(EFAULT);
906
907 d->granted_count++;
908 }
909 return 0;
910 }
911
912 int r128_cce_buffers( DRM_IOCTL_ARGS )
913 {
914 DRM_DEVICE;
915 drm_device_dma_t *dma = dev->dma;
916 int ret = 0;
917 drm_dma_t d;
918
919 LOCK_TEST_WITH_RETURN( dev, filp );
920
921 DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *) data, sizeof(d) );
922
923 /* Please don't send us buffers.
924 */
925 if ( d.send_count != 0 ) {
926 DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
927 DRM_CURRENTPID, d.send_count );
928 return DRM_ERR(EINVAL);
929 }
930
931 /* We'll send you buffers.
932 */
933 if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
934 DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
935 DRM_CURRENTPID, d.request_count, dma->buf_count );
936 return DRM_ERR(EINVAL);
937 }
938
939 d.granted_count = 0;
940
941 if ( d.request_count ) {
942 ret = r128_cce_get_buffers( filp, dev, &d );
943 }
944
945 DRM_COPY_TO_USER_IOCTL((drm_dma_t *) data, d, sizeof(d) );
946
947 return ret;
948 }
Cache object: 278b33c0794a4eb0cc4cfff50213594d
|