This patch (untested) tries to fix an issue on arm I fixed on the ACPI-using platforms a while back. It fixes the top-level bus drivers to activate resources (assign bus tags and handles so you can use bus_space_*()) in bus_activate_resource() methods instead of in bus_alloc_resource(). This is important for any drivers that want do what ACPI does: allocate a resource and then subdivide it to hand it out to child devices. A driver that does this can still pass the bus_activate_resource() request up the tree to actually get bus_space properly set up with this fix. Note that i80321_pci still has a hack to deal with the variant base address for the PCI memory region, but the rest of the drivers should be correct now. Please test, thanks. --- //depot/vendor/freebsd/src/sys/arm/arm/nexus.c 2008/09/11 12:40:24 +++ //depot/user/jhb/acpipci/arm/arm/nexus.c 2008/09/11 15:37:38 @@ -198,6 +198,8 @@ struct rman *rm; int needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + switch (type) { case SYS_RES_MEMORY: rm = &mem_rman; @@ -220,8 +222,6 @@ return 0; rman_set_rid(rv, *rid); - rman_set_bustag(rv, (void*)ARM_BUS_SPACE_MEM); - rman_set_bushandle(rv, rman_get_start(rv)); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { @@ -233,7 +233,7 @@ /* * If this is a memory resource, map it into the kernel. */ - if (rman_get_bustag(r) == (void*)ARM_BUS_SPACE_MEM) { + if (type == SYS_RES_MEMORY) { caddr_t vaddr = 0; u_int32_t paddr; u_int32_t psize; @@ -244,6 +244,7 @@ poffs = paddr - trunc_page(paddr); vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs; rman_set_virtual(r, vaddr); + rman_set_bustag(r, (void*)ARM_BUS_SPACE_MEM); rman_set_bushandle(r, (bus_space_handle_t) vaddr); } return (rman_activate_resource(r)); --- //depot/vendor/freebsd/src/sys/arm/at91/at91.c 2009/01/22 21:55:14 +++ //depot/user/jhb/acpipci/arm/at91/at91.c 2009/01/26 15:14:34 @@ -549,11 +549,14 @@ struct resource_list_entry *rle; struct at91_ivar *ivar = device_get_ivars(child); struct resource_list *rl = &ivar->resources; + int needactivate = flags & RF_ACTIVE; if (device_get_parent(child) != dev) return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid, start, end, count, flags)); + flags &= ~RF_ACTIVE; + rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); @@ -573,10 +576,6 @@ case SYS_RES_MEMORY: rle->res = rman_reserve_resource(&sc->sc_mem_rman, start, end, count, flags, child); - if (rle->res != NULL) { - rman_set_bustag(rle->res, &at91_bs_tag); - rman_set_bushandle(rle->res, start); - } break; } if (rle->res) { @@ -584,6 +583,12 @@ rle->end = rman_get_end(rle->res); rle->count = count; rman_set_rid(rle->res, *rid); + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } + } } return (rle->res); } @@ -610,6 +615,11 @@ rle = resource_list_find(rl, type, rid); if (rle == NULL) return (EINVAL); + if (rman_get_flags(r) & RF_ACTIVE) { + int error = bus_deactivate_resource(child, type, rid, r); + if (error) + return (error); + } rman_release_resource(r); rle->res = NULL; return (0); @@ -649,15 +659,19 @@ #if 0 u_long p; int error; +#endif if (type == SYS_RES_MEMORY) { + rman_set_bustag(r, &at91_bs_tag); + rman_set_bushandle(r, start); +#if 0 error = bus_space_map(rman_get_bustag(r), rman_get_bushandle(r), rman_get_size(r), 0, &p); if (error) return (error); rman_set_bushandle(r, p); +#endif } -#endif return (rman_activate_resource(r)); } --- //depot/vendor/freebsd/src/sys/arm/xscale/i80321/i80321_pci.c 2007/09/30 11:08:30 +++ //depot/user/jhb/acpipci/arm/xscale/i80321/i80321_pci.c 2007/12/20 23:43:49 @@ -283,8 +283,7 @@ struct i80321_pci_softc *sc = device_get_softc(bus); struct resource *rv; struct rman *rm; - bus_space_tag_t bt = NULL; - bus_space_handle_t bh = 0; + bus_handle_t bh = 0; switch (type) { case SYS_RES_IRQ: @@ -292,7 +291,6 @@ break; case SYS_RES_MEMORY: rm = &sc->sc_mem_rman; - bt = sc->sc_pcimem; bh = (start >= 0x80000000 && start < 0x84000000) ? 0x80000000 : sc->sc_mem; start &= (0x1000000 - 1); @@ -300,8 +298,6 @@ break; case SYS_RES_IOPORT: rm = &sc->sc_io_rman; - bt = sc->sc_pciio; - bh = sc->sc_io; if (start < sc->sc_io) { start = start - 0x90000000 + sc->sc_io; end = end - 0x90000000 + sc->sc_io; @@ -311,21 +307,22 @@ return (NULL); } - rv = rman_reserve_resource(rm, start, end, count, flags, child); + rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, + child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); - if (type != SYS_RES_IRQ) { - if (type == SYS_RES_MEMORY) - bh += (rman_get_start(rv)); - rman_set_bustag(rv, bt); + if (type == SYS_RES_MEMORY) + /* + * XXX: This isn't quite right but we don't have a better way + * to pass this on to our activate_resource() routine. + */ rman_set_bushandle(rv, bh); - if (flags & RF_ACTIVE) { - if (bus_activate_resource(child, type, *rid, rv)) { - rman_release_resource(rv); - return (NULL); - } - } + if (flags & RF_ACTIVE) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } } return (rv); } @@ -334,16 +331,27 @@ i80321_pci_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { + struct i80321_pci_softc *sc = device_get_softc(bus); u_long p; int error; - - if (type == SYS_RES_MEMORY) { - error = bus_space_map(rman_get_bustag(r), - rman_get_bushandle(r), rman_get_size(r), 0, &p); + + switch (type) { + case SYS_RES_MEMORY: + /* + * XXX: We rely on having the bushandle initially set to the + * start of the PCI memio window above. + */ + error = bus_space_map(sc->sc_pcimem, rman_get_bushandle(r) + + rman_get_start(r), rman_get_size(r), 0, &p); if (error) return (error); + rman_set_bustag(r, sc->sc_pcimem); rman_set_bushandle(r, p); - + break; + case SYS_RES_IOPORT: + rman_set_bustag(r, sc->sc_pciio); + rman_set_bushandle(r, sc->sc_io); + break; } return (rman_activate_resource(r)); } --- //depot/vendor/freebsd/src/sys/arm/xscale/i80321/obio.c 2007/07/27 14:57:30 +++ //depot/user/jhb/acpipci/arm/xscale/i80321/obio.c 2007/09/24 17:24:13 @@ -98,8 +98,6 @@ { struct resource *rv; struct rman *rm; - bus_space_tag_t bt = NULL; - bus_space_handle_t bh = 0; struct obio_softc *sc = device_get_softc(bus); switch (type) { @@ -110,24 +108,24 @@ return (NULL); case SYS_RES_IOPORT: rm = &sc->oba_rman; - bt = sc->oba_st; - bh = sc->oba_addr; - start = bh; + start = sc->oba_addr; break; default: return (NULL); } - - rv = rman_reserve_resource(rm, start, end, count, flags, child); + rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, + child); if (rv == NULL) return (NULL); - if (type == SYS_RES_IRQ) - return (rv); rman_set_rid(rv, *rid); - rman_set_bustag(rv, bt); - rman_set_bushandle(rv, bh); + if (flags & RF_ACTIVE) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } + } return (rv); } @@ -136,8 +134,15 @@ obio_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - return (0); + struct obio_softc *sc = device_get_softc(bus); + + if (type == SYS_RES_IOPORT) { + rman_set_bustag(r, sc->oba_st); + rman_set_bushandle(r, sc->oba_addr); + } + return (rman_activate_resource(r)); } + static device_method_t obio_methods[] = { DEVMETHOD(device_probe, obio_probe), DEVMETHOD(device_attach, obio_attach), --- //depot/vendor/freebsd/src/sys/arm/xscale/i8134x/i81342_pci.c 2008/06/12 01:50:14 +++ //depot/user/jhb/acpipci/arm/xscale/i8134x/i81342_pci.c 2008/06/18 21:41:56 @@ -334,8 +334,7 @@ struct i81342_pci_softc *sc = device_get_softc(bus); struct resource *rv; struct rman *rm; - bus_space_tag_t bt = NULL; - bus_space_handle_t bh = 0; + u_long off; switch (type) { case SYS_RES_IRQ: @@ -343,41 +342,30 @@ break; case SYS_RES_MEMORY: rm = &sc->sc_mem_rman; - bt = &sc->sc_pcimem; - bh = 0; break; case SYS_RES_IOPORT: rm = &sc->sc_io_rman; - bt = &sc->sc_pciio; - bh = sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR : + off = sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR : IOP34X_PCIE_OIOBAR_VADDR; - start += bh; - end += bh; + start += off; + end += off; break; default: return (NULL); } - rv = rman_reserve_resource(rm, start, end, count, flags, child); + rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, + child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); - if (type != SYS_RES_IRQ) { - if (type == SYS_RES_MEMORY) - bh += (rman_get_start(rv)); - rman_set_bustag(rv, bt); - rman_set_bushandle(rv, bh); - if (flags & RF_ACTIVE) { - if (bus_activate_resource(child, type, *rid, rv)) { - rman_release_resource(rv); - return (NULL); - } - } - } + if (flags & RF_ACTIVE) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } + } return (rv); - - - return (NULL); } static int @@ -386,14 +374,23 @@ { u_long p; int error; - - if (type == SYS_RES_MEMORY) { - error = bus_space_map(rman_get_bustag(r), - rman_get_bushandle(r), rman_get_size(r), 0, &p); + + switch (type) { + case SYS_RES_MEMORY: + error = bus_space_map(&sc->sc_pcimem, rman_get_start(r), + rman_get_size(r), 0, &p); if (error) return (error); + rman_set_bustag(r, &sc->sc_pcimem); rman_set_bushandle(r, p); - + break; + case SYS_RES_IOPORT: + rman_set_bus_tag(r, &sc->sc_pciio); + if (sc->sc_is_atux) + rman_set_bushandle(r, IOP34X_PCIX_OIOBAR_VADDR); + else + rman_set_bushandle(r, IOP34X_PCIE_OIOBAR_VADDR); + break; } return (rman_activate_resource(r)); } --- //depot/vendor/freebsd/src/sys/arm/xscale/i8134x/obio.c 2007/07/27 14:57:30 +++ //depot/user/jhb/acpipci/arm/xscale/i8134x/obio.c 2007/12/20 23:44:30 @@ -93,8 +93,6 @@ { struct resource *rv; struct rman *rm; - bus_space_tag_t bt = NULL; - bus_space_handle_t bh = 0; struct obio_softc *sc = device_get_softc(bus); int unit = device_get_unit(child); @@ -110,14 +108,11 @@ return (NULL); case SYS_RES_IOPORT: rm = &sc->oba_rman; - bt = sc->oba_st; if (unit == 0) { - bh = IOP34X_UART0_VADDR; - start = bh; + start = IOP34X_UART0_VADDR; end = IOP34X_UART1_VADDR; } else { - bh = IOP34X_UART1_VADDR; - start = bh; + start = IOP34X_UART1_VADDR; end = start + 0x40; } break; @@ -126,15 +121,18 @@ } - rv = rman_reserve_resource(rm, start, end, count, flags, child); + rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, + child); if (rv == NULL) return (NULL); - if (type == SYS_RES_IRQ) - return (rv); rman_set_rid(rv, *rid); - rman_set_bustag(rv, bt); - rman_set_bushandle(rv, bh); - + if (flags & RF_ACTIVE) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } + } + return (rv); } @@ -143,8 +141,16 @@ obio_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - return (0); + + switch (type) { + case SYS_RES_IOPORT: + rman_set_bustag(r, sc->oba_st); + rman_set_bushandle(r, rman_get_start(r)); + break; + } + return (rman_activate_resource(r)); } + static device_method_t obio_methods[] = { DEVMETHOD(device_probe, obio_probe), DEVMETHOD(device_attach, obio_attach), --- //depot/vendor/freebsd/src/sys/arm/xscale/ixp425/ixp425.c 2009/02/03 19:20:14 +++ //depot/user/jhb/acpipci/arm/xscale/ixp425/ixp425.c 2009/02/04 21:20:56 @@ -361,7 +361,7 @@ struct ixp425_softc *sc = device_get_softc(dev); struct rman *rmanp; struct resource *rv; - uint32_t vbase, addr; + uint32_t addr; int irq; switch (type) { @@ -371,7 +371,7 @@ if (BUS_READ_IVAR(dev, child, IXP425_IVAR_IRQ, &irq) == 0) start = end = irq; rv = rman_reserve_resource(rmanp, start, end, count, - flags, child); + flags & ~RF_ACTIVE, child); if (rv != NULL) rman_set_rid(rv, *rid); break; @@ -390,21 +390,45 @@ return NULL; } rv = rman_reserve_resource(rmanp, start, end, count, - flags, child); - if (rv != NULL) { + flags & ~RF_ACTIVE, child); + if (rv != NULL) rman_set_rid(rv, *rid); - if (strcmp(device_get_name(child), "uart") == 0) - rman_set_bustag(rv, &ixp425_a4x_bs_tag); - else - rman_set_bustag(rv, sc->sc_iot); - rman_set_bushandle(rv, vbase); - } break; default: rv = NULL; break; } - return rv; + + if (rv != NULL && flags & RF_ACTIVE) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); +} + +static int +ixp425_activate_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + struct ixp425_softc *sc = device_get_softc(dev); + int error; + uint32_t vbase; + + if (type == SYS_RES_MEMORY) { + error = getvbase(rman_get_start(r), rman_get_size(r), &vbase); + if (error) + return (error); + if (strcmp(device_get_name(child), "uart") == 0) + rman_set_bustag(rv, &ixp425_a4x_bs_tag); + else + rman_set_bustag(rv, sc->sc_iot); + rman_set_bushandle(rv, vbase); + } + + return (rman_activate_resource(r)); } static __inline void @@ -472,6 +496,7 @@ DEVMETHOD(bus_read_ivar, ixp425_read_ivar), DEVMETHOD(bus_alloc_resource, ixp425_alloc_resource), + DEVMETHOD(bus_activate_resource, ixp425_activate_resource), DEVMETHOD(bus_setup_intr, ixp425_setup_intr), DEVMETHOD(bus_teardown_intr, ixp425_teardown_intr), --- //depot/vendor/freebsd/src/sys/arm/xscale/ixp425/ixp425_pci.c 2008/12/20 03:30:40 +++ //depot/user/jhb/acpipci/arm/xscale/ixp425/ixp425_pci.c 2009/01/15 19:41:17 @@ -278,12 +278,10 @@ ixppcib_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - bus_space_tag_t tag; struct ixppcib_softc *sc = device_get_softc(bus); struct rman *rmanp; struct resource *rv; - tag = NULL; /* shut up stupid gcc */ rv = NULL; switch (type) { case SYS_RES_IRQ: @@ -292,28 +290,25 @@ case SYS_RES_IOPORT: rmanp = &sc->sc_io_rman; - tag = &sc->sc_pci_iot; break; case SYS_RES_MEMORY: rmanp = &sc->sc_mem_rman; - tag = &sc->sc_pci_memt; break; default: return (rv); } - rv = rman_reserve_resource(rmanp, start, end, count, flags, child); - if (rv != NULL) { - rman_set_rid(rv, *rid); - if (type == SYS_RES_IOPORT) { - rman_set_bustag(rv, tag); - rman_set_bushandle(rv, rman_get_start(rv)); - } else if (type == SYS_RES_MEMORY) { - rman_set_bustag(rv, tag); - rman_set_bushandle(rv, rman_get_bushandle(sc->sc_mem) + - (rman_get_start(rv) - IXP425_PCI_MEM_HWBASE)); + rv = rman_reserve_resource(rmanp, start, end, count, flags & ~RF_ACTIVE, + child); + if (rv == NULL) + return (NULL); + rman_set_rid(rv, *rid); + if (flags & RF_ACTIVE) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); } } @@ -324,9 +319,21 @@ ixppcib_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { + struct ixppcib_softc *sc = device_get_softc(bus); - device_printf(bus, "%s called activate_resource\n", device_get_nameunit(child)); - return (ENXIO); + switch (type) { + case SYS_RES_IOPORT: + rman_set_bustag(r, &sc->sc_pci_iot); + rman_set_bushandle(r, rman_get_start(r)); + break; + case SYS_RES_MEMORY: + rman_set_bustag(r, &sc->sc_pci_memt); + rman_set_bushandle(r, rman_get_bushandle(sc->sc_mem) + + (rman_get_start(r) - IXP425_PCI_MEM_HWBASE)); + break; + } + + return (rman_activate_resource(r)); } static int