Ticket #6641: driver.cpp

File driver.cpp, 5.1 KB (added by lukove, 14 years ago)
Line 
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
36const 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"}, // Intel Mystic Lake (dg41mj)
61 {0x2a42, INTEL_TYPE_GM45, "GM45"},
62};
63
64int32 api_version = B_CUR_DRIVER_API_VERSION;
65
66char* gDeviceNames[MAX_CARDS + 1];
67intel_info* gDeviceInfo[MAX_CARDS];
68pci_module_info* gPCI;
69agp_gart_module_info* gGART;
70mutex gLock;
71
72
73static status_t
74get_next_intel_extreme(int32 *_cookie, pci_info &info, uint32 &type)
75{
76 int32 index = *_cookie;
77
78 // find devices
79
80 for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) {
81 // check vendor
82 if (info.vendor_id != VENDOR_ID_INTEL
83 || info.class_base != PCI_display
84 || info.class_sub != PCI_vga)
85 continue;
86
87 // check device
88 for (uint32 i = 0; i < sizeof(kSupportedDevices)
89 / sizeof(kSupportedDevices[0]); i++) {
90 if (info.device_id == kSupportedDevices[i].device_id) {
91 type = i;
92 *_cookie = index + 1;
93 return B_OK;
94 }
95 }
96 }
97
98 return B_ENTRY_NOT_FOUND;
99}
100
101
102extern "C" const char **
103publish_devices(void)
104{
105 TRACE((DEVICE_NAME ": publish_devices()\n"));
106 return (const char **)gDeviceNames;
107}
108
109
110extern "C" status_t
111init_hardware(void)
112{
113 TRACE((DEVICE_NAME ": init_hardware()\n"));
114
115 status_t status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPCI);
116 if (status != B_OK) {
117 TRACE((DEVICE_NAME ": pci module unavailable\n"));
118 return status;
119 }
120
121 int32 cookie = 0;
122 uint32 type;
123 pci_info info;
124 status = get_next_intel_extreme(&cookie, info, type);
125
126 put_module(B_PCI_MODULE_NAME);
127 return status;
128}
129
130
131extern "C" status_t
132init_driver(void)
133{
134 TRACE((DEVICE_NAME ": init_driver()\n"));
135
136 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI);
137 if (status != B_OK) {
138 TRACE((DEVICE_NAME ": pci module unavailable\n"));
139 return status;
140 }
141
142 status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART);
143 if (status != B_OK) {
144 TRACE((DEVICE_NAME ": AGP GART module unavailable\n"));
145 put_module(B_PCI_MODULE_NAME);
146 return status;
147 }
148
149 mutex_init(&gLock, "intel extreme ksync");
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 mutex_destroy(&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
213extern "C" void
214uninit_driver(void)
215{
216 TRACE((DEVICE_NAME ": uninit_driver()\n"));
217
218 mutex_destroy(&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
232extern "C" device_hooks*
233find_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