Stricter tests for PCI bridges at interrupt routing.
Validate the candidate child device a bit more by checking the device ID and the base and subclass of the device. We don't even know if the child is still on the PCI bus and some firmware may mark disabled devices by simply invalidating one of these values. Possibly fixes #8111. Added TODO concerning that we might not want to fail at all since we ensure that we matched all devices after routing preparation at which state we would notice any missing child devices anyway.
This commit is contained in:
@@ -595,6 +595,26 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify that the device is really present...
|
||||||
|
uint16 deviceID = pci->read_pci_config(pciAddress.bus,
|
||||||
|
pciAddress.device, pciAddress.function, PCI_device_id, 2);
|
||||||
|
if (deviceID == 0xffff) {
|
||||||
|
// Not present or disabled.
|
||||||
|
TRACE("device not present\n");
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... and that it really is a PCI bridge we support.
|
||||||
|
uint8 baseClass = pci->read_pci_config(pciAddress.bus,
|
||||||
|
pciAddress.device, pciAddress.function, PCI_class_base, 1);
|
||||||
|
uint8 subClass = pci->read_pci_config(pciAddress.bus,
|
||||||
|
pciAddress.device, pciAddress.function, PCI_class_sub, 1);
|
||||||
|
if (baseClass != PCI_bridge || subClass != PCI_pci) {
|
||||||
|
// Not a bridge or an unsupported one.
|
||||||
|
TRACE("not a PCI bridge\n");
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
uint8 headerType = pci->read_pci_config(pciAddress.bus,
|
uint8 headerType = pci->read_pci_config(pciAddress.bus,
|
||||||
pciAddress.device, pciAddress.function, PCI_header_type, 1);
|
pciAddress.device, pciAddress.function, PCI_header_type, 1);
|
||||||
|
|
||||||
@@ -605,8 +625,8 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Simply not a bridge or not present at all.
|
// Unsupported header type.
|
||||||
TRACE("not a PCI bridge (0x%02x)\n", headerType);
|
TRACE("unsupported header type (0x%02x)\n", headerType);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,6 +645,11 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
|||||||
dprintf("invalid secondary bus %u on primary bus %u,"
|
dprintf("invalid secondary bus %u on primary bus %u,"
|
||||||
" can't configure irq routing of devices below\n",
|
" can't configure irq routing of devices below\n",
|
||||||
secondaryBus, currentBus);
|
secondaryBus, currentBus);
|
||||||
|
// TODO: Maybe we want to just return B_OK anyway so that we don't
|
||||||
|
// fail this step. We ensure that we matched all devices at the
|
||||||
|
// end of preparation, so we'd detect missing child devices anyway
|
||||||
|
// and it would not cause us to fail for empty misconfigured busses
|
||||||
|
// that we don't actually care about.
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user