---
src/pciinit.c | 69 +++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 48 insertions(+), 21 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c
index a574e38..92942d5 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -17,6 +17,7 @@
#define PCI_BRIDGE_IO_MIN 0x1000
#define PCI_BRIDGE_MEM_MIN 0x100000
+#define PCI_BRIDGE_MEM_MAX 0x80000000
enum pci_region_type {
PCI_REGION_TYPE_IO,
@@ -45,6 +46,7 @@ struct pci_bus {
s64 base;
s64 bases[32 - PCI_MEM_INDEX_SHIFT];
} r[PCI_REGION_TYPE_COUNT];
+ int is64;
struct pci_device *bus_dev;
};
@@ -369,6 +371,26 @@ static void pci_bios_bus_reserve(struct pci_bus *bus, int
type, u32 size)
bus->r[type].max = size;
}
+static void pci_bios_secondary_bus_reserve(struct pci_bus *parent,
+ struct pci_bus *s, int type)
+{
+ u32 limit = (type == PCI_REGION_TYPE_IO) ?
+ PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
+
+ if (s->r[type].sum> PCI_BRIDGE_MEM_MAX) {
+ panic("Size: %08x%08x is too big\n",
+ (u32)s->r[type].sum, (u32)(s->r[type].sum>>32));
+ }
+ s->r[type].size = (u32)s->r[type].sum;
+ if (s->r[type].size< limit)
+ s->r[type].size = limit;
+ s->r[type].size = pci_size_roundup(s->r[type].size);
+
+ pci_bios_bus_reserve(parent, type, s->r[type].size);
+ dprintf(1, " size: %x, type %s\n",
+ s->r[type].size, region_type_name[type]);
+}
+
static void pci_bios_check_devices(struct pci_bus *busses)
{
dprintf(1, "PCI: check devices\n");
@@ -392,8 +414,10 @@ static void pci_bios_check_devices(struct pci_bus *busses)
pci_bios_bus_reserve(bus, type, size);
pci->bars[i].addr = val;
pci->bars[i].size = size;
- if (type == PCI_REGION_TYPE_PREFMEM_64)
+ if (type == PCI_REGION_TYPE_PREFMEM_64) {
+ bus->is64 = 1;
i++;
+ }
}
}
@@ -404,22 +428,21 @@ static void pci_bios_check_devices(struct pci_bus *busses)
if (!s->bus_dev)
continue;
struct pci_bus *parent =&busses[pci_bdf_to_bus(s->bus_dev->bdf)];
+
+ if (s->r[PCI_REGION_TYPE_PREFMEM_64].sum&&
+ s->r[PCI_REGION_TYPE_PREFMEM].sum) {
+ panic("Sparse PCI prefmem regions on the bus %d\n", secondary_bus);
+ }
+
+ dprintf(1, "PCI: secondary bus %d\n", secondary_bus);
int type;
for (type = 0; type< PCI_REGION_TYPE_COUNT; type++) {
- u32 limit = (type == PCI_REGION_TYPE_IO) ?
- PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
- s->r[type].size = s->r[type].sum;
- if (s->r[type].size< limit)
- s->r[type].size = limit;
- s->r[type].size = pci_size_roundup(s->r[type].size);
- pci_bios_bus_reserve(parent, type, s->r[type].size);
- }
- dprintf(1, "PCI: secondary bus %d sizes: io %x, mem %x, prefmem %x\n",
- secondary_bus,
- s->r[PCI_REGION_TYPE_IO].size,
- s->r[PCI_REGION_TYPE_MEM].size,
- s->r[PCI_REGION_TYPE_PREFMEM].size);
- }
+ if ((type == PCI_REGION_TYPE_PREFMEM_64&& !s->is64) ||
+ (type == PCI_REGION_TYPE_PREFMEM&& s->is64))
+ continue;