radeon_cp.c revision 112015
195584Sanholt/* radeon_cp.c -- CP support for Radeon -*- linux-c -*-
295584Sanholt *
395584Sanholt * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
495584Sanholt * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
595584Sanholt * All Rights Reserved.
695584Sanholt *
795584Sanholt * Permission is hereby granted, free of charge, to any person obtaining a
895584Sanholt * copy of this software and associated documentation files (the "Software"),
995584Sanholt * to deal in the Software without restriction, including without limitation
1095584Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1195584Sanholt * and/or sell copies of the Software, and to permit persons to whom the
1295584Sanholt * Software is furnished to do so, subject to the following conditions:
1395584Sanholt *
1495584Sanholt * The above copyright notice and this permission notice (including the next
1595584Sanholt * paragraph) shall be included in all copies or substantial portions of the
1695584Sanholt * Software.
1795584Sanholt *
1895584Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1995584Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2095584Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2195584Sanholt * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2295584Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2395584Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2495584Sanholt * DEALINGS IN THE SOFTWARE.
2595584Sanholt *
2695584Sanholt * Authors:
2795584Sanholt *    Kevin E. Martin <martin@valinux.com>
2895584Sanholt *    Gareth Hughes <gareth@valinux.com>
2995584Sanholt *
3095584Sanholt * $FreeBSD: head/sys/dev/drm/radeon_cp.c 112015 2003-03-09 02:08:30Z anholt $
3195584Sanholt */
3295584Sanholt
3395584Sanholt#include "dev/drm/radeon.h"
3495584Sanholt#include "dev/drm/drmP.h"
35112015Sanholt#include "dev/drm/drm.h"
3695746Sanholt#include "dev/drm/radeon_drm.h"
3795584Sanholt#include "dev/drm/radeon_drv.h"
3895584Sanholt
3995584Sanholt#define RADEON_FIFO_DEBUG	0
4095584Sanholt
41112015Sanholt#if defined(__alpha__) || defined(__powerpc__)
4295584Sanholt# define PCIGART_ENABLED
4395584Sanholt#else
4495584Sanholt# undef PCIGART_ENABLED
4595584Sanholt#endif
4695584Sanholt
4795584Sanholt
4895584Sanholt/* CP microcode (from ATI) */
49112015Sanholtstatic u32 R200_cp_microcode[][2] = {
50112015Sanholt	{ 0x21007000, 0000000000 },
51112015Sanholt	{ 0x20007000, 0000000000 },
52112015Sanholt	{ 0x000000ab, 0x00000004 },
53112015Sanholt	{ 0x000000af, 0x00000004 },
54112015Sanholt	{ 0x66544a49, 0000000000 },
55112015Sanholt	{ 0x49494174, 0000000000 },
56112015Sanholt	{ 0x54517d83, 0000000000 },
57112015Sanholt	{ 0x498d8b64, 0000000000 },
58112015Sanholt	{ 0x49494949, 0000000000 },
59112015Sanholt	{ 0x49da493c, 0000000000 },
60112015Sanholt	{ 0x49989898, 0000000000 },
61112015Sanholt	{ 0xd34949d5, 0000000000 },
62112015Sanholt	{ 0x9dc90e11, 0000000000 },
63112015Sanholt	{ 0xce9b9b9b, 0000000000 },
64112015Sanholt	{ 0x000f0000, 0x00000016 },
65112015Sanholt	{ 0x352e232c, 0000000000 },
66112015Sanholt	{ 0x00000013, 0x00000004 },
67112015Sanholt	{ 0x000f0000, 0x00000016 },
68112015Sanholt	{ 0x352e272c, 0000000000 },
69112015Sanholt	{ 0x000f0001, 0x00000016 },
70112015Sanholt	{ 0x3239362f, 0000000000 },
71112015Sanholt	{ 0x000077ef, 0x00000002 },
72112015Sanholt	{ 0x00061000, 0x00000002 },
73112015Sanholt	{ 0x00000020, 0x0000001a },
74112015Sanholt	{ 0x00004000, 0x0000001e },
75112015Sanholt	{ 0x00061000, 0x00000002 },
76112015Sanholt	{ 0x00000020, 0x0000001a },
77112015Sanholt	{ 0x00004000, 0x0000001e },
78112015Sanholt	{ 0x00061000, 0x00000002 },
79112015Sanholt	{ 0x00000020, 0x0000001a },
80112015Sanholt	{ 0x00004000, 0x0000001e },
81112015Sanholt	{ 0x00000016, 0x00000004 },
82112015Sanholt	{ 0x0003802a, 0x00000002 },
83112015Sanholt	{ 0x040067e0, 0x00000002 },
84112015Sanholt	{ 0x00000016, 0x00000004 },
85112015Sanholt	{ 0x000077e0, 0x00000002 },
86112015Sanholt	{ 0x00065000, 0x00000002 },
87112015Sanholt	{ 0x000037e1, 0x00000002 },
88112015Sanholt	{ 0x040067e1, 0x00000006 },
89112015Sanholt	{ 0x000077e0, 0x00000002 },
90112015Sanholt	{ 0x000077e1, 0x00000002 },
91112015Sanholt	{ 0x000077e1, 0x00000006 },
92112015Sanholt	{ 0xffffffff, 0000000000 },
93112015Sanholt	{ 0x10000000, 0000000000 },
94112015Sanholt	{ 0x0003802a, 0x00000002 },
95112015Sanholt	{ 0x040067e0, 0x00000006 },
96112015Sanholt	{ 0x00007675, 0x00000002 },
97112015Sanholt	{ 0x00007676, 0x00000002 },
98112015Sanholt	{ 0x00007677, 0x00000002 },
99112015Sanholt	{ 0x00007678, 0x00000006 },
100112015Sanholt	{ 0x0003802b, 0x00000002 },
101112015Sanholt	{ 0x04002676, 0x00000002 },
102112015Sanholt	{ 0x00007677, 0x00000002 },
103112015Sanholt	{ 0x00007678, 0x00000006 },
104112015Sanholt	{ 0x0000002e, 0x00000018 },
105112015Sanholt	{ 0x0000002e, 0x00000018 },
106112015Sanholt	{ 0000000000, 0x00000006 },
107112015Sanholt	{ 0x0000002f, 0x00000018 },
108112015Sanholt	{ 0x0000002f, 0x00000018 },
109112015Sanholt	{ 0000000000, 0x00000006 },
110112015Sanholt	{ 0x01605000, 0x00000002 },
111112015Sanholt	{ 0x00065000, 0x00000002 },
112112015Sanholt	{ 0x00098000, 0x00000002 },
113112015Sanholt	{ 0x00061000, 0x00000002 },
114112015Sanholt	{ 0x64c0603d, 0x00000004 },
115112015Sanholt	{ 0x00080000, 0x00000016 },
116112015Sanholt	{ 0000000000, 0000000000 },
117112015Sanholt	{ 0x0400251d, 0x00000002 },
118112015Sanholt	{ 0x00007580, 0x00000002 },
119112015Sanholt	{ 0x00067581, 0x00000002 },
120112015Sanholt	{ 0x04002580, 0x00000002 },
121112015Sanholt	{ 0x00067581, 0x00000002 },
122112015Sanholt	{ 0x00000046, 0x00000004 },
123112015Sanholt	{ 0x00005000, 0000000000 },
124112015Sanholt	{ 0x00061000, 0x00000002 },
125112015Sanholt	{ 0x0000750e, 0x00000002 },
126112015Sanholt	{ 0x00019000, 0x00000002 },
127112015Sanholt	{ 0x00011055, 0x00000014 },
128112015Sanholt	{ 0x00000055, 0x00000012 },
129112015Sanholt	{ 0x0400250f, 0x00000002 },
130112015Sanholt	{ 0x0000504a, 0x00000004 },
131112015Sanholt	{ 0x00007565, 0x00000002 },
132112015Sanholt	{ 0x00007566, 0x00000002 },
133112015Sanholt	{ 0x00000051, 0x00000004 },
134112015Sanholt	{ 0x01e655b4, 0x00000002 },
135112015Sanholt	{ 0x4401b0dc, 0x00000002 },
136112015Sanholt	{ 0x01c110dc, 0x00000002 },
137112015Sanholt	{ 0x2666705d, 0x00000018 },
138112015Sanholt	{ 0x040c2565, 0x00000002 },
139112015Sanholt	{ 0x0000005d, 0x00000018 },
140112015Sanholt	{ 0x04002564, 0x00000002 },
141112015Sanholt	{ 0x00007566, 0x00000002 },
142112015Sanholt	{ 0x00000054, 0x00000004 },
143112015Sanholt	{ 0x00401060, 0x00000008 },
144112015Sanholt	{ 0x00101000, 0x00000002 },
145112015Sanholt	{ 0x000d80ff, 0x00000002 },
146112015Sanholt	{ 0x00800063, 0x00000008 },
147112015Sanholt	{ 0x000f9000, 0x00000002 },
148112015Sanholt	{ 0x000e00ff, 0x00000002 },
149112015Sanholt	{ 0000000000, 0x00000006 },
150112015Sanholt	{ 0x00000080, 0x00000018 },
151112015Sanholt	{ 0x00000054, 0x00000004 },
152112015Sanholt	{ 0x00007576, 0x00000002 },
153112015Sanholt	{ 0x00065000, 0x00000002 },
154112015Sanholt	{ 0x00009000, 0x00000002 },
155112015Sanholt	{ 0x00041000, 0x00000002 },
156112015Sanholt	{ 0x0c00350e, 0x00000002 },
157112015Sanholt	{ 0x00049000, 0x00000002 },
158112015Sanholt	{ 0x00051000, 0x00000002 },
159112015Sanholt	{ 0x01e785f8, 0x00000002 },
160112015Sanholt	{ 0x00200000, 0x00000002 },
161112015Sanholt	{ 0x00600073, 0x0000000c },
162112015Sanholt	{ 0x00007563, 0x00000002 },
163112015Sanholt	{ 0x006075f0, 0x00000021 },
164112015Sanholt	{ 0x20007068, 0x00000004 },
165112015Sanholt	{ 0x00005068, 0x00000004 },
166112015Sanholt	{ 0x00007576, 0x00000002 },
167112015Sanholt	{ 0x00007577, 0x00000002 },
168112015Sanholt	{ 0x0000750e, 0x00000002 },
169112015Sanholt	{ 0x0000750f, 0x00000002 },
170112015Sanholt	{ 0x00a05000, 0x00000002 },
171112015Sanholt	{ 0x00600076, 0x0000000c },
172112015Sanholt	{ 0x006075f0, 0x00000021 },
173112015Sanholt	{ 0x000075f8, 0x00000002 },
174112015Sanholt	{ 0x00000076, 0x00000004 },
175112015Sanholt	{ 0x000a750e, 0x00000002 },
176112015Sanholt	{ 0x0020750f, 0x00000002 },
177112015Sanholt	{ 0x00600079, 0x00000004 },
178112015Sanholt	{ 0x00007570, 0x00000002 },
179112015Sanholt	{ 0x00007571, 0x00000002 },
180112015Sanholt	{ 0x00007572, 0x00000006 },
181112015Sanholt	{ 0x00005000, 0x00000002 },
182112015Sanholt	{ 0x00a05000, 0x00000002 },
183112015Sanholt	{ 0x00007568, 0x00000002 },
184112015Sanholt	{ 0x00061000, 0x00000002 },
185112015Sanholt	{ 0x00000084, 0x0000000c },
186112015Sanholt	{ 0x00058000, 0x00000002 },
187112015Sanholt	{ 0x0c607562, 0x00000002 },
188112015Sanholt	{ 0x00000086, 0x00000004 },
189112015Sanholt	{ 0x00600085, 0x00000004 },
190112015Sanholt	{ 0x400070dd, 0000000000 },
191112015Sanholt	{ 0x000380dd, 0x00000002 },
192112015Sanholt	{ 0x00000093, 0x0000001c },
193112015Sanholt	{ 0x00065095, 0x00000018 },
194112015Sanholt	{ 0x040025bb, 0x00000002 },
195112015Sanholt	{ 0x00061096, 0x00000018 },
196112015Sanholt	{ 0x040075bc, 0000000000 },
197112015Sanholt	{ 0x000075bb, 0x00000002 },
198112015Sanholt	{ 0x000075bc, 0000000000 },
199112015Sanholt	{ 0x00090000, 0x00000006 },
200112015Sanholt	{ 0x00090000, 0x00000002 },
201112015Sanholt	{ 0x000d8002, 0x00000006 },
202112015Sanholt	{ 0x00005000, 0x00000002 },
203112015Sanholt	{ 0x00007821, 0x00000002 },
204112015Sanholt	{ 0x00007800, 0000000000 },
205112015Sanholt	{ 0x00007821, 0x00000002 },
206112015Sanholt	{ 0x00007800, 0000000000 },
207112015Sanholt	{ 0x01665000, 0x00000002 },
208112015Sanholt	{ 0x000a0000, 0x00000002 },
209112015Sanholt	{ 0x000671cc, 0x00000002 },
210112015Sanholt	{ 0x0286f1cd, 0x00000002 },
211112015Sanholt	{ 0x000000a3, 0x00000010 },
212112015Sanholt	{ 0x21007000, 0000000000 },
213112015Sanholt	{ 0x000000aa, 0x0000001c },
214112015Sanholt	{ 0x00065000, 0x00000002 },
215112015Sanholt	{ 0x000a0000, 0x00000002 },
216112015Sanholt	{ 0x00061000, 0x00000002 },
217112015Sanholt	{ 0x000b0000, 0x00000002 },
218112015Sanholt	{ 0x38067000, 0x00000002 },
219112015Sanholt	{ 0x000a00a6, 0x00000004 },
220112015Sanholt	{ 0x20007000, 0000000000 },
221112015Sanholt	{ 0x01200000, 0x00000002 },
222112015Sanholt	{ 0x20077000, 0x00000002 },
223112015Sanholt	{ 0x01200000, 0x00000002 },
224112015Sanholt	{ 0x20007000, 0000000000 },
225112015Sanholt	{ 0x00061000, 0x00000002 },
226112015Sanholt	{ 0x0120751b, 0x00000002 },
227112015Sanholt	{ 0x8040750a, 0x00000002 },
228112015Sanholt	{ 0x8040750b, 0x00000002 },
229112015Sanholt	{ 0x00110000, 0x00000002 },
230112015Sanholt	{ 0x000380dd, 0x00000002 },
231112015Sanholt	{ 0x000000bd, 0x0000001c },
232112015Sanholt	{ 0x00061096, 0x00000018 },
233112015Sanholt	{ 0x844075bd, 0x00000002 },
234112015Sanholt	{ 0x00061095, 0x00000018 },
235112015Sanholt	{ 0x840075bb, 0x00000002 },
236112015Sanholt	{ 0x00061096, 0x00000018 },
237112015Sanholt	{ 0x844075bc, 0x00000002 },
238112015Sanholt	{ 0x000000c0, 0x00000004 },
239112015Sanholt	{ 0x804075bd, 0x00000002 },
240112015Sanholt	{ 0x800075bb, 0x00000002 },
241112015Sanholt	{ 0x804075bc, 0x00000002 },
242112015Sanholt	{ 0x00108000, 0x00000002 },
243112015Sanholt	{ 0x01400000, 0x00000002 },
244112015Sanholt	{ 0x006000c4, 0x0000000c },
245112015Sanholt	{ 0x20c07000, 0x00000020 },
246112015Sanholt	{ 0x000000c6, 0x00000012 },
247112015Sanholt	{ 0x00800000, 0x00000006 },
248112015Sanholt	{ 0x0080751d, 0x00000006 },
249112015Sanholt	{ 0x000025bb, 0x00000002 },
250112015Sanholt	{ 0x000040c0, 0x00000004 },
251112015Sanholt	{ 0x0000775c, 0x00000002 },
252112015Sanholt	{ 0x00a05000, 0x00000002 },
253112015Sanholt	{ 0x00661000, 0x00000002 },
254112015Sanholt	{ 0x0460275d, 0x00000020 },
255112015Sanholt	{ 0x00004000, 0000000000 },
256112015Sanholt	{ 0x00007999, 0x00000002 },
257112015Sanholt	{ 0x00a05000, 0x00000002 },
258112015Sanholt	{ 0x00661000, 0x00000002 },
259112015Sanholt	{ 0x0460299b, 0x00000020 },
260112015Sanholt	{ 0x00004000, 0000000000 },
261112015Sanholt	{ 0x01e00830, 0x00000002 },
262112015Sanholt	{ 0x21007000, 0000000000 },
263112015Sanholt	{ 0x00005000, 0x00000002 },
264112015Sanholt	{ 0x00038042, 0x00000002 },
265112015Sanholt	{ 0x040025e0, 0x00000002 },
266112015Sanholt	{ 0x000075e1, 0000000000 },
267112015Sanholt	{ 0x00000001, 0000000000 },
268112015Sanholt	{ 0x000380d9, 0x00000002 },
269112015Sanholt	{ 0x04007394, 0000000000 },
270112015Sanholt	{ 0000000000, 0000000000 },
271112015Sanholt	{ 0000000000, 0000000000 },
272112015Sanholt	{ 0000000000, 0000000000 },
273112015Sanholt	{ 0000000000, 0000000000 },
274112015Sanholt	{ 0000000000, 0000000000 },
275112015Sanholt	{ 0000000000, 0000000000 },
276112015Sanholt	{ 0000000000, 0000000000 },
277112015Sanholt	{ 0000000000, 0000000000 },
278112015Sanholt	{ 0000000000, 0000000000 },
279112015Sanholt	{ 0000000000, 0000000000 },
280112015Sanholt	{ 0000000000, 0000000000 },
281112015Sanholt	{ 0000000000, 0000000000 },
282112015Sanholt	{ 0000000000, 0000000000 },
283112015Sanholt	{ 0000000000, 0000000000 },
284112015Sanholt	{ 0000000000, 0000000000 },
285112015Sanholt	{ 0000000000, 0000000000 },
286112015Sanholt	{ 0000000000, 0000000000 },
287112015Sanholt	{ 0000000000, 0000000000 },
288112015Sanholt	{ 0000000000, 0000000000 },
289112015Sanholt	{ 0000000000, 0000000000 },
290112015Sanholt	{ 0000000000, 0000000000 },
291112015Sanholt	{ 0000000000, 0000000000 },
292112015Sanholt	{ 0000000000, 0000000000 },
293112015Sanholt	{ 0000000000, 0000000000 },
294112015Sanholt	{ 0000000000, 0000000000 },
295112015Sanholt	{ 0000000000, 0000000000 },
296112015Sanholt	{ 0000000000, 0000000000 },
297112015Sanholt	{ 0000000000, 0000000000 },
298112015Sanholt	{ 0000000000, 0000000000 },
299112015Sanholt	{ 0000000000, 0000000000 },
300112015Sanholt	{ 0000000000, 0000000000 },
301112015Sanholt	{ 0000000000, 0000000000 },
302112015Sanholt	{ 0000000000, 0000000000 },
303112015Sanholt	{ 0000000000, 0000000000 },
304112015Sanholt	{ 0000000000, 0000000000 },
305112015Sanholt	{ 0000000000, 0000000000 },
306112015Sanholt};
307112015Sanholt
308112015Sanholt
30995584Sanholtstatic u32 radeon_cp_microcode[][2] = {
31095584Sanholt	{ 0x21007000, 0000000000 },
31195584Sanholt	{ 0x20007000, 0000000000 },
31295584Sanholt	{ 0x000000b4, 0x00000004 },
31395584Sanholt	{ 0x000000b8, 0x00000004 },
31495584Sanholt	{ 0x6f5b4d4c, 0000000000 },
31595584Sanholt	{ 0x4c4c427f, 0000000000 },
31695584Sanholt	{ 0x5b568a92, 0000000000 },
31795584Sanholt	{ 0x4ca09c6d, 0000000000 },
31895584Sanholt	{ 0xad4c4c4c, 0000000000 },
31995584Sanholt	{ 0x4ce1af3d, 0000000000 },
32095584Sanholt	{ 0xd8afafaf, 0000000000 },
32195584Sanholt	{ 0xd64c4cdc, 0000000000 },
32295584Sanholt	{ 0x4cd10d10, 0000000000 },
32395584Sanholt	{ 0x000f0000, 0x00000016 },
32495584Sanholt	{ 0x362f242d, 0000000000 },
32595584Sanholt	{ 0x00000012, 0x00000004 },
32695584Sanholt	{ 0x000f0000, 0x00000016 },
32795584Sanholt	{ 0x362f282d, 0000000000 },
32895584Sanholt	{ 0x000380e7, 0x00000002 },
32995584Sanholt	{ 0x04002c97, 0x00000002 },
33095584Sanholt	{ 0x000f0001, 0x00000016 },
33195584Sanholt	{ 0x333a3730, 0000000000 },
33295584Sanholt	{ 0x000077ef, 0x00000002 },
33395584Sanholt	{ 0x00061000, 0x00000002 },
33495584Sanholt	{ 0x00000021, 0x0000001a },
33595584Sanholt	{ 0x00004000, 0x0000001e },
33695584Sanholt	{ 0x00061000, 0x00000002 },
33795584Sanholt	{ 0x00000021, 0x0000001a },
33895584Sanholt	{ 0x00004000, 0x0000001e },
33995584Sanholt	{ 0x00061000, 0x00000002 },
34095584Sanholt	{ 0x00000021, 0x0000001a },
34195584Sanholt	{ 0x00004000, 0x0000001e },
34295584Sanholt	{ 0x00000017, 0x00000004 },
34395584Sanholt	{ 0x0003802b, 0x00000002 },
34495584Sanholt	{ 0x040067e0, 0x00000002 },
34595584Sanholt	{ 0x00000017, 0x00000004 },
34695584Sanholt	{ 0x000077e0, 0x00000002 },
34795584Sanholt	{ 0x00065000, 0x00000002 },
34895584Sanholt	{ 0x000037e1, 0x00000002 },
34995584Sanholt	{ 0x040067e1, 0x00000006 },
35095584Sanholt	{ 0x000077e0, 0x00000002 },
35195584Sanholt	{ 0x000077e1, 0x00000002 },
35295584Sanholt	{ 0x000077e1, 0x00000006 },
35395584Sanholt	{ 0xffffffff, 0000000000 },
35495584Sanholt	{ 0x10000000, 0000000000 },
35595584Sanholt	{ 0x0003802b, 0x00000002 },
35695584Sanholt	{ 0x040067e0, 0x00000006 },
35795584Sanholt	{ 0x00007675, 0x00000002 },
35895584Sanholt	{ 0x00007676, 0x00000002 },
35995584Sanholt	{ 0x00007677, 0x00000002 },
36095584Sanholt	{ 0x00007678, 0x00000006 },
36195584Sanholt	{ 0x0003802c, 0x00000002 },
36295584Sanholt	{ 0x04002676, 0x00000002 },
36395584Sanholt	{ 0x00007677, 0x00000002 },
36495584Sanholt	{ 0x00007678, 0x00000006 },
36595584Sanholt	{ 0x0000002f, 0x00000018 },
36695584Sanholt	{ 0x0000002f, 0x00000018 },
36795584Sanholt	{ 0000000000, 0x00000006 },
36895584Sanholt	{ 0x00000030, 0x00000018 },
36995584Sanholt	{ 0x00000030, 0x00000018 },
37095584Sanholt	{ 0000000000, 0x00000006 },
37195584Sanholt	{ 0x01605000, 0x00000002 },
37295584Sanholt	{ 0x00065000, 0x00000002 },
37395584Sanholt	{ 0x00098000, 0x00000002 },
37495584Sanholt	{ 0x00061000, 0x00000002 },
37595584Sanholt	{ 0x64c0603e, 0x00000004 },
37695584Sanholt	{ 0x000380e6, 0x00000002 },
37795584Sanholt	{ 0x040025c5, 0x00000002 },
37895584Sanholt	{ 0x00080000, 0x00000016 },
37995584Sanholt	{ 0000000000, 0000000000 },
38095584Sanholt	{ 0x0400251d, 0x00000002 },
38195584Sanholt	{ 0x00007580, 0x00000002 },
38295584Sanholt	{ 0x00067581, 0x00000002 },
38395584Sanholt	{ 0x04002580, 0x00000002 },
38495584Sanholt	{ 0x00067581, 0x00000002 },
38595584Sanholt	{ 0x00000049, 0x00000004 },
38695584Sanholt	{ 0x00005000, 0000000000 },
38795584Sanholt	{ 0x000380e6, 0x00000002 },
38895584Sanholt	{ 0x040025c5, 0x00000002 },
38995584Sanholt	{ 0x00061000, 0x00000002 },
39095584Sanholt	{ 0x0000750e, 0x00000002 },
39195584Sanholt	{ 0x00019000, 0x00000002 },
39295584Sanholt	{ 0x00011055, 0x00000014 },
39395584Sanholt	{ 0x00000055, 0x00000012 },
39495584Sanholt	{ 0x0400250f, 0x00000002 },
39595584Sanholt	{ 0x0000504f, 0x00000004 },
39695584Sanholt	{ 0x000380e6, 0x00000002 },
39795584Sanholt	{ 0x040025c5, 0x00000002 },
39895584Sanholt	{ 0x00007565, 0x00000002 },
39995584Sanholt	{ 0x00007566, 0x00000002 },
40095584Sanholt	{ 0x00000058, 0x00000004 },
40195584Sanholt	{ 0x000380e6, 0x00000002 },
40295584Sanholt	{ 0x040025c5, 0x00000002 },
40395584Sanholt	{ 0x01e655b4, 0x00000002 },
40495584Sanholt	{ 0x4401b0e4, 0x00000002 },
40595584Sanholt	{ 0x01c110e4, 0x00000002 },
40695584Sanholt	{ 0x26667066, 0x00000018 },
40795584Sanholt	{ 0x040c2565, 0x00000002 },
40895584Sanholt	{ 0x00000066, 0x00000018 },
40995584Sanholt	{ 0x04002564, 0x00000002 },
41095584Sanholt	{ 0x00007566, 0x00000002 },
41195584Sanholt	{ 0x0000005d, 0x00000004 },
41295584Sanholt	{ 0x00401069, 0x00000008 },
41395584Sanholt	{ 0x00101000, 0x00000002 },
41495584Sanholt	{ 0x000d80ff, 0x00000002 },
41595584Sanholt	{ 0x0080006c, 0x00000008 },
41695584Sanholt	{ 0x000f9000, 0x00000002 },
41795584Sanholt	{ 0x000e00ff, 0x00000002 },
41895584Sanholt	{ 0000000000, 0x00000006 },
41995584Sanholt	{ 0x0000008f, 0x00000018 },
42095584Sanholt	{ 0x0000005b, 0x00000004 },
42195584Sanholt	{ 0x000380e6, 0x00000002 },
42295584Sanholt	{ 0x040025c5, 0x00000002 },
42395584Sanholt	{ 0x00007576, 0x00000002 },
42495584Sanholt	{ 0x00065000, 0x00000002 },
42595584Sanholt	{ 0x00009000, 0x00000002 },
42695584Sanholt	{ 0x00041000, 0x00000002 },
42795584Sanholt	{ 0x0c00350e, 0x00000002 },
42895584Sanholt	{ 0x00049000, 0x00000002 },
42995584Sanholt	{ 0x00051000, 0x00000002 },
43095584Sanholt	{ 0x01e785f8, 0x00000002 },
43195584Sanholt	{ 0x00200000, 0x00000002 },
43295584Sanholt	{ 0x0060007e, 0x0000000c },
43395584Sanholt	{ 0x00007563, 0x00000002 },
43495584Sanholt	{ 0x006075f0, 0x00000021 },
43595584Sanholt	{ 0x20007073, 0x00000004 },
43695584Sanholt	{ 0x00005073, 0x00000004 },
43795584Sanholt	{ 0x000380e6, 0x00000002 },
43895584Sanholt	{ 0x040025c5, 0x00000002 },
43995584Sanholt	{ 0x00007576, 0x00000002 },
44095584Sanholt	{ 0x00007577, 0x00000002 },
44195584Sanholt	{ 0x0000750e, 0x00000002 },
44295584Sanholt	{ 0x0000750f, 0x00000002 },
44395584Sanholt	{ 0x00a05000, 0x00000002 },
44495584Sanholt	{ 0x00600083, 0x0000000c },
44595584Sanholt	{ 0x006075f0, 0x00000021 },
44695584Sanholt	{ 0x000075f8, 0x00000002 },
44795584Sanholt	{ 0x00000083, 0x00000004 },
44895584Sanholt	{ 0x000a750e, 0x00000002 },
44995584Sanholt	{ 0x000380e6, 0x00000002 },
45095584Sanholt	{ 0x040025c5, 0x00000002 },
45195584Sanholt	{ 0x0020750f, 0x00000002 },
45295584Sanholt	{ 0x00600086, 0x00000004 },
45395584Sanholt	{ 0x00007570, 0x00000002 },
45495584Sanholt	{ 0x00007571, 0x00000002 },
45595584Sanholt	{ 0x00007572, 0x00000006 },
45695584Sanholt	{ 0x000380e6, 0x00000002 },
45795584Sanholt	{ 0x040025c5, 0x00000002 },
45895584Sanholt	{ 0x00005000, 0x00000002 },
45995584Sanholt	{ 0x00a05000, 0x00000002 },
46095584Sanholt	{ 0x00007568, 0x00000002 },
46195584Sanholt	{ 0x00061000, 0x00000002 },
46295584Sanholt	{ 0x00000095, 0x0000000c },
46395584Sanholt	{ 0x00058000, 0x00000002 },
46495584Sanholt	{ 0x0c607562, 0x00000002 },
46595584Sanholt	{ 0x00000097, 0x00000004 },
46695584Sanholt	{ 0x000380e6, 0x00000002 },
46795584Sanholt	{ 0x040025c5, 0x00000002 },
46895584Sanholt	{ 0x00600096, 0x00000004 },
46995584Sanholt	{ 0x400070e5, 0000000000 },
47095584Sanholt	{ 0x000380e6, 0x00000002 },
47195584Sanholt	{ 0x040025c5, 0x00000002 },
47295584Sanholt	{ 0x000380e5, 0x00000002 },
47395584Sanholt	{ 0x000000a8, 0x0000001c },
47495584Sanholt	{ 0x000650aa, 0x00000018 },
47595584Sanholt	{ 0x040025bb, 0x00000002 },
47695584Sanholt	{ 0x000610ab, 0x00000018 },
47795584Sanholt	{ 0x040075bc, 0000000000 },
47895584Sanholt	{ 0x000075bb, 0x00000002 },
47995584Sanholt	{ 0x000075bc, 0000000000 },
48095584Sanholt	{ 0x00090000, 0x00000006 },
48195584Sanholt	{ 0x00090000, 0x00000002 },
48295584Sanholt	{ 0x000d8002, 0x00000006 },
48395584Sanholt	{ 0x00007832, 0x00000002 },
48495584Sanholt	{ 0x00005000, 0x00000002 },
48595584Sanholt	{ 0x000380e7, 0x00000002 },
48695584Sanholt	{ 0x04002c97, 0x00000002 },
48795584Sanholt	{ 0x00007820, 0x00000002 },
48895584Sanholt	{ 0x00007821, 0x00000002 },
48995584Sanholt	{ 0x00007800, 0000000000 },
49095584Sanholt	{ 0x01200000, 0x00000002 },
49195584Sanholt	{ 0x20077000, 0x00000002 },
49295584Sanholt	{ 0x01200000, 0x00000002 },
49395584Sanholt	{ 0x20007000, 0x00000002 },
49495584Sanholt	{ 0x00061000, 0x00000002 },
49595584Sanholt	{ 0x0120751b, 0x00000002 },
49695584Sanholt	{ 0x8040750a, 0x00000002 },
49795584Sanholt	{ 0x8040750b, 0x00000002 },
49895584Sanholt	{ 0x00110000, 0x00000002 },
49995584Sanholt	{ 0x000380e5, 0x00000002 },
50095584Sanholt	{ 0x000000c6, 0x0000001c },
50195584Sanholt	{ 0x000610ab, 0x00000018 },
50295584Sanholt	{ 0x844075bd, 0x00000002 },
50395584Sanholt	{ 0x000610aa, 0x00000018 },
50495584Sanholt	{ 0x840075bb, 0x00000002 },
50595584Sanholt	{ 0x000610ab, 0x00000018 },
50695584Sanholt	{ 0x844075bc, 0x00000002 },
50795584Sanholt	{ 0x000000c9, 0x00000004 },
50895584Sanholt	{ 0x804075bd, 0x00000002 },
50995584Sanholt	{ 0x800075bb, 0x00000002 },
51095584Sanholt	{ 0x804075bc, 0x00000002 },
51195584Sanholt	{ 0x00108000, 0x00000002 },
51295584Sanholt	{ 0x01400000, 0x00000002 },
51395584Sanholt	{ 0x006000cd, 0x0000000c },
51495584Sanholt	{ 0x20c07000, 0x00000020 },
51595584Sanholt	{ 0x000000cf, 0x00000012 },
51695584Sanholt	{ 0x00800000, 0x00000006 },
51795584Sanholt	{ 0x0080751d, 0x00000006 },
51895584Sanholt	{ 0000000000, 0000000000 },
51995584Sanholt	{ 0x0000775c, 0x00000002 },
52095584Sanholt	{ 0x00a05000, 0x00000002 },
52195584Sanholt	{ 0x00661000, 0x00000002 },
52295584Sanholt	{ 0x0460275d, 0x00000020 },
52395584Sanholt	{ 0x00004000, 0000000000 },
52495584Sanholt	{ 0x01e00830, 0x00000002 },
52595584Sanholt	{ 0x21007000, 0000000000 },
52695584Sanholt	{ 0x6464614d, 0000000000 },
52795584Sanholt	{ 0x69687420, 0000000000 },
52895584Sanholt	{ 0x00000073, 0000000000 },
52995584Sanholt	{ 0000000000, 0000000000 },
53095584Sanholt	{ 0x00005000, 0x00000002 },
53195584Sanholt	{ 0x000380d0, 0x00000002 },
53295584Sanholt	{ 0x040025e0, 0x00000002 },
53395584Sanholt	{ 0x000075e1, 0000000000 },
53495584Sanholt	{ 0x00000001, 0000000000 },
53595584Sanholt	{ 0x000380e0, 0x00000002 },
53695584Sanholt	{ 0x04002394, 0x00000002 },
53795584Sanholt	{ 0x00005000, 0000000000 },
53895584Sanholt	{ 0000000000, 0000000000 },
53995584Sanholt	{ 0000000000, 0000000000 },
54095584Sanholt	{ 0x00000008, 0000000000 },
54195584Sanholt	{ 0x00000004, 0000000000 },
54295584Sanholt	{ 0000000000, 0000000000 },
54395584Sanholt	{ 0000000000, 0000000000 },
54495584Sanholt	{ 0000000000, 0000000000 },
54595584Sanholt	{ 0000000000, 0000000000 },
54695584Sanholt	{ 0000000000, 0000000000 },
54795584Sanholt	{ 0000000000, 0000000000 },
54895584Sanholt	{ 0000000000, 0000000000 },
54995584Sanholt	{ 0000000000, 0000000000 },
55095584Sanholt	{ 0000000000, 0000000000 },
55195584Sanholt	{ 0000000000, 0000000000 },
55295584Sanholt	{ 0000000000, 0000000000 },
55395584Sanholt	{ 0000000000, 0000000000 },
55495584Sanholt	{ 0000000000, 0000000000 },
55595584Sanholt	{ 0000000000, 0000000000 },
55695584Sanholt	{ 0000000000, 0000000000 },
55795584Sanholt	{ 0000000000, 0000000000 },
55895584Sanholt	{ 0000000000, 0000000000 },
55995584Sanholt	{ 0000000000, 0000000000 },
56095584Sanholt	{ 0000000000, 0000000000 },
56195584Sanholt	{ 0000000000, 0000000000 },
56295584Sanholt	{ 0000000000, 0000000000 },
56395584Sanholt	{ 0000000000, 0000000000 },
56495584Sanholt	{ 0000000000, 0000000000 },
56595584Sanholt	{ 0000000000, 0000000000 },
56695584Sanholt};
56795584Sanholt
56895584Sanholt
56995584Sanholtint RADEON_READ_PLL(drm_device_t *dev, int addr)
57095584Sanholt{
57195584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
57295584Sanholt
57395584Sanholt	RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
57495584Sanholt	return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
57595584Sanholt}
57695584Sanholt
57795584Sanholt#if RADEON_FIFO_DEBUG
57895584Sanholtstatic void radeon_status( drm_radeon_private_t *dev_priv )
57995584Sanholt{
580112015Sanholt	printk( "%s:\n", __FUNCTION__ );
58195584Sanholt	printk( "RBBM_STATUS = 0x%08x\n",
58295584Sanholt		(unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) );
58395584Sanholt	printk( "CP_RB_RTPR = 0x%08x\n",
58495584Sanholt		(unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
58595584Sanholt	printk( "CP_RB_WTPR = 0x%08x\n",
58695584Sanholt		(unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
58795584Sanholt	printk( "AIC_CNTL = 0x%08x\n",
58895584Sanholt		(unsigned int)RADEON_READ( RADEON_AIC_CNTL ) );
58995584Sanholt	printk( "AIC_STAT = 0x%08x\n",
59095584Sanholt		(unsigned int)RADEON_READ( RADEON_AIC_STAT ) );
59195584Sanholt	printk( "AIC_PT_BASE = 0x%08x\n",
59295584Sanholt		(unsigned int)RADEON_READ( RADEON_AIC_PT_BASE ) );
59395584Sanholt	printk( "TLB_ADDR = 0x%08x\n",
59495584Sanholt		(unsigned int)RADEON_READ( RADEON_AIC_TLB_ADDR ) );
59595584Sanholt	printk( "TLB_DATA = 0x%08x\n",
59695584Sanholt		(unsigned int)RADEON_READ( RADEON_AIC_TLB_DATA ) );
59795584Sanholt}
59895584Sanholt#endif
59995584Sanholt
60095584Sanholt
60195584Sanholt/* ================================================================
60295584Sanholt * Engine, FIFO control
60395584Sanholt */
60495584Sanholt
60595584Sanholtstatic int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv )
60695584Sanholt{
60795584Sanholt	u32 tmp;
60895584Sanholt	int i;
60995584Sanholt
610112015Sanholt	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
611112015Sanholt
61295584Sanholt	tmp  = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
61395584Sanholt	tmp |= RADEON_RB2D_DC_FLUSH_ALL;
61495584Sanholt	RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
61595584Sanholt
61695584Sanholt	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
61795584Sanholt		if ( !(RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT )
61895584Sanholt		       & RADEON_RB2D_DC_BUSY) ) {
61995584Sanholt			return 0;
62095584Sanholt		}
621112015Sanholt		DRM_UDELAY( 1 );
62295584Sanholt	}
62395584Sanholt
62495584Sanholt#if RADEON_FIFO_DEBUG
62595584Sanholt	DRM_ERROR( "failed!\n" );
62695584Sanholt	radeon_status( dev_priv );
62795584Sanholt#endif
628112015Sanholt	return DRM_ERR(EBUSY);
62995584Sanholt}
63095584Sanholt
63195584Sanholtstatic int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
63295584Sanholt				    int entries )
63395584Sanholt{
63495584Sanholt	int i;
63595584Sanholt
636112015Sanholt	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
637112015Sanholt
63895584Sanholt	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
63995584Sanholt		int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
64095584Sanholt			      & RADEON_RBBM_FIFOCNT_MASK );
64195584Sanholt		if ( slots >= entries ) return 0;
642112015Sanholt		DRM_UDELAY( 1 );
64395584Sanholt	}
64495584Sanholt
64595584Sanholt#if RADEON_FIFO_DEBUG
64695584Sanholt	DRM_ERROR( "failed!\n" );
64795584Sanholt	radeon_status( dev_priv );
64895584Sanholt#endif
649112015Sanholt	return DRM_ERR(EBUSY);
65095584Sanholt}
65195584Sanholt
65295584Sanholtstatic int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
65395584Sanholt{
65495584Sanholt	int i, ret;
65595584Sanholt
656112015Sanholt	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
657112015Sanholt
65895584Sanholt	ret = radeon_do_wait_for_fifo( dev_priv, 64 );
65995584Sanholt	if ( ret ) return ret;
660112015Sanholt
66195584Sanholt	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
66295584Sanholt		if ( !(RADEON_READ( RADEON_RBBM_STATUS )
66395584Sanholt		       & RADEON_RBBM_ACTIVE) ) {
66495584Sanholt			radeon_do_pixcache_flush( dev_priv );
66595584Sanholt			return 0;
66695584Sanholt		}
667112015Sanholt		DRM_UDELAY( 1 );
66895584Sanholt	}
66995584Sanholt
67095584Sanholt#if RADEON_FIFO_DEBUG
67195584Sanholt	DRM_ERROR( "failed!\n" );
67295584Sanholt	radeon_status( dev_priv );
67395584Sanholt#endif
674112015Sanholt	return DRM_ERR(EBUSY);
67595584Sanholt}
67695584Sanholt
67795584Sanholt
67895584Sanholt/* ================================================================
67995584Sanholt * CP control, initialization
68095584Sanholt */
68195584Sanholt
68295584Sanholt/* Load the microcode for the CP */
68395584Sanholtstatic void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
68495584Sanholt{
68595584Sanholt	int i;
686112015Sanholt	DRM_DEBUG( "\n" );
68795584Sanholt
68895584Sanholt	radeon_do_wait_for_idle( dev_priv );
68995584Sanholt
69095584Sanholt	RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 );
691112015Sanholt
692112015Sanholt	if (dev_priv->is_r200)
693112015Sanholt	{
694112015Sanholt		DRM_INFO("Loading R200 Microcode\n");
695112015Sanholt		for ( i = 0 ; i < 256 ; i++ )
696112015Sanholt		{
697112015Sanholt			RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
698112015Sanholt				      R200_cp_microcode[i][1] );
699112015Sanholt			RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
700112015Sanholt				      R200_cp_microcode[i][0] );
701112015Sanholt		}
70295584Sanholt	}
703112015Sanholt	else
704112015Sanholt	{
705112015Sanholt		for ( i = 0 ; i < 256 ; i++ ) {
706112015Sanholt			RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
707112015Sanholt				      radeon_cp_microcode[i][1] );
708112015Sanholt			RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
709112015Sanholt				      radeon_cp_microcode[i][0] );
710112015Sanholt		}
711112015Sanholt	}
71295584Sanholt}
71395584Sanholt
71495584Sanholt/* Flush any pending commands to the CP.  This should only be used just
71595584Sanholt * prior to a wait for idle, as it informs the engine that the command
71695584Sanholt * stream is ending.
71795584Sanholt */
71895584Sanholtstatic void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
71995584Sanholt{
720112015Sanholt	DRM_DEBUG( "\n" );
72195584Sanholt#if 0
72295584Sanholt	u32 tmp;
72395584Sanholt
72495584Sanholt	tmp = RADEON_READ( RADEON_CP_RB_WPTR ) | (1 << 31);
72595584Sanholt	RADEON_WRITE( RADEON_CP_RB_WPTR, tmp );
72695584Sanholt#endif
72795584Sanholt}
72895584Sanholt
72995584Sanholt/* Wait for the CP to go idle.
73095584Sanholt */
73195584Sanholtint radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
73295584Sanholt{
73395584Sanholt	RING_LOCALS;
734112015Sanholt	DRM_DEBUG( "\n" );
73595584Sanholt
73695584Sanholt	BEGIN_RING( 6 );
73795584Sanholt
73895584Sanholt	RADEON_PURGE_CACHE();
73995584Sanholt	RADEON_PURGE_ZCACHE();
74095584Sanholt	RADEON_WAIT_UNTIL_IDLE();
74195584Sanholt
74295584Sanholt	ADVANCE_RING();
743112015Sanholt	COMMIT_RING();
74495584Sanholt
74595584Sanholt	return radeon_do_wait_for_idle( dev_priv );
74695584Sanholt}
74795584Sanholt
74895584Sanholt/* Start the Command Processor.
74995584Sanholt */
75095584Sanholtstatic void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
75195584Sanholt{
75295584Sanholt	RING_LOCALS;
753112015Sanholt	DRM_DEBUG( "\n" );
75495584Sanholt
75595584Sanholt	radeon_do_wait_for_idle( dev_priv );
75695584Sanholt
75795584Sanholt	RADEON_WRITE( RADEON_CP_CSQ_CNTL, dev_priv->cp_mode );
75895584Sanholt
75995584Sanholt	dev_priv->cp_running = 1;
76095584Sanholt
76195584Sanholt	BEGIN_RING( 6 );
76295584Sanholt
76395584Sanholt	RADEON_PURGE_CACHE();
76495584Sanholt	RADEON_PURGE_ZCACHE();
76595584Sanholt	RADEON_WAIT_UNTIL_IDLE();
76695584Sanholt
76795584Sanholt	ADVANCE_RING();
768112015Sanholt	COMMIT_RING();
76995584Sanholt}
77095584Sanholt
77195584Sanholt/* Reset the Command Processor.  This will not flush any pending
77295584Sanholt * commands, so you must wait for the CP command stream to complete
77395584Sanholt * before calling this routine.
77495584Sanholt */
77595584Sanholtstatic void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
77695584Sanholt{
77795584Sanholt	u32 cur_read_ptr;
778112015Sanholt	DRM_DEBUG( "\n" );
77995584Sanholt
78095584Sanholt	cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
78195584Sanholt	RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
78295584Sanholt	*dev_priv->ring.head = cur_read_ptr;
78395584Sanholt	dev_priv->ring.tail = cur_read_ptr;
78495584Sanholt}
78595584Sanholt
78695584Sanholt/* Stop the Command Processor.  This will not flush any pending
78795584Sanholt * commands, so you must flush the command stream and wait for the CP
78895584Sanholt * to go idle before calling this routine.
78995584Sanholt */
79095584Sanholtstatic void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
79195584Sanholt{
792112015Sanholt	DRM_DEBUG( "\n" );
79395584Sanholt
79495584Sanholt	RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
79595584Sanholt
79695584Sanholt	dev_priv->cp_running = 0;
79795584Sanholt}
79895584Sanholt
79995584Sanholt/* Reset the engine.  This will stop the CP if it is running.
80095584Sanholt */
80195584Sanholtstatic int radeon_do_engine_reset( drm_device_t *dev )
80295584Sanholt{
80395584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
80495584Sanholt	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
805112015Sanholt	DRM_DEBUG( "\n" );
80695584Sanholt
80795584Sanholt	radeon_do_pixcache_flush( dev_priv );
80895584Sanholt
80995584Sanholt	clock_cntl_index = RADEON_READ( RADEON_CLOCK_CNTL_INDEX );
81095584Sanholt	mclk_cntl = RADEON_READ_PLL( dev, RADEON_MCLK_CNTL );
81195584Sanholt
81295584Sanholt	RADEON_WRITE_PLL( RADEON_MCLK_CNTL, ( mclk_cntl |
81395584Sanholt					      RADEON_FORCEON_MCLKA |
81495584Sanholt					      RADEON_FORCEON_MCLKB |
81595584Sanholt 					      RADEON_FORCEON_YCLKA |
81695584Sanholt					      RADEON_FORCEON_YCLKB |
81795584Sanholt					      RADEON_FORCEON_MC |
81895584Sanholt					      RADEON_FORCEON_AIC ) );
81995584Sanholt
82095584Sanholt	rbbm_soft_reset = RADEON_READ( RADEON_RBBM_SOFT_RESET );
82195584Sanholt
82295584Sanholt	RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset |
82395584Sanholt						RADEON_SOFT_RESET_CP |
82495584Sanholt						RADEON_SOFT_RESET_HI |
82595584Sanholt						RADEON_SOFT_RESET_SE |
82695584Sanholt						RADEON_SOFT_RESET_RE |
82795584Sanholt						RADEON_SOFT_RESET_PP |
82895584Sanholt						RADEON_SOFT_RESET_E2 |
82995584Sanholt						RADEON_SOFT_RESET_RB ) );
83095584Sanholt	RADEON_READ( RADEON_RBBM_SOFT_RESET );
83195584Sanholt	RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset &
83295584Sanholt						~( RADEON_SOFT_RESET_CP |
83395584Sanholt						   RADEON_SOFT_RESET_HI |
83495584Sanholt						   RADEON_SOFT_RESET_SE |
83595584Sanholt						   RADEON_SOFT_RESET_RE |
83695584Sanholt						   RADEON_SOFT_RESET_PP |
83795584Sanholt						   RADEON_SOFT_RESET_E2 |
83895584Sanholt						   RADEON_SOFT_RESET_RB ) ) );
83995584Sanholt	RADEON_READ( RADEON_RBBM_SOFT_RESET );
84095584Sanholt
84195584Sanholt
84295584Sanholt	RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl );
84395584Sanholt	RADEON_WRITE( RADEON_CLOCK_CNTL_INDEX, clock_cntl_index );
84495584Sanholt	RADEON_WRITE( RADEON_RBBM_SOFT_RESET,  rbbm_soft_reset );
84595584Sanholt
84695584Sanholt	/* Reset the CP ring */
84795584Sanholt	radeon_do_cp_reset( dev_priv );
84895584Sanholt
84995584Sanholt	/* The CP is no longer running after an engine reset */
85095584Sanholt	dev_priv->cp_running = 0;
85195584Sanholt
85295584Sanholt	/* Reset any pending vertex, indirect buffers */
85395584Sanholt	radeon_freelist_reset( dev );
85495584Sanholt
85595584Sanholt	return 0;
85695584Sanholt}
85795584Sanholt
85895584Sanholtstatic void radeon_cp_init_ring_buffer( drm_device_t *dev,
85995584Sanholt				        drm_radeon_private_t *dev_priv )
86095584Sanholt{
86195584Sanholt	u32 ring_start, cur_read_ptr;
86295584Sanholt	u32 tmp;
86395584Sanholt
86495584Sanholt	/* Initialize the memory controller */
86595584Sanholt	RADEON_WRITE( RADEON_MC_FB_LOCATION,
86695584Sanholt		      (dev_priv->agp_vm_start - 1) & 0xffff0000 );
86795584Sanholt
86895584Sanholt	if ( !dev_priv->is_pci ) {
86995584Sanholt		RADEON_WRITE( RADEON_MC_AGP_LOCATION,
87095584Sanholt			      (((dev_priv->agp_vm_start - 1 +
87195584Sanholt				 dev_priv->agp_size) & 0xffff0000) |
87295584Sanholt			       (dev_priv->agp_vm_start >> 16)) );
87395584Sanholt	}
87495584Sanholt
87595584Sanholt#if __REALLY_HAVE_AGP
87695584Sanholt	if ( !dev_priv->is_pci )
87795584Sanholt		ring_start = (dev_priv->cp_ring->offset
87895584Sanholt			      - dev->agp->base
87995584Sanholt			      + dev_priv->agp_vm_start);
88095584Sanholt       else
88195584Sanholt#endif
88295584Sanholt		ring_start = (dev_priv->cp_ring->offset
88395584Sanholt			      - dev->sg->handle
88495584Sanholt			      + dev_priv->agp_vm_start);
88595584Sanholt
88695584Sanholt	RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
88795584Sanholt
88895584Sanholt	/* Set the write pointer delay */
88995584Sanholt	RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 );
89095584Sanholt
89195584Sanholt	/* Initialize the ring buffer's read and write pointers */
89295584Sanholt	cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
89395584Sanholt	RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
89495584Sanholt	*dev_priv->ring.head = cur_read_ptr;
89595584Sanholt	dev_priv->ring.tail = cur_read_ptr;
89695584Sanholt
89795584Sanholt	if ( !dev_priv->is_pci ) {
89895584Sanholt		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
89995584Sanholt			      dev_priv->ring_rptr->offset );
90095584Sanholt	} else {
90195584Sanholt		drm_sg_mem_t *entry = dev->sg;
90295584Sanholt		unsigned long tmp_ofs, page_ofs;
90395584Sanholt
90495584Sanholt		tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
90595584Sanholt		page_ofs = tmp_ofs >> PAGE_SHIFT;
90695584Sanholt
90795584Sanholt		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
90895584Sanholt			     entry->busaddr[page_ofs]);
90995584Sanholt		DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
91095584Sanholt			   entry->busaddr[page_ofs],
91195584Sanholt			   entry->handle + tmp_ofs );
91295584Sanholt	}
91395584Sanholt
914112015Sanholt	/* Initialize the scratch register pointer.  This will cause
915112015Sanholt	 * the scratch register values to be written out to memory
916112015Sanholt	 * whenever they are updated.
917112015Sanholt	 *
918112015Sanholt	 * We simply put this behind the ring read pointer, this works
919112015Sanholt	 * with PCI GART as well as (whatever kind of) AGP GART
920112015Sanholt	 */
921112015Sanholt	RADEON_WRITE( RADEON_SCRATCH_ADDR, RADEON_READ( RADEON_CP_RB_RPTR_ADDR )
922112015Sanholt					 + RADEON_SCRATCH_REG_OFFSET );
923112015Sanholt
924112015Sanholt	dev_priv->scratch = ((__volatile__ u32 *)
925112015Sanholt			     dev_priv->ring.head +
926112015Sanholt			     (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
927112015Sanholt
928112015Sanholt	RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
929112015Sanholt
930112015Sanholt	/* Writeback doesn't seem to work everywhere, test it first */
931112015Sanholt	DRM_WRITE32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0 );
932112015Sanholt	RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
933112015Sanholt
934112015Sanholt	for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
935112015Sanholt		if ( DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1) ) == 0xdeadbeef )
936112015Sanholt			break;
937112015Sanholt		DRM_UDELAY( 1 );
938112015Sanholt	}
939112015Sanholt
940112015Sanholt	if ( tmp < dev_priv->usec_timeout ) {
941112015Sanholt		dev_priv->writeback_works = 1;
942112015Sanholt		DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
943112015Sanholt	} else {
944112015Sanholt		dev_priv->writeback_works = 0;
945112015Sanholt		DRM_DEBUG( "writeback test failed\n" );
946112015Sanholt	}
947112015Sanholt
948112015Sanholt	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
949112015Sanholt	RADEON_WRITE( RADEON_LAST_FRAME_REG,
950112015Sanholt		      dev_priv->sarea_priv->last_frame );
951112015Sanholt
952112015Sanholt	dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
953112015Sanholt	RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
954112015Sanholt		      dev_priv->sarea_priv->last_dispatch );
955112015Sanholt
956112015Sanholt	dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
957112015Sanholt	RADEON_WRITE( RADEON_LAST_CLEAR_REG,
958112015Sanholt		      dev_priv->sarea_priv->last_clear );
959112015Sanholt
96095584Sanholt	/* Set ring buffer size */
961112015Sanholt#ifdef __BIG_ENDIAN
962112015Sanholt	RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT );
963112015Sanholt#else
96495584Sanholt	RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
965112015Sanholt#endif
96695584Sanholt
96795584Sanholt	radeon_do_wait_for_idle( dev_priv );
96895584Sanholt
96995584Sanholt	/* Turn on bus mastering */
97095584Sanholt	tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
97195584Sanholt	RADEON_WRITE( RADEON_BUS_CNTL, tmp );
97295584Sanholt
97395584Sanholt	/* Sync everything up */
97495584Sanholt	RADEON_WRITE( RADEON_ISYNC_CNTL,
97595584Sanholt		      (RADEON_ISYNC_ANY2D_IDLE3D |
97695584Sanholt		       RADEON_ISYNC_ANY3D_IDLE2D |
97795584Sanholt		       RADEON_ISYNC_WAIT_IDLEGUI |
97895584Sanholt		       RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
97995584Sanholt}
98095584Sanholt
98195584Sanholtstatic int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
98295584Sanholt{
98395584Sanholt	drm_radeon_private_t *dev_priv;
98495584Sanholt	u32 tmp;
985112015Sanholt	DRM_DEBUG( "\n" );
98695584Sanholt
98795584Sanholt	dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
98895584Sanholt	if ( dev_priv == NULL )
989112015Sanholt		return DRM_ERR(ENOMEM);
99095584Sanholt
99195584Sanholt	memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
99295584Sanholt
99395584Sanholt	dev_priv->is_pci = init->is_pci;
99495584Sanholt
99595584Sanholt#if !defined(PCIGART_ENABLED)
99695584Sanholt	/* PCI support is not 100% working, so we disable it here.
99795584Sanholt	 */
99895584Sanholt	if ( dev_priv->is_pci ) {
99995584Sanholt		DRM_ERROR( "PCI GART not yet supported for Radeon!\n" );
100095584Sanholt		dev->dev_private = (void *)dev_priv;
100195584Sanholt		radeon_do_cleanup_cp(dev);
1002112015Sanholt		return DRM_ERR(EINVAL);
100395584Sanholt	}
100495584Sanholt#endif
100595584Sanholt
100695584Sanholt	if ( dev_priv->is_pci && !dev->sg ) {
100795584Sanholt		DRM_ERROR( "PCI GART memory not allocated!\n" );
100895584Sanholt		dev->dev_private = (void *)dev_priv;
100995584Sanholt		radeon_do_cleanup_cp(dev);
1010112015Sanholt		return DRM_ERR(EINVAL);
101195584Sanholt	}
101295584Sanholt
101395584Sanholt	dev_priv->usec_timeout = init->usec_timeout;
101495584Sanholt	if ( dev_priv->usec_timeout < 1 ||
101595584Sanholt	     dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
101695584Sanholt		DRM_DEBUG( "TIMEOUT problem!\n" );
101795584Sanholt		dev->dev_private = (void *)dev_priv;
101895584Sanholt		radeon_do_cleanup_cp(dev);
1019112015Sanholt		return DRM_ERR(EINVAL);
102095584Sanholt	}
102195584Sanholt
1022112015Sanholt	dev_priv->is_r200 = (init->func == RADEON_INIT_R200_CP);
1023112015Sanholt	dev_priv->do_boxes = 0;
102495584Sanholt	dev_priv->cp_mode = init->cp_mode;
102595584Sanholt
102695584Sanholt	/* We don't support anything other than bus-mastering ring mode,
102795584Sanholt	 * but the ring can be in either AGP or PCI space for the ring
102895584Sanholt	 * read pointer.
102995584Sanholt	 */
103095584Sanholt	if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
103195584Sanholt	     ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
103295584Sanholt		DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
103395584Sanholt		dev->dev_private = (void *)dev_priv;
103495584Sanholt		radeon_do_cleanup_cp(dev);
1035112015Sanholt		return DRM_ERR(EINVAL);
103695584Sanholt	}
103795584Sanholt
103895584Sanholt	switch ( init->fb_bpp ) {
103995584Sanholt	case 16:
104095584Sanholt		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
104195584Sanholt		break;
104295584Sanholt	case 32:
104395584Sanholt	default:
104495584Sanholt		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
104595584Sanholt		break;
104695584Sanholt	}
104795584Sanholt	dev_priv->front_offset	= init->front_offset;
104895584Sanholt	dev_priv->front_pitch	= init->front_pitch;
104995584Sanholt	dev_priv->back_offset	= init->back_offset;
105095584Sanholt	dev_priv->back_pitch	= init->back_pitch;
105195584Sanholt
105295584Sanholt	switch ( init->depth_bpp ) {
105395584Sanholt	case 16:
105495584Sanholt		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
105595584Sanholt		break;
105695584Sanholt	case 32:
105795584Sanholt	default:
105895584Sanholt		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
105995584Sanholt		break;
106095584Sanholt	}
106195584Sanholt	dev_priv->depth_offset	= init->depth_offset;
106295584Sanholt	dev_priv->depth_pitch	= init->depth_pitch;
106395584Sanholt
106495584Sanholt	dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
106595584Sanholt					(dev_priv->front_offset >> 10));
106695584Sanholt	dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
106795584Sanholt				       (dev_priv->back_offset >> 10));
106895584Sanholt	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
106995584Sanholt					(dev_priv->depth_offset >> 10));
107095584Sanholt
107195584Sanholt	/* Hardware state for depth clears.  Remove this if/when we no
107295584Sanholt	 * longer clear the depth buffer with a 3D rectangle.  Hard-code
107395584Sanholt	 * all values to prevent unwanted 3D state from slipping through
107495584Sanholt	 * and screwing with the clear operation.
107595584Sanholt	 */
107695584Sanholt	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
107795584Sanholt					   (dev_priv->color_fmt << 10) |
1078112015Sanholt					   (1<<15));
107995584Sanholt
1080112015Sanholt	dev_priv->depth_clear.rb3d_zstencilcntl =
1081112015Sanholt		(dev_priv->depth_fmt |
1082112015Sanholt		 RADEON_Z_TEST_ALWAYS |
1083112015Sanholt		 RADEON_STENCIL_TEST_ALWAYS |
1084112015Sanholt		 RADEON_STENCIL_S_FAIL_REPLACE |
1085112015Sanholt		 RADEON_STENCIL_ZPASS_REPLACE |
1086112015Sanholt		 RADEON_STENCIL_ZFAIL_REPLACE |
1087112015Sanholt		 RADEON_Z_WRITE_ENABLE);
108895584Sanholt
108995584Sanholt	dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
109095584Sanholt					 RADEON_BFACE_SOLID |
109195584Sanholt					 RADEON_FFACE_SOLID |
109295584Sanholt					 RADEON_FLAT_SHADE_VTX_LAST |
109395584Sanholt					 RADEON_DIFFUSE_SHADE_FLAT |
109495584Sanholt					 RADEON_ALPHA_SHADE_FLAT |
109595584Sanholt					 RADEON_SPECULAR_SHADE_FLAT |
109695584Sanholt					 RADEON_FOG_SHADE_FLAT |
109795584Sanholt					 RADEON_VTX_PIX_CENTER_OGL |
109895584Sanholt					 RADEON_ROUND_MODE_TRUNC |
109995584Sanholt					 RADEON_ROUND_PREC_8TH_PIX);
110095584Sanholt
1101112015Sanholt	DRM_GETSAREA();
1102112015Sanholt
110395584Sanholt	if(!dev_priv->sarea) {
110495584Sanholt		DRM_ERROR("could not find sarea!\n");
110595584Sanholt		dev->dev_private = (void *)dev_priv;
110695584Sanholt		radeon_do_cleanup_cp(dev);
1107112015Sanholt		return DRM_ERR(EINVAL);
110895584Sanholt	}
110995584Sanholt
111095584Sanholt	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
111195584Sanholt	if(!dev_priv->fb) {
111295584Sanholt		DRM_ERROR("could not find framebuffer!\n");
111395584Sanholt		dev->dev_private = (void *)dev_priv;
111495584Sanholt		radeon_do_cleanup_cp(dev);
1115112015Sanholt		return DRM_ERR(EINVAL);
111695584Sanholt	}
111795584Sanholt	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
111895584Sanholt	if(!dev_priv->mmio) {
111995584Sanholt		DRM_ERROR("could not find mmio region!\n");
112095584Sanholt		dev->dev_private = (void *)dev_priv;
112195584Sanholt		radeon_do_cleanup_cp(dev);
1122112015Sanholt		return DRM_ERR(EINVAL);
112395584Sanholt	}
112495584Sanholt	DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
112595584Sanholt	if(!dev_priv->cp_ring) {
112695584Sanholt		DRM_ERROR("could not find cp ring region!\n");
112795584Sanholt		dev->dev_private = (void *)dev_priv;
112895584Sanholt		radeon_do_cleanup_cp(dev);
1129112015Sanholt		return DRM_ERR(EINVAL);
113095584Sanholt	}
113195584Sanholt	DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
113295584Sanholt	if(!dev_priv->ring_rptr) {
113395584Sanholt		DRM_ERROR("could not find ring read pointer!\n");
113495584Sanholt		dev->dev_private = (void *)dev_priv;
113595584Sanholt		radeon_do_cleanup_cp(dev);
1136112015Sanholt		return DRM_ERR(EINVAL);
113795584Sanholt	}
113895584Sanholt	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
113995584Sanholt	if(!dev_priv->buffers) {
114095584Sanholt		DRM_ERROR("could not find dma buffer region!\n");
114195584Sanholt		dev->dev_private = (void *)dev_priv;
114295584Sanholt		radeon_do_cleanup_cp(dev);
1143112015Sanholt		return DRM_ERR(EINVAL);
114495584Sanholt	}
114595584Sanholt
114695584Sanholt	if ( !dev_priv->is_pci ) {
114795584Sanholt		DRM_FIND_MAP( dev_priv->agp_textures,
114895584Sanholt			      init->agp_textures_offset );
114995584Sanholt		if(!dev_priv->agp_textures) {
115095584Sanholt			DRM_ERROR("could not find agp texture region!\n");
115195584Sanholt			dev->dev_private = (void *)dev_priv;
115295584Sanholt			radeon_do_cleanup_cp(dev);
1153112015Sanholt			return DRM_ERR(EINVAL);
115495584Sanholt		}
115595584Sanholt	}
115695584Sanholt
115795584Sanholt	dev_priv->sarea_priv =
115895584Sanholt		(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
115995584Sanholt				       init->sarea_priv_offset);
116095584Sanholt
116195584Sanholt	if ( !dev_priv->is_pci ) {
116295584Sanholt		DRM_IOREMAP( dev_priv->cp_ring );
116395584Sanholt		DRM_IOREMAP( dev_priv->ring_rptr );
116495584Sanholt		DRM_IOREMAP( dev_priv->buffers );
116595584Sanholt		if(!dev_priv->cp_ring->handle ||
116695584Sanholt		   !dev_priv->ring_rptr->handle ||
116795584Sanholt		   !dev_priv->buffers->handle) {
116895584Sanholt			DRM_ERROR("could not find ioremap agp regions!\n");
116995584Sanholt			dev->dev_private = (void *)dev_priv;
117095584Sanholt			radeon_do_cleanup_cp(dev);
1171112015Sanholt			return DRM_ERR(EINVAL);
117295584Sanholt		}
117395584Sanholt	} else {
117495584Sanholt		dev_priv->cp_ring->handle =
117595584Sanholt			(void *)dev_priv->cp_ring->offset;
117695584Sanholt		dev_priv->ring_rptr->handle =
117795584Sanholt			(void *)dev_priv->ring_rptr->offset;
117895584Sanholt		dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
117995584Sanholt
118095584Sanholt		DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
118195584Sanholt			   dev_priv->cp_ring->handle );
118295584Sanholt		DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
118395584Sanholt			   dev_priv->ring_rptr->handle );
118495584Sanholt		DRM_DEBUG( "dev_priv->buffers->handle %p\n",
118595584Sanholt			   dev_priv->buffers->handle );
118695584Sanholt	}
118795584Sanholt
118895584Sanholt
118995584Sanholt	dev_priv->agp_size = init->agp_size;
119095584Sanholt	dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
119195584Sanholt#if __REALLY_HAVE_AGP
119295584Sanholt	if ( !dev_priv->is_pci )
119395584Sanholt		dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
119495584Sanholt						- dev->agp->base
119595584Sanholt						+ dev_priv->agp_vm_start);
119695584Sanholt	else
119795584Sanholt#endif
119895584Sanholt		dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
119995584Sanholt						- dev->sg->handle
120095584Sanholt						+ dev_priv->agp_vm_start);
120195584Sanholt
120295584Sanholt	DRM_DEBUG( "dev_priv->agp_size %d\n",
120395584Sanholt		   dev_priv->agp_size );
120495584Sanholt	DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n",
120595584Sanholt		   dev_priv->agp_vm_start );
120695584Sanholt	DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n",
120795584Sanholt		   dev_priv->agp_buffers_offset );
120895584Sanholt
120995584Sanholt	dev_priv->ring.head = ((__volatile__ u32 *)
121095584Sanholt			       dev_priv->ring_rptr->handle);
121195584Sanholt
121295584Sanholt	dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle;
121395584Sanholt	dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
121495584Sanholt			      + init->ring_size / sizeof(u32));
121595584Sanholt	dev_priv->ring.size = init->ring_size;
121695584Sanholt	dev_priv->ring.size_l2qw = DRM(order)( init->ring_size / 8 );
121795584Sanholt
121895584Sanholt	dev_priv->ring.tail_mask =
121995584Sanholt		(dev_priv->ring.size / sizeof(u32)) - 1;
122095584Sanholt
122195584Sanholt	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
1222112015Sanholt	dev_priv->ring.ring_rptr = dev_priv->ring_rptr;
122395584Sanholt
122495584Sanholt#if __REALLY_HAVE_SG
122595584Sanholt	if ( dev_priv->is_pci ) {
122695584Sanholt		if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
122795584Sanholt					    &dev_priv->bus_pci_gart)) {
122895584Sanholt			DRM_ERROR( "failed to init PCI GART!\n" );
122995584Sanholt			dev->dev_private = (void *)dev_priv;
123095584Sanholt			radeon_do_cleanup_cp(dev);
1231112015Sanholt			return DRM_ERR(ENOMEM);
123295584Sanholt		}
123395584Sanholt		/* Turn on PCI GART
123495584Sanholt		 */
123595584Sanholt		tmp = RADEON_READ( RADEON_AIC_CNTL )
123695584Sanholt		      | RADEON_PCIGART_TRANSLATE_EN;
123795584Sanholt		RADEON_WRITE( RADEON_AIC_CNTL, tmp );
123895584Sanholt
123995584Sanholt		/* set PCI GART page-table base address
124095584Sanholt		 */
124195584Sanholt		RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );
124295584Sanholt
124395584Sanholt		/* set address range for PCI address translate
124495584Sanholt		 */
124595584Sanholt		RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start );
124695584Sanholt		RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start
124795584Sanholt						  + dev_priv->agp_size - 1);
124895584Sanholt
124995584Sanholt		/* Turn off AGP aperture -- is this required for PCIGART?
125095584Sanholt		 */
125195584Sanholt		RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
125295584Sanholt		RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
125395584Sanholt	} else {
1254112015Sanholt#endif /* __REALLY_HAVE_SG */
125595584Sanholt		/* Turn off PCI GART
125695584Sanholt		 */
125795584Sanholt		tmp = RADEON_READ( RADEON_AIC_CNTL )
125895584Sanholt		      & ~RADEON_PCIGART_TRANSLATE_EN;
125995584Sanholt		RADEON_WRITE( RADEON_AIC_CNTL, tmp );
126095584Sanholt#if __REALLY_HAVE_SG
126195584Sanholt	}
1262112015Sanholt#endif /* __REALLY_HAVE_SG */
126395584Sanholt
126495584Sanholt	radeon_cp_load_microcode( dev_priv );
126595584Sanholt	radeon_cp_init_ring_buffer( dev, dev_priv );
126695584Sanholt
126795584Sanholt	dev_priv->last_buf = 0;
126895584Sanholt
126995584Sanholt	dev->dev_private = (void *)dev_priv;
127095584Sanholt
127195584Sanholt	radeon_do_engine_reset( dev );
127295584Sanholt
127395584Sanholt	return 0;
127495584Sanholt}
127595584Sanholt
127695584Sanholtint radeon_do_cleanup_cp( drm_device_t *dev )
127795584Sanholt{
1278112015Sanholt	DRM_DEBUG( "\n" );
127995584Sanholt
128095584Sanholt	if ( dev->dev_private ) {
128195584Sanholt		drm_radeon_private_t *dev_priv = dev->dev_private;
128295584Sanholt
128395584Sanholt		if ( !dev_priv->is_pci ) {
128495584Sanholt			DRM_IOREMAPFREE( dev_priv->cp_ring );
128595584Sanholt			DRM_IOREMAPFREE( dev_priv->ring_rptr );
128695584Sanholt			DRM_IOREMAPFREE( dev_priv->buffers );
1287112015Sanholt		} else {
128895584Sanholt#if __REALLY_HAVE_SG
128995584Sanholt			if (!DRM(ati_pcigart_cleanup)( dev,
129095584Sanholt						dev_priv->phys_pci_gart,
129195584Sanholt						dev_priv->bus_pci_gart ))
129295584Sanholt				DRM_ERROR( "failed to cleanup PCI GART!\n" );
1293112015Sanholt#endif /* __REALLY_HAVE_SG */
129495584Sanholt		}
129595584Sanholt
129695584Sanholt		DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
129795584Sanholt			   DRM_MEM_DRIVER );
129895584Sanholt		dev->dev_private = NULL;
129995584Sanholt	}
130095584Sanholt
130195584Sanholt	return 0;
130295584Sanholt}
130395584Sanholt
1304112015Sanholtint radeon_cp_init( DRM_IOCTL_ARGS )
130595584Sanholt{
1306112015Sanholt	DRM_DEVICE;
130795584Sanholt	drm_radeon_init_t init;
130895584Sanholt
1309112015Sanholt	DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) );
131095584Sanholt
131195584Sanholt	switch ( init.func ) {
131295584Sanholt	case RADEON_INIT_CP:
1313112015Sanholt	case RADEON_INIT_R200_CP:
131495584Sanholt		return radeon_do_init_cp( dev, &init );
131595584Sanholt	case RADEON_CLEANUP_CP:
131695584Sanholt		return radeon_do_cleanup_cp( dev );
131795584Sanholt	}
131895584Sanholt
1319112015Sanholt	return DRM_ERR(EINVAL);
132095584Sanholt}
132195584Sanholt
1322112015Sanholtint radeon_cp_start( DRM_IOCTL_ARGS )
132395584Sanholt{
1324112015Sanholt	DRM_DEVICE;
132595584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1326112015Sanholt	DRM_DEBUG( "\n" );
132795584Sanholt
132895584Sanholt	LOCK_TEST_WITH_RETURN( dev );
132995584Sanholt
133095584Sanholt	if ( dev_priv->cp_running ) {
1331112015Sanholt		DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
133295584Sanholt		return 0;
133395584Sanholt	}
133495584Sanholt	if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) {
133595584Sanholt		DRM_DEBUG( "%s called with bogus CP mode (%d)\n",
1336112015Sanholt			   __FUNCTION__, dev_priv->cp_mode );
133795584Sanholt		return 0;
133895584Sanholt	}
133995584Sanholt
134095584Sanholt	radeon_do_cp_start( dev_priv );
134195584Sanholt
134295584Sanholt	return 0;
134395584Sanholt}
134495584Sanholt
134595584Sanholt/* Stop the CP.  The engine must have been idled before calling this
134695584Sanholt * routine.
134795584Sanholt */
1348112015Sanholtint radeon_cp_stop( DRM_IOCTL_ARGS )
134995584Sanholt{
1350112015Sanholt	DRM_DEVICE;
135195584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
135295584Sanholt	drm_radeon_cp_stop_t stop;
135395584Sanholt	int ret;
1354112015Sanholt	DRM_DEBUG( "\n" );
135595584Sanholt
135695584Sanholt	LOCK_TEST_WITH_RETURN( dev );
135795584Sanholt
1358112015Sanholt	DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t *)data, sizeof(stop) );
135995584Sanholt
1360112015Sanholt	if (!dev_priv->cp_running)
1361112015Sanholt		return 0;
1362112015Sanholt
136395584Sanholt	/* Flush any pending CP commands.  This ensures any outstanding
136495584Sanholt	 * commands are exectuted by the engine before we turn it off.
136595584Sanholt	 */
136695584Sanholt	if ( stop.flush ) {
136795584Sanholt		radeon_do_cp_flush( dev_priv );
136895584Sanholt	}
136995584Sanholt
137095584Sanholt	/* If we fail to make the engine go idle, we return an error
137195584Sanholt	 * code so that the DRM ioctl wrapper can try again.
137295584Sanholt	 */
137395584Sanholt	if ( stop.idle ) {
137495584Sanholt		ret = radeon_do_cp_idle( dev_priv );
137595584Sanholt		if ( ret ) return ret;
137695584Sanholt	}
137795584Sanholt
137895584Sanholt	/* Finally, we can turn off the CP.  If the engine isn't idle,
137995584Sanholt	 * we will get some dropped triangles as they won't be fully
138095584Sanholt	 * rendered before the CP is shut down.
138195584Sanholt	 */
138295584Sanholt	radeon_do_cp_stop( dev_priv );
138395584Sanholt
138495584Sanholt	/* Reset the engine */
138595584Sanholt	radeon_do_engine_reset( dev );
138695584Sanholt
138795584Sanholt	return 0;
138895584Sanholt}
138995584Sanholt
1390112015Sanholt
1391112015Sanholtvoid radeon_do_release( drm_device_t *dev )
1392112015Sanholt{
1393112015Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1394112015Sanholt	int ret;
1395112015Sanholt
1396112015Sanholt	if (dev_priv) {
1397112015Sanholt		if (dev_priv->cp_running) {
1398112015Sanholt			/* Stop the cp */
1399112015Sanholt			while ((ret = radeon_do_cp_idle( dev_priv )) != 0) {
1400112015Sanholt				DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
1401112015Sanholt#ifdef __linux__
1402112015Sanholt				schedule();
1403112015Sanholt#else
1404112015Sanholt				tsleep(&ret, PZERO, "rdnrel", 1);
1405112015Sanholt#endif
1406112015Sanholt			}
1407112015Sanholt			radeon_do_cp_stop( dev_priv );
1408112015Sanholt			radeon_do_engine_reset( dev );
1409112015Sanholt		}
1410112015Sanholt
1411112015Sanholt		/* Disable *all* interrupts */
1412112015Sanholt		RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
1413112015Sanholt
1414112015Sanholt		/* Free memory heap structures */
1415112015Sanholt		radeon_mem_takedown( &(dev_priv->agp_heap) );
1416112015Sanholt		radeon_mem_takedown( &(dev_priv->fb_heap) );
1417112015Sanholt
1418112015Sanholt		/* deallocate kernel resources */
1419112015Sanholt		radeon_do_cleanup_cp( dev );
1420112015Sanholt	}
1421112015Sanholt}
1422112015Sanholt
142395584Sanholt/* Just reset the CP ring.  Called as part of an X Server engine reset.
142495584Sanholt */
1425112015Sanholtint radeon_cp_reset( DRM_IOCTL_ARGS )
142695584Sanholt{
1427112015Sanholt	DRM_DEVICE;
142895584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1429112015Sanholt	DRM_DEBUG( "\n" );
143095584Sanholt
143195584Sanholt	LOCK_TEST_WITH_RETURN( dev );
143295584Sanholt
143395584Sanholt	if ( !dev_priv ) {
1434112015Sanholt		DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
1435112015Sanholt		return DRM_ERR(EINVAL);
143695584Sanholt	}
143795584Sanholt
143895584Sanholt	radeon_do_cp_reset( dev_priv );
143995584Sanholt
144095584Sanholt	/* The CP is no longer running after an engine reset */
144195584Sanholt	dev_priv->cp_running = 0;
144295584Sanholt
144395584Sanholt	return 0;
144495584Sanholt}
144595584Sanholt
1446112015Sanholtint radeon_cp_idle( DRM_IOCTL_ARGS )
144795584Sanholt{
1448112015Sanholt	DRM_DEVICE;
144995584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1450112015Sanholt	DRM_DEBUG( "\n" );
145195584Sanholt
145295584Sanholt	LOCK_TEST_WITH_RETURN( dev );
145395584Sanholt
145495584Sanholt	return radeon_do_cp_idle( dev_priv );
145595584Sanholt}
145695584Sanholt
1457112015Sanholtint radeon_engine_reset( DRM_IOCTL_ARGS )
145895584Sanholt{
1459112015Sanholt	DRM_DEVICE;
1460112015Sanholt	DRM_DEBUG( "\n" );
146195584Sanholt
146295584Sanholt	LOCK_TEST_WITH_RETURN( dev );
146395584Sanholt
146495584Sanholt	return radeon_do_engine_reset( dev );
146595584Sanholt}
146695584Sanholt
146795584Sanholt
146895584Sanholt/* ================================================================
146995584Sanholt * Fullscreen mode
147095584Sanholt */
147195584Sanholt
1472112015Sanholt/* KW: Deprecated to say the least:
1473112015Sanholt */
1474112015Sanholtint radeon_fullscreen( DRM_IOCTL_ARGS )
147595584Sanholt{
147695584Sanholt	return 0;
147795584Sanholt}
147895584Sanholt
147995584Sanholt
148095584Sanholt/* ================================================================
148195584Sanholt * Freelist management
148295584Sanholt */
148395584Sanholt
1484112015Sanholt/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
1485112015Sanholt *   bufs until freelist code is used.  Note this hides a problem with
1486112015Sanholt *   the scratch register * (used to keep track of last buffer
1487112015Sanholt *   completed) being written to before * the last buffer has actually
1488112015Sanholt *   completed rendering.
1489112015Sanholt *
1490112015Sanholt * KW:  It's also a good way to find free buffers quickly.
1491112015Sanholt *
1492112015Sanholt * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
1493112015Sanholt * sleep.  However, bugs in older versions of radeon_accel.c mean that
1494112015Sanholt * we essentially have to do this, else old clients will break.
1495112015Sanholt *
1496112015Sanholt * However, it does leave open a potential deadlock where all the
1497112015Sanholt * buffers are held by other clients, which can't release them because
1498112015Sanholt * they can't get the lock.
1499112015Sanholt */
1500112015Sanholt
1501112015Sanholtdrm_buf_t *radeon_freelist_get( drm_device_t *dev )
150295584Sanholt{
150395584Sanholt	drm_device_dma_t *dma = dev->dma;
150495584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1505112015Sanholt	drm_radeon_buf_priv_t *buf_priv;
150695584Sanholt	drm_buf_t *buf;
1507112015Sanholt	int i, t;
1508112015Sanholt	int start;
150995584Sanholt
1510112015Sanholt	if ( ++dev_priv->last_buf >= dma->buf_count )
1511112015Sanholt		dev_priv->last_buf = 0;
151295584Sanholt
1513112015Sanholt	start = dev_priv->last_buf;
151495584Sanholt
1515112015Sanholt	for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
1516112015Sanholt		u32 done_age = GET_SCRATCH( 1 );
1517112015Sanholt		DRM_DEBUG("done_age = %d\n",done_age);
1518112015Sanholt		for ( i = start ; i < dma->buf_count ; i++ ) {
1519112015Sanholt			buf = dma->buflist[i];
1520112015Sanholt			buf_priv = buf->dev_private;
1521112015Sanholt			if ( buf->pid == 0 || (buf->pending &&
1522112015Sanholt					       buf_priv->age <= done_age) ) {
1523112015Sanholt				dev_priv->stats.requested_bufs++;
1524112015Sanholt				buf->pending = 0;
1525112015Sanholt				return buf;
1526112015Sanholt			}
1527112015Sanholt			start = 0;
1528112015Sanholt		}
152995584Sanholt
1530112015Sanholt		if (t) {
1531112015Sanholt			DRM_UDELAY( 1 );
1532112015Sanholt			dev_priv->stats.freelist_loops++;
1533112015Sanholt		}
153495584Sanholt	}
153595584Sanholt
1536112015Sanholt	DRM_DEBUG( "returning NULL!\n" );
1537112015Sanholt	return NULL;
153895584Sanholt}
1539112015Sanholt#if 0
154095584Sanholtdrm_buf_t *radeon_freelist_get( drm_device_t *dev )
154195584Sanholt{
154295584Sanholt	drm_device_dma_t *dma = dev->dma;
154395584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
154495584Sanholt	drm_radeon_buf_priv_t *buf_priv;
154595584Sanholt	drm_buf_t *buf;
154695584Sanholt	int i, t;
154795584Sanholt	int start;
1548112015Sanholt	u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
154995584Sanholt
155095584Sanholt	if ( ++dev_priv->last_buf >= dma->buf_count )
155195584Sanholt		dev_priv->last_buf = 0;
1552112015Sanholt
155395584Sanholt	start = dev_priv->last_buf;
1554112015Sanholt	dev_priv->stats.freelist_loops++;
1555112015Sanholt
1556112015Sanholt	for ( t = 0 ; t < 2 ; t++ ) {
155795584Sanholt		for ( i = start ; i < dma->buf_count ; i++ ) {
155895584Sanholt			buf = dma->buflist[i];
155995584Sanholt			buf_priv = buf->dev_private;
1560112015Sanholt			if ( buf->pid == 0 || (buf->pending &&
1561112015Sanholt					       buf_priv->age <= done_age) ) {
1562112015Sanholt				dev_priv->stats.requested_bufs++;
156395584Sanholt				buf->pending = 0;
156495584Sanholt				return buf;
156595584Sanholt			}
156695584Sanholt		}
1567112015Sanholt		start = 0;
156895584Sanholt	}
156995584Sanholt
157095584Sanholt	return NULL;
157195584Sanholt}
1572112015Sanholt#endif
157395584Sanholt
157495584Sanholtvoid radeon_freelist_reset( drm_device_t *dev )
157595584Sanholt{
157695584Sanholt	drm_device_dma_t *dma = dev->dma;
157795584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
157895584Sanholt	int i;
157995584Sanholt
158095584Sanholt	dev_priv->last_buf = 0;
158195584Sanholt	for ( i = 0 ; i < dma->buf_count ; i++ ) {
158295584Sanholt		drm_buf_t *buf = dma->buflist[i];
158395584Sanholt		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
158495584Sanholt		buf_priv->age = 0;
158595584Sanholt	}
158695584Sanholt}
158795584Sanholt
158895584Sanholt
158995584Sanholt/* ================================================================
159095584Sanholt * CP command submission
159195584Sanholt */
159295584Sanholt
159395584Sanholtint radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
159495584Sanholt{
159595584Sanholt	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
159695584Sanholt	int i;
1597112015Sanholt	u32 last_head = GET_RING_HEAD(ring);
159895584Sanholt
159995584Sanholt	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
1600112015Sanholt		u32 head = GET_RING_HEAD(ring);
1601112015Sanholt
1602112015Sanholt		ring->space = (head - ring->tail) * sizeof(u32);
1603112015Sanholt		if ( ring->space <= 0 )
1604112015Sanholt			ring->space += ring->size;
160595584Sanholt		if ( ring->space > n )
160695584Sanholt			return 0;
1607112015Sanholt
1608112015Sanholt		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
1609112015Sanholt
1610112015Sanholt		if (head != last_head)
1611112015Sanholt			i = 0;
1612112015Sanholt		last_head = head;
1613112015Sanholt
1614112015Sanholt		DRM_UDELAY( 1 );
161595584Sanholt	}
161695584Sanholt
161795584Sanholt	/* FIXME: This return value is ignored in the BEGIN_RING macro! */
161895584Sanholt#if RADEON_FIFO_DEBUG
161995584Sanholt	radeon_status( dev_priv );
162095584Sanholt	DRM_ERROR( "failed!\n" );
162195584Sanholt#endif
1622112015Sanholt	return DRM_ERR(EBUSY);
162395584Sanholt}
162495584Sanholt
162595584Sanholtstatic int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d )
162695584Sanholt{
162795584Sanholt	int i;
162895584Sanholt	drm_buf_t *buf;
162995584Sanholt
163095584Sanholt	for ( i = d->granted_count ; i < d->request_count ; i++ ) {
163195584Sanholt		buf = radeon_freelist_get( dev );
1632112015Sanholt		if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */
163395584Sanholt
1634112015Sanholt		buf->pid = DRM_CURRENTPID;
163595584Sanholt
1636112015Sanholt		if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
163795584Sanholt				   sizeof(buf->idx) ) )
1638112015Sanholt			return DRM_ERR(EFAULT);
1639112015Sanholt		if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
164095584Sanholt				   sizeof(buf->total) ) )
1641112015Sanholt			return DRM_ERR(EFAULT);
164295584Sanholt
164395584Sanholt		d->granted_count++;
164495584Sanholt	}
164595584Sanholt	return 0;
164695584Sanholt}
164795584Sanholt
1648112015Sanholtint radeon_cp_buffers( DRM_IOCTL_ARGS )
164995584Sanholt{
1650112015Sanholt	DRM_DEVICE;
165195584Sanholt	drm_device_dma_t *dma = dev->dma;
165295584Sanholt	int ret = 0;
165395584Sanholt	drm_dma_t d;
165495584Sanholt
165595584Sanholt	LOCK_TEST_WITH_RETURN( dev );
165695584Sanholt
1657112015Sanholt	DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *)data, sizeof(d) );
165895584Sanholt
165995584Sanholt	/* Please don't send us buffers.
166095584Sanholt	 */
166195584Sanholt	if ( d.send_count != 0 ) {
166295584Sanholt		DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
1663112015Sanholt			   DRM_CURRENTPID, d.send_count );
1664112015Sanholt		return DRM_ERR(EINVAL);
166595584Sanholt	}
166695584Sanholt
166795584Sanholt	/* We'll send you buffers.
166895584Sanholt	 */
166995584Sanholt	if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
167095584Sanholt		DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
1671112015Sanholt			   DRM_CURRENTPID, d.request_count, dma->buf_count );
1672112015Sanholt		return DRM_ERR(EINVAL);
167395584Sanholt	}
167495584Sanholt
167595584Sanholt	d.granted_count = 0;
167695584Sanholt
167795584Sanholt	if ( d.request_count ) {
167895584Sanholt		ret = radeon_cp_get_buffers( dev, &d );
167995584Sanholt	}
168095584Sanholt
1681112015Sanholt	DRM_COPY_TO_USER_IOCTL( (drm_dma_t *)data, d, sizeof(d) );
168295584Sanholt
168395584Sanholt	return ret;
168495584Sanholt}
1685