Index: head/sys/mips/mips/bus_space_generic.c =================================================================== --- head/sys/mips/mips/bus_space_generic.c (revision 295503) +++ head/sys/mips/mips/bus_space_generic.c (revision 295504) @@ -1,749 +1,750 @@ /* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */ /*- * $Id: bus.h,v 1.6 2007/08/09 11:23:32 katta Exp $ * * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, * NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1996 Charles M. Hannum. All rights reserved. * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou * for the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: src/sys/alpha/include/bus.h,v 1.5 1999/08/28 00:38:40 peter * $FreeBSD$ */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include static struct bus_space generic_space = { /* cookie */ .bs_cookie = (void *) 0, /* mapping/unmapping */ .bs_map = generic_bs_map, .bs_unmap = generic_bs_unmap, .bs_subregion = generic_bs_subregion, /* allocation/deallocation */ .bs_alloc = generic_bs_alloc, .bs_free = generic_bs_free, /* barrier */ .bs_barrier = generic_bs_barrier, /* read (single) */ .bs_r_1 = generic_bs_r_1, .bs_r_2 = generic_bs_r_2, .bs_r_4 = generic_bs_r_4, .bs_r_8 = generic_bs_r_8, /* read multiple */ .bs_rm_1 = generic_bs_rm_1, .bs_rm_2 = generic_bs_rm_2, .bs_rm_4 = generic_bs_rm_4, .bs_rm_8 = generic_bs_rm_8, /* read region */ .bs_rr_1 = generic_bs_rr_1, .bs_rr_2 = generic_bs_rr_2, .bs_rr_4 = generic_bs_rr_4, .bs_rr_8 = generic_bs_rr_8, /* write (single) */ .bs_w_1 = generic_bs_w_1, .bs_w_2 = generic_bs_w_2, .bs_w_4 = generic_bs_w_4, .bs_w_8 = generic_bs_w_8, /* write multiple */ .bs_wm_1 = generic_bs_wm_1, .bs_wm_2 = generic_bs_wm_2, .bs_wm_4 = generic_bs_wm_4, .bs_wm_8 = generic_bs_wm_8, /* write region */ .bs_wr_1 = generic_bs_wr_1, .bs_wr_2 = generic_bs_wr_2, .bs_wr_4 = generic_bs_wr_4, .bs_wr_8 = generic_bs_wr_8, /* set multiple */ .bs_sm_1 = generic_bs_sm_1, .bs_sm_2 = generic_bs_sm_2, .bs_sm_4 = generic_bs_sm_4, .bs_sm_8 = generic_bs_sm_8, /* set region */ .bs_sr_1 = generic_bs_sr_1, .bs_sr_2 = generic_bs_sr_2, .bs_sr_4 = generic_bs_sr_4, .bs_sr_8 = generic_bs_sr_8, /* copy */ .bs_c_1 = generic_bs_c_1, .bs_c_2 = generic_bs_c_2, .bs_c_4 = generic_bs_c_4, .bs_c_8 = generic_bs_c_8, /* read (single) stream */ .bs_r_1_s = generic_bs_r_1, .bs_r_2_s = generic_bs_r_2, .bs_r_4_s = generic_bs_r_4, .bs_r_8_s = generic_bs_r_8, /* read multiple stream */ .bs_rm_1_s = generic_bs_rm_1, .bs_rm_2_s = generic_bs_rm_2, .bs_rm_4_s = generic_bs_rm_4, .bs_rm_8_s = generic_bs_rm_8, /* read region stream */ .bs_rr_1_s = generic_bs_rr_1, .bs_rr_2_s = generic_bs_rr_2, .bs_rr_4_s = generic_bs_rr_4, .bs_rr_8_s = generic_bs_rr_8, /* write (single) stream */ .bs_w_1_s = generic_bs_w_1, .bs_w_2_s = generic_bs_w_2, .bs_w_4_s = generic_bs_w_4, .bs_w_8_s = generic_bs_w_8, /* write multiple stream */ .bs_wm_1_s = generic_bs_wm_1, .bs_wm_2_s = generic_bs_wm_2, .bs_wm_4_s = generic_bs_wm_4, .bs_wm_8_s = generic_bs_wm_8, /* write region stream */ .bs_wr_1_s = generic_bs_wr_1, .bs_wr_2_s = generic_bs_wr_2, .bs_wr_4_s = generic_bs_wr_4, .bs_wr_8_s = generic_bs_wr_8, }; /* Ultra-gross kludge */ #if defined(CPU_CNMIPS) && (defined(__mips_n32) || defined(__mips_o32)) #include #define rd8(a) cvmx_read64_uint8(a) #define rd16(a) cvmx_read64_uint16(a) #define rd32(a) cvmx_read64_uint32(a) #define rd64(a) cvmx_read64_uint64(a) #define wr8(a, v) cvmx_write64_uint8(a, v) #define wr16(a, v) cvmx_write64_uint16(a, v) #define wr32(a, v) cvmx_write64_uint32(a, v) #define wr64(a, v) cvmx_write64_uint64(a, v) #elif defined(CPU_SB1) && _BYTE_ORDER == _BIG_ENDIAN #include #define rd8(a) sb_big_endian_read8(a) #define rd16(a) sb_big_endian_read16(a) #define rd32(a) sb_big_endian_read32(a) #define wr8(a, v) sb_big_endian_write8(a, v) #define wr16(a, v) sb_big_endian_write16(a, v) #define wr32(a, v) sb_big_endian_write32(a, v) #else #define rd8(a) readb(a) #define rd16(a) readw(a) #define rd32(a) readl(a) #ifdef readq #define rd64(a) readq((a)) #endif #define wr8(a, v) writeb(a, v) #define wr16(a, v) writew(a, v) #define wr32(a, v) writel(a, v) #ifdef writeq #define wr64(a, v) writeq(a, v) #endif #endif /* generic bus_space tag */ bus_space_tag_t mips_bus_space_generic = &generic_space; int generic_bs_map(void *t __unused, bus_addr_t addr, - bus_size_t size __unused, int flags __unused, + bus_size_t size, int flags __unused, bus_space_handle_t *bshp) { - *bshp = addr; + *bshp = (bus_space_handle_t)pmap_mapdev((vm_paddr_t)addr, + (vm_size_t)size); return (0); } void -generic_bs_unmap(void *t __unused, bus_space_handle_t bh __unused, - bus_size_t size __unused) +generic_bs_unmap(void *t __unused, bus_space_handle_t bh, + bus_size_t size) { - /* Do nothing */ + pmap_unmapdev((vm_offset_t)bh, (vm_size_t)size); } int generic_bs_subregion(void *t __unused, bus_space_handle_t handle, bus_size_t offset, bus_size_t size __unused, bus_space_handle_t *bshp) { *bshp = handle + offset; return (0); } int generic_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, bus_addr_t *bpap, bus_space_handle_t *bshp) { panic("%s: not implemented", __func__); } void generic_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) { panic("%s: not implemented", __func__); } uint8_t generic_bs_r_1(void *t, bus_space_handle_t handle, bus_size_t offset) { return (rd8(handle + offset)); } uint16_t generic_bs_r_2(void *t, bus_space_handle_t handle, bus_size_t offset) { return (rd16(handle + offset)); } uint32_t generic_bs_r_4(void *t, bus_space_handle_t handle, bus_size_t offset) { return (rd32(handle + offset)); } uint64_t generic_bs_r_8(void *t, bus_space_handle_t handle, bus_size_t offset) { #ifdef rd64 return(rd64(handle + offset)); #else panic("%s: not implemented", __func__); #endif } void generic_bs_rm_1(void *t, bus_space_handle_t bsh, bus_size_t offset, uint8_t *addr, size_t count) { while (count--) *addr++ = rd8(bsh + offset); } void generic_bs_rm_2(void *t, bus_space_handle_t bsh, bus_size_t offset, uint16_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) *addr++ = rd16(baddr); } void generic_bs_rm_4(void *t, bus_space_handle_t bsh, bus_size_t offset, uint32_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) *addr++ = rd32(baddr); } void generic_bs_rm_8(void *t, bus_space_handle_t bsh, bus_size_t offset, uint64_t *addr, size_t count) { #ifdef rd64 bus_addr_t baddr = bsh + offset; while (count--) *addr++ = rd64(baddr); #else panic("%s: not implemented", __func__); #endif } /* * Read `count' 1, 2, 4, or 8 byte quantities from bus space * described by tag/handle and starting at `offset' and copy into * buffer provided. */ void generic_bs_rr_1(void *t, bus_space_handle_t bsh, bus_size_t offset, uint8_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) { *addr++ = rd8(baddr); baddr += 1; } } void generic_bs_rr_2(void *t, bus_space_handle_t bsh, bus_size_t offset, uint16_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) { *addr++ = rd16(baddr); baddr += 2; } } void generic_bs_rr_4(void *t, bus_space_handle_t bsh, bus_size_t offset, uint32_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) { *addr++ = rd32(baddr); baddr += 4; } } void generic_bs_rr_8(void *t, bus_space_handle_t bsh, bus_size_t offset, uint64_t *addr, size_t count) { #ifdef rd64 bus_addr_t baddr = bsh + offset; while (count--) { *addr++ = rd64(baddr); baddr += 8; } #else panic("%s: not implemented", __func__); #endif } /* * Write the 1, 2, 4, or 8 byte value `value' to bus space * described by tag/handle/offset. */ void generic_bs_w_1(void *t, bus_space_handle_t bsh, bus_size_t offset, uint8_t value) { wr8(bsh + offset, value); } void generic_bs_w_2(void *t, bus_space_handle_t bsh, bus_size_t offset, uint16_t value) { wr16(bsh + offset, value); } void generic_bs_w_4(void *t, bus_space_handle_t bsh, bus_size_t offset, uint32_t value) { wr32(bsh + offset, value); } void generic_bs_w_8(void *t, bus_space_handle_t bsh, bus_size_t offset, uint64_t value) { #ifdef wr64 wr64(bsh + offset, value); #else panic("%s: not implemented", __func__); #endif } /* * Write `count' 1, 2, 4, or 8 byte quantities from the buffer * provided to bus space described by tag/handle/offset. */ void generic_bs_wm_1(void *t, bus_space_handle_t bsh, bus_size_t offset, const uint8_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) wr8(baddr, *addr++); } void generic_bs_wm_2(void *t, bus_space_handle_t bsh, bus_size_t offset, const uint16_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) wr16(baddr, *addr++); } void generic_bs_wm_4(void *t, bus_space_handle_t bsh, bus_size_t offset, const uint32_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) wr32(baddr, *addr++); } void generic_bs_wm_8(void *t, bus_space_handle_t bsh, bus_size_t offset, const uint64_t *addr, size_t count) { #ifdef wr64 bus_addr_t baddr = bsh + offset; while (count--) wr64(baddr, *addr++); #else panic("%s: not implemented", __func__); #endif } /* * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided * to bus space described by tag/handle starting at `offset'. */ void generic_bs_wr_1(void *t, bus_space_handle_t bsh, bus_size_t offset, const uint8_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) { wr8(baddr, *addr++); baddr += 1; } } void generic_bs_wr_2(void *t, bus_space_handle_t bsh, bus_size_t offset, const uint16_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) { wr16(baddr, *addr++); baddr += 2; } } void generic_bs_wr_4(void *t, bus_space_handle_t bsh, bus_size_t offset, const uint32_t *addr, size_t count) { bus_addr_t baddr = bsh + offset; while (count--) { wr32(baddr, *addr++); baddr += 4; } } void generic_bs_wr_8(void *t, bus_space_handle_t bsh, bus_size_t offset, const uint64_t *addr, size_t count) { #ifdef wr64 bus_addr_t baddr = bsh + offset; while (count--) { wr64(baddr, *addr++); baddr += 8; } #else panic("%s: not implemented", __func__); #endif } /* * Write the 1, 2, 4, or 8 byte value `val' to bus space described * by tag/handle/offset `count' times. */ void generic_bs_sm_1(void *t, bus_space_handle_t bsh, bus_size_t offset, uint8_t value, size_t count) { bus_addr_t addr = bsh + offset; while (count--) wr8(addr, value); } void generic_bs_sm_2(void *t, bus_space_handle_t bsh, bus_size_t offset, uint16_t value, size_t count) { bus_addr_t addr = bsh + offset; while (count--) wr16(addr, value); } void generic_bs_sm_4(void *t, bus_space_handle_t bsh, bus_size_t offset, uint32_t value, size_t count) { bus_addr_t addr = bsh + offset; while (count--) wr32(addr, value); } void generic_bs_sm_8(void *t, bus_space_handle_t bsh, bus_size_t offset, uint64_t value, size_t count) { #ifdef wr64 bus_addr_t addr = bsh + offset; while (count--) wr64(addr, value); #else panic("%s: not implemented", __func__); #endif } /* * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described * by tag/handle starting at `offset'. */ void generic_bs_sr_1(void *t, bus_space_handle_t bsh, bus_size_t offset, uint8_t value, size_t count) { bus_addr_t addr = bsh + offset; for (; count != 0; count--, addr++) wr8(addr, value); } void generic_bs_sr_2(void *t, bus_space_handle_t bsh, bus_size_t offset, uint16_t value, size_t count) { bus_addr_t addr = bsh + offset; for (; count != 0; count--, addr += 2) wr16(addr, value); } void generic_bs_sr_4(void *t, bus_space_handle_t bsh, bus_size_t offset, uint32_t value, size_t count) { bus_addr_t addr = bsh + offset; for (; count != 0; count--, addr += 4) wr32(addr, value); } void generic_bs_sr_8(void *t, bus_space_handle_t bsh, bus_size_t offset, uint64_t value, size_t count) { #ifdef wr64 bus_addr_t addr = bsh + offset; for (; count != 0; count--, addr += 8) wr64(addr, value); #else panic("%s: not implemented", __func__); #endif } /* * Copy `count' 1, 2, 4, or 8 byte values from bus space starting * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. */ void generic_bs_c_1(void *t, bus_space_handle_t bsh1, bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, size_t count) { bus_addr_t addr1 = bsh1 + off1; bus_addr_t addr2 = bsh2 + off2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; count != 0; count--, addr1++, addr2++) wr8(addr2, rd8(addr1)); } else { /* dest after src: copy backwards */ for (addr1 += (count - 1), addr2 += (count - 1); count != 0; count--, addr1--, addr2--) wr8(addr2, rd8(addr1)); } } void generic_bs_c_2(void *t, bus_space_handle_t bsh1, bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, size_t count) { bus_addr_t addr1 = bsh1 + off1; bus_addr_t addr2 = bsh2 + off2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; count != 0; count--, addr1 += 2, addr2 += 2) wr16(addr2, rd16(addr1)); } else { /* dest after src: copy backwards */ for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); count != 0; count--, addr1 -= 2, addr2 -= 2) wr16(addr2, rd16(addr1)); } } void generic_bs_c_4(void *t, bus_space_handle_t bsh1, bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, size_t count) { bus_addr_t addr1 = bsh1 + off1; bus_addr_t addr2 = bsh2 + off2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; count != 0; count--, addr1 += 4, addr2 += 4) wr32(addr2, rd32(addr1)); } else { /* dest after src: copy backwards */ for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); count != 0; count--, addr1 -= 4, addr2 -= 4) wr32(addr2, rd32(addr1)); } } void generic_bs_c_8(void *t, bus_space_handle_t bsh1, bus_size_t off1, bus_space_handle_t bsh2, bus_size_t off2, size_t count) { #if defined(rd64) && defined(wr64) bus_addr_t addr1 = bsh1 + off1; bus_addr_t addr2 = bsh2 + off2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; count != 0; count--, addr1 += 8, addr2 += 8) wr64(addr2, rd64(addr1)); } else { /* dest after src: copy backwards */ for (addr1 += 8 * (count - 1), addr2 += 8 * (count - 1); count != 0; count--, addr1 -= 8, addr2 -= 8) wr64(addr2, rd64(addr1)); } #else panic("%s: not implemented", __func__); #endif } void generic_bs_barrier(void *t __unused, bus_space_handle_t bsh __unused, bus_size_t offset __unused, bus_size_t len __unused, int flags) { #if 0 if (flags & BUS_SPACE_BARRIER_WRITE) mips_dcache_wbinv_all(); #endif if (flags & BUS_SPACE_BARRIER_READ) rmb(); if (flags & BUS_SPACE_BARRIER_WRITE) wmb(); } Index: head/sys/mips/mips/nexus.c =================================================================== --- head/sys/mips/mips/nexus.c (revision 295503) +++ head/sys/mips/mips/nexus.c (revision 295504) @@ -1,580 +1,590 @@ /*- * Copyright 1998 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that both the above copyright notice and this * permission notice appear in all copies, that both the above * copyright notice and this permission notice appear in all * supporting documentation, and that the name of M.I.T. not be used * in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. makes * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * This code implements a `root nexus' for MIPS Architecture * machines. The function of the root nexus is to serve as an * attachment point for both processors and buses, and to manage * resources which are common to all of them. In particular, * this code implements the core resource managers for interrupt * requests and memory address space. */ #include "opt_platform.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef MIPS_INTRNG #include #else #include #endif #include "opt_platform.h" #ifdef FDT #include #include "ofw_bus_if.h" #endif #undef NEXUS_DEBUG #ifdef NEXUS_DEBUG #define dprintf printf #else #define dprintf(x, arg...) #endif /* NEXUS_DEBUG */ #define NUM_MIPS_IRQS 6 static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); struct nexus_device { struct resource_list nx_resources; }; #define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) static struct rman irq_rman; static struct rman mem_rman; static struct resource * nexus_alloc_resource(device_t, device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); static device_t nexus_add_child(device_t, u_int, const char *, int); static int nexus_attach(device_t); static void nexus_delete_resource(device_t, device_t, int, int); static struct resource_list * nexus_get_reslist(device_t, device_t); static int nexus_get_resource(device_t, device_t, int, int, rman_res_t *, rman_res_t *); static int nexus_print_child(device_t, device_t); static int nexus_print_all_resources(device_t dev); static int nexus_probe(device_t); static int nexus_release_resource(device_t, device_t, int, int, struct resource *); static int nexus_set_resource(device_t, device_t, int, int, rman_res_t, rman_res_t); static int nexus_activate_resource(device_t, device_t, int, int, struct resource *); static int nexus_deactivate_resource(device_t, device_t, int, int, struct resource *); static void nexus_hinted_child(device_t, const char *, int); 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); static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); #ifdef MIPS_INTRNG #ifdef SMP static int nexus_bind_intr(device_t, device_t, struct resource *, int); #endif #ifdef FDT static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr); #endif static int nexus_describe_intr(device_t dev, device_t child, struct resource *irq, void *cookie, const char *descr); static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol); #endif static device_method_t nexus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, nexus_probe), DEVMETHOD(device_attach, nexus_attach), /* Bus interface */ DEVMETHOD(bus_add_child, nexus_add_child), DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), DEVMETHOD(bus_delete_resource, nexus_delete_resource), DEVMETHOD(bus_get_resource, nexus_get_resource), DEVMETHOD(bus_get_resource_list, nexus_get_reslist), DEVMETHOD(bus_print_child, nexus_print_child), DEVMETHOD(bus_release_resource, nexus_release_resource), DEVMETHOD(bus_set_resource, nexus_set_resource), DEVMETHOD(bus_setup_intr, nexus_setup_intr), DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), DEVMETHOD(bus_activate_resource,nexus_activate_resource), DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), DEVMETHOD(bus_hinted_child, nexus_hinted_child), #ifdef MIPS_INTRNG DEVMETHOD(bus_config_intr, nexus_config_intr), DEVMETHOD(bus_describe_intr, nexus_describe_intr), #ifdef SMP DEVMETHOD(bus_bind_intr, nexus_bind_intr), #endif #ifdef FDT DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), #endif #endif { 0, 0 } }; static driver_t nexus_driver = { "nexus", nexus_methods, 1 /* no softc */ }; static devclass_t nexus_devclass; static int nexus_probe(device_t dev) { device_set_desc(dev, "MIPS32 root nexus"); irq_rman.rm_start = 0; irq_rman.rm_end = NUM_MIPS_IRQS - 1; irq_rman.rm_type = RMAN_ARRAY; irq_rman.rm_descr = "Hardware IRQs"; if (rman_init(&irq_rman) != 0 || rman_manage_region(&irq_rman, 0, NUM_MIPS_IRQS - 1) != 0) { panic("%s: irq_rman", __func__); } mem_rman.rm_start = 0; mem_rman.rm_end = ~0ul; mem_rman.rm_type = RMAN_ARRAY; mem_rman.rm_descr = "Memory addresses"; if (rman_init(&mem_rman) != 0 || rman_manage_region(&mem_rman, 0, ~0) != 0) { panic("%s: mem_rman", __func__); } return (0); } static int nexus_attach(device_t dev) { bus_generic_probe(dev); bus_enumerate_hinted_children(dev); bus_generic_attach(dev); return (0); } static int nexus_print_child(device_t bus, device_t child) { int retval = 0; retval += bus_print_child_header(bus, child); retval += nexus_print_all_resources(child); if (device_get_flags(child)) retval += printf(" flags %#x", device_get_flags(child)); retval += printf(" on %s\n", device_get_nameunit(bus)); return (retval); } static int nexus_print_all_resources(device_t dev) { struct nexus_device *ndev = DEVTONX(dev); struct resource_list *rl = &ndev->nx_resources; int retval = 0; if (STAILQ_FIRST(rl)) retval += printf(" at"); retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); return (retval); } static device_t nexus_add_child(device_t bus, u_int order, const char *name, int unit) { device_t child; struct nexus_device *ndev; ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO); if (!ndev) return (0); resource_list_init(&ndev->nx_resources); child = device_add_child_ordered(bus, order, name, unit); if (child == NULL) { device_printf(bus, "failed to add child: %s%d\n", name, unit); return (0); } /* should we free this in nexus_child_detached? */ device_set_ivars(child, ndev); return (child); } /* * Allocate a resource on behalf of child. NB: child is usually going to be a * child of one of our descendants, not a direct child of nexus0. * (Exceptions include footbridge.) */ static struct resource * nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct nexus_device *ndev = DEVTONX(child); struct resource *rv; struct resource_list_entry *rle; struct rman *rm; int isdefault, needactivate, passthrough; dprintf("%s: entry (%p, %p, %d, %p, %p, %p, %ld, %d)\n", __func__, bus, child, type, rid, (void *)(intptr_t)start, (void *)(intptr_t)end, count, flags); dprintf("%s: requested rid is %d\n", __func__, *rid); isdefault = (start == 0UL && end == ~0UL && count == 1); needactivate = flags & RF_ACTIVE; passthrough = (device_get_parent(child) != bus); rle = NULL; /* * If this is an allocation of the "default" range for a given RID, * and we know what the resources for this device are (ie. they aren't * maintained by a child bus), then work out the start/end values. */ if (isdefault) { rle = resource_list_find(&ndev->nx_resources, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) { panic("%s: resource entry is busy", __func__); } start = rle->start; end = rle->end; count = rle->count; } switch (type) { case SYS_RES_IRQ: rm = &irq_rman; break; case SYS_RES_MEMORY: rm = &mem_rman; break; default: printf("%s: unknown resource type %d\n", __func__, type); return (0); } rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == 0) { printf("%s: could not reserve resource for %s\n", __func__, device_get_nameunit(child)); return (0); } rman_set_rid(rv, *rid); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { printf("%s: could not activate resource\n", __func__); rman_release_resource(rv); return (0); } } return (rv); } static struct resource_list * nexus_get_reslist(device_t dev, device_t child) { struct nexus_device *ndev = DEVTONX(child); return (&ndev->nx_resources); } static int nexus_set_resource(device_t dev, device_t child, int type, int rid, rman_res_t start, rman_res_t count) { struct nexus_device *ndev = DEVTONX(child); struct resource_list *rl = &ndev->nx_resources; struct resource_list_entry *rle; dprintf("%s: entry (%p, %p, %d, %d, %p, %ld)\n", __func__, dev, child, type, rid, (void *)(intptr_t)start, count); rle = resource_list_add(rl, type, rid, start, start + count - 1, count); if (rle == NULL) return (ENXIO); return (0); } static int nexus_get_resource(device_t dev, device_t child, int type, int rid, rman_res_t *startp, rman_res_t *countp) { struct nexus_device *ndev = DEVTONX(child); struct resource_list *rl = &ndev->nx_resources; struct resource_list_entry *rle; rle = resource_list_find(rl, type, rid); if (!rle) return(ENOENT); if (startp) *startp = rle->start; if (countp) *countp = rle->count; return (0); } static void nexus_delete_resource(device_t dev, device_t child, int type, int rid) { struct nexus_device *ndev = DEVTONX(child); struct resource_list *rl = &ndev->nx_resources; dprintf("%s: entry\n", __func__); resource_list_delete(rl, type, rid); } static int nexus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { dprintf("%s: entry\n", __func__); if (rman_get_flags(r) & RF_ACTIVE) { int error = bus_deactivate_resource(child, type, rid, r); if (error) return error; } return (rman_release_resource(r)); } static int nexus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { void *vaddr; vm_paddr_t paddr; vm_size_t psize; + int err; /* * If this is a memory resource, use pmap_mapdev to map it. */ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { paddr = rman_get_start(r); psize = rman_get_size(r); - vaddr = pmap_mapdev(paddr, psize); - - rman_set_virtual(r, vaddr); rman_set_bustag(r, mips_bus_space_generic); + err = bus_space_map(rman_get_bustag(r), paddr, psize, 0, + (bus_space_handle_t *)&vaddr); + if (err != 0) { + rman_deactivate_resource(r); + return (err); + } + rman_set_virtual(r, vaddr); rman_set_bushandle(r, (bus_space_handle_t)(uintptr_t)vaddr); } return (rman_activate_resource(r)); } static int nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - vm_offset_t va; - - if (type == SYS_RES_MEMORY) { - va = (vm_offset_t)rman_get_virtual(r); - pmap_unmapdev(va, rman_get_size(r)); + bus_space_handle_t vaddr; + bus_size_t psize; + + vaddr = rman_get_bushandle(r); + + if (type == SYS_RES_MEMORY && vaddr != 0) { + psize = (bus_size_t)rman_get_size(r); + bus_space_unmap(rman_get_bustag(r), vaddr, psize); + rman_set_virtual(r, NULL); + rman_set_bushandle(r, 0); } return (rman_deactivate_resource(r)); } 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) { int irq; #ifdef MIPS_INTRNG for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) { intr_irq_add_handler(child, filt, intr, arg, irq, flags, cookiep); } #else register_t s; s = intr_disable(); irq = rman_get_start(res); if (irq >= NUM_MIPS_IRQS) { intr_restore(s); return (0); } cpu_establish_hardintr(device_get_nameunit(child), filt, intr, arg, irq, flags, cookiep); intr_restore(s); #endif return (0); } static int nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) { #ifdef MIPS_INTRNG return (intr_irq_remove_handler(child, rman_get_start(r), ih)); #else printf("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__); return (0); #endif } #ifdef MIPS_INTRNG static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol) { return (intr_irq_config(irq, trig, pol)); } static int nexus_describe_intr(device_t dev, device_t child, struct resource *irq, void *cookie, const char *descr) { return (intr_irq_describe(rman_get_start(irq), cookie, descr)); } #ifdef SMP static int nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) { return (intr_irq_bind(rman_get_start(irq), cpu)); } #endif #ifdef FDT static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr) { return (intr_fdt_map_irq(iparent, intr, icells)); } #endif #endif /* MIPS_INTRNG */ static void nexus_hinted_child(device_t bus, const char *dname, int dunit) { device_t child; long maddr; int msize; int order; int result; int irq; int mem_hints_count; if ((resource_int_value(dname, dunit, "order", &order)) != 0) order = 1000; child = BUS_ADD_CHILD(bus, order, dname, dunit); if (child == NULL) return; /* * Set hard-wired resources for hinted child using * specific RIDs. */ mem_hints_count = 0; if (resource_long_value(dname, dunit, "maddr", &maddr) == 0) mem_hints_count++; if (resource_int_value(dname, dunit, "msize", &msize) == 0) mem_hints_count++; /* check if all info for mem resource has been provided */ if ((mem_hints_count > 0) && (mem_hints_count < 2)) { printf("Either maddr or msize hint is missing for %s%d\n", dname, dunit); } else if (mem_hints_count) { dprintf("%s: discovered hinted child %s at maddr %p(%d)\n", __func__, device_get_nameunit(child), (void *)(intptr_t)maddr, msize); result = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize); if (result != 0) { device_printf(bus, "warning: bus_set_resource() failed\n"); } } if (resource_int_value(dname, dunit, "irq", &irq) == 0) { result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); if (result != 0) device_printf(bus, "warning: bus_set_resource() failed\n"); } } EARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_EARLY);