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