1 /* $NetBSD: bus_space.c,v 1.6 2000/06/29 08:17:59 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1999, by UCHIYAMA Yasushi 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. The name of the developer may NOT be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 /* $NetBSD: bus_space.c,v 1.6 2000/06/29 08:17:59 mrg Exp $ */ 29 30 /*- 31 * Copyright (c) 1998 The NetBSD Foundation, Inc. 32 * All rights reserved. 33 * 34 * This code is derived from software contributed to The NetBSD Foundation 35 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 36 * NASA Ames Research Center. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by the NetBSD 49 * Foundation, Inc. and its contributors. 50 * 4. Neither the name of The NetBSD Foundation nor the names of its 51 * contributors may be used to endorse or promote products derived 52 * from this software without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 55 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 64 * POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/malloc.h> 70 #include <sys/map.h> 71 #include <sys/extent.h> 72 73 #include <uvm/uvm_extern.h> 74 75 #include <mips/cpuregs.h> 76 #include <mips/pte.h> 77 #include <machine/bus.h> 78 79 #ifdef BUS_SPACE_DEBUG 80 #define DPRINTF(arg) printf arg 81 #else 82 #define DPRINTF(arg) 83 #endif 84 85 #define MAX_BUSSPACE_TAG 10 86 87 static struct hpcmips_bus_space sys_bus_space[MAX_BUSSPACE_TAG]; 88 static int bus_space_index = 0; 89 bus_space_handle_t __hpcmips_cacheable __P((bus_space_tag_t, bus_addr_t, bus_size_t, int)); 90 91 bus_space_tag_t 92 hpcmips_alloc_bus_space_tag() 93 { 94 bus_space_tag_t t; 95 96 if (bus_space_index >= MAX_BUSSPACE_TAG) { 97 panic("hpcmips_internal_alloc_bus_space_tag: tag full."); 98 } 99 t = &sys_bus_space[bus_space_index++]; 100 return t; 101 } 102 103 void 104 hpcmips_init_bus_space_extent(t) 105 bus_space_tag_t t; 106 { 107 u_int32_t pa, endpa; 108 vaddr_t va; 109 110 /* 111 * If request physical address is greater than 512MByte, 112 * mapping it to kseg2. 113 */ 114 if (t->t_base >= 0x20000000) { 115 pa = mips_trunc_page(t->t_base); 116 endpa = mips_round_page(t->t_base + t->t_size); 117 118 if (!(va = uvm_km_valloc(kernel_map, endpa - pa))) { 119 panic("hpcmips_init_bus_space_extent: can't allocate kernel virtual"); 120 } 121 DPRINTF(("pa:0x%08x -> kv:0x%08x+0x%08x", (unsigned int)t->t_base, 122 (unsigned int)va, t->t_size)); 123 t->t_base = va; /* kseg2 addr */ 124 125 for (; pa < endpa; pa += NBPG, va += NBPG) { 126 pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE); 127 } 128 } 129 130 t->t_extent = (void*)extent_create(t->t_name, t->t_base, 131 t->t_base + t->t_size, M_DEVBUF, 132 0, 0, EX_NOWAIT); 133 if (!t->t_extent) { 134 panic("hpcmips_init_bus_space_extent: unable to allocate %s map", t->t_name); 135 } 136 } 137 138 bus_space_handle_t 139 __hpcmips_cacheable(t, bpa, size, cacheable) 140 bus_space_tag_t t; 141 bus_addr_t bpa; 142 bus_size_t size; 143 int cacheable; 144 { 145 vaddr_t va, endva; 146 pt_entry_t *pte; 147 u_int32_t opte, npte; 148 149 MachFlushCache(); 150 if (t->t_base >= MIPS_KSEG2_START) { 151 va = mips_trunc_page(bpa); 152 endva = mips_round_page(bpa + size); 153 npte = CPUISMIPS3 ? MIPS3_PG_UNCACHED : MIPS1_PG_N; 154 155 for (; va < endva; va += NBPG) { 156 pte = kvtopte(va); 157 opte = pte->pt_entry; 158 if (cacheable) { 159 opte &= ~npte; 160 } else { 161 opte |= npte; 162 } 163 pte->pt_entry = opte; 164 /* 165 * Update the same virtual address entry. 166 */ 167 MachTLBUpdate(va, opte); 168 } 169 return bpa; 170 } 171 172 return cacheable ? MIPS_PHYS_TO_KSEG0(bpa) : MIPS_PHYS_TO_KSEG1(bpa); 173 } 174 175 /* ARGSUSED */ 176 int 177 bus_space_map(t, bpa, size, flags, bshp) 178 bus_space_tag_t t; 179 bus_addr_t bpa; 180 bus_size_t size; 181 int flags; 182 bus_space_handle_t *bshp; 183 { 184 int err; 185 int cacheable = flags & BUS_SPACE_MAP_CACHEABLE; 186 187 if (!t->t_extent) { /* Before autoconfiguration, can't use extent */ 188 DPRINTF(("bus_space_map: map temprary region:0x%08x-0x%08x\n", bpa, bpa+size)); 189 bpa += t->t_base; 190 } else { 191 bpa += t->t_base; 192 if ((err = extent_alloc_region(t->t_extent, bpa, size, 193 EX_NOWAIT|EX_MALLOCOK))) { 194 return err; 195 } 196 } 197 *bshp = __hpcmips_cacheable(t, bpa, size, cacheable); 198 DPRINTF(("\tbus_space_map:%#x(%#x)+%#x\n", bpa, bpa - t->t_base, size)); 199 200 return 0; 201 } 202 203 /* ARGSUSED */ 204 int 205 bus_space_alloc(t, rstart, rend, size, alignment, boundary, flags, 206 bpap, bshp) 207 bus_space_tag_t t; 208 bus_addr_t rstart, rend; 209 bus_size_t size, alignment, boundary; 210 int flags; 211 bus_addr_t *bpap; 212 bus_space_handle_t *bshp; 213 { 214 int cacheable = flags & BUS_SPACE_MAP_CACHEABLE; 215 u_long bpa; 216 int err; 217 218 if (!t->t_extent) 219 panic("bus_space_alloc: no extent"); 220 221 rstart += t->t_base; 222 rend += t->t_base; 223 if ((err = extent_alloc_subregion(t->t_extent, rstart, rend, size, 224 alignment, boundary, 225 EX_FAST|EX_NOWAIT|EX_MALLOCOK, &bpa))) { 226 return err; 227 } 228 229 *bshp = __hpcmips_cacheable(t, bpa, size, cacheable); 230 231 if (bpap) { 232 *bpap = bpa; 233 } 234 235 DPRINTF(("\tbus_space_alloc:%#x(%#x)+%#x\n", (unsigned)bpa, (unsigned)(bpa - t->t_base), size)); 236 237 return 0; 238 } 239 240 /* ARGSUSED */ 241 void 242 bus_space_free(t, bsh, size) 243 bus_space_tag_t t; 244 bus_space_handle_t bsh; 245 bus_size_t size; 246 { 247 /* bus_space_unmap() does all that we need to do. */ 248 bus_space_unmap(t, bsh, size); 249 } 250 251 void 252 bus_space_unmap(t, bsh, size) 253 bus_space_tag_t t; 254 bus_space_handle_t bsh; 255 bus_size_t size; 256 { 257 int err; 258 u_int32_t addr; 259 260 if (!t->t_extent) { 261 return; /* Before autoconfiguration, can't use extent */ 262 } 263 264 if (t->t_base < MIPS_KSEG2_START) { 265 addr = MIPS_KSEG1_TO_PHYS(bsh); 266 } else { 267 addr = bsh; 268 } 269 270 if ((err = extent_free(t->t_extent, addr, size, EX_NOWAIT))) { 271 DPRINTF(("warning: %#x-%#x of %s space lost\n", 272 bsh, bsh+size, t->t_name)); 273 } 274 } 275 276 /* ARGSUSED */ 277 int 278 bus_space_subregion(t, bsh, offset, size, nbshp) 279 bus_space_tag_t t; 280 bus_space_handle_t bsh; 281 bus_size_t offset, size; 282 bus_space_handle_t *nbshp; 283 { 284 *nbshp = bsh + offset; 285 286 return 0; 287 } 288