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