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