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