1 /* 2 * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2004-2006, Rudolf Cornelissen. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 // TODO: rethink the AGP interface for more than one bridge/device! 9 // (should be done with the new driver API then) 10 11 /* 12 Notes: 13 - currently we just setup all found devices with AGP interface to the same 14 highest common mode, we don't distinquish different AGP busses. 15 TODO: it might be a better idea to just setup one instead. 16 17 - AGP3 defines 'asynchronous request size' and 'calibration cycle' fields 18 in the status and command registers. Currently programming zero's which will 19 make it work, although further optimisation is possible. 20 21 - AGP3.5 also defines isochronous transfers which are not implemented here: 22 the hardware keeps them disabled by default. 23 */ 24 25 26 #include <AGP.h> 27 28 #include <stdlib.h> 29 30 #include <KernelExport.h> 31 #include <PCI.h> 32 33 #include <util/OpenHashTable.h> 34 #ifdef __HAIKU__ 35 # include <kernel/lock.h> 36 # include <vm/vm_page.h> 37 # include <vm/vm_types.h> 38 #endif 39 40 #include <lock.h> 41 42 #ifndef __HAIKU__ 43 # define PCI_capabilities_ptr 0x34 44 # define PCI_status_capabilities 0x0010 45 # define PCI_cap_id_agp 0x02 46 #endif 47 48 #define TRACE_AGP 49 #ifdef TRACE_AGP 50 # define TRACE(x...) dprintf("\33[36mAGP:\33[0m " x) 51 #else 52 # define TRACE(x...) ; 53 #endif 54 55 56 #define MAX_DEVICES 8 57 58 #define AGP_ID(address) (address) 59 #define AGP_STATUS(address) (address + 4) 60 #define AGP_COMMAND(address) (address + 8) 61 62 /* read and write to PCI config space */ 63 #define get_pci_config(info, offset, size) \ 64 (sPCI->read_pci_config((info).bus, (info).device, (info).function, \ 65 (offset), (size))) 66 #define set_pci_config(info, offset, size, value) \ 67 (sPCI->write_pci_config((info).bus, (info).device, (info).function, \ 68 (offset), (size), (value))) 69 70 #define RESERVED_APERTURE 0x80000000 71 #define ALLOCATED_APERTURE 0x40000000 72 #define BIND_APERTURE 0x20000000 73 #define APERTURE_PUBLIC_FLAGS_MASK 0x0000ffff 74 75 struct aperture_memory { 76 aperture_memory *next; 77 aperture_memory *hash_link; 78 addr_t base; 79 size_t size; 80 uint32 flags; 81 #if defined(__HAIKU__) && !defined(GART_TEST) 82 union { 83 vm_page **pages; 84 vm_page *page; 85 }; 86 #ifdef DEBUG_PAGE_ACCESS 87 thread_id allocating_thread; 88 #endif 89 #else 90 area_id area; 91 #endif 92 }; 93 94 class Aperture; 95 96 class MemoryHashDefinition { 97 public: 98 typedef addr_t KeyType; 99 typedef aperture_memory ValueType; 100 101 MemoryHashDefinition(aperture_info &info) : fInfo(info) {} 102 103 size_t HashKey(const KeyType &base) const 104 { return (base - fInfo.base) / B_PAGE_SIZE; } 105 size_t Hash(aperture_memory *memory) const 106 { return (memory->base - fInfo.base) / B_PAGE_SIZE; } 107 bool Compare(const KeyType &base, aperture_memory *memory) const 108 { return base == memory->base; } 109 aperture_memory *&GetLink(aperture_memory *memory) const 110 { return memory->hash_link; } 111 112 private: 113 aperture_info &fInfo; 114 }; 115 116 typedef BOpenHashTable<MemoryHashDefinition> MemoryHashTable; 117 118 struct agp_device_info { 119 uint8 address; /* location of AGP interface in PCI capabilities */ 120 agp_info info; 121 }; 122 123 class Aperture { 124 public: 125 Aperture(agp_gart_bus_module_info *module, void *aperture); 126 ~Aperture(); 127 128 status_t InitCheck() const { return fLock.sem >= B_OK ? B_OK : fLock.sem; } 129 130 void DeleteMemory(aperture_memory *memory); 131 aperture_memory *CreateMemory(size_t size, size_t alignment, uint32 flags); 132 133 status_t AllocateMemory(aperture_memory *memory, uint32 flags); 134 135 status_t UnbindMemory(aperture_memory *memory); 136 status_t BindMemory(aperture_memory *memory, addr_t base, size_t size); 137 138 status_t GetInfo(aperture_info *info); 139 140 aperture_memory *GetMemory(addr_t base) { return fHashTable.Lookup(base); } 141 142 addr_t Base() const { return fInfo.base; } 143 addr_t Size() const { return fInfo.size; } 144 int32 ID() const { return fID; } 145 struct lock &Lock() { return fLock; } 146 147 private: 148 bool _AdaptToReserved(addr_t &base, size_t &size, int32 *_offset = NULL); 149 void _Free(aperture_memory *memory); 150 void _Remove(aperture_memory *memory); 151 status_t _Insert(aperture_memory *memory, size_t size, size_t alignment, 152 uint32 flags); 153 154 struct lock fLock; 155 agp_gart_bus_module_info *fModule; 156 int32 fID; 157 aperture_info fInfo; 158 MemoryHashTable fHashTable; 159 aperture_memory *fFirstMemory; 160 void *fPrivateAperture; 161 162 public: 163 Aperture *fNext; 164 }; 165 166 class ApertureHashDefinition { 167 public: 168 typedef int32 KeyType; 169 typedef Aperture ValueType; 170 171 size_t HashKey(const KeyType &id) const 172 { return id; } 173 size_t Hash(Aperture *aperture) const 174 { return aperture->ID(); } 175 bool Compare(const KeyType &id, Aperture *aperture) const 176 { return id == aperture->ID(); } 177 Aperture *&GetLink(Aperture *aperture) const 178 { return aperture->fNext; } 179 }; 180 181 typedef BOpenHashTable<ApertureHashDefinition> ApertureHashTable; 182 183 184 static agp_device_info sDeviceInfos[MAX_DEVICES]; 185 static uint32 sDeviceCount; 186 static pci_module_info *sPCI; 187 static int32 sAcquired; 188 static ApertureHashTable sApertureHashTable; 189 static int32 sNextApertureID; 190 static struct lock sLock; 191 192 193 // #pragma mark - private support functions 194 195 196 /*! Makes sure that all bits lower than the maximum supported rate is set. */ 197 static uint32 198 fix_rate_support(uint32 command) 199 { 200 if ((command & AGP_3_MODE) != 0) { 201 if ((command & AGP_3_8x) != 0) 202 command |= AGP_3_4x; 203 204 command &= ~AGP_RATE_MASK | AGP_3_8x | AGP_3_4x; 205 command |= AGP_SBA; 206 // SBA is required for AGP3 207 } else { 208 /* AGP 2.0 scheme applies */ 209 if ((command & AGP_2_4x) != 0) 210 command |= AGP_2_2x; 211 if ((command & AGP_2_2x) != 0) 212 command |= AGP_2_1x; 213 } 214 215 return command; 216 } 217 218 219 /*! Makes sure that only the highest rate bit is set. */ 220 static uint32 221 fix_rate_command(uint32 command) 222 { 223 if ((command & AGP_3_MODE) != 0) { 224 if ((command & AGP_3_8x) != 0) 225 command &= ~AGP_3_4x; 226 } else { 227 /* AGP 2.0 scheme applies */ 228 if ((command & AGP_2_4x) != 0) 229 command &= ~(AGP_2_2x | AGP_2_1x); 230 if ((command & AGP_2_2x) != 0) 231 command &= ~AGP_2_1x; 232 } 233 234 return command; 235 } 236 237 238 /*! Checks the capabilities of the device, and removes everything from 239 \a command that the device does not support. 240 */ 241 static void 242 check_capabilities(agp_device_info &deviceInfo, uint32 &command) 243 { 244 uint32 agpStatus = deviceInfo.info.interface.status; 245 if (deviceInfo.info.class_base == PCI_bridge) { 246 // make sure the AGP rate support mask is correct 247 // (ie. has the lower bits set) 248 agpStatus = fix_rate_support(agpStatus); 249 } 250 251 TRACE("device %u.%u.%u has AGP capabilities %lx\n", deviceInfo.info.bus, 252 deviceInfo.info.device, deviceInfo.info.function, agpStatus); 253 254 // block non-supported AGP modes 255 command &= (agpStatus & (AGP_3_MODE | AGP_RATE_MASK)) 256 | ~(AGP_3_MODE | AGP_RATE_MASK); 257 258 // If no AGP mode is supported at all, nothing remains: 259 // devices exist that have the AGP style connector with AGP style registers, 260 // but not the features! 261 // (confirmed Matrox Millenium II AGP for instance) 262 if ((agpStatus & AGP_RATE_MASK) == 0) 263 command = 0; 264 265 // block side band adressing if not supported 266 if ((agpStatus & AGP_SBA) == 0) 267 command &= ~AGP_SBA; 268 269 // block fast writes if not supported 270 if ((agpStatus & AGP_FAST_WRITE) == 0) 271 command &= ~AGP_FAST_WRITE; 272 273 // adjust maximum request depth to least depth supported 274 // note: this is writable only in the graphics card 275 uint8 requestDepth = ((agpStatus & AGP_REQUEST) >> AGP_REQUEST_SHIFT); 276 if (requestDepth < ((command & AGP_REQUEST) >> AGP_REQUEST_SHIFT)) { 277 command &= ~AGP_REQUEST; 278 command |= (requestDepth << AGP_REQUEST_SHIFT); 279 } 280 } 281 282 283 /*! Checks the PCI capabilities if the device is an AGP device 284 */ 285 static bool 286 is_agp_device(pci_info &info, uint8 *_address) 287 { 288 // Check if device implements a list of capabilities 289 if ((get_pci_config(info, PCI_status, 2) & PCI_status_capabilities) == 0) 290 return false; 291 292 // Get pointer to PCI capabilities list 293 // (AGP devices only, no need to take cardbus into account) 294 uint8 address = get_pci_config(info, PCI_capabilities_ptr, 1); 295 296 while (true) { 297 uint8 id = get_pci_config(info, address, 1); 298 uint8 next = get_pci_config(info, address + 1, 1) & ~0x3; 299 300 if (id == PCI_cap_id_agp) { 301 // is an AGP device 302 if (_address != NULL) 303 *_address = address; 304 return true; 305 } 306 if (next == 0) { 307 // end of list 308 break; 309 } 310 311 address = next; 312 } 313 314 return false; 315 } 316 317 318 static status_t 319 get_next_agp_device(uint32 *_cookie, pci_info &info, agp_device_info &device) 320 { 321 uint32 index = *_cookie; 322 323 // find devices 324 325 for (; sPCI->get_nth_pci_info(index, &info) == B_OK; index++) { 326 // is it a bridge or a graphics card? 327 if ((info.class_base != PCI_bridge || info.class_sub != PCI_host) 328 && info.class_base != PCI_display) 329 continue; 330 331 if (is_agp_device(info, &device.address)) { 332 device.info.vendor_id = info.vendor_id; 333 device.info.device_id = info.device_id; 334 device.info.bus = info.bus; 335 device.info.device = info.device; 336 device.info.function = info.function; 337 device.info.class_sub = info.class_sub; 338 device.info.class_base = info.class_base; 339 340 /* get the contents of the AGP registers from this device */ 341 device.info.interface.capability_id = get_pci_config(info, 342 AGP_ID(device.address), 4); 343 device.info.interface.status = get_pci_config(info, 344 AGP_STATUS(device.address), 4); 345 device.info.interface.command = get_pci_config(info, 346 AGP_COMMAND(device.address), 4); 347 348 *_cookie = index + 1; 349 return B_OK; 350 } 351 } 352 353 return B_ENTRY_NOT_FOUND; 354 } 355 356 357 static void 358 set_agp_command(agp_device_info &deviceInfo, uint32 command) 359 { 360 set_pci_config(deviceInfo.info, AGP_COMMAND(deviceInfo.address), 4, command); 361 deviceInfo.info.interface.command = get_pci_config(deviceInfo.info, 362 AGP_COMMAND(deviceInfo.address), 4); 363 } 364 365 366 static void 367 set_pci_mode() 368 { 369 TRACE("set PCI mode on all AGP capable devices.\n"); 370 371 // First program all graphics cards 372 373 for (uint32 index = 0; index < sDeviceCount; index++) { 374 agp_device_info &deviceInfo = sDeviceInfos[index]; 375 if (deviceInfo.info.class_base != PCI_display) 376 continue; 377 378 set_agp_command(deviceInfo, 0); 379 } 380 381 // Then program all bridges - it's the other around for AGP mode 382 383 for (uint32 index = 0; index < sDeviceCount; index++) { 384 agp_device_info &deviceInfo = sDeviceInfos[index]; 385 if (deviceInfo.info.class_base != PCI_bridge) 386 continue; 387 388 set_agp_command(deviceInfo, 0); 389 } 390 391 // Wait 10mS for the bridges to recover (failsafe!) 392 // Note: some SiS bridge chipsets apparantly require 5mS to recover 393 // or the master (graphics card) cannot be initialized correctly! 394 snooze(10000); 395 } 396 397 398 status_t 399 get_area_base_and_size(area_id area, addr_t &base, size_t &size) 400 { 401 area_info info; 402 status_t status = get_area_info(area, &info); 403 if (status < B_OK) 404 return status; 405 406 base = (addr_t)info.address; 407 size = info.size; 408 return B_OK; 409 } 410 411 412 Aperture * 413 get_aperture(aperture_id id) 414 { 415 Autolock _(sLock); 416 return sApertureHashTable.Lookup(id); 417 } 418 419 420 // #pragma mark - Aperture 421 422 423 Aperture::Aperture(agp_gart_bus_module_info *module, void *aperture) 424 : 425 fModule(module), 426 fHashTable(fInfo), 427 fFirstMemory(NULL), 428 fPrivateAperture(aperture) 429 { 430 fModule->get_aperture_info(fPrivateAperture, &fInfo); 431 fID = atomic_add(&sNextApertureID, 1); 432 init_lock(&fLock, "aperture"); 433 } 434 435 436 Aperture::~Aperture() 437 { 438 while (fFirstMemory != NULL) { 439 DeleteMemory(fFirstMemory); 440 } 441 442 fModule->delete_aperture(fPrivateAperture); 443 put_module(fModule->info.name); 444 } 445 446 447 status_t 448 Aperture::GetInfo(aperture_info *info) 449 { 450 if (info == NULL) 451 return B_BAD_VALUE; 452 453 *info = fInfo; 454 return B_OK; 455 } 456 457 458 void 459 Aperture::DeleteMemory(aperture_memory *memory) 460 { 461 TRACE("delete memory %p\n", memory); 462 463 UnbindMemory(memory); 464 _Free(memory); 465 _Remove(memory); 466 fHashTable.Remove(memory); 467 delete memory; 468 } 469 470 471 aperture_memory * 472 Aperture::CreateMemory(size_t size, size_t alignment, uint32 flags) 473 { 474 aperture_memory *memory = new(std::nothrow) aperture_memory; 475 if (memory == NULL) 476 return NULL; 477 478 status_t status = _Insert(memory, size, alignment, flags); 479 if (status < B_OK) { 480 // did not find a free space large for this memory object 481 delete memory; 482 return NULL; 483 } 484 485 TRACE("create memory %p, base %lx, size %lx, flags %lx\n", memory, 486 memory->base, memory->size, flags); 487 488 memory->flags = flags; 489 #if defined(__HAIKU__) && !defined(GART_TEST) 490 memory->pages = NULL; 491 #else 492 memory->area = -1; 493 #endif 494 495 fHashTable.Insert(memory); 496 return memory; 497 } 498 499 500 bool 501 Aperture::_AdaptToReserved(addr_t &base, size_t &size, int32 *_offset) 502 { 503 addr_t reservedEnd = fInfo.base + fInfo.reserved_size; 504 if (reservedEnd <= base) 505 return false; 506 507 if (reservedEnd >= base + size) { 508 size = 0; 509 return true; 510 } 511 512 if (_offset != NULL) 513 *_offset = reservedEnd - base; 514 515 size -= reservedEnd - base; 516 base = reservedEnd; 517 return true; 518 } 519 520 521 status_t 522 Aperture::AllocateMemory(aperture_memory *memory, uint32 flags) 523 { 524 // We don't need to allocate reserved memory - it's 525 // already there for us to use 526 addr_t base = memory->base; 527 size_t size = memory->size; 528 if (_AdaptToReserved(base, size)) { 529 if (size == 0) { 530 TRACE("allocation is made of reserved memory\n"); 531 return B_OK; 532 } 533 534 memset((void *)memory->base, 0, memory->size - size); 535 } 536 TRACE("allocate %ld bytes out of %ld\n", size, memory->size); 537 538 #if defined(__HAIKU__) && !defined(GART_TEST) 539 uint32 count = size / B_PAGE_SIZE; 540 541 if ((flags & B_APERTURE_NEED_PHYSICAL) != 0) { 542 physical_address_restrictions restrictions = {}; 543 memory->page = vm_page_allocate_page_run( 544 PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR, count, &restrictions, 545 VM_PRIORITY_SYSTEM); 546 if (memory->page == NULL) 547 return B_NO_MEMORY; 548 } else { 549 // Allocate table to hold the pages 550 memory->pages = (vm_page **)malloc(count * sizeof(vm_page *)); 551 if (memory->pages == NULL) 552 return B_NO_MEMORY; 553 554 vm_page_reservation reservation; 555 vm_page_reserve_pages(&reservation, count, VM_PRIORITY_SYSTEM); 556 for (uint32 i = 0; i < count; i++) { 557 memory->pages[i] = vm_page_allocate_page(&reservation, 558 PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR); 559 } 560 vm_page_unreserve_pages(&reservation); 561 } 562 563 #ifdef DEBUG_PAGE_ACCESS 564 memory->allocating_thread = find_thread(NULL); 565 #endif 566 567 #else 568 void *address; 569 memory->area = create_area("GART memory", &address, B_ANY_KERNEL_ADDRESS, 570 size, B_FULL_LOCK | ((flags & B_APERTURE_NEED_PHYSICAL) != 0 571 ? B_CONTIGUOUS : 0), 0); 572 if (memory->area < B_OK) 573 return B_NO_MEMORY; 574 #endif 575 576 memory->flags |= ALLOCATED_APERTURE; 577 return B_OK; 578 } 579 580 581 status_t 582 Aperture::UnbindMemory(aperture_memory *memory) 583 { 584 if ((memory->flags & BIND_APERTURE) == 0) 585 return B_BAD_VALUE; 586 587 // We must not unbind reserved memory 588 addr_t base = memory->base; 589 size_t size = memory->size; 590 if (_AdaptToReserved(base, size) && size == 0) { 591 memory->flags &= ~BIND_APERTURE; 592 return B_OK; 593 } 594 595 addr_t start = base - Base(); 596 TRACE("unbind %ld bytes at %lx\n", size, start); 597 598 for (addr_t offset = 0; offset < memory->size; offset += B_PAGE_SIZE) { 599 status_t status = fModule->unbind_page(fPrivateAperture, start + offset); 600 if (status < B_OK) 601 return status; 602 } 603 604 memory->flags &= ~BIND_APERTURE; 605 fModule->flush_tlbs(fPrivateAperture); 606 return B_OK; 607 } 608 609 610 status_t 611 Aperture::BindMemory(aperture_memory *memory, addr_t address, size_t size) 612 { 613 bool physical = false; 614 615 if ((memory->flags & ALLOCATED_APERTURE) != 0) { 616 // We allocated this memory, get the base and size from there 617 #ifdef __HAIKU__ 618 size = memory->size; 619 physical = true; 620 #else 621 status_t status = get_area_base_and_size(memory->area, address, size); 622 if (status < B_OK) 623 return status; 624 #endif 625 } 626 627 // We don't need to bind reserved memory 628 addr_t base = memory->base; 629 int32 offset; 630 if (_AdaptToReserved(base, size, &offset)) { 631 if (size == 0) { 632 TRACE("reserved memory already bound\n"); 633 memory->flags |= BIND_APERTURE; 634 return B_OK; 635 } 636 637 address += offset; 638 } 639 640 addr_t start = base - Base(); 641 TRACE("bind %ld bytes at %lx\n", size, base); 642 643 for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) { 644 phys_addr_t physicalAddress = 0; 645 status_t status; 646 647 if (!physical) { 648 physical_entry entry; 649 status = get_memory_map((void *)(address + offset), B_PAGE_SIZE, 650 &entry, 1); 651 if (status < B_OK) 652 return status; 653 654 physicalAddress = entry.address; 655 } else { 656 #ifdef __HAIKU__ 657 uint32 index = offset >> PAGE_SHIFT; 658 vm_page *page; 659 if ((memory->flags & B_APERTURE_NEED_PHYSICAL) != 0) 660 page = memory->page + index; 661 else 662 page = memory->pages[index]; 663 664 physicalAddress 665 = (phys_addr_t)page->physical_page_number << PAGE_SHIFT; 666 #endif 667 } 668 669 status = fModule->bind_page(fPrivateAperture, start + offset, 670 physicalAddress); 671 if (status < B_OK) 672 return status; 673 } 674 675 memory->flags |= BIND_APERTURE; 676 fModule->flush_tlbs(fPrivateAperture); 677 return B_OK; 678 } 679 680 681 void 682 Aperture::_Free(aperture_memory *memory) 683 { 684 if ((memory->flags & ALLOCATED_APERTURE) == 0) 685 return; 686 687 #if defined(__HAIKU__) && !defined(GART_TEST) 688 // Remove the stolen area from the allocation 689 size_t size = memory->size; 690 addr_t reservedEnd = fInfo.base + fInfo.reserved_size; 691 if (memory->base < reservedEnd) 692 size -= reservedEnd - memory->base; 693 694 // Free previously allocated pages and page table 695 uint32 count = size / B_PAGE_SIZE; 696 697 if ((memory->flags & B_APERTURE_NEED_PHYSICAL) != 0) { 698 vm_page *page = memory->page; 699 for (uint32 i = 0; i < count; i++, page++) { 700 DEBUG_PAGE_ACCESS_TRANSFER(page, memory->allocating_thread); 701 vm_page_set_state(page, PAGE_STATE_FREE); 702 } 703 704 memory->page = NULL; 705 } else { 706 for (uint32 i = 0; i < count; i++) { 707 DEBUG_PAGE_ACCESS_TRANSFER(memory->pages[i], 708 memory->allocating_thread); 709 vm_page_set_state(memory->pages[i], PAGE_STATE_FREE); 710 } 711 712 free(memory->pages); 713 memory->pages = NULL; 714 } 715 #else 716 delete_area(memory->area); 717 memory->area = -1; 718 #endif 719 720 memory->flags &= ~ALLOCATED_APERTURE; 721 } 722 723 724 void 725 Aperture::_Remove(aperture_memory *memory) 726 { 727 aperture_memory *current = fFirstMemory, *last = NULL; 728 729 while (current != NULL) { 730 if (memory == current) { 731 if (last != NULL) { 732 last->next = current->next; 733 } else { 734 fFirstMemory = current->next; 735 } 736 break; 737 } 738 739 last = current; 740 current = current->next; 741 } 742 } 743 744 745 status_t 746 Aperture::_Insert(aperture_memory *memory, size_t size, size_t alignment, 747 uint32 flags) 748 { 749 aperture_memory *last = NULL; 750 aperture_memory *next; 751 bool foundSpot = false; 752 753 // do some sanity checking 754 if (size == 0 || size > fInfo.size) 755 return B_BAD_VALUE; 756 757 if (alignment < B_PAGE_SIZE) 758 alignment = B_PAGE_SIZE; 759 760 addr_t start = fInfo.base; 761 if ((flags & (B_APERTURE_NON_RESERVED | B_APERTURE_NEED_PHYSICAL)) != 0) 762 start += fInfo.reserved_size; 763 764 start = ROUNDUP(start, alignment); 765 if (start > fInfo.base - 1 + fInfo.size || start < fInfo.base) 766 return B_NO_MEMORY; 767 768 // walk up to the spot where we should start searching 769 770 next = fFirstMemory; 771 while (next) { 772 if (next->base >= start + size) { 773 // we have a winner 774 break; 775 } 776 last = next; 777 next = next->next; 778 } 779 780 // find a big enough hole 781 if (last == NULL) { 782 // see if we can build it at the beginning of the virtual map 783 if (next == NULL || (next->base >= ROUNDUP(start, alignment) + size)) { 784 memory->base = ROUNDUP(start, alignment); 785 foundSpot = true; 786 } else { 787 last = next; 788 next = next->next; 789 } 790 } 791 792 if (!foundSpot) { 793 // keep walking 794 while (next != NULL) { 795 if (next->base >= ROUNDUP(last->base + last->size, alignment) + size) { 796 // we found a spot (it'll be filled up below) 797 break; 798 } 799 last = next; 800 next = next->next; 801 } 802 803 if ((fInfo.base + (fInfo.size - 1)) >= (ROUNDUP(last->base + last->size, 804 alignment) + (size - 1))) { 805 // got a spot 806 foundSpot = true; 807 memory->base = ROUNDUP(last->base + last->size, alignment); 808 if (memory->base < start) 809 memory->base = start; 810 } 811 812 if (!foundSpot) 813 return B_NO_MEMORY; 814 } 815 816 memory->size = size; 817 if (last) { 818 memory->next = last->next; 819 last->next = memory; 820 } else { 821 memory->next = fFirstMemory; 822 fFirstMemory = memory; 823 } 824 825 return B_OK; 826 } 827 828 829 // #pragma mark - AGP module interface 830 831 832 status_t 833 get_nth_agp_info(uint32 index, agp_info *info) 834 { 835 TRACE("get_nth_agp_info(index %lu)\n", index); 836 837 if (index >= sDeviceCount) 838 return B_BAD_VALUE; 839 840 // refresh from the contents of the AGP registers from this device 841 sDeviceInfos[index].info.interface.status = get_pci_config( 842 sDeviceInfos[index].info, AGP_STATUS(sDeviceInfos[index].address), 4); 843 sDeviceInfos[index].info.interface.command = get_pci_config( 844 sDeviceInfos[index].info, AGP_COMMAND(sDeviceInfos[index].address), 4); 845 846 *info = sDeviceInfos[index].info; 847 return B_OK; 848 } 849 850 851 status_t 852 acquire_agp(void) 853 { 854 if (atomic_or(&sAcquired, 1) == 1) 855 return B_BUSY; 856 857 return B_OK; 858 } 859 860 861 void 862 release_agp(void) 863 { 864 atomic_and(&sAcquired, 0); 865 } 866 867 868 uint32 869 set_agp_mode(uint32 command) 870 { 871 TRACE("set_agp_mode(command %lx)\n", command); 872 873 if ((command & AGP_ENABLE) == 0) { 874 set_pci_mode(); 875 return 0; 876 } 877 878 // Make sure we accept all modes lower than requested one and we 879 // reset reserved bits 880 command = fix_rate_support(command); 881 882 // iterate through our device list to find the common capabilities supported 883 for (uint32 index = 0; index < sDeviceCount; index++) { 884 agp_device_info &deviceInfo = sDeviceInfos[index]; 885 886 // Refresh from the contents of the AGP capability registers 887 // (note: some graphics driver may have been tweaking, like nvidia) 888 deviceInfo.info.interface.status = get_pci_config(deviceInfo.info, 889 AGP_STATUS(deviceInfo.address), 4); 890 891 check_capabilities(deviceInfo, command); 892 } 893 894 command = fix_rate_command(command); 895 TRACE("set AGP command %lx on all capable devices.\n", command); 896 897 // The order of programming differs for enabling/disabling AGP mode 898 // (see AGP specification) 899 900 // First program all bridges (master) 901 902 for (uint32 index = 0; index < sDeviceCount; index++) { 903 agp_device_info &deviceInfo = sDeviceInfos[index]; 904 if (deviceInfo.info.class_base != PCI_bridge) 905 continue; 906 907 set_agp_command(deviceInfo, command); 908 } 909 910 // Wait 10mS for the bridges to recover (failsafe, see set_pci_mode()!) 911 snooze(10000); 912 913 // Then all graphics cards (target) 914 915 for (uint32 index = 0; index < sDeviceCount; index++) { 916 agp_device_info &deviceInfo = sDeviceInfos[index]; 917 if (deviceInfo.info.class_base != PCI_display) 918 continue; 919 920 set_agp_command(deviceInfo, command); 921 } 922 923 return command; 924 } 925 926 927 // #pragma mark - GART module interface 928 929 930 static aperture_id 931 map_aperture(uint8 bus, uint8 device, uint8 function, size_t size, 932 addr_t *_apertureBase) 933 { 934 void *iterator = open_module_list("busses/agp_gart"); 935 status_t status = B_ENTRY_NOT_FOUND; 936 Aperture *aperture = NULL; 937 938 Autolock _(sLock); 939 940 while (true) { 941 char name[256]; 942 size_t nameLength = sizeof(name); 943 if (read_next_module_name(iterator, name, &nameLength) != B_OK) 944 break; 945 946 agp_gart_bus_module_info *module; 947 if (get_module(name, (module_info **)&module) == B_OK) { 948 void *privateAperture; 949 status = module->create_aperture(bus, device, function, size, 950 &privateAperture); 951 if (status < B_OK) { 952 put_module(name); 953 continue; 954 } 955 956 aperture = new(std::nothrow) Aperture(module, privateAperture); 957 status = aperture->InitCheck(); 958 if (status == B_OK) { 959 if (_apertureBase != NULL) 960 *_apertureBase = aperture->Base(); 961 962 sApertureHashTable.Insert(aperture); 963 } else { 964 delete aperture; 965 aperture = NULL; 966 } 967 break; 968 } 969 } 970 971 close_module_list(iterator); 972 return aperture != NULL ? aperture->ID() : status; 973 } 974 975 976 static aperture_id 977 map_custom_aperture(gart_bus_module_info *module, addr_t *_apertureBase) 978 { 979 return B_ERROR; 980 } 981 982 983 static status_t 984 unmap_aperture(aperture_id id) 985 { 986 Autolock _(sLock); 987 Aperture *aperture = sApertureHashTable.Lookup(id); 988 if (aperture == NULL) 989 return B_ENTRY_NOT_FOUND; 990 991 sApertureHashTable.Remove(aperture); 992 delete aperture; 993 return B_OK; 994 } 995 996 997 static status_t 998 get_aperture_info(aperture_id id, aperture_info *info) 999 { 1000 Aperture *aperture = get_aperture(id); 1001 if (aperture == NULL) 1002 return B_ENTRY_NOT_FOUND; 1003 1004 Autolock _(aperture->Lock()); 1005 return aperture->GetInfo(info); 1006 } 1007 1008 1009 static status_t 1010 allocate_memory(aperture_id id, size_t size, size_t alignment, uint32 flags, 1011 addr_t *_apertureBase, phys_addr_t *_physicalBase) 1012 { 1013 if ((flags & ~APERTURE_PUBLIC_FLAGS_MASK) != 0 || _apertureBase == NULL) 1014 return B_BAD_VALUE; 1015 1016 Aperture *aperture = get_aperture(id); 1017 if (aperture == NULL) 1018 return B_ENTRY_NOT_FOUND; 1019 1020 size = ROUNDUP(size, B_PAGE_SIZE); 1021 1022 Autolock _(aperture->Lock()); 1023 1024 aperture_memory *memory = aperture->CreateMemory(size, alignment, flags); 1025 if (memory == NULL) 1026 return B_NO_MEMORY; 1027 1028 status_t status = aperture->AllocateMemory(memory, flags); 1029 if (status == B_OK) 1030 status = aperture->BindMemory(memory, 0, 0); 1031 if (status < B_OK) { 1032 aperture->DeleteMemory(memory); 1033 return status; 1034 } 1035 1036 if (_physicalBase != NULL && (flags & B_APERTURE_NEED_PHYSICAL) != 0) { 1037 #if defined(__HAIKU__) && !defined(GART_TEST) 1038 *_physicalBase 1039 = (phys_addr_t)memory->page->physical_page_number * B_PAGE_SIZE; 1040 #else 1041 physical_entry entry; 1042 status = get_memory_map((void *)memory->base, B_PAGE_SIZE, &entry, 1); 1043 if (status < B_OK) { 1044 aperture->DeleteMemory(memory); 1045 return status; 1046 } 1047 1048 *_physicalBase = entry.address; 1049 #endif 1050 } 1051 1052 *_apertureBase = memory->base; 1053 return B_OK; 1054 } 1055 1056 1057 static status_t 1058 free_memory(aperture_id id, addr_t base) 1059 { 1060 Aperture *aperture = get_aperture(id); 1061 if (aperture == NULL) 1062 return B_ENTRY_NOT_FOUND; 1063 1064 Autolock _(aperture->Lock()); 1065 aperture_memory *memory = aperture->GetMemory(base); 1066 if (memory == NULL) 1067 return B_BAD_VALUE; 1068 1069 aperture->DeleteMemory(memory); 1070 return B_OK; 1071 } 1072 1073 1074 static status_t 1075 reserve_aperture(aperture_id id, size_t size, addr_t *_apertureBase) 1076 { 1077 Aperture *aperture = get_aperture(id); 1078 if (aperture == NULL) 1079 return B_ENTRY_NOT_FOUND; 1080 1081 return B_ERROR; 1082 } 1083 1084 1085 static status_t 1086 unreserve_aperture(aperture_id id, addr_t apertureBase) 1087 { 1088 Aperture *aperture = get_aperture(id); 1089 if (aperture == NULL) 1090 return B_ENTRY_NOT_FOUND; 1091 1092 return B_ERROR; 1093 } 1094 1095 1096 static status_t 1097 bind_aperture(aperture_id id, area_id area, addr_t base, size_t size, 1098 size_t alignment, addr_t reservedBase, addr_t *_apertureBase) 1099 { 1100 Aperture *aperture = get_aperture(id); 1101 if (aperture == NULL) 1102 return B_ENTRY_NOT_FOUND; 1103 1104 if (area < 0) { 1105 if (size == 0 || size > aperture->Size() 1106 || (base & (B_PAGE_SIZE - 1)) != 0 1107 || base == 0) 1108 return B_BAD_VALUE; 1109 1110 size = ROUNDUP(size, B_PAGE_SIZE); 1111 } 1112 1113 if (area >= 0) { 1114 status_t status = get_area_base_and_size(area, base, size); 1115 if (status < B_OK) 1116 return status; 1117 } 1118 1119 Autolock _(aperture->Lock()); 1120 aperture_memory *memory = NULL; 1121 if (reservedBase != 0) { 1122 // use reserved aperture to bind the pages 1123 memory = aperture->GetMemory(reservedBase); 1124 if (memory == NULL) 1125 return B_BAD_VALUE; 1126 } else { 1127 // create new memory object 1128 memory = aperture->CreateMemory(size, alignment, 1129 B_APERTURE_NON_RESERVED); 1130 if (memory == NULL) 1131 return B_NO_MEMORY; 1132 } 1133 1134 // just bind the physical pages backing the memory into the GART 1135 1136 status_t status = aperture->BindMemory(memory, base, size); 1137 if (status < B_OK) { 1138 if (reservedBase < 0) 1139 aperture->DeleteMemory(memory); 1140 1141 return status; 1142 } 1143 1144 if (_apertureBase != NULL) 1145 *_apertureBase = memory->base; 1146 1147 return B_OK; 1148 } 1149 1150 1151 static status_t 1152 unbind_aperture(aperture_id id, addr_t base) 1153 { 1154 Aperture *aperture = get_aperture(id); 1155 if (aperture == NULL) 1156 return B_ENTRY_NOT_FOUND; 1157 1158 Autolock _(aperture->Lock()); 1159 aperture_memory *memory = aperture->GetMemory(base); 1160 if (memory == NULL || (memory->flags & BIND_APERTURE) == 0) 1161 return B_BAD_VALUE; 1162 1163 if ((memory->flags & ALLOCATED_APERTURE) != 0) 1164 panic("unbind memory %lx (%p) allocated by agp_gart.", base, memory); 1165 1166 status_t status = aperture->UnbindMemory(memory); 1167 if (status < B_OK) 1168 return status; 1169 1170 if ((memory->flags & RESERVED_APERTURE) == 0) 1171 aperture->DeleteMemory(memory); 1172 1173 return B_OK; 1174 } 1175 1176 1177 // #pragma mark - 1178 1179 1180 static status_t 1181 agp_init(void) 1182 { 1183 TRACE("bus manager init\n"); 1184 1185 if (get_module(B_PCI_MODULE_NAME, (module_info **)&sPCI) != B_OK) 1186 return B_ERROR; 1187 1188 uint32 cookie = 0; 1189 sDeviceCount = 0; 1190 pci_info info; 1191 while (get_next_agp_device(&cookie, info, sDeviceInfos[sDeviceCount]) 1192 == B_OK) { 1193 sDeviceCount++; 1194 } 1195 1196 TRACE("found %ld AGP devices\n", sDeviceCount); 1197 1198 // Since there can be custom aperture modules (for memory management only), 1199 // we always succeed if we could get the resources we need. 1200 1201 new(&sApertureHashTable) ApertureHashTable(); 1202 return init_lock(&sLock, "agp_gart"); 1203 } 1204 1205 1206 void 1207 agp_uninit(void) 1208 { 1209 TRACE("bus manager uninit\n"); 1210 1211 ApertureHashTable::Iterator iterator = sApertureHashTable.GetIterator(); 1212 while (iterator.HasNext()) { 1213 Aperture *aperture = iterator.Next(); 1214 sApertureHashTable.Remove(aperture); 1215 delete aperture; 1216 } 1217 1218 put_module(B_PCI_MODULE_NAME); 1219 } 1220 1221 1222 static int32 1223 agp_std_ops(int32 op, ...) 1224 { 1225 switch (op) { 1226 case B_MODULE_INIT: 1227 return agp_init(); 1228 case B_MODULE_UNINIT: 1229 agp_uninit(); 1230 return B_OK; 1231 } 1232 1233 return B_BAD_VALUE; 1234 } 1235 1236 1237 static struct agp_gart_module_info sAGPModuleInfo = { 1238 { 1239 { 1240 B_AGP_GART_MODULE_NAME, 1241 B_KEEP_LOADED, // Keep loaded, even if no driver requires it 1242 agp_std_ops 1243 }, 1244 NULL // the rescan function 1245 }, 1246 get_nth_agp_info, 1247 acquire_agp, 1248 release_agp, 1249 set_agp_mode, 1250 1251 map_aperture, 1252 map_custom_aperture, 1253 unmap_aperture, 1254 get_aperture_info, 1255 allocate_memory, 1256 free_memory, 1257 reserve_aperture, 1258 unreserve_aperture, 1259 bind_aperture, 1260 unbind_aperture, 1261 }; 1262 1263 module_info *modules[] = { 1264 (module_info *)&sAGPModuleInfo, 1265 NULL 1266 }; 1267