1 /* 2 * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2011-2016, Haiku, Inc. All Rights Reserved. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Axel Dörfler, axeld@pinc-software.de 8 * Jerome Duval, jerome.duval@gmail.com 9 * Adrien Destugues, pulkomandy@gmail.com 10 * Michael Lotz, mmlr@mlotz.ch 11 * Alexander von Gluck IV, kallisti5@unixzen.com 12 */ 13 14 15 #include <AreaKeeper.h> 16 #include <intel_extreme.h> 17 18 #include <stdlib.h> 19 20 #include <AGP.h> 21 #include <KernelExport.h> 22 #include <PCI.h> 23 24 #include <new> 25 26 27 #define TRACE_INTEL 28 #ifdef TRACE_INTEL 29 # define TRACE(x...) dprintf("intel_gart: " x) 30 #else 31 # define TRACE(x...) ; 32 #endif 33 #define ERROR(x...) dprintf("intel_gart: " x) 34 35 36 /* read and write to PCI config space */ 37 #define get_pci_config(info, offset, size) \ 38 (sPCI->read_pci_config((info).bus, (info).device, (info).function, \ 39 (offset), (size))) 40 #define set_pci_config(info, offset, size, value) \ 41 (sPCI->write_pci_config((info).bus, (info).device, (info).function, \ 42 (offset), (size), (value))) 43 #define write32(address, data) \ 44 (*((volatile uint32*)(address)) = (data)) 45 #define read32(address) \ 46 (*((volatile uint32*)(address))) 47 48 49 // PCI "Host bridge" is most cases :-) 50 const struct supported_device { 51 uint32 bridge_id; 52 uint32 display_id; 53 int32 type; 54 const char *name; 55 } kSupportedDevices[] = { 56 {0x3575, 0x3577, INTEL_GROUP_83x, "i830GM"}, 57 {0x2560, 0x2562, INTEL_GROUP_83x, "i845G"}, 58 {0x3580, 0x3582, INTEL_GROUP_85x, "i855G"}, 59 {0x358c, 0x358e, INTEL_GROUP_85x, "i855G"}, 60 {0x2570, 0x2572, INTEL_GROUP_85x, "i865G"}, 61 62 // {0x2792, INTEL_GROUP_91x, "i910"}, 63 // {0x258a, INTEL_GROUP_91x, "i915"}, 64 {0x2580, 0x2582, INTEL_MODEL_915, "i915G"}, 65 {0x2590, 0x2592, INTEL_MODEL_915M, "i915GM"}, 66 {0x2770, 0x2772, INTEL_MODEL_945, "i945G"}, 67 {0x27a0, 0x27a2, INTEL_MODEL_945M, "i945GM"}, 68 {0x27ac, 0x27ae, INTEL_MODEL_945M, "i945GME"}, 69 70 {0x2970, 0x2972, INTEL_MODEL_965, "i946GZ"}, 71 {0x2980, 0x2982, INTEL_MODEL_965, "G35"}, 72 {0x2990, 0x2992, INTEL_MODEL_965, "i965Q"}, 73 {0x29a0, 0x29a2, INTEL_MODEL_965, "i965G"}, 74 {0x2a00, 0x2a02, INTEL_MODEL_965, "i965GM"}, 75 {0x2a10, 0x2a12, INTEL_MODEL_965, "i965GME"}, 76 77 {0x29b0, 0x29b2, INTEL_MODEL_G33, "G33"}, 78 {0x29c0, 0x29c2, INTEL_MODEL_G33, "Q35"}, 79 {0x29d0, 0x29d2, INTEL_MODEL_G33, "Q33"}, 80 81 {0x2a40, 0x2a42, INTEL_MODEL_GM45, "GM45"}, 82 {0x2e00, 0x2e02, INTEL_MODEL_G45, "IGD"}, 83 {0x2e10, 0x2e12, INTEL_MODEL_G45, "Q45"}, 84 {0x2e20, 0x2e22, INTEL_MODEL_G45, "G45"}, 85 {0x2e30, 0x2e32, INTEL_MODEL_G45, "G41"}, 86 {0x2e40, 0x2e42, INTEL_MODEL_G45, "B43"}, 87 {0x2e90, 0x2e92, INTEL_MODEL_G45, "B43"}, 88 89 {0xa000, 0xa001, INTEL_MODEL_PINE, "Atom D4xx"}, 90 {0xa000, 0xa002, INTEL_MODEL_PINE, "Atom D5xx"}, 91 {0xa010, 0xa011, INTEL_MODEL_PINEM, "Atom N4xx"}, 92 {0xa010, 0xa012, INTEL_MODEL_PINEM, "Atom N5xx"}, 93 94 {0x0040, 0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"}, 95 {0x0044, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 96 {0x0062, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 97 {0x006a, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 98 99 {0x0100, 0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"}, 100 {0x0100, 0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"}, 101 {0x0100, 0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"}, 102 {0x0104, 0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"}, 103 {0x0104, 0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"}, 104 {0x0104, 0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"}, 105 {0x0108, 0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"}, 106 107 {0x0150, 0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"}, 108 {0x0150, 0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"}, 109 {0x0154, 0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"}, 110 {0x0154, 0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"}, 111 {0x0158, 0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"}, 112 {0x0158, 0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"}, 113 114 {0x0c00, 0x0412, INTEL_MODEL_HAS, "Haswell Desktop"}, 115 {0x0c04, 0x0416, INTEL_MODEL_HASM, "Haswell Mobile"}, 116 {0x0d04, 0x0d26, INTEL_MODEL_HASM, "Haswell Mobile"}, 117 {0x0a04, 0x0a16, INTEL_MODEL_HASM, "Haswell Mobile"}, 118 119 // XXX: 0x0f00 only confirmed on 0x0f30, 0x0f31 120 {0x0f00, 0x0155, INTEL_MODEL_VLV, "ValleyView Desktop"}, 121 {0x0f00, 0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 122 {0x0f00, 0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 123 {0x0f00, 0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 124 {0x0f00, 0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 125 {0x0f00, 0x0157, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 126 127 {0x1604, 0x1616, INTEL_MODEL_BDWM, "HD Graphics 5500 (Broadwell GT2)"}, 128 129 // XXX: 0x1904 only confirmed on 0x1916 130 {0x1904, 0x1902, INTEL_MODEL_SKY, "Skylake GT1"}, 131 {0x1904, 0x1906, INTEL_MODEL_SKYM, "Skylake GT1"}, 132 {0x1904, 0x190a, INTEL_MODEL_SKYS, "Skylake GT1"}, 133 {0x1904, 0x190b, INTEL_MODEL_SKY, "Skylake GT1"}, 134 {0x1904, 0x190e, INTEL_MODEL_SKYM, "Skylake GT1"}, 135 {0x191f, 0x1912, INTEL_MODEL_SKY, "Skylake GT2"}, // confirmed 136 {0x1904, 0x1916, INTEL_MODEL_SKYM, "Skylake GT2"}, 137 {0x1904, 0x191a, INTEL_MODEL_SKYS, "Skylake GT2"}, 138 {0x1904, 0x191b, INTEL_MODEL_SKY, "Skylake GT2"}, 139 {0x1904, 0x191d, INTEL_MODEL_SKY, "Skylake GT2"}, 140 {0x1904, 0x191e, INTEL_MODEL_SKYM, "Skylake GT2"}, 141 {0x1904, 0x1921, INTEL_MODEL_SKYM, "Skylake GT2F"}, 142 {0x1904, 0x1926, INTEL_MODEL_SKYM, "Skylake GT3"}, 143 {0x1904, 0x192a, INTEL_MODEL_SKYS, "Skylake GT3"}, 144 {0x1904, 0x192b, INTEL_MODEL_SKY, "Skylake GT3"}, 145 146 {0x5904, 0x5906, INTEL_MODEL_KBY, "Kabylake ULT GT1"}, 147 {0x590f, 0x5902, INTEL_MODEL_KBY, "Kabylake DT GT1"}, 148 {0x5904, 0x5916, INTEL_MODEL_KBYM, "Kabylake ULT GT2"}, 149 {0x590c, 0x5916, INTEL_MODEL_KBYM, "Kabylake ULT GT2"}, 150 {0x5904, 0x5921, INTEL_MODEL_KBYM, "Kabylake ULT GT2F"}, 151 {0x590c, 0x591c, INTEL_MODEL_KBY, "Kabylake ULX GT2"}, 152 {0x590c, 0x591e, INTEL_MODEL_KBY, "Kabylake ULX GT2"}, 153 {0x591f, 0x5912, INTEL_MODEL_KBY, "Kabylake DT GT2"}, 154 {0x5914, 0x5917, INTEL_MODEL_KBYM, "Kabylake Mobile GT2"}, 155 {0x5910, 0x591b, INTEL_MODEL_KBYM, "Kabylake Halo GT2"}, 156 {0x5918, 0x591d, INTEL_MODEL_KBY, "Kabylake WKS GT2"}, 157 {0x5904, 0x5926, INTEL_MODEL_KBY, "Kabylake ULT GT3"}, 158 {0x5904, 0x5927, INTEL_MODEL_KBY, "Kabylake ULT GT3"}, 159 160 {0x3e0f, 0x3e90, INTEL_MODEL_CFL, "CoffeeLake GT1"}, 161 {0x3e0f, 0x3e93, INTEL_MODEL_CFL, "CoffeeLake GT1"}, 162 {0x3e1f, 0x3e91, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 163 {0x3ec2, 0x3e92, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 164 {0x3e18, 0x3e96, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 165 {0x3e30, 0x3e98, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 166 {0x3e31, 0x3e9a, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 167 {0x3ec4, 0x3e9b, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"}, 168 {0x3e10, 0x3eab, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"}, 169 {0x3ec4, 0x3eab, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"}, 170 {0x3ed0, 0x3ea5, INTEL_MODEL_CFL, "CoffeeLake GT3"}, 171 {0x3ed0, 0x3ea6, INTEL_MODEL_CFL, "CoffeeLake GT3"}, 172 }; 173 174 struct intel_info { 175 pci_info bridge; 176 pci_info display; 177 DeviceType* type; 178 179 uint32* gtt_base; 180 phys_addr_t gtt_physical_base; 181 area_id gtt_area; 182 size_t gtt_entries; 183 size_t gtt_stolen_entries; 184 185 vuint32* registers; 186 area_id registers_area; 187 188 addr_t aperture_base; 189 phys_addr_t aperture_physical_base; 190 area_id aperture_area; 191 size_t aperture_size; 192 size_t aperture_stolen_size; 193 194 phys_addr_t scratch_page; 195 area_id scratch_area; 196 }; 197 198 static intel_info sInfo; 199 static pci_module_info* sPCI; 200 201 202 static bool 203 has_display_device(pci_info &info, uint32 deviceID) 204 { 205 for (uint32 index = 0; sPCI->get_nth_pci_info(index, &info) == B_OK; 206 index++) { 207 if (info.vendor_id != VENDOR_ID_INTEL 208 || info.device_id != deviceID 209 || info.class_base != PCI_display) 210 continue; 211 212 return true; 213 } 214 215 return false; 216 } 217 218 219 static uint16 220 gtt_memory_config(intel_info &info) 221 { 222 uint8 controlRegister = INTEL_GRAPHICS_MEMORY_CONTROL; 223 if (info.type->Generation() >= 6) 224 controlRegister = SNB_GRAPHICS_MEMORY_CONTROL; 225 226 return get_pci_config(info.bridge, controlRegister, 2); 227 } 228 229 230 static size_t 231 determine_gtt_stolen(intel_info &info) 232 { 233 uint16 memoryConfig = gtt_memory_config(info); 234 size_t memorySize = 1 << 20; // 1 MB 235 236 if (info.type->InGroup(INTEL_GROUP_83x)) { 237 // Older chips 238 switch (memoryConfig & STOLEN_MEMORY_MASK) { 239 case i830_LOCAL_MEMORY_ONLY: 240 // TODO: determine its size! 241 ERROR("getting local memory size not implemented.\n"); 242 break; 243 case i830_STOLEN_512K: 244 memorySize >>= 1; 245 break; 246 case i830_STOLEN_1M: 247 // default case 248 break; 249 case i830_STOLEN_8M: 250 memorySize *= 8; 251 break; 252 } 253 } else if (info.type->InGroup(INTEL_GROUP_SNB) 254 || info.type->InGroup(INTEL_GROUP_IVB) 255 || info.type->InGroup(INTEL_GROUP_HAS)) { 256 switch (memoryConfig & SNB_STOLEN_MEMORY_MASK) { 257 case SNB_STOLEN_MEMORY_32MB: 258 memorySize *= 32; 259 break; 260 case SNB_STOLEN_MEMORY_64MB: 261 memorySize *= 64; 262 break; 263 case SNB_STOLEN_MEMORY_96MB: 264 memorySize *= 96; 265 break; 266 case SNB_STOLEN_MEMORY_128MB: 267 memorySize *= 128; 268 break; 269 case SNB_STOLEN_MEMORY_160MB: 270 memorySize *= 160; 271 break; 272 case SNB_STOLEN_MEMORY_192MB: 273 memorySize *= 192; 274 break; 275 case SNB_STOLEN_MEMORY_224MB: 276 memorySize *= 224; 277 break; 278 case SNB_STOLEN_MEMORY_256MB: 279 memorySize *= 256; 280 break; 281 case SNB_STOLEN_MEMORY_288MB: 282 memorySize *= 288; 283 break; 284 case SNB_STOLEN_MEMORY_320MB: 285 memorySize *= 320; 286 break; 287 case SNB_STOLEN_MEMORY_352MB: 288 memorySize *= 352; 289 break; 290 case SNB_STOLEN_MEMORY_384MB: 291 memorySize *= 384; 292 break; 293 case SNB_STOLEN_MEMORY_416MB: 294 memorySize *= 416; 295 break; 296 case SNB_STOLEN_MEMORY_448MB: 297 memorySize *= 448; 298 break; 299 case SNB_STOLEN_MEMORY_480MB: 300 memorySize *= 480; 301 break; 302 case SNB_STOLEN_MEMORY_512MB: 303 memorySize *= 512; 304 break; 305 } 306 } else if (info.type->InGroup(INTEL_GROUP_BDW) 307 || info.type->InFamily(INTEL_FAMILY_LAKE)) { 308 switch (memoryConfig & BDW_STOLEN_MEMORY_MASK) { 309 case BDW_STOLEN_MEMORY_32MB: 310 memorySize *= 32; 311 break; 312 case BDW_STOLEN_MEMORY_64MB: 313 memorySize *= 64; 314 break; 315 case BDW_STOLEN_MEMORY_96MB: 316 memorySize *= 96; 317 break; 318 case BDW_STOLEN_MEMORY_128MB: 319 memorySize *= 128; 320 break; 321 case BDW_STOLEN_MEMORY_160MB: 322 memorySize *= 160; 323 break; 324 case BDW_STOLEN_MEMORY_192MB: 325 memorySize *= 192; 326 break; 327 case BDW_STOLEN_MEMORY_224MB: 328 memorySize *= 224; 329 break; 330 case BDW_STOLEN_MEMORY_256MB: 331 memorySize *= 256; 332 break; 333 case BDW_STOLEN_MEMORY_288MB: 334 memorySize *= 288; 335 break; 336 case BDW_STOLEN_MEMORY_320MB: 337 memorySize *= 320; 338 break; 339 case BDW_STOLEN_MEMORY_352MB: 340 memorySize *= 352; 341 break; 342 case BDW_STOLEN_MEMORY_384MB: 343 memorySize *= 384; 344 break; 345 case BDW_STOLEN_MEMORY_416MB: 346 memorySize *= 416; 347 break; 348 case BDW_STOLEN_MEMORY_448MB: 349 memorySize *= 448; 350 break; 351 case BDW_STOLEN_MEMORY_480MB: 352 memorySize *= 480; 353 break; 354 case BDW_STOLEN_MEMORY_512MB: 355 memorySize *= 512; 356 break; 357 case BDW_STOLEN_MEMORY_1024MB: 358 memorySize *= 1024; 359 break; 360 case BDW_STOLEN_MEMORY_1536MB: 361 memorySize *= 1536; 362 break; 363 } 364 if(info.type->InGroup(INTEL_GROUP_BDW)) { 365 if((memoryConfig & BDW_STOLEN_MEMORY_MASK) == BDW_STOLEN_MEMORY_2016MB) { 366 memorySize *= 2016; 367 } 368 } else if(info.type->InFamily(INTEL_FAMILY_LAKE)) { 369 switch(memoryConfig & BDW_STOLEN_MEMORY_MASK) { 370 case SKL_STOLEN_MEMORY_4MB: 371 memorySize *= 4; 372 break; 373 case SKL_STOLEN_MEMORY_8MB: 374 memorySize *= 8; 375 break; 376 case SKL_STOLEN_MEMORY_12MB: 377 memorySize *= 12; 378 break; 379 case SKL_STOLEN_MEMORY_16MB: 380 memorySize *= 16; 381 break; 382 case SKL_STOLEN_MEMORY_20MB: 383 memorySize *= 20; 384 break; 385 case SKL_STOLEN_MEMORY_24MB: 386 memorySize *= 24; 387 break; 388 case SKL_STOLEN_MEMORY_28MB: 389 memorySize *= 28; 390 break; 391 case SKL_STOLEN_MEMORY_32MB: 392 memorySize *= 32; 393 break; 394 case SKL_STOLEN_MEMORY_36MB: 395 memorySize *= 36; 396 break; 397 case SKL_STOLEN_MEMORY_40MB: 398 memorySize *= 40; 399 break; 400 case SKL_STOLEN_MEMORY_44MB: 401 memorySize *= 44; 402 break; 403 case SKL_STOLEN_MEMORY_48MB: 404 memorySize *= 48; 405 break; 406 case SKL_STOLEN_MEMORY_52MB: 407 memorySize *= 52; 408 break; 409 case SKL_STOLEN_MEMORY_56MB: 410 memorySize *= 56; 411 break; 412 case SKL_STOLEN_MEMORY_60MB: 413 memorySize *= 60; 414 break; 415 } 416 } 417 } else if (info.type->InGroup(INTEL_GROUP_85x) 418 || info.type->InFamily(INTEL_FAMILY_9xx) 419 || info.type->InGroup(INTEL_GROUP_ILK)) { 420 switch (memoryConfig & STOLEN_MEMORY_MASK) { 421 case i855_STOLEN_MEMORY_4M: 422 memorySize *= 4; 423 break; 424 case i855_STOLEN_MEMORY_8M: 425 memorySize *= 8; 426 break; 427 case i855_STOLEN_MEMORY_16M: 428 memorySize *= 16; 429 break; 430 case i855_STOLEN_MEMORY_32M: 431 memorySize *= 32; 432 break; 433 case i855_STOLEN_MEMORY_48M: 434 memorySize *= 48; 435 break; 436 case i855_STOLEN_MEMORY_64M: 437 memorySize *= 64; 438 break; 439 case i855_STOLEN_MEMORY_128M: 440 memorySize *= 128; 441 break; 442 case i855_STOLEN_MEMORY_256M: 443 memorySize *= 256; 444 break; 445 case G4X_STOLEN_MEMORY_96MB: 446 memorySize *= 96; 447 break; 448 case G4X_STOLEN_MEMORY_160MB: 449 memorySize *= 160; 450 break; 451 case G4X_STOLEN_MEMORY_224MB: 452 memorySize *= 224; 453 break; 454 case G4X_STOLEN_MEMORY_352MB: 455 memorySize *= 352; 456 break; 457 } 458 } else { 459 // TODO: error out! 460 memorySize = 4096; 461 } 462 return memorySize - 4096; 463 } 464 465 466 static size_t 467 determine_gtt_size(intel_info &info) 468 { 469 uint16 memoryConfig = gtt_memory_config(info); 470 size_t gttSize = 0; 471 472 if (info.type->IsModel(INTEL_MODEL_965)) { 473 switch (memoryConfig & i965_GTT_MASK) { 474 case i965_GTT_128K: 475 gttSize = 128 << 10; 476 break; 477 case i965_GTT_256K: 478 gttSize = 256 << 10; 479 break; 480 case i965_GTT_512K: 481 gttSize = 512 << 10; 482 break; 483 } 484 } else if (info.type->IsModel(INTEL_MODEL_G33) 485 || info.type->InGroup(INTEL_GROUP_PIN)) { 486 switch (memoryConfig & G33_GTT_MASK) { 487 case G33_GTT_1M: 488 gttSize = 1 << 20; 489 break; 490 case G33_GTT_2M: 491 gttSize = 2 << 20; 492 break; 493 } 494 } else if (info.type->InGroup(INTEL_GROUP_G4x) 495 || info.type->InGroup(INTEL_GROUP_ILK)) { 496 switch (memoryConfig & G4X_GTT_MASK) { 497 case G4X_GTT_NONE: 498 gttSize = 0; 499 break; 500 case G4X_GTT_1M_NO_IVT: 501 gttSize = 1 << 20; 502 break; 503 case G4X_GTT_2M_NO_IVT: 504 case G4X_GTT_2M_IVT: 505 gttSize = 2 << 20; 506 break; 507 case G4X_GTT_3M_IVT: 508 gttSize = 3 << 20; 509 break; 510 case G4X_GTT_4M_IVT: 511 gttSize = 4 << 20; 512 break; 513 } 514 } else if (info.type->InGroup(INTEL_GROUP_SNB) 515 || info.type->InGroup(INTEL_GROUP_IVB) 516 || info.type->InGroup(INTEL_GROUP_HAS)) { 517 switch (memoryConfig & SNB_GTT_SIZE_MASK) { 518 case SNB_GTT_SIZE_NONE: 519 gttSize = 0; 520 break; 521 case SNB_GTT_SIZE_1MB: 522 gttSize = 1 << 20; 523 break; 524 case SNB_GTT_SIZE_2MB: 525 gttSize = 2 << 20; 526 break; 527 } 528 } else if (info.type->InGroup(INTEL_GROUP_BDW) 529 || info.type->InFamily(INTEL_FAMILY_LAKE)) { 530 switch (memoryConfig & BDW_GTT_SIZE_MASK) { 531 case BDW_GTT_SIZE_NONE: 532 gttSize = 0; 533 break; 534 case BDW_GTT_SIZE_2MB: 535 gttSize = 2 << 20; 536 break; 537 case BDW_GTT_SIZE_4MB: 538 gttSize = 4 << 20; 539 break; 540 case BDW_GTT_SIZE_8MB: 541 gttSize = 8 << 20; 542 break; 543 } 544 } else { 545 // older models have the GTT as large as their frame buffer mapping 546 // TODO: check if the i9xx version works with the i8xx chips as well 547 size_t frameBufferSize = 0; 548 if (info.type->InFamily(INTEL_FAMILY_8xx)) { 549 if (info.type->InGroup(INTEL_GROUP_83x) 550 && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M) 551 frameBufferSize = 64 << 20; 552 else 553 frameBufferSize = 128 << 20; 554 } else if (info.type->Generation() >= 3) { 555 frameBufferSize = info.display.u.h0.base_register_sizes[2]; 556 } 557 558 TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20); 559 gttSize = frameBufferSize / 1024; 560 } 561 return gttSize; 562 } 563 564 565 static void 566 set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress) 567 { 568 if (info.type->Generation() >= 8) { 569 // CHV + BXT 570 physicalAddress |= (physicalAddress >> 28) & 0x07f0; 571 // TODO: cache control? 572 } else if (info.type->Generation() >= 6) { 573 // SandyBridge, IronLake, IvyBridge, Haswell 574 physicalAddress |= (physicalAddress >> 28) & 0x0ff0; 575 physicalAddress |= 0x02; // cache control, l3 cacheable 576 } else if (info.type->Generation() >= 4) { 577 // Intel 9xx minus 91x, 94x, G33 578 // possible high bits are stored in the lower end 579 physicalAddress |= (physicalAddress >> 28) & 0x00f0; 580 // TODO: cache control? 581 } 582 583 // TODO: this is not 64-bit safe! 584 write32(info.gtt_base + (offset >> GTT_PAGE_SHIFT), 585 (uint32)physicalAddress | GTT_ENTRY_VALID); 586 } 587 588 589 static void 590 intel_unmap(intel_info &info) 591 { 592 delete_area(info.registers_area); 593 delete_area(info.gtt_area); 594 delete_area(info.scratch_area); 595 delete_area(info.aperture_area); 596 info.aperture_size = 0; 597 } 598 599 600 static status_t 601 intel_map(intel_info &info) 602 { 603 int fbIndex = 0; 604 int mmioIndex = 1; 605 if (info.type->Generation() >= 3) { 606 // for some reason Intel saw the need to change the order of the 607 // mappings with the introduction of the i9xx family 608 mmioIndex = 0; 609 fbIndex = 2; 610 } 611 612 AreaKeeper mmioMapper; 613 info.registers_area = mmioMapper.Map("intel GMCH mmio", 614 info.display.u.h0.base_registers[mmioIndex], 615 info.display.u.h0.base_register_sizes[mmioIndex], B_ANY_KERNEL_ADDRESS, 616 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.registers); 617 618 if (mmioMapper.InitCheck() < B_OK) { 619 ERROR("could not map memory I/O!\n"); 620 return info.registers_area; 621 } 622 623 // make sure bus master, memory-mapped I/O, and frame buffer is enabled 624 set_pci_config(info.display, PCI_command, 2, 625 get_pci_config(info.display, PCI_command, 2) 626 | PCI_command_io | PCI_command_memory | PCI_command_master); 627 628 void* scratchAddress; 629 AreaKeeper scratchCreator; 630 info.scratch_area = scratchCreator.Create("intel GMCH scratch", 631 &scratchAddress, B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_FULL_LOCK, 632 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 633 if (scratchCreator.InitCheck() < B_OK) { 634 ERROR("could not create scratch page!\n"); 635 return info.scratch_area; 636 } 637 638 physical_entry entry; 639 if (get_memory_map(scratchAddress, B_PAGE_SIZE, &entry, 1) != B_OK) 640 return B_ERROR; 641 642 // TODO: Review these 643 if (info.type->InFamily(INTEL_FAMILY_8xx)) { 644 info.gtt_physical_base = read32(info.registers 645 + INTEL_PAGE_TABLE_CONTROL) & ~PAGE_TABLE_ENABLED; 646 if (info.gtt_physical_base == 0) { 647 // TODO: not sure how this is supposed to work under Linux/FreeBSD, 648 // but on my i865, this code is needed for Haiku. 649 ERROR("Use GTT address fallback.\n"); 650 info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] 651 + i830_GTT_BASE; 652 } 653 } else if (info.type->InGroup(INTEL_GROUP_91x)) { 654 info.gtt_physical_base = get_pci_config(info.display, i915_GTT_BASE, 4); 655 } else { 656 // 945+? 657 info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] 658 + (2UL << 20); 659 } 660 661 size_t gttSize = determine_gtt_size(info); 662 size_t stolenSize = determine_gtt_stolen(info); 663 664 info.gtt_entries = gttSize / 4096; 665 info.gtt_stolen_entries = stolenSize / 4096; 666 667 TRACE("GTT base %" B_PRIxPHYSADDR ", size %lu, entries %lu, stolen %lu\n", 668 info.gtt_physical_base, gttSize, info.gtt_entries, stolenSize); 669 670 AreaKeeper gttMapper; 671 info.gtt_area = gttMapper.Map("intel GMCH gtt", 672 info.gtt_physical_base, gttSize, B_ANY_KERNEL_ADDRESS, 673 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.gtt_base); 674 if (gttMapper.InitCheck() < B_OK) { 675 ERROR("could not map GTT!\n"); 676 return info.gtt_area; 677 } 678 679 info.aperture_physical_base = info.display.u.h0.base_registers[fbIndex]; 680 info.aperture_stolen_size = stolenSize; 681 if (info.aperture_size == 0) 682 info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex]; 683 684 ERROR("detected %ld MB of stolen memory, aperture size %ld MB, " 685 "GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20, 686 info.aperture_size >> 20, gttSize >> 10); 687 688 ERROR("GTT base = 0x%" B_PRIxPHYSADDR "\n", info.gtt_physical_base); 689 ERROR("MMIO base = 0x%" B_PRIx32 "\n", 690 info.display.u.h0.base_registers[mmioIndex]); 691 ERROR("GMR base = 0x%" B_PRIxPHYSADDR "\n", info.aperture_physical_base); 692 693 AreaKeeper apertureMapper; 694 info.aperture_area = apertureMapper.Map("intel graphics aperture", 695 info.aperture_physical_base, info.aperture_size, 696 B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC, 697 B_READ_AREA | B_WRITE_AREA, (void**)&info.aperture_base); 698 if (apertureMapper.InitCheck() < B_OK) { 699 // try again without write combining 700 ERROR("enabling write combined mode failed.\n"); 701 702 info.aperture_area = apertureMapper.Map("intel graphics aperture", 703 info.aperture_physical_base, info.aperture_size, 704 B_ANY_KERNEL_BLOCK_ADDRESS, B_READ_AREA | B_WRITE_AREA, 705 (void**)&info.aperture_base); 706 } 707 if (apertureMapper.InitCheck() < B_OK) { 708 ERROR("could not map graphics aperture!\n"); 709 return info.aperture_area; 710 } 711 712 info.scratch_page = entry.address; 713 714 gttMapper.Detach(); 715 mmioMapper.Detach(); 716 scratchCreator.Detach(); 717 apertureMapper.Detach(); 718 719 return B_OK; 720 } 721 722 723 // #pragma mark - module interface 724 725 726 status_t 727 intel_create_aperture(uint8 bus, uint8 device, uint8 function, size_t size, 728 void** _aperture) 729 { 730 // TODO: we currently only support a single AGP bridge! 731 if ((bus != sInfo.bridge.bus || device != sInfo.bridge.device 732 || function != sInfo.bridge.function) 733 && (bus != sInfo.display.bus || device != sInfo.display.device 734 || function != sInfo.display.function)) 735 return B_BAD_VALUE; 736 737 sInfo.aperture_size = size; 738 739 if (intel_map(sInfo) < B_OK) 740 return B_ERROR; 741 742 uint16 gmchControl = get_pci_config(sInfo.bridge, 743 INTEL_GRAPHICS_MEMORY_CONTROL, 2) | MEMORY_CONTROL_ENABLED; 744 set_pci_config(sInfo.bridge, INTEL_GRAPHICS_MEMORY_CONTROL, 2, gmchControl); 745 746 write32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL, 747 sInfo.gtt_physical_base | PAGE_TABLE_ENABLED); 748 read32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL); 749 750 if (sInfo.scratch_page != 0) { 751 for (size_t i = sInfo.gtt_stolen_entries; i < sInfo.gtt_entries; i++) { 752 set_gtt_entry(sInfo, i << GTT_PAGE_SHIFT, sInfo.scratch_page); 753 } 754 read32(sInfo.gtt_base + sInfo.gtt_entries - 1); 755 } 756 757 asm("wbinvd;"); 758 759 *_aperture = NULL; 760 return B_OK; 761 } 762 763 764 void 765 intel_delete_aperture(void* aperture) 766 { 767 intel_unmap(sInfo); 768 } 769 770 771 static status_t 772 intel_get_aperture_info(void* aperture, aperture_info* info) 773 { 774 if (info == NULL) 775 return B_BAD_VALUE; 776 777 info->base = sInfo.aperture_base; 778 info->physical_base = sInfo.aperture_physical_base; 779 info->size = sInfo.aperture_size; 780 info->reserved_size = sInfo.aperture_stolen_size; 781 782 return B_OK; 783 } 784 785 786 status_t 787 intel_set_aperture_size(void* aperture, size_t size) 788 { 789 return B_ERROR; 790 } 791 792 793 static status_t 794 intel_bind_page(void* aperture, uint32 offset, phys_addr_t physicalAddress) 795 { 796 //TRACE("bind_page(offset %lx, physical %lx)\n", offset, physicalAddress); 797 798 set_gtt_entry(sInfo, offset, physicalAddress); 799 return B_OK; 800 } 801 802 803 static status_t 804 intel_unbind_page(void* aperture, uint32 offset) 805 { 806 //TRACE("unbind_page(offset %lx)\n", offset); 807 808 if (sInfo.scratch_page != 0) 809 set_gtt_entry(sInfo, offset, sInfo.scratch_page); 810 811 return B_OK; 812 } 813 814 815 void 816 intel_flush_tlbs(void* aperture) 817 { 818 read32(sInfo.gtt_base + sInfo.gtt_entries - 1); 819 asm("wbinvd;"); 820 } 821 822 823 // #pragma mark - 824 825 826 static status_t 827 intel_init() 828 { 829 TRACE("bus manager init\n"); 830 831 if (get_module(B_PCI_MODULE_NAME, (module_info**)&sPCI) != B_OK) 832 return B_ERROR; 833 834 for (uint32 index = 0; sPCI->get_nth_pci_info(index, &sInfo.bridge) == B_OK; 835 index++) { 836 if (sInfo.bridge.vendor_id != VENDOR_ID_INTEL 837 || sInfo.bridge.class_base != PCI_bridge) 838 continue; 839 840 // check device 841 for (uint32 i = 0; i < sizeof(kSupportedDevices) 842 / sizeof(kSupportedDevices[0]); i++) { 843 if (sInfo.bridge.device_id == kSupportedDevices[i].bridge_id) { 844 sInfo.type = new DeviceType(kSupportedDevices[i].type); 845 if (has_display_device(sInfo.display, 846 kSupportedDevices[i].display_id)) { 847 TRACE("found intel bridge\n"); 848 return B_OK; 849 } 850 } 851 } 852 } 853 854 return ENODEV; 855 } 856 857 858 static void 859 intel_uninit() 860 { 861 if (sInfo.type) 862 delete sInfo.type; 863 } 864 865 866 static int32 867 intel_std_ops(int32 op, ...) 868 { 869 switch (op) { 870 case B_MODULE_INIT: 871 return intel_init(); 872 case B_MODULE_UNINIT: 873 intel_uninit(); 874 return B_OK; 875 } 876 877 return B_BAD_VALUE; 878 } 879 880 881 static struct agp_gart_bus_module_info sIntelModuleInfo = { 882 { 883 "busses/agp_gart/intel/v0", 884 0, 885 intel_std_ops 886 }, 887 888 intel_create_aperture, 889 intel_delete_aperture, 890 891 intel_get_aperture_info, 892 intel_set_aperture_size, 893 intel_bind_page, 894 intel_unbind_page, 895 intel_flush_tlbs 896 }; 897 898 module_info* modules[] = { 899 (module_info*)&sIntelModuleInfo, 900 NULL 901 }; 902