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