--- //depot/vendor/freebsd/src/sys/amd64/include/resource.h +++ //depot/projects/pci/sys/amd64/include/resource.h @@ -40,5 +40,8 @@ #define SYS_RES_DRQ 2 /* isa dma lines */ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ +#ifdef NEW_PCIB +#define PCI_RES_BUS 5 /* PCI bus numbers */ +#endif #endif /* !_MACHINE_RESOURCE_H_ */ --- //depot/vendor/freebsd/src/sys/dev/acpica/acpi_pcib_acpi.c +++ //depot/projects/pci/sys/dev/acpica/acpi_pcib_acpi.c @@ -44,6 +44,7 @@ #include #include +#include #include #include #include "pcib_if.h" @@ -96,6 +97,11 @@ static int acpi_pcib_acpi_adjust_resource(device_t dev, device_t child, int type, struct resource *r, u_long start, u_long end); +#ifdef PCI_RES_BUS +static int acpi_pcib_acpi_release_resource(device_t dev, + device_t child, int type, int rid, + struct resource *r); +#endif #endif static device_method_t acpi_pcib_acpi_methods[] = { @@ -115,7 +121,11 @@ #else DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), #endif +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + DEVMETHOD(bus_release_resource, acpi_pcib_acpi_release_resource), +#else DEVMETHOD(bus_release_resource, bus_generic_release_resource), +#endif DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), @@ -271,6 +281,20 @@ } #endif +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) +static int +first_decoded_bus(struct acpi_hpcib_softc *sc, u_long *startp) +{ + struct resource_list_entry *rle; + + rle = resource_list_find(&sc->ap_host_res.hr_rl, PCI_RES_BUS, 0); + if (rle == NULL) + return (ENXIO); + *startp = rle->start; + return (0); +} +#endif + static int acpi_pcib_acpi_attach(device_t dev) { @@ -278,6 +302,11 @@ ACPI_STATUS status; static int bus0_seen = 0; u_int slot, func, busok; +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + struct resource *bus_res; + u_long start; + int rid; +#endif uint8_t busno; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); @@ -389,8 +418,41 @@ } } +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) /* * If nothing else worked, hope that ACPI at least lays out the + * Host-PCI bridges in order and that as a result the next free + * bus number is our bus number. + */ + if (busok == 0) { + /* + * If we have a region of bus numbers, use the first + * number for our bus. + */ + if (first_decoded_bus(sc, &start) == 0) + sc->ap_bus = start; + else { + rid = 0; + bus_res = pci_domain_alloc_bus(sc->ap_segment, dev, &rid, 0, + PCI_BUSMAX, 1, 0); + if (bus_res == NULL) { + device_printf(dev, + "could not allocate bus number\n"); + pcib_host_res_free(dev, &sc->ap_host_res); + return (ENXIO); + } + sc->ap_bus = rman_get_start(bus_res); + pci_domain_release_bus(sc->ap_segment, dev, rid, bus_res); + } + } else { +#ifdef INVARIANTS + if (first_decoded_bus(sc, &start) == 0) + KASSERT(start == sc->ap_bus, ("bus number mismatch")); +#endif + } +#else + /* + * If nothing else worked, hope that ACPI at least lays out the * host-PCI bridges in order and that as a result our unit number * is actually our bus number. There are several reasons this * might not be true. @@ -399,6 +461,7 @@ sc->ap_bus = device_get_unit(dev); device_printf(dev, "trying bus number %d\n", sc->ap_bus); } +#endif /* If this is bus 0 on segment 0, note that it has been seen already. */ if (sc->ap_segment == 0 && sc->ap_bus == 0) @@ -534,6 +597,11 @@ #ifdef NEW_PCIB sc = device_get_softc(dev); +#ifdef PCI_RES_BUS + if (type == PCI_RES_BUS) + return (pci_domain_alloc_bus(sc->ap_segment, child, rid, start, end, + count, flags)); +#endif res = pcib_host_res_alloc(&sc->ap_host_res, child, type, rid, start, end, count, flags); @@ -562,7 +630,26 @@ struct acpi_hpcib_softc *sc; sc = device_get_softc(dev); +#ifdef PCI_RES_BUS + if (type == PCI_RES_BUS) + return (pci_domain_adjust_bus(sc->ap_segment, child, r, start, + end)); +#endif return (pcib_host_res_adjust(&sc->ap_host_res, child, type, r, start, end)); } + +#ifdef PCI_RES_BUS +int +acpi_pcib_acpi_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + struct acpi_hpcib_softc *sc; + + sc = device_get_softc(dev); + if (type == PCI_RES_BUS) + return (pci_domain_release_bus(sc->ap_segment, child, rid, r)); + return (bus_generic_release_resource(dev, child, type, rid, r)); +} +#endif #endif --- //depot/vendor/freebsd/src/sys/dev/acpica/acpi_pcib_pci.c +++ //depot/projects/pci/sys/dev/acpica/acpi_pcib_pci.c @@ -120,7 +120,7 @@ pcib_attach_common(dev); sc = device_get_softc(dev); sc->ap_handle = acpi_get_handle(dev); - return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_pcibsc.secbus)); + return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_pcibsc.bus.sec)); } static int --- //depot/vendor/freebsd/src/sys/dev/cardbus/cardbus.c +++ //depot/projects/pci/sys/dev/cardbus/cardbus.c @@ -96,17 +96,36 @@ cardbus_attach(device_t cbdev) { struct cardbus_softc *sc; +#ifdef PCI_RES_BUS + int rid; +#endif sc = device_get_softc(cbdev); sc->sc_dev = cbdev; +#ifdef PCI_RES_BUS + rid = 0; + sc->sc_bus = bus_alloc_resource(cbdev, PCI_RES_BUS, &rid, + pcib_get_bus(cbdev), pcib_get_bus(cbdev), 1, 0); + if (sc->sc_bus == NULL) { + device_printf(cbdev, "failed to allocate bus number\n"); + return (ENXIO); + } +#endif return (0); } static int cardbus_detach(device_t cbdev) { +#ifdef PCI_RES_BUS + struct cardbus_softc *sc; +#endif cardbus_detach_card(cbdev); +#ifdef PCI_RES_BUS + sc = device_get_softc(cbdev); + (void)bus_release_resource(cbdev, PCI_RES_BUS, 0, sc->sc_bus); +#endif return (0); } --- //depot/vendor/freebsd/src/sys/dev/cardbus/cardbusvar.h +++ //depot/projects/pci/sys/dev/cardbus/cardbusvar.h @@ -69,6 +69,9 @@ struct cardbus_softc { device_t sc_dev; +#ifdef PCI_RES_BUS + struct resource *sc_bus; +#endif }; /* --- //depot/vendor/freebsd/src/sys/dev/pccbb/pccbb.c +++ //depot/projects/pci/sys/dev/pccbb/pccbb.c @@ -97,6 +97,7 @@ #include #include +#include #include #include @@ -1548,7 +1549,7 @@ *result = sc->domain; return (0); case PCIB_IVAR_BUS: - *result = sc->secbus; + *result = sc->bus.sec; return (0); } return (ENOENT); @@ -1557,14 +1558,12 @@ int cbb_write_ivar(device_t brdev, device_t child, int which, uintptr_t value) { - struct cbb_softc *sc = device_get_softc(brdev); switch (which) { case PCIB_IVAR_DOMAIN: return (EINVAL); case PCIB_IVAR_BUS: - sc->secbus = value; - return (0); + return (EINVAL); } return (ENOENT); } --- //depot/vendor/freebsd/src/sys/dev/pccbb/pccbb_isa.c +++ //depot/projects/pci/sys/dev/pccbb/pccbb_isa.c @@ -51,6 +51,9 @@ #include +#include +#include + #include #include --- //depot/vendor/freebsd/src/sys/dev/pccbb/pccbb_pci.c +++ //depot/projects/pci/sys/dev/pccbb/pccbb_pci.c @@ -93,6 +93,7 @@ #include #include +#include #include #include @@ -303,13 +304,15 @@ static int cbb_pci_attach(device_t brdev) { +#if !(defined(NEW_PCIB) && defined(PCI_RES_BUS)) static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */ + uint32_t pribus; +#endif struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(brdev); struct sysctl_ctx_list *sctx; struct sysctl_oid *soid; int rid; device_t parent; - uint32_t pribus; parent = device_get_parent(brdev); mtx_init(&sc->mtx, device_get_nameunit(brdev), "cbb", MTX_DEF); @@ -318,9 +321,13 @@ sc->cbdev = NULL; sc->exca[0].pccarddev = NULL; sc->domain = pci_get_domain(brdev); - sc->secbus = pci_read_config(brdev, PCIR_SECBUS_2, 1); - sc->subbus = pci_read_config(brdev, PCIR_SUBBUS_2, 1); + sc->bus.sec = pci_read_config(brdev, PCIR_SECBUS_2, 1); + sc->bus.sub = pci_read_config(brdev, PCIR_SUBBUS_2, 1); sc->pribus = pcib_get_bus(parent); +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + pci_write_config(brdev, PCIR_PRIBUS_2, sc->pribus, 1); + pcib_setup_secbus(brdev, &sc->bus, 1); +#endif SLIST_INIT(&sc->rl); cbb_powerstate_d0(brdev); @@ -352,9 +359,9 @@ SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "pribus", CTLFLAG_RD, &sc->pribus, 0, "Primary bus number"); SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus", - CTLFLAG_RD, &sc->secbus, 0, "Secondary bus number"); + CTLFLAG_RD, &sc->bus.sec, 0, "Secondary bus number"); SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus", - CTLFLAG_RD, &sc->subbus, 0, "Subordinate bus number"); + CTLFLAG_RD, &sc->bus.sub, 0, "Subordinate bus number"); #if 0 SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "memory", CTLFLAG_RD, &sc->subbus, 0, "Memory window open"); @@ -366,15 +373,16 @@ CTLFLAG_RD, &sc->subbus, 0, "io range 2 open"); #endif +#if !(defined(NEW_PCIB) && defined(PCI_RES_BUS)) /* * This is a gross hack. We should be scanning the entire pci * tree, assigning bus numbers in a way such that we (1) can * reserve 1 extra bus just in case and (2) all sub busses * are in an appropriate range. */ - DEVPRINTF((brdev, "Secondary bus is %d\n", sc->secbus)); + DEVPRINTF((brdev, "Secondary bus is %d\n", sc->bus.sec)); pribus = pci_read_config(brdev, PCIR_PRIBUS_2, 1); - if (sc->secbus == 0 || sc->pribus != pribus) { + if (sc->bus.sec == 0 || sc->pribus != pribus) { if (curr_bus_number <= sc->pribus) curr_bus_number = sc->pribus + 1; if (pribus != sc->pribus) { @@ -382,13 +390,14 @@ sc->pribus)); pci_write_config(brdev, PCIR_PRIBUS_2, sc->pribus, 1); } - sc->secbus = curr_bus_number++; - sc->subbus = curr_bus_number++; + sc->bus.sec = curr_bus_number++; + sc->bus.sub = curr_bus_number++; DEVPRINTF((brdev, "Secondary bus set to %d subbus %d\n", - sc->secbus, sc->subbus)); - pci_write_config(brdev, PCIR_SECBUS_2, sc->secbus, 1); - pci_write_config(brdev, PCIR_SUBBUS_2, sc->subbus, 1); + sc->bus.sec, sc->bus.sub)); + pci_write_config(brdev, PCIR_SECBUS_2, sc->bus.sec, 1); + pci_write_config(brdev, PCIR_SUBBUS_2, sc->bus.sub, 1); } +#endif /* attach children */ sc->cbdev = device_add_child(brdev, "cardbus", -1); @@ -467,8 +476,8 @@ /* Restore bus configuration */ pci_write_config(sc->dev, PCIR_PRIBUS_2, sc->pribus, 1); - pci_write_config(sc->dev, PCIR_SECBUS_2, sc->secbus, 1); - pci_write_config(sc->dev, PCIR_SUBBUS_2, sc->subbus, 1); + pci_write_config(sc->dev, PCIR_SECBUS_2, sc->bus.sec, 1); + pci_write_config(sc->dev, PCIR_SUBBUS_2, sc->bus.sub, 1); /* Enable memory access */ pci_enable_busmaster(sc->dev); @@ -783,6 +792,58 @@ return retval; } +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) +static struct resource * +cbb_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct cbb_softc *sc; + + sc = device_get_softc(bus); + if (type == PCI_RES_BUS) + return (pcib_alloc_subbus(&sc->bus, child, rid, start, end, + count, flags)); + return (cbb_alloc_resource(bus, child, type, rid, start, end, count, + flags)); +} + +static int +cbb_pci_adjust_resource(device_t bus, device_t child, int type, + struct resource *r, u_long start, u_long end) +{ + struct cbb_softc *sc; + + sc = device_get_softc(bus); + if (type == PCI_RES_BUS) { + if (!rman_is_region_manager(r, &sc->bus.rman)) + return (EINVAL); + return (rman_adjust_resource(r, start, end)); + } + return (bus_generic_adjust_resource(bus, child, type, r, start, end)); +} + +static int +cbb_pci_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + struct cbb_softc *sc; + int error; + + sc = device_get_softc(bus); + if (type == PCI_RES_BUS) { + if (!rman_is_region_manager(r, &sc->bus.rman)) + return (EINVAL); + if (rman_get_flags(r) & RF_ACTIVE) { + error = bus_deactivate_resource(child, type, rid, r); + if (error) + return (error); + } + return (rman_release_resource(r)); + } + return (cbb_release_resource(bus, child, type, rid, r)); +} +#endif + /************************************************************************/ /* PCI compat methods */ /************************************************************************/ @@ -826,8 +887,14 @@ /* bus methods */ DEVMETHOD(bus_read_ivar, cbb_read_ivar), DEVMETHOD(bus_write_ivar, cbb_write_ivar), +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + DEVMETHOD(bus_alloc_resource, cbb_pci_alloc_resource), + DEVMETHOD(bus_adjust_resource, cbb_pci_adjust_resource), + DEVMETHOD(bus_release_resource, cbb_pci_release_resource), +#else DEVMETHOD(bus_alloc_resource, cbb_alloc_resource), DEVMETHOD(bus_release_resource, cbb_release_resource), +#endif DEVMETHOD(bus_activate_resource, cbb_activate_resource), DEVMETHOD(bus_deactivate_resource, cbb_deactivate_resource), DEVMETHOD(bus_driver_added, cbb_driver_added), --- //depot/vendor/freebsd/src/sys/dev/pccbb/pccbbvar.h +++ //depot/projects/pci/sys/dev/pccbb/pccbbvar.h @@ -64,8 +64,7 @@ bus_space_handle_t bsh; uint32_t domain; unsigned int pribus; - unsigned int secbus; - unsigned int subbus; + struct pcib_secbus bus; struct mtx mtx; int cardok; u_int32_t flags; --- //depot/vendor/freebsd/src/sys/dev/pci/pci.c +++ //depot/projects/pci/sys/dev/pci/pci.c @@ -92,6 +99,9 @@ struct resource_list *rl, int force, int prefetch); static int pci_probe(device_t dev); static int pci_attach(device_t dev); +#ifdef PCI_RES_BUS +static int pci_detach(device_t dev); +#endif static void pci_load_vendor_data(void); static int pci_describe_parse_line(char **ptr, int *vendor, int *device, char **desc); @@ -125,7 +135,11 @@ /* Device interface */ DEVMETHOD(device_probe, pci_probe), DEVMETHOD(device_attach, pci_attach), +#ifdef PCI_RES_BUS + DEVMETHOD(device_detach, pci_detach), +#else DEVMETHOD(device_detach, bus_generic_detach), +#endif DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, pci_suspend), DEVMETHOD(device_resume, pci_resume), @@ -337,6 +351,13 @@ SYSCTL_INT(_hw_pci, OID_AUTO, clear_bars, CTLFLAG_RDTUN, &pci_clear_bars, 0, "Ignore firmware-assigned resources for BARs."); +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) +static int pci_clear_buses; +TUNABLE_INT("hw.pci.clear_buses", &pci_clear_buses); +SYSCTL_INT(_hw_pci, OID_AUTO, clear_buses, CTLFLAG_RDTUN, &pci_clear_buses, 0, + "Ignore firmware-assigned bus numbers."); +#endif + static int pci_has_quirk(uint32_t devid, int quirk) { @@ -3197,6 +3218,167 @@ bus_release_resource(self, SYS_RES_MEMORY, rid, res); } +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) +static void +pci_reserve_secbus(device_t bus, device_t dev, pcicfgregs *cfg, + struct resource_list *rl) +{ + struct resource *res; + char *cp; + u_long start, end, count; + int rid, sec_bus, sec_reg, sub_bus, sub_reg, sup_bus; + + switch (cfg->hdrtype & PCIM_HDRTYPE) { + case PCIM_HDRTYPE_BRIDGE: + sec_reg = PCIR_SECBUS_1; + sub_reg = PCIR_SUBBUS_1; + break; + case PCIM_HDRTYPE_CARDBUS: + sec_reg = PCIR_SECBUS_2; + sub_reg = PCIR_SUBBUS_2; + break; + default: + return; + } + + /* + * If the existing bus range is valid, attempt to reserve it + * from our parent. If this fails for any reason, clear the + * secbus and subbus registers. + * + * XXX: Should we reset sub_bus to sec_bus if it is < sec_bus? + * This would at least preserve the existing sec_bus if it is + * valid. + */ + sec_bus = PCI_READ_CONFIG(bus, dev, sec_reg, 1); + sub_bus = PCI_READ_CONFIG(bus, dev, sub_reg, 1); + + /* Quirk handling. */ + switch (pci_get_devid(dev)) { + case 0x12258086: /* Intel 82454KX/GX (Orion) */ + sup_bus = pci_read_config(dev, 0x41, 1); + if (sup_bus != 0xff) { + sec_bus = sup_bus + 1; + sub_bus = sup_bus + 1; + PCI_WRITE_CONFIG(bus, dev, sec_reg, sec_bus, 1); + PCI_WRITE_CONFIG(bus, dev, sub_reg, sub_bus, 1); + } + break; + + case 0x00dd10de: + /* Compaq R3000 BIOS sets wrong subordinate bus number. */ + if ((cp = getenv("smbios.planar.maker")) == NULL) + break; + if (strncmp(cp, "Compal", 6) != 0) { + freeenv(cp); + break; + } + freeenv(cp); + if ((cp = getenv("smbios.planar.product")) == NULL) + break; + if (strncmp(cp, "08A0", 4) != 0) { + freeenv(cp); + break; + } + freeenv(cp); + if (sub_bus < 0xa) { + sub_bus = 0xa; + PCI_WRITE_CONFIG(bus, dev, sub_reg, sub_bus, 1); + } + break; + } + + if (bootverbose || 1) + printf("\tsecbus=%d, subbus=%d\n", sec_bus, sub_bus); + if (sec_bus > 0 && sub_bus >= sec_bus) { + start = sec_bus; + end = sub_bus; + count = end - start + 1; + + resource_list_add(rl, PCI_RES_BUS, 0, 0ul, ~0ul, count); + + /* + * If requested, clear secondary bus registers in + * bridge devices to force a complete renumbering + * rather than reserving the existing range. However, + * preserve the existing size. + */ + if (pci_clear_buses) + goto clear; + + rid = 0; + res = resource_list_reserve(rl, bus, dev, PCI_RES_BUS, &rid, + start, end, count, 0); + if (res != NULL) { + /* XXX */ + pci_printf(cfg, "allocated initial secbus range\n"); + return; + } + + if (bootverbose || 1) + device_printf(bus, + "pci%d:%d:%d:%d secbus failed to allocate\n", + pci_get_domain(dev), pci_get_bus(dev), + pci_get_slot(dev), pci_get_function(dev)); + } + +clear: + PCI_WRITE_CONFIG(bus, dev, sec_reg, 0, 1); + PCI_WRITE_CONFIG(bus, dev, sub_reg, 0, 1); +} + +static struct resource * +pci_alloc_secbus(device_t dev, device_t child, int *rid, u_long start, + u_long end, u_long count, u_int flags) +{ + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + struct resource_list *rl; + struct resource *res; + int sec_reg, sub_reg; + + dinfo = device_get_ivars(child); + cfg = &dinfo->cfg; + rl = &dinfo->resources; + switch (cfg->hdrtype & PCIM_HDRTYPE) { + case PCIM_HDRTYPE_BRIDGE: + sec_reg = PCIR_SECBUS_1; + sub_reg = PCIR_SUBBUS_1; + break; + case PCIM_HDRTYPE_CARDBUS: + sec_reg = PCIR_SECBUS_2; + sub_reg = PCIR_SUBBUS_2; + break; + default: + return (NULL); + } + + if (*rid != 0) + return (NULL); + + if (resource_list_find(rl, PCI_RES_BUS, *rid) == NULL) + resource_list_add(rl, PCI_RES_BUS, *rid, start, end, count); + if (!resource_list_reserved(rl, PCI_RES_BUS, *rid)) { + res = resource_list_reserve(rl, dev, child, PCI_RES_BUS, rid, + start, end, count, flags & ~RF_ACTIVE); + if (res == NULL) { + resource_list_delete(rl, PCI_RES_BUS, *rid); + device_printf(child, "allocating %lu bus%s failed\n", + count, count == 1 ? "" : "es"); + return (NULL); + } + if (bootverbose) + device_printf(child, + "Lazy allocation of %lu bus%s at %lu\n", count, + count == 1 ? "" : "es", rman_get_start(res)); + PCI_WRITE_CONFIG(dev, child, sec_reg, rman_get_start(res), 1); + PCI_WRITE_CONFIG(dev, child, sub_reg, rman_get_end(res), 1); + } + return (resource_list_alloc(rl, dev, child, PCI_RES_BUS, rid, start, + end, count, flags)); +} +#endif + void pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask) { @@ -3269,6 +3451,14 @@ else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_UHCI) uhci_early_takeover(dev); } + +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + /* + * Reserve resources for secondary bus ranges behind bridge + * devices. + */ + pci_reserve_secbus(bus, dev, cfg, rl); +#endif } void @@ -3334,10 +3524,22 @@ #ifdef PCI_DMA_BOUNDARY int error, tag_valid; #endif +#ifdef PCI_RES_BUS + int rid; +#endif sc = device_get_softc(dev); domain = pcib_get_domain(dev); busno = pcib_get_bus(dev); +#ifdef PCI_RES_BUS + rid = 0; + sc->sc_bus = bus_alloc_resource(dev, PCI_RES_BUS, &rid, busno, busno, + 1, 0); + if (sc->sc_bus == NULL) { + device_printf(dev, "failed to allocate bus number\n"); + return (ENXIO); + } +#endif if (bootverbose) device_printf(dev, "domain=%d, physical bus=%d\n", domain, busno); @@ -3382,6 +3584,21 @@ return (bus_generic_attach(dev)); } +#ifdef PCI_RES_BUS +static int +pci_detach(device_t dev) +{ + struct pci_softc *sc; + int error; + + error = bus_generic_detach(dev); + if (error) + return (error); + sc = device_get_softc(dev); + return (bus_release_resource(dev, PCI_RES_BUS, 0, sc->sc_bus)); +} +#endif + static void pci_set_power_children(device_t dev, device_t *devlist, int numdevs, int state) @@ -3711,6 +3928,10 @@ retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); +#ifdef PCI_RES_BUS + /* XXX: Maybe? */ + retval += resource_list_print_type(rl, "bus", PCI_RES_BUS, "%ld"); +#endif if (device_get_flags(dev)) retval += printf(" flags %#x", device_get_flags(dev)); @@ -3879,6 +4100,10 @@ pci_printf(&dinfo->cfg, "Device leaked memory resources\n"); if (resource_list_release_active(rl, dev, child, SYS_RES_IOPORT) != 0) pci_printf(&dinfo->cfg, "Device leaked I/O resources\n"); +#ifdef PCI_RES_BUS + if (resource_list_release_active(rl, dev, child, PCI_RES_BUS) != 0) + pci_printf(&dinfo->cfg, "Device leaked PCI bus numbers\n"); +#endif pci_cfg_save(child, dinfo, 1); } @@ -4295,6 +4520,11 @@ rl = &dinfo->resources; cfg = &dinfo->cfg; switch (type) { +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + case PCI_RES_BUS: + return (pci_alloc_secbus(dev, child, rid, start, end, count, + flags)); +#endif case SYS_RES_IRQ: /* * Can't alloc legacy interrupt once MSI messages have --- //depot/vendor/freebsd/src/sys/dev/pci/pci_pci.c +++ //depot/projects/pci/sys/dev/pci/pci_pci.c @@ -119,6 +119,10 @@ { switch (type) { +#ifdef PCI_RES_BUS + case PCI_RES_BUS: + return (rman_is_region_manager(r, &sc->bus.rman)); +#endif case SYS_RES_IOPORT: return (rman_is_region_manager(r, &sc->io.rman)); case SYS_RES_MEMORY: @@ -523,6 +527,182 @@ } } +#ifdef PCI_RES_BUS +/* + * Allocate a suitable secondary bus for this bridge if needed and + * initialize the resource manager for the secondary bus range. Note + * that the minimum count is a desired value and this may allocate a + * smaller range. + */ +void +pcib_setup_secbus(device_t dev, struct pcib_secbus *bus, int min_count) +{ + char buf[64]; + int error, rid; + + switch (pci_read_config(dev, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) { + case PCIM_HDRTYPE_BRIDGE: + bus->sub_reg = PCIR_SUBBUS_1; + break; + case PCIM_HDRTYPE_CARDBUS: + bus->sub_reg = PCIR_SUBBUS_2; + break; + default: + panic("not a PCI bridge"); + } + bus->dev = dev; + bus->rman.rm_start = 0; + bus->rman.rm_end = PCI_BUSMAX; + bus->rman.rm_type = RMAN_ARRAY; + snprintf(buf, sizeof(buf), "%s bus numbers", device_get_nameunit(dev)); + bus->rman.rm_descr = strdup(buf, M_DEVBUF); + error = rman_init(&bus->rman); + if (error) + panic("Failed to initialize %s bus number rman", + device_get_nameunit(dev)); + + /* + * Allocate a bus range. This will return an existing bus range + * if one exists, or a new bus range if one does not. + */ + rid = 0; + bus->res = bus_alloc_resource(dev, PCI_RES_BUS, &rid, 0ul, ~0ul, + min_count, 0); + if (bus->res == NULL) { + /* + * Fall back to just allocating a range of a single bus + * number. + */ + bus->res = bus_alloc_resource(dev, PCI_RES_BUS, &rid, 0ul, ~0ul, + 1, 0); + } else if (rman_get_size(bus->res) < min_count) + /* + * Attempt to grow the existing range to satisfy the + * minimum desired count. + */ + (void)bus_adjust_resource(dev, PCI_RES_BUS, bus->res, + rman_get_start(bus->res), rman_get_start(bus->res) + + min_count - 1); + + /* XXX */ + if (bus->res != NULL) + device_printf(dev, + "allocated secbus range %lu-%lu\n", + rman_get_start(bus->res), rman_get_end(bus->res)); + else + device_printf(dev, + "failed to allocate secondary bus number\n"); + + /* + * Add the initial resource to the rman. + */ + if (bus->res != NULL) { + error = rman_manage_region(&bus->rman, rman_get_start(bus->res), + rman_get_end(bus->res)); + if (error) + panic("Failed to add resource to rman"); + bus->sec = rman_get_start(bus->res); + bus->sub = rman_get_end(bus->res); + } +} + +static struct resource * +pcib_suballoc_bus(struct pcib_secbus *bus, device_t child, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource *res; + + res = rman_reserve_resource(&bus->rman, start, end, count, flags, + child); + if (res == NULL) + return (NULL); + + if (bootverbose) + device_printf(bus->dev, + "allocated bus range (%lu-%lu) for rid %d of %s\n", + rman_get_start(res), rman_get_end(res), *rid, + pcib_child_name(child)); + rman_set_rid(res, *rid); + return (res); +} + +/* + * Attempt to grow the secondary bus range. This is much simpler than + * for I/O windows as the range can only be grown by increasing + * subbus. + */ +static int +pcib_grow_subbus(struct pcib_secbus *bus, u_long new_end) +{ + u_long old_end; + int error; + + old_end = rman_get_end(bus->res); + KASSERT(new_end > old_end, ("attempt to shrink subbus")); + error = bus_adjust_resource(bus->dev, PCI_RES_BUS, bus->res, + rman_get_start(bus->res), new_end); + if (error) + return (error); + if (bootverbose || 1) + device_printf(bus->dev, "grew bus range to %lu-%lu\n", + rman_get_start(bus->res), rman_get_end(bus->res)); + error = rman_manage_region(&bus->rman, old_end + 1, + rman_get_end(bus->res)); + if (error) + panic("Failed to add resource to rman"); + bus->sub = rman_get_end(bus->res); + pci_write_config(bus->dev, bus->sub_reg, bus->sub, 1); + return (0); +} + +struct resource * +pcib_alloc_subbus(struct pcib_secbus *bus, device_t child, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource *res; + u_long start_free, end_free, new_end; + + /* + * First, see if the request can be satisified by the existing + * bus range. + */ + res = pcib_suballoc_bus(bus, child, rid, start, end, count, flags); + if (res != NULL) + return (res); + + /* + * Figure out a range to grow the bus range. First, find the + * first bus number after the last allocated bus in the rman and + * enforce that as a minimum starting point for the range. + */ + if (rman_last_free_region(&bus->rman, &start_free, &end_free) != 0 || + end_free != bus->sub) + start_free = bus->sub + 1; + if (start_free < start) + start_free = start; + new_end = start_free + count - 1; + + /* + * See if this new range would satisfy the request if it + * succeeds. + */ + if (new_end > end) + return (NULL); + + /* Finally, attempt to grow the existing resource. */ + if (bootverbose || 1) { + device_printf(bus->dev, + "attempting to grow bus range for %lu buses\n", count); + printf("\tback candidate range: %lu-%lu\n", start_free, + new_end); + } + if (pcib_grow_subbus(bus, new_end) == 0) + return (pcib_suballoc_bus(bus, child, rid, start, end, count, + flags)); + return (NULL); +} +#endif + #else /* @@ -669,8 +849,8 @@ sc->command = pci_read_config(dev, PCIR_COMMAND, 2); sc->pribus = pci_read_config(dev, PCIR_PRIBUS_1, 1); - sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1); - sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); + sc->bus.sec = pci_read_config(dev, PCIR_SECBUS_1, 1); + sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1); sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1); #ifndef NEW_PCIB @@ -693,8 +873,8 @@ pci_write_config(dev, PCIR_COMMAND, sc->command, 2); pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1); - pci_write_config(dev, PCIR_SECBUS_1, sc->secbus, 1); - pci_write_config(dev, PCIR_SUBBUS_1, sc->subbus, 1); + pci_write_config(dev, PCIR_SECBUS_1, sc->bus.sec, 1); + pci_write_config(dev, PCIR_SUBBUS_1, sc->bus.sub, 1); pci_write_config(dev, PCIR_BRIDGECTL_1, sc->bridgectl, 2); pci_write_config(dev, PCIR_SECLAT_1, sc->seclat, 1); #ifdef NEW_PCIB @@ -740,6 +920,13 @@ pcib_cfg_save(sc); /* + * The primary bus register should always be the bus of the + * parent. + */ + sc->pribus = pci_get_bus(dev); + pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1); + + /* * Setup sysctl reporting nodes */ sctx = device_get_sysctl_ctx(dev); @@ -749,25 +936,27 @@ SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "pribus", CTLFLAG_RD, &sc->pribus, 0, "Primary bus number"); SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus", - CTLFLAG_RD, &sc->secbus, 0, "Secondary bus number"); + CTLFLAG_RD, &sc->bus.sec, 0, "Secondary bus number"); SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus", - CTLFLAG_RD, &sc->subbus, 0, "Subordinate bus number"); + CTLFLAG_RD, &sc->bus.sub, 0, "Subordinate bus number"); /* * Quirk handling. */ switch (pci_get_devid(dev)) { +#if !defined(NEW_PCIB) && !defined(PCI_RES_BUS) case 0x12258086: /* Intel 82454KX/GX (Orion) */ { uint8_t supbus; supbus = pci_read_config(dev, 0x41, 1); if (supbus != 0xff) { - sc->secbus = supbus + 1; - sc->subbus = supbus + 1; + sc->bus.sec = supbus + 1; + sc->bus.sub = supbus + 1; } break; } +#endif /* * The i82380FB mobile docking controller is a PCI-PCI bridge, @@ -781,6 +970,7 @@ sc->flags |= PCIB_SUBTRACTIVE; break; +#if !defined(NEW_PCIB) && !defined(PCI_RES_BUS) /* Compaq R3000 BIOS sets wrong subordinate bus number. */ case 0x00dd10de: { @@ -800,12 +990,13 @@ break; } freeenv(cp); - if (sc->subbus < 0xa) { + if (sc->bus.sub < 0xa) { pci_write_config(dev, PCIR_SUBBUS_1, 0xa, 1); - sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); + sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1); } break; } +#endif } if (pci_msi_device_blacklisted(dev)) @@ -827,12 +1018,15 @@ sc->flags |= PCIB_SUBTRACTIVE; #ifdef NEW_PCIB +#ifdef PCI_RES_BUS + pcib_setup_secbus(dev, &sc->bus, 1); +#endif pcib_probe_windows(sc); #endif if (bootverbose) { device_printf(dev, " domain %d\n", sc->domain); - device_printf(dev, " secondary bus %d\n", sc->secbus); - device_printf(dev, " subordinate bus %d\n", sc->subbus); + device_printf(dev, " secondary bus %d\n", sc->bus.sec); + device_printf(dev, " subordinate bus %d\n", sc->bus.sub); #ifdef NEW_PCIB if (pcib_is_window_open(&sc->io)) device_printf(dev, " I/O decode 0x%jx-0x%jx\n", @@ -873,20 +1067,6 @@ } /* - * XXX If the secondary bus number is zero, we should assign a bus number - * since the BIOS hasn't, then initialise the bridge. A simple - * bus_alloc_resource with the a couple of busses seems like the right - * approach, but we don't know what busses the BIOS might have already - * assigned to other bridges on this bus that probe later than we do. - * - * If the subordinate bus number is less than the secondary bus number, - * we should pick a better value. One sensible alternative would be to - * pick 255; the only tradeoff here is that configuration transactions - * would be more widely routed than absolutely necessary. We could - * then do a walk of the tree later and fix it. - */ - - /* * Always enable busmastering on bridges so that transactions * initiated on the secondary bus are passed through to the * primary bus. @@ -902,8 +1082,8 @@ pcib_attach_common(dev); sc = device_get_softc(dev); - if (sc->secbus != 0) { - child = device_add_child(dev, "pci", sc->secbus); + if (sc->bus.sec != 0) { + child = device_add_child(dev, "pci", sc->bus.sec); if (child != NULL) return(bus_generic_attach(dev)); } @@ -953,7 +1133,7 @@ *result = sc->domain; return(0); case PCIB_IVAR_BUS: - *result = sc->secbus; + *result = sc->bus.sec; return(0); } return(ENOENT); @@ -962,14 +1142,12 @@ int pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) { - struct pcib_softc *sc = device_get_softc(dev); switch (which) { case PCIB_IVAR_DOMAIN: return(EINVAL); case PCIB_IVAR_BUS: - sc->secbus = value; - return(0); + return(EINVAL); } return(ENOENT); } @@ -1379,6 +1557,11 @@ } switch (type) { +#ifdef PCI_RES_BUS + case PCI_RES_BUS: + return (pcib_alloc_subbus(&sc->bus, child, rid, start, end, + count, flags)); +#endif case SYS_RES_IOPORT: if (pcib_is_isa_range(sc, start, end, count)) return (NULL); --- //depot/vendor/freebsd/src/sys/dev/pci/pci_private.h +++ //depot/projects/pci/sys/dev/pci/pci_private.h @@ -40,6 +40,9 @@ struct pci_softc { bus_dma_tag_t sc_dma_tag; +#ifdef PCI_RES_BUS + struct resource *sc_bus; +#endif }; extern int pci_do_power_resume; --- //depot/vendor/freebsd/src/sys/dev/pci/pci_subr.c +++ //depot/projects/pci/sys/dev/pci/pci_subr.c @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -183,7 +184,11 @@ struct resource_list_entry *rle; int rid; +#ifdef PCI_RES_BUS + if (bootverbose || type == PCI_RES_BUS) +#else if (bootverbose) +#endif device_printf(hr->hr_pcib, "decoding %d %srange %#lx-%#lx\n", type, flags & RF_PREFETCHABLE ? "prefetchable ": "", start, end); @@ -237,7 +242,11 @@ r = bus_generic_alloc_resource(hr->hr_pcib, dev, type, rid, new_start, new_end, count, flags); if (r != NULL) { +#ifdef PCI_RES_BUS + if (bootverbose || type == PCI_RES_BUS) +#else if (bootverbose) +#endif device_printf(hr->hr_pcib, "allocated type %d (%#lx-%#lx) for rid %x of %s\n", type, rman_get_start(r), rman_get_end(r), @@ -282,4 +291,102 @@ } return (ERANGE); } + +#ifdef PCI_RES_BUS +struct pci_domain { + int pd_domain; + struct rman pd_bus_rman; + TAILQ_ENTRY(pci_domain) pd_link; +}; + +static TAILQ_HEAD(, pci_domain) domains = TAILQ_HEAD_INITIALIZER(domains); + +/* + * Each PCI domain maintains its own resource manager for PCI bus + * numbers in that domain. Domain objects are created on first use. + * Host to PCI bridge drivers and PCI-PCI bridge drivers should + * allocate their bus ranges from their domain. + */ +static struct pci_domain * +pci_find_domain(int domain) +{ + struct pci_domain *d; + char buf[64]; + int error; + + TAILQ_FOREACH(d, &domains, pd_link) { + if (d->pd_domain == domain) + return (d); + } + + snprintf(buf, sizeof(buf), "PCI domain %d bus numbers", domain); + d = malloc(sizeof(*d) + strlen(buf) + 1, M_DEVBUF, M_WAITOK | M_ZERO); + d->pd_domain = domain; + d->pd_bus_rman.rm_start = 0; + d->pd_bus_rman.rm_end = PCI_BUSMAX; + d->pd_bus_rman.rm_type = RMAN_ARRAY; + strcpy((char *)(d + 1), buf); + d->pd_bus_rman.rm_descr = (char *)(d + 1); + error = rman_init(&d->pd_bus_rman); + if (error == 0) + error = rman_manage_region(&d->pd_bus_rman, 0, PCI_BUSMAX); + if (error) + panic("Failed to initialize PCI domain %d rman", domain); + TAILQ_INSERT_TAIL(&domains, d, pd_link); + return (d); +} + +struct resource * +pci_domain_alloc_bus(int domain, device_t dev, int *rid, u_long start, + u_long end, u_long count, u_int flags) +{ + struct pci_domain *d; + struct resource *res; + + if (domain < 0 || domain > PCI_DOMAINMAX) + return (NULL); + d = pci_find_domain(domain); + res = rman_reserve_resource(&d->pd_bus_rman, start, end, count, flags, + dev); + if (res == NULL) + return (NULL); + + rman_set_rid(res, *rid); + return (res); +} + +int +pci_domain_adjust_bus(int domain, device_t dev, struct resource *r, + u_long start, u_long end) +{ +#ifdef INVARIANTS + struct pci_domain *d; +#endif + + if (domain < 0 || domain > PCI_DOMAINMAX) + return (EINVAL); +#ifdef INVARIANTS + d = pci_find_domain(domain); + KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource")); +#endif + return (rman_adjust_resource(r, start, end)); +} + +int +pci_domain_release_bus(int domain, device_t dev, int rid, struct resource *r) +{ +#ifdef INVARIANTS + struct pci_domain *d; +#endif + + if (domain < 0 || domain > PCI_DOMAINMAX) + return (EINVAL); +#ifdef INVARIANTS + d = pci_find_domain(domain); + KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource")); +#endif + return (rman_release_resource(r)); +} +#endif /* PCI_RES_BUS */ + #endif /* NEW_PCIB */ --- //depot/vendor/freebsd/src/sys/dev/pci/pcib_private.h +++ //depot/projects/pci/sys/dev/pci/pcib_private.h @@ -83,6 +83,18 @@ }; #endif +struct pcib_secbus { + u_int sec; + u_int sub; +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + device_t dev; + struct rman rman; + struct resource *res; + const char *name; + int sub_reg; +#endif +}; + /* * Bridge-specific data. */ @@ -96,8 +108,7 @@ uint16_t command; /* command register */ u_int domain; /* domain number */ u_int pribus; /* primary bus number */ - u_int secbus; /* secondary bus number */ - u_int subbus; /* subordinate bus number */ + struct pcib_secbus bus; /* secondary bus numbers */ #ifdef NEW_PCIB struct pcib_window io; /* I/O port window */ struct pcib_window mem; /* memory window */ @@ -117,13 +128,26 @@ typedef uint32_t pci_read_config_fn(int b, int s, int f, int reg, int width); -#ifdef NEW_PCIB -const char *pcib_child_name(device_t child); -#endif int host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, uint8_t *busnum); +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) +struct resource *pci_domain_alloc_bus(int domain, device_t dev, int *rid, + u_long start, u_long end, u_long count, u_int flags); +int pci_domain_adjust_bus(int domain, device_t dev, + struct resource *r, u_long start, u_long end); +int pci_domain_release_bus(int domain, device_t dev, int rid, + struct resource *r); +struct resource *pcib_alloc_subbus(struct pcib_secbus *bus, device_t child, + int *rid, u_long start, u_long end, u_long count, + u_int flags); +void pcib_setup_secbus(device_t dev, struct pcib_secbus *bus, + int min_count); +#endif int pcib_attach(device_t dev); void pcib_attach_common(device_t dev); +#ifdef NEW_PCIB +const char *pcib_child_name(device_t child); +#endif int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result); int pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value); struct resource *pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, --- //depot/vendor/freebsd/src/sys/i386/include/resource.h +++ //depot/projects/pci/sys/i386/include/resource.h @@ -40,5 +40,8 @@ #define SYS_RES_DRQ 2 /* isa dma lines */ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ +#ifdef NEW_PCIB +#define PCI_RES_BUS 5 /* PCI bus numbers */ +#endif #endif /* !_MACHINE_RESOURCE_H_ */ --- //depot/vendor/freebsd/src/sys/sparc64/pci/apb.c +++ //depot/projects/pci/sys/sparc64/pci/apb.c @@ -177,9 +177,9 @@ pci_read_config(dev, PCIR_COMMAND, 2); sc->sc_bsc.ops_pcib_sc.pribus = pci_read_config(dev, PCIR_PRIBUS_1, 1); - sc->sc_bsc.ops_pcib_sc.secbus = + sc->sc_bsc.ops_pcib_sc.bus.sec = pci_read_config(dev, PCIR_SECBUS_1, 1); - sc->sc_bsc.ops_pcib_sc.subbus = + sc->sc_bsc.ops_pcib_sc.bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1); sc->sc_bsc.ops_pcib_sc.bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); @@ -200,10 +200,10 @@ CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.pribus, 0, "Primary bus number"); SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus", - CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.secbus, 0, + CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.bus.sec, 0, "Secondary bus number"); SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus", - CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.subbus, 0, + CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.bus.sub, 0, "Subordinate bus number"); ofw_pcib_gen_setup(dev); @@ -212,9 +212,9 @@ device_printf(dev, " domain %d\n", sc->sc_bsc.ops_pcib_sc.domain); device_printf(dev, " secondary bus %d\n", - sc->sc_bsc.ops_pcib_sc.secbus); + sc->sc_bsc.ops_pcib_sc.bus.sec); device_printf(dev, " subordinate bus %d\n", - sc->sc_bsc.ops_pcib_sc.subbus); + sc->sc_bsc.ops_pcib_sc.bus.sub); device_printf(dev, " I/O decode "); apb_map_print(sc->sc_iomap, APB_IO_SCALE); printf("\n"); --- //depot/vendor/freebsd/src/sys/x86/include/legacyvar.h +++ //depot/projects/pci/sys/x86/include/legacyvar.h @@ -57,6 +57,10 @@ uintptr_t value); struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags); +int legacy_pcib_adjust_resource(device_t dev, device_t child, int type, + struct resource *r, u_long start, u_long end); +int legacy_pcib_release_resource(device_t dev, device_t child, int type, + int rid, struct resource *r); int legacy_pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs); int legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq); --- //depot/vendor/freebsd/src/sys/x86/pci/pci_bus.c +++ //depot/projects/pci/sys/x86/pci/pci_bus.c @@ -597,10 +597,37 @@ u_long start, u_long end, u_long count, u_int flags) { - start = hostb_alloc_start(type, start, end, count); - return (bus_generic_alloc_resource(dev, child, type, rid, start, end, - count, flags)); +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + if (type == PCI_RES_BUS) + return (pci_domain_alloc_bus(0, child, rid, start, end, count, + flags)); +#endif + start = hostb_alloc_start(type, start, end, count); + return (bus_generic_alloc_resource(dev, child, type, rid, start, end, + count, flags)); +} + +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) +int +legacy_pcib_adjust_resource(device_t dev, device_t child, int type, + struct resource *r, u_long start, u_long end) +{ + + if (type == PCI_RES_BUS) + return (pci_domain_adjust_bus(0, child, r, start, end)); + return (bus_generic_adjust_resource(dev, child, type, r, start, end)); +} + +int +legacy_pcib_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + + if (type == PCI_RES_BUS) + return (pci_domain_release_bus(0, child, rid, r)); + return (bus_generic_release_resource(dev, child, type, rid, r)); } +#endif static device_method_t legacy_pcib_methods[] = { /* Device interface */ @@ -615,8 +642,13 @@ DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar), DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar), DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource), +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + DEVMETHOD(bus_adjust_resource, legacy_pcib_adjust_resource), + DEVMETHOD(bus_release_resource, legacy_pcib_release_resource), +#else DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), +#endif DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), --- //depot/vendor/freebsd/src/sys/x86/pci/qpi.c +++ //depot/projects/pci/sys/x86/pci/qpi.c @@ -238,6 +238,20 @@ } } +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) +static struct resource * +qpi_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + + if (type == PCI_RES_BUS) + return (pci_domain_alloc_bus(0, child, rid, start, end, count, + flags)); + return (bus_generic_alloc_resource(dev, child, type, rid, start, end, + count, flags)); +} +#endif + static int qpi_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data) @@ -258,8 +272,14 @@ /* Bus interface */ DEVMETHOD(bus_read_ivar, qpi_pcib_read_ivar), +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + DEVMETHOD(bus_alloc_resource, qpi_pcib_alloc_resource), + DEVMETHOD(bus_adjust_resource, legacy_pcib_adjust_resource), + DEVMETHOD(bus_release_resource, legacy_pcib_release_resource), +#else DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), +#endif DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), --- //depot/vendor/freebsd/src/sys/x86/x86/mptable_pci.c +++ //depot/projects/pci/sys/x86/x86/mptable_pci.c @@ -105,6 +105,11 @@ { struct mptable_hostb_softc *sc; +#ifdef PCI_RES_BUS + if (type == PCI_RES_BUS) + return (pci_domain_alloc_bus(0, child, rid, start, end, count, + flags)); +#endif sc = device_get_softc(dev); if (type == SYS_RES_IOPORT && start + count - 1 == end) { if (mptable_is_isa_range(start, end)) { @@ -141,6 +146,10 @@ { struct mptable_hostb_softc *sc; +#ifdef PCI_RES_BUS + if (type == PCI_RES_BUS) + return (pci_domain_adjust_bus(0, child, r, start, end)); +#endif sc = device_get_softc(dev); return (pcib_host_res_adjust(&sc->sc_host_res, child, type, r, start, end)); @@ -165,7 +174,11 @@ DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource), DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), #endif +#if defined(NEW_PCIB) && defined(PCI_RES_BUS) + DEVMETHOD(bus_release_resource, legacy_pcib_release_resource), +#else DEVMETHOD(bus_release_resource, bus_generic_release_resource), +#endif DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),