r128_cce.c revision 139749
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: head/sys/dev/drm/r128_cce.c 139749 2005-01-06 01:43:34Z imp $
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) */
42static 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
86int 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
95static 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
117static 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
138static 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
154static 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 */
181static 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 */
202static 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 */
212int 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 */
238static 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 */
255static 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 */
266static 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 */
277static 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
316static 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
354static 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
589int 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
628int 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
649int 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 */
670int 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 */
711int 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
732int 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
747int 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
757int 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
770static 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
817drm_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
855void 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
872int 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
889static 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
912int 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}
949