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