160727d8bSWarner Losh /*- 28860e8c6SPeter Grehan * Copyright 2002 by Peter Grehan. All rights reserved. 38860e8c6SPeter Grehan * 48860e8c6SPeter Grehan * Redistribution and use in source and binary forms, with or without 58860e8c6SPeter Grehan * modification, are permitted provided that the following conditions 68860e8c6SPeter Grehan * are met: 78860e8c6SPeter Grehan * 1. Redistributions of source code must retain the above copyright 88860e8c6SPeter Grehan * notice, this list of conditions and the following disclaimer. 98860e8c6SPeter Grehan * 2. Redistributions in binary form must reproduce the above copyright 108860e8c6SPeter Grehan * notice, this list of conditions and the following disclaimer in the 118860e8c6SPeter Grehan * documentation and/or other materials provided with the distribution. 128860e8c6SPeter Grehan * 3. The name of the author may not be used to endorse or promote products 138860e8c6SPeter Grehan * derived from this software without specific prior written permission. 148860e8c6SPeter Grehan * 158860e8c6SPeter Grehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 168860e8c6SPeter Grehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 178860e8c6SPeter Grehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 188860e8c6SPeter Grehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 198860e8c6SPeter Grehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 208860e8c6SPeter Grehan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 218860e8c6SPeter Grehan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 228860e8c6SPeter Grehan * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 238860e8c6SPeter Grehan * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 248860e8c6SPeter Grehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 258860e8c6SPeter Grehan * SUCH DAMAGE. 268860e8c6SPeter Grehan * 278860e8c6SPeter Grehan * $FreeBSD$ 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 478860e8c6SPeter Grehan #include <dev/ofw/openfirm.h> 488860e8c6SPeter Grehan 498860e8c6SPeter Grehan #include <machine/vmparam.h> 508860e8c6SPeter Grehan #include <vm/vm.h> 518860e8c6SPeter Grehan #include <vm/pmap.h> 528860e8c6SPeter Grehan #include <machine/pmap.h> 538860e8c6SPeter Grehan 548860e8c6SPeter Grehan #include <machine/resource.h> 558860e8c6SPeter Grehan #include <machine/nexusvar.h> 568860e8c6SPeter Grehan 578860e8c6SPeter Grehan #include <powerpc/psim/iobusvar.h> 588860e8c6SPeter Grehan 5957dc54dbSPeter Grehan struct iobus_softc { 6057dc54dbSPeter Grehan phandle_t sc_node; 6157dc54dbSPeter Grehan vm_offset_t sc_addr; 6257dc54dbSPeter Grehan vm_offset_t sc_size; 6357dc54dbSPeter Grehan struct rman sc_mem_rman; 6457dc54dbSPeter Grehan }; 6557dc54dbSPeter Grehan 668860e8c6SPeter Grehan static MALLOC_DEFINE(M_IOBUS, "iobus", "iobus device information"); 678860e8c6SPeter Grehan 688860e8c6SPeter Grehan static int iobus_probe(device_t); 698860e8c6SPeter Grehan static int iobus_attach(device_t); 708860e8c6SPeter Grehan static int iobus_print_child(device_t dev, device_t child); 718860e8c6SPeter Grehan static void iobus_probe_nomatch(device_t, device_t); 728860e8c6SPeter Grehan static int iobus_read_ivar(device_t, device_t, int, uintptr_t *); 738860e8c6SPeter Grehan static int iobus_write_ivar(device_t, device_t, int, uintptr_t); 748860e8c6SPeter Grehan static struct resource *iobus_alloc_resource(device_t, device_t, int, int *, 758860e8c6SPeter Grehan u_long, u_long, u_long, u_int); 768860e8c6SPeter Grehan static int iobus_activate_resource(device_t, device_t, int, int, 778860e8c6SPeter Grehan struct resource *); 788860e8c6SPeter Grehan static int iobus_deactivate_resource(device_t, device_t, int, int, 798860e8c6SPeter Grehan struct resource *); 808860e8c6SPeter Grehan static int iobus_release_resource(device_t, device_t, int, int, 818860e8c6SPeter Grehan struct resource *); 828860e8c6SPeter Grehan 838860e8c6SPeter Grehan /* 848860e8c6SPeter Grehan * Bus interface definition 858860e8c6SPeter Grehan */ 868860e8c6SPeter Grehan static device_method_t iobus_methods[] = { 878860e8c6SPeter Grehan /* Device interface */ 888860e8c6SPeter Grehan DEVMETHOD(device_probe, iobus_probe), 898860e8c6SPeter Grehan DEVMETHOD(device_attach, iobus_attach), 908860e8c6SPeter Grehan DEVMETHOD(device_detach, bus_generic_detach), 918860e8c6SPeter Grehan DEVMETHOD(device_shutdown, bus_generic_shutdown), 928860e8c6SPeter Grehan DEVMETHOD(device_suspend, bus_generic_suspend), 938860e8c6SPeter Grehan DEVMETHOD(device_resume, bus_generic_resume), 948860e8c6SPeter Grehan 958860e8c6SPeter Grehan /* Bus interface */ 968860e8c6SPeter Grehan DEVMETHOD(bus_print_child, iobus_print_child), 978860e8c6SPeter Grehan DEVMETHOD(bus_probe_nomatch, iobus_probe_nomatch), 988860e8c6SPeter Grehan DEVMETHOD(bus_read_ivar, iobus_read_ivar), 998860e8c6SPeter Grehan DEVMETHOD(bus_write_ivar, iobus_write_ivar), 1008860e8c6SPeter Grehan DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 1018860e8c6SPeter Grehan DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 1028860e8c6SPeter Grehan 1038860e8c6SPeter Grehan DEVMETHOD(bus_alloc_resource, iobus_alloc_resource), 1048860e8c6SPeter Grehan DEVMETHOD(bus_release_resource, iobus_release_resource), 1058860e8c6SPeter Grehan DEVMETHOD(bus_activate_resource, iobus_activate_resource), 1068860e8c6SPeter Grehan DEVMETHOD(bus_deactivate_resource, iobus_deactivate_resource), 1078860e8c6SPeter Grehan 1088860e8c6SPeter Grehan { 0, 0 } 1098860e8c6SPeter Grehan }; 1108860e8c6SPeter Grehan 1118860e8c6SPeter Grehan static driver_t iobus_driver = { 1128860e8c6SPeter Grehan "iobus", 1138860e8c6SPeter Grehan iobus_methods, 1148860e8c6SPeter Grehan sizeof(struct iobus_softc) 1158860e8c6SPeter Grehan }; 1168860e8c6SPeter Grehan 1178860e8c6SPeter Grehan devclass_t iobus_devclass; 1188860e8c6SPeter Grehan 1198860e8c6SPeter Grehan DRIVER_MODULE(iobus, nexus, iobus_driver, iobus_devclass, 0, 0); 1208860e8c6SPeter Grehan 1218860e8c6SPeter Grehan static int 1228860e8c6SPeter Grehan iobus_probe(device_t dev) 1238860e8c6SPeter Grehan { 1248860e8c6SPeter Grehan char *type = nexus_get_name(dev); 1258860e8c6SPeter Grehan 1268860e8c6SPeter Grehan if (strcmp(type, "psim-iobus") != 0) 1278860e8c6SPeter Grehan return (ENXIO); 1288860e8c6SPeter Grehan 1298860e8c6SPeter Grehan device_set_desc(dev, "PSIM local bus"); 1308860e8c6SPeter Grehan return (0); 1318860e8c6SPeter Grehan } 1328860e8c6SPeter Grehan 1338860e8c6SPeter Grehan /* 1348860e8c6SPeter Grehan * Add interrupt/addr range to the dev's resource list if present 1358860e8c6SPeter Grehan */ 1368860e8c6SPeter Grehan static void 1378860e8c6SPeter Grehan iobus_add_intr(phandle_t devnode, struct iobus_devinfo *dinfo) 1388860e8c6SPeter Grehan { 1398860e8c6SPeter Grehan u_int intr = -1; 1408860e8c6SPeter Grehan 1418860e8c6SPeter Grehan if (OF_getprop(devnode, "interrupt", &intr, sizeof(intr)) != -1) { 1428860e8c6SPeter Grehan resource_list_add(&dinfo->id_resources, 1438860e8c6SPeter Grehan SYS_RES_IRQ, 0, intr, intr, 1); 1448860e8c6SPeter Grehan } 1458860e8c6SPeter Grehan dinfo->id_interrupt = intr; 1468860e8c6SPeter Grehan } 1478860e8c6SPeter Grehan 1488860e8c6SPeter Grehan 1498860e8c6SPeter Grehan static void 1508860e8c6SPeter Grehan iobus_add_reg(phandle_t devnode, struct iobus_devinfo *dinfo, 1518860e8c6SPeter Grehan vm_offset_t iobus_off) 1528860e8c6SPeter Grehan { 1538860e8c6SPeter Grehan u_int size; 1548860e8c6SPeter Grehan int i; 1558860e8c6SPeter Grehan 1568860e8c6SPeter Grehan size = OF_getprop(devnode, "reg", dinfo->id_reg,sizeof(dinfo->id_reg)); 1578860e8c6SPeter Grehan 1588860e8c6SPeter Grehan if (size != -1) { 1598860e8c6SPeter Grehan dinfo->id_nregs = size / (sizeof(dinfo->id_reg[0])); 1608860e8c6SPeter Grehan 1618860e8c6SPeter Grehan for (i = 0; i < dinfo->id_nregs; i+= 3) { 1628860e8c6SPeter Grehan /* 1638860e8c6SPeter Grehan * Scale the absolute addresses back to iobus 1648860e8c6SPeter Grehan * relative offsets. This is to better simulate 1658860e8c6SPeter Grehan * macio 1668860e8c6SPeter Grehan */ 1678860e8c6SPeter Grehan dinfo->id_reg[i+1] -= iobus_off; 1688860e8c6SPeter Grehan 1698860e8c6SPeter Grehan resource_list_add(&dinfo->id_resources, 1708860e8c6SPeter Grehan SYS_RES_MEMORY, 0, 1718860e8c6SPeter Grehan dinfo->id_reg[i+1], 1728860e8c6SPeter Grehan dinfo->id_reg[i+1] + 1738860e8c6SPeter Grehan dinfo->id_reg[i+2], 1748860e8c6SPeter Grehan dinfo->id_reg[i+2]); 1758860e8c6SPeter Grehan } 1768860e8c6SPeter Grehan } 1778860e8c6SPeter Grehan } 1788860e8c6SPeter Grehan 1798860e8c6SPeter Grehan 1808860e8c6SPeter Grehan static int 1818860e8c6SPeter Grehan iobus_attach(device_t dev) 1828860e8c6SPeter Grehan { 1838860e8c6SPeter Grehan struct iobus_softc *sc; 1848860e8c6SPeter Grehan struct iobus_devinfo *dinfo; 1858860e8c6SPeter Grehan phandle_t root; 1868860e8c6SPeter Grehan phandle_t child; 1878860e8c6SPeter Grehan device_t cdev; 1888860e8c6SPeter Grehan char *name; 1898860e8c6SPeter Grehan u_int reg[2]; 1908860e8c6SPeter Grehan int size; 1918860e8c6SPeter Grehan 1928860e8c6SPeter Grehan sc = device_get_softc(dev); 1938860e8c6SPeter Grehan sc->sc_node = nexus_get_node(dev); 1948860e8c6SPeter Grehan 1958860e8c6SPeter Grehan /* 1968860e8c6SPeter Grehan * Find the base addr/size of the iobus, and initialize the 1978860e8c6SPeter Grehan * resource manager 1988860e8c6SPeter Grehan */ 1998860e8c6SPeter Grehan size = OF_getprop(sc->sc_node, "reg", reg, sizeof(reg)); 2008860e8c6SPeter Grehan if (size == sizeof(reg)) { 2018860e8c6SPeter Grehan sc->sc_addr = reg[0]; 2028860e8c6SPeter Grehan sc->sc_size = reg[1]; 2038860e8c6SPeter Grehan } else { 2048860e8c6SPeter Grehan return (ENXIO); 2058860e8c6SPeter Grehan } 2068860e8c6SPeter Grehan 2078860e8c6SPeter Grehan sc->sc_mem_rman.rm_type = RMAN_ARRAY; 2088860e8c6SPeter Grehan sc->sc_mem_rman.rm_descr = "IOBus Device Memory"; 2098860e8c6SPeter Grehan if (rman_init(&sc->sc_mem_rman) != 0) { 2108860e8c6SPeter Grehan device_printf(dev, 2118860e8c6SPeter Grehan "failed to init mem range resources\n"); 2128860e8c6SPeter Grehan return (ENXIO); 2138860e8c6SPeter Grehan } 2148860e8c6SPeter Grehan rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size); 2158860e8c6SPeter Grehan 2168860e8c6SPeter Grehan /* 2178860e8c6SPeter Grehan * Iterate through the sub-devices 2188860e8c6SPeter Grehan */ 2198860e8c6SPeter Grehan root = sc->sc_node; 2208860e8c6SPeter Grehan 2218860e8c6SPeter Grehan for (child = OF_child(root); child != 0; child = OF_peer(child)) { 2228860e8c6SPeter Grehan OF_getprop_alloc(child, "name", 1, (void **)&name); 2238860e8c6SPeter Grehan 2248860e8c6SPeter Grehan cdev = device_add_child(dev, NULL, -1); 2258860e8c6SPeter Grehan if (cdev != NULL) { 226a163d034SWarner Losh dinfo = malloc(sizeof(*dinfo), M_IOBUS, M_WAITOK); 2278860e8c6SPeter Grehan memset(dinfo, 0, sizeof(*dinfo)); 2288860e8c6SPeter Grehan resource_list_init(&dinfo->id_resources); 2298860e8c6SPeter Grehan dinfo->id_node = child; 2308860e8c6SPeter Grehan dinfo->id_name = name; 2318860e8c6SPeter Grehan iobus_add_intr(child, dinfo); 2328860e8c6SPeter Grehan iobus_add_reg(child, dinfo, sc->sc_addr); 2338860e8c6SPeter Grehan device_set_ivars(cdev, dinfo); 2348860e8c6SPeter Grehan } else { 2358860e8c6SPeter Grehan free(name, M_OFWPROP); 2368860e8c6SPeter Grehan } 2378860e8c6SPeter Grehan } 2388860e8c6SPeter Grehan 2398860e8c6SPeter Grehan return (bus_generic_attach(dev)); 2408860e8c6SPeter Grehan } 2418860e8c6SPeter Grehan 2428860e8c6SPeter Grehan 2438860e8c6SPeter Grehan static int 2448860e8c6SPeter Grehan iobus_print_child(device_t dev, device_t child) 2458860e8c6SPeter Grehan { 2468860e8c6SPeter Grehan struct iobus_devinfo *dinfo; 2478860e8c6SPeter Grehan struct resource_list *rl; 2488860e8c6SPeter Grehan int retval = 0; 2498860e8c6SPeter Grehan 2508860e8c6SPeter Grehan dinfo = device_get_ivars(child); 2518860e8c6SPeter Grehan rl = &dinfo->id_resources; 2528860e8c6SPeter Grehan 2538860e8c6SPeter Grehan retval += bus_print_child_header(dev, child); 2548860e8c6SPeter Grehan 2558860e8c6SPeter Grehan retval += printf(" offset 0x%x", dinfo->id_reg[1]); 2568860e8c6SPeter Grehan retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); 2578860e8c6SPeter Grehan 2588860e8c6SPeter Grehan retval += bus_print_child_footer(dev, child); 2598860e8c6SPeter Grehan 2608860e8c6SPeter Grehan return (retval); 2618860e8c6SPeter Grehan } 2628860e8c6SPeter Grehan 2638860e8c6SPeter Grehan 2648860e8c6SPeter Grehan static void 2658860e8c6SPeter Grehan iobus_probe_nomatch(device_t dev, device_t child) 2668860e8c6SPeter Grehan { 2678860e8c6SPeter Grehan } 2688860e8c6SPeter Grehan 2698860e8c6SPeter Grehan 2708860e8c6SPeter Grehan static int 2718860e8c6SPeter Grehan iobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 2728860e8c6SPeter Grehan { 2738860e8c6SPeter Grehan struct iobus_devinfo *dinfo; 2748860e8c6SPeter Grehan 2758860e8c6SPeter Grehan if ((dinfo = device_get_ivars(child)) == 0) 2768860e8c6SPeter Grehan return (ENOENT); 2778860e8c6SPeter Grehan 2788860e8c6SPeter Grehan switch (which) { 2798860e8c6SPeter Grehan case IOBUS_IVAR_NODE: 2808860e8c6SPeter Grehan *result = dinfo->id_node; 2818860e8c6SPeter Grehan break; 2828860e8c6SPeter Grehan case IOBUS_IVAR_NAME: 2838860e8c6SPeter Grehan *result = (uintptr_t)dinfo->id_name; 2848860e8c6SPeter Grehan break; 2858860e8c6SPeter Grehan case IOBUS_IVAR_NREGS: 2868860e8c6SPeter Grehan *result = dinfo->id_nregs; 2878860e8c6SPeter Grehan break; 2888860e8c6SPeter Grehan case IOBUS_IVAR_REGS: 2898860e8c6SPeter Grehan *result = (uintptr_t)dinfo->id_reg; 2908860e8c6SPeter Grehan break; 2918860e8c6SPeter Grehan default: 2928860e8c6SPeter Grehan return (ENOENT); 2938860e8c6SPeter Grehan } 2948860e8c6SPeter Grehan 2958860e8c6SPeter Grehan return (0); 2968860e8c6SPeter Grehan } 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 3058860e8c6SPeter Grehan 3068860e8c6SPeter Grehan static struct resource * 3078860e8c6SPeter Grehan iobus_alloc_resource(device_t bus, device_t child, int type, int *rid, 3088860e8c6SPeter Grehan u_long start, u_long end, u_long count, u_int flags) 3098860e8c6SPeter Grehan { 3108860e8c6SPeter Grehan struct iobus_softc *sc; 3118860e8c6SPeter Grehan int needactivate; 3128860e8c6SPeter Grehan struct resource *rv; 3138860e8c6SPeter Grehan struct rman *rm; 3148860e8c6SPeter Grehan bus_space_tag_t tagval; 3158860e8c6SPeter Grehan 3168860e8c6SPeter Grehan sc = device_get_softc(bus); 3178860e8c6SPeter Grehan 3188860e8c6SPeter Grehan needactivate = flags & RF_ACTIVE; 3198860e8c6SPeter Grehan flags &= ~RF_ACTIVE; 3208860e8c6SPeter Grehan 3218860e8c6SPeter Grehan switch (type) { 3228860e8c6SPeter Grehan case SYS_RES_MEMORY: 3238860e8c6SPeter Grehan case SYS_RES_IOPORT: 3248860e8c6SPeter Grehan rm = &sc->sc_mem_rman; 3258860e8c6SPeter Grehan tagval = PPC_BUS_SPACE_MEM; 3268860e8c6SPeter Grehan break; 3278860e8c6SPeter Grehan case SYS_RES_IRQ: 3288860e8c6SPeter Grehan return (bus_alloc_resource(bus, type, rid, start, end, count, 3298860e8c6SPeter Grehan flags)); 3308860e8c6SPeter Grehan break; 3318860e8c6SPeter Grehan default: 3328860e8c6SPeter Grehan device_printf(bus, "unknown resource request from %s\n", 3338860e8c6SPeter Grehan device_get_nameunit(child)); 3348860e8c6SPeter Grehan return (NULL); 3358860e8c6SPeter Grehan } 3368860e8c6SPeter Grehan 3378860e8c6SPeter Grehan rv = rman_reserve_resource(rm, start, end, count, flags, child); 3388860e8c6SPeter Grehan if (rv == NULL) { 3398860e8c6SPeter Grehan device_printf(bus, "failed to reserve resource for %s\n", 3408860e8c6SPeter Grehan device_get_nameunit(child)); 3418860e8c6SPeter Grehan return (NULL); 3428860e8c6SPeter Grehan } 3438860e8c6SPeter Grehan 3448860e8c6SPeter Grehan rman_set_bustag(rv, tagval); 3458860e8c6SPeter Grehan rman_set_bushandle(rv, rman_get_start(rv)); 3468860e8c6SPeter Grehan 3478860e8c6SPeter Grehan if (needactivate) { 3488860e8c6SPeter Grehan if (bus_activate_resource(child, type, *rid, rv) != 0) { 3498860e8c6SPeter Grehan device_printf(bus, 3508860e8c6SPeter Grehan "failed to activate resource for %s\n", 3518860e8c6SPeter Grehan device_get_nameunit(child)); 3528860e8c6SPeter Grehan rman_release_resource(rv); 3538860e8c6SPeter Grehan return (NULL); 3548860e8c6SPeter Grehan } 3558860e8c6SPeter Grehan } 3568860e8c6SPeter Grehan 3578860e8c6SPeter Grehan return (rv); 3588860e8c6SPeter Grehan } 3598860e8c6SPeter Grehan 3608860e8c6SPeter Grehan 3618860e8c6SPeter Grehan static int 3628860e8c6SPeter Grehan iobus_release_resource(device_t bus, device_t child, int type, int rid, 3638860e8c6SPeter Grehan struct resource *res) 3648860e8c6SPeter Grehan { 3658860e8c6SPeter Grehan if (rman_get_flags(res) & RF_ACTIVE) { 3668860e8c6SPeter Grehan int error = bus_deactivate_resource(child, type, rid, res); 3678860e8c6SPeter Grehan if (error) 3688860e8c6SPeter Grehan return error; 3698860e8c6SPeter Grehan } 3708860e8c6SPeter Grehan 3718860e8c6SPeter Grehan return (rman_release_resource(res)); 3728860e8c6SPeter Grehan } 3738860e8c6SPeter Grehan 3748860e8c6SPeter Grehan 3758860e8c6SPeter Grehan static int 3768860e8c6SPeter Grehan iobus_activate_resource(device_t bus, device_t child, int type, int rid, 3778860e8c6SPeter Grehan struct resource *res) 3788860e8c6SPeter Grehan { 3798860e8c6SPeter Grehan struct iobus_softc *sc; 3808860e8c6SPeter Grehan void *p; 3818860e8c6SPeter Grehan 3828860e8c6SPeter Grehan sc = device_get_softc(bus); 3838860e8c6SPeter Grehan 3848860e8c6SPeter Grehan if (type == SYS_RES_IRQ) 3858860e8c6SPeter Grehan return (bus_activate_resource(bus, type, rid, res)); 3868860e8c6SPeter Grehan 3878860e8c6SPeter Grehan if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { 3888860e8c6SPeter Grehan p = pmap_mapdev((vm_offset_t)rman_get_start(res) + sc->sc_addr, 3898860e8c6SPeter Grehan (vm_size_t)rman_get_size(res)); 3908860e8c6SPeter Grehan if (p == NULL) 3918860e8c6SPeter Grehan return (ENOMEM); 3928860e8c6SPeter Grehan rman_set_virtual(res, p); 3938860e8c6SPeter Grehan rman_set_bushandle(res, (u_long)p); 3948860e8c6SPeter Grehan } 3958860e8c6SPeter Grehan 3968860e8c6SPeter Grehan return (rman_activate_resource(res)); 3978860e8c6SPeter Grehan } 3988860e8c6SPeter Grehan 3998860e8c6SPeter Grehan 4008860e8c6SPeter Grehan static int 4018860e8c6SPeter Grehan iobus_deactivate_resource(device_t bus, device_t child, int type, int rid, 4028860e8c6SPeter Grehan struct resource *res) 4038860e8c6SPeter Grehan { 4048860e8c6SPeter Grehan /* 4058860e8c6SPeter Grehan * If this is a memory resource, unmap it. 4068860e8c6SPeter Grehan */ 4078860e8c6SPeter Grehan if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { 4088860e8c6SPeter Grehan u_int32_t psize; 4098860e8c6SPeter Grehan 4108860e8c6SPeter Grehan psize = rman_get_size(res); 4118860e8c6SPeter Grehan pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); 4128860e8c6SPeter Grehan } 4138860e8c6SPeter Grehan 4148860e8c6SPeter Grehan return (rman_deactivate_resource(res)); 4158860e8c6SPeter Grehan } 416