1/*
2 * Copyright (c) 2002, Thomas Kurschel
3 * Copyright 2004-2011 Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 *
6 * Authors:
7 *		Thomas Kurschel
8 *		Clemens Zeidler, <haiku@clemens-zeidler.de>
9 *		Alexander von Gluck IV, kallisti5@unixzen.com
10 */
11
12
13#include "driver.h"
14#include "device.h"
15#include "lock.h"
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20
21#include <AGP.h>
22#include <KernelExport.h>
23#include <OS.h>
24#include <PCI.h>
25#include <SupportDefs.h>
26
27
28#define TRACE_DRIVER
29#ifdef TRACE_DRIVER
30#	define TRACE(x...) dprintf("radeon_hd: " x)
31#else
32#	define TRACE(x...) ;
33#endif
34
35#define ERROR(x...) dprintf("radeon_hd: " x)
36
37#define MAX_CARDS 1
38
39
40// ATI / AMD cards starting at the Radeon X700 have an AtomBIOS
41
42// list of supported devices
43const struct supported_device {
44	uint32		pciID;
45	uint8		dceMajor;	// Display block family
46	uint8		dceMinor;	// Display block family
47	uint16		chipsetID;
48	uint32		chipsetFlags;
49	const char*	deviceName;
50} kSupportedDevices[] = {
51	// Marketing Names: Radeon X?00
52	// Intorduced: 2004
53	// Codename: Loki
54	// R420 Series  (Radeon) DCE 0.0 (*very* early AtomBIOS)
55
56	// Marketing Names: Radeon X1?00
57	// Introduced: 2005
58	// Codename: Fudo
59	#if 0
60	{0x791e, 1, 0, RADEON_RS690, CHIP_IGP, "Radeon X1200"},
61	{0x791f, 1, 0, RADEON_RS690, CHIP_IGP, "Radeon X1200"},
62	{0x793f, 1, 0, RADEON_RS600, CHIP_IGP, "Radeon X1200"},
63	{0x7941, 1, 0, RADEON_RS600, CHIP_IGP, "Radeon X1200"},
64	{0x7942, 1, 0, RADEON_RS600, CHIP_IGP, "Radeon X1250"},
65	{0x796c, 1, 0, RADEON_RS740, CHIP_IGP, "Radeon RS740"},
66	{0x796d, 1, 0, RADEON_RS740, CHIP_IGP, "Radeon RS740"},
67	{0x796e, 1, 0, RADEON_RS740, CHIP_IGP, "Radeon 2100"},
68	{0x796f, 1, 0, RADEON_RS740, CHIP_IGP, "Radeon RS740"},
69	{0x7140, 1, 0, RADEON_RV515, CHIP_STD, "Radeon X1600"},
70	{0x7100, 1, 0, RADEON_R520,  CHIP_STD, "Radeon X1800"},
71	{0x7104, 1, 0, RADEON_R520,  CHIP_STD, "FireGL v7200"},
72	{0x7109, 1, 0, RADEON_R520,  CHIP_STD, "Radeon X1800"},
73	{0x710a, 1, 0, RADEON_R520,  CHIP_STD, "Radeon X1800"},
74	{0x710b, 1, 0, RADEON_R520,  CHIP_STD, "Radeon X1800"},
75	{0x710c, 1, 0, RADEON_R520,  CHIP_STD, "Radeon X1800"},
76	{0x7120, 1, 0, RADEON_R520,  CHIP_STD, "Radeon X1800"},
77	{0x7129, 1, 0, RADEON_R520,  CHIP_STD, "Radeon X1800"},
78	#endif
79
80	// Marketing Names: Radeon HD 24xx - HD 42xx
81	// Introduced: 2006
82	// Codename: Pele
83	// Process: 55 nm
84	{0x94c7, 2, 0, RADEON_RV610, CHIP_STD, "Radeon HD 2350"},
85	{0x94c1, 2, 0, RADEON_RV610, CHIP_IGP, "Radeon HD 2400"},
86	{0x94c3, 2, 0, RADEON_RV610, CHIP_STD, "Radeon HD 2400"},
87	{0x94cc, 2, 0, RADEON_RV610, CHIP_STD, "Radeon HD 2400"},
88	{0x9519, 2, 0, RADEON_RV630, CHIP_STD, "AMD FireStream 9170"},
89	{0x9586, 2, 0, RADEON_RV630, CHIP_STD, "Radeon HD 2600"},
90	{0x9588, 2, 0, RADEON_RV630, CHIP_STD, "Radeon HD 2600"},
91	{0x958a, 2, 0, RADEON_RV630, CHIP_STD, "Radeon HD 2600 X2"},
92	//	Radeon 2700		- RV630
93	{0x9400, 2, 0, RADEON_R600,  CHIP_STD, "Radeon HD 2900"},
94	{0x9401, 2, 0, RADEON_R600,  CHIP_STD, "Radeon HD 2900"},
95	{0x9402, 2, 0, RADEON_R600,  CHIP_STD, "Radeon HD 2900"},
96	{0x9403, 2, 0, RADEON_R600,  CHIP_STD, "Radeon HD 2900 Pro"},
97	{0x9405, 2, 0, RADEON_R600,  CHIP_STD, "Radeon HD 2900"},
98	{0x940a, 2, 0, RADEON_R600,  CHIP_STD, "Radeon FireGL V8650"},
99	{0x940b, 2, 0, RADEON_R600,  CHIP_STD, "Radeon FireGL V8600"},
100	{0x940f, 2, 0, RADEON_R600,  CHIP_STD, "Radeon FireGL V7600"},
101	{0x9616, 2, 0, RADEON_RV610, CHIP_IGP, "Radeon HD 3000"},
102	{0x9611, 3, 0, RADEON_RV620, CHIP_IGP, "Radeon HD 3100"},
103	{0x9613, 3, 0, RADEON_RV620, CHIP_IGP, "Radeon HD 3100"},
104	{0x9610, 2, 0, RADEON_RV610, CHIP_IGP, "Radeon HD 3200"},
105	{0x9612, 2, 0, RADEON_RV610, CHIP_IGP, "Radeon HD 3200"},
106	{0x9615, 2, 0, RADEON_RV610, CHIP_IGP, "Radeon HD 3200"},
107	{0x9614, 2, 0, RADEON_RV610, CHIP_IGP, "Radeon HD 3300"},
108	//  Radeon 3430		- RV620
109	{0x95c5, 3, 0, RADEON_RV620, CHIP_STD, "Radeon HD 3450"},
110	{0x95c6, 3, 0, RADEON_RV620, CHIP_STD, "Radeon HD 3450"},
111	{0x95c7, 3, 0, RADEON_RV620, CHIP_STD, "Radeon HD 3450"},
112	{0x95c9, 3, 0, RADEON_RV620, CHIP_STD, "Radeon HD 3450"},
113	{0x95c4, 3, 0, RADEON_RV620, CHIP_STD, "Radeon HD 3470"},
114	{0x95c0, 3, 0, RADEON_RV620, CHIP_STD, "Radeon HD 3550"},
115	{0x9581, 2, 0, RADEON_RV630, CHIP_STD, "Radeon HD 3600"},
116	{0x9583, 2, 0, RADEON_RV630, CHIP_STD, "Radeon HD 3600"},
117	{0x9598, 2, 0, RADEON_RV630, CHIP_STD, "Radeon HD 3600"},
118	{0x9591, 3, 0, RADEON_RV635, CHIP_STD, "Radeon HD 3600"},
119	{0x9589, 2, 0, RADEON_RV630, CHIP_STD, "Radeon HD 3610"},
120	//  Radeon 3650		- RV635
121	//  Radeon 3670		- RV635
122	{0x9507, 2, 0, RADEON_RV670, CHIP_STD, "Radeon HD 3830"},
123	{0x9505, 2, 0, RADEON_RV670, CHIP_STD, "Radeon HD 3850"},
124	{0x9513, 2, 0, RADEON_RV670, CHIP_STD, "Radeon HD 3850 X2"},
125	{0x9515, 2, 0, RADEON_RV670, CHIP_STD, "Radeon HD 3850"},
126	{0x9501, 2, 0, RADEON_RV670, CHIP_STD, "Radeon HD 3870"},
127	{0x950F, 2, 0, RADEON_RV670, CHIP_STD, "Radeon HD 3870 X2"},
128	{0x9710, 3, 0, RADEON_RV620, CHIP_IGP, "Radeon HD 4200"},
129	{0x9715, 3, 0, RADEON_RV620, CHIP_IGP, "Radeon HD 4250"},
130	{0x9712, 3, 0, RADEON_RV620, CHIP_IGP, "Radeon HD 4270"},
131	{0x9714, 3, 0, RADEON_RV620, CHIP_IGP, "Radeon HD 4290"},
132
133	// Marketing Names: Radeon HD 4330 - HD 4890, HD 51xx, HD 5xxV
134	// Introduced: 2008
135	// Codename: Wekiva
136	// Process: 55 nm
137	//	Radeon 4330		- RV710
138	{0x954f, 3, 2, RADEON_RV710, CHIP_IGP, "Radeon HD 4300"},
139	{0x9552, 3, 2, RADEON_RV710, CHIP_IGP, "Radeon HD 4300"},
140	{0x9553, 3, 2, RADEON_RV710, CHIP_IGP, "Radeon HD 4500"},
141	{0x9555, 3, 2, RADEON_RV710, CHIP_STD, "Radeon HD 4350"},
142	{0x9540, 3, 2, RADEON_RV710, CHIP_STD, "Radeon HD 4550"},
143	{0x9452, 3, 2, RADEON_RV730, CHIP_STD, "AMD FireStream 9250"},
144	{0x9480, 3, 2, RADEON_RV730, CHIP_STD, "Radeon HD 4650"},
145	{0x9488, 3, 2, RADEON_RV730, CHIP_MOBILE, "Radeon HD 4650"},
146	{0x9498, 3, 2, RADEON_RV730, CHIP_STD, "Radeon HD 4650"},
147	{0x94b4, 3, 2, RADEON_RV740, CHIP_STD, "Radeon HD 4700"},
148	{0x9490, 3, 2, RADEON_RV730, CHIP_STD, "Radeon HD 4710"},
149	{0x94b3, 3, 2, RADEON_RV740, CHIP_STD, "Radeon HD 4770"},
150	{0x94b5, 3, 2, RADEON_RV740, CHIP_STD, "Radeon HD 4770"},
151	{0x9450, 3, 1, RADEON_RV770, CHIP_STD, "AMD FireStream 9270"},
152	{0x944a, 3, 1, RADEON_RV770, CHIP_MOBILE, "Radeon HD 4850"},
153	{0x944e, 3, 1, RADEON_RV770, CHIP_STD, "Radeon HD 4810"},
154	{0x944c, 3, 1, RADEON_RV770, CHIP_STD, "Radeon HD 4830"},
155	{0x9442, 3, 1, RADEON_RV770, CHIP_STD, "Radeon HD 4850"},
156	{0x9443, 3, 1, RADEON_RV770, CHIP_STD, "Radeon HD 4850 X2"},
157	{0x94a1, 3, 1, RADEON_RV770, CHIP_IGP, "Radeon HD 4860"},
158	{0x9440, 3, 1, RADEON_RV770, CHIP_STD, "Radeon HD 4870"},
159	{0x9441, 3, 1, RADEON_RV770, CHIP_STD, "Radeon HD 4870 X2"},
160	{0x9460, 3, 1, RADEON_RV770, CHIP_STD, "Radeon HD 4890"},
161
162	// From here on AMD no longer used numeric identifiers
163
164	// Marketing Names: Radeon HD 54xx ~ HD 63xx
165	// Introduced: 2009
166	// Codename: Evergreen
167	// Process: 40 nm
168	//  Cedar
169	{0x68e1, 4, 0, RADEON_CEDAR, CHIP_STD, "Radeon HD 5430"},
170	{0x68f9, 4, 0, RADEON_CEDAR, CHIP_STD, "Radeon HD 5450"},
171	{0x68e0, 4, 0, RADEON_CEDAR, CHIP_IGP, "Radeon HD 5470"},
172	//  Redwood
173	{0x68da, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5500"},
174	{0x68d9, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5570"},
175	{0x68b9, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5600"},
176	{0x68c1, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5650"},
177	{0x68d8, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5670"},
178	//  Juniper
179	{0x68be, 4, 0, RADEON_JUNIPER, CHIP_STD, "Radeon HD 5700"},
180	{0x68b8, 4, 0, RADEON_JUNIPER, CHIP_STD, "Radeon HD 5770"},
181	//  Juniper LE / XT (67X0 is rebranded 57X0 + tweaks)
182	{0x68bf, 4, 0, RADEON_JUNIPER, CHIP_STD, "Radeon HD 6750"},
183	{0x68ba, 4, 0, RADEON_JUNIPER, CHIP_STD, "Radeon HD 6770"},
184	//  Cypress
185	{0x689e, 4, 0, RADEON_CYPRESS, CHIP_STD, "Radeon HD 5800"},
186	{0x6899, 4, 0, RADEON_CYPRESS, CHIP_STD, "Radeon HD 5850"},
187	{0x6898, 4, 0, RADEON_CYPRESS, CHIP_STD, "Radeon HD 5870"},
188	//  Hemlock
189	{0x689c, 4, 0, RADEON_HEMLOCK, CHIP_STD, "Radeon HD 5900"},
190	// Fusion APUS
191	//  Palm
192	{0x9804, 4, 1, RADEON_PALM, CHIP_APU, "Radeon HD 6250"},
193	{0x9805, 4, 1, RADEON_PALM, CHIP_APU, "Radeon HD 6290"},
194	{0x9807, 4, 1, RADEON_PALM, CHIP_APU, "Radeon HD 6290"},
195	{0x9802, 4, 1, RADEON_PALM, CHIP_APU, "Radeon HD 6310"},
196	{0x9803, 4, 1, RADEON_PALM, CHIP_APU, "Radeon HD 6310"},
197	{0x9806, 4, 1, RADEON_PALM, CHIP_APU, "Radeon HD 6320"},
198	//  Sumo (no VGA / LVDS!, only DP)
199	{0x9640, 4, 1, RADEON_SUMO, CHIP_APU, "Radeon HD 6550D"},
200	{0x9641, 4, 1, RADEON_SUMO, CHIP_APU, "Radeon HD SUMO M"},
201	{0x9647, 4, 1, RADEON_SUMO, CHIP_APU, "Radeon HD 6520G (M)"},
202	{0x9648, 4, 1, RADEON_SUMO, CHIP_APU, "Radeon HD 6480G (M)"},
203	{0x964a, 4, 1, RADEON_SUMO, CHIP_APU, "Radeon HD 6530D"},
204	{0x964e, 4, 1, RADEON_SUMO, CHIP_APU, "Radeon HD SUMO M"},
205	{0x964f, 4, 1, RADEON_SUMO, CHIP_APU, "Radeon HD SUMO M"},
206	//  Sumo2 (no VGA / LVDS!, only DP)
207	{0x9642, 4, 1, RADEON_SUMO2, CHIP_APU, "Radeon HD 6370D"},
208	{0x9643, 4, 1, RADEON_SUMO2, CHIP_APU, "Radeon HD SUMO2 M"},
209	{0x9644, 4, 1, RADEON_SUMO2, CHIP_APU, "Radeon HD 6410D"},
210	{0x9645, 4, 1, RADEON_SUMO2, CHIP_APU, "Radeon HD SUMO2 M"},
211
212	// Radeon HD 64xx - HD 69xx
213	// Introduced: 2010
214	// Codename: Nothern Islands
215	// Process: 40 nm
216	//  Caicos
217	{0x6760, 5, 0, RADEON_CAICOS, CHIP_MOBILE, "Radeon HD 6470M"},
218	{0x6761, 5, 0, RADEON_CAICOS, CHIP_MOBILE, "Radeon HD 6430M"},
219	{0x6762, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD CAICOS"},
220	{0x6763, 5, 0, RADEON_CAICOS, CHIP_DISCREET, "Radeon HD E6460"},
221	{0x6764, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD CAICOS"},
222	{0x6765, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD CAICOS"},
223	{0x6766, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD CAICOS"},
224	{0x6767, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD CAICOS"},
225	{0x6768, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD CAICOS"},
226	{0x6770, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 6400"},
227	{0x6778, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD CAICOS"},
228	{0x6779, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 6450"},
229	{0x68fa, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 7350"},
230	{0x68f9, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 7350"},
231	{0x677b, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 7400"},
232	{0x6772, 5, 0, RADEON_CAICOS, CHIP_APU, "Radeon HD 7400A"},
233	//  Turks
234	{0x6740, 5, 0, RADEON_TURKS, CHIP_MOBILE, "Radeon HD 6770M"},
235	{0x6741, 5, 0, RADEON_TURKS, CHIP_MOBILE, "Radeon HD 6650M"},
236	{0x6742, 5, 0, RADEON_TURKS, CHIP_MOBILE, "Radeon HD 6625M"},
237	{0x6743, 5, 0, RADEON_TURKS, CHIP_DISCREET, "Radeon HD E6760"},
238	{0x6744, 5, 0, RADEON_TURKS, CHIP_MOBILE, "Radeon HD TURKS M"},
239	{0x6745, 5, 0, RADEON_TURKS, CHIP_MOBILE, "Radeon HD TURKS M"},
240	{0x6746, 5, 0, RADEON_TURKS, CHIP_STD, "Radeon HD TURKS"},
241	{0x6747, 5, 0, RADEON_TURKS, CHIP_STD, "Radeon HD TURKS"},
242	{0x6748, 5, 0, RADEON_TURKS, CHIP_STD, "Radeon HD TURKS"},
243	{0x6749, 5, 0, RADEON_TURKS, CHIP_STD, "FirePro v4900"},
244	{0x6750, 5, 0, RADEON_TURKS, CHIP_STD, "Radeon HD 6500"},
245	{0x6758, 5, 0, RADEON_TURKS, CHIP_STD, "Radeon HD 6670"},
246	{0x6759, 5, 0, RADEON_TURKS, CHIP_STD, "Radeon HD 6570/7570"},
247	//  Barts
248	{0x673e, 5, 0, RADEON_BARTS, CHIP_STD, "Radeon HD 6790"},
249	{0x6739, 5, 0, RADEON_BARTS, CHIP_STD, "Radeon HD 6850"},
250	{0x6738, 5, 0, RADEON_BARTS, CHIP_STD, "Radeon HD 6870"},
251	//  Cayman
252	{0x6700, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD CAYMAN"},
253	{0x6701, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD CAYMAN"},
254	{0x6702, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD CAYMAN"},
255	{0x6703, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD CAYMAN"},
256	{0x6704, 5, 0, RADEON_CAYMAN, CHIP_STD, "FirePro v????"},
257	{0x6705, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD CAYMAN"},
258	{0x6706, 5, 0, RADEON_CAYMAN, CHIP_STD, "FirePro v????"},
259	{0x6707, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD CAYMAN"},
260	{0x6708, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD CAYMAN"},
261	{0x6709, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD CAYMAN"},
262	{0x6718, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD 6970"},
263	{0x6719, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD 6950"},
264	{0x671c, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD CAYMAN"},
265	{0x671f, 5, 0, RADEON_CAYMAN, CHIP_STD, "Radeon HD 6900"},
266	//  Antilles (Top, Dual GPU)
267	{0x671d, 5, 0, RADEON_ANTILLES, CHIP_STD, "Radeon HD 6990"},
268
269	// Marketing Names: Radeon HD 74xx - HD 79xx
270	// Introduced: Late 2011
271	// Codename: Southern Islands
272	// Process: 28 nm
273	//  Lombok?
274	{0x6850, 6, 0, RADEON_LOMBOK, CHIP_MOBILE, "Radeon HD 7570"},
275	//  Cape Verde (TODO: Need to find friendly names)
276	{0x6820, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
277	{0x6821, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
278	{0x6823, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
279	{0x6824, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
280	{0x6825, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
281	{0x6826, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
282	{0x6827, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
283	{0x6828, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
284	{0x6829, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
285	{0x682d, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
286	{0x682f, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
287	{0x6830, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
288	{0x6831, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
289	{0x6837, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
290	{0x6838, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
291	{0x6839, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
292	{0x683b, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD Verde"},
293	{0x683f, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD 7750"},
294	{0x683d, 6, 0, RADEON_CAPEVERDE, CHIP_STD, "Radeon HD 7770"},
295	//  Pitcairn (TODO: Need to find friendly names)
296	{0x6800, 6, 0, RADEON_PITCAIRN, CHIP_MOBILE, "Radeon HD 7970"},
297	{0x6801, 6, 0, RADEON_PITCAIRN, CHIP_STD, "Radeon HD Pitcairn"},
298	{0x6802, 6, 0, RADEON_PITCAIRN, CHIP_STD, "Radeon HD Pitcairn"},
299	{0x6808, 6, 0, RADEON_PITCAIRN, CHIP_STD, "Radeon HD Pitcairn"},
300	{0x6809, 6, 0, RADEON_PITCAIRN, CHIP_STD, "Radeon HD Pitcairn"},
301	{0x6810, 6, 0, RADEON_PITCAIRN, CHIP_STD, "Radeon HD Pitcairn"},
302	{0x6818, 6, 0, RADEON_PITCAIRN, CHIP_STD, "Radeon HD 7870"},
303	{0x6819, 6, 0, RADEON_PITCAIRN, CHIP_STD, "Radeon HD 7800"},
304	{0x684c, 6, 0, RADEON_PITCAIRN, CHIP_STD, "Radeon HD Pitcairn"},
305	//  Tahiti (TODO: Need to find friendly names)
306	{0x6780, 6, 0, RADEON_TAHITI, CHIP_STD, "Radeon HD Tahiti"},
307	{0x6784, 6, 0, RADEON_TAHITI, CHIP_STD, "Radeon HD Tahiti"},
308	{0x6788, 6, 0, RADEON_TAHITI, CHIP_STD, "Radeon HD Tahiti"},
309	{0x678a, 6, 0, RADEON_TAHITI, CHIP_STD, "Radeon HD Tahiti"},
310	{0x6790, 6, 0, RADEON_TAHITI, CHIP_STD, "Radeon HD Tahiti"},
311	{0x679e, 6, 0, RADEON_TAHITI, CHIP_STD, "Radeon HD Tahiti"},
312	{0x679f, 6, 0, RADEON_TAHITI, CHIP_STD, "Radeon HD Tahiti"},
313	{0x679a, 6, 0, RADEON_TAHITI, CHIP_STD, "Radeon HD 7950"},
314	{0x6798, 6, 0, RADEON_TAHITI, CHIP_STD, "Radeon HD 7970"},
315	//  New Zealand (Top, Dual GPU)
316	{0x6799, 6, 0, RADEON_TAHITI, CHIP_STD, "Radeon HD 7990"}
317};
318
319
320int32 api_version = B_CUR_DRIVER_API_VERSION;
321
322
323char* gDeviceNames[MAX_CARDS + 1];
324radeon_info* gDeviceInfo[MAX_CARDS];
325pci_module_info* gPCI;
326mutex gLock;
327
328
329static status_t
330get_next_radeon_hd(int32* _cookie, pci_info &info, uint32 &type)
331{
332	int32 index = *_cookie;
333
334	// find devices
335
336	for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) {
337		// check vendor
338		if (info.vendor_id != VENDOR_ID_ATI
339			|| info.class_base != PCI_display
340			|| info.class_sub != PCI_vga)
341			continue;
342
343		// check device
344		for (uint32 i = 0; i < sizeof(kSupportedDevices)
345				/ sizeof(kSupportedDevices[0]); i++) {
346			if (info.device_id == kSupportedDevices[i].pciID) {
347				type = i;
348				*_cookie = index + 1;
349				return B_OK;
350			}
351		}
352	}
353
354	return B_ENTRY_NOT_FOUND;
355}
356
357
358extern "C" const char**
359publish_devices(void)
360{
361	TRACE("%s\n", __func__);
362	return (const char**)gDeviceNames;
363}
364
365
366extern "C" status_t
367init_hardware(void)
368{
369	TRACE("%s\n", __func__);
370
371	status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI);
372	if (status != B_OK) {
373		ERROR("%s: ERROR: pci module unavailable\n", __func__);
374		return status;
375	}
376
377	int32 cookie = 0;
378	uint32 type;
379	pci_info info;
380	status = get_next_radeon_hd(&cookie, info, type);
381
382	put_module(B_PCI_MODULE_NAME);
383	return status;
384}
385
386
387extern "C" status_t
388init_driver(void)
389{
390	TRACE("%s\n", __func__);
391
392	status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI);
393	if (status != B_OK) {
394		ERROR("%s: ERROR: pci module unavailable\n", __func__);
395		return status;
396	}
397
398	mutex_init(&gLock, "radeon hd ksync");
399
400	// find devices
401
402	int32 found = 0;
403
404	for (int32 cookie = 0; found < MAX_CARDS;) {
405		pci_info* info = (pci_info*)malloc(sizeof(pci_info));
406		if (info == NULL)
407			break;
408
409		uint32 type;
410		status = get_next_radeon_hd(&cookie, *info, type);
411		if (status < B_OK) {
412			free(info);
413			break;
414		}
415
416		// create device names & allocate device info structure
417
418		char name[64];
419		sprintf(name, "graphics/radeon_hd_%02x%02x%02x",
420			info->bus, info->device,
421			info->function);
422
423		gDeviceNames[found] = strdup(name);
424		if (gDeviceNames[found] == NULL)
425			break;
426
427		gDeviceInfo[found] = (radeon_info*)malloc(sizeof(radeon_info));
428		if (gDeviceInfo[found] == NULL) {
429			free(gDeviceNames[found]);
430			break;
431		}
432
433		// initialize the structure for later use
434
435		memset(gDeviceInfo[found], 0, sizeof(radeon_info));
436		gDeviceInfo[found]->init_status = B_NO_INIT;
437		gDeviceInfo[found]->id = found;
438		gDeviceInfo[found]->pci = info;
439		gDeviceInfo[found]->registers = (uint8*)info->u.h0.base_registers[0];
440		gDeviceInfo[found]->pciID = kSupportedDevices[type].pciID;
441		gDeviceInfo[found]->deviceName = kSupportedDevices[type].deviceName;
442		gDeviceInfo[found]->chipsetID = kSupportedDevices[type].chipsetID;
443		gDeviceInfo[found]->dceMajor = kSupportedDevices[type].dceMajor;
444		gDeviceInfo[found]->dceMinor = kSupportedDevices[type].dceMinor;
445		gDeviceInfo[found]->chipsetFlags = kSupportedDevices[type].chipsetFlags;
446
447		ERROR("%s: GPU(%ld) %s, revision = 0x%x\n", __func__, found,
448			kSupportedDevices[type].deviceName, info->revision);
449
450		found++;
451	}
452
453	gDeviceNames[found] = NULL;
454
455	if (found == 0) {
456		mutex_destroy(&gLock);
457		put_module(B_AGP_GART_MODULE_NAME);
458		put_module(B_PCI_MODULE_NAME);
459		ERROR("%s: no supported devices found\n", __func__);
460		return ENODEV;
461	}
462
463	return B_OK;
464}
465
466
467extern "C" void
468uninit_driver(void)
469{
470	TRACE("%s\n", __func__);
471
472	mutex_destroy(&gLock);
473
474	// free device related structures
475	char* name;
476	for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) {
477		free(gDeviceInfo[index]);
478		free(name);
479	}
480
481	put_module(B_PCI_MODULE_NAME);
482}
483
484
485extern "C" device_hooks*
486find_device(const char* name)
487{
488	int index;
489
490	TRACE("%s\n", __func__);
491
492	for (index = 0; gDeviceNames[index] != NULL; index++) {
493		if (!strcmp(name, gDeviceNames[index]))
494			return &gDeviceHooks;
495	}
496
497	ERROR("%s: %s wasn't found!\n", __func__, name);
498	return NULL;
499}
500
501