Index: sys/dev/pci/pci_host_generic.c =================================================================== --- sys/dev/pci/pci_host_generic.c +++ sys/dev/pci/pci_host_generic.c @@ -137,7 +137,7 @@ phys_base = sc->ranges[tuple].phys_base; pci_base = sc->ranges[tuple].pci_base; size = sc->ranges[tuple].size; - if (phys_base == 0 || size == 0) + if (size == 0) continue; /* empty range element */ switch (FLAG_TYPE(sc->ranges[tuple].flags)) { case FLAG_TYPE_PMEM: @@ -331,9 +331,6 @@ struct generic_pcie_core_softc *sc; struct resource *res; struct rman *rm; - uint64_t phys_base; - uint64_t pci_base; - uint64_t size; int i, space; bool found; @@ -351,19 +348,12 @@ return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid, start, end, count, flags)); - /* Translate the address from a PCI address to a physical address */ + res = NULL; switch (type) { case SYS_RES_IOPORT: case SYS_RES_MEMORY: found = false; for (i = 0; i < MAX_RANGES_TUPLES; i++) { - pci_base = sc->ranges[i].pci_base; - phys_base = sc->ranges[i].phys_base; - size = sc->ranges[i].size; - - if (start < pci_base || start >= pci_base + size) - continue; - switch (FLAG_TYPE(sc->ranges[i].flags)) { case FLAG_TYPE_MEM: case FLAG_TYPE_PMEM: @@ -373,13 +363,16 @@ space = SYS_RES_IOPORT; break; default: - space = -1; continue; } - if (type == space) { - start = start - pci_base + phys_base; - end = end - pci_base + phys_base; + if (type != space) + continue; + + res = rman_reserve_resource(rm, start, end, count, + flags, child); + + if (res != NULL) { found = true; break; } @@ -403,7 +396,6 @@ start, end, count); } - res = rman_reserve_resource(rm, start, end, count, flags, child); if (res == NULL) goto fail; @@ -430,15 +422,56 @@ int rid, struct resource *r) { struct generic_pcie_core_softc *sc; - int res; + uint64_t pci_base, phys_base, size; + int i, res; + bool found; sc = device_get_softc(dev); if ((res = rman_activate_resource(r)) != 0) return (res); - return (BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, type, - rid, r)); + switch (type) { + case SYS_RES_IOPORT: + case SYS_RES_MEMORY: + /* + * Translate the address from a PCI address to a physical + * address. + */ + found = 0; + for (i = 0; i < MAX_RANGES_TUPLES; i++) { + pci_base = sc->ranges[i].pci_base; + phys_base = sc->ranges[i].phys_base; + size = sc->ranges[i].size; + + if ((rman_get_start(r) >= pci_base) && + (rman_get_start(r) < (pci_base + size))) { + found = 1; + break; + } + } + if (found) { + rman_set_start(r, + rman_get_start(r) - pci_base + phys_base); + rman_set_end(r, rman_get_end(r) - pci_base + phys_base); + res = BUS_ACTIVATE_RESOURCE(device_get_parent(dev), + child, type, rid, r); + } else { + device_printf(dev, + "Failed to activate %s resource\n", + type == SYS_RES_IOPORT ? "IOPORT" : "MEMORY"); + res = ENXIO; + } + break; + case SYS_RES_IRQ: + res = BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, + type, rid, r); + break; + default: + break; + } + + return (res); } static int