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 {0x0a06, INTEL_MODEL_HASM, "Haswell ULT GT1 Mobile"}, 104 {0x0412, INTEL_MODEL_HAS, "Haswell GT2 Desktop"}, 105 {0x0416, INTEL_MODEL_HASM, "Haswell GT2 Mobile"}, 106 {0x0a16, INTEL_MODEL_HASM, "Haswell ULT GT2 Mobile"}, 107 {0x0d26, INTEL_MODEL_HASM, "Haswell CRW GT3 Mobile"}, 108 109 #if 0 110 {0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 111 {0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 112 {0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 113 {0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 114 #endif 115 116 {0x1606, INTEL_MODEL_BDWM, "Broadwell GT1 ULT"}, 117 {0x160b, INTEL_MODEL_BDWM, "Broadwell GT1 Iris"}, 118 {0x160e, INTEL_MODEL_BDWM, "Broadwell GT1 ULX"}, 119 {0x1602, INTEL_MODEL_BDWM, "Broadwell GT1 ULT"}, 120 {0x160a, INTEL_MODEL_BDWS, "Broadwell GT1 Server"}, 121 {0x160d, INTEL_MODEL_BDW, "Broadwell GT1 Workstation"}, 122 {0x1616, INTEL_MODEL_BDWM, "Broadwell GT2 ULT"}, 123 {0x161b, INTEL_MODEL_BDWM, "Broadwell GT2 ULT"}, 124 {0x161e, INTEL_MODEL_BDWM, "Broadwell GT2 ULX"}, 125 {0x1612, INTEL_MODEL_BDWM, "Broadwell GT2 Halo"}, 126 {0x161a, INTEL_MODEL_BDWS, "Broadwell GT2 Server"}, 127 {0x161d, INTEL_MODEL_BDW, "Broadwell GT2 Workstation"}, 128 {0x1626, INTEL_MODEL_BDWM, "Broadwell GT3 ULT"}, 129 {0x162b, INTEL_MODEL_BDWM, "Broadwell GT3 Iris"}, 130 {0x162e, INTEL_MODEL_BDWM, "Broadwell GT3 ULX"}, 131 {0x1622, INTEL_MODEL_BDWM, "Broadwell GT3 ULT"}, 132 {0x162a, INTEL_MODEL_BDWS, "Broadwell GT3 Server"}, 133 {0x162d, INTEL_MODEL_BDW, "Broadwell GT3 Workstation"}, 134 135 {0x1902, INTEL_MODEL_SKY, "Skylake GT1"}, 136 {0x1906, INTEL_MODEL_SKYM, "Skylake GT1"}, 137 {0x190a, INTEL_MODEL_SKYS, "Skylake GT1"}, 138 {0x190b, INTEL_MODEL_SKY, "Skylake GT1"}, 139 {0x190e, INTEL_MODEL_SKYM, "Skylake GT1"}, 140 {0x1912, INTEL_MODEL_SKY, "Skylake GT2"}, //confirmed OK 141 {0x1916, INTEL_MODEL_SKYM, "Skylake GT2"}, //confirmed native mode panel OK 142 {0x191a, INTEL_MODEL_SKYS, "Skylake GT2"}, 143 {0x191b, INTEL_MODEL_SKY, "Skylake GT2"}, 144 {0x191d, INTEL_MODEL_SKY, "Skylake GT2"}, 145 {0x191e, INTEL_MODEL_SKYM, "Skylake GT2"}, 146 {0x1921, INTEL_MODEL_SKYM, "Skylake GT2F"}, 147 {0x1926, INTEL_MODEL_SKYM, "Skylake GT3"}, 148 {0x192a, INTEL_MODEL_SKYS, "Skylake GT3"}, 149 {0x192b, INTEL_MODEL_SKY, "Skylake GT3"}, 150 151 {0x5906, INTEL_MODEL_KBY, "Kabylake ULT GT1"}, 152 {0x5902, INTEL_MODEL_KBY, "Kabylake DT GT1"}, 153 {0x5916, INTEL_MODEL_KBYM, "Kabylake ULT GT2"}, 154 {0x5921, INTEL_MODEL_KBYM, "Kabylake ULT GT2F"}, 155 {0x591c, INTEL_MODEL_KBY, "Kabylake ULX GT2"}, 156 {0x591e, INTEL_MODEL_KBY, "Kabylake ULX GT2"}, 157 {0x5912, INTEL_MODEL_KBY, "Kabylake DT GT2"}, 158 {0x5917, INTEL_MODEL_KBYM, "Kabylake Mobile GT2"}, 159 {0x591b, INTEL_MODEL_KBYM, "Kabylake Halo GT2"}, 160 {0x591d, INTEL_MODEL_KBY, "Kabylake WKS GT2"}, 161 {0x5926, INTEL_MODEL_KBY, "Kabylake ULT GT3"}, 162 {0x5927, INTEL_MODEL_KBY, "Kabylake ULT GT3"}, 163 164 {0x3185, INTEL_MODEL_KBYM, "GeminiLake GT1"}, // Same device id for desktop and mobile. 165 {0x3184, INTEL_MODEL_KBYM, "GeminiLake GT1.5"}, // Same device id for desktop and mobile. 166 167 {0x3e90, INTEL_MODEL_CFL, "CoffeeLake GT1"}, 168 {0x3e93, INTEL_MODEL_CFL, "CoffeeLake GT1"}, 169 {0x3e91, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 170 {0x3e92, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 171 {0x3e96, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 172 {0x3e98, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 173 {0x3e9a, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 174 {0x3e9b, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"}, 175 {0x3eab, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"}, 176 {0x3ea5, INTEL_MODEL_CFL, "CoffeeLake GT3"}, 177 {0x3ea6, INTEL_MODEL_CFL, "CoffeeLake GT3"}, 178 179 {0x8a56, INTEL_MODEL_CFLM, "IceLake GT1"}, 180 {0x8a5c, INTEL_MODEL_CFLM, "IceLake GT1.5"}, 181 {0x8a5a, INTEL_MODEL_CFLM, "IceLake GT1.5"}, 182 {0x8a51, INTEL_MODEL_CFLM, "IceLake GT2"}, 183 {0x8a52, INTEL_MODEL_CFLM, "IceLake GT2"}, 184 {0x8a53, INTEL_MODEL_CFLM, "IceLake GT2"}, 185 186 {0x9ba4, INTEL_MODEL_CML, "CometLake GT1"}, 187 {0x9ba8, INTEL_MODEL_CML, "CometLake GT1"}, 188 {0x9b21, INTEL_MODEL_CMLM, "CometLake U GT1"}, 189 {0x9baa, INTEL_MODEL_CMLM, "CometLake U GT1"}, 190 {0x9bc4, INTEL_MODEL_CML, "CometLake GT2"}, 191 {0x9bc5, INTEL_MODEL_CML, "CometLake GT2"}, 192 {0x9bc6, INTEL_MODEL_CML, "CometLake GT2"}, 193 {0x9bc8, INTEL_MODEL_CML, "CometLake GT2"}, 194 {0x9be6, INTEL_MODEL_CML, "CometLake GT2"}, 195 {0x9bf6, INTEL_MODEL_CML, "CometLake GT2"}, 196 {0x9b41, INTEL_MODEL_CMLM, "CometLake U GT2"}, 197 {0x9bca, INTEL_MODEL_CMLM, "CometLake U GT2"}, 198 {0x9bcc, INTEL_MODEL_CMLM, "CometLake U GT2"}, 199 200 {0x4e55, INTEL_MODEL_JSL, "JasperLake"}, 201 {0x4e61, INTEL_MODEL_JSL, "JasperLake"}, 202 {0x4e71, INTEL_MODEL_JSLM, "JasperLake"}, 203 204 {0x9a49, INTEL_MODEL_TGLM, "TigerLake"}, 205 {0x9a78, INTEL_MODEL_TGLM, "TigerLake"}, 206 {0x9a40, INTEL_MODEL_TGLM, "TigerLake"}, 207 {0x9a60, INTEL_MODEL_TGLM, "TigerLake"}, 208 {0x9a68, INTEL_MODEL_TGLM, "TigerLake"}, 209 {0x9a70, INTEL_MODEL_TGLM, "TigerLake"}, 210 }; 211 212 int32 api_version = B_CUR_DRIVER_API_VERSION; 213 214 char* gDeviceNames[MAX_CARDS + 1]; 215 intel_info* gDeviceInfo[MAX_CARDS]; 216 pci_module_info* gPCI; 217 agp_gart_module_info* gGART; 218 mutex gLock; 219 220 221 static status_t 222 get_next_intel_extreme(int32* _cookie, pci_info &info, uint32 &type) 223 { 224 int32 index = *_cookie; 225 226 // find devices 227 228 for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) { 229 // check vendor 230 if (info.vendor_id != VENDOR_ID_INTEL 231 || info.class_base != PCI_display 232 || (info.class_sub != PCI_vga && info.class_sub != PCI_display_other)) 233 continue; 234 235 // check device 236 for (uint32 i = 0; i < sizeof(kSupportedDevices) 237 / sizeof(kSupportedDevices[0]); i++) { 238 if (info.device_id == kSupportedDevices[i].device_id) { 239 type = i; 240 *_cookie = index + 1; 241 ERROR("%s: Intel gfx deviceID: 0x%04x\n", __func__, info.device_id); 242 return B_OK; 243 } 244 } 245 } 246 247 return B_ENTRY_NOT_FOUND; 248 } 249 250 251 static enum pch_info 252 detect_intel_pch() 253 { 254 pci_info info; 255 256 // find devices 257 for (int32 i = 0; gPCI->get_nth_pci_info(i, &info) == B_OK; i++) { 258 // check vendor 259 if (info.vendor_id != VENDOR_ID_INTEL 260 || info.class_base != PCI_bridge 261 || info.class_sub != PCI_isa) { 262 continue; 263 } 264 265 // check device 266 unsigned short id = info.device_id & INTEL_PCH_DEVICE_ID_MASK; 267 ERROR("%s: Intel PCH deviceID: 0x%04x\n", __func__, info.device_id); 268 switch(id) { 269 case INTEL_PCH_IBX_DEVICE_ID: 270 ERROR("%s: Found Ibex Peak PCH\n", __func__); 271 return INTEL_PCH_IBX; 272 case INTEL_PCH_CPT_DEVICE_ID: 273 ERROR("%s: Found CougarPoint PCH\n", __func__); 274 return INTEL_PCH_CPT; 275 case INTEL_PCH_PPT_DEVICE_ID: 276 ERROR("%s: Found PantherPoint PCH\n", __func__); 277 return INTEL_PCH_CPT; 278 case INTEL_PCH_LPT_DEVICE_ID: 279 case INTEL_PCH_LPT_LP_DEVICE_ID: 280 ERROR("%s: Found LynxPoint PCH\n", __func__); 281 return INTEL_PCH_LPT; 282 case INTEL_PCH_WPT_DEVICE_ID: 283 case INTEL_PCH_WPT_LP_DEVICE_ID: 284 ERROR("%s: Found WildcatPoint PCH\n", __func__); 285 return INTEL_PCH_LPT; 286 case INTEL_PCH_SPT_DEVICE_ID: 287 case INTEL_PCH_SPT_LP_DEVICE_ID: 288 ERROR("%s: Found SunrisePoint PCH\n", __func__); 289 return INTEL_PCH_SPT; 290 case INTEL_PCH_KBP_DEVICE_ID: 291 ERROR("%s: Found Kaby Lake PCH\n", __func__); 292 return INTEL_PCH_SPT; 293 case INTEL_PCH_GMP_DEVICE_ID: 294 ERROR("%s: Found Gemini Lake PCH\n", __func__); 295 return INTEL_PCH_CNP; 296 case INTEL_PCH_CNP_DEVICE_ID: 297 case INTEL_PCH_CNP_LP_DEVICE_ID: 298 ERROR("%s: Found Cannon Lake PCH\n", __func__); 299 return INTEL_PCH_CNP; 300 case INTEL_PCH_CMP_DEVICE_ID: 301 case INTEL_PCH_CMP2_DEVICE_ID: 302 ERROR("%s: Found Comet Lake PCH\n", __func__); 303 return INTEL_PCH_CNP; 304 case INTEL_PCH_CMP_V_DEVICE_ID: 305 ERROR("%s: Found Comet Lake V PCH\n", __func__); 306 return INTEL_PCH_SPT; 307 case INTEL_PCH_ICP_DEVICE_ID: 308 case INTEL_PCH_ICP2_DEVICE_ID: 309 ERROR("%s: Found Ice Lake PCH\n", __func__); 310 return INTEL_PCH_ICP; 311 case INTEL_PCH_MCC_DEVICE_ID: 312 ERROR("%s: Found Mule Creek Canyon PCH\n", __func__); 313 return INTEL_PCH_MCC; 314 case INTEL_PCH_TGP_DEVICE_ID: 315 case INTEL_PCH_TGP2_DEVICE_ID: 316 ERROR("%s: Found Tiger Lake PCH\n", __func__); 317 return INTEL_PCH_TGP; 318 case INTEL_PCH_JSP_DEVICE_ID: 319 ERROR("%s: Found Jasper Lake PCH\n", __func__); 320 return INTEL_PCH_JSP; 321 case INTEL_PCH_ADP_DEVICE_ID: 322 case INTEL_PCH_ADP2_DEVICE_ID: 323 case INTEL_PCH_ADP3_DEVICE_ID: 324 case INTEL_PCH_ADP4_DEVICE_ID: 325 ERROR("%s: Found Alder Lake PCH\n", __func__); 326 return INTEL_PCH_ADP; 327 } 328 } 329 330 ERROR("%s: No PCH detected.\n", __func__); 331 return INTEL_PCH_NONE; 332 } 333 334 335 extern "C" const char** 336 publish_devices(void) 337 { 338 CALLED(); 339 return (const char**)gDeviceNames; 340 } 341 342 343 extern "C" status_t 344 init_hardware(void) 345 { 346 CALLED(); 347 348 status_t status = get_module(B_PCI_MODULE_NAME,(module_info**)&gPCI); 349 if (status != B_OK) { 350 ERROR("pci module unavailable\n"); 351 return status; 352 } 353 354 int32 cookie = 0; 355 uint32 type; 356 pci_info info; 357 status = get_next_intel_extreme(&cookie, info, type); 358 359 put_module(B_PCI_MODULE_NAME); 360 return status; 361 } 362 363 364 extern "C" status_t 365 init_driver(void) 366 { 367 CALLED(); 368 369 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 370 if (status != B_OK) { 371 ERROR("pci module unavailable\n"); 372 return status; 373 } 374 375 status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART); 376 if (status != B_OK) { 377 ERROR("AGP GART module unavailable\n"); 378 put_module(B_PCI_MODULE_NAME); 379 return status; 380 } 381 382 mutex_init(&gLock, "intel extreme ksync"); 383 384 // find the PCH device (if any) 385 enum pch_info pchInfo = detect_intel_pch(); 386 387 // find devices 388 389 int32 found = 0; 390 391 for (int32 cookie = 0; found < MAX_CARDS;) { 392 pci_info* info = (pci_info*)malloc(sizeof(pci_info)); 393 if (info == NULL) 394 break; 395 396 uint32 type; 397 status = get_next_intel_extreme(&cookie, *info, type); 398 if (status < B_OK) { 399 free(info); 400 break; 401 } 402 403 // create device names & allocate device info structure 404 405 char name[64]; 406 sprintf(name, "graphics/intel_extreme_%02x%02x%02x", 407 info->bus, info->device, 408 info->function); 409 410 gDeviceNames[found] = strdup(name); 411 if (gDeviceNames[found] == NULL) 412 break; 413 414 gDeviceInfo[found] = (intel_info*)malloc(sizeof(intel_info)); 415 if (gDeviceInfo[found] == NULL) { 416 free(gDeviceNames[found]); 417 break; 418 } 419 420 // initialize the structure for later use 421 422 memset(gDeviceInfo[found], 0, sizeof(intel_info)); 423 gDeviceInfo[found]->init_status = B_NO_INIT; 424 gDeviceInfo[found]->id = found; 425 gDeviceInfo[found]->pci = info; 426 gDeviceInfo[found]->registers = info->u.h0.base_registers[0]; 427 gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name; 428 gDeviceInfo[found]->device_type = kSupportedDevices[type].type; 429 gDeviceInfo[found]->pch_info = pchInfo; 430 431 dprintf(DEVICE_NAME ": (%" B_PRId32 ") %s, revision = 0x%x\n", found, 432 kSupportedDevices[type].name, info->revision); 433 434 found++; 435 } 436 437 gDeviceNames[found] = NULL; 438 439 if (found == 0) { 440 mutex_destroy(&gLock); 441 put_module(B_AGP_GART_MODULE_NAME); 442 put_module(B_PCI_MODULE_NAME); 443 return ENODEV; 444 } 445 446 return B_OK; 447 } 448 449 450 extern "C" void 451 uninit_driver(void) 452 { 453 CALLED(); 454 455 mutex_destroy(&gLock); 456 457 // free device related structures 458 char* name; 459 for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) { 460 free(gDeviceInfo[index]); 461 free(name); 462 } 463 464 put_module(B_AGP_GART_MODULE_NAME); 465 put_module(B_PCI_MODULE_NAME); 466 } 467 468 469 extern "C" device_hooks* 470 find_device(const char* name) 471 { 472 CALLED(); 473 474 int index; 475 for (index = 0; gDeviceNames[index] != NULL; index++) { 476 if (!strcmp(name, gDeviceNames[index])) 477 return &gDeviceHooks; 478 } 479 480 return NULL; 481 } 482