160727d8bSWarner Losh /*- 271e3c308SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 371e3c308SPedro F. Giffuni * 48860e8c6SPeter Grehan * Copyright 2002 by Peter Grehan. All rights reserved. 58860e8c6SPeter Grehan * 68860e8c6SPeter Grehan * Redistribution and use in source and binary forms, with or without 78860e8c6SPeter Grehan * modification, are permitted provided that the following conditions 88860e8c6SPeter Grehan * are met: 98860e8c6SPeter Grehan * 1. Redistributions of source code must retain the above copyright 108860e8c6SPeter Grehan * notice, this list of conditions and the following disclaimer. 118860e8c6SPeter Grehan * 2. Redistributions in binary form must reproduce the above copyright 128860e8c6SPeter Grehan * notice, this list of conditions and the following disclaimer in the 138860e8c6SPeter Grehan * documentation and/or other materials provided with the distribution. 148860e8c6SPeter Grehan * 3. The name of the author may not be used to endorse or promote products 158860e8c6SPeter Grehan * derived from this software without specific prior written permission. 168860e8c6SPeter Grehan * 178860e8c6SPeter Grehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 188860e8c6SPeter Grehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 198860e8c6SPeter Grehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 208860e8c6SPeter Grehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 218860e8c6SPeter Grehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 228860e8c6SPeter Grehan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 238860e8c6SPeter Grehan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 248860e8c6SPeter Grehan * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 258860e8c6SPeter Grehan * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 268860e8c6SPeter Grehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 278860e8c6SPeter Grehan * SUCH DAMAGE. 288860e8c6SPeter Grehan */ 298860e8c6SPeter Grehan 308860e8c6SPeter Grehan /* 318860e8c6SPeter Grehan * PSIM 'iobus' local bus. Should be set up in the device tree like: 328860e8c6SPeter Grehan * 338860e8c6SPeter Grehan * /iobus@0x80000000/name psim-iobus 348860e8c6SPeter Grehan * 358860e8c6SPeter Grehan * Code borrowed from various nexus.c and uninorth.c :-) 368860e8c6SPeter Grehan */ 378860e8c6SPeter Grehan 388860e8c6SPeter Grehan #include <sys/param.h> 398860e8c6SPeter Grehan #include <sys/systm.h> 408860e8c6SPeter Grehan #include <sys/kernel.h> 418860e8c6SPeter Grehan #include <sys/malloc.h> 4240cdee9dSPeter Grehan #include <sys/module.h> 438860e8c6SPeter Grehan #include <sys/bus.h> 448860e8c6SPeter Grehan #include <machine/bus.h> 458860e8c6SPeter Grehan #include <sys/rman.h> 468860e8c6SPeter Grehan 4751d163d3SNathan Whitehorn #include <dev/ofw/ofw_bus.h> 488860e8c6SPeter Grehan #include <dev/ofw/openfirm.h> 498860e8c6SPeter Grehan 508860e8c6SPeter Grehan #include <machine/vmparam.h> 518860e8c6SPeter Grehan #include <vm/vm.h> 528860e8c6SPeter Grehan #include <vm/pmap.h> 538860e8c6SPeter Grehan 548860e8c6SPeter Grehan #include <machine/resource.h> 558860e8c6SPeter Grehan 568860e8c6SPeter Grehan #include <powerpc/psim/iobusvar.h> 578860e8c6SPeter Grehan 5857dc54dbSPeter Grehan struct iobus_softc { 5957dc54dbSPeter Grehan phandle_t sc_node; 6057dc54dbSPeter Grehan vm_offset_t sc_addr; 6157dc54dbSPeter Grehan vm_offset_t sc_size; 6257dc54dbSPeter Grehan struct rman sc_mem_rman; 6357dc54dbSPeter Grehan }; 6457dc54dbSPeter Grehan 658860e8c6SPeter Grehan static MALLOC_DEFINE(M_IOBUS, "iobus", "iobus device information"); 668860e8c6SPeter Grehan 678860e8c6SPeter Grehan static int iobus_probe(device_t); 688860e8c6SPeter Grehan static int iobus_attach(device_t); 698860e8c6SPeter Grehan static int iobus_print_child(device_t dev, device_t child); 708860e8c6SPeter Grehan static void iobus_probe_nomatch(device_t, device_t); 718860e8c6SPeter Grehan static int iobus_read_ivar(device_t, device_t, int, uintptr_t *); 728860e8c6SPeter Grehan static int iobus_write_ivar(device_t, device_t, int, uintptr_t); 73d7c16b33SJohn Baldwin static struct rman *iobus_get_rman(device_t, int, u_int); 748860e8c6SPeter Grehan static struct resource *iobus_alloc_resource(device_t, device_t, int, int *, 752dd1bdf1SJustin Hibbits rman_res_t, rman_res_t, rman_res_t, 762dd1bdf1SJustin Hibbits u_int); 77fef01f04SJohn Baldwin static int iobus_adjust_resource(device_t, device_t, struct resource *, 78d7c16b33SJohn Baldwin rman_res_t, rman_res_t); 792baed46eSJohn Baldwin static int iobus_activate_resource(device_t, device_t, struct resource *); 802baed46eSJohn Baldwin static int iobus_deactivate_resource(device_t, device_t, struct resource *); 81d77f2092SJohn Baldwin static int iobus_map_resource(device_t, device_t, struct resource *, 82d7c16b33SJohn Baldwin struct resource_map_request *, 83d7c16b33SJohn Baldwin struct resource_map *); 84d77f2092SJohn Baldwin static int iobus_unmap_resource(device_t, device_t, struct resource *, 85d7c16b33SJohn Baldwin struct resource_map *); 869dbf5b0eSJohn Baldwin static int iobus_release_resource(device_t, device_t, struct resource *); 878860e8c6SPeter Grehan 888860e8c6SPeter Grehan /* 898860e8c6SPeter Grehan * Bus interface definition 908860e8c6SPeter Grehan */ 918860e8c6SPeter Grehan static device_method_t iobus_methods[] = { 928860e8c6SPeter Grehan /* Device interface */ 938860e8c6SPeter Grehan DEVMETHOD(device_probe, iobus_probe), 948860e8c6SPeter Grehan DEVMETHOD(device_attach, iobus_attach), 958860e8c6SPeter Grehan DEVMETHOD(device_detach, bus_generic_detach), 968860e8c6SPeter Grehan DEVMETHOD(device_shutdown, bus_generic_shutdown), 978860e8c6SPeter Grehan DEVMETHOD(device_suspend, bus_generic_suspend), 988860e8c6SPeter Grehan DEVMETHOD(device_resume, bus_generic_resume), 998860e8c6SPeter Grehan 1008860e8c6SPeter Grehan /* Bus interface */ 1018860e8c6SPeter Grehan DEVMETHOD(bus_print_child, iobus_print_child), 1028860e8c6SPeter Grehan DEVMETHOD(bus_probe_nomatch, iobus_probe_nomatch), 1038860e8c6SPeter Grehan DEVMETHOD(bus_read_ivar, iobus_read_ivar), 1048860e8c6SPeter Grehan DEVMETHOD(bus_write_ivar, iobus_write_ivar), 1058860e8c6SPeter Grehan DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 1068860e8c6SPeter Grehan DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 1078860e8c6SPeter Grehan 108d7c16b33SJohn Baldwin DEVMETHOD(bus_get_rman, iobus_get_rman), 1098860e8c6SPeter Grehan DEVMETHOD(bus_alloc_resource, iobus_alloc_resource), 110d7c16b33SJohn Baldwin DEVMETHOD(bus_adjust_resource, iobus_adjust_resource), 1118860e8c6SPeter Grehan DEVMETHOD(bus_release_resource, iobus_release_resource), 1128860e8c6SPeter Grehan DEVMETHOD(bus_activate_resource, iobus_activate_resource), 1138860e8c6SPeter Grehan DEVMETHOD(bus_deactivate_resource, iobus_deactivate_resource), 114d7c16b33SJohn Baldwin DEVMETHOD(bus_map_resource, iobus_map_resource), 115d7c16b33SJohn Baldwin DEVMETHOD(bus_unmap_resource, iobus_unmap_resource), 1168860e8c6SPeter Grehan { 0, 0 } 1178860e8c6SPeter Grehan }; 1188860e8c6SPeter Grehan 1198860e8c6SPeter Grehan static driver_t iobus_driver = { 1208860e8c6SPeter Grehan "iobus", 1218860e8c6SPeter Grehan iobus_methods, 1228860e8c6SPeter Grehan sizeof(struct iobus_softc) 1238860e8c6SPeter Grehan }; 1248860e8c6SPeter Grehan 125f92448c9SJohn Baldwin DRIVER_MODULE(iobus, ofwbus, iobus_driver, 0, 0); 1268860e8c6SPeter Grehan 1278860e8c6SPeter Grehan static int 1288860e8c6SPeter Grehan iobus_probe(device_t dev) 1298860e8c6SPeter Grehan { 13051d163d3SNathan Whitehorn const char *type = ofw_bus_get_name(dev); 1318860e8c6SPeter Grehan 1328860e8c6SPeter Grehan if (strcmp(type, "psim-iobus") != 0) 1338860e8c6SPeter Grehan return (ENXIO); 1348860e8c6SPeter Grehan 1358860e8c6SPeter Grehan device_set_desc(dev, "PSIM local bus"); 1368860e8c6SPeter Grehan return (0); 1378860e8c6SPeter Grehan } 1388860e8c6SPeter Grehan 1398860e8c6SPeter Grehan /* 1408860e8c6SPeter Grehan * Add interrupt/addr range to the dev's resource list if present 1418860e8c6SPeter Grehan */ 1428860e8c6SPeter Grehan static void 1438860e8c6SPeter Grehan iobus_add_intr(phandle_t devnode, struct iobus_devinfo *dinfo) 1448860e8c6SPeter Grehan { 1458860e8c6SPeter Grehan u_int intr = -1; 1468860e8c6SPeter Grehan 1478860e8c6SPeter Grehan if (OF_getprop(devnode, "interrupt", &intr, sizeof(intr)) != -1) { 1488860e8c6SPeter Grehan resource_list_add(&dinfo->id_resources, 1498860e8c6SPeter Grehan SYS_RES_IRQ, 0, intr, intr, 1); 1508860e8c6SPeter Grehan } 1518860e8c6SPeter Grehan dinfo->id_interrupt = intr; 1528860e8c6SPeter Grehan } 1538860e8c6SPeter Grehan 1548860e8c6SPeter Grehan static void 1558860e8c6SPeter Grehan iobus_add_reg(phandle_t devnode, struct iobus_devinfo *dinfo, 1568860e8c6SPeter Grehan vm_offset_t iobus_off) 1578860e8c6SPeter Grehan { 1588860e8c6SPeter Grehan u_int size; 1598860e8c6SPeter Grehan int i; 1608860e8c6SPeter Grehan 1618860e8c6SPeter Grehan size = OF_getprop(devnode, "reg", dinfo->id_reg,sizeof(dinfo->id_reg)); 1628860e8c6SPeter Grehan 1638860e8c6SPeter Grehan if (size != -1) { 1648860e8c6SPeter Grehan dinfo->id_nregs = size / (sizeof(dinfo->id_reg[0])); 1658860e8c6SPeter Grehan 1668860e8c6SPeter Grehan for (i = 0; i < dinfo->id_nregs; i+= 3) { 1678860e8c6SPeter Grehan /* 1688860e8c6SPeter Grehan * Scale the absolute addresses back to iobus 1698860e8c6SPeter Grehan * relative offsets. This is to better simulate 1708860e8c6SPeter Grehan * macio 1718860e8c6SPeter Grehan */ 1728860e8c6SPeter Grehan dinfo->id_reg[i+1] -= iobus_off; 1738860e8c6SPeter Grehan 1748860e8c6SPeter Grehan resource_list_add(&dinfo->id_resources, 1758860e8c6SPeter Grehan SYS_RES_MEMORY, 0, 1768860e8c6SPeter Grehan dinfo->id_reg[i+1], 1778860e8c6SPeter Grehan dinfo->id_reg[i+1] + 1788860e8c6SPeter Grehan dinfo->id_reg[i+2], 1798860e8c6SPeter Grehan dinfo->id_reg[i+2]); 1808860e8c6SPeter Grehan } 1818860e8c6SPeter Grehan } 1828860e8c6SPeter Grehan } 1838860e8c6SPeter Grehan 1848860e8c6SPeter Grehan static int 1858860e8c6SPeter Grehan iobus_attach(device_t dev) 1868860e8c6SPeter Grehan { 1878860e8c6SPeter Grehan struct iobus_softc *sc; 1888860e8c6SPeter Grehan struct iobus_devinfo *dinfo; 1898860e8c6SPeter Grehan phandle_t root; 1908860e8c6SPeter Grehan phandle_t child; 1918860e8c6SPeter Grehan device_t cdev; 1928860e8c6SPeter Grehan char *name; 1938860e8c6SPeter Grehan u_int reg[2]; 1948860e8c6SPeter Grehan int size; 1958860e8c6SPeter Grehan 1968860e8c6SPeter Grehan sc = device_get_softc(dev); 19751d163d3SNathan Whitehorn sc->sc_node = ofw_bus_get_node(dev); 1988860e8c6SPeter Grehan 1998860e8c6SPeter Grehan /* 2008860e8c6SPeter Grehan * Find the base addr/size of the iobus, and initialize the 2018860e8c6SPeter Grehan * resource manager 2028860e8c6SPeter Grehan */ 2038860e8c6SPeter Grehan size = OF_getprop(sc->sc_node, "reg", reg, sizeof(reg)); 2048860e8c6SPeter Grehan if (size == sizeof(reg)) { 2058860e8c6SPeter Grehan sc->sc_addr = reg[0]; 2068860e8c6SPeter Grehan sc->sc_size = reg[1]; 2078860e8c6SPeter Grehan } else { 2088860e8c6SPeter Grehan return (ENXIO); 2098860e8c6SPeter Grehan } 2108860e8c6SPeter Grehan 2118860e8c6SPeter Grehan sc->sc_mem_rman.rm_type = RMAN_ARRAY; 2128860e8c6SPeter Grehan sc->sc_mem_rman.rm_descr = "IOBus Device Memory"; 2138860e8c6SPeter Grehan if (rman_init(&sc->sc_mem_rman) != 0) { 2148860e8c6SPeter Grehan device_printf(dev, 2158860e8c6SPeter Grehan "failed to init mem range resources\n"); 2168860e8c6SPeter Grehan return (ENXIO); 2178860e8c6SPeter Grehan } 2188860e8c6SPeter Grehan rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size); 2198860e8c6SPeter Grehan 2208860e8c6SPeter Grehan /* 2218860e8c6SPeter Grehan * Iterate through the sub-devices 2228860e8c6SPeter Grehan */ 2238860e8c6SPeter Grehan root = sc->sc_node; 2248860e8c6SPeter Grehan 2258860e8c6SPeter Grehan for (child = OF_child(root); child != 0; child = OF_peer(child)) { 226217d17bcSOleksandr Tymoshenko OF_getprop_alloc(child, "name", (void **)&name); 2278860e8c6SPeter Grehan 2285b56413dSWarner Losh cdev = device_add_child(dev, NULL, DEVICE_UNIT_ANY); 2298860e8c6SPeter Grehan if (cdev != NULL) { 230a163d034SWarner Losh dinfo = malloc(sizeof(*dinfo), M_IOBUS, M_WAITOK); 2318860e8c6SPeter Grehan memset(dinfo, 0, sizeof(*dinfo)); 2328860e8c6SPeter Grehan resource_list_init(&dinfo->id_resources); 2338860e8c6SPeter Grehan dinfo->id_node = child; 2348860e8c6SPeter Grehan dinfo->id_name = name; 2358860e8c6SPeter Grehan iobus_add_intr(child, dinfo); 2368860e8c6SPeter Grehan iobus_add_reg(child, dinfo, sc->sc_addr); 2378860e8c6SPeter Grehan device_set_ivars(cdev, dinfo); 2388860e8c6SPeter Grehan } else { 2390cc376c1SOleksandr Tymoshenko OF_prop_free(name); 2408860e8c6SPeter Grehan } 2418860e8c6SPeter Grehan } 2428860e8c6SPeter Grehan 243*18250ec6SJohn Baldwin bus_attach_children(dev); 244*18250ec6SJohn Baldwin return (0); 2458860e8c6SPeter Grehan } 2468860e8c6SPeter Grehan 2478860e8c6SPeter Grehan static int 2488860e8c6SPeter Grehan iobus_print_child(device_t dev, device_t child) 2498860e8c6SPeter Grehan { 2508860e8c6SPeter Grehan struct iobus_devinfo *dinfo; 2518860e8c6SPeter Grehan struct resource_list *rl; 2528860e8c6SPeter Grehan int retval = 0; 2538860e8c6SPeter Grehan 2548860e8c6SPeter Grehan dinfo = device_get_ivars(child); 2558860e8c6SPeter Grehan rl = &dinfo->id_resources; 2568860e8c6SPeter Grehan 2578860e8c6SPeter Grehan retval += bus_print_child_header(dev, child); 2588860e8c6SPeter Grehan 2598860e8c6SPeter Grehan retval += printf(" offset 0x%x", dinfo->id_reg[1]); 260f8fd3fb5SJustin Hibbits retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd"); 2618860e8c6SPeter Grehan 2628860e8c6SPeter Grehan retval += bus_print_child_footer(dev, child); 2638860e8c6SPeter Grehan 2648860e8c6SPeter Grehan return (retval); 2658860e8c6SPeter Grehan } 2668860e8c6SPeter Grehan 2678860e8c6SPeter Grehan static void 2688860e8c6SPeter Grehan iobus_probe_nomatch(device_t dev, device_t child) 2698860e8c6SPeter Grehan { 2708860e8c6SPeter Grehan } 2718860e8c6SPeter Grehan 2728860e8c6SPeter Grehan static int 2738860e8c6SPeter Grehan iobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 2748860e8c6SPeter Grehan { 2758860e8c6SPeter Grehan struct iobus_devinfo *dinfo; 2768860e8c6SPeter Grehan 27726f0e234SPedro F. Giffuni if ((dinfo = device_get_ivars(child)) == NULL) 2788860e8c6SPeter Grehan return (ENOENT); 2798860e8c6SPeter Grehan 2808860e8c6SPeter Grehan switch (which) { 2818860e8c6SPeter Grehan case IOBUS_IVAR_NODE: 2828860e8c6SPeter Grehan *result = dinfo->id_node; 2838860e8c6SPeter Grehan break; 2848860e8c6SPeter Grehan case IOBUS_IVAR_NAME: 2858860e8c6SPeter Grehan *result = (uintptr_t)dinfo->id_name; 2868860e8c6SPeter Grehan break; 2878860e8c6SPeter Grehan case IOBUS_IVAR_NREGS: 2888860e8c6SPeter Grehan *result = dinfo->id_nregs; 2898860e8c6SPeter Grehan break; 2908860e8c6SPeter Grehan case IOBUS_IVAR_REGS: 2918860e8c6SPeter Grehan *result = (uintptr_t)dinfo->id_reg; 2928860e8c6SPeter Grehan break; 2938860e8c6SPeter Grehan default: 2948860e8c6SPeter Grehan return (ENOENT); 2958860e8c6SPeter Grehan } 2968860e8c6SPeter Grehan 2978860e8c6SPeter Grehan return (0); 2988860e8c6SPeter Grehan } 2998860e8c6SPeter Grehan 3008860e8c6SPeter Grehan static int 3018860e8c6SPeter Grehan iobus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 3028860e8c6SPeter Grehan { 3038860e8c6SPeter Grehan return (EINVAL); 3048860e8c6SPeter Grehan } 3058860e8c6SPeter Grehan 306d7c16b33SJohn Baldwin static struct rman * 307d7c16b33SJohn Baldwin iobus_get_rman(device_t bus, int type, u_int flags) 308d7c16b33SJohn Baldwin { 309d7c16b33SJohn Baldwin struct iobus_softc *sc; 310d7c16b33SJohn Baldwin 311d7c16b33SJohn Baldwin sc = device_get_softc(bus); 312d7c16b33SJohn Baldwin switch (type) { 313d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 314d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 315d7c16b33SJohn Baldwin return (&sc->sc_mem_rman); 316d7c16b33SJohn Baldwin default: 317d7c16b33SJohn Baldwin return (NULL); 318d7c16b33SJohn Baldwin } 319d7c16b33SJohn Baldwin } 320d7c16b33SJohn Baldwin 3218860e8c6SPeter Grehan static struct resource * 3228860e8c6SPeter Grehan iobus_alloc_resource(device_t bus, device_t child, int type, int *rid, 3232dd1bdf1SJustin Hibbits rman_res_t start, rman_res_t end, rman_res_t count, 3242dd1bdf1SJustin Hibbits u_int flags) 3258860e8c6SPeter Grehan { 3268860e8c6SPeter Grehan 3278860e8c6SPeter Grehan switch (type) { 3288860e8c6SPeter Grehan case SYS_RES_MEMORY: 3298860e8c6SPeter Grehan case SYS_RES_IOPORT: 330d7c16b33SJohn Baldwin return (bus_generic_rman_alloc_resource(bus, child, type, rid, 331d7c16b33SJohn Baldwin start, end, count, flags)); 3328860e8c6SPeter Grehan case SYS_RES_IRQ: 3338860e8c6SPeter Grehan return (bus_alloc_resource(bus, type, rid, start, end, count, 3348860e8c6SPeter Grehan flags)); 3358860e8c6SPeter Grehan default: 3368860e8c6SPeter Grehan device_printf(bus, "unknown resource request from %s\n", 3378860e8c6SPeter Grehan device_get_nameunit(child)); 3388860e8c6SPeter Grehan return (NULL); 3398860e8c6SPeter Grehan } 3408860e8c6SPeter Grehan } 3418860e8c6SPeter Grehan 342d7c16b33SJohn Baldwin static int 343fef01f04SJohn Baldwin iobus_adjust_resource(device_t bus, device_t child, struct resource *r, 344fef01f04SJohn Baldwin rman_res_t start, rman_res_t end) 345d7c16b33SJohn Baldwin { 3468860e8c6SPeter Grehan 347fef01f04SJohn Baldwin switch (rman_get_type(r)) { 348d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 349d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 350fef01f04SJohn Baldwin return (bus_generic_rman_adjust_resource(bus, child, r, start, 351ccb1b43eSJohn Baldwin end)); 352fef01f04SJohn Baldwin case SYS_RES_IRQ: 353fef01f04SJohn Baldwin return (bus_generic_adjust_resource(bus, child, r, start, end)); 354d7c16b33SJohn Baldwin default: 355d7c16b33SJohn Baldwin return (EINVAL); 3568860e8c6SPeter Grehan } 3578860e8c6SPeter Grehan } 3588860e8c6SPeter Grehan 3598860e8c6SPeter Grehan static int 3609dbf5b0eSJohn Baldwin iobus_release_resource(device_t bus, device_t child, struct resource *res) 3618860e8c6SPeter Grehan { 3628860e8c6SPeter Grehan 3639dbf5b0eSJohn Baldwin switch (rman_get_type(res)) { 364d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 365d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 3669dbf5b0eSJohn Baldwin return (bus_generic_rman_release_resource(bus, child, res)); 367d7c16b33SJohn Baldwin case SYS_RES_IRQ: 3689dbf5b0eSJohn Baldwin return (bus_generic_release_resource(bus, child, res)); 369d7c16b33SJohn Baldwin default: 370d7c16b33SJohn Baldwin return (EINVAL); 371d7c16b33SJohn Baldwin } 3728860e8c6SPeter Grehan } 3738860e8c6SPeter Grehan 3748860e8c6SPeter Grehan static int 3752baed46eSJohn Baldwin iobus_activate_resource(device_t bus, device_t child, struct resource *res) 3768860e8c6SPeter Grehan { 3778860e8c6SPeter Grehan 3782baed46eSJohn Baldwin switch (rman_get_type(res)) { 379d7c16b33SJohn Baldwin case SYS_RES_IRQ: 3802baed46eSJohn Baldwin return (bus_generic_activate_resource(bus, child, res)); 381d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 382d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 3832baed46eSJohn Baldwin return (bus_generic_rman_activate_resource(bus, child, res)); 384d7c16b33SJohn Baldwin default: 385d7c16b33SJohn Baldwin return (EINVAL); 3868860e8c6SPeter Grehan } 3878860e8c6SPeter Grehan } 3888860e8c6SPeter Grehan 3898860e8c6SPeter Grehan static int 3902baed46eSJohn Baldwin iobus_deactivate_resource(device_t bus, device_t child, struct resource *res) 3918860e8c6SPeter Grehan { 3928860e8c6SPeter Grehan 3932baed46eSJohn Baldwin switch (rman_get_type(res)) { 394d7c16b33SJohn Baldwin case SYS_RES_IRQ: 3952baed46eSJohn Baldwin return (bus_generic_deactivate_resource(bus, child, res)); 396d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 397d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 3982baed46eSJohn Baldwin return (bus_generic_rman_deactivate_resource(bus, child, res)); 399d7c16b33SJohn Baldwin default: 400d7c16b33SJohn Baldwin return (EINVAL); 401d7c16b33SJohn Baldwin } 4028860e8c6SPeter Grehan } 4038860e8c6SPeter Grehan 404d7c16b33SJohn Baldwin static int 405d77f2092SJohn Baldwin iobus_map_resource(device_t bus, device_t child, struct resource *r, 406d7c16b33SJohn Baldwin struct resource_map_request *argsp, struct resource_map *map) 407d7c16b33SJohn Baldwin { 408d7c16b33SJohn Baldwin struct resource_map_request args; 409d7c16b33SJohn Baldwin struct iobus_softc *sc; 410d7c16b33SJohn Baldwin rman_res_t length, start; 411d7c16b33SJohn Baldwin int error; 412d7c16b33SJohn Baldwin 413d7c16b33SJohn Baldwin /* Resources must be active to be mapped. */ 414d7c16b33SJohn Baldwin if (!(rman_get_flags(r) & RF_ACTIVE)) 415d7c16b33SJohn Baldwin return (ENXIO); 416d7c16b33SJohn Baldwin 417d7c16b33SJohn Baldwin /* Mappings are only supported on I/O and memory resources. */ 418d77f2092SJohn Baldwin switch (rman_get_type(r)) { 419d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 420d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 421d7c16b33SJohn Baldwin break; 422d7c16b33SJohn Baldwin default: 423d7c16b33SJohn Baldwin return (EINVAL); 424d7c16b33SJohn Baldwin } 425d7c16b33SJohn Baldwin 426d7c16b33SJohn Baldwin resource_init_map_request(&args); 427d7c16b33SJohn Baldwin error = resource_validate_map_request(r, argsp, &args, &start, &length); 428d7c16b33SJohn Baldwin if (error) 429d7c16b33SJohn Baldwin return (error); 430d7c16b33SJohn Baldwin 431d7c16b33SJohn Baldwin sc = device_get_softc(bus); 432d7c16b33SJohn Baldwin map->r_vaddr = pmap_mapdev_attr((vm_paddr_t)start + sc->sc_addr, 433d7c16b33SJohn Baldwin (vm_size_t)length, args.memattr); 434d7c16b33SJohn Baldwin if (map->r_vaddr == NULL) 435d7c16b33SJohn Baldwin return (ENOMEM); 436d7c16b33SJohn Baldwin map->r_bustag = &bs_le_tag; 437d7c16b33SJohn Baldwin map->r_bushandle = (vm_offset_t)map->r_vaddr; 438d7c16b33SJohn Baldwin map->r_size = length; 439d7c16b33SJohn Baldwin return (0); 440d7c16b33SJohn Baldwin } 441d7c16b33SJohn Baldwin 442d7c16b33SJohn Baldwin static int 443d77f2092SJohn Baldwin iobus_unmap_resource(device_t bus, device_t child, struct resource *r, 444d7c16b33SJohn Baldwin struct resource_map *map) 445d7c16b33SJohn Baldwin { 446d7c16b33SJohn Baldwin 447d77f2092SJohn Baldwin switch (rman_get_type(r)) { 448d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 449d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 450d7c16b33SJohn Baldwin pmap_unmapdev(map->r_vaddr, map->r_size); 451d7c16b33SJohn Baldwin return (0); 452d7c16b33SJohn Baldwin default: 453d7c16b33SJohn Baldwin return (EINVAL); 454d7c16b33SJohn Baldwin } 4558860e8c6SPeter Grehan } 456