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