xref: /haiku/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp (revision cbed190f71b8aff814bf95539c39a1bcfb953ed8)
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 x
28 #else
29 #	define TRACE(x) ;
30 #endif
31 
32 #define MAX_CARDS 4
33 
34 
35 // list of supported devices
36 const struct supported_device {
37 	uint32		device_id;
38 	int32		type;
39 	const char*	name;
40 } kSupportedDevices[] = {
41 	{0x3577, INTEL_TYPE_83x, "i830GM"},
42 	{0x2562, INTEL_TYPE_83x, "i845G"},
43 
44 	{0x2572, INTEL_TYPE_85x, "i865G"},
45 	{0x3582, INTEL_TYPE_85x, "i855G"},
46 
47 	{0x2792, INTEL_TYPE_91x, "i910"},
48 	{0x258a, INTEL_TYPE_91x, "i915"},
49 	{0x2582, INTEL_TYPE_91x, "i915G"},
50 	{0x2592, INTEL_TYPE_91x, "i915GM"},
51 	{0x2772, INTEL_TYPE_945, "i945G"},
52 	{0x27a2, INTEL_TYPE_945, "i945GM"},
53 	{0x27ae, INTEL_TYPE_945M, "i945GME"},
54 	{0x29a2, INTEL_TYPE_965, "i965G"},
55 	{0x2a02, INTEL_TYPE_965M, "i965GM"},
56 	{0x29b2, INTEL_TYPE_G33, "G33G"},
57 	{0x29c2, INTEL_TYPE_G33, "Q35G"},
58 	{0x29d2, INTEL_TYPE_G33, "Q33G"},
59 
60 	{0x2e32, INTEL_TYPE_GM45, "GMA_X4500_VGA"},
61 	{0x2a42, INTEL_TYPE_GM45, "GM45"},
62 
63 	{0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"},
64 	{0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"},
65 };
66 
67 int32 api_version = B_CUR_DRIVER_API_VERSION;
68 
69 char* gDeviceNames[MAX_CARDS + 1];
70 intel_info* gDeviceInfo[MAX_CARDS];
71 pci_module_info* gPCI;
72 agp_gart_module_info* gGART;
73 mutex gLock;
74 
75 
76 static status_t
77 get_next_intel_extreme(int32 *_cookie, pci_info &info, uint32 &type)
78 {
79 	int32 index = *_cookie;
80 
81 	// find devices
82 
83 	for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) {
84 		// check vendor
85 		if (info.vendor_id != VENDOR_ID_INTEL
86 			|| info.class_base != PCI_display
87 			|| info.class_sub != PCI_vga)
88 			continue;
89 
90 		// check device
91 		for (uint32 i = 0; i < sizeof(kSupportedDevices)
92 				/ sizeof(kSupportedDevices[0]); i++) {
93 			if (info.device_id == kSupportedDevices[i].device_id) {
94 				type = i;
95 				*_cookie = index + 1;
96 				return B_OK;
97 			}
98 		}
99 	}
100 
101 	return B_ENTRY_NOT_FOUND;
102 }
103 
104 
105 extern "C" const char **
106 publish_devices(void)
107 {
108 	TRACE((DEVICE_NAME ": publish_devices()\n"));
109 	return (const char **)gDeviceNames;
110 }
111 
112 
113 extern "C" status_t
114 init_hardware(void)
115 {
116 	TRACE((DEVICE_NAME ": init_hardware()\n"));
117 
118 	status_t status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPCI);
119 	if (status != B_OK) {
120 		TRACE((DEVICE_NAME ": pci module unavailable\n"));
121 		return status;
122 	}
123 
124 	int32 cookie = 0;
125 	uint32 type;
126 	pci_info info;
127 	status = get_next_intel_extreme(&cookie, info, type);
128 
129 	put_module(B_PCI_MODULE_NAME);
130 	return status;
131 }
132 
133 
134 extern "C" status_t
135 init_driver(void)
136 {
137 	TRACE((DEVICE_NAME ": init_driver()\n"));
138 
139 	status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI);
140 	if (status != B_OK) {
141 		TRACE((DEVICE_NAME ": pci module unavailable\n"));
142 		return status;
143 	}
144 
145 	status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART);
146 	if (status != B_OK) {
147 		TRACE((DEVICE_NAME ": AGP GART module unavailable\n"));
148 		put_module(B_PCI_MODULE_NAME);
149 		return status;
150 	}
151 
152 	mutex_init(&gLock, "intel extreme ksync");
153 
154 	// find devices
155 
156 	int32 found = 0;
157 
158 	for (int32 cookie = 0; found < MAX_CARDS;) {
159 		pci_info* info = (pci_info*)malloc(sizeof(pci_info));
160 		if (info == NULL)
161 			break;
162 
163 		uint32 type;
164 		status = get_next_intel_extreme(&cookie, *info, type);
165 		if (status < B_OK) {
166 			free(info);
167 			break;
168 		}
169 
170 		// create device names & allocate device info structure
171 
172 		char name[64];
173 		sprintf(name, "graphics/intel_extreme_%02x%02x%02x",
174 			 info->bus, info->device,
175 			 info->function);
176 
177 		gDeviceNames[found] = strdup(name);
178 		if (gDeviceNames[found] == NULL)
179 			break;
180 
181 		gDeviceInfo[found] = (intel_info*)malloc(sizeof(intel_info));
182 		if (gDeviceInfo[found] == NULL) {
183 			free(gDeviceNames[found]);
184 			break;
185 		}
186 
187 		// initialize the structure for later use
188 
189 		memset(gDeviceInfo[found], 0, sizeof(intel_info));
190 		gDeviceInfo[found]->init_status = B_NO_INIT;
191 		gDeviceInfo[found]->id = found;
192 		gDeviceInfo[found]->pci = info;
193 		gDeviceInfo[found]->registers = (uint8 *)info->u.h0.base_registers[0];
194 		gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name;
195 		gDeviceInfo[found]->device_type = kSupportedDevices[type].type;
196 
197 		dprintf(DEVICE_NAME ": (%ld) %s, revision = 0x%x\n", found,
198 			kSupportedDevices[type].name, info->revision);
199 
200 		found++;
201 	}
202 
203 	gDeviceNames[found] = NULL;
204 
205 	if (found == 0) {
206 		mutex_destroy(&gLock);
207 		put_module(B_AGP_GART_MODULE_NAME);
208 		put_module(B_PCI_MODULE_NAME);
209 		return ENODEV;
210 	}
211 
212 	return B_OK;
213 }
214 
215 
216 extern "C" void
217 uninit_driver(void)
218 {
219 	TRACE((DEVICE_NAME ": uninit_driver()\n"));
220 
221 	mutex_destroy(&gLock);
222 
223 	// free device related structures
224 	char* name;
225 	for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) {
226 		free(gDeviceInfo[index]);
227 		free(name);
228 	}
229 
230 	put_module(B_AGP_GART_MODULE_NAME);
231 	put_module(B_PCI_MODULE_NAME);
232 }
233 
234 
235 extern "C" device_hooks*
236 find_device(const char* name)
237 {
238 	int index;
239 
240 	TRACE((DEVICE_NAME ": find_device()\n"));
241 
242 	for (index = 0; gDeviceNames[index] != NULL; index++) {
243 		if (!strcmp(name, gDeviceNames[index]))
244 			return &gDeviceHooks;
245 	}
246 
247 	return NULL;
248 }
249 
250