radeon_cp.c revision 119895
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 119895 2003-09-09 00:24:31Z 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
4195584Sanholt
4295584Sanholt/* CP microcode (from ATI) */
43112015Sanholtstatic u32 R200_cp_microcode[][2] = {
44112015Sanholt	{ 0x21007000, 0000000000 },
45112015Sanholt	{ 0x20007000, 0000000000 },
46112015Sanholt	{ 0x000000ab, 0x00000004 },
47112015Sanholt	{ 0x000000af, 0x00000004 },
48112015Sanholt	{ 0x66544a49, 0000000000 },
49112015Sanholt	{ 0x49494174, 0000000000 },
50112015Sanholt	{ 0x54517d83, 0000000000 },
51112015Sanholt	{ 0x498d8b64, 0000000000 },
52112015Sanholt	{ 0x49494949, 0000000000 },
53112015Sanholt	{ 0x49da493c, 0000000000 },
54112015Sanholt	{ 0x49989898, 0000000000 },
55112015Sanholt	{ 0xd34949d5, 0000000000 },
56112015Sanholt	{ 0x9dc90e11, 0000000000 },
57112015Sanholt	{ 0xce9b9b9b, 0000000000 },
58112015Sanholt	{ 0x000f0000, 0x00000016 },
59112015Sanholt	{ 0x352e232c, 0000000000 },
60112015Sanholt	{ 0x00000013, 0x00000004 },
61112015Sanholt	{ 0x000f0000, 0x00000016 },
62112015Sanholt	{ 0x352e272c, 0000000000 },
63112015Sanholt	{ 0x000f0001, 0x00000016 },
64112015Sanholt	{ 0x3239362f, 0000000000 },
65112015Sanholt	{ 0x000077ef, 0x00000002 },
66112015Sanholt	{ 0x00061000, 0x00000002 },
67112015Sanholt	{ 0x00000020, 0x0000001a },
68112015Sanholt	{ 0x00004000, 0x0000001e },
69112015Sanholt	{ 0x00061000, 0x00000002 },
70112015Sanholt	{ 0x00000020, 0x0000001a },
71112015Sanholt	{ 0x00004000, 0x0000001e },
72112015Sanholt	{ 0x00061000, 0x00000002 },
73112015Sanholt	{ 0x00000020, 0x0000001a },
74112015Sanholt	{ 0x00004000, 0x0000001e },
75112015Sanholt	{ 0x00000016, 0x00000004 },
76112015Sanholt	{ 0x0003802a, 0x00000002 },
77112015Sanholt	{ 0x040067e0, 0x00000002 },
78112015Sanholt	{ 0x00000016, 0x00000004 },
79112015Sanholt	{ 0x000077e0, 0x00000002 },
80112015Sanholt	{ 0x00065000, 0x00000002 },
81112015Sanholt	{ 0x000037e1, 0x00000002 },
82112015Sanholt	{ 0x040067e1, 0x00000006 },
83112015Sanholt	{ 0x000077e0, 0x00000002 },
84112015Sanholt	{ 0x000077e1, 0x00000002 },
85112015Sanholt	{ 0x000077e1, 0x00000006 },
86112015Sanholt	{ 0xffffffff, 0000000000 },
87112015Sanholt	{ 0x10000000, 0000000000 },
88112015Sanholt	{ 0x0003802a, 0x00000002 },
89112015Sanholt	{ 0x040067e0, 0x00000006 },
90112015Sanholt	{ 0x00007675, 0x00000002 },
91112015Sanholt	{ 0x00007676, 0x00000002 },
92112015Sanholt	{ 0x00007677, 0x00000002 },
93112015Sanholt	{ 0x00007678, 0x00000006 },
94112015Sanholt	{ 0x0003802b, 0x00000002 },
95112015Sanholt	{ 0x04002676, 0x00000002 },
96112015Sanholt	{ 0x00007677, 0x00000002 },
97112015Sanholt	{ 0x00007678, 0x00000006 },
98112015Sanholt	{ 0x0000002e, 0x00000018 },
99112015Sanholt	{ 0x0000002e, 0x00000018 },
100112015Sanholt	{ 0000000000, 0x00000006 },
101112015Sanholt	{ 0x0000002f, 0x00000018 },
102112015Sanholt	{ 0x0000002f, 0x00000018 },
103112015Sanholt	{ 0000000000, 0x00000006 },
104112015Sanholt	{ 0x01605000, 0x00000002 },
105112015Sanholt	{ 0x00065000, 0x00000002 },
106112015Sanholt	{ 0x00098000, 0x00000002 },
107112015Sanholt	{ 0x00061000, 0x00000002 },
108112015Sanholt	{ 0x64c0603d, 0x00000004 },
109112015Sanholt	{ 0x00080000, 0x00000016 },
110112015Sanholt	{ 0000000000, 0000000000 },
111112015Sanholt	{ 0x0400251d, 0x00000002 },
112112015Sanholt	{ 0x00007580, 0x00000002 },
113112015Sanholt	{ 0x00067581, 0x00000002 },
114112015Sanholt	{ 0x04002580, 0x00000002 },
115112015Sanholt	{ 0x00067581, 0x00000002 },
116112015Sanholt	{ 0x00000046, 0x00000004 },
117112015Sanholt	{ 0x00005000, 0000000000 },
118112015Sanholt	{ 0x00061000, 0x00000002 },
119112015Sanholt	{ 0x0000750e, 0x00000002 },
120112015Sanholt	{ 0x00019000, 0x00000002 },
121112015Sanholt	{ 0x00011055, 0x00000014 },
122112015Sanholt	{ 0x00000055, 0x00000012 },
123112015Sanholt	{ 0x0400250f, 0x00000002 },
124112015Sanholt	{ 0x0000504a, 0x00000004 },
125112015Sanholt	{ 0x00007565, 0x00000002 },
126112015Sanholt	{ 0x00007566, 0x00000002 },
127112015Sanholt	{ 0x00000051, 0x00000004 },
128112015Sanholt	{ 0x01e655b4, 0x00000002 },
129112015Sanholt	{ 0x4401b0dc, 0x00000002 },
130112015Sanholt	{ 0x01c110dc, 0x00000002 },
131112015Sanholt	{ 0x2666705d, 0x00000018 },
132112015Sanholt	{ 0x040c2565, 0x00000002 },
133112015Sanholt	{ 0x0000005d, 0x00000018 },
134112015Sanholt	{ 0x04002564, 0x00000002 },
135112015Sanholt	{ 0x00007566, 0x00000002 },
136112015Sanholt	{ 0x00000054, 0x00000004 },
137112015Sanholt	{ 0x00401060, 0x00000008 },
138112015Sanholt	{ 0x00101000, 0x00000002 },
139112015Sanholt	{ 0x000d80ff, 0x00000002 },
140112015Sanholt	{ 0x00800063, 0x00000008 },
141112015Sanholt	{ 0x000f9000, 0x00000002 },
142112015Sanholt	{ 0x000e00ff, 0x00000002 },
143112015Sanholt	{ 0000000000, 0x00000006 },
144112015Sanholt	{ 0x00000080, 0x00000018 },
145112015Sanholt	{ 0x00000054, 0x00000004 },
146112015Sanholt	{ 0x00007576, 0x00000002 },
147112015Sanholt	{ 0x00065000, 0x00000002 },
148112015Sanholt	{ 0x00009000, 0x00000002 },
149112015Sanholt	{ 0x00041000, 0x00000002 },
150112015Sanholt	{ 0x0c00350e, 0x00000002 },
151112015Sanholt	{ 0x00049000, 0x00000002 },
152112015Sanholt	{ 0x00051000, 0x00000002 },
153112015Sanholt	{ 0x01e785f8, 0x00000002 },
154112015Sanholt	{ 0x00200000, 0x00000002 },
155112015Sanholt	{ 0x00600073, 0x0000000c },
156112015Sanholt	{ 0x00007563, 0x00000002 },
157112015Sanholt	{ 0x006075f0, 0x00000021 },
158112015Sanholt	{ 0x20007068, 0x00000004 },
159112015Sanholt	{ 0x00005068, 0x00000004 },
160112015Sanholt	{ 0x00007576, 0x00000002 },
161112015Sanholt	{ 0x00007577, 0x00000002 },
162112015Sanholt	{ 0x0000750e, 0x00000002 },
163112015Sanholt	{ 0x0000750f, 0x00000002 },
164112015Sanholt	{ 0x00a05000, 0x00000002 },
165112015Sanholt	{ 0x00600076, 0x0000000c },
166112015Sanholt	{ 0x006075f0, 0x00000021 },
167112015Sanholt	{ 0x000075f8, 0x00000002 },
168112015Sanholt	{ 0x00000076, 0x00000004 },
169112015Sanholt	{ 0x000a750e, 0x00000002 },
170112015Sanholt	{ 0x0020750f, 0x00000002 },
171112015Sanholt	{ 0x00600079, 0x00000004 },
172112015Sanholt	{ 0x00007570, 0x00000002 },
173112015Sanholt	{ 0x00007571, 0x00000002 },
174112015Sanholt	{ 0x00007572, 0x00000006 },
175112015Sanholt	{ 0x00005000, 0x00000002 },
176112015Sanholt	{ 0x00a05000, 0x00000002 },
177112015Sanholt	{ 0x00007568, 0x00000002 },
178112015Sanholt	{ 0x00061000, 0x00000002 },
179112015Sanholt	{ 0x00000084, 0x0000000c },
180112015Sanholt	{ 0x00058000, 0x00000002 },
181112015Sanholt	{ 0x0c607562, 0x00000002 },
182112015Sanholt	{ 0x00000086, 0x00000004 },
183112015Sanholt	{ 0x00600085, 0x00000004 },
184112015Sanholt	{ 0x400070dd, 0000000000 },
185112015Sanholt	{ 0x000380dd, 0x00000002 },
186112015Sanholt	{ 0x00000093, 0x0000001c },
187112015Sanholt	{ 0x00065095, 0x00000018 },
188112015Sanholt	{ 0x040025bb, 0x00000002 },
189112015Sanholt	{ 0x00061096, 0x00000018 },
190112015Sanholt	{ 0x040075bc, 0000000000 },
191112015Sanholt	{ 0x000075bb, 0x00000002 },
192112015Sanholt	{ 0x000075bc, 0000000000 },
193112015Sanholt	{ 0x00090000, 0x00000006 },
194112015Sanholt	{ 0x00090000, 0x00000002 },
195112015Sanholt	{ 0x000d8002, 0x00000006 },
196112015Sanholt	{ 0x00005000, 0x00000002 },
197112015Sanholt	{ 0x00007821, 0x00000002 },
198112015Sanholt	{ 0x00007800, 0000000000 },
199112015Sanholt	{ 0x00007821, 0x00000002 },
200112015Sanholt	{ 0x00007800, 0000000000 },
201112015Sanholt	{ 0x01665000, 0x00000002 },
202112015Sanholt	{ 0x000a0000, 0x00000002 },
203112015Sanholt	{ 0x000671cc, 0x00000002 },
204112015Sanholt	{ 0x0286f1cd, 0x00000002 },
205112015Sanholt	{ 0x000000a3, 0x00000010 },
206112015Sanholt	{ 0x21007000, 0000000000 },
207112015Sanholt	{ 0x000000aa, 0x0000001c },
208112015Sanholt	{ 0x00065000, 0x00000002 },
209112015Sanholt	{ 0x000a0000, 0x00000002 },
210112015Sanholt	{ 0x00061000, 0x00000002 },
211112015Sanholt	{ 0x000b0000, 0x00000002 },
212112015Sanholt	{ 0x38067000, 0x00000002 },
213112015Sanholt	{ 0x000a00a6, 0x00000004 },
214112015Sanholt	{ 0x20007000, 0000000000 },
215112015Sanholt	{ 0x01200000, 0x00000002 },
216112015Sanholt	{ 0x20077000, 0x00000002 },
217112015Sanholt	{ 0x01200000, 0x00000002 },
218112015Sanholt	{ 0x20007000, 0000000000 },
219112015Sanholt	{ 0x00061000, 0x00000002 },
220112015Sanholt	{ 0x0120751b, 0x00000002 },
221112015Sanholt	{ 0x8040750a, 0x00000002 },
222112015Sanholt	{ 0x8040750b, 0x00000002 },
223112015Sanholt	{ 0x00110000, 0x00000002 },
224112015Sanholt	{ 0x000380dd, 0x00000002 },
225112015Sanholt	{ 0x000000bd, 0x0000001c },
226112015Sanholt	{ 0x00061096, 0x00000018 },
227112015Sanholt	{ 0x844075bd, 0x00000002 },
228112015Sanholt	{ 0x00061095, 0x00000018 },
229112015Sanholt	{ 0x840075bb, 0x00000002 },
230112015Sanholt	{ 0x00061096, 0x00000018 },
231112015Sanholt	{ 0x844075bc, 0x00000002 },
232112015Sanholt	{ 0x000000c0, 0x00000004 },
233112015Sanholt	{ 0x804075bd, 0x00000002 },
234112015Sanholt	{ 0x800075bb, 0x00000002 },
235112015Sanholt	{ 0x804075bc, 0x00000002 },
236112015Sanholt	{ 0x00108000, 0x00000002 },
237112015Sanholt	{ 0x01400000, 0x00000002 },
238112015Sanholt	{ 0x006000c4, 0x0000000c },
239112015Sanholt	{ 0x20c07000, 0x00000020 },
240112015Sanholt	{ 0x000000c6, 0x00000012 },
241112015Sanholt	{ 0x00800000, 0x00000006 },
242112015Sanholt	{ 0x0080751d, 0x00000006 },
243112015Sanholt	{ 0x000025bb, 0x00000002 },
244112015Sanholt	{ 0x000040c0, 0x00000004 },
245112015Sanholt	{ 0x0000775c, 0x00000002 },
246112015Sanholt	{ 0x00a05000, 0x00000002 },
247112015Sanholt	{ 0x00661000, 0x00000002 },
248112015Sanholt	{ 0x0460275d, 0x00000020 },
249112015Sanholt	{ 0x00004000, 0000000000 },
250112015Sanholt	{ 0x00007999, 0x00000002 },
251112015Sanholt	{ 0x00a05000, 0x00000002 },
252112015Sanholt	{ 0x00661000, 0x00000002 },
253112015Sanholt	{ 0x0460299b, 0x00000020 },
254112015Sanholt	{ 0x00004000, 0000000000 },
255112015Sanholt	{ 0x01e00830, 0x00000002 },
256112015Sanholt	{ 0x21007000, 0000000000 },
257112015Sanholt	{ 0x00005000, 0x00000002 },
258112015Sanholt	{ 0x00038042, 0x00000002 },
259112015Sanholt	{ 0x040025e0, 0x00000002 },
260112015Sanholt	{ 0x000075e1, 0000000000 },
261112015Sanholt	{ 0x00000001, 0000000000 },
262112015Sanholt	{ 0x000380d9, 0x00000002 },
263112015Sanholt	{ 0x04007394, 0000000000 },
264112015Sanholt	{ 0000000000, 0000000000 },
265112015Sanholt	{ 0000000000, 0000000000 },
266112015Sanholt	{ 0000000000, 0000000000 },
267112015Sanholt	{ 0000000000, 0000000000 },
268112015Sanholt	{ 0000000000, 0000000000 },
269112015Sanholt	{ 0000000000, 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};
301112015Sanholt
302112015Sanholt
30395584Sanholtstatic u32 radeon_cp_microcode[][2] = {
30495584Sanholt	{ 0x21007000, 0000000000 },
30595584Sanholt	{ 0x20007000, 0000000000 },
30695584Sanholt	{ 0x000000b4, 0x00000004 },
30795584Sanholt	{ 0x000000b8, 0x00000004 },
30895584Sanholt	{ 0x6f5b4d4c, 0000000000 },
30995584Sanholt	{ 0x4c4c427f, 0000000000 },
31095584Sanholt	{ 0x5b568a92, 0000000000 },
31195584Sanholt	{ 0x4ca09c6d, 0000000000 },
31295584Sanholt	{ 0xad4c4c4c, 0000000000 },
31395584Sanholt	{ 0x4ce1af3d, 0000000000 },
31495584Sanholt	{ 0xd8afafaf, 0000000000 },
31595584Sanholt	{ 0xd64c4cdc, 0000000000 },
31695584Sanholt	{ 0x4cd10d10, 0000000000 },
31795584Sanholt	{ 0x000f0000, 0x00000016 },
31895584Sanholt	{ 0x362f242d, 0000000000 },
31995584Sanholt	{ 0x00000012, 0x00000004 },
32095584Sanholt	{ 0x000f0000, 0x00000016 },
32195584Sanholt	{ 0x362f282d, 0000000000 },
32295584Sanholt	{ 0x000380e7, 0x00000002 },
32395584Sanholt	{ 0x04002c97, 0x00000002 },
32495584Sanholt	{ 0x000f0001, 0x00000016 },
32595584Sanholt	{ 0x333a3730, 0000000000 },
32695584Sanholt	{ 0x000077ef, 0x00000002 },
32795584Sanholt	{ 0x00061000, 0x00000002 },
32895584Sanholt	{ 0x00000021, 0x0000001a },
32995584Sanholt	{ 0x00004000, 0x0000001e },
33095584Sanholt	{ 0x00061000, 0x00000002 },
33195584Sanholt	{ 0x00000021, 0x0000001a },
33295584Sanholt	{ 0x00004000, 0x0000001e },
33395584Sanholt	{ 0x00061000, 0x00000002 },
33495584Sanholt	{ 0x00000021, 0x0000001a },
33595584Sanholt	{ 0x00004000, 0x0000001e },
33695584Sanholt	{ 0x00000017, 0x00000004 },
33795584Sanholt	{ 0x0003802b, 0x00000002 },
33895584Sanholt	{ 0x040067e0, 0x00000002 },
33995584Sanholt	{ 0x00000017, 0x00000004 },
34095584Sanholt	{ 0x000077e0, 0x00000002 },
34195584Sanholt	{ 0x00065000, 0x00000002 },
34295584Sanholt	{ 0x000037e1, 0x00000002 },
34395584Sanholt	{ 0x040067e1, 0x00000006 },
34495584Sanholt	{ 0x000077e0, 0x00000002 },
34595584Sanholt	{ 0x000077e1, 0x00000002 },
34695584Sanholt	{ 0x000077e1, 0x00000006 },
34795584Sanholt	{ 0xffffffff, 0000000000 },
34895584Sanholt	{ 0x10000000, 0000000000 },
34995584Sanholt	{ 0x0003802b, 0x00000002 },
35095584Sanholt	{ 0x040067e0, 0x00000006 },
35195584Sanholt	{ 0x00007675, 0x00000002 },
35295584Sanholt	{ 0x00007676, 0x00000002 },
35395584Sanholt	{ 0x00007677, 0x00000002 },
35495584Sanholt	{ 0x00007678, 0x00000006 },
35595584Sanholt	{ 0x0003802c, 0x00000002 },
35695584Sanholt	{ 0x04002676, 0x00000002 },
35795584Sanholt	{ 0x00007677, 0x00000002 },
35895584Sanholt	{ 0x00007678, 0x00000006 },
35995584Sanholt	{ 0x0000002f, 0x00000018 },
36095584Sanholt	{ 0x0000002f, 0x00000018 },
36195584Sanholt	{ 0000000000, 0x00000006 },
36295584Sanholt	{ 0x00000030, 0x00000018 },
36395584Sanholt	{ 0x00000030, 0x00000018 },
36495584Sanholt	{ 0000000000, 0x00000006 },
36595584Sanholt	{ 0x01605000, 0x00000002 },
36695584Sanholt	{ 0x00065000, 0x00000002 },
36795584Sanholt	{ 0x00098000, 0x00000002 },
36895584Sanholt	{ 0x00061000, 0x00000002 },
36995584Sanholt	{ 0x64c0603e, 0x00000004 },
37095584Sanholt	{ 0x000380e6, 0x00000002 },
37195584Sanholt	{ 0x040025c5, 0x00000002 },
37295584Sanholt	{ 0x00080000, 0x00000016 },
37395584Sanholt	{ 0000000000, 0000000000 },
37495584Sanholt	{ 0x0400251d, 0x00000002 },
37595584Sanholt	{ 0x00007580, 0x00000002 },
37695584Sanholt	{ 0x00067581, 0x00000002 },
37795584Sanholt	{ 0x04002580, 0x00000002 },
37895584Sanholt	{ 0x00067581, 0x00000002 },
37995584Sanholt	{ 0x00000049, 0x00000004 },
38095584Sanholt	{ 0x00005000, 0000000000 },
38195584Sanholt	{ 0x000380e6, 0x00000002 },
38295584Sanholt	{ 0x040025c5, 0x00000002 },
38395584Sanholt	{ 0x00061000, 0x00000002 },
38495584Sanholt	{ 0x0000750e, 0x00000002 },
38595584Sanholt	{ 0x00019000, 0x00000002 },
38695584Sanholt	{ 0x00011055, 0x00000014 },
38795584Sanholt	{ 0x00000055, 0x00000012 },
38895584Sanholt	{ 0x0400250f, 0x00000002 },
38995584Sanholt	{ 0x0000504f, 0x00000004 },
39095584Sanholt	{ 0x000380e6, 0x00000002 },
39195584Sanholt	{ 0x040025c5, 0x00000002 },
39295584Sanholt	{ 0x00007565, 0x00000002 },
39395584Sanholt	{ 0x00007566, 0x00000002 },
39495584Sanholt	{ 0x00000058, 0x00000004 },
39595584Sanholt	{ 0x000380e6, 0x00000002 },
39695584Sanholt	{ 0x040025c5, 0x00000002 },
39795584Sanholt	{ 0x01e655b4, 0x00000002 },
39895584Sanholt	{ 0x4401b0e4, 0x00000002 },
39995584Sanholt	{ 0x01c110e4, 0x00000002 },
40095584Sanholt	{ 0x26667066, 0x00000018 },
40195584Sanholt	{ 0x040c2565, 0x00000002 },
40295584Sanholt	{ 0x00000066, 0x00000018 },
40395584Sanholt	{ 0x04002564, 0x00000002 },
40495584Sanholt	{ 0x00007566, 0x00000002 },
40595584Sanholt	{ 0x0000005d, 0x00000004 },
40695584Sanholt	{ 0x00401069, 0x00000008 },
40795584Sanholt	{ 0x00101000, 0x00000002 },
40895584Sanholt	{ 0x000d80ff, 0x00000002 },
40995584Sanholt	{ 0x0080006c, 0x00000008 },
41095584Sanholt	{ 0x000f9000, 0x00000002 },
41195584Sanholt	{ 0x000e00ff, 0x00000002 },
41295584Sanholt	{ 0000000000, 0x00000006 },
41395584Sanholt	{ 0x0000008f, 0x00000018 },
41495584Sanholt	{ 0x0000005b, 0x00000004 },
41595584Sanholt	{ 0x000380e6, 0x00000002 },
41695584Sanholt	{ 0x040025c5, 0x00000002 },
41795584Sanholt	{ 0x00007576, 0x00000002 },
41895584Sanholt	{ 0x00065000, 0x00000002 },
41995584Sanholt	{ 0x00009000, 0x00000002 },
42095584Sanholt	{ 0x00041000, 0x00000002 },
42195584Sanholt	{ 0x0c00350e, 0x00000002 },
42295584Sanholt	{ 0x00049000, 0x00000002 },
42395584Sanholt	{ 0x00051000, 0x00000002 },
42495584Sanholt	{ 0x01e785f8, 0x00000002 },
42595584Sanholt	{ 0x00200000, 0x00000002 },
42695584Sanholt	{ 0x0060007e, 0x0000000c },
42795584Sanholt	{ 0x00007563, 0x00000002 },
42895584Sanholt	{ 0x006075f0, 0x00000021 },
42995584Sanholt	{ 0x20007073, 0x00000004 },
43095584Sanholt	{ 0x00005073, 0x00000004 },
43195584Sanholt	{ 0x000380e6, 0x00000002 },
43295584Sanholt	{ 0x040025c5, 0x00000002 },
43395584Sanholt	{ 0x00007576, 0x00000002 },
43495584Sanholt	{ 0x00007577, 0x00000002 },
43595584Sanholt	{ 0x0000750e, 0x00000002 },
43695584Sanholt	{ 0x0000750f, 0x00000002 },
43795584Sanholt	{ 0x00a05000, 0x00000002 },
43895584Sanholt	{ 0x00600083, 0x0000000c },
43995584Sanholt	{ 0x006075f0, 0x00000021 },
44095584Sanholt	{ 0x000075f8, 0x00000002 },
44195584Sanholt	{ 0x00000083, 0x00000004 },
44295584Sanholt	{ 0x000a750e, 0x00000002 },
44395584Sanholt	{ 0x000380e6, 0x00000002 },
44495584Sanholt	{ 0x040025c5, 0x00000002 },
44595584Sanholt	{ 0x0020750f, 0x00000002 },
44695584Sanholt	{ 0x00600086, 0x00000004 },
44795584Sanholt	{ 0x00007570, 0x00000002 },
44895584Sanholt	{ 0x00007571, 0x00000002 },
44995584Sanholt	{ 0x00007572, 0x00000006 },
45095584Sanholt	{ 0x000380e6, 0x00000002 },
45195584Sanholt	{ 0x040025c5, 0x00000002 },
45295584Sanholt	{ 0x00005000, 0x00000002 },
45395584Sanholt	{ 0x00a05000, 0x00000002 },
45495584Sanholt	{ 0x00007568, 0x00000002 },
45595584Sanholt	{ 0x00061000, 0x00000002 },
45695584Sanholt	{ 0x00000095, 0x0000000c },
45795584Sanholt	{ 0x00058000, 0x00000002 },
45895584Sanholt	{ 0x0c607562, 0x00000002 },
45995584Sanholt	{ 0x00000097, 0x00000004 },
46095584Sanholt	{ 0x000380e6, 0x00000002 },
46195584Sanholt	{ 0x040025c5, 0x00000002 },
46295584Sanholt	{ 0x00600096, 0x00000004 },
46395584Sanholt	{ 0x400070e5, 0000000000 },
46495584Sanholt	{ 0x000380e6, 0x00000002 },
46595584Sanholt	{ 0x040025c5, 0x00000002 },
46695584Sanholt	{ 0x000380e5, 0x00000002 },
46795584Sanholt	{ 0x000000a8, 0x0000001c },
46895584Sanholt	{ 0x000650aa, 0x00000018 },
46995584Sanholt	{ 0x040025bb, 0x00000002 },
47095584Sanholt	{ 0x000610ab, 0x00000018 },
47195584Sanholt	{ 0x040075bc, 0000000000 },
47295584Sanholt	{ 0x000075bb, 0x00000002 },
47395584Sanholt	{ 0x000075bc, 0000000000 },
47495584Sanholt	{ 0x00090000, 0x00000006 },
47595584Sanholt	{ 0x00090000, 0x00000002 },
47695584Sanholt	{ 0x000d8002, 0x00000006 },
47795584Sanholt	{ 0x00007832, 0x00000002 },
47895584Sanholt	{ 0x00005000, 0x00000002 },
47995584Sanholt	{ 0x000380e7, 0x00000002 },
48095584Sanholt	{ 0x04002c97, 0x00000002 },
48195584Sanholt	{ 0x00007820, 0x00000002 },
48295584Sanholt	{ 0x00007821, 0x00000002 },
48395584Sanholt	{ 0x00007800, 0000000000 },
48495584Sanholt	{ 0x01200000, 0x00000002 },
48595584Sanholt	{ 0x20077000, 0x00000002 },
48695584Sanholt	{ 0x01200000, 0x00000002 },
48795584Sanholt	{ 0x20007000, 0x00000002 },
48895584Sanholt	{ 0x00061000, 0x00000002 },
48995584Sanholt	{ 0x0120751b, 0x00000002 },
49095584Sanholt	{ 0x8040750a, 0x00000002 },
49195584Sanholt	{ 0x8040750b, 0x00000002 },
49295584Sanholt	{ 0x00110000, 0x00000002 },
49395584Sanholt	{ 0x000380e5, 0x00000002 },
49495584Sanholt	{ 0x000000c6, 0x0000001c },
49595584Sanholt	{ 0x000610ab, 0x00000018 },
49695584Sanholt	{ 0x844075bd, 0x00000002 },
49795584Sanholt	{ 0x000610aa, 0x00000018 },
49895584Sanholt	{ 0x840075bb, 0x00000002 },
49995584Sanholt	{ 0x000610ab, 0x00000018 },
50095584Sanholt	{ 0x844075bc, 0x00000002 },
50195584Sanholt	{ 0x000000c9, 0x00000004 },
50295584Sanholt	{ 0x804075bd, 0x00000002 },
50395584Sanholt	{ 0x800075bb, 0x00000002 },
50495584Sanholt	{ 0x804075bc, 0x00000002 },
50595584Sanholt	{ 0x00108000, 0x00000002 },
50695584Sanholt	{ 0x01400000, 0x00000002 },
50795584Sanholt	{ 0x006000cd, 0x0000000c },
50895584Sanholt	{ 0x20c07000, 0x00000020 },
50995584Sanholt	{ 0x000000cf, 0x00000012 },
51095584Sanholt	{ 0x00800000, 0x00000006 },
51195584Sanholt	{ 0x0080751d, 0x00000006 },
51295584Sanholt	{ 0000000000, 0000000000 },
51395584Sanholt	{ 0x0000775c, 0x00000002 },
51495584Sanholt	{ 0x00a05000, 0x00000002 },
51595584Sanholt	{ 0x00661000, 0x00000002 },
51695584Sanholt	{ 0x0460275d, 0x00000020 },
51795584Sanholt	{ 0x00004000, 0000000000 },
51895584Sanholt	{ 0x01e00830, 0x00000002 },
51995584Sanholt	{ 0x21007000, 0000000000 },
52095584Sanholt	{ 0x6464614d, 0000000000 },
52195584Sanholt	{ 0x69687420, 0000000000 },
52295584Sanholt	{ 0x00000073, 0000000000 },
52395584Sanholt	{ 0000000000, 0000000000 },
52495584Sanholt	{ 0x00005000, 0x00000002 },
52595584Sanholt	{ 0x000380d0, 0x00000002 },
52695584Sanholt	{ 0x040025e0, 0x00000002 },
52795584Sanholt	{ 0x000075e1, 0000000000 },
52895584Sanholt	{ 0x00000001, 0000000000 },
52995584Sanholt	{ 0x000380e0, 0x00000002 },
53095584Sanholt	{ 0x04002394, 0x00000002 },
53195584Sanholt	{ 0x00005000, 0000000000 },
53295584Sanholt	{ 0000000000, 0000000000 },
53395584Sanholt	{ 0000000000, 0000000000 },
53495584Sanholt	{ 0x00000008, 0000000000 },
53595584Sanholt	{ 0x00000004, 0000000000 },
53695584Sanholt	{ 0000000000, 0000000000 },
53795584Sanholt	{ 0000000000, 0000000000 },
53895584Sanholt	{ 0000000000, 0000000000 },
53995584Sanholt	{ 0000000000, 0000000000 },
54095584Sanholt	{ 0000000000, 0000000000 },
54195584Sanholt	{ 0000000000, 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};
56195584Sanholt
56295584Sanholt
56395584Sanholtint RADEON_READ_PLL(drm_device_t *dev, int addr)
56495584Sanholt{
56595584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
56695584Sanholt
56795584Sanholt	RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
56895584Sanholt	return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
56995584Sanholt}
57095584Sanholt
57195584Sanholt#if RADEON_FIFO_DEBUG
57295584Sanholtstatic void radeon_status( drm_radeon_private_t *dev_priv )
57395584Sanholt{
574112015Sanholt	printk( "%s:\n", __FUNCTION__ );
57595584Sanholt	printk( "RBBM_STATUS = 0x%08x\n",
57695584Sanholt		(unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) );
57795584Sanholt	printk( "CP_RB_RTPR = 0x%08x\n",
57895584Sanholt		(unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
57995584Sanholt	printk( "CP_RB_WTPR = 0x%08x\n",
58095584Sanholt		(unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
58195584Sanholt	printk( "AIC_CNTL = 0x%08x\n",
58295584Sanholt		(unsigned int)RADEON_READ( RADEON_AIC_CNTL ) );
58395584Sanholt	printk( "AIC_STAT = 0x%08x\n",
58495584Sanholt		(unsigned int)RADEON_READ( RADEON_AIC_STAT ) );
58595584Sanholt	printk( "AIC_PT_BASE = 0x%08x\n",
58695584Sanholt		(unsigned int)RADEON_READ( RADEON_AIC_PT_BASE ) );
58795584Sanholt	printk( "TLB_ADDR = 0x%08x\n",
58895584Sanholt		(unsigned int)RADEON_READ( RADEON_AIC_TLB_ADDR ) );
58995584Sanholt	printk( "TLB_DATA = 0x%08x\n",
59095584Sanholt		(unsigned int)RADEON_READ( RADEON_AIC_TLB_DATA ) );
59195584Sanholt}
59295584Sanholt#endif
59395584Sanholt
59495584Sanholt
59595584Sanholt/* ================================================================
59695584Sanholt * Engine, FIFO control
59795584Sanholt */
59895584Sanholt
59995584Sanholtstatic int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv )
60095584Sanholt{
60195584Sanholt	u32 tmp;
60295584Sanholt	int i;
60395584Sanholt
604112015Sanholt	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
605112015Sanholt
60695584Sanholt	tmp  = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
60795584Sanholt	tmp |= RADEON_RB2D_DC_FLUSH_ALL;
60895584Sanholt	RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
60995584Sanholt
61095584Sanholt	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
61195584Sanholt		if ( !(RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT )
61295584Sanholt		       & RADEON_RB2D_DC_BUSY) ) {
61395584Sanholt			return 0;
61495584Sanholt		}
615112015Sanholt		DRM_UDELAY( 1 );
61695584Sanholt	}
61795584Sanholt
61895584Sanholt#if RADEON_FIFO_DEBUG
61995584Sanholt	DRM_ERROR( "failed!\n" );
62095584Sanholt	radeon_status( dev_priv );
62195584Sanholt#endif
622112015Sanholt	return DRM_ERR(EBUSY);
62395584Sanholt}
62495584Sanholt
62595584Sanholtstatic int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
62695584Sanholt				    int entries )
62795584Sanholt{
62895584Sanholt	int i;
62995584Sanholt
630112015Sanholt	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
631112015Sanholt
63295584Sanholt	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
63395584Sanholt		int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
63495584Sanholt			      & RADEON_RBBM_FIFOCNT_MASK );
63595584Sanholt		if ( slots >= entries ) return 0;
636112015Sanholt		DRM_UDELAY( 1 );
63795584Sanholt	}
63895584Sanholt
63995584Sanholt#if RADEON_FIFO_DEBUG
64095584Sanholt	DRM_ERROR( "failed!\n" );
64195584Sanholt	radeon_status( dev_priv );
64295584Sanholt#endif
643112015Sanholt	return DRM_ERR(EBUSY);
64495584Sanholt}
64595584Sanholt
64695584Sanholtstatic int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
64795584Sanholt{
64895584Sanholt	int i, ret;
64995584Sanholt
650112015Sanholt	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
651112015Sanholt
65295584Sanholt	ret = radeon_do_wait_for_fifo( dev_priv, 64 );
65395584Sanholt	if ( ret ) return ret;
654112015Sanholt
65595584Sanholt	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
65695584Sanholt		if ( !(RADEON_READ( RADEON_RBBM_STATUS )
65795584Sanholt		       & RADEON_RBBM_ACTIVE) ) {
65895584Sanholt			radeon_do_pixcache_flush( dev_priv );
65995584Sanholt			return 0;
66095584Sanholt		}
661112015Sanholt		DRM_UDELAY( 1 );
66295584Sanholt	}
66395584Sanholt
66495584Sanholt#if RADEON_FIFO_DEBUG
66595584Sanholt	DRM_ERROR( "failed!\n" );
66695584Sanholt	radeon_status( dev_priv );
66795584Sanholt#endif
668112015Sanholt	return DRM_ERR(EBUSY);
66995584Sanholt}
67095584Sanholt
67195584Sanholt
67295584Sanholt/* ================================================================
67395584Sanholt * CP control, initialization
67495584Sanholt */
67595584Sanholt
67695584Sanholt/* Load the microcode for the CP */
67795584Sanholtstatic void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
67895584Sanholt{
67995584Sanholt	int i;
680112015Sanholt	DRM_DEBUG( "\n" );
68195584Sanholt
68295584Sanholt	radeon_do_wait_for_idle( dev_priv );
68395584Sanholt
68495584Sanholt	RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 );
685112015Sanholt
686112015Sanholt	if (dev_priv->is_r200)
687112015Sanholt	{
688112015Sanholt		DRM_INFO("Loading R200 Microcode\n");
689112015Sanholt		for ( i = 0 ; i < 256 ; i++ )
690112015Sanholt		{
691112015Sanholt			RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
692112015Sanholt				      R200_cp_microcode[i][1] );
693112015Sanholt			RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
694112015Sanholt				      R200_cp_microcode[i][0] );
695112015Sanholt		}
69695584Sanholt	}
697112015Sanholt	else
698112015Sanholt	{
699112015Sanholt		for ( i = 0 ; i < 256 ; i++ ) {
700112015Sanholt			RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
701112015Sanholt				      radeon_cp_microcode[i][1] );
702112015Sanholt			RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
703112015Sanholt				      radeon_cp_microcode[i][0] );
704112015Sanholt		}
705112015Sanholt	}
70695584Sanholt}
70795584Sanholt
70895584Sanholt/* Flush any pending commands to the CP.  This should only be used just
70995584Sanholt * prior to a wait for idle, as it informs the engine that the command
71095584Sanholt * stream is ending.
71195584Sanholt */
71295584Sanholtstatic void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
71395584Sanholt{
714112015Sanholt	DRM_DEBUG( "\n" );
71595584Sanholt#if 0
71695584Sanholt	u32 tmp;
71795584Sanholt
71895584Sanholt	tmp = RADEON_READ( RADEON_CP_RB_WPTR ) | (1 << 31);
71995584Sanholt	RADEON_WRITE( RADEON_CP_RB_WPTR, tmp );
72095584Sanholt#endif
72195584Sanholt}
72295584Sanholt
72395584Sanholt/* Wait for the CP to go idle.
72495584Sanholt */
72595584Sanholtint radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
72695584Sanholt{
72795584Sanholt	RING_LOCALS;
728112015Sanholt	DRM_DEBUG( "\n" );
72995584Sanholt
73095584Sanholt	BEGIN_RING( 6 );
73195584Sanholt
73295584Sanholt	RADEON_PURGE_CACHE();
73395584Sanholt	RADEON_PURGE_ZCACHE();
73495584Sanholt	RADEON_WAIT_UNTIL_IDLE();
73595584Sanholt
73695584Sanholt	ADVANCE_RING();
737112015Sanholt	COMMIT_RING();
73895584Sanholt
73995584Sanholt	return radeon_do_wait_for_idle( dev_priv );
74095584Sanholt}
74195584Sanholt
74295584Sanholt/* Start the Command Processor.
74395584Sanholt */
74495584Sanholtstatic void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
74595584Sanholt{
74695584Sanholt	RING_LOCALS;
747112015Sanholt	DRM_DEBUG( "\n" );
74895584Sanholt
74995584Sanholt	radeon_do_wait_for_idle( dev_priv );
75095584Sanholt
75195584Sanholt	RADEON_WRITE( RADEON_CP_CSQ_CNTL, dev_priv->cp_mode );
75295584Sanholt
75395584Sanholt	dev_priv->cp_running = 1;
75495584Sanholt
75595584Sanholt	BEGIN_RING( 6 );
75695584Sanholt
75795584Sanholt	RADEON_PURGE_CACHE();
75895584Sanholt	RADEON_PURGE_ZCACHE();
75995584Sanholt	RADEON_WAIT_UNTIL_IDLE();
76095584Sanholt
76195584Sanholt	ADVANCE_RING();
762112015Sanholt	COMMIT_RING();
76395584Sanholt}
76495584Sanholt
76595584Sanholt/* Reset the Command Processor.  This will not flush any pending
76695584Sanholt * commands, so you must wait for the CP command stream to complete
76795584Sanholt * before calling this routine.
76895584Sanholt */
76995584Sanholtstatic void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
77095584Sanholt{
77195584Sanholt	u32 cur_read_ptr;
772112015Sanholt	DRM_DEBUG( "\n" );
77395584Sanholt
77495584Sanholt	cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
77595584Sanholt	RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
776113995Sanholt	SET_RING_HEAD( dev_priv, cur_read_ptr );
77795584Sanholt	dev_priv->ring.tail = cur_read_ptr;
77895584Sanholt}
77995584Sanholt
78095584Sanholt/* Stop the Command Processor.  This will not flush any pending
78195584Sanholt * commands, so you must flush the command stream and wait for the CP
78295584Sanholt * to go idle before calling this routine.
78395584Sanholt */
78495584Sanholtstatic void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
78595584Sanholt{
786112015Sanholt	DRM_DEBUG( "\n" );
78795584Sanholt
78895584Sanholt	RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
78995584Sanholt
79095584Sanholt	dev_priv->cp_running = 0;
79195584Sanholt}
79295584Sanholt
79395584Sanholt/* Reset the engine.  This will stop the CP if it is running.
79495584Sanholt */
79595584Sanholtstatic int radeon_do_engine_reset( drm_device_t *dev )
79695584Sanholt{
79795584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
79895584Sanholt	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
799112015Sanholt	DRM_DEBUG( "\n" );
80095584Sanholt
80195584Sanholt	radeon_do_pixcache_flush( dev_priv );
80295584Sanholt
80395584Sanholt	clock_cntl_index = RADEON_READ( RADEON_CLOCK_CNTL_INDEX );
80495584Sanholt	mclk_cntl = RADEON_READ_PLL( dev, RADEON_MCLK_CNTL );
80595584Sanholt
80695584Sanholt	RADEON_WRITE_PLL( RADEON_MCLK_CNTL, ( mclk_cntl |
80795584Sanholt					      RADEON_FORCEON_MCLKA |
80895584Sanholt					      RADEON_FORCEON_MCLKB |
80995584Sanholt 					      RADEON_FORCEON_YCLKA |
81095584Sanholt					      RADEON_FORCEON_YCLKB |
81195584Sanholt					      RADEON_FORCEON_MC |
81295584Sanholt					      RADEON_FORCEON_AIC ) );
81395584Sanholt
81495584Sanholt	rbbm_soft_reset = RADEON_READ( RADEON_RBBM_SOFT_RESET );
81595584Sanholt
81695584Sanholt	RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset |
81795584Sanholt						RADEON_SOFT_RESET_CP |
81895584Sanholt						RADEON_SOFT_RESET_HI |
81995584Sanholt						RADEON_SOFT_RESET_SE |
82095584Sanholt						RADEON_SOFT_RESET_RE |
82195584Sanholt						RADEON_SOFT_RESET_PP |
82295584Sanholt						RADEON_SOFT_RESET_E2 |
82395584Sanholt						RADEON_SOFT_RESET_RB ) );
82495584Sanholt	RADEON_READ( RADEON_RBBM_SOFT_RESET );
82595584Sanholt	RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset &
82695584Sanholt						~( RADEON_SOFT_RESET_CP |
82795584Sanholt						   RADEON_SOFT_RESET_HI |
82895584Sanholt						   RADEON_SOFT_RESET_SE |
82995584Sanholt						   RADEON_SOFT_RESET_RE |
83095584Sanholt						   RADEON_SOFT_RESET_PP |
83195584Sanholt						   RADEON_SOFT_RESET_E2 |
83295584Sanholt						   RADEON_SOFT_RESET_RB ) ) );
83395584Sanholt	RADEON_READ( RADEON_RBBM_SOFT_RESET );
83495584Sanholt
83595584Sanholt
83695584Sanholt	RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl );
83795584Sanholt	RADEON_WRITE( RADEON_CLOCK_CNTL_INDEX, clock_cntl_index );
83895584Sanholt	RADEON_WRITE( RADEON_RBBM_SOFT_RESET,  rbbm_soft_reset );
83995584Sanholt
84095584Sanholt	/* Reset the CP ring */
84195584Sanholt	radeon_do_cp_reset( dev_priv );
84295584Sanholt
84395584Sanholt	/* The CP is no longer running after an engine reset */
84495584Sanholt	dev_priv->cp_running = 0;
84595584Sanholt
84695584Sanholt	/* Reset any pending vertex, indirect buffers */
84795584Sanholt	radeon_freelist_reset( dev );
84895584Sanholt
84995584Sanholt	return 0;
85095584Sanholt}
85195584Sanholt
85295584Sanholtstatic void radeon_cp_init_ring_buffer( drm_device_t *dev,
85395584Sanholt				        drm_radeon_private_t *dev_priv )
85495584Sanholt{
85595584Sanholt	u32 ring_start, cur_read_ptr;
85695584Sanholt	u32 tmp;
85795584Sanholt
85895584Sanholt	/* Initialize the memory controller */
85995584Sanholt	RADEON_WRITE( RADEON_MC_FB_LOCATION,
860119895Sanholt		      (dev_priv->gart_vm_start - 1) & 0xffff0000 );
86195584Sanholt
862119895Sanholt#if __REALLY_HAVE_AGP
86395584Sanholt	if ( !dev_priv->is_pci ) {
86495584Sanholt		RADEON_WRITE( RADEON_MC_AGP_LOCATION,
865119895Sanholt			      (((dev_priv->gart_vm_start - 1 +
866119895Sanholt				 dev_priv->gart_size) & 0xffff0000) |
867119895Sanholt			       (dev_priv->gart_vm_start >> 16)) );
86895584Sanholt
86995584Sanholt		ring_start = (dev_priv->cp_ring->offset
87095584Sanholt			      - dev->agp->base
871119895Sanholt			      + dev_priv->gart_vm_start);
872119895Sanholt       } else
87395584Sanholt#endif
87495584Sanholt		ring_start = (dev_priv->cp_ring->offset
87595584Sanholt			      - dev->sg->handle
876119895Sanholt			      + dev_priv->gart_vm_start);
87795584Sanholt
87895584Sanholt	RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
87995584Sanholt
88095584Sanholt	/* Set the write pointer delay */
88195584Sanholt	RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 );
88295584Sanholt
88395584Sanholt	/* Initialize the ring buffer's read and write pointers */
88495584Sanholt	cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
88595584Sanholt	RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
886113995Sanholt	SET_RING_HEAD( dev_priv, cur_read_ptr );
88795584Sanholt	dev_priv->ring.tail = cur_read_ptr;
88895584Sanholt
889113995Sanholt#if __REALLY_HAVE_AGP
89095584Sanholt	if ( !dev_priv->is_pci ) {
89195584Sanholt		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
892113995Sanholt			      dev_priv->ring_rptr->offset
893113995Sanholt			      - dev->agp->base
894119895Sanholt			      + dev_priv->gart_vm_start);
895113995Sanholt	} else
896113995Sanholt#endif
897113995Sanholt	{
89895584Sanholt		drm_sg_mem_t *entry = dev->sg;
89995584Sanholt		unsigned long tmp_ofs, page_ofs;
90095584Sanholt
90195584Sanholt		tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
90295584Sanholt		page_ofs = tmp_ofs >> PAGE_SHIFT;
90395584Sanholt
90495584Sanholt		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
90595584Sanholt			     entry->busaddr[page_ofs]);
906113995Sanholt		DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
907119098Sanholt			   (unsigned long) entry->busaddr[page_ofs],
90895584Sanholt			   entry->handle + tmp_ofs );
90995584Sanholt	}
91095584Sanholt
911112015Sanholt	/* Initialize the scratch register pointer.  This will cause
912112015Sanholt	 * the scratch register values to be written out to memory
913112015Sanholt	 * whenever they are updated.
914112015Sanholt	 *
915112015Sanholt	 * We simply put this behind the ring read pointer, this works
916112015Sanholt	 * with PCI GART as well as (whatever kind of) AGP GART
917112015Sanholt	 */
918112015Sanholt	RADEON_WRITE( RADEON_SCRATCH_ADDR, RADEON_READ( RADEON_CP_RB_RPTR_ADDR )
919112015Sanholt					 + RADEON_SCRATCH_REG_OFFSET );
920112015Sanholt
921112015Sanholt	dev_priv->scratch = ((__volatile__ u32 *)
922113995Sanholt			     dev_priv->ring_rptr->handle +
923112015Sanholt			     (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
924112015Sanholt
925112015Sanholt	RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
926112015Sanholt
927112015Sanholt	/* Writeback doesn't seem to work everywhere, test it first */
928112015Sanholt	DRM_WRITE32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0 );
929112015Sanholt	RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
930112015Sanholt
931112015Sanholt	for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
932112015Sanholt		if ( DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1) ) == 0xdeadbeef )
933112015Sanholt			break;
934112015Sanholt		DRM_UDELAY( 1 );
935112015Sanholt	}
936112015Sanholt
937112015Sanholt	if ( tmp < dev_priv->usec_timeout ) {
938112015Sanholt		dev_priv->writeback_works = 1;
939112015Sanholt		DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
940112015Sanholt	} else {
941112015Sanholt		dev_priv->writeback_works = 0;
942112015Sanholt		DRM_DEBUG( "writeback test failed\n" );
943112015Sanholt	}
944112015Sanholt
945112015Sanholt	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
946112015Sanholt	RADEON_WRITE( RADEON_LAST_FRAME_REG,
947112015Sanholt		      dev_priv->sarea_priv->last_frame );
948112015Sanholt
949112015Sanholt	dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
950112015Sanholt	RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
951112015Sanholt		      dev_priv->sarea_priv->last_dispatch );
952112015Sanholt
953112015Sanholt	dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
954112015Sanholt	RADEON_WRITE( RADEON_LAST_CLEAR_REG,
955112015Sanholt		      dev_priv->sarea_priv->last_clear );
956112015Sanholt
95795584Sanholt	/* Set ring buffer size */
958112015Sanholt#ifdef __BIG_ENDIAN
959112015Sanholt	RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT );
960112015Sanholt#else
96195584Sanholt	RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
962112015Sanholt#endif
96395584Sanholt
96495584Sanholt	radeon_do_wait_for_idle( dev_priv );
96595584Sanholt
96695584Sanholt	/* Turn on bus mastering */
96795584Sanholt	tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
96895584Sanholt	RADEON_WRITE( RADEON_BUS_CNTL, tmp );
96995584Sanholt
97095584Sanholt	/* Sync everything up */
97195584Sanholt	RADEON_WRITE( RADEON_ISYNC_CNTL,
97295584Sanholt		      (RADEON_ISYNC_ANY2D_IDLE3D |
97395584Sanholt		       RADEON_ISYNC_ANY3D_IDLE2D |
97495584Sanholt		       RADEON_ISYNC_WAIT_IDLEGUI |
97595584Sanholt		       RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
97695584Sanholt}
97795584Sanholt
978119098Sanholt/* Enable or disable PCI GART on the chip */
979119098Sanholtstatic void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on )
980119098Sanholt{
981119098Sanholt	u32 tmp	= RADEON_READ( RADEON_AIC_CNTL );
982119098Sanholt
983119098Sanholt	if ( on ) {
984119098Sanholt		RADEON_WRITE( RADEON_AIC_CNTL, tmp | RADEON_PCIGART_TRANSLATE_EN );
985119098Sanholt
986119098Sanholt		/* set PCI GART page-table base address
987119098Sanholt		 */
988119098Sanholt		RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );
989119098Sanholt
990119098Sanholt		/* set address range for PCI address translate
991119098Sanholt		 */
992119895Sanholt		RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start );
993119895Sanholt		RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
994119895Sanholt						  + dev_priv->gart_size - 1);
995119098Sanholt
996119895Sanholt		/* Turn off AGP aperture -- is this required for PCI GART?
997119098Sanholt		 */
998119098Sanholt		RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
999119098Sanholt		RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
1000119098Sanholt	} else {
1001119098Sanholt		RADEON_WRITE( RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN );
1002119098Sanholt	}
1003119098Sanholt}
1004119098Sanholt
100595584Sanholtstatic int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
100695584Sanholt{
100795584Sanholt	drm_radeon_private_t *dev_priv;
1008112015Sanholt	DRM_DEBUG( "\n" );
100995584Sanholt
101095584Sanholt	dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
101195584Sanholt	if ( dev_priv == NULL )
1012112015Sanholt		return DRM_ERR(ENOMEM);
101395584Sanholt
101495584Sanholt	memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
101595584Sanholt
101695584Sanholt	dev_priv->is_pci = init->is_pci;
101795584Sanholt
101895584Sanholt	if ( dev_priv->is_pci && !dev->sg ) {
101995584Sanholt		DRM_ERROR( "PCI GART memory not allocated!\n" );
102095584Sanholt		dev->dev_private = (void *)dev_priv;
102195584Sanholt		radeon_do_cleanup_cp(dev);
1022112015Sanholt		return DRM_ERR(EINVAL);
102395584Sanholt	}
102495584Sanholt
102595584Sanholt	dev_priv->usec_timeout = init->usec_timeout;
102695584Sanholt	if ( dev_priv->usec_timeout < 1 ||
102795584Sanholt	     dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
102895584Sanholt		DRM_DEBUG( "TIMEOUT problem!\n" );
102995584Sanholt		dev->dev_private = (void *)dev_priv;
103095584Sanholt		radeon_do_cleanup_cp(dev);
1031112015Sanholt		return DRM_ERR(EINVAL);
103295584Sanholt	}
103395584Sanholt
1034112015Sanholt	dev_priv->is_r200 = (init->func == RADEON_INIT_R200_CP);
1035112015Sanholt	dev_priv->do_boxes = 0;
103695584Sanholt	dev_priv->cp_mode = init->cp_mode;
103795584Sanholt
103895584Sanholt	/* We don't support anything other than bus-mastering ring mode,
103995584Sanholt	 * but the ring can be in either AGP or PCI space for the ring
104095584Sanholt	 * read pointer.
104195584Sanholt	 */
104295584Sanholt	if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
104395584Sanholt	     ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
104495584Sanholt		DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
104595584Sanholt		dev->dev_private = (void *)dev_priv;
104695584Sanholt		radeon_do_cleanup_cp(dev);
1047112015Sanholt		return DRM_ERR(EINVAL);
104895584Sanholt	}
104995584Sanholt
105095584Sanholt	switch ( init->fb_bpp ) {
105195584Sanholt	case 16:
105295584Sanholt		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
105395584Sanholt		break;
105495584Sanholt	case 32:
105595584Sanholt	default:
105695584Sanholt		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
105795584Sanholt		break;
105895584Sanholt	}
105995584Sanholt	dev_priv->front_offset	= init->front_offset;
106095584Sanholt	dev_priv->front_pitch	= init->front_pitch;
106195584Sanholt	dev_priv->back_offset	= init->back_offset;
106295584Sanholt	dev_priv->back_pitch	= init->back_pitch;
106395584Sanholt
106495584Sanholt	switch ( init->depth_bpp ) {
106595584Sanholt	case 16:
106695584Sanholt		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
106795584Sanholt		break;
106895584Sanholt	case 32:
106995584Sanholt	default:
107095584Sanholt		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
107195584Sanholt		break;
107295584Sanholt	}
107395584Sanholt	dev_priv->depth_offset	= init->depth_offset;
107495584Sanholt	dev_priv->depth_pitch	= init->depth_pitch;
107595584Sanholt
107695584Sanholt	dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
107795584Sanholt					(dev_priv->front_offset >> 10));
107895584Sanholt	dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
107995584Sanholt				       (dev_priv->back_offset >> 10));
108095584Sanholt	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
108195584Sanholt					(dev_priv->depth_offset >> 10));
108295584Sanholt
108395584Sanholt	/* Hardware state for depth clears.  Remove this if/when we no
108495584Sanholt	 * longer clear the depth buffer with a 3D rectangle.  Hard-code
108595584Sanholt	 * all values to prevent unwanted 3D state from slipping through
108695584Sanholt	 * and screwing with the clear operation.
108795584Sanholt	 */
108895584Sanholt	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
108995584Sanholt					   (dev_priv->color_fmt << 10) |
1090112015Sanholt					   (1<<15));
109195584Sanholt
1092112015Sanholt	dev_priv->depth_clear.rb3d_zstencilcntl =
1093112015Sanholt		(dev_priv->depth_fmt |
1094112015Sanholt		 RADEON_Z_TEST_ALWAYS |
1095112015Sanholt		 RADEON_STENCIL_TEST_ALWAYS |
1096112015Sanholt		 RADEON_STENCIL_S_FAIL_REPLACE |
1097112015Sanholt		 RADEON_STENCIL_ZPASS_REPLACE |
1098112015Sanholt		 RADEON_STENCIL_ZFAIL_REPLACE |
1099112015Sanholt		 RADEON_Z_WRITE_ENABLE);
110095584Sanholt
110195584Sanholt	dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
110295584Sanholt					 RADEON_BFACE_SOLID |
110395584Sanholt					 RADEON_FFACE_SOLID |
110495584Sanholt					 RADEON_FLAT_SHADE_VTX_LAST |
110595584Sanholt					 RADEON_DIFFUSE_SHADE_FLAT |
110695584Sanholt					 RADEON_ALPHA_SHADE_FLAT |
110795584Sanholt					 RADEON_SPECULAR_SHADE_FLAT |
110895584Sanholt					 RADEON_FOG_SHADE_FLAT |
110995584Sanholt					 RADEON_VTX_PIX_CENTER_OGL |
111095584Sanholt					 RADEON_ROUND_MODE_TRUNC |
111195584Sanholt					 RADEON_ROUND_PREC_8TH_PIX);
111295584Sanholt
1113112015Sanholt	DRM_GETSAREA();
1114113995Sanholt
1115113995Sanholt	dev_priv->fb_offset = init->fb_offset;
1116113995Sanholt	dev_priv->mmio_offset = init->mmio_offset;
1117113995Sanholt	dev_priv->ring_offset = init->ring_offset;
1118113995Sanholt	dev_priv->ring_rptr_offset = init->ring_rptr_offset;
1119113995Sanholt	dev_priv->buffers_offset = init->buffers_offset;
1120119895Sanholt	dev_priv->gart_textures_offset = init->gart_textures_offset;
1121112015Sanholt
112295584Sanholt	if(!dev_priv->sarea) {
112395584Sanholt		DRM_ERROR("could not find sarea!\n");
112495584Sanholt		dev->dev_private = (void *)dev_priv;
112595584Sanholt		radeon_do_cleanup_cp(dev);
1126112015Sanholt		return DRM_ERR(EINVAL);
112795584Sanholt	}
112895584Sanholt
112995584Sanholt	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
113095584Sanholt	if(!dev_priv->fb) {
113195584Sanholt		DRM_ERROR("could not find framebuffer!\n");
113295584Sanholt		dev->dev_private = (void *)dev_priv;
113395584Sanholt		radeon_do_cleanup_cp(dev);
1134112015Sanholt		return DRM_ERR(EINVAL);
113595584Sanholt	}
113695584Sanholt	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
113795584Sanholt	if(!dev_priv->mmio) {
113895584Sanholt		DRM_ERROR("could not find mmio region!\n");
113995584Sanholt		dev->dev_private = (void *)dev_priv;
114095584Sanholt		radeon_do_cleanup_cp(dev);
1141112015Sanholt		return DRM_ERR(EINVAL);
114295584Sanholt	}
114395584Sanholt	DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
114495584Sanholt	if(!dev_priv->cp_ring) {
114595584Sanholt		DRM_ERROR("could not find cp ring region!\n");
114695584Sanholt		dev->dev_private = (void *)dev_priv;
114795584Sanholt		radeon_do_cleanup_cp(dev);
1148112015Sanholt		return DRM_ERR(EINVAL);
114995584Sanholt	}
115095584Sanholt	DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
115195584Sanholt	if(!dev_priv->ring_rptr) {
115295584Sanholt		DRM_ERROR("could not find ring read pointer!\n");
115395584Sanholt		dev->dev_private = (void *)dev_priv;
115495584Sanholt		radeon_do_cleanup_cp(dev);
1155112015Sanholt		return DRM_ERR(EINVAL);
115695584Sanholt	}
115795584Sanholt	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
115895584Sanholt	if(!dev_priv->buffers) {
115995584Sanholt		DRM_ERROR("could not find dma buffer region!\n");
116095584Sanholt		dev->dev_private = (void *)dev_priv;
116195584Sanholt		radeon_do_cleanup_cp(dev);
1162112015Sanholt		return DRM_ERR(EINVAL);
116395584Sanholt	}
116495584Sanholt
1165119895Sanholt	if ( init->gart_textures_offset ) {
1166119895Sanholt		DRM_FIND_MAP( dev_priv->gart_textures, init->gart_textures_offset );
1167119895Sanholt		if ( !dev_priv->gart_textures ) {
1168119895Sanholt			DRM_ERROR("could not find GART texture region!\n");
116995584Sanholt			dev->dev_private = (void *)dev_priv;
117095584Sanholt			radeon_do_cleanup_cp(dev);
1171112015Sanholt			return DRM_ERR(EINVAL);
117295584Sanholt		}
117395584Sanholt	}
117495584Sanholt
117595584Sanholt	dev_priv->sarea_priv =
117695584Sanholt		(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
117795584Sanholt				       init->sarea_priv_offset);
117895584Sanholt
1179119098Sanholt#if __REALLY_HAVE_AGP
118095584Sanholt	if ( !dev_priv->is_pci ) {
1181119098Sanholt		DRM_IOREMAP( dev_priv->cp_ring, dev );
1182119098Sanholt		DRM_IOREMAP( dev_priv->ring_rptr, dev );
1183119098Sanholt		DRM_IOREMAP( dev_priv->buffers, dev );
118495584Sanholt		if(!dev_priv->cp_ring->handle ||
118595584Sanholt		   !dev_priv->ring_rptr->handle ||
118695584Sanholt		   !dev_priv->buffers->handle) {
118795584Sanholt			DRM_ERROR("could not find ioremap agp regions!\n");
118895584Sanholt			dev->dev_private = (void *)dev_priv;
118995584Sanholt			radeon_do_cleanup_cp(dev);
1190112015Sanholt			return DRM_ERR(EINVAL);
119195584Sanholt		}
1192119098Sanholt	} else
1193119098Sanholt#endif
1194119098Sanholt	{
119595584Sanholt		dev_priv->cp_ring->handle =
119695584Sanholt			(void *)dev_priv->cp_ring->offset;
119795584Sanholt		dev_priv->ring_rptr->handle =
119895584Sanholt			(void *)dev_priv->ring_rptr->offset;
119995584Sanholt		dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
120095584Sanholt
120195584Sanholt		DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
120295584Sanholt			   dev_priv->cp_ring->handle );
120395584Sanholt		DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
120495584Sanholt			   dev_priv->ring_rptr->handle );
120595584Sanholt		DRM_DEBUG( "dev_priv->buffers->handle %p\n",
120695584Sanholt			   dev_priv->buffers->handle );
120795584Sanholt	}
120895584Sanholt
120995584Sanholt
1210119895Sanholt	dev_priv->gart_size = init->gart_size;
1211119895Sanholt	dev_priv->gart_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
121295584Sanholt#if __REALLY_HAVE_AGP
121395584Sanholt	if ( !dev_priv->is_pci )
1214119895Sanholt		dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
121595584Sanholt						- dev->agp->base
1216119895Sanholt						+ dev_priv->gart_vm_start);
121795584Sanholt	else
121895584Sanholt#endif
1219119895Sanholt		dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
122095584Sanholt						- dev->sg->handle
1221119895Sanholt						+ dev_priv->gart_vm_start);
122295584Sanholt
1223119895Sanholt	DRM_DEBUG( "dev_priv->gart_size %d\n",
1224119895Sanholt		   dev_priv->gart_size );
1225119895Sanholt	DRM_DEBUG( "dev_priv->gart_vm_start 0x%x\n",
1226119895Sanholt		   dev_priv->gart_vm_start );
1227119895Sanholt	DRM_DEBUG( "dev_priv->gart_buffers_offset 0x%lx\n",
1228119895Sanholt		   dev_priv->gart_buffers_offset );
122995584Sanholt
123095584Sanholt	dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle;
123195584Sanholt	dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
123295584Sanholt			      + init->ring_size / sizeof(u32));
123395584Sanholt	dev_priv->ring.size = init->ring_size;
123495584Sanholt	dev_priv->ring.size_l2qw = DRM(order)( init->ring_size / 8 );
123595584Sanholt
123695584Sanholt	dev_priv->ring.tail_mask =
123795584Sanholt		(dev_priv->ring.size / sizeof(u32)) - 1;
123895584Sanholt
123995584Sanholt	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
124095584Sanholt
1241119098Sanholt#if __REALLY_HAVE_AGP
1242119098Sanholt	if ( !dev_priv->is_pci ) {
1243119098Sanholt		/* Turn off PCI GART */
1244119098Sanholt		radeon_set_pcigart( dev_priv, 0 );
1245119098Sanholt	} else
1246119098Sanholt#endif
1247119098Sanholt	{
124895584Sanholt		if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
124995584Sanholt					    &dev_priv->bus_pci_gart)) {
125095584Sanholt			DRM_ERROR( "failed to init PCI GART!\n" );
125195584Sanholt			dev->dev_private = (void *)dev_priv;
125295584Sanholt			radeon_do_cleanup_cp(dev);
1253112015Sanholt			return DRM_ERR(ENOMEM);
125495584Sanholt		}
125595584Sanholt
1256119098Sanholt		/* Turn on PCI GART */
1257119098Sanholt		radeon_set_pcigart( dev_priv, 1 );
125895584Sanholt	}
125995584Sanholt
126095584Sanholt	radeon_cp_load_microcode( dev_priv );
126195584Sanholt	radeon_cp_init_ring_buffer( dev, dev_priv );
126295584Sanholt
126395584Sanholt	dev_priv->last_buf = 0;
126495584Sanholt
126595584Sanholt	dev->dev_private = (void *)dev_priv;
126695584Sanholt
126795584Sanholt	radeon_do_engine_reset( dev );
126895584Sanholt
126995584Sanholt	return 0;
127095584Sanholt}
127195584Sanholt
127295584Sanholtint radeon_do_cleanup_cp( drm_device_t *dev )
127395584Sanholt{
1274112015Sanholt	DRM_DEBUG( "\n" );
127595584Sanholt
1276119098Sanholt#if _HAVE_DMA_IRQ
1277119098Sanholt	/* Make sure interrupts are disabled here because the uninstall ioctl
1278119098Sanholt	 * may not have been called from userspace and after dev_private
1279119098Sanholt	 * is freed, it's too late.
1280119098Sanholt	 */
1281119098Sanholt	if ( dev->irq ) DRM(irq_uninstall)(dev);
1282119098Sanholt#endif
1283119098Sanholt
128495584Sanholt	if ( dev->dev_private ) {
128595584Sanholt		drm_radeon_private_t *dev_priv = dev->dev_private;
128695584Sanholt
1287119098Sanholt#if __REALLY_HAVE_AGP
128895584Sanholt		if ( !dev_priv->is_pci ) {
1289113995Sanholt			if ( dev_priv->cp_ring != NULL )
1290119098Sanholt				DRM_IOREMAPFREE( dev_priv->cp_ring, dev );
1291113995Sanholt			if ( dev_priv->ring_rptr != NULL )
1292119098Sanholt				DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
1293113995Sanholt			if ( dev_priv->buffers != NULL )
1294119098Sanholt				DRM_IOREMAPFREE( dev_priv->buffers, dev );
1295119098Sanholt		} else
1296119098Sanholt#endif
1297119098Sanholt		{
129895584Sanholt			if (!DRM(ati_pcigart_cleanup)( dev,
129995584Sanholt						dev_priv->phys_pci_gart,
130095584Sanholt						dev_priv->bus_pci_gart ))
130195584Sanholt				DRM_ERROR( "failed to cleanup PCI GART!\n" );
130295584Sanholt		}
130395584Sanholt
130495584Sanholt		DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
130595584Sanholt			   DRM_MEM_DRIVER );
130695584Sanholt		dev->dev_private = NULL;
130795584Sanholt	}
130895584Sanholt
130995584Sanholt	return 0;
131095584Sanholt}
131195584Sanholt
1312119098Sanholt/* This code will reinit the Radeon CP hardware after a resume from disc.
1313119098Sanholt * AFAIK, it would be very difficult to pickle the state at suspend time, so
1314119098Sanholt * here we make sure that all Radeon hardware initialisation is re-done without
1315119098Sanholt * affecting running applications.
1316119098Sanholt *
1317119098Sanholt * Charl P. Botha <http://cpbotha.net>
1318119098Sanholt */
1319119098Sanholtstatic int radeon_do_resume_cp( drm_device_t *dev )
1320119098Sanholt{
1321119098Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1322119098Sanholt
1323119098Sanholt	if ( !dev_priv ) {
1324119098Sanholt		DRM_ERROR( "Called with no initialization\n" );
1325119098Sanholt		return DRM_ERR( EINVAL );
1326119098Sanholt	}
1327119098Sanholt
1328119098Sanholt	DRM_DEBUG("Starting radeon_do_resume_cp()\n");
1329119098Sanholt
1330119098Sanholt#if __REALLY_HAVE_AGP
1331119098Sanholt	if ( !dev_priv->is_pci ) {
1332119098Sanholt		/* Turn off PCI GART */
1333119098Sanholt		radeon_set_pcigart( dev_priv, 0 );
1334119098Sanholt	} else
1335119098Sanholt#endif
1336119098Sanholt	{
1337119098Sanholt		/* Turn on PCI GART */
1338119098Sanholt		radeon_set_pcigart( dev_priv, 1 );
1339119098Sanholt	}
1340119098Sanholt
1341119098Sanholt	radeon_cp_load_microcode( dev_priv );
1342119098Sanholt	radeon_cp_init_ring_buffer( dev, dev_priv );
1343119098Sanholt
1344119098Sanholt	radeon_do_engine_reset( dev );
1345119098Sanholt
1346119098Sanholt	DRM_DEBUG("radeon_do_resume_cp() complete\n");
1347119098Sanholt
1348119098Sanholt	return 0;
1349119098Sanholt}
1350119098Sanholt
1351119098Sanholt
1352112015Sanholtint radeon_cp_init( DRM_IOCTL_ARGS )
135395584Sanholt{
1354112015Sanholt	DRM_DEVICE;
135595584Sanholt	drm_radeon_init_t init;
135695584Sanholt
1357119098Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
1358119098Sanholt
1359112015Sanholt	DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) );
136095584Sanholt
136195584Sanholt	switch ( init.func ) {
136295584Sanholt	case RADEON_INIT_CP:
1363112015Sanholt	case RADEON_INIT_R200_CP:
136495584Sanholt		return radeon_do_init_cp( dev, &init );
136595584Sanholt	case RADEON_CLEANUP_CP:
136695584Sanholt		return radeon_do_cleanup_cp( dev );
136795584Sanholt	}
136895584Sanholt
1369112015Sanholt	return DRM_ERR(EINVAL);
137095584Sanholt}
137195584Sanholt
1372112015Sanholtint radeon_cp_start( DRM_IOCTL_ARGS )
137395584Sanholt{
1374112015Sanholt	DRM_DEVICE;
137595584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1376112015Sanholt	DRM_DEBUG( "\n" );
137795584Sanholt
1378113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
137995584Sanholt
138095584Sanholt	if ( dev_priv->cp_running ) {
1381112015Sanholt		DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
138295584Sanholt		return 0;
138395584Sanholt	}
138495584Sanholt	if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) {
138595584Sanholt		DRM_DEBUG( "%s called with bogus CP mode (%d)\n",
1386112015Sanholt			   __FUNCTION__, dev_priv->cp_mode );
138795584Sanholt		return 0;
138895584Sanholt	}
138995584Sanholt
139095584Sanholt	radeon_do_cp_start( dev_priv );
139195584Sanholt
139295584Sanholt	return 0;
139395584Sanholt}
139495584Sanholt
139595584Sanholt/* Stop the CP.  The engine must have been idled before calling this
139695584Sanholt * routine.
139795584Sanholt */
1398112015Sanholtint radeon_cp_stop( DRM_IOCTL_ARGS )
139995584Sanholt{
1400112015Sanholt	DRM_DEVICE;
140195584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
140295584Sanholt	drm_radeon_cp_stop_t stop;
140395584Sanholt	int ret;
1404112015Sanholt	DRM_DEBUG( "\n" );
140595584Sanholt
1406113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
140795584Sanholt
1408112015Sanholt	DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t *)data, sizeof(stop) );
140995584Sanholt
1410112015Sanholt	if (!dev_priv->cp_running)
1411112015Sanholt		return 0;
1412112015Sanholt
141395584Sanholt	/* Flush any pending CP commands.  This ensures any outstanding
141495584Sanholt	 * commands are exectuted by the engine before we turn it off.
141595584Sanholt	 */
141695584Sanholt	if ( stop.flush ) {
141795584Sanholt		radeon_do_cp_flush( dev_priv );
141895584Sanholt	}
141995584Sanholt
142095584Sanholt	/* If we fail to make the engine go idle, we return an error
142195584Sanholt	 * code so that the DRM ioctl wrapper can try again.
142295584Sanholt	 */
142395584Sanholt	if ( stop.idle ) {
142495584Sanholt		ret = radeon_do_cp_idle( dev_priv );
142595584Sanholt		if ( ret ) return ret;
142695584Sanholt	}
142795584Sanholt
142895584Sanholt	/* Finally, we can turn off the CP.  If the engine isn't idle,
142995584Sanholt	 * we will get some dropped triangles as they won't be fully
143095584Sanholt	 * rendered before the CP is shut down.
143195584Sanholt	 */
143295584Sanholt	radeon_do_cp_stop( dev_priv );
143395584Sanholt
143495584Sanholt	/* Reset the engine */
143595584Sanholt	radeon_do_engine_reset( dev );
143695584Sanholt
143795584Sanholt	return 0;
143895584Sanholt}
143995584Sanholt
1440112015Sanholt
1441112015Sanholtvoid radeon_do_release( drm_device_t *dev )
1442112015Sanholt{
1443112015Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1444112015Sanholt	int ret;
1445112015Sanholt
1446112015Sanholt	if (dev_priv) {
1447112015Sanholt		if (dev_priv->cp_running) {
1448112015Sanholt			/* Stop the cp */
1449112015Sanholt			while ((ret = radeon_do_cp_idle( dev_priv )) != 0) {
1450112015Sanholt				DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
1451112015Sanholt#ifdef __linux__
1452112015Sanholt				schedule();
1453112015Sanholt#else
1454112015Sanholt				tsleep(&ret, PZERO, "rdnrel", 1);
1455112015Sanholt#endif
1456112015Sanholt			}
1457112015Sanholt			radeon_do_cp_stop( dev_priv );
1458112015Sanholt			radeon_do_engine_reset( dev );
1459112015Sanholt		}
1460112015Sanholt
1461112015Sanholt		/* Disable *all* interrupts */
1462112015Sanholt		RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
1463112015Sanholt
1464112015Sanholt		/* Free memory heap structures */
1465119895Sanholt		radeon_mem_takedown( &(dev_priv->gart_heap) );
1466112015Sanholt		radeon_mem_takedown( &(dev_priv->fb_heap) );
1467112015Sanholt
1468112015Sanholt		/* deallocate kernel resources */
1469112015Sanholt		radeon_do_cleanup_cp( dev );
1470112015Sanholt	}
1471112015Sanholt}
1472112015Sanholt
147395584Sanholt/* Just reset the CP ring.  Called as part of an X Server engine reset.
147495584Sanholt */
1475112015Sanholtint radeon_cp_reset( DRM_IOCTL_ARGS )
147695584Sanholt{
1477112015Sanholt	DRM_DEVICE;
147895584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1479112015Sanholt	DRM_DEBUG( "\n" );
148095584Sanholt
1481113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
148295584Sanholt
148395584Sanholt	if ( !dev_priv ) {
1484112015Sanholt		DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
1485112015Sanholt		return DRM_ERR(EINVAL);
148695584Sanholt	}
148795584Sanholt
148895584Sanholt	radeon_do_cp_reset( dev_priv );
148995584Sanholt
149095584Sanholt	/* The CP is no longer running after an engine reset */
149195584Sanholt	dev_priv->cp_running = 0;
149295584Sanholt
149395584Sanholt	return 0;
149495584Sanholt}
149595584Sanholt
1496112015Sanholtint radeon_cp_idle( DRM_IOCTL_ARGS )
149795584Sanholt{
1498112015Sanholt	DRM_DEVICE;
149995584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1500112015Sanholt	DRM_DEBUG( "\n" );
150195584Sanholt
1502113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
150395584Sanholt
150495584Sanholt	return radeon_do_cp_idle( dev_priv );
150595584Sanholt}
150695584Sanholt
1507119098Sanholt/* Added by Charl P. Botha to call radeon_do_resume_cp().
1508119098Sanholt */
1509119098Sanholtint radeon_cp_resume( DRM_IOCTL_ARGS )
1510119098Sanholt{
1511119098Sanholt	DRM_DEVICE;
1512119098Sanholt
1513119098Sanholt	return radeon_do_resume_cp(dev);
1514119098Sanholt}
1515119098Sanholt
1516119098Sanholt
1517112015Sanholtint radeon_engine_reset( DRM_IOCTL_ARGS )
151895584Sanholt{
1519112015Sanholt	DRM_DEVICE;
1520112015Sanholt	DRM_DEBUG( "\n" );
152195584Sanholt
1522113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
152395584Sanholt
152495584Sanholt	return radeon_do_engine_reset( dev );
152595584Sanholt}
152695584Sanholt
152795584Sanholt
152895584Sanholt/* ================================================================
152995584Sanholt * Fullscreen mode
153095584Sanholt */
153195584Sanholt
1532112015Sanholt/* KW: Deprecated to say the least:
1533112015Sanholt */
1534112015Sanholtint radeon_fullscreen( DRM_IOCTL_ARGS )
153595584Sanholt{
153695584Sanholt	return 0;
153795584Sanholt}
153895584Sanholt
153995584Sanholt
154095584Sanholt/* ================================================================
154195584Sanholt * Freelist management
154295584Sanholt */
154395584Sanholt
1544112015Sanholt/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
1545112015Sanholt *   bufs until freelist code is used.  Note this hides a problem with
1546112015Sanholt *   the scratch register * (used to keep track of last buffer
1547112015Sanholt *   completed) being written to before * the last buffer has actually
1548112015Sanholt *   completed rendering.
1549112015Sanholt *
1550112015Sanholt * KW:  It's also a good way to find free buffers quickly.
1551112015Sanholt *
1552112015Sanholt * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
1553112015Sanholt * sleep.  However, bugs in older versions of radeon_accel.c mean that
1554112015Sanholt * we essentially have to do this, else old clients will break.
1555112015Sanholt *
1556112015Sanholt * However, it does leave open a potential deadlock where all the
1557112015Sanholt * buffers are held by other clients, which can't release them because
1558112015Sanholt * they can't get the lock.
1559112015Sanholt */
1560112015Sanholt
1561112015Sanholtdrm_buf_t *radeon_freelist_get( drm_device_t *dev )
156295584Sanholt{
156395584Sanholt	drm_device_dma_t *dma = dev->dma;
156495584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1565112015Sanholt	drm_radeon_buf_priv_t *buf_priv;
156695584Sanholt	drm_buf_t *buf;
1567112015Sanholt	int i, t;
1568112015Sanholt	int start;
156995584Sanholt
1570112015Sanholt	if ( ++dev_priv->last_buf >= dma->buf_count )
1571112015Sanholt		dev_priv->last_buf = 0;
157295584Sanholt
1573112015Sanholt	start = dev_priv->last_buf;
157495584Sanholt
1575112015Sanholt	for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
1576112015Sanholt		u32 done_age = GET_SCRATCH( 1 );
1577112015Sanholt		DRM_DEBUG("done_age = %d\n",done_age);
1578112015Sanholt		for ( i = start ; i < dma->buf_count ; i++ ) {
1579112015Sanholt			buf = dma->buflist[i];
1580112015Sanholt			buf_priv = buf->dev_private;
1581113995Sanholt			if ( buf->filp == 0 || (buf->pending &&
1582112015Sanholt					       buf_priv->age <= done_age) ) {
1583112015Sanholt				dev_priv->stats.requested_bufs++;
1584112015Sanholt				buf->pending = 0;
1585112015Sanholt				return buf;
1586112015Sanholt			}
1587112015Sanholt			start = 0;
1588112015Sanholt		}
158995584Sanholt
1590112015Sanholt		if (t) {
1591112015Sanholt			DRM_UDELAY( 1 );
1592112015Sanholt			dev_priv->stats.freelist_loops++;
1593112015Sanholt		}
159495584Sanholt	}
159595584Sanholt
1596112015Sanholt	DRM_DEBUG( "returning NULL!\n" );
1597112015Sanholt	return NULL;
159895584Sanholt}
1599112015Sanholt#if 0
160095584Sanholtdrm_buf_t *radeon_freelist_get( drm_device_t *dev )
160195584Sanholt{
160295584Sanholt	drm_device_dma_t *dma = dev->dma;
160395584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
160495584Sanholt	drm_radeon_buf_priv_t *buf_priv;
160595584Sanholt	drm_buf_t *buf;
160695584Sanholt	int i, t;
160795584Sanholt	int start;
1608112015Sanholt	u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
160995584Sanholt
161095584Sanholt	if ( ++dev_priv->last_buf >= dma->buf_count )
161195584Sanholt		dev_priv->last_buf = 0;
1612112015Sanholt
161395584Sanholt	start = dev_priv->last_buf;
1614112015Sanholt	dev_priv->stats.freelist_loops++;
1615112015Sanholt
1616112015Sanholt	for ( t = 0 ; t < 2 ; t++ ) {
161795584Sanholt		for ( i = start ; i < dma->buf_count ; i++ ) {
161895584Sanholt			buf = dma->buflist[i];
161995584Sanholt			buf_priv = buf->dev_private;
1620113995Sanholt			if ( buf->filp == 0 || (buf->pending &&
1621112015Sanholt					       buf_priv->age <= done_age) ) {
1622112015Sanholt				dev_priv->stats.requested_bufs++;
162395584Sanholt				buf->pending = 0;
162495584Sanholt				return buf;
162595584Sanholt			}
162695584Sanholt		}
1627112015Sanholt		start = 0;
162895584Sanholt	}
162995584Sanholt
163095584Sanholt	return NULL;
163195584Sanholt}
1632112015Sanholt#endif
163395584Sanholt
163495584Sanholtvoid radeon_freelist_reset( drm_device_t *dev )
163595584Sanholt{
163695584Sanholt	drm_device_dma_t *dma = dev->dma;
163795584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
163895584Sanholt	int i;
163995584Sanholt
164095584Sanholt	dev_priv->last_buf = 0;
164195584Sanholt	for ( i = 0 ; i < dma->buf_count ; i++ ) {
164295584Sanholt		drm_buf_t *buf = dma->buflist[i];
164395584Sanholt		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
164495584Sanholt		buf_priv->age = 0;
164595584Sanholt	}
164695584Sanholt}
164795584Sanholt
164895584Sanholt
164995584Sanholt/* ================================================================
165095584Sanholt * CP command submission
165195584Sanholt */
165295584Sanholt
165395584Sanholtint radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
165495584Sanholt{
165595584Sanholt	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
165695584Sanholt	int i;
1657113995Sanholt	u32 last_head = GET_RING_HEAD( dev_priv );
165895584Sanholt
165995584Sanholt	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
1660113995Sanholt		u32 head = GET_RING_HEAD( dev_priv );
1661112015Sanholt
1662112015Sanholt		ring->space = (head - ring->tail) * sizeof(u32);
1663112015Sanholt		if ( ring->space <= 0 )
1664112015Sanholt			ring->space += ring->size;
166595584Sanholt		if ( ring->space > n )
166695584Sanholt			return 0;
1667112015Sanholt
1668112015Sanholt		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
1669112015Sanholt
1670112015Sanholt		if (head != last_head)
1671112015Sanholt			i = 0;
1672112015Sanholt		last_head = head;
1673112015Sanholt
1674112015Sanholt		DRM_UDELAY( 1 );
167595584Sanholt	}
167695584Sanholt
167795584Sanholt	/* FIXME: This return value is ignored in the BEGIN_RING macro! */
167895584Sanholt#if RADEON_FIFO_DEBUG
167995584Sanholt	radeon_status( dev_priv );
168095584Sanholt	DRM_ERROR( "failed!\n" );
168195584Sanholt#endif
1682112015Sanholt	return DRM_ERR(EBUSY);
168395584Sanholt}
168495584Sanholt
1685113995Sanholtstatic int radeon_cp_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d )
168695584Sanholt{
168795584Sanholt	int i;
168895584Sanholt	drm_buf_t *buf;
168995584Sanholt
169095584Sanholt	for ( i = d->granted_count ; i < d->request_count ; i++ ) {
169195584Sanholt		buf = radeon_freelist_get( dev );
1692112015Sanholt		if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */
169395584Sanholt
1694113995Sanholt		buf->filp = filp;
169595584Sanholt
1696112015Sanholt		if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
169795584Sanholt				   sizeof(buf->idx) ) )
1698112015Sanholt			return DRM_ERR(EFAULT);
1699112015Sanholt		if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
170095584Sanholt				   sizeof(buf->total) ) )
1701112015Sanholt			return DRM_ERR(EFAULT);
170295584Sanholt
170395584Sanholt		d->granted_count++;
170495584Sanholt	}
170595584Sanholt	return 0;
170695584Sanholt}
170795584Sanholt
1708112015Sanholtint radeon_cp_buffers( DRM_IOCTL_ARGS )
170995584Sanholt{
1710112015Sanholt	DRM_DEVICE;
171195584Sanholt	drm_device_dma_t *dma = dev->dma;
171295584Sanholt	int ret = 0;
171395584Sanholt	drm_dma_t d;
171495584Sanholt
1715113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
171695584Sanholt
1717112015Sanholt	DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *)data, sizeof(d) );
171895584Sanholt
171995584Sanholt	/* Please don't send us buffers.
172095584Sanholt	 */
172195584Sanholt	if ( d.send_count != 0 ) {
172295584Sanholt		DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
1723112015Sanholt			   DRM_CURRENTPID, d.send_count );
1724112015Sanholt		return DRM_ERR(EINVAL);
172595584Sanholt	}
172695584Sanholt
172795584Sanholt	/* We'll send you buffers.
172895584Sanholt	 */
172995584Sanholt	if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
173095584Sanholt		DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
1731112015Sanholt			   DRM_CURRENTPID, d.request_count, dma->buf_count );
1732112015Sanholt		return DRM_ERR(EINVAL);
173395584Sanholt	}
173495584Sanholt
173595584Sanholt	d.granted_count = 0;
173695584Sanholt
173795584Sanholt	if ( d.request_count ) {
1738113995Sanholt		ret = radeon_cp_get_buffers( filp, dev, &d );
173995584Sanholt	}
174095584Sanholt
1741112015Sanholt	DRM_COPY_TO_USER_IOCTL( (drm_dma_t *)data, d, sizeof(d) );
174295584Sanholt
174395584Sanholt	return ret;
174495584Sanholt}
1745