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 memory->page = vm_page_allocate_page_run( 543 PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR, 0, count, 544 VM_PRIORITY_SYSTEM); 545 if (memory->page == NULL) 546 return B_NO_MEMORY; 547 } else { 548 // Allocate table to hold the pages 549 memory->pages = (vm_page **)malloc(count * sizeof(vm_page *)); 550 if (memory->pages == NULL) 551 return B_NO_MEMORY; 552 553 vm_page_reservation reservation; 554 vm_page_reserve_pages(&reservation, count, VM_PRIORITY_SYSTEM); 555 for (uint32 i = 0; i < count; i++) { 556 memory->pages[i] = vm_page_allocate_page(&reservation, 557 PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR); 558 } 559 vm_page_unreserve_pages(&reservation); 560 } 561 562 #ifdef DEBUG_PAGE_ACCESS 563 memory->allocating_thread = find_thread(NULL); 564 #endif 565 566 #else 567 void *address; 568 memory->area = create_area("GART memory", &address, B_ANY_KERNEL_ADDRESS, 569 size, B_FULL_LOCK | ((flags & B_APERTURE_NEED_PHYSICAL) != 0 570 ? B_CONTIGUOUS : 0), 0); 571 if (memory->area < B_OK) 572 return B_NO_MEMORY; 573 #endif 574 575 memory->flags |= ALLOCATED_APERTURE; 576 return B_OK; 577 } 578 579 580 status_t 581 Aperture::UnbindMemory(aperture_memory *memory) 582 { 583 if ((memory->flags & BIND_APERTURE) == 0) 584 return B_BAD_VALUE; 585 586 // We must not unbind reserved memory 587 addr_t base = memory->base; 588 size_t size = memory->size; 589 if (_AdaptToReserved(base, size) && size == 0) { 590 memory->flags &= ~BIND_APERTURE; 591 return B_OK; 592 } 593 594 addr_t start = base - Base(); 595 TRACE("unbind %ld bytes at %lx\n", size, start); 596 597 for (addr_t offset = 0; offset < memory->size; offset += B_PAGE_SIZE) { 598 status_t status = fModule->unbind_page(fPrivateAperture, start + offset); 599 if (status < B_OK) 600 return status; 601 } 602 603 memory->flags &= ~BIND_APERTURE; 604 fModule->flush_tlbs(fPrivateAperture); 605 return B_OK; 606 } 607 608 609 status_t 610 Aperture::BindMemory(aperture_memory *memory, addr_t address, size_t size) 611 { 612 bool physical = false; 613 614 if ((memory->flags & ALLOCATED_APERTURE) != 0) { 615 // We allocated this memory, get the base and size from there 616 #ifdef __HAIKU__ 617 size = memory->size; 618 physical = true; 619 #else 620 status_t status = get_area_base_and_size(memory->area, address, size); 621 if (status < B_OK) 622 return status; 623 #endif 624 } 625 626 // We don't need to bind reserved memory 627 addr_t base = memory->base; 628 int32 offset; 629 if (_AdaptToReserved(base, size, &offset)) { 630 if (size == 0) { 631 TRACE("reserved memory already bound\n"); 632 memory->flags |= BIND_APERTURE; 633 return B_OK; 634 } 635 636 address += offset; 637 } 638 639 addr_t start = base - Base(); 640 TRACE("bind %ld bytes at %lx\n", size, base); 641 642 for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) { 643 phys_addr_t physicalAddress = 0; 644 status_t status; 645 646 if (!physical) { 647 physical_entry entry; 648 status = get_memory_map((void *)(address + offset), B_PAGE_SIZE, 649 &entry, 1); 650 if (status < B_OK) 651 return status; 652 653 physicalAddress = entry.address; 654 } else { 655 #ifdef __HAIKU__ 656 uint32 index = offset >> PAGE_SHIFT; 657 vm_page *page; 658 if ((memory->flags & B_APERTURE_NEED_PHYSICAL) != 0) 659 page = memory->page + index; 660 else 661 page = memory->pages[index]; 662 663 physicalAddress 664 = (phys_addr_t)page->physical_page_number << PAGE_SHIFT; 665 #endif 666 } 667 668 status = fModule->bind_page(fPrivateAperture, start + offset, 669 physicalAddress); 670 if (status < B_OK) 671 return status; 672 } 673 674 memory->flags |= BIND_APERTURE; 675 fModule->flush_tlbs(fPrivateAperture); 676 return B_OK; 677 } 678 679 680 void 681 Aperture::_Free(aperture_memory *memory) 682 { 683 if ((memory->flags & ALLOCATED_APERTURE) == 0) 684 return; 685 686 #if defined(__HAIKU__) && !defined(GART_TEST) 687 // Remove the stolen area from the allocation 688 size_t size = memory->size; 689 addr_t reservedEnd = fInfo.base + fInfo.reserved_size; 690 if (memory->base < reservedEnd) 691 size -= reservedEnd - memory->base; 692 693 // Free previously allocated pages and page table 694 uint32 count = size / B_PAGE_SIZE; 695 696 if ((memory->flags & B_APERTURE_NEED_PHYSICAL) != 0) { 697 vm_page *page = memory->page; 698 for (uint32 i = 0; i < count; i++, page++) { 699 DEBUG_PAGE_ACCESS_TRANSFER(page, memory->allocating_thread); 700 vm_page_set_state(page, PAGE_STATE_FREE); 701 } 702 703 memory->page = NULL; 704 } else { 705 for (uint32 i = 0; i < count; i++) { 706 DEBUG_PAGE_ACCESS_TRANSFER(memory->pages[i], 707 memory->allocating_thread); 708 vm_page_set_state(memory->pages[i], PAGE_STATE_FREE); 709 } 710 711 free(memory->pages); 712 memory->pages = NULL; 713 } 714 #else 715 delete_area(memory->area); 716 memory->area = -1; 717 #endif 718 719 memory->flags &= ~ALLOCATED_APERTURE; 720 } 721 722 723 void 724 Aperture::_Remove(aperture_memory *memory) 725 { 726 aperture_memory *current = fFirstMemory, *last = NULL; 727 728 while (current != NULL) { 729 if (memory == current) { 730 if (last != NULL) { 731 last->next = current->next; 732 } else { 733 fFirstMemory = current->next; 734 } 735 break; 736 } 737 738 last = current; 739 current = current->next; 740 } 741 } 742 743 744 status_t 745 Aperture::_Insert(aperture_memory *memory, size_t size, size_t alignment, 746 uint32 flags) 747 { 748 aperture_memory *last = NULL; 749 aperture_memory *next; 750 bool foundSpot = false; 751 752 // do some sanity checking 753 if (size == 0 || size > fInfo.size) 754 return B_BAD_VALUE; 755 756 if (alignment < B_PAGE_SIZE) 757 alignment = B_PAGE_SIZE; 758 759 addr_t start = fInfo.base; 760 if ((flags & (B_APERTURE_NON_RESERVED | B_APERTURE_NEED_PHYSICAL)) != 0) 761 start += fInfo.reserved_size; 762 763 start = ROUNDUP(start, alignment); 764 if (start > fInfo.base - 1 + fInfo.size || start < fInfo.base) 765 return B_NO_MEMORY; 766 767 // walk up to the spot where we should start searching 768 769 next = fFirstMemory; 770 while (next) { 771 if (next->base >= start + size) { 772 // we have a winner 773 break; 774 } 775 last = next; 776 next = next->next; 777 } 778 779 // find a big enough hole 780 if (last == NULL) { 781 // see if we can build it at the beginning of the virtual map 782 if (next == NULL || (next->base >= ROUNDUP(start, alignment) + size)) { 783 memory->base = ROUNDUP(start, alignment); 784 foundSpot = true; 785 } else { 786 last = next; 787 next = next->next; 788 } 789 } 790 791 if (!foundSpot) { 792 // keep walking 793 while (next != NULL) { 794 if (next->base >= ROUNDUP(last->base + last->size, alignment) + size) { 795 // we found a spot (it'll be filled up below) 796 break; 797 } 798 last = next; 799 next = next->next; 800 } 801 802 if ((fInfo.base + (fInfo.size - 1)) >= (ROUNDUP(last->base + last->size, 803 alignment) + (size - 1))) { 804 // got a spot 805 foundSpot = true; 806 memory->base = ROUNDUP(last->base + last->size, alignment); 807 if (memory->base < start) 808 memory->base = start; 809 } 810 811 if (!foundSpot) 812 return B_NO_MEMORY; 813 } 814 815 memory->size = size; 816 if (last) { 817 memory->next = last->next; 818 last->next = memory; 819 } else { 820 memory->next = fFirstMemory; 821 fFirstMemory = memory; 822 } 823 824 return B_OK; 825 } 826 827 828 // #pragma mark - AGP module interface 829 830 831 status_t 832 get_nth_agp_info(uint32 index, agp_info *info) 833 { 834 TRACE("get_nth_agp_info(index %lu)\n", index); 835 836 if (index >= sDeviceCount) 837 return B_BAD_VALUE; 838 839 // refresh from the contents of the AGP registers from this device 840 sDeviceInfos[index].info.interface.status = get_pci_config( 841 sDeviceInfos[index].info, AGP_STATUS(sDeviceInfos[index].address), 4); 842 sDeviceInfos[index].info.interface.command = get_pci_config( 843 sDeviceInfos[index].info, AGP_COMMAND(sDeviceInfos[index].address), 4); 844 845 *info = sDeviceInfos[index].info; 846 return B_OK; 847 } 848 849 850 status_t 851 acquire_agp(void) 852 { 853 if (atomic_or(&sAcquired, 1) == 1) 854 return B_BUSY; 855 856 return B_OK; 857 } 858 859 860 void 861 release_agp(void) 862 { 863 atomic_and(&sAcquired, 0); 864 } 865 866 867 uint32 868 set_agp_mode(uint32 command) 869 { 870 TRACE("set_agp_mode(command %lx)\n", command); 871 872 if ((command & AGP_ENABLE) == 0) { 873 set_pci_mode(); 874 return 0; 875 } 876 877 // Make sure we accept all modes lower than requested one and we 878 // reset reserved bits 879 command = fix_rate_support(command); 880 881 // iterate through our device list to find the common capabilities supported 882 for (uint32 index = 0; index < sDeviceCount; index++) { 883 agp_device_info &deviceInfo = sDeviceInfos[index]; 884 885 // Refresh from the contents of the AGP capability registers 886 // (note: some graphics driver may have been tweaking, like nvidia) 887 deviceInfo.info.interface.status = get_pci_config(deviceInfo.info, 888 AGP_STATUS(deviceInfo.address), 4); 889 890 check_capabilities(deviceInfo, command); 891 } 892 893 command = fix_rate_command(command); 894 TRACE("set AGP command %lx on all capable devices.\n", command); 895 896 // The order of programming differs for enabling/disabling AGP mode 897 // (see AGP specification) 898 899 // First program all bridges (master) 900 901 for (uint32 index = 0; index < sDeviceCount; index++) { 902 agp_device_info &deviceInfo = sDeviceInfos[index]; 903 if (deviceInfo.info.class_base != PCI_bridge) 904 continue; 905 906 set_agp_command(deviceInfo, command); 907 } 908 909 // Wait 10mS for the bridges to recover (failsafe, see set_pci_mode()!) 910 snooze(10000); 911 912 // Then all graphics cards (target) 913 914 for (uint32 index = 0; index < sDeviceCount; index++) { 915 agp_device_info &deviceInfo = sDeviceInfos[index]; 916 if (deviceInfo.info.class_base != PCI_display) 917 continue; 918 919 set_agp_command(deviceInfo, command); 920 } 921 922 return command; 923 } 924 925 926 // #pragma mark - GART module interface 927 928 929 static aperture_id 930 map_aperture(uint8 bus, uint8 device, uint8 function, size_t size, 931 addr_t *_apertureBase) 932 { 933 void *iterator = open_module_list("busses/agp_gart"); 934 status_t status = B_ENTRY_NOT_FOUND; 935 Aperture *aperture = NULL; 936 937 Autolock _(sLock); 938 939 while (true) { 940 char name[256]; 941 size_t nameLength = sizeof(name); 942 if (read_next_module_name(iterator, name, &nameLength) != B_OK) 943 break; 944 945 agp_gart_bus_module_info *module; 946 if (get_module(name, (module_info **)&module) == B_OK) { 947 void *privateAperture; 948 status = module->create_aperture(bus, device, function, size, 949 &privateAperture); 950 if (status < B_OK) { 951 put_module(name); 952 continue; 953 } 954 955 aperture = new(std::nothrow) Aperture(module, privateAperture); 956 status = aperture->InitCheck(); 957 if (status == B_OK) { 958 if (_apertureBase != NULL) 959 *_apertureBase = aperture->Base(); 960 961 sApertureHashTable.Insert(aperture); 962 } else { 963 delete aperture; 964 aperture = NULL; 965 } 966 break; 967 } 968 } 969 970 close_module_list(iterator); 971 return aperture != NULL ? aperture->ID() : status; 972 } 973 974 975 static aperture_id 976 map_custom_aperture(gart_bus_module_info *module, addr_t *_apertureBase) 977 { 978 return B_ERROR; 979 } 980 981 982 static status_t 983 unmap_aperture(aperture_id id) 984 { 985 Autolock _(sLock); 986 Aperture *aperture = sApertureHashTable.Lookup(id); 987 if (aperture == NULL) 988 return B_ENTRY_NOT_FOUND; 989 990 sApertureHashTable.Remove(aperture); 991 delete aperture; 992 return B_OK; 993 } 994 995 996 static status_t 997 get_aperture_info(aperture_id id, aperture_info *info) 998 { 999 Aperture *aperture = get_aperture(id); 1000 if (aperture == NULL) 1001 return B_ENTRY_NOT_FOUND; 1002 1003 Autolock _(aperture->Lock()); 1004 return aperture->GetInfo(info); 1005 } 1006 1007 1008 static status_t 1009 allocate_memory(aperture_id id, size_t size, size_t alignment, uint32 flags, 1010 addr_t *_apertureBase, phys_addr_t *_physicalBase) 1011 { 1012 if ((flags & ~APERTURE_PUBLIC_FLAGS_MASK) != 0 || _apertureBase == NULL) 1013 return B_BAD_VALUE; 1014 1015 Aperture *aperture = get_aperture(id); 1016 if (aperture == NULL) 1017 return B_ENTRY_NOT_FOUND; 1018 1019 size = ROUNDUP(size, B_PAGE_SIZE); 1020 1021 Autolock _(aperture->Lock()); 1022 1023 aperture_memory *memory = aperture->CreateMemory(size, alignment, flags); 1024 if (memory == NULL) 1025 return B_NO_MEMORY; 1026 1027 status_t status = aperture->AllocateMemory(memory, flags); 1028 if (status == B_OK) 1029 status = aperture->BindMemory(memory, 0, 0); 1030 if (status < B_OK) { 1031 aperture->DeleteMemory(memory); 1032 return status; 1033 } 1034 1035 if (_physicalBase != NULL && (flags & B_APERTURE_NEED_PHYSICAL) != 0) { 1036 #if defined(__HAIKU__) && !defined(GART_TEST) 1037 *_physicalBase 1038 = (phys_addr_t)memory->page->physical_page_number * B_PAGE_SIZE; 1039 #else 1040 physical_entry entry; 1041 status = get_memory_map((void *)memory->base, B_PAGE_SIZE, &entry, 1); 1042 if (status < B_OK) { 1043 aperture->DeleteMemory(memory); 1044 return status; 1045 } 1046 1047 *_physicalBase = entry.address; 1048 #endif 1049 } 1050 1051 *_apertureBase = memory->base; 1052 return B_OK; 1053 } 1054 1055 1056 static status_t 1057 free_memory(aperture_id id, addr_t base) 1058 { 1059 Aperture *aperture = get_aperture(id); 1060 if (aperture == NULL) 1061 return B_ENTRY_NOT_FOUND; 1062 1063 Autolock _(aperture->Lock()); 1064 aperture_memory *memory = aperture->GetMemory(base); 1065 if (memory == NULL) 1066 return B_BAD_VALUE; 1067 1068 aperture->DeleteMemory(memory); 1069 return B_OK; 1070 } 1071 1072 1073 static status_t 1074 reserve_aperture(aperture_id id, size_t size, addr_t *_apertureBase) 1075 { 1076 Aperture *aperture = get_aperture(id); 1077 if (aperture == NULL) 1078 return B_ENTRY_NOT_FOUND; 1079 1080 return B_ERROR; 1081 } 1082 1083 1084 static status_t 1085 unreserve_aperture(aperture_id id, addr_t apertureBase) 1086 { 1087 Aperture *aperture = get_aperture(id); 1088 if (aperture == NULL) 1089 return B_ENTRY_NOT_FOUND; 1090 1091 return B_ERROR; 1092 } 1093 1094 1095 static status_t 1096 bind_aperture(aperture_id id, area_id area, addr_t base, size_t size, 1097 size_t alignment, addr_t reservedBase, addr_t *_apertureBase) 1098 { 1099 Aperture *aperture = get_aperture(id); 1100 if (aperture == NULL) 1101 return B_ENTRY_NOT_FOUND; 1102 1103 if (area < 0) { 1104 if (size == 0 || size > aperture->Size() 1105 || (base & (B_PAGE_SIZE - 1)) != 0 1106 || base == 0) 1107 return B_BAD_VALUE; 1108 1109 size = ROUNDUP(size, B_PAGE_SIZE); 1110 } 1111 1112 if (area >= 0) { 1113 status_t status = get_area_base_and_size(area, base, size); 1114 if (status < B_OK) 1115 return status; 1116 } 1117 1118 Autolock _(aperture->Lock()); 1119 aperture_memory *memory = NULL; 1120 if (reservedBase != 0) { 1121 // use reserved aperture to bind the pages 1122 memory = aperture->GetMemory(reservedBase); 1123 if (memory == NULL) 1124 return B_BAD_VALUE; 1125 } else { 1126 // create new memory object 1127 memory = aperture->CreateMemory(size, alignment, 1128 B_APERTURE_NON_RESERVED); 1129 if (memory == NULL) 1130 return B_NO_MEMORY; 1131 } 1132 1133 // just bind the physical pages backing the memory into the GART 1134 1135 status_t status = aperture->BindMemory(memory, base, size); 1136 if (status < B_OK) { 1137 if (reservedBase < 0) 1138 aperture->DeleteMemory(memory); 1139 1140 return status; 1141 } 1142 1143 if (_apertureBase != NULL) 1144 *_apertureBase = memory->base; 1145 1146 return B_OK; 1147 } 1148 1149 1150 static status_t 1151 unbind_aperture(aperture_id id, addr_t base) 1152 { 1153 Aperture *aperture = get_aperture(id); 1154 if (aperture == NULL) 1155 return B_ENTRY_NOT_FOUND; 1156 1157 Autolock _(aperture->Lock()); 1158 aperture_memory *memory = aperture->GetMemory(base); 1159 if (memory == NULL || (memory->flags & BIND_APERTURE) == 0) 1160 return B_BAD_VALUE; 1161 1162 if ((memory->flags & ALLOCATED_APERTURE) != 0) 1163 panic("unbind memory %lx (%p) allocated by agp_gart.", base, memory); 1164 1165 status_t status = aperture->UnbindMemory(memory); 1166 if (status < B_OK) 1167 return status; 1168 1169 if ((memory->flags & RESERVED_APERTURE) == 0) 1170 aperture->DeleteMemory(memory); 1171 1172 return B_OK; 1173 } 1174 1175 1176 // #pragma mark - 1177 1178 1179 static status_t 1180 agp_init(void) 1181 { 1182 TRACE("bus manager init\n"); 1183 1184 if (get_module(B_PCI_MODULE_NAME, (module_info **)&sPCI) != B_OK) 1185 return B_ERROR; 1186 1187 uint32 cookie = 0; 1188 sDeviceCount = 0; 1189 pci_info info; 1190 while (get_next_agp_device(&cookie, info, sDeviceInfos[sDeviceCount]) 1191 == B_OK) { 1192 sDeviceCount++; 1193 } 1194 1195 TRACE("found %ld AGP devices\n", sDeviceCount); 1196 1197 // Since there can be custom aperture modules (for memory management only), 1198 // we always succeed if we could get the resources we need. 1199 1200 new(&sApertureHashTable) ApertureHashTable(); 1201 return init_lock(&sLock, "agp_gart"); 1202 } 1203 1204 1205 void 1206 agp_uninit(void) 1207 { 1208 TRACE("bus manager uninit\n"); 1209 1210 ApertureHashTable::Iterator iterator = sApertureHashTable.GetIterator(); 1211 while (iterator.HasNext()) { 1212 Aperture *aperture = iterator.Next(); 1213 sApertureHashTable.Remove(aperture); 1214 delete aperture; 1215 } 1216 1217 put_module(B_PCI_MODULE_NAME); 1218 } 1219 1220 1221 static int32 1222 agp_std_ops(int32 op, ...) 1223 { 1224 switch (op) { 1225 case B_MODULE_INIT: 1226 return agp_init(); 1227 case B_MODULE_UNINIT: 1228 agp_uninit(); 1229 return B_OK; 1230 } 1231 1232 return B_BAD_VALUE; 1233 } 1234 1235 1236 static struct agp_gart_module_info sAGPModuleInfo = { 1237 { 1238 { 1239 B_AGP_GART_MODULE_NAME, 1240 B_KEEP_LOADED, // Keep loaded, even if no driver requires it 1241 agp_std_ops 1242 }, 1243 NULL // the rescan function 1244 }, 1245 get_nth_agp_info, 1246 acquire_agp, 1247 release_agp, 1248 set_agp_mode, 1249 1250 map_aperture, 1251 map_custom_aperture, 1252 unmap_aperture, 1253 get_aperture_info, 1254 allocate_memory, 1255 free_memory, 1256 reserve_aperture, 1257 unreserve_aperture, 1258 bind_aperture, 1259 unbind_aperture, 1260 }; 1261 1262 module_info *modules[] = { 1263 (module_info *)&sAGPModuleInfo, 1264 NULL 1265 }; 1266