xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp (revision d374a27286b8a52974a97dba0d5966ea026a665d)
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  */
10 
11 
12 #include "driver.h"
13 #include "device.h"
14 #include "lock.h"
15 
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 
20 #include <AGP.h>
21 #include <KernelExport.h>
22 #include <OS.h>
23 #include <PCI.h>
24 #include <SupportDefs.h>
25 
26 
27 #define TRACE_DRIVER
28 #ifdef TRACE_DRIVER
29 #	define TRACE(x) dprintf x
30 #else
31 #	define TRACE(x) ;
32 #endif
33 
34 #define MAX_CARDS 1
35 
36 
37 // list of supported devices
38 const struct supported_device {
39 	uint32		device_id;
40 	int32		type;
41 	const char*	name;
42 } kSupportedDevices[] = {
43 	//R600 series	(HD 2xxx - 42xx)
44 	//	Radeon 2400		- RV610
45 	{0x9611, 0, "Radeon HD 3100"},	/*RV620, IGP*/
46 	{0x9613, 0, "Radeon HD 3100"},	/*RV620, IGP*/
47 	{0x9610, 0, "Radeon HD 3200"},	/*RV620, IGP*/
48 	{0x9612, 0, "Radeon HD 3200"},	/*RV620, IGP*/
49 	{0x9615, 0, "Radeon HD 3200"},	/*RV620, IGP*/
50 	//  Radeon 3410		- RV620
51 	//  Radeon 3430		- RV620
52 	{0x95c5, 0, "Radeon HD 3450"},	/*RV620*/
53 	//  Radeon 3470		- RV620
54 	//	Radeon 4200		- RV620
55 	//	Radeon 4225		- RV620
56 	//	Radeon 4250		- RV620
57 	//	Radeon 4270		- RV620
58 	//	Radeon 2600		- RV630
59 	//	Radeon 2700		- RV630
60 	//  Radeon 3650		- RV635
61 	//  Radeon 3670		- RV635
62 	//  Radeon 3850		- RV670
63 	//  Radeon 3870		- RV670
64 	//  Radeon 3850 x2	- RV680
65 	//  Radeon 3870 x2	- RV680
66 
67 	//R700 series	(HD 43xx - HD 48xx)
68 	//	Radeon 4330		- RV710
69 	{0x954f, 0, "Radeon HD 4350"},	/*RV710*/
70 	{0x9555, 0, "Radeon HD 4350"},	/*RV710*/
71 	//	Radeon 4530		- RV710
72 	{0x9540, 0, "Radeon HD 4550"}	/*RV710*/
73 	//	Radeon 4570		- RV710
74 	//	Radeon 4650		- RV730
75 	//	Radeon 4670		- RV730
76 	//	Radeon 4830		- RV740
77 	//	Radeon 4850		- RV770
78 	//	Radeon 4860		- RV740
79 	//	Radeon 4870		- RV770
80 	//	Radeon 4870	x2	- RV770
81 };
82 
83 
84 const uint32 kATIVendorId = 0x1002;
85 
86 
87 int32 api_version = B_CUR_DRIVER_API_VERSION;
88 
89 
90 char* gDeviceNames[MAX_CARDS + 1];
91 radeon_info* gDeviceInfo[MAX_CARDS];
92 pci_module_info* gPCI;
93 mutex gLock;
94 
95 
96 static status_t
97 get_next_radeon_hd(int32 *_cookie, pci_info &info, uint32 &type)
98 {
99 	int32 index = *_cookie;
100 
101 	// find devices
102 
103 	for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) {
104 		// check vendor
105 		if (info.vendor_id != kATIVendorId
106 			|| info.class_base != PCI_display
107 			|| info.class_sub != PCI_vga)
108 			continue;
109 
110 		// check device
111 		for (uint32 i = 0; i < sizeof(kSupportedDevices)
112 				/ sizeof(kSupportedDevices[0]); i++) {
113 			if (info.device_id == kSupportedDevices[i].device_id) {
114 				type = i;
115 				*_cookie = index + 1;
116 				return B_OK;
117 			}
118 		}
119 	}
120 
121 	return B_ENTRY_NOT_FOUND;
122 }
123 
124 
125 extern "C" const char **
126 publish_devices(void)
127 {
128 	TRACE((DEVICE_NAME ": publish_devices()\n"));
129 	return (const char **)gDeviceNames;
130 }
131 
132 
133 extern "C" status_t
134 init_hardware(void)
135 {
136 	TRACE((DEVICE_NAME ": init_hardware()\n"));
137 
138 	status_t status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPCI);
139 	if (status != B_OK) {
140 		TRACE((DEVICE_NAME ": pci module unavailable\n"));
141 		return status;
142 	}
143 
144 	int32 cookie = 0;
145 	uint32 type;
146 	pci_info info;
147 	status = get_next_radeon_hd(&cookie, info, type);
148 
149 	put_module(B_PCI_MODULE_NAME);
150 	return status;
151 }
152 
153 
154 extern "C" status_t
155 init_driver(void)
156 {
157 	TRACE((DEVICE_NAME ": init_driver()\n"));
158 
159 	status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI);
160 	if (status != B_OK) {
161 		TRACE((DEVICE_NAME ": pci module unavailable\n"));
162 		return status;
163 	}
164 
165 	mutex_init(&gLock, "radeon hd ksync");
166 
167 	// find devices
168 
169 	int32 found = 0;
170 
171 	for (int32 cookie = 0; found < MAX_CARDS;) {
172 		pci_info* info = (pci_info*)malloc(sizeof(pci_info));
173 		if (info == NULL)
174 			break;
175 
176 		uint32 type;
177 		status = get_next_radeon_hd(&cookie, *info, type);
178 		if (status < B_OK) {
179 			free(info);
180 			break;
181 		}
182 
183 		// create device names & allocate device info structure
184 
185 		char name[64];
186 		sprintf(name, "graphics/radeon_hd_%02x%02x%02x",
187 			info->bus, info->device,
188 			info->function);
189 
190 		gDeviceNames[found] = strdup(name);
191 		if (gDeviceNames[found] == NULL)
192 			break;
193 
194 		gDeviceInfo[found] = (radeon_info*)malloc(sizeof(radeon_info));
195 		if (gDeviceInfo[found] == NULL) {
196 			free(gDeviceNames[found]);
197 			break;
198 		}
199 
200 		// initialize the structure for later use
201 
202 		memset(gDeviceInfo[found], 0, sizeof(radeon_info));
203 		gDeviceInfo[found]->init_status = B_NO_INIT;
204 		gDeviceInfo[found]->id = found;
205 		gDeviceInfo[found]->pci = info;
206 		gDeviceInfo[found]->registers = (uint8 *)info->u.h0.base_registers[0];
207 		gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name;
208 		gDeviceInfo[found]->device_type = kSupportedDevices[type].type;
209 
210 		dprintf(DEVICE_NAME ": (%ld) %s, revision = 0x%x\n", found,
211 			kSupportedDevices[type].name, info->revision);
212 
213 		found++;
214 	}
215 
216 	gDeviceNames[found] = NULL;
217 
218 	if (found == 0) {
219 		mutex_destroy(&gLock);
220 		put_module(B_AGP_GART_MODULE_NAME);
221 		put_module(B_PCI_MODULE_NAME);
222 		return ENODEV;
223 	}
224 
225 	return B_OK;
226 }
227 
228 
229 extern "C" void
230 uninit_driver(void)
231 {
232 	TRACE((DEVICE_NAME ": uninit_driver()\n"));
233 
234 	mutex_destroy(&gLock);
235 
236 	// free device related structures
237 	char* name;
238 	for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) {
239 		free(gDeviceInfo[index]);
240 		free(name);
241 	}
242 
243 	put_module(B_PCI_MODULE_NAME);
244 }
245 
246 
247 extern "C" device_hooks*
248 find_device(const char* name)
249 {
250 	int index;
251 
252 	TRACE((DEVICE_NAME ": find_device()\n"));
253 
254 	for (index = 0; gDeviceNames[index] != NULL; index++) {
255 		if (!strcmp(name, gDeviceNames[index]))
256 			return &gDeviceHooks;
257 	}
258 
259 	return NULL;
260 }
261 
262