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
40const 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	{0x0a06, INTEL_MODEL_HASM, "Haswell ULT GT1 Mobile"},
104	{0x0412, INTEL_MODEL_HAS, "Haswell GT2 Desktop"},
105	{0x0416, INTEL_MODEL_HASM, "Haswell GT2 Mobile"},
106	{0x0a16, INTEL_MODEL_HASM, "Haswell ULT GT2 Mobile"},
107	{0x0d26, INTEL_MODEL_HASM, "Haswell CRW GT3 Mobile"},
108
109#if 0
110	{0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"},
111	{0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"},
112	{0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"},
113	{0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"},
114#endif
115
116	{0x1606, INTEL_MODEL_BDWM, "Broadwell GT1 ULT"},
117	{0x160b, INTEL_MODEL_BDWM, "Broadwell GT1 Iris"},
118	{0x160e, INTEL_MODEL_BDWM, "Broadwell GT1 ULX"},
119	{0x1602, INTEL_MODEL_BDWM, "Broadwell GT1 ULT"},
120	{0x160a, INTEL_MODEL_BDWS, "Broadwell GT1 Server"},
121	{0x160d, INTEL_MODEL_BDW,  "Broadwell GT1 Workstation"},
122	{0x1616, INTEL_MODEL_BDWM, "Broadwell GT2 ULT"},
123	{0x161b, INTEL_MODEL_BDWM, "Broadwell GT2 ULT"},
124	{0x161e, INTEL_MODEL_BDWM, "Broadwell GT2 ULX"},
125	{0x1612, INTEL_MODEL_BDWM, "Broadwell GT2 Halo"},
126	{0x161a, INTEL_MODEL_BDWS, "Broadwell GT2 Server"},
127	{0x161d, INTEL_MODEL_BDW,  "Broadwell GT2 Workstation"},
128	{0x1626, INTEL_MODEL_BDWM, "Broadwell GT3 ULT"},
129	{0x162b, INTEL_MODEL_BDWM, "Broadwell GT3 Iris"},
130	{0x162e, INTEL_MODEL_BDWM, "Broadwell GT3 ULX"},
131	{0x1622, INTEL_MODEL_BDWM, "Broadwell GT3 ULT"},
132	{0x162a, INTEL_MODEL_BDWS, "Broadwell GT3 Server"},
133	{0x162d, INTEL_MODEL_BDW,  "Broadwell GT3 Workstation"},
134
135	{0x1902, INTEL_MODEL_SKY,  "Skylake GT1"},
136	{0x1906, INTEL_MODEL_SKYM, "Skylake GT1"},
137	{0x190a, INTEL_MODEL_SKYS, "Skylake GT1"},
138	{0x190b, INTEL_MODEL_SKY,  "Skylake GT1"},
139	{0x190e, INTEL_MODEL_SKYM, "Skylake GT1"},
140	{0x1912, INTEL_MODEL_SKY,  "Skylake GT2"}, //confirmed OK
141	{0x1916, INTEL_MODEL_SKYM, "Skylake GT2"}, //confirmed native mode panel OK
142	{0x191a, INTEL_MODEL_SKYS, "Skylake GT2"},
143	{0x191b, INTEL_MODEL_SKY,  "Skylake GT2"},
144	{0x191d, INTEL_MODEL_SKY,  "Skylake GT2"},
145	{0x191e, INTEL_MODEL_SKYM, "Skylake GT2"},
146	{0x1921, INTEL_MODEL_SKYM, "Skylake GT2F"},
147	{0x1926, INTEL_MODEL_SKYM, "Skylake GT3"},
148	{0x192a, INTEL_MODEL_SKYS, "Skylake GT3"},
149	{0x192b, INTEL_MODEL_SKY,  "Skylake GT3"},
150
151	{0x5906, INTEL_MODEL_KBY,  "Kabylake ULT GT1"},
152	{0x5902, INTEL_MODEL_KBY,  "Kabylake DT GT1"},
153	{0x5916, INTEL_MODEL_KBYM, "Kabylake ULT GT2"},
154	{0x5921, INTEL_MODEL_KBYM, "Kabylake ULT GT2F"},
155	{0x591c, INTEL_MODEL_KBY,  "Kabylake ULX GT2"},
156	{0x591e, INTEL_MODEL_KBY,  "Kabylake ULX GT2"},
157	{0x5912, INTEL_MODEL_KBY,  "Kabylake DT GT2"},
158	{0x5917, INTEL_MODEL_KBYM, "Kabylake Mobile GT2"},
159	{0x591b, INTEL_MODEL_KBYM, "Kabylake Halo GT2"},
160	{0x591d, INTEL_MODEL_KBY,  "Kabylake WKS GT2"},
161	{0x5926, INTEL_MODEL_KBY,  "Kabylake ULT GT3"},
162	{0x5927, INTEL_MODEL_KBY,  "Kabylake ULT GT3"},
163
164	{0x3e90, INTEL_MODEL_CFL,  "CoffeeLake GT1"},
165	{0x3e93, INTEL_MODEL_CFL,  "CoffeeLake GT1"},
166	{0x3e91, INTEL_MODEL_CFL,  "CoffeeLake GT2"},
167	{0x3e92, INTEL_MODEL_CFL,  "CoffeeLake GT2"},
168	{0x3e96, INTEL_MODEL_CFL,  "CoffeeLake GT2"},
169	{0x3e98, INTEL_MODEL_CFL,  "CoffeeLake GT2"},
170	{0x3e9a, INTEL_MODEL_CFL,  "CoffeeLake GT2"},
171	{0x3e9b, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"},
172	{0x3eab, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"},
173	{0x3ea5, INTEL_MODEL_CFL,  "CoffeeLake GT3"},
174	{0x3ea6, INTEL_MODEL_CFL,  "CoffeeLake GT3"},
175
176	{0x9ba4, INTEL_MODEL_CML,	"CometLake GT1"},
177	{0x9ba8, INTEL_MODEL_CML,	"CometLake GT1"},
178	{0x9b21, INTEL_MODEL_CMLM,	"CometLake U GT1"},
179	{0x9baa, INTEL_MODEL_CMLM,	"CometLake U GT1"},
180	{0x9bc4, INTEL_MODEL_CML,	"CometLake GT2"},
181	{0x9bc5, INTEL_MODEL_CML,	"CometLake GT2"},
182	{0x9bc6, INTEL_MODEL_CML,	"CometLake GT2"},
183	{0x9bc8, INTEL_MODEL_CML,	"CometLake GT2"},
184	{0x9be6, INTEL_MODEL_CML,	"CometLake GT2"},
185	{0x9bf6, INTEL_MODEL_CML,	"CometLake GT2"},
186	{0x9b41, INTEL_MODEL_CMLM,	"CometLake U GT2"},
187	{0x9bca, INTEL_MODEL_CMLM,	"CometLake U GT2"},
188	{0x9bcc, INTEL_MODEL_CMLM,	"CometLake U GT2"},
189
190	{0x4e55, INTEL_MODEL_JSL,	"JasperLake"},
191	{0x4e61, INTEL_MODEL_JSL,	"JasperLake"},
192	{0x4e71, INTEL_MODEL_JSLM,	"JasperLake"},
193
194	{0x9a49, INTEL_MODEL_TGLM,	"TigerLake"},
195};
196
197int32 api_version = B_CUR_DRIVER_API_VERSION;
198
199char* gDeviceNames[MAX_CARDS + 1];
200intel_info* gDeviceInfo[MAX_CARDS];
201pci_module_info* gPCI;
202agp_gart_module_info* gGART;
203mutex gLock;
204
205
206static status_t
207get_next_intel_extreme(int32* _cookie, pci_info &info, uint32 &type)
208{
209	int32 index = *_cookie;
210
211	// find devices
212
213	for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) {
214		// check vendor
215		if (info.vendor_id != VENDOR_ID_INTEL
216			|| info.class_base != PCI_display
217			|| (info.class_sub != PCI_vga && info.class_sub != PCI_display_other))
218			continue;
219
220		// check device
221		for (uint32 i = 0; i < sizeof(kSupportedDevices)
222				/ sizeof(kSupportedDevices[0]); i++) {
223			if (info.device_id == kSupportedDevices[i].device_id) {
224				type = i;
225				*_cookie = index + 1;
226				ERROR("%s: Intel gfx deviceID: 0x%04x\n", __func__, info.device_id);
227				return B_OK;
228			}
229		}
230	}
231
232	return B_ENTRY_NOT_FOUND;
233}
234
235
236static enum pch_info
237detect_intel_pch()
238{
239	pci_info info;
240
241	// find devices
242	for (int32 i = 0; gPCI->get_nth_pci_info(i, &info) == B_OK; i++) {
243		// check vendor
244		if (info.vendor_id != VENDOR_ID_INTEL
245			|| info.class_base != PCI_bridge
246			|| info.class_sub != PCI_isa) {
247			continue;
248		}
249
250		// check device
251		unsigned short id = info.device_id & INTEL_PCH_DEVICE_ID_MASK;
252		ERROR("%s: Intel PCH deviceID: 0x%04x\n", __func__, info.device_id);
253		switch(id) {
254			case INTEL_PCH_IBX_DEVICE_ID:
255				ERROR("%s: Found Ibex Peak PCH\n", __func__);
256				return INTEL_PCH_IBX;
257			case INTEL_PCH_CPT_DEVICE_ID:
258				ERROR("%s: Found CougarPoint PCH\n", __func__);
259				return INTEL_PCH_CPT;
260			case INTEL_PCH_PPT_DEVICE_ID:
261				ERROR("%s: Found PantherPoint PCH\n", __func__);
262				return INTEL_PCH_CPT;
263			case INTEL_PCH_LPT_DEVICE_ID:
264			case INTEL_PCH_LPT_LP_DEVICE_ID:
265				ERROR("%s: Found LynxPoint PCH\n", __func__);
266				return INTEL_PCH_LPT;
267			case INTEL_PCH_WPT_DEVICE_ID:
268			case INTEL_PCH_WPT_LP_DEVICE_ID:
269				ERROR("%s: Found WildcatPoint PCH\n", __func__);
270				return INTEL_PCH_LPT;
271			case INTEL_PCH_SPT_DEVICE_ID:
272			case INTEL_PCH_SPT_LP_DEVICE_ID:
273				ERROR("%s: Found SunrisePoint PCH\n", __func__);
274				return INTEL_PCH_SPT;
275			case INTEL_PCH_KBP_DEVICE_ID:
276				ERROR("%s: Found Kaby Lake PCH\n", __func__);
277				return INTEL_PCH_SPT;
278			case INTEL_PCH_CNP_DEVICE_ID:
279			case INTEL_PCH_CNP_LP_DEVICE_ID:
280				ERROR("%s: Found Cannon Lake PCH\n", __func__);
281				return INTEL_PCH_CNP;
282			case INTEL_PCH_CMP_DEVICE_ID:
283			case INTEL_PCH_CMP2_DEVICE_ID:
284				ERROR("%s: Found Comet Lake PCH\n", __func__);
285				return INTEL_PCH_CNP;
286			case INTEL_PCH_CMP_V_DEVICE_ID:
287				ERROR("%s: Found Comet Lake V PCH\n", __func__);
288				return INTEL_PCH_SPT;
289			case INTEL_PCH_ICP_DEVICE_ID:
290			case INTEL_PCH_ICP2_DEVICE_ID:
291				ERROR("%s: Found Ice Lake PCH\n", __func__);
292				return INTEL_PCH_ICP;
293			case INTEL_PCH_MCC_DEVICE_ID:
294				ERROR("%s: Found Mule Creek Canyon PCH\n", __func__);
295				return INTEL_PCH_MCC;
296			case INTEL_PCH_TGP_DEVICE_ID:
297			case INTEL_PCH_TGP2_DEVICE_ID:
298				ERROR("%s: Found Tiger Lake PCH\n", __func__);
299				return INTEL_PCH_TGP;
300			case INTEL_PCH_JSP_DEVICE_ID:
301				ERROR("%s: Found Jasper Lake PCH\n", __func__);
302				return INTEL_PCH_JSP;
303			case INTEL_PCH_ADP_DEVICE_ID:
304			case INTEL_PCH_ADP2_DEVICE_ID:
305			case INTEL_PCH_ADP3_DEVICE_ID:
306			case INTEL_PCH_ADP4_DEVICE_ID:
307				ERROR("%s: Found Alder Lake PCH\n", __func__);
308				return INTEL_PCH_ADP;
309		}
310	}
311
312	ERROR("%s: No PCH detected.\n", __func__);
313	return INTEL_PCH_NONE;
314}
315
316
317extern "C" const char**
318publish_devices(void)
319{
320	CALLED();
321	return (const char**)gDeviceNames;
322}
323
324
325extern "C" status_t
326init_hardware(void)
327{
328	CALLED();
329
330	status_t status = get_module(B_PCI_MODULE_NAME,(module_info**)&gPCI);
331	if (status != B_OK) {
332		ERROR("pci module unavailable\n");
333		return status;
334	}
335
336	int32 cookie = 0;
337	uint32 type;
338	pci_info info;
339	status = get_next_intel_extreme(&cookie, info, type);
340
341	put_module(B_PCI_MODULE_NAME);
342	return status;
343}
344
345
346extern "C" status_t
347init_driver(void)
348{
349	CALLED();
350
351	status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI);
352	if (status != B_OK) {
353		ERROR("pci module unavailable\n");
354		return status;
355	}
356
357	status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART);
358	if (status != B_OK) {
359		ERROR("AGP GART module unavailable\n");
360		put_module(B_PCI_MODULE_NAME);
361		return status;
362	}
363
364	mutex_init(&gLock, "intel extreme ksync");
365
366	// find the PCH device (if any)
367	enum pch_info pchInfo = detect_intel_pch();
368
369	// find devices
370
371	int32 found = 0;
372
373	for (int32 cookie = 0; found < MAX_CARDS;) {
374		pci_info* info = (pci_info*)malloc(sizeof(pci_info));
375		if (info == NULL)
376			break;
377
378		uint32 type;
379		status = get_next_intel_extreme(&cookie, *info, type);
380		if (status < B_OK) {
381			free(info);
382			break;
383		}
384
385		// create device names & allocate device info structure
386
387		char name[64];
388		sprintf(name, "graphics/intel_extreme_%02x%02x%02x",
389			 info->bus, info->device,
390			 info->function);
391
392		gDeviceNames[found] = strdup(name);
393		if (gDeviceNames[found] == NULL)
394			break;
395
396		gDeviceInfo[found] = (intel_info*)malloc(sizeof(intel_info));
397		if (gDeviceInfo[found] == NULL) {
398			free(gDeviceNames[found]);
399			break;
400		}
401
402		// initialize the structure for later use
403
404		memset(gDeviceInfo[found], 0, sizeof(intel_info));
405		gDeviceInfo[found]->init_status = B_NO_INIT;
406		gDeviceInfo[found]->id = found;
407		gDeviceInfo[found]->pci = info;
408		gDeviceInfo[found]->registers = info->u.h0.base_registers[0];
409		gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name;
410		gDeviceInfo[found]->device_type = kSupportedDevices[type].type;
411		gDeviceInfo[found]->pch_info = pchInfo;
412
413		dprintf(DEVICE_NAME ": (%" B_PRId32 ") %s, revision = 0x%x\n", found,
414			kSupportedDevices[type].name, info->revision);
415
416		found++;
417	}
418
419	gDeviceNames[found] = NULL;
420
421	if (found == 0) {
422		mutex_destroy(&gLock);
423		put_module(B_AGP_GART_MODULE_NAME);
424		put_module(B_PCI_MODULE_NAME);
425		return ENODEV;
426	}
427
428	return B_OK;
429}
430
431
432extern "C" void
433uninit_driver(void)
434{
435	CALLED();
436
437	mutex_destroy(&gLock);
438
439	// free device related structures
440	char* name;
441	for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) {
442		free(gDeviceInfo[index]);
443		free(name);
444	}
445
446	put_module(B_AGP_GART_MODULE_NAME);
447	put_module(B_PCI_MODULE_NAME);
448}
449
450
451extern "C" device_hooks*
452find_device(const char* name)
453{
454	CALLED();
455
456	int index;
457	for (index = 0; gDeviceNames[index] != NULL; index++) {
458		if (!strcmp(name, gDeviceNames[index]))
459			return &gDeviceHooks;
460	}
461
462	return NULL;
463}
464