Ticket #7520: pci_route_fallback.diff
File pci_route_fallback.diff, 7.9 KB (added by , 13 years ago) |
---|
-
src/system/kernel/arch/x86/irq_routing_table.cpp
16 16 #include <PCI.h> 17 17 18 18 19 //#define TRACE_PRT19 #define TRACE_PRT 20 20 #ifdef TRACE_PRT 21 21 # define TRACE(x...) dprintf("IRQRoutingTable: "x) 22 22 #else … … 32 32 33 33 // TODO: as per PCI 3.0, the PCI module hardcodes it in various places as well. 34 34 static const uint8 kMaxPCIFunctionCount = 8; 35 static const uint8 kMaxPCIDeviceCount = 32; 36 // TODO: actually this is mechanism dependent 35 37 static const uint8 kMaxISAInterrupts = 16; 36 38 37 39 irq_descriptor::irq_descriptor() … … 388 390 dprintf("no matching PCI device for irq entry: "); 389 391 print_irq_routing_entry(irqEntry); 390 392 #endif 391 return status;392 393 } else { 393 394 #ifdef TRACE_PRT 394 395 dprintf("found matching PCI device for irq entry: "); … … 408 409 } 409 410 410 411 412 irq_routing_entry* 413 find_routing_table_entry(IRQRoutingTable& table, uint8 bus, uint8 device, 414 uint8 pin) 415 { 416 for (int i = 0; i < table.Count(); i++) { 417 irq_routing_entry& irqEntry = table.ElementAt(i); 418 if (irqEntry.pci_bus != bus || irqEntry.pci_device != device) 419 continue; 420 421 if (irqEntry.pin + 1 == pin) 422 return &irqEntry; 423 } 424 425 return NULL; 426 } 427 428 411 429 static status_t 430 ensure_all_functions_matched(pci_module_info* pci, uint8 bus, 431 IRQRoutingTable& matchedTable, IRQRoutingTable& unmatchedTable, 432 Vector<pci_address>& parents) 433 { 434 for (uint8 device = 0; device < kMaxPCIDeviceCount; device++) { 435 if (pci->read_pci_config(bus, device, 0, PCI_vendor_id, 2) == 0xffff) { 436 // not present 437 continue; 438 } 439 440 uint8 headerType = pci->read_pci_config(bus, device, 0, 441 PCI_header_type, 1); 442 443 uint8 functionCount = 1; 444 if ((headerType & PCI_multifunction) != 0) 445 functionCount = kMaxPCIFunctionCount; 446 447 for (uint8 function = 0; function < functionCount; function++) { 448 // check for device presence by looking for a valid vendor 449 if (pci->read_pci_config(bus, device, function, PCI_vendor_id, 2) 450 == 0xffff) { 451 // not present 452 continue; 453 } 454 455 if (function > 0) { 456 headerType = pci->read_pci_config(bus, device, function, 457 PCI_header_type, 1); 458 } 459 460 // if this is a bridge, recurse down 461 if ((headerType & PCI_header_type_mask) 462 == PCI_header_type_PCI_to_PCI_bridge) { 463 464 pci_address pciAddress; 465 pciAddress.bus = bus; 466 pciAddress.device = device; 467 pciAddress.function = function; 468 469 parents.PushBack(pciAddress); 470 471 uint8 secondaryBus = pci->read_pci_config(bus, device, function, 472 PCI_secondary_bus, 1); 473 if (secondaryBus != 0xff) { 474 ensure_all_functions_matched(pci, secondaryBus, 475 matchedTable, unmatchedTable, parents); 476 } 477 478 parents.PopBack(); 479 } 480 481 uint8 interruptPin = pci->read_pci_config(bus, device, function, 482 PCI_interrupt_pin, 1); 483 if (interruptPin == 0 || interruptPin > 4) { 484 // not routed 485 continue; 486 } 487 488 irq_routing_entry* irqEntry = find_routing_table_entry(matchedTable, 489 bus, device, interruptPin); 490 if (irqEntry != NULL) { 491 // we already have a matching entry for that device/pin, make 492 // sure the function mask includes us 493 irqEntry->pci_function_mask |= 1 << function; 494 continue; 495 } 496 497 // This function has no matching routing table entry yet. Try to 498 // figure one out in the parent, based on the device number and 499 // interrupt pin. 500 bool matched = false; 501 uint8 parentPin = ((device + interruptPin - 1) % 4) + 1; 502 for (int i = parents.Count() - 1; i >= 0; i--) { 503 pci_address& parent = parents.ElementAt(i); 504 irqEntry = find_routing_table_entry(matchedTable, parent.bus, 505 parent.device, parentPin); 506 if (irqEntry == NULL) { 507 // try the unmatched table as well 508 irqEntry = find_routing_table_entry(unmatchedTable, 509 parent.bus, parent.device, parentPin); 510 } 511 512 if (irqEntry == NULL) { 513 // no match in that parent, go further up 514 parentPin = ((parent.device + parentPin - 1) % 4) + 1; 515 continue; 516 } 517 518 // found a match, make a copy and add it to the table 519 irq_routing_entry newEntry = *irqEntry; 520 newEntry.device_address = (device << 16) | 0xffff; 521 newEntry.pin = interruptPin - 1; 522 newEntry.pci_bus = bus; 523 newEntry.pci_device = device; 524 newEntry.pci_function_mask = 1 << function; 525 526 if (newEntry.bios_irq != 0 && newEntry.bios_irq != 255) { 527 uint8 biosIRQ = pci->read_pci_config(bus, device, function, 528 PCI_interrupt_line, 1); 529 if (biosIRQ != 0 && biosIRQ != 255 530 && newEntry.bios_irq != biosIRQ) { 531 // If the function was actually routed to that pin, 532 // the two bios irqs should match. If they don't 533 // that means we're not correct in our routing 534 // assumption. 535 panic("calculated irq routing doesn't match bios for " 536 "PCI %u:%u:%u", bus, device, function); 537 newEntry.bios_irq = biosIRQ; 538 return B_ERROR; 539 } 540 } 541 542 dprintf("calculated irq routing entry: "); 543 print_irq_routing_entry(newEntry); 544 545 matchedTable.PushBack(newEntry); 546 matched = true; 547 break; 548 } 549 550 if (!matched) { 551 panic("unable to find irq routing for PCI %u:%u:%u", bus, 552 device, function); 553 return B_ERROR; 554 } 555 } 556 } 557 558 return B_OK; 559 } 560 561 562 static status_t 412 563 read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, 413 564 acpi_handle device, uint8 currentBus, IRQRoutingTable& table, 414 bool rootBridge, interrupt_available_check_function checkFunction) 565 IRQRoutingTable& unmatchedTable, bool rootBridge, 566 interrupt_available_check_function checkFunction) 415 567 { 416 568 if (!rootBridge) { 417 569 // check if this actually is a bridge … … 484 636 return B_ERROR; 485 637 } 486 638 487 table.PushBack(irqEntry); 639 if (irqEntry.pci_function_mask != 0) 640 table.PushBack(irqEntry); 641 else 642 unmatchedTable.PushBack(irqEntry); 488 643 } 489 644 490 645 acpiTable = (acpi_pci_routing_table*)((uint8*)acpiTable … … 496 651 TRACE("no irq routing table present\n"); 497 652 } 498 653 499 // recurse down t o thechild devices654 // recurse down the ACPI child devices 500 655 acpi_data pathBuffer; 501 656 pathBuffer.pointer = NULL; 502 657 pathBuffer.length = ACPI_ALLOCATE_BUFFER; … … 520 675 521 676 TRACE("recursing down to child \"%s\"\n", childName); 522 677 status = read_irq_routing_table_recursive(acpi, pci, childHandle, 523 currentBus, table, false, checkFunction);678 currentBus, table, unmatchedTable, false, checkFunction); 524 679 if (status != B_OK) 525 680 break; 526 681 } … … 568 723 return status; 569 724 } 570 725 726 IRQRoutingTable unmatchedTable; 571 727 status = read_irq_routing_table_recursive(acpi, pci, rootPciHandle, rootBus, 572 table, true, checkFunction); 728 table, unmatchedTable, true, checkFunction); 729 if (status != B_OK) { 730 put_module(B_PCI_MODULE_NAME); 731 return status; 732 } 573 733 574 put_module(B_PCI_MODULE_NAME); 734 if (table.Count() == 0) { 735 put_module(B_PCI_MODULE_NAME); 736 return B_ERROR; 737 } 575 738 576 if (status != B_OK) 577 return status; 739 // Now go through all the PCI devices and verify that they have a routing 740 // table entry. For the devices without a match, we calculate their pins 741 // on the bridges and try to match these in the parent routing table. We 742 // do this recursively going up the tree until we find a match or arrive 743 // at the top. 744 Vector<pci_address> parents; 745 status = ensure_all_functions_matched(pci, rootBus, table, unmatchedTable, 746 parents); 578 747 579 return table.Count() > 0 ? B_OK : B_ERROR; 748 put_module(B_PCI_MODULE_NAME); 749 return status; 580 750 } 581 751 582 752 … … 618 788 619 789 status = update_pci_info_for_entry(pci, irqEntry); 620 790 if (status != B_OK) { 621 #ifdef TRACE_PRT 622 dprintf("failed to update interrupt_line info for entry:\n"); 623 print_irq_routing_entry(irqEntry); 624 #endif 791 panic("failed to update interrupt_line for PCI %u:%u mask %lx", 792 irqEntry.pci_bus, irqEntry.pci_device, 793 irqEntry.pci_function_mask); 625 794 } 626 795 } 627 796