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