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 #ifndef __HAIKU__ 36 # define B_KERNEL_READ_AREA 0 37 # define B_KERNEL_WRITE_AREA 0 38 #endif 39 40 /* read and write to PCI config space */ 41 #define get_pci_config(info, offset, size) \ 42 (sPCI->read_pci_config((info).bus, (info).device, (info).function, \ 43 (offset), (size))) 44 #define set_pci_config(info, offset, size, value) \ 45 (sPCI->write_pci_config((info).bus, (info).device, (info).function, \ 46 (offset), (size), (value))) 47 #define write32(address, data) \ 48 (*((volatile uint32*)(address)) = (data)) 49 #define read32(address) \ 50 (*((volatile uint32*)(address))) 51 52 53 // PCI "Host bridge" is most cases :-) 54 const struct supported_device { 55 uint32 bridge_id; 56 uint32 display_id; 57 int32 type; 58 const char *name; 59 } kSupportedDevices[] = { 60 {0x3575, 0x3577, INTEL_GROUP_83x, "i830GM"}, 61 {0x2560, 0x2562, INTEL_GROUP_83x, "i845G"}, 62 {0x3580, 0x3582, INTEL_GROUP_85x, "i855G"}, 63 {0x358c, 0x358e, INTEL_GROUP_85x, "i855G"}, 64 {0x2570, 0x2572, INTEL_GROUP_85x, "i865G"}, 65 66 // {0x2792, INTEL_GROUP_91x, "i910"}, 67 // {0x258a, INTEL_GROUP_91x, "i915"}, 68 {0x2580, 0x2582, INTEL_MODEL_915, "i915G"}, 69 {0x2590, 0x2592, INTEL_MODEL_915M, "i915GM"}, 70 {0x2770, 0x2772, INTEL_MODEL_945, "i945G"}, 71 {0x27a0, 0x27a2, INTEL_MODEL_945M, "i945GM"}, 72 {0x27ac, 0x27ae, INTEL_MODEL_945M, "i945GME"}, 73 74 {0x2970, 0x2972, INTEL_MODEL_965, "i946GZ"}, 75 {0x2980, 0x2982, INTEL_MODEL_965, "G35"}, 76 {0x2990, 0x2992, INTEL_MODEL_965, "i965Q"}, 77 {0x29a0, 0x29a2, INTEL_MODEL_965, "i965G"}, 78 {0x2a00, 0x2a02, INTEL_MODEL_965, "i965GM"}, 79 {0x2a10, 0x2a12, INTEL_MODEL_965, "i965GME"}, 80 81 {0x29b0, 0x29b2, INTEL_MODEL_G33, "G33"}, 82 {0x29c0, 0x29c2, INTEL_MODEL_G33, "Q35"}, 83 {0x29d0, 0x29d2, INTEL_MODEL_G33, "Q33"}, 84 85 {0x2a40, 0x2a42, INTEL_MODEL_GM45, "GM45"}, 86 {0x2e00, 0x2e02, INTEL_MODEL_G45, "IGD"}, 87 {0x2e10, 0x2e12, INTEL_MODEL_G45, "Q45"}, 88 {0x2e20, 0x2e22, INTEL_MODEL_G45, "G45"}, 89 {0x2e30, 0x2e32, INTEL_MODEL_G45, "G41"}, 90 {0x2e40, 0x2e42, INTEL_MODEL_G45, "B43"}, 91 {0x2e90, 0x2e92, INTEL_MODEL_G45, "B43"}, 92 93 {0xa000, 0xa001, INTEL_MODEL_PINE, "Atom D4xx"}, 94 {0xa000, 0xa002, INTEL_MODEL_PINE, "Atom D5xx"}, 95 {0xa010, 0xa011, INTEL_MODEL_PINEM, "Atom N4xx"}, 96 {0xa010, 0xa012, INTEL_MODEL_PINEM, "Atom N5xx"}, 97 98 {0x0040, 0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"}, 99 {0x0044, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 100 {0x0062, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 101 {0x006a, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 102 103 {0x0100, 0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"}, 104 {0x0100, 0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"}, 105 {0x0100, 0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"}, 106 {0x0104, 0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"}, 107 {0x0104, 0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"}, 108 {0x0104, 0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"}, 109 {0x0108, 0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"}, 110 111 {0x0150, 0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"}, 112 {0x0150, 0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"}, 113 {0x0154, 0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"}, 114 {0x0154, 0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"}, 115 {0x0158, 0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"}, 116 {0x0158, 0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"}, 117 118 {0x0c00, 0x0412, INTEL_MODEL_HAS, "Haswell Desktop"}, 119 {0x0c04, 0x0416, INTEL_MODEL_HASM, "Haswell Mobile"}, 120 {0x0d04, 0x0d26, INTEL_MODEL_HASM, "Haswell Mobile"}, 121 {0x0a04, 0x0a16, INTEL_MODEL_HASM, "Haswell Mobile"}, 122 123 // XXX: 0x0f00 only confirmed on 0x0f30, 0x0f31 124 {0x0f00, 0x0155, INTEL_MODEL_VLV, "ValleyView Desktop"}, 125 {0x0f00, 0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 126 {0x0f00, 0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 127 {0x0f00, 0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 128 {0x0f00, 0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 129 {0x0f00, 0x0157, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 130 131 // XXX: 0x1904 only confirmed on 0x1916 132 {0x1904, 0x1902, INTEL_MODEL_SKY, "Skylake GT1"}, 133 {0x1904, 0x1906, INTEL_MODEL_SKYM, "Skylake GT1"}, 134 {0x1904, 0x190a, INTEL_MODEL_SKYS, "Skylake GT1"}, 135 {0x1904, 0x190b, INTEL_MODEL_SKY, "Skylake GT1"}, 136 {0x1904, 0x190e, INTEL_MODEL_SKYM, "Skylake GT1"}, 137 {0x1904, 0x1912, INTEL_MODEL_SKY, "Skylake GT2"}, 138 {0x1904, 0x1916, INTEL_MODEL_SKYM, "Skylake GT2"}, 139 {0x1904, 0x191a, INTEL_MODEL_SKYS, "Skylake GT2"}, 140 {0x1904, 0x191b, INTEL_MODEL_SKY, "Skylake GT2"}, 141 {0x1904, 0x191d, INTEL_MODEL_SKY, "Skylake GT2"}, 142 {0x1904, 0x191e, INTEL_MODEL_SKYM, "Skylake GT2"}, 143 {0x1904, 0x1921, INTEL_MODEL_SKYM, "Skylake GT2F"}, 144 {0x1904, 0x1926, INTEL_MODEL_SKYM, "Skylake GT3"}, 145 {0x1904, 0x192a, INTEL_MODEL_SKYS, "Skylake GT3"}, 146 {0x1904, 0x192b, INTEL_MODEL_SKY, "Skylake GT3"}, 147 }; 148 149 struct intel_info { 150 pci_info bridge; 151 pci_info display; 152 DeviceType* type; 153 154 uint32* gtt_base; 155 phys_addr_t gtt_physical_base; 156 area_id gtt_area; 157 size_t gtt_entries; 158 size_t gtt_stolen_entries; 159 160 vuint32* registers; 161 area_id registers_area; 162 163 addr_t aperture_base; 164 phys_addr_t aperture_physical_base; 165 area_id aperture_area; 166 size_t aperture_size; 167 size_t aperture_stolen_size; 168 169 phys_addr_t scratch_page; 170 area_id scratch_area; 171 }; 172 173 static intel_info sInfo; 174 static pci_module_info* sPCI; 175 176 177 static bool 178 has_display_device(pci_info &info, uint32 deviceID) 179 { 180 for (uint32 index = 0; sPCI->get_nth_pci_info(index, &info) == B_OK; 181 index++) { 182 if (info.vendor_id != VENDOR_ID_INTEL 183 || info.device_id != deviceID 184 || info.class_base != PCI_display) 185 continue; 186 187 return true; 188 } 189 190 return false; 191 } 192 193 194 static uint16 195 gtt_memory_config(intel_info &info) 196 { 197 uint8 controlRegister = INTEL_GRAPHICS_MEMORY_CONTROL; 198 if (info.type->InGroup(INTEL_GROUP_SNB)) 199 controlRegister = SNB_GRAPHICS_MEMORY_CONTROL; 200 201 return get_pci_config(info.bridge, controlRegister, 2); 202 } 203 204 205 static size_t 206 determine_gtt_stolen(intel_info &info) 207 { 208 uint16 memoryConfig = gtt_memory_config(info); 209 size_t memorySize = 1 << 20; // 1 MB 210 211 if (info.type->InGroup(INTEL_GROUP_83x)) { 212 // Older chips 213 switch (memoryConfig & STOLEN_MEMORY_MASK) { 214 case i830_LOCAL_MEMORY_ONLY: 215 // TODO: determine its size! 216 ERROR("getting local memory size not implemented.\n"); 217 break; 218 case i830_STOLEN_512K: 219 memorySize >>= 1; 220 break; 221 case i830_STOLEN_1M: 222 // default case 223 break; 224 case i830_STOLEN_8M: 225 memorySize *= 8; 226 break; 227 } 228 } else if (info.type->InGroup(INTEL_GROUP_SNB)) { 229 switch (memoryConfig & SNB_STOLEN_MEMORY_MASK) { 230 case SNB_STOLEN_MEMORY_32MB: 231 memorySize *= 32; 232 break; 233 case SNB_STOLEN_MEMORY_64MB: 234 memorySize *= 64; 235 break; 236 case SNB_STOLEN_MEMORY_96MB: 237 memorySize *= 96; 238 break; 239 case SNB_STOLEN_MEMORY_128MB: 240 memorySize *= 128; 241 break; 242 case SNB_STOLEN_MEMORY_160MB: 243 memorySize *= 160; 244 break; 245 case SNB_STOLEN_MEMORY_192MB: 246 memorySize *= 192; 247 break; 248 case SNB_STOLEN_MEMORY_224MB: 249 memorySize *= 224; 250 break; 251 case SNB_STOLEN_MEMORY_256MB: 252 memorySize *= 256; 253 break; 254 case SNB_STOLEN_MEMORY_288MB: 255 memorySize *= 288; 256 break; 257 case SNB_STOLEN_MEMORY_320MB: 258 memorySize *= 320; 259 break; 260 case SNB_STOLEN_MEMORY_352MB: 261 memorySize *= 352; 262 break; 263 case SNB_STOLEN_MEMORY_384MB: 264 memorySize *= 384; 265 break; 266 case SNB_STOLEN_MEMORY_416MB: 267 memorySize *= 416; 268 break; 269 case SNB_STOLEN_MEMORY_448MB: 270 memorySize *= 448; 271 break; 272 case SNB_STOLEN_MEMORY_480MB: 273 memorySize *= 480; 274 break; 275 case SNB_STOLEN_MEMORY_512MB: 276 memorySize *= 512; 277 break; 278 } 279 } else if (info.type->InGroup(INTEL_GROUP_85x) 280 || info.type->InFamily(INTEL_FAMILY_9xx) 281 || info.type->InFamily(INTEL_FAMILY_SER5) 282 || info.type->InFamily(INTEL_FAMILY_SOC0) 283 || info.type->InFamily(INTEL_FAMILY_POVR)) { 284 switch (memoryConfig & STOLEN_MEMORY_MASK) { 285 case i855_STOLEN_MEMORY_4M: 286 memorySize *= 4; 287 break; 288 case i855_STOLEN_MEMORY_8M: 289 memorySize *= 8; 290 break; 291 case i855_STOLEN_MEMORY_16M: 292 memorySize *= 16; 293 break; 294 case i855_STOLEN_MEMORY_32M: 295 memorySize *= 32; 296 break; 297 case i855_STOLEN_MEMORY_48M: 298 memorySize *= 48; 299 break; 300 case i855_STOLEN_MEMORY_64M: 301 memorySize *= 64; 302 break; 303 case i855_STOLEN_MEMORY_128M: 304 memorySize *= 128; 305 break; 306 case i855_STOLEN_MEMORY_256M: 307 memorySize *= 256; 308 break; 309 case G4X_STOLEN_MEMORY_96MB: 310 memorySize *= 96; 311 break; 312 case G4X_STOLEN_MEMORY_160MB: 313 memorySize *= 160; 314 break; 315 case G4X_STOLEN_MEMORY_224MB: 316 memorySize *= 224; 317 break; 318 case G4X_STOLEN_MEMORY_352MB: 319 memorySize *= 352; 320 break; 321 } 322 } else { 323 // TODO: error out! 324 memorySize = 4096; 325 } 326 return memorySize - 4096; 327 } 328 329 330 static size_t 331 determine_gtt_size(intel_info &info) 332 { 333 uint16 memoryConfig = gtt_memory_config(info); 334 size_t gttSize = 0; 335 336 if (info.type->IsModel(INTEL_MODEL_965)) { 337 switch (memoryConfig & i965_GTT_MASK) { 338 case i965_GTT_128K: 339 gttSize = 128 << 10; 340 break; 341 case i965_GTT_256K: 342 gttSize = 256 << 10; 343 break; 344 case i965_GTT_512K: 345 gttSize = 512 << 10; 346 break; 347 } 348 } else if (info.type->IsModel(INTEL_MODEL_G33) 349 || info.type->InGroup(INTEL_GROUP_PIN)) { 350 switch (memoryConfig & G33_GTT_MASK) { 351 case G33_GTT_1M: 352 gttSize = 1 << 20; 353 break; 354 case G33_GTT_2M: 355 gttSize = 2 << 20; 356 break; 357 } 358 } else if (info.type->InGroup(INTEL_GROUP_G4x) 359 || info.type->InGroup(INTEL_GROUP_ILK)) { 360 switch (memoryConfig & G4X_GTT_MASK) { 361 case G4X_GTT_NONE: 362 gttSize = 0; 363 break; 364 case G4X_GTT_1M_NO_IVT: 365 gttSize = 1 << 20; 366 break; 367 case G4X_GTT_2M_NO_IVT: 368 case G4X_GTT_2M_IVT: 369 gttSize = 2 << 20; 370 break; 371 case G4X_GTT_3M_IVT: 372 gttSize = 3 << 20; 373 break; 374 case G4X_GTT_4M_IVT: 375 gttSize = 4 << 20; 376 break; 377 } 378 } else if (info.type->InGroup(INTEL_GROUP_SNB)) { 379 switch (memoryConfig & SNB_GTT_SIZE_MASK) { 380 case SNB_GTT_SIZE_NONE: 381 gttSize = 0; 382 break; 383 case SNB_GTT_SIZE_1MB: 384 gttSize = 1 << 20; 385 break; 386 case SNB_GTT_SIZE_2MB: 387 gttSize = 2 << 20; 388 break; 389 } 390 } else { 391 // older models have the GTT as large as their frame buffer mapping 392 // TODO: check if the i9xx version works with the i8xx chips as well 393 size_t frameBufferSize = 0; 394 if (info.type->InFamily(INTEL_FAMILY_8xx)) { 395 if (info.type->InGroup(INTEL_GROUP_83x) 396 && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M) 397 frameBufferSize = 64 << 20; 398 else 399 frameBufferSize = 128 << 20; 400 } else if (info.type->Generation() >= 3) { 401 frameBufferSize = info.display.u.h0.base_register_sizes[2]; 402 } 403 404 TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20); 405 gttSize = frameBufferSize / 1024; 406 } 407 return gttSize; 408 } 409 410 411 static void 412 set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress) 413 { 414 if (info.type->Generation() >= 8) { 415 // CHV + BXT 416 physicalAddress |= (physicalAddress >> 28) & 0x07f0; 417 // TODO: cache control? 418 } else if (info.type->Generation() >= 6) { 419 // SandyBridge, IronLake, IvyBridge, Haswell 420 physicalAddress |= (physicalAddress >> 28) & 0x0ff0; 421 physicalAddress |= 0x02; // cache control, l3 cacheable 422 } else if (info.type->Generation() >= 4) { 423 // Intel 9xx minus 91x, 94x, G33 424 // possible high bits are stored in the lower end 425 physicalAddress |= (physicalAddress >> 28) & 0x00f0; 426 // TODO: cache control? 427 } 428 429 // TODO: this is not 64-bit safe! 430 write32(info.gtt_base + (offset >> GTT_PAGE_SHIFT), 431 (uint32)physicalAddress | GTT_ENTRY_VALID); 432 } 433 434 435 static void 436 intel_unmap(intel_info &info) 437 { 438 delete_area(info.registers_area); 439 delete_area(info.gtt_area); 440 delete_area(info.scratch_area); 441 delete_area(info.aperture_area); 442 info.aperture_size = 0; 443 } 444 445 446 static status_t 447 intel_map(intel_info &info) 448 { 449 int fbIndex = 0; 450 int mmioIndex = 1; 451 if (info.type->Generation() >= 3) { 452 // for some reason Intel saw the need to change the order of the 453 // mappings with the introduction of the i9xx family 454 mmioIndex = 0; 455 fbIndex = 2; 456 } 457 458 AreaKeeper mmioMapper; 459 info.registers_area = mmioMapper.Map("intel GMCH mmio", 460 info.display.u.h0.base_registers[mmioIndex], 461 info.display.u.h0.base_register_sizes[mmioIndex], B_ANY_KERNEL_ADDRESS, 462 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.registers); 463 464 if (mmioMapper.InitCheck() < B_OK) { 465 ERROR("could not map memory I/O!\n"); 466 return info.registers_area; 467 } 468 469 // make sure bus master, memory-mapped I/O, and frame buffer is enabled 470 set_pci_config(info.display, PCI_command, 2, 471 get_pci_config(info.display, PCI_command, 2) 472 | PCI_command_io | PCI_command_memory | PCI_command_master); 473 474 void* scratchAddress; 475 AreaKeeper scratchCreator; 476 info.scratch_area = scratchCreator.Create("intel GMCH scratch", 477 &scratchAddress, B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_FULL_LOCK, 478 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 479 if (scratchCreator.InitCheck() < B_OK) { 480 ERROR("could not create scratch page!\n"); 481 return info.scratch_area; 482 } 483 484 physical_entry entry; 485 if (get_memory_map(scratchAddress, B_PAGE_SIZE, &entry, 1) != B_OK) 486 return B_ERROR; 487 488 // TODO: Review these 489 if (info.type->InFamily(INTEL_FAMILY_8xx)) { 490 info.gtt_physical_base = read32(info.registers 491 + INTEL_PAGE_TABLE_CONTROL) & ~PAGE_TABLE_ENABLED; 492 if (info.gtt_physical_base == 0) { 493 // TODO: not sure how this is supposed to work under Linux/FreeBSD, 494 // but on my i865, this code is needed for Haiku. 495 ERROR("Use GTT address fallback.\n"); 496 info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] 497 + i830_GTT_BASE; 498 } 499 } else if (info.type->InGroup(INTEL_GROUP_91x)) { 500 info.gtt_physical_base = get_pci_config(info.display, i915_GTT_BASE, 4); 501 } else { 502 // 945+? 503 info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] 504 + (2UL << 20); 505 } 506 507 size_t gttSize = determine_gtt_size(info); 508 size_t stolenSize = determine_gtt_stolen(info); 509 510 info.gtt_entries = gttSize / 4096; 511 info.gtt_stolen_entries = stolenSize / 4096; 512 513 TRACE("GTT base %" B_PRIxPHYSADDR ", size %lu, entries %lu, stolen %lu\n", 514 info.gtt_physical_base, gttSize, info.gtt_entries, stolenSize); 515 516 AreaKeeper gttMapper; 517 info.gtt_area = gttMapper.Map("intel GMCH gtt", 518 info.gtt_physical_base, gttSize, B_ANY_KERNEL_ADDRESS, 519 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.gtt_base); 520 if (gttMapper.InitCheck() < B_OK) { 521 ERROR("could not map GTT!\n"); 522 return info.gtt_area; 523 } 524 525 info.aperture_physical_base = info.display.u.h0.base_registers[fbIndex]; 526 info.aperture_stolen_size = stolenSize; 527 if (info.aperture_size == 0) 528 info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex]; 529 530 ERROR("detected %ld MB of stolen memory, aperture size %ld MB, " 531 "GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20, 532 info.aperture_size >> 20, gttSize >> 10); 533 534 ERROR("GTT base = 0x%" B_PRIxPHYSADDR "\n", info.gtt_physical_base); 535 ERROR("MMIO base = 0x%" B_PRIx32 "\n", 536 info.display.u.h0.base_registers[mmioIndex]); 537 ERROR("GMR base = 0x%" B_PRIxPHYSADDR "\n", info.aperture_physical_base); 538 539 AreaKeeper apertureMapper; 540 info.aperture_area = apertureMapper.Map("intel graphics aperture", 541 info.aperture_physical_base, info.aperture_size, 542 B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC, 543 B_READ_AREA | B_WRITE_AREA, (void**)&info.aperture_base); 544 if (apertureMapper.InitCheck() < B_OK) { 545 // try again without write combining 546 ERROR("enabling write combined mode failed.\n"); 547 548 info.aperture_area = apertureMapper.Map("intel graphics aperture", 549 info.aperture_physical_base, info.aperture_size, 550 B_ANY_KERNEL_BLOCK_ADDRESS, B_READ_AREA | B_WRITE_AREA, 551 (void**)&info.aperture_base); 552 } 553 if (apertureMapper.InitCheck() < B_OK) { 554 ERROR("could not map graphics aperture!\n"); 555 return info.aperture_area; 556 } 557 558 info.scratch_page = entry.address; 559 560 gttMapper.Detach(); 561 mmioMapper.Detach(); 562 scratchCreator.Detach(); 563 apertureMapper.Detach(); 564 565 return B_OK; 566 } 567 568 569 // #pragma mark - module interface 570 571 572 status_t 573 intel_create_aperture(uint8 bus, uint8 device, uint8 function, size_t size, 574 void** _aperture) 575 { 576 // TODO: we currently only support a single AGP bridge! 577 if ((bus != sInfo.bridge.bus || device != sInfo.bridge.device 578 || function != sInfo.bridge.function) 579 && (bus != sInfo.display.bus || device != sInfo.display.device 580 || function != sInfo.display.function)) 581 return B_BAD_VALUE; 582 583 sInfo.aperture_size = size; 584 585 if (intel_map(sInfo) < B_OK) 586 return B_ERROR; 587 588 uint16 gmchControl = get_pci_config(sInfo.bridge, 589 INTEL_GRAPHICS_MEMORY_CONTROL, 2) | MEMORY_CONTROL_ENABLED; 590 set_pci_config(sInfo.bridge, INTEL_GRAPHICS_MEMORY_CONTROL, 2, gmchControl); 591 592 write32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL, 593 sInfo.gtt_physical_base | PAGE_TABLE_ENABLED); 594 read32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL); 595 596 if (sInfo.scratch_page != 0) { 597 for (size_t i = sInfo.gtt_stolen_entries; i < sInfo.gtt_entries; i++) { 598 set_gtt_entry(sInfo, i << GTT_PAGE_SHIFT, sInfo.scratch_page); 599 } 600 read32(sInfo.gtt_base + sInfo.gtt_entries - 1); 601 } 602 603 asm("wbinvd;"); 604 605 *_aperture = NULL; 606 return B_OK; 607 } 608 609 610 void 611 intel_delete_aperture(void* aperture) 612 { 613 intel_unmap(sInfo); 614 } 615 616 617 static status_t 618 intel_get_aperture_info(void* aperture, aperture_info* info) 619 { 620 if (info == NULL) 621 return B_BAD_VALUE; 622 623 info->base = sInfo.aperture_base; 624 info->physical_base = sInfo.aperture_physical_base; 625 info->size = sInfo.aperture_size; 626 info->reserved_size = sInfo.aperture_stolen_size; 627 628 return B_OK; 629 } 630 631 632 status_t 633 intel_set_aperture_size(void* aperture, size_t size) 634 { 635 return B_ERROR; 636 } 637 638 639 static status_t 640 intel_bind_page(void* aperture, uint32 offset, phys_addr_t physicalAddress) 641 { 642 //TRACE("bind_page(offset %lx, physical %lx)\n", offset, physicalAddress); 643 644 set_gtt_entry(sInfo, offset, physicalAddress); 645 return B_OK; 646 } 647 648 649 static status_t 650 intel_unbind_page(void* aperture, uint32 offset) 651 { 652 //TRACE("unbind_page(offset %lx)\n", offset); 653 654 if (sInfo.scratch_page != 0) 655 set_gtt_entry(sInfo, offset, sInfo.scratch_page); 656 657 return B_OK; 658 } 659 660 661 void 662 intel_flush_tlbs(void* aperture) 663 { 664 read32(sInfo.gtt_base + sInfo.gtt_entries - 1); 665 asm("wbinvd;"); 666 } 667 668 669 // #pragma mark - 670 671 672 static status_t 673 intel_init() 674 { 675 TRACE("bus manager init\n"); 676 677 if (get_module(B_PCI_MODULE_NAME, (module_info**)&sPCI) != B_OK) 678 return B_ERROR; 679 680 for (uint32 index = 0; sPCI->get_nth_pci_info(index, &sInfo.bridge) == B_OK; 681 index++) { 682 if (sInfo.bridge.vendor_id != VENDOR_ID_INTEL 683 || sInfo.bridge.class_base != PCI_bridge) 684 continue; 685 686 // check device 687 for (uint32 i = 0; i < sizeof(kSupportedDevices) 688 / sizeof(kSupportedDevices[0]); i++) { 689 if (sInfo.bridge.device_id == kSupportedDevices[i].bridge_id) { 690 sInfo.type = new DeviceType(kSupportedDevices[i].type); 691 if (has_display_device(sInfo.display, 692 kSupportedDevices[i].display_id)) { 693 TRACE("found intel bridge\n"); 694 return B_OK; 695 } 696 } 697 } 698 } 699 700 return ENODEV; 701 } 702 703 704 static void 705 intel_uninit() 706 { 707 if (sInfo.type) 708 delete sInfo.type; 709 } 710 711 712 static int32 713 intel_std_ops(int32 op, ...) 714 { 715 switch (op) { 716 case B_MODULE_INIT: 717 return intel_init(); 718 case B_MODULE_UNINIT: 719 intel_uninit(); 720 return B_OK; 721 } 722 723 return B_BAD_VALUE; 724 } 725 726 727 static struct agp_gart_bus_module_info sIntelModuleInfo = { 728 { 729 "busses/agp_gart/intel/v0", 730 0, 731 intel_std_ops 732 }, 733 734 intel_create_aperture, 735 intel_delete_aperture, 736 737 intel_get_aperture_info, 738 intel_set_aperture_size, 739 intel_bind_page, 740 intel_unbind_page, 741 intel_flush_tlbs 742 }; 743 744 module_info* modules[] = { 745 (module_info*)&sIntelModuleInfo, 746 NULL 747 }; 748