1 1.40 thorpej /* $NetBSD: tc_bus_mem.c,v 1.40 2021/07/04 22:42:36 thorpej Exp $ */ 2 1.1 cgd 3 1.1 cgd /* 4 1.1 cgd * Copyright (c) 1996 Carnegie-Mellon University. 5 1.1 cgd * All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Author: Chris G. Demetriou 8 1.34 matt * 9 1.1 cgd * Permission to use, copy, modify and distribute this software and 10 1.1 cgd * its documentation is hereby granted, provided that both the copyright 11 1.1 cgd * notice and this permission notice appear in all copies of the 12 1.1 cgd * software, derivative works or modified versions, and any portions 13 1.1 cgd * thereof, and that both notices appear in supporting documentation. 14 1.34 matt * 15 1.34 matt * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 1.34 matt * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 1.1 cgd * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 1.34 matt * 19 1.1 cgd * Carnegie Mellon requests users of this software to return to 20 1.1 cgd * 21 1.1 cgd * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 22 1.1 cgd * School of Computer Science 23 1.1 cgd * Carnegie Mellon University 24 1.1 cgd * Pittsburgh PA 15213-3890 25 1.1 cgd * 26 1.1 cgd * any improvements or extensions that they make and grant Carnegie the 27 1.1 cgd * rights to redistribute these changes. 28 1.1 cgd */ 29 1.1 cgd 30 1.1 cgd /* 31 1.38 flxd * Common TURBOchannel Chipset "bus memory" functions. 32 1.1 cgd */ 33 1.14 cgd 34 1.15 cgd #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 35 1.15 cgd 36 1.40 thorpej __KERNEL_RCSID(0, "$NetBSD: tc_bus_mem.c,v 1.40 2021/07/04 22:42:36 thorpej Exp $"); 37 1.1 cgd 38 1.1 cgd #include <sys/param.h> 39 1.7 cgd #include <sys/systm.h> 40 1.1 cgd #include <sys/syslog.h> 41 1.1 cgd #include <sys/device.h> 42 1.24 mrg 43 1.32 dyoung #include <sys/bus.h> 44 1.1 cgd #include <dev/tc/tcvar.h> 45 1.1 cgd 46 1.16 cgd #define __C(A,B) __CONCAT(A,B) 47 1.16 cgd 48 1.8 cgd /* mapping/unmapping */ 49 1.39 thorpej static int tc_mem_map(void *, bus_addr_t, bus_size_t, int, 50 1.28 dsl bus_space_handle_t *, int); 51 1.39 thorpej static void tc_mem_unmap(void *, bus_space_handle_t, bus_size_t, int); 52 1.39 thorpej static int tc_mem_subregion(void *, bus_space_handle_t, bus_size_t, 53 1.28 dsl bus_size_t, bus_space_handle_t *); 54 1.28 dsl 55 1.39 thorpej static int tc_mem_translate(void *, bus_addr_t, bus_size_t, 56 1.28 dsl int, struct alpha_bus_space_translation *); 57 1.39 thorpej static int tc_mem_get_window(void *, int, 58 1.28 dsl struct alpha_bus_space_translation *); 59 1.20 thorpej 60 1.8 cgd /* allocation/deallocation */ 61 1.39 thorpej static int tc_mem_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t, 62 1.8 cgd bus_size_t, bus_addr_t, int, bus_addr_t *, 63 1.28 dsl bus_space_handle_t *); 64 1.39 thorpej static void tc_mem_free(void *, bus_space_handle_t, bus_size_t); 65 1.8 cgd 66 1.22 drochner /* get kernel virtual address */ 67 1.39 thorpej static void * tc_mem_vaddr(void *, bus_space_handle_t); 68 1.22 drochner 69 1.25 thorpej /* mmap for user */ 70 1.39 thorpej static paddr_t tc_mem_mmap(void *, bus_addr_t, off_t, int, int); 71 1.25 thorpej 72 1.12 cgd /* barrier */ 73 1.39 thorpej static inline void tc_mem_barrier(void *, bus_space_handle_t, 74 1.28 dsl bus_size_t, bus_size_t, int); 75 1.12 cgd 76 1.8 cgd /* read (single) */ 77 1.39 thorpej static inline uint8_t tc_mem_read_1(void *, bus_space_handle_t, bus_size_t); 78 1.34 matt static inline uint16_t tc_mem_read_2(void *, bus_space_handle_t, bus_size_t); 79 1.34 matt static inline uint32_t tc_mem_read_4(void *, bus_space_handle_t, bus_size_t); 80 1.34 matt static inline uint64_t tc_mem_read_8(void *, bus_space_handle_t, bus_size_t); 81 1.8 cgd 82 1.8 cgd /* read multiple */ 83 1.39 thorpej static void tc_mem_read_multi_1(void *, bus_space_handle_t, 84 1.34 matt bus_size_t, uint8_t *, bus_size_t); 85 1.39 thorpej static void tc_mem_read_multi_2(void *, bus_space_handle_t, 86 1.34 matt bus_size_t, uint16_t *, bus_size_t); 87 1.39 thorpej static void tc_mem_read_multi_4(void *, bus_space_handle_t, 88 1.34 matt bus_size_t, uint32_t *, bus_size_t); 89 1.39 thorpej static void tc_mem_read_multi_8(void *, bus_space_handle_t, 90 1.34 matt bus_size_t, uint64_t *, bus_size_t); 91 1.8 cgd 92 1.8 cgd /* read region */ 93 1.39 thorpej static void tc_mem_read_region_1(void *, bus_space_handle_t, 94 1.34 matt bus_size_t, uint8_t *, bus_size_t); 95 1.39 thorpej static void tc_mem_read_region_2(void *, bus_space_handle_t, 96 1.34 matt bus_size_t, uint16_t *, bus_size_t); 97 1.39 thorpej static void tc_mem_read_region_4(void *, bus_space_handle_t, 98 1.34 matt bus_size_t, uint32_t *, bus_size_t); 99 1.39 thorpej static void tc_mem_read_region_8(void *, bus_space_handle_t, 100 1.34 matt bus_size_t, uint64_t *, bus_size_t); 101 1.8 cgd 102 1.8 cgd /* write (single) */ 103 1.39 thorpej static inline void tc_mem_write_1(void *, bus_space_handle_t, bus_size_t, 104 1.34 matt uint8_t); 105 1.39 thorpej static inline void tc_mem_write_2(void *, bus_space_handle_t, bus_size_t, 106 1.34 matt uint16_t); 107 1.39 thorpej static inline void tc_mem_write_4(void *, bus_space_handle_t, bus_size_t, 108 1.34 matt uint32_t); 109 1.39 thorpej static inline void tc_mem_write_8(void *, bus_space_handle_t, bus_size_t, 110 1.34 matt uint64_t); 111 1.8 cgd 112 1.8 cgd /* write multiple */ 113 1.39 thorpej static void tc_mem_write_multi_1(void *, bus_space_handle_t, 114 1.34 matt bus_size_t, const uint8_t *, bus_size_t); 115 1.39 thorpej static void tc_mem_write_multi_2(void *, bus_space_handle_t, 116 1.34 matt bus_size_t, const uint16_t *, bus_size_t); 117 1.39 thorpej static void tc_mem_write_multi_4(void *, bus_space_handle_t, 118 1.34 matt bus_size_t, const uint32_t *, bus_size_t); 119 1.39 thorpej static void tc_mem_write_multi_8(void *, bus_space_handle_t, 120 1.34 matt bus_size_t, const uint64_t *, bus_size_t); 121 1.8 cgd 122 1.8 cgd /* write region */ 123 1.39 thorpej static void tc_mem_write_region_1(void *, bus_space_handle_t, 124 1.34 matt bus_size_t, const uint8_t *, bus_size_t); 125 1.39 thorpej static void tc_mem_write_region_2(void *, bus_space_handle_t, 126 1.34 matt bus_size_t, const uint16_t *, bus_size_t); 127 1.39 thorpej static void tc_mem_write_region_4(void *, bus_space_handle_t, 128 1.34 matt bus_size_t, const uint32_t *, bus_size_t); 129 1.39 thorpej static void tc_mem_write_region_8(void *, bus_space_handle_t, 130 1.34 matt bus_size_t, const uint64_t *, bus_size_t); 131 1.8 cgd 132 1.11 cgd /* set multiple */ 133 1.39 thorpej static void tc_mem_set_multi_1(void *, bus_space_handle_t, 134 1.34 matt bus_size_t, uint8_t, bus_size_t); 135 1.39 thorpej static void tc_mem_set_multi_2(void *, bus_space_handle_t, 136 1.34 matt bus_size_t, uint16_t, bus_size_t); 137 1.39 thorpej static void tc_mem_set_multi_4(void *, bus_space_handle_t, 138 1.34 matt bus_size_t, uint32_t, bus_size_t); 139 1.39 thorpej static void tc_mem_set_multi_8(void *, bus_space_handle_t, 140 1.34 matt bus_size_t, uint64_t, bus_size_t); 141 1.11 cgd 142 1.11 cgd /* set region */ 143 1.39 thorpej static void tc_mem_set_region_1(void *, bus_space_handle_t, 144 1.34 matt bus_size_t, uint8_t, bus_size_t); 145 1.39 thorpej static void tc_mem_set_region_2(void *, bus_space_handle_t, 146 1.34 matt bus_size_t, uint16_t, bus_size_t); 147 1.39 thorpej static void tc_mem_set_region_4(void *, bus_space_handle_t, 148 1.34 matt bus_size_t, uint32_t, bus_size_t); 149 1.39 thorpej static void tc_mem_set_region_8(void *, bus_space_handle_t, 150 1.34 matt bus_size_t, uint64_t, bus_size_t); 151 1.11 cgd 152 1.13 cgd /* copy */ 153 1.39 thorpej static void tc_mem_copy_region_1(void *, bus_space_handle_t, 154 1.28 dsl bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 155 1.39 thorpej static void tc_mem_copy_region_2(void *, bus_space_handle_t, 156 1.28 dsl bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 157 1.39 thorpej static void tc_mem_copy_region_4(void *, bus_space_handle_t, 158 1.28 dsl bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 159 1.39 thorpej static void tc_mem_copy_region_8(void *, bus_space_handle_t, 160 1.28 dsl bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 161 1.13 cgd 162 1.8 cgd static struct alpha_bus_space tc_mem_space = { 163 1.8 cgd /* cookie */ 164 1.8 cgd NULL, 165 1.8 cgd 166 1.8 cgd /* mapping/unmapping */ 167 1.8 cgd tc_mem_map, 168 1.8 cgd tc_mem_unmap, 169 1.8 cgd tc_mem_subregion, 170 1.8 cgd 171 1.20 thorpej tc_mem_translate, 172 1.21 thorpej tc_mem_get_window, 173 1.20 thorpej 174 1.8 cgd /* allocation/deallocation */ 175 1.8 cgd tc_mem_alloc, 176 1.8 cgd tc_mem_free, 177 1.8 cgd 178 1.22 drochner /* get kernel virtual address */ 179 1.23 tron tc_mem_vaddr, 180 1.22 drochner 181 1.25 thorpej /* mmap for user */ 182 1.25 thorpej tc_mem_mmap, 183 1.25 thorpej 184 1.12 cgd /* barrier */ 185 1.12 cgd tc_mem_barrier, 186 1.12 cgd 187 1.8 cgd /* read (single) */ 188 1.8 cgd tc_mem_read_1, 189 1.8 cgd tc_mem_read_2, 190 1.8 cgd tc_mem_read_4, 191 1.8 cgd tc_mem_read_8, 192 1.8 cgd 193 1.11 cgd /* read multiple */ 194 1.8 cgd tc_mem_read_multi_1, 195 1.8 cgd tc_mem_read_multi_2, 196 1.8 cgd tc_mem_read_multi_4, 197 1.8 cgd tc_mem_read_multi_8, 198 1.8 cgd 199 1.8 cgd /* read region */ 200 1.8 cgd tc_mem_read_region_1, 201 1.8 cgd tc_mem_read_region_2, 202 1.8 cgd tc_mem_read_region_4, 203 1.8 cgd tc_mem_read_region_8, 204 1.8 cgd 205 1.8 cgd /* write (single) */ 206 1.8 cgd tc_mem_write_1, 207 1.8 cgd tc_mem_write_2, 208 1.8 cgd tc_mem_write_4, 209 1.8 cgd tc_mem_write_8, 210 1.8 cgd 211 1.11 cgd /* write multiple */ 212 1.8 cgd tc_mem_write_multi_1, 213 1.8 cgd tc_mem_write_multi_2, 214 1.8 cgd tc_mem_write_multi_4, 215 1.8 cgd tc_mem_write_multi_8, 216 1.8 cgd 217 1.8 cgd /* write region */ 218 1.8 cgd tc_mem_write_region_1, 219 1.8 cgd tc_mem_write_region_2, 220 1.8 cgd tc_mem_write_region_4, 221 1.8 cgd tc_mem_write_region_8, 222 1.8 cgd 223 1.11 cgd /* set multiple */ 224 1.11 cgd tc_mem_set_multi_1, 225 1.11 cgd tc_mem_set_multi_2, 226 1.11 cgd tc_mem_set_multi_4, 227 1.11 cgd tc_mem_set_multi_8, 228 1.8 cgd 229 1.8 cgd /* set region */ 230 1.11 cgd tc_mem_set_region_1, 231 1.11 cgd tc_mem_set_region_2, 232 1.11 cgd tc_mem_set_region_4, 233 1.11 cgd tc_mem_set_region_8, 234 1.8 cgd 235 1.8 cgd /* copy */ 236 1.16 cgd tc_mem_copy_region_1, 237 1.16 cgd tc_mem_copy_region_2, 238 1.16 cgd tc_mem_copy_region_4, 239 1.16 cgd tc_mem_copy_region_8, 240 1.8 cgd }; 241 1.1 cgd 242 1.8 cgd bus_space_tag_t 243 1.29 dsl tc_bus_mem_init(void *memv) 244 1.1 cgd { 245 1.8 cgd bus_space_tag_t h = &tc_mem_space; 246 1.1 cgd 247 1.8 cgd h->abs_cookie = memv; 248 1.8 cgd return (h); 249 1.20 thorpej } 250 1.20 thorpej 251 1.20 thorpej /* ARGSUSED */ 252 1.39 thorpej static int 253 1.29 dsl tc_mem_translate(void *v, bus_addr_t memaddr, bus_size_t memlen, int flags, struct alpha_bus_space_translation *abst) 254 1.21 thorpej { 255 1.21 thorpej 256 1.21 thorpej return (EOPNOTSUPP); 257 1.21 thorpej } 258 1.21 thorpej 259 1.21 thorpej /* ARGSUSED */ 260 1.39 thorpej static int 261 1.29 dsl tc_mem_get_window(void *v, int window, struct alpha_bus_space_translation *abst) 262 1.20 thorpej { 263 1.20 thorpej 264 1.20 thorpej return (EOPNOTSUPP); 265 1.1 cgd } 266 1.1 cgd 267 1.18 thorpej /* ARGSUSED */ 268 1.39 thorpej static int 269 1.29 dsl tc_mem_map(void *v, bus_addr_t memaddr, bus_size_t memsize, int flags, bus_space_handle_t *memhp, int acct) 270 1.1 cgd { 271 1.16 cgd int cacheable = flags & BUS_SPACE_MAP_CACHEABLE; 272 1.16 cgd int linear = flags & BUS_SPACE_MAP_LINEAR; 273 1.16 cgd 274 1.16 cgd /* Requests for linear uncacheable space can't be satisfied. */ 275 1.16 cgd if (linear && !cacheable) 276 1.16 cgd return (EOPNOTSUPP); 277 1.1 cgd 278 1.1 cgd if (memaddr & 0x7) 279 1.37 christos panic("%s: need 8 byte alignment", __func__); 280 1.1 cgd if (cacheable) 281 1.7 cgd *memhp = ALPHA_PHYS_TO_K0SEG(memaddr); 282 1.1 cgd else 283 1.7 cgd *memhp = ALPHA_PHYS_TO_K0SEG(TC_DENSE_TO_SPARSE(memaddr)); 284 1.1 cgd return (0); 285 1.1 cgd } 286 1.1 cgd 287 1.18 thorpej /* ARGSUSED */ 288 1.39 thorpej static void 289 1.29 dsl tc_mem_unmap(void *v, bus_space_handle_t memh, bus_size_t memsize, int acct) 290 1.1 cgd { 291 1.1 cgd 292 1.8 cgd /* XXX XX XXX nothing to do. */ 293 1.1 cgd } 294 1.1 cgd 295 1.39 thorpej static int 296 1.30 dsl tc_mem_subregion(void *v, bus_space_handle_t memh, bus_size_t offset, bus_size_t size, bus_space_handle_t *nmemh) 297 1.4 cgd { 298 1.4 cgd 299 1.5 cgd /* Disallow subregioning that would make the handle unaligned. */ 300 1.5 cgd if ((offset & 0x7) != 0) 301 1.5 cgd return (1); 302 1.5 cgd 303 1.4 cgd if ((memh & TC_SPACE_SPARSE) != 0) 304 1.6 cgd *nmemh = memh + (offset << 1); 305 1.4 cgd else 306 1.6 cgd *nmemh = memh + offset; 307 1.5 cgd 308 1.4 cgd return (0); 309 1.4 cgd } 310 1.4 cgd 311 1.39 thorpej static int 312 1.30 dsl tc_mem_alloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size, bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp, bus_space_handle_t *bshp) 313 1.8 cgd { 314 1.8 cgd 315 1.8 cgd /* XXX XXX XXX XXX XXX XXX */ 316 1.37 christos panic("%s: unimplemented", __func__); 317 1.8 cgd } 318 1.8 cgd 319 1.39 thorpej static void 320 1.29 dsl tc_mem_free(void *v, bus_space_handle_t bsh, bus_size_t size) 321 1.8 cgd { 322 1.8 cgd 323 1.8 cgd /* XXX XXX XXX XXX XXX XXX */ 324 1.37 christos panic("%s: unimplemented", __func__); 325 1.22 drochner } 326 1.22 drochner 327 1.39 thorpej static void * 328 1.29 dsl tc_mem_vaddr(void *v, bus_space_handle_t bsh) 329 1.22 drochner { 330 1.22 drochner #ifdef DIAGNOSTIC 331 1.22 drochner if ((bsh & TC_SPACE_SPARSE) != 0) { 332 1.22 drochner /* 333 1.22 drochner * tc_mem_map() catches linear && !cacheable, 334 1.22 drochner * so we shouldn't come here 335 1.22 drochner */ 336 1.37 christos panic("%s: can't do sparse", __func__); 337 1.22 drochner } 338 1.22 drochner #endif 339 1.22 drochner return ((void *)bsh); 340 1.25 thorpej } 341 1.25 thorpej 342 1.39 thorpej static paddr_t 343 1.29 dsl tc_mem_mmap(void *v, bus_addr_t addr, off_t off, int prot, int flags) 344 1.25 thorpej { 345 1.25 thorpej int linear = flags & BUS_SPACE_MAP_LINEAR; 346 1.25 thorpej bus_addr_t rv; 347 1.25 thorpej 348 1.25 thorpej if (linear) 349 1.25 thorpej rv = addr + off; 350 1.25 thorpej else 351 1.25 thorpej rv = TC_DENSE_TO_SPARSE(addr + off); 352 1.25 thorpej 353 1.25 thorpej return (alpha_btop(rv)); 354 1.8 cgd } 355 1.8 cgd 356 1.33 chs static inline void 357 1.30 dsl tc_mem_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int f) 358 1.12 cgd { 359 1.12 cgd 360 1.16 cgd if ((f & BUS_SPACE_BARRIER_READ) != 0) 361 1.12 cgd alpha_mb(); 362 1.16 cgd else if ((f & BUS_SPACE_BARRIER_WRITE) != 0) 363 1.12 cgd alpha_wmb(); 364 1.12 cgd } 365 1.12 cgd 366 1.36 christos /* 367 1.36 christos * https://web-docs.gsi.de/~kraemer/COLLECTION/DEC/d3syspmb.pdf 368 1.36 christos * http://h20565.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c04623255 369 1.36 christos */ 370 1.36 christos #define TC_SPARSE_PTR(memh, off) \ 371 1.37 christos ((void *)((memh) + ((off & ((bus_size_t)-1 << 2)) << 1))) 372 1.36 christos 373 1.34 matt static inline uint8_t 374 1.29 dsl tc_mem_read_1(void *v, bus_space_handle_t memh, bus_size_t off) 375 1.1 cgd { 376 1.1 cgd 377 1.8 cgd alpha_mb(); /* XXX XXX XXX */ 378 1.2 cgd 379 1.36 christos if ((memh & TC_SPACE_SPARSE) != 0) { 380 1.36 christos volatile uint32_t *p; 381 1.36 christos 382 1.36 christos p = TC_SPARSE_PTR(memh, off); 383 1.37 christos return ((*p >> ((off & 3) << 3)) & 0xff); 384 1.36 christos } else { 385 1.36 christos volatile uint8_t *p; 386 1.1 cgd 387 1.36 christos p = (uint8_t *)(memh + off); 388 1.36 christos return (*p); 389 1.36 christos } 390 1.1 cgd } 391 1.1 cgd 392 1.34 matt static inline uint16_t 393 1.29 dsl tc_mem_read_2(void *v, bus_space_handle_t memh, bus_size_t off) 394 1.1 cgd { 395 1.1 cgd 396 1.8 cgd alpha_mb(); /* XXX XXX XXX */ 397 1.2 cgd 398 1.36 christos if ((memh & TC_SPACE_SPARSE) != 0) { 399 1.36 christos volatile uint32_t *p; 400 1.36 christos 401 1.36 christos p = TC_SPARSE_PTR(memh, off); 402 1.37 christos return ((*p >> ((off & 2) << 3)) & 0xffff); 403 1.36 christos } else { 404 1.36 christos volatile uint16_t *p; 405 1.1 cgd 406 1.36 christos p = (uint16_t *)(memh + off); 407 1.36 christos return (*p); 408 1.36 christos } 409 1.1 cgd } 410 1.1 cgd 411 1.34 matt static inline uint32_t 412 1.29 dsl tc_mem_read_4(void *v, bus_space_handle_t memh, bus_size_t off) 413 1.1 cgd { 414 1.34 matt volatile uint32_t *p; 415 1.1 cgd 416 1.8 cgd alpha_mb(); /* XXX XXX XXX */ 417 1.2 cgd 418 1.1 cgd if ((memh & TC_SPACE_SPARSE) != 0) 419 1.1 cgd /* Nothing special to do for 4-byte sparse space accesses */ 420 1.34 matt p = (uint32_t *)(memh + (off << 1)); 421 1.1 cgd else 422 1.37 christos /* 423 1.37 christos * LDL to a dense space address always results in two 424 1.37 christos * TURBOchannel I/O read transactions to consecutive longword 425 1.37 christos * addresses. Use caution in dense space if the option has 426 1.37 christos * registers with read side effects. 427 1.37 christos */ 428 1.34 matt p = (uint32_t *)(memh + off); 429 1.1 cgd return (*p); 430 1.1 cgd } 431 1.1 cgd 432 1.34 matt static inline uint64_t 433 1.29 dsl tc_mem_read_8(void *v, bus_space_handle_t memh, bus_size_t off) 434 1.1 cgd { 435 1.34 matt volatile uint64_t *p; 436 1.1 cgd 437 1.8 cgd alpha_mb(); /* XXX XXX XXX */ 438 1.2 cgd 439 1.1 cgd if ((memh & TC_SPACE_SPARSE) != 0) 440 1.37 christos panic("%s: not implemented for sparse space", __func__); 441 1.1 cgd 442 1.34 matt p = (uint64_t *)(memh + off); 443 1.1 cgd return (*p); 444 1.1 cgd } 445 1.1 cgd 446 1.8 cgd #define tc_mem_read_multi_N(BYTES,TYPE) \ 447 1.39 thorpej static void \ 448 1.34 matt __C(tc_mem_read_multi_,BYTES)( \ 449 1.34 matt void *v, \ 450 1.34 matt bus_space_handle_t h, \ 451 1.34 matt bus_size_t o, \ 452 1.34 matt TYPE *a, \ 453 1.34 matt bus_size_t c) \ 454 1.8 cgd { \ 455 1.8 cgd \ 456 1.8 cgd while (c-- > 0) { \ 457 1.16 cgd tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_READ); \ 458 1.16 cgd *a++ = __C(tc_mem_read_,BYTES)(v, h, o); \ 459 1.8 cgd } \ 460 1.8 cgd } 461 1.34 matt tc_mem_read_multi_N(1,uint8_t) 462 1.34 matt tc_mem_read_multi_N(2,uint16_t) 463 1.34 matt tc_mem_read_multi_N(4,uint32_t) 464 1.34 matt tc_mem_read_multi_N(8,uint64_t) 465 1.8 cgd 466 1.8 cgd #define tc_mem_read_region_N(BYTES,TYPE) \ 467 1.39 thorpej static void \ 468 1.34 matt __C(tc_mem_read_region_,BYTES)( \ 469 1.34 matt void *v, \ 470 1.34 matt bus_space_handle_t h, \ 471 1.34 matt bus_size_t o, \ 472 1.34 matt TYPE *a, \ 473 1.34 matt bus_size_t c) \ 474 1.8 cgd { \ 475 1.8 cgd \ 476 1.8 cgd while (c-- > 0) { \ 477 1.16 cgd *a++ = __C(tc_mem_read_,BYTES)(v, h, o); \ 478 1.9 cgd o += sizeof *a; \ 479 1.8 cgd } \ 480 1.8 cgd } 481 1.34 matt tc_mem_read_region_N(1,uint8_t) 482 1.34 matt tc_mem_read_region_N(2,uint16_t) 483 1.34 matt tc_mem_read_region_N(4,uint32_t) 484 1.34 matt tc_mem_read_region_N(8,uint64_t) 485 1.8 cgd 486 1.37 christos #define TC_SPARSE_WR_PVAL(msk, b, v) \ 487 1.37 christos ((UINT64_C(msk) << (32 + (b))) | ((uint64_t)(v) << ((b) << 3))) 488 1.37 christos 489 1.33 chs static inline void 490 1.34 matt tc_mem_write_1(void *v, bus_space_handle_t memh, bus_size_t off, uint8_t val) 491 1.1 cgd { 492 1.1 cgd 493 1.1 cgd if ((memh & TC_SPACE_SPARSE) != 0) { 494 1.35 christos volatile uint64_t *p; 495 1.1 cgd 496 1.36 christos p = TC_SPARSE_PTR(memh, off); 497 1.37 christos *p = TC_SPARSE_WR_PVAL(0x1, off & 3, val); 498 1.36 christos } else 499 1.37 christos panic("%s: not implemented for dense space", __func__); 500 1.1 cgd 501 1.34 matt alpha_mb(); /* XXX XXX XXX */ 502 1.1 cgd } 503 1.1 cgd 504 1.33 chs static inline void 505 1.34 matt tc_mem_write_2(void *v, bus_space_handle_t memh, bus_size_t off, uint16_t val) 506 1.1 cgd { 507 1.1 cgd 508 1.1 cgd if ((memh & TC_SPACE_SPARSE) != 0) { 509 1.35 christos volatile uint64_t *p; 510 1.1 cgd 511 1.36 christos p = TC_SPARSE_PTR(memh, off); 512 1.37 christos *p = TC_SPARSE_WR_PVAL(0x3, off & 2, val); 513 1.36 christos } else 514 1.37 christos panic("%s: not implemented for dense space", __func__); 515 1.1 cgd 516 1.34 matt alpha_mb(); /* XXX XXX XXX */ 517 1.1 cgd } 518 1.1 cgd 519 1.33 chs static inline void 520 1.34 matt tc_mem_write_4(void *v, bus_space_handle_t memh, bus_size_t off, uint32_t val) 521 1.1 cgd { 522 1.34 matt volatile uint32_t *p; 523 1.1 cgd 524 1.1 cgd if ((memh & TC_SPACE_SPARSE) != 0) 525 1.1 cgd /* Nothing special to do for 4-byte sparse space accesses */ 526 1.34 matt p = (uint32_t *)(memh + (off << 1)); 527 1.1 cgd else 528 1.34 matt p = (uint32_t *)(memh + off); 529 1.1 cgd *p = val; 530 1.36 christos 531 1.34 matt alpha_mb(); /* XXX XXX XXX */ 532 1.1 cgd } 533 1.1 cgd 534 1.33 chs static inline void 535 1.34 matt tc_mem_write_8(void *v, bus_space_handle_t memh, bus_size_t off, uint64_t val) 536 1.1 cgd { 537 1.34 matt volatile uint64_t *p; 538 1.1 cgd 539 1.1 cgd if ((memh & TC_SPACE_SPARSE) != 0) 540 1.37 christos panic("%s: not implemented for sparse space", __func__); 541 1.1 cgd 542 1.34 matt p = (uint64_t *)(memh + off); 543 1.1 cgd *p = val; 544 1.36 christos 545 1.34 matt alpha_mb(); /* XXX XXX XXX */ 546 1.3 cgd } 547 1.10 cgd 548 1.8 cgd #define tc_mem_write_multi_N(BYTES,TYPE) \ 549 1.39 thorpej static void \ 550 1.34 matt __C(tc_mem_write_multi_,BYTES)( \ 551 1.34 matt void *v, \ 552 1.34 matt bus_space_handle_t h, \ 553 1.34 matt bus_size_t o, \ 554 1.34 matt const TYPE *a, \ 555 1.34 matt bus_size_t c) \ 556 1.8 cgd { \ 557 1.8 cgd \ 558 1.8 cgd while (c-- > 0) { \ 559 1.16 cgd __C(tc_mem_write_,BYTES)(v, h, o, *a++); \ 560 1.16 cgd tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_WRITE); \ 561 1.8 cgd } \ 562 1.8 cgd } 563 1.34 matt tc_mem_write_multi_N(1,uint8_t) 564 1.34 matt tc_mem_write_multi_N(2,uint16_t) 565 1.34 matt tc_mem_write_multi_N(4,uint32_t) 566 1.34 matt tc_mem_write_multi_N(8,uint64_t) 567 1.8 cgd 568 1.8 cgd #define tc_mem_write_region_N(BYTES,TYPE) \ 569 1.39 thorpej static void \ 570 1.34 matt __C(tc_mem_write_region_,BYTES)( \ 571 1.34 matt void *v, \ 572 1.34 matt bus_space_handle_t h, \ 573 1.34 matt bus_size_t o, \ 574 1.34 matt const TYPE *a, \ 575 1.34 matt bus_size_t c) \ 576 1.8 cgd { \ 577 1.8 cgd \ 578 1.8 cgd while (c-- > 0) { \ 579 1.16 cgd __C(tc_mem_write_,BYTES)(v, h, o, *a++); \ 580 1.9 cgd o += sizeof *a; \ 581 1.8 cgd } \ 582 1.8 cgd } 583 1.34 matt tc_mem_write_region_N(1,uint8_t) 584 1.34 matt tc_mem_write_region_N(2,uint16_t) 585 1.34 matt tc_mem_write_region_N(4,uint32_t) 586 1.34 matt tc_mem_write_region_N(8,uint64_t) 587 1.11 cgd 588 1.11 cgd #define tc_mem_set_multi_N(BYTES,TYPE) \ 589 1.39 thorpej static void \ 590 1.34 matt __C(tc_mem_set_multi_,BYTES)( \ 591 1.34 matt void *v, \ 592 1.34 matt bus_space_handle_t h, \ 593 1.34 matt bus_size_t o, \ 594 1.34 matt TYPE val, \ 595 1.34 matt bus_size_t c) \ 596 1.11 cgd { \ 597 1.11 cgd \ 598 1.11 cgd while (c-- > 0) { \ 599 1.16 cgd __C(tc_mem_write_,BYTES)(v, h, o, val); \ 600 1.16 cgd tc_mem_barrier(v, h, o, sizeof val, BUS_SPACE_BARRIER_WRITE); \ 601 1.11 cgd } \ 602 1.11 cgd } 603 1.34 matt tc_mem_set_multi_N(1,uint8_t) 604 1.34 matt tc_mem_set_multi_N(2,uint16_t) 605 1.34 matt tc_mem_set_multi_N(4,uint32_t) 606 1.34 matt tc_mem_set_multi_N(8,uint64_t) 607 1.11 cgd 608 1.11 cgd #define tc_mem_set_region_N(BYTES,TYPE) \ 609 1.39 thorpej static void \ 610 1.34 matt __C(tc_mem_set_region_,BYTES)( \ 611 1.34 matt void *v, \ 612 1.34 matt bus_space_handle_t h, \ 613 1.34 matt bus_size_t o, \ 614 1.34 matt TYPE val, \ 615 1.34 matt bus_size_t c) \ 616 1.11 cgd { \ 617 1.11 cgd \ 618 1.11 cgd while (c-- > 0) { \ 619 1.16 cgd __C(tc_mem_write_,BYTES)(v, h, o, val); \ 620 1.11 cgd o += sizeof val; \ 621 1.11 cgd } \ 622 1.11 cgd } 623 1.34 matt tc_mem_set_region_N(1,uint8_t) 624 1.34 matt tc_mem_set_region_N(2,uint16_t) 625 1.34 matt tc_mem_set_region_N(4,uint32_t) 626 1.34 matt tc_mem_set_region_N(8,uint64_t) 627 1.13 cgd 628 1.16 cgd #define tc_mem_copy_region_N(BYTES) \ 629 1.39 thorpej static void \ 630 1.34 matt __C(tc_mem_copy_region_,BYTES)( \ 631 1.34 matt void *v, \ 632 1.34 matt bus_space_handle_t h1, \ 633 1.34 matt bus_size_t o1, \ 634 1.34 matt bus_space_handle_t h2, \ 635 1.34 matt bus_size_t o2, \ 636 1.34 matt bus_size_t c) \ 637 1.13 cgd { \ 638 1.16 cgd bus_size_t o; \ 639 1.13 cgd \ 640 1.13 cgd if ((h1 & TC_SPACE_SPARSE) != 0 && \ 641 1.13 cgd (h2 & TC_SPACE_SPARSE) != 0) { \ 642 1.19 perry memmove((void *)(h2 + o2), (void *)(h1 + o1), c * BYTES); \ 643 1.13 cgd return; \ 644 1.13 cgd } \ 645 1.13 cgd \ 646 1.16 cgd if (h1 + o1 >= h2 + o2) \ 647 1.16 cgd /* src after dest: copy forward */ \ 648 1.16 cgd for (o = 0; c > 0; c--, o += BYTES) \ 649 1.16 cgd __C(tc_mem_write_,BYTES)(v, h2, o2 + o, \ 650 1.16 cgd __C(tc_mem_read_,BYTES)(v, h1, o1 + o)); \ 651 1.16 cgd else \ 652 1.16 cgd /* dest after src: copy backwards */ \ 653 1.16 cgd for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES) \ 654 1.16 cgd __C(tc_mem_write_,BYTES)(v, h2, o2 + o, \ 655 1.16 cgd __C(tc_mem_read_,BYTES)(v, h1, o1 + o)); \ 656 1.16 cgd } 657 1.16 cgd tc_mem_copy_region_N(1) 658 1.16 cgd tc_mem_copy_region_N(2) 659 1.16 cgd tc_mem_copy_region_N(4) 660 1.16 cgd tc_mem_copy_region_N(8) 661