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_GROUP_83x, "i830GM"}, 46 {0x2562, INTEL_GROUP_83x, "i845G"}, 47 48 {0x2572, INTEL_GROUP_85x, "i865G"}, 49 {0x3582, INTEL_GROUP_85x, "i855G"}, 50 {0x358e, INTEL_GROUP_85x, "i855G"}, 51 52 {0x2582, INTEL_MODEL_915, "i915G"}, 53 {0x258a, INTEL_MODEL_915, "i915"}, 54 {0x2592, INTEL_MODEL_915M, "i915GM"}, 55 {0x2792, INTEL_MODEL_915, "i910"}, 56 {0x2772, INTEL_MODEL_945, "i945G"}, 57 {0x27a2, INTEL_MODEL_945M, "i945GM"}, 58 {0x27ae, INTEL_MODEL_945M, "i945GME"}, 59 {0x2972, INTEL_MODEL_965, "i946G"}, 60 {0x2982, INTEL_MODEL_965, "G35"}, 61 {0x2992, INTEL_MODEL_965, "i965Q"}, 62 {0x29a2, INTEL_MODEL_965, "i965G"}, 63 {0x2a02, INTEL_MODEL_965M, "i965GM"}, 64 {0x2a12, INTEL_MODEL_965M, "i965GME"}, 65 {0x29b2, INTEL_MODEL_G33, "G33G"}, 66 {0x29c2, INTEL_MODEL_G33, "Q35G"}, 67 {0x29d2, INTEL_MODEL_G33, "Q33G"}, 68 69 {0x2a42, INTEL_MODEL_GM45, "GM45"}, 70 {0x2e02, INTEL_MODEL_G45, "IGD"}, 71 {0x2e12, INTEL_MODEL_G45, "Q45"}, 72 {0x2e22, INTEL_MODEL_G45, "G45"}, 73 {0x2e32, INTEL_MODEL_G45, "G41"}, 74 {0x2e42, INTEL_MODEL_G45, "B43"}, 75 {0x2e92, INTEL_MODEL_G45, "B43"}, 76 77 {0xa001, INTEL_MODEL_PINE, "Atom D4xx"}, 78 {0xa002, INTEL_MODEL_PINE, "Atom D5xx"}, 79 {0xa011, INTEL_MODEL_PINEM, "Atom N4xx"}, 80 {0xa012, INTEL_MODEL_PINEM, "Atom N5xx"}, 81 82 {0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"}, 83 {0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 84 {0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 85 {0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 86 87 {0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"}, 88 {0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"}, 89 {0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"}, 90 {0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"}, 91 {0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"}, 92 {0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"}, 93 {0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"}, 94 95 {0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"}, 96 {0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"}, 97 {0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"}, 98 {0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"}, 99 {0x0152, INTEL_MODEL_IVBGS, "IvyBridge Server"}, 100 {0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"}, 101 {0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"}, 102 103 {0x0412, INTEL_MODEL_HAS, "Haswell Desktop"}, 104 {0x0416, INTEL_MODEL_HASM, "Haswell Mobile"}, 105 {0x0d26, INTEL_MODEL_HASM, "Haswell Mobile"}, 106 {0x0a16, INTEL_MODEL_HASM, "Haswell Mobile"}, 107 108 {0x1912, INTEL_MODEL_SKY, "Skylake GT2"}, // testing.. 109 {0x1916, INTEL_MODEL_SKYM, "Skylake GT2"}, // testing.. 110 111 #if 0 112 // The driver does not make any attempt to handle this modern hardware. 113 // Better let VESA/UEFI do it. 114 {0x0155, INTEL_MODEL_VLV, "ValleyView Desktop"}, 115 {0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 116 {0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 117 {0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 118 {0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 119 {0x0157, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 120 121 // {0x1616, INTEL_MODEL_BDWM, "HD Graphics 5500 (Broadwell GT2)"}, 122 123 {0x1902, INTEL_MODEL_SKY, "Skylake GT1"}, 124 {0x1906, INTEL_MODEL_SKYM, "Skylake GT1"}, 125 {0x190a, INTEL_MODEL_SKYS, "Skylake GT1"}, 126 {0x190b, INTEL_MODEL_SKY, "Skylake GT1"}, 127 {0x190e, INTEL_MODEL_SKYM, "Skylake GT1"}, 128 {0x1912, INTEL_MODEL_SKY, "Skylake GT2"}, 129 {0x1916, INTEL_MODEL_SKYM, "Skylake GT2"}, 130 {0x191a, INTEL_MODEL_SKYS, "Skylake GT2"}, 131 {0x191b, INTEL_MODEL_SKY, "Skylake GT2"}, 132 {0x191d, INTEL_MODEL_SKY, "Skylake GT2"}, 133 {0x191e, INTEL_MODEL_SKYM, "Skylake GT2"}, 134 {0x1921, INTEL_MODEL_SKYM, "Skylake GT2F"}, 135 {0x1926, INTEL_MODEL_SKYM, "Skylake GT3"}, 136 {0x192a, INTEL_MODEL_SKYS, "Skylake GT3"}, 137 {0x192b, INTEL_MODEL_SKY, "Skylake GT3"}, 138 #endif 139 }; 140 141 int32 api_version = B_CUR_DRIVER_API_VERSION; 142 143 char* gDeviceNames[MAX_CARDS + 1]; 144 intel_info* gDeviceInfo[MAX_CARDS]; 145 pci_module_info* gPCI; 146 pci_x86_module_info* gPCIx86Module = NULL; 147 agp_gart_module_info* gGART; 148 mutex gLock; 149 150 151 static status_t 152 get_next_intel_extreme(int32* _cookie, pci_info &info, uint32 &type) 153 { 154 int32 index = *_cookie; 155 156 // find devices 157 158 for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) { 159 // check vendor 160 if (info.vendor_id != VENDOR_ID_INTEL 161 || info.class_base != PCI_display 162 || info.class_sub != PCI_vga) 163 continue; 164 165 // check device 166 for (uint32 i = 0; i < sizeof(kSupportedDevices) 167 / sizeof(kSupportedDevices[0]); i++) { 168 if (info.device_id == kSupportedDevices[i].device_id) { 169 type = i; 170 *_cookie = index + 1; 171 return B_OK; 172 } 173 } 174 } 175 176 return B_ENTRY_NOT_FOUND; 177 } 178 179 180 static enum pch_info 181 detect_intel_pch() 182 { 183 pci_info info; 184 185 // find devices 186 for (int32 i = 0; gPCI->get_nth_pci_info(i, &info) == B_OK; i++) { 187 // check vendor 188 if (info.vendor_id != VENDOR_ID_INTEL 189 || info.class_base != PCI_bridge 190 || info.class_sub != PCI_isa) { 191 continue; 192 } 193 194 // check device 195 unsigned short id = info.device_id & INTEL_PCH_DEVICE_ID_MASK; 196 switch(id) { 197 case INTEL_PCH_IBX_DEVICE_ID: 198 ERROR("%s: Found Ibex Peak PCH\n", __func__); 199 return INTEL_PCH_IBX; 200 case INTEL_PCH_CPT_DEVICE_ID: 201 ERROR("%s: Found CougarPoint PCH\n", __func__); 202 return INTEL_PCH_CPT; 203 case INTEL_PCH_PPT_DEVICE_ID: 204 ERROR("%s: Found PantherPoint PCH\n", __func__); 205 return INTEL_PCH_CPT; 206 case INTEL_PCH_LPT_DEVICE_ID: 207 case INTEL_PCH_LPT_LP_DEVICE_ID: 208 case INTEL_PCH_WPT_DEVICE_ID: 209 case INTEL_PCH_WPT_LP_DEVICE_ID: 210 // WildcatPoint is LPT compatible 211 ERROR("%s: Found LynxPoint PCH\n", __func__); 212 return INTEL_PCH_LPT; 213 case INTEL_PCH_SPT_DEVICE_ID: 214 case INTEL_PCH_SPT_LP_DEVICE_ID: 215 ERROR("%s: Found SunrisePoint PCH\n", __func__); 216 return INTEL_PCH_SPT; 217 case INTEL_PCH_KBP_DEVICE_ID: 218 ERROR("%s: Found Kaby Lake PCH\n", __func__); 219 return INTEL_PCH_KBP; 220 case INTEL_PCH_CNP_DEVICE_ID: 221 case INTEL_PCH_CNP_LP_DEVICE_ID: 222 ERROR("%s: Found Cannon Lake PCH\n", __func__); 223 return INTEL_PCH_CNP; 224 case INTEL_PCH_ICP_DEVICE_ID: 225 ERROR("%s: Found Ice Lake PCH\n", __func__); 226 return INTEL_PCH_ICP; 227 } 228 } 229 230 ERROR("%s: No PCH detected.\n", __func__); 231 return INTEL_PCH_NONE; 232 } 233 234 235 extern "C" const char** 236 publish_devices(void) 237 { 238 CALLED(); 239 return (const char**)gDeviceNames; 240 } 241 242 243 extern "C" status_t 244 init_hardware(void) 245 { 246 CALLED(); 247 248 status_t status = get_module(B_PCI_MODULE_NAME,(module_info**)&gPCI); 249 if (status != B_OK) { 250 ERROR("pci module unavailable\n"); 251 return status; 252 } 253 254 int32 cookie = 0; 255 uint32 type; 256 pci_info info; 257 status = get_next_intel_extreme(&cookie, info, type); 258 259 put_module(B_PCI_MODULE_NAME); 260 return status; 261 } 262 263 264 extern "C" status_t 265 init_driver(void) 266 { 267 CALLED(); 268 269 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 270 if (status != B_OK) { 271 ERROR("pci module unavailable\n"); 272 return status; 273 } 274 275 status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART); 276 if (status != B_OK) { 277 ERROR("AGP GART module unavailable\n"); 278 put_module(B_PCI_MODULE_NAME); 279 return status; 280 } 281 282 mutex_init(&gLock, "intel extreme ksync"); 283 284 // Try to get the PCI x86 module as well so we can enable possible MSIs. 285 if (get_module(B_PCI_X86_MODULE_NAME, 286 (module_info **)&gPCIx86Module) != B_OK) { 287 ERROR("failed to get pci x86 module\n"); 288 gPCIx86Module = NULL; 289 } 290 291 // find the PCH device (if any) 292 enum pch_info pchInfo = detect_intel_pch(); 293 294 // find devices 295 296 int32 found = 0; 297 298 for (int32 cookie = 0; found < MAX_CARDS;) { 299 pci_info* info = (pci_info*)malloc(sizeof(pci_info)); 300 if (info == NULL) 301 break; 302 303 uint32 type; 304 status = get_next_intel_extreme(&cookie, *info, type); 305 if (status < B_OK) { 306 free(info); 307 break; 308 } 309 310 // create device names & allocate device info structure 311 312 char name[64]; 313 sprintf(name, "graphics/intel_extreme_%02x%02x%02x", 314 info->bus, info->device, 315 info->function); 316 317 gDeviceNames[found] = strdup(name); 318 if (gDeviceNames[found] == NULL) 319 break; 320 321 gDeviceInfo[found] = (intel_info*)malloc(sizeof(intel_info)); 322 if (gDeviceInfo[found] == NULL) { 323 free(gDeviceNames[found]); 324 break; 325 } 326 327 // initialize the structure for later use 328 329 memset(gDeviceInfo[found], 0, sizeof(intel_info)); 330 gDeviceInfo[found]->init_status = B_NO_INIT; 331 gDeviceInfo[found]->id = found; 332 gDeviceInfo[found]->pci = info; 333 gDeviceInfo[found]->registers = info->u.h0.base_registers[0]; 334 gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name; 335 gDeviceInfo[found]->device_type = kSupportedDevices[type].type; 336 gDeviceInfo[found]->pch_info = pchInfo; 337 338 dprintf(DEVICE_NAME ": (%" B_PRId32 ") %s, revision = 0x%x\n", found, 339 kSupportedDevices[type].name, info->revision); 340 341 found++; 342 } 343 344 gDeviceNames[found] = NULL; 345 346 if (found == 0) { 347 mutex_destroy(&gLock); 348 put_module(B_AGP_GART_MODULE_NAME); 349 put_module(B_PCI_MODULE_NAME); 350 if (gPCIx86Module != NULL) { 351 gPCIx86Module = NULL; 352 put_module(B_PCI_X86_MODULE_NAME); 353 } 354 return ENODEV; 355 } 356 357 return B_OK; 358 } 359 360 361 extern "C" void 362 uninit_driver(void) 363 { 364 CALLED(); 365 366 mutex_destroy(&gLock); 367 368 // free device related structures 369 char* name; 370 for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) { 371 free(gDeviceInfo[index]); 372 free(name); 373 } 374 375 put_module(B_AGP_GART_MODULE_NAME); 376 put_module(B_PCI_MODULE_NAME); 377 if (gPCIx86Module != NULL) { 378 gPCIx86Module = NULL; 379 put_module(B_PCI_X86_MODULE_NAME); 380 } 381 } 382 383 384 extern "C" device_hooks* 385 find_device(const char* name) 386 { 387 CALLED(); 388 389 int index; 390 for (index = 0; gDeviceNames[index] != NULL; index++) { 391 if (!strcmp(name, gDeviceNames[index])) 392 return &gDeviceHooks; 393 } 394 395 return NULL; 396 } 397