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