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 {0x1904, 0x1912, INTEL_MODEL_SKY, "Skylake GT2"}, 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 147 struct intel_info { 148 pci_info bridge; 149 pci_info display; 150 DeviceType* type; 151 152 uint32* gtt_base; 153 phys_addr_t gtt_physical_base; 154 area_id gtt_area; 155 size_t gtt_entries; 156 size_t gtt_stolen_entries; 157 158 vuint32* registers; 159 area_id registers_area; 160 161 addr_t aperture_base; 162 phys_addr_t aperture_physical_base; 163 area_id aperture_area; 164 size_t aperture_size; 165 size_t aperture_stolen_size; 166 167 phys_addr_t scratch_page; 168 area_id scratch_area; 169 }; 170 171 static intel_info sInfo; 172 static pci_module_info* sPCI; 173 174 175 static bool 176 has_display_device(pci_info &info, uint32 deviceID) 177 { 178 for (uint32 index = 0; sPCI->get_nth_pci_info(index, &info) == B_OK; 179 index++) { 180 if (info.vendor_id != VENDOR_ID_INTEL 181 || info.device_id != deviceID 182 || info.class_base != PCI_display) 183 continue; 184 185 return true; 186 } 187 188 return false; 189 } 190 191 192 static uint16 193 gtt_memory_config(intel_info &info) 194 { 195 uint8 controlRegister = INTEL_GRAPHICS_MEMORY_CONTROL; 196 if (info.type->InGroup(INTEL_GROUP_SNB)) 197 controlRegister = SNB_GRAPHICS_MEMORY_CONTROL; 198 199 return get_pci_config(info.bridge, controlRegister, 2); 200 } 201 202 203 static size_t 204 determine_gtt_stolen(intel_info &info) 205 { 206 uint16 memoryConfig = gtt_memory_config(info); 207 size_t memorySize = 1 << 20; // 1 MB 208 209 if (info.type->InGroup(INTEL_GROUP_83x)) { 210 // Older chips 211 switch (memoryConfig & STOLEN_MEMORY_MASK) { 212 case i830_LOCAL_MEMORY_ONLY: 213 // TODO: determine its size! 214 ERROR("getting local memory size not implemented.\n"); 215 break; 216 case i830_STOLEN_512K: 217 memorySize >>= 1; 218 break; 219 case i830_STOLEN_1M: 220 // default case 221 break; 222 case i830_STOLEN_8M: 223 memorySize *= 8; 224 break; 225 } 226 } else if (info.type->InGroup(INTEL_GROUP_SNB)) { 227 switch (memoryConfig & SNB_STOLEN_MEMORY_MASK) { 228 case SNB_STOLEN_MEMORY_32MB: 229 memorySize *= 32; 230 break; 231 case SNB_STOLEN_MEMORY_64MB: 232 memorySize *= 64; 233 break; 234 case SNB_STOLEN_MEMORY_96MB: 235 memorySize *= 96; 236 break; 237 case SNB_STOLEN_MEMORY_128MB: 238 memorySize *= 128; 239 break; 240 case SNB_STOLEN_MEMORY_160MB: 241 memorySize *= 160; 242 break; 243 case SNB_STOLEN_MEMORY_192MB: 244 memorySize *= 192; 245 break; 246 case SNB_STOLEN_MEMORY_224MB: 247 memorySize *= 224; 248 break; 249 case SNB_STOLEN_MEMORY_256MB: 250 memorySize *= 256; 251 break; 252 case SNB_STOLEN_MEMORY_288MB: 253 memorySize *= 288; 254 break; 255 case SNB_STOLEN_MEMORY_320MB: 256 memorySize *= 320; 257 break; 258 case SNB_STOLEN_MEMORY_352MB: 259 memorySize *= 352; 260 break; 261 case SNB_STOLEN_MEMORY_384MB: 262 memorySize *= 384; 263 break; 264 case SNB_STOLEN_MEMORY_416MB: 265 memorySize *= 416; 266 break; 267 case SNB_STOLEN_MEMORY_448MB: 268 memorySize *= 448; 269 break; 270 case SNB_STOLEN_MEMORY_480MB: 271 memorySize *= 480; 272 break; 273 case SNB_STOLEN_MEMORY_512MB: 274 memorySize *= 512; 275 break; 276 } 277 } else if (info.type->InGroup(INTEL_GROUP_85x) 278 || info.type->InFamily(INTEL_FAMILY_9xx) 279 || info.type->InFamily(INTEL_FAMILY_SER5) 280 || info.type->InFamily(INTEL_FAMILY_SOC0) 281 || info.type->InFamily(INTEL_FAMILY_POVR)) { 282 switch (memoryConfig & STOLEN_MEMORY_MASK) { 283 case i855_STOLEN_MEMORY_4M: 284 memorySize *= 4; 285 break; 286 case i855_STOLEN_MEMORY_8M: 287 memorySize *= 8; 288 break; 289 case i855_STOLEN_MEMORY_16M: 290 memorySize *= 16; 291 break; 292 case i855_STOLEN_MEMORY_32M: 293 memorySize *= 32; 294 break; 295 case i855_STOLEN_MEMORY_48M: 296 memorySize *= 48; 297 break; 298 case i855_STOLEN_MEMORY_64M: 299 memorySize *= 64; 300 break; 301 case i855_STOLEN_MEMORY_128M: 302 memorySize *= 128; 303 break; 304 case i855_STOLEN_MEMORY_256M: 305 memorySize *= 256; 306 break; 307 case G4X_STOLEN_MEMORY_96MB: 308 memorySize *= 96; 309 break; 310 case G4X_STOLEN_MEMORY_160MB: 311 memorySize *= 160; 312 break; 313 case G4X_STOLEN_MEMORY_224MB: 314 memorySize *= 224; 315 break; 316 case G4X_STOLEN_MEMORY_352MB: 317 memorySize *= 352; 318 break; 319 } 320 } else { 321 // TODO: error out! 322 memorySize = 4096; 323 } 324 return memorySize - 4096; 325 } 326 327 328 static size_t 329 determine_gtt_size(intel_info &info) 330 { 331 uint16 memoryConfig = gtt_memory_config(info); 332 size_t gttSize = 0; 333 334 if (info.type->IsModel(INTEL_MODEL_965)) { 335 switch (memoryConfig & i965_GTT_MASK) { 336 case i965_GTT_128K: 337 gttSize = 128 << 10; 338 break; 339 case i965_GTT_256K: 340 gttSize = 256 << 10; 341 break; 342 case i965_GTT_512K: 343 gttSize = 512 << 10; 344 break; 345 } 346 } else if (info.type->IsModel(INTEL_MODEL_G33) 347 || info.type->InGroup(INTEL_GROUP_PIN)) { 348 switch (memoryConfig & G33_GTT_MASK) { 349 case G33_GTT_1M: 350 gttSize = 1 << 20; 351 break; 352 case G33_GTT_2M: 353 gttSize = 2 << 20; 354 break; 355 } 356 } else if (info.type->InGroup(INTEL_GROUP_G4x) 357 || info.type->InGroup(INTEL_GROUP_ILK)) { 358 switch (memoryConfig & G4X_GTT_MASK) { 359 case G4X_GTT_NONE: 360 gttSize = 0; 361 break; 362 case G4X_GTT_1M_NO_IVT: 363 gttSize = 1 << 20; 364 break; 365 case G4X_GTT_2M_NO_IVT: 366 case G4X_GTT_2M_IVT: 367 gttSize = 2 << 20; 368 break; 369 case G4X_GTT_3M_IVT: 370 gttSize = 3 << 20; 371 break; 372 case G4X_GTT_4M_IVT: 373 gttSize = 4 << 20; 374 break; 375 } 376 } else if (info.type->InGroup(INTEL_GROUP_SNB)) { 377 switch (memoryConfig & SNB_GTT_SIZE_MASK) { 378 case SNB_GTT_SIZE_NONE: 379 gttSize = 0; 380 break; 381 case SNB_GTT_SIZE_1MB: 382 gttSize = 1 << 20; 383 break; 384 case SNB_GTT_SIZE_2MB: 385 gttSize = 2 << 20; 386 break; 387 } 388 } else { 389 // older models have the GTT as large as their frame buffer mapping 390 // TODO: check if the i9xx version works with the i8xx chips as well 391 size_t frameBufferSize = 0; 392 if (info.type->InFamily(INTEL_FAMILY_8xx)) { 393 if (info.type->InGroup(INTEL_GROUP_83x) 394 && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M) 395 frameBufferSize = 64 << 20; 396 else 397 frameBufferSize = 128 << 20; 398 } else if (info.type->Generation() >= 3) { 399 frameBufferSize = info.display.u.h0.base_register_sizes[2]; 400 } 401 402 TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20); 403 gttSize = frameBufferSize / 1024; 404 } 405 return gttSize; 406 } 407 408 409 static void 410 set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress) 411 { 412 if (info.type->Generation() >= 8) { 413 // CHV + BXT 414 physicalAddress |= (physicalAddress >> 28) & 0x07f0; 415 // TODO: cache control? 416 } else if (info.type->Generation() >= 6) { 417 // SandyBridge, IronLake, IvyBridge, Haswell 418 physicalAddress |= (physicalAddress >> 28) & 0x0ff0; 419 physicalAddress |= 0x02; // cache control, l3 cacheable 420 } else if (info.type->Generation() >= 4) { 421 // Intel 9xx minus 91x, 94x, G33 422 // possible high bits are stored in the lower end 423 physicalAddress |= (physicalAddress >> 28) & 0x00f0; 424 // TODO: cache control? 425 } 426 427 // TODO: this is not 64-bit safe! 428 write32(info.gtt_base + (offset >> GTT_PAGE_SHIFT), 429 (uint32)physicalAddress | GTT_ENTRY_VALID); 430 } 431 432 433 static void 434 intel_unmap(intel_info &info) 435 { 436 delete_area(info.registers_area); 437 delete_area(info.gtt_area); 438 delete_area(info.scratch_area); 439 delete_area(info.aperture_area); 440 info.aperture_size = 0; 441 } 442 443 444 static status_t 445 intel_map(intel_info &info) 446 { 447 int fbIndex = 0; 448 int mmioIndex = 1; 449 if (info.type->Generation() >= 3) { 450 // for some reason Intel saw the need to change the order of the 451 // mappings with the introduction of the i9xx family 452 mmioIndex = 0; 453 fbIndex = 2; 454 } 455 456 AreaKeeper mmioMapper; 457 info.registers_area = mmioMapper.Map("intel GMCH mmio", 458 info.display.u.h0.base_registers[mmioIndex], 459 info.display.u.h0.base_register_sizes[mmioIndex], B_ANY_KERNEL_ADDRESS, 460 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.registers); 461 462 if (mmioMapper.InitCheck() < B_OK) { 463 ERROR("could not map memory I/O!\n"); 464 return info.registers_area; 465 } 466 467 // make sure bus master, memory-mapped I/O, and frame buffer is enabled 468 set_pci_config(info.display, PCI_command, 2, 469 get_pci_config(info.display, PCI_command, 2) 470 | PCI_command_io | PCI_command_memory | PCI_command_master); 471 472 void* scratchAddress; 473 AreaKeeper scratchCreator; 474 info.scratch_area = scratchCreator.Create("intel GMCH scratch", 475 &scratchAddress, B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_FULL_LOCK, 476 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 477 if (scratchCreator.InitCheck() < B_OK) { 478 ERROR("could not create scratch page!\n"); 479 return info.scratch_area; 480 } 481 482 physical_entry entry; 483 if (get_memory_map(scratchAddress, B_PAGE_SIZE, &entry, 1) != B_OK) 484 return B_ERROR; 485 486 // TODO: Review these 487 if (info.type->InFamily(INTEL_FAMILY_8xx)) { 488 info.gtt_physical_base = read32(info.registers 489 + INTEL_PAGE_TABLE_CONTROL) & ~PAGE_TABLE_ENABLED; 490 if (info.gtt_physical_base == 0) { 491 // TODO: not sure how this is supposed to work under Linux/FreeBSD, 492 // but on my i865, this code is needed for Haiku. 493 ERROR("Use GTT address fallback.\n"); 494 info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] 495 + i830_GTT_BASE; 496 } 497 } else if (info.type->InGroup(INTEL_GROUP_91x)) { 498 info.gtt_physical_base = get_pci_config(info.display, i915_GTT_BASE, 4); 499 } else { 500 // 945+? 501 info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] 502 + (2UL << 20); 503 } 504 505 size_t gttSize = determine_gtt_size(info); 506 size_t stolenSize = determine_gtt_stolen(info); 507 508 info.gtt_entries = gttSize / 4096; 509 info.gtt_stolen_entries = stolenSize / 4096; 510 511 TRACE("GTT base %" B_PRIxPHYSADDR ", size %lu, entries %lu, stolen %lu\n", 512 info.gtt_physical_base, gttSize, info.gtt_entries, stolenSize); 513 514 AreaKeeper gttMapper; 515 info.gtt_area = gttMapper.Map("intel GMCH gtt", 516 info.gtt_physical_base, gttSize, B_ANY_KERNEL_ADDRESS, 517 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.gtt_base); 518 if (gttMapper.InitCheck() < B_OK) { 519 ERROR("could not map GTT!\n"); 520 return info.gtt_area; 521 } 522 523 info.aperture_physical_base = info.display.u.h0.base_registers[fbIndex]; 524 info.aperture_stolen_size = stolenSize; 525 if (info.aperture_size == 0) 526 info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex]; 527 528 ERROR("detected %ld MB of stolen memory, aperture size %ld MB, " 529 "GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20, 530 info.aperture_size >> 20, gttSize >> 10); 531 532 ERROR("GTT base = 0x%" B_PRIxPHYSADDR "\n", info.gtt_physical_base); 533 ERROR("MMIO base = 0x%" B_PRIx32 "\n", 534 info.display.u.h0.base_registers[mmioIndex]); 535 ERROR("GMR base = 0x%" B_PRIxPHYSADDR "\n", info.aperture_physical_base); 536 537 AreaKeeper apertureMapper; 538 info.aperture_area = apertureMapper.Map("intel graphics aperture", 539 info.aperture_physical_base, info.aperture_size, 540 B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC, 541 B_READ_AREA | B_WRITE_AREA, (void**)&info.aperture_base); 542 if (apertureMapper.InitCheck() < B_OK) { 543 // try again without write combining 544 ERROR("enabling write combined mode failed.\n"); 545 546 info.aperture_area = apertureMapper.Map("intel graphics aperture", 547 info.aperture_physical_base, info.aperture_size, 548 B_ANY_KERNEL_BLOCK_ADDRESS, B_READ_AREA | B_WRITE_AREA, 549 (void**)&info.aperture_base); 550 } 551 if (apertureMapper.InitCheck() < B_OK) { 552 ERROR("could not map graphics aperture!\n"); 553 return info.aperture_area; 554 } 555 556 info.scratch_page = entry.address; 557 558 gttMapper.Detach(); 559 mmioMapper.Detach(); 560 scratchCreator.Detach(); 561 apertureMapper.Detach(); 562 563 return B_OK; 564 } 565 566 567 // #pragma mark - module interface 568 569 570 status_t 571 intel_create_aperture(uint8 bus, uint8 device, uint8 function, size_t size, 572 void** _aperture) 573 { 574 // TODO: we currently only support a single AGP bridge! 575 if ((bus != sInfo.bridge.bus || device != sInfo.bridge.device 576 || function != sInfo.bridge.function) 577 && (bus != sInfo.display.bus || device != sInfo.display.device 578 || function != sInfo.display.function)) 579 return B_BAD_VALUE; 580 581 sInfo.aperture_size = size; 582 583 if (intel_map(sInfo) < B_OK) 584 return B_ERROR; 585 586 uint16 gmchControl = get_pci_config(sInfo.bridge, 587 INTEL_GRAPHICS_MEMORY_CONTROL, 2) | MEMORY_CONTROL_ENABLED; 588 set_pci_config(sInfo.bridge, INTEL_GRAPHICS_MEMORY_CONTROL, 2, gmchControl); 589 590 write32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL, 591 sInfo.gtt_physical_base | PAGE_TABLE_ENABLED); 592 read32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL); 593 594 if (sInfo.scratch_page != 0) { 595 for (size_t i = sInfo.gtt_stolen_entries; i < sInfo.gtt_entries; i++) { 596 set_gtt_entry(sInfo, i << GTT_PAGE_SHIFT, sInfo.scratch_page); 597 } 598 read32(sInfo.gtt_base + sInfo.gtt_entries - 1); 599 } 600 601 asm("wbinvd;"); 602 603 *_aperture = NULL; 604 return B_OK; 605 } 606 607 608 void 609 intel_delete_aperture(void* aperture) 610 { 611 intel_unmap(sInfo); 612 } 613 614 615 static status_t 616 intel_get_aperture_info(void* aperture, aperture_info* info) 617 { 618 if (info == NULL) 619 return B_BAD_VALUE; 620 621 info->base = sInfo.aperture_base; 622 info->physical_base = sInfo.aperture_physical_base; 623 info->size = sInfo.aperture_size; 624 info->reserved_size = sInfo.aperture_stolen_size; 625 626 return B_OK; 627 } 628 629 630 status_t 631 intel_set_aperture_size(void* aperture, size_t size) 632 { 633 return B_ERROR; 634 } 635 636 637 static status_t 638 intel_bind_page(void* aperture, uint32 offset, phys_addr_t physicalAddress) 639 { 640 //TRACE("bind_page(offset %lx, physical %lx)\n", offset, physicalAddress); 641 642 set_gtt_entry(sInfo, offset, physicalAddress); 643 return B_OK; 644 } 645 646 647 static status_t 648 intel_unbind_page(void* aperture, uint32 offset) 649 { 650 //TRACE("unbind_page(offset %lx)\n", offset); 651 652 if (sInfo.scratch_page != 0) 653 set_gtt_entry(sInfo, offset, sInfo.scratch_page); 654 655 return B_OK; 656 } 657 658 659 void 660 intel_flush_tlbs(void* aperture) 661 { 662 read32(sInfo.gtt_base + sInfo.gtt_entries - 1); 663 asm("wbinvd;"); 664 } 665 666 667 // #pragma mark - 668 669 670 static status_t 671 intel_init() 672 { 673 TRACE("bus manager init\n"); 674 675 if (get_module(B_PCI_MODULE_NAME, (module_info**)&sPCI) != B_OK) 676 return B_ERROR; 677 678 for (uint32 index = 0; sPCI->get_nth_pci_info(index, &sInfo.bridge) == B_OK; 679 index++) { 680 if (sInfo.bridge.vendor_id != VENDOR_ID_INTEL 681 || sInfo.bridge.class_base != PCI_bridge) 682 continue; 683 684 // check device 685 for (uint32 i = 0; i < sizeof(kSupportedDevices) 686 / sizeof(kSupportedDevices[0]); i++) { 687 if (sInfo.bridge.device_id == kSupportedDevices[i].bridge_id) { 688 sInfo.type = new DeviceType(kSupportedDevices[i].type); 689 if (has_display_device(sInfo.display, 690 kSupportedDevices[i].display_id)) { 691 TRACE("found intel bridge\n"); 692 return B_OK; 693 } 694 } 695 } 696 } 697 698 return ENODEV; 699 } 700 701 702 static void 703 intel_uninit() 704 { 705 if (sInfo.type) 706 delete sInfo.type; 707 } 708 709 710 static int32 711 intel_std_ops(int32 op, ...) 712 { 713 switch (op) { 714 case B_MODULE_INIT: 715 return intel_init(); 716 case B_MODULE_UNINIT: 717 intel_uninit(); 718 return B_OK; 719 } 720 721 return B_BAD_VALUE; 722 } 723 724 725 static struct agp_gart_bus_module_info sIntelModuleInfo = { 726 { 727 "busses/agp_gart/intel/v0", 728 0, 729 intel_std_ops 730 }, 731 732 intel_create_aperture, 733 intel_delete_aperture, 734 735 intel_get_aperture_info, 736 intel_set_aperture_size, 737 intel_bind_page, 738 intel_unbind_page, 739 intel_flush_tlbs 740 }; 741 742 module_info* modules[] = { 743 (module_info*)&sIntelModuleInfo, 744 NULL 745 }; 746