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