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 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
239typedef 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) onboard video
249#define MOBILE_IGP ISMOBILITY | INTEGRATED // 2 disabilites for the price of 1
250
251// list of supported devices
252RadeonDevice 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_m 7
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 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 ;)
474static 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
483bool 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"
507								" pci index %ld, device 0x%04x/0x%04x",
508								pci_index, pcii.vendor_id, pcii.device_id);
509							found_one = TRUE;
510							goto done;
511						}
512					}
513					devices++;
514				}
515			}
516			vendor++;
517		}
518
519		pci_index++;
520	}
521	SHOW_INFO0(0, "no supported devices found");
522
523done:
524	put_module(B_PCI_MODULE_NAME);
525
526	return (found_one ? B_OK : B_ERROR);
527}
528
529
530// !extend this array whenever a new ASIC is a added!
531static struct {
532	const char 		*name;			// name of ASIC
533	tv_chip_type	tv_chip;		// TV-Out chip (if any)
534	bool 			has_crtc2;		// has second CRTC
535	bool			has_vip;		// has VIP/I2C
536	bool			new_pll;		// reference divider of PPLL moved to other location
537} asic_properties[] =
538{
539	{ "r100",	tc_external_rt1,	false,	true,	false},
540	{ "rv100",	tc_internal_rt1, 	true,	true,	false},
541	{ "rs100",	tc_internal_rt1,	true,	false,	false},
542	{ "rv200",	tc_internal_rt2, 	true,	true,	false},
543	{ "rs200",	tc_internal_rt1, 	true,	false,	false},
544	{ "r200",	tc_external_rt1, 	true,	true,	false},
545	{ "rv250",	tc_internal_rt2, 	true,	true,	false},
546	{ "rs300",	tc_internal_rt1, 	true,	false,	false},
547	{ "rv280",	tc_internal_rt2, 	true,	true,	false},
548	{ "r300",	tc_internal_rt2, 	true,	true,	true },
549	{ "r350",	tc_internal_rt2, 	true,	true,	true },
550	{ "rv350",	tc_internal_rt2, 	true,	true,	true },
551	{ "rv380",	tc_internal_rt2, 	true,	true,	true },
552	{ "r420",	tc_internal_rt2, 	true,	true,	true }
553
554};
555
556
557// get next supported device
558static bool probeDevice(device_info *di)
559{
560	int vendor;
561
562	/* if we match a supported vendor */
563	for (vendor = 0; SupportedVendors[vendor].vendor_id; ++vendor) {
564		RadeonDevice *device;
565
566		if (SupportedVendors[vendor].vendor_id != di->pcii.vendor_id)
567			continue;
568
569		for (device = SupportedVendors[vendor].devices; device->device_id;
570			++device) {
571			// avoid double-detection
572			if (device->device_id != di->pcii.device_id)
573				continue;
574
575			di->num_crtc = asic_properties[device->asic].has_crtc2 ? 2 : 1;
576			di->tv_chip = asic_properties[device->asic].tv_chip;
577			di->asic = device->asic;
578			di->is_mobility = (device->features & ISMOBILITY) ? true : false;
579			di->has_vip = asic_properties[device->asic].has_vip;
580			di->new_pll = asic_properties[device->asic].new_pll;
581			di->is_igp = (device->features & INTEGRATED) ? true : false;
582
583			// detect chips with broken I2C
584			switch (device->device_id) {
585				case DEVICE_ID_RADEON_LY:
586				case DEVICE_ID_RADEON_LZ:
587				case DEVICE_ID_RADEON_LW:
588				case DEVICE_ID_RADEON_LX:
589				case DEVICE_ID_RADEON_If:
590				case DEVICE_ID_RADEON_Ig:
591				case DEVICE_ID_RADEON_5460:
592				case DEVICE_ID_RADEON_5464:
593					di->has_no_i2c = true;
594					break;
595				default:
596					di->has_no_i2c = false;
597			}
598
599			// disable 2d DMA engine for chips that don't work with our
600			// dma code (yet).  I would have used asic type, but R410s are
601			// treated same asic as r420s in code, and the AGP x800 works fine.
602			switch (device->device_id) {
603				// rv370
604				case DEVICE_ID_RADEON_5b60:
605				case DEVICE_ID_RADEON_5b62:
606				case DEVICE_ID_RADEON_5b64:
607				case DEVICE_ID_RADEON_5b65:
608				case DEVICE_ID_RADEON_5460:
609				case DEVICE_ID_RADEON_5464:
610
611				// rv380
612				case DEVICE_ID_RADEON_3e50:
613				case DEVICE_ID_RADEON_3e54:
614				case DEVICE_ID_RADEON_3150:
615				case DEVICE_ID_RADEON_3154:
616				case DEVICE_ID_RADEON_5462:
617
618				// rv410
619				case DEVICE_ID_RADEON_5e48:
620				case DEVICE_ID_RADEON_564a:
621				case DEVICE_ID_RADEON_564b:
622				case DEVICE_ID_RADEON_564f:
623				case DEVICE_ID_RADEON_5652:
624				case DEVICE_ID_RADEON_5653:
625				case DEVICE_ID_RADEON_5e4b:
626				case DEVICE_ID_RADEON_5e4a:
627				case DEVICE_ID_RADEON_5e4d:
628				case DEVICE_ID_RADEON_5e4c:
629				case DEVICE_ID_RADEON_5e4f:
630
631				// rs400
632				case DEVICE_ID_RS400_5a41:
633				case DEVICE_ID_RS400_5a42:
634
635				// rs410
636				case DEVICE_ID_RS410_5a61:
637				case DEVICE_ID_RS410_5a62:
638
639				// r430
640				case DEVICE_ID_RADEON_UM:
641
642				// rs480
643				case DEVICE_ID_RS480_5954:
644				case DEVICE_ID_RS480_5955:
645				case DEVICE_ID_RS482_5974:
646				case DEVICE_ID_RS482_5975:
647					di->acc_dma = false;
648					break;
649				default:
650					di->acc_dma = true;
651					break;
652			}
653
654			if (Radeon_MapBIOS(&di->pcii, &di->rom) != B_OK)
655				// give up checking this device - no BIOS, no fun
656				return false;
657
658			if (Radeon_ReadBIOSData(di) != B_OK) {
659				Radeon_UnmapBIOS(&di->rom);
660				return false;
661			}
662
663			// we don't need BIOS any more
664			Radeon_UnmapBIOS(&di->rom);
665
666			SHOW_INFO(0, "found %s; ASIC: %s", device->name,
667				asic_properties[device->asic].name);
668
669			sprintf(di->name, "graphics/%04X_%04X_%02X%02X%02X",
670				di->pcii.vendor_id, di->pcii.device_id,
671				di->pcii.bus, di->pcii.device, di->pcii.function);
672			SHOW_FLOW(3, "making /dev/%s", di->name);
673
674			// we always publish it as a video grabber; we should check for Rage
675			// Theater, but the corresponding code (vip.c) needs a fully
676			// initialized driver, and this is too much hazzly, so we leave it
677			// to the media add-on to verify that the card supports video-in
678			sprintf(di->video_name, "video/radeon/%04X_%04X_%02X%02X%02X",
679				di->pcii.vendor_id, di->pcii.device_id,
680				di->pcii.bus, di->pcii.device, di->pcii.function);
681
682			di->is_open = 0;
683			di->shared_area = -1;
684			di->si = NULL;
685
686			return true;
687		}
688	}
689
690	return false;
691}
692
693
694// gather list of supported devices
695// (currently, we rely on proper BIOS detection, which
696//  only works for primary graphics adapter, so multiple
697//  devices won't really work)
698void Radeon_ProbeDevices(void)
699{
700	uint32 pci_index = 0;
701	uint32 count = 0;
702	device_info *di = devices->di;
703
704	while (count < MAX_DEVICES) {
705		memset(di, 0, sizeof(*di));
706
707		if ((*pci_bus->get_nth_pci_info)(pci_index, &(di->pcii)) != B_NO_ERROR)
708			break;
709
710		if (probeDevice(di)) {
711			devices->device_names[2 * count] = di->name;
712			devices->device_names[2 * count + 1] = di->video_name;
713			di++;
714			count++;
715		}
716
717		pci_index++;
718	}
719
720	devices->count = count;
721	devices->device_names[2 * count] = NULL;
722
723	SHOW_INFO(0, "%" B_PRIu32 " supported devices", count);
724}
725