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