PCI: handle "non fixed" addresses

If the max address for a PCI bus is not fixed, try to compute it from
the minimum and length (if available).

Change-Id: I23d87da32779d22324f944b5b359390f523ec7a7
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7111
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
PulkoMandy 2023-11-15 14:39:37 +01:00 committed by waddlesplash
parent a38355a483
commit 8e4a60d3f1

View File

@ -83,6 +83,35 @@ ECAMPCIControllerACPI::AcpiCrsScanCallback(acpi_resource *res, void *context)
}
/** Convert an ACPI address resource descriptor into a pci_resource_range.
*
* This is a template because ACPI resources can be encoded using 8, 16, 32 or 64 bit values.
*/
template<typename T> void
DecodeAddress(const T& resource, pci_resource_range& range)
{
const auto& acpiRange = resource.address;
dprintf("PCI: range from ACPI [%lx(%d),%lx(%d)] with length %lx\n",
(unsigned long)acpiRange.minimum, resource.minAddress_fixed,
(unsigned long)acpiRange.maximum, resource.maxAddress_fixed,
(unsigned long)acpiRange.address_length);
// If address_length isn't set, compute it from minimum and maximum
// If maximum isn't set, compute it from minimum and length
auto addressLength = acpiRange.address_length;
phys_addr_t addressMaximum = acpiRange.maximum;
if (addressLength == 0)
addressLength = acpiRange.maximum - acpiRange.minimum + 1;
else if (!resource.maxAddress_fixed)
addressMaximum = acpiRange.minimum + addressLength - 1;
ASSERT((phys_addr_t)(acpiRange.minimum + addressLength - 1) == addressMaximum);
range.host_addr = acpiRange.minimum + acpiRange.translation_offset;
range.pci_addr = acpiRange.minimum;
range.size = addressLength;
}
acpi_status
ECAMPCIControllerACPI::AcpiCrsScanCallbackInt(acpi_resource *res)
{
@ -108,39 +137,18 @@ ECAMPCIControllerACPI::AcpiCrsScanCallbackInt(acpi_resource *res)
switch (res->type) {
case ACPI_RESOURCE_TYPE_ADDRESS16: {
const auto &address = res->data.address16.address;
// If address_length isn't set, compute it from minimum and maximum
auto address_length = address.address_length;
if (address_length == 0)
address_length = address.maximum - address.minimum + 1;
ASSERT(address.minimum + address_length - 1 == address.maximum);
range.host_addr = address.minimum + address.translation_offset;
range.pci_addr = address.minimum;
range.size = address_length;
const auto &address = res->data.address16;
DecodeAddress(address, range);
break;
}
case ACPI_RESOURCE_TYPE_ADDRESS32: {
const auto &address = res->data.address32.address;
// If address_length isn't set, compute it from minimum and maximum
auto address_length = address.address_length;
if (address_length == 0)
address_length = address.maximum - address.minimum + 1;
ASSERT(address.minimum + address_length - 1 == address.maximum);
range.host_addr = address.minimum + address.translation_offset;
range.pci_addr = address.minimum;
range.size = address_length;
const auto &address = res->data.address32;
DecodeAddress(address, range);
break;
}
case ACPI_RESOURCE_TYPE_ADDRESS64: {
const auto &address = res->data.address64.address;
// If address_length isn't set, compute it from minimum and maximum
auto address_length = address.address_length;
if (address_length == 0)
address_length = address.maximum - address.minimum + 1;
ASSERT(address.minimum + address_length - 1 == address.maximum);
range.host_addr = address.minimum + address.translation_offset;
range.pci_addr = address.minimum;
range.size = address_length;
const auto &address = res->data.address64;
DecodeAddress(address, range);
break;
}
}