1 /* $NetBSD: bus_space.c,v 1.7 2002/02/11 17:22:39 uch Exp $ */ 2 3 /*- 4 * Copyright (c) 2001, 2002 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 "debug_hpcsh.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/malloc.h> 41 #include <sys/extent.h> 42 43 #include <machine/bus.h> 44 45 /* bus.h turn on BUS_SPACE_DEBUG if the global DEBUG option is enabled. */ 46 #ifdef BUS_SPACE_DEBUG 47 #define DPRINTF_ENABLE 48 #define DPRINTF_DEBUG bus_space_debug 49 #endif 50 #include <machine/debug.h> 51 52 #define _BUS_SPACE_ACCESS_HOOK() ((void)0) 53 _BUS_SPACE_READ(_bus_space, 1, 8) 54 _BUS_SPACE_READ(_bus_space, 2, 16) 55 _BUS_SPACE_READ(_bus_space, 4, 32) 56 _BUS_SPACE_READ(_bus_space, 8, 64) 57 _BUS_SPACE_READ_MULTI(_bus_space, 1, 8) 58 _BUS_SPACE_READ_MULTI(_bus_space, 2, 16) 59 _BUS_SPACE_READ_MULTI(_bus_space, 4, 32) 60 _BUS_SPACE_READ_MULTI(_bus_space, 8, 64) 61 _BUS_SPACE_READ_REGION(_bus_space, 1, 8) 62 _BUS_SPACE_READ_REGION(_bus_space, 2, 16) 63 _BUS_SPACE_READ_REGION(_bus_space, 4, 32) 64 _BUS_SPACE_READ_REGION(_bus_space, 8, 64) 65 _BUS_SPACE_WRITE(_bus_space, 1, 8) 66 _BUS_SPACE_WRITE(_bus_space, 2, 16) 67 _BUS_SPACE_WRITE(_bus_space, 4, 32) 68 _BUS_SPACE_WRITE(_bus_space, 8, 64) 69 _BUS_SPACE_WRITE_MULTI(_bus_space, 1, 8) 70 _BUS_SPACE_WRITE_MULTI(_bus_space, 2, 16) 71 _BUS_SPACE_WRITE_MULTI(_bus_space, 4, 32) 72 _BUS_SPACE_WRITE_MULTI(_bus_space, 8, 64) 73 _BUS_SPACE_WRITE_REGION(_bus_space, 1, 8) 74 _BUS_SPACE_WRITE_REGION(_bus_space, 2, 16) 75 _BUS_SPACE_WRITE_REGION(_bus_space, 4, 32) 76 _BUS_SPACE_WRITE_REGION(_bus_space, 8, 64) 77 _BUS_SPACE_SET_MULTI(_bus_space, 1, 8) 78 _BUS_SPACE_SET_MULTI(_bus_space, 2, 16) 79 _BUS_SPACE_SET_MULTI(_bus_space, 4, 32) 80 _BUS_SPACE_SET_MULTI(_bus_space, 8, 64) 81 _BUS_SPACE_COPY_REGION(_bus_space, 1, 8) 82 _BUS_SPACE_COPY_REGION(_bus_space, 2, 16) 83 _BUS_SPACE_COPY_REGION(_bus_space, 4, 32) 84 _BUS_SPACE_COPY_REGION(_bus_space, 8, 64) 85 #undef _BUS_SPACE_ACCESS_HOOK 86 87 static int _bus_space_map(void *, bus_addr_t, bus_size_t, int, 88 bus_space_handle_t *); 89 static void _bus_space_unmap(void *, bus_space_handle_t, bus_size_t); 90 static int _bus_space_subregion(void *, bus_space_handle_t, bus_size_t, 91 bus_size_t, bus_space_handle_t *); 92 static int _bus_space_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t, 93 bus_size_t, bus_size_t, int, 94 bus_addr_t *, bus_space_handle_t *); 95 static void _bus_space_free(void *, bus_space_handle_t, bus_size_t); 96 static void *_bus_space_vaddr(void *, bus_space_handle_t); 97 98 static struct hpcsh_bus_space __default_bus_space = { 99 hbs_extent : 0, 100 hbs_map : _bus_space_map, 101 hbs_unmap : _bus_space_unmap, 102 hbs_subregion : _bus_space_subregion, 103 hbs_alloc : _bus_space_alloc, 104 hbs_free : _bus_space_free, 105 hbs_vaddr : _bus_space_vaddr, 106 hbs_r_1 : _bus_space_read_1, 107 hbs_r_2 : _bus_space_read_2, 108 hbs_r_4 : _bus_space_read_4, 109 hbs_r_8 : _bus_space_read_8, 110 hbs_rm_1 : _bus_space_read_multi_1, 111 hbs_rm_2 : _bus_space_read_multi_2, 112 hbs_rm_4 : _bus_space_read_multi_4, 113 hbs_rm_8 : _bus_space_read_multi_8, 114 hbs_rr_1 : _bus_space_read_region_1, 115 hbs_rr_2 : _bus_space_read_region_2, 116 hbs_rr_4 : _bus_space_read_region_4, 117 hbs_rr_8 : _bus_space_read_region_8, 118 hbs_w_1 : _bus_space_write_1, 119 hbs_w_2 : _bus_space_write_2, 120 hbs_w_4 : _bus_space_write_4, 121 hbs_w_8 : _bus_space_write_8, 122 hbs_wm_1 : _bus_space_write_multi_1, 123 hbs_wm_2 : _bus_space_write_multi_2, 124 hbs_wm_4 : _bus_space_write_multi_4, 125 hbs_wm_8 : _bus_space_write_multi_8, 126 hbs_wr_1 : _bus_space_write_region_1, 127 hbs_wr_2 : _bus_space_write_region_2, 128 hbs_wr_4 : _bus_space_write_region_4, 129 hbs_wr_8 : _bus_space_write_region_8, 130 hbs_sm_1 : _bus_space_set_multi_1, 131 hbs_sm_2 : _bus_space_set_multi_2, 132 hbs_sm_4 : _bus_space_set_multi_4, 133 hbs_sm_8 : _bus_space_set_multi_8, 134 hbs_c_1 : _bus_space_copy_region_1, 135 hbs_c_2 : _bus_space_copy_region_2, 136 hbs_c_4 : _bus_space_copy_region_4, 137 hbs_c_8 : _bus_space_copy_region_8 138 }; 139 140 /* create default bus_space_tag */ 141 bus_space_tag_t 142 bus_space_create(struct hpcsh_bus_space *hbs, const char *name, 143 bus_addr_t addr, bus_size_t size) 144 { 145 if (hbs == 0) 146 hbs = malloc(sizeof(*hbs), M_DEVBUF, M_NOWAIT); 147 KASSERT(hbs); 148 149 memset(hbs, 0, sizeof(*hbs)); 150 151 /* set default method */ 152 *hbs = __default_bus_space; 153 hbs->hbs_cookie = hbs; 154 155 /* set access region */ 156 if (size == 0) { 157 hbs->hbs_base_addr = addr; /* no extent */ 158 } else { 159 hbs->hbs_extent = extent_create(name, addr, addr + size - 1, 160 M_DEVBUF, 0, 0, EX_NOWAIT); 161 if (hbs->hbs_extent == 0) { 162 panic("%s:: unable to create bus_space for " 163 "0x%08lx-%#lx\n", __FUNCTION__, addr, size); 164 } 165 } 166 167 return hbs; 168 } 169 170 void 171 bus_space_destroy(bus_space_tag_t t) 172 { 173 struct hpcsh_bus_space *hbs = t; 174 struct extent *ex = hbs->hbs_extent; 175 176 if (ex != 0) 177 extent_destroy(ex); 178 179 free(t, M_DEVBUF); 180 } 181 182 /* default bus_space tag */ 183 static int 184 _bus_space_map(void *t, bus_addr_t bpa, bus_size_t size, int flags, 185 bus_space_handle_t *bshp) 186 { 187 struct hpcsh_bus_space *hbs = t; 188 struct extent *ex = hbs->hbs_extent; 189 int error; 190 191 if (ex == 0) { 192 *bshp = (bus_space_handle_t)(bpa + hbs->hbs_base_addr); 193 return (0); 194 } 195 196 bpa += ex->ex_start; 197 error = extent_alloc_region(ex, bpa, size, EX_NOWAIT | EX_MALLOCOK); 198 199 if (error) { 200 DPRINTF("failed.\n"); 201 return (error); 202 } 203 204 *bshp = (bus_space_handle_t)bpa; 205 206 return (0); 207 } 208 209 static int 210 _bus_space_subregion(void *t, bus_space_handle_t bsh, 211 bus_size_t offset, bus_size_t size, 212 bus_space_handle_t *nbshp) 213 { 214 *nbshp = bsh + offset; 215 216 return (0); 217 } 218 219 static int 220 _bus_space_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, 221 bus_size_t size, bus_size_t alignment, bus_size_t boundary, 222 int flags, bus_addr_t *bpap, bus_space_handle_t *bshp) 223 { 224 struct hpcsh_bus_space *hbs = t; 225 struct extent *ex = hbs->hbs_extent; 226 u_long bpa, base; 227 int error; 228 229 if (ex == 0) { 230 *bshp = *bpap = rstart + hbs->hbs_base_addr; 231 return (0); 232 } 233 234 base = ex->ex_start; 235 236 error = extent_alloc_subregion(ex, rstart + base, rend + base, size, 237 alignment, boundary, 238 EX_FAST | EX_NOWAIT | EX_MALLOCOK, 239 &bpa); 240 241 if (error) { 242 DPRINTF("failed. base=0x%08x rstart=0x%08x, rend=0x%08x" 243 " size=0x%08x\n", (u_int32_t)base, (u_int32_t)rstart, 244 (u_int32_t)rend, (u_int32_t)size); 245 return (error); 246 } 247 248 *bshp = (bus_space_handle_t)bpa; 249 250 if (bpap) 251 *bpap = bpa; 252 253 return (0); 254 } 255 256 static void 257 _bus_space_free(void *t, bus_space_handle_t bsh, bus_size_t size) 258 { 259 struct hpcsh_bus_space *hbs = t; 260 struct extent *ex = hbs->hbs_extent; 261 262 if (ex != 0) 263 _bus_space_unmap(t, bsh, size); 264 } 265 266 static void 267 _bus_space_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) 268 { 269 struct hpcsh_bus_space *hbs = t; 270 struct extent *ex = hbs->hbs_extent; 271 int error; 272 273 if (ex == 0) 274 return; 275 276 error = extent_free(ex, bsh, size, EX_NOWAIT); 277 278 if (error) { 279 DPRINTF("%#lx-%#lx of %s space lost\n", bsh, bsh + size, 280 ex->ex_name); 281 } 282 } 283 284 void * 285 _bus_space_vaddr(void *t, bus_space_handle_t h) 286 { 287 return (void *)h; 288 } 289