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