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