[haiku-commits] r41395 - haiku/trunk/src/system/kernel/arch/x86

Author: mmlr
Date: 2011-05-09 13:53:52 +0200 (Mon, 09 May 2011)
New Revision: 41395
Changeset: https://dev.haiku-os.org/changeset/41395

Modified:
   haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp
Log:
Do the PCI device matching using direct PCI config space matches instead of
using the already parsed pci_info data from the PCI module. This removes the
need to iterate over all of the pci_infos for each routing table entries which
makes this an order of magnitude less expensive. Heavily inspired by the
corresponding FreeBSD code.


Modified: haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp        
2011-05-09 11:49:03 UTC (rev 41394)
+++ haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp        
2011-05-09 11:53:52 UTC (rev 41395)
@@ -86,46 +86,49 @@
 static status_t
 update_pci_info_for_entry(pci_module_info* pci, irq_routing_entry& entry)
 {
-       pci_info info;
-       long index = 0;
-       uint32 updateCount = 0;
-       while (pci->get_nth_pci_info(index++, &info) >= 0) {
-               if (info.bus != entry.pci_bus || info.device != 
entry.pci_device)
-                       continue;
+       // check the base device at function 0
+       uint8 headerType = pci->read_pci_config(entry.pci_bus, 
entry.pci_device, 0,
+               PCI_header_type, 1);
+       switch (headerType & PCI_header_type_mask) {
+               case PCI_header_type_generic:
+               case PCI_header_type_PCI_to_PCI_bridge:
+                       // We don't really care about bridges as we won't 
install
+                       // interrupt handlers for them, but we can still map 
them and
+                       // update their info for completeness.
+                       break;
 
-               uint8 pin = 0;
-               switch (info.header_type & PCI_header_type_mask) {
-                       case PCI_header_type_generic:
-                               pin = info.u.h0.interrupt_pin;
-                               break;
+               default:
+                       // either an unsupported or a non-present device (0xff)
+                       return B_ENTRY_NOT_FOUND;
+       }
 
-                       case PCI_header_type_PCI_to_PCI_bridge:
-                               // We don't really care about bridges as we 
won't install
-                               // interrupt handlers for them, but we can 
still map them and
-                               // update their info for completeness.
-                               pin = info.u.h1.interrupt_pin;
-                               break;
+       // we have a device, check how many functions we need to iterate
+       uint8 functionCount = 1;
+       if ((headerType & PCI_multifunction) != 0) {
+               functionCount = 8;
+                       // TODO: as per PCI 3.0, the PCI module hardcodes it in 
various
+                       // places as well...
+       }
 
-                       default:
-                               // Skip anything unknown as we wouldn't know 
how to update the
-                               // info anyway.
-                               continue;
-               }
+       uint32 updateCount = 0;
+       for (uint8 function = 0; function < functionCount; function++) {
+               // check for device presence by looking for a valid vendor
+               uint16 vendorId = pci->read_pci_config(entry.pci_bus, 
entry.pci_device,
+                       function, PCI_vendor_id, 2);
+               if (vendorId == 0xffff)
+                       continue;
 
-               if (pin == 0)
-                       continue; // no interrupts are used
+               uint8 interruptPin = pci->read_pci_config(entry.pci_bus,
+                       entry.pci_device, function, PCI_interrupt_pin, 1);
 
-               // Now match the pin to find the corresponding function, note 
that PCI
-               // pins are 1 based while ACPI ones are 0 based.
-               if (pin == entry.pin + 1) {
-                       if (pci->update_interrupt_line(info.bus, info.device, 
info.function,
-                               entry.irq) == B_OK) {
+               // Finally match the pin with the entry, note that PCI pins are 
1 based
+               // while ACPI ones are 0 based.
+               if (interruptPin == entry.pin + 1) {
+                       if (pci->update_interrupt_line(entry.pci_bus, 
entry.pci_device,
+                               function, entry.irq) == B_OK) {
                                updateCount++;
                        }
                }
-
-               // Sadly multiple functions can share the same interrupt pin so 
we
-               // have to run through the whole list each time...
        }
 
        return updateCount > 0 ? B_OK : B_ENTRY_NOT_FOUND;


Other related posts:

  • » [haiku-commits] r41395 - haiku/trunk/src/system/kernel/arch/x86 - mmlr