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 228*5b56413dSWarner 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 2438860e8c6SPeter Grehan return (bus_generic_attach(dev)); 2448860e8c6SPeter Grehan } 2458860e8c6SPeter Grehan 2468860e8c6SPeter Grehan static int 2478860e8c6SPeter Grehan iobus_print_child(device_t dev, device_t child) 2488860e8c6SPeter Grehan { 2498860e8c6SPeter Grehan struct iobus_devinfo *dinfo; 2508860e8c6SPeter Grehan struct resource_list *rl; 2518860e8c6SPeter Grehan int retval = 0; 2528860e8c6SPeter Grehan 2538860e8c6SPeter Grehan dinfo = device_get_ivars(child); 2548860e8c6SPeter Grehan rl = &dinfo->id_resources; 2558860e8c6SPeter Grehan 2568860e8c6SPeter Grehan retval += bus_print_child_header(dev, child); 2578860e8c6SPeter Grehan 2588860e8c6SPeter Grehan retval += printf(" offset 0x%x", dinfo->id_reg[1]); 259f8fd3fb5SJustin Hibbits retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd"); 2608860e8c6SPeter Grehan 2618860e8c6SPeter Grehan retval += bus_print_child_footer(dev, child); 2628860e8c6SPeter Grehan 2638860e8c6SPeter Grehan return (retval); 2648860e8c6SPeter Grehan } 2658860e8c6SPeter Grehan 2668860e8c6SPeter Grehan static void 2678860e8c6SPeter Grehan iobus_probe_nomatch(device_t dev, device_t child) 2688860e8c6SPeter Grehan { 2698860e8c6SPeter Grehan } 2708860e8c6SPeter Grehan 2718860e8c6SPeter Grehan static int 2728860e8c6SPeter Grehan iobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 2738860e8c6SPeter Grehan { 2748860e8c6SPeter Grehan struct iobus_devinfo *dinfo; 2758860e8c6SPeter Grehan 27626f0e234SPedro F. Giffuni if ((dinfo = device_get_ivars(child)) == NULL) 2778860e8c6SPeter Grehan return (ENOENT); 2788860e8c6SPeter Grehan 2798860e8c6SPeter Grehan switch (which) { 2808860e8c6SPeter Grehan case IOBUS_IVAR_NODE: 2818860e8c6SPeter Grehan *result = dinfo->id_node; 2828860e8c6SPeter Grehan break; 2838860e8c6SPeter Grehan case IOBUS_IVAR_NAME: 2848860e8c6SPeter Grehan *result = (uintptr_t)dinfo->id_name; 2858860e8c6SPeter Grehan break; 2868860e8c6SPeter Grehan case IOBUS_IVAR_NREGS: 2878860e8c6SPeter Grehan *result = dinfo->id_nregs; 2888860e8c6SPeter Grehan break; 2898860e8c6SPeter Grehan case IOBUS_IVAR_REGS: 2908860e8c6SPeter Grehan *result = (uintptr_t)dinfo->id_reg; 2918860e8c6SPeter Grehan break; 2928860e8c6SPeter Grehan default: 2938860e8c6SPeter Grehan return (ENOENT); 2948860e8c6SPeter Grehan } 2958860e8c6SPeter Grehan 2968860e8c6SPeter Grehan return (0); 2978860e8c6SPeter Grehan } 2988860e8c6SPeter Grehan 2998860e8c6SPeter Grehan static int 3008860e8c6SPeter Grehan iobus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 3018860e8c6SPeter Grehan { 3028860e8c6SPeter Grehan return (EINVAL); 3038860e8c6SPeter Grehan } 3048860e8c6SPeter Grehan 305d7c16b33SJohn Baldwin static struct rman * 306d7c16b33SJohn Baldwin iobus_get_rman(device_t bus, int type, u_int flags) 307d7c16b33SJohn Baldwin { 308d7c16b33SJohn Baldwin struct iobus_softc *sc; 309d7c16b33SJohn Baldwin 310d7c16b33SJohn Baldwin sc = device_get_softc(bus); 311d7c16b33SJohn Baldwin switch (type) { 312d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 313d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 314d7c16b33SJohn Baldwin return (&sc->sc_mem_rman); 315d7c16b33SJohn Baldwin default: 316d7c16b33SJohn Baldwin return (NULL); 317d7c16b33SJohn Baldwin } 318d7c16b33SJohn Baldwin } 319d7c16b33SJohn Baldwin 3208860e8c6SPeter Grehan static struct resource * 3218860e8c6SPeter Grehan iobus_alloc_resource(device_t bus, device_t child, int type, int *rid, 3222dd1bdf1SJustin Hibbits rman_res_t start, rman_res_t end, rman_res_t count, 3232dd1bdf1SJustin Hibbits u_int flags) 3248860e8c6SPeter Grehan { 3258860e8c6SPeter Grehan 3268860e8c6SPeter Grehan switch (type) { 3278860e8c6SPeter Grehan case SYS_RES_MEMORY: 3288860e8c6SPeter Grehan case SYS_RES_IOPORT: 329d7c16b33SJohn Baldwin return (bus_generic_rman_alloc_resource(bus, child, type, rid, 330d7c16b33SJohn Baldwin start, end, count, flags)); 3318860e8c6SPeter Grehan case SYS_RES_IRQ: 3328860e8c6SPeter Grehan return (bus_alloc_resource(bus, type, rid, start, end, count, 3338860e8c6SPeter Grehan flags)); 3348860e8c6SPeter Grehan default: 3358860e8c6SPeter Grehan device_printf(bus, "unknown resource request from %s\n", 3368860e8c6SPeter Grehan device_get_nameunit(child)); 3378860e8c6SPeter Grehan return (NULL); 3388860e8c6SPeter Grehan } 3398860e8c6SPeter Grehan } 3408860e8c6SPeter Grehan 341d7c16b33SJohn Baldwin static int 342fef01f04SJohn Baldwin iobus_adjust_resource(device_t bus, device_t child, struct resource *r, 343fef01f04SJohn Baldwin rman_res_t start, rman_res_t end) 344d7c16b33SJohn Baldwin { 3458860e8c6SPeter Grehan 346fef01f04SJohn Baldwin switch (rman_get_type(r)) { 347d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 348d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 349fef01f04SJohn Baldwin return (bus_generic_rman_adjust_resource(bus, child, r, start, 350ccb1b43eSJohn Baldwin end)); 351fef01f04SJohn Baldwin case SYS_RES_IRQ: 352fef01f04SJohn Baldwin return (bus_generic_adjust_resource(bus, child, r, start, end)); 353d7c16b33SJohn Baldwin default: 354d7c16b33SJohn Baldwin return (EINVAL); 3558860e8c6SPeter Grehan } 3568860e8c6SPeter Grehan } 3578860e8c6SPeter Grehan 3588860e8c6SPeter Grehan static int 3599dbf5b0eSJohn Baldwin iobus_release_resource(device_t bus, device_t child, struct resource *res) 3608860e8c6SPeter Grehan { 3618860e8c6SPeter Grehan 3629dbf5b0eSJohn Baldwin switch (rman_get_type(res)) { 363d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 364d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 3659dbf5b0eSJohn Baldwin return (bus_generic_rman_release_resource(bus, child, res)); 366d7c16b33SJohn Baldwin case SYS_RES_IRQ: 3679dbf5b0eSJohn Baldwin return (bus_generic_release_resource(bus, child, res)); 368d7c16b33SJohn Baldwin default: 369d7c16b33SJohn Baldwin return (EINVAL); 370d7c16b33SJohn Baldwin } 3718860e8c6SPeter Grehan } 3728860e8c6SPeter Grehan 3738860e8c6SPeter Grehan static int 3742baed46eSJohn Baldwin iobus_activate_resource(device_t bus, device_t child, struct resource *res) 3758860e8c6SPeter Grehan { 3768860e8c6SPeter Grehan 3772baed46eSJohn Baldwin switch (rman_get_type(res)) { 378d7c16b33SJohn Baldwin case SYS_RES_IRQ: 3792baed46eSJohn Baldwin return (bus_generic_activate_resource(bus, child, res)); 380d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 381d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 3822baed46eSJohn Baldwin return (bus_generic_rman_activate_resource(bus, child, res)); 383d7c16b33SJohn Baldwin default: 384d7c16b33SJohn Baldwin return (EINVAL); 3858860e8c6SPeter Grehan } 3868860e8c6SPeter Grehan } 3878860e8c6SPeter Grehan 3888860e8c6SPeter Grehan static int 3892baed46eSJohn Baldwin iobus_deactivate_resource(device_t bus, device_t child, struct resource *res) 3908860e8c6SPeter Grehan { 3918860e8c6SPeter Grehan 3922baed46eSJohn Baldwin switch (rman_get_type(res)) { 393d7c16b33SJohn Baldwin case SYS_RES_IRQ: 3942baed46eSJohn Baldwin return (bus_generic_deactivate_resource(bus, child, res)); 395d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 396d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 3972baed46eSJohn Baldwin return (bus_generic_rman_deactivate_resource(bus, child, res)); 398d7c16b33SJohn Baldwin default: 399d7c16b33SJohn Baldwin return (EINVAL); 400d7c16b33SJohn Baldwin } 4018860e8c6SPeter Grehan } 4028860e8c6SPeter Grehan 403d7c16b33SJohn Baldwin static int 404d77f2092SJohn Baldwin iobus_map_resource(device_t bus, device_t child, struct resource *r, 405d7c16b33SJohn Baldwin struct resource_map_request *argsp, struct resource_map *map) 406d7c16b33SJohn Baldwin { 407d7c16b33SJohn Baldwin struct resource_map_request args; 408d7c16b33SJohn Baldwin struct iobus_softc *sc; 409d7c16b33SJohn Baldwin rman_res_t length, start; 410d7c16b33SJohn Baldwin int error; 411d7c16b33SJohn Baldwin 412d7c16b33SJohn Baldwin /* Resources must be active to be mapped. */ 413d7c16b33SJohn Baldwin if (!(rman_get_flags(r) & RF_ACTIVE)) 414d7c16b33SJohn Baldwin return (ENXIO); 415d7c16b33SJohn Baldwin 416d7c16b33SJohn Baldwin /* Mappings are only supported on I/O and memory resources. */ 417d77f2092SJohn Baldwin switch (rman_get_type(r)) { 418d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 419d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 420d7c16b33SJohn Baldwin break; 421d7c16b33SJohn Baldwin default: 422d7c16b33SJohn Baldwin return (EINVAL); 423d7c16b33SJohn Baldwin } 424d7c16b33SJohn Baldwin 425d7c16b33SJohn Baldwin resource_init_map_request(&args); 426d7c16b33SJohn Baldwin error = resource_validate_map_request(r, argsp, &args, &start, &length); 427d7c16b33SJohn Baldwin if (error) 428d7c16b33SJohn Baldwin return (error); 429d7c16b33SJohn Baldwin 430d7c16b33SJohn Baldwin sc = device_get_softc(bus); 431d7c16b33SJohn Baldwin map->r_vaddr = pmap_mapdev_attr((vm_paddr_t)start + sc->sc_addr, 432d7c16b33SJohn Baldwin (vm_size_t)length, args.memattr); 433d7c16b33SJohn Baldwin if (map->r_vaddr == NULL) 434d7c16b33SJohn Baldwin return (ENOMEM); 435d7c16b33SJohn Baldwin map->r_bustag = &bs_le_tag; 436d7c16b33SJohn Baldwin map->r_bushandle = (vm_offset_t)map->r_vaddr; 437d7c16b33SJohn Baldwin map->r_size = length; 438d7c16b33SJohn Baldwin return (0); 439d7c16b33SJohn Baldwin } 440d7c16b33SJohn Baldwin 441d7c16b33SJohn Baldwin static int 442d77f2092SJohn Baldwin iobus_unmap_resource(device_t bus, device_t child, struct resource *r, 443d7c16b33SJohn Baldwin struct resource_map *map) 444d7c16b33SJohn Baldwin { 445d7c16b33SJohn Baldwin 446d77f2092SJohn Baldwin switch (rman_get_type(r)) { 447d7c16b33SJohn Baldwin case SYS_RES_IOPORT: 448d7c16b33SJohn Baldwin case SYS_RES_MEMORY: 449d7c16b33SJohn Baldwin pmap_unmapdev(map->r_vaddr, map->r_size); 450d7c16b33SJohn Baldwin return (0); 451d7c16b33SJohn Baldwin default: 452d7c16b33SJohn Baldwin return (EINVAL); 453d7c16b33SJohn Baldwin } 4548860e8c6SPeter Grehan } 455