xref: /titanic_50/usr/src/uts/intel/io/drm/radeon_cp.c (revision e57b9183811d515e3bbcd1a104516f0102fde114)
1*e57b9183Scg149915 /*
2*e57b9183Scg149915  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3*e57b9183Scg149915  * Use is subject to license terms.
4*e57b9183Scg149915  */
5*e57b9183Scg149915 
6*e57b9183Scg149915 /* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */
7*e57b9183Scg149915 /*
8*e57b9183Scg149915  * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
9*e57b9183Scg149915  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
10*e57b9183Scg149915  * All Rights Reserved.
11*e57b9183Scg149915  *
12*e57b9183Scg149915  * Permission is hereby granted, free of charge, to any person obtaining a
13*e57b9183Scg149915  * copy of this software and associated documentation files (the "Software"),
14*e57b9183Scg149915  * to deal in the Software without restriction, including without limitation
15*e57b9183Scg149915  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16*e57b9183Scg149915  * and/or sell copies of the Software, and to permit persons to whom the
17*e57b9183Scg149915  * Software is furnished to do so, subject to the following conditions:
18*e57b9183Scg149915  *
19*e57b9183Scg149915  * The above copyright notice and this permission notice (including the next
20*e57b9183Scg149915  * paragraph) shall be included in all copies or substantial portions of the
21*e57b9183Scg149915  * Software.
22*e57b9183Scg149915  *
23*e57b9183Scg149915  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24*e57b9183Scg149915  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25*e57b9183Scg149915  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
26*e57b9183Scg149915  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
27*e57b9183Scg149915  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28*e57b9183Scg149915  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29*e57b9183Scg149915  * DEALINGS IN THE SOFTWARE.
30*e57b9183Scg149915  *
31*e57b9183Scg149915  * Authors:
32*e57b9183Scg149915  *    Kevin E. Martin <martin@valinux.com>
33*e57b9183Scg149915  *    Gareth Hughes <gareth@valinux.com>
34*e57b9183Scg149915  */
35*e57b9183Scg149915 
36*e57b9183Scg149915 #pragma ident	"%Z%%M%	%I%	%E% SMI"
37*e57b9183Scg149915 
38*e57b9183Scg149915 #include "drmP.h"
39*e57b9183Scg149915 #include "drm.h"
40*e57b9183Scg149915 #include "radeon_drm.h"
41*e57b9183Scg149915 #include "radeon_drv.h"
42*e57b9183Scg149915 #include "r300_reg.h"
43*e57b9183Scg149915 #include "radeon_io32.h"
44*e57b9183Scg149915 
45*e57b9183Scg149915 static int radeon_do_cleanup_cp(drm_device_t *dev);
46*e57b9183Scg149915 
47*e57b9183Scg149915 /* CP microcode (from ATI) */
48*e57b9183Scg149915 static const u32 R200_cp_microcode[][2] = {
49*e57b9183Scg149915 	{0x21007000, 0000000000},
50*e57b9183Scg149915 	{0x20007000, 0000000000},
51*e57b9183Scg149915 	{0x000000ab, 0x00000004},
52*e57b9183Scg149915 	{0x000000af, 0x00000004},
53*e57b9183Scg149915 	{0x66544a49, 0000000000},
54*e57b9183Scg149915 	{0x49494174, 0000000000},
55*e57b9183Scg149915 	{0x54517d83, 0000000000},
56*e57b9183Scg149915 	{0x498d8b64, 0000000000},
57*e57b9183Scg149915 	{0x49494949, 0000000000},
58*e57b9183Scg149915 	{0x49da493c, 0000000000},
59*e57b9183Scg149915 	{0x49989898, 0000000000},
60*e57b9183Scg149915 	{0xd34949d5, 0000000000},
61*e57b9183Scg149915 	{0x9dc90e11, 0000000000},
62*e57b9183Scg149915 	{0xce9b9b9b, 0000000000},
63*e57b9183Scg149915 	{0x000f0000, 0x00000016},
64*e57b9183Scg149915 	{0x352e232c, 0000000000},
65*e57b9183Scg149915 	{0x00000013, 0x00000004},
66*e57b9183Scg149915 	{0x000f0000, 0x00000016},
67*e57b9183Scg149915 	{0x352e272c, 0000000000},
68*e57b9183Scg149915 	{0x000f0001, 0x00000016},
69*e57b9183Scg149915 	{0x3239362f, 0000000000},
70*e57b9183Scg149915 	{0x000077ef, 0x00000002},
71*e57b9183Scg149915 	{0x00061000, 0x00000002},
72*e57b9183Scg149915 	{0x00000020, 0x0000001a},
73*e57b9183Scg149915 	{0x00004000, 0x0000001e},
74*e57b9183Scg149915 	{0x00061000, 0x00000002},
75*e57b9183Scg149915 	{0x00000020, 0x0000001a},
76*e57b9183Scg149915 	{0x00004000, 0x0000001e},
77*e57b9183Scg149915 	{0x00061000, 0x00000002},
78*e57b9183Scg149915 	{0x00000020, 0x0000001a},
79*e57b9183Scg149915 	{0x00004000, 0x0000001e},
80*e57b9183Scg149915 	{0x00000016, 0x00000004},
81*e57b9183Scg149915 	{0x0003802a, 0x00000002},
82*e57b9183Scg149915 	{0x040067e0, 0x00000002},
83*e57b9183Scg149915 	{0x00000016, 0x00000004},
84*e57b9183Scg149915 	{0x000077e0, 0x00000002},
85*e57b9183Scg149915 	{0x00065000, 0x00000002},
86*e57b9183Scg149915 	{0x000037e1, 0x00000002},
87*e57b9183Scg149915 	{0x040067e1, 0x00000006},
88*e57b9183Scg149915 	{0x000077e0, 0x00000002},
89*e57b9183Scg149915 	{0x000077e1, 0x00000002},
90*e57b9183Scg149915 	{0x000077e1, 0x00000006},
91*e57b9183Scg149915 	{0xffffffff, 0000000000},
92*e57b9183Scg149915 	{0x10000000, 0000000000},
93*e57b9183Scg149915 	{0x0003802a, 0x00000002},
94*e57b9183Scg149915 	{0x040067e0, 0x00000006},
95*e57b9183Scg149915 	{0x00007675, 0x00000002},
96*e57b9183Scg149915 	{0x00007676, 0x00000002},
97*e57b9183Scg149915 	{0x00007677, 0x00000002},
98*e57b9183Scg149915 	{0x00007678, 0x00000006},
99*e57b9183Scg149915 	{0x0003802b, 0x00000002},
100*e57b9183Scg149915 	{0x04002676, 0x00000002},
101*e57b9183Scg149915 	{0x00007677, 0x00000002},
102*e57b9183Scg149915 	{0x00007678, 0x00000006},
103*e57b9183Scg149915 	{0x0000002e, 0x00000018},
104*e57b9183Scg149915 	{0x0000002e, 0x00000018},
105*e57b9183Scg149915 	{0000000000, 0x00000006},
106*e57b9183Scg149915 	{0x0000002f, 0x00000018},
107*e57b9183Scg149915 	{0x0000002f, 0x00000018},
108*e57b9183Scg149915 	{0000000000, 0x00000006},
109*e57b9183Scg149915 	{0x01605000, 0x00000002},
110*e57b9183Scg149915 	{0x00065000, 0x00000002},
111*e57b9183Scg149915 	{0x00098000, 0x00000002},
112*e57b9183Scg149915 	{0x00061000, 0x00000002},
113*e57b9183Scg149915 	{0x64c0603d, 0x00000004},
114*e57b9183Scg149915 	{0x00080000, 0x00000016},
115*e57b9183Scg149915 	{0000000000, 0000000000},
116*e57b9183Scg149915 	{0x0400251d, 0x00000002},
117*e57b9183Scg149915 	{0x00007580, 0x00000002},
118*e57b9183Scg149915 	{0x00067581, 0x00000002},
119*e57b9183Scg149915 	{0x04002580, 0x00000002},
120*e57b9183Scg149915 	{0x00067581, 0x00000002},
121*e57b9183Scg149915 	{0x00000046, 0x00000004},
122*e57b9183Scg149915 	{0x00005000, 0000000000},
123*e57b9183Scg149915 	{0x00061000, 0x00000002},
124*e57b9183Scg149915 	{0x0000750e, 0x00000002},
125*e57b9183Scg149915 	{0x00019000, 0x00000002},
126*e57b9183Scg149915 	{0x00011055, 0x00000014},
127*e57b9183Scg149915 	{0x00000055, 0x00000012},
128*e57b9183Scg149915 	{0x0400250f, 0x00000002},
129*e57b9183Scg149915 	{0x0000504a, 0x00000004},
130*e57b9183Scg149915 	{0x00007565, 0x00000002},
131*e57b9183Scg149915 	{0x00007566, 0x00000002},
132*e57b9183Scg149915 	{0x00000051, 0x00000004},
133*e57b9183Scg149915 	{0x01e655b4, 0x00000002},
134*e57b9183Scg149915 	{0x4401b0dc, 0x00000002},
135*e57b9183Scg149915 	{0x01c110dc, 0x00000002},
136*e57b9183Scg149915 	{0x2666705d, 0x00000018},
137*e57b9183Scg149915 	{0x040c2565, 0x00000002},
138*e57b9183Scg149915 	{0x0000005d, 0x00000018},
139*e57b9183Scg149915 	{0x04002564, 0x00000002},
140*e57b9183Scg149915 	{0x00007566, 0x00000002},
141*e57b9183Scg149915 	{0x00000054, 0x00000004},
142*e57b9183Scg149915 	{0x00401060, 0x00000008},
143*e57b9183Scg149915 	{0x00101000, 0x00000002},
144*e57b9183Scg149915 	{0x000d80ff, 0x00000002},
145*e57b9183Scg149915 	{0x00800063, 0x00000008},
146*e57b9183Scg149915 	{0x000f9000, 0x00000002},
147*e57b9183Scg149915 	{0x000e00ff, 0x00000002},
148*e57b9183Scg149915 	{0000000000, 0x00000006},
149*e57b9183Scg149915 	{0x00000080, 0x00000018},
150*e57b9183Scg149915 	{0x00000054, 0x00000004},
151*e57b9183Scg149915 	{0x00007576, 0x00000002},
152*e57b9183Scg149915 	{0x00065000, 0x00000002},
153*e57b9183Scg149915 	{0x00009000, 0x00000002},
154*e57b9183Scg149915 	{0x00041000, 0x00000002},
155*e57b9183Scg149915 	{0x0c00350e, 0x00000002},
156*e57b9183Scg149915 	{0x00049000, 0x00000002},
157*e57b9183Scg149915 	{0x00051000, 0x00000002},
158*e57b9183Scg149915 	{0x01e785f8, 0x00000002},
159*e57b9183Scg149915 	{0x00200000, 0x00000002},
160*e57b9183Scg149915 	{0x00600073, 0x0000000c},
161*e57b9183Scg149915 	{0x00007563, 0x00000002},
162*e57b9183Scg149915 	{0x006075f0, 0x00000021},
163*e57b9183Scg149915 	{0x20007068, 0x00000004},
164*e57b9183Scg149915 	{0x00005068, 0x00000004},
165*e57b9183Scg149915 	{0x00007576, 0x00000002},
166*e57b9183Scg149915 	{0x00007577, 0x00000002},
167*e57b9183Scg149915 	{0x0000750e, 0x00000002},
168*e57b9183Scg149915 	{0x0000750f, 0x00000002},
169*e57b9183Scg149915 	{0x00a05000, 0x00000002},
170*e57b9183Scg149915 	{0x00600076, 0x0000000c},
171*e57b9183Scg149915 	{0x006075f0, 0x00000021},
172*e57b9183Scg149915 	{0x000075f8, 0x00000002},
173*e57b9183Scg149915 	{0x00000076, 0x00000004},
174*e57b9183Scg149915 	{0x000a750e, 0x00000002},
175*e57b9183Scg149915 	{0x0020750f, 0x00000002},
176*e57b9183Scg149915 	{0x00600079, 0x00000004},
177*e57b9183Scg149915 	{0x00007570, 0x00000002},
178*e57b9183Scg149915 	{0x00007571, 0x00000002},
179*e57b9183Scg149915 	{0x00007572, 0x00000006},
180*e57b9183Scg149915 	{0x00005000, 0x00000002},
181*e57b9183Scg149915 	{0x00a05000, 0x00000002},
182*e57b9183Scg149915 	{0x00007568, 0x00000002},
183*e57b9183Scg149915 	{0x00061000, 0x00000002},
184*e57b9183Scg149915 	{0x00000084, 0x0000000c},
185*e57b9183Scg149915 	{0x00058000, 0x00000002},
186*e57b9183Scg149915 	{0x0c607562, 0x00000002},
187*e57b9183Scg149915 	{0x00000086, 0x00000004},
188*e57b9183Scg149915 	{0x00600085, 0x00000004},
189*e57b9183Scg149915 	{0x400070dd, 0000000000},
190*e57b9183Scg149915 	{0x000380dd, 0x00000002},
191*e57b9183Scg149915 	{0x00000093, 0x0000001c},
192*e57b9183Scg149915 	{0x00065095, 0x00000018},
193*e57b9183Scg149915 	{0x040025bb, 0x00000002},
194*e57b9183Scg149915 	{0x00061096, 0x00000018},
195*e57b9183Scg149915 	{0x040075bc, 0000000000},
196*e57b9183Scg149915 	{0x000075bb, 0x00000002},
197*e57b9183Scg149915 	{0x000075bc, 0000000000},
198*e57b9183Scg149915 	{0x00090000, 0x00000006},
199*e57b9183Scg149915 	{0x00090000, 0x00000002},
200*e57b9183Scg149915 	{0x000d8002, 0x00000006},
201*e57b9183Scg149915 	{0x00005000, 0x00000002},
202*e57b9183Scg149915 	{0x00007821, 0x00000002},
203*e57b9183Scg149915 	{0x00007800, 0000000000},
204*e57b9183Scg149915 	{0x00007821, 0x00000002},
205*e57b9183Scg149915 	{0x00007800, 0000000000},
206*e57b9183Scg149915 	{0x01665000, 0x00000002},
207*e57b9183Scg149915 	{0x000a0000, 0x00000002},
208*e57b9183Scg149915 	{0x000671cc, 0x00000002},
209*e57b9183Scg149915 	{0x0286f1cd, 0x00000002},
210*e57b9183Scg149915 	{0x000000a3, 0x00000010},
211*e57b9183Scg149915 	{0x21007000, 0000000000},
212*e57b9183Scg149915 	{0x000000aa, 0x0000001c},
213*e57b9183Scg149915 	{0x00065000, 0x00000002},
214*e57b9183Scg149915 	{0x000a0000, 0x00000002},
215*e57b9183Scg149915 	{0x00061000, 0x00000002},
216*e57b9183Scg149915 	{0x000b0000, 0x00000002},
217*e57b9183Scg149915 	{0x38067000, 0x00000002},
218*e57b9183Scg149915 	{0x000a00a6, 0x00000004},
219*e57b9183Scg149915 	{0x20007000, 0000000000},
220*e57b9183Scg149915 	{0x01200000, 0x00000002},
221*e57b9183Scg149915 	{0x20077000, 0x00000002},
222*e57b9183Scg149915 	{0x01200000, 0x00000002},
223*e57b9183Scg149915 	{0x20007000, 0000000000},
224*e57b9183Scg149915 	{0x00061000, 0x00000002},
225*e57b9183Scg149915 	{0x0120751b, 0x00000002},
226*e57b9183Scg149915 	{0x8040750a, 0x00000002},
227*e57b9183Scg149915 	{0x8040750b, 0x00000002},
228*e57b9183Scg149915 	{0x00110000, 0x00000002},
229*e57b9183Scg149915 	{0x000380dd, 0x00000002},
230*e57b9183Scg149915 	{0x000000bd, 0x0000001c},
231*e57b9183Scg149915 	{0x00061096, 0x00000018},
232*e57b9183Scg149915 	{0x844075bd, 0x00000002},
233*e57b9183Scg149915 	{0x00061095, 0x00000018},
234*e57b9183Scg149915 	{0x840075bb, 0x00000002},
235*e57b9183Scg149915 	{0x00061096, 0x00000018},
236*e57b9183Scg149915 	{0x844075bc, 0x00000002},
237*e57b9183Scg149915 	{0x000000c0, 0x00000004},
238*e57b9183Scg149915 	{0x804075bd, 0x00000002},
239*e57b9183Scg149915 	{0x800075bb, 0x00000002},
240*e57b9183Scg149915 	{0x804075bc, 0x00000002},
241*e57b9183Scg149915 	{0x00108000, 0x00000002},
242*e57b9183Scg149915 	{0x01400000, 0x00000002},
243*e57b9183Scg149915 	{0x006000c4, 0x0000000c},
244*e57b9183Scg149915 	{0x20c07000, 0x00000020},
245*e57b9183Scg149915 	{0x000000c6, 0x00000012},
246*e57b9183Scg149915 	{0x00800000, 0x00000006},
247*e57b9183Scg149915 	{0x0080751d, 0x00000006},
248*e57b9183Scg149915 	{0x000025bb, 0x00000002},
249*e57b9183Scg149915 	{0x000040c0, 0x00000004},
250*e57b9183Scg149915 	{0x0000775c, 0x00000002},
251*e57b9183Scg149915 	{0x00a05000, 0x00000002},
252*e57b9183Scg149915 	{0x00661000, 0x00000002},
253*e57b9183Scg149915 	{0x0460275d, 0x00000020},
254*e57b9183Scg149915 	{0x00004000, 0000000000},
255*e57b9183Scg149915 	{0x00007999, 0x00000002},
256*e57b9183Scg149915 	{0x00a05000, 0x00000002},
257*e57b9183Scg149915 	{0x00661000, 0x00000002},
258*e57b9183Scg149915 	{0x0460299b, 0x00000020},
259*e57b9183Scg149915 	{0x00004000, 0000000000},
260*e57b9183Scg149915 	{0x01e00830, 0x00000002},
261*e57b9183Scg149915 	{0x21007000, 0000000000},
262*e57b9183Scg149915 	{0x00005000, 0x00000002},
263*e57b9183Scg149915 	{0x00038042, 0x00000002},
264*e57b9183Scg149915 	{0x040025e0, 0x00000002},
265*e57b9183Scg149915 	{0x000075e1, 0000000000},
266*e57b9183Scg149915 	{0x00000001, 0000000000},
267*e57b9183Scg149915 	{0x000380d9, 0x00000002},
268*e57b9183Scg149915 	{0x04007394, 0000000000},
269*e57b9183Scg149915 	{0000000000, 0000000000},
270*e57b9183Scg149915 	{0000000000, 0000000000},
271*e57b9183Scg149915 	{0000000000, 0000000000},
272*e57b9183Scg149915 	{0000000000, 0000000000},
273*e57b9183Scg149915 	{0000000000, 0000000000},
274*e57b9183Scg149915 	{0000000000, 0000000000},
275*e57b9183Scg149915 	{0000000000, 0000000000},
276*e57b9183Scg149915 	{0000000000, 0000000000},
277*e57b9183Scg149915 	{0000000000, 0000000000},
278*e57b9183Scg149915 	{0000000000, 0000000000},
279*e57b9183Scg149915 	{0000000000, 0000000000},
280*e57b9183Scg149915 	{0000000000, 0000000000},
281*e57b9183Scg149915 	{0000000000, 0000000000},
282*e57b9183Scg149915 	{0000000000, 0000000000},
283*e57b9183Scg149915 	{0000000000, 0000000000},
284*e57b9183Scg149915 	{0000000000, 0000000000},
285*e57b9183Scg149915 	{0000000000, 0000000000},
286*e57b9183Scg149915 	{0000000000, 0000000000},
287*e57b9183Scg149915 	{0000000000, 0000000000},
288*e57b9183Scg149915 	{0000000000, 0000000000},
289*e57b9183Scg149915 	{0000000000, 0000000000},
290*e57b9183Scg149915 	{0000000000, 0000000000},
291*e57b9183Scg149915 	{0000000000, 0000000000},
292*e57b9183Scg149915 	{0000000000, 0000000000},
293*e57b9183Scg149915 	{0000000000, 0000000000},
294*e57b9183Scg149915 	{0000000000, 0000000000},
295*e57b9183Scg149915 	{0000000000, 0000000000},
296*e57b9183Scg149915 	{0000000000, 0000000000},
297*e57b9183Scg149915 	{0000000000, 0000000000},
298*e57b9183Scg149915 	{0000000000, 0000000000},
299*e57b9183Scg149915 	{0000000000, 0000000000},
300*e57b9183Scg149915 	{0000000000, 0000000000},
301*e57b9183Scg149915 	{0000000000, 0000000000},
302*e57b9183Scg149915 	{0000000000, 0000000000},
303*e57b9183Scg149915 	{0000000000, 0000000000},
304*e57b9183Scg149915 	{0000000000, 0000000000},
305*e57b9183Scg149915 };
306*e57b9183Scg149915 
307*e57b9183Scg149915 static const u32 radeon_cp_microcode[][2] = {
308*e57b9183Scg149915 	{0x21007000, 0000000000},
309*e57b9183Scg149915 	{0x20007000, 0000000000},
310*e57b9183Scg149915 	{0x000000b4, 0x00000004},
311*e57b9183Scg149915 	{0x000000b8, 0x00000004},
312*e57b9183Scg149915 	{0x6f5b4d4c, 0000000000},
313*e57b9183Scg149915 	{0x4c4c427f, 0000000000},
314*e57b9183Scg149915 	{0x5b568a92, 0000000000},
315*e57b9183Scg149915 	{0x4ca09c6d, 0000000000},
316*e57b9183Scg149915 	{0xad4c4c4c, 0000000000},
317*e57b9183Scg149915 	{0x4ce1af3d, 0000000000},
318*e57b9183Scg149915 	{0xd8afafaf, 0000000000},
319*e57b9183Scg149915 	{0xd64c4cdc, 0000000000},
320*e57b9183Scg149915 	{0x4cd10d10, 0000000000},
321*e57b9183Scg149915 	{0x000f0000, 0x00000016},
322*e57b9183Scg149915 	{0x362f242d, 0000000000},
323*e57b9183Scg149915 	{0x00000012, 0x00000004},
324*e57b9183Scg149915 	{0x000f0000, 0x00000016},
325*e57b9183Scg149915 	{0x362f282d, 0000000000},
326*e57b9183Scg149915 	{0x000380e7, 0x00000002},
327*e57b9183Scg149915 	{0x04002c97, 0x00000002},
328*e57b9183Scg149915 	{0x000f0001, 0x00000016},
329*e57b9183Scg149915 	{0x333a3730, 0000000000},
330*e57b9183Scg149915 	{0x000077ef, 0x00000002},
331*e57b9183Scg149915 	{0x00061000, 0x00000002},
332*e57b9183Scg149915 	{0x00000021, 0x0000001a},
333*e57b9183Scg149915 	{0x00004000, 0x0000001e},
334*e57b9183Scg149915 	{0x00061000, 0x00000002},
335*e57b9183Scg149915 	{0x00000021, 0x0000001a},
336*e57b9183Scg149915 	{0x00004000, 0x0000001e},
337*e57b9183Scg149915 	{0x00061000, 0x00000002},
338*e57b9183Scg149915 	{0x00000021, 0x0000001a},
339*e57b9183Scg149915 	{0x00004000, 0x0000001e},
340*e57b9183Scg149915 	{0x00000017, 0x00000004},
341*e57b9183Scg149915 	{0x0003802b, 0x00000002},
342*e57b9183Scg149915 	{0x040067e0, 0x00000002},
343*e57b9183Scg149915 	{0x00000017, 0x00000004},
344*e57b9183Scg149915 	{0x000077e0, 0x00000002},
345*e57b9183Scg149915 	{0x00065000, 0x00000002},
346*e57b9183Scg149915 	{0x000037e1, 0x00000002},
347*e57b9183Scg149915 	{0x040067e1, 0x00000006},
348*e57b9183Scg149915 	{0x000077e0, 0x00000002},
349*e57b9183Scg149915 	{0x000077e1, 0x00000002},
350*e57b9183Scg149915 	{0x000077e1, 0x00000006},
351*e57b9183Scg149915 	{0xffffffff, 0000000000},
352*e57b9183Scg149915 	{0x10000000, 0000000000},
353*e57b9183Scg149915 	{0x0003802b, 0x00000002},
354*e57b9183Scg149915 	{0x040067e0, 0x00000006},
355*e57b9183Scg149915 	{0x00007675, 0x00000002},
356*e57b9183Scg149915 	{0x00007676, 0x00000002},
357*e57b9183Scg149915 	{0x00007677, 0x00000002},
358*e57b9183Scg149915 	{0x00007678, 0x00000006},
359*e57b9183Scg149915 	{0x0003802c, 0x00000002},
360*e57b9183Scg149915 	{0x04002676, 0x00000002},
361*e57b9183Scg149915 	{0x00007677, 0x00000002},
362*e57b9183Scg149915 	{0x00007678, 0x00000006},
363*e57b9183Scg149915 	{0x0000002f, 0x00000018},
364*e57b9183Scg149915 	{0x0000002f, 0x00000018},
365*e57b9183Scg149915 	{0000000000, 0x00000006},
366*e57b9183Scg149915 	{0x00000030, 0x00000018},
367*e57b9183Scg149915 	{0x00000030, 0x00000018},
368*e57b9183Scg149915 	{0000000000, 0x00000006},
369*e57b9183Scg149915 	{0x01605000, 0x00000002},
370*e57b9183Scg149915 	{0x00065000, 0x00000002},
371*e57b9183Scg149915 	{0x00098000, 0x00000002},
372*e57b9183Scg149915 	{0x00061000, 0x00000002},
373*e57b9183Scg149915 	{0x64c0603e, 0x00000004},
374*e57b9183Scg149915 	{0x000380e6, 0x00000002},
375*e57b9183Scg149915 	{0x040025c5, 0x00000002},
376*e57b9183Scg149915 	{0x00080000, 0x00000016},
377*e57b9183Scg149915 	{0000000000, 0000000000},
378*e57b9183Scg149915 	{0x0400251d, 0x00000002},
379*e57b9183Scg149915 	{0x00007580, 0x00000002},
380*e57b9183Scg149915 	{0x00067581, 0x00000002},
381*e57b9183Scg149915 	{0x04002580, 0x00000002},
382*e57b9183Scg149915 	{0x00067581, 0x00000002},
383*e57b9183Scg149915 	{0x00000049, 0x00000004},
384*e57b9183Scg149915 	{0x00005000, 0000000000},
385*e57b9183Scg149915 	{0x000380e6, 0x00000002},
386*e57b9183Scg149915 	{0x040025c5, 0x00000002},
387*e57b9183Scg149915 	{0x00061000, 0x00000002},
388*e57b9183Scg149915 	{0x0000750e, 0x00000002},
389*e57b9183Scg149915 	{0x00019000, 0x00000002},
390*e57b9183Scg149915 	{0x00011055, 0x00000014},
391*e57b9183Scg149915 	{0x00000055, 0x00000012},
392*e57b9183Scg149915 	{0x0400250f, 0x00000002},
393*e57b9183Scg149915 	{0x0000504f, 0x00000004},
394*e57b9183Scg149915 	{0x000380e6, 0x00000002},
395*e57b9183Scg149915 	{0x040025c5, 0x00000002},
396*e57b9183Scg149915 	{0x00007565, 0x00000002},
397*e57b9183Scg149915 	{0x00007566, 0x00000002},
398*e57b9183Scg149915 	{0x00000058, 0x00000004},
399*e57b9183Scg149915 	{0x000380e6, 0x00000002},
400*e57b9183Scg149915 	{0x040025c5, 0x00000002},
401*e57b9183Scg149915 	{0x01e655b4, 0x00000002},
402*e57b9183Scg149915 	{0x4401b0e4, 0x00000002},
403*e57b9183Scg149915 	{0x01c110e4, 0x00000002},
404*e57b9183Scg149915 	{0x26667066, 0x00000018},
405*e57b9183Scg149915 	{0x040c2565, 0x00000002},
406*e57b9183Scg149915 	{0x00000066, 0x00000018},
407*e57b9183Scg149915 	{0x04002564, 0x00000002},
408*e57b9183Scg149915 	{0x00007566, 0x00000002},
409*e57b9183Scg149915 	{0x0000005d, 0x00000004},
410*e57b9183Scg149915 	{0x00401069, 0x00000008},
411*e57b9183Scg149915 	{0x00101000, 0x00000002},
412*e57b9183Scg149915 	{0x000d80ff, 0x00000002},
413*e57b9183Scg149915 	{0x0080006c, 0x00000008},
414*e57b9183Scg149915 	{0x000f9000, 0x00000002},
415*e57b9183Scg149915 	{0x000e00ff, 0x00000002},
416*e57b9183Scg149915 	{0000000000, 0x00000006},
417*e57b9183Scg149915 	{0x0000008f, 0x00000018},
418*e57b9183Scg149915 	{0x0000005b, 0x00000004},
419*e57b9183Scg149915 	{0x000380e6, 0x00000002},
420*e57b9183Scg149915 	{0x040025c5, 0x00000002},
421*e57b9183Scg149915 	{0x00007576, 0x00000002},
422*e57b9183Scg149915 	{0x00065000, 0x00000002},
423*e57b9183Scg149915 	{0x00009000, 0x00000002},
424*e57b9183Scg149915 	{0x00041000, 0x00000002},
425*e57b9183Scg149915 	{0x0c00350e, 0x00000002},
426*e57b9183Scg149915 	{0x00049000, 0x00000002},
427*e57b9183Scg149915 	{0x00051000, 0x00000002},
428*e57b9183Scg149915 	{0x01e785f8, 0x00000002},
429*e57b9183Scg149915 	{0x00200000, 0x00000002},
430*e57b9183Scg149915 	{0x0060007e, 0x0000000c},
431*e57b9183Scg149915 	{0x00007563, 0x00000002},
432*e57b9183Scg149915 	{0x006075f0, 0x00000021},
433*e57b9183Scg149915 	{0x20007073, 0x00000004},
434*e57b9183Scg149915 	{0x00005073, 0x00000004},
435*e57b9183Scg149915 	{0x000380e6, 0x00000002},
436*e57b9183Scg149915 	{0x040025c5, 0x00000002},
437*e57b9183Scg149915 	{0x00007576, 0x00000002},
438*e57b9183Scg149915 	{0x00007577, 0x00000002},
439*e57b9183Scg149915 	{0x0000750e, 0x00000002},
440*e57b9183Scg149915 	{0x0000750f, 0x00000002},
441*e57b9183Scg149915 	{0x00a05000, 0x00000002},
442*e57b9183Scg149915 	{0x00600083, 0x0000000c},
443*e57b9183Scg149915 	{0x006075f0, 0x00000021},
444*e57b9183Scg149915 	{0x000075f8, 0x00000002},
445*e57b9183Scg149915 	{0x00000083, 0x00000004},
446*e57b9183Scg149915 	{0x000a750e, 0x00000002},
447*e57b9183Scg149915 	{0x000380e6, 0x00000002},
448*e57b9183Scg149915 	{0x040025c5, 0x00000002},
449*e57b9183Scg149915 	{0x0020750f, 0x00000002},
450*e57b9183Scg149915 	{0x00600086, 0x00000004},
451*e57b9183Scg149915 	{0x00007570, 0x00000002},
452*e57b9183Scg149915 	{0x00007571, 0x00000002},
453*e57b9183Scg149915 	{0x00007572, 0x00000006},
454*e57b9183Scg149915 	{0x000380e6, 0x00000002},
455*e57b9183Scg149915 	{0x040025c5, 0x00000002},
456*e57b9183Scg149915 	{0x00005000, 0x00000002},
457*e57b9183Scg149915 	{0x00a05000, 0x00000002},
458*e57b9183Scg149915 	{0x00007568, 0x00000002},
459*e57b9183Scg149915 	{0x00061000, 0x00000002},
460*e57b9183Scg149915 	{0x00000095, 0x0000000c},
461*e57b9183Scg149915 	{0x00058000, 0x00000002},
462*e57b9183Scg149915 	{0x0c607562, 0x00000002},
463*e57b9183Scg149915 	{0x00000097, 0x00000004},
464*e57b9183Scg149915 	{0x000380e6, 0x00000002},
465*e57b9183Scg149915 	{0x040025c5, 0x00000002},
466*e57b9183Scg149915 	{0x00600096, 0x00000004},
467*e57b9183Scg149915 	{0x400070e5, 0000000000},
468*e57b9183Scg149915 	{0x000380e6, 0x00000002},
469*e57b9183Scg149915 	{0x040025c5, 0x00000002},
470*e57b9183Scg149915 	{0x000380e5, 0x00000002},
471*e57b9183Scg149915 	{0x000000a8, 0x0000001c},
472*e57b9183Scg149915 	{0x000650aa, 0x00000018},
473*e57b9183Scg149915 	{0x040025bb, 0x00000002},
474*e57b9183Scg149915 	{0x000610ab, 0x00000018},
475*e57b9183Scg149915 	{0x040075bc, 0000000000},
476*e57b9183Scg149915 	{0x000075bb, 0x00000002},
477*e57b9183Scg149915 	{0x000075bc, 0000000000},
478*e57b9183Scg149915 	{0x00090000, 0x00000006},
479*e57b9183Scg149915 	{0x00090000, 0x00000002},
480*e57b9183Scg149915 	{0x000d8002, 0x00000006},
481*e57b9183Scg149915 	{0x00007832, 0x00000002},
482*e57b9183Scg149915 	{0x00005000, 0x00000002},
483*e57b9183Scg149915 	{0x000380e7, 0x00000002},
484*e57b9183Scg149915 	{0x04002c97, 0x00000002},
485*e57b9183Scg149915 	{0x00007820, 0x00000002},
486*e57b9183Scg149915 	{0x00007821, 0x00000002},
487*e57b9183Scg149915 	{0x00007800, 0000000000},
488*e57b9183Scg149915 	{0x01200000, 0x00000002},
489*e57b9183Scg149915 	{0x20077000, 0x00000002},
490*e57b9183Scg149915 	{0x01200000, 0x00000002},
491*e57b9183Scg149915 	{0x20007000, 0x00000002},
492*e57b9183Scg149915 	{0x00061000, 0x00000002},
493*e57b9183Scg149915 	{0x0120751b, 0x00000002},
494*e57b9183Scg149915 	{0x8040750a, 0x00000002},
495*e57b9183Scg149915 	{0x8040750b, 0x00000002},
496*e57b9183Scg149915 	{0x00110000, 0x00000002},
497*e57b9183Scg149915 	{0x000380e5, 0x00000002},
498*e57b9183Scg149915 	{0x000000c6, 0x0000001c},
499*e57b9183Scg149915 	{0x000610ab, 0x00000018},
500*e57b9183Scg149915 	{0x844075bd, 0x00000002},
501*e57b9183Scg149915 	{0x000610aa, 0x00000018},
502*e57b9183Scg149915 	{0x840075bb, 0x00000002},
503*e57b9183Scg149915 	{0x000610ab, 0x00000018},
504*e57b9183Scg149915 	{0x844075bc, 0x00000002},
505*e57b9183Scg149915 	{0x000000c9, 0x00000004},
506*e57b9183Scg149915 	{0x804075bd, 0x00000002},
507*e57b9183Scg149915 	{0x800075bb, 0x00000002},
508*e57b9183Scg149915 	{0x804075bc, 0x00000002},
509*e57b9183Scg149915 	{0x00108000, 0x00000002},
510*e57b9183Scg149915 	{0x01400000, 0x00000002},
511*e57b9183Scg149915 	{0x006000cd, 0x0000000c},
512*e57b9183Scg149915 	{0x20c07000, 0x00000020},
513*e57b9183Scg149915 	{0x000000cf, 0x00000012},
514*e57b9183Scg149915 	{0x00800000, 0x00000006},
515*e57b9183Scg149915 	{0x0080751d, 0x00000006},
516*e57b9183Scg149915 	{0000000000, 0000000000},
517*e57b9183Scg149915 	{0x0000775c, 0x00000002},
518*e57b9183Scg149915 	{0x00a05000, 0x00000002},
519*e57b9183Scg149915 	{0x00661000, 0x00000002},
520*e57b9183Scg149915 	{0x0460275d, 0x00000020},
521*e57b9183Scg149915 	{0x00004000, 0000000000},
522*e57b9183Scg149915 	{0x01e00830, 0x00000002},
523*e57b9183Scg149915 	{0x21007000, 0000000000},
524*e57b9183Scg149915 	{0x6464614d, 0000000000},
525*e57b9183Scg149915 	{0x69687420, 0000000000},
526*e57b9183Scg149915 	{0x00000073, 0000000000},
527*e57b9183Scg149915 	{0000000000, 0000000000},
528*e57b9183Scg149915 	{0x00005000, 0x00000002},
529*e57b9183Scg149915 	{0x000380d0, 0x00000002},
530*e57b9183Scg149915 	{0x040025e0, 0x00000002},
531*e57b9183Scg149915 	{0x000075e1, 0000000000},
532*e57b9183Scg149915 	{0x00000001, 0000000000},
533*e57b9183Scg149915 	{0x000380e0, 0x00000002},
534*e57b9183Scg149915 	{0x04002394, 0x00000002},
535*e57b9183Scg149915 	{0x00005000, 0000000000},
536*e57b9183Scg149915 	{0000000000, 0000000000},
537*e57b9183Scg149915 	{0000000000, 0000000000},
538*e57b9183Scg149915 	{0x00000008, 0000000000},
539*e57b9183Scg149915 	{0x00000004, 0000000000},
540*e57b9183Scg149915 	{0000000000, 0000000000},
541*e57b9183Scg149915 	{0000000000, 0000000000},
542*e57b9183Scg149915 	{0000000000, 0000000000},
543*e57b9183Scg149915 	{0000000000, 0000000000},
544*e57b9183Scg149915 	{0000000000, 0000000000},
545*e57b9183Scg149915 	{0000000000, 0000000000},
546*e57b9183Scg149915 	{0000000000, 0000000000},
547*e57b9183Scg149915 	{0000000000, 0000000000},
548*e57b9183Scg149915 	{0000000000, 0000000000},
549*e57b9183Scg149915 	{0000000000, 0000000000},
550*e57b9183Scg149915 	{0000000000, 0000000000},
551*e57b9183Scg149915 	{0000000000, 0000000000},
552*e57b9183Scg149915 	{0000000000, 0000000000},
553*e57b9183Scg149915 	{0000000000, 0000000000},
554*e57b9183Scg149915 	{0000000000, 0000000000},
555*e57b9183Scg149915 	{0000000000, 0000000000},
556*e57b9183Scg149915 	{0000000000, 0000000000},
557*e57b9183Scg149915 	{0000000000, 0000000000},
558*e57b9183Scg149915 	{0000000000, 0000000000},
559*e57b9183Scg149915 	{0000000000, 0000000000},
560*e57b9183Scg149915 	{0000000000, 0000000000},
561*e57b9183Scg149915 	{0000000000, 0000000000},
562*e57b9183Scg149915 	{0000000000, 0000000000},
563*e57b9183Scg149915 	{0000000000, 0000000000},
564*e57b9183Scg149915 };
565*e57b9183Scg149915 
566*e57b9183Scg149915 static const u32 R300_cp_microcode[][2] = {
567*e57b9183Scg149915 	{ 0x4200e000, 0000000000 },
568*e57b9183Scg149915 	{ 0x4000e000, 0000000000 },
569*e57b9183Scg149915 	{ 0x000000af, 0x00000008 },
570*e57b9183Scg149915 	{ 0x000000b3, 0x00000008 },
571*e57b9183Scg149915 	{ 0x6c5a504f, 0000000000 },
572*e57b9183Scg149915 	{ 0x4f4f497a, 0000000000 },
573*e57b9183Scg149915 	{ 0x5a578288, 0000000000 },
574*e57b9183Scg149915 	{ 0x4f91906a, 0000000000 },
575*e57b9183Scg149915 	{ 0x4f4f4f4f, 0000000000 },
576*e57b9183Scg149915 	{ 0x4fe24f44, 0000000000 },
577*e57b9183Scg149915 	{ 0x4f9c9c9c, 0000000000 },
578*e57b9183Scg149915 	{ 0xdc4f4fde, 0000000000 },
579*e57b9183Scg149915 	{ 0xa1cd4f4f, 0000000000 },
580*e57b9183Scg149915 	{ 0xd29d9d9d, 0000000000 },
581*e57b9183Scg149915 	{ 0x4f0f9fd7, 0000000000 },
582*e57b9183Scg149915 	{ 0x000ca000, 0x00000004 },
583*e57b9183Scg149915 	{ 0x000d0012, 0x00000038 },
584*e57b9183Scg149915 	{ 0x0000e8b4, 0x00000004 },
585*e57b9183Scg149915 	{ 0x000d0014, 0x00000038 },
586*e57b9183Scg149915 	{ 0x0000e8b6, 0x00000004 },
587*e57b9183Scg149915 	{ 0x000d0016, 0x00000038 },
588*e57b9183Scg149915 	{ 0x0000e854, 0x00000004 },
589*e57b9183Scg149915 	{ 0x000d0018, 0x00000038 },
590*e57b9183Scg149915 	{ 0x0000e855, 0x00000004 },
591*e57b9183Scg149915 	{ 0x000d001a, 0x00000038 },
592*e57b9183Scg149915 	{ 0x0000e856, 0x00000004 },
593*e57b9183Scg149915 	{ 0x000d001c, 0x00000038 },
594*e57b9183Scg149915 	{ 0x0000e857, 0x00000004 },
595*e57b9183Scg149915 	{ 0x000d001e, 0x00000038 },
596*e57b9183Scg149915 	{ 0x0000e824, 0x00000004 },
597*e57b9183Scg149915 	{ 0x000d0020, 0x00000038 },
598*e57b9183Scg149915 	{ 0x0000e825, 0x00000004 },
599*e57b9183Scg149915 	{ 0x000d0022, 0x00000038 },
600*e57b9183Scg149915 	{ 0x0000e830, 0x00000004 },
601*e57b9183Scg149915 	{ 0x000d0024, 0x00000038 },
602*e57b9183Scg149915 	{ 0x0000f0c0, 0x00000004 },
603*e57b9183Scg149915 	{ 0x000d0026, 0x00000038 },
604*e57b9183Scg149915 	{ 0x0000f0c1, 0x00000004 },
605*e57b9183Scg149915 	{ 0x000d0028, 0x00000038 },
606*e57b9183Scg149915 	{ 0x0000f041, 0x00000004 },
607*e57b9183Scg149915 	{ 0x000d002a, 0x00000038 },
608*e57b9183Scg149915 	{ 0x0000f184, 0x00000004 },
609*e57b9183Scg149915 	{ 0x000d002c, 0x00000038 },
610*e57b9183Scg149915 	{ 0x0000f185, 0x00000004 },
611*e57b9183Scg149915 	{ 0x000d002e, 0x00000038 },
612*e57b9183Scg149915 	{ 0x0000f186, 0x00000004 },
613*e57b9183Scg149915 	{ 0x000d0030, 0x00000038 },
614*e57b9183Scg149915 	{ 0x0000f187, 0x00000004 },
615*e57b9183Scg149915 	{ 0x000d0032, 0x00000038 },
616*e57b9183Scg149915 	{ 0x0000f180, 0x00000004 },
617*e57b9183Scg149915 	{ 0x000d0034, 0x00000038 },
618*e57b9183Scg149915 	{ 0x0000f393, 0x00000004 },
619*e57b9183Scg149915 	{ 0x000d0036, 0x00000038 },
620*e57b9183Scg149915 	{ 0x0000f38a, 0x00000004 },
621*e57b9183Scg149915 	{ 0x000d0038, 0x00000038 },
622*e57b9183Scg149915 	{ 0x0000f38e, 0x00000004 },
623*e57b9183Scg149915 	{ 0x0000e821, 0x00000004 },
624*e57b9183Scg149915 	{ 0x0140a000, 0x00000004 },
625*e57b9183Scg149915 	{ 0x00000043, 0x00000018 },
626*e57b9183Scg149915 	{ 0x00cce800, 0x00000004 },
627*e57b9183Scg149915 	{ 0x001b0001, 0x00000004 },
628*e57b9183Scg149915 	{ 0x08004800, 0x00000004 },
629*e57b9183Scg149915 	{ 0x001b0001, 0x00000004 },
630*e57b9183Scg149915 	{ 0x08004800, 0x00000004 },
631*e57b9183Scg149915 	{ 0x001b0001, 0x00000004 },
632*e57b9183Scg149915 	{ 0x08004800, 0x00000004 },
633*e57b9183Scg149915 	{ 0x0000003a, 0x00000008 },
634*e57b9183Scg149915 	{ 0x0000a000, 0000000000 },
635*e57b9183Scg149915 	{ 0x02c0a000, 0x00000004 },
636*e57b9183Scg149915 	{ 0x000ca000, 0x00000004 },
637*e57b9183Scg149915 	{ 0x00130000, 0x00000004 },
638*e57b9183Scg149915 	{ 0x000c2000, 0x00000004 },
639*e57b9183Scg149915 	{ 0xc980c045, 0x00000008 },
640*e57b9183Scg149915 	{ 0x2000451d, 0x00000004 },
641*e57b9183Scg149915 	{ 0x0000e580, 0x00000004 },
642*e57b9183Scg149915 	{ 0x000ce581, 0x00000004 },
643*e57b9183Scg149915 	{ 0x08004580, 0x00000004 },
644*e57b9183Scg149915 	{ 0x000ce581, 0x00000004 },
645*e57b9183Scg149915 	{ 0x0000004c, 0x00000008 },
646*e57b9183Scg149915 	{ 0x0000a000, 0000000000 },
647*e57b9183Scg149915 	{ 0x000c2000, 0x00000004 },
648*e57b9183Scg149915 	{ 0x0000e50e, 0x00000004 },
649*e57b9183Scg149915 	{ 0x00032000, 0x00000004 },
650*e57b9183Scg149915 	{ 0x00022056, 0x00000028 },
651*e57b9183Scg149915 	{ 0x00000056, 0x00000024 },
652*e57b9183Scg149915 	{ 0x0800450f, 0x00000004 },
653*e57b9183Scg149915 	{ 0x0000a050, 0x00000008 },
654*e57b9183Scg149915 	{ 0x0000e565, 0x00000004 },
655*e57b9183Scg149915 	{ 0x0000e566, 0x00000004 },
656*e57b9183Scg149915 	{ 0x00000057, 0x00000008 },
657*e57b9183Scg149915 	{ 0x03cca5b4, 0x00000004 },
658*e57b9183Scg149915 	{ 0x05432000, 0x00000004 },
659*e57b9183Scg149915 	{ 0x00022000, 0x00000004 },
660*e57b9183Scg149915 	{ 0x4ccce063, 0x00000030 },
661*e57b9183Scg149915 	{ 0x08274565, 0x00000004 },
662*e57b9183Scg149915 	{ 0x00000063, 0x00000030 },
663*e57b9183Scg149915 	{ 0x08004564, 0x00000004 },
664*e57b9183Scg149915 	{ 0x0000e566, 0x00000004 },
665*e57b9183Scg149915 	{ 0x0000005a, 0x00000008 },
666*e57b9183Scg149915 	{ 0x00802066, 0x00000010 },
667*e57b9183Scg149915 	{ 0x00202000, 0x00000004 },
668*e57b9183Scg149915 	{ 0x001b00ff, 0x00000004 },
669*e57b9183Scg149915 	{ 0x01000069, 0x00000010 },
670*e57b9183Scg149915 	{ 0x001f2000, 0x00000004 },
671*e57b9183Scg149915 	{ 0x001c00ff, 0x00000004 },
672*e57b9183Scg149915 	{ 0000000000, 0x0000000c },
673*e57b9183Scg149915 	{ 0x00000085, 0x00000030 },
674*e57b9183Scg149915 	{ 0x0000005a, 0x00000008 },
675*e57b9183Scg149915 	{ 0x0000e576, 0x00000004 },
676*e57b9183Scg149915 	{ 0x000ca000, 0x00000004 },
677*e57b9183Scg149915 	{ 0x00012000, 0x00000004 },
678*e57b9183Scg149915 	{ 0x00082000, 0x00000004 },
679*e57b9183Scg149915 	{ 0x1800650e, 0x00000004 },
680*e57b9183Scg149915 	{ 0x00092000, 0x00000004 },
681*e57b9183Scg149915 	{ 0x000a2000, 0x00000004 },
682*e57b9183Scg149915 	{ 0x000f0000, 0x00000004 },
683*e57b9183Scg149915 	{ 0x00400000, 0x00000004 },
684*e57b9183Scg149915 	{ 0x00000079, 0x00000018 },
685*e57b9183Scg149915 	{ 0x0000e563, 0x00000004 },
686*e57b9183Scg149915 	{ 0x00c0e5f9, 0x000000c2 },
687*e57b9183Scg149915 	{ 0x0000006e, 0x00000008 },
688*e57b9183Scg149915 	{ 0x0000a06e, 0x00000008 },
689*e57b9183Scg149915 	{ 0x0000e576, 0x00000004 },
690*e57b9183Scg149915 	{ 0x0000e577, 0x00000004 },
691*e57b9183Scg149915 	{ 0x0000e50e, 0x00000004 },
692*e57b9183Scg149915 	{ 0x0000e50f, 0x00000004 },
693*e57b9183Scg149915 	{ 0x0140a000, 0x00000004 },
694*e57b9183Scg149915 	{ 0x0000007c, 0x00000018 },
695*e57b9183Scg149915 	{ 0x00c0e5f9, 0x000000c2 },
696*e57b9183Scg149915 	{ 0x0000007c, 0x00000008 },
697*e57b9183Scg149915 	{ 0x0014e50e, 0x00000004 },
698*e57b9183Scg149915 	{ 0x0040e50f, 0x00000004 },
699*e57b9183Scg149915 	{ 0x00c0007f, 0x00000008 },
700*e57b9183Scg149915 	{ 0x0000e570, 0x00000004 },
701*e57b9183Scg149915 	{ 0x0000e571, 0x00000004 },
702*e57b9183Scg149915 	{ 0x0000e572, 0x0000000c },
703*e57b9183Scg149915 	{ 0x0000a000, 0x00000004 },
704*e57b9183Scg149915 	{ 0x0140a000, 0x00000004 },
705*e57b9183Scg149915 	{ 0x0000e568, 0x00000004 },
706*e57b9183Scg149915 	{ 0x000c2000, 0x00000004 },
707*e57b9183Scg149915 	{ 0x00000089, 0x00000018 },
708*e57b9183Scg149915 	{ 0x000b0000, 0x00000004 },
709*e57b9183Scg149915 	{ 0x18c0e562, 0x00000004 },
710*e57b9183Scg149915 	{ 0x0000008b, 0x00000008 },
711*e57b9183Scg149915 	{ 0x00c0008a, 0x00000008 },
712*e57b9183Scg149915 	{ 0x000700e4, 0x00000004 },
713*e57b9183Scg149915 	{ 0x00000097, 0x00000038 },
714*e57b9183Scg149915 	{ 0x000ca099, 0x00000030 },
715*e57b9183Scg149915 	{ 0x080045bb, 0x00000004 },
716*e57b9183Scg149915 	{ 0x000c209a, 0x00000030 },
717*e57b9183Scg149915 	{ 0x0800e5bc, 0000000000 },
718*e57b9183Scg149915 	{ 0x0000e5bb, 0x00000004 },
719*e57b9183Scg149915 	{ 0x0000e5bc, 0000000000 },
720*e57b9183Scg149915 	{ 0x00120000, 0x0000000c },
721*e57b9183Scg149915 	{ 0x00120000, 0x00000004 },
722*e57b9183Scg149915 	{ 0x001b0002, 0x0000000c },
723*e57b9183Scg149915 	{ 0x0000a000, 0x00000004 },
724*e57b9183Scg149915 	{ 0x0000e821, 0x00000004 },
725*e57b9183Scg149915 	{ 0x0000e800, 0000000000 },
726*e57b9183Scg149915 	{ 0x0000e821, 0x00000004 },
727*e57b9183Scg149915 	{ 0x0000e82e, 0000000000 },
728*e57b9183Scg149915 	{ 0x02cca000, 0x00000004 },
729*e57b9183Scg149915 	{ 0x00140000, 0x00000004 },
730*e57b9183Scg149915 	{ 0x000ce1cc, 0x00000004 },
731*e57b9183Scg149915 	{ 0x050de1cd, 0x00000004 },
732*e57b9183Scg149915 	{ 0x000000a7, 0x00000020 },
733*e57b9183Scg149915 	{ 0x4200e000, 0000000000 },
734*e57b9183Scg149915 	{ 0x000000ae, 0x00000038 },
735*e57b9183Scg149915 	{ 0x000ca000, 0x00000004 },
736*e57b9183Scg149915 	{ 0x00140000, 0x00000004 },
737*e57b9183Scg149915 	{ 0x000c2000, 0x00000004 },
738*e57b9183Scg149915 	{ 0x00160000, 0x00000004 },
739*e57b9183Scg149915 	{ 0x700ce000, 0x00000004 },
740*e57b9183Scg149915 	{ 0x001400aa, 0x00000008 },
741*e57b9183Scg149915 	{ 0x4000e000, 0000000000 },
742*e57b9183Scg149915 	{ 0x02400000, 0x00000004 },
743*e57b9183Scg149915 	{ 0x400ee000, 0x00000004 },
744*e57b9183Scg149915 	{ 0x02400000, 0x00000004 },
745*e57b9183Scg149915 	{ 0x4000e000, 0000000000 },
746*e57b9183Scg149915 	{ 0x000c2000, 0x00000004 },
747*e57b9183Scg149915 	{ 0x0240e51b, 0x00000004 },
748*e57b9183Scg149915 	{ 0x0080e50a, 0x00000005 },
749*e57b9183Scg149915 	{ 0x0080e50b, 0x00000005 },
750*e57b9183Scg149915 	{ 0x00220000, 0x00000004 },
751*e57b9183Scg149915 	{ 0x000700e4, 0x00000004 },
752*e57b9183Scg149915 	{ 0x000000c1, 0x00000038 },
753*e57b9183Scg149915 	{ 0x000c209a, 0x00000030 },
754*e57b9183Scg149915 	{ 0x0880e5bd, 0x00000005 },
755*e57b9183Scg149915 	{ 0x000c2099, 0x00000030 },
756*e57b9183Scg149915 	{ 0x0800e5bb, 0x00000005 },
757*e57b9183Scg149915 	{ 0x000c209a, 0x00000030 },
758*e57b9183Scg149915 	{ 0x0880e5bc, 0x00000005 },
759*e57b9183Scg149915 	{ 0x000000c4, 0x00000008 },
760*e57b9183Scg149915 	{ 0x0080e5bd, 0x00000005 },
761*e57b9183Scg149915 	{ 0x0000e5bb, 0x00000005 },
762*e57b9183Scg149915 	{ 0x0080e5bc, 0x00000005 },
763*e57b9183Scg149915 	{ 0x00210000, 0x00000004 },
764*e57b9183Scg149915 	{ 0x02800000, 0x00000004 },
765*e57b9183Scg149915 	{ 0x00c000c8, 0x00000018 },
766*e57b9183Scg149915 	{ 0x4180e000, 0x00000040 },
767*e57b9183Scg149915 	{ 0x000000ca, 0x00000024 },
768*e57b9183Scg149915 	{ 0x01000000, 0x0000000c },
769*e57b9183Scg149915 	{ 0x0100e51d, 0x0000000c },
770*e57b9183Scg149915 	{ 0x000045bb, 0x00000004 },
771*e57b9183Scg149915 	{ 0x000080c4, 0x00000008 },
772*e57b9183Scg149915 	{ 0x0000f3ce, 0x00000004 },
773*e57b9183Scg149915 	{ 0x0140a000, 0x00000004 },
774*e57b9183Scg149915 	{ 0x00cc2000, 0x00000004 },
775*e57b9183Scg149915 	{ 0x08c053cf, 0x00000040 },
776*e57b9183Scg149915 	{ 0x00008000, 0000000000 },
777*e57b9183Scg149915 	{ 0x0000f3d2, 0x00000004 },
778*e57b9183Scg149915 	{ 0x0140a000, 0x00000004 },
779*e57b9183Scg149915 	{ 0x00cc2000, 0x00000004 },
780*e57b9183Scg149915 	{ 0x08c053d3, 0x00000040 },
781*e57b9183Scg149915 	{ 0x00008000, 0000000000 },
782*e57b9183Scg149915 	{ 0x0000f39d, 0x00000004 },
783*e57b9183Scg149915 	{ 0x0140a000, 0x00000004 },
784*e57b9183Scg149915 	{ 0x00cc2000, 0x00000004 },
785*e57b9183Scg149915 	{ 0x08c0539e, 0x00000040 },
786*e57b9183Scg149915 	{ 0x00008000, 0000000000 },
787*e57b9183Scg149915 	{ 0x03c00830, 0x00000004 },
788*e57b9183Scg149915 	{ 0x4200e000, 0000000000 },
789*e57b9183Scg149915 	{ 0x0000a000, 0x00000004 },
790*e57b9183Scg149915 	{ 0x200045e0, 0x00000004 },
791*e57b9183Scg149915 	{ 0x0000e5e1, 0000000000 },
792*e57b9183Scg149915 	{ 0x00000001, 0000000000 },
793*e57b9183Scg149915 	{ 0x000700e1, 0x00000004 },
794*e57b9183Scg149915 	{ 0x0800e394, 0000000000 },
795*e57b9183Scg149915 	{ 0000000000, 0000000000 },
796*e57b9183Scg149915 	{ 0000000000, 0000000000 },
797*e57b9183Scg149915 	{ 0000000000, 0000000000 },
798*e57b9183Scg149915 	{ 0000000000, 0000000000 },
799*e57b9183Scg149915 	{ 0000000000, 0000000000 },
800*e57b9183Scg149915 	{ 0000000000, 0000000000 },
801*e57b9183Scg149915 	{ 0000000000, 0000000000 },
802*e57b9183Scg149915 	{ 0000000000, 0000000000 },
803*e57b9183Scg149915 	{ 0000000000, 0000000000 },
804*e57b9183Scg149915 	{ 0000000000, 0000000000 },
805*e57b9183Scg149915 	{ 0000000000, 0000000000 },
806*e57b9183Scg149915 	{ 0000000000, 0000000000 },
807*e57b9183Scg149915 	{ 0000000000, 0000000000 },
808*e57b9183Scg149915 	{ 0000000000, 0000000000 },
809*e57b9183Scg149915 	{ 0000000000, 0000000000 },
810*e57b9183Scg149915 	{ 0000000000, 0000000000 },
811*e57b9183Scg149915 	{ 0000000000, 0000000000 },
812*e57b9183Scg149915 	{ 0000000000, 0000000000 },
813*e57b9183Scg149915 	{ 0000000000, 0000000000 },
814*e57b9183Scg149915 	{ 0000000000, 0000000000 },
815*e57b9183Scg149915 	{ 0000000000, 0000000000 },
816*e57b9183Scg149915 	{ 0000000000, 0000000000 },
817*e57b9183Scg149915 	{ 0000000000, 0000000000 },
818*e57b9183Scg149915 	{ 0000000000, 0000000000 },
819*e57b9183Scg149915 	{ 0000000000, 0000000000 },
820*e57b9183Scg149915 	{ 0000000000, 0000000000 },
821*e57b9183Scg149915 	{ 0000000000, 0000000000 },
822*e57b9183Scg149915 	{ 0000000000, 0000000000 },
823*e57b9183Scg149915 };
824*e57b9183Scg149915 
RADEON_READ_PLL(drm_device_t * dev,int addr)825*e57b9183Scg149915 static int RADEON_READ_PLL(drm_device_t *dev, int addr)
826*e57b9183Scg149915 {
827*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
828*e57b9183Scg149915 
829*e57b9183Scg149915 	RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
830*e57b9183Scg149915 	return (RADEON_READ(RADEON_CLOCK_CNTL_DATA));
831*e57b9183Scg149915 }
832*e57b9183Scg149915 
RADEON_READ_PCIE(drm_radeon_private_t * dev_priv,int addr)833*e57b9183Scg149915 static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
834*e57b9183Scg149915 {
835*e57b9183Scg149915 	RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
836*e57b9183Scg149915 	return (RADEON_READ(RADEON_PCIE_DATA));
837*e57b9183Scg149915 }
838*e57b9183Scg149915 
839*e57b9183Scg149915 #if RADEON_FIFO_DEBUG
radeon_status(drm_radeon_private_t * dev_priv)840*e57b9183Scg149915 static void radeon_status(drm_radeon_private_t *dev_priv)
841*e57b9183Scg149915 {
842*e57b9183Scg149915 	cmn_err(CE_NOTE, "RBBM_STATUS = 0x%08x\n",
843*e57b9183Scg149915 	    (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
844*e57b9183Scg149915 	cmn_err(CE_NOTE, "CP_RB_RTPR = 0x%08x\n",
845*e57b9183Scg149915 	    (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR));
846*e57b9183Scg149915 	cmn_err(CE_NOTE, "CP_RB_WTPR = 0x%08x\n",
847*e57b9183Scg149915 	    (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR));
848*e57b9183Scg149915 	cmn_err(CE_NOTE, "AIC_CNTL = 0x%08x\n",
849*e57b9183Scg149915 	    (unsigned int)RADEON_READ(RADEON_AIC_CNTL));
850*e57b9183Scg149915 	cmn_err(CE_NOTE, "AIC_STAT = 0x%08x\n",
851*e57b9183Scg149915 	    (unsigned int)RADEON_READ(RADEON_AIC_STAT));
852*e57b9183Scg149915 	cmn_err(CE_NOTE, "AIC_PT_BASE = 0x%08x\n",
853*e57b9183Scg149915 	    (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE));
854*e57b9183Scg149915 	cmn_err(CE_NOTE, "TLB_ADDR = 0x%08x\n",
855*e57b9183Scg149915 	    (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR));
856*e57b9183Scg149915 	cmn_err(CE_NOTE, "TLB_DATA = 0x%08x\n",
857*e57b9183Scg149915 	    (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA));
858*e57b9183Scg149915 }
859*e57b9183Scg149915 #endif
860*e57b9183Scg149915 
861*e57b9183Scg149915 /*
862*e57b9183Scg149915  * Engine, FIFO control
863*e57b9183Scg149915  */
864*e57b9183Scg149915 
radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)865*e57b9183Scg149915 static int radeon_do_pixcache_flush(drm_radeon_private_t *dev_priv)
866*e57b9183Scg149915 {
867*e57b9183Scg149915 	u32 tmp;
868*e57b9183Scg149915 	int i;
869*e57b9183Scg149915 
870*e57b9183Scg149915 	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
871*e57b9183Scg149915 
872*e57b9183Scg149915 	tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
873*e57b9183Scg149915 	tmp |= RADEON_RB3D_DC_FLUSH_ALL;
874*e57b9183Scg149915 	RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
875*e57b9183Scg149915 
876*e57b9183Scg149915 	for (i = 0; i < dev_priv->usec_timeout; i++) {
877*e57b9183Scg149915 		if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT) &
878*e57b9183Scg149915 		    RADEON_RB3D_DC_BUSY)) {
879*e57b9183Scg149915 			return (0);
880*e57b9183Scg149915 		}
881*e57b9183Scg149915 		DRM_UDELAY(1);
882*e57b9183Scg149915 	}
883*e57b9183Scg149915 
884*e57b9183Scg149915 #if RADEON_FIFO_DEBUG
885*e57b9183Scg149915 	DRM_ERROR("failed!\n");
886*e57b9183Scg149915 	radeon_status(dev_priv);
887*e57b9183Scg149915 #endif
888*e57b9183Scg149915 	return (EBUSY);
889*e57b9183Scg149915 }
890*e57b9183Scg149915 
radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv,int entries)891*e57b9183Scg149915 static int radeon_do_wait_for_fifo(drm_radeon_private_t *dev_priv, int entries)
892*e57b9183Scg149915 {
893*e57b9183Scg149915 	int i;
894*e57b9183Scg149915 
895*e57b9183Scg149915 	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
896*e57b9183Scg149915 
897*e57b9183Scg149915 	for (i = 0; i < dev_priv->usec_timeout; i++) {
898*e57b9183Scg149915 		int slots = (RADEON_READ(RADEON_RBBM_STATUS) &
899*e57b9183Scg149915 		    RADEON_RBBM_FIFOCNT_MASK);
900*e57b9183Scg149915 		if (slots >= entries)
901*e57b9183Scg149915 			return (0);
902*e57b9183Scg149915 		DRM_UDELAY(1);
903*e57b9183Scg149915 	}
904*e57b9183Scg149915 
905*e57b9183Scg149915 
906*e57b9183Scg149915 	DRM_ERROR("radeon_do_wait_for_fifo: failed timeout=%d",
907*e57b9183Scg149915 	    dev_priv->usec_timeout);
908*e57b9183Scg149915 #if RADEON_FIFO_DEBUG
909*e57b9183Scg149915 	radeon_status(dev_priv);
910*e57b9183Scg149915 #endif
911*e57b9183Scg149915 	return (EBUSY);
912*e57b9183Scg149915 }
913*e57b9183Scg149915 
radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)914*e57b9183Scg149915 static int radeon_do_wait_for_idle(drm_radeon_private_t *dev_priv)
915*e57b9183Scg149915 {
916*e57b9183Scg149915 	int i, ret;
917*e57b9183Scg149915 
918*e57b9183Scg149915 	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
919*e57b9183Scg149915 
920*e57b9183Scg149915 	ret = radeon_do_wait_for_fifo(dev_priv, 64);
921*e57b9183Scg149915 	if (ret)
922*e57b9183Scg149915 		return (ret);
923*e57b9183Scg149915 
924*e57b9183Scg149915 	for (i = 0; i < dev_priv->usec_timeout; i++) {
925*e57b9183Scg149915 		if (!(RADEON_READ(RADEON_RBBM_STATUS) &
926*e57b9183Scg149915 		    RADEON_RBBM_ACTIVE)) {
927*e57b9183Scg149915 			(void) radeon_do_pixcache_flush(dev_priv);
928*e57b9183Scg149915 			return (0);
929*e57b9183Scg149915 		}
930*e57b9183Scg149915 		DRM_UDELAY(1);
931*e57b9183Scg149915 	}
932*e57b9183Scg149915 
933*e57b9183Scg149915 	DRM_ERROR("radeon_do_wait_for_idle: failed timeout=%d",
934*e57b9183Scg149915 	    dev_priv->usec_timeout);
935*e57b9183Scg149915 
936*e57b9183Scg149915 #if RADEON_FIFO_DEBUG
937*e57b9183Scg149915 	radeon_status(dev_priv);
938*e57b9183Scg149915 #endif
939*e57b9183Scg149915 	return (EBUSY);
940*e57b9183Scg149915 }
941*e57b9183Scg149915 
942*e57b9183Scg149915 /*
943*e57b9183Scg149915  * CP control, initialization
944*e57b9183Scg149915  */
945*e57b9183Scg149915 
946*e57b9183Scg149915 /* Load the microcode for the CP */
radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)947*e57b9183Scg149915 static void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv)
948*e57b9183Scg149915 {
949*e57b9183Scg149915 	int i;
950*e57b9183Scg149915 
951*e57b9183Scg149915 	(void) radeon_do_wait_for_idle(dev_priv);
952*e57b9183Scg149915 
953*e57b9183Scg149915 	RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
954*e57b9183Scg149915 
955*e57b9183Scg149915 	if (dev_priv->microcode_version == UCODE_R200) {
956*e57b9183Scg149915 		DRM_INFO("Loading R200 Microcode\n");
957*e57b9183Scg149915 		for (i = 0; i < 256; i++) {
958*e57b9183Scg149915 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
959*e57b9183Scg149915 			    R200_cp_microcode[i][1]);
960*e57b9183Scg149915 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
961*e57b9183Scg149915 			    R200_cp_microcode[i][0]);
962*e57b9183Scg149915 		}
963*e57b9183Scg149915 	} else if (dev_priv->microcode_version == UCODE_R300) {
964*e57b9183Scg149915 		DRM_INFO("Loading R300 Microcode\n");
965*e57b9183Scg149915 		for (i = 0; i < 256; i++) {
966*e57b9183Scg149915 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
967*e57b9183Scg149915 			    R300_cp_microcode[i][1]);
968*e57b9183Scg149915 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
969*e57b9183Scg149915 			    R300_cp_microcode[i][0]);
970*e57b9183Scg149915 		}
971*e57b9183Scg149915 	} else {
972*e57b9183Scg149915 		for (i = 0; i < 256; i++) {
973*e57b9183Scg149915 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
974*e57b9183Scg149915 			    radeon_cp_microcode[i][1]);
975*e57b9183Scg149915 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
976*e57b9183Scg149915 			    radeon_cp_microcode[i][0]);
977*e57b9183Scg149915 		}
978*e57b9183Scg149915 	}
979*e57b9183Scg149915 }
980*e57b9183Scg149915 
981*e57b9183Scg149915 /*
982*e57b9183Scg149915  * Flush any pending commands to the CP.  This should only be used just
983*e57b9183Scg149915  * prior to a wait for idle, as it informs the engine that the command
984*e57b9183Scg149915  * stream is ending.
985*e57b9183Scg149915  */
986*e57b9183Scg149915 /*ARGSUSED*/
radeon_do_cp_flush(drm_radeon_private_t * dev_priv)987*e57b9183Scg149915 static void radeon_do_cp_flush(drm_radeon_private_t *dev_priv)
988*e57b9183Scg149915 {
989*e57b9183Scg149915 	DRM_DEBUG("\n");
990*e57b9183Scg149915 
991*e57b9183Scg149915 #if 0
992*e57b9183Scg149915 	u32 tmp;
993*e57b9183Scg149915 
994*e57b9183Scg149915 	tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31);
995*e57b9183Scg149915 	RADEON_WRITE(RADEON_CP_RB_WPTR, tmp);
996*e57b9183Scg149915 #endif
997*e57b9183Scg149915 }
998*e57b9183Scg149915 
999*e57b9183Scg149915 /* Wait for the CP to go idle. */
1000*e57b9183Scg149915 int
radeon_do_cp_idle(drm_radeon_private_t * dev_priv)1001*e57b9183Scg149915 radeon_do_cp_idle(drm_radeon_private_t *dev_priv)
1002*e57b9183Scg149915 {
1003*e57b9183Scg149915 	RING_LOCALS;
1004*e57b9183Scg149915 
1005*e57b9183Scg149915 	BEGIN_RING(6);
1006*e57b9183Scg149915 
1007*e57b9183Scg149915 	RADEON_PURGE_CACHE();
1008*e57b9183Scg149915 	RADEON_PURGE_ZCACHE();
1009*e57b9183Scg149915 	RADEON_WAIT_UNTIL_IDLE();
1010*e57b9183Scg149915 
1011*e57b9183Scg149915 	ADVANCE_RING();
1012*e57b9183Scg149915 	COMMIT_RING();
1013*e57b9183Scg149915 
1014*e57b9183Scg149915 	return (radeon_do_wait_for_idle(dev_priv));
1015*e57b9183Scg149915 }
1016*e57b9183Scg149915 
1017*e57b9183Scg149915 /* Start the Command Processor. */
radeon_do_cp_start(drm_radeon_private_t * dev_priv)1018*e57b9183Scg149915 static void radeon_do_cp_start(drm_radeon_private_t *dev_priv)
1019*e57b9183Scg149915 {
1020*e57b9183Scg149915 	RING_LOCALS;
1021*e57b9183Scg149915 
1022*e57b9183Scg149915 	(void) radeon_do_wait_for_idle(dev_priv);
1023*e57b9183Scg149915 
1024*e57b9183Scg149915 	RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode);
1025*e57b9183Scg149915 
1026*e57b9183Scg149915 	dev_priv->cp_running = 1;
1027*e57b9183Scg149915 
1028*e57b9183Scg149915 	BEGIN_RING(6);
1029*e57b9183Scg149915 
1030*e57b9183Scg149915 	RADEON_PURGE_CACHE();
1031*e57b9183Scg149915 	RADEON_PURGE_ZCACHE();
1032*e57b9183Scg149915 	RADEON_WAIT_UNTIL_IDLE();
1033*e57b9183Scg149915 
1034*e57b9183Scg149915 	ADVANCE_RING();
1035*e57b9183Scg149915 	COMMIT_RING();
1036*e57b9183Scg149915 }
1037*e57b9183Scg149915 
1038*e57b9183Scg149915 /*
1039*e57b9183Scg149915  * Reset the Command Processor.  This will not flush any pending
1040*e57b9183Scg149915  * commands, so you must wait for the CP command stream to complete
1041*e57b9183Scg149915  * before calling this routine.
1042*e57b9183Scg149915  */
radeon_do_cp_reset(drm_radeon_private_t * dev_priv)1043*e57b9183Scg149915 static void radeon_do_cp_reset(drm_radeon_private_t *dev_priv)
1044*e57b9183Scg149915 {
1045*e57b9183Scg149915 	u32 cur_read_ptr;
1046*e57b9183Scg149915 	DRM_DEBUG("\n");
1047*e57b9183Scg149915 
1048*e57b9183Scg149915 	cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
1049*e57b9183Scg149915 	RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
1050*e57b9183Scg149915 	SET_RING_HEAD(dev_priv, cur_read_ptr);
1051*e57b9183Scg149915 	dev_priv->ring.tail = cur_read_ptr;
1052*e57b9183Scg149915 }
1053*e57b9183Scg149915 
1054*e57b9183Scg149915 /*
1055*e57b9183Scg149915  * Stop the Command Processor.  This will not flush any pending
1056*e57b9183Scg149915  * commands, so you must flush the command stream and wait for the CP
1057*e57b9183Scg149915  * to go idle before calling this routine.
1058*e57b9183Scg149915  */
radeon_do_cp_stop(drm_radeon_private_t * dev_priv)1059*e57b9183Scg149915 static void radeon_do_cp_stop(drm_radeon_private_t *dev_priv)
1060*e57b9183Scg149915 {
1061*e57b9183Scg149915 	DRM_DEBUG("\n");
1062*e57b9183Scg149915 
1063*e57b9183Scg149915 	RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
1064*e57b9183Scg149915 
1065*e57b9183Scg149915 	dev_priv->cp_running = 0;
1066*e57b9183Scg149915 }
1067*e57b9183Scg149915 
1068*e57b9183Scg149915 /* Reset the engine.  This will stop the CP if it is running. */
radeon_do_engine_reset(drm_device_t * dev)1069*e57b9183Scg149915 static int radeon_do_engine_reset(drm_device_t *dev)
1070*e57b9183Scg149915 {
1071*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
1072*e57b9183Scg149915 	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
1073*e57b9183Scg149915 	DRM_DEBUG("\n");
1074*e57b9183Scg149915 
1075*e57b9183Scg149915 	(void) radeon_do_pixcache_flush(dev_priv);
1076*e57b9183Scg149915 
1077*e57b9183Scg149915 	clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
1078*e57b9183Scg149915 	mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
1079*e57b9183Scg149915 
1080*e57b9183Scg149915 	RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
1081*e57b9183Scg149915 	    RADEON_FORCEON_MCLKA |
1082*e57b9183Scg149915 	    RADEON_FORCEON_MCLKB |
1083*e57b9183Scg149915 	    RADEON_FORCEON_YCLKA |
1084*e57b9183Scg149915 	    RADEON_FORCEON_YCLKB |
1085*e57b9183Scg149915 	    RADEON_FORCEON_MC |
1086*e57b9183Scg149915 	    RADEON_FORCEON_AIC));
1087*e57b9183Scg149915 
1088*e57b9183Scg149915 	rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
1089*e57b9183Scg149915 
1090*e57b9183Scg149915 	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
1091*e57b9183Scg149915 	    RADEON_SOFT_RESET_CP |
1092*e57b9183Scg149915 	    RADEON_SOFT_RESET_HI |
1093*e57b9183Scg149915 	    RADEON_SOFT_RESET_SE |
1094*e57b9183Scg149915 	    RADEON_SOFT_RESET_RE |
1095*e57b9183Scg149915 	    RADEON_SOFT_RESET_PP |
1096*e57b9183Scg149915 	    RADEON_SOFT_RESET_E2 |
1097*e57b9183Scg149915 	    RADEON_SOFT_RESET_RB));
1098*e57b9183Scg149915 	(void) RADEON_READ(RADEON_RBBM_SOFT_RESET);
1099*e57b9183Scg149915 	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
1100*e57b9183Scg149915 	    ~(RADEON_SOFT_RESET_CP |
1101*e57b9183Scg149915 	    RADEON_SOFT_RESET_HI |
1102*e57b9183Scg149915 	    RADEON_SOFT_RESET_SE |
1103*e57b9183Scg149915 	    RADEON_SOFT_RESET_RE |
1104*e57b9183Scg149915 	    RADEON_SOFT_RESET_PP |
1105*e57b9183Scg149915 	    RADEON_SOFT_RESET_E2 |
1106*e57b9183Scg149915 	    RADEON_SOFT_RESET_RB)));
1107*e57b9183Scg149915 	(void) RADEON_READ(RADEON_RBBM_SOFT_RESET);
1108*e57b9183Scg149915 
1109*e57b9183Scg149915 	RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
1110*e57b9183Scg149915 	RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
1111*e57b9183Scg149915 	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
1112*e57b9183Scg149915 
1113*e57b9183Scg149915 	/* Reset the CP ring */
1114*e57b9183Scg149915 	radeon_do_cp_reset(dev_priv);
1115*e57b9183Scg149915 
1116*e57b9183Scg149915 	/* The CP is no longer running after an engine reset */
1117*e57b9183Scg149915 	dev_priv->cp_running = 0;
1118*e57b9183Scg149915 
1119*e57b9183Scg149915 	/* Reset any pending vertex, indirect buffers */
1120*e57b9183Scg149915 	radeon_freelist_reset(dev);
1121*e57b9183Scg149915 
1122*e57b9183Scg149915 	return (0);
1123*e57b9183Scg149915 }
1124*e57b9183Scg149915 
1125*e57b9183Scg149915 static void
radeon_cp_init_ring_buffer(drm_device_t * dev,drm_radeon_private_t * dev_priv)1126*e57b9183Scg149915 radeon_cp_init_ring_buffer(drm_device_t *dev, drm_radeon_private_t *dev_priv)
1127*e57b9183Scg149915 {
1128*e57b9183Scg149915 	u32 ring_start, cur_read_ptr;
1129*e57b9183Scg149915 	u32 tmp;
1130*e57b9183Scg149915 
1131*e57b9183Scg149915 	/*
1132*e57b9183Scg149915 	 * Initialize the memory controller. With new memory map, the fb
1133*e57b9183Scg149915 	 * location is not changed, it should have been properly initialized
1134*e57b9183Scg149915 	 * already. Part of the problem is that the code below is bogus,
1135*e57b9183Scg149915 	 * assuming the GART is always appended to the fb which is not
1136*e57b9183Scg149915 	 * necessarily the case
1137*e57b9183Scg149915 	 */
1138*e57b9183Scg149915 	if (!dev_priv->new_memmap)
1139*e57b9183Scg149915 		RADEON_WRITE(RADEON_MC_FB_LOCATION,
1140*e57b9183Scg149915 		    ((dev_priv->gart_vm_start - 1) & 0xffff0000) |
1141*e57b9183Scg149915 		    (dev_priv->fb_location >> 16));
1142*e57b9183Scg149915 
1143*e57b9183Scg149915 #if __OS_HAS_AGP
1144*e57b9183Scg149915 	if (dev_priv->flags & RADEON_IS_AGP) {
1145*e57b9183Scg149915 		RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
1146*e57b9183Scg149915 		RADEON_WRITE(RADEON_MC_AGP_LOCATION,
1147*e57b9183Scg149915 		    (((dev_priv->gart_vm_start - 1 +
1148*e57b9183Scg149915 		    dev_priv->gart_size) & 0xffff0000) |
1149*e57b9183Scg149915 		    (dev_priv->gart_vm_start >> 16)));
1150*e57b9183Scg149915 
1151*e57b9183Scg149915 		ring_start = dev_priv->cp_ring->offset -
1152*e57b9183Scg149915 		    dev->agp->base + dev_priv->gart_vm_start;
1153*e57b9183Scg149915 	} else
1154*e57b9183Scg149915 #endif
1155*e57b9183Scg149915 		ring_start = (dev_priv->cp_ring->offset -
1156*e57b9183Scg149915 		    (unsigned long)dev->sg->virtual +
1157*e57b9183Scg149915 		    dev_priv->gart_vm_start);
1158*e57b9183Scg149915 
1159*e57b9183Scg149915 	RADEON_WRITE(RADEON_CP_RB_BASE, ring_start);
1160*e57b9183Scg149915 
1161*e57b9183Scg149915 	/* Set the write pointer delay */
1162*e57b9183Scg149915 	RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0);
1163*e57b9183Scg149915 
1164*e57b9183Scg149915 	/* Initialize the ring buffer's read and write pointers */
1165*e57b9183Scg149915 	cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
1166*e57b9183Scg149915 	RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
1167*e57b9183Scg149915 	SET_RING_HEAD(dev_priv, cur_read_ptr);
1168*e57b9183Scg149915 	dev_priv->ring.tail = cur_read_ptr;
1169*e57b9183Scg149915 
1170*e57b9183Scg149915 #if __OS_HAS_AGP
1171*e57b9183Scg149915 	if (dev_priv->flags & RADEON_IS_AGP) {
1172*e57b9183Scg149915 		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
1173*e57b9183Scg149915 		    dev_priv->ring_rptr->offset -
1174*e57b9183Scg149915 		    dev->agp->base + dev_priv->gart_vm_start);
1175*e57b9183Scg149915 	} else
1176*e57b9183Scg149915 #endif
1177*e57b9183Scg149915 	{
1178*e57b9183Scg149915 		drm_sg_mem_t *entry = dev->sg;
1179*e57b9183Scg149915 		unsigned long tmp_ofs, page_ofs;
1180*e57b9183Scg149915 
1181*e57b9183Scg149915 		tmp_ofs = dev_priv->ring_rptr->offset -
1182*e57b9183Scg149915 		    (unsigned long)dev->sg->virtual;
1183*e57b9183Scg149915 		page_ofs = tmp_ofs >> PAGE_SHIFT;
1184*e57b9183Scg149915 
1185*e57b9183Scg149915 		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]);
1186*e57b9183Scg149915 		DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n",
1187*e57b9183Scg149915 		    (unsigned long)entry->busaddr[page_ofs],
1188*e57b9183Scg149915 		    entry->handle + tmp_ofs);
1189*e57b9183Scg149915 	}
1190*e57b9183Scg149915 
1191*e57b9183Scg149915 	/* Set ring buffer size */
1192*e57b9183Scg149915 #ifdef __BIG_ENDIAN
1193*e57b9183Scg149915 	RADEON_WRITE(RADEON_CP_RB_CNTL,
1194*e57b9183Scg149915 	    dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
1195*e57b9183Scg149915 #else
1196*e57b9183Scg149915 	RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
1197*e57b9183Scg149915 #endif
1198*e57b9183Scg149915 
1199*e57b9183Scg149915 	/* Start with assuming that writeback doesn't work */
1200*e57b9183Scg149915 	dev_priv->writeback_works = 0;
1201*e57b9183Scg149915 
1202*e57b9183Scg149915 	/*
1203*e57b9183Scg149915 	 * Initialize the scratch register pointer.  This will cause
1204*e57b9183Scg149915 	 * the scratch register values to be written out to memory
1205*e57b9183Scg149915 	 * whenever they are updated.
1206*e57b9183Scg149915 	 *
1207*e57b9183Scg149915 	 * We simply put this behind the ring read pointer, this works
1208*e57b9183Scg149915 	 * with PCI GART as well as (whatever kind of) AGP GART
1209*e57b9183Scg149915 	 */
1210*e57b9183Scg149915 	RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
1211*e57b9183Scg149915 	    + RADEON_SCRATCH_REG_OFFSET);
1212*e57b9183Scg149915 
1213*e57b9183Scg149915 	dev_priv->scratch = ((__volatile__ u32 *)
1214*e57b9183Scg149915 	    dev_priv->ring_rptr->handle +
1215*e57b9183Scg149915 	    (RADEON_SCRATCH_REG_OFFSET / sizeof (u32)));
1216*e57b9183Scg149915 
1217*e57b9183Scg149915 	RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
1218*e57b9183Scg149915 
1219*e57b9183Scg149915 	/* Turn on bus mastering */
1220*e57b9183Scg149915 	tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
1221*e57b9183Scg149915 	RADEON_WRITE(RADEON_BUS_CNTL, tmp);
1222*e57b9183Scg149915 
1223*e57b9183Scg149915 	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
1224*e57b9183Scg149915 	RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
1225*e57b9183Scg149915 
1226*e57b9183Scg149915 	dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
1227*e57b9183Scg149915 	RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
1228*e57b9183Scg149915 	    dev_priv->sarea_priv->last_dispatch);
1229*e57b9183Scg149915 
1230*e57b9183Scg149915 	dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
1231*e57b9183Scg149915 	RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
1232*e57b9183Scg149915 
1233*e57b9183Scg149915 	(void) radeon_do_wait_for_idle(dev_priv);
1234*e57b9183Scg149915 
1235*e57b9183Scg149915 	/* Sync everything up */
1236*e57b9183Scg149915 	RADEON_WRITE(RADEON_ISYNC_CNTL,
1237*e57b9183Scg149915 	    (RADEON_ISYNC_ANY2D_IDLE3D |
1238*e57b9183Scg149915 	    RADEON_ISYNC_ANY3D_IDLE2D |
1239*e57b9183Scg149915 	    RADEON_ISYNC_WAIT_IDLEGUI |
1240*e57b9183Scg149915 	    RADEON_ISYNC_CPSCRATCH_IDLEGUI));
1241*e57b9183Scg149915 
1242*e57b9183Scg149915 }
1243*e57b9183Scg149915 
radeon_test_writeback(drm_radeon_private_t * dev_priv)1244*e57b9183Scg149915 static void radeon_test_writeback(drm_radeon_private_t *dev_priv)
1245*e57b9183Scg149915 {
1246*e57b9183Scg149915 #if 0
1247*e57b9183Scg149915 	u32 tmp;
1248*e57b9183Scg149915 
1249*e57b9183Scg149915 	/*
1250*e57b9183Scg149915 	 * Writeback doesn't seem to work everywhere, test it here and possibly
1251*e57b9183Scg149915 	 * enable it if it appears to work
1252*e57b9183Scg149915 	 */
1253*e57b9183Scg149915 	DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
1254*e57b9183Scg149915 	RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
1255*e57b9183Scg149915 
1256*e57b9183Scg149915 	for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
1257*e57b9183Scg149915 		if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
1258*e57b9183Scg149915 		    0xdeadbeef)
1259*e57b9183Scg149915 			break;
1260*e57b9183Scg149915 		DRM_UDELAY(1);
1261*e57b9183Scg149915 	}
1262*e57b9183Scg149915 
1263*e57b9183Scg149915 	tmp = dev_priv->usec_timeout;
1264*e57b9183Scg149915 
1265*e57b9183Scg149915 	if (tmp < dev_priv->usec_timeout) {
1266*e57b9183Scg149915 		dev_priv->writeback_works = 1;
1267*e57b9183Scg149915 		DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
1268*e57b9183Scg149915 	} else {
1269*e57b9183Scg149915 		dev_priv->writeback_works = 0;
1270*e57b9183Scg149915 		DRM_INFO("writeback test failed\n");
1271*e57b9183Scg149915 	}
1272*e57b9183Scg149915 	if (radeon_no_wb == 1) {
1273*e57b9183Scg149915 		dev_priv->writeback_works = 0;
1274*e57b9183Scg149915 		DRM_INFO("writeback forced off\n");
1275*e57b9183Scg149915 	}
1276*e57b9183Scg149915 #else
1277*e57b9183Scg149915 	/*
1278*e57b9183Scg149915 	 * Writeback doesn't work everywhere. And the timeout is so long
1279*e57b9183Scg149915 	 * so Xserver needs more time to start itself. But dtlogin doesn't
1280*e57b9183Scg149915 	 * want to wait for the timeout, and it just stops Xserver and
1281*e57b9183Scg149915 	 * restart it again. As a result, Xserver cannot start. So, we
1282*e57b9183Scg149915 	 * just ignore writeback here.
1283*e57b9183Scg149915 	 */
1284*e57b9183Scg149915 	dev_priv->writeback_works = 0;
1285*e57b9183Scg149915 #endif
1286*e57b9183Scg149915 
1287*e57b9183Scg149915 	if (!dev_priv->writeback_works) {
1288*e57b9183Scg149915 		/*
1289*e57b9183Scg149915 		 * Disable writeback to avoid unnecessary bus master
1290*e57b9183Scg149915 		 * transfers
1291*e57b9183Scg149915 		 */
1292*e57b9183Scg149915 		RADEON_WRITE(RADEON_CP_RB_CNTL,
1293*e57b9183Scg149915 		    RADEON_READ(RADEON_CP_RB_CNTL) | RADEON_RB_NO_UPDATE);
1294*e57b9183Scg149915 		RADEON_WRITE(RADEON_SCRATCH_UMSK, 0);
1295*e57b9183Scg149915 	}
1296*e57b9183Scg149915 
1297*e57b9183Scg149915 }
1298*e57b9183Scg149915 
1299*e57b9183Scg149915 /* Enable or disable PCI-E GART on the chip */
radeon_set_pciegart(drm_radeon_private_t * dev_priv,int on)1300*e57b9183Scg149915 static void radeon_set_pciegart(drm_radeon_private_t *dev_priv, int on)
1301*e57b9183Scg149915 {
1302*e57b9183Scg149915 	u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
1303*e57b9183Scg149915 	if (on) {
1304*e57b9183Scg149915 
1305*e57b9183Scg149915 		DRM_DEBUG("programming pcie %08X %08lX %08X\n",
1306*e57b9183Scg149915 		    dev_priv->gart_vm_start,
1307*e57b9183Scg149915 		    (long)dev_priv->gart_info.bus_addr,
1308*e57b9183Scg149915 		    dev_priv->gart_size);
1309*e57b9183Scg149915 		RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO,
1310*e57b9183Scg149915 		    dev_priv->gart_vm_start);
1311*e57b9183Scg149915 		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE,
1312*e57b9183Scg149915 		    dev_priv->gart_info.bus_addr);
1313*e57b9183Scg149915 		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO,
1314*e57b9183Scg149915 		    dev_priv->gart_vm_start);
1315*e57b9183Scg149915 		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO,
1316*e57b9183Scg149915 		    dev_priv->gart_vm_start + dev_priv->gart_size - 1);
1317*e57b9183Scg149915 
1318*e57b9183Scg149915 		RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);	/* ?? */
1319*e57b9183Scg149915 
1320*e57b9183Scg149915 		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
1321*e57b9183Scg149915 		    RADEON_PCIE_TX_GART_EN);
1322*e57b9183Scg149915 	} else {
1323*e57b9183Scg149915 		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
1324*e57b9183Scg149915 		    tmp & ~RADEON_PCIE_TX_GART_EN);
1325*e57b9183Scg149915 	}
1326*e57b9183Scg149915 }
1327*e57b9183Scg149915 
1328*e57b9183Scg149915 /* Enable or disable PCI GART on the chip */
radeon_set_pcigart(drm_radeon_private_t * dev_priv,int on)1329*e57b9183Scg149915 static void radeon_set_pcigart(drm_radeon_private_t *dev_priv, int on)
1330*e57b9183Scg149915 {
1331*e57b9183Scg149915 	u32 tmp;
1332*e57b9183Scg149915 
1333*e57b9183Scg149915 	if (dev_priv->flags & RADEON_IS_PCIE) {
1334*e57b9183Scg149915 		radeon_set_pciegart(dev_priv, on);
1335*e57b9183Scg149915 		return;
1336*e57b9183Scg149915 	}
1337*e57b9183Scg149915 
1338*e57b9183Scg149915 	tmp = RADEON_READ(RADEON_AIC_CNTL);
1339*e57b9183Scg149915 
1340*e57b9183Scg149915 	if (on) {
1341*e57b9183Scg149915 		RADEON_WRITE(RADEON_AIC_CNTL,
1342*e57b9183Scg149915 		    tmp | RADEON_PCIGART_TRANSLATE_EN);
1343*e57b9183Scg149915 
1344*e57b9183Scg149915 		/* set PCI GART page-table base address */
1345*e57b9183Scg149915 		RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);
1346*e57b9183Scg149915 
1347*e57b9183Scg149915 		/* set address range for PCI address translate */
1348*e57b9183Scg149915 		RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start);
1349*e57b9183Scg149915 		RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start +
1350*e57b9183Scg149915 		    dev_priv->gart_size - 1);
1351*e57b9183Scg149915 
1352*e57b9183Scg149915 		/* Turn off AGP aperture -- is this required for PCI GART?  */
1353*e57b9183Scg149915 		RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);	/* ?? */
1354*e57b9183Scg149915 		RADEON_WRITE(RADEON_AGP_COMMAND, 0);	/* clear AGP_COMMAND */
1355*e57b9183Scg149915 	} else {
1356*e57b9183Scg149915 		RADEON_WRITE(RADEON_AIC_CNTL,
1357*e57b9183Scg149915 		    tmp & ~RADEON_PCIGART_TRANSLATE_EN);
1358*e57b9183Scg149915 	}
1359*e57b9183Scg149915 }
1360*e57b9183Scg149915 
radeon_do_init_cp(drm_device_t * dev,drm_radeon_init_t * init)1361*e57b9183Scg149915 static int radeon_do_init_cp(drm_device_t *dev, drm_radeon_init_t *init)
1362*e57b9183Scg149915 {
1363*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
1364*e57b9183Scg149915 
1365*e57b9183Scg149915 	/* if we require new memory map but we don't have it fail */
1366*e57b9183Scg149915 	if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
1367*e57b9183Scg149915 		DRM_ERROR("Cannot initialise DRM on this card\n"
1368*e57b9183Scg149915 		    "This card requires a new X.org DDX for 3D\n");
1369*e57b9183Scg149915 		(void) radeon_do_cleanup_cp(dev);
1370*e57b9183Scg149915 		return (EINVAL);
1371*e57b9183Scg149915 	}
1372*e57b9183Scg149915 
1373*e57b9183Scg149915 	if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
1374*e57b9183Scg149915 		DRM_DEBUG("Forcing AGP card to PCI mode\n");
1375*e57b9183Scg149915 		dev_priv->flags &= ~RADEON_IS_AGP;
1376*e57b9183Scg149915 	} else if (!(dev_priv->flags &
1377*e57b9183Scg149915 	    (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE)) &&
1378*e57b9183Scg149915 	    !init->is_pci) {
1379*e57b9183Scg149915 		DRM_DEBUG("Restoring AGP flag\n");
1380*e57b9183Scg149915 		dev_priv->flags |= RADEON_IS_AGP;
1381*e57b9183Scg149915 	}
1382*e57b9183Scg149915 
1383*e57b9183Scg149915 	if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
1384*e57b9183Scg149915 		DRM_ERROR("PCI GART memory not allocated!\n");
1385*e57b9183Scg149915 		(void) radeon_do_cleanup_cp(dev);
1386*e57b9183Scg149915 		return (EINVAL);
1387*e57b9183Scg149915 	}
1388*e57b9183Scg149915 
1389*e57b9183Scg149915 	dev_priv->usec_timeout = init->usec_timeout;
1390*e57b9183Scg149915 	if (dev_priv->usec_timeout < 1 ||
1391*e57b9183Scg149915 	    dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
1392*e57b9183Scg149915 		(void) radeon_do_cleanup_cp(dev);
1393*e57b9183Scg149915 		return (EINVAL);
1394*e57b9183Scg149915 	}
1395*e57b9183Scg149915 
1396*e57b9183Scg149915 	switch (init->func) {
1397*e57b9183Scg149915 	case RADEON_INIT_R200_CP:
1398*e57b9183Scg149915 		dev_priv->microcode_version = UCODE_R200;
1399*e57b9183Scg149915 		break;
1400*e57b9183Scg149915 	case RADEON_INIT_R300_CP:
1401*e57b9183Scg149915 		dev_priv->microcode_version = UCODE_R300;
1402*e57b9183Scg149915 		break;
1403*e57b9183Scg149915 	default:
1404*e57b9183Scg149915 		dev_priv->microcode_version = UCODE_R100;
1405*e57b9183Scg149915 	}
1406*e57b9183Scg149915 
1407*e57b9183Scg149915 	dev_priv->do_boxes = 0;
1408*e57b9183Scg149915 	dev_priv->cp_mode = init->cp_mode;
1409*e57b9183Scg149915 
1410*e57b9183Scg149915 	/*
1411*e57b9183Scg149915 	 * We don't support anything other than bus-mastering ring mode,
1412*e57b9183Scg149915 	 * but the ring can be in either AGP or PCI space for the ring
1413*e57b9183Scg149915 	 * read pointer.
1414*e57b9183Scg149915 	 */
1415*e57b9183Scg149915 	if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
1416*e57b9183Scg149915 	    (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
1417*e57b9183Scg149915 		DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
1418*e57b9183Scg149915 		(void) radeon_do_cleanup_cp(dev);
1419*e57b9183Scg149915 		return (EINVAL);
1420*e57b9183Scg149915 	}
1421*e57b9183Scg149915 
1422*e57b9183Scg149915 	switch (init->fb_bpp) {
1423*e57b9183Scg149915 	case 16:
1424*e57b9183Scg149915 		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
1425*e57b9183Scg149915 		break;
1426*e57b9183Scg149915 	case 32:
1427*e57b9183Scg149915 	default:
1428*e57b9183Scg149915 		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
1429*e57b9183Scg149915 		break;
1430*e57b9183Scg149915 	}
1431*e57b9183Scg149915 	dev_priv->front_offset = init->front_offset;
1432*e57b9183Scg149915 	dev_priv->front_pitch = init->front_pitch;
1433*e57b9183Scg149915 	dev_priv->back_offset = init->back_offset;
1434*e57b9183Scg149915 	dev_priv->back_pitch = init->back_pitch;
1435*e57b9183Scg149915 
1436*e57b9183Scg149915 	switch (init->depth_bpp) {
1437*e57b9183Scg149915 	case 16:
1438*e57b9183Scg149915 		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
1439*e57b9183Scg149915 		break;
1440*e57b9183Scg149915 	case 32:
1441*e57b9183Scg149915 	default:
1442*e57b9183Scg149915 		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
1443*e57b9183Scg149915 		break;
1444*e57b9183Scg149915 	}
1445*e57b9183Scg149915 	dev_priv->depth_offset = init->depth_offset;
1446*e57b9183Scg149915 	dev_priv->depth_pitch = init->depth_pitch;
1447*e57b9183Scg149915 
1448*e57b9183Scg149915 	/*
1449*e57b9183Scg149915 	 * Hardware state for depth clears.  Remove this if/when we no
1450*e57b9183Scg149915 	 * longer clear the depth buffer with a 3D rectangle.  Hard-code
1451*e57b9183Scg149915 	 * all values to prevent unwanted 3D state from slipping through
1452*e57b9183Scg149915 	 * and screwing with the clear operation.
1453*e57b9183Scg149915 	 */
1454*e57b9183Scg149915 	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
1455*e57b9183Scg149915 	    (dev_priv->color_fmt << 10) |
1456*e57b9183Scg149915 	    (dev_priv->microcode_version ==
1457*e57b9183Scg149915 	    UCODE_R100 ? RADEON_ZBLOCK16 : 0));
1458*e57b9183Scg149915 
1459*e57b9183Scg149915 	dev_priv->depth_clear.rb3d_zstencilcntl =
1460*e57b9183Scg149915 	    (dev_priv->depth_fmt |
1461*e57b9183Scg149915 	    RADEON_Z_TEST_ALWAYS |
1462*e57b9183Scg149915 	    RADEON_STENCIL_TEST_ALWAYS |
1463*e57b9183Scg149915 	    RADEON_STENCIL_S_FAIL_REPLACE |
1464*e57b9183Scg149915 	    RADEON_STENCIL_ZPASS_REPLACE |
1465*e57b9183Scg149915 	    RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE);
1466*e57b9183Scg149915 
1467*e57b9183Scg149915 	dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
1468*e57b9183Scg149915 	    RADEON_BFACE_SOLID |
1469*e57b9183Scg149915 	    RADEON_FFACE_SOLID |
1470*e57b9183Scg149915 	    RADEON_FLAT_SHADE_VTX_LAST |
1471*e57b9183Scg149915 	    RADEON_DIFFUSE_SHADE_FLAT |
1472*e57b9183Scg149915 	    RADEON_ALPHA_SHADE_FLAT |
1473*e57b9183Scg149915 	    RADEON_SPECULAR_SHADE_FLAT |
1474*e57b9183Scg149915 	    RADEON_FOG_SHADE_FLAT |
1475*e57b9183Scg149915 	    RADEON_VTX_PIX_CENTER_OGL |
1476*e57b9183Scg149915 	    RADEON_ROUND_MODE_TRUNC |
1477*e57b9183Scg149915 	    RADEON_ROUND_PREC_8TH_PIX);
1478*e57b9183Scg149915 
1479*e57b9183Scg149915 	DRM_GETSAREA();
1480*e57b9183Scg149915 
1481*e57b9183Scg149915 	dev_priv->ring_offset = init->ring_offset;
1482*e57b9183Scg149915 	dev_priv->ring_rptr_offset = init->ring_rptr_offset;
1483*e57b9183Scg149915 	dev_priv->buffers_offset = init->buffers_offset;
1484*e57b9183Scg149915 	dev_priv->gart_textures_offset = init->gart_textures_offset;
1485*e57b9183Scg149915 
1486*e57b9183Scg149915 	if (!dev_priv->sarea) {
1487*e57b9183Scg149915 		DRM_ERROR("could not find sarea!\n");
1488*e57b9183Scg149915 		(void) radeon_do_cleanup_cp(dev);
1489*e57b9183Scg149915 		return (EINVAL);
1490*e57b9183Scg149915 	}
1491*e57b9183Scg149915 
1492*e57b9183Scg149915 	dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
1493*e57b9183Scg149915 	if (!dev_priv->cp_ring) {
1494*e57b9183Scg149915 		DRM_ERROR("could not find cp ring region, offset=0x%lx\n",
1495*e57b9183Scg149915 		    init->ring_offset);
1496*e57b9183Scg149915 		(void) radeon_do_cleanup_cp(dev);
1497*e57b9183Scg149915 		return (EINVAL);
1498*e57b9183Scg149915 	}
1499*e57b9183Scg149915 	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
1500*e57b9183Scg149915 	if (!dev_priv->ring_rptr) {
1501*e57b9183Scg149915 		DRM_ERROR("could not find ring read pointer, offset=0x%lx\n",
1502*e57b9183Scg149915 		    init->ring_rptr_offset);
1503*e57b9183Scg149915 		(void) radeon_do_cleanup_cp(dev);
1504*e57b9183Scg149915 		return (EINVAL);
1505*e57b9183Scg149915 	}
1506*e57b9183Scg149915 	dev->agp_buffer_token = init->buffers_offset;
1507*e57b9183Scg149915 	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
1508*e57b9183Scg149915 	if (!dev->agp_buffer_map) {
1509*e57b9183Scg149915 		DRM_ERROR("could not find dma buffer region, offset=0x%lx\n",
1510*e57b9183Scg149915 		    init->buffers_offset);
1511*e57b9183Scg149915 		(void) radeon_do_cleanup_cp(dev);
1512*e57b9183Scg149915 		return (EINVAL);
1513*e57b9183Scg149915 	}
1514*e57b9183Scg149915 
1515*e57b9183Scg149915 	if (init->gart_textures_offset) {
1516*e57b9183Scg149915 		dev_priv->gart_textures =
1517*e57b9183Scg149915 		    drm_core_findmap(dev, init->gart_textures_offset);
1518*e57b9183Scg149915 		if (!dev_priv->gart_textures) {
1519*e57b9183Scg149915 			DRM_ERROR("could not find GART texture region, "
1520*e57b9183Scg149915 			    "offset=0x%lx\n", init->gart_textures_offset);
1521*e57b9183Scg149915 			(void) radeon_do_cleanup_cp(dev);
1522*e57b9183Scg149915 			return (EINVAL);
1523*e57b9183Scg149915 		}
1524*e57b9183Scg149915 	}
1525*e57b9183Scg149915 
1526*e57b9183Scg149915 	dev_priv->sarea_priv = (drm_radeon_sarea_t *)(uintptr_t)
1527*e57b9183Scg149915 	    ((u8 *)(uintptr_t)dev_priv->sarea->handle +
1528*e57b9183Scg149915 	    init->sarea_priv_offset);
1529*e57b9183Scg149915 
1530*e57b9183Scg149915 #if __OS_HAS_AGP
1531*e57b9183Scg149915 	if (dev_priv->flags & RADEON_IS_AGP) {
1532*e57b9183Scg149915 		drm_core_ioremap(dev_priv->cp_ring, dev);
1533*e57b9183Scg149915 		drm_core_ioremap(dev_priv->ring_rptr, dev);
1534*e57b9183Scg149915 		drm_core_ioremap(dev->agp_buffer_map, dev);
1535*e57b9183Scg149915 		if (!dev_priv->cp_ring->handle ||
1536*e57b9183Scg149915 		    !dev_priv->ring_rptr->handle ||
1537*e57b9183Scg149915 		    !dev->agp_buffer_map->handle) {
1538*e57b9183Scg149915 			DRM_ERROR("radeon_do_init_cp: failed to find agp "
1539*e57b9183Scg149915 			    "regions,"
1540*e57b9183Scg149915 			    "cp_ring=0x%x, ring_rptr=0x%x, agp_buf=0x%x",
1541*e57b9183Scg149915 			    dev_priv->cp_ring->handle,
1542*e57b9183Scg149915 			    dev_priv->ring_rptr->handle,
1543*e57b9183Scg149915 			    dev->agp_buffer_map->handle);
1544*e57b9183Scg149915 			(void) radeon_do_cleanup_cp(dev);
1545*e57b9183Scg149915 			return (EINVAL);
1546*e57b9183Scg149915 		}
1547*e57b9183Scg149915 	} else
1548*e57b9183Scg149915 #endif
1549*e57b9183Scg149915 	{
1550*e57b9183Scg149915 		dev_priv->cp_ring->handle =
1551*e57b9183Scg149915 		    (void *)(intptr_t)dev_priv->cp_ring->offset;
1552*e57b9183Scg149915 		dev_priv->ring_rptr->handle =
1553*e57b9183Scg149915 		    (void *)(intptr_t)dev_priv->ring_rptr->offset;
1554*e57b9183Scg149915 		dev->agp_buffer_map->handle =
1555*e57b9183Scg149915 		    (void *)(intptr_t)dev->agp_buffer_map->offset;
1556*e57b9183Scg149915 
1557*e57b9183Scg149915 		DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
1558*e57b9183Scg149915 		    dev_priv->cp_ring->handle);
1559*e57b9183Scg149915 		DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
1560*e57b9183Scg149915 		    dev_priv->ring_rptr->handle);
1561*e57b9183Scg149915 		DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
1562*e57b9183Scg149915 		    dev->agp_buffer_map->handle);
1563*e57b9183Scg149915 	}
1564*e57b9183Scg149915 
1565*e57b9183Scg149915 	dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION) &
1566*e57b9183Scg149915 	    0xffff) << 16;
1567*e57b9183Scg149915 	dev_priv->fb_size =
1568*e57b9183Scg149915 	    ((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000)
1569*e57b9183Scg149915 	    - dev_priv->fb_location;
1570*e57b9183Scg149915 
1571*e57b9183Scg149915 	dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
1572*e57b9183Scg149915 	    ((dev_priv->front_offset + dev_priv->fb_location) >> 10));
1573*e57b9183Scg149915 
1574*e57b9183Scg149915 	dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
1575*e57b9183Scg149915 	    ((dev_priv->back_offset + dev_priv->fb_location) >> 10));
1576*e57b9183Scg149915 
1577*e57b9183Scg149915 	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
1578*e57b9183Scg149915 	    ((dev_priv->depth_offset + dev_priv->fb_location) >> 10));
1579*e57b9183Scg149915 
1580*e57b9183Scg149915 	dev_priv->gart_size = init->gart_size;
1581*e57b9183Scg149915 
1582*e57b9183Scg149915 	/* New let's set the memory map ... */
1583*e57b9183Scg149915 	if (dev_priv->new_memmap) {
1584*e57b9183Scg149915 		u32 base = 0;
1585*e57b9183Scg149915 
1586*e57b9183Scg149915 		DRM_INFO("Setting GART location based on new memory map\n");
1587*e57b9183Scg149915 
1588*e57b9183Scg149915 		/*
1589*e57b9183Scg149915 		 * If using AGP, try to locate the AGP aperture at the same
1590*e57b9183Scg149915 		 * location in the card and on the bus, though we have to
1591*e57b9183Scg149915 		 * align it down.
1592*e57b9183Scg149915 		 */
1593*e57b9183Scg149915 #if __OS_HAS_AGP
1594*e57b9183Scg149915 		if (dev_priv->flags & RADEON_IS_AGP) {
1595*e57b9183Scg149915 			base = dev->agp->base;
1596*e57b9183Scg149915 			/* Check if valid */
1597*e57b9183Scg149915 			if ((base + dev_priv->gart_size - 1) >=
1598*e57b9183Scg149915 			    dev_priv->fb_location &&
1599*e57b9183Scg149915 			    base < (dev_priv->fb_location +
1600*e57b9183Scg149915 			    dev_priv->fb_size - 1)) {
1601*e57b9183Scg149915 				DRM_INFO("Can't use AGP base @0x%08lx,"
1602*e57b9183Scg149915 				    "won't fit\n", dev->agp->base);
1603*e57b9183Scg149915 				base = 0;
1604*e57b9183Scg149915 			}
1605*e57b9183Scg149915 		}
1606*e57b9183Scg149915 #endif
1607*e57b9183Scg149915 		/* If not or if AGP is at 0 (Macs), try to put it elsewhere */
1608*e57b9183Scg149915 		if (base == 0) {
1609*e57b9183Scg149915 			base = dev_priv->fb_location + dev_priv->fb_size;
1610*e57b9183Scg149915 			if (base < dev_priv->fb_location ||
1611*e57b9183Scg149915 			    ((base + dev_priv->gart_size) &
1612*e57b9183Scg149915 			    0xfffffffful) < base)
1613*e57b9183Scg149915 				base = dev_priv->fb_location -
1614*e57b9183Scg149915 				    dev_priv->gart_size;
1615*e57b9183Scg149915 		}
1616*e57b9183Scg149915 		dev_priv->gart_vm_start = base & 0xffc00000u;
1617*e57b9183Scg149915 		if (dev_priv->gart_vm_start != base)
1618*e57b9183Scg149915 			DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
1619*e57b9183Scg149915 			    base, dev_priv->gart_vm_start);
1620*e57b9183Scg149915 	} else {
1621*e57b9183Scg149915 		DRM_INFO("Setting GART location based on old memory map\n");
1622*e57b9183Scg149915 		dev_priv->gart_vm_start = dev_priv->fb_location +
1623*e57b9183Scg149915 		    RADEON_READ(RADEON_CONFIG_APER_SIZE);
1624*e57b9183Scg149915 	}
1625*e57b9183Scg149915 
1626*e57b9183Scg149915 #if __OS_HAS_AGP
1627*e57b9183Scg149915 	if (dev_priv->flags & RADEON_IS_AGP)
1628*e57b9183Scg149915 		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset -
1629*e57b9183Scg149915 		    dev->agp->base + dev_priv->gart_vm_start);
1630*e57b9183Scg149915 	else
1631*e57b9183Scg149915 #endif
1632*e57b9183Scg149915 		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset -
1633*e57b9183Scg149915 		    (unsigned long)dev->sg->virtual + dev_priv->gart_vm_start);
1634*e57b9183Scg149915 
1635*e57b9183Scg149915 	DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
1636*e57b9183Scg149915 	DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start);
1637*e57b9183Scg149915 	DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",
1638*e57b9183Scg149915 	    dev_priv->gart_buffers_offset);
1639*e57b9183Scg149915 
1640*e57b9183Scg149915 	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
1641*e57b9183Scg149915 	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle +
1642*e57b9183Scg149915 	    init->ring_size / sizeof (u32));
1643*e57b9183Scg149915 	dev_priv->ring.size = init->ring_size;
1644*e57b9183Scg149915 	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
1645*e57b9183Scg149915 
1646*e57b9183Scg149915 	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof (u32)) - 1;
1647*e57b9183Scg149915 
1648*e57b9183Scg149915 	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
1649*e57b9183Scg149915 
1650*e57b9183Scg149915 #if __OS_HAS_AGP
1651*e57b9183Scg149915 	if (dev_priv->flags & RADEON_IS_AGP) {
1652*e57b9183Scg149915 		/* Turn off PCI GART */
1653*e57b9183Scg149915 		radeon_set_pcigart(dev_priv, 0);
1654*e57b9183Scg149915 	} else
1655*e57b9183Scg149915 #endif
1656*e57b9183Scg149915 	{
1657*e57b9183Scg149915 		/* if we have an offset set from userspace */
1658*e57b9183Scg149915 		if (dev_priv->pcigart_offset) {
1659*e57b9183Scg149915 			dev_priv->gart_info.bus_addr =
1660*e57b9183Scg149915 			    dev_priv->pcigart_offset + dev_priv->fb_location;
1661*e57b9183Scg149915 			dev_priv->gart_info.mapping.offset =
1662*e57b9183Scg149915 			    dev_priv->gart_info.bus_addr;
1663*e57b9183Scg149915 			dev_priv->gart_info.mapping.size =
1664*e57b9183Scg149915 			    RADEON_PCIGART_TABLE_SIZE;
1665*e57b9183Scg149915 
1666*e57b9183Scg149915 			drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
1667*e57b9183Scg149915 			dev_priv->gart_info.addr =
1668*e57b9183Scg149915 			    dev_priv->gart_info.mapping.handle;
1669*e57b9183Scg149915 
1670*e57b9183Scg149915 			dev_priv->gart_info.is_pcie =
1671*e57b9183Scg149915 			    !!(dev_priv->flags & RADEON_IS_PCIE);
1672*e57b9183Scg149915 			dev_priv->gart_info.gart_table_location =
1673*e57b9183Scg149915 			    DRM_ATI_GART_FB;
1674*e57b9183Scg149915 
1675*e57b9183Scg149915 			DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
1676*e57b9183Scg149915 			    dev_priv->gart_info.addr, dev_priv->pcigart_offset);
1677*e57b9183Scg149915 		} else {
1678*e57b9183Scg149915 			dev_priv->gart_info.gart_table_location =
1679*e57b9183Scg149915 			    DRM_ATI_GART_MAIN;
1680*e57b9183Scg149915 			dev_priv->gart_info.addr = NULL;
1681*e57b9183Scg149915 			dev_priv->gart_info.bus_addr = 0;
1682*e57b9183Scg149915 			if (dev_priv->flags & RADEON_IS_PCIE) {
1683*e57b9183Scg149915 				DRM_ERROR("Cannot use PCI Express without "
1684*e57b9183Scg149915 				    "GART in FB memory\n");
1685*e57b9183Scg149915 				(void) radeon_do_cleanup_cp(dev);
1686*e57b9183Scg149915 				return (EINVAL);
1687*e57b9183Scg149915 			}
1688*e57b9183Scg149915 		}
1689*e57b9183Scg149915 
1690*e57b9183Scg149915 		if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
1691*e57b9183Scg149915 			DRM_ERROR("failed to init PCI GART!\n");
1692*e57b9183Scg149915 			(void) radeon_do_cleanup_cp(dev);
1693*e57b9183Scg149915 			return (ENOMEM);
1694*e57b9183Scg149915 		}
1695*e57b9183Scg149915 
1696*e57b9183Scg149915 		/* Turn on PCI GART */
1697*e57b9183Scg149915 		radeon_set_pcigart(dev_priv, 1);
1698*e57b9183Scg149915 	}
1699*e57b9183Scg149915 
1700*e57b9183Scg149915 	radeon_cp_load_microcode(dev_priv);
1701*e57b9183Scg149915 	radeon_cp_init_ring_buffer(dev, dev_priv);
1702*e57b9183Scg149915 
1703*e57b9183Scg149915 	dev_priv->last_buf = 0;
1704*e57b9183Scg149915 
1705*e57b9183Scg149915 	(void) radeon_do_engine_reset(dev);
1706*e57b9183Scg149915 	radeon_test_writeback(dev_priv);
1707*e57b9183Scg149915 
1708*e57b9183Scg149915 	return (0);
1709*e57b9183Scg149915 }
1710*e57b9183Scg149915 
radeon_do_cleanup_cp(drm_device_t * dev)1711*e57b9183Scg149915 static int radeon_do_cleanup_cp(drm_device_t *dev)
1712*e57b9183Scg149915 {
1713*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
1714*e57b9183Scg149915 
1715*e57b9183Scg149915 	/*
1716*e57b9183Scg149915 	 * Make sure interrupts are disabled here because the uninstall ioctl
1717*e57b9183Scg149915 	 * may not have been called from userspace and after dev_private
1718*e57b9183Scg149915 	 * is freed, it's too late.
1719*e57b9183Scg149915 	 */
1720*e57b9183Scg149915 	if (dev->irq_enabled)
1721*e57b9183Scg149915 		(void) drm_irq_uninstall(dev);
1722*e57b9183Scg149915 
1723*e57b9183Scg149915 #if __OS_HAS_AGP
1724*e57b9183Scg149915 	if (dev_priv->flags & RADEON_IS_AGP) {
1725*e57b9183Scg149915 		if (dev_priv->cp_ring != NULL) {
1726*e57b9183Scg149915 			drm_core_ioremapfree(dev_priv->cp_ring, dev);
1727*e57b9183Scg149915 			dev_priv->cp_ring = NULL;
1728*e57b9183Scg149915 		}
1729*e57b9183Scg149915 		if (dev_priv->ring_rptr != NULL) {
1730*e57b9183Scg149915 			drm_core_ioremapfree(dev_priv->ring_rptr, dev);
1731*e57b9183Scg149915 			dev_priv->ring_rptr = NULL;
1732*e57b9183Scg149915 		}
1733*e57b9183Scg149915 		if (dev->agp_buffer_map != NULL) {
1734*e57b9183Scg149915 			drm_core_ioremapfree(dev->agp_buffer_map, dev);
1735*e57b9183Scg149915 			dev->agp_buffer_map = NULL;
1736*e57b9183Scg149915 		}
1737*e57b9183Scg149915 	} else
1738*e57b9183Scg149915 #endif
1739*e57b9183Scg149915 	{
1740*e57b9183Scg149915 
1741*e57b9183Scg149915 		if (dev_priv->gart_info.bus_addr) {
1742*e57b9183Scg149915 			/* Turn off PCI GART */
1743*e57b9183Scg149915 			radeon_set_pcigart(dev_priv, 0);
1744*e57b9183Scg149915 			if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
1745*e57b9183Scg149915 				DRM_ERROR("failed to cleanup PCI GART!\n");
1746*e57b9183Scg149915 		}
1747*e57b9183Scg149915 
1748*e57b9183Scg149915 		if (dev_priv->gart_info.gart_table_location ==
1749*e57b9183Scg149915 		    DRM_ATI_GART_FB) {
1750*e57b9183Scg149915 			drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
1751*e57b9183Scg149915 			dev_priv->gart_info.addr = 0;
1752*e57b9183Scg149915 		}
1753*e57b9183Scg149915 	}
1754*e57b9183Scg149915 	/* only clear to the start of flags */
1755*e57b9183Scg149915 	(void) memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
1756*e57b9183Scg149915 
1757*e57b9183Scg149915 	return (0);
1758*e57b9183Scg149915 }
1759*e57b9183Scg149915 
1760*e57b9183Scg149915 /*
1761*e57b9183Scg149915  * This code will reinit the Radeon CP hardware after a resume from disc.
1762*e57b9183Scg149915  * AFAIK, it would be very difficult to pickle the state at suspend time, so
1763*e57b9183Scg149915  * here we make sure that all Radeon hardware initialisation is re-done without
1764*e57b9183Scg149915  * affecting running applications.
1765*e57b9183Scg149915  *
1766*e57b9183Scg149915  * Charl P. Botha <http://cpbotha.net>
1767*e57b9183Scg149915  */
radeon_do_resume_cp(drm_device_t * dev)1768*e57b9183Scg149915 static int radeon_do_resume_cp(drm_device_t *dev)
1769*e57b9183Scg149915 {
1770*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
1771*e57b9183Scg149915 
1772*e57b9183Scg149915 	if (!dev_priv) {
1773*e57b9183Scg149915 		DRM_ERROR("Called with no initialization\n");
1774*e57b9183Scg149915 		return (EINVAL);
1775*e57b9183Scg149915 	}
1776*e57b9183Scg149915 
1777*e57b9183Scg149915 	DRM_DEBUG("Starting radeon_do_resume_cp()\n");
1778*e57b9183Scg149915 
1779*e57b9183Scg149915 #if __OS_HAS_AGP
1780*e57b9183Scg149915 	if (dev_priv->flags & RADEON_IS_AGP) {
1781*e57b9183Scg149915 		/* Turn off PCI GART */
1782*e57b9183Scg149915 		radeon_set_pcigart(dev_priv, 0);
1783*e57b9183Scg149915 	} else
1784*e57b9183Scg149915 #endif
1785*e57b9183Scg149915 	{
1786*e57b9183Scg149915 		/* Turn on PCI GART */
1787*e57b9183Scg149915 		radeon_set_pcigart(dev_priv, 1);
1788*e57b9183Scg149915 	}
1789*e57b9183Scg149915 
1790*e57b9183Scg149915 	radeon_cp_load_microcode(dev_priv);
1791*e57b9183Scg149915 	radeon_cp_init_ring_buffer(dev, dev_priv);
1792*e57b9183Scg149915 
1793*e57b9183Scg149915 	(void) radeon_do_engine_reset(dev);
1794*e57b9183Scg149915 
1795*e57b9183Scg149915 	DRM_DEBUG("radeon_do_resume_cp() complete\n");
1796*e57b9183Scg149915 
1797*e57b9183Scg149915 	return (0);
1798*e57b9183Scg149915 }
1799*e57b9183Scg149915 
1800*e57b9183Scg149915 /*ARGSUSED*/
1801*e57b9183Scg149915 int
radeon_cp_init(DRM_IOCTL_ARGS)1802*e57b9183Scg149915 radeon_cp_init(DRM_IOCTL_ARGS)
1803*e57b9183Scg149915 {
1804*e57b9183Scg149915 	DRM_DEVICE;
1805*e57b9183Scg149915 	drm_radeon_init_t init;
1806*e57b9183Scg149915 
1807*e57b9183Scg149915 
1808*e57b9183Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
1809*e57b9183Scg149915 
1810*e57b9183Scg149915 #ifdef _MULTI_DATAMODEL
1811*e57b9183Scg149915 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
1812*e57b9183Scg149915 		drm_radeon_init_32_t init32;
1813*e57b9183Scg149915 
1814*e57b9183Scg149915 		DRM_COPYFROM_WITH_RETURN(&init32, (void *) data,
1815*e57b9183Scg149915 		    sizeof (init32));
1816*e57b9183Scg149915 		init.func = init32.func;
1817*e57b9183Scg149915 		init.sarea_priv_offset = init32.sarea_priv_offset;
1818*e57b9183Scg149915 		init.is_pci = init32.is_pci;
1819*e57b9183Scg149915 		init.cp_mode = init32.cp_mode;
1820*e57b9183Scg149915 		init.gart_size = init32.gart_size;
1821*e57b9183Scg149915 		init.ring_size = init32.ring_size;
1822*e57b9183Scg149915 		init.usec_timeout = init32.usec_timeout;
1823*e57b9183Scg149915 		init.fb_bpp = init32.fb_bpp;
1824*e57b9183Scg149915 		init.front_offset = init32.front_offset;
1825*e57b9183Scg149915 		init.front_pitch = init32.front_pitch;
1826*e57b9183Scg149915 		init.back_offset = init32.back_offset;
1827*e57b9183Scg149915 		init.back_pitch = init32.back_pitch;
1828*e57b9183Scg149915 		init.depth_bpp = init32.depth_bpp;
1829*e57b9183Scg149915 		init.depth_offset = init32.depth_offset;
1830*e57b9183Scg149915 		init.depth_pitch = init32.depth_pitch;
1831*e57b9183Scg149915 		init.ring_offset = init32.ring_offset;
1832*e57b9183Scg149915 		init.ring_rptr_offset = init32.ring_rptr_offset;
1833*e57b9183Scg149915 		init.buffers_offset = init32.buffers_offset;
1834*e57b9183Scg149915 		init.gart_textures_offset = init32.gart_textures_offset;
1835*e57b9183Scg149915 	} else {
1836*e57b9183Scg149915 #endif
1837*e57b9183Scg149915 		DRM_COPYFROM_WITH_RETURN(&init, (void *) data, sizeof (init));
1838*e57b9183Scg149915 #ifdef _MULTI_DATAMODEL
1839*e57b9183Scg149915 	}
1840*e57b9183Scg149915 #endif
1841*e57b9183Scg149915 
1842*e57b9183Scg149915 	if (init.func == RADEON_INIT_R300_CP)
1843*e57b9183Scg149915 		r300_init_reg_flags();
1844*e57b9183Scg149915 
1845*e57b9183Scg149915 	switch (init.func) {
1846*e57b9183Scg149915 	case RADEON_INIT_CP:
1847*e57b9183Scg149915 	case RADEON_INIT_R200_CP:
1848*e57b9183Scg149915 	case RADEON_INIT_R300_CP:
1849*e57b9183Scg149915 		return (radeon_do_init_cp(dev, &init));
1850*e57b9183Scg149915 	case RADEON_CLEANUP_CP:
1851*e57b9183Scg149915 		return (radeon_do_cleanup_cp(dev));
1852*e57b9183Scg149915 	}
1853*e57b9183Scg149915 
1854*e57b9183Scg149915 	return (EINVAL);
1855*e57b9183Scg149915 }
1856*e57b9183Scg149915 
1857*e57b9183Scg149915 /*ARGSUSED*/
1858*e57b9183Scg149915 int
radeon_cp_start(DRM_IOCTL_ARGS)1859*e57b9183Scg149915 radeon_cp_start(DRM_IOCTL_ARGS)
1860*e57b9183Scg149915 {
1861*e57b9183Scg149915 	DRM_DEVICE;
1862*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
1863*e57b9183Scg149915 
1864*e57b9183Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
1865*e57b9183Scg149915 
1866*e57b9183Scg149915 	if (dev_priv->cp_running) {
1867*e57b9183Scg149915 		return (0);
1868*e57b9183Scg149915 	}
1869*e57b9183Scg149915 	if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
1870*e57b9183Scg149915 		DRM_DEBUG("called with bogus CP mode (%d)\n",
1871*e57b9183Scg149915 		    dev_priv->cp_mode);
1872*e57b9183Scg149915 		return (0);
1873*e57b9183Scg149915 	}
1874*e57b9183Scg149915 
1875*e57b9183Scg149915 	radeon_do_cp_start(dev_priv);
1876*e57b9183Scg149915 
1877*e57b9183Scg149915 	return (0);
1878*e57b9183Scg149915 }
1879*e57b9183Scg149915 
1880*e57b9183Scg149915 /*
1881*e57b9183Scg149915  * Stop the CP.  The engine must have been idled before calling this
1882*e57b9183Scg149915  * routine.
1883*e57b9183Scg149915  */
1884*e57b9183Scg149915 /*ARGSUSED*/
1885*e57b9183Scg149915 int
radeon_cp_stop(DRM_IOCTL_ARGS)1886*e57b9183Scg149915 radeon_cp_stop(DRM_IOCTL_ARGS)
1887*e57b9183Scg149915 {
1888*e57b9183Scg149915 	DRM_DEVICE;
1889*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
1890*e57b9183Scg149915 	drm_radeon_cp_stop_t stop;
1891*e57b9183Scg149915 	int ret;
1892*e57b9183Scg149915 
1893*e57b9183Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
1894*e57b9183Scg149915 
1895*e57b9183Scg149915 	DRM_COPYFROM_WITH_RETURN(&stop, (void *) data, sizeof (stop));
1896*e57b9183Scg149915 
1897*e57b9183Scg149915 	if (!dev_priv->cp_running)
1898*e57b9183Scg149915 		return (0);
1899*e57b9183Scg149915 
1900*e57b9183Scg149915 	/*
1901*e57b9183Scg149915 	 * Flush any pending CP commands.  This ensures any outstanding
1902*e57b9183Scg149915 	 * commands are exectuted by the engine before we turn it off.
1903*e57b9183Scg149915 	 */
1904*e57b9183Scg149915 	if (stop.flush) {
1905*e57b9183Scg149915 		radeon_do_cp_flush(dev_priv);
1906*e57b9183Scg149915 	}
1907*e57b9183Scg149915 
1908*e57b9183Scg149915 	/*
1909*e57b9183Scg149915 	 * If we fail to make the engine go idle, we return an error
1910*e57b9183Scg149915 	 * code so that the DRM ioctl wrapper can try again.
1911*e57b9183Scg149915 	 */
1912*e57b9183Scg149915 	if (stop.idle) {
1913*e57b9183Scg149915 		ret = radeon_do_cp_idle(dev_priv);
1914*e57b9183Scg149915 		if (ret)
1915*e57b9183Scg149915 			return (ret);
1916*e57b9183Scg149915 	}
1917*e57b9183Scg149915 
1918*e57b9183Scg149915 	/*
1919*e57b9183Scg149915 	 * Finally, we can turn off the CP.  If the engine isn't idle,
1920*e57b9183Scg149915 	 * we will get some dropped triangles as they won't be fully
1921*e57b9183Scg149915 	 * rendered before the CP is shut down.
1922*e57b9183Scg149915 	 */
1923*e57b9183Scg149915 	radeon_do_cp_stop(dev_priv);
1924*e57b9183Scg149915 
1925*e57b9183Scg149915 	/* Reset the engine */
1926*e57b9183Scg149915 	(void) radeon_do_engine_reset(dev);
1927*e57b9183Scg149915 
1928*e57b9183Scg149915 	return (0);
1929*e57b9183Scg149915 }
1930*e57b9183Scg149915 
1931*e57b9183Scg149915 void
radeon_do_release(drm_device_t * dev)1932*e57b9183Scg149915 radeon_do_release(drm_device_t *dev)
1933*e57b9183Scg149915 {
1934*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
1935*e57b9183Scg149915 	int i, ret;
1936*e57b9183Scg149915 
1937*e57b9183Scg149915 	if (dev_priv) {
1938*e57b9183Scg149915 		if (dev_priv->cp_running) {
1939*e57b9183Scg149915 			/* Stop the cp */
1940*e57b9183Scg149915 			while ((ret = radeon_do_cp_idle(dev_priv)) != 0) {
1941*e57b9183Scg149915 				DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
1942*e57b9183Scg149915 #ifdef __linux__
1943*e57b9183Scg149915 				schedule();
1944*e57b9183Scg149915 #else
1945*e57b9183Scg149915 #if defined(__FreeBSD__) && __FreeBSD_version > 500000
1946*e57b9183Scg149915 				msleep(&ret, &dev->dev_lock, PZERO,
1947*e57b9183Scg149915 				    "rdnrel", 1);
1948*e57b9183Scg149915 #else
1949*e57b9183Scg149915 #if defined(__SOLARIS__) || defined(sun)
1950*e57b9183Scg149915 				(void) drv_usectohz(5);
1951*e57b9183Scg149915 #else
1952*e57b9183Scg149915 				tsleep(&ret, PZERO, "rdnrel", 1);
1953*e57b9183Scg149915 #endif
1954*e57b9183Scg149915 #endif
1955*e57b9183Scg149915 #endif
1956*e57b9183Scg149915 			}
1957*e57b9183Scg149915 			radeon_do_cp_stop(dev_priv);
1958*e57b9183Scg149915 			(void) radeon_do_engine_reset(dev);
1959*e57b9183Scg149915 		}
1960*e57b9183Scg149915 
1961*e57b9183Scg149915 		/* Disable *all* interrupts */
1962*e57b9183Scg149915 		/* remove this after permanent addmaps */
1963*e57b9183Scg149915 		if (dev_priv->mmio)
1964*e57b9183Scg149915 			RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
1965*e57b9183Scg149915 
1966*e57b9183Scg149915 		if (dev_priv->mmio) {	/* remove all surfaces */
1967*e57b9183Scg149915 			for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1968*e57b9183Scg149915 				RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0);
1969*e57b9183Scg149915 				RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND +
1970*e57b9183Scg149915 				    16 * i, 0);
1971*e57b9183Scg149915 				RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND +
1972*e57b9183Scg149915 				    16 * i, 0);
1973*e57b9183Scg149915 			}
1974*e57b9183Scg149915 		}
1975*e57b9183Scg149915 
1976*e57b9183Scg149915 		/* Free memory heap structures */
1977*e57b9183Scg149915 		radeon_mem_takedown(&(dev_priv->gart_heap));
1978*e57b9183Scg149915 		radeon_mem_takedown(&(dev_priv->fb_heap));
1979*e57b9183Scg149915 
1980*e57b9183Scg149915 		/* deallocate kernel resources */
1981*e57b9183Scg149915 		(void) radeon_do_cleanup_cp(dev);
1982*e57b9183Scg149915 	}
1983*e57b9183Scg149915 }
1984*e57b9183Scg149915 
1985*e57b9183Scg149915 /* Just reset the CP ring.  Called as part of an X Server engine reset. */
1986*e57b9183Scg149915 /*ARGSUSED*/
1987*e57b9183Scg149915 int
radeon_cp_reset(DRM_IOCTL_ARGS)1988*e57b9183Scg149915 radeon_cp_reset(DRM_IOCTL_ARGS)
1989*e57b9183Scg149915 {
1990*e57b9183Scg149915 	DRM_DEVICE;
1991*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
1992*e57b9183Scg149915 
1993*e57b9183Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
1994*e57b9183Scg149915 
1995*e57b9183Scg149915 	if (!dev_priv) {
1996*e57b9183Scg149915 		DRM_DEBUG("radeon_cp_reset called before init done\n");
1997*e57b9183Scg149915 		return (EINVAL);
1998*e57b9183Scg149915 	}
1999*e57b9183Scg149915 
2000*e57b9183Scg149915 	radeon_do_cp_reset(dev_priv);
2001*e57b9183Scg149915 
2002*e57b9183Scg149915 	/* The CP is no longer running after an engine reset */
2003*e57b9183Scg149915 	dev_priv->cp_running = 0;
2004*e57b9183Scg149915 
2005*e57b9183Scg149915 	return (0);
2006*e57b9183Scg149915 }
2007*e57b9183Scg149915 
2008*e57b9183Scg149915 /*ARGSUSED*/
2009*e57b9183Scg149915 int
radeon_cp_idle(DRM_IOCTL_ARGS)2010*e57b9183Scg149915 radeon_cp_idle(DRM_IOCTL_ARGS)
2011*e57b9183Scg149915 {
2012*e57b9183Scg149915 	DRM_DEVICE;
2013*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
2014*e57b9183Scg149915 
2015*e57b9183Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
2016*e57b9183Scg149915 
2017*e57b9183Scg149915 	return (radeon_do_cp_idle(dev_priv));
2018*e57b9183Scg149915 }
2019*e57b9183Scg149915 
2020*e57b9183Scg149915 /* Added by Charl P. Botha to call radeon_do_resume_cp(). */
2021*e57b9183Scg149915 /*ARGSUSED*/
2022*e57b9183Scg149915 int
radeon_cp_resume(DRM_IOCTL_ARGS)2023*e57b9183Scg149915 radeon_cp_resume(DRM_IOCTL_ARGS)
2024*e57b9183Scg149915 {
2025*e57b9183Scg149915 	DRM_DEVICE;
2026*e57b9183Scg149915 
2027*e57b9183Scg149915 	return (radeon_do_resume_cp(dev));
2028*e57b9183Scg149915 }
2029*e57b9183Scg149915 
2030*e57b9183Scg149915 /*ARGSUSED*/
2031*e57b9183Scg149915 int
radeon_engine_reset(DRM_IOCTL_ARGS)2032*e57b9183Scg149915 radeon_engine_reset(DRM_IOCTL_ARGS)
2033*e57b9183Scg149915 {
2034*e57b9183Scg149915 	DRM_DEVICE;
2035*e57b9183Scg149915 
2036*e57b9183Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
2037*e57b9183Scg149915 
2038*e57b9183Scg149915 	return (radeon_do_engine_reset(dev));
2039*e57b9183Scg149915 }
2040*e57b9183Scg149915 
2041*e57b9183Scg149915 /*
2042*e57b9183Scg149915  * Fullscreen mode
2043*e57b9183Scg149915  */
2044*e57b9183Scg149915 
2045*e57b9183Scg149915 /* KW: Deprecated to say the least: */
2046*e57b9183Scg149915 /*ARGSUSED*/
2047*e57b9183Scg149915 int
radeon_fullscreen(DRM_IOCTL_ARGS)2048*e57b9183Scg149915 radeon_fullscreen(DRM_IOCTL_ARGS)
2049*e57b9183Scg149915 {
2050*e57b9183Scg149915 	return (0);
2051*e57b9183Scg149915 }
2052*e57b9183Scg149915 
2053*e57b9183Scg149915 /*
2054*e57b9183Scg149915  * Freelist management
2055*e57b9183Scg149915  */
2056*e57b9183Scg149915 
2057*e57b9183Scg149915 /*
2058*e57b9183Scg149915  * Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
2059*e57b9183Scg149915  *   bufs until freelist code is used.  Note this hides a problem with
2060*e57b9183Scg149915  *   the scratch register * (used to keep track of last buffer
2061*e57b9183Scg149915  *   completed) being written to before * the last buffer has actually
2062*e57b9183Scg149915  *   completed rendering.
2063*e57b9183Scg149915  *
2064*e57b9183Scg149915  * KW:  It's also a good way to find free buffers quickly.
2065*e57b9183Scg149915  *
2066*e57b9183Scg149915  * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
2067*e57b9183Scg149915  * sleep.  However, bugs in older versions of radeon_accel.c mean that
2068*e57b9183Scg149915  * we essentially have to do this, else old clients will break.
2069*e57b9183Scg149915  *
2070*e57b9183Scg149915  * However, it does leave open a potential deadlock where all the
2071*e57b9183Scg149915  * buffers are held by other clients, which can't release them because
2072*e57b9183Scg149915  * they can't get the lock.
2073*e57b9183Scg149915  */
2074*e57b9183Scg149915 
2075*e57b9183Scg149915 drm_buf_t *
radeon_freelist_get(drm_device_t * dev)2076*e57b9183Scg149915 radeon_freelist_get(drm_device_t *dev)
2077*e57b9183Scg149915 {
2078*e57b9183Scg149915 	drm_device_dma_t *dma = dev->dma;
2079*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
2080*e57b9183Scg149915 	drm_radeon_buf_priv_t *buf_priv;
2081*e57b9183Scg149915 	drm_buf_t *buf;
2082*e57b9183Scg149915 	int i, t;
2083*e57b9183Scg149915 	int start;
2084*e57b9183Scg149915 
2085*e57b9183Scg149915 	if (++dev_priv->last_buf >= dma->buf_count)
2086*e57b9183Scg149915 		dev_priv->last_buf = 0;
2087*e57b9183Scg149915 
2088*e57b9183Scg149915 	start = dev_priv->last_buf;
2089*e57b9183Scg149915 
2090*e57b9183Scg149915 	for (t = 0; t < dev_priv->usec_timeout; t++) {
2091*e57b9183Scg149915 		u32 done_age = GET_SCRATCH(1);
2092*e57b9183Scg149915 		DRM_DEBUG("done_age = %d\n", done_age);
2093*e57b9183Scg149915 		for (i = start; i < dma->buf_count; i++) {
2094*e57b9183Scg149915 			buf = dma->buflist[i];
2095*e57b9183Scg149915 			buf_priv = buf->dev_private;
2096*e57b9183Scg149915 			if (buf->filp == 0 || (buf->pending &&
2097*e57b9183Scg149915 			    buf_priv->age <= done_age)) {
2098*e57b9183Scg149915 				dev_priv->stats.requested_bufs++;
2099*e57b9183Scg149915 				buf->pending = 0;
2100*e57b9183Scg149915 				return (buf);
2101*e57b9183Scg149915 			}
2102*e57b9183Scg149915 			start = 0;
2103*e57b9183Scg149915 		}
2104*e57b9183Scg149915 
2105*e57b9183Scg149915 		if (t) {
2106*e57b9183Scg149915 			DRM_UDELAY(1);
2107*e57b9183Scg149915 			dev_priv->stats.freelist_loops++;
2108*e57b9183Scg149915 		}
2109*e57b9183Scg149915 	}
2110*e57b9183Scg149915 
2111*e57b9183Scg149915 	DRM_DEBUG("returning NULL!\n");
2112*e57b9183Scg149915 	return (NULL);
2113*e57b9183Scg149915 }
2114*e57b9183Scg149915 
2115*e57b9183Scg149915 #if 0
2116*e57b9183Scg149915 drm_buf_t *
2117*e57b9183Scg149915 radeon_freelist_get(drm_device_t *dev)
2118*e57b9183Scg149915 {
2119*e57b9183Scg149915 	drm_device_dma_t *dma = dev->dma;
2120*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
2121*e57b9183Scg149915 	drm_radeon_buf_priv_t *buf_priv;
2122*e57b9183Scg149915 	drm_buf_t *buf;
2123*e57b9183Scg149915 	int i, t;
2124*e57b9183Scg149915 	int start;
2125*e57b9183Scg149915 	u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
2126*e57b9183Scg149915 
2127*e57b9183Scg149915 	if (++dev_priv->last_buf >= dma->buf_count)
2128*e57b9183Scg149915 		dev_priv->last_buf = 0;
2129*e57b9183Scg149915 
2130*e57b9183Scg149915 	start = dev_priv->last_buf;
2131*e57b9183Scg149915 	dev_priv->stats.freelist_loops++;
2132*e57b9183Scg149915 
2133*e57b9183Scg149915 	for (t = 0; t < 2; t++) {
2134*e57b9183Scg149915 		for (i = start; i < dma->buf_count; i++) {
2135*e57b9183Scg149915 			buf = dma->buflist[i];
2136*e57b9183Scg149915 			buf_priv = buf->dev_private;
2137*e57b9183Scg149915 			if (buf->filp == 0 || (buf->pending &&
2138*e57b9183Scg149915 			    buf_priv->age <= done_age)) {
2139*e57b9183Scg149915 				dev_priv->stats.requested_bufs++;
2140*e57b9183Scg149915 				buf->pending = 0;
2141*e57b9183Scg149915 				return (buf);
2142*e57b9183Scg149915 			}
2143*e57b9183Scg149915 		}
2144*e57b9183Scg149915 		start = 0;
2145*e57b9183Scg149915 	}
2146*e57b9183Scg149915 
2147*e57b9183Scg149915 	return (NULL);
2148*e57b9183Scg149915 }
2149*e57b9183Scg149915 #endif
2150*e57b9183Scg149915 
2151*e57b9183Scg149915 void
radeon_freelist_reset(drm_device_t * dev)2152*e57b9183Scg149915 radeon_freelist_reset(drm_device_t *dev)
2153*e57b9183Scg149915 {
2154*e57b9183Scg149915 	drm_device_dma_t *dma = dev->dma;
2155*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
2156*e57b9183Scg149915 	int i;
2157*e57b9183Scg149915 
2158*e57b9183Scg149915 	dev_priv->last_buf = 0;
2159*e57b9183Scg149915 	for (i = 0; i < dma->buf_count; i++) {
2160*e57b9183Scg149915 		drm_buf_t *buf = dma->buflist[i];
2161*e57b9183Scg149915 		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
2162*e57b9183Scg149915 		buf_priv->age = 0;
2163*e57b9183Scg149915 	}
2164*e57b9183Scg149915 }
2165*e57b9183Scg149915 
2166*e57b9183Scg149915 /*
2167*e57b9183Scg149915  * CP command submission
2168*e57b9183Scg149915  */
2169*e57b9183Scg149915 int
radeon_wait_ring(drm_radeon_private_t * dev_priv,int n)2170*e57b9183Scg149915 radeon_wait_ring(drm_radeon_private_t *dev_priv, int n)
2171*e57b9183Scg149915 {
2172*e57b9183Scg149915 	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
2173*e57b9183Scg149915 	int i;
2174*e57b9183Scg149915 	u32 last_head = GET_RING_HEAD(dev_priv);
2175*e57b9183Scg149915 
2176*e57b9183Scg149915 	for (i = 0; i < dev_priv->usec_timeout; i++) {
2177*e57b9183Scg149915 		u32 head = GET_RING_HEAD(dev_priv);
2178*e57b9183Scg149915 
2179*e57b9183Scg149915 		ring->space = (head - ring->tail) * sizeof (u32);
2180*e57b9183Scg149915 		if (ring->space <= 0)
2181*e57b9183Scg149915 			ring->space += ring->size;
2182*e57b9183Scg149915 		if (ring->space > n)
2183*e57b9183Scg149915 			return (0);
2184*e57b9183Scg149915 
2185*e57b9183Scg149915 		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
2186*e57b9183Scg149915 
2187*e57b9183Scg149915 		if (head != last_head)
2188*e57b9183Scg149915 			i = 0;
2189*e57b9183Scg149915 		last_head = head;
2190*e57b9183Scg149915 
2191*e57b9183Scg149915 		DRM_UDELAY(1);
2192*e57b9183Scg149915 	}
2193*e57b9183Scg149915 
2194*e57b9183Scg149915 	/* FIXME: This return value is ignored in the BEGIN_RING macro! */
2195*e57b9183Scg149915 #if RADEON_FIFO_DEBUG
2196*e57b9183Scg149915 	cmn_err(CE_WARN, "radeon_wait_ring failed\n");
2197*e57b9183Scg149915 	radeon_status(dev_priv);
2198*e57b9183Scg149915 	DRM_ERROR("failed!\n");
2199*e57b9183Scg149915 #endif
2200*e57b9183Scg149915 	return (EBUSY);
2201*e57b9183Scg149915 }
2202*e57b9183Scg149915 
2203*e57b9183Scg149915 static int
radeon_cp_get_buffers(drm_file_t * filp,drm_device_t * dev,drm_dma_t * d)2204*e57b9183Scg149915 radeon_cp_get_buffers(drm_file_t *filp, drm_device_t *dev, drm_dma_t *d)
2205*e57b9183Scg149915 {
2206*e57b9183Scg149915 	int i;
2207*e57b9183Scg149915 	drm_buf_t *buf;
2208*e57b9183Scg149915 
2209*e57b9183Scg149915 	for (i = d->granted_count; i < d->request_count; i++) {
2210*e57b9183Scg149915 		buf = radeon_freelist_get(dev);
2211*e57b9183Scg149915 		if (!buf)
2212*e57b9183Scg149915 			return (EBUSY);	/* NOTE: broken client */
2213*e57b9183Scg149915 
2214*e57b9183Scg149915 		buf->filp = filp;
2215*e57b9183Scg149915 
2216*e57b9183Scg149915 		if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
2217*e57b9183Scg149915 		    sizeof (buf->idx)))
2218*e57b9183Scg149915 			return (EFAULT);
2219*e57b9183Scg149915 		if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
2220*e57b9183Scg149915 		    sizeof (buf->total)))
2221*e57b9183Scg149915 			return (EFAULT);
2222*e57b9183Scg149915 
2223*e57b9183Scg149915 		d->granted_count++;
2224*e57b9183Scg149915 	}
2225*e57b9183Scg149915 	return (0);
2226*e57b9183Scg149915 }
2227*e57b9183Scg149915 
2228*e57b9183Scg149915 /*ARGSUSED*/
2229*e57b9183Scg149915 int
radeon_cp_buffers(DRM_IOCTL_ARGS)2230*e57b9183Scg149915 radeon_cp_buffers(DRM_IOCTL_ARGS)
2231*e57b9183Scg149915 {
2232*e57b9183Scg149915 	DRM_DEVICE;
2233*e57b9183Scg149915 	drm_device_dma_t *dma = dev->dma;
2234*e57b9183Scg149915 	int ret = 0;
2235*e57b9183Scg149915 	drm_dma_t d;
2236*e57b9183Scg149915 
2237*e57b9183Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
2238*e57b9183Scg149915 
2239*e57b9183Scg149915 #ifdef _MULTI_DATAMODEL
2240*e57b9183Scg149915 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2241*e57b9183Scg149915 		drm_dma_32_t	dma32;
2242*e57b9183Scg149915 
2243*e57b9183Scg149915 		DRM_COPYFROM_WITH_RETURN(&dma32, (void *)data, sizeof (dma32));
2244*e57b9183Scg149915 		d.context = dma32.context;
2245*e57b9183Scg149915 		d.send_count = dma32.send_count;
2246*e57b9183Scg149915 		d.send_indices = (void *)(uintptr_t)dma32.send_indices;
2247*e57b9183Scg149915 		d.send_sizes = (void *)(uintptr_t)dma32.send_sizes;
2248*e57b9183Scg149915 		d.flags = dma32.flags;
2249*e57b9183Scg149915 		d.request_count = dma32.request_count;
2250*e57b9183Scg149915 		d.request_size = dma32.request_size;
2251*e57b9183Scg149915 		d.request_indices = (void *)(uintptr_t)dma32.request_indices;
2252*e57b9183Scg149915 		d.request_sizes = (void *)(uintptr_t)dma32.request_sizes;
2253*e57b9183Scg149915 		d.granted_count = dma32.granted_count;
2254*e57b9183Scg149915 	} else {
2255*e57b9183Scg149915 #endif
2256*e57b9183Scg149915 		DRM_COPYFROM_WITH_RETURN(&d, (void *)data, sizeof (d));
2257*e57b9183Scg149915 #ifdef _MULTI_DATAMODEL
2258*e57b9183Scg149915 	}
2259*e57b9183Scg149915 #endif
2260*e57b9183Scg149915 	/* Please don't send us buffers. */
2261*e57b9183Scg149915 	if (d.send_count != 0) {
2262*e57b9183Scg149915 		DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
2263*e57b9183Scg149915 		    DRM_CURRENTPID, d.send_count);
2264*e57b9183Scg149915 		return (EINVAL);
2265*e57b9183Scg149915 	}
2266*e57b9183Scg149915 
2267*e57b9183Scg149915 	/* We'll send you buffers. */
2268*e57b9183Scg149915 	if (d.request_count < 0 || d.request_count > dma->buf_count) {
2269*e57b9183Scg149915 		DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
2270*e57b9183Scg149915 		    DRM_CURRENTPID, d.request_count, dma->buf_count);
2271*e57b9183Scg149915 		return (EINVAL);
2272*e57b9183Scg149915 	}
2273*e57b9183Scg149915 
2274*e57b9183Scg149915 	d.granted_count = 0;
2275*e57b9183Scg149915 
2276*e57b9183Scg149915 	if (d.request_count) {
2277*e57b9183Scg149915 		ret = radeon_cp_get_buffers(fpriv, dev, &d);
2278*e57b9183Scg149915 	}
2279*e57b9183Scg149915 
2280*e57b9183Scg149915 #ifdef _MULTI_DATAMODEL
2281*e57b9183Scg149915 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2282*e57b9183Scg149915 		drm_dma_32_t	dma32;
2283*e57b9183Scg149915 
2284*e57b9183Scg149915 		dma32.context = d.context;
2285*e57b9183Scg149915 		dma32.send_count = d.send_count;
2286*e57b9183Scg149915 		dma32.send_indices = (uintptr_t)d.send_indices;
2287*e57b9183Scg149915 		dma32.send_sizes = (uintptr_t)d.send_sizes;
2288*e57b9183Scg149915 		dma32.flags = d.flags;
2289*e57b9183Scg149915 		dma32.request_count = d.request_count;
2290*e57b9183Scg149915 		dma32.request_size = d.request_size;
2291*e57b9183Scg149915 		dma32.request_indices = (uintptr_t)d.request_indices;
2292*e57b9183Scg149915 		dma32.request_sizes = (uintptr_t)d.request_sizes;
2293*e57b9183Scg149915 		dma32.granted_count = d.granted_count;
2294*e57b9183Scg149915 		DRM_COPYTO_WITH_RETURN((void *)data, &dma32, sizeof (dma32));
2295*e57b9183Scg149915 	} else {
2296*e57b9183Scg149915 #endif
2297*e57b9183Scg149915 		DRM_COPYTO_WITH_RETURN((void *)data, &d, sizeof (d));
2298*e57b9183Scg149915 #ifdef _MULTI_DATAMODEL
2299*e57b9183Scg149915 	}
2300*e57b9183Scg149915 #endif
2301*e57b9183Scg149915 	return (ret);
2302*e57b9183Scg149915 }
2303*e57b9183Scg149915 
2304*e57b9183Scg149915 int
radeon_driver_load(struct drm_device * dev,unsigned long flags)2305*e57b9183Scg149915 radeon_driver_load(struct drm_device *dev, unsigned long flags)
2306*e57b9183Scg149915 {
2307*e57b9183Scg149915 	drm_radeon_private_t *dev_priv;
2308*e57b9183Scg149915 	int ret = 0;
2309*e57b9183Scg149915 
2310*e57b9183Scg149915 	dev_priv = drm_alloc(sizeof (drm_radeon_private_t), DRM_MEM_DRIVER);
2311*e57b9183Scg149915 	if (dev_priv == NULL)
2312*e57b9183Scg149915 		return (ENOMEM);
2313*e57b9183Scg149915 
2314*e57b9183Scg149915 	(void) memset(dev_priv, 0, sizeof (drm_radeon_private_t));
2315*e57b9183Scg149915 	dev->dev_private = (void *)dev_priv;
2316*e57b9183Scg149915 	dev_priv->flags = (int)flags;
2317*e57b9183Scg149915 
2318*e57b9183Scg149915 	switch (flags & RADEON_FAMILY_MASK) {
2319*e57b9183Scg149915 	case CHIP_R100:
2320*e57b9183Scg149915 	case CHIP_RV200:
2321*e57b9183Scg149915 	case CHIP_R200:
2322*e57b9183Scg149915 	case CHIP_R300:
2323*e57b9183Scg149915 	case CHIP_R350:
2324*e57b9183Scg149915 	case CHIP_R420:
2325*e57b9183Scg149915 	case CHIP_RV410:
2326*e57b9183Scg149915 		dev_priv->flags |= RADEON_HAS_HIERZ;
2327*e57b9183Scg149915 		break;
2328*e57b9183Scg149915 	default:
2329*e57b9183Scg149915 		/* all other chips have no hierarchical z buffer */
2330*e57b9183Scg149915 		break;
2331*e57b9183Scg149915 	}
2332*e57b9183Scg149915 
2333*e57b9183Scg149915 	if (drm_device_is_agp(dev))
2334*e57b9183Scg149915 		dev_priv->flags |= RADEON_IS_AGP;
2335*e57b9183Scg149915 	else if (drm_device_is_pcie(dev))
2336*e57b9183Scg149915 		dev_priv->flags |= RADEON_IS_PCIE;
2337*e57b9183Scg149915 	else
2338*e57b9183Scg149915 		dev_priv->flags |= RADEON_IS_PCI;
2339*e57b9183Scg149915 
2340*e57b9183Scg149915 	return (ret);
2341*e57b9183Scg149915 }
2342*e57b9183Scg149915 
2343*e57b9183Scg149915 /*
2344*e57b9183Scg149915  * Create mappings for registers and framebuffer so userland doesn't necessarily
2345*e57b9183Scg149915  * have to find them.
2346*e57b9183Scg149915  */
2347*e57b9183Scg149915 int
radeon_driver_firstopen(struct drm_device * dev)2348*e57b9183Scg149915 radeon_driver_firstopen(struct drm_device *dev)
2349*e57b9183Scg149915 {
2350*e57b9183Scg149915 	int ret;
2351*e57b9183Scg149915 	drm_local_map_t *map;
2352*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
2353*e57b9183Scg149915 
2354*e57b9183Scg149915 	/* dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; */
2355*e57b9183Scg149915 
2356*e57b9183Scg149915 	ret = drm_addmap(dev, (uint_t)drm_get_resource_start(dev, 2),
2357*e57b9183Scg149915 	    (uint_t)drm_get_resource_len(dev, 2), _DRM_REGISTERS,
2358*e57b9183Scg149915 	    _DRM_READ_ONLY, &dev_priv->mmio);
2359*e57b9183Scg149915 
2360*e57b9183Scg149915 	if (ret != 0) {
2361*e57b9183Scg149915 		cmn_err(CE_WARN, "radeon_driver_firstopen: "
2362*e57b9183Scg149915 		    "failed to mmap BAR2 addr=0x%x, len=0x%x",
2363*e57b9183Scg149915 		    (uint_t)drm_get_resource_start(dev, 2),
2364*e57b9183Scg149915 		    (uint_t)drm_get_resource_len(dev, 2));
2365*e57b9183Scg149915 		return (ret);
2366*e57b9183Scg149915 	}
2367*e57b9183Scg149915 
2368*e57b9183Scg149915 	ret = drm_addmap(dev, (uint_t)drm_get_resource_start(dev, 0),
2369*e57b9183Scg149915 	    (uint_t)drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
2370*e57b9183Scg149915 	    _DRM_WRITE_COMBINING, &map);
2371*e57b9183Scg149915 	if (ret != 0)
2372*e57b9183Scg149915 		return (ret);
2373*e57b9183Scg149915 
2374*e57b9183Scg149915 	return (0);
2375*e57b9183Scg149915 }
2376*e57b9183Scg149915 
2377*e57b9183Scg149915 int
radeon_driver_unload(struct drm_device * dev)2378*e57b9183Scg149915 radeon_driver_unload(struct drm_device *dev)
2379*e57b9183Scg149915 {
2380*e57b9183Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
2381*e57b9183Scg149915 
2382*e57b9183Scg149915 	DRM_DEBUG("\n");
2383*e57b9183Scg149915 	drm_free(dev_priv, sizeof (*dev_priv), DRM_MEM_DRIVER);
2384*e57b9183Scg149915 
2385*e57b9183Scg149915 	dev->dev_private = NULL;
2386*e57b9183Scg149915 	return (0);
2387*e57b9183Scg149915 }
2388