1 /* 2 * Copyright 2003-2008, Marcus Overhagen. All rights reserved. 3 * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include <string.h> 10 #include <KernelExport.h> 11 #define __HAIKU_PCI_BUS_MANAGER_TESTING 1 12 #include <PCI.h> 13 14 #include "util/kernel_cpp.h" 15 #include "pci_fixup.h" 16 #include "pci_info.h" 17 #include "pci_private.h" 18 #include "pci.h" 19 20 #define TRACE_CAP(x...) dprintf(x) 21 #define FLOW(x...) 22 //#define FLOW(x...) dprintf(x) 23 24 25 PCI *gPCI; 26 27 28 // #pragma mark bus manager exports 29 30 31 status_t 32 pci_controller_add(pci_controller *controller, void *cookie) 33 { 34 return gPCI->AddController(controller, cookie); 35 } 36 37 38 long 39 pci_get_nth_pci_info(long index, pci_info *outInfo) 40 { 41 return gPCI->GetNthInfo(index, outInfo); 42 } 43 44 45 uint32 46 pci_read_config(uint8 virtualBus, uint8 device, uint8 function, uint16 offset, 47 uint8 size) 48 { 49 uint8 bus; 50 uint8 domain; 51 uint32 value; 52 53 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 54 return 0xffffffff; 55 56 if (gPCI->ReadConfig(domain, bus, device, function, offset, size, 57 &value) != B_OK) 58 return 0xffffffff; 59 60 return value; 61 } 62 63 64 void 65 pci_write_config(uint8 virtualBus, uint8 device, uint8 function, uint16 offset, 66 uint8 size, uint32 value) 67 { 68 uint8 bus; 69 uint8 domain; 70 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 71 return; 72 73 gPCI->WriteConfig(domain, bus, device, function, offset, size, value); 74 } 75 76 77 status_t 78 pci_find_capability(uint8 virtualBus, uint8 device, uint8 function, 79 uint8 capID, uint8 *offset) 80 { 81 uint8 bus; 82 uint8 domain; 83 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 84 return B_ERROR; 85 86 return gPCI->FindCapability(domain, bus, device, function, capID, offset); 87 } 88 89 90 status_t 91 pci_find_extended_capability(uint8 virtualBus, uint8 device, uint8 function, 92 uint16 capID, uint16 *offset) 93 { 94 uint8 bus; 95 uint8 domain; 96 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 97 return B_ERROR; 98 99 return gPCI->FindExtendedCapability(domain, bus, device, function, capID, 100 offset); 101 } 102 103 104 status_t 105 pci_reserve_device(uchar virtualBus, uchar device, uchar function, 106 const char *driverName, void *nodeCookie) 107 { 108 status_t status; 109 uint8 bus; 110 uint8 domain; 111 TRACE(("pci_reserve_device(%d, %d, %d, %s)\n", virtualBus, device, function, 112 driverName)); 113 114 /* 115 * we add 2 nodes to the PCI devices, one with constant attributes, 116 * so adding for another driver fails, and a subnode with the 117 * driver-provided informations. 118 */ 119 120 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 121 return B_ERROR; 122 123 //TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus, 124 // domain, bus, device, function, driverName, nodeCookie)); 125 126 device_attr matchPCIRoot[] = { 127 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "PCI"}}, 128 {NULL} 129 }; 130 device_attr matchThis[] = { 131 // info about device 132 {B_DEVICE_BUS, B_STRING_TYPE, {string: "pci"}}, 133 134 // location on PCI bus 135 {B_PCI_DEVICE_DOMAIN, B_UINT8_TYPE, {ui8: domain}}, 136 {B_PCI_DEVICE_BUS, B_UINT8_TYPE, {ui8: bus}}, 137 {B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {ui8: device}}, 138 {B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {ui8: function}}, 139 {NULL} 140 }; 141 device_attr legacyAttrs[] = { 142 // info about device 143 {B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}}, 144 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Legacy Driver Reservation"}}, 145 {NULL} 146 }; 147 device_attr drvAttrs[] = { 148 // info about device 149 {B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}}, 150 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: driverName}}, 151 {"legacy_driver", B_STRING_TYPE, {string: driverName}}, 152 {"legacy_driver_cookie", B_UINT64_TYPE, {ui64: (uint64)nodeCookie}}, 153 {NULL} 154 }; 155 device_node *root, *pci, *node, *legacy; 156 157 status = B_DEVICE_NOT_FOUND; 158 root = gDeviceManager->get_root_node(); 159 if (!root) 160 return status; 161 162 pci = NULL; 163 if (gDeviceManager->get_next_child_node(root, matchPCIRoot, &pci) < B_OK) 164 goto err0; 165 166 node = NULL; 167 if (gDeviceManager->get_next_child_node(pci, matchThis, &node) < B_OK) 168 goto err1; 169 170 // common API for all legacy modules ? 171 //status = legacy_driver_register(node, driverName, nodeCookie, PCI_LEGACY_DRIVER_MODULE_NAME); 172 173 status = gDeviceManager->register_node(node, PCI_LEGACY_DRIVER_MODULE_NAME, 174 legacyAttrs, NULL, &legacy); 175 if (status < B_OK) 176 goto err2; 177 178 status = gDeviceManager->register_node(legacy, PCI_LEGACY_DRIVER_MODULE_NAME, 179 drvAttrs, NULL, NULL); 180 if (status < B_OK) 181 goto err3; 182 183 gDeviceManager->put_node(node); 184 gDeviceManager->put_node(pci); 185 gDeviceManager->put_node(root); 186 187 return B_OK; 188 189 err3: 190 gDeviceManager->unregister_node(legacy); 191 err2: 192 gDeviceManager->put_node(node); 193 err1: 194 gDeviceManager->put_node(pci); 195 err0: 196 gDeviceManager->put_node(root); 197 TRACE(("pci_reserve_device for driver %s failed: %s\n", driverName, 198 strerror(status))); 199 return status; 200 } 201 202 203 status_t 204 pci_unreserve_device(uchar virtualBus, uchar device, uchar function, 205 const char *driverName, void *nodeCookie) 206 { 207 status_t status; 208 uint8 bus; 209 uint8 domain; 210 TRACE(("pci_unreserve_device(%d, %d, %d, %s)\n", virtualBus, device, 211 function, driverName)); 212 213 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 214 return B_ERROR; 215 216 //TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus, 217 // domain, bus, device, function, driverName, nodeCookie)); 218 219 device_attr matchPCIRoot[] = { 220 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "PCI"}}, 221 {NULL} 222 }; 223 device_attr matchThis[] = { 224 // info about device 225 {B_DEVICE_BUS, B_STRING_TYPE, {string: "pci"}}, 226 227 // location on PCI bus 228 {B_PCI_DEVICE_DOMAIN, B_UINT8_TYPE, {ui8: domain}}, 229 {B_PCI_DEVICE_BUS, B_UINT8_TYPE, {ui8: bus}}, 230 {B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {ui8: device}}, 231 {B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {ui8: function}}, 232 {NULL} 233 }; 234 device_attr legacyAttrs[] = { 235 // info about device 236 {B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}}, 237 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Legacy Driver Reservation"}}, 238 {NULL} 239 }; 240 device_attr drvAttrs[] = { 241 // info about device 242 {B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}}, 243 {"legacy_driver", B_STRING_TYPE, {string: driverName}}, 244 {"legacy_driver_cookie", B_UINT64_TYPE, {ui64: (uint64)nodeCookie}}, 245 {NULL} 246 }; 247 device_node *root, *pci, *node, *legacy, *drv; 248 249 status = B_DEVICE_NOT_FOUND; 250 root = gDeviceManager->get_root_node(); 251 if (!root) 252 return status; 253 254 pci = NULL; 255 if (gDeviceManager->get_next_child_node(root, matchPCIRoot, &pci) < B_OK) 256 goto err0; 257 258 node = NULL; 259 if (gDeviceManager->get_next_child_node(pci, matchThis, &node) < B_OK) 260 goto err1; 261 262 // common API for all legacy modules ? 263 //status = legacy_driver_unregister(node, driverName, nodeCookie); 264 265 legacy = NULL; 266 if (gDeviceManager->get_next_child_node(node, legacyAttrs, &legacy) < B_OK) 267 goto err2; 268 269 drv = NULL; 270 if (gDeviceManager->get_next_child_node(legacy, drvAttrs, &drv) < B_OK) 271 goto err3; 272 273 gDeviceManager->put_node(drv); 274 status = gDeviceManager->unregister_node(drv); 275 //dprintf("unreg:drv:%s\n", strerror(status)); 276 277 gDeviceManager->put_node(legacy); 278 status = gDeviceManager->unregister_node(legacy); 279 //dprintf("unreg:legacy:%s\n", strerror(status)); 280 // we'll get EBUSY here anyway... 281 282 gDeviceManager->put_node(node); 283 gDeviceManager->put_node(pci); 284 gDeviceManager->put_node(root); 285 return B_OK; 286 287 err3: 288 gDeviceManager->put_node(legacy); 289 err2: 290 gDeviceManager->put_node(node); 291 err1: 292 gDeviceManager->put_node(pci); 293 err0: 294 gDeviceManager->put_node(root); 295 TRACE(("pci_unreserve_device for driver %s failed: %s\n", driverName, 296 strerror(status))); 297 return status; 298 } 299 300 301 status_t 302 pci_update_interrupt_line(uchar virtualBus, uchar device, uchar function, 303 uchar newInterruptLineValue) 304 { 305 uint8 bus; 306 uint8 domain; 307 if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) 308 return B_ERROR; 309 310 return gPCI->UpdateInterruptLine(domain, bus, device, function, 311 newInterruptLineValue); 312 } 313 314 315 // used by pci_info.cpp print_info_basic() 316 void 317 __pci_resolve_virtual_bus(uint8 virtualBus, uint8 *domain, uint8 *bus) 318 { 319 if (gPCI->ResolveVirtualBus(virtualBus, domain, bus) < B_OK) 320 panic("ResolveVirtualBus failed"); 321 } 322 323 324 // #pragma mark kernel debugger commands 325 326 327 static int 328 display_io(int argc, char **argv) 329 { 330 int32 displayWidth; 331 int32 itemSize; 332 int32 num = 1; 333 int address; 334 int i = 1, j; 335 336 switch (argc) { 337 case 3: 338 num = atoi(argv[2]); 339 case 2: 340 address = strtoul(argv[1], NULL, 0); 341 break; 342 default: 343 kprintf("usage: %s <address> [num]\n", argv[0]); 344 return 0; 345 } 346 347 // build the format string 348 if (strcmp(argv[0], "inb") == 0 || strcmp(argv[0], "in8") == 0) { 349 itemSize = 1; 350 displayWidth = 16; 351 } else if (strcmp(argv[0], "ins") == 0 || strcmp(argv[0], "in16") == 0) { 352 itemSize = 2; 353 displayWidth = 8; 354 } else if (strcmp(argv[0], "inw") == 0 || strcmp(argv[0], "in32") == 0) { 355 itemSize = 4; 356 displayWidth = 4; 357 } else { 358 kprintf("display_io called in an invalid way!\n"); 359 return 0; 360 } 361 362 for (i = 0; i < num; i++) { 363 if ((i % displayWidth) == 0) { 364 int32 displayed = min_c(displayWidth, (num-i)) * itemSize; 365 if (i != 0) 366 kprintf("\n"); 367 368 kprintf("[0x%" B_PRIx32 "] ", address + i * itemSize); 369 370 if (num > displayWidth) { 371 // make sure the spacing in the last line is correct 372 for (j = displayed; j < displayWidth * itemSize; j++) 373 kprintf(" "); 374 } 375 kprintf(" "); 376 } 377 378 switch (itemSize) { 379 case 1: 380 kprintf(" %02" B_PRIx8, pci_read_io_8(address + i * itemSize)); 381 break; 382 case 2: 383 kprintf(" %04" B_PRIx16, pci_read_io_16(address + i * itemSize)); 384 break; 385 case 4: 386 kprintf(" %08" B_PRIx32, pci_read_io_32(address + i * itemSize)); 387 break; 388 } 389 } 390 391 kprintf("\n"); 392 return 0; 393 } 394 395 396 static int 397 write_io(int argc, char **argv) 398 { 399 int32 itemSize; 400 uint32 value; 401 int address; 402 int i = 1; 403 404 if (argc < 3) { 405 kprintf("usage: %s <address> <value> [value [...]]\n", argv[0]); 406 return 0; 407 } 408 409 address = strtoul(argv[1], NULL, 0); 410 411 if (strcmp(argv[0], "outb") == 0 || strcmp(argv[0], "out8") == 0) { 412 itemSize = 1; 413 } else if (strcmp(argv[0], "outs") == 0 || strcmp(argv[0], "out16") == 0) { 414 itemSize = 2; 415 } else if (strcmp(argv[0], "outw") == 0 || strcmp(argv[0], "out32") == 0) { 416 itemSize = 4; 417 } else { 418 kprintf("write_io called in an invalid way!\n"); 419 return 0; 420 } 421 422 // skip cmd name and address 423 argv += 2; 424 argc -= 2; 425 426 for (i = 0; i < argc; i++) { 427 value = strtoul(argv[i], NULL, 0); 428 switch (itemSize) { 429 case 1: 430 pci_write_io_8(address + i * itemSize, value); 431 break; 432 case 2: 433 pci_write_io_16(address + i * itemSize, value); 434 break; 435 case 4: 436 pci_write_io_32(address + i * itemSize, value); 437 break; 438 } 439 } 440 441 return 0; 442 } 443 444 445 static int 446 pcistatus(int argc, char **argv) 447 { 448 gPCI->ClearDeviceStatus(NULL, true); 449 return 0; 450 } 451 452 453 static int 454 pcirefresh(int argc, char **argv) 455 { 456 gPCI->RefreshDeviceInfo(); 457 pci_print_info(); 458 return 0; 459 } 460 461 462 // #pragma mark bus manager init/uninit 463 464 465 status_t 466 pci_init(void) 467 { 468 gPCI = new PCI; 469 470 if (pci_io_init() != B_OK) { 471 TRACE(("PCI: pci_io_init failed\n")); 472 return B_ERROR; 473 } 474 475 add_debugger_command("inw", &display_io, "dump io words (32-bit)"); 476 add_debugger_command("in32", &display_io, "dump io words (32-bit)"); 477 add_debugger_command("ins", &display_io, "dump io shorts (16-bit)"); 478 add_debugger_command("in16", &display_io, "dump io shorts (16-bit)"); 479 add_debugger_command("inb", &display_io, "dump io bytes (8-bit)"); 480 add_debugger_command("in8", &display_io, "dump io bytes (8-bit)"); 481 482 add_debugger_command("outw", &write_io, "write io words (32-bit)"); 483 add_debugger_command("out32", &write_io, "write io words (32-bit)"); 484 add_debugger_command("outs", &write_io, "write io shorts (16-bit)"); 485 add_debugger_command("out16", &write_io, "write io shorts (16-bit)"); 486 add_debugger_command("outb", &write_io, "write io bytes (8-bit)"); 487 add_debugger_command("out8", &write_io, "write io bytes (8-bit)"); 488 489 if (pci_controller_init() != B_OK) { 490 TRACE(("PCI: pci_controller_init failed\n")); 491 panic("PCI: pci_controller_init failed\n"); 492 return B_ERROR; 493 } 494 495 gPCI->InitDomainData(); 496 gPCI->InitBus(); 497 498 add_debugger_command("pcistatus", &pcistatus, "dump and clear pci device status registers"); 499 add_debugger_command("pcirefresh", &pcirefresh, "refresh and print all pci_info"); 500 501 return B_OK; 502 } 503 504 505 void 506 pci_uninit(void) 507 { 508 remove_debugger_command("outw", &write_io); 509 remove_debugger_command("out32", &write_io); 510 remove_debugger_command("outs", &write_io); 511 remove_debugger_command("out16", &write_io); 512 remove_debugger_command("outb", &write_io); 513 remove_debugger_command("out8", &write_io); 514 515 remove_debugger_command("inw", &display_io); 516 remove_debugger_command("in32", &display_io); 517 remove_debugger_command("ins", &display_io); 518 remove_debugger_command("in16", &display_io); 519 remove_debugger_command("inb", &display_io); 520 remove_debugger_command("in8", &display_io); 521 522 remove_debugger_command("pcistatus", &pcistatus); 523 remove_debugger_command("pcirefresh", &pcirefresh); 524 525 delete gPCI; 526 } 527 528 529 // #pragma mark PCI class 530 531 532 PCI::PCI() 533 : 534 fRootBus(0), 535 fDomainCount(0), 536 fBusEnumeration(false), 537 fVirtualBusMap(), 538 fNextVirtualBus(0) 539 { 540 #if defined(__POWERPC__) || defined(__M68K__) 541 fBusEnumeration = true; 542 #endif 543 } 544 545 546 void 547 PCI::InitBus() 548 { 549 PCIBus **nextBus = &fRootBus; 550 for (uint8 i = 0; i < fDomainCount; i++) { 551 PCIBus *bus = new PCIBus; 552 bus->next = NULL; 553 bus->parent = NULL; 554 bus->child = NULL; 555 bus->domain = i; 556 bus->bus = 0; 557 *nextBus = bus; 558 nextBus = &bus->next; 559 } 560 561 if (fBusEnumeration) { 562 for (uint8 i = 0; i < fDomainCount; i++) { 563 _EnumerateBus(i, 0); 564 } 565 } 566 567 if (1) { 568 for (uint8 i = 0; i < fDomainCount; i++) { 569 _FixupDevices(i, 0); 570 } 571 } 572 573 if (fRootBus) { 574 _DiscoverBus(fRootBus); 575 _ConfigureBridges(fRootBus); 576 ClearDeviceStatus(fRootBus, false); 577 _RefreshDeviceInfo(fRootBus); 578 } 579 } 580 581 582 PCI::~PCI() 583 { 584 } 585 586 587 status_t 588 PCI::_CreateVirtualBus(uint8 domain, uint8 bus, uint8 *virtualBus) 589 { 590 #if defined(__i386__) || defined(__x86_64__) 591 592 // IA32 doesn't use domains 593 if (domain) 594 panic("PCI::CreateVirtualBus domain != 0"); 595 *virtualBus = bus; 596 return B_OK; 597 598 #else 599 600 if (fNextVirtualBus > 0xff) 601 panic("PCI::CreateVirtualBus: virtual bus number space exhausted"); 602 603 uint16 value = domain << 8 | bus; 604 605 for (VirtualBusMap::Iterator it = fVirtualBusMap.Begin(); 606 it != fVirtualBusMap.End(); ++it) { 607 if (it->Value() == value) { 608 *virtualBus = it->Key(); 609 FLOW("PCI::CreateVirtualBus: domain %d, bus %d already in map => " 610 "virtualBus %d\n", domain, bus, *virtualBus); 611 return B_OK; 612 } 613 } 614 615 *virtualBus = fNextVirtualBus++; 616 617 FLOW("PCI::CreateVirtualBus: domain %d, bus %d => virtualBus %d\n", domain, 618 bus, *virtualBus); 619 620 return fVirtualBusMap.Insert(*virtualBus, value); 621 622 #endif 623 } 624 625 626 status_t 627 PCI::ResolveVirtualBus(uint8 virtualBus, uint8 *domain, uint8 *bus) 628 { 629 #if defined(__i386__) || defined(__x86_64__) 630 631 // IA32 doesn't use domains 632 *bus = virtualBus; 633 *domain = 0; 634 return B_OK; 635 636 #else 637 638 if (virtualBus >= fNextVirtualBus) 639 return B_ERROR; 640 641 uint16 value = fVirtualBusMap.Get(virtualBus); 642 *domain = value >> 8; 643 *bus = value & 0xff; 644 return B_OK; 645 646 #endif 647 } 648 649 650 status_t 651 PCI::AddController(pci_controller *controller, void *controller_cookie) 652 { 653 if (fDomainCount == MAX_PCI_DOMAINS) 654 return B_ERROR; 655 656 fDomainData[fDomainCount].controller = controller; 657 fDomainData[fDomainCount].controller_cookie = controller_cookie; 658 659 // initialized later to avoid call back into controller at this point 660 fDomainData[fDomainCount].max_bus_devices = -1; 661 662 fDomainCount++; 663 return B_OK; 664 } 665 666 void 667 PCI::InitDomainData() 668 { 669 for (uint8 i = 0; i < fDomainCount; i++) { 670 int32 count; 671 status_t status; 672 673 status = (*fDomainData[i].controller->get_max_bus_devices)( 674 fDomainData[i].controller_cookie, &count); 675 fDomainData[i].max_bus_devices = (status == B_OK) ? count : 0; 676 } 677 } 678 679 680 domain_data * 681 PCI::_GetDomainData(uint8 domain) 682 { 683 if (domain >= fDomainCount) 684 return NULL; 685 686 return &fDomainData[domain]; 687 } 688 689 690 inline int 691 PCI::_NumFunctions(uint8 domain, uint8 bus, uint8 device) 692 { 693 uint8 type = ReadConfig(domain, bus, device, 694 0, PCI_header_type, 1); 695 return (type & PCI_multifunction) != 0 ? 8 : 1; 696 } 697 698 699 status_t 700 PCI::GetNthInfo(long index, pci_info *outInfo) 701 { 702 long currentIndex = 0; 703 if (!fRootBus) 704 return B_ERROR; 705 706 return _GetNthInfo(fRootBus, ¤tIndex, index, outInfo); 707 } 708 709 710 status_t 711 PCI::_GetNthInfo(PCIBus *bus, long *currentIndex, long wantIndex, 712 pci_info *outInfo) 713 { 714 // maps tree structure to linear indexed view 715 PCIDev *dev = bus->child; 716 while (dev) { 717 if (*currentIndex == wantIndex) { 718 *outInfo = dev->info; 719 return B_OK; 720 } 721 *currentIndex += 1; 722 if (dev->child && B_OK == _GetNthInfo(dev->child, currentIndex, 723 wantIndex, outInfo)) 724 return B_OK; 725 dev = dev->next; 726 } 727 728 if (bus->next) 729 return _GetNthInfo(bus->next, currentIndex, wantIndex, outInfo); 730 731 return B_ERROR; 732 } 733 734 735 void 736 PCI::_EnumerateBus(uint8 domain, uint8 bus, uint8 *subordinateBus) 737 { 738 TRACE(("PCI: EnumerateBus: domain %u, bus %u\n", domain, bus)); 739 740 int maxBusDevices = _GetDomainData(domain)->max_bus_devices; 741 742 // step 1: disable all bridges on this bus 743 for (int dev = 0; dev < maxBusDevices; dev++) { 744 uint16 vendor_id = ReadConfig(domain, bus, dev, 0, PCI_vendor_id, 2); 745 if (vendor_id == 0xffff) 746 continue; 747 748 int numFunctions = _NumFunctions(domain, bus, dev); 749 for (int function = 0; function < numFunctions; function++) { 750 uint16 device_id = ReadConfig(domain, bus, dev, function, 751 PCI_device_id, 2); 752 if (device_id == 0xffff) 753 continue; 754 755 uint8 baseClass = ReadConfig(domain, bus, dev, function, 756 PCI_class_base, 1); 757 uint8 subClass = ReadConfig(domain, bus, dev, function, 758 PCI_class_sub, 1); 759 if (baseClass != PCI_bridge || subClass != PCI_pci) 760 continue; 761 762 // skip incorrectly configured devices 763 uint8 headerType = ReadConfig(domain, bus, dev, function, 764 PCI_header_type, 1) & PCI_header_type_mask; 765 if (headerType != PCI_header_type_PCI_to_PCI_bridge) 766 continue; 767 768 TRACE(("PCI: found PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n", 769 domain, bus, dev, function)); 770 TRACE(("PCI: original settings: pcicmd %04" B_PRIx32 ", primary-bus " 771 "%" B_PRIu32 ", secondary-bus %" B_PRIu32 ", subordinate-bus " 772 "%" B_PRIu32 "\n", 773 ReadConfig(domain, bus, dev, function, PCI_command, 2), 774 ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), 775 ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), 776 ReadConfig(domain, bus, dev, function, PCI_subordinate_bus, 1))); 777 778 // disable decoding 779 uint16 pcicmd; 780 pcicmd = ReadConfig(domain, bus, dev, function, PCI_command, 2); 781 pcicmd &= ~(PCI_command_io | PCI_command_memory 782 | PCI_command_master); 783 WriteConfig(domain, bus, dev, function, PCI_command, 2, pcicmd); 784 785 // disable busses 786 WriteConfig(domain, bus, dev, function, PCI_primary_bus, 1, 0); 787 WriteConfig(domain, bus, dev, function, PCI_secondary_bus, 1, 0); 788 WriteConfig(domain, bus, dev, function, PCI_subordinate_bus, 1, 0); 789 790 TRACE(("PCI: disabled settings: pcicmd %04" B_PRIx32 ", primary-bus " 791 "%" B_PRIu32 ", secondary-bus %" B_PRIu32 ", subordinate-bus " 792 "%" B_PRIu32 "\n", 793 ReadConfig(domain, bus, dev, function, PCI_command, 2), 794 ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), 795 ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), 796 ReadConfig(domain, bus, dev, function, PCI_subordinate_bus, 1))); 797 } 798 } 799 800 uint8 lastUsedBusNumber = bus; 801 802 // step 2: assign busses to all bridges, and enable them again 803 for (int dev = 0; dev < maxBusDevices; dev++) { 804 uint16 vendor_id = ReadConfig(domain, bus, dev, 0, PCI_vendor_id, 2); 805 if (vendor_id == 0xffff) 806 continue; 807 808 int numFunctions = _NumFunctions(domain, bus, dev); 809 for (int function = 0; function < numFunctions; function++) { 810 uint16 deviceID = ReadConfig(domain, bus, dev, function, 811 PCI_device_id, 2); 812 if (deviceID == 0xffff) 813 continue; 814 815 uint8 baseClass = ReadConfig(domain, bus, dev, function, 816 PCI_class_base, 1); 817 uint8 subClass = ReadConfig(domain, bus, dev, function, 818 PCI_class_sub, 1); 819 if (baseClass != PCI_bridge || subClass != PCI_pci) 820 continue; 821 822 // skip incorrectly configured devices 823 uint8 headerType = ReadConfig(domain, bus, dev, function, 824 PCI_header_type, 1) & PCI_header_type_mask; 825 if (headerType != PCI_header_type_PCI_to_PCI_bridge) 826 continue; 827 828 TRACE(("PCI: configuring PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n", 829 domain, bus, dev, function)); 830 831 // open Scheunentor for enumerating the bus behind the bridge 832 WriteConfig(domain, bus, dev, function, PCI_primary_bus, 1, bus); 833 WriteConfig(domain, bus, dev, function, PCI_secondary_bus, 1, 834 lastUsedBusNumber + 1); 835 WriteConfig(domain, bus, dev, function, PCI_subordinate_bus, 1, 255); 836 837 // enable decoding (too early here?) 838 uint16 pcicmd; 839 pcicmd = ReadConfig(domain, bus, dev, function, PCI_command, 2); 840 pcicmd |= PCI_command_io | PCI_command_memory | PCI_command_master; 841 WriteConfig(domain, bus, dev, function, PCI_command, 2, pcicmd); 842 843 TRACE(("PCI: probing settings: pcicmd %04" B_PRIx32 ", primary-bus " 844 "%" B_PRIu32 ", secondary-bus %" B_PRIu32 ", subordinate-bus " 845 "%" B_PRIu32 "\n", 846 ReadConfig(domain, bus, dev, function, PCI_command, 2), 847 ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), 848 ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), 849 ReadConfig(domain, bus, dev, function, PCI_subordinate_bus, 1))); 850 851 // enumerate bus 852 _EnumerateBus(domain, lastUsedBusNumber + 1, &lastUsedBusNumber); 853 854 // close Scheunentor 855 WriteConfig(domain, bus, dev, function, PCI_subordinate_bus, 1, lastUsedBusNumber); 856 857 TRACE(("PCI: configured settings: pcicmd %04" B_PRIx32 ", primary-bus " 858 "%" B_PRIu32 ", secondary-bus %" B_PRIu32 ", subordinate-bus " 859 "%" B_PRIu32 "\n", 860 ReadConfig(domain, bus, dev, function, PCI_command, 2), 861 ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), 862 ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), 863 ReadConfig(domain, bus, dev, function, PCI_subordinate_bus, 1))); 864 } 865 } 866 if (subordinateBus) 867 *subordinateBus = lastUsedBusNumber; 868 869 TRACE(("PCI: EnumerateBus done: domain %u, bus %u, last used bus number %u\n", domain, bus, lastUsedBusNumber)); 870 } 871 872 873 void 874 PCI::_FixupDevices(uint8 domain, uint8 bus) 875 { 876 FLOW("PCI: FixupDevices domain %u, bus %u\n", domain, bus); 877 878 int maxBusDevices = _GetDomainData(domain)->max_bus_devices; 879 static int recursed = 0; 880 881 if (recursed++ > 10) { 882 // guard against buggy chipsets 883 // XXX: is there any official limit ? 884 dprintf("PCI: FixupDevices: too many recursions (buggy chipset?)\n"); 885 recursed--; 886 return; 887 } 888 889 for (int dev = 0; dev < maxBusDevices; dev++) { 890 uint16 vendorId = ReadConfig(domain, bus, dev, 0, PCI_vendor_id, 2); 891 if (vendorId == 0xffff) 892 continue; 893 894 int numFunctions = _NumFunctions(domain, bus, dev); 895 for (int function = 0; function < numFunctions; function++) { 896 uint16 deviceId = ReadConfig(domain, bus, dev, function, 897 PCI_device_id, 2); 898 if (deviceId == 0xffff) 899 continue; 900 901 pci_fixup_device(this, domain, bus, dev, function); 902 903 uint8 baseClass = ReadConfig(domain, bus, dev, function, 904 PCI_class_base, 1); 905 if (baseClass != PCI_bridge) 906 continue; 907 uint8 subClass = ReadConfig(domain, bus, dev, function, 908 PCI_class_sub, 1); 909 if (subClass != PCI_pci) 910 continue; 911 912 // some FIC motherboards have a buggy BIOS... 913 // make sure the header type is correct for a bridge, 914 uint8 headerType = ReadConfig(domain, bus, dev, function, 915 PCI_header_type, 1) & PCI_header_type_mask; 916 if (headerType != PCI_header_type_PCI_to_PCI_bridge) { 917 dprintf("PCI: dom %u, bus %u, dev %2u, func %u, PCI bridge" 918 " class but wrong header type 0x%02x, ignoring.\n", 919 domain, bus, dev, function, headerType); 920 continue; 921 } 922 923 924 int busBehindBridge = ReadConfig(domain, bus, dev, function, 925 PCI_secondary_bus, 1); 926 927 TRACE(("PCI: FixupDevices: checking bus %d behind %04x:%04x\n", 928 busBehindBridge, vendorId, deviceId)); 929 _FixupDevices(domain, busBehindBridge); 930 } 931 } 932 recursed--; 933 } 934 935 936 void 937 PCI::_ConfigureBridges(PCIBus *bus) 938 { 939 for (PCIDev *dev = bus->child; dev; dev = dev->next) { 940 if (dev->info.class_base == PCI_bridge 941 && dev->info.class_sub == PCI_pci 942 && (dev->info.header_type & PCI_header_type_mask) 943 == PCI_header_type_PCI_to_PCI_bridge) { 944 uint16 bridgeControlOld = ReadConfig(dev->domain, dev->bus, 945 dev->device, dev->function, PCI_bridge_control, 2); 946 uint16 bridgeControlNew = bridgeControlOld; 947 // Enable: Parity Error Response, SERR, Master Abort Mode, Discard 948 // Timer SERR 949 // Clear: Discard Timer Status 950 bridgeControlNew |= PCI_bridge_parity_error_response 951 | PCI_bridge_serr | PCI_bridge_master_abort 952 | PCI_bridge_discard_timer_status 953 | PCI_bridge_discard_timer_serr; 954 // Set discard timer to 2^15 PCI clocks 955 bridgeControlNew &= ~(PCI_bridge_primary_discard_timeout 956 | PCI_bridge_secondary_discard_timeout); 957 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 958 PCI_bridge_control, 2, bridgeControlNew); 959 bridgeControlNew = ReadConfig(dev->domain, dev->bus, dev->device, 960 dev->function, PCI_bridge_control, 2); 961 dprintf("PCI: dom %u, bus %u, dev %2u, func %u, changed PCI bridge" 962 " control from 0x%04x to 0x%04x\n", dev->domain, dev->bus, 963 dev->device, dev->function, bridgeControlOld, 964 bridgeControlNew); 965 } 966 967 if (dev->child) 968 _ConfigureBridges(dev->child); 969 } 970 971 if (bus->next) 972 _ConfigureBridges(bus->next); 973 } 974 975 976 void 977 PCI::ClearDeviceStatus(PCIBus *bus, bool dumpStatus) 978 { 979 if (!bus) { 980 if (!fRootBus) 981 return; 982 bus = fRootBus; 983 } 984 985 for (PCIDev *dev = bus->child; dev; dev = dev->next) { 986 // Clear and dump PCI device status 987 uint16 status = ReadConfig(dev->domain, dev->bus, dev->device, 988 dev->function, PCI_status, 2); 989 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 990 PCI_status, 2, status); 991 if (dumpStatus) { 992 kprintf("domain %u, bus %u, dev %2u, func %u, PCI device status " 993 "0x%04x\n", dev->domain, dev->bus, dev->device, dev->function, 994 status); 995 if (status & PCI_status_parity_error_detected) 996 kprintf(" Detected Parity Error\n"); 997 if (status & PCI_status_serr_signalled) 998 kprintf(" Signalled System Error\n"); 999 if (status & PCI_status_master_abort_received) 1000 kprintf(" Received Master-Abort\n"); 1001 if (status & PCI_status_target_abort_received) 1002 kprintf(" Received Target-Abort\n"); 1003 if (status & PCI_status_target_abort_signalled) 1004 kprintf(" Signalled Target-Abort\n"); 1005 if (status & PCI_status_parity_signalled) 1006 kprintf(" Master Data Parity Error\n"); 1007 } 1008 1009 if (dev->info.class_base == PCI_bridge 1010 && dev->info.class_sub == PCI_pci) { 1011 // Clear and dump PCI bridge secondary status 1012 uint16 secondaryStatus = ReadConfig(dev->domain, dev->bus, 1013 dev->device, dev->function, PCI_secondary_status, 2); 1014 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1015 PCI_secondary_status, 2, secondaryStatus); 1016 if (dumpStatus) { 1017 kprintf("domain %u, bus %u, dev %2u, func %u, PCI bridge " 1018 "secondary status 0x%04x\n", dev->domain, dev->bus, 1019 dev->device, dev->function, secondaryStatus); 1020 if (secondaryStatus & PCI_status_parity_error_detected) 1021 kprintf(" Detected Parity Error\n"); 1022 if (secondaryStatus & PCI_status_serr_signalled) 1023 kprintf(" Received System Error\n"); 1024 if (secondaryStatus & PCI_status_master_abort_received) 1025 kprintf(" Received Master-Abort\n"); 1026 if (secondaryStatus & PCI_status_target_abort_received) 1027 kprintf(" Received Target-Abort\n"); 1028 if (secondaryStatus & PCI_status_target_abort_signalled) 1029 kprintf(" Signalled Target-Abort\n"); 1030 if (secondaryStatus & PCI_status_parity_signalled) 1031 kprintf(" Data Parity Reported\n"); 1032 } 1033 1034 // Clear and dump the discard-timer error bit located in bridge-control register 1035 uint16 bridgeControl = ReadConfig(dev->domain, dev->bus, 1036 dev->device, dev->function, PCI_bridge_control, 2); 1037 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1038 PCI_bridge_control, 2, bridgeControl); 1039 if (dumpStatus) { 1040 kprintf("domain %u, bus %u, dev %2u, func %u, PCI bridge " 1041 "control 0x%04x\n", dev->domain, dev->bus, dev->device, 1042 dev->function, bridgeControl); 1043 if (bridgeControl & PCI_bridge_discard_timer_status) { 1044 kprintf(" bridge-control: Discard Timer Error\n"); 1045 } 1046 } 1047 } 1048 1049 if (dev->child) 1050 ClearDeviceStatus(dev->child, dumpStatus); 1051 } 1052 1053 if (bus->next) 1054 ClearDeviceStatus(bus->next, dumpStatus); 1055 } 1056 1057 1058 void 1059 PCI::_DiscoverBus(PCIBus *bus) 1060 { 1061 FLOW("PCI: DiscoverBus, domain %u, bus %u\n", bus->domain, bus->bus); 1062 1063 int maxBusDevices = _GetDomainData(bus->domain)->max_bus_devices; 1064 static int recursed = 0; 1065 1066 if (recursed++ > 10) { 1067 // guard against buggy chipsets 1068 // XXX: is there any official limit ? 1069 dprintf("PCI: DiscoverBus: too many recursions (buggy chipset?)\n"); 1070 recursed--; 1071 return; 1072 } 1073 1074 for (int dev = 0; dev < maxBusDevices; dev++) { 1075 uint16 vendorID = ReadConfig(bus->domain, bus->bus, dev, 0, 1076 PCI_vendor_id, 2); 1077 if (vendorID == 0xffff) 1078 continue; 1079 1080 int numFunctions = _NumFunctions(bus->domain, bus->bus, dev); 1081 for (int function = 0; function < numFunctions; function++) 1082 _DiscoverDevice(bus, dev, function); 1083 } 1084 1085 if (bus->next) 1086 _DiscoverBus(bus->next); 1087 recursed--; 1088 } 1089 1090 1091 void 1092 PCI::_DiscoverDevice(PCIBus *bus, uint8 dev, uint8 function) 1093 { 1094 FLOW("PCI: DiscoverDevice, domain %u, bus %u, dev %u, func %u\n", bus->domain, bus->bus, dev, function); 1095 1096 uint16 deviceID = ReadConfig(bus->domain, bus->bus, dev, function, 1097 PCI_device_id, 2); 1098 if (deviceID == 0xffff) 1099 return; 1100 1101 PCIDev *newDev = _CreateDevice(bus, dev, function); 1102 1103 uint8 baseClass = ReadConfig(bus->domain, bus->bus, dev, function, 1104 PCI_class_base, 1); 1105 uint8 subClass = ReadConfig(bus->domain, bus->bus, dev, function, 1106 PCI_class_sub, 1); 1107 uint8 headerType = ReadConfig(bus->domain, bus->bus, dev, function, 1108 PCI_header_type, 1) & PCI_header_type_mask; 1109 if (baseClass == PCI_bridge && subClass == PCI_pci 1110 && headerType == PCI_header_type_PCI_to_PCI_bridge) { 1111 uint8 secondaryBus = ReadConfig(bus->domain, bus->bus, dev, function, 1112 PCI_secondary_bus, 1); 1113 PCIBus *newBus = _CreateBus(newDev, bus->domain, secondaryBus); 1114 _DiscoverBus(newBus); 1115 } 1116 } 1117 1118 1119 PCIBus * 1120 PCI::_CreateBus(PCIDev *parent, uint8 domain, uint8 bus) 1121 { 1122 PCIBus *newBus = new(std::nothrow) PCIBus; 1123 if (newBus == NULL) 1124 return NULL; 1125 1126 newBus->next = NULL; 1127 newBus->parent = parent; 1128 newBus->child = NULL; 1129 newBus->domain = domain; 1130 newBus->bus = bus; 1131 1132 // append 1133 parent->child = newBus; 1134 1135 return newBus; 1136 } 1137 1138 1139 PCIDev * 1140 PCI::_CreateDevice(PCIBus *parent, uint8 device, uint8 function) 1141 { 1142 FLOW("PCI: CreateDevice, domain %u, bus %u, dev %u, func %u:\n", parent->domain, 1143 parent->bus, device, function); 1144 1145 PCIDev *newDev = new(std::nothrow) PCIDev; 1146 if (newDev == NULL) 1147 return NULL; 1148 1149 newDev->next = NULL; 1150 newDev->parent = parent; 1151 newDev->child = NULL; 1152 newDev->domain = parent->domain; 1153 newDev->bus = parent->bus; 1154 newDev->device = device; 1155 newDev->function = function; 1156 memset(&newDev->info, 0, sizeof(newDev->info)); 1157 1158 _ReadBasicInfo(newDev); 1159 1160 FLOW("PCI: CreateDevice, vendor 0x%04x, device 0x%04x, class_base 0x%02x, " 1161 "class_sub 0x%02x\n", newDev->info.vendor_id, newDev->info.device_id, 1162 newDev->info.class_base, newDev->info.class_sub); 1163 1164 // append 1165 if (parent->child == NULL) { 1166 parent->child = newDev; 1167 } else { 1168 PCIDev *sub = parent->child; 1169 while (sub->next) 1170 sub = sub->next; 1171 sub->next = newDev; 1172 } 1173 1174 return newDev; 1175 } 1176 1177 1178 uint64 1179 PCI::_BarSize(uint64 bits) 1180 { 1181 if (!bits) 1182 return 0; 1183 1184 uint64 size = 1; 1185 while ((bits & size) == 0) 1186 size <<= 1; 1187 1188 return size; 1189 } 1190 1191 1192 size_t 1193 PCI::_GetBarInfo(PCIDev *dev, uint8 offset, uint32 &_ramAddress, 1194 uint32 &_pciAddress, uint32 &_size, uint8 &flags, uint32 *_highRAMAddress, 1195 uint32 *_highPCIAddress, uint32 *_highSize) 1196 { 1197 uint64 pciAddress = ReadConfig(dev->domain, dev->bus, dev->device, 1198 dev->function, offset, 4); 1199 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, offset, 4, 1200 0xffffffff); 1201 uint64 size = ReadConfig(dev->domain, dev->bus, dev->device, dev->function, 1202 offset, 4); 1203 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, offset, 4, 1204 pciAddress); 1205 1206 uint32 mask = PCI_address_memory_32_mask; 1207 bool is64bit = false; 1208 if ((pciAddress & PCI_address_space) != 0) 1209 mask = PCI_address_io_mask; 1210 else { 1211 is64bit = (pciAddress & PCI_address_type) == PCI_address_type_64; 1212 1213 if (is64bit && _highRAMAddress != NULL) { 1214 uint64 highPCIAddress = ReadConfig(dev->domain, dev->bus, 1215 dev->device, dev->function, offset + 4, 4); 1216 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1217 offset + 4, 4, 0xffffffff); 1218 uint64 highSize = ReadConfig(dev->domain, dev->bus, dev->device, 1219 dev->function, offset + 4, 4); 1220 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1221 offset + 4, 4, highPCIAddress); 1222 1223 pciAddress |= highPCIAddress << 32; 1224 size |= highSize << 32; 1225 } 1226 } 1227 1228 flags = (uint32)pciAddress & ~mask; 1229 pciAddress &= ((uint64)0xffffffff << 32) | mask; 1230 size &= ((uint64)0xffffffff << 32) | mask; 1231 1232 size = _BarSize(size); 1233 uint64 ramAddress = pci_ram_address(pciAddress); 1234 1235 _ramAddress = ramAddress; 1236 _pciAddress = pciAddress; 1237 _size = size; 1238 if (!is64bit) 1239 return 1; 1240 1241 if (_highRAMAddress == NULL || _highPCIAddress == NULL || _highSize == NULL) 1242 panic("64 bit PCI BAR but no space to store high values\n"); 1243 else { 1244 *_highRAMAddress = ramAddress >> 32; 1245 *_highPCIAddress = pciAddress >> 32; 1246 *_highSize = size >> 32; 1247 } 1248 1249 return 2; 1250 } 1251 1252 1253 void 1254 PCI::_GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 &_address, uint32 *_size, 1255 uint8 *_flags) 1256 { 1257 uint32 oldValue = ReadConfig(dev->domain, dev->bus, dev->device, dev->function, 1258 offset, 4); 1259 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, offset, 4, 1260 0xfffffffe); // LSB must be 0 1261 uint32 newValue = ReadConfig(dev->domain, dev->bus, dev->device, dev->function, 1262 offset, 4); 1263 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, offset, 4, 1264 oldValue); 1265 1266 _address = oldValue & PCI_rom_address_mask; 1267 if (_size != NULL) 1268 *_size = _BarSize(newValue & PCI_rom_address_mask); 1269 if (_flags != NULL) 1270 *_flags = newValue & 0xf; 1271 } 1272 1273 1274 void 1275 PCI::_ReadBasicInfo(PCIDev *dev) 1276 { 1277 uint8 virtualBus; 1278 1279 if (_CreateVirtualBus(dev->domain, dev->bus, &virtualBus) != B_OK) { 1280 dprintf("PCI: CreateVirtualBus failed, domain %u, bus %u\n", dev->domain, dev->bus); 1281 return; 1282 } 1283 1284 dev->info.vendor_id = ReadConfig(dev->domain, dev->bus, dev->device, 1285 dev->function, PCI_vendor_id, 2); 1286 dev->info.device_id = ReadConfig(dev->domain, dev->bus, dev->device, 1287 dev->function, PCI_device_id, 2); 1288 dev->info.bus = virtualBus; 1289 dev->info.device = dev->device; 1290 dev->info.function = dev->function; 1291 dev->info.revision = ReadConfig(dev->domain, dev->bus, dev->device, 1292 dev->function, PCI_revision, 1); 1293 dev->info.class_api = ReadConfig(dev->domain, dev->bus, dev->device, 1294 dev->function, PCI_class_api, 1); 1295 dev->info.class_sub = ReadConfig(dev->domain, dev->bus, dev->device, 1296 dev->function, PCI_class_sub, 1); 1297 dev->info.class_base = ReadConfig(dev->domain, dev->bus, dev->device, 1298 dev->function, PCI_class_base, 1); 1299 dev->info.line_size = ReadConfig(dev->domain, dev->bus, dev->device, 1300 dev->function, PCI_line_size, 1); 1301 dev->info.latency = ReadConfig(dev->domain, dev->bus, dev->device, 1302 dev->function, PCI_latency, 1); 1303 // BeOS does not mask off the multifunction bit, developer must use 1304 // (header_type & PCI_header_type_mask) 1305 dev->info.header_type = ReadConfig(dev->domain, dev->bus, dev->device, 1306 dev->function, PCI_header_type, 1); 1307 dev->info.bist = ReadConfig(dev->domain, dev->bus, dev->device, 1308 dev->function, PCI_bist, 1); 1309 dev->info.reserved = 0; 1310 } 1311 1312 1313 void 1314 PCI::_ReadHeaderInfo(PCIDev *dev) 1315 { 1316 switch (dev->info.header_type & PCI_header_type_mask) { 1317 case PCI_header_type_generic: 1318 { 1319 // disable PCI device address decoding (io and memory) while BARs 1320 // are modified 1321 uint16 pcicmd = ReadConfig(dev->domain, dev->bus, dev->device, 1322 dev->function, PCI_command, 2); 1323 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1324 PCI_command, 2, 1325 pcicmd & ~(PCI_command_io | PCI_command_memory)); 1326 1327 // get BAR size infos 1328 _GetRomBarInfo(dev, PCI_rom_base, dev->info.u.h0.rom_base_pci, 1329 &dev->info.u.h0.rom_size); 1330 for (int i = 0; i < 6;) { 1331 i += _GetBarInfo(dev, PCI_base_registers + 4 * i, 1332 dev->info.u.h0.base_registers[i], 1333 dev->info.u.h0.base_registers_pci[i], 1334 dev->info.u.h0.base_register_sizes[i], 1335 dev->info.u.h0.base_register_flags[i], 1336 i < 5 ? &dev->info.u.h0.base_registers[i + 1] : NULL, 1337 i < 5 ? &dev->info.u.h0.base_registers_pci[i + 1] : NULL, 1338 i < 5 ? &dev->info.u.h0.base_register_sizes[i + 1] : NULL); 1339 } 1340 1341 // restore PCI device address decoding 1342 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1343 PCI_command, 2, pcicmd); 1344 1345 dev->info.u.h0.rom_base = (uint32)pci_ram_address( 1346 dev->info.u.h0.rom_base_pci); 1347 1348 dev->info.u.h0.cardbus_cis = ReadConfig(dev->domain, dev->bus, 1349 dev->device, dev->function, PCI_cardbus_cis, 4); 1350 dev->info.u.h0.subsystem_id = ReadConfig(dev->domain, dev->bus, 1351 dev->device, dev->function, PCI_subsystem_id, 2); 1352 dev->info.u.h0.subsystem_vendor_id = ReadConfig(dev->domain, 1353 dev->bus, dev->device, dev->function, PCI_subsystem_vendor_id, 1354 2); 1355 dev->info.u.h0.interrupt_line = ReadConfig(dev->domain, dev->bus, 1356 dev->device, dev->function, PCI_interrupt_line, 1); 1357 dev->info.u.h0.interrupt_pin = ReadConfig(dev->domain, dev->bus, 1358 dev->device, dev->function, PCI_interrupt_pin, 1); 1359 dev->info.u.h0.min_grant = ReadConfig(dev->domain, dev->bus, 1360 dev->device, dev->function, PCI_min_grant, 1); 1361 dev->info.u.h0.max_latency = ReadConfig(dev->domain, dev->bus, 1362 dev->device, dev->function, PCI_max_latency, 1); 1363 break; 1364 } 1365 1366 case PCI_header_type_PCI_to_PCI_bridge: 1367 { 1368 // disable PCI device address decoding (io and memory) while BARs 1369 // are modified 1370 uint16 pcicmd = ReadConfig(dev->domain, dev->bus, dev->device, 1371 dev->function, PCI_command, 2); 1372 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1373 PCI_command, 2, 1374 pcicmd & ~(PCI_command_io | PCI_command_memory)); 1375 1376 _GetRomBarInfo(dev, PCI_bridge_rom_base, 1377 dev->info.u.h1.rom_base_pci); 1378 for (int i = 0; i < 2;) { 1379 i += _GetBarInfo(dev, PCI_base_registers + 4 * i, 1380 dev->info.u.h1.base_registers[i], 1381 dev->info.u.h1.base_registers_pci[i], 1382 dev->info.u.h1.base_register_sizes[i], 1383 dev->info.u.h1.base_register_flags[i], 1384 i < 1 ? &dev->info.u.h1.base_registers[i + 1] : NULL, 1385 i < 1 ? &dev->info.u.h1.base_registers_pci[i + 1] : NULL, 1386 i < 1 ? &dev->info.u.h1.base_register_sizes[i + 1] : NULL); 1387 } 1388 1389 // restore PCI device address decoding 1390 WriteConfig(dev->domain, dev->bus, dev->device, dev->function, 1391 PCI_command, 2, pcicmd); 1392 1393 dev->info.u.h1.rom_base = (uint32)pci_ram_address( 1394 dev->info.u.h1.rom_base_pci); 1395 1396 dev->info.u.h1.primary_bus = ReadConfig(dev->domain, dev->bus, 1397 dev->device, dev->function, PCI_primary_bus, 1); 1398 dev->info.u.h1.secondary_bus = ReadConfig(dev->domain, dev->bus, 1399 dev->device, dev->function, PCI_secondary_bus, 1); 1400 dev->info.u.h1.subordinate_bus = ReadConfig(dev->domain, 1401 dev->bus, dev->device, dev->function, PCI_subordinate_bus, 1); 1402 dev->info.u.h1.secondary_latency = ReadConfig(dev->domain, 1403 dev->bus, dev->device, dev->function, PCI_secondary_latency, 1); 1404 dev->info.u.h1.io_base = ReadConfig(dev->domain, dev->bus, 1405 dev->device, dev->function, PCI_io_base, 1); 1406 dev->info.u.h1.io_limit = ReadConfig(dev->domain, dev->bus, 1407 dev->device, dev->function, PCI_io_limit, 1); 1408 dev->info.u.h1.secondary_status = ReadConfig(dev->domain, 1409 dev->bus, dev->device, dev->function, PCI_secondary_status, 2); 1410 dev->info.u.h1.memory_base = ReadConfig(dev->domain, dev->bus, 1411 dev->device, dev->function, PCI_memory_base, 2); 1412 dev->info.u.h1.memory_limit = ReadConfig(dev->domain, dev->bus, 1413 dev->device, dev->function, PCI_memory_limit, 2); 1414 dev->info.u.h1.prefetchable_memory_base = ReadConfig(dev->domain, 1415 dev->bus, dev->device, dev->function, 1416 PCI_prefetchable_memory_base, 2); 1417 dev->info.u.h1.prefetchable_memory_limit = ReadConfig( 1418 dev->domain, dev->bus, dev->device, dev->function, 1419 PCI_prefetchable_memory_limit, 2); 1420 dev->info.u.h1.prefetchable_memory_base_upper32 = ReadConfig( 1421 dev->domain, dev->bus, dev->device, dev->function, 1422 PCI_prefetchable_memory_base_upper32, 4); 1423 dev->info.u.h1.prefetchable_memory_limit_upper32 = ReadConfig( 1424 dev->domain, dev->bus, dev->device, dev->function, 1425 PCI_prefetchable_memory_limit_upper32, 4); 1426 dev->info.u.h1.io_base_upper16 = ReadConfig(dev->domain, 1427 dev->bus, dev->device, dev->function, PCI_io_base_upper16, 2); 1428 dev->info.u.h1.io_limit_upper16 = ReadConfig(dev->domain, 1429 dev->bus, dev->device, dev->function, PCI_io_limit_upper16, 2); 1430 dev->info.u.h1.interrupt_line = ReadConfig(dev->domain, dev->bus, 1431 dev->device, dev->function, PCI_interrupt_line, 1); 1432 dev->info.u.h1.interrupt_pin = ReadConfig(dev->domain, dev->bus, 1433 dev->device, dev->function, PCI_interrupt_pin, 1); 1434 dev->info.u.h1.bridge_control = ReadConfig(dev->domain, dev->bus, 1435 dev->device, dev->function, PCI_bridge_control, 2); 1436 dev->info.u.h1.subsystem_id = ReadConfig(dev->domain, dev->bus, 1437 dev->device, dev->function, PCI_sub_device_id_1, 2); 1438 dev->info.u.h1.subsystem_vendor_id = ReadConfig(dev->domain, 1439 dev->bus, dev->device, dev->function, PCI_sub_vendor_id_1, 2); 1440 break; 1441 } 1442 1443 case PCI_header_type_cardbus: 1444 { 1445 // for testing only, not final: 1446 dev->info.u.h2.subsystem_id = ReadConfig(dev->domain, dev->bus, 1447 dev->device, dev->function, PCI_sub_device_id_2, 2); 1448 dev->info.u.h2.subsystem_vendor_id = ReadConfig(dev->domain, 1449 dev->bus, dev->device, dev->function, PCI_sub_vendor_id_2, 2); 1450 dev->info.u.h2.primary_bus = ReadConfig(dev->domain, dev->bus, 1451 dev->device, dev->function, PCI_primary_bus_2, 1); 1452 dev->info.u.h2.secondary_bus = ReadConfig(dev->domain, dev->bus, 1453 dev->device, dev->function, PCI_secondary_bus_2, 1); 1454 dev->info.u.h2.subordinate_bus = ReadConfig(dev->domain, 1455 dev->bus, dev->device, dev->function, PCI_subordinate_bus_2, 1); 1456 dev->info.u.h2.secondary_latency = ReadConfig(dev->domain, 1457 dev->bus, dev->device, dev->function, PCI_secondary_latency_2, 1); 1458 dev->info.u.h2.reserved = 0; 1459 dev->info.u.h2.memory_base = ReadConfig(dev->domain, dev->bus, 1460 dev->device, dev->function, PCI_memory_base0_2, 4); 1461 dev->info.u.h2.memory_limit = ReadConfig(dev->domain, dev->bus, 1462 dev->device, dev->function, PCI_memory_limit0_2, 4); 1463 dev->info.u.h2.memory_base_upper32 = ReadConfig(dev->domain, 1464 dev->bus, dev->device, dev->function, PCI_memory_base1_2, 4); 1465 dev->info.u.h2.memory_limit_upper32 = ReadConfig(dev->domain, 1466 dev->bus, dev->device, dev->function, PCI_memory_limit1_2, 4); 1467 dev->info.u.h2.io_base = ReadConfig(dev->domain, dev->bus, 1468 dev->device, dev->function, PCI_io_base0_2, 4); 1469 dev->info.u.h2.io_limit = ReadConfig(dev->domain, dev->bus, 1470 dev->device, dev->function, PCI_io_limit0_2, 4); 1471 dev->info.u.h2.io_base_upper32 = ReadConfig(dev->domain, 1472 dev->bus, dev->device, dev->function, PCI_io_base1_2, 4); 1473 dev->info.u.h2.io_limit_upper32 = ReadConfig(dev->domain, 1474 dev->bus, dev->device, dev->function, PCI_io_limit1_2, 4); 1475 dev->info.u.h2.secondary_status = ReadConfig(dev->domain, 1476 dev->bus, dev->device, dev->function, PCI_secondary_status_2, 2); 1477 dev->info.u.h2.bridge_control = ReadConfig(dev->domain, 1478 dev->bus, dev->device, dev->function, PCI_bridge_control_2, 2); 1479 break; 1480 } 1481 1482 default: 1483 TRACE(("PCI: Header type unknown (0x%02x)\n", dev->info.header_type)); 1484 break; 1485 } 1486 } 1487 1488 1489 void 1490 PCI::RefreshDeviceInfo() 1491 { 1492 if (fRootBus == NULL) 1493 return; 1494 1495 _RefreshDeviceInfo(fRootBus); 1496 } 1497 1498 1499 void 1500 PCI::_RefreshDeviceInfo(PCIBus *bus) 1501 { 1502 for (PCIDev *dev = bus->child; dev; dev = dev->next) { 1503 _ReadBasicInfo(dev); 1504 _ReadHeaderInfo(dev); 1505 #if defined(__i386__) || defined(__x86_64__) 1506 pci_read_arch_info(dev); 1507 #endif 1508 if (dev->child) 1509 _RefreshDeviceInfo(dev->child); 1510 } 1511 1512 if (bus->next) 1513 _RefreshDeviceInfo(bus->next); 1514 } 1515 1516 1517 status_t 1518 PCI::ReadConfig(uint8 domain, uint8 bus, uint8 device, uint8 function, 1519 uint16 offset, uint8 size, uint32 *value) 1520 { 1521 domain_data *info = _GetDomainData(domain); 1522 if (!info) 1523 return B_ERROR; 1524 1525 if (device > (info->max_bus_devices - 1) 1526 || function > 7 1527 || (size != 1 && size != 2 && size != 4) 1528 || (size == 2 && (offset & 3) == 3) 1529 || (size == 4 && (offset & 3) != 0)) { 1530 dprintf("PCI: can't read config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n", 1531 domain, bus, device, function, offset, size); 1532 return B_ERROR; 1533 } 1534 1535 return (*info->controller->read_pci_config)(info->controller_cookie, bus, 1536 device, function, offset, size, value); 1537 } 1538 1539 1540 uint32 1541 PCI::ReadConfig(uint8 domain, uint8 bus, uint8 device, uint8 function, 1542 uint16 offset, uint8 size) 1543 { 1544 uint32 value; 1545 if (ReadConfig(domain, bus, device, function, offset, size, &value) 1546 != B_OK) 1547 return 0xffffffff; 1548 1549 return value; 1550 } 1551 1552 1553 uint32 1554 PCI::ReadConfig(PCIDev *device, uint16 offset, uint8 size) 1555 { 1556 uint32 value; 1557 if (ReadConfig(device->domain, device->bus, device->device, 1558 device->function, offset, size, &value) != B_OK) 1559 return 0xffffffff; 1560 1561 return value; 1562 } 1563 1564 1565 status_t 1566 PCI::WriteConfig(uint8 domain, uint8 bus, uint8 device, uint8 function, 1567 uint16 offset, uint8 size, uint32 value) 1568 { 1569 domain_data *info = _GetDomainData(domain); 1570 if (!info) 1571 return B_ERROR; 1572 1573 if (device > (info->max_bus_devices - 1) 1574 || function > 7 1575 || (size != 1 && size != 2 && size != 4) 1576 || (size == 2 && (offset & 3) == 3) 1577 || (size == 4 && (offset & 3) != 0)) { 1578 dprintf("PCI: can't write config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n", 1579 domain, bus, device, function, offset, size); 1580 return B_ERROR; 1581 } 1582 1583 return (*info->controller->write_pci_config)(info->controller_cookie, bus, 1584 device, function, offset, size, value); 1585 } 1586 1587 1588 status_t 1589 PCI::WriteConfig(PCIDev *device, uint16 offset, uint8 size, uint32 value) 1590 { 1591 return WriteConfig(device->domain, device->bus, device->device, 1592 device->function, offset, size, value); 1593 } 1594 1595 1596 status_t 1597 PCI::FindCapability(uint8 domain, uint8 bus, uint8 device, uint8 function, 1598 uint8 capID, uint8 *offset) 1599 { 1600 uint16 status = ReadConfig(domain, bus, device, function, PCI_status, 2); 1601 if (!(status & PCI_status_capabilities)) { 1602 FLOW("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x " 1603 "not supported\n", bus, device, function, capID); 1604 return B_ERROR; 1605 } 1606 1607 uint8 headerType = ReadConfig(domain, bus, device, function, 1608 PCI_header_type, 1); 1609 uint8 capPointer; 1610 1611 switch (headerType & PCI_header_type_mask) { 1612 case PCI_header_type_generic: 1613 case PCI_header_type_PCI_to_PCI_bridge: 1614 capPointer = PCI_capabilities_ptr; 1615 break; 1616 case PCI_header_type_cardbus: 1617 capPointer = PCI_capabilities_ptr_2; 1618 break; 1619 default: 1620 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability " 1621 "%#02x unknown header type\n", bus, device, function, capID); 1622 return B_ERROR; 1623 } 1624 1625 capPointer = ReadConfig(domain, bus, device, function, capPointer, 1); 1626 capPointer &= ~3; 1627 if (capPointer == 0) { 1628 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x " 1629 "empty list\n", bus, device, function, capID); 1630 return B_NAME_NOT_FOUND; 1631 } 1632 1633 for (int i = 0; i < 48; i++) { 1634 if (ReadConfig(domain, bus, device, function, capPointer, 1) == capID) { 1635 if (offset != NULL) 1636 *offset = capPointer; 1637 return B_OK; 1638 } 1639 1640 capPointer = ReadConfig(domain, bus, device, function, capPointer + 1, 1641 1); 1642 capPointer &= ~3; 1643 1644 if (capPointer == 0) 1645 return B_NAME_NOT_FOUND; 1646 } 1647 1648 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x circular list\n", bus, device, function, capID); 1649 return B_ERROR; 1650 } 1651 1652 1653 status_t 1654 PCI::FindCapability(PCIDev *device, uint8 capID, uint8 *offset) 1655 { 1656 return FindCapability(device->domain, device->bus, device->device, 1657 device->function, capID, offset); 1658 } 1659 1660 1661 status_t 1662 PCI::FindExtendedCapability(uint8 domain, uint8 bus, uint8 device, 1663 uint8 function, uint16 capID, uint16 *offset) 1664 { 1665 if (FindCapability(domain, bus, device, function, PCI_cap_id_pcie) 1666 != B_OK) { 1667 FLOW("PCI:FindExtendedCapability ERROR %u:%u:%u capability %#02x " 1668 "not supported\n", bus, device, function, capID); 1669 return B_ERROR; 1670 } 1671 uint16 capPointer = PCI_extended_capability; 1672 uint32 capability = ReadConfig(domain, bus, device, function, 1673 capPointer, 4); 1674 1675 if (capability == 0 || capability == 0xffffffff) 1676 return B_NAME_NOT_FOUND; 1677 1678 for (int i = 0; i < 48; i++) { 1679 if (PCI_extcap_id(capability) == capID) { 1680 if (offset != NULL) 1681 *offset = capPointer; 1682 return B_OK; 1683 } 1684 1685 capPointer = PCI_extcap_next_ptr(capability) & ~3; 1686 if (capPointer < PCI_extended_capability) 1687 return B_NAME_NOT_FOUND; 1688 capability = ReadConfig(domain, bus, device, function, 1689 capPointer, 4); 1690 } 1691 1692 TRACE_CAP("PCI:FindExtendedCapability ERROR %u:%u:%u capability %#04x " 1693 "circular list\n", bus, device, function, capID); 1694 return B_ERROR; 1695 } 1696 1697 1698 status_t 1699 PCI::FindExtendedCapability(PCIDev *device, uint16 capID, uint16 *offset) 1700 { 1701 return FindExtendedCapability(device->domain, device->bus, device->device, 1702 device->function, capID, offset); 1703 } 1704 1705 1706 status_t 1707 PCI::FindHTCapability(uint8 domain, uint8 bus, uint8 device, 1708 uint8 function, uint16 capID, uint8 *offset) 1709 { 1710 uint8 capPointer; 1711 // consider the passed offset as the current ht capability block pointer 1712 // when it's non zero 1713 if (offset != NULL && *offset != 0) { 1714 capPointer = ReadConfig(domain, bus, device, function, *offset + 1, 1715 1); 1716 } else if (FindCapability(domain, bus, device, function, PCI_cap_id_ht, 1717 &capPointer) != B_OK) { 1718 FLOW("PCI:FindHTCapability ERROR %u:%u:%u capability %#02x " 1719 "not supported\n", bus, device, function, capID); 1720 return B_NAME_NOT_FOUND; 1721 } 1722 1723 uint16 mask = PCI_ht_command_cap_mask_5_bits; 1724 if (capID == PCI_ht_command_cap_slave || capID == PCI_ht_command_cap_host) 1725 mask = PCI_ht_command_cap_mask_3_bits; 1726 for (int i = 0; i < 48; i++) { 1727 capPointer &= ~3; 1728 if (capPointer == 0) 1729 return B_NAME_NOT_FOUND; 1730 1731 uint8 capability = ReadConfig(domain, bus, device, function, 1732 capPointer, 1); 1733 if (capability == PCI_cap_id_ht) { 1734 if ((ReadConfig(domain, bus, device, function, 1735 capPointer + PCI_ht_command, 2) & mask) == capID) { 1736 if (offset != NULL) 1737 *offset = capPointer; 1738 return B_OK; 1739 } 1740 } 1741 1742 capPointer = ReadConfig(domain, bus, device, function, capPointer + 1, 1743 1); 1744 } 1745 1746 TRACE_CAP("PCI:FindHTCapability ERROR %u:%u:%u capability %#04x " 1747 "circular list\n", bus, device, function, capID); 1748 return B_ERROR; 1749 } 1750 1751 1752 status_t 1753 PCI::FindHTCapability(PCIDev *device, uint16 capID, uint8 *offset) 1754 { 1755 return FindHTCapability(device->domain, device->bus, device->device, 1756 device->function, capID, offset); 1757 } 1758 1759 1760 PCIDev * 1761 PCI::FindDevice(uint8 domain, uint8 bus, uint8 device, uint8 function) 1762 { 1763 return _FindDevice(fRootBus, domain, bus, device, function); 1764 } 1765 1766 1767 PCIDev * 1768 PCI::_FindDevice(PCIBus *current, uint8 domain, uint8 bus, uint8 device, 1769 uint8 function) 1770 { 1771 if (current->domain == domain) { 1772 // search device on this bus 1773 1774 for (PCIDev *child = current->child; child != NULL; 1775 child = child->next) { 1776 if (child->bus == bus && child->device == device 1777 && child->function == function) 1778 return child; 1779 1780 if (child->child != NULL) { 1781 // search child busses 1782 PCIDev *found = _FindDevice(child->child, domain, bus, device, 1783 function); 1784 if (found != NULL) 1785 return found; 1786 } 1787 } 1788 } 1789 1790 // search other busses 1791 if (current->next != NULL) 1792 return _FindDevice(current->next, domain, bus, device, function); 1793 1794 return NULL; 1795 } 1796 1797 1798 status_t 1799 PCI::UpdateInterruptLine(uint8 domain, uint8 bus, uint8 _device, uint8 function, 1800 uint8 newInterruptLineValue) 1801 { 1802 PCIDev *device = FindDevice(domain, bus, _device, function); 1803 if (device == NULL) 1804 return B_ERROR; 1805 1806 pci_info &info = device->info; 1807 switch (info.header_type & PCI_header_type_mask) { 1808 case PCI_header_type_generic: 1809 info.u.h0.interrupt_line = newInterruptLineValue; 1810 break; 1811 1812 case PCI_header_type_PCI_to_PCI_bridge: 1813 info.u.h1.interrupt_line = newInterruptLineValue; 1814 break; 1815 1816 default: 1817 return B_ERROR; 1818 } 1819 1820 return WriteConfig(device, PCI_interrupt_line, 1, newInterruptLineValue); 1821 } 1822 1823 1824 uint8 1825 PCI::GetPowerstate(PCIDev *device) 1826 { 1827 uint8 capabilityOffset; 1828 status_t res = FindCapability(device, PCI_cap_id_pm, &capabilityOffset); 1829 if (res == B_OK) { 1830 uint32 state = ReadConfig(device, capabilityOffset + PCI_pm_status, 2); 1831 return (state & PCI_pm_mask); 1832 } 1833 return PCI_pm_state_d0; 1834 } 1835 1836 1837 void 1838 PCI::SetPowerstate(PCIDev *device, uint8 newState) 1839 { 1840 uint8 capabilityOffset; 1841 status_t res = FindCapability(device, PCI_cap_id_pm, &capabilityOffset); 1842 if (res == B_OK) { 1843 uint32 state = ReadConfig(device, capabilityOffset + PCI_pm_status, 2); 1844 if ((state & PCI_pm_mask) != newState) { 1845 WriteConfig(device, capabilityOffset + PCI_pm_status, 2, 1846 (state & ~PCI_pm_mask) | newState); 1847 if ((state & PCI_pm_mask) == PCI_pm_state_d3) 1848 snooze(10); 1849 } 1850 } 1851 } 1852 1853