1254885Sdumbbell/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */
2254885Sdumbbell/*
3254885Sdumbbell * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
4254885Sdumbbell * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
5254885Sdumbbell * Copyright 2007 Advanced Micro Devices, Inc.
6254885Sdumbbell * All Rights Reserved.
7254885Sdumbbell *
8254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
9254885Sdumbbell * copy of this software and associated documentation files (the "Software"),
10254885Sdumbbell * to deal in the Software without restriction, including without limitation
11254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the
13254885Sdumbbell * Software is furnished to do so, subject to the following conditions:
14254885Sdumbbell *
15254885Sdumbbell * The above copyright notice and this permission notice (including the next
16254885Sdumbbell * paragraph) shall be included in all copies or substantial portions of the
17254885Sdumbbell * Software.
18254885Sdumbbell *
19254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22254885Sdumbbell * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25254885Sdumbbell * DEALINGS IN THE SOFTWARE.
26254885Sdumbbell *
27254885Sdumbbell * Authors:
28254885Sdumbbell *    Kevin E. Martin <martin@valinux.com>
29254885Sdumbbell *    Gareth Hughes <gareth@valinux.com>
30254885Sdumbbell */
31254885Sdumbbell
32254885Sdumbbell#include <sys/cdefs.h>
33254885Sdumbbell__FBSDID("$FreeBSD$");
34254885Sdumbbell
35254885Sdumbbell#include <sys/param.h>
36254885Sdumbbell#include <sys/systm.h>
37254885Sdumbbell#include <sys/linker.h>
38254885Sdumbbell#include <sys/firmware.h>
39254885Sdumbbell
40254885Sdumbbell#include <dev/drm2/drmP.h>
41254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h>
42254885Sdumbbell#include "radeon_drv.h"
43254885Sdumbbell#include "r300_reg.h"
44254885Sdumbbell
45254885Sdumbbell#define RADEON_FIFO_DEBUG	0
46254885Sdumbbell
47254885Sdumbbell/* Firmware Names */
48254885Sdumbbell#define FIRMWARE_R100		"radeonkmsfw_R100_cp"
49254885Sdumbbell#define FIRMWARE_R200		"radeonkmsfw_R200_cp"
50254885Sdumbbell#define FIRMWARE_R300		"radeonkmsfw_R300_cp"
51254885Sdumbbell#define FIRMWARE_R420		"radeonkmsfw_R420_cp"
52254885Sdumbbell#define FIRMWARE_RS690		"radeonkmsfw_RS690_cp"
53254885Sdumbbell#define FIRMWARE_RS600		"radeonkmsfw_RS600_cp"
54254885Sdumbbell#define FIRMWARE_R520		"radeonkmsfw_R520_cp"
55254885Sdumbbell
56254885Sdumbbellstatic int radeon_do_cleanup_cp(struct drm_device * dev);
57254885Sdumbbellstatic void radeon_do_cp_start(drm_radeon_private_t * dev_priv);
58254885Sdumbbell
59254885Sdumbbellu32 radeon_read_ring_rptr(drm_radeon_private_t *dev_priv, u32 off)
60254885Sdumbbell{
61254885Sdumbbell	u32 val;
62254885Sdumbbell
63254885Sdumbbell	if (dev_priv->flags & RADEON_IS_AGP) {
64254885Sdumbbell		val = DRM_READ32(dev_priv->ring_rptr, off);
65254885Sdumbbell	} else {
66254885Sdumbbell		val = *(((volatile u32 *)
67254885Sdumbbell			 dev_priv->ring_rptr->handle) +
68254885Sdumbbell			(off / sizeof(u32)));
69254885Sdumbbell		val = le32_to_cpu(val);
70254885Sdumbbell	}
71254885Sdumbbell	return val;
72254885Sdumbbell}
73254885Sdumbbell
74254885Sdumbbellu32 radeon_get_ring_head(drm_radeon_private_t *dev_priv)
75254885Sdumbbell{
76254885Sdumbbell	if (dev_priv->writeback_works)
77254885Sdumbbell		return radeon_read_ring_rptr(dev_priv, 0);
78254885Sdumbbell	else {
79254885Sdumbbell		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
80254885Sdumbbell			return RADEON_READ(R600_CP_RB_RPTR);
81254885Sdumbbell		else
82254885Sdumbbell			return RADEON_READ(RADEON_CP_RB_RPTR);
83254885Sdumbbell	}
84254885Sdumbbell}
85254885Sdumbbell
86254885Sdumbbellvoid radeon_write_ring_rptr(drm_radeon_private_t *dev_priv, u32 off, u32 val)
87254885Sdumbbell{
88254885Sdumbbell	if (dev_priv->flags & RADEON_IS_AGP)
89254885Sdumbbell		DRM_WRITE32(dev_priv->ring_rptr, off, val);
90254885Sdumbbell	else
91254885Sdumbbell		*(((volatile u32 *) dev_priv->ring_rptr->handle) +
92254885Sdumbbell		  (off / sizeof(u32))) = cpu_to_le32(val);
93254885Sdumbbell}
94254885Sdumbbell
95254885Sdumbbellvoid radeon_set_ring_head(drm_radeon_private_t *dev_priv, u32 val)
96254885Sdumbbell{
97254885Sdumbbell	radeon_write_ring_rptr(dev_priv, 0, val);
98254885Sdumbbell}
99254885Sdumbbell
100254885Sdumbbellu32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index)
101254885Sdumbbell{
102254885Sdumbbell	if (dev_priv->writeback_works) {
103254885Sdumbbell		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
104254885Sdumbbell			return radeon_read_ring_rptr(dev_priv,
105254885Sdumbbell						     R600_SCRATCHOFF(index));
106254885Sdumbbell		else
107254885Sdumbbell			return radeon_read_ring_rptr(dev_priv,
108254885Sdumbbell						     RADEON_SCRATCHOFF(index));
109254885Sdumbbell	} else {
110254885Sdumbbell		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
111254885Sdumbbell			return RADEON_READ(R600_SCRATCH_REG0 + 4*index);
112254885Sdumbbell		else
113254885Sdumbbell			return RADEON_READ(RADEON_SCRATCH_REG0 + 4*index);
114254885Sdumbbell	}
115254885Sdumbbell}
116254885Sdumbbell
117254885Sdumbbellstatic u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
118254885Sdumbbell{
119254885Sdumbbell	u32 ret;
120254885Sdumbbell	RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff));
121254885Sdumbbell	ret = RADEON_READ(R520_MC_IND_DATA);
122254885Sdumbbell	RADEON_WRITE(R520_MC_IND_INDEX, 0);
123254885Sdumbbell	return ret;
124254885Sdumbbell}
125254885Sdumbbell
126254885Sdumbbellstatic u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
127254885Sdumbbell{
128254885Sdumbbell	u32 ret;
129254885Sdumbbell	RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff);
130254885Sdumbbell	ret = RADEON_READ(RS480_NB_MC_DATA);
131254885Sdumbbell	RADEON_WRITE(RS480_NB_MC_INDEX, 0xff);
132254885Sdumbbell	return ret;
133254885Sdumbbell}
134254885Sdumbbell
135254885Sdumbbellstatic u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
136254885Sdumbbell{
137254885Sdumbbell	u32 ret;
138254885Sdumbbell	RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK));
139254885Sdumbbell	ret = RADEON_READ(RS690_MC_DATA);
140254885Sdumbbell	RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK);
141254885Sdumbbell	return ret;
142254885Sdumbbell}
143254885Sdumbbell
144254885Sdumbbellstatic u32 RS600_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
145254885Sdumbbell{
146254885Sdumbbell	u32 ret;
147254885Sdumbbell	RADEON_WRITE(RS600_MC_INDEX, ((addr & RS600_MC_ADDR_MASK) |
148254885Sdumbbell				      RS600_MC_IND_CITF_ARB0));
149254885Sdumbbell	ret = RADEON_READ(RS600_MC_DATA);
150254885Sdumbbell	return ret;
151254885Sdumbbell}
152254885Sdumbbell
153254885Sdumbbellstatic u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
154254885Sdumbbell{
155254885Sdumbbell	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
156254885Sdumbbell	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
157254885Sdumbbell		return RS690_READ_MCIND(dev_priv, addr);
158254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
159254885Sdumbbell		return RS600_READ_MCIND(dev_priv, addr);
160254885Sdumbbell	else
161254885Sdumbbell		return RS480_READ_MCIND(dev_priv, addr);
162254885Sdumbbell}
163254885Sdumbbell
164254885Sdumbbellu32 radeon_read_fb_location(drm_radeon_private_t *dev_priv)
165254885Sdumbbell{
166254885Sdumbbell
167254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
168254885Sdumbbell		return RADEON_READ(R700_MC_VM_FB_LOCATION);
169254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
170254885Sdumbbell		return RADEON_READ(R600_MC_VM_FB_LOCATION);
171254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
172254885Sdumbbell		return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
173254885Sdumbbell	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
174254885Sdumbbell		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
175254885Sdumbbell		return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION);
176254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
177254885Sdumbbell		return RS600_READ_MCIND(dev_priv, RS600_MC_FB_LOCATION);
178254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
179254885Sdumbbell		return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
180254885Sdumbbell	else
181254885Sdumbbell		return RADEON_READ(RADEON_MC_FB_LOCATION);
182254885Sdumbbell}
183254885Sdumbbell
184254885Sdumbbellstatic void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc)
185254885Sdumbbell{
186254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
187254885Sdumbbell		RADEON_WRITE(R700_MC_VM_FB_LOCATION, fb_loc);
188254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
189254885Sdumbbell		RADEON_WRITE(R600_MC_VM_FB_LOCATION, fb_loc);
190254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
191254885Sdumbbell		R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
192254885Sdumbbell	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
193254885Sdumbbell		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
194254885Sdumbbell		RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc);
195254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
196254885Sdumbbell		RS600_WRITE_MCIND(RS600_MC_FB_LOCATION, fb_loc);
197254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
198254885Sdumbbell		R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
199254885Sdumbbell	else
200254885Sdumbbell		RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc);
201254885Sdumbbell}
202254885Sdumbbell
203254885Sdumbbellvoid radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc)
204254885Sdumbbell{
205254885Sdumbbell	/*R6xx/R7xx: AGP_TOP and BOT are actually 18 bits each */
206254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) {
207254885Sdumbbell		RADEON_WRITE(R700_MC_VM_AGP_BOT, agp_loc & 0xffff); /* FIX ME */
208254885Sdumbbell		RADEON_WRITE(R700_MC_VM_AGP_TOP, (agp_loc >> 16) & 0xffff);
209254885Sdumbbell	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
210254885Sdumbbell		RADEON_WRITE(R600_MC_VM_AGP_BOT, agp_loc & 0xffff); /* FIX ME */
211254885Sdumbbell		RADEON_WRITE(R600_MC_VM_AGP_TOP, (agp_loc >> 16) & 0xffff);
212254885Sdumbbell	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
213254885Sdumbbell		R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
214254885Sdumbbell	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
215254885Sdumbbell		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
216254885Sdumbbell		RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc);
217254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
218254885Sdumbbell		RS600_WRITE_MCIND(RS600_MC_AGP_LOCATION, agp_loc);
219254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
220254885Sdumbbell		R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
221254885Sdumbbell	else
222254885Sdumbbell		RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc);
223254885Sdumbbell}
224254885Sdumbbell
225254885Sdumbbellvoid radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base)
226254885Sdumbbell{
227254885Sdumbbell	u32 agp_base_hi = upper_32_bits(agp_base);
228254885Sdumbbell	u32 agp_base_lo = agp_base & 0xffffffff;
229254885Sdumbbell	u32 r6xx_agp_base = (agp_base >> 22) & 0x3ffff;
230254885Sdumbbell
231254885Sdumbbell	/* R6xx/R7xx must be aligned to a 4MB boundary */
232254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
233254885Sdumbbell		RADEON_WRITE(R700_MC_VM_AGP_BASE, r6xx_agp_base);
234254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
235254885Sdumbbell		RADEON_WRITE(R600_MC_VM_AGP_BASE, r6xx_agp_base);
236254885Sdumbbell	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) {
237254885Sdumbbell		R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo);
238254885Sdumbbell		R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi);
239254885Sdumbbell	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
240254885Sdumbbell		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
241254885Sdumbbell		RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo);
242254885Sdumbbell		RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi);
243254885Sdumbbell	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) {
244254885Sdumbbell		RS600_WRITE_MCIND(RS600_AGP_BASE, agp_base_lo);
245254885Sdumbbell		RS600_WRITE_MCIND(RS600_AGP_BASE_2, agp_base_hi);
246254885Sdumbbell	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) {
247254885Sdumbbell		R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo);
248254885Sdumbbell		R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi);
249254885Sdumbbell	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
250254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
251254885Sdumbbell		RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
252254885Sdumbbell		RADEON_WRITE(RS480_AGP_BASE_2, agp_base_hi);
253254885Sdumbbell	} else {
254254885Sdumbbell		RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
255254885Sdumbbell		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200)
256254885Sdumbbell			RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi);
257254885Sdumbbell	}
258254885Sdumbbell}
259254885Sdumbbell
260254885Sdumbbellvoid radeon_enable_bm(struct drm_radeon_private *dev_priv)
261254885Sdumbbell{
262254885Sdumbbell	u32 tmp;
263254885Sdumbbell	/* Turn on bus mastering */
264254885Sdumbbell	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
265254885Sdumbbell	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
266254885Sdumbbell		/* rs600/rs690/rs740 */
267254885Sdumbbell		tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
268254885Sdumbbell		RADEON_WRITE(RADEON_BUS_CNTL, tmp);
269254885Sdumbbell	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV350) ||
270254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
271254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
272254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
273254885Sdumbbell		/* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */
274254885Sdumbbell		tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
275254885Sdumbbell		RADEON_WRITE(RADEON_BUS_CNTL, tmp);
276254885Sdumbbell	} /* PCIE cards appears to not need this */
277254885Sdumbbell}
278254885Sdumbbell
279254885Sdumbbellstatic int RADEON_READ_PLL(struct drm_device * dev, int addr)
280254885Sdumbbell{
281254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
282254885Sdumbbell
283254885Sdumbbell	RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
284254885Sdumbbell	return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
285254885Sdumbbell}
286254885Sdumbbell
287254885Sdumbbellstatic u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
288254885Sdumbbell{
289254885Sdumbbell	RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
290254885Sdumbbell	return RADEON_READ(RADEON_PCIE_DATA);
291254885Sdumbbell}
292254885Sdumbbell
293254885Sdumbbell#if RADEON_FIFO_DEBUG
294254885Sdumbbellstatic void radeon_status(drm_radeon_private_t * dev_priv)
295254885Sdumbbell{
296254885Sdumbbell	printk("%s:\n", __func__);
297254885Sdumbbell	printk("RBBM_STATUS = 0x%08x\n",
298254885Sdumbbell	       (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
299254885Sdumbbell	printk("CP_RB_RTPR = 0x%08x\n",
300254885Sdumbbell	       (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR));
301254885Sdumbbell	printk("CP_RB_WTPR = 0x%08x\n",
302254885Sdumbbell	       (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR));
303254885Sdumbbell	printk("AIC_CNTL = 0x%08x\n",
304254885Sdumbbell	       (unsigned int)RADEON_READ(RADEON_AIC_CNTL));
305254885Sdumbbell	printk("AIC_STAT = 0x%08x\n",
306254885Sdumbbell	       (unsigned int)RADEON_READ(RADEON_AIC_STAT));
307254885Sdumbbell	printk("AIC_PT_BASE = 0x%08x\n",
308254885Sdumbbell	       (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE));
309254885Sdumbbell	printk("TLB_ADDR = 0x%08x\n",
310254885Sdumbbell	       (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR));
311254885Sdumbbell	printk("TLB_DATA = 0x%08x\n",
312254885Sdumbbell	       (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA));
313254885Sdumbbell}
314254885Sdumbbell#endif
315254885Sdumbbell
316254885Sdumbbell/* ================================================================
317254885Sdumbbell * Engine, FIFO control
318254885Sdumbbell */
319254885Sdumbbell
320254885Sdumbbellstatic int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
321254885Sdumbbell{
322254885Sdumbbell	u32 tmp;
323254885Sdumbbell	int i;
324254885Sdumbbell
325254885Sdumbbell	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
326254885Sdumbbell
327254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {
328254885Sdumbbell		tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
329254885Sdumbbell		tmp |= RADEON_RB3D_DC_FLUSH_ALL;
330254885Sdumbbell		RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
331254885Sdumbbell
332254885Sdumbbell		for (i = 0; i < dev_priv->usec_timeout; i++) {
333254885Sdumbbell			if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
334254885Sdumbbell			      & RADEON_RB3D_DC_BUSY)) {
335254885Sdumbbell				return 0;
336254885Sdumbbell			}
337254885Sdumbbell			DRM_UDELAY(1);
338254885Sdumbbell		}
339254885Sdumbbell	} else {
340254885Sdumbbell		/* don't flush or purge cache here or lockup */
341254885Sdumbbell		return 0;
342254885Sdumbbell	}
343254885Sdumbbell
344254885Sdumbbell#if RADEON_FIFO_DEBUG
345254885Sdumbbell	DRM_ERROR("failed!\n");
346254885Sdumbbell	radeon_status(dev_priv);
347254885Sdumbbell#endif
348254885Sdumbbell	return -EBUSY;
349254885Sdumbbell}
350254885Sdumbbell
351254885Sdumbbellstatic int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
352254885Sdumbbell{
353254885Sdumbbell	int i;
354254885Sdumbbell
355254885Sdumbbell	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
356254885Sdumbbell
357254885Sdumbbell	for (i = 0; i < dev_priv->usec_timeout; i++) {
358254885Sdumbbell		int slots = (RADEON_READ(RADEON_RBBM_STATUS)
359254885Sdumbbell			     & RADEON_RBBM_FIFOCNT_MASK);
360254885Sdumbbell		if (slots >= entries)
361254885Sdumbbell			return 0;
362254885Sdumbbell		DRM_UDELAY(1);
363254885Sdumbbell	}
364254885Sdumbbell	DRM_DEBUG("wait for fifo failed status : 0x%08X 0x%08X\n",
365254885Sdumbbell		 RADEON_READ(RADEON_RBBM_STATUS),
366254885Sdumbbell		 RADEON_READ(R300_VAP_CNTL_STATUS));
367254885Sdumbbell
368254885Sdumbbell#if RADEON_FIFO_DEBUG
369254885Sdumbbell	DRM_ERROR("failed!\n");
370254885Sdumbbell	radeon_status(dev_priv);
371254885Sdumbbell#endif
372254885Sdumbbell	return -EBUSY;
373254885Sdumbbell}
374254885Sdumbbell
375254885Sdumbbellstatic int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
376254885Sdumbbell{
377254885Sdumbbell	int i, ret;
378254885Sdumbbell
379254885Sdumbbell	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
380254885Sdumbbell
381254885Sdumbbell	ret = radeon_do_wait_for_fifo(dev_priv, 64);
382254885Sdumbbell	if (ret)
383254885Sdumbbell		return ret;
384254885Sdumbbell
385254885Sdumbbell	for (i = 0; i < dev_priv->usec_timeout; i++) {
386254885Sdumbbell		if (!(RADEON_READ(RADEON_RBBM_STATUS)
387254885Sdumbbell		      & RADEON_RBBM_ACTIVE)) {
388254885Sdumbbell			radeon_do_pixcache_flush(dev_priv);
389254885Sdumbbell			return 0;
390254885Sdumbbell		}
391254885Sdumbbell		DRM_UDELAY(1);
392254885Sdumbbell	}
393254885Sdumbbell	DRM_DEBUG("wait idle failed status : 0x%08X 0x%08X\n",
394254885Sdumbbell		 RADEON_READ(RADEON_RBBM_STATUS),
395254885Sdumbbell		 RADEON_READ(R300_VAP_CNTL_STATUS));
396254885Sdumbbell
397254885Sdumbbell#if RADEON_FIFO_DEBUG
398254885Sdumbbell	DRM_ERROR("failed!\n");
399254885Sdumbbell	radeon_status(dev_priv);
400254885Sdumbbell#endif
401254885Sdumbbell	return -EBUSY;
402254885Sdumbbell}
403254885Sdumbbell
404254885Sdumbbellstatic void radeon_init_pipes(struct drm_device *dev)
405254885Sdumbbell{
406254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
407254885Sdumbbell	uint32_t gb_tile_config, gb_pipe_sel = 0;
408254885Sdumbbell
409254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) {
410254885Sdumbbell		uint32_t z_pipe_sel = RADEON_READ(RV530_GB_PIPE_SELECT2);
411254885Sdumbbell		if ((z_pipe_sel & 3) == 3)
412254885Sdumbbell			dev_priv->num_z_pipes = 2;
413254885Sdumbbell		else
414254885Sdumbbell			dev_priv->num_z_pipes = 1;
415254885Sdumbbell	} else
416254885Sdumbbell		dev_priv->num_z_pipes = 1;
417254885Sdumbbell
418254885Sdumbbell	/* RS4xx/RS6xx/R4xx/R5xx */
419254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
420254885Sdumbbell		gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
421254885Sdumbbell		dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
422254885Sdumbbell		/* SE cards have 1 pipe */
423254885Sdumbbell		if ((dev->pci_device == 0x5e4c) ||
424254885Sdumbbell		    (dev->pci_device == 0x5e4f))
425254885Sdumbbell			dev_priv->num_gb_pipes = 1;
426254885Sdumbbell	} else {
427254885Sdumbbell		/* R3xx */
428254885Sdumbbell		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300 &&
429254885Sdumbbell		     dev->pci_device != 0x4144) ||
430254885Sdumbbell		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350 &&
431254885Sdumbbell		     dev->pci_device != 0x4148)) {
432254885Sdumbbell			dev_priv->num_gb_pipes = 2;
433254885Sdumbbell		} else {
434254885Sdumbbell			/* RV3xx/R300 AD/R350 AH */
435254885Sdumbbell			dev_priv->num_gb_pipes = 1;
436254885Sdumbbell		}
437254885Sdumbbell	}
438254885Sdumbbell	DRM_INFO("Num pipes: %d\n", dev_priv->num_gb_pipes);
439254885Sdumbbell
440254885Sdumbbell	gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/);
441254885Sdumbbell
442254885Sdumbbell	switch (dev_priv->num_gb_pipes) {
443254885Sdumbbell	case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
444254885Sdumbbell	case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
445254885Sdumbbell	case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
446254885Sdumbbell	default:
447254885Sdumbbell	case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
448254885Sdumbbell	}
449254885Sdumbbell
450254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
451254885Sdumbbell		RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
452254885Sdumbbell		RADEON_WRITE(R300_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
453254885Sdumbbell	}
454254885Sdumbbell	RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config);
455254885Sdumbbell	radeon_do_wait_for_idle(dev_priv);
456254885Sdumbbell	RADEON_WRITE(R300_DST_PIPE_CONFIG, RADEON_READ(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
457254885Sdumbbell	RADEON_WRITE(R300_RB2D_DSTCACHE_MODE, (RADEON_READ(R300_RB2D_DSTCACHE_MODE) |
458254885Sdumbbell					       R300_DC_AUTOFLUSH_ENABLE |
459254885Sdumbbell					       R300_DC_DC_DISABLE_IGNORE_PE));
460254885Sdumbbell
461254885Sdumbbell
462254885Sdumbbell}
463254885Sdumbbell
464254885Sdumbbell/* ================================================================
465254885Sdumbbell * CP control, initialization
466254885Sdumbbell */
467254885Sdumbbell
468254885Sdumbbell/* Load the microcode for the CP */
469254885Sdumbbellstatic int radeon_cp_init_microcode(drm_radeon_private_t *dev_priv)
470254885Sdumbbell{
471254885Sdumbbell	const char *fw_name = NULL;
472254885Sdumbbell	int err;
473254885Sdumbbell
474254885Sdumbbell	DRM_DEBUG("\n");
475254885Sdumbbell
476254885Sdumbbell	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) ||
477254885Sdumbbell	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) ||
478254885Sdumbbell	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) ||
479254885Sdumbbell	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) ||
480254885Sdumbbell	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) {
481254885Sdumbbell		DRM_INFO("Loading R100 Microcode\n");
482254885Sdumbbell		fw_name = FIRMWARE_R100;
483254885Sdumbbell	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) ||
484254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) ||
485254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) ||
486254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) {
487254885Sdumbbell		DRM_INFO("Loading R200 Microcode\n");
488254885Sdumbbell		fw_name = FIRMWARE_R200;
489254885Sdumbbell	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
490254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
491254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
492254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
493254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
494254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
495254885Sdumbbell		DRM_INFO("Loading R300 Microcode\n");
496254885Sdumbbell		fw_name = FIRMWARE_R300;
497254885Sdumbbell	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
498254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) ||
499254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
500254885Sdumbbell		DRM_INFO("Loading R400 Microcode\n");
501254885Sdumbbell		fw_name = FIRMWARE_R420;
502254885Sdumbbell	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
503254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
504254885Sdumbbell		DRM_INFO("Loading RS690/RS740 Microcode\n");
505254885Sdumbbell		fw_name = FIRMWARE_RS690;
506254885Sdumbbell	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) {
507254885Sdumbbell		DRM_INFO("Loading RS600 Microcode\n");
508254885Sdumbbell		fw_name = FIRMWARE_RS600;
509254885Sdumbbell	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) ||
510254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) ||
511254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) ||
512254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) ||
513254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) ||
514254885Sdumbbell		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
515254885Sdumbbell		DRM_INFO("Loading R500 Microcode\n");
516254885Sdumbbell		fw_name = FIRMWARE_R520;
517254885Sdumbbell	}
518254885Sdumbbell
519254885Sdumbbell	err = 0;
520254885Sdumbbell
521254885Sdumbbell	dev_priv->me_fw = firmware_get(fw_name);
522254885Sdumbbell	if (dev_priv->me_fw == NULL) {
523254885Sdumbbell		err = -ENOENT;
524254885Sdumbbell		DRM_ERROR("radeon_cp: Failed to load firmware \"%s\"\n",
525254885Sdumbbell		       fw_name);
526254885Sdumbbell	} else if (dev_priv->me_fw->datasize % 8) {
527254885Sdumbbell		DRM_ERROR(
528254885Sdumbbell		       "radeon_cp: Bogus length %zu in firmware \"%s\"\n",
529254885Sdumbbell		       dev_priv->me_fw->datasize, fw_name);
530254885Sdumbbell		err = -EINVAL;
531254885Sdumbbell		firmware_put(dev_priv->me_fw, FIRMWARE_UNLOAD);
532254885Sdumbbell		dev_priv->me_fw = NULL;
533254885Sdumbbell	}
534254885Sdumbbell	return err;
535254885Sdumbbell}
536254885Sdumbbell
537254885Sdumbbellstatic void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv)
538254885Sdumbbell{
539254885Sdumbbell	const __be32 *fw_data;
540254885Sdumbbell	int i, size;
541254885Sdumbbell
542254885Sdumbbell	radeon_do_wait_for_idle(dev_priv);
543254885Sdumbbell
544254885Sdumbbell	if (dev_priv->me_fw) {
545254885Sdumbbell		size = dev_priv->me_fw->datasize / 4;
546254885Sdumbbell		fw_data = (const __be32 *)dev_priv->me_fw->data;
547254885Sdumbbell		RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
548254885Sdumbbell		for (i = 0; i < size; i += 2) {
549254885Sdumbbell			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
550254885Sdumbbell				     be32_to_cpup(&fw_data[i]));
551254885Sdumbbell			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
552254885Sdumbbell				     be32_to_cpup(&fw_data[i + 1]));
553254885Sdumbbell		}
554254885Sdumbbell	}
555254885Sdumbbell}
556254885Sdumbbell
557254885Sdumbbell/* Flush any pending commands to the CP.  This should only be used just
558254885Sdumbbell * prior to a wait for idle, as it informs the engine that the command
559254885Sdumbbell * stream is ending.
560254885Sdumbbell */
561254885Sdumbbellstatic void radeon_do_cp_flush(drm_radeon_private_t * dev_priv)
562254885Sdumbbell{
563254885Sdumbbell	DRM_DEBUG("\n");
564254885Sdumbbell#if 0
565254885Sdumbbell	u32 tmp;
566254885Sdumbbell
567254885Sdumbbell	tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31);
568254885Sdumbbell	RADEON_WRITE(RADEON_CP_RB_WPTR, tmp);
569254885Sdumbbell#endif
570254885Sdumbbell}
571254885Sdumbbell
572254885Sdumbbell/* Wait for the CP to go idle.
573254885Sdumbbell */
574254885Sdumbbellint radeon_do_cp_idle(drm_radeon_private_t * dev_priv)
575254885Sdumbbell{
576254885Sdumbbell	RING_LOCALS;
577254885Sdumbbell	DRM_DEBUG("\n");
578254885Sdumbbell
579254885Sdumbbell	BEGIN_RING(6);
580254885Sdumbbell
581254885Sdumbbell	RADEON_PURGE_CACHE();
582254885Sdumbbell	RADEON_PURGE_ZCACHE();
583254885Sdumbbell	RADEON_WAIT_UNTIL_IDLE();
584254885Sdumbbell
585254885Sdumbbell	ADVANCE_RING();
586254885Sdumbbell	COMMIT_RING();
587254885Sdumbbell
588254885Sdumbbell	return radeon_do_wait_for_idle(dev_priv);
589254885Sdumbbell}
590254885Sdumbbell
591254885Sdumbbell/* Start the Command Processor.
592254885Sdumbbell */
593254885Sdumbbellstatic void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
594254885Sdumbbell{
595254885Sdumbbell	RING_LOCALS;
596254885Sdumbbell	DRM_DEBUG("\n");
597254885Sdumbbell
598254885Sdumbbell	radeon_do_wait_for_idle(dev_priv);
599254885Sdumbbell
600254885Sdumbbell	RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode);
601254885Sdumbbell
602254885Sdumbbell	dev_priv->cp_running = 1;
603254885Sdumbbell
604254885Sdumbbell	/* on r420, any DMA from CP to system memory while 2D is active
605254885Sdumbbell	 * can cause a hang.  workaround is to queue a CP RESYNC token
606254885Sdumbbell	 */
607254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
608254885Sdumbbell		BEGIN_RING(3);
609254885Sdumbbell		OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1));
610254885Sdumbbell		OUT_RING(5); /* scratch reg 5 */
611254885Sdumbbell		OUT_RING(0xdeadbeef);
612254885Sdumbbell		ADVANCE_RING();
613254885Sdumbbell		COMMIT_RING();
614254885Sdumbbell	}
615254885Sdumbbell
616254885Sdumbbell	BEGIN_RING(8);
617254885Sdumbbell	/* isync can only be written through cp on r5xx write it here */
618254885Sdumbbell	OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0));
619254885Sdumbbell	OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D |
620254885Sdumbbell		 RADEON_ISYNC_ANY3D_IDLE2D |
621254885Sdumbbell		 RADEON_ISYNC_WAIT_IDLEGUI |
622254885Sdumbbell		 RADEON_ISYNC_CPSCRATCH_IDLEGUI);
623254885Sdumbbell	RADEON_PURGE_CACHE();
624254885Sdumbbell	RADEON_PURGE_ZCACHE();
625254885Sdumbbell	RADEON_WAIT_UNTIL_IDLE();
626254885Sdumbbell	ADVANCE_RING();
627254885Sdumbbell	COMMIT_RING();
628254885Sdumbbell
629254885Sdumbbell	dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
630254885Sdumbbell}
631254885Sdumbbell
632254885Sdumbbell/* Reset the Command Processor.  This will not flush any pending
633254885Sdumbbell * commands, so you must wait for the CP command stream to complete
634254885Sdumbbell * before calling this routine.
635254885Sdumbbell */
636254885Sdumbbellstatic void radeon_do_cp_reset(drm_radeon_private_t * dev_priv)
637254885Sdumbbell{
638254885Sdumbbell	u32 cur_read_ptr;
639254885Sdumbbell	DRM_DEBUG("\n");
640254885Sdumbbell
641254885Sdumbbell	cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
642254885Sdumbbell	RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
643254885Sdumbbell	SET_RING_HEAD(dev_priv, cur_read_ptr);
644254885Sdumbbell	dev_priv->ring.tail = cur_read_ptr;
645254885Sdumbbell}
646254885Sdumbbell
647254885Sdumbbell/* Stop the Command Processor.  This will not flush any pending
648254885Sdumbbell * commands, so you must flush the command stream and wait for the CP
649254885Sdumbbell * to go idle before calling this routine.
650254885Sdumbbell */
651254885Sdumbbellstatic void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
652254885Sdumbbell{
653254885Sdumbbell	RING_LOCALS;
654254885Sdumbbell	DRM_DEBUG("\n");
655254885Sdumbbell
656254885Sdumbbell	/* finish the pending CP_RESYNC token */
657254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
658254885Sdumbbell		BEGIN_RING(2);
659254885Sdumbbell		OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
660254885Sdumbbell		OUT_RING(R300_RB3D_DC_FINISH);
661254885Sdumbbell		ADVANCE_RING();
662254885Sdumbbell		COMMIT_RING();
663254885Sdumbbell		radeon_do_wait_for_idle(dev_priv);
664254885Sdumbbell	}
665254885Sdumbbell
666254885Sdumbbell	RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
667254885Sdumbbell
668254885Sdumbbell	dev_priv->cp_running = 0;
669254885Sdumbbell}
670254885Sdumbbell
671254885Sdumbbell/* Reset the engine.  This will stop the CP if it is running.
672254885Sdumbbell */
673254885Sdumbbellstatic int radeon_do_engine_reset(struct drm_device * dev)
674254885Sdumbbell{
675254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
676254885Sdumbbell	u32 clock_cntl_index = 0, mclk_cntl = 0, rbbm_soft_reset;
677254885Sdumbbell	DRM_DEBUG("\n");
678254885Sdumbbell
679254885Sdumbbell	radeon_do_pixcache_flush(dev_priv);
680254885Sdumbbell
681254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
682254885Sdumbbell		/* may need something similar for newer chips */
683254885Sdumbbell		clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
684254885Sdumbbell		mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
685254885Sdumbbell
686254885Sdumbbell		RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
687254885Sdumbbell						    RADEON_FORCEON_MCLKA |
688254885Sdumbbell						    RADEON_FORCEON_MCLKB |
689254885Sdumbbell						    RADEON_FORCEON_YCLKA |
690254885Sdumbbell						    RADEON_FORCEON_YCLKB |
691254885Sdumbbell						    RADEON_FORCEON_MC |
692254885Sdumbbell						    RADEON_FORCEON_AIC));
693254885Sdumbbell	}
694254885Sdumbbell
695254885Sdumbbell	rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
696254885Sdumbbell
697254885Sdumbbell	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
698254885Sdumbbell					      RADEON_SOFT_RESET_CP |
699254885Sdumbbell					      RADEON_SOFT_RESET_HI |
700254885Sdumbbell					      RADEON_SOFT_RESET_SE |
701254885Sdumbbell					      RADEON_SOFT_RESET_RE |
702254885Sdumbbell					      RADEON_SOFT_RESET_PP |
703254885Sdumbbell					      RADEON_SOFT_RESET_E2 |
704254885Sdumbbell					      RADEON_SOFT_RESET_RB));
705254885Sdumbbell	RADEON_READ(RADEON_RBBM_SOFT_RESET);
706254885Sdumbbell	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
707254885Sdumbbell					      ~(RADEON_SOFT_RESET_CP |
708254885Sdumbbell						RADEON_SOFT_RESET_HI |
709254885Sdumbbell						RADEON_SOFT_RESET_SE |
710254885Sdumbbell						RADEON_SOFT_RESET_RE |
711254885Sdumbbell						RADEON_SOFT_RESET_PP |
712254885Sdumbbell						RADEON_SOFT_RESET_E2 |
713254885Sdumbbell						RADEON_SOFT_RESET_RB)));
714254885Sdumbbell	RADEON_READ(RADEON_RBBM_SOFT_RESET);
715254885Sdumbbell
716254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
717254885Sdumbbell		RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
718254885Sdumbbell		RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
719254885Sdumbbell		RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
720254885Sdumbbell	}
721254885Sdumbbell
722254885Sdumbbell	/* setup the raster pipes */
723254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300)
724254885Sdumbbell	    radeon_init_pipes(dev);
725254885Sdumbbell
726254885Sdumbbell	/* Reset the CP ring */
727254885Sdumbbell	radeon_do_cp_reset(dev_priv);
728254885Sdumbbell
729254885Sdumbbell	/* The CP is no longer running after an engine reset */
730254885Sdumbbell	dev_priv->cp_running = 0;
731254885Sdumbbell
732254885Sdumbbell	/* Reset any pending vertex, indirect buffers */
733254885Sdumbbell	radeon_freelist_reset(dev);
734254885Sdumbbell
735254885Sdumbbell	return 0;
736254885Sdumbbell}
737254885Sdumbbell
738254885Sdumbbellstatic void radeon_cp_init_ring_buffer(struct drm_device * dev,
739254885Sdumbbell				       drm_radeon_private_t *dev_priv,
740254885Sdumbbell				       struct drm_file *file_priv)
741254885Sdumbbell{
742254885Sdumbbell	struct drm_radeon_master_private *master_priv;
743254885Sdumbbell	u32 ring_start, cur_read_ptr;
744254885Sdumbbell
745254885Sdumbbell	/* Initialize the memory controller. With new memory map, the fb location
746254885Sdumbbell	 * is not changed, it should have been properly initialized already. Part
747254885Sdumbbell	 * of the problem is that the code below is bogus, assuming the GART is
748254885Sdumbbell	 * always appended to the fb which is not necessarily the case
749254885Sdumbbell	 */
750254885Sdumbbell	if (!dev_priv->new_memmap)
751254885Sdumbbell		radeon_write_fb_location(dev_priv,
752254885Sdumbbell			     ((dev_priv->gart_vm_start - 1) & 0xffff0000)
753254885Sdumbbell			     | (dev_priv->fb_location >> 16));
754254885Sdumbbell
755254885Sdumbbell#if __OS_HAS_AGP
756254885Sdumbbell	if (dev_priv->flags & RADEON_IS_AGP) {
757254885Sdumbbell		radeon_write_agp_base(dev_priv, dev->agp->base);
758254885Sdumbbell
759254885Sdumbbell		radeon_write_agp_location(dev_priv,
760254885Sdumbbell			     (((dev_priv->gart_vm_start - 1 +
761254885Sdumbbell				dev_priv->gart_size) & 0xffff0000) |
762254885Sdumbbell			      (dev_priv->gart_vm_start >> 16)));
763254885Sdumbbell
764254885Sdumbbell		ring_start = (dev_priv->cp_ring->offset
765254885Sdumbbell			      - dev->agp->base
766254885Sdumbbell			      + dev_priv->gart_vm_start);
767254885Sdumbbell	} else
768254885Sdumbbell#endif
769254885Sdumbbell		ring_start = (dev_priv->cp_ring->offset
770254885Sdumbbell			      - (unsigned long)dev->sg->vaddr
771254885Sdumbbell			      + dev_priv->gart_vm_start);
772254885Sdumbbell
773254885Sdumbbell	RADEON_WRITE(RADEON_CP_RB_BASE, ring_start);
774254885Sdumbbell
775254885Sdumbbell	/* Set the write pointer delay */
776254885Sdumbbell	RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0);
777254885Sdumbbell
778254885Sdumbbell	/* Initialize the ring buffer's read and write pointers */
779254885Sdumbbell	cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
780254885Sdumbbell	RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
781254885Sdumbbell	SET_RING_HEAD(dev_priv, cur_read_ptr);
782254885Sdumbbell	dev_priv->ring.tail = cur_read_ptr;
783254885Sdumbbell
784254885Sdumbbell#if __OS_HAS_AGP
785254885Sdumbbell	if (dev_priv->flags & RADEON_IS_AGP) {
786254885Sdumbbell		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
787254885Sdumbbell			     dev_priv->ring_rptr->offset
788254885Sdumbbell			     - dev->agp->base + dev_priv->gart_vm_start);
789254885Sdumbbell	} else
790254885Sdumbbell#endif
791254885Sdumbbell	{
792254885Sdumbbell		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
793254885Sdumbbell			     dev_priv->ring_rptr->offset
794254885Sdumbbell			     - ((unsigned long) dev->sg->vaddr)
795254885Sdumbbell			     + dev_priv->gart_vm_start);
796254885Sdumbbell	}
797254885Sdumbbell
798254885Sdumbbell	/* Set ring buffer size */
799254885Sdumbbell#ifdef __BIG_ENDIAN
800254885Sdumbbell	RADEON_WRITE(RADEON_CP_RB_CNTL,
801254885Sdumbbell		     RADEON_BUF_SWAP_32BIT |
802254885Sdumbbell		     (dev_priv->ring.fetch_size_l2ow << 18) |
803254885Sdumbbell		     (dev_priv->ring.rptr_update_l2qw << 8) |
804254885Sdumbbell		     dev_priv->ring.size_l2qw);
805254885Sdumbbell#else
806254885Sdumbbell	RADEON_WRITE(RADEON_CP_RB_CNTL,
807254885Sdumbbell		     (dev_priv->ring.fetch_size_l2ow << 18) |
808254885Sdumbbell		     (dev_priv->ring.rptr_update_l2qw << 8) |
809254885Sdumbbell		     dev_priv->ring.size_l2qw);
810254885Sdumbbell#endif
811254885Sdumbbell
812254885Sdumbbell
813254885Sdumbbell	/* Initialize the scratch register pointer.  This will cause
814254885Sdumbbell	 * the scratch register values to be written out to memory
815254885Sdumbbell	 * whenever they are updated.
816254885Sdumbbell	 *
817254885Sdumbbell	 * We simply put this behind the ring read pointer, this works
818254885Sdumbbell	 * with PCI GART as well as (whatever kind of) AGP GART
819254885Sdumbbell	 */
820254885Sdumbbell	RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
821254885Sdumbbell		     + RADEON_SCRATCH_REG_OFFSET);
822254885Sdumbbell
823254885Sdumbbell	RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
824254885Sdumbbell
825254885Sdumbbell	radeon_enable_bm(dev_priv);
826254885Sdumbbell
827254885Sdumbbell	radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(0), 0);
828254885Sdumbbell	RADEON_WRITE(RADEON_LAST_FRAME_REG, 0);
829254885Sdumbbell
830254885Sdumbbell	radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1), 0);
831254885Sdumbbell	RADEON_WRITE(RADEON_LAST_DISPATCH_REG, 0);
832254885Sdumbbell
833254885Sdumbbell	radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(2), 0);
834254885Sdumbbell	RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
835254885Sdumbbell
836254885Sdumbbell	/* reset sarea copies of these */
837254885Sdumbbell	master_priv = file_priv->masterp->driver_priv;
838254885Sdumbbell	if (master_priv->sarea_priv) {
839254885Sdumbbell		master_priv->sarea_priv->last_frame = 0;
840254885Sdumbbell		master_priv->sarea_priv->last_dispatch = 0;
841254885Sdumbbell		master_priv->sarea_priv->last_clear = 0;
842254885Sdumbbell	}
843254885Sdumbbell
844254885Sdumbbell	radeon_do_wait_for_idle(dev_priv);
845254885Sdumbbell
846254885Sdumbbell	/* Sync everything up */
847254885Sdumbbell	RADEON_WRITE(RADEON_ISYNC_CNTL,
848254885Sdumbbell		     (RADEON_ISYNC_ANY2D_IDLE3D |
849254885Sdumbbell		      RADEON_ISYNC_ANY3D_IDLE2D |
850254885Sdumbbell		      RADEON_ISYNC_WAIT_IDLEGUI |
851254885Sdumbbell		      RADEON_ISYNC_CPSCRATCH_IDLEGUI));
852254885Sdumbbell
853254885Sdumbbell}
854254885Sdumbbell
855254885Sdumbbellstatic void radeon_test_writeback(drm_radeon_private_t * dev_priv)
856254885Sdumbbell{
857254885Sdumbbell	u32 tmp;
858254885Sdumbbell
859254885Sdumbbell	/* Start with assuming that writeback doesn't work */
860254885Sdumbbell	dev_priv->writeback_works = 0;
861254885Sdumbbell
862254885Sdumbbell	/* Writeback doesn't seem to work everywhere, test it here and possibly
863254885Sdumbbell	 * enable it if it appears to work
864254885Sdumbbell	 */
865254885Sdumbbell	radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1), 0);
866254885Sdumbbell
867254885Sdumbbell	RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
868254885Sdumbbell
869254885Sdumbbell	for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
870254885Sdumbbell		u32 val;
871254885Sdumbbell
872254885Sdumbbell		val = radeon_read_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1));
873254885Sdumbbell		if (val == 0xdeadbeef)
874254885Sdumbbell			break;
875254885Sdumbbell		DRM_UDELAY(1);
876254885Sdumbbell	}
877254885Sdumbbell
878254885Sdumbbell	if (tmp < dev_priv->usec_timeout) {
879254885Sdumbbell		dev_priv->writeback_works = 1;
880254885Sdumbbell		DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
881254885Sdumbbell	} else {
882254885Sdumbbell		dev_priv->writeback_works = 0;
883254885Sdumbbell		DRM_INFO("writeback test failed\n");
884254885Sdumbbell	}
885254885Sdumbbell	if (radeon_no_wb == 1) {
886254885Sdumbbell		dev_priv->writeback_works = 0;
887254885Sdumbbell		DRM_INFO("writeback forced off\n");
888254885Sdumbbell	}
889254885Sdumbbell
890254885Sdumbbell	if (!dev_priv->writeback_works) {
891254885Sdumbbell		/* Disable writeback to avoid unnecessary bus master transfer */
892254885Sdumbbell		RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) |
893254885Sdumbbell			     RADEON_RB_NO_UPDATE);
894254885Sdumbbell		RADEON_WRITE(RADEON_SCRATCH_UMSK, 0);
895254885Sdumbbell	}
896254885Sdumbbell}
897254885Sdumbbell
898254885Sdumbbell/* Enable or disable IGP GART on the chip */
899254885Sdumbbellstatic void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
900254885Sdumbbell{
901254885Sdumbbell	u32 temp;
902254885Sdumbbell
903254885Sdumbbell	if (on) {
904254885Sdumbbell		DRM_DEBUG("programming igp gart %08X %08lX %08X\n",
905254885Sdumbbell			  dev_priv->gart_vm_start,
906254885Sdumbbell			  (long)dev_priv->gart_info.bus_addr,
907254885Sdumbbell			  dev_priv->gart_size);
908254885Sdumbbell
909254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL);
910254885Sdumbbell		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
911254885Sdumbbell		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
912254885Sdumbbell			IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN |
913254885Sdumbbell							     RS690_BLOCK_GFX_D3_EN));
914254885Sdumbbell		else
915254885Sdumbbell			IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN);
916254885Sdumbbell
917254885Sdumbbell		IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
918254885Sdumbbell							       RS480_VA_SIZE_32MB));
919254885Sdumbbell
920254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS480_GART_FEATURE_ID);
921254885Sdumbbell		IGP_WRITE_MCIND(RS480_GART_FEATURE_ID, (RS480_HANG_EN |
922254885Sdumbbell							RS480_TLB_ENABLE |
923254885Sdumbbell							RS480_GTW_LAC_EN |
924254885Sdumbbell							RS480_1LEVEL_GART));
925254885Sdumbbell
926254885Sdumbbell		temp = dev_priv->gart_info.bus_addr & 0xfffff000;
927254885Sdumbbell		temp |= (upper_32_bits(dev_priv->gart_info.bus_addr) & 0xff) << 4;
928254885Sdumbbell		IGP_WRITE_MCIND(RS480_GART_BASE, temp);
929254885Sdumbbell
930254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS480_AGP_MODE_CNTL);
931254885Sdumbbell		IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) |
932254885Sdumbbell						      RS480_REQ_TYPE_SNOOP_DIS));
933254885Sdumbbell
934254885Sdumbbell		radeon_write_agp_base(dev_priv, dev_priv->gart_vm_start);
935254885Sdumbbell
936254885Sdumbbell		dev_priv->gart_size = 32*1024*1024;
937254885Sdumbbell		temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) &
938254885Sdumbbell			 0xffff0000) | (dev_priv->gart_vm_start >> 16));
939254885Sdumbbell
940254885Sdumbbell		radeon_write_agp_location(dev_priv, temp);
941254885Sdumbbell
942254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS480_AGP_ADDRESS_SPACE_SIZE);
943254885Sdumbbell		IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
944254885Sdumbbell							       RS480_VA_SIZE_32MB));
945254885Sdumbbell
946254885Sdumbbell		do {
947254885Sdumbbell			temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
948254885Sdumbbell			if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
949254885Sdumbbell				break;
950254885Sdumbbell			DRM_UDELAY(1);
951254885Sdumbbell		} while (1);
952254885Sdumbbell
953254885Sdumbbell		IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL,
954254885Sdumbbell				RS480_GART_CACHE_INVALIDATE);
955254885Sdumbbell
956254885Sdumbbell		do {
957254885Sdumbbell			temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
958254885Sdumbbell			if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
959254885Sdumbbell				break;
960254885Sdumbbell			DRM_UDELAY(1);
961254885Sdumbbell		} while (1);
962254885Sdumbbell
963254885Sdumbbell		IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0);
964254885Sdumbbell	} else {
965254885Sdumbbell		IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, 0);
966254885Sdumbbell	}
967254885Sdumbbell}
968254885Sdumbbell
969254885Sdumbbell/* Enable or disable IGP GART on the chip */
970254885Sdumbbellstatic void rs600_set_igpgart(drm_radeon_private_t *dev_priv, int on)
971254885Sdumbbell{
972254885Sdumbbell	u32 temp;
973254885Sdumbbell	int i;
974254885Sdumbbell
975254885Sdumbbell	if (on) {
976254885Sdumbbell		DRM_DEBUG("programming igp gart %08X %08lX %08X\n",
977254885Sdumbbell			 dev_priv->gart_vm_start,
978254885Sdumbbell			 (long)dev_priv->gart_info.bus_addr,
979254885Sdumbbell			 dev_priv->gart_size);
980254885Sdumbbell
981254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (RS600_EFFECTIVE_L2_CACHE_SIZE(6) |
982254885Sdumbbell						    RS600_EFFECTIVE_L2_QUEUE_SIZE(6)));
983254885Sdumbbell
984254885Sdumbbell		for (i = 0; i < 19; i++)
985254885Sdumbbell			IGP_WRITE_MCIND(RS600_MC_PT0_CLIENT0_CNTL + i,
986254885Sdumbbell					(RS600_ENABLE_TRANSLATION_MODE_OVERRIDE |
987254885Sdumbbell					 RS600_SYSTEM_ACCESS_MODE_IN_SYS |
988254885Sdumbbell					 RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH |
989254885Sdumbbell					 RS600_EFFECTIVE_L1_CACHE_SIZE(3) |
990254885Sdumbbell					 RS600_ENABLE_FRAGMENT_PROCESSING |
991254885Sdumbbell					 RS600_EFFECTIVE_L1_QUEUE_SIZE(3)));
992254885Sdumbbell
993254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_CNTL, (RS600_ENABLE_PAGE_TABLE |
994254885Sdumbbell							     RS600_PAGE_TABLE_TYPE_FLAT));
995254885Sdumbbell
996254885Sdumbbell		/* disable all other contexts */
997254885Sdumbbell		for (i = 1; i < 8; i++)
998254885Sdumbbell			IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_CNTL + i, 0);
999254885Sdumbbell
1000254885Sdumbbell		/* setup the page table aperture */
1001254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR,
1002254885Sdumbbell				dev_priv->gart_info.bus_addr);
1003254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR,
1004254885Sdumbbell				dev_priv->gart_vm_start);
1005254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR,
1006254885Sdumbbell				(dev_priv->gart_vm_start + dev_priv->gart_size - 1));
1007254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0);
1008254885Sdumbbell
1009254885Sdumbbell		/* setup the system aperture */
1010254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR,
1011254885Sdumbbell				dev_priv->gart_vm_start);
1012254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR,
1013254885Sdumbbell				(dev_priv->gart_vm_start + dev_priv->gart_size - 1));
1014254885Sdumbbell
1015254885Sdumbbell		/* enable page tables */
1016254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL);
1017254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (temp | RS600_ENABLE_PT));
1018254885Sdumbbell
1019254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS600_MC_CNTL1);
1020254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_CNTL1, (temp | RS600_ENABLE_PAGE_TABLES));
1021254885Sdumbbell
1022254885Sdumbbell		/* invalidate the cache */
1023254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL);
1024254885Sdumbbell
1025254885Sdumbbell		temp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE);
1026254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp);
1027254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL);
1028254885Sdumbbell
1029254885Sdumbbell		temp |= RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE;
1030254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp);
1031254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL);
1032254885Sdumbbell
1033254885Sdumbbell		temp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE);
1034254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp);
1035254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL);
1036254885Sdumbbell
1037254885Sdumbbell	} else {
1038254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, 0);
1039254885Sdumbbell		temp = IGP_READ_MCIND(dev_priv, RS600_MC_CNTL1);
1040254885Sdumbbell		temp &= ~RS600_ENABLE_PAGE_TABLES;
1041254885Sdumbbell		IGP_WRITE_MCIND(RS600_MC_CNTL1, temp);
1042254885Sdumbbell	}
1043254885Sdumbbell}
1044254885Sdumbbell
1045254885Sdumbbellstatic void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
1046254885Sdumbbell{
1047254885Sdumbbell	u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
1048254885Sdumbbell	if (on) {
1049254885Sdumbbell
1050254885Sdumbbell		DRM_DEBUG("programming pcie %08X %08lX %08X\n",
1051254885Sdumbbell			  dev_priv->gart_vm_start,
1052254885Sdumbbell			  (long)dev_priv->gart_info.bus_addr,
1053254885Sdumbbell			  dev_priv->gart_size);
1054254885Sdumbbell		RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO,
1055254885Sdumbbell				  dev_priv->gart_vm_start);
1056254885Sdumbbell		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE,
1057254885Sdumbbell				  dev_priv->gart_info.bus_addr);
1058254885Sdumbbell		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO,
1059254885Sdumbbell				  dev_priv->gart_vm_start);
1060254885Sdumbbell		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO,
1061254885Sdumbbell				  dev_priv->gart_vm_start +
1062254885Sdumbbell				  dev_priv->gart_size - 1);
1063254885Sdumbbell
1064254885Sdumbbell		radeon_write_agp_location(dev_priv, 0xffffffc0); /* ?? */
1065254885Sdumbbell
1066254885Sdumbbell		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
1067254885Sdumbbell				  RADEON_PCIE_TX_GART_EN);
1068254885Sdumbbell	} else {
1069254885Sdumbbell		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
1070254885Sdumbbell				  tmp & ~RADEON_PCIE_TX_GART_EN);
1071254885Sdumbbell	}
1072254885Sdumbbell}
1073254885Sdumbbell
1074254885Sdumbbell/* Enable or disable PCI GART on the chip */
1075254885Sdumbbellstatic void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
1076254885Sdumbbell{
1077254885Sdumbbell	u32 tmp;
1078254885Sdumbbell
1079254885Sdumbbell	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
1080254885Sdumbbell	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740) ||
1081254885Sdumbbell	    (dev_priv->flags & RADEON_IS_IGPGART)) {
1082254885Sdumbbell		radeon_set_igpgart(dev_priv, on);
1083254885Sdumbbell		return;
1084254885Sdumbbell	}
1085254885Sdumbbell
1086254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) {
1087254885Sdumbbell		rs600_set_igpgart(dev_priv, on);
1088254885Sdumbbell		return;
1089254885Sdumbbell	}
1090254885Sdumbbell
1091254885Sdumbbell	if (dev_priv->flags & RADEON_IS_PCIE) {
1092254885Sdumbbell		radeon_set_pciegart(dev_priv, on);
1093254885Sdumbbell		return;
1094254885Sdumbbell	}
1095254885Sdumbbell
1096254885Sdumbbell	tmp = RADEON_READ(RADEON_AIC_CNTL);
1097254885Sdumbbell
1098254885Sdumbbell	if (on) {
1099254885Sdumbbell		RADEON_WRITE(RADEON_AIC_CNTL,
1100254885Sdumbbell			     tmp | RADEON_PCIGART_TRANSLATE_EN);
1101254885Sdumbbell
1102254885Sdumbbell		/* set PCI GART page-table base address
1103254885Sdumbbell		 */
1104254885Sdumbbell		RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);
1105254885Sdumbbell
1106254885Sdumbbell		/* set address range for PCI address translate
1107254885Sdumbbell		 */
1108254885Sdumbbell		RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start);
1109254885Sdumbbell		RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
1110254885Sdumbbell			     + dev_priv->gart_size - 1);
1111254885Sdumbbell
1112254885Sdumbbell		/* Turn off AGP aperture -- is this required for PCI GART?
1113254885Sdumbbell		 */
1114254885Sdumbbell		radeon_write_agp_location(dev_priv, 0xffffffc0);
1115254885Sdumbbell		RADEON_WRITE(RADEON_AGP_COMMAND, 0);	/* clear AGP_COMMAND */
1116254885Sdumbbell	} else {
1117254885Sdumbbell		RADEON_WRITE(RADEON_AIC_CNTL,
1118254885Sdumbbell			     tmp & ~RADEON_PCIGART_TRANSLATE_EN);
1119254885Sdumbbell	}
1120254885Sdumbbell}
1121254885Sdumbbell
1122254885Sdumbbellstatic int radeon_setup_pcigart_surface(drm_radeon_private_t *dev_priv)
1123254885Sdumbbell{
1124254885Sdumbbell	struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info;
1125254885Sdumbbell	struct radeon_virt_surface *vp;
1126254885Sdumbbell	int i;
1127254885Sdumbbell
1128254885Sdumbbell	for (i = 0; i < RADEON_MAX_SURFACES * 2; i++) {
1129254885Sdumbbell		if (!dev_priv->virt_surfaces[i].file_priv ||
1130254885Sdumbbell		    dev_priv->virt_surfaces[i].file_priv == PCIGART_FILE_PRIV)
1131254885Sdumbbell			break;
1132254885Sdumbbell	}
1133254885Sdumbbell	if (i >= 2 * RADEON_MAX_SURFACES)
1134254885Sdumbbell		return -ENOMEM;
1135254885Sdumbbell	vp = &dev_priv->virt_surfaces[i];
1136254885Sdumbbell
1137254885Sdumbbell	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1138254885Sdumbbell		struct radeon_surface *sp = &dev_priv->surfaces[i];
1139254885Sdumbbell		if (sp->refcount)
1140254885Sdumbbell			continue;
1141254885Sdumbbell
1142254885Sdumbbell		vp->surface_index = i;
1143254885Sdumbbell		vp->lower = gart_info->bus_addr;
1144254885Sdumbbell		vp->upper = vp->lower + gart_info->table_size;
1145254885Sdumbbell		vp->flags = 0;
1146254885Sdumbbell		vp->file_priv = PCIGART_FILE_PRIV;
1147254885Sdumbbell
1148254885Sdumbbell		sp->refcount = 1;
1149254885Sdumbbell		sp->lower = vp->lower;
1150254885Sdumbbell		sp->upper = vp->upper;
1151254885Sdumbbell		sp->flags = 0;
1152254885Sdumbbell
1153254885Sdumbbell		RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, sp->flags);
1154254885Sdumbbell		RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * i, sp->lower);
1155254885Sdumbbell		RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * i, sp->upper);
1156254885Sdumbbell		return 0;
1157254885Sdumbbell	}
1158254885Sdumbbell
1159254885Sdumbbell	return -ENOMEM;
1160254885Sdumbbell}
1161254885Sdumbbell
1162254885Sdumbbellstatic int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
1163254885Sdumbbell			     struct drm_file *file_priv)
1164254885Sdumbbell{
1165254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1166254885Sdumbbell	struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
1167254885Sdumbbell
1168254885Sdumbbell	DRM_DEBUG("\n");
1169254885Sdumbbell
1170254885Sdumbbell	/* if we require new memory map but we don't have it fail */
1171254885Sdumbbell	if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
1172254885Sdumbbell		DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
1173254885Sdumbbell		radeon_do_cleanup_cp(dev);
1174254885Sdumbbell		return -EINVAL;
1175254885Sdumbbell	}
1176254885Sdumbbell
1177254885Sdumbbell	if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
1178254885Sdumbbell		DRM_DEBUG("Forcing AGP card to PCI mode\n");
1179254885Sdumbbell		dev_priv->flags &= ~RADEON_IS_AGP;
1180254885Sdumbbell	} else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
1181254885Sdumbbell		   && !init->is_pci) {
1182254885Sdumbbell		DRM_DEBUG("Restoring AGP flag\n");
1183254885Sdumbbell		dev_priv->flags |= RADEON_IS_AGP;
1184254885Sdumbbell	}
1185254885Sdumbbell
1186254885Sdumbbell	if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
1187254885Sdumbbell		DRM_ERROR("PCI GART memory not allocated!\n");
1188254885Sdumbbell		radeon_do_cleanup_cp(dev);
1189254885Sdumbbell		return -EINVAL;
1190254885Sdumbbell	}
1191254885Sdumbbell
1192254885Sdumbbell	dev_priv->usec_timeout = init->usec_timeout;
1193254885Sdumbbell	if (dev_priv->usec_timeout < 1 ||
1194254885Sdumbbell	    dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
1195254885Sdumbbell		DRM_DEBUG("TIMEOUT problem!\n");
1196254885Sdumbbell		radeon_do_cleanup_cp(dev);
1197254885Sdumbbell		return -EINVAL;
1198254885Sdumbbell	}
1199254885Sdumbbell
1200254885Sdumbbell	/* Enable vblank on CRTC1 for older X servers
1201254885Sdumbbell	 */
1202254885Sdumbbell	dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
1203254885Sdumbbell
1204254885Sdumbbell	switch(init->func) {
1205254885Sdumbbell	case RADEON_INIT_R200_CP:
1206254885Sdumbbell		dev_priv->microcode_version = UCODE_R200;
1207254885Sdumbbell		break;
1208254885Sdumbbell	case RADEON_INIT_R300_CP:
1209254885Sdumbbell		dev_priv->microcode_version = UCODE_R300;
1210254885Sdumbbell		break;
1211254885Sdumbbell	default:
1212254885Sdumbbell		dev_priv->microcode_version = UCODE_R100;
1213254885Sdumbbell	}
1214254885Sdumbbell
1215254885Sdumbbell	dev_priv->do_boxes = 0;
1216254885Sdumbbell	dev_priv->cp_mode = init->cp_mode;
1217254885Sdumbbell
1218254885Sdumbbell	/* We don't support anything other than bus-mastering ring mode,
1219254885Sdumbbell	 * but the ring can be in either AGP or PCI space for the ring
1220254885Sdumbbell	 * read pointer.
1221254885Sdumbbell	 */
1222254885Sdumbbell	if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
1223254885Sdumbbell	    (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
1224254885Sdumbbell		DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
1225254885Sdumbbell		radeon_do_cleanup_cp(dev);
1226254885Sdumbbell		return -EINVAL;
1227254885Sdumbbell	}
1228254885Sdumbbell
1229254885Sdumbbell	switch (init->fb_bpp) {
1230254885Sdumbbell	case 16:
1231254885Sdumbbell		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
1232254885Sdumbbell		break;
1233254885Sdumbbell	case 32:
1234254885Sdumbbell	default:
1235254885Sdumbbell		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
1236254885Sdumbbell		break;
1237254885Sdumbbell	}
1238254885Sdumbbell	dev_priv->front_offset = init->front_offset;
1239254885Sdumbbell	dev_priv->front_pitch = init->front_pitch;
1240254885Sdumbbell	dev_priv->back_offset = init->back_offset;
1241254885Sdumbbell	dev_priv->back_pitch = init->back_pitch;
1242254885Sdumbbell
1243254885Sdumbbell	switch (init->depth_bpp) {
1244254885Sdumbbell	case 16:
1245254885Sdumbbell		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
1246254885Sdumbbell		break;
1247254885Sdumbbell	case 32:
1248254885Sdumbbell	default:
1249254885Sdumbbell		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
1250254885Sdumbbell		break;
1251254885Sdumbbell	}
1252254885Sdumbbell	dev_priv->depth_offset = init->depth_offset;
1253254885Sdumbbell	dev_priv->depth_pitch = init->depth_pitch;
1254254885Sdumbbell
1255254885Sdumbbell	/* Hardware state for depth clears.  Remove this if/when we no
1256254885Sdumbbell	 * longer clear the depth buffer with a 3D rectangle.  Hard-code
1257254885Sdumbbell	 * all values to prevent unwanted 3D state from slipping through
1258254885Sdumbbell	 * and screwing with the clear operation.
1259254885Sdumbbell	 */
1260254885Sdumbbell	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
1261254885Sdumbbell					   (dev_priv->color_fmt << 10) |
1262254885Sdumbbell					   (dev_priv->microcode_version ==
1263254885Sdumbbell					    UCODE_R100 ? RADEON_ZBLOCK16 : 0));
1264254885Sdumbbell
1265254885Sdumbbell	dev_priv->depth_clear.rb3d_zstencilcntl =
1266254885Sdumbbell	    (dev_priv->depth_fmt |
1267254885Sdumbbell	     RADEON_Z_TEST_ALWAYS |
1268254885Sdumbbell	     RADEON_STENCIL_TEST_ALWAYS |
1269254885Sdumbbell	     RADEON_STENCIL_S_FAIL_REPLACE |
1270254885Sdumbbell	     RADEON_STENCIL_ZPASS_REPLACE |
1271254885Sdumbbell	     RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE);
1272254885Sdumbbell
1273254885Sdumbbell	dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
1274254885Sdumbbell					 RADEON_BFACE_SOLID |
1275254885Sdumbbell					 RADEON_FFACE_SOLID |
1276254885Sdumbbell					 RADEON_FLAT_SHADE_VTX_LAST |
1277254885Sdumbbell					 RADEON_DIFFUSE_SHADE_FLAT |
1278254885Sdumbbell					 RADEON_ALPHA_SHADE_FLAT |
1279254885Sdumbbell					 RADEON_SPECULAR_SHADE_FLAT |
1280254885Sdumbbell					 RADEON_FOG_SHADE_FLAT |
1281254885Sdumbbell					 RADEON_VTX_PIX_CENTER_OGL |
1282254885Sdumbbell					 RADEON_ROUND_MODE_TRUNC |
1283254885Sdumbbell					 RADEON_ROUND_PREC_8TH_PIX);
1284254885Sdumbbell
1285254885Sdumbbell
1286254885Sdumbbell	dev_priv->ring_offset = init->ring_offset;
1287254885Sdumbbell	dev_priv->ring_rptr_offset = init->ring_rptr_offset;
1288254885Sdumbbell	dev_priv->buffers_offset = init->buffers_offset;
1289254885Sdumbbell	dev_priv->gart_textures_offset = init->gart_textures_offset;
1290254885Sdumbbell
1291254885Sdumbbell	master_priv->sarea = drm_getsarea(dev);
1292254885Sdumbbell	if (!master_priv->sarea) {
1293254885Sdumbbell		DRM_ERROR("could not find sarea!\n");
1294254885Sdumbbell		radeon_do_cleanup_cp(dev);
1295254885Sdumbbell		return -EINVAL;
1296254885Sdumbbell	}
1297254885Sdumbbell
1298254885Sdumbbell	dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
1299254885Sdumbbell	if (!dev_priv->cp_ring) {
1300254885Sdumbbell		DRM_ERROR("could not find cp ring region!\n");
1301254885Sdumbbell		radeon_do_cleanup_cp(dev);
1302254885Sdumbbell		return -EINVAL;
1303254885Sdumbbell	}
1304254885Sdumbbell	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
1305254885Sdumbbell	if (!dev_priv->ring_rptr) {
1306254885Sdumbbell		DRM_ERROR("could not find ring read pointer!\n");
1307254885Sdumbbell		radeon_do_cleanup_cp(dev);
1308254885Sdumbbell		return -EINVAL;
1309254885Sdumbbell	}
1310254885Sdumbbell	dev->agp_buffer_token = init->buffers_offset;
1311254885Sdumbbell	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
1312254885Sdumbbell	if (!dev->agp_buffer_map) {
1313254885Sdumbbell		DRM_ERROR("could not find dma buffer region!\n");
1314254885Sdumbbell		radeon_do_cleanup_cp(dev);
1315254885Sdumbbell		return -EINVAL;
1316254885Sdumbbell	}
1317254885Sdumbbell
1318254885Sdumbbell	if (init->gart_textures_offset) {
1319254885Sdumbbell		dev_priv->gart_textures =
1320254885Sdumbbell		    drm_core_findmap(dev, init->gart_textures_offset);
1321254885Sdumbbell		if (!dev_priv->gart_textures) {
1322254885Sdumbbell			DRM_ERROR("could not find GART texture region!\n");
1323254885Sdumbbell			radeon_do_cleanup_cp(dev);
1324254885Sdumbbell			return -EINVAL;
1325254885Sdumbbell		}
1326254885Sdumbbell	}
1327254885Sdumbbell
1328254885Sdumbbell#if __OS_HAS_AGP
1329254885Sdumbbell	if (dev_priv->flags & RADEON_IS_AGP) {
1330254885Sdumbbell		drm_core_ioremap_wc(dev_priv->cp_ring, dev);
1331254885Sdumbbell		drm_core_ioremap_wc(dev_priv->ring_rptr, dev);
1332254885Sdumbbell		drm_core_ioremap_wc(dev->agp_buffer_map, dev);
1333254885Sdumbbell		if (!dev_priv->cp_ring->handle ||
1334254885Sdumbbell		    !dev_priv->ring_rptr->handle ||
1335254885Sdumbbell		    !dev->agp_buffer_map->handle) {
1336254885Sdumbbell			DRM_ERROR("could not find ioremap agp regions!\n");
1337254885Sdumbbell			radeon_do_cleanup_cp(dev);
1338254885Sdumbbell			return -EINVAL;
1339254885Sdumbbell		}
1340254885Sdumbbell	} else
1341254885Sdumbbell#endif
1342254885Sdumbbell	{
1343254885Sdumbbell		dev_priv->cp_ring->handle =
1344254885Sdumbbell			(void *)(unsigned long)dev_priv->cp_ring->offset;
1345254885Sdumbbell		dev_priv->ring_rptr->handle =
1346254885Sdumbbell			(void *)(unsigned long)dev_priv->ring_rptr->offset;
1347254885Sdumbbell		dev->agp_buffer_map->handle =
1348254885Sdumbbell			(void *)(unsigned long)dev->agp_buffer_map->offset;
1349254885Sdumbbell
1350254885Sdumbbell		DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
1351254885Sdumbbell			  dev_priv->cp_ring->handle);
1352254885Sdumbbell		DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
1353254885Sdumbbell			  dev_priv->ring_rptr->handle);
1354254885Sdumbbell		DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
1355254885Sdumbbell			  dev->agp_buffer_map->handle);
1356254885Sdumbbell	}
1357254885Sdumbbell
1358254885Sdumbbell	dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16;
1359254885Sdumbbell	dev_priv->fb_size =
1360254885Sdumbbell		((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000)
1361254885Sdumbbell		- dev_priv->fb_location;
1362254885Sdumbbell
1363254885Sdumbbell	dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
1364254885Sdumbbell					((dev_priv->front_offset
1365254885Sdumbbell					  + dev_priv->fb_location) >> 10));
1366254885Sdumbbell
1367254885Sdumbbell	dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
1368254885Sdumbbell				       ((dev_priv->back_offset
1369254885Sdumbbell					 + dev_priv->fb_location) >> 10));
1370254885Sdumbbell
1371254885Sdumbbell	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
1372254885Sdumbbell					((dev_priv->depth_offset
1373254885Sdumbbell					  + dev_priv->fb_location) >> 10));
1374254885Sdumbbell
1375254885Sdumbbell	dev_priv->gart_size = init->gart_size;
1376254885Sdumbbell
1377254885Sdumbbell	/* New let's set the memory map ... */
1378254885Sdumbbell	if (dev_priv->new_memmap) {
1379254885Sdumbbell		u32 base = 0;
1380254885Sdumbbell
1381254885Sdumbbell		DRM_INFO("Setting GART location based on new memory map\n");
1382254885Sdumbbell
1383254885Sdumbbell		/* If using AGP, try to locate the AGP aperture at the same
1384254885Sdumbbell		 * location in the card and on the bus, though we have to
1385254885Sdumbbell		 * align it down.
1386254885Sdumbbell		 */
1387254885Sdumbbell#if __OS_HAS_AGP
1388254885Sdumbbell		if (dev_priv->flags & RADEON_IS_AGP) {
1389254885Sdumbbell			base = dev->agp->base;
1390254885Sdumbbell			/* Check if valid */
1391254885Sdumbbell			if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
1392254885Sdumbbell			    base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
1393254885Sdumbbell				DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
1394254885Sdumbbell					 dev->agp->base);
1395254885Sdumbbell				base = 0;
1396254885Sdumbbell			}
1397254885Sdumbbell		}
1398254885Sdumbbell#endif
1399254885Sdumbbell		/* If not or if AGP is at 0 (Macs), try to put it elsewhere */
1400254885Sdumbbell		if (base == 0) {
1401254885Sdumbbell			base = dev_priv->fb_location + dev_priv->fb_size;
1402254885Sdumbbell			if (base < dev_priv->fb_location ||
1403254885Sdumbbell			    ((base + dev_priv->gart_size) & 0xfffffffful) < base)
1404254885Sdumbbell				base = dev_priv->fb_location
1405254885Sdumbbell					- dev_priv->gart_size;
1406254885Sdumbbell		}
1407254885Sdumbbell		dev_priv->gart_vm_start = base & 0xffc00000u;
1408254885Sdumbbell		if (dev_priv->gart_vm_start != base)
1409254885Sdumbbell			DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
1410254885Sdumbbell				 base, dev_priv->gart_vm_start);
1411254885Sdumbbell	} else {
1412254885Sdumbbell		DRM_INFO("Setting GART location based on old memory map\n");
1413254885Sdumbbell		dev_priv->gart_vm_start = dev_priv->fb_location +
1414254885Sdumbbell			RADEON_READ(RADEON_CONFIG_APER_SIZE);
1415254885Sdumbbell	}
1416254885Sdumbbell
1417254885Sdumbbell#if __OS_HAS_AGP
1418254885Sdumbbell	if (dev_priv->flags & RADEON_IS_AGP)
1419254885Sdumbbell		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
1420254885Sdumbbell						 - dev->agp->base
1421254885Sdumbbell						 + dev_priv->gart_vm_start);
1422254885Sdumbbell	else
1423254885Sdumbbell#endif
1424254885Sdumbbell		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
1425254885Sdumbbell					- (unsigned long)dev->sg->vaddr
1426254885Sdumbbell					+ dev_priv->gart_vm_start);
1427254885Sdumbbell
1428254885Sdumbbell	DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
1429254885Sdumbbell	DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start);
1430254885Sdumbbell	DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",
1431254885Sdumbbell		  dev_priv->gart_buffers_offset);
1432254885Sdumbbell
1433254885Sdumbbell	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
1434254885Sdumbbell	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
1435254885Sdumbbell			      + init->ring_size / sizeof(u32));
1436254885Sdumbbell	dev_priv->ring.size = init->ring_size;
1437254885Sdumbbell	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
1438254885Sdumbbell
1439254885Sdumbbell	dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
1440254885Sdumbbell	dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8);
1441254885Sdumbbell
1442254885Sdumbbell	dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
1443254885Sdumbbell	dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16);
1444254885Sdumbbell	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
1445254885Sdumbbell
1446254885Sdumbbell	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
1447254885Sdumbbell
1448254885Sdumbbell#if __OS_HAS_AGP
1449254885Sdumbbell	if (dev_priv->flags & RADEON_IS_AGP) {
1450254885Sdumbbell		/* Turn off PCI GART */
1451254885Sdumbbell		radeon_set_pcigart(dev_priv, 0);
1452254885Sdumbbell	} else
1453254885Sdumbbell#endif
1454254885Sdumbbell	{
1455254885Sdumbbell		u32 sctrl;
1456254885Sdumbbell		int ret;
1457254885Sdumbbell
1458254885Sdumbbell		dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
1459254885Sdumbbell		/* if we have an offset set from userspace */
1460254885Sdumbbell		if (dev_priv->pcigart_offset_set) {
1461254885Sdumbbell			dev_priv->gart_info.bus_addr =
1462254885Sdumbbell				(resource_size_t)dev_priv->pcigart_offset + dev_priv->fb_location;
1463254885Sdumbbell			dev_priv->gart_info.mapping.offset =
1464254885Sdumbbell			    dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
1465254885Sdumbbell			dev_priv->gart_info.mapping.size =
1466254885Sdumbbell			    dev_priv->gart_info.table_size;
1467254885Sdumbbell
1468254885Sdumbbell			drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev);
1469254885Sdumbbell			dev_priv->gart_info.addr =
1470254885Sdumbbell			    dev_priv->gart_info.mapping.handle;
1471254885Sdumbbell
1472254885Sdumbbell			if (dev_priv->flags & RADEON_IS_PCIE)
1473254885Sdumbbell				dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
1474254885Sdumbbell			else
1475254885Sdumbbell				dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
1476254885Sdumbbell			dev_priv->gart_info.gart_table_location =
1477254885Sdumbbell			    DRM_ATI_GART_FB;
1478254885Sdumbbell
1479254885Sdumbbell			DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
1480254885Sdumbbell				  dev_priv->gart_info.addr,
1481254885Sdumbbell				  dev_priv->pcigart_offset);
1482254885Sdumbbell		} else {
1483254885Sdumbbell			if (dev_priv->flags & RADEON_IS_IGPGART)
1484254885Sdumbbell				dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP;
1485254885Sdumbbell			else
1486254885Sdumbbell				dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
1487254885Sdumbbell			dev_priv->gart_info.gart_table_location =
1488254885Sdumbbell			    DRM_ATI_GART_MAIN;
1489254885Sdumbbell			dev_priv->gart_info.addr = NULL;
1490254885Sdumbbell			dev_priv->gart_info.bus_addr = 0;
1491254885Sdumbbell			if (dev_priv->flags & RADEON_IS_PCIE) {
1492254885Sdumbbell				DRM_ERROR
1493254885Sdumbbell				    ("Cannot use PCI Express without GART in FB memory\n");
1494254885Sdumbbell				radeon_do_cleanup_cp(dev);
1495254885Sdumbbell				return -EINVAL;
1496254885Sdumbbell			}
1497254885Sdumbbell		}
1498254885Sdumbbell
1499254885Sdumbbell		sctrl = RADEON_READ(RADEON_SURFACE_CNTL);
1500254885Sdumbbell		RADEON_WRITE(RADEON_SURFACE_CNTL, 0);
1501254885Sdumbbell		if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
1502254885Sdumbbell			ret = r600_page_table_init(dev);
1503254885Sdumbbell		else
1504254885Sdumbbell			ret = drm_ati_pcigart_init(dev, &dev_priv->gart_info);
1505254885Sdumbbell		RADEON_WRITE(RADEON_SURFACE_CNTL, sctrl);
1506254885Sdumbbell
1507254885Sdumbbell		if (!ret) {
1508254885Sdumbbell			DRM_ERROR("failed to init PCI GART!\n");
1509254885Sdumbbell			radeon_do_cleanup_cp(dev);
1510254885Sdumbbell			return -ENOMEM;
1511254885Sdumbbell		}
1512254885Sdumbbell
1513254885Sdumbbell		ret = radeon_setup_pcigart_surface(dev_priv);
1514254885Sdumbbell		if (ret) {
1515254885Sdumbbell			DRM_ERROR("failed to setup GART surface!\n");
1516254885Sdumbbell			if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
1517254885Sdumbbell				r600_page_table_cleanup(dev, &dev_priv->gart_info);
1518254885Sdumbbell			else
1519254885Sdumbbell				drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info);
1520254885Sdumbbell			radeon_do_cleanup_cp(dev);
1521254885Sdumbbell			return ret;
1522254885Sdumbbell		}
1523254885Sdumbbell
1524254885Sdumbbell		/* Turn on PCI GART */
1525254885Sdumbbell		radeon_set_pcigart(dev_priv, 1);
1526254885Sdumbbell	}
1527254885Sdumbbell
1528254885Sdumbbell	if (!dev_priv->me_fw) {
1529254885Sdumbbell		int err = radeon_cp_init_microcode(dev_priv);
1530254885Sdumbbell		if (err) {
1531254885Sdumbbell			DRM_ERROR("Failed to load firmware!\n");
1532254885Sdumbbell			radeon_do_cleanup_cp(dev);
1533254885Sdumbbell			return err;
1534254885Sdumbbell		}
1535254885Sdumbbell	}
1536254885Sdumbbell	radeon_cp_load_microcode(dev_priv);
1537254885Sdumbbell	radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
1538254885Sdumbbell
1539254885Sdumbbell	dev_priv->last_buf = 0;
1540254885Sdumbbell
1541254885Sdumbbell	radeon_do_engine_reset(dev);
1542254885Sdumbbell	radeon_test_writeback(dev_priv);
1543254885Sdumbbell
1544254885Sdumbbell	return 0;
1545254885Sdumbbell}
1546254885Sdumbbell
1547254885Sdumbbellstatic int radeon_do_cleanup_cp(struct drm_device * dev)
1548254885Sdumbbell{
1549254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1550254885Sdumbbell	DRM_DEBUG("\n");
1551254885Sdumbbell
1552254885Sdumbbell	/* Make sure interrupts are disabled here because the uninstall ioctl
1553254885Sdumbbell	 * may not have been called from userspace and after dev_private
1554254885Sdumbbell	 * is freed, it's too late.
1555254885Sdumbbell	 */
1556254885Sdumbbell	if (dev->irq_enabled)
1557254885Sdumbbell		drm_irq_uninstall(dev);
1558254885Sdumbbell
1559254885Sdumbbell#if __OS_HAS_AGP
1560254885Sdumbbell	if (dev_priv->flags & RADEON_IS_AGP) {
1561254885Sdumbbell		if (dev_priv->cp_ring != NULL) {
1562254885Sdumbbell			drm_core_ioremapfree(dev_priv->cp_ring, dev);
1563254885Sdumbbell			dev_priv->cp_ring = NULL;
1564254885Sdumbbell		}
1565254885Sdumbbell		if (dev_priv->ring_rptr != NULL) {
1566254885Sdumbbell			drm_core_ioremapfree(dev_priv->ring_rptr, dev);
1567254885Sdumbbell			dev_priv->ring_rptr = NULL;
1568254885Sdumbbell		}
1569254885Sdumbbell		if (dev->agp_buffer_map != NULL) {
1570254885Sdumbbell			drm_core_ioremapfree(dev->agp_buffer_map, dev);
1571254885Sdumbbell			dev->agp_buffer_map = NULL;
1572254885Sdumbbell		}
1573254885Sdumbbell	} else
1574254885Sdumbbell#endif
1575254885Sdumbbell	{
1576254885Sdumbbell
1577254885Sdumbbell		if (dev_priv->gart_info.bus_addr) {
1578254885Sdumbbell			/* Turn off PCI GART */
1579254885Sdumbbell			radeon_set_pcigart(dev_priv, 0);
1580254885Sdumbbell			if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
1581254885Sdumbbell				r600_page_table_cleanup(dev, &dev_priv->gart_info);
1582254885Sdumbbell			else {
1583254885Sdumbbell				if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
1584254885Sdumbbell					DRM_ERROR("failed to cleanup PCI GART!\n");
1585254885Sdumbbell			}
1586254885Sdumbbell		}
1587254885Sdumbbell
1588254885Sdumbbell		if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
1589254885Sdumbbell		{
1590254885Sdumbbell			drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
1591254885Sdumbbell			dev_priv->gart_info.addr = NULL;
1592254885Sdumbbell		}
1593254885Sdumbbell	}
1594254885Sdumbbell	/* only clear to the start of flags */
1595254885Sdumbbell	memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
1596254885Sdumbbell
1597254885Sdumbbell	return 0;
1598254885Sdumbbell}
1599254885Sdumbbell
1600254885Sdumbbell/* This code will reinit the Radeon CP hardware after a resume from disc.
1601254885Sdumbbell * AFAIK, it would be very difficult to pickle the state at suspend time, so
1602254885Sdumbbell * here we make sure that all Radeon hardware initialisation is re-done without
1603254885Sdumbbell * affecting running applications.
1604254885Sdumbbell *
1605254885Sdumbbell * Charl P. Botha <http://cpbotha.net>
1606254885Sdumbbell */
1607254885Sdumbbellstatic int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv)
1608254885Sdumbbell{
1609254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1610254885Sdumbbell
1611254885Sdumbbell	if (!dev_priv) {
1612254885Sdumbbell		DRM_ERROR("Called with no initialization\n");
1613254885Sdumbbell		return -EINVAL;
1614254885Sdumbbell	}
1615254885Sdumbbell
1616254885Sdumbbell	DRM_DEBUG("Starting radeon_do_resume_cp()\n");
1617254885Sdumbbell
1618254885Sdumbbell#if __OS_HAS_AGP
1619254885Sdumbbell	if (dev_priv->flags & RADEON_IS_AGP) {
1620254885Sdumbbell		/* Turn off PCI GART */
1621254885Sdumbbell		radeon_set_pcigart(dev_priv, 0);
1622254885Sdumbbell	} else
1623254885Sdumbbell#endif
1624254885Sdumbbell	{
1625254885Sdumbbell		/* Turn on PCI GART */
1626254885Sdumbbell		radeon_set_pcigart(dev_priv, 1);
1627254885Sdumbbell	}
1628254885Sdumbbell
1629254885Sdumbbell	radeon_cp_load_microcode(dev_priv);
1630254885Sdumbbell	radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
1631254885Sdumbbell
1632254885Sdumbbell	dev_priv->have_z_offset = 0;
1633254885Sdumbbell	radeon_do_engine_reset(dev);
1634254885Sdumbbell	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
1635254885Sdumbbell
1636254885Sdumbbell	DRM_DEBUG("radeon_do_resume_cp() complete\n");
1637254885Sdumbbell
1638254885Sdumbbell	return 0;
1639254885Sdumbbell}
1640254885Sdumbbell
1641254885Sdumbbellint radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
1642254885Sdumbbell{
1643254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1644254885Sdumbbell	drm_radeon_init_t *init = data;
1645254885Sdumbbell
1646254885Sdumbbell	LOCK_TEST_WITH_RETURN(dev, file_priv);
1647254885Sdumbbell
1648254885Sdumbbell	if (init->func == RADEON_INIT_R300_CP)
1649254885Sdumbbell		r300_init_reg_flags(dev);
1650254885Sdumbbell
1651254885Sdumbbell	switch (init->func) {
1652254885Sdumbbell	case RADEON_INIT_CP:
1653254885Sdumbbell	case RADEON_INIT_R200_CP:
1654254885Sdumbbell	case RADEON_INIT_R300_CP:
1655254885Sdumbbell		return radeon_do_init_cp(dev, init, file_priv);
1656254885Sdumbbell	case RADEON_INIT_R600_CP:
1657254885Sdumbbell		return r600_do_init_cp(dev, init, file_priv);
1658254885Sdumbbell		break;
1659254885Sdumbbell	case RADEON_CLEANUP_CP:
1660254885Sdumbbell		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
1661254885Sdumbbell			return r600_do_cleanup_cp(dev);
1662254885Sdumbbell		else
1663254885Sdumbbell			return radeon_do_cleanup_cp(dev);
1664254885Sdumbbell	}
1665254885Sdumbbell
1666254885Sdumbbell	return -EINVAL;
1667254885Sdumbbell}
1668254885Sdumbbell
1669254885Sdumbbellint radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
1670254885Sdumbbell{
1671254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1672254885Sdumbbell	DRM_DEBUG("\n");
1673254885Sdumbbell
1674254885Sdumbbell	LOCK_TEST_WITH_RETURN(dev, file_priv);
1675254885Sdumbbell
1676254885Sdumbbell	if (dev_priv->cp_running) {
1677254885Sdumbbell		DRM_DEBUG("while CP running\n");
1678254885Sdumbbell		return 0;
1679254885Sdumbbell	}
1680254885Sdumbbell	if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
1681254885Sdumbbell		DRM_DEBUG("called with bogus CP mode (%d)\n",
1682254885Sdumbbell			  dev_priv->cp_mode);
1683254885Sdumbbell		return 0;
1684254885Sdumbbell	}
1685254885Sdumbbell
1686254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
1687254885Sdumbbell		r600_do_cp_start(dev_priv);
1688254885Sdumbbell	else
1689254885Sdumbbell		radeon_do_cp_start(dev_priv);
1690254885Sdumbbell
1691254885Sdumbbell	return 0;
1692254885Sdumbbell}
1693254885Sdumbbell
1694254885Sdumbbell/* Stop the CP.  The engine must have been idled before calling this
1695254885Sdumbbell * routine.
1696254885Sdumbbell */
1697254885Sdumbbellint radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv)
1698254885Sdumbbell{
1699254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1700254885Sdumbbell	drm_radeon_cp_stop_t *stop = data;
1701254885Sdumbbell	int ret;
1702254885Sdumbbell	DRM_DEBUG("\n");
1703254885Sdumbbell
1704254885Sdumbbell	LOCK_TEST_WITH_RETURN(dev, file_priv);
1705254885Sdumbbell
1706254885Sdumbbell	if (!dev_priv->cp_running)
1707254885Sdumbbell		return 0;
1708254885Sdumbbell
1709254885Sdumbbell	/* Flush any pending CP commands.  This ensures any outstanding
1710254885Sdumbbell	 * commands are exectuted by the engine before we turn it off.
1711254885Sdumbbell	 */
1712254885Sdumbbell	if (stop->flush) {
1713254885Sdumbbell		radeon_do_cp_flush(dev_priv);
1714254885Sdumbbell	}
1715254885Sdumbbell
1716254885Sdumbbell	/* If we fail to make the engine go idle, we return an error
1717254885Sdumbbell	 * code so that the DRM ioctl wrapper can try again.
1718254885Sdumbbell	 */
1719254885Sdumbbell	if (stop->idle) {
1720254885Sdumbbell		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
1721254885Sdumbbell			ret = r600_do_cp_idle(dev_priv);
1722254885Sdumbbell		else
1723254885Sdumbbell			ret = radeon_do_cp_idle(dev_priv);
1724254885Sdumbbell		if (ret)
1725254885Sdumbbell			return ret;
1726254885Sdumbbell	}
1727254885Sdumbbell
1728254885Sdumbbell	/* Finally, we can turn off the CP.  If the engine isn't idle,
1729254885Sdumbbell	 * we will get some dropped triangles as they won't be fully
1730254885Sdumbbell	 * rendered before the CP is shut down.
1731254885Sdumbbell	 */
1732254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
1733254885Sdumbbell		r600_do_cp_stop(dev_priv);
1734254885Sdumbbell	else
1735254885Sdumbbell		radeon_do_cp_stop(dev_priv);
1736254885Sdumbbell
1737254885Sdumbbell	/* Reset the engine */
1738254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
1739254885Sdumbbell		r600_do_engine_reset(dev);
1740254885Sdumbbell	else
1741254885Sdumbbell		radeon_do_engine_reset(dev);
1742254885Sdumbbell
1743254885Sdumbbell	return 0;
1744254885Sdumbbell}
1745254885Sdumbbell
1746254885Sdumbbellvoid radeon_do_release(struct drm_device * dev)
1747254885Sdumbbell{
1748254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1749254885Sdumbbell	int i, ret;
1750254885Sdumbbell
1751254885Sdumbbell	if (dev_priv) {
1752254885Sdumbbell		if (dev_priv->cp_running) {
1753254885Sdumbbell			/* Stop the cp */
1754254885Sdumbbell			if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
1755254885Sdumbbell				while ((ret = r600_do_cp_idle(dev_priv)) != 0) {
1756254885Sdumbbell					DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
1757254885Sdumbbell#ifdef __linux__
1758254885Sdumbbell					schedule();
1759254885Sdumbbell#else
1760254885Sdumbbell					tsleep(&ret, PZERO, "rdnrel", 1);
1761254885Sdumbbell#endif
1762254885Sdumbbell				}
1763254885Sdumbbell			} else {
1764254885Sdumbbell				while ((ret = radeon_do_cp_idle(dev_priv)) != 0) {
1765254885Sdumbbell					DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
1766254885Sdumbbell#ifdef __linux__
1767254885Sdumbbell					schedule();
1768254885Sdumbbell#else
1769254885Sdumbbell					tsleep(&ret, PZERO, "rdnrel", 1);
1770254885Sdumbbell#endif
1771254885Sdumbbell				}
1772254885Sdumbbell			}
1773254885Sdumbbell			if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
1774254885Sdumbbell				r600_do_cp_stop(dev_priv);
1775254885Sdumbbell				r600_do_engine_reset(dev);
1776254885Sdumbbell			} else {
1777254885Sdumbbell				radeon_do_cp_stop(dev_priv);
1778254885Sdumbbell				radeon_do_engine_reset(dev);
1779254885Sdumbbell			}
1780254885Sdumbbell		}
1781254885Sdumbbell
1782254885Sdumbbell		if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_R600) {
1783254885Sdumbbell			/* Disable *all* interrupts */
1784254885Sdumbbell			if (dev_priv->mmio)	/* remove this after permanent addmaps */
1785254885Sdumbbell				RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
1786254885Sdumbbell
1787254885Sdumbbell			if (dev_priv->mmio) {	/* remove all surfaces */
1788254885Sdumbbell				for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1789254885Sdumbbell					RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0);
1790254885Sdumbbell					RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND +
1791254885Sdumbbell						     16 * i, 0);
1792254885Sdumbbell					RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND +
1793254885Sdumbbell						     16 * i, 0);
1794254885Sdumbbell				}
1795254885Sdumbbell			}
1796254885Sdumbbell		}
1797254885Sdumbbell
1798254885Sdumbbell		/* Free memory heap structures */
1799254885Sdumbbell		radeon_mem_takedown(&(dev_priv->gart_heap));
1800254885Sdumbbell		radeon_mem_takedown(&(dev_priv->fb_heap));
1801254885Sdumbbell
1802254885Sdumbbell		/* deallocate kernel resources */
1803254885Sdumbbell		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
1804254885Sdumbbell			r600_do_cleanup_cp(dev);
1805254885Sdumbbell		else
1806254885Sdumbbell			radeon_do_cleanup_cp(dev);
1807254885Sdumbbell		if (dev_priv->me_fw != NULL) {
1808254885Sdumbbell			firmware_put(dev_priv->me_fw, FIRMWARE_UNLOAD);
1809254885Sdumbbell			dev_priv->me_fw = NULL;
1810254885Sdumbbell		}
1811254885Sdumbbell		if (dev_priv->pfp_fw != NULL) {
1812254885Sdumbbell			firmware_put(dev_priv->pfp_fw, FIRMWARE_UNLOAD);
1813254885Sdumbbell			dev_priv->pfp_fw = NULL;
1814254885Sdumbbell		}
1815254885Sdumbbell	}
1816254885Sdumbbell}
1817254885Sdumbbell
1818254885Sdumbbell/* Just reset the CP ring.  Called as part of an X Server engine reset.
1819254885Sdumbbell */
1820254885Sdumbbellint radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
1821254885Sdumbbell{
1822254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1823254885Sdumbbell	DRM_DEBUG("\n");
1824254885Sdumbbell
1825254885Sdumbbell	LOCK_TEST_WITH_RETURN(dev, file_priv);
1826254885Sdumbbell
1827254885Sdumbbell	if (!dev_priv) {
1828254885Sdumbbell		DRM_DEBUG("called before init done\n");
1829254885Sdumbbell		return -EINVAL;
1830254885Sdumbbell	}
1831254885Sdumbbell
1832254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
1833254885Sdumbbell		r600_do_cp_reset(dev_priv);
1834254885Sdumbbell	else
1835254885Sdumbbell		radeon_do_cp_reset(dev_priv);
1836254885Sdumbbell
1837254885Sdumbbell	/* The CP is no longer running after an engine reset */
1838254885Sdumbbell	dev_priv->cp_running = 0;
1839254885Sdumbbell
1840254885Sdumbbell	return 0;
1841254885Sdumbbell}
1842254885Sdumbbell
1843254885Sdumbbellint radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv)
1844254885Sdumbbell{
1845254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1846254885Sdumbbell	DRM_DEBUG("\n");
1847254885Sdumbbell
1848254885Sdumbbell	LOCK_TEST_WITH_RETURN(dev, file_priv);
1849254885Sdumbbell
1850254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
1851254885Sdumbbell		return r600_do_cp_idle(dev_priv);
1852254885Sdumbbell	else
1853254885Sdumbbell		return radeon_do_cp_idle(dev_priv);
1854254885Sdumbbell}
1855254885Sdumbbell
1856254885Sdumbbell/* Added by Charl P. Botha to call radeon_do_resume_cp().
1857254885Sdumbbell */
1858254885Sdumbbellint radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
1859254885Sdumbbell{
1860254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1861254885Sdumbbell	DRM_DEBUG("\n");
1862254885Sdumbbell
1863254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
1864254885Sdumbbell		return r600_do_resume_cp(dev, file_priv);
1865254885Sdumbbell	else
1866254885Sdumbbell		return radeon_do_resume_cp(dev, file_priv);
1867254885Sdumbbell}
1868254885Sdumbbell
1869254885Sdumbbellint radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
1870254885Sdumbbell{
1871254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1872254885Sdumbbell	DRM_DEBUG("\n");
1873254885Sdumbbell
1874254885Sdumbbell	LOCK_TEST_WITH_RETURN(dev, file_priv);
1875254885Sdumbbell
1876254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
1877254885Sdumbbell		return r600_do_engine_reset(dev);
1878254885Sdumbbell	else
1879254885Sdumbbell		return radeon_do_engine_reset(dev);
1880254885Sdumbbell}
1881254885Sdumbbell
1882254885Sdumbbell/* ================================================================
1883254885Sdumbbell * Fullscreen mode
1884254885Sdumbbell */
1885254885Sdumbbell
1886254885Sdumbbell/* KW: Deprecated to say the least:
1887254885Sdumbbell */
1888254885Sdumbbellint radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv)
1889254885Sdumbbell{
1890254885Sdumbbell	return 0;
1891254885Sdumbbell}
1892254885Sdumbbell
1893254885Sdumbbell/* ================================================================
1894254885Sdumbbell * Freelist management
1895254885Sdumbbell */
1896254885Sdumbbell
1897254885Sdumbbell/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
1898254885Sdumbbell *   bufs until freelist code is used.  Note this hides a problem with
1899254885Sdumbbell *   the scratch register * (used to keep track of last buffer
1900254885Sdumbbell *   completed) being written to before * the last buffer has actually
1901254885Sdumbbell *   completed rendering.
1902254885Sdumbbell *
1903254885Sdumbbell * KW:  It's also a good way to find free buffers quickly.
1904254885Sdumbbell *
1905254885Sdumbbell * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
1906254885Sdumbbell * sleep.  However, bugs in older versions of radeon_accel.c mean that
1907254885Sdumbbell * we essentially have to do this, else old clients will break.
1908254885Sdumbbell *
1909254885Sdumbbell * However, it does leave open a potential deadlock where all the
1910254885Sdumbbell * buffers are held by other clients, which can't release them because
1911254885Sdumbbell * they can't get the lock.
1912254885Sdumbbell */
1913254885Sdumbbell
1914254885Sdumbbellstruct drm_buf *radeon_freelist_get(struct drm_device * dev)
1915254885Sdumbbell{
1916254885Sdumbbell	struct drm_device_dma *dma = dev->dma;
1917254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1918254885Sdumbbell	drm_radeon_buf_priv_t *buf_priv;
1919254885Sdumbbell	struct drm_buf *buf;
1920254885Sdumbbell	int i, t;
1921254885Sdumbbell	int start;
1922254885Sdumbbell
1923254885Sdumbbell	if (++dev_priv->last_buf >= dma->buf_count)
1924254885Sdumbbell		dev_priv->last_buf = 0;
1925254885Sdumbbell
1926254885Sdumbbell	start = dev_priv->last_buf;
1927254885Sdumbbell
1928254885Sdumbbell	for (t = 0; t < dev_priv->usec_timeout; t++) {
1929254885Sdumbbell		u32 done_age = GET_SCRATCH(dev_priv, 1);
1930254885Sdumbbell		DRM_DEBUG("done_age = %d\n", done_age);
1931254885Sdumbbell		for (i = 0; i < dma->buf_count; i++) {
1932254885Sdumbbell			buf = dma->buflist[start];
1933254885Sdumbbell			buf_priv = buf->dev_private;
1934254885Sdumbbell			if (buf->file_priv == NULL || (buf->pending &&
1935254885Sdumbbell						       buf_priv->age <=
1936254885Sdumbbell						       done_age)) {
1937254885Sdumbbell				dev_priv->stats.requested_bufs++;
1938254885Sdumbbell				buf->pending = 0;
1939254885Sdumbbell				return buf;
1940254885Sdumbbell			}
1941254885Sdumbbell			if (++start >= dma->buf_count)
1942254885Sdumbbell				start = 0;
1943254885Sdumbbell		}
1944254885Sdumbbell
1945254885Sdumbbell		if (t) {
1946254885Sdumbbell			DRM_UDELAY(1);
1947254885Sdumbbell			dev_priv->stats.freelist_loops++;
1948254885Sdumbbell		}
1949254885Sdumbbell	}
1950254885Sdumbbell
1951254885Sdumbbell	return NULL;
1952254885Sdumbbell}
1953254885Sdumbbell
1954254885Sdumbbellvoid radeon_freelist_reset(struct drm_device * dev)
1955254885Sdumbbell{
1956254885Sdumbbell	struct drm_device_dma *dma = dev->dma;
1957254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
1958254885Sdumbbell	int i;
1959254885Sdumbbell
1960254885Sdumbbell	dev_priv->last_buf = 0;
1961254885Sdumbbell	for (i = 0; i < dma->buf_count; i++) {
1962254885Sdumbbell		struct drm_buf *buf = dma->buflist[i];
1963254885Sdumbbell		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
1964254885Sdumbbell		buf_priv->age = 0;
1965254885Sdumbbell	}
1966254885Sdumbbell}
1967254885Sdumbbell
1968254885Sdumbbell/* ================================================================
1969254885Sdumbbell * CP command submission
1970254885Sdumbbell */
1971254885Sdumbbell
1972254885Sdumbbellint radeon_wait_ring(drm_radeon_private_t * dev_priv, int n)
1973254885Sdumbbell{
1974254885Sdumbbell	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
1975254885Sdumbbell	int i;
1976254885Sdumbbell	u32 last_head = GET_RING_HEAD(dev_priv);
1977254885Sdumbbell
1978254885Sdumbbell	for (i = 0; i < dev_priv->usec_timeout; i++) {
1979254885Sdumbbell		u32 head = GET_RING_HEAD(dev_priv);
1980254885Sdumbbell
1981254885Sdumbbell		ring->space = (head - ring->tail) * sizeof(u32);
1982254885Sdumbbell		if (ring->space <= 0)
1983254885Sdumbbell			ring->space += ring->size;
1984254885Sdumbbell		if (ring->space > n)
1985254885Sdumbbell			return 0;
1986254885Sdumbbell
1987254885Sdumbbell		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
1988254885Sdumbbell
1989254885Sdumbbell		if (head != last_head)
1990254885Sdumbbell			i = 0;
1991254885Sdumbbell		last_head = head;
1992254885Sdumbbell
1993254885Sdumbbell		DRM_UDELAY(1);
1994254885Sdumbbell	}
1995254885Sdumbbell
1996254885Sdumbbell	/* FIXME: This return value is ignored in the BEGIN_RING macro! */
1997254885Sdumbbell#if RADEON_FIFO_DEBUG
1998254885Sdumbbell	radeon_status(dev_priv);
1999254885Sdumbbell	DRM_ERROR("failed!\n");
2000254885Sdumbbell#endif
2001254885Sdumbbell	return -EBUSY;
2002254885Sdumbbell}
2003254885Sdumbbell
2004254885Sdumbbellstatic int radeon_cp_get_buffers(struct drm_device *dev,
2005254885Sdumbbell				 struct drm_file *file_priv,
2006254885Sdumbbell				 struct drm_dma * d)
2007254885Sdumbbell{
2008254885Sdumbbell	int i;
2009254885Sdumbbell	struct drm_buf *buf;
2010254885Sdumbbell
2011254885Sdumbbell	for (i = d->granted_count; i < d->request_count; i++) {
2012254885Sdumbbell		buf = radeon_freelist_get(dev);
2013254885Sdumbbell		if (!buf)
2014254885Sdumbbell			return -EBUSY;	/* NOTE: broken client */
2015254885Sdumbbell
2016254885Sdumbbell		buf->file_priv = file_priv;
2017254885Sdumbbell
2018254885Sdumbbell		if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
2019254885Sdumbbell				     sizeof(buf->idx)))
2020254885Sdumbbell			return -EFAULT;
2021254885Sdumbbell		if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
2022254885Sdumbbell				     sizeof(buf->total)))
2023254885Sdumbbell			return -EFAULT;
2024254885Sdumbbell
2025254885Sdumbbell		d->granted_count++;
2026254885Sdumbbell	}
2027254885Sdumbbell	return 0;
2028254885Sdumbbell}
2029254885Sdumbbell
2030254885Sdumbbellint radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
2031254885Sdumbbell{
2032254885Sdumbbell	struct drm_device_dma *dma = dev->dma;
2033254885Sdumbbell	int ret = 0;
2034254885Sdumbbell	struct drm_dma *d = data;
2035254885Sdumbbell
2036254885Sdumbbell	LOCK_TEST_WITH_RETURN(dev, file_priv);
2037254885Sdumbbell
2038254885Sdumbbell	/* Please don't send us buffers.
2039254885Sdumbbell	 */
2040254885Sdumbbell	if (d->send_count != 0) {
2041254885Sdumbbell		DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
2042254885Sdumbbell			  DRM_CURRENTPID, d->send_count);
2043254885Sdumbbell		return -EINVAL;
2044254885Sdumbbell	}
2045254885Sdumbbell
2046254885Sdumbbell	/* We'll send you buffers.
2047254885Sdumbbell	 */
2048254885Sdumbbell	if (d->request_count < 0 || d->request_count > dma->buf_count) {
2049254885Sdumbbell		DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
2050254885Sdumbbell			  DRM_CURRENTPID, d->request_count, dma->buf_count);
2051254885Sdumbbell		return -EINVAL;
2052254885Sdumbbell	}
2053254885Sdumbbell
2054254885Sdumbbell	d->granted_count = 0;
2055254885Sdumbbell
2056254885Sdumbbell	if (d->request_count) {
2057254885Sdumbbell		ret = radeon_cp_get_buffers(dev, file_priv, d);
2058254885Sdumbbell	}
2059254885Sdumbbell
2060254885Sdumbbell	return ret;
2061254885Sdumbbell}
2062254885Sdumbbell
2063254885Sdumbbellint radeon_driver_load(struct drm_device *dev, unsigned long flags)
2064254885Sdumbbell{
2065254885Sdumbbell	drm_radeon_private_t *dev_priv;
2066254885Sdumbbell	int ret = 0;
2067254885Sdumbbell
2068254885Sdumbbell	dev_priv = malloc(sizeof(drm_radeon_private_t),
2069254885Sdumbbell	    DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
2070254885Sdumbbell	if (dev_priv == NULL)
2071254885Sdumbbell		return -ENOMEM;
2072254885Sdumbbell
2073254885Sdumbbell	dev->dev_private = (void *)dev_priv;
2074254885Sdumbbell	dev_priv->flags = flags;
2075254885Sdumbbell
2076254885Sdumbbell	switch (flags & RADEON_FAMILY_MASK) {
2077254885Sdumbbell	case CHIP_R100:
2078254885Sdumbbell	case CHIP_RV200:
2079254885Sdumbbell	case CHIP_R200:
2080254885Sdumbbell	case CHIP_R300:
2081254885Sdumbbell	case CHIP_R350:
2082254885Sdumbbell	case CHIP_R420:
2083254885Sdumbbell	case CHIP_R423:
2084254885Sdumbbell	case CHIP_RV410:
2085254885Sdumbbell	case CHIP_RV515:
2086254885Sdumbbell	case CHIP_R520:
2087254885Sdumbbell	case CHIP_RV570:
2088254885Sdumbbell	case CHIP_R580:
2089254885Sdumbbell		dev_priv->flags |= RADEON_HAS_HIERZ;
2090254885Sdumbbell		break;
2091254885Sdumbbell	default:
2092254885Sdumbbell		/* all other chips have no hierarchical z buffer */
2093254885Sdumbbell		break;
2094254885Sdumbbell	}
2095254885Sdumbbell
2096254885Sdumbbell	pci_enable_busmaster(dev->device);
2097254885Sdumbbell
2098254885Sdumbbell	if (drm_device_is_agp(dev))
2099254885Sdumbbell		dev_priv->flags |= RADEON_IS_AGP;
2100254885Sdumbbell	else if (drm_device_is_pcie(dev))
2101254885Sdumbbell		dev_priv->flags |= RADEON_IS_PCIE;
2102254885Sdumbbell	else
2103254885Sdumbbell		dev_priv->flags |= RADEON_IS_PCI;
2104254885Sdumbbell
2105254885Sdumbbell	ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
2106254885Sdumbbell			 drm_get_resource_len(dev, 2), _DRM_REGISTERS,
2107254885Sdumbbell			 _DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio);
2108254885Sdumbbell	if (ret != 0)
2109254885Sdumbbell		return ret;
2110254885Sdumbbell
2111254885Sdumbbell	ret = drm_vblank_init(dev, 2);
2112254885Sdumbbell	if (ret) {
2113254885Sdumbbell		radeon_driver_unload(dev);
2114254885Sdumbbell		return ret;
2115254885Sdumbbell	}
2116254885Sdumbbell
2117254885Sdumbbell	DRM_DEBUG("%s card detected\n",
2118254885Sdumbbell		  ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
2119254885Sdumbbell	return ret;
2120254885Sdumbbell}
2121254885Sdumbbell
2122254885Sdumbbellint radeon_master_create(struct drm_device *dev, struct drm_master *master)
2123254885Sdumbbell{
2124254885Sdumbbell	struct drm_radeon_master_private *master_priv;
2125254885Sdumbbell	unsigned long sareapage;
2126254885Sdumbbell	int ret;
2127254885Sdumbbell
2128254885Sdumbbell	master_priv = malloc(sizeof(*master_priv),
2129254885Sdumbbell	    DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
2130254885Sdumbbell	if (!master_priv)
2131254885Sdumbbell		return -ENOMEM;
2132254885Sdumbbell
2133254885Sdumbbell	/* prebuild the SAREA */
2134254885Sdumbbell	sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
2135254885Sdumbbell	ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK,
2136254885Sdumbbell			 &master_priv->sarea);
2137254885Sdumbbell	if (ret) {
2138254885Sdumbbell		DRM_ERROR("SAREA setup failed\n");
2139254885Sdumbbell		free(master_priv, DRM_MEM_DRIVER);
2140254885Sdumbbell		return ret;
2141254885Sdumbbell	}
2142254885Sdumbbell	master_priv->sarea_priv = (drm_radeon_sarea_t *)((char *)master_priv->sarea->handle) +
2143254885Sdumbbell	    sizeof(struct drm_sarea);
2144254885Sdumbbell	master_priv->sarea_priv->pfCurrentPage = 0;
2145254885Sdumbbell
2146254885Sdumbbell	master->driver_priv = master_priv;
2147254885Sdumbbell	return 0;
2148254885Sdumbbell}
2149254885Sdumbbell
2150254885Sdumbbellvoid radeon_master_destroy(struct drm_device *dev, struct drm_master *master)
2151254885Sdumbbell{
2152254885Sdumbbell	struct drm_radeon_master_private *master_priv = master->driver_priv;
2153254885Sdumbbell
2154254885Sdumbbell	if (!master_priv)
2155254885Sdumbbell		return;
2156254885Sdumbbell
2157254885Sdumbbell	if (master_priv->sarea_priv &&
2158254885Sdumbbell	    master_priv->sarea_priv->pfCurrentPage != 0)
2159254885Sdumbbell		radeon_cp_dispatch_flip(dev, master);
2160254885Sdumbbell
2161254885Sdumbbell	master_priv->sarea_priv = NULL;
2162254885Sdumbbell	if (master_priv->sarea)
2163254885Sdumbbell#ifdef __linux__
2164254885Sdumbbell		drm_rmmap_locked(dev, master_priv->sarea);
2165254885Sdumbbell#else
2166254885Sdumbbell		drm_rmmap(dev, master_priv->sarea);
2167254885Sdumbbell#endif
2168254885Sdumbbell
2169254885Sdumbbell	free(master_priv, DRM_MEM_DRIVER);
2170254885Sdumbbell
2171254885Sdumbbell	master->driver_priv = NULL;
2172254885Sdumbbell}
2173254885Sdumbbell
2174254885Sdumbbell/* Create mappings for registers and framebuffer so userland doesn't necessarily
2175254885Sdumbbell * have to find them.
2176254885Sdumbbell */
2177254885Sdumbbellint radeon_driver_firstopen(struct drm_device *dev)
2178254885Sdumbbell{
2179254885Sdumbbell	int ret;
2180254885Sdumbbell	drm_local_map_t *map;
2181254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
2182254885Sdumbbell
2183254885Sdumbbell	dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
2184254885Sdumbbell
2185254885Sdumbbell	dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0);
2186254885Sdumbbell	ret = drm_addmap(dev, dev_priv->fb_aper_offset,
2187254885Sdumbbell			 drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
2188254885Sdumbbell			 _DRM_WRITE_COMBINING, &map);
2189254885Sdumbbell	if (ret != 0)
2190254885Sdumbbell		return ret;
2191254885Sdumbbell
2192254885Sdumbbell	return 0;
2193254885Sdumbbell}
2194254885Sdumbbell
2195254885Sdumbbellint radeon_driver_unload(struct drm_device *dev)
2196254885Sdumbbell{
2197254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
2198254885Sdumbbell
2199254885Sdumbbell	DRM_DEBUG("\n");
2200254885Sdumbbell
2201254885Sdumbbell	drm_rmmap(dev, dev_priv->mmio);
2202254885Sdumbbell
2203254885Sdumbbell	free(dev_priv, DRM_MEM_DRIVER);
2204254885Sdumbbell
2205254885Sdumbbell	dev->dev_private = NULL;
2206254885Sdumbbell	return 0;
2207254885Sdumbbell}
2208254885Sdumbbell
2209254885Sdumbbellvoid radeon_commit_ring(drm_radeon_private_t *dev_priv)
2210254885Sdumbbell{
2211254885Sdumbbell	int i;
2212254885Sdumbbell	u32 *ring;
2213254885Sdumbbell	int tail_aligned;
2214254885Sdumbbell
2215254885Sdumbbell	/* check if the ring is padded out to 16-dword alignment */
2216254885Sdumbbell
2217254885Sdumbbell	tail_aligned = dev_priv->ring.tail & (RADEON_RING_ALIGN-1);
2218254885Sdumbbell	if (tail_aligned) {
2219254885Sdumbbell		int num_p2 = RADEON_RING_ALIGN - tail_aligned;
2220254885Sdumbbell
2221254885Sdumbbell		ring = dev_priv->ring.start;
2222254885Sdumbbell		/* pad with some CP_PACKET2 */
2223254885Sdumbbell		for (i = 0; i < num_p2; i++)
2224254885Sdumbbell			ring[dev_priv->ring.tail + i] = CP_PACKET2();
2225254885Sdumbbell
2226254885Sdumbbell		dev_priv->ring.tail += i;
2227254885Sdumbbell
2228254885Sdumbbell		dev_priv->ring.space -= num_p2 * sizeof(u32);
2229254885Sdumbbell	}
2230254885Sdumbbell
2231254885Sdumbbell	dev_priv->ring.tail &= dev_priv->ring.tail_mask;
2232254885Sdumbbell
2233254885Sdumbbell	DRM_MEMORYBARRIER();
2234254885Sdumbbell	GET_RING_HEAD( dev_priv );
2235254885Sdumbbell
2236254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
2237254885Sdumbbell		RADEON_WRITE(R600_CP_RB_WPTR, dev_priv->ring.tail);
2238254885Sdumbbell		/* read from PCI bus to ensure correct posting */
2239254885Sdumbbell		RADEON_READ(R600_CP_RB_RPTR);
2240254885Sdumbbell	} else {
2241254885Sdumbbell		RADEON_WRITE(RADEON_CP_RB_WPTR, dev_priv->ring.tail);
2242254885Sdumbbell		/* read from PCI bus to ensure correct posting */
2243254885Sdumbbell		RADEON_READ(RADEON_CP_RB_RPTR);
2244254885Sdumbbell	}
2245254885Sdumbbell}
2246