1 /* $NetBSD: bus_space.c,v 1.4 2000/11/24 09:36:40 scw Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Steve C. Woodford and Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Implementation of bus_space mapping for the mvme68k. 41 * Derived from the hp300 bus_space implementation by Jason Thorpe. 42 */ 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/malloc.h> 47 48 #include <machine/cpu.h> 49 #include <machine/pte.h> 50 #define _MVME68K_BUS_DMA_PRIVATE /* For _bus_dmamem_map/_bus_dmamem_unmap */ 51 #define _MVME68K_BUS_SPACE_PRIVATE 52 #include <machine/bus.h> 53 #undef _MVME68K_BUS_DMA_PRIVATE 54 #undef _MVME68K_BUS_SPACE_PRIVATE 55 56 static void peek1(void *, void *); 57 static void peek2(void *, void *); 58 static void peek4(void *, void *); 59 static void poke1(void *, u_int); 60 static void poke2(void *, u_int); 61 static void poke4(void *, u_int); 62 static int do_peek(void (*)(void *, void *), void *, void *); 63 static int do_poke(void (*)(void *, u_int), void *, u_int); 64 65 /* 66 * Used in locore.s/trap.c to determine if faults are being trapped. 67 */ 68 label_t *nofault; 69 70 71 /* ARGSUSED */ 72 int 73 _bus_space_map(cookie, addr, size, flags, bushp) 74 void *cookie; 75 bus_addr_t addr; 76 bus_size_t size; 77 int flags; 78 bus_space_handle_t *bushp; 79 { 80 bus_dma_segment_t seg; 81 caddr_t va; 82 83 if (addr >= intiobase_phys && addr < intiotop_phys) { 84 #ifdef DEBUG 85 if ((addr + size) >= intiotop_phys) 86 panic("mvme68k_bus_space_map: Invalid INTIO range!"); 87 #endif 88 /* 89 * Intio space is direct-mapped in pmap_bootstrap(); just 90 * do the translation. 91 */ 92 addr -= intiobase_phys; 93 *bushp = (bus_space_handle_t) &(intiobase[addr]); 94 return (0); 95 } 96 97 /* 98 * Otherwise, set up a VM mapping for the requested address range 99 */ 100 seg.ds_addr = seg._ds_cpuaddr = m68k_trunc_page(addr); 101 seg.ds_len = m68k_round_page(size); 102 103 if (_bus_dmamem_map(NULL, &seg, 1, seg.ds_len, &va, 104 flags | BUS_DMA_COHERENT)) 105 return EIO; 106 107 /* 108 * The handle is really the virtual address we just mapped 109 */ 110 *bushp = (bus_space_handle_t) (va + m68k_page_offset(addr)); 111 112 return (0); 113 } 114 115 /* ARGSUSED */ 116 void 117 _bus_space_unmap(cookie, bush, size) 118 void *cookie; 119 bus_space_handle_t bush; 120 bus_size_t size; 121 { 122 /* Nothing to do for INTIO space */ 123 if ((char *)bush >= intiobase && (char *)bush < intiolimit) 124 return; 125 126 bush = m68k_trunc_page(bush); 127 size = m68k_round_page(size); 128 129 _bus_dmamem_unmap(NULL, (caddr_t) bush, size); 130 } 131 132 /* ARGSUSED */ 133 int 134 _bus_space_peek_1(cookie, bush, offset, valuep) 135 void *cookie; 136 bus_space_handle_t bush; 137 bus_size_t offset; 138 u_int8_t *valuep; 139 { 140 u_int8_t v; 141 142 if (valuep == NULL) 143 valuep = &v; 144 145 return (do_peek(&peek1, (void *)(bush + offset), (void *)valuep)); 146 } 147 148 /* ARGSUSED */ 149 int 150 _bus_space_peek_2(cookie, bush, offset, valuep) 151 void *cookie; 152 bus_space_handle_t bush; 153 bus_size_t offset; 154 u_int16_t *valuep; 155 { 156 u_int16_t v; 157 158 if (valuep == NULL) 159 valuep = &v; 160 161 return (do_peek(&peek2, (void *)(bush + offset), (void *)valuep)); 162 } 163 164 /* ARGSUSED */ 165 int 166 _bus_space_peek_4(cookie, bush, offset, valuep) 167 void *cookie; 168 bus_space_handle_t bush; 169 bus_size_t offset; 170 u_int32_t *valuep; 171 { 172 u_int32_t v; 173 174 if (valuep == NULL) 175 valuep = &v; 176 177 return (do_peek(&peek4, (void *)(bush + offset), (void *)valuep)); 178 } 179 180 /* ARGSUSED */ 181 int 182 _bus_space_poke_1(cookie, bush, offset, value) 183 void *cookie; 184 bus_space_handle_t bush; 185 bus_size_t offset; 186 u_int8_t value; 187 { 188 return (do_poke(&poke1, (void *)(bush + offset), (u_int)value)); 189 } 190 191 /* ARGSUSED */ 192 int 193 _bus_space_poke_2(cookie, bush, offset, value) 194 void *cookie; 195 bus_space_handle_t bush; 196 bus_size_t offset; 197 u_int16_t value; 198 { 199 return (do_poke(&poke2, (void *)(bush + offset), (u_int)value)); 200 } 201 202 /* ARGSUSED */ 203 int 204 _bus_space_poke_4(cookie, bush, offset, value) 205 void *cookie; 206 bus_space_handle_t bush; 207 bus_size_t offset; 208 u_int32_t value; 209 { 210 return (do_poke(&poke4, (void *)(bush + offset), (u_int)value)); 211 } 212 213 static void 214 peek1(addr, vp) 215 void *addr; 216 void *vp; 217 { 218 *((u_int8_t *)vp) = *((u_int8_t *)addr); 219 } 220 221 static void 222 peek2(addr, vp) 223 void *addr; 224 void *vp; 225 { 226 *((u_int16_t *)vp) = *((u_int16_t *)addr); 227 } 228 229 static void 230 peek4(addr, vp) 231 void *addr; 232 void *vp; 233 { 234 *((u_int32_t *)vp) = *((u_int32_t *)addr); 235 } 236 237 static void 238 poke1(addr, value) 239 void *addr; 240 u_int value; 241 { 242 *((u_int8_t *)addr) = value; 243 } 244 245 static void 246 poke2(addr, value) 247 void *addr; 248 u_int value; 249 { 250 *((u_int16_t *)addr) = value; 251 } 252 253 static void 254 poke4(addr, value) 255 void *addr; 256 u_int value; 257 { 258 *((u_int32_t *)addr) = value; 259 } 260 261 static int 262 do_peek(peekfn, addr, valuep) 263 void (*peekfn)(void *, void *); 264 void *addr; 265 void *valuep; 266 { 267 label_t faultbuf; 268 269 nofault = &faultbuf; 270 if (setjmp(&faultbuf)) { 271 nofault = NULL; 272 return (1); 273 } 274 275 (*peekfn)(addr, valuep); 276 277 nofault = NULL; 278 return (0); 279 } 280 281 static int 282 do_poke(pokefn, addr, value) 283 void (*pokefn)(void *, u_int); 284 void *addr; 285 u_int value; 286 { 287 label_t faultbuf; 288 289 nofault = &faultbuf; 290 if (setjmp(&faultbuf)) { 291 nofault = NULL; 292 return (1); 293 } 294 295 (*pokefn)(addr, value); 296 297 nofault = NULL; 298 return (0); 299 } 300