From bda8e754a1ac3be73c297bf03353d56c7ab81ce3 Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Sun, 2 Oct 2011 23:22:38 +0000 Subject: [PATCH] Make sparc64 compatible with NEW_PCIB and enable it: - Implement bus_adjust_resource() methods as far as necessary and in non-PCI bridge drivers as far as feasible without rototilling them. - As NEW_PCIB does a layering violation by activating resources at layers above pci(4) without previously bubbling up their allocation there, move the assignment of bus tags and handles from the bus_alloc_resource() to the bus_activate_resource() methods like at least the other NEW_PCIB enabled architectures do. This is somewhat unfortunate as previously sparc64 (ab)used resource activation to indicate whether SYS_RES_MEMORY resources should be mapped into KVA, which is only necessary if their going to be accessed via the pointer returned from rman_get_virtual() but not for bus_space(9) as the later always uses physical access on sparc64. Besides wasting KVA if we always map in SYS_RES_MEMORY resources, a driver also may deliberately not map them in if the firmware already has done so, possibly in a special way. So in order to still allow a driver to decide whether a SYS_RES_MEMORY resource should be mapped into KVA we let it indicate that by calling bus_space_map(9) with BUS_SPACE_MAP_LINEAR as actually documented in the bus_space(9) page. This is implemented by allocating a separate bus tag per SYS_RES_MEMORY resource and passing the resource via the previously unused bus tag cookie so we later on can call rman_set_virtual() in sparc64_bus_mem_map(). As a side effect this now also allows to actually indicate that a SYS_RES_MEMORY resource should be mapped in as cacheable and/or read-only via BUS_SPACE_MAP_CACHEABLE and BUS_SPACE_MAP_READONLY respectively. - Do some minor cleanup like taking advantage of rman_init_from_resource(), factor out the common part of bus tag allocation into a newly added sparc64_alloc_bus_tag(), hook up some missing newbus methods and replace some homegrown versions with the generic counterparts etc. - While at it, let apb_attach() (which can't use the generic NEW_PCIB code as APB bridges just don't have the base and limit registers implemented) regarding the config space registers cached in pcib_softc and the SYSCTL reporting nodes set up. --- sys/dev/fb/machfb.c | 112 ++++++++++---------- sys/dev/le/lebuffer_sbus.c | 1 + sys/sparc64/central/central.c | 11 ++ sys/sparc64/conf/DEFAULTS | 2 + sys/sparc64/ebus/ebus.c | 102 ++++++++++++------- sys/sparc64/fhc/fhc.c | 11 ++ sys/sparc64/include/bus.h | 23 +---- sys/sparc64/include/bus_private.h | 12 ++- sys/sparc64/pci/apb.c | 62 +++++++++++- sys/sparc64/pci/fire.c | 157 ++++++++++++---------------- sys/sparc64/pci/firevar.h | 1 - sys/sparc64/pci/ofw_pcib_subr.c | 1 + sys/sparc64/pci/psycho.c | 157 ++++++++++++---------------- sys/sparc64/pci/psychovar.h | 1 - sys/sparc64/pci/sbbc.c | 60 ++++++++--- sys/sparc64/pci/schizo.c | 163 +++++++++++++----------------- sys/sparc64/pci/schizovar.h | 1 - sys/sparc64/sbus/dma_sbus.c | 1 + sys/sparc64/sbus/sbus.c | 158 ++++++++++++++--------------- sys/sparc64/sparc64/bus_machdep.c | 75 ++++++++++++-- sys/sparc64/sparc64/nexus.c | 110 ++++++++++++-------- sys/sparc64/sparc64/upa.c | 15 ++- 22 files changed, 685 insertions(+), 551 deletions(-) diff --git a/sys/dev/fb/machfb.c b/sys/dev/fb/machfb.c index dad41d86ba75..1c3023de4d56 100644 --- a/sys/dev/fb/machfb.c +++ b/sys/dev/fb/machfb.c @@ -87,7 +87,9 @@ struct machfb_softc { struct resource *sc_vmemres; bus_space_tag_t sc_memt; bus_space_tag_t sc_regt; + bus_space_tag_t sc_vmemt; bus_space_handle_t sc_memh; + bus_space_handle_t sc_vmemh; bus_space_handle_t sc_regh; u_long sc_mem; u_long sc_vmem; @@ -1175,68 +1177,52 @@ machfb_pci_attach(device_t dev) adp = &sc->sc_va; vi = &adp->va_info; - /* - * Allocate resources regardless of whether we are the console - * and already obtained the bus tag and handle for the framebuffer - * in machfb_configure() or not so the resources are marked as - * taken in the respective RMAN. - */ - - /* Enable memory and IO access. */ - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_PORTEN | - PCIM_CMD_MEMEN, 2); - - /* - * NB: we need to take care that the framebuffer isn't mapped - * in twice as besides wasting resources this isn't possible with - * all MMUs. - */ rid = PCIR_BAR(0); - if ((sc->sc_memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &rid, 0)) == NULL) { + if ((sc->sc_memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE)) == NULL) { device_printf(dev, "cannot allocate memory resources\n"); return (ENXIO); } + sc->sc_memt = rman_get_bustag(sc->sc_memres); + sc->sc_memh = rman_get_bushandle(sc->sc_memres); + sc->sc_mem = rman_get_start(sc->sc_memres); + vi->vi_buffer = sc->sc_memh; + vi->vi_buffer_size = rman_get_size(sc->sc_memres); if (OF_getprop(sc->sc_node, "address", &u32, sizeof(u32)) > 0 && - vtophys(u32) == rman_get_bushandle(sc->sc_memres)) + vtophys(u32) == sc->sc_memh) adp->va_mem_base = u32; else { - bus_release_resource(dev, SYS_RES_MEMORY, - rman_get_rid(sc->sc_memres), sc->sc_memres); - rid = PCIR_BAR(0); - if ((sc->sc_memres = bus_alloc_resource_any(dev, - SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) { - device_printf(dev, - "cannot allocate memory resources\n"); - return (ENXIO); + if (bus_space_map(sc->sc_memt, vi->vi_buffer, + vi->vi_buffer_size, BUS_SPACE_MAP_LINEAR, + &sc->sc_memh) != 0) { + device_printf(dev, "cannot map memory resources\n"); + error = ENXIO; + goto fail_memres; } adp->va_mem_base = (vm_offset_t)rman_get_virtual(sc->sc_memres); } - sc->sc_memt = rman_get_bustag(sc->sc_memres); - sc->sc_memh = rman_get_bushandle(sc->sc_memres); - sc->sc_regt = sc->sc_memt; - bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF, - MACH64_REG_SIZE, &sc->sc_regh); - adp->va_mem_size = rman_get_size(sc->sc_memres); + adp->va_mem_size = vi->vi_buffer_size; adp->va_buffer = adp->va_mem_base; adp->va_buffer_size = adp->va_mem_size; - sc->sc_mem = rman_get_start(sc->sc_memres); - vi->vi_buffer = sc->sc_memh; - vi->vi_buffer_size = adp->va_buffer_size; + sc->sc_regt = sc->sc_memt; + if (bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF, + MACH64_REG_SIZE, &sc->sc_regh) != 0) { + device_printf(dev, "cannot allocate register resources\n"); + error = ENXIO; + goto fail_memmap; + } /* * Depending on the firmware version the VGA I/O and/or memory - * resources of the Mach64 chips come up disabled. We generally - * enable them above (pci(4) actually already did this unless - * pci_enable_io_modes is not set) but this doesn't necessarily - * mean that we get valid ones. Invalid resources seem to have - * in common that they start at address 0. We don't allocate - * them in this case in order to avoid warnings in apb(4) and - * crashes when using these invalid resources. X.Org is aware - * of this and doesn't use the VGA resources in this case (but - * demands them if they are valid). + * resources of the Mach64 chips come up disabled. These will be + * enabled by pci(4) when activating the resource in question but + * this doesn't necessarily mean that the resource is valid. + * Invalid resources seem to have in common that they start at + * address 0. We don't allocate the VGA memory in this case in + * order to avoid warnings in apb(4) and crashes when using this + * invalid resources. X.Org is aware of this and doesn't use the + * VGA memory resource in this case (but demands it if it's valid). */ rid = PCIR_BAR(2); if (bus_get_resource_start(dev, SYS_RES_MEMORY, rid) != 0) { @@ -1245,21 +1231,31 @@ machfb_pci_attach(device_t dev) device_printf(dev, "cannot allocate VGA memory resources\n"); error = ENXIO; - goto fail_memres; + goto fail_memmap; + } + sc->sc_vmemt = rman_get_bustag(sc->sc_vmemres); + sc->sc_vmemh = rman_get_bushandle(sc->sc_vmemres); + sc->sc_vmem = rman_get_start(sc->sc_vmemres); + vi->vi_registers = sc->sc_vmemh; + vi->vi_registers_size = rman_get_size(sc->sc_vmemres); + if (bus_space_map(sc->sc_vmemt, vi->vi_registers, + vi->vi_registers_size, BUS_SPACE_MAP_LINEAR, + &sc->sc_vmemh) != 0) { + device_printf(dev, + "cannot map VGA memory resources\n"); + error = ENXIO; + goto fail_vmemres; } adp->va_registers = (vm_offset_t)rman_get_virtual(sc->sc_vmemres); - adp->va_registers_size = rman_get_size(sc->sc_vmemres); - sc->sc_vmem = rman_get_start(sc->sc_vmemres); - vi->vi_registers = rman_get_bushandle(sc->sc_vmemres); - vi->vi_registers_size = adp->va_registers_size; + adp->va_registers_size = vi->vi_registers_size; } if (!(sc->sc_flags & MACHFB_CONSOLE)) { if ((sw = vid_get_switch(MACHFB_DRIVER_NAME)) == NULL) { device_printf(dev, "cannot get video switch\n"); error = ENODEV; - goto fail_vmemres; + goto fail_vmemmap; } /* * During device configuration we don't necessarily probe @@ -1275,7 +1271,7 @@ machfb_pci_attach(device_t dev) break; if ((error = sw->init(i, adp, 0)) != 0) { device_printf(dev, "cannot initialize adapter\n"); - goto fail_vmemres; + goto fail_vmemmap; } } @@ -1283,8 +1279,8 @@ machfb_pci_attach(device_t dev) * Test whether the aperture is byte swapped or not, set * va_window and va_window_size as appropriate. Note that * the aperture could be mapped either big or little endian - * on independently of the endianess of the host so this - * has to be a runtime test. + * independently of the endianess of the host so this has + * to be a runtime test. */ p32 = (uint32_t *)adp->va_buffer; u32 = *p32; @@ -1346,10 +1342,16 @@ machfb_pci_attach(device_t dev) return (0); + fail_vmemmap: + if (adp->va_registers != 0) + bus_space_unmap(sc->sc_vmemt, sc->sc_vmemh, + vi->vi_registers_size); fail_vmemres: if (sc->sc_vmemres != NULL) bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->sc_vmemres), sc->sc_vmemres); + fail_memmap: + bus_space_unmap(sc->sc_memt, sc->sc_memh, vi->vi_buffer_size); fail_memres: bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->sc_memres), sc->sc_memres); diff --git a/sys/dev/le/lebuffer_sbus.c b/sys/dev/le/lebuffer_sbus.c index 1f768a11f1fe..1254fc3b5a99 100644 --- a/sys/dev/le/lebuffer_sbus.c +++ b/sys/dev/le/lebuffer_sbus.c @@ -81,6 +81,7 @@ static device_method_t lebuffer_methods[] = { DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), + DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), diff --git a/sys/sparc64/central/central.c b/sys/sparc64/central/central.c index 777660fdfebb..e418a8be458d 100644 --- a/sys/sparc64/central/central.c +++ b/sys/sparc64/central/central.c @@ -60,6 +60,7 @@ static device_attach_t central_attach; static bus_print_child_t central_print_child; static bus_probe_nomatch_t central_probe_nomatch; static bus_alloc_resource_t central_alloc_resource; +static bus_adjust_resource_t central_adjust_resource; static bus_get_resource_list_t central_get_resource_list; static ofw_bus_get_devinfo_t central_get_devinfo; @@ -79,6 +80,7 @@ static device_method_t central_methods[] = { DEVMETHOD(bus_alloc_resource, central_alloc_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, central_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), @@ -179,6 +181,15 @@ central_attach(device_t dev) return (bus_generic_attach(dev)); } +static int +central_adjust_resource(device_t bus __unused, device_t child __unused, + int type __unused, struct resource *r __unused, u_long start __unused, + u_long end __unused) +{ + + return (ENXIO); +} + static int central_print_child(device_t dev, device_t child) { diff --git a/sys/sparc64/conf/DEFAULTS b/sys/sparc64/conf/DEFAULTS index 38b2408bf449..de7b253364fa 100644 --- a/sys/sparc64/conf/DEFAULTS +++ b/sys/sparc64/conf/DEFAULTS @@ -19,3 +19,5 @@ options GEOM_PART_VTOC8 # Let sunkbd emulate an AT keyboard by default. options SUNKBD_EMULATE_ATKBD + +#options NEW_PCIB diff --git a/sys/sparc64/ebus/ebus.c b/sys/sparc64/ebus/ebus.c index 317cdfa3b958..42bac06c1919 100644 --- a/sys/sparc64/ebus/ebus.c +++ b/sys/sparc64/ebus/ebus.c @@ -136,6 +136,8 @@ static device_attach_t ebus_pci_attach; static bus_print_child_t ebus_print_child; static bus_probe_nomatch_t ebus_probe_nomatch; static bus_alloc_resource_t ebus_alloc_resource; +static bus_activate_resource_t ebus_activate_resource; +static bus_adjust_resource_t ebus_adjust_resource; static bus_release_resource_t ebus_release_resource; static bus_setup_intr_t ebus_setup_intr; static bus_get_resource_list_t ebus_get_resource_list; @@ -161,8 +163,9 @@ static device_method_t ebus_nexus_methods[] = { DEVMETHOD(bus_print_child, ebus_print_child), DEVMETHOD(bus_probe_nomatch, ebus_probe_nomatch), DEVMETHOD(bus_alloc_resource, ebus_alloc_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_activate_resource, ebus_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, ebus_adjust_resource), DEVMETHOD(bus_release_resource, ebus_release_resource), DEVMETHOD(bus_setup_intr, ebus_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), @@ -342,16 +345,10 @@ ebus_pci_attach(device_t dev) eri->eri_res = res; eri->eri_rman.rm_type = RMAN_ARRAY; eri->eri_rman.rm_descr = "EBus range"; - if (rman_init(&eri->eri_rman) != 0) { + if (rman_init_from_resource(&eri->eri_rman, res) != 0) { printf("%s: failed to initialize rman!", __func__); goto fail; } - if (rman_manage_region(&eri->eri_rman, rman_get_start(res), - rman_get_end(res)) != 0) { - printf("%s: failed to register region!", __func__); - rman_fini(&eri->eri_rman); - goto fail; - } } return (ebus_attach(dev, sc, node)); @@ -423,12 +420,10 @@ ebus_alloc_resource(device_t bus, device_t child, int type, int *rid, struct resource_list *rl; struct resource_list_entry *rle = NULL; struct resource *res; - struct ebus_rinfo *ri; + struct ebus_rinfo *eri; struct ebus_nexus_ranges *enr; - bus_space_tag_t bt; - bus_space_handle_t bh; uint64_t cend, cstart, offset; - int i, isdefault, passthrough, ridx, rv; + int i, isdefault, passthrough, ridx; isdefault = (start == 0UL && end == ~0UL); passthrough = (device_get_parent(child) != bus); @@ -459,23 +454,17 @@ ebus_alloc_resource(device_t bus, device_t child, int type, int *rid, */ (void)ofw_isa_range_map(sc->sc_range, sc->sc_nrange, &start, &end, &ridx); - ri = &sc->sc_rinfo[ridx]; - res = rman_reserve_resource(&ri->eri_rman, start, end, - count, flags, child); + eri = &sc->sc_rinfo[ridx]; + res = rman_reserve_resource(&eri->eri_rman, start, + end, count, flags & ~RF_ACTIVE, child); if (res == NULL) return (NULL); rman_set_rid(res, *rid); - bt = rman_get_bustag(ri->eri_res); - rman_set_bustag(res, bt); - rv = bus_space_subregion(bt, - rman_get_bushandle(ri->eri_res), - rman_get_start(res) - rman_get_start(ri->eri_res), - count, &bh); - if (rv != 0) { + if ((flags & RF_ACTIVE) != 0 && bus_activate_resource( + child, type, *rid, res) != 0) { rman_release_resource(res); return (NULL); } - rman_set_bushandle(res, bh); } else { /* Map EBus ranges to nexus ranges. */ for (i = 0; i < sc->sc_nrange; i++) { @@ -496,7 +485,6 @@ ebus_alloc_resource(device_t bus, device_t child, int type, int *rid, break; } } - } if (!passthrough) rle->res = res; @@ -508,6 +496,48 @@ ebus_alloc_resource(device_t bus, device_t child, int type, int *rid, return (NULL); } +static int +ebus_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + struct ebus_softc *sc; + struct ebus_rinfo *eri; + bus_space_tag_t bt; + bus_space_handle_t bh; + int i, rv; + + sc = device_get_softc(bus); + if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) { + for (i = 0; i < sc->sc_nrange; i++) { + eri = &sc->sc_rinfo[i]; + if (rman_is_region_manager(res, &eri->eri_rman) != 0) { + bt = rman_get_bustag(eri->eri_res); + rv = bus_space_subregion(bt, + rman_get_bushandle(eri->eri_res), + rman_get_start(res) - + rman_get_start(eri->eri_res), + rman_get_size(res), &bh); + if (rv != 0) + return (rv); + rman_set_bustag(res, bt); + rman_set_bushandle(res, bh); + return (rman_activate_resource(res)); + } + } + return (EINVAL); + } + return (bus_generic_activate_resource(bus, child, type, rid, res)); +} + +static int +ebus_adjust_resource(device_t bus __unused, device_t child __unused, + int type __unused, struct resource *res __unused, u_long start __unused, + u_long end __unused) +{ + + return (ENXIO); +} + static int ebus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *res) @@ -519,13 +549,15 @@ ebus_release_resource(device_t bus, device_t child, int type, int rid, passthrough = (device_get_parent(child) != bus); rl = BUS_GET_RESOURCE_LIST(bus, child); - switch (type) { - case SYS_RES_MEMORY: - sc = device_get_softc(bus); - if ((sc->sc_flags & EBUS_PCI) == 0) - return (resource_list_release(rl, bus, child, type, - rid, res)); - if ((rv = rman_release_resource(res)) != 0) + sc = device_get_softc(bus); + if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) { + if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){ + rv = bus_deactivate_resource(child, type, rid, res); + if (rv != 0) + return (rv); + } + rv = rman_release_resource(res); + if (rv != 0) return (rv); if (!passthrough) { rle = resource_list_find(rl, type, rid); @@ -535,13 +567,9 @@ ebus_release_resource(device_t bus, device_t child, int type, int rid, ("%s: resource entry is not busy", __func__)); rle->res = NULL; } - break; - case SYS_RES_IRQ: - return (resource_list_release(rl, bus, child, type, rid, res)); - default: - panic("%s: unsupported resource type %d", __func__, type); + return (0); } - return (0); + return (resource_list_release(rl, bus, child, type, rid, res)); } static int diff --git a/sys/sparc64/fhc/fhc.c b/sys/sparc64/fhc/fhc.c index 2b15e5e3adc5..0200bb1ffdb5 100644 --- a/sys/sparc64/fhc/fhc.c +++ b/sys/sparc64/fhc/fhc.c @@ -69,6 +69,7 @@ static bus_print_child_t fhc_print_child; static bus_probe_nomatch_t fhc_probe_nomatch; static bus_setup_intr_t fhc_setup_intr; static bus_alloc_resource_t fhc_alloc_resource; +static bus_adjust_resource_t fhc_adjust_resource; static bus_get_resource_list_t fhc_get_resource_list; static ofw_bus_get_devinfo_t fhc_get_devinfo; @@ -93,6 +94,7 @@ static device_method_t fhc_methods[] = { DEVMETHOD(bus_alloc_resource, fhc_alloc_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, fhc_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_setup_intr, fhc_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), @@ -475,6 +477,15 @@ fhc_alloc_resource(device_t bus, device_t child, int type, int *rid, return (res); } +static int +fhc_adjust_resource(device_t bus __unused, device_t child __unused, + int type __unused, struct resource *r __unused, u_long start __unused, + u_long end __unused) +{ + + return (ENXIO); +} + static struct resource_list * fhc_get_resource_list(device_t bus, device_t child) { diff --git a/sys/sparc64/include/bus.h b/sys/sparc64/include/bus.h index 75e598934ec1..c641a25577d6 100644 --- a/sys/sparc64/include/bus.h +++ b/sys/sparc64/include/bus.h @@ -122,32 +122,15 @@ static int bus_space_subregion(bus_space_tag_t, bus_space_handle_t, /* * Map a region of device bus space into CPU virtual address space. */ - -static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr, - bus_size_t size, int flags, bus_space_handle_t *bshp); - -static __inline int -bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr, - bus_size_t size __unused, int flags __unused, bus_space_handle_t *bshp) -{ - - *bshp = addr; - return (0); -} +int bus_space_map(bus_space_tag_t tag, bus_addr_t address, bus_size_t size, + int flags, bus_space_handle_t *handlep); /* * Unmap a region of device bus space. */ -static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, +void bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size); -static __inline void -bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused, - bus_size_t size __unused) -{ - -} - /* This macro finds the first "upstream" implementation of method `f' */ #define _BS_CALL(t,f) \ while (t->f == NULL) \ diff --git a/sys/sparc64/include/bus_private.h b/sys/sparc64/include/bus_private.h index fb6f8d395cf2..bccd2293cdd8 100644 --- a/sys/sparc64/include/bus_private.h +++ b/sys/sparc64/include/bus_private.h @@ -36,10 +36,14 @@ /* * Helpers */ -int sparc64_bus_mem_map(bus_space_tag_t, bus_space_handle_t, bus_size_t, - int, vm_offset_t, void **); -int sparc64_bus_mem_unmap(void *, bus_size_t); -bus_space_handle_t sparc64_fake_bustag(int, bus_addr_t, struct bus_space_tag *); +int sparc64_bus_mem_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, + int flags, vm_offset_t vaddr, bus_space_handle_t *hp); +int sparc64_bus_mem_unmap(bus_space_tag_t tag, bus_space_handle_t handle, + bus_size_t size); +bus_space_tag_t sparc64_alloc_bus_tag(void *cookie, + struct bus_space_tag *ptag, int type, void *barrier); +bus_space_handle_t sparc64_fake_bustag(int space, bus_addr_t addr, + struct bus_space_tag *ptag); struct bus_dmamap_res { struct resource *dr_res; diff --git a/sys/sparc64/pci/apb.c b/sys/sparc64/pci/apb.c index 87f182109569..7d42b7b0da7f 100644 --- a/sys/sparc64/pci/apb.c +++ b/sys/sparc64/pci/apb.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -77,6 +78,7 @@ struct apb_softc { static device_probe_t apb_probe; static device_attach_t apb_attach; static bus_alloc_resource_t apb_alloc_resource; +static bus_adjust_resource_t apb_adjust_resource; static device_method_t apb_methods[] = { /* Device interface */ @@ -85,6 +87,8 @@ static device_method_t apb_methods[] = { /* Bus interface */ DEVMETHOD(bus_alloc_resource, apb_alloc_resource), + DEVMETHOD(bus_adjust_resource, apb_adjust_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), /* pcib interface */ DEVMETHOD(pcib_route_interrupt, ofw_pcib_gen_route_interrupt), @@ -158,6 +162,8 @@ static int apb_attach(device_t dev) { struct apb_softc *sc; + struct sysctl_ctx_list *sctx; + struct sysctl_oid *soid; sc = device_get_softc(dev); @@ -165,12 +171,41 @@ apb_attach(device_t dev) * Get current bridge configuration. */ sc->sc_bsc.ops_pcib_sc.domain = pci_get_domain(dev); + sc->sc_bsc.ops_pcib_sc.secstat = + pci_read_config(dev, PCIR_SECSTAT_1, 2); + sc->sc_bsc.ops_pcib_sc.command = + 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 = pci_read_config(dev, PCIR_SECBUS_1, 1); sc->sc_bsc.ops_pcib_sc.subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); + sc->sc_bsc.ops_pcib_sc.bridgectl = + pci_read_config(dev, PCIR_BRIDGECTL_1, 2); + sc->sc_bsc.ops_pcib_sc.seclat = + pci_read_config(dev, PCIR_SECLAT_1, 1); sc->sc_iomap = pci_read_config(dev, APBR_IOMAP, 1); sc->sc_memmap = pci_read_config(dev, APBR_MEMMAP, 1); + + /* + * Setup SYSCTL reporting nodes. + */ + sctx = device_get_sysctl_ctx(dev); + soid = device_get_sysctl_tree(dev); + SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "domain", + CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.domain, 0, + "Domain number"); + SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "pribus", + 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, + "Secondary bus number"); + SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus", + CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.subbus, 0, + "Subordinate bus number"); + ofw_pcib_gen_setup(dev); if (bootverbose) { @@ -233,9 +268,9 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid, "%s requested decoded I/O range 0x%lx-0x%lx\n", device_get_nameunit(child), start, end); break; - case SYS_RES_MEMORY: - if (!apb_checkrange(sc->sc_memmap, APB_MEM_SCALE, start, end)) { + if (!apb_checkrange(sc->sc_memmap, APB_MEM_SCALE, start, + end)) { device_printf(dev, "device %s requested unsupported " "memory range 0x%lx-0x%lx\n", device_get_nameunit(child), start, end); @@ -246,9 +281,6 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid, "%s requested decoded memory range 0x%lx-0x%lx\n", device_get_nameunit(child), start, end); break; - - default: - break; } passup: @@ -258,3 +290,23 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid, return (bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags)); } + +static int +apb_adjust_resource(device_t dev, device_t child, int type, + struct resource *r, u_long start, u_long end) +{ + struct apb_softc *sc; + + sc = device_get_softc(dev); + switch (type) { + case SYS_RES_IOPORT: + if (!apb_checkrange(sc->sc_iomap, APB_IO_SCALE, start, end)) + return (ENXIO); + break; + case SYS_RES_MEMORY: + if (!apb_checkrange(sc->sc_memmap, APB_MEM_SCALE, start, end)) + return (ENXIO); + break; + } + return (bus_generic_adjust_resource(dev, child, type, r, start, end)); +} diff --git a/sys/sparc64/pci/fire.c b/sys/sparc64/pci/fire.c index 040289653947..5a1e08af6fa0 100644 --- a/sys/sparc64/pci/fire.c +++ b/sys/sparc64/pci/fire.c @@ -85,7 +85,6 @@ __FBSDID("$FreeBSD$"); struct fire_msiqarg; -static bus_space_tag_t fire_alloc_bus_tag(struct fire_softc *sc, int type); static const struct fire_desc *fire_get_desc(device_t dev); static void fire_dmamap_sync(bus_dma_tag_t dt __unused, bus_dmamap_t map, bus_dmasync_op_t op); @@ -113,11 +112,11 @@ static driver_filter_t fire_xcb; * Methods */ static bus_activate_resource_t fire_activate_resource; +static bus_adjust_resource_t fire_adjust_resource; static pcib_alloc_msi_t fire_alloc_msi; static pcib_alloc_msix_t fire_alloc_msix; static bus_alloc_resource_t fire_alloc_resource; static device_attach_t fire_attach; -static bus_deactivate_resource_t fire_deactivate_resource; static bus_get_dma_tag_t fire_get_dma_tag; static ofw_bus_get_node_t fire_get_node; static pcib_map_msi_t fire_map_msi; @@ -127,7 +126,6 @@ static pcib_read_config_t fire_read_config; static bus_read_ivar_t fire_read_ivar; static pcib_release_msi_t fire_release_msi; static pcib_release_msix_t fire_release_msix; -static bus_release_resource_t fire_release_resource; static pcib_route_interrupt_t fire_route_interrupt; static bus_setup_intr_t fire_setup_intr; static bus_teardown_intr_t fire_teardown_intr; @@ -147,9 +145,10 @@ static device_method_t fire_methods[] = { DEVMETHOD(bus_setup_intr, fire_setup_intr), DEVMETHOD(bus_teardown_intr, fire_teardown_intr), DEVMETHOD(bus_alloc_resource, fire_alloc_resource), - DEVMETHOD(bus_activate_resource, fire_activate_resource), - DEVMETHOD(bus_deactivate_resource, fire_deactivate_resource), - DEVMETHOD(bus_release_resource, fire_release_resource), + DEVMETHOD(bus_activate_resource, fire_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, fire_adjust_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), DEVMETHOD(bus_get_dma_tag, fire_get_dma_tag), /* pcib interface */ @@ -757,13 +756,19 @@ fire_attach(device_t dev) free(range, M_OFWPROP); /* Allocate our tags. */ - sc->sc_pci_memt = fire_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE); - sc->sc_pci_iot = fire_alloc_bus_tag(sc, PCI_IO_BUS_SPACE); - sc->sc_pci_cfgt = fire_alloc_bus_tag(sc, PCI_CONFIG_BUS_SPACE); + sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag( + sc->sc_mem_res[FIRE_PCI]), PCI_IO_BUS_SPACE, NULL); + if (sc->sc_pci_iot == NULL) + panic("%s: could not allocate PCI I/O tag", __func__); + sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag( + sc->sc_mem_res[FIRE_PCI]), PCI_CONFIG_BUS_SPACE, NULL); + if (sc->sc_pci_cfgt == NULL) + panic("%s: could not allocate PCI configuration space tag", + __func__); if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0) - panic("%s: bus_dma_tag_create failed", __func__); + panic("%s: could not create PCI DMA tag", __func__); /* Customize the tag. */ sc->sc_pci_dmat->dt_cookie = &sc->sc_is; sc->sc_pci_dmat->dt_mt = &sc->sc_dma_methods; @@ -2015,14 +2020,10 @@ fire_alloc_resource(device_t bus, device_t child, int type, int *rid, struct fire_softc *sc; struct resource *rv; struct rman *rm; - bus_space_tag_t bt; - bus_space_handle_t bh; - int needactivate = flags & RF_ACTIVE; - - flags &= ~RF_ACTIVE; sc = device_get_softc(bus); - if (type == SYS_RES_IRQ) { + switch (type) { + case SYS_RES_IRQ: /* * XXX: Don't accept blank ranges for now, only single * interrupts. The other case should not happen with @@ -2034,38 +2035,28 @@ fire_alloc_resource(device_t bus, device_t child, int type, int *rid, panic("%s: XXX: interrupt range", __func__); if (*rid == 0) start = end = INTMAP_VEC(sc->sc_ign, end); - return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, - type, rid, start, end, count, flags)); - } - switch (type) { + return (bus_generic_alloc_resource(bus, child, type, rid, + start, end, count, flags)); case SYS_RES_MEMORY: rm = &sc->sc_pci_mem_rman; - bt = sc->sc_pci_memt; - bh = sc->sc_pci_bh[OFW_PCI_CS_MEM32]; break; case SYS_RES_IOPORT: rm = &sc->sc_pci_io_rman; - bt = sc->sc_pci_iot; - bh = sc->sc_pci_bh[OFW_PCI_CS_IO]; break; default: return (NULL); - /* NOTREACHED */ } - 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); - bh += rman_get_start(rv); - rman_set_bustag(rv, bt); - rman_set_bushandle(rv, bh); - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv)) { - rman_release_resource(rv); - return (NULL); - } + if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, + *rid, rv) != 0) { + rman_release_resource(rv); + return (NULL); } return (rv); } @@ -2074,56 +2065,56 @@ static int fire_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - void *p; - int error; + struct fire_softc *sc; + struct bus_space_tag *tag; - if (type == SYS_RES_IRQ) - return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child, - type, rid, r)); - if (type == SYS_RES_MEMORY) { - /* - * Need to memory-map the device space, as some drivers - * depend on the virtual address being set and usable. - */ - error = sparc64_bus_mem_map(rman_get_bustag(r), - rman_get_bushandle(r), rman_get_size(r), 0, 0, &p); - if (error != 0) - return (error); - rman_set_virtual(r, p); + sc = device_get_softc(bus); + switch (type) { + case SYS_RES_IRQ: + return (bus_generic_activate_resource(bus, child, type, rid, + r)); + case SYS_RES_MEMORY: + tag = sparc64_alloc_bus_tag(r, rman_get_bustag( + sc->sc_mem_res[FIRE_PCI]), PCI_MEMORY_BUS_SPACE, NULL); + if (tag == NULL) + return (ENOMEM); + rman_set_bustag(r, tag); + rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] + + rman_get_start(r)); + break; + case SYS_RES_IOPORT: + rman_set_bustag(r, sc->sc_pci_iot); + rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] + + rman_get_start(r)); + break; } return (rman_activate_resource(r)); } static int -fire_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +fire_adjust_resource(device_t bus, device_t child, int type, + struct resource *r, u_long start, u_long end) { + struct fire_softc *sc; + struct rman *rm; - if (type == SYS_RES_IRQ) - return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child, - type, rid, r)); - if (type == SYS_RES_MEMORY) { - sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r)); - rman_set_virtual(r, NULL); + sc = device_get_softc(bus); + switch (type) { + case SYS_RES_IRQ: + return (bus_generic_adjust_resource(bus, child, type, r, + start, end)); + case SYS_RES_MEMORY: + rm = &sc->sc_pci_mem_rman; + break; + case SYS_RES_IOPORT: + rm = &sc->sc_pci_io_rman; + break; + default: + return (EINVAL); } - return (rman_deactivate_resource(r)); -} - -static int -fire_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - int error; - - if (type == SYS_RES_IRQ) - return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child, - type, rid, r)); - if (rman_get_flags(r) & RF_ACTIVE) { - error = bus_deactivate_resource(child, type, rid, r); - if (error) - return (error); - } - return (rman_release_resource(r)); + if (rman_is_region_manager(r, rm) == 0) + return (EINVAL); + return (rman_adjust_resource(r, start, end)); } static bus_dma_tag_t @@ -2145,22 +2136,6 @@ fire_get_node(device_t bus, device_t child __unused) return (sc->sc_node); } -static bus_space_tag_t -fire_alloc_bus_tag(struct fire_softc *sc, int type) -{ - bus_space_tag_t bt; - - bt = malloc(sizeof(struct bus_space_tag), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (bt == NULL) - panic("%s: out of memory", __func__); - - bt->bst_cookie = sc; - bt->bst_parent = rman_get_bustag(sc->sc_mem_res[FIRE_PCI]); - bt->bst_type = type; - return (bt); -} - static u_int fire_get_timecount(struct timecounter *tc) { diff --git a/sys/sparc64/pci/firevar.h b/sys/sparc64/pci/firevar.h index 58ba419daeea..d414c1adc503 100644 --- a/sys/sparc64/pci/firevar.h +++ b/sys/sparc64/pci/firevar.h @@ -47,7 +47,6 @@ struct fire_softc { bus_space_handle_t sc_pci_bh[FIRE_NRANGE]; bus_space_tag_t sc_pci_cfgt; bus_space_tag_t sc_pci_iot; - bus_space_tag_t sc_pci_memt; bus_dma_tag_t sc_pci_dmat; device_t sc_dev; diff --git a/sys/sparc64/pci/ofw_pcib_subr.c b/sys/sparc64/pci/ofw_pcib_subr.c index 600102316e10..2ffb32d1ba3b 100644 --- a/sys/sparc64/pci/ofw_pcib_subr.c +++ b/sys/sparc64/pci/ofw_pcib_subr.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c index 2b81f2721787..f7b5d4a31146 100644 --- a/sys/sparc64/pci/psycho.c +++ b/sys/sparc64/pci/psycho.c @@ -89,7 +89,6 @@ static void psycho_intr_enable(void *); static void psycho_intr_disable(void *); static void psycho_intr_assign(void *); static void psycho_intr_clear(void *); -static bus_space_tag_t psycho_alloc_bus_tag(struct psycho_softc *, int); /* Interrupt handlers */ static driver_filter_t psycho_ue; @@ -113,8 +112,7 @@ static bus_read_ivar_t psycho_read_ivar; static bus_setup_intr_t psycho_setup_intr; static bus_alloc_resource_t psycho_alloc_resource; static bus_activate_resource_t psycho_activate_resource; -static bus_deactivate_resource_t psycho_deactivate_resource; -static bus_release_resource_t psycho_release_resource; +static bus_adjust_resource_t psycho_adjust_resource; static bus_get_dma_tag_t psycho_get_dma_tag; static pcib_maxslots_t psycho_maxslots; static pcib_read_config_t psycho_read_config; @@ -137,9 +135,10 @@ static device_method_t psycho_methods[] = { DEVMETHOD(bus_setup_intr, psycho_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_alloc_resource, psycho_alloc_resource), - DEVMETHOD(bus_activate_resource, psycho_activate_resource), - DEVMETHOD(bus_deactivate_resource, psycho_deactivate_resource), - DEVMETHOD(bus_release_resource, psycho_release_resource), + DEVMETHOD(bus_activate_resource, psycho_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, psycho_adjust_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), DEVMETHOD(bus_describe_intr, bus_generic_describe_intr), DEVMETHOD(bus_get_dma_tag, psycho_get_dma_tag), @@ -567,13 +566,19 @@ psycho_attach(device_t dev) } /* Allocate our tags. */ - sc->sc_pci_memt = psycho_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE); - sc->sc_pci_iot = psycho_alloc_bus_tag(sc, PCI_IO_BUS_SPACE); - sc->sc_pci_cfgt = psycho_alloc_bus_tag(sc, PCI_CONFIG_BUS_SPACE); + sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag( + sc->sc_mem_res), PCI_IO_BUS_SPACE, NULL); + if (sc->sc_pci_iot == NULL) + panic("%s: could not allocate PCI I/O tag", __func__); + sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag( + sc->sc_mem_res), PCI_CONFIG_BUS_SPACE, NULL); + if (sc->sc_pci_cfgt == NULL) + panic("%s: could not allocate PCI configuration space tag", + __func__); if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, sc->sc_is->is_pmaxaddr, ~0, NULL, NULL, sc->sc_is->is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0) - panic("%s: bus_dma_tag_create failed", __func__); + panic("%s: could not create PCI DMA tag", __func__); /* Customize the tag. */ sc->sc_pci_dmat->dt_cookie = sc->sc_is; sc->sc_pci_dmat->dt_mt = sc->sc_dma_methods; @@ -1165,14 +1170,10 @@ psycho_alloc_resource(device_t bus, device_t child, int type, int *rid, struct psycho_softc *sc; struct resource *rv; struct rman *rm; - bus_space_tag_t bt; - bus_space_handle_t bh; - int needactivate = flags & RF_ACTIVE; - - flags &= ~RF_ACTIVE; sc = device_get_softc(bus); - if (type == SYS_RES_IRQ) { + switch (type) { + case SYS_RES_IRQ: /* * XXX: Don't accept blank ranges for now, only single * interrupts. The other case should not happen with @@ -1183,38 +1184,28 @@ psycho_alloc_resource(device_t bus, device_t child, int type, int *rid, if (start != end) panic("%s: XXX: interrupt range", __func__); start = end = INTMAP_VEC(sc->sc_ign, end); - return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, - type, rid, start, end, count, flags)); - } - switch (type) { + return (bus_generic_alloc_resource(bus, child, type, rid, + start, end, count, flags)); case SYS_RES_MEMORY: rm = &sc->sc_pci_mem_rman; - bt = sc->sc_pci_memt; - bh = sc->sc_pci_bh[OFW_PCI_CS_MEM32]; break; case SYS_RES_IOPORT: rm = &sc->sc_pci_io_rman; - bt = sc->sc_pci_iot; - bh = sc->sc_pci_bh[OFW_PCI_CS_IO]; break; default: return (NULL); - /* NOTREACHED */ } - 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); - bh += rman_get_start(rv); - rman_set_bustag(rv, bt); - rman_set_bushandle(rv, bh); - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv)) { - rman_release_resource(rv); - return (NULL); - } + if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, + *rid, rv) != 0) { + rman_release_resource(rv); + return (NULL); } return (rv); } @@ -1223,56 +1214,56 @@ static int psycho_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - void *p; - int error; + struct psycho_softc *sc; + struct bus_space_tag *tag; - if (type == SYS_RES_IRQ) - return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child, - type, rid, r)); - if (type == SYS_RES_MEMORY) { - /* - * Need to memory-map the device space, as some drivers - * depend on the virtual address being set and usable. - */ - error = sparc64_bus_mem_map(rman_get_bustag(r), - rman_get_bushandle(r), rman_get_size(r), 0, 0, &p); - if (error != 0) - return (error); - rman_set_virtual(r, p); + sc = device_get_softc(bus); + switch (type) { + case SYS_RES_IRQ: + return (bus_generic_activate_resource(bus, child, type, rid, + r)); + case SYS_RES_MEMORY: + tag = sparc64_alloc_bus_tag(r, rman_get_bustag( + sc->sc_mem_res), PCI_MEMORY_BUS_SPACE, NULL); + if (tag == NULL) + return (ENOMEM); + rman_set_bustag(r, tag); + rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] + + rman_get_start(r)); + break; + case SYS_RES_IOPORT: + rman_set_bustag(r, sc->sc_pci_iot); + rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] + + rman_get_start(r)); + break; } return (rman_activate_resource(r)); } static int -psycho_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +psycho_adjust_resource(device_t bus, device_t child, int type, + struct resource *r, u_long start, u_long end) { + struct psycho_softc *sc; + struct rman *rm; - if (type == SYS_RES_IRQ) - return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child, - type, rid, r)); - if (type == SYS_RES_MEMORY) { - sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r)); - rman_set_virtual(r, NULL); + sc = device_get_softc(bus); + switch (type) { + case SYS_RES_IRQ: + return (bus_generic_adjust_resource(bus, child, type, r, + start, end)); + case SYS_RES_MEMORY: + rm = &sc->sc_pci_mem_rman; + break; + case SYS_RES_IOPORT: + rm = &sc->sc_pci_io_rman; + break; + default: + return (EINVAL); } - return (rman_deactivate_resource(r)); -} - -static int -psycho_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - int error; - - if (type == SYS_RES_IRQ) - return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child, - type, rid, r)); - if (rman_get_flags(r) & RF_ACTIVE) { - error = bus_deactivate_resource(child, type, rid, r); - if (error) - return (error); - } - return (rman_release_resource(r)); + if (rman_is_region_manager(r, rm) == 0) + return (EINVAL); + return (rman_adjust_resource(r, start, end)); } static bus_dma_tag_t @@ -1312,19 +1303,3 @@ psycho_setup_device(device_t bus, device_t child) PCICTL_WRITE8(sc, PCR_CS, PCICTL_READ8(sc, PCR_CS) & ~PCICTL_ARB_PARK); } - -static bus_space_tag_t -psycho_alloc_bus_tag(struct psycho_softc *sc, int type) -{ - bus_space_tag_t bt; - - bt = malloc(sizeof(struct bus_space_tag), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (bt == NULL) - panic("%s: out of memory", __func__); - - bt->bst_cookie = sc; - bt->bst_parent = rman_get_bustag(sc->sc_mem_res); - bt->bst_type = type; - return (bt); -} diff --git a/sys/sparc64/pci/psychovar.h b/sys/sparc64/pci/psychovar.h index 117b7385aeb3..5532d16bbe6f 100644 --- a/sys/sparc64/pci/psychovar.h +++ b/sys/sparc64/pci/psychovar.h @@ -65,7 +65,6 @@ struct psycho_softc { /* Tags for PCI access */ bus_space_tag_t sc_pci_cfgt; - bus_space_tag_t sc_pci_memt; bus_space_tag_t sc_pci_iot; bus_dma_tag_t sc_pci_dmat; diff --git a/sys/sparc64/pci/sbbc.c b/sys/sparc64/pci/sbbc.c index be95f0532114..812b350ea89c 100644 --- a/sys/sparc64/pci/sbbc.c +++ b/sys/sparc64/pci/sbbc.c @@ -259,6 +259,9 @@ static const char *sbbc_serengeti_set_console_input(char *new); /* * SBBC PCI interface */ +static bus_activate_resource_t sbbc_bus_activate_resource; +static bus_adjust_resource_t sbbc_bus_adjust_resource; +static bus_deactivate_resource_t sbbc_bus_deactivate_resource; static bus_alloc_resource_t sbbc_bus_alloc_resource; static bus_release_resource_t sbbc_bus_release_resource; static bus_get_resource_list_t sbbc_bus_get_resource_list; @@ -278,9 +281,13 @@ static device_method_t sbbc_pci_methods[] = { DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_alloc_resource, sbbc_bus_alloc_resource), + DEVMETHOD(bus_activate_resource,sbbc_bus_activate_resource), + DEVMETHOD(bus_deactivate_resource,sbbc_bus_deactivate_resource), + DEVMETHOD(bus_adjust_resource, sbbc_bus_adjust_resource), DEVMETHOD(bus_release_resource, sbbc_bus_release_resource), DEVMETHOD(bus_setup_intr, sbbc_bus_setup_intr), DEVMETHOD(bus_teardown_intr, sbbc_bus_teardown_intr), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, sbbc_bus_get_resource_list), /* clock interface */ @@ -333,11 +340,8 @@ sbbc_pci_attach(device_t dev) sc = device_get_softc(dev); rid = SBBC_PCI_BAR; - /* - * Note that we don't activate the resource so it's not mapped twice - * but only once by the firmware. - */ - sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0); + sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); if (sc->sc_res == NULL) { device_printf(dev, "failed to allocate resources\n"); return (ENXIO); @@ -402,24 +406,52 @@ sbbc_bus_alloc_resource(device_t dev, device_t child __unused, int type, sc = device_get_softc(dev); switch (type) { case SYS_RES_IRQ: - return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, type, - rid, start, end, count, flags)); + return (bus_generic_alloc_resource(dev, dev, type, rid, start, + end, count, flags)); case SYS_RES_MEMORY: return (sc->sc_res); default: return (NULL); - /* NOTREACHED */ } } +static int +sbbc_bus_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + + if (type == SYS_RES_MEMORY) + return (0); + return (bus_generic_activate_resource(bus, child, type, rid, res)); +} + +static int +sbbc_bus_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + + if (type == SYS_RES_MEMORY) + return (0); + return (bus_generic_deactivate_resource(bus, child, type, rid, res)); +} + +static int +sbbc_bus_adjust_resource(device_t bus __unused, device_t child __unused, + int type __unused, struct resource *res __unused, u_long start __unused, + u_long end __unused) +{ + + return (ENXIO); +} + static int sbbc_bus_release_resource(device_t dev, device_t child __unused, int type, int rid, struct resource *res) { if (type == SYS_RES_IRQ) - return (BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, - type, rid, res)); + return (bus_generic_release_resource(dev, dev, type, rid, + res)); return (0); } @@ -427,7 +459,7 @@ static struct resource_list * sbbc_bus_get_resource_list(device_t dev, device_t child __unused) { - return (BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev)); + return (bus_generic_get_resource_list(dev, dev)); } static int @@ -436,8 +468,8 @@ sbbc_bus_setup_intr(device_t dev, device_t child __unused, driver_intr_t *intr, void *arg, void **cookiep) { - return (BUS_SETUP_INTR(device_get_parent(dev), dev, res, flags, filt, - intr, arg, cookiep)); + return (bus_generic_setup_intr(dev, dev, res, flags, filt, intr, arg, + cookiep)); } static int @@ -445,7 +477,7 @@ sbbc_bus_teardown_intr(device_t dev, device_t child __unused, struct resource *res, void *cookie) { - return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, res, cookie)); + return (bus_generic_teardown_intr(dev, dev, res, cookie)); } /* diff --git a/sys/sparc64/pci/schizo.c b/sys/sparc64/pci/schizo.c index 3d147c8f3329..b0e754512515 100644 --- a/sys/sparc64/pci/schizo.c +++ b/sys/sparc64/pci/schizo.c @@ -91,7 +91,6 @@ static void schizo_intr_clear(void *); static int schizo_intr_register(struct schizo_softc *sc, u_int ino); static int schizo_get_intrmap(struct schizo_softc *, u_int, bus_addr_t *, bus_addr_t *); -static bus_space_tag_t schizo_alloc_bus_tag(struct schizo_softc *, int); static timecounter_get_t schizo_get_timecount; /* Interrupt handlers */ @@ -113,8 +112,7 @@ static bus_read_ivar_t schizo_read_ivar; static bus_setup_intr_t schizo_setup_intr; static bus_alloc_resource_t schizo_alloc_resource; static bus_activate_resource_t schizo_activate_resource; -static bus_deactivate_resource_t schizo_deactivate_resource; -static bus_release_resource_t schizo_release_resource; +static bus_adjust_resource_t schizo_adjust_resource; static bus_get_dma_tag_t schizo_get_dma_tag; static pcib_maxslots_t schizo_maxslots; static pcib_read_config_t schizo_read_config; @@ -137,9 +135,10 @@ static device_method_t schizo_methods[] = { DEVMETHOD(bus_setup_intr, schizo_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_alloc_resource, schizo_alloc_resource), - DEVMETHOD(bus_activate_resource, schizo_activate_resource), - DEVMETHOD(bus_deactivate_resource, schizo_deactivate_resource), - DEVMETHOD(bus_release_resource, schizo_release_resource), + DEVMETHOD(bus_activate_resource, schizo_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, schizo_adjust_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), DEVMETHOD(bus_get_dma_tag, schizo_get_dma_tag), /* pcib interface */ @@ -151,7 +150,7 @@ static device_method_t schizo_methods[] = { /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, schizo_get_node), - /* ofw_pci interface */ + /* ofw_pci interface */ DEVMETHOD(ofw_pci_setup_device, schizo_setup_device), KOBJMETHOD_END @@ -580,14 +579,20 @@ schizo_attach(device_t dev) SLIST_INSERT_HEAD(&schizo_softcs, sc, sc_link); /* Allocate our tags. */ - sc->sc_pci_memt = schizo_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE); - sc->sc_pci_iot = schizo_alloc_bus_tag(sc, PCI_IO_BUS_SPACE); - sc->sc_pci_cfgt = schizo_alloc_bus_tag(sc, PCI_CONFIG_BUS_SPACE); + sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag( + sc->sc_mem_res[STX_PCI]), PCI_IO_BUS_SPACE, NULL); + if (sc->sc_pci_iot == NULL) + panic("%s: could not allocate PCI I/O tag", __func__); + sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag( + sc->sc_mem_res[STX_PCI]), PCI_CONFIG_BUS_SPACE, NULL); + if (sc->sc_pci_cfgt == NULL) + panic("%s: could not allocate PCI configuration space tag", + __func__); if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, sc->sc_is.sis_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.sis_is.is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0) - panic("%s: bus_dma_tag_create failed", __func__); + panic("%s: could not create PCI DMA tag", __func__); /* Customize the tag. */ sc->sc_pci_dmat->dt_cookie = &sc->sc_is; sc->sc_pci_dmat->dt_mt = &sc->sc_dma_methods; @@ -1161,7 +1166,7 @@ schizo_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op) if ((op & BUS_DMASYNC_POSTREAD) != 0) { /* - * Note that in order to allow this function to be called from + * Note that in order to allow this function to be called from * filters we would need to use a spin mutex for serialization * but given that these disable interrupts we have to emulate * one. @@ -1333,14 +1338,10 @@ schizo_alloc_resource(device_t bus, device_t child, int type, int *rid, struct schizo_softc *sc; struct resource *rv; struct rman *rm; - bus_space_tag_t bt; - bus_space_handle_t bh; - int needactivate = flags & RF_ACTIVE; - - flags &= ~RF_ACTIVE; sc = device_get_softc(bus); - if (type == SYS_RES_IRQ) { + switch (type) { + case SYS_RES_IRQ: /* * XXX: Don't accept blank ranges for now, only single * interrupts. The other case should not happen with @@ -1351,38 +1352,28 @@ schizo_alloc_resource(device_t bus, device_t child, int type, int *rid, if (start != end) panic("%s: XXX: interrupt range", __func__); start = end = INTMAP_VEC(sc->sc_ign, end); - return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, - type, rid, start, end, count, flags)); - } - switch (type) { + return (bus_generic_alloc_resource(bus, child, type, rid, + start, end, count, flags)); case SYS_RES_MEMORY: rm = &sc->sc_pci_mem_rman; - bt = sc->sc_pci_memt; - bh = sc->sc_pci_bh[OFW_PCI_CS_MEM32]; break; case SYS_RES_IOPORT: rm = &sc->sc_pci_io_rman; - bt = sc->sc_pci_iot; - bh = sc->sc_pci_bh[OFW_PCI_CS_IO]; break; default: return (NULL); - /* NOTREACHED */ } - 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); - bh += rman_get_start(rv); - rman_set_bustag(rv, bt); - rman_set_bushandle(rv, bh); - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv)) { - rman_release_resource(rv); - return (NULL); - } + if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, + *rid, rv) != 0) { + rman_release_resource(rv); + return (NULL); } return (rv); } @@ -1391,56 +1382,56 @@ static int schizo_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - void *p; - int error; + struct schizo_softc *sc; + struct bus_space_tag *tag; - if (type == SYS_RES_IRQ) - return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child, - type, rid, r)); - if (type == SYS_RES_MEMORY) { - /* - * Need to memory-map the device space, as some drivers - * depend on the virtual address being set and usable. - */ - error = sparc64_bus_mem_map(rman_get_bustag(r), - rman_get_bushandle(r), rman_get_size(r), 0, 0, &p); - if (error != 0) - return (error); - rman_set_virtual(r, p); + sc = device_get_softc(bus); + switch (type) { + case SYS_RES_IRQ: + return (bus_generic_activate_resource(bus, child, type, rid, + r)); + case SYS_RES_MEMORY: + tag = sparc64_alloc_bus_tag(r, rman_get_bustag( + sc->sc_mem_res[STX_PCI]), PCI_MEMORY_BUS_SPACE, NULL); + if (tag == NULL) + return (ENOMEM); + rman_set_bustag(r, tag); + rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] + + rman_get_start(r)); + break; + case SYS_RES_IOPORT: + rman_set_bustag(r, sc->sc_pci_iot); + rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] + + rman_get_start(r)); + break; } return (rman_activate_resource(r)); } static int -schizo_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +schizo_adjust_resource(device_t bus, device_t child, int type, + struct resource *r, u_long start, u_long end) { + struct schizo_softc *sc; + struct rman *rm; - if (type == SYS_RES_IRQ) - return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child, - type, rid, r)); - if (type == SYS_RES_MEMORY) { - sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r)); - rman_set_virtual(r, NULL); + sc = device_get_softc(bus); + switch (type) { + case SYS_RES_IRQ: + return (bus_generic_adjust_resource(bus, child, type, r, + start, end)); + case SYS_RES_MEMORY: + rm = &sc->sc_pci_mem_rman; + break; + case SYS_RES_IOPORT: + rm = &sc->sc_pci_io_rman; + break; + default: + return (EINVAL); } - return (rman_deactivate_resource(r)); -} - -static int -schizo_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - int error; - - if (type == SYS_RES_IRQ) - return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child, - type, rid, r)); - if (rman_get_flags(r) & RF_ACTIVE) { - error = bus_deactivate_resource(child, type, rid, r); - if (error) - return (error); - } - return (rman_release_resource(r)); + if (rman_is_region_manager(r, rm) == 0) + return (EINVAL); + return (rman_adjust_resource(r, start, end)); } static bus_dma_tag_t @@ -1473,7 +1464,7 @@ schizo_setup_device(device_t bus, device_t child) /* * Disable bus parking in order to work around a bus hang caused by * Casinni/Skyhawk combinations. - */ + */ if (OF_getproplen(ofw_bus_get_node(child), "pci-req-removal") >= 0) SCHIZO_PCI_SET(sc, STX_PCI_CTRL, SCHIZO_PCI_READ_8(sc, STX_PCI_CTRL) & ~STX_PCI_CTRL_ARB_PARK); @@ -1498,22 +1489,6 @@ schizo_setup_device(device_t bus, device_t child) } } -static bus_space_tag_t -schizo_alloc_bus_tag(struct schizo_softc *sc, int type) -{ - bus_space_tag_t bt; - - bt = malloc(sizeof(struct bus_space_tag), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (bt == NULL) - panic("%s: out of memory", __func__); - - bt->bst_cookie = sc; - bt->bst_parent = rman_get_bustag(sc->sc_mem_res[STX_PCI]); - bt->bst_type = type; - return (bt); -} - static u_int schizo_get_timecount(struct timecounter *tc) { diff --git a/sys/sparc64/pci/schizovar.h b/sys/sparc64/pci/schizovar.h index 8e18b58d7b15..3fe7cdc353ca 100644 --- a/sys/sparc64/pci/schizovar.h +++ b/sys/sparc64/pci/schizovar.h @@ -81,7 +81,6 @@ struct schizo_softc { bus_space_handle_t sc_pci_bh[STX_NRANGE]; bus_space_tag_t sc_pci_cfgt; bus_space_tag_t sc_pci_iot; - bus_space_tag_t sc_pci_memt; bus_dma_tag_t sc_pci_dmat; uint32_t sc_stats_dma_ce; diff --git a/sys/sparc64/sbus/dma_sbus.c b/sys/sparc64/sbus/dma_sbus.c index 1310f375a40f..2594243df03c 100644 --- a/sys/sparc64/sbus/dma_sbus.c +++ b/sys/sparc64/sbus/dma_sbus.c @@ -118,6 +118,7 @@ static device_method_t dma_methods[] = { DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c index dbe38598265a..f9f78da45599 100644 --- a/sys/sparc64/sbus/sbus.c +++ b/sys/sparc64/sbus/sbus.c @@ -108,7 +108,6 @@ struct sbus_rd { struct sbus_softc { device_t sc_dev; bus_dma_tag_t sc_cdmatag; - bus_space_tag_t sc_cbustag; int sc_clockfreq; /* clock frequency (in Hz) */ int sc_nrange; struct sbus_rd *sc_rd; @@ -137,9 +136,9 @@ static bus_read_ivar_t sbus_read_ivar; static bus_get_resource_list_t sbus_get_resource_list; static bus_setup_intr_t sbus_setup_intr; static bus_alloc_resource_t sbus_alloc_resource; -static bus_release_resource_t sbus_release_resource; static bus_activate_resource_t sbus_activate_resource; -static bus_deactivate_resource_t sbus_deactivate_resource; +static bus_adjust_resource_t sbus_adjust_resource; +static bus_release_resource_t sbus_release_resource; static bus_get_dma_tag_t sbus_get_dma_tag; static ofw_bus_get_devinfo_t sbus_get_devinfo; @@ -153,7 +152,6 @@ static void sbus_intr_assign(void *); static void sbus_intr_clear(void *); static int sbus_find_intrmap(struct sbus_softc *, u_int, bus_addr_t *, bus_addr_t *); -static bus_space_tag_t sbus_alloc_bustag(struct sbus_softc *); static driver_intr_t sbus_overtemp; static driver_intr_t sbus_pwrfail; static int sbus_print_res(struct sbus_devinfo *); @@ -171,10 +169,11 @@ static device_method_t sbus_methods[] = { DEVMETHOD(bus_probe_nomatch, sbus_probe_nomatch), DEVMETHOD(bus_read_ivar, sbus_read_ivar), DEVMETHOD(bus_alloc_resource, sbus_alloc_resource), - DEVMETHOD(bus_activate_resource, sbus_activate_resource), - DEVMETHOD(bus_deactivate_resource, sbus_deactivate_resource), + DEVMETHOD(bus_activate_resource, sbus_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, sbus_adjust_resource), DEVMETHOD(bus_release_resource, sbus_release_resource), - DEVMETHOD(bus_setup_intr, sbus_setup_intr), + DEVMETHOD(bus_setup_intr, sbus_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, sbus_get_resource_list), @@ -284,7 +283,6 @@ sbus_attach(device_t dev) if (OF_getprop(node, "interrupts", &prop, sizeof(prop)) == -1) panic("%s: cannot get IGN", __func__); sc->sc_ign = INTIGN(prop); - sc->sc_cbustag = sbus_alloc_bustag(sc); /* * Record clock frequency for synchronous SCSI. @@ -343,7 +341,6 @@ sbus_attach(device_t dev) sc->sc_burst = (SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF; - /* initalise the IOMMU */ /* punch in our copies */ @@ -375,7 +372,7 @@ sbus_attach(device_t dev) sc->sc_cdmatag->dt_cookie = &sc->sc_is; sc->sc_cdmatag->dt_mt = &iommu_dma_methods; - /* + /* * Hunt through all the interrupt mapping regs and register our * interrupt controller for the corresponding interrupt vectors. * We do this early in order to be able to catch stray interrupts. @@ -701,12 +698,12 @@ sbus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, /* * Make sure the vector is fully specified and we registered * our interrupt controller for it. - */ + */ vec = rman_get_start(ires); if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &sbus_ic) { device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); - return (EINVAL); - } + return (EINVAL); + } return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, arg, cookiep)); } @@ -721,14 +718,12 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid, struct resource_list *rl; struct resource_list_entry *rle; device_t schild; - bus_space_handle_t bh; bus_addr_t toffs; bus_size_t tend; int i, slot; - int isdefault, needactivate, passthrough; + int isdefault, passthrough; isdefault = (start == 0UL && end == ~0UL); - needactivate = flags & RF_ACTIVE; passthrough = (device_get_parent(child) != bus); rle = NULL; sc = device_get_softc(bus); @@ -751,7 +746,6 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid, } } rm = NULL; - bh = toffs = tend = 0; schild = child; while (device_get_parent(schild) != bus) schild = device_get_parent(schild); @@ -768,24 +762,21 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid, toffs = start - sc->sc_rd[i].rd_coffset; tend = end - sc->sc_rd[i].rd_coffset; rm = &sc->sc_rd[i].rd_rman; - bh = sc->sc_rd[i].rd_bushandle; break; } if (rm == NULL) return (NULL); - flags &= ~RF_ACTIVE; - rv = rman_reserve_resource(rm, toffs, tend, count, flags, - child); + + rv = rman_reserve_resource(rm, toffs, tend, count, flags & + ~RF_ACTIVE, child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); - rman_set_bustag(rv, sc->sc_cbustag); - rman_set_bushandle(rv, bh + rman_get_start(rv)); - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv)) { - rman_release_resource(rv); - return (NULL); - } + + if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, + type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); } if (!passthrough) rle->res = rv; @@ -799,41 +790,53 @@ static int sbus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - void *p; - int error; + struct sbus_softc *sc; + struct bus_space_tag *tag; + int i; - if (type == SYS_RES_IRQ) { - return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), - child, type, rid, r)); + switch (type) { + case SYS_RES_IRQ: + return (bus_generic_activate_resource(bus, child, type, rid, + r)); + case SYS_RES_MEMORY: + sc = device_get_softc(bus); + for (i = 0; i < sc->sc_nrange; i++) { + if (rman_is_region_manager(r, + &sc->sc_rd[i].rd_rman) != 0) { + tag = sparc64_alloc_bus_tag(r, + rman_get_bustag(sc->sc_sysio_res), + SBUS_BUS_SPACE, NULL); + if (tag == NULL) + return (ENOMEM); + rman_set_bustag(r, tag); + rman_set_bushandle(r, + sc->sc_rd[i].rd_bushandle + + rman_get_start(r)); + return (rman_activate_resource(r)); + } + } + /* FALLTHROUGH */ + default: + return (EINVAL); } - if (type == SYS_RES_MEMORY) { - /* - * Need to memory-map the device space, as some drivers - * depend on the virtual address being set and usable. - */ - error = sparc64_bus_mem_map(rman_get_bustag(r), - rman_get_bushandle(r), rman_get_size(r), 0, 0, &p); - if (error != 0) - return (error); - rman_set_virtual(r, p); - } - return (rman_activate_resource(r)); } static int -sbus_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +sbus_adjust_resource(device_t bus, device_t child, int type, + struct resource *r, u_long start, u_long end) { + struct sbus_softc *sc; + int i; - if (type == SYS_RES_IRQ) { - return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), - child, type, rid, r)); - } if (type == SYS_RES_MEMORY) { - sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r)); - rman_set_virtual(r, NULL); + sc = device_get_softc(bus); + for (i = 0; i < sc->sc_nrange; i++) + if (rman_is_region_manager(r, + &sc->sc_rd[i].rd_rman) != 0) + return (rman_adjust_resource(r, start, end)); + return (EINVAL); } - return (rman_deactivate_resource(r)); + return (bus_generic_adjust_resource(bus, child, type, r, start, end)); } static int @@ -846,23 +849,26 @@ sbus_release_resource(device_t bus, device_t child, int type, int rid, passthrough = (device_get_parent(child) != bus); rl = BUS_GET_RESOURCE_LIST(bus, child); - if (type == SYS_RES_IRQ) - return (resource_list_release(rl, bus, child, type, rid, r)); - if ((rman_get_flags(r) & RF_ACTIVE) != 0) { - error = bus_deactivate_resource(child, type, rid, r); + if (type == SYS_RES_MEMORY) { + if ((rman_get_flags(r) & RF_ACTIVE) != 0) { + error = bus_deactivate_resource(child, type, rid, r); + if (error) + return (error); + } + error = rman_release_resource(r); if (error != 0) return (error); + if (!passthrough) { + rle = resource_list_find(rl, type, rid); + KASSERT(rle != NULL, + ("%s: resource entry not found!", __func__)); + KASSERT(rle->res != NULL, + ("%s: resource entry is not busy", __func__)); + rle->res = NULL; + } + return (0); } - error = rman_release_resource(r); - if (error != 0 || passthrough) - return (error); - rle = resource_list_find(rl, type, rid); - if (rle == NULL) - panic("%s: cannot find resource", __func__); - if (rle->res == NULL) - panic("%s: resource entry is not busy", __func__); - rle->res = NULL; - return (0); + return (resource_list_release(rl, bus, child, type, rid, r)); } static bus_dma_tag_t @@ -918,22 +924,6 @@ sbus_pwrfail(void *arg) shutdown_nice(0); } -static bus_space_tag_t -sbus_alloc_bustag(struct sbus_softc *sc) -{ - bus_space_tag_t sbt; - - sbt = (bus_space_tag_t)malloc(sizeof(struct bus_space_tag), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (sbt == NULL) - panic("%s: out of memory", __func__); - - sbt->bst_cookie = sc; - sbt->bst_parent = rman_get_bustag(sc->sc_sysio_res); - sbt->bst_type = SBUS_BUS_SPACE; - return (sbt); -} - static int sbus_print_res(struct sbus_devinfo *sdi) { diff --git a/sys/sparc64/sparc64/bus_machdep.c b/sys/sparc64/sparc64/bus_machdep.c index 3e8748f52872..4667e443b280 100644 --- a/sys/sparc64/sparc64/bus_machdep.c +++ b/sys/sparc64/sparc64/bus_machdep.c @@ -101,6 +101,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -665,7 +666,7 @@ nexus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) contigfree(vaddr, dmat->dt_maxsize, M_DEVBUF); } -struct bus_dma_methods nexus_dma_methods = { +static struct bus_dma_methods nexus_dma_methods = { nexus_dmamap_create, nexus_dmamap_destroy, nexus_dmamap_load, @@ -703,22 +704,43 @@ struct bus_dma_tag nexus_dmatag = { * Helpers to map/unmap bus memory */ int -sparc64_bus_mem_map(bus_space_tag_t tag, bus_space_handle_t handle, - bus_size_t size, int flags, vm_offset_t vaddr, void **hp) +bus_space_map(bus_space_tag_t tag, bus_addr_t address, bus_size_t size, + int flags, bus_space_handle_t *handlep) +{ + + return (sparc64_bus_mem_map(tag, address, size, flags, 0, handlep)); +} + +int +sparc64_bus_mem_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, + int flags, vm_offset_t vaddr, bus_space_handle_t *hp) { - vm_offset_t addr; vm_offset_t sva; vm_offset_t va; vm_paddr_t pa; vm_size_t vsz; u_long pm_flags; - addr = (vm_offset_t)handle; + /* + * Given that we use physical access for bus_space(9) there's no need + * need to map anything in unless BUS_SPACE_MAP_LINEAR is requested. + */ + if ((flags & BUS_SPACE_MAP_LINEAR) == 0) { + *hp = addr; + return (0); + } + + if (tag->bst_cookie == NULL) { + printf("%s: resource cookie not set\n", __func__); + return (EINVAL); + } + size = round_page(size); if (size == 0) { printf("%s: zero size\n", __func__); return (EINVAL); } + switch (tag->bst_type) { case PCI_CONFIG_BUS_SPACE: case PCI_IO_BUS_SPACE: @@ -730,7 +752,7 @@ sparc64_bus_mem_map(bus_space_tag_t tag, bus_space_handle_t handle, break; } - if (!(flags & BUS_SPACE_MAP_CACHEABLE)) + if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0) pm_flags |= TD_E; if (vaddr != 0L) @@ -740,9 +762,6 @@ sparc64_bus_mem_map(bus_space_tag_t tag, bus_space_handle_t handle, panic("%s: cannot allocate virtual memory", __func__); } - /* Preserve page offset. */ - *hp = (void *)(sva | ((u_long)addr & PAGE_MASK)); - pa = trunc_page(addr); if ((flags & BUS_SPACE_MAP_READONLY) == 0) pm_flags |= TD_W; @@ -755,17 +774,32 @@ sparc64_bus_mem_map(bus_space_tag_t tag, bus_space_handle_t handle, pa += PAGE_SIZE; } while ((vsz -= PAGE_SIZE) > 0); tlb_range_demap(kernel_pmap, sva, sva + size - 1); + + /* Note: we preserve the page offset. */ + rman_set_virtual(tag->bst_cookie, (void *)(sva | (addr & PAGE_MASK))); return (0); } +void +bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t handle, + bus_size_t size) +{ + + sparc64_bus_mem_unmap(tag, handle, size); +} + int -sparc64_bus_mem_unmap(void *bh, bus_size_t size) +sparc64_bus_mem_unmap(bus_space_tag_t tag, bus_space_handle_t handle, + bus_size_t size) { vm_offset_t sva; vm_offset_t va; vm_offset_t endva; - sva = trunc_page((vm_offset_t)bh); + if (tag->bst_cookie == NULL || + (sva = (vm_offset_t)rman_get_virtual(tag->bst_cookie)) == 0) + return (0); + sva = trunc_page(sva); endva = sva + round_page(size); for (va = sva; va < endva; va += PAGE_SIZE) pmap_kremove_flags(va); @@ -790,6 +824,25 @@ sparc64_fake_bustag(int space, bus_addr_t addr, struct bus_space_tag *ptag) return (addr); } +/* + * Allocate a bus tag. + */ +bus_space_tag_t +sparc64_alloc_bus_tag(void *cookie, struct bus_space_tag *ptag, int type, + void *barrier) +{ + bus_space_tag_t bt; + + bt = malloc(sizeof(struct bus_space_tag), M_DEVBUF, M_NOWAIT); + if (bt == NULL) + return (NULL); + bt->bst_cookie = cookie; + bt->bst_parent = ptag; + bt->bst_type = type; + bt->bst_bus_barrier = barrier; + return (bt); +} + /* * Base bus space handlers. */ diff --git a/sys/sparc64/sparc64/nexus.c b/sys/sparc64/sparc64/nexus.c index 4c1379e829ef..041f2ff608d6 100644 --- a/sys/sparc64/sparc64/nexus.c +++ b/sys/sparc64/sparc64/nexus.c @@ -90,6 +90,7 @@ static bus_teardown_intr_t nexus_teardown_intr; static bus_alloc_resource_t nexus_alloc_resource; static bus_activate_resource_t nexus_activate_resource; static bus_deactivate_resource_t nexus_deactivate_resource; +static bus_adjust_resource_t nexus_adjust_resource; static bus_release_resource_t nexus_release_resource; static bus_get_resource_list_t nexus_get_resource_list; #ifdef SMP @@ -122,6 +123,7 @@ static device_method_t nexus_methods[] = { DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), DEVMETHOD(bus_activate_resource, nexus_activate_resource), DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), + DEVMETHOD(bus_adjust_resource, nexus_adjust_resource), DEVMETHOD(bus_release_resource, nexus_release_resource), DEVMETHOD(bus_setup_intr, nexus_setup_intr), DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), @@ -277,22 +279,22 @@ nexus_add_child(device_t dev, u_int order, const char *name, int unit) } static int -nexus_print_child(device_t dev, device_t child) +nexus_print_child(device_t bus, device_t child) { int rv; - rv = bus_print_child_header(dev, child); + rv = bus_print_child_header(bus, child); rv += nexus_print_res(device_get_ivars(child)); - rv += bus_print_child_footer(dev, child); + rv += bus_print_child_footer(bus, child); return (rv); } static void -nexus_probe_nomatch(device_t dev, device_t child) +nexus_probe_nomatch(device_t bus, device_t child) { const char *type; - device_printf(dev, "<%s>", ofw_bus_get_name(child)); + device_printf(bus, "<%s>", ofw_bus_get_name(child)); nexus_print_res(device_get_ivars(child)); type = ofw_bus_get_type(child); printf(" type %s (no driver attached)\n", @@ -300,23 +302,24 @@ nexus_probe_nomatch(device_t dev, device_t child) } static int -nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, - driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) +nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r, + int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, + void **cookiep) { int error; - if (res == NULL) + if (r == NULL) panic("%s: NULL interrupt resource!", __func__); - if ((rman_get_flags(res) & RF_SHAREABLE) == 0) + if ((rman_get_flags(r) & RF_SHAREABLE) == 0) flags |= INTR_EXCL; /* We depend here on rman_activate_resource() being idempotent. */ - error = rman_activate_resource(res); + error = rman_activate_resource(r); if (error) return (error); - error = inthand_add(device_get_nameunit(child), rman_get_start(res), + error = inthand_add(device_get_nameunit(child), rman_get_start(r), filt, intr, arg, flags, cookiep); /* @@ -328,7 +331,8 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, } static int -nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) +nexus_teardown_intr(device_t bus __unused, device_t child __unused, + struct resource *r, void *ih) { inthand_remove(rman_get_start(r), ih); @@ -337,7 +341,8 @@ nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) #ifdef SMP static int -nexus_bind_intr(device_t dev, device_t child, struct resource *r, int cpu) +nexus_bind_intr(device_t bus __unused, device_t child __unused, + struct resource *r, int cpu) { return (intr_bind(rman_get_start(r), cpu)); @@ -345,8 +350,8 @@ nexus_bind_intr(device_t dev, device_t child, struct resource *r, int cpu) #endif static int -nexus_describe_intr(device_t dev, device_t child, struct resource *r, - void *cookie, const char *descr) +nexus_describe_intr(device_t bus __unused, device_t child __unused, + struct resource *r, void *cookie, const char *descr) { return (intr_describe(rman_get_start(r), cookie, descr)); @@ -361,10 +366,9 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, struct resource *rv; struct resource_list_entry *rle; device_t nexus; - int isdefault, needactivate, passthrough; + int isdefault, passthrough; isdefault = (start == 0UL && end == ~0UL); - needactivate = flags & RF_ACTIVE; passthrough = (device_get_parent(child) != bus); nexus = bus; while (strcmp(device_get_name(device_get_parent(nexus)), "root") != 0) @@ -397,21 +401,16 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, return (NULL); } - flags &= ~RF_ACTIVE; - 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_MEMORY) { - rman_set_bustag(rv, &nexus_bustag); - rman_set_bushandle(rv, rman_get_start(rv)); - } - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv) != 0) { - rman_release_resource(rv); - return (NULL); - } + if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, + *rid, rv) != 0) { + rman_release_resource(rv); + return (NULL); } if (!passthrough) { @@ -425,30 +424,61 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, } static int -nexus_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +nexus_activate_resource(device_t bus __unused, device_t child __unused, + int type, int rid __unused, struct resource *r) { - /* Not much to be done yet... */ + if (type == SYS_RES_MEMORY) { + rman_set_bustag(r, &nexus_bustag); + rman_set_bushandle(r, rman_get_start(r)); + } return (rman_activate_resource(r)); } static int -nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +nexus_deactivate_resource(device_t bus __unused, device_t child __unused, + int type __unused, int rid __unused, struct resource *r) { - /* Not much to be done yet... */ return (rman_deactivate_resource(r)); } static int -nexus_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) +nexus_adjust_resource(device_t bus, device_t child __unused, int type, + struct resource *r, u_long start, u_long end) +{ + struct nexus_softc *sc; + struct rman *rm; + device_t nexus; + + nexus = bus; + while (strcmp(device_get_name(device_get_parent(nexus)), "root") != 0) + nexus = device_get_parent(nexus); + sc = device_get_softc(nexus); + switch (type) { + case SYS_RES_IRQ: + rm = &sc->sc_intr_rman; + break; + case SYS_RES_MEMORY: + rm = &sc->sc_mem_rman; + break; + default: + return (EINVAL); + } + if (rm == NULL) + return (ENXIO); + if (rman_is_region_manager(r, rm) == 0) + return (EINVAL); + return (rman_adjust_resource(r, start, end)); +} + +static int +nexus_release_resource(device_t bus __unused, device_t child, int type, + int rid, struct resource *r) { int error; - if (rman_get_flags(r) & RF_ACTIVE) { + if ((rman_get_flags(r) & RF_ACTIVE) != 0) { error = bus_deactivate_resource(child, type, rid, r); if (error) return (error); @@ -457,7 +487,7 @@ nexus_release_resource(device_t bus, device_t child, int type, int rid, } static struct resource_list * -nexus_get_resource_list(device_t dev, device_t child) +nexus_get_resource_list(device_t bus __unused, device_t child) { struct nexus_devinfo *ndi; @@ -466,14 +496,14 @@ nexus_get_resource_list(device_t dev, device_t child) } static bus_dma_tag_t -nexus_get_dma_tag(device_t bus, device_t child) +nexus_get_dma_tag(device_t bus __unused, device_t child __unused) { return (&nexus_dmatag); } static const struct ofw_bus_devinfo * -nexus_get_devinfo(device_t dev, device_t child) +nexus_get_devinfo(device_t bus __unused, device_t child) { struct nexus_devinfo *ndi; diff --git a/sys/sparc64/sparc64/upa.c b/sys/sparc64/sparc64/upa.c index ecb11a2db4f3..1891de17e51f 100644 --- a/sys/sparc64/sparc64/upa.c +++ b/sys/sparc64/sparc64/upa.c @@ -99,10 +99,11 @@ struct upa_softc { static device_probe_t upa_probe; static device_attach_t upa_attach; -static bus_alloc_resource_t upa_alloc_resource; -static bus_setup_intr_t upa_setup_intr; static bus_print_child_t upa_print_child; static bus_probe_nomatch_t upa_probe_nomatch; +static bus_alloc_resource_t upa_alloc_resource; +static bus_adjust_resource_t upa_adjust_resource; +static bus_setup_intr_t upa_setup_intr; static bus_get_resource_list_t upa_get_resource_list; static ofw_bus_get_devinfo_t upa_get_devinfo; @@ -130,6 +131,7 @@ static device_method_t upa_methods[] = { DEVMETHOD(bus_alloc_resource, upa_alloc_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_adjust_resource, upa_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_setup_intr, upa_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), @@ -506,6 +508,15 @@ upa_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, arg, cookiep)); } +static int +upa_adjust_resource(device_t bus __unused, device_t child __unused, + int type __unused, struct resource *r __unused, u_long start __unused, + u_long end __unused) +{ + + return (ENXIO); +} + static struct resource_list * upa_get_resource_list(device_t dev, device_t child) {