radeon_cp.c revision 122580
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 122580 2003-11-12 20:56: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
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,
860122580Sanholt		      ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 )
861122580Sanholt		    | ( dev_priv->fb_location >> 16 ) );
86295584Sanholt
863119895Sanholt#if __REALLY_HAVE_AGP
86495584Sanholt	if ( !dev_priv->is_pci ) {
86595584Sanholt		RADEON_WRITE( RADEON_MC_AGP_LOCATION,
866119895Sanholt			      (((dev_priv->gart_vm_start - 1 +
867119895Sanholt				 dev_priv->gart_size) & 0xffff0000) |
868119895Sanholt			       (dev_priv->gart_vm_start >> 16)) );
86995584Sanholt
87095584Sanholt		ring_start = (dev_priv->cp_ring->offset
87195584Sanholt			      - dev->agp->base
872119895Sanholt			      + dev_priv->gart_vm_start);
873119895Sanholt       } else
87495584Sanholt#endif
87595584Sanholt		ring_start = (dev_priv->cp_ring->offset
87695584Sanholt			      - dev->sg->handle
877119895Sanholt			      + dev_priv->gart_vm_start);
87895584Sanholt
87995584Sanholt	RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
88095584Sanholt
88195584Sanholt	/* Set the write pointer delay */
88295584Sanholt	RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 );
88395584Sanholt
88495584Sanholt	/* Initialize the ring buffer's read and write pointers */
88595584Sanholt	cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
88695584Sanholt	RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
887113995Sanholt	SET_RING_HEAD( dev_priv, cur_read_ptr );
88895584Sanholt	dev_priv->ring.tail = cur_read_ptr;
88995584Sanholt
890113995Sanholt#if __REALLY_HAVE_AGP
89195584Sanholt	if ( !dev_priv->is_pci ) {
89295584Sanholt		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
893113995Sanholt			      dev_priv->ring_rptr->offset
894113995Sanholt			      - dev->agp->base
895119895Sanholt			      + dev_priv->gart_vm_start);
896113995Sanholt	} else
897113995Sanholt#endif
898113995Sanholt	{
89995584Sanholt		drm_sg_mem_t *entry = dev->sg;
90095584Sanholt		unsigned long tmp_ofs, page_ofs;
90195584Sanholt
90295584Sanholt		tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
90395584Sanholt		page_ofs = tmp_ofs >> PAGE_SHIFT;
90495584Sanholt
90595584Sanholt		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
90695584Sanholt			     entry->busaddr[page_ofs]);
907113995Sanholt		DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
908119098Sanholt			   (unsigned long) entry->busaddr[page_ofs],
90995584Sanholt			   entry->handle + tmp_ofs );
91095584Sanholt	}
91195584Sanholt
912112015Sanholt	/* Initialize the scratch register pointer.  This will cause
913112015Sanholt	 * the scratch register values to be written out to memory
914112015Sanholt	 * whenever they are updated.
915112015Sanholt	 *
916112015Sanholt	 * We simply put this behind the ring read pointer, this works
917112015Sanholt	 * with PCI GART as well as (whatever kind of) AGP GART
918112015Sanholt	 */
919112015Sanholt	RADEON_WRITE( RADEON_SCRATCH_ADDR, RADEON_READ( RADEON_CP_RB_RPTR_ADDR )
920112015Sanholt					 + RADEON_SCRATCH_REG_OFFSET );
921112015Sanholt
922112015Sanholt	dev_priv->scratch = ((__volatile__ u32 *)
923113995Sanholt			     dev_priv->ring_rptr->handle +
924112015Sanholt			     (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
925112015Sanholt
926112015Sanholt	RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
927112015Sanholt
928112015Sanholt	/* Writeback doesn't seem to work everywhere, test it first */
929112015Sanholt	DRM_WRITE32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0 );
930112015Sanholt	RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
931112015Sanholt
932112015Sanholt	for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
933112015Sanholt		if ( DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1) ) == 0xdeadbeef )
934112015Sanholt			break;
935112015Sanholt		DRM_UDELAY( 1 );
936112015Sanholt	}
937112015Sanholt
938112015Sanholt	if ( tmp < dev_priv->usec_timeout ) {
939112015Sanholt		dev_priv->writeback_works = 1;
940112015Sanholt		DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
941112015Sanholt	} else {
942112015Sanholt		dev_priv->writeback_works = 0;
943112015Sanholt		DRM_DEBUG( "writeback test failed\n" );
944112015Sanholt	}
945112015Sanholt
946112015Sanholt	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
947112015Sanholt	RADEON_WRITE( RADEON_LAST_FRAME_REG,
948112015Sanholt		      dev_priv->sarea_priv->last_frame );
949112015Sanholt
950112015Sanholt	dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
951112015Sanholt	RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
952112015Sanholt		      dev_priv->sarea_priv->last_dispatch );
953112015Sanholt
954112015Sanholt	dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
955112015Sanholt	RADEON_WRITE( RADEON_LAST_CLEAR_REG,
956112015Sanholt		      dev_priv->sarea_priv->last_clear );
957112015Sanholt
95895584Sanholt	/* Set ring buffer size */
959112015Sanholt#ifdef __BIG_ENDIAN
960112015Sanholt	RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT );
961112015Sanholt#else
96295584Sanholt	RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
963112015Sanholt#endif
96495584Sanholt
96595584Sanholt	radeon_do_wait_for_idle( dev_priv );
96695584Sanholt
96795584Sanholt	/* Turn on bus mastering */
96895584Sanholt	tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
96995584Sanholt	RADEON_WRITE( RADEON_BUS_CNTL, tmp );
97095584Sanholt
97195584Sanholt	/* Sync everything up */
97295584Sanholt	RADEON_WRITE( RADEON_ISYNC_CNTL,
97395584Sanholt		      (RADEON_ISYNC_ANY2D_IDLE3D |
97495584Sanholt		       RADEON_ISYNC_ANY3D_IDLE2D |
97595584Sanholt		       RADEON_ISYNC_WAIT_IDLEGUI |
97695584Sanholt		       RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
97795584Sanholt}
97895584Sanholt
979119098Sanholt/* Enable or disable PCI GART on the chip */
980119098Sanholtstatic void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on )
981119098Sanholt{
982119098Sanholt	u32 tmp	= RADEON_READ( RADEON_AIC_CNTL );
983119098Sanholt
984119098Sanholt	if ( on ) {
985119098Sanholt		RADEON_WRITE( RADEON_AIC_CNTL, tmp | RADEON_PCIGART_TRANSLATE_EN );
986119098Sanholt
987119098Sanholt		/* set PCI GART page-table base address
988119098Sanholt		 */
989119098Sanholt		RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );
990119098Sanholt
991119098Sanholt		/* set address range for PCI address translate
992119098Sanholt		 */
993119895Sanholt		RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start );
994119895Sanholt		RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
995119895Sanholt						  + dev_priv->gart_size - 1);
996119098Sanholt
997119895Sanholt		/* Turn off AGP aperture -- is this required for PCI GART?
998119098Sanholt		 */
999119098Sanholt		RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
1000119098Sanholt		RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
1001119098Sanholt	} else {
1002119098Sanholt		RADEON_WRITE( RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN );
1003119098Sanholt	}
1004119098Sanholt}
1005119098Sanholt
100695584Sanholtstatic int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
100795584Sanholt{
100895584Sanholt	drm_radeon_private_t *dev_priv;
1009112015Sanholt	DRM_DEBUG( "\n" );
101095584Sanholt
101195584Sanholt	dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
101295584Sanholt	if ( dev_priv == NULL )
1013112015Sanholt		return DRM_ERR(ENOMEM);
101495584Sanholt
101595584Sanholt	memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
101695584Sanholt
101795584Sanholt	dev_priv->is_pci = init->is_pci;
101895584Sanholt
101995584Sanholt	if ( dev_priv->is_pci && !dev->sg ) {
102095584Sanholt		DRM_ERROR( "PCI GART memory not allocated!\n" );
102195584Sanholt		dev->dev_private = (void *)dev_priv;
102295584Sanholt		radeon_do_cleanup_cp(dev);
1023112015Sanholt		return DRM_ERR(EINVAL);
102495584Sanholt	}
102595584Sanholt
102695584Sanholt	dev_priv->usec_timeout = init->usec_timeout;
102795584Sanholt	if ( dev_priv->usec_timeout < 1 ||
102895584Sanholt	     dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
102995584Sanholt		DRM_DEBUG( "TIMEOUT problem!\n" );
103095584Sanholt		dev->dev_private = (void *)dev_priv;
103195584Sanholt		radeon_do_cleanup_cp(dev);
1032112015Sanholt		return DRM_ERR(EINVAL);
103395584Sanholt	}
103495584Sanholt
1035112015Sanholt	dev_priv->is_r200 = (init->func == RADEON_INIT_R200_CP);
1036112015Sanholt	dev_priv->do_boxes = 0;
103795584Sanholt	dev_priv->cp_mode = init->cp_mode;
103895584Sanholt
103995584Sanholt	/* We don't support anything other than bus-mastering ring mode,
104095584Sanholt	 * but the ring can be in either AGP or PCI space for the ring
104195584Sanholt	 * read pointer.
104295584Sanholt	 */
104395584Sanholt	if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
104495584Sanholt	     ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
104595584Sanholt		DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
104695584Sanholt		dev->dev_private = (void *)dev_priv;
104795584Sanholt		radeon_do_cleanup_cp(dev);
1048112015Sanholt		return DRM_ERR(EINVAL);
104995584Sanholt	}
105095584Sanholt
105195584Sanholt	switch ( init->fb_bpp ) {
105295584Sanholt	case 16:
105395584Sanholt		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
105495584Sanholt		break;
105595584Sanholt	case 32:
105695584Sanholt	default:
105795584Sanholt		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
105895584Sanholt		break;
105995584Sanholt	}
106095584Sanholt	dev_priv->front_offset	= init->front_offset;
106195584Sanholt	dev_priv->front_pitch	= init->front_pitch;
106295584Sanholt	dev_priv->back_offset	= init->back_offset;
106395584Sanholt	dev_priv->back_pitch	= init->back_pitch;
106495584Sanholt
106595584Sanholt	switch ( init->depth_bpp ) {
106695584Sanholt	case 16:
106795584Sanholt		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
106895584Sanholt		break;
106995584Sanholt	case 32:
107095584Sanholt	default:
107195584Sanholt		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
107295584Sanholt		break;
107395584Sanholt	}
107495584Sanholt	dev_priv->depth_offset	= init->depth_offset;
107595584Sanholt	dev_priv->depth_pitch	= init->depth_pitch;
107695584Sanholt
107795584Sanholt	/* Hardware state for depth clears.  Remove this if/when we no
107895584Sanholt	 * longer clear the depth buffer with a 3D rectangle.  Hard-code
107995584Sanholt	 * all values to prevent unwanted 3D state from slipping through
108095584Sanholt	 * and screwing with the clear operation.
108195584Sanholt	 */
108295584Sanholt	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
108395584Sanholt					   (dev_priv->color_fmt << 10) |
1084112015Sanholt					   (1<<15));
108595584Sanholt
1086112015Sanholt	dev_priv->depth_clear.rb3d_zstencilcntl =
1087112015Sanholt		(dev_priv->depth_fmt |
1088112015Sanholt		 RADEON_Z_TEST_ALWAYS |
1089112015Sanholt		 RADEON_STENCIL_TEST_ALWAYS |
1090112015Sanholt		 RADEON_STENCIL_S_FAIL_REPLACE |
1091112015Sanholt		 RADEON_STENCIL_ZPASS_REPLACE |
1092112015Sanholt		 RADEON_STENCIL_ZFAIL_REPLACE |
1093112015Sanholt		 RADEON_Z_WRITE_ENABLE);
109495584Sanholt
109595584Sanholt	dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
109695584Sanholt					 RADEON_BFACE_SOLID |
109795584Sanholt					 RADEON_FFACE_SOLID |
109895584Sanholt					 RADEON_FLAT_SHADE_VTX_LAST |
109995584Sanholt					 RADEON_DIFFUSE_SHADE_FLAT |
110095584Sanholt					 RADEON_ALPHA_SHADE_FLAT |
110195584Sanholt					 RADEON_SPECULAR_SHADE_FLAT |
110295584Sanholt					 RADEON_FOG_SHADE_FLAT |
110395584Sanholt					 RADEON_VTX_PIX_CENTER_OGL |
110495584Sanholt					 RADEON_ROUND_MODE_TRUNC |
110595584Sanholt					 RADEON_ROUND_PREC_8TH_PIX);
110695584Sanholt
1107112015Sanholt	DRM_GETSAREA();
1108113995Sanholt
1109113995Sanholt	dev_priv->fb_offset = init->fb_offset;
1110113995Sanholt	dev_priv->mmio_offset = init->mmio_offset;
1111113995Sanholt	dev_priv->ring_offset = init->ring_offset;
1112113995Sanholt	dev_priv->ring_rptr_offset = init->ring_rptr_offset;
1113113995Sanholt	dev_priv->buffers_offset = init->buffers_offset;
1114119895Sanholt	dev_priv->gart_textures_offset = init->gart_textures_offset;
1115112015Sanholt
111695584Sanholt	if(!dev_priv->sarea) {
111795584Sanholt		DRM_ERROR("could not find sarea!\n");
111895584Sanholt		dev->dev_private = (void *)dev_priv;
111995584Sanholt		radeon_do_cleanup_cp(dev);
1120112015Sanholt		return DRM_ERR(EINVAL);
112195584Sanholt	}
112295584Sanholt
112395584Sanholt	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
112495584Sanholt	if(!dev_priv->fb) {
112595584Sanholt		DRM_ERROR("could not find framebuffer!\n");
112695584Sanholt		dev->dev_private = (void *)dev_priv;
112795584Sanholt		radeon_do_cleanup_cp(dev);
1128112015Sanholt		return DRM_ERR(EINVAL);
112995584Sanholt	}
113095584Sanholt	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
113195584Sanholt	if(!dev_priv->mmio) {
113295584Sanholt		DRM_ERROR("could not find mmio region!\n");
113395584Sanholt		dev->dev_private = (void *)dev_priv;
113495584Sanholt		radeon_do_cleanup_cp(dev);
1135112015Sanholt		return DRM_ERR(EINVAL);
113695584Sanholt	}
113795584Sanholt	DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
113895584Sanholt	if(!dev_priv->cp_ring) {
113995584Sanholt		DRM_ERROR("could not find cp ring region!\n");
114095584Sanholt		dev->dev_private = (void *)dev_priv;
114195584Sanholt		radeon_do_cleanup_cp(dev);
1142112015Sanholt		return DRM_ERR(EINVAL);
114395584Sanholt	}
114495584Sanholt	DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
114595584Sanholt	if(!dev_priv->ring_rptr) {
114695584Sanholt		DRM_ERROR("could not find ring read pointer!\n");
114795584Sanholt		dev->dev_private = (void *)dev_priv;
114895584Sanholt		radeon_do_cleanup_cp(dev);
1149112015Sanholt		return DRM_ERR(EINVAL);
115095584Sanholt	}
115195584Sanholt	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
115295584Sanholt	if(!dev_priv->buffers) {
115395584Sanholt		DRM_ERROR("could not find dma buffer region!\n");
115495584Sanholt		dev->dev_private = (void *)dev_priv;
115595584Sanholt		radeon_do_cleanup_cp(dev);
1156112015Sanholt		return DRM_ERR(EINVAL);
115795584Sanholt	}
115895584Sanholt
1159119895Sanholt	if ( init->gart_textures_offset ) {
1160119895Sanholt		DRM_FIND_MAP( dev_priv->gart_textures, init->gart_textures_offset );
1161119895Sanholt		if ( !dev_priv->gart_textures ) {
1162119895Sanholt			DRM_ERROR("could not find GART texture region!\n");
116395584Sanholt			dev->dev_private = (void *)dev_priv;
116495584Sanholt			radeon_do_cleanup_cp(dev);
1165112015Sanholt			return DRM_ERR(EINVAL);
116695584Sanholt		}
116795584Sanholt	}
116895584Sanholt
116995584Sanholt	dev_priv->sarea_priv =
117095584Sanholt		(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
117195584Sanholt				       init->sarea_priv_offset);
117295584Sanholt
1173119098Sanholt#if __REALLY_HAVE_AGP
117495584Sanholt	if ( !dev_priv->is_pci ) {
1175119098Sanholt		DRM_IOREMAP( dev_priv->cp_ring, dev );
1176119098Sanholt		DRM_IOREMAP( dev_priv->ring_rptr, dev );
1177119098Sanholt		DRM_IOREMAP( dev_priv->buffers, dev );
117895584Sanholt		if(!dev_priv->cp_ring->handle ||
117995584Sanholt		   !dev_priv->ring_rptr->handle ||
118095584Sanholt		   !dev_priv->buffers->handle) {
118195584Sanholt			DRM_ERROR("could not find ioremap agp regions!\n");
118295584Sanholt			dev->dev_private = (void *)dev_priv;
118395584Sanholt			radeon_do_cleanup_cp(dev);
1184112015Sanholt			return DRM_ERR(EINVAL);
118595584Sanholt		}
1186119098Sanholt	} else
1187119098Sanholt#endif
1188119098Sanholt	{
118995584Sanholt		dev_priv->cp_ring->handle =
119095584Sanholt			(void *)dev_priv->cp_ring->offset;
119195584Sanholt		dev_priv->ring_rptr->handle =
119295584Sanholt			(void *)dev_priv->ring_rptr->offset;
119395584Sanholt		dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
119495584Sanholt
119595584Sanholt		DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
119695584Sanholt			   dev_priv->cp_ring->handle );
119795584Sanholt		DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
119895584Sanholt			   dev_priv->ring_rptr->handle );
119995584Sanholt		DRM_DEBUG( "dev_priv->buffers->handle %p\n",
120095584Sanholt			   dev_priv->buffers->handle );
120195584Sanholt	}
120295584Sanholt
1203122580Sanholt	dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION )
1204122580Sanholt				& 0xffff ) << 16;
120595584Sanholt
1206122580Sanholt	dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
1207122580Sanholt					( ( dev_priv->front_offset
1208122580Sanholt					  + dev_priv->fb_location ) >> 10 ) );
1209122580Sanholt
1210122580Sanholt	dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
1211122580Sanholt				       ( ( dev_priv->back_offset
1212122580Sanholt					 + dev_priv->fb_location ) >> 10 ) );
1213122580Sanholt
1214122580Sanholt	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
1215122580Sanholt					( ( dev_priv->depth_offset
1216122580Sanholt					  + dev_priv->fb_location ) >> 10 ) );
1217122580Sanholt
1218122580Sanholt
1219119895Sanholt	dev_priv->gart_size = init->gart_size;
1220122580Sanholt	dev_priv->gart_vm_start = dev_priv->fb_location
1221122580Sanholt				+ RADEON_READ( RADEON_CONFIG_APER_SIZE );
1222122580Sanholt
122395584Sanholt#if __REALLY_HAVE_AGP
122495584Sanholt	if ( !dev_priv->is_pci )
1225119895Sanholt		dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
122695584Sanholt						- dev->agp->base
1227119895Sanholt						+ dev_priv->gart_vm_start);
122895584Sanholt	else
122995584Sanholt#endif
1230119895Sanholt		dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
123195584Sanholt						- dev->sg->handle
1232119895Sanholt						+ dev_priv->gart_vm_start);
123395584Sanholt
1234119895Sanholt	DRM_DEBUG( "dev_priv->gart_size %d\n",
1235119895Sanholt		   dev_priv->gart_size );
1236119895Sanholt	DRM_DEBUG( "dev_priv->gart_vm_start 0x%x\n",
1237119895Sanholt		   dev_priv->gart_vm_start );
1238119895Sanholt	DRM_DEBUG( "dev_priv->gart_buffers_offset 0x%lx\n",
1239119895Sanholt		   dev_priv->gart_buffers_offset );
124095584Sanholt
124195584Sanholt	dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle;
124295584Sanholt	dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
124395584Sanholt			      + init->ring_size / sizeof(u32));
124495584Sanholt	dev_priv->ring.size = init->ring_size;
124595584Sanholt	dev_priv->ring.size_l2qw = DRM(order)( init->ring_size / 8 );
124695584Sanholt
124795584Sanholt	dev_priv->ring.tail_mask =
124895584Sanholt		(dev_priv->ring.size / sizeof(u32)) - 1;
124995584Sanholt
125095584Sanholt	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
125195584Sanholt
1252119098Sanholt#if __REALLY_HAVE_AGP
1253119098Sanholt	if ( !dev_priv->is_pci ) {
1254119098Sanholt		/* Turn off PCI GART */
1255119098Sanholt		radeon_set_pcigart( dev_priv, 0 );
1256119098Sanholt	} else
1257119098Sanholt#endif
1258119098Sanholt	{
125995584Sanholt		if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
126095584Sanholt					    &dev_priv->bus_pci_gart)) {
126195584Sanholt			DRM_ERROR( "failed to init PCI GART!\n" );
126295584Sanholt			dev->dev_private = (void *)dev_priv;
126395584Sanholt			radeon_do_cleanup_cp(dev);
1264112015Sanholt			return DRM_ERR(ENOMEM);
126595584Sanholt		}
126695584Sanholt
1267119098Sanholt		/* Turn on PCI GART */
1268119098Sanholt		radeon_set_pcigart( dev_priv, 1 );
126995584Sanholt	}
127095584Sanholt
127195584Sanholt	radeon_cp_load_microcode( dev_priv );
127295584Sanholt	radeon_cp_init_ring_buffer( dev, dev_priv );
127395584Sanholt
127495584Sanholt	dev_priv->last_buf = 0;
127595584Sanholt
127695584Sanholt	dev->dev_private = (void *)dev_priv;
127795584Sanholt
127895584Sanholt	radeon_do_engine_reset( dev );
127995584Sanholt
128095584Sanholt	return 0;
128195584Sanholt}
128295584Sanholt
128395584Sanholtint radeon_do_cleanup_cp( drm_device_t *dev )
128495584Sanholt{
1285112015Sanholt	DRM_DEBUG( "\n" );
128695584Sanholt
1287121447Sanholt#if __HAVE_IRQ
1288119098Sanholt	/* Make sure interrupts are disabled here because the uninstall ioctl
1289119098Sanholt	 * may not have been called from userspace and after dev_private
1290119098Sanholt	 * is freed, it's too late.
1291119098Sanholt	 */
1292122580Sanholt	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
1293119098Sanholt#endif
1294119098Sanholt
129595584Sanholt	if ( dev->dev_private ) {
129695584Sanholt		drm_radeon_private_t *dev_priv = dev->dev_private;
129795584Sanholt
1298119098Sanholt#if __REALLY_HAVE_AGP
129995584Sanholt		if ( !dev_priv->is_pci ) {
1300113995Sanholt			if ( dev_priv->cp_ring != NULL )
1301119098Sanholt				DRM_IOREMAPFREE( dev_priv->cp_ring, dev );
1302113995Sanholt			if ( dev_priv->ring_rptr != NULL )
1303119098Sanholt				DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
1304113995Sanholt			if ( dev_priv->buffers != NULL )
1305119098Sanholt				DRM_IOREMAPFREE( dev_priv->buffers, dev );
1306119098Sanholt		} else
1307119098Sanholt#endif
1308119098Sanholt		{
130995584Sanholt			if (!DRM(ati_pcigart_cleanup)( dev,
131095584Sanholt						dev_priv->phys_pci_gart,
131195584Sanholt						dev_priv->bus_pci_gart ))
131295584Sanholt				DRM_ERROR( "failed to cleanup PCI GART!\n" );
131395584Sanholt		}
131495584Sanholt
131595584Sanholt		DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
131695584Sanholt			   DRM_MEM_DRIVER );
131795584Sanholt		dev->dev_private = NULL;
131895584Sanholt	}
131995584Sanholt
132095584Sanholt	return 0;
132195584Sanholt}
132295584Sanholt
1323119098Sanholt/* This code will reinit the Radeon CP hardware after a resume from disc.
1324119098Sanholt * AFAIK, it would be very difficult to pickle the state at suspend time, so
1325119098Sanholt * here we make sure that all Radeon hardware initialisation is re-done without
1326119098Sanholt * affecting running applications.
1327119098Sanholt *
1328119098Sanholt * Charl P. Botha <http://cpbotha.net>
1329119098Sanholt */
1330119098Sanholtstatic int radeon_do_resume_cp( drm_device_t *dev )
1331119098Sanholt{
1332119098Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1333119098Sanholt
1334119098Sanholt	if ( !dev_priv ) {
1335119098Sanholt		DRM_ERROR( "Called with no initialization\n" );
1336119098Sanholt		return DRM_ERR( EINVAL );
1337119098Sanholt	}
1338119098Sanholt
1339119098Sanholt	DRM_DEBUG("Starting radeon_do_resume_cp()\n");
1340119098Sanholt
1341119098Sanholt#if __REALLY_HAVE_AGP
1342119098Sanholt	if ( !dev_priv->is_pci ) {
1343119098Sanholt		/* Turn off PCI GART */
1344119098Sanholt		radeon_set_pcigart( dev_priv, 0 );
1345119098Sanholt	} else
1346119098Sanholt#endif
1347119098Sanholt	{
1348119098Sanholt		/* Turn on PCI GART */
1349119098Sanholt		radeon_set_pcigart( dev_priv, 1 );
1350119098Sanholt	}
1351119098Sanholt
1352119098Sanholt	radeon_cp_load_microcode( dev_priv );
1353119098Sanholt	radeon_cp_init_ring_buffer( dev, dev_priv );
1354119098Sanholt
1355119098Sanholt	radeon_do_engine_reset( dev );
1356119098Sanholt
1357119098Sanholt	DRM_DEBUG("radeon_do_resume_cp() complete\n");
1358119098Sanholt
1359119098Sanholt	return 0;
1360119098Sanholt}
1361119098Sanholt
1362119098Sanholt
1363112015Sanholtint radeon_cp_init( DRM_IOCTL_ARGS )
136495584Sanholt{
1365112015Sanholt	DRM_DEVICE;
136695584Sanholt	drm_radeon_init_t init;
136795584Sanholt
1368119098Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
1369119098Sanholt
1370112015Sanholt	DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) );
137195584Sanholt
137295584Sanholt	switch ( init.func ) {
137395584Sanholt	case RADEON_INIT_CP:
1374112015Sanholt	case RADEON_INIT_R200_CP:
137595584Sanholt		return radeon_do_init_cp( dev, &init );
137695584Sanholt	case RADEON_CLEANUP_CP:
137795584Sanholt		return radeon_do_cleanup_cp( dev );
137895584Sanholt	}
137995584Sanholt
1380112015Sanholt	return DRM_ERR(EINVAL);
138195584Sanholt}
138295584Sanholt
1383112015Sanholtint radeon_cp_start( DRM_IOCTL_ARGS )
138495584Sanholt{
1385112015Sanholt	DRM_DEVICE;
138695584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1387112015Sanholt	DRM_DEBUG( "\n" );
138895584Sanholt
1389113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
139095584Sanholt
139195584Sanholt	if ( dev_priv->cp_running ) {
1392112015Sanholt		DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
139395584Sanholt		return 0;
139495584Sanholt	}
139595584Sanholt	if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) {
139695584Sanholt		DRM_DEBUG( "%s called with bogus CP mode (%d)\n",
1397112015Sanholt			   __FUNCTION__, dev_priv->cp_mode );
139895584Sanholt		return 0;
139995584Sanholt	}
140095584Sanholt
140195584Sanholt	radeon_do_cp_start( dev_priv );
140295584Sanholt
140395584Sanholt	return 0;
140495584Sanholt}
140595584Sanholt
140695584Sanholt/* Stop the CP.  The engine must have been idled before calling this
140795584Sanholt * routine.
140895584Sanholt */
1409112015Sanholtint radeon_cp_stop( DRM_IOCTL_ARGS )
141095584Sanholt{
1411112015Sanholt	DRM_DEVICE;
141295584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
141395584Sanholt	drm_radeon_cp_stop_t stop;
141495584Sanholt	int ret;
1415112015Sanholt	DRM_DEBUG( "\n" );
141695584Sanholt
1417113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
141895584Sanholt
1419112015Sanholt	DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t *)data, sizeof(stop) );
142095584Sanholt
1421112015Sanholt	if (!dev_priv->cp_running)
1422112015Sanholt		return 0;
1423112015Sanholt
142495584Sanholt	/* Flush any pending CP commands.  This ensures any outstanding
142595584Sanholt	 * commands are exectuted by the engine before we turn it off.
142695584Sanholt	 */
142795584Sanholt	if ( stop.flush ) {
142895584Sanholt		radeon_do_cp_flush( dev_priv );
142995584Sanholt	}
143095584Sanholt
143195584Sanholt	/* If we fail to make the engine go idle, we return an error
143295584Sanholt	 * code so that the DRM ioctl wrapper can try again.
143395584Sanholt	 */
143495584Sanholt	if ( stop.idle ) {
143595584Sanholt		ret = radeon_do_cp_idle( dev_priv );
143695584Sanholt		if ( ret ) return ret;
143795584Sanholt	}
143895584Sanholt
143995584Sanholt	/* Finally, we can turn off the CP.  If the engine isn't idle,
144095584Sanholt	 * we will get some dropped triangles as they won't be fully
144195584Sanholt	 * rendered before the CP is shut down.
144295584Sanholt	 */
144395584Sanholt	radeon_do_cp_stop( dev_priv );
144495584Sanholt
144595584Sanholt	/* Reset the engine */
144695584Sanholt	radeon_do_engine_reset( dev );
144795584Sanholt
144895584Sanholt	return 0;
144995584Sanholt}
145095584Sanholt
1451112015Sanholt
1452112015Sanholtvoid radeon_do_release( drm_device_t *dev )
1453112015Sanholt{
1454112015Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1455112015Sanholt	int ret;
1456112015Sanholt
1457112015Sanholt	if (dev_priv) {
1458112015Sanholt		if (dev_priv->cp_running) {
1459112015Sanholt			/* Stop the cp */
1460112015Sanholt			while ((ret = radeon_do_cp_idle( dev_priv )) != 0) {
1461112015Sanholt				DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
1462112015Sanholt#ifdef __linux__
1463112015Sanholt				schedule();
1464112015Sanholt#else
1465112015Sanholt				tsleep(&ret, PZERO, "rdnrel", 1);
1466112015Sanholt#endif
1467112015Sanholt			}
1468112015Sanholt			radeon_do_cp_stop( dev_priv );
1469112015Sanholt			radeon_do_engine_reset( dev );
1470112015Sanholt		}
1471112015Sanholt
1472112015Sanholt		/* Disable *all* interrupts */
1473112015Sanholt		RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
1474112015Sanholt
1475112015Sanholt		/* Free memory heap structures */
1476119895Sanholt		radeon_mem_takedown( &(dev_priv->gart_heap) );
1477112015Sanholt		radeon_mem_takedown( &(dev_priv->fb_heap) );
1478112015Sanholt
1479112015Sanholt		/* deallocate kernel resources */
1480112015Sanholt		radeon_do_cleanup_cp( dev );
1481112015Sanholt	}
1482112015Sanholt}
1483112015Sanholt
148495584Sanholt/* Just reset the CP ring.  Called as part of an X Server engine reset.
148595584Sanholt */
1486112015Sanholtint radeon_cp_reset( DRM_IOCTL_ARGS )
148795584Sanholt{
1488112015Sanholt	DRM_DEVICE;
148995584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1490112015Sanholt	DRM_DEBUG( "\n" );
149195584Sanholt
1492113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
149395584Sanholt
149495584Sanholt	if ( !dev_priv ) {
1495112015Sanholt		DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
1496112015Sanholt		return DRM_ERR(EINVAL);
149795584Sanholt	}
149895584Sanholt
149995584Sanholt	radeon_do_cp_reset( dev_priv );
150095584Sanholt
150195584Sanholt	/* The CP is no longer running after an engine reset */
150295584Sanholt	dev_priv->cp_running = 0;
150395584Sanholt
150495584Sanholt	return 0;
150595584Sanholt}
150695584Sanholt
1507112015Sanholtint radeon_cp_idle( DRM_IOCTL_ARGS )
150895584Sanholt{
1509112015Sanholt	DRM_DEVICE;
151095584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1511112015Sanholt	DRM_DEBUG( "\n" );
151295584Sanholt
1513113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
151495584Sanholt
151595584Sanholt	return radeon_do_cp_idle( dev_priv );
151695584Sanholt}
151795584Sanholt
1518119098Sanholt/* Added by Charl P. Botha to call radeon_do_resume_cp().
1519119098Sanholt */
1520119098Sanholtint radeon_cp_resume( DRM_IOCTL_ARGS )
1521119098Sanholt{
1522119098Sanholt	DRM_DEVICE;
1523119098Sanholt
1524119098Sanholt	return radeon_do_resume_cp(dev);
1525119098Sanholt}
1526119098Sanholt
1527119098Sanholt
1528112015Sanholtint radeon_engine_reset( DRM_IOCTL_ARGS )
152995584Sanholt{
1530112015Sanholt	DRM_DEVICE;
1531112015Sanholt	DRM_DEBUG( "\n" );
153295584Sanholt
1533113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
153495584Sanholt
153595584Sanholt	return radeon_do_engine_reset( dev );
153695584Sanholt}
153795584Sanholt
153895584Sanholt
153995584Sanholt/* ================================================================
154095584Sanholt * Fullscreen mode
154195584Sanholt */
154295584Sanholt
1543112015Sanholt/* KW: Deprecated to say the least:
1544112015Sanholt */
1545112015Sanholtint radeon_fullscreen( DRM_IOCTL_ARGS )
154695584Sanholt{
154795584Sanholt	return 0;
154895584Sanholt}
154995584Sanholt
155095584Sanholt
155195584Sanholt/* ================================================================
155295584Sanholt * Freelist management
155395584Sanholt */
155495584Sanholt
1555112015Sanholt/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
1556112015Sanholt *   bufs until freelist code is used.  Note this hides a problem with
1557112015Sanholt *   the scratch register * (used to keep track of last buffer
1558112015Sanholt *   completed) being written to before * the last buffer has actually
1559112015Sanholt *   completed rendering.
1560112015Sanholt *
1561112015Sanholt * KW:  It's also a good way to find free buffers quickly.
1562112015Sanholt *
1563112015Sanholt * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
1564112015Sanholt * sleep.  However, bugs in older versions of radeon_accel.c mean that
1565112015Sanholt * we essentially have to do this, else old clients will break.
1566112015Sanholt *
1567112015Sanholt * However, it does leave open a potential deadlock where all the
1568112015Sanholt * buffers are held by other clients, which can't release them because
1569112015Sanholt * they can't get the lock.
1570112015Sanholt */
1571112015Sanholt
1572112015Sanholtdrm_buf_t *radeon_freelist_get( drm_device_t *dev )
157395584Sanholt{
157495584Sanholt	drm_device_dma_t *dma = dev->dma;
157595584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
1576112015Sanholt	drm_radeon_buf_priv_t *buf_priv;
157795584Sanholt	drm_buf_t *buf;
1578112015Sanholt	int i, t;
1579112015Sanholt	int start;
158095584Sanholt
1581112015Sanholt	if ( ++dev_priv->last_buf >= dma->buf_count )
1582112015Sanholt		dev_priv->last_buf = 0;
158395584Sanholt
1584112015Sanholt	start = dev_priv->last_buf;
158595584Sanholt
1586112015Sanholt	for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
1587112015Sanholt		u32 done_age = GET_SCRATCH( 1 );
1588112015Sanholt		DRM_DEBUG("done_age = %d\n",done_age);
1589112015Sanholt		for ( i = start ; i < dma->buf_count ; i++ ) {
1590112015Sanholt			buf = dma->buflist[i];
1591112015Sanholt			buf_priv = buf->dev_private;
1592113995Sanholt			if ( buf->filp == 0 || (buf->pending &&
1593112015Sanholt					       buf_priv->age <= done_age) ) {
1594112015Sanholt				dev_priv->stats.requested_bufs++;
1595112015Sanholt				buf->pending = 0;
1596112015Sanholt				return buf;
1597112015Sanholt			}
1598112015Sanholt			start = 0;
1599112015Sanholt		}
160095584Sanholt
1601112015Sanholt		if (t) {
1602112015Sanholt			DRM_UDELAY( 1 );
1603112015Sanholt			dev_priv->stats.freelist_loops++;
1604112015Sanholt		}
160595584Sanholt	}
160695584Sanholt
1607112015Sanholt	DRM_DEBUG( "returning NULL!\n" );
1608112015Sanholt	return NULL;
160995584Sanholt}
1610112015Sanholt#if 0
161195584Sanholtdrm_buf_t *radeon_freelist_get( drm_device_t *dev )
161295584Sanholt{
161395584Sanholt	drm_device_dma_t *dma = dev->dma;
161495584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
161595584Sanholt	drm_radeon_buf_priv_t *buf_priv;
161695584Sanholt	drm_buf_t *buf;
161795584Sanholt	int i, t;
161895584Sanholt	int start;
1619112015Sanholt	u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
162095584Sanholt
162195584Sanholt	if ( ++dev_priv->last_buf >= dma->buf_count )
162295584Sanholt		dev_priv->last_buf = 0;
1623112015Sanholt
162495584Sanholt	start = dev_priv->last_buf;
1625112015Sanholt	dev_priv->stats.freelist_loops++;
1626112015Sanholt
1627112015Sanholt	for ( t = 0 ; t < 2 ; t++ ) {
162895584Sanholt		for ( i = start ; i < dma->buf_count ; i++ ) {
162995584Sanholt			buf = dma->buflist[i];
163095584Sanholt			buf_priv = buf->dev_private;
1631113995Sanholt			if ( buf->filp == 0 || (buf->pending &&
1632112015Sanholt					       buf_priv->age <= done_age) ) {
1633112015Sanholt				dev_priv->stats.requested_bufs++;
163495584Sanholt				buf->pending = 0;
163595584Sanholt				return buf;
163695584Sanholt			}
163795584Sanholt		}
1638112015Sanholt		start = 0;
163995584Sanholt	}
164095584Sanholt
164195584Sanholt	return NULL;
164295584Sanholt}
1643112015Sanholt#endif
164495584Sanholt
164595584Sanholtvoid radeon_freelist_reset( drm_device_t *dev )
164695584Sanholt{
164795584Sanholt	drm_device_dma_t *dma = dev->dma;
164895584Sanholt	drm_radeon_private_t *dev_priv = dev->dev_private;
164995584Sanholt	int i;
165095584Sanholt
165195584Sanholt	dev_priv->last_buf = 0;
165295584Sanholt	for ( i = 0 ; i < dma->buf_count ; i++ ) {
165395584Sanholt		drm_buf_t *buf = dma->buflist[i];
165495584Sanholt		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
165595584Sanholt		buf_priv->age = 0;
165695584Sanholt	}
165795584Sanholt}
165895584Sanholt
165995584Sanholt
166095584Sanholt/* ================================================================
166195584Sanholt * CP command submission
166295584Sanholt */
166395584Sanholt
166495584Sanholtint radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
166595584Sanholt{
166695584Sanholt	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
166795584Sanholt	int i;
1668113995Sanholt	u32 last_head = GET_RING_HEAD( dev_priv );
166995584Sanholt
167095584Sanholt	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
1671113995Sanholt		u32 head = GET_RING_HEAD( dev_priv );
1672112015Sanholt
1673112015Sanholt		ring->space = (head - ring->tail) * sizeof(u32);
1674112015Sanholt		if ( ring->space <= 0 )
1675112015Sanholt			ring->space += ring->size;
167695584Sanholt		if ( ring->space > n )
167795584Sanholt			return 0;
1678112015Sanholt
1679112015Sanholt		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
1680112015Sanholt
1681112015Sanholt		if (head != last_head)
1682112015Sanholt			i = 0;
1683112015Sanholt		last_head = head;
1684112015Sanholt
1685112015Sanholt		DRM_UDELAY( 1 );
168695584Sanholt	}
168795584Sanholt
168895584Sanholt	/* FIXME: This return value is ignored in the BEGIN_RING macro! */
168995584Sanholt#if RADEON_FIFO_DEBUG
169095584Sanholt	radeon_status( dev_priv );
169195584Sanholt	DRM_ERROR( "failed!\n" );
169295584Sanholt#endif
1693112015Sanholt	return DRM_ERR(EBUSY);
169495584Sanholt}
169595584Sanholt
1696113995Sanholtstatic int radeon_cp_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d )
169795584Sanholt{
169895584Sanholt	int i;
169995584Sanholt	drm_buf_t *buf;
170095584Sanholt
170195584Sanholt	for ( i = d->granted_count ; i < d->request_count ; i++ ) {
170295584Sanholt		buf = radeon_freelist_get( dev );
1703112015Sanholt		if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */
170495584Sanholt
1705113995Sanholt		buf->filp = filp;
170695584Sanholt
1707112015Sanholt		if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
170895584Sanholt				   sizeof(buf->idx) ) )
1709112015Sanholt			return DRM_ERR(EFAULT);
1710112015Sanholt		if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
171195584Sanholt				   sizeof(buf->total) ) )
1712112015Sanholt			return DRM_ERR(EFAULT);
171395584Sanholt
171495584Sanholt		d->granted_count++;
171595584Sanholt	}
171695584Sanholt	return 0;
171795584Sanholt}
171895584Sanholt
1719112015Sanholtint radeon_cp_buffers( DRM_IOCTL_ARGS )
172095584Sanholt{
1721112015Sanholt	DRM_DEVICE;
172295584Sanholt	drm_device_dma_t *dma = dev->dma;
172395584Sanholt	int ret = 0;
172495584Sanholt	drm_dma_t d;
172595584Sanholt
1726113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
172795584Sanholt
1728112015Sanholt	DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *)data, sizeof(d) );
172995584Sanholt
173095584Sanholt	/* Please don't send us buffers.
173195584Sanholt	 */
173295584Sanholt	if ( d.send_count != 0 ) {
173395584Sanholt		DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
1734112015Sanholt			   DRM_CURRENTPID, d.send_count );
1735112015Sanholt		return DRM_ERR(EINVAL);
173695584Sanholt	}
173795584Sanholt
173895584Sanholt	/* We'll send you buffers.
173995584Sanholt	 */
174095584Sanholt	if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
174195584Sanholt		DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
1742112015Sanholt			   DRM_CURRENTPID, d.request_count, dma->buf_count );
1743112015Sanholt		return DRM_ERR(EINVAL);
174495584Sanholt	}
174595584Sanholt
174695584Sanholt	d.granted_count = 0;
174795584Sanholt
174895584Sanholt	if ( d.request_count ) {
1749113995Sanholt		ret = radeon_cp_get_buffers( filp, dev, &d );
175095584Sanholt	}
175195584Sanholt
1752112015Sanholt	DRM_COPY_TO_USER_IOCTL( (drm_dma_t *)data, d, sizeof(d) );
175395584Sanholt
175495584Sanholt	return ret;
175595584Sanholt}
1756