xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon/detect.c (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
1 /*
2  * Copyright (c) 2002, Thomas Kurschel
3  * Distributed under the terms of the MIT license.
4  */
5 
6 /**	Graphics card detection */
7 
8 
9 #include "radeon_driver.h"
10 
11 #include <stdio.h>
12 #include <string.h>
13 
14 
15 // this table is gathered from different sources
16 // and may even contain some wrong entries
17 #define VENDOR_ID_ATI		0x1002
18 
19 // R100
20 #define DEVICE_ID_RADEON_QD		0x5144
21 #define DEVICE_ID_RADEON_QE		0x5145
22 #define DEVICE_ID_RADEON_QF		0x5146
23 #define DEVICE_ID_RADEON_QG		0x5147
24 
25 // RV100
26 #define DEVICE_ID_RADEON_QY		0x5159
27 #define DEVICE_ID_RADEON_QZ		0x515a
28 
29 #define DEVICE_ID_RN50_515E		0x515E
30 #define DEVICE_ID_RN50_5969		0x5969
31 
32 // M6
33 #define DEVICE_ID_RADEON_LY		0x4c59
34 #define DEVICE_ID_RADEON_LZ		0x4c5a
35 
36 // RV200
37 #define DEVICE_ID_RADEON_QW		0x5157
38 #define DEVICE_ID_RADEON_QX		0x5158
39 
40 // R200 mobility
41 #define DEVICE_ID_RADEON_LW		0x4c57
42 #define DEVICE_ID_RADEON_LX		0x4c58
43 
44 // R200
45 #define DEVICE_ID_RADEON_QH		0x5148
46 #define DEVICE_ID_RADEON_QI		0x5149
47 #define DEVICE_ID_RADEON_QJ		0x514a
48 #define DEVICE_ID_RADEON_QK		0x514b
49 #define DEVICE_ID_RADEON_QL		0x514c
50 #define DEVICE_ID_RADEON_QM		0x514d
51 
52 #define DEVICE_ID_RADEON_Qh		0x5168
53 #define DEVICE_ID_RADEON_Qi		0x5169
54 #define DEVICE_ID_RADEON_Qj		0x516a
55 #define DEVICE_ID_RADEON_Qk		0x516b
56 
57 #define DEVICE_ID_RADEON_BB		0x4242
58 #define DEVICE_ID_RADEON_BC		0x4243
59 
60 // RV250
61 #define DEVICE_ID_RADEON_If     0x4966
62 #define DEVICE_ID_RADEON_Ig     0x4967
63 
64 // M9 (RV250)
65 #define DEVICE_ID_RADEON_Ld     0x4c64
66 #define DEVICE_ID_RADEON_Le     0x4c65
67 #define DEVICE_ID_RADEON_Lf     0x4c66
68 #define DEVICE_ID_RADEON_Lg     0x4c67
69 
70 // RV280
71 #define DEVICE_ID_RADEON_5960	0x5960
72 #define DEVICE_ID_RADEON_Za		0x5961
73 #define DEVICE_ID_RADEON_Zb		0x5962 // new
74 #define DEVICE_ID_RADEON_Zd		0x5964
75 #define DEVICE_ID_RADEON_Ze		0x5965 // new
76 
77 // M9+ (RV280)
78 #define DEVICE_ID_RADEON_5c61   0x5c61
79 #define DEVICE_ID_RADEON_5c63   0x5c63 // new
80 
81 // r300
82 #define DEVICE_ID_RADEON_ND     0x4e44
83 #define DEVICE_ID_RADEON_NE     0x4e45
84 #define DEVICE_ID_RADEON_NF     0x4e46
85 #define DEVICE_ID_RADEON_NG     0x4e47
86 
87 // r300-4P
88 #define DEVICE_ID_RADEON_AD     0x4144
89 #define DEVICE_ID_RADEON_AE     0x4145
90 #define DEVICE_ID_RADEON_AF     0x4146
91 #define DEVICE_ID_RADEON_AG     0x4147
92 
93 // rv350
94 #define DEVICE_ID_RADEON_AP		0x4150
95 #define DEVICE_ID_RADEON_AQ		0x4151
96 #define DEVICE_ID_RADEON_AR		0x4152 // RS360
97 #define DEVICE_ID_RADEON_AS		0x4153 // RV350 ?? on X.org
98 #define DEVICE_ID_RADEON_AT		0x4154 // new
99 #define DEVICE_ID_RADEON_4155	0x4155 // new
100 #define DEVICE_ID_RADEON_AV		0x4156 // new
101 
102 // m10 (rv350)
103 #define DEVICE_ID_RADEON_NP		0x4e50
104 #define DEVICE_ID_RADEON_NQ		0x4e51 // new
105 #define DEVICE_ID_RADEON_NR		0x4e52 // new
106 #define DEVICE_ID_RADEON_NS		0x4e53 // new
107 #define DEVICE_ID_RADEON_NT		0x4e54
108 #define DEVICE_ID_RADEON_NV		0x4e56 // new
109 
110 // r350
111 #define DEVICE_ID_RADEON_AH		0x4148
112 #define DEVICE_ID_RADEON_AI		0x4149 // new
113 #define DEVICE_ID_RADEON_AJ		0x414a // new
114 #define DEVICE_ID_RADEON_AK		0x414b // new
115 #define DEVICE_ID_RADEON_NH		0x4e48
116 #define DEVICE_ID_RADEON_NI		0x4e49
117 #define DEVICE_ID_RADEON_NK		0x4e4b // new
118 
119 // r360
120 #define DEVICE_ID_RADEON_NJ		0x4e4a
121 
122 // rv370 X300
123 //#define DEVICE_ID_RADEON_5b50	0x5b50
124 #define DEVICE_ID_RADEON_5b60	0x5b60
125 #define DEVICE_ID_RADEON_5b62	0x5b62
126 #define DEVICE_ID_RADEON_5b63   0x5b63 // new
127 #define DEVICE_ID_RADEON_5b64	0x5b64 // new
128 #define DEVICE_ID_RADEON_5b65	0x5b65 // new
129 #define DEVICE_ID_RADEON_5460	0x5460
130 #define DEVICE_ID_RADEON_5464	0x5464 // new
131 
132 // rv380 X600
133 #define DEVICE_ID_RADEON_3e50	0x3e50
134 #define DEVICE_ID_RADEON_3e54	0x3e54 // new
135 #define DEVICE_ID_RADEON_3150	0x3150 // new
136 #define DEVICE_ID_RADEON_3154	0x3154 // new
137 #define DEVICE_ID_RADEON_5462	0x5462 // new X600SE on Toshiba M50 really an X300???
138 
139 // rv380 X600AIW
140 #define DEVICE_ID_RADEON_5b62	0x5b62
141 
142 // rv410 X700 pro
143 #define DEVICE_ID_RADEON_5e48	0x5e48 // new
144 #define DEVICE_ID_RADEON_564a	0x564a // new
145 #define DEVICE_ID_RADEON_564b	0x564b // new
146 #define DEVICE_ID_RADEON_564f	0x564f // new
147 #define DEVICE_ID_RADEON_5652	0x5652 // new
148 #define DEVICE_ID_RADEON_5653	0x5653 // new
149 #define DEVICE_ID_RADEON_5e4b	0x5e4b
150 #define DEVICE_ID_RADEON_5e4a	0x5e4a // new
151 #define DEVICE_ID_RADEON_5e4d	0x5e4d // new
152 #define DEVICE_ID_RADEON_5e4c	0x5e4c // new
153 #define DEVICE_ID_RADEON_5e4f	0x5e4f // new
154 
155 
156 // r420 X800
157 #define DEVICE_ID_RADEON_JH 	0x4a48 // new
158 #define DEVICE_ID_RADEON_JI		0x4a49
159 #define DEVICE_ID_RADEON_JJ 	0x4a4a
160 #define DEVICE_ID_RADEON_JK		0x4a4b
161 #define DEVICE_ID_RADEON_JL		0x4a4c // new mobility
162 #define DEVICE_ID_RADEON_JM 	0x4a4d // new
163 #define DEVICE_ID_RADEON_JN		0x4a4e // new
164 #define DEVICE_ID_RADEON_JP		0x4a50
165 #define DEVICE_ID_RADEON_4a4f	0x4a4f // new
166 
167 // r423 X800
168 #define DEVICE_ID_RADEON_UH		0x5548 // new
169 #define DEVICE_ID_RADEON_UI		0x5549
170 #define DEVICE_ID_RADEON_UJ		0x554a
171 #define DEVICE_ID_RADEON_UK		0x554b
172 #define DEVICE_ID_RADEON_UQ		0x5551 // new
173 #define DEVICE_ID_RADEON_UR		0x5552 // new
174 #define DEVICE_ID_RADEON_UT		0x5554 // new
175 
176 #define DEVICE_ID_RADEON_UM		0x554d // ?
177 #define DEVICE_ID_RADEON_UO		0x554f // ?
178 
179 #define DEVICE_ID_RADEON_5d57	0x5d57
180 #define DEVICE_ID_RADEON_5550	0x5550 // new
181 
182 // r430 X850
183 #define DEVICE_ID_RADEON_5d49	0x5d49 // new mob
184 #define DEVICE_ID_RADEON_5d4a	0x5d4a // new mob
185 #define DEVICE_ID_RADEON_5d48	0x5d48 // new mob
186 #define DEVICE_ID_RADEON_554f	0x554f // new
187 #define DEVICE_ID_RADEON_554d	0x554d // new
188 #define DEVICE_ID_RADEON_554e	0x554e // new
189 #define DEVICE_ID_RADEON_554c	0x554c // new
190 
191 // r480
192 #define DEVICE_ID_RADEON_5d4c	0x5d4c // new
193 #define DEVICE_ID_RADEON_5d50	0x5d50 // new
194 #define DEVICE_ID_RADEON_5d4e	0x5d4e // new
195 #define DEVICE_ID_RADEON_5d4f	0x5d4f // new
196 #define DEVICE_ID_RADEON_5d52	0x5d52 // new
197 #define DEVICE_ID_RADEON_5d4d	0x5d4d // new
198 
199 // r481
200 #define DEVICE_ID_RADEON_KJ		0x4b4a
201 #define DEVICE_ID_RADEON_KK		0x4b4b
202 #define DEVICE_ID_RADEON_KL		0x4b4c
203 #define DEVICE_ID_RADEON_KI		0x4b49
204 
205 // rs100
206 #define DEVICE_ID_RS100_4136	0x4136
207 #define DEVICE_ID_RS100_4336	0x4336
208 
209 // rs200
210 #define DEVICE_ID_RS200_4337	0x4337
211 #define DEVICE_ID_RS200_4137	0x4137
212 
213 // rs250
214 #define DEVICE_ID_RS250_4237	0x4237
215 #define DEVICE_ID_RS250_4437	0x4437
216 
217 // rs300
218 #define DEVICE_ID_RS300_5834	0x5834
219 #define DEVICE_ID_RS300_5835	0x5835
220 
221 // rs350
222 #define DEVICE_ID_RS350_7834	0x7834
223 #define DEVICE_ID_RS350_7835	0x7835
224 
225 // rs400
226 #define DEVICE_ID_RS400_5a41	0x5a41
227 #define DEVICE_ID_RS400_5a42	0x5a42
228 
229 // rs410
230 #define DEVICE_ID_RS410_5a61	0x5a61
231 #define DEVICE_ID_RS410_5a62	0x5a62
232 
233 // rs480/82
234 #define DEVICE_ID_RS480_5954	0x5954
235 #define DEVICE_ID_RS480_5955	0x5955
236 #define DEVICE_ID_RS482_5974	0x5974
237 #define DEVICE_ID_RS482_5975	0x5975
238 
239 typedef struct {
240 	uint16 device_id;
241 	radeon_type asic;
242 	uint32 features;
243 	char *name;
244 } RadeonDevice;
245 
246 #define STD_RADEON 0 // common as muck PC graphics card (if there is such a thing)
247 #define ISMOBILITY 1 // is mobility
248 #define INTEGRATED 2 // is IGP (Integrated Graphics Processor) built in to PC mainboard northbridge typically uses system RAM for graphics
249 #define MOBILE_IGP ISMOBILITY | INTEGRATED // 2 disabilites for the price of 1
250 
251 // list of supported devices
252 RadeonDevice radeon_device_list[] = {
253 	// original Radeons, now called r100
254 	{ DEVICE_ID_RADEON_QD	,	rt_r100,	STD_RADEON,	"Radeon 7200 / Radeon / ALL-IN-WONDER Radeon" },
255 	{ DEVICE_ID_RADEON_QE	,	rt_r100,	STD_RADEON,	"Radeon QE" },
256 	{ DEVICE_ID_RADEON_QF	,	rt_r100,	STD_RADEON,	"Radeon QF" },
257 	{ DEVICE_ID_RADEON_QG	,	rt_r100,	STD_RADEON,	"Radeon QG" },
258 
259 	// Radeon VE (low-cost, dual CRT, no TCL), was rt_ve now refered to as rv100
260 	{ DEVICE_ID_RADEON_QY	,	rt_rv100,	STD_RADEON,	"Radeon 7000 / Radeon VE" },
261 	{ DEVICE_ID_RADEON_QZ	,	rt_rv100,	STD_RADEON,	"Radeon QZ VE" },
262 
263 	{ DEVICE_ID_RN50_515E	,	rt_rv100,	STD_RADEON,	"ES1000 515E (PCI)" }, // Evans and Sutherland something or other?
264     { DEVICE_ID_RN50_5969	, 	rt_rv100,	STD_RADEON,	"ES1000 5969 (PCI)" },
265 
266 	// mobility version of original Radeon (based on VE), now called M6
267 	{ DEVICE_ID_RADEON_LY	,	rt_rv100,	ISMOBILITY,	"Radeon Mobility" },
268 	{ DEVICE_ID_RADEON_LZ	,	rt_rv100,	ISMOBILITY,	"Radeon Mobility M6 LZ" },
269 
270 	// RV200 (dual CRT)
271 	{ DEVICE_ID_RADEON_QW	,	rt_rv200,	STD_RADEON,	"Radeon 7500 / ALL-IN-WONDER Radeon 7500" },
272 	{ DEVICE_ID_RADEON_QX	,	rt_rv200,	STD_RADEON,	"Radeon 7500 QX" },
273 
274 	// M7 (based on RV200) was rt_m7
275 	{ DEVICE_ID_RADEON_LW	,	rt_rv200,	ISMOBILITY,	"Radeon Mobility 7500" },
276 	{ DEVICE_ID_RADEON_LX	,	rt_rv200,	ISMOBILITY,	"Radeon Mobility 7500 GL" },
277 
278 	// R200
279 	{ DEVICE_ID_RADEON_QH	,	rt_r200,	STD_RADEON,	"Fire GL E1" },	// chip type: fgl8800
280 	{ DEVICE_ID_RADEON_QI	,	rt_r200,	STD_RADEON,	"Radeon 8500 QI" },
281 	{ DEVICE_ID_RADEON_QJ	,	rt_r200,	STD_RADEON,	"Radeon 8500 QJ" },
282 	{ DEVICE_ID_RADEON_QK	,	rt_r200,	STD_RADEON,	"Radeon 8500 QK" },
283 	{ DEVICE_ID_RADEON_QL	,	rt_r200,	STD_RADEON,	"Radeon 8500 / 8500LE / ALL-IN-WONDER Radeon 8500" },
284 	{ DEVICE_ID_RADEON_QM	,	rt_r200,	STD_RADEON,	"Radeon 9100" },
285 
286 	{ DEVICE_ID_RADEON_Qh	,	rt_r200,	STD_RADEON,	"Radeon 8500 Qh" },
287 	{ DEVICE_ID_RADEON_Qi	,	rt_r200,	STD_RADEON,	"Radeon 8500 Qi" },
288 	{ DEVICE_ID_RADEON_Qj	,	rt_r200,	STD_RADEON,	"Radeon 8500 Qj" },
289 	{ DEVICE_ID_RADEON_Qk	,	rt_r200,	STD_RADEON,	"Radeon 8500 Qk" },
290 
291 	{ DEVICE_ID_RADEON_BB	,	rt_r200,	STD_RADEON,	"ALL-IN-Wonder Radeon 8500 DV (BB)" },
292 	{ DEVICE_ID_RADEON_BC	,	rt_r200,	STD_RADEON,	"ALL-IN-Wonder Radeon 8500 DV (BC)" },
293 
294 	// RV250 (cut-down R200 with integrated TV-Out)
295 	{ DEVICE_ID_RADEON_If	,  rt_rv250,	STD_RADEON,	"Radeon 9000" },
296 	{ DEVICE_ID_RADEON_Ig	,  rt_rv250,	STD_RADEON,	"Radeon 9000 Ig" },
297 
298 	// M9 (based on rv250) was rt_m9
299 	{ DEVICE_ID_RADEON_Ld	,	rt_rv250,	ISMOBILITY,	"Radeon Mobility 9000 Ld" },
300 	{ DEVICE_ID_RADEON_Le	,	rt_rv250,	ISMOBILITY,	"Radeon Mobility 9000 Le" },
301 	{ DEVICE_ID_RADEON_Lf	,	rt_rv250,	ISMOBILITY,	"Radeon Mobility 9000 Lf" },
302 	{ DEVICE_ID_RADEON_Lg	,	rt_rv250,	ISMOBILITY,	"Radeon Mobility 9000 Lg" },
303 
304 	// RV280 (rv250 but faster)
305 	{ DEVICE_ID_RADEON_5960	,	rt_rv280,	STD_RADEON,	"Radeon 9200 Pro" },
306 	{ DEVICE_ID_RADEON_Za	,	rt_rv280,	STD_RADEON,	"Radeon 9200" },
307 	{ DEVICE_ID_RADEON_Zb	,	rt_rv280,	STD_RADEON,	"Radeon 9200" },
308 	{ DEVICE_ID_RADEON_Zd	,	rt_rv280,	STD_RADEON,	"Radeon 9200 SE" },
309 	{ DEVICE_ID_RADEON_Ze	,	rt_rv280,	STD_RADEON,	"Ati FireMV 2200" },
310 
311 	// M9+ (based on rv280) was rt_m9plus
312 	{ DEVICE_ID_RADEON_5c61	,	rt_rv280,	ISMOBILITY,	"Radeon Mobility 9200" },
313 	{ DEVICE_ID_RADEON_5c63	,	rt_rv280,	ISMOBILITY,	"Radeon Mobility 9200" },
314 
315 	// R300
316 	{ DEVICE_ID_RADEON_ND	,	rt_r300,	STD_RADEON,	"Radeon 9700 ND" },
317 	{ DEVICE_ID_RADEON_NE	,	rt_r300,	STD_RADEON,	"Radeon 9700 NE" },
318 	{ DEVICE_ID_RADEON_NF	,	rt_r300,	STD_RADEON,	"Radeon 9600 XT" },
319 	{ DEVICE_ID_RADEON_NG	,	rt_r300,	STD_RADEON,	"Radeon 9700 NG" },
320 
321 	// r300-4P
322 	{ DEVICE_ID_RADEON_AD	,	rt_r300,	STD_RADEON,	"Radeon 9700 AD" },
323 	{ DEVICE_ID_RADEON_AE	,	rt_r300,	STD_RADEON,	"Radeon 9700 AE" },
324 	{ DEVICE_ID_RADEON_AF	,	rt_r300,	STD_RADEON,	"Radeon 9700 AF" },
325 	{ DEVICE_ID_RADEON_AG	,	rt_r300,	STD_RADEON,	"Radeon 9700 AG" },
326 
327 	// RV350
328 	{ DEVICE_ID_RADEON_AP	, 	rt_rv350,	STD_RADEON,	"Radeon 9600 AP" },
329 	{ DEVICE_ID_RADEON_AQ	, 	rt_rv350,	STD_RADEON,	"Radeon 9600SE AQ" },
330 	{ DEVICE_ID_RADEON_AR	, 	rt_rv350,	STD_RADEON,	"Radeon 9600XT AR" },
331 	{ DEVICE_ID_RADEON_AS	, 	rt_rv350,	STD_RADEON,	"Radeon 9550 AS" },
332 	{ DEVICE_ID_RADEON_AT	, 	rt_rv350,	STD_RADEON,	"FireGL T2 AT" },
333 	{ DEVICE_ID_RADEON_4155	,	rt_rv350,	STD_RADEON,	"Radeon 9650 4155" },
334 	{ DEVICE_ID_RADEON_AV	, 	rt_rv350,	STD_RADEON,	"Radeon 9600 AQ" },
335 
336 	// rv350 M10 (based on rv350) was rt_m10
337 	{ DEVICE_ID_RADEON_NP	,	rt_rv350,	ISMOBILITY,	"Radeon Mobility 9600/9700 (M10/M11) NP " },
338 	{ DEVICE_ID_RADEON_NQ	,	rt_rv350,	ISMOBILITY,	"Radeon Mobility 9600 (M10) NQ " },
339 	{ DEVICE_ID_RADEON_NR	,	rt_rv350,	ISMOBILITY,	"Radeon Mobility 9600 (M11) NR " },
340 	{ DEVICE_ID_RADEON_NS	,	rt_rv350,	ISMOBILITY,	"Radeon Mobility 9600 (M10) NS " },
341 	{ DEVICE_ID_RADEON_NT	,	rt_rv350,	ISMOBILITY,	"ATI FireGL Mobility T2 (M10) NT" },
342 	{ DEVICE_ID_RADEON_NV	,	rt_rv350,	ISMOBILITY,	"ATI FireGL Mobility T2e (M11) NV" },
343 
344 	// R350
345 	{ DEVICE_ID_RADEON_AH	,	rt_r350,	STD_RADEON,	"Radeon 9800SE AH" },
346 	{ DEVICE_ID_RADEON_AI	,	rt_r350,	STD_RADEON,	"Radeon 9800 AI" },
347 	{ DEVICE_ID_RADEON_AJ	,	rt_r350,	STD_RADEON,	"Radeon 9800 AJ" },
348 	{ DEVICE_ID_RADEON_AK	,	rt_r350,	STD_RADEON,	"FireGL X2 AK" },
349 	{ DEVICE_ID_RADEON_NH	,	rt_r350,	STD_RADEON,	"Radeon 9800 Pro NH" },
350 	{ DEVICE_ID_RADEON_NI	,	rt_r350,	STD_RADEON,	"Radeon 9800 NI" },
351 	{ DEVICE_ID_RADEON_NK	,	rt_r350,	STD_RADEON,	"FireGL X2 NK" },
352 	{ DEVICE_ID_RADEON_NJ	,	rt_r350,	STD_RADEON,	"Radeon 9800 XT" },
353 
354 	// rv370
355 	{ DEVICE_ID_RADEON_5b60	,	rt_rv380,	STD_RADEON,	"Radeon X300 (RV370) 5B60" },
356 	{ DEVICE_ID_RADEON_5b62	,	rt_rv380,	STD_RADEON,	"Radeon X600 (RV370) 5B62" },
357 	{ DEVICE_ID_RADEON_5b63 ,	rt_rv380,	STD_RADEON,	"Radeon X1050 (RV370) 5B63" },
358 	{ DEVICE_ID_RADEON_5b64	,	rt_rv380,	STD_RADEON,	"FireGL V3100 (RV370) 5B64" },
359 	{ DEVICE_ID_RADEON_5b65	,	rt_rv380,	STD_RADEON,	"FireGL D1100 (RV370) 5B65" },
360 	{ DEVICE_ID_RADEON_5460 ,	rt_rv380,	ISMOBILITY,	"Radeon Mobility M300 (M22) 5460" },
361 	{ DEVICE_ID_RADEON_5464 ,	rt_rv380,	ISMOBILITY,	"FireGL M22 GL 5464" },
362 
363 	// rv380
364 	{ DEVICE_ID_RADEON_3e50	,	rt_rv380,	STD_RADEON,	"Radeon X600 (RV380) 3E50" },
365 	{ DEVICE_ID_RADEON_3e54	,	rt_rv380,	STD_RADEON,	"FireGL V3200 (RV380) 3E54" },
366 	{ DEVICE_ID_RADEON_3150	,	rt_rv380,	ISMOBILITY,	"Radeon Mobility X600 (M24) 3150" },
367 	{ DEVICE_ID_RADEON_3154	,	rt_rv380,	ISMOBILITY,	"FireGL M24 GL 3154" },
368 	{ DEVICE_ID_RADEON_5462 ,	rt_rv380,	ISMOBILITY,	"Radeon X600SE (RV3?0) 5462" },
369 
370 	// rv380
371 	{ DEVICE_ID_RADEON_5b62	 ,	rt_rv380,	STD_RADEON,	"Radeon X600 AIW" },
372 
373 	// rv410
374 	{ DEVICE_ID_RADEON_5e48	,	rt_r420,	STD_RADEON,	"FireGL V5000 (RV410)" },
375 	{ DEVICE_ID_RADEON_564a	,	rt_r420,	ISMOBILITY,	"Mobility FireGL V5000 (M26)" },
376 	{ DEVICE_ID_RADEON_564b	,	rt_r420,	ISMOBILITY,	"Mobility FireGL V5000 (M26)" },
377 	{ DEVICE_ID_RADEON_564f ,	rt_r420,	ISMOBILITY,	"Mobility Radeon X700 XL (M26)" },
378 	{ DEVICE_ID_RADEON_5652	,	rt_r420,	ISMOBILITY,	"Mobility Radeon X700 (M26)" },
379 	{ DEVICE_ID_RADEON_5653	,	rt_r420,	ISMOBILITY,	"Mobility Radeon X700 (M26)" },
380 	{ DEVICE_ID_RADEON_5e4b	,	rt_r420,	STD_RADEON,	"Radeon X700 PRO (RV410)" },
381 	{ DEVICE_ID_RADEON_5e4a	,	rt_r420,	STD_RADEON,	"Radeon X700 XT (RV410)" },
382 	{ DEVICE_ID_RADEON_5e4d	,	rt_r420,	STD_RADEON,	"Radeon X700 (RV410)" },
383 	{ DEVICE_ID_RADEON_5e4c	,	rt_r420,	STD_RADEON,	"Radeon X700 SE (RV410)" },
384 	{ DEVICE_ID_RADEON_5e4f	,	rt_r420,	STD_RADEON,	"Radeon X700 SE (RV410)" },
385 
386 	// r420
387 	{ DEVICE_ID_RADEON_JH 	,	rt_r420,	STD_RADEON,	"Radeon X800 (R420) JH" },
388 	{ DEVICE_ID_RADEON_JI	,	rt_r420,	STD_RADEON,	"Radeon X800PRO (R420) JI" },
389 	{ DEVICE_ID_RADEON_JJ 	,	rt_r420,	STD_RADEON,	"Radeon X800SE (R420) JJ" },
390 	{ DEVICE_ID_RADEON_JK	,	rt_r420,	STD_RADEON,	"Radeon X800 (R420) JK" },
391 	{ DEVICE_ID_RADEON_JL	,	rt_r420,	STD_RADEON,	"Radeon X800 (R420) JL" },
392 	{ DEVICE_ID_RADEON_JM 	,	rt_r420,	STD_RADEON,	"FireGL X3 (R420) JM" },
393 	{ DEVICE_ID_RADEON_JN	,	rt_r420,	ISMOBILITY,	"Radeon Mobility 9800 (M18) JN" },
394 	{ DEVICE_ID_RADEON_JP	,	rt_r420,	STD_RADEON,	"Radeon X800XT (R420) JP" },
395 	{ DEVICE_ID_RADEON_4a4f	,	rt_r420,	STD_RADEON,	"Radeon X800 SE (R420)" },
396 
397 	// r423
398 	{ DEVICE_ID_RADEON_UH	,	rt_r420,	STD_RADEON,	"Radeon X800 (R423) UH" },
399 	{ DEVICE_ID_RADEON_UI	,	rt_r420,	STD_RADEON,	"Radeon X800PRO (R423) UI" },
400 	{ DEVICE_ID_RADEON_UJ	,	rt_r420,	STD_RADEON,	"Radeon X800LE (R423) UJ" },
401 	{ DEVICE_ID_RADEON_UK	,	rt_r420,	STD_RADEON,	"Radeon X800SE (R423) UK" },
402 	{ DEVICE_ID_RADEON_UQ	,	rt_r420,	STD_RADEON,	"FireGL V7200 (R423) UQ" },
403 	{ DEVICE_ID_RADEON_UR	,	rt_r420,	STD_RADEON,	"FireGL V5100 (R423) UR" },
404 	{ DEVICE_ID_RADEON_UT	,	rt_r420,	STD_RADEON,	"FireGL V7100 (R423) UT" },
405 
406 	{ DEVICE_ID_RADEON_UO	,	rt_r420,	STD_RADEON,	"Radeon X800 UO" },
407 	{ DEVICE_ID_RADEON_UM	,	rt_r420,	STD_RADEON,	"Radeon X800 UM" },
408 
409 	{ DEVICE_ID_RADEON_5d57	,	rt_r420,	STD_RADEON,	"Radeon X800 XT" },
410 	{ DEVICE_ID_RADEON_5550	,	rt_r420,	STD_RADEON,	"FireGL V7100 (R423)" },
411 
412 	// r430
413 	{ DEVICE_ID_RADEON_5d49 ,	rt_r420,	ISMOBILITY,	"Mobility FireGL V5100 (M28)" },
414 	{ DEVICE_ID_RADEON_5d4a	,	rt_r420,	ISMOBILITY,	"Mobility Radeon X800 (M28)" },
415 	{ DEVICE_ID_RADEON_5d48	,	rt_r420,	ISMOBILITY,	"Mobility Radeon X800 XT (M28)" },
416 	{ DEVICE_ID_RADEON_554f ,	rt_r420,	STD_RADEON,	"Radeon X800 (R430)" },
417 	{ DEVICE_ID_RADEON_554d	,	rt_r420,	STD_RADEON,	"Radeon X800 XL (R430)" },
418 	{ DEVICE_ID_RADEON_554e	,	rt_r420,	STD_RADEON,	"Radeon X800 SE (R430)" },
419 	{ DEVICE_ID_RADEON_554c ,	rt_r420,	STD_RADEON,	"Radeon X800 XTP (R430)" },
420 
421 	// r480
422 	{ DEVICE_ID_RADEON_5d4c ,	rt_r420,	STD_RADEON,	"Radeon X850 5D4C" },
423 	{ DEVICE_ID_RADEON_5d50	,	rt_r420,	STD_RADEON,	"Radeon FireGL (R480) GL 5D50" },
424 	{ DEVICE_ID_RADEON_5d4e	,	rt_r420,	STD_RADEON,	"Radeon X850 SE (R480)" },
425 	{ DEVICE_ID_RADEON_5d4f ,	rt_r420,	STD_RADEON,	"Radeon X850 PRO (R480)" },
426 	{ DEVICE_ID_RADEON_5d52	,	rt_r420,	STD_RADEON,	"Radeon X850 XT (R480)" },
427 	{ DEVICE_ID_RADEON_5d4d	,	rt_r420,	STD_RADEON,	"Radeon X850 XT PE (R480)" },
428 
429 	// r481
430 	{ DEVICE_ID_RADEON_KJ	,	rt_r420,	STD_RADEON,	"Radeon X850 PRO (R480)" },
431 	{ DEVICE_ID_RADEON_KK	,	rt_r420,	STD_RADEON,	"Radeon X850 SE (R480)" },
432 	{ DEVICE_ID_RADEON_KL	,	rt_r420,	STD_RADEON,	"Radeon X850 XT (R480)" },
433 	{ DEVICE_ID_RADEON_KI	,	rt_r420,	STD_RADEON,	"Radeon X850 XT PE (R480)" },
434 
435 	// rs100 (aka IGP 320)
436 	{ DEVICE_ID_RS100_4136	, 	rt_rs100,	INTEGRATED,	"Radeon IGP320 (A3) 4136" },
437 	{ DEVICE_ID_RS100_4336	, 	rt_rs100,	MOBILE_IGP,	"Radeon IGP320M (U1) 4336" },
438 
439 	// rs200 (aka IGP 340)
440 	{ DEVICE_ID_RS200_4137	,	rt_rs200,	INTEGRATED,	"Radeon IGP330/340/350 (A4) 4137" },
441 	{ DEVICE_ID_RS200_4337	,	rt_rs200,	MOBILE_IGP,	"Radeon IGP330M/340M/350M (U2) 4337" },
442 
443 	// rs250 (aka 7000 IGP)
444 	{ DEVICE_ID_RS250_4237	,	rt_rs200,	INTEGRATED,	"IGP330M/340M/350M (U2) 4337" },
445 	{ DEVICE_ID_RS250_4437	,	rt_rs200,	MOBILE_IGP,	"Radeon Mobility 7000 IGP 4437" },
446 
447 	// rs300
448 	{ DEVICE_ID_RS300_5834	,	rt_rs300,	INTEGRATED,	"Radeon 9100 IGP (A5) 5834" },
449 	{ DEVICE_ID_RS300_5835	,	rt_rs300,	MOBILE_IGP,	"Radeon Mobility 9100 IGP (U3) 5835" },
450 
451 	// rs350
452 	{ DEVICE_ID_RS350_7834	,	rt_rs300,	INTEGRATED,	"Radeon 9100 PRO IGP 7834" },
453 	{ DEVICE_ID_RS350_7835	,	rt_rs300,	MOBILE_IGP,	"Radeon Mobility 9200 IGP 7835" },
454 
455 	// rs400
456 	{ DEVICE_ID_RS400_5a41	,	rt_rv380,	STD_RADEON,	"Radeon XPRESS 200 5A41" }, // X.org people unsure what this is for now
457 	{ DEVICE_ID_RS400_5a42	,	rt_rv380,	ISMOBILITY,	"Radeon XPRESS 200M 5A42" },
458 
459 	// rs410
460 	{ DEVICE_ID_RS410_5a61	,	rt_rv380,	STD_RADEON,	"Radeon XPRESS 200 5A61" }, // X.org people unsure what this is for now
461 	{ DEVICE_ID_RS410_5a62	,	rt_rv380,	ISMOBILITY,	"Radeon XPRESS 200M 5A62" },
462 
463 	// rs480
464 	{ DEVICE_ID_RS480_5954	,	rt_rv380,	STD_RADEON,	"Radeon XPRESS 200 5954" }, // X.org people unsure what this is for now
465 	{ DEVICE_ID_RS480_5955	,	rt_rv380,	ISMOBILITY,	"Radeon XPRESS 200M 5955" },
466 	{ DEVICE_ID_RS482_5974	,	rt_rv380,	STD_RADEON,	"Radeon XPRESS 200 5974" }, // X.org people unsure what this is for now
467 	{ DEVICE_ID_RS482_5975	,	rt_rv380,	ISMOBILITY,	"Radeon XPRESS 200M 5975" },
468 
469 	{ 0, 0, 0, NULL }
470 };
471 
472 
473 // list of supported vendors (there aren't many ;)
474 static struct {
475 	uint16	vendor_id;
476 	RadeonDevice *devices;
477 } SupportedVendors[] = {
478 	{ VENDOR_ID_ATI, radeon_device_list },
479 	{ 0x0000, NULL }
480 };
481 
482 // check, whether there is *any* supported card plugged in
483 bool Radeon_CardDetect( void )
484 {
485 	long		pci_index = 0;
486 	pci_info	pcii;
487 	bool		found_one = FALSE;
488 
489 	if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK)
490 		return B_ERROR;
491 
492 	while ((*pci_bus->get_nth_pci_info)(pci_index, &pcii) == B_NO_ERROR) {
493 		int vendor = 0;
494 
495 		while (SupportedVendors[vendor].vendor_id) {
496 			if (SupportedVendors[vendor].vendor_id == pcii.vendor_id) {
497 				RadeonDevice *devices = SupportedVendors[vendor].devices;
498 
499 				while (devices->device_id) {
500 					if (devices->device_id == pcii.device_id ) {
501 						rom_info ri;
502 
503 						if( Radeon_MapBIOS( &pcii, &ri ) == B_OK ) {
504 							Radeon_UnmapBIOS( &ri );
505 
506 							SHOW_INFO( 0, "found supported device pci index %ld, device 0x%04x/0x%04x",
507 								pci_index, pcii.vendor_id, pcii.device_id );
508 							found_one = TRUE;
509 							goto done;
510 						}
511 					}
512 					devices++;
513 				}
514 			}
515 			vendor++;
516 		}
517 
518 		pci_index++;
519 	}
520 	SHOW_INFO0( 0, "no supported devices found" );
521 
522 done:
523 	put_module(B_PCI_MODULE_NAME);
524 
525 	return (found_one ? B_OK : B_ERROR);
526 }
527 
528 // !extend this array whenever a new ASIC is a added!
529 static struct {
530 	const char 		*name;			// name of ASIC
531 	tv_chip_type	tv_chip;		// TV-Out chip (if any)
532 	bool 			has_crtc2;		// has second CRTC
533 	bool			has_vip;		// has VIP/I2C
534 	bool			new_pll;		// reference divider of PPLL moved to other location
535 } asic_properties[] =
536 {
537 	{ "r100",	tc_external_rt1,	false,	true,	false,},
538 	{ "rv100",	tc_internal_rt1, 	true,	true,	false,},
539 	{ "rs100",	tc_internal_rt1,	true,	false,	false,},
540 	{ "rv200",	tc_internal_rt2, 	true,	true,	false,},
541 	{ "rs200",	tc_internal_rt1, 	true,	false,	false,},
542 	{ "r200",	tc_external_rt1, 	true,	true,	false,},
543 	{ "rv250",	tc_internal_rt2, 	true,	true,	false,},
544 	{ "rs300",	tc_internal_rt1, 	true,	false,	false,},
545 	{ "rv280",	tc_internal_rt2, 	true,	true,	false,},
546 	{ "r300",	tc_internal_rt2, 	true,	true,	true, },
547 	{ "r350",	tc_internal_rt2, 	true,	true,	true, },
548 	{ "rv350",	tc_internal_rt2, 	true,	true,	true, },
549 	{ "rv380",	tc_internal_rt2, 	true,	true,	true, },
550 	{ "r420",	tc_internal_rt2, 	true,	true,	true, }
551 
552 };
553 
554 
555 // get next supported device
556 static bool probeDevice( device_info *di )
557 {
558 	int vendor;
559 
560 	/* if we match a supported vendor */
561 	for( vendor = 0; SupportedVendors[vendor].vendor_id; ++vendor ) {
562 		RadeonDevice *device;
563 
564 		if( SupportedVendors[vendor].vendor_id != di->pcii.vendor_id )
565 			continue;
566 
567 		for( device = SupportedVendors[vendor].devices; device->device_id; ++device ) {
568 			// avoid double-detection
569 			if (device->device_id != di->pcii.device_id )
570 				continue;
571 
572 			di->num_crtc = asic_properties[device->asic].has_crtc2 ? 2 : 1;
573 			di->tv_chip = asic_properties[device->asic].tv_chip;
574 			di->asic = device->asic;
575 			di->is_mobility = (device->features & ISMOBILITY) ? true : false;
576 			di->has_vip = asic_properties[device->asic].has_vip;
577 			di->new_pll = asic_properties[device->asic].new_pll;
578 			di->is_igp = (device->features & INTEGRATED) ? true : false;
579 
580 			// detect chips with broken I2C
581 			switch( device->device_id)
582 			{
583 		    	case DEVICE_ID_RADEON_LY:
584 				case DEVICE_ID_RADEON_LZ:
585 				case DEVICE_ID_RADEON_LW:
586 				case DEVICE_ID_RADEON_LX:
587 				case DEVICE_ID_RADEON_If:
588 				case DEVICE_ID_RADEON_Ig:
589 				case DEVICE_ID_RADEON_5460:
590 				case DEVICE_ID_RADEON_5464:
591 				di->has_no_i2c = true;
592 				default:
593 				di->has_no_i2c = false;
594 
595 			}
596 
597 			// disable 2d DMA engine for chips that don't work with our
598 			// dma code (yet).  I would have used asic type, but R410s are
599 			// treated same asic as r420s in code, and the AGP x800 works fine.
600 			switch ( device->device_id )
601 			{
602 				// rv370
603 				case DEVICE_ID_RADEON_5b60:
604 				case DEVICE_ID_RADEON_5b62:
605 				case DEVICE_ID_RADEON_5b64:
606 				case DEVICE_ID_RADEON_5b65:
607 				case DEVICE_ID_RADEON_5460:
608 				case DEVICE_ID_RADEON_5464:
609 
610 				// rv380
611 				case DEVICE_ID_RADEON_3e50:
612 				case DEVICE_ID_RADEON_3e54:
613 				case DEVICE_ID_RADEON_3150:
614 				case DEVICE_ID_RADEON_3154:
615 				case DEVICE_ID_RADEON_5462:
616 
617 				// rv410
618 				case DEVICE_ID_RADEON_5e48:
619 				case DEVICE_ID_RADEON_564a:
620 				case DEVICE_ID_RADEON_564b:
621 				case DEVICE_ID_RADEON_564f:
622 				case DEVICE_ID_RADEON_5652:
623 				case DEVICE_ID_RADEON_5653:
624 				case DEVICE_ID_RADEON_5e4b:
625 				case DEVICE_ID_RADEON_5e4a:
626 				case DEVICE_ID_RADEON_5e4d:
627 				case DEVICE_ID_RADEON_5e4c:
628 				case DEVICE_ID_RADEON_5e4f:
629 
630 				// rs400
631 				case DEVICE_ID_RS400_5a41:
632 				case DEVICE_ID_RS400_5a42:
633 
634 				// rs410
635 				case DEVICE_ID_RS410_5a61:
636 				case DEVICE_ID_RS410_5a62:
637 				// r430
638 				case DEVICE_ID_RADEON_UM:
639 				// rs480
640 				case DEVICE_ID_RS480_5954:
641 				case DEVICE_ID_RS480_5955:
642 				case DEVICE_ID_RS482_5974:
643 				case DEVICE_ID_RS482_5975:
644 
645 					di->acc_dma = false;
646 					break;
647 				default:
648 					di->acc_dma = true;
649 					break;
650 			}
651 
652 			if( Radeon_MapBIOS( &di->pcii, &di->rom ) != B_OK )
653 				// give up checking this device - no BIOS, no fun
654 				return false;
655 
656 			if( Radeon_ReadBIOSData( di ) != B_OK ) {
657 				Radeon_UnmapBIOS( &di->rom );
658 				return false;
659 			}
660 
661 			// we don't need BIOS any more
662 			Radeon_UnmapBIOS( &di->rom );
663 
664 			SHOW_INFO( 0, "found %s; ASIC: %s", device->name, asic_properties[device->asic].name );
665 
666 			sprintf(di->name, "graphics/%04X_%04X_%02X%02X%02X",
667 				di->pcii.vendor_id, di->pcii.device_id,
668 				di->pcii.bus, di->pcii.device, di->pcii.function);
669 			SHOW_FLOW( 3, "making /dev/%s", di->name );
670 
671 			// we always publish it as a video grabber; we should check for Rage
672 			// Theater, but the corresponding code (vip.c) needs a fully initialized
673 			// driver, and this is too much hazzly, so we leave it to the media add-on
674 			// to verify that the card really supports video-in
675 			sprintf(di->video_name, "video/radeon/%04X_%04X_%02X%02X%02X",
676 				di->pcii.vendor_id, di->pcii.device_id,
677 				di->pcii.bus, di->pcii.device, di->pcii.function);
678 
679 			di->is_open = 0;
680 			di->shared_area = -1;
681 			di->si = NULL;
682 
683 			return true;
684 		}
685 	}
686 
687 	return false;
688 }
689 
690 
691 // gather list of supported devices
692 // (currently, we rely on proper BIOS detection, which
693 //  only works for primary graphics adapter, so multiple
694 //  devices won't really work)
695 void Radeon_ProbeDevices( void )
696 {
697 	uint32 pci_index = 0;
698 	uint32 count = 0;
699 	device_info *di = devices->di;
700 
701 	while( count < MAX_DEVICES ) {
702 		memset( di, 0, sizeof( *di ));
703 
704 		if( (*pci_bus->get_nth_pci_info)(pci_index, &(di->pcii)) != B_NO_ERROR)
705 			break;
706 
707 		if( probeDevice( di )) {
708 			devices->device_names[2*count] = di->name;
709 			devices->device_names[2*count+1] = di->video_name;
710 			di++;
711 			count++;
712 		}
713 
714 		pci_index++;
715 	}
716 
717 	devices->count = count;
718 	devices->device_names[2*count] = NULL;
719 
720 	SHOW_INFO( 0, "%ld supported devices", count );
721 }
722