1 /* $NetBSD: bus_space.c,v 1.2 2002/09/27 15:36:35 provos Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 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. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the NetBSD 18 * Foundation, Inc. and its contributors. 19 * 4. Neither the name of The NetBSD Foundation nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/malloc.h> 39 #include <sys/extent.h> 40 41 #define _PLAYSTATION2_BUS_SPACE_PRIVATE 42 #include <machine/bus.h> 43 44 #ifdef BUS_SPACE_DEBUG 45 int bus_space_debug = 0; 46 #define DPRINTF(fmt, args...) \ 47 if (bus_space_debug) \ 48 printf("%s: " fmt, __FUNCTION__ , ##args) 49 #define DPRINTFN(n, arg) \ 50 if (bus_space_debug > (n)) \ 51 printf("%s: " fmt, __FUNCTION__ , ##args) 52 #else 53 #define DPRINTF(arg...) ((void)0) 54 #define DPRINTFN(n, arg...) ((void)0) 55 #endif 56 57 #define VADDR(h, o) (h + o) 58 _BUS_SPACE_READ(_default, 1, 8) 59 _BUS_SPACE_READ(_default, 2, 16) 60 _BUS_SPACE_READ(_default, 4, 32) 61 _BUS_SPACE_READ(_default, 8, 64) 62 _BUS_SPACE_READ_MULTI(_default, 1, 8) 63 _BUS_SPACE_READ_MULTI(_default, 2, 16) 64 _BUS_SPACE_READ_MULTI(_default, 4, 32) 65 _BUS_SPACE_READ_MULTI(_default, 8, 64) 66 _BUS_SPACE_READ_REGION(_default, 1, 8) 67 _BUS_SPACE_READ_REGION(_default, 2, 16) 68 _BUS_SPACE_READ_REGION(_default, 4, 32) 69 _BUS_SPACE_READ_REGION(_default, 8, 64) 70 _BUS_SPACE_WRITE(_default, 1, 8) 71 _BUS_SPACE_WRITE(_default, 2, 16) 72 _BUS_SPACE_WRITE(_default, 4, 32) 73 _BUS_SPACE_WRITE(_default, 8, 64) 74 _BUS_SPACE_WRITE_MULTI(_default, 1, 8) 75 _BUS_SPACE_WRITE_MULTI(_default, 2, 16) 76 _BUS_SPACE_WRITE_MULTI(_default, 4, 32) 77 _BUS_SPACE_WRITE_MULTI(_default, 8, 64) 78 _BUS_SPACE_WRITE_REGION(_default, 1, 8) 79 _BUS_SPACE_WRITE_REGION(_default, 2, 16) 80 _BUS_SPACE_WRITE_REGION(_default, 4, 32) 81 _BUS_SPACE_WRITE_REGION(_default, 8, 64) 82 _BUS_SPACE_SET_MULTI(_default, 1, 8) 83 _BUS_SPACE_SET_MULTI(_default, 2, 16) 84 _BUS_SPACE_SET_MULTI(_default, 4, 32) 85 _BUS_SPACE_SET_MULTI(_default, 8, 64) 86 _BUS_SPACE_SET_REGION(_default, 1, 8) 87 _BUS_SPACE_SET_REGION(_default, 2, 16) 88 _BUS_SPACE_SET_REGION(_default, 4, 32) 89 _BUS_SPACE_SET_REGION(_default, 8, 64) 90 _BUS_SPACE_COPY_REGION(_default, 1, 8) 91 _BUS_SPACE_COPY_REGION(_default, 2, 16) 92 _BUS_SPACE_COPY_REGION(_default, 4, 32) 93 _BUS_SPACE_COPY_REGION(_default, 8, 64) 94 #undef VADDR 95 96 static int _default_map(void *, bus_addr_t, bus_size_t, int, 97 bus_space_handle_t *); 98 static void _default_unmap(void *, bus_space_handle_t, bus_size_t); 99 static int _default_subregion(void *, bus_space_handle_t, bus_size_t, 100 bus_size_t, bus_space_handle_t *); 101 static int _default_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t, 102 bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *); 103 static void _default_free(void *, bus_space_handle_t, bus_size_t); 104 static void *_default_vaddr(void *, bus_space_handle_t); 105 106 static const struct playstation2_bus_space _default_bus_space = { 107 pbs_map : _default_map, 108 pbs_unmap : _default_unmap, 109 pbs_subregion : _default_subregion, 110 pbs_alloc : _default_alloc, 111 pbs_free : _default_free, 112 pbs_vaddr : _default_vaddr, 113 pbs_r_1 : _default_read_1, 114 pbs_r_2 : _default_read_2, 115 pbs_r_4 : _default_read_4, 116 pbs_r_8 : _default_read_8, 117 pbs_rm_1 : _default_read_multi_1, 118 pbs_rm_2 : _default_read_multi_2, 119 pbs_rm_4 : _default_read_multi_4, 120 pbs_rm_8 : _default_read_multi_8, 121 pbs_rr_1 : _default_read_region_1, 122 pbs_rr_2 : _default_read_region_2, 123 pbs_rr_4 : _default_read_region_4, 124 pbs_rr_8 : _default_read_region_8, 125 pbs_w_1 : _default_write_1, 126 pbs_w_2 : _default_write_2, 127 pbs_w_4 : _default_write_4, 128 pbs_w_8 : _default_write_8, 129 pbs_wm_1 : _default_write_multi_1, 130 pbs_wm_2 : _default_write_multi_2, 131 pbs_wm_4 : _default_write_multi_4, 132 pbs_wm_8 : _default_write_multi_8, 133 pbs_wr_1 : _default_write_region_1, 134 pbs_wr_2 : _default_write_region_2, 135 pbs_wr_4 : _default_write_region_4, 136 pbs_wr_8 : _default_write_region_8, 137 pbs_sm_1 : _default_set_multi_1, 138 pbs_sm_2 : _default_set_multi_2, 139 pbs_sm_4 : _default_set_multi_4, 140 pbs_sm_8 : _default_set_multi_8, 141 pbs_sr_1 : _default_set_region_1, 142 pbs_sr_2 : _default_set_region_2, 143 pbs_sr_4 : _default_set_region_4, 144 pbs_sr_8 : _default_set_region_8, 145 pbs_c_1 : _default_copy_region_1, 146 pbs_c_2 : _default_copy_region_2, 147 pbs_c_4 : _default_copy_region_4, 148 pbs_c_8 : _default_copy_region_8 149 }; 150 151 /* create default bus_space_tag */ 152 bus_space_tag_t 153 bus_space_create(bus_space_tag_t t, const char *name, 154 bus_addr_t addr, bus_size_t size) 155 { 156 struct playstation2_bus_space *pbs = (void *)t; /* discard const */ 157 158 if (pbs == 0) 159 pbs = malloc(sizeof(*pbs), M_DEVBUF, M_NOWAIT); 160 KDASSERT(pbs); 161 162 memset(pbs, 0, sizeof(*pbs)); 163 164 /* set default method */ 165 *pbs = _default_bus_space; 166 pbs->pbs_cookie = pbs; 167 168 /* set access region */ 169 if (size == 0) { 170 pbs->pbs_base_addr = addr; /* no extent */ 171 } else { 172 pbs->pbs_extent = extent_create(name, addr, addr + size - 1, 173 M_DEVBUF, 0, 0, EX_NOWAIT); 174 if (pbs->pbs_extent == 0) { 175 panic("%s:: unable to create bus_space for " 176 "0x%08lx-%#lx", __FUNCTION__, addr, size); 177 } 178 } 179 180 return (pbs); 181 } 182 183 void 184 bus_space_destroy(bus_space_tag_t t) 185 { 186 struct playstation2_bus_space *pbs = (void *)t; /* discard const */ 187 struct extent *ex = pbs->pbs_extent; 188 189 if (ex != 0) 190 extent_destroy(ex); 191 192 free(pbs, M_DEVBUF); 193 } 194 195 void 196 _bus_space_invalid_access(void) 197 { 198 panic("invalid bus space access."); 199 } 200 201 /* default bus_space tag */ 202 static int 203 _default_map(void *t, bus_addr_t bpa, bus_size_t size, int flags, 204 bus_space_handle_t *bshp) 205 { 206 struct playstation2_bus_space *pbs = t; 207 struct extent *ex = pbs->pbs_extent; 208 int error; 209 210 if (ex == 0) { 211 *bshp = (bus_space_handle_t)(bpa + pbs->pbs_base_addr); 212 return (0); 213 } 214 215 bpa += ex->ex_start; 216 error = extent_alloc_region(ex, bpa, size, EX_NOWAIT | EX_MALLOCOK); 217 218 if (error) { 219 DPRINTF("failed.\n"); 220 return (error); 221 } 222 223 *bshp = (bus_space_handle_t)bpa; 224 225 DPRINTF("success.\n"); 226 227 return (0); 228 } 229 230 static int 231 _default_subregion(void *t, bus_space_handle_t bsh, 232 bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) 233 { 234 *nbshp = bsh + offset; 235 236 return (0); 237 } 238 239 static int 240 _default_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, 241 bus_size_t size, bus_size_t alignment, bus_size_t boundary, 242 int flags, bus_addr_t *bpap, bus_space_handle_t *bshp) 243 { 244 struct playstation2_bus_space *pbs = t; 245 struct extent *ex = pbs->pbs_extent; 246 u_long bpa, base; 247 int error; 248 249 if (ex == 0) { 250 *bshp = *bpap = rstart + pbs->pbs_base_addr; 251 return (0); 252 } 253 254 base = ex->ex_start; 255 256 error = extent_alloc_subregion(ex, rstart + base, rend + base, size, 257 alignment, boundary, 258 EX_FAST | EX_NOWAIT | EX_MALLOCOK, 259 &bpa); 260 261 if (error) { 262 DPRINTF("failed.\n"); 263 return (error); 264 } 265 266 *bshp = (bus_space_handle_t)bpa; 267 268 if (bpap) 269 *bpap = bpa; 270 271 DPRINTF("success.\n"); 272 273 return (0); 274 } 275 276 static void 277 _default_free(void *t, bus_space_handle_t bsh, bus_size_t size) 278 { 279 struct playstation2_bus_space *pbs = t; 280 struct extent *ex = pbs->pbs_extent; 281 282 if (ex != 0) 283 _default_unmap(t, bsh, size); 284 } 285 286 static void 287 _default_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) 288 { 289 struct playstation2_bus_space *pbs = t; 290 struct extent *ex = pbs->pbs_extent; 291 int error; 292 293 if (ex == 0) 294 return; 295 296 error = extent_free(ex, bsh, size, EX_NOWAIT); 297 298 if (error) { 299 DPRINTF("%#lx-%#lx of %s space lost\n", bsh, bsh + size, 300 ex->ex_name); 301 } 302 } 303 304 void * 305 _default_vaddr(void *t, bus_space_handle_t h) 306 { 307 return (void *)h; 308 } 309