xref: /haiku/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp (revision 001e157a7b43a4f40219ddbadc7870ed1b43d8da)
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_GROUP_83x, "i830GM"},
46 	{0x2562, INTEL_GROUP_83x, "i845G"},
47 
48 	{0x2572, INTEL_GROUP_85x, "i865G"},
49 	{0x3582, INTEL_GROUP_85x, "i855G"},
50 	{0x358e, INTEL_GROUP_85x, "i855G"},
51 
52 	{0x2582, INTEL_MODEL_915, "i915G"},
53 	{0x258a, INTEL_MODEL_915, "i915"},
54 	{0x2592, INTEL_MODEL_915M, "i915GM"},
55 	{0x2792, INTEL_MODEL_915, "i910"},
56 	{0x2772, INTEL_MODEL_945, "i945G"},
57 	{0x27a2, INTEL_MODEL_945M, "i945GM"},
58 	{0x27ae, INTEL_MODEL_945M, "i945GME"},
59 	{0x2972, INTEL_MODEL_965, "i946G"},
60 	{0x2982, INTEL_MODEL_965, "G35"},
61 	{0x2992, INTEL_MODEL_965, "i965Q"},
62 	{0x29a2, INTEL_MODEL_965, "i965G"},
63 	{0x2a02, INTEL_MODEL_965M, "i965GM"},
64 	{0x2a12, INTEL_MODEL_965M, "i965GME"},
65 	{0x29b2, INTEL_MODEL_G33, "G33G"},
66 	{0x29c2, INTEL_MODEL_G33, "Q35G"},
67 	{0x29d2, INTEL_MODEL_G33, "Q33G"},
68 
69 	{0x2a42, INTEL_MODEL_GM45, "GM45"},
70 	{0x2e02, INTEL_MODEL_G45, "IGD"},
71 	{0x2e12, INTEL_MODEL_G45, "Q45"},
72 	{0x2e22, INTEL_MODEL_G45, "G45"},
73 	{0x2e32, INTEL_MODEL_G45, "G41"},
74 	{0x2e42, INTEL_MODEL_G45, "B43"},
75 	{0x2e92, INTEL_MODEL_G45, "B43"},
76 
77 	{0xa001, INTEL_MODEL_PINE, "Atom D4xx"},
78 	{0xa002, INTEL_MODEL_PINE, "Atom D5xx"},
79 	{0xa011, INTEL_MODEL_PINEM, "Atom N4xx"},
80 	{0xa012, INTEL_MODEL_PINEM, "Atom N5xx"},
81 
82 	{0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"},
83 	{0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
84 	{0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
85 	{0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
86 
87 	{0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"},
88 	{0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"},
89 	{0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"},
90 	{0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"},
91 	{0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"},
92 	{0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"},
93 	{0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"},
94 
95 	{0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"},
96 	{0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"},
97 	{0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"},
98 	{0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"},
99 	{0x0152, INTEL_MODEL_IVBGS, "IvyBridge Server"},
100 	{0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"},
101 	{0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"},
102 
103 	{0x0412, INTEL_MODEL_HAS, "Haswell Desktop"},
104 	{0x0416, INTEL_MODEL_HASM, "Haswell Mobile"},
105 	{0x0d26, INTEL_MODEL_HASM, "Haswell Mobile"},
106 	{0x0a16, INTEL_MODEL_HASM, "Haswell Mobile"},
107 
108 	{0x1912, INTEL_MODEL_SKY,  "Skylake GT2"}, // testing..
109 	{0x1916, INTEL_MODEL_SKYM, "Skylake GT2"}, // testing..
110 
111 #if 0
112 	// The driver does not make any attempt to handle this modern hardware.
113 	// Better let VESA/UEFI do it.
114 	{0x0155, INTEL_MODEL_VLV, "ValleyView Desktop"},
115 	{0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"},
116 	{0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"},
117 	{0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"},
118 	{0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"},
119 	{0x0157, INTEL_MODEL_VLVM, "ValleyView Mobile"},
120 
121 //	{0x1616, INTEL_MODEL_BDWM, "HD Graphics 5500 (Broadwell GT2)"},
122 
123 	{0x1902, INTEL_MODEL_SKY,  "Skylake GT1"},
124 	{0x1906, INTEL_MODEL_SKYM, "Skylake GT1"},
125 	{0x190a, INTEL_MODEL_SKYS, "Skylake GT1"},
126 	{0x190b, INTEL_MODEL_SKY,  "Skylake GT1"},
127 	{0x190e, INTEL_MODEL_SKYM, "Skylake GT1"},
128 	{0x1912, INTEL_MODEL_SKY,  "Skylake GT2"},
129 	{0x1916, INTEL_MODEL_SKYM, "Skylake GT2"},
130 	{0x191a, INTEL_MODEL_SKYS, "Skylake GT2"},
131 	{0x191b, INTEL_MODEL_SKY,  "Skylake GT2"},
132 	{0x191d, INTEL_MODEL_SKY,  "Skylake GT2"},
133 	{0x191e, INTEL_MODEL_SKYM, "Skylake GT2"},
134 	{0x1921, INTEL_MODEL_SKYM, "Skylake GT2F"},
135 	{0x1926, INTEL_MODEL_SKYM, "Skylake GT3"},
136 	{0x192a, INTEL_MODEL_SKYS, "Skylake GT3"},
137 	{0x192b, INTEL_MODEL_SKY,  "Skylake GT3"},
138 #endif
139 };
140 
141 int32 api_version = B_CUR_DRIVER_API_VERSION;
142 
143 char* gDeviceNames[MAX_CARDS + 1];
144 intel_info* gDeviceInfo[MAX_CARDS];
145 pci_module_info* gPCI;
146 pci_x86_module_info* gPCIx86Module = NULL;
147 agp_gart_module_info* gGART;
148 mutex gLock;
149 
150 
151 static status_t
152 get_next_intel_extreme(int32* _cookie, pci_info &info, uint32 &type)
153 {
154 	int32 index = *_cookie;
155 
156 	// find devices
157 
158 	for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) {
159 		// check vendor
160 		if (info.vendor_id != VENDOR_ID_INTEL
161 			|| info.class_base != PCI_display
162 			|| info.class_sub != PCI_vga)
163 			continue;
164 
165 		// check device
166 		for (uint32 i = 0; i < sizeof(kSupportedDevices)
167 				/ sizeof(kSupportedDevices[0]); i++) {
168 			if (info.device_id == kSupportedDevices[i].device_id) {
169 				type = i;
170 				*_cookie = index + 1;
171 				return B_OK;
172 			}
173 		}
174 	}
175 
176 	return B_ENTRY_NOT_FOUND;
177 }
178 
179 
180 static enum pch_info
181 detect_intel_pch()
182 {
183 	pci_info info;
184 
185 	// find devices
186 	for (int32 i = 0; gPCI->get_nth_pci_info(i, &info) == B_OK; i++) {
187 		// check vendor
188 		if (info.vendor_id != VENDOR_ID_INTEL
189 			|| info.class_base != PCI_bridge
190 			|| info.class_sub != PCI_isa) {
191 			continue;
192 		}
193 
194 		// check device
195 		unsigned short id = info.device_id & INTEL_PCH_DEVICE_ID_MASK;
196 		switch(id) {
197 			case INTEL_PCH_IBX_DEVICE_ID:
198 				ERROR("%s: Found Ibex Peak PCH\n", __func__);
199 				return INTEL_PCH_IBX;
200 			case INTEL_PCH_CPT_DEVICE_ID:
201 				ERROR("%s: Found CougarPoint PCH\n", __func__);
202 				return INTEL_PCH_CPT;
203 			case INTEL_PCH_PPT_DEVICE_ID:
204 				ERROR("%s: Found PantherPoint PCH\n", __func__);
205 				return INTEL_PCH_CPT;
206 			case INTEL_PCH_LPT_DEVICE_ID:
207 			case INTEL_PCH_LPT_LP_DEVICE_ID:
208 			case INTEL_PCH_WPT_DEVICE_ID:
209 			case INTEL_PCH_WPT_LP_DEVICE_ID:
210 				// WildcatPoint is LPT compatible
211 				ERROR("%s: Found LynxPoint PCH\n", __func__);
212 				return INTEL_PCH_LPT;
213 			case INTEL_PCH_SPT_DEVICE_ID:
214 			case INTEL_PCH_SPT_LP_DEVICE_ID:
215 				ERROR("%s: Found SunrisePoint PCH\n", __func__);
216 				return INTEL_PCH_SPT;
217 			case INTEL_PCH_KBP_DEVICE_ID:
218 				ERROR("%s: Found Kaby Lake PCH\n", __func__);
219 				return INTEL_PCH_KBP;
220 			case INTEL_PCH_CNP_DEVICE_ID:
221 			case INTEL_PCH_CNP_LP_DEVICE_ID:
222 				ERROR("%s: Found Cannon Lake PCH\n", __func__);
223 				return INTEL_PCH_CNP;
224 			case INTEL_PCH_ICP_DEVICE_ID:
225 				ERROR("%s: Found Ice Lake PCH\n", __func__);
226 				return INTEL_PCH_ICP;
227 		}
228 	}
229 
230 	ERROR("%s: No PCH detected.\n", __func__);
231 	return INTEL_PCH_NONE;
232 }
233 
234 
235 extern "C" const char**
236 publish_devices(void)
237 {
238 	CALLED();
239 	return (const char**)gDeviceNames;
240 }
241 
242 
243 extern "C" status_t
244 init_hardware(void)
245 {
246 	CALLED();
247 
248 	status_t status = get_module(B_PCI_MODULE_NAME,(module_info**)&gPCI);
249 	if (status != B_OK) {
250 		ERROR("pci module unavailable\n");
251 		return status;
252 	}
253 
254 	int32 cookie = 0;
255 	uint32 type;
256 	pci_info info;
257 	status = get_next_intel_extreme(&cookie, info, type);
258 
259 	put_module(B_PCI_MODULE_NAME);
260 	return status;
261 }
262 
263 
264 extern "C" status_t
265 init_driver(void)
266 {
267 	CALLED();
268 
269 	status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI);
270 	if (status != B_OK) {
271 		ERROR("pci module unavailable\n");
272 		return status;
273 	}
274 
275 	status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART);
276 	if (status != B_OK) {
277 		ERROR("AGP GART module unavailable\n");
278 		put_module(B_PCI_MODULE_NAME);
279 		return status;
280 	}
281 
282 	mutex_init(&gLock, "intel extreme ksync");
283 
284 	// Try to get the PCI x86 module as well so we can enable possible MSIs.
285 	if (get_module(B_PCI_X86_MODULE_NAME,
286 			(module_info **)&gPCIx86Module) != B_OK) {
287 		ERROR("failed to get pci x86 module\n");
288 		gPCIx86Module = NULL;
289 	}
290 
291 	// find the PCH device (if any)
292 	enum pch_info pchInfo = detect_intel_pch();
293 
294 	// find devices
295 
296 	int32 found = 0;
297 
298 	for (int32 cookie = 0; found < MAX_CARDS;) {
299 		pci_info* info = (pci_info*)malloc(sizeof(pci_info));
300 		if (info == NULL)
301 			break;
302 
303 		uint32 type;
304 		status = get_next_intel_extreme(&cookie, *info, type);
305 		if (status < B_OK) {
306 			free(info);
307 			break;
308 		}
309 
310 		// create device names & allocate device info structure
311 
312 		char name[64];
313 		sprintf(name, "graphics/intel_extreme_%02x%02x%02x",
314 			 info->bus, info->device,
315 			 info->function);
316 
317 		gDeviceNames[found] = strdup(name);
318 		if (gDeviceNames[found] == NULL)
319 			break;
320 
321 		gDeviceInfo[found] = (intel_info*)malloc(sizeof(intel_info));
322 		if (gDeviceInfo[found] == NULL) {
323 			free(gDeviceNames[found]);
324 			break;
325 		}
326 
327 		// initialize the structure for later use
328 
329 		memset(gDeviceInfo[found], 0, sizeof(intel_info));
330 		gDeviceInfo[found]->init_status = B_NO_INIT;
331 		gDeviceInfo[found]->id = found;
332 		gDeviceInfo[found]->pci = info;
333 		gDeviceInfo[found]->registers = info->u.h0.base_registers[0];
334 		gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name;
335 		gDeviceInfo[found]->device_type = kSupportedDevices[type].type;
336 		gDeviceInfo[found]->pch_info = pchInfo;
337 
338 		dprintf(DEVICE_NAME ": (%" B_PRId32 ") %s, revision = 0x%x\n", found,
339 			kSupportedDevices[type].name, info->revision);
340 
341 		found++;
342 	}
343 
344 	gDeviceNames[found] = NULL;
345 
346 	if (found == 0) {
347 		mutex_destroy(&gLock);
348 		put_module(B_AGP_GART_MODULE_NAME);
349 		put_module(B_PCI_MODULE_NAME);
350 		if (gPCIx86Module != NULL) {
351 			gPCIx86Module = NULL;
352 			put_module(B_PCI_X86_MODULE_NAME);
353 		}
354 		return ENODEV;
355 	}
356 
357 	return B_OK;
358 }
359 
360 
361 extern "C" void
362 uninit_driver(void)
363 {
364 	CALLED();
365 
366 	mutex_destroy(&gLock);
367 
368 	// free device related structures
369 	char* name;
370 	for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) {
371 		free(gDeviceInfo[index]);
372 		free(name);
373 	}
374 
375 	put_module(B_AGP_GART_MODULE_NAME);
376 	put_module(B_PCI_MODULE_NAME);
377 	if (gPCIx86Module != NULL) {
378 		gPCIx86Module = NULL;
379 		put_module(B_PCI_X86_MODULE_NAME);
380 	}
381 }
382 
383 
384 extern "C" device_hooks*
385 find_device(const char* name)
386 {
387 	CALLED();
388 
389 	int index;
390 	for (index = 0; gDeviceNames[index] != NULL; index++) {
391 		if (!strcmp(name, gDeviceNames[index]))
392 			return &gDeviceHooks;
393 	}
394 
395 	return NULL;
396 }
397