PCI: Support more than 6 PCI memory ranges.
Also use the standard kernel-wide constants for IO or memory space rather than defining new ones, as well as the PCI constants for address types. Change-Id: Iad03f7666ad5121a5c9a398339aa1a191339a1d1 Reviewed-on: https://review.haiku-os.org/c/haiku/+/7336 Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
6533df4fe4
commit
fabb71cc0e
@ -58,20 +58,11 @@ typedef struct pci_device_module_info {
|
||||
} pci_device_module_info;
|
||||
|
||||
|
||||
enum {
|
||||
kPciRangeInvalid = 0,
|
||||
kPciRangeIoPort = 1,
|
||||
kPciRangeMmio = 2,
|
||||
kPciRangeMmio64Bit = 1 << 0,
|
||||
kPciRangeMmioPrefetch = 1 << 1,
|
||||
kPciRangeMmioEnd = 6,
|
||||
kPciRangeEnd = 6,
|
||||
};
|
||||
|
||||
typedef struct pci_resource_range {
|
||||
uint32 type;
|
||||
phys_addr_t host_addr;
|
||||
phys_addr_t pci_addr;
|
||||
uint8 address_type;
|
||||
phys_addr_t host_address;
|
||||
phys_addr_t pci_address;
|
||||
uint64 size;
|
||||
} pci_resource_range;
|
||||
|
||||
|
@ -81,8 +81,8 @@ pci_ram_address(phys_addr_t childAdr)
|
||||
#else
|
||||
uint8 domain;
|
||||
pci_resource_range range;
|
||||
if (gPCI->LookupRange(kPciRangeMmio, childAdr, domain, range) >= B_OK)
|
||||
hostAdr = childAdr - range.pci_addr + range.host_addr;
|
||||
if (gPCI->LookupRange(B_IO_MEMORY, childAdr, domain, range) >= B_OK)
|
||||
hostAdr = childAdr - range.pci_address + range.host_address;
|
||||
#endif
|
||||
//dprintf("pci_ram_address(%#" B_PRIx64 ") -> %#" B_PRIx64 "\n", childAdr, hostAdr);
|
||||
return hostAdr;
|
||||
@ -673,33 +673,27 @@ status_t
|
||||
PCI::LookupRange(uint32 type, phys_addr_t pciAddr,
|
||||
uint8 &domain, pci_resource_range &range, uint8 **mappedAdr)
|
||||
{
|
||||
if (type >= kPciRangeEnd)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
for (uint8 curDomain = 0; curDomain < fDomainCount; curDomain++) {
|
||||
pci_resource_range const *const &ranges = fDomainData[curDomain].ranges;
|
||||
const auto &ranges = fDomainData[curDomain].ranges;
|
||||
|
||||
uint32 typeBeg, typeEnd;
|
||||
if (type == kPciRangeMmio) {
|
||||
typeBeg = kPciRangeMmio;
|
||||
typeEnd = kPciRangeMmioEnd;
|
||||
} else {
|
||||
typeBeg = type;
|
||||
typeEnd = type + 1;
|
||||
}
|
||||
for (uint32 curType = typeBeg; curType < typeEnd; curType++) {
|
||||
const pci_resource_range curRange = ranges[curType];
|
||||
if (pciAddr >= curRange.pci_addr && pciAddr < curRange.pci_addr + curRange.size) {
|
||||
for (int32 i = 0; i < ranges.Count(); i++) {
|
||||
const pci_resource_range curRange = ranges[i];
|
||||
if (curRange.type != type)
|
||||
continue;
|
||||
|
||||
if (pciAddr >= curRange.pci_address
|
||||
&& pciAddr < (curRange.pci_address + curRange.size)) {
|
||||
domain = curDomain;
|
||||
range = curRange;
|
||||
#if !(defined(__i386__) || defined(__x86_64__))
|
||||
if (type == kPciRangeIoPort && mappedAdr != NULL)
|
||||
if (type == B_IO_PORT && mappedAdr != NULL)
|
||||
*mappedAdr = fDomainData[curDomain].io_port_adr;
|
||||
#endif
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
@ -716,23 +710,27 @@ PCI::InitDomainData(domain_data &data)
|
||||
status = ctrl->get_max_bus_devices(ctrlCookie, &count);
|
||||
data.max_bus_devices = (status == B_OK) ? count : 0;
|
||||
|
||||
memset(data.ranges, 0, sizeof(data.ranges));
|
||||
pci_resource_range range;
|
||||
for (uint32 j = 0; ctrl->get_range(ctrlCookie, j, &range) >= B_OK; j++) {
|
||||
if (range.type < kPciRangeEnd && range.size > 0)
|
||||
data.ranges[range.type] = range;
|
||||
}
|
||||
for (uint32 j = 0; ctrl->get_range(ctrlCookie, j, &range) >= B_OK; j++)
|
||||
data.ranges.Add(range);
|
||||
|
||||
#if !(defined(__i386__) || defined(__x86_64__))
|
||||
// TODO: free resources when domain is detached
|
||||
pci_resource_range &ioPortRange = data.ranges[kPciRangeIoPort];
|
||||
if (ioPortRange.size > 0) {
|
||||
data.io_port_area = map_physical_memory("PCI IO Ports",
|
||||
ioPortRange.host_addr, ioPortRange.size, B_ANY_KERNEL_ADDRESS,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void **)&data.io_port_adr);
|
||||
for (int32 i = 0; i < data.ranges.Count(); i++) {
|
||||
pci_resource_range &ioPortRange = data.ranges[i];
|
||||
if (ioPortRange.type != B_IO_PORT)
|
||||
continue;
|
||||
|
||||
if (data.io_port_area < B_OK)
|
||||
data.io_port_adr = NULL;
|
||||
if (ioPortRange.size > 0) {
|
||||
data.io_port_area = map_physical_memory("PCI IO Ports",
|
||||
ioPortRange.host_address, ioPortRange.size, B_ANY_KERNEL_ADDRESS,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void **)&data.io_port_adr);
|
||||
|
||||
if (data.io_port_area < B_OK)
|
||||
data.io_port_adr = NULL;
|
||||
|
||||
// TODO: Map other IO ports (if any.)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -47,6 +47,14 @@ struct PCIDev {
|
||||
|
||||
|
||||
struct domain_data {
|
||||
~domain_data()
|
||||
{
|
||||
#if !(defined(__i386__) || defined(__x86_64__))
|
||||
if (io_port_area >= 0)
|
||||
delete_area(io_port_area);
|
||||
#endif
|
||||
}
|
||||
|
||||
// These two are set in PCI::AddController:
|
||||
pci_controller_module_info *controller;
|
||||
void * controller_cookie;
|
||||
@ -55,11 +63,11 @@ struct domain_data {
|
||||
|
||||
// All the rest is set in PCI::InitDomainData
|
||||
int max_bus_devices;
|
||||
pci_resource_range ranges[kPciRangeEnd];
|
||||
Vector<pci_resource_range> ranges;
|
||||
|
||||
#if !(defined(__i386__) || defined(__x86_64__))
|
||||
area_id io_port_area;
|
||||
uint8 * io_port_adr;
|
||||
area_id io_port_area = -1;
|
||||
uint8 * io_port_adr = NULL;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -201,28 +201,30 @@ DWPCIController::ReadResourceInfo()
|
||||
uint64_t parentAdr = B_BENDIAN_TO_HOST_INT64(*(uint64_t*)(it + 3));
|
||||
uint64_t len = B_BENDIAN_TO_HOST_INT64(*(uint64_t*)(it + 5));
|
||||
|
||||
uint32 outType = kPciRangeInvalid;
|
||||
pci_resource_range range = {};
|
||||
range.host_address = parentAdr;
|
||||
range.pci_address = childAdr;
|
||||
range.size = len;
|
||||
|
||||
if ((type & fdtPciRangePrefechable) != 0)
|
||||
range.address_type |= PCI_address_prefetchable;
|
||||
|
||||
switch (type & fdtPciRangeTypeMask) {
|
||||
case fdtPciRangeIoPort:
|
||||
outType = kPciRangeIoPort;
|
||||
range.type = B_IO_PORT;
|
||||
fResourceRanges.Add(range);
|
||||
break;
|
||||
case fdtPciRangeMmio32Bit:
|
||||
outType = kPciRangeMmio;
|
||||
range.type = B_IO_MEMORY;
|
||||
range.address_type |= PCI_address_type_32;
|
||||
fResourceRanges.Add(range);
|
||||
break;
|
||||
case fdtPciRangeMmio64Bit:
|
||||
outType = kPciRangeMmio + kPciRangeMmio64Bit;
|
||||
range.type = B_IO_MEMORY;
|
||||
range.address_type |= PCI_address_type_64;
|
||||
fResourceRanges.Add(range);
|
||||
break;
|
||||
}
|
||||
if (outType >= kPciRangeMmio && outType < kPciRangeMmioEnd
|
||||
&& (fdtPciRangePrefechable & type) != 0)
|
||||
outType += kPciRangeMmioPrefetch;
|
||||
|
||||
if (outType != kPciRangeInvalid) {
|
||||
fResourceRanges[outType].type = outType;
|
||||
fResourceRanges[outType].host_addr = parentAdr;
|
||||
fResourceRanges[outType].pci_addr = childAdr;
|
||||
fResourceRanges[outType].size = len;
|
||||
}
|
||||
|
||||
switch (type & fdtPciRangeTypeMask) {
|
||||
case fdtPciRangeConfig: dprintf("CONFIG"); break;
|
||||
@ -392,7 +394,7 @@ DWPCIController::WriteIrq(uint8 bus, uint8 device, uint8 function,
|
||||
status_t
|
||||
DWPCIController::GetRange(uint32 index, pci_resource_range* range)
|
||||
{
|
||||
if (index >= kPciRangeEnd)
|
||||
if (index >= (uint32)fResourceRanges.Count())
|
||||
return B_BAD_INDEX;
|
||||
|
||||
*range = fResourceRanges[index];
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <AutoDeleterOS.h>
|
||||
#include <lock.h>
|
||||
#include <util/Vector.h>
|
||||
|
||||
|
||||
#define CHECK_RET(err) {status_t _err = (err); if (_err < B_OK) return _err;}
|
||||
@ -231,7 +232,7 @@ private:
|
||||
addr_t fConfigBase {};
|
||||
size_t fConfigSize {};
|
||||
|
||||
pci_resource_range fResourceRanges[kPciRangeEnd] {};
|
||||
Vector<pci_resource_range> fResourceRanges;
|
||||
InterruptMapMask fInterruptMapMask {};
|
||||
uint32 fInterruptMapLen {};
|
||||
ArrayDeleter<InterruptMap> fInterruptMap;
|
||||
|
@ -245,7 +245,7 @@ ECAMPCIController::WriteIrq(uint8 bus, uint8 device, uint8 function,
|
||||
status_t
|
||||
ECAMPCIController::GetRange(uint32 index, pci_resource_range* range)
|
||||
{
|
||||
if (index >= kPciRangeEnd)
|
||||
if (index >= (uint32)fResourceRanges.Count())
|
||||
return B_BAD_INDEX;
|
||||
|
||||
*range = fResourceRanges[index];
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <AutoDeleterOS.h>
|
||||
#include <lock.h>
|
||||
#include <util/Vector.h>
|
||||
|
||||
|
||||
#define CHECK_RET(err) {status_t _err = (err); if (_err < B_OK) return _err;}
|
||||
@ -128,7 +129,7 @@ protected:
|
||||
uint8 volatile* fRegs{};
|
||||
uint64 fRegsLen{};
|
||||
|
||||
pci_resource_range fResourceRanges[kPciRangeEnd] {};
|
||||
Vector<pci_resource_range> fResourceRanges;
|
||||
};
|
||||
|
||||
|
||||
|
@ -106,8 +106,8 @@ DecodeAddress(const T& resource, pci_resource_range& range)
|
||||
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.host_address = acpiRange.minimum + acpiRange.translation_offset;
|
||||
range.pci_address = acpiRange.minimum;
|
||||
range.size = addressLength;
|
||||
}
|
||||
|
||||
@ -115,44 +115,46 @@ DecodeAddress(const T& resource, pci_resource_range& range)
|
||||
acpi_status
|
||||
ECAMPCIControllerACPI::AcpiCrsScanCallbackInt(acpi_resource *res)
|
||||
{
|
||||
uint32 outType;
|
||||
|
||||
switch (res->data.address.resource_type) {
|
||||
case 0: // ACPI_MEMORY_RANGE
|
||||
outType = kPciRangeMmio;
|
||||
if (res->type == ACPI_RESOURCE_TYPE_ADDRESS64)
|
||||
outType += kPciRangeMmio64Bit;
|
||||
if (res->data.address.info.mem.caching == 3 /*ACPI_PREFETCHABLE_MEMORY*/)
|
||||
outType += kPciRangeMmioPrefetch;
|
||||
break;
|
||||
case 1: // ACPI_IO_RANGE
|
||||
outType = kPciRangeIoPort;
|
||||
break;
|
||||
default:
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
pci_resource_range& range = fResourceRanges[outType];
|
||||
range.type = outType;
|
||||
pci_resource_range range = {};
|
||||
|
||||
switch (res->type) {
|
||||
case ACPI_RESOURCE_TYPE_ADDRESS16: {
|
||||
const auto &address = res->data.address16;
|
||||
const auto& address = res->data.address16;
|
||||
DecodeAddress(address, range);
|
||||
break;
|
||||
}
|
||||
case ACPI_RESOURCE_TYPE_ADDRESS32: {
|
||||
const auto &address = res->data.address32;
|
||||
const auto& address = res->data.address32;
|
||||
DecodeAddress(address, range);
|
||||
range.address_type |= PCI_address_type_32;
|
||||
break;
|
||||
}
|
||||
case ACPI_RESOURCE_TYPE_ADDRESS64: {
|
||||
const auto &address = res->data.address64;
|
||||
const auto& address = res->data.address64;
|
||||
DecodeAddress(address, range);
|
||||
range.address_type |= PCI_address_type_64;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
switch (res->data.address.resource_type) {
|
||||
case 0: // ACPI_MEMORY_RANGE
|
||||
range.type = B_IO_MEMORY;
|
||||
if (res->data.address.info.mem.caching == 3 /*ACPI_PREFETCHABLE_MEMORY*/)
|
||||
range.address_type |= PCI_address_prefetchable;
|
||||
break;
|
||||
case 1: // ACPI_IO_RANGE
|
||||
range.type = B_IO_PORT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
fResourceRanges.Add(range);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -44,28 +44,30 @@ ECAMPCIControllerFDT::ReadResourceInfo()
|
||||
uint64_t parentAdr = B_BENDIAN_TO_HOST_INT64(*(uint64_t*)(it + 3));
|
||||
uint64_t len = B_BENDIAN_TO_HOST_INT64(*(uint64_t*)(it + 5));
|
||||
|
||||
uint32 outType = kPciRangeInvalid;
|
||||
pci_resource_range range = {};
|
||||
range.host_address = parentAdr;
|
||||
range.pci_address = childAdr;
|
||||
range.size = len;
|
||||
|
||||
if ((type & fdtPciRangePrefechable) != 0)
|
||||
range.address_type |= PCI_address_prefetchable;
|
||||
|
||||
switch (type & fdtPciRangeTypeMask) {
|
||||
case fdtPciRangeIoPort:
|
||||
outType = kPciRangeIoPort;
|
||||
range.type = B_IO_PORT;
|
||||
fResourceRanges.Add(range);
|
||||
break;
|
||||
case fdtPciRangeMmio32Bit:
|
||||
outType = kPciRangeMmio;
|
||||
range.type = B_IO_MEMORY;
|
||||
range.address_type |= PCI_address_type_32;
|
||||
fResourceRanges.Add(range);
|
||||
break;
|
||||
case fdtPciRangeMmio64Bit:
|
||||
outType = kPciRangeMmio + kPciRangeMmio64Bit;
|
||||
range.type = B_IO_MEMORY;
|
||||
range.address_type |= PCI_address_type_64;
|
||||
fResourceRanges.Add(range);
|
||||
break;
|
||||
}
|
||||
if (outType >= kPciRangeMmio && outType < kPciRangeMmioEnd
|
||||
&& (fdtPciRangePrefechable & type) != 0)
|
||||
outType += kPciRangeMmioPrefetch;
|
||||
|
||||
if (outType != kPciRangeInvalid) {
|
||||
fResourceRanges[outType].type = outType;
|
||||
fResourceRanges[outType].host_addr = parentAdr;
|
||||
fResourceRanges[outType].pci_addr = childAdr;
|
||||
fResourceRanges[outType].size = len;
|
||||
}
|
||||
|
||||
switch (type & fdtPciRangeTypeMask) {
|
||||
case fdtPciRangeConfig: dprintf("CONFIG"); break;
|
||||
|
Loading…
Reference in New Issue
Block a user