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("intel_extreme: " x) 28 #else 29 # define TRACE(x) ; 30 #endif 31 32 #define ERROR(x...) dprintf("intel_extreme: " x) 33 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 34 35 36 #define MAX_CARDS 4 37 38 39 // list of supported devices 40 const struct supported_device { 41 uint32 device_id; 42 int32 type; 43 const char* name; 44 } kSupportedDevices[] = { 45 {0x3577, INTEL_TYPE_83x, "i830GM"}, 46 {0x2562, INTEL_TYPE_83x, "i845G"}, 47 48 {0x2572, INTEL_TYPE_85x, "i865G"}, 49 {0x3582, INTEL_TYPE_85x, "i855G"}, 50 {0x358e, INTEL_TYPE_85x, "i855G"}, 51 52 {0x2582, INTEL_TYPE_915, "i915G"}, 53 {0x258a, INTEL_TYPE_915, "i915"}, 54 {0x2592, INTEL_TYPE_915M, "i915GM"}, 55 {0x2792, INTEL_TYPE_915, "i910"}, 56 {0x2772, INTEL_TYPE_945, "i945G"}, 57 {0x27a2, INTEL_TYPE_945M, "i945GM"}, 58 {0x27ae, INTEL_TYPE_945M, "i945GME"}, 59 {0x2972, INTEL_TYPE_965, "i946G"}, 60 {0x2982, INTEL_TYPE_965, "G35"}, 61 {0x2992, INTEL_TYPE_965, "i965Q"}, 62 {0x29a2, INTEL_TYPE_965, "i965G"}, 63 {0x2a02, INTEL_TYPE_965M, "i965GM"}, 64 {0x2a12, INTEL_TYPE_965M, "i965GME"}, 65 {0x29b2, INTEL_TYPE_G33, "G33G"}, 66 {0x29c2, INTEL_TYPE_G33, "Q35G"}, 67 {0x29d2, INTEL_TYPE_G33, "Q33G"}, 68 69 {0x2a42, INTEL_TYPE_GM45, "GM45"}, 70 {0x2e02, INTEL_TYPE_G45, "IGD"}, 71 {0x2e12, INTEL_TYPE_G45, "Q45"}, 72 {0x2e22, INTEL_TYPE_G45, "G45"}, 73 {0x2e32, INTEL_TYPE_G45, "G41"}, 74 {0x2e42, INTEL_TYPE_G45, "B43"}, 75 {0x2e92, INTEL_TYPE_G45, "B43"}, 76 77 {0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"}, 78 {0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"}, 79 80 {0x0042, INTEL_TYPE_ILKG, "IronLake Desktop"}, 81 {0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, 82 {0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, 83 {0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, 84 85 {0x0102, INTEL_TYPE_SNBG, "SandyBridge Desktop GT1"}, 86 {0x0112, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2"}, 87 {0x0122, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2+"}, 88 {0x0106, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT1"}, 89 {0x0116, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2"}, 90 {0x0126, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2+"}, 91 {0x010a, INTEL_TYPE_SNBGS, "SandyBridge Server"}, 92 93 {0x0152, INTEL_TYPE_IVBG, "IvyBridge Desktop GT1"}, 94 {0x0162, INTEL_TYPE_IVBG, "IvyBridge Desktop GT2"}, 95 {0x0156, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT1"}, 96 {0x0166, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT2"}, 97 {0x015a, INTEL_TYPE_IVBGS, "IvyBridge Server GT1"}, 98 {0x016a, INTEL_TYPE_IVBGS, "IvyBridge Server GT2"}, 99 100 {0x0412, INTEL_TYPE_IVBG, "Haswell Desktop"}, 101 {0x0416, INTEL_TYPE_IVBGM, "Haswell Mobile"}, 102 {0x0d26, INTEL_TYPE_IVBGM, "Haswell Mobile"}, 103 104 {0x0155, INTEL_TYPE_VLVG, "ValleyView Desktop"}, 105 {0x0f30, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, 106 {0x0f31, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, 107 {0x0f32, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, 108 {0x0f33, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, 109 {0x0157, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, 110 }; 111 112 int32 api_version = B_CUR_DRIVER_API_VERSION; 113 114 char* gDeviceNames[MAX_CARDS + 1]; 115 intel_info* gDeviceInfo[MAX_CARDS]; 116 pci_module_info* gPCI; 117 pci_x86_module_info* gPCIx86Module = NULL; 118 agp_gart_module_info* gGART; 119 mutex gLock; 120 121 122 static status_t 123 get_next_intel_extreme(int32* _cookie, pci_info &info, uint32 &type) 124 { 125 int32 index = *_cookie; 126 127 // find devices 128 129 for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) { 130 // check vendor 131 if (info.vendor_id != VENDOR_ID_INTEL 132 || info.class_base != PCI_display 133 || info.class_sub != PCI_vga) 134 continue; 135 136 // check device 137 for (uint32 i = 0; i < sizeof(kSupportedDevices) 138 / sizeof(kSupportedDevices[0]); i++) { 139 if (info.device_id == kSupportedDevices[i].device_id) { 140 type = i; 141 *_cookie = index + 1; 142 return B_OK; 143 } 144 } 145 } 146 147 return B_ENTRY_NOT_FOUND; 148 } 149 150 151 extern "C" const char** 152 publish_devices(void) 153 { 154 CALLED(); 155 return (const char**)gDeviceNames; 156 } 157 158 159 extern "C" status_t 160 init_hardware(void) 161 { 162 CALLED(); 163 164 status_t status = get_module(B_PCI_MODULE_NAME,(module_info**)&gPCI); 165 if (status != B_OK) { 166 ERROR("pci module unavailable\n"); 167 return status; 168 } 169 170 int32 cookie = 0; 171 uint32 type; 172 pci_info info; 173 status = get_next_intel_extreme(&cookie, info, type); 174 175 put_module(B_PCI_MODULE_NAME); 176 return status; 177 } 178 179 180 extern "C" status_t 181 init_driver(void) 182 { 183 CALLED(); 184 185 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 186 if (status != B_OK) { 187 ERROR("pci module unavailable\n"); 188 return status; 189 } 190 191 status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART); 192 if (status != B_OK) { 193 ERROR("AGP GART module unavailable\n"); 194 put_module(B_PCI_MODULE_NAME); 195 return status; 196 } 197 198 mutex_init(&gLock, "intel extreme ksync"); 199 200 // Try to get the PCI x86 module as well so we can enable possible MSIs. 201 if (get_module(B_PCI_X86_MODULE_NAME, 202 (module_info **)&gPCIx86Module) != B_OK) { 203 ERROR("failed to get pci x86 module\n"); 204 gPCIx86Module = NULL; 205 } 206 207 208 // find devices 209 210 int32 found = 0; 211 212 for (int32 cookie = 0; found < MAX_CARDS;) { 213 pci_info* info = (pci_info*)malloc(sizeof(pci_info)); 214 if (info == NULL) 215 break; 216 217 uint32 type; 218 status = get_next_intel_extreme(&cookie, *info, type); 219 if (status < B_OK) { 220 free(info); 221 break; 222 } 223 224 // create device names & allocate device info structure 225 226 char name[64]; 227 sprintf(name, "graphics/intel_extreme_%02x%02x%02x", 228 info->bus, info->device, 229 info->function); 230 231 gDeviceNames[found] = strdup(name); 232 if (gDeviceNames[found] == NULL) 233 break; 234 235 gDeviceInfo[found] = (intel_info*)malloc(sizeof(intel_info)); 236 if (gDeviceInfo[found] == NULL) { 237 free(gDeviceNames[found]); 238 break; 239 } 240 241 // initialize the structure for later use 242 243 memset(gDeviceInfo[found], 0, sizeof(intel_info)); 244 gDeviceInfo[found]->init_status = B_NO_INIT; 245 gDeviceInfo[found]->id = found; 246 gDeviceInfo[found]->pci = info; 247 gDeviceInfo[found]->registers = info->u.h0.base_registers[0]; 248 gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name; 249 gDeviceInfo[found]->device_type = kSupportedDevices[type].type; 250 251 dprintf(DEVICE_NAME ": (%ld) %s, revision = 0x%x\n", found, 252 kSupportedDevices[type].name, info->revision); 253 254 found++; 255 } 256 257 gDeviceNames[found] = NULL; 258 259 if (found == 0) { 260 mutex_destroy(&gLock); 261 put_module(B_AGP_GART_MODULE_NAME); 262 put_module(B_PCI_MODULE_NAME); 263 if (gPCIx86Module != NULL) { 264 gPCIx86Module = NULL; 265 put_module(B_PCI_X86_MODULE_NAME); 266 } 267 return ENODEV; 268 } 269 270 return B_OK; 271 } 272 273 274 extern "C" void 275 uninit_driver(void) 276 { 277 CALLED(); 278 279 mutex_destroy(&gLock); 280 281 // free device related structures 282 char* name; 283 for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) { 284 free(gDeviceInfo[index]); 285 free(name); 286 } 287 288 put_module(B_AGP_GART_MODULE_NAME); 289 put_module(B_PCI_MODULE_NAME); 290 if (gPCIx86Module != NULL) { 291 gPCIx86Module = NULL; 292 put_module(B_PCI_X86_MODULE_NAME); 293 } 294 } 295 296 297 extern "C" device_hooks* 298 find_device(const char* name) 299 { 300 CALLED(); 301 302 int index; 303 for (index = 0; gDeviceNames[index] != NULL; index++) { 304 if (!strcmp(name, gDeviceNames[index])) 305 return &gDeviceHooks; 306 } 307 308 return NULL; 309 } 310 311