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