xref: /haiku/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp (revision a5a3b2d9a3d95cbae71eaf371708c73a1780ac0d)
1 /*
2  * Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  */
8 
9 
10 #include "driver.h"
11 #include "device.h"
12 #include "lock.h"
13 
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 
18 #include <AGP.h>
19 #include <KernelExport.h>
20 #include <OS.h>
21 #include <PCI.h>
22 #include <SupportDefs.h>
23 
24 
25 #define TRACE_DRIVER
26 #ifdef TRACE_DRIVER
27 #	define TRACE(x...) dprintf("intel_extreme: " x)
28 #else
29 #	define TRACE(x) ;
30 #endif
31 
32 #define ERROR(x...) dprintf("intel_extreme: " x)
33 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
34 
35 
36 #define MAX_CARDS 4
37 
38 
39 // list of supported devices
40 const struct supported_device {
41 	uint32		device_id;
42 	int32		type;
43 	const char*	name;
44 } kSupportedDevices[] = {
45 	{0x3577, INTEL_TYPE_83x, "i830GM"},
46 	{0x2562, INTEL_TYPE_83x, "i845G"},
47 
48 	{0x2572, INTEL_TYPE_85x, "i865G"},
49 	{0x3582, INTEL_TYPE_85x, "i855G"},
50 	{0x358e, INTEL_TYPE_85x, "i855G"},
51 
52 	{0x2582, INTEL_TYPE_915, "i915G"},
53 	{0x258a, INTEL_TYPE_915, "i915"},
54 	{0x2592, INTEL_TYPE_915M, "i915GM"},
55 	{0x2792, INTEL_TYPE_915, "i910"},
56 	{0x2772, INTEL_TYPE_945, "i945G"},
57 	{0x27a2, INTEL_TYPE_945M, "i945GM"},
58 	{0x27ae, INTEL_TYPE_945M, "i945GME"},
59 	{0x2972, INTEL_TYPE_965, "i946G"},
60 	{0x2982, INTEL_TYPE_965, "G35"},
61 	{0x2992, INTEL_TYPE_965, "i965Q"},
62 	{0x29a2, INTEL_TYPE_965, "i965G"},
63 	{0x2a02, INTEL_TYPE_965M, "i965GM"},
64 	{0x2a12, INTEL_TYPE_965M, "i965GME"},
65 	{0x29b2, INTEL_TYPE_G33, "G33G"},
66 	{0x29c2, INTEL_TYPE_G33, "Q35G"},
67 	{0x29d2, INTEL_TYPE_G33, "Q33G"},
68 
69 	{0x2a42, INTEL_TYPE_GM45, "GM45"},
70 	{0x2e02, INTEL_TYPE_G45, "IGD"},
71 	{0x2e12, INTEL_TYPE_G45, "Q45"},
72 	{0x2e22, INTEL_TYPE_G45, "G45"},
73 	{0x2e32, INTEL_TYPE_G45, "G41"},
74 	{0x2e42, INTEL_TYPE_G45, "B43"},
75 	{0x2e92, INTEL_TYPE_G45, "B43"},
76 
77 	{0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"},
78 	{0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"},
79 
80 	{0x0042, INTEL_TYPE_ILKG, "IronLake Desktop"},
81 	{0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"},
82 	{0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"},
83 	{0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"},
84 
85 	{0x0102, INTEL_TYPE_SNBG, "SandyBridge Desktop GT1"},
86 	{0x0112, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2"},
87 	{0x0122, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2+"},
88 	{0x0106, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT1"},
89 	{0x0116, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2"},
90 	{0x0126, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2+"},
91 	{0x010a, INTEL_TYPE_SNBGS, "SandyBridge Server"},
92 
93 	{0x0152, INTEL_TYPE_IVBG, "IvyBridge Desktop GT1"},
94 	{0x0162, INTEL_TYPE_IVBG, "IvyBridge Desktop GT2"},
95 	{0x0156, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT1"},
96 	{0x0166, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT2"},
97 	{0x015a, INTEL_TYPE_IVBGS, "IvyBridge Server GT1"},
98 	{0x016a, INTEL_TYPE_IVBGS, "IvyBridge Server GT2"},
99 
100 	{0x0412, INTEL_TYPE_IVBG, "Haswell Desktop"},
101 	{0x0416, INTEL_TYPE_IVBGM, "Haswell Mobile"},
102 	{0x0d26, INTEL_TYPE_IVBGM, "Haswell Mobile"},
103 
104 	{0x0155, INTEL_TYPE_VLVG, "ValleyView Desktop"},
105 	{0x0f30, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
106 	{0x0f31, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
107 	{0x0f32, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
108 	{0x0f33, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
109 	{0x0157, INTEL_TYPE_VLVGM, "ValleyView Mobile"},
110 };
111 
112 int32 api_version = B_CUR_DRIVER_API_VERSION;
113 
114 char* gDeviceNames[MAX_CARDS + 1];
115 intel_info* gDeviceInfo[MAX_CARDS];
116 pci_module_info* gPCI;
117 pci_x86_module_info* gPCIx86Module = NULL;
118 agp_gart_module_info* gGART;
119 mutex gLock;
120 
121 
122 static status_t
123 get_next_intel_extreme(int32* _cookie, pci_info &info, uint32 &type)
124 {
125 	int32 index = *_cookie;
126 
127 	// find devices
128 
129 	for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) {
130 		// check vendor
131 		if (info.vendor_id != VENDOR_ID_INTEL
132 			|| info.class_base != PCI_display
133 			|| info.class_sub != PCI_vga)
134 			continue;
135 
136 		// check device
137 		for (uint32 i = 0; i < sizeof(kSupportedDevices)
138 				/ sizeof(kSupportedDevices[0]); i++) {
139 			if (info.device_id == kSupportedDevices[i].device_id) {
140 				type = i;
141 				*_cookie = index + 1;
142 				return B_OK;
143 			}
144 		}
145 	}
146 
147 	return B_ENTRY_NOT_FOUND;
148 }
149 
150 
151 extern "C" const char**
152 publish_devices(void)
153 {
154 	CALLED();
155 	return (const char**)gDeviceNames;
156 }
157 
158 
159 extern "C" status_t
160 init_hardware(void)
161 {
162 	CALLED();
163 
164 	status_t status = get_module(B_PCI_MODULE_NAME,(module_info**)&gPCI);
165 	if (status != B_OK) {
166 		ERROR("pci module unavailable\n");
167 		return status;
168 	}
169 
170 	int32 cookie = 0;
171 	uint32 type;
172 	pci_info info;
173 	status = get_next_intel_extreme(&cookie, info, type);
174 
175 	put_module(B_PCI_MODULE_NAME);
176 	return status;
177 }
178 
179 
180 extern "C" status_t
181 init_driver(void)
182 {
183 	CALLED();
184 
185 	status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI);
186 	if (status != B_OK) {
187 		ERROR("pci module unavailable\n");
188 		return status;
189 	}
190 
191 	status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART);
192 	if (status != B_OK) {
193 		ERROR("AGP GART module unavailable\n");
194 		put_module(B_PCI_MODULE_NAME);
195 		return status;
196 	}
197 
198 	mutex_init(&gLock, "intel extreme ksync");
199 
200 	// Try to get the PCI x86 module as well so we can enable possible MSIs.
201 	if (get_module(B_PCI_X86_MODULE_NAME,
202 			(module_info **)&gPCIx86Module) != B_OK) {
203 		ERROR("failed to get pci x86 module\n");
204 		gPCIx86Module = NULL;
205 	}
206 
207 
208 	// find devices
209 
210 	int32 found = 0;
211 
212 	for (int32 cookie = 0; found < MAX_CARDS;) {
213 		pci_info* info = (pci_info*)malloc(sizeof(pci_info));
214 		if (info == NULL)
215 			break;
216 
217 		uint32 type;
218 		status = get_next_intel_extreme(&cookie, *info, type);
219 		if (status < B_OK) {
220 			free(info);
221 			break;
222 		}
223 
224 		// create device names & allocate device info structure
225 
226 		char name[64];
227 		sprintf(name, "graphics/intel_extreme_%02x%02x%02x",
228 			 info->bus, info->device,
229 			 info->function);
230 
231 		gDeviceNames[found] = strdup(name);
232 		if (gDeviceNames[found] == NULL)
233 			break;
234 
235 		gDeviceInfo[found] = (intel_info*)malloc(sizeof(intel_info));
236 		if (gDeviceInfo[found] == NULL) {
237 			free(gDeviceNames[found]);
238 			break;
239 		}
240 
241 		// initialize the structure for later use
242 
243 		memset(gDeviceInfo[found], 0, sizeof(intel_info));
244 		gDeviceInfo[found]->init_status = B_NO_INIT;
245 		gDeviceInfo[found]->id = found;
246 		gDeviceInfo[found]->pci = info;
247 		gDeviceInfo[found]->registers = info->u.h0.base_registers[0];
248 		gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name;
249 		gDeviceInfo[found]->device_type = kSupportedDevices[type].type;
250 
251 		dprintf(DEVICE_NAME ": (%ld) %s, revision = 0x%x\n", found,
252 			kSupportedDevices[type].name, info->revision);
253 
254 		found++;
255 	}
256 
257 	gDeviceNames[found] = NULL;
258 
259 	if (found == 0) {
260 		mutex_destroy(&gLock);
261 		put_module(B_AGP_GART_MODULE_NAME);
262 		put_module(B_PCI_MODULE_NAME);
263 		if (gPCIx86Module != NULL) {
264 			gPCIx86Module = NULL;
265 			put_module(B_PCI_X86_MODULE_NAME);
266 		}
267 		return ENODEV;
268 	}
269 
270 	return B_OK;
271 }
272 
273 
274 extern "C" void
275 uninit_driver(void)
276 {
277 	CALLED();
278 
279 	mutex_destroy(&gLock);
280 
281 	// free device related structures
282 	char* name;
283 	for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) {
284 		free(gDeviceInfo[index]);
285 		free(name);
286 	}
287 
288 	put_module(B_AGP_GART_MODULE_NAME);
289 	put_module(B_PCI_MODULE_NAME);
290 	if (gPCIx86Module != NULL) {
291 		gPCIx86Module = NULL;
292 		put_module(B_PCI_X86_MODULE_NAME);
293 	}
294 }
295 
296 
297 extern "C" device_hooks*
298 find_device(const char* name)
299 {
300 	CALLED();
301 
302 	int index;
303 	for (index = 0; gDeviceNames[index] != NULL; index++) {
304 		if (!strcmp(name, gDeviceNames[index]))
305 			return &gDeviceHooks;
306 	}
307 
308 	return NULL;
309 }
310 
311