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