1 /* $NetBSD: au_himem_space.c,v 1.14 2012/01/27 18:52:57 para Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Itronix Inc. 5 * All rights reserved. 6 * 7 * Written by Garrett D'Amore for Itronix Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of Itronix Inc. may not be used to endorse 18 * or promote products derived from this software without specific 19 * prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /* 34 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. 35 * All rights reserved. 36 * 37 * This code is derived from software contributed to The NetBSD Foundation 38 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 39 * Simulation Facility, NASA Ames Research Center. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 51 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 52 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 54 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 60 * POSSIBILITY OF SUCH DAMAGE. 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: au_himem_space.c,v 1.14 2012/01/27 18:52:57 para Exp $"); 65 66 /* 67 * This provides mappings for the upper I/O regions used on some 68 * Alchemy parts, e.g. PCI, PCMCIA, and LCD. The mappings do not use 69 * wired TLB entries, but instead rely on wiring entries in the kernel 70 * pmap. 71 */ 72 73 #include <sys/param.h> 74 #include <sys/systm.h> 75 #include <sys/extent.h> 76 #include <sys/malloc.h> 77 #include <sys/endian.h> 78 #include <uvm/uvm.h> 79 80 #include <sys/bus.h> 81 #include <mips/locore.h> 82 #include <mips/alchemy/include/au_himem_space.h> 83 84 #define TRUNC_PAGE(x) ((x) & ~(PAGE_SIZE - 1)) 85 #define ROUND_PAGE(x) TRUNC_PAGE((x) + (PAGE_SIZE - 1)) 86 87 typedef struct au_himem_cookie { 88 const char *c_name; 89 bus_addr_t c_start; 90 bus_addr_t c_end; 91 paddr_t c_physoff; 92 int c_flags; 93 int c_swswap; 94 bool c_hwswap; 95 struct extent *c_extent; 96 } au_himem_cookie_t; 97 98 int au_himem_map(void *, bus_addr_t, bus_size_t, int, 99 bus_space_handle_t *, int); 100 void au_himem_unmap(void *, bus_space_handle_t, bus_size_t, int); 101 void *au_himem_vaddr(void *, bus_space_handle_t); 102 int au_himem_subregion(void *, bus_space_handle_t, bus_size_t, bus_size_t, 103 bus_space_handle_t *); 104 paddr_t au_himem_mmap(void *, bus_addr_t, off_t, int, int); 105 int au_himem_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t, 106 bus_size_t, int, bus_addr_t *, bus_space_handle_t *); 107 void au_himem_free(void *, bus_space_handle_t, bus_size_t); 108 void au_himem_barrier(void *, bus_space_handle_t, bus_size_t, bus_size_t, int); 109 uint8_t au_himem_r_1(void *, bus_space_handle_t, bus_size_t); 110 uint16_t au_himem_r_2(void *, bus_space_handle_t, bus_size_t); 111 uint32_t au_himem_r_4(void *, bus_space_handle_t, bus_size_t); 112 uint64_t au_himem_r_8(void *, bus_space_handle_t, bus_size_t); 113 void au_himem_rm_1(void *, bus_space_handle_t, bus_size_t, uint8_t *, 114 bus_size_t); 115 void au_himem_rm_2(void *, bus_space_handle_t, bus_size_t, uint16_t *, 116 bus_size_t); 117 void au_himem_rm_4(void *, bus_space_handle_t, bus_size_t, uint32_t *, 118 bus_size_t); 119 void au_himem_rm_8(void *, bus_space_handle_t, bus_size_t, uint64_t *, 120 bus_size_t); 121 void au_himem_rr_1(void *, bus_space_handle_t, bus_size_t, uint8_t *, 122 bus_size_t); 123 void au_himem_rr_2(void *, bus_space_handle_t, bus_size_t, uint16_t *, 124 bus_size_t); 125 void au_himem_rr_4(void *, bus_space_handle_t, bus_size_t, uint32_t *, 126 bus_size_t); 127 void au_himem_rr_8(void *, bus_space_handle_t, bus_size_t, uint64_t *, 128 bus_size_t); 129 void au_himem_w_1(void *, bus_space_handle_t, bus_size_t, uint8_t); 130 void au_himem_w_2(void *, bus_space_handle_t, bus_size_t, uint16_t); 131 void au_himem_w_4(void *, bus_space_handle_t, bus_size_t, uint32_t); 132 void au_himem_w_8(void *, bus_space_handle_t, bus_size_t, uint64_t); 133 void au_himem_wm_1(void *, bus_space_handle_t, bus_size_t, const uint8_t *, 134 bus_size_t); 135 void au_himem_wm_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *, 136 bus_size_t); 137 void au_himem_wm_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *, 138 bus_size_t); 139 void au_himem_wm_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *, 140 bus_size_t); 141 void au_himem_wr_1(void *, bus_space_handle_t, bus_size_t, const uint8_t *, 142 bus_size_t); 143 void au_himem_wr_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *, 144 bus_size_t); 145 void au_himem_wr_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *, 146 bus_size_t); 147 void au_himem_wr_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *, 148 bus_size_t); 149 void au_himem_sm_1(void *, bus_space_handle_t, bus_size_t, uint8_t, 150 bus_size_t); 151 void au_himem_sm_2(void *, bus_space_handle_t, bus_size_t, uint16_t, 152 bus_size_t); 153 void au_himem_sm_4(void *, bus_space_handle_t, bus_size_t, uint32_t, 154 bus_size_t); 155 void au_himem_sm_8(void *, bus_space_handle_t, bus_size_t, uint64_t, 156 bus_size_t); 157 void au_himem_sr_1(void *, bus_space_handle_t, bus_size_t, uint8_t, 158 bus_size_t); 159 void au_himem_sr_2(void *, bus_space_handle_t, bus_size_t, uint16_t, 160 bus_size_t); 161 void au_himem_sr_4(void *, bus_space_handle_t, bus_size_t, uint32_t, 162 bus_size_t); 163 void au_himem_sr_8(void *, bus_space_handle_t, bus_size_t, uint64_t, 164 bus_size_t); 165 void au_himem_c_1(void *, bus_space_handle_t, bus_size_t, 166 bus_space_handle_t, bus_size_t, bus_size_t); 167 void au_himem_c_2(void *, bus_space_handle_t, bus_size_t, 168 bus_space_handle_t, bus_size_t, bus_size_t); 169 void au_himem_c_4(void *, bus_space_handle_t, bus_size_t, 170 bus_space_handle_t, bus_size_t, bus_size_t); 171 void au_himem_c_8(void *, bus_space_handle_t, bus_size_t, 172 bus_space_handle_t, bus_size_t, bus_size_t); 173 uint16_t au_himem_rs_2(void *, bus_space_handle_t, bus_size_t); 174 uint32_t au_himem_rs_4(void *, bus_space_handle_t, bus_size_t); 175 uint64_t au_himem_rs_8(void *, bus_space_handle_t, bus_size_t); 176 void au_himem_ws_2(void *, bus_space_handle_t, bus_size_t, uint16_t); 177 void au_himem_ws_4(void *, bus_space_handle_t, bus_size_t, uint32_t); 178 void au_himem_ws_8(void *, bus_space_handle_t, bus_size_t, uint64_t); 179 void au_himem_rms_2(void *, bus_space_handle_t, bus_size_t, uint16_t *, 180 bus_size_t); 181 void au_himem_rms_4(void *, bus_space_handle_t, bus_size_t, uint32_t *, 182 bus_size_t); 183 void au_himem_rms_8(void *, bus_space_handle_t, bus_size_t, uint64_t *, 184 bus_size_t); 185 void au_himem_rrs_2(void *, bus_space_handle_t, bus_size_t, uint16_t *, 186 bus_size_t); 187 void au_himem_rrs_4(void *, bus_space_handle_t, bus_size_t, uint32_t *, 188 bus_size_t); 189 void au_himem_rrs_8(void *, bus_space_handle_t, bus_size_t, uint64_t *, 190 bus_size_t); 191 void au_himem_wms_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *, 192 bus_size_t); 193 void au_himem_wms_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *, 194 bus_size_t); 195 void au_himem_wms_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *, 196 bus_size_t); 197 void au_himem_wrs_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *, 198 bus_size_t); 199 void au_himem_wrs_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *, 200 bus_size_t); 201 void au_himem_wrs_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *, 202 bus_size_t); 203 204 int 205 au_himem_map(void *cookie, bus_addr_t addr, bus_size_t size, 206 int flags, bus_space_handle_t *bshp, int acct) 207 { 208 au_himem_cookie_t *c = (au_himem_cookie_t *)cookie; 209 int err; 210 paddr_t pa; 211 vaddr_t va; 212 vsize_t realsz; 213 int s; 214 215 /* make sure we can map this bus address */ 216 if (addr < c->c_start || (addr + size) > c->c_end) { 217 return EINVAL; 218 } 219 220 /* physical address, page aligned */ 221 pa = TRUNC_PAGE(c->c_physoff + addr); 222 223 /* 224 * we are only going to work with whole pages. the 225 * calculation is the offset into the first page, plus the 226 * intended size, rounded up to a whole number of pages. 227 */ 228 realsz = ROUND_PAGE((addr & PAGE_MASK) + size); 229 230 va = uvm_km_alloc(kernel_map, 231 realsz, PAGE_SIZE, UVM_KMF_VAONLY | UVM_KMF_NOWAIT); 232 if (va == 0) { 233 return ENOMEM; 234 } 235 236 /* virtual address in handle (offset appropriately) */ 237 *bshp = va + (addr & PAGE_MASK); 238 239 /* map the pages in the kernel pmap */ 240 s = splhigh(); 241 while (realsz) { 242 pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0); 243 pa += PAGE_SIZE; 244 va += PAGE_SIZE; 245 realsz -= PAGE_SIZE; 246 } 247 pmap_update(pmap_kernel()); 248 splx(s); 249 250 /* record our allocated range of bus addresses */ 251 if (acct && c->c_extent != NULL) { 252 err = extent_alloc_region(c->c_extent, addr, size, EX_NOWAIT); 253 if (err) { 254 au_himem_unmap(cookie, *bshp, size, 0); 255 return err; 256 } 257 } 258 259 return 0; 260 } 261 262 void 263 au_himem_unmap(void *cookie, bus_space_handle_t bsh, bus_size_t size, int acct) 264 { 265 au_himem_cookie_t *c = (au_himem_cookie_t *)cookie; 266 vaddr_t va; 267 vsize_t realsz; 268 paddr_t pa; 269 int s; 270 271 va = (vaddr_t)TRUNC_PAGE(bsh); 272 realsz = (vsize_t)ROUND_PAGE((bsh & PAGE_MASK) + size); 273 274 s = splhigh(); 275 276 /* make sure that any pending writes are flushed */ 277 wbflush(); 278 279 /* 280 * we have to get the bus address, so that we can free it in the 281 * extent manager. this is the unfortunate thing about using 282 * virtual memory instead of just a 1:1 mapping scheme. 283 */ 284 if (pmap_extract(pmap_kernel(), va, &pa) == false) 285 panic("au_himem_unmap: virtual address invalid!"); 286 287 /* now remove it from the pmap */ 288 pmap_kremove(va, realsz); 289 pmap_update(pmap_kernel()); 290 splx(s); 291 292 /* finally we can release both virtual and bus address ranges */ 293 uvm_km_free(kernel_map, va, realsz, UVM_KMF_VAONLY); 294 295 if (acct) { 296 bus_addr_t addr; 297 addr = ((pa - c->c_physoff) + (bsh & PAGE_MASK)); 298 extent_free(c->c_extent, addr, size, EX_NOWAIT); 299 } 300 } 301 302 int 303 au_himem_subregion(void *cookie, bus_space_handle_t bsh, 304 bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) 305 { 306 307 *nbshp = bsh + offset; 308 return 0; 309 } 310 311 void * 312 au_himem_vaddr(void *cookie, bus_space_handle_t bsh) 313 { 314 315 return ((void *)bsh); 316 } 317 318 paddr_t 319 au_himem_mmap(void *cookie, bus_addr_t addr, off_t off, int prot, int flags) 320 { 321 au_himem_cookie_t *c = (au_himem_cookie_t *)cookie; 322 323 /* I/O spaces should not be directly mmap'ed */ 324 if (c->c_flags & AU_HIMEM_SPACE_IO) 325 return -1; 326 327 if (addr < c->c_start || (addr + off) >= c->c_end) 328 return -1; 329 330 return mips_btop(c->c_physoff + addr + off); 331 } 332 333 int 334 au_himem_alloc(void *cookie, bus_addr_t start, bus_addr_t end, 335 bus_size_t size, bus_size_t align, bus_size_t boundary, int flags, 336 bus_addr_t *addrp, bus_space_handle_t *bshp) 337 { 338 au_himem_cookie_t *c = (au_himem_cookie_t *)cookie; 339 int err; 340 u_long addr; 341 342 err = extent_alloc_subregion(c->c_extent, start, end, size, 343 align, boundary, EX_FAST | EX_NOWAIT, &addr); 344 if (err) { 345 return err; 346 } 347 err = au_himem_map(cookie, addr, size, flags, bshp, 0); 348 if (err) 349 extent_free(c->c_extent, addr, size, EX_NOWAIT); 350 *addrp = addr; 351 return err; 352 } 353 354 void 355 au_himem_free(void *cookie, bus_space_handle_t bsh, bus_size_t size) 356 { 357 358 /* unmap takes care of it all */ 359 au_himem_unmap(cookie, bsh, size, 1); 360 } 361 362 inline void 363 au_himem_barrier(void *cookie, bus_space_handle_t bsh, bus_size_t o, 364 bus_size_t l, int f) 365 { 366 367 if (f & BUS_SPACE_BARRIER_WRITE) 368 wbflush(); 369 } 370 371 inline uint8_t 372 au_himem_r_1(void *v, bus_space_handle_t h, bus_size_t o) 373 { 374 wbflush(); 375 return (*(volatile uint8_t *)(intptr_t)(h + o)); 376 } 377 378 inline uint16_t 379 au_himem_r_2(void *v, bus_space_handle_t h, bus_size_t o) 380 { 381 uint16_t val; 382 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 383 384 wbflush(); 385 val = (*(volatile uint16_t *)(intptr_t)(h + o)); 386 return (c->c_swswap ? bswap16(val) : val); 387 } 388 389 inline uint32_t 390 au_himem_r_4(void *v, bus_space_handle_t h, bus_size_t o) 391 { 392 uint32_t val; 393 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 394 395 wbflush(); 396 val = (*(volatile uint32_t *)(intptr_t)(h + o)); 397 return (c->c_swswap ? bswap32(val) : val); 398 } 399 400 inline uint64_t 401 au_himem_r_8(void *v, bus_space_handle_t h, bus_size_t o) 402 { 403 uint64_t val; 404 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 405 406 wbflush(); 407 val = (*(volatile uint64_t *)(intptr_t)(h + o)); 408 return (c->c_swswap ? bswap64(val) : val); 409 } 410 411 inline void 412 au_himem_w_1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t val) 413 { 414 415 *(volatile uint8_t *)(intptr_t)(h + o) = val; 416 wbflush(); 417 } 418 419 inline void 420 au_himem_w_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t val) 421 { 422 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 423 424 *(volatile uint16_t *)(intptr_t)(h + o) = c->c_swswap ? bswap16(val) : val; 425 wbflush(); 426 } 427 428 inline void 429 au_himem_w_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t val) 430 { 431 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 432 433 *(volatile uint32_t *)(intptr_t)(h + o) = c->c_swswap ? bswap32(val) : val; 434 wbflush(); 435 } 436 437 inline void 438 au_himem_w_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t val) 439 { 440 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 441 442 *(volatile uint64_t *)(intptr_t)(h + o) = c->c_swswap ? bswap64(val) : val; 443 wbflush(); 444 } 445 446 inline uint16_t 447 au_himem_rs_2(void *v, bus_space_handle_t h, bus_size_t o) 448 { 449 uint16_t val; 450 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 451 452 wbflush(); 453 val = (*(volatile uint16_t *)(intptr_t)(h + o)); 454 return (c->c_hwswap ? bswap16(val) : val); 455 } 456 457 inline uint32_t 458 au_himem_rs_4(void *v, bus_space_handle_t h, bus_size_t o) 459 { 460 uint32_t val; 461 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 462 463 wbflush(); 464 val = (*(volatile uint32_t *)(intptr_t)(h + o)); 465 return (c->c_hwswap ? bswap32(val) : val); 466 } 467 468 inline uint64_t 469 au_himem_rs_8(void *v, bus_space_handle_t h, bus_size_t o) 470 { 471 uint64_t val; 472 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 473 474 wbflush(); 475 val = (*(volatile uint64_t *)(intptr_t)(h + o)); 476 return (c->c_hwswap ? bswap64(val) : val); 477 } 478 479 inline void 480 au_himem_ws_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t val) 481 { 482 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 483 484 *(volatile uint16_t *)(intptr_t)(h + o) = c->c_hwswap ? bswap16(val) : val; 485 wbflush(); 486 } 487 488 inline void 489 au_himem_ws_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t val) 490 { 491 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 492 493 *(volatile uint32_t *)(intptr_t)(h + o) = c->c_hwswap ? bswap32(val) : val; 494 wbflush(); 495 } 496 497 inline void 498 au_himem_ws_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t val) 499 { 500 au_himem_cookie_t *c = (au_himem_cookie_t *)v; 501 502 *(volatile uint64_t *)(intptr_t)(h + o) = c->c_hwswap ? bswap64(val) : val; 503 wbflush(); 504 } 505 506 #define AU_HIMEM_RM(TYPE,BYTES) \ 507 void \ 508 __CONCAT(au_himem_rm_,BYTES)(void *v, \ 509 bus_space_handle_t h, bus_size_t o, TYPE *dst, bus_size_t cnt) \ 510 { \ 511 \ 512 while (cnt-- > 0) \ 513 *dst ++ = __CONCAT(au_himem_r_,BYTES)(v, h, o); \ 514 } 515 AU_HIMEM_RM(uint8_t,1) 516 AU_HIMEM_RM(uint16_t,2) 517 AU_HIMEM_RM(uint32_t,4) 518 AU_HIMEM_RM(uint64_t,8) 519 520 #define AU_HIMEM_RMS(TYPE,BYTES) \ 521 void \ 522 __CONCAT(au_himem_rms_,BYTES)(void *v, \ 523 bus_space_handle_t h, bus_size_t o, TYPE *dst, bus_size_t cnt) \ 524 { \ 525 \ 526 while (cnt-- > 0) { \ 527 *dst++ = __CONCAT(au_himem_rs_,BYTES)(v, h, o); \ 528 } \ 529 } 530 AU_HIMEM_RMS(uint16_t,2) 531 AU_HIMEM_RMS(uint32_t,4) 532 AU_HIMEM_RMS(uint64_t,8) 533 534 #define AU_HIMEM_RR(TYPE,BYTES) \ 535 void \ 536 __CONCAT(au_himem_rr_,BYTES)(void *v, \ 537 bus_space_handle_t h, bus_size_t o, TYPE *dst, bus_size_t cnt) \ 538 { \ 539 \ 540 while (cnt-- > 0) { \ 541 *dst++ = __CONCAT(au_himem_r_,BYTES)(v, h, o); \ 542 o += BYTES; \ 543 } \ 544 } 545 AU_HIMEM_RR(uint8_t,1) 546 AU_HIMEM_RR(uint16_t,2) 547 AU_HIMEM_RR(uint32_t,4) 548 AU_HIMEM_RR(uint64_t,8) 549 550 #define AU_HIMEM_RRS(TYPE,BYTES) \ 551 void \ 552 __CONCAT(au_himem_rrs_,BYTES)(void *v, \ 553 bus_space_handle_t h, bus_size_t o, TYPE *dst, bus_size_t cnt) \ 554 { \ 555 \ 556 while (cnt-- > 0) { \ 557 *dst++ = __CONCAT(au_himem_rs_,BYTES)(v, h, o); \ 558 o += BYTES; \ 559 } \ 560 } 561 AU_HIMEM_RRS(uint16_t,2) 562 AU_HIMEM_RRS(uint32_t,4) 563 AU_HIMEM_RRS(uint64_t,8) 564 565 #define AU_HIMEM_WM(TYPE,BYTES) \ 566 void \ 567 __CONCAT(au_himem_wm_,BYTES)(void *v, \ 568 bus_space_handle_t h, bus_size_t o, const TYPE *src, \ 569 bus_size_t cnt) \ 570 { \ 571 \ 572 while (cnt-- > 0) { \ 573 __CONCAT(au_himem_w_,BYTES)(v, h, o, *src++); \ 574 } \ 575 } 576 AU_HIMEM_WM(uint8_t,1) 577 AU_HIMEM_WM(uint16_t,2) 578 AU_HIMEM_WM(uint32_t,4) 579 AU_HIMEM_WM(uint64_t,8) 580 581 #define AU_HIMEM_WMS(TYPE,BYTES) \ 582 void \ 583 __CONCAT(au_himem_wms_,BYTES)(void *v, \ 584 bus_space_handle_t h, bus_size_t o, const TYPE *src, \ 585 bus_size_t cnt) \ 586 { \ 587 \ 588 while (cnt-- > 0) { \ 589 __CONCAT(au_himem_ws_,BYTES)(v, h, o, *src++); \ 590 } \ 591 } 592 AU_HIMEM_WMS(uint16_t,2) 593 AU_HIMEM_WMS(uint32_t,4) 594 AU_HIMEM_WMS(uint64_t,8) 595 596 #define AU_HIMEM_WR(TYPE,BYTES) \ 597 void \ 598 __CONCAT(au_himem_wr_,BYTES)(void *v, \ 599 bus_space_handle_t h, bus_size_t o, const TYPE *src, \ 600 bus_size_t cnt) \ 601 { \ 602 \ 603 while (cnt-- > 0) { \ 604 __CONCAT(au_himem_w_,BYTES)(v, h, o, *src++); \ 605 o += BYTES; \ 606 } \ 607 } 608 AU_HIMEM_WR(uint8_t,1) 609 AU_HIMEM_WR(uint16_t,2) 610 AU_HIMEM_WR(uint32_t,4) 611 AU_HIMEM_WR(uint64_t,8) 612 613 #define AU_HIMEM_WRS(TYPE,BYTES) \ 614 void \ 615 __CONCAT(au_himem_wrs_,BYTES)(void *v, \ 616 bus_space_handle_t h, bus_size_t o, const TYPE *src, \ 617 bus_size_t cnt) \ 618 { \ 619 \ 620 while (cnt-- > 0) { \ 621 __CONCAT(au_himem_ws_,BYTES)(v, h, o, *src++); \ 622 o += BYTES; \ 623 } \ 624 } 625 AU_HIMEM_WRS(uint16_t,2) 626 AU_HIMEM_WRS(uint32_t,4) 627 AU_HIMEM_WRS(uint64_t,8) 628 629 #define AU_HIMEM_SM(TYPE,BYTES) \ 630 void \ 631 __CONCAT(au_himem_sm_,BYTES)(void *v, \ 632 bus_space_handle_t h, bus_size_t o, TYPE val, \ 633 bus_size_t cnt) \ 634 { \ 635 \ 636 while (cnt-- > 0) { \ 637 __CONCAT(au_himem_w_,BYTES)(v, h, o, val); \ 638 } \ 639 } 640 AU_HIMEM_SM(uint8_t,1) 641 AU_HIMEM_SM(uint16_t,2) 642 AU_HIMEM_SM(uint32_t,4) 643 AU_HIMEM_SM(uint64_t,8) 644 645 #define AU_HIMEM_SR(TYPE,BYTES) \ 646 void \ 647 __CONCAT(au_himem_sr_,BYTES)(void *v, \ 648 bus_space_handle_t h, bus_size_t o, TYPE val, \ 649 bus_size_t cnt) \ 650 { \ 651 \ 652 while (cnt-- > 0) { \ 653 __CONCAT(au_himem_w_,BYTES)(v, h, o, val); \ 654 o += BYTES; \ 655 } \ 656 } 657 AU_HIMEM_SR(uint8_t,1) 658 AU_HIMEM_SR(uint16_t,2) 659 AU_HIMEM_SR(uint32_t,4) 660 AU_HIMEM_SR(uint64_t,8) 661 662 663 #define AU_HIMEM_C(TYPE,BYTES) \ 664 void \ 665 __CONCAT(au_himem_c_,BYTES)(void *v, \ 666 bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, \ 667 bus_size_t o2, bus_size_t cnt) \ 668 { \ 669 volatile TYPE *src, *dst; \ 670 src = (volatile TYPE *)(intptr_t)(h1 + o1); \ 671 dst = (volatile TYPE *)(intptr_t)(h2 + o2); \ 672 \ 673 if (src >= dst) { \ 674 while (cnt-- > 0) \ 675 *dst++ = *src++; \ 676 } else { \ 677 src += cnt - 1; \ 678 dst += cnt - 1; \ 679 while (cnt-- > 0) \ 680 *dst-- = *src--; \ 681 } \ 682 } 683 AU_HIMEM_C(uint8_t,1) 684 AU_HIMEM_C(uint16_t,2) 685 AU_HIMEM_C(uint32_t,4) 686 AU_HIMEM_C(uint64_t,8) 687 688 689 void 690 au_himem_space_init(bus_space_tag_t bst, const char *name, 691 paddr_t physoff, bus_addr_t start, bus_addr_t end, int flags) 692 { 693 au_himem_cookie_t *c; 694 695 c = malloc(sizeof (struct au_himem_cookie), M_DEVBUF, 696 M_NOWAIT | M_ZERO); 697 698 c->c_name = name; 699 c->c_start = start; 700 c->c_end = end; 701 c->c_physoff = physoff; 702 703 /* allocate extent manager */ 704 c->c_extent = extent_create(name, start, end, 705 NULL, 0, EX_NOWAIT); 706 if (c->c_extent == NULL) 707 panic("au_himem_space_init: %s: cannot create extent", name); 708 709 #if _BYTE_ORDER == _BIG_ENDIAN 710 if (flags & AU_HIMEM_SPACE_LITTLE_ENDIAN) { 711 if (flags & AU_HIMEM_SPACE_SWAP_HW) 712 c->c_hwswap = 1; 713 else 714 c->c_swswap = 1; 715 } 716 717 #elif _BYTE_ORDER == _LITTLE_ENDIAN 718 if (flags & AU_HIMEM_SPACE_BIG_ENDIAN) { 719 if (flags & AU_HIMEM_SPACE_SWAP_HW) 720 c->c_hwswap = 1; 721 else 722 c->c_swswap = 1; 723 } 724 #endif 725 726 bst->bs_cookie = c; 727 bst->bs_map = au_himem_map; 728 bst->bs_unmap = au_himem_unmap; 729 bst->bs_subregion = au_himem_subregion; 730 bst->bs_translate = NULL; /* we don't use these */ 731 bst->bs_get_window = NULL; /* we don't use these */ 732 bst->bs_alloc = au_himem_alloc; 733 bst->bs_free = au_himem_free; 734 bst->bs_vaddr = au_himem_vaddr; 735 bst->bs_mmap = au_himem_mmap; 736 bst->bs_barrier = au_himem_barrier; 737 bst->bs_r_1 = au_himem_r_1; 738 bst->bs_w_1 = au_himem_w_1; 739 bst->bs_r_2 = au_himem_r_2; 740 bst->bs_r_4 = au_himem_r_4; 741 bst->bs_r_8 = au_himem_r_8; 742 bst->bs_w_2 = au_himem_w_2; 743 bst->bs_w_4 = au_himem_w_4; 744 bst->bs_w_8 = au_himem_w_8; 745 bst->bs_rm_1 = au_himem_rm_1; 746 bst->bs_rm_2 = au_himem_rm_2; 747 bst->bs_rm_4 = au_himem_rm_4; 748 bst->bs_rm_8 = au_himem_rm_8; 749 bst->bs_rr_1 = au_himem_rr_1; 750 bst->bs_rr_2 = au_himem_rr_2; 751 bst->bs_rr_4 = au_himem_rr_4; 752 bst->bs_rr_8 = au_himem_rr_8; 753 bst->bs_wm_1 = au_himem_wm_1; 754 bst->bs_wm_2 = au_himem_wm_2; 755 bst->bs_wm_4 = au_himem_wm_4; 756 bst->bs_wm_8 = au_himem_wm_8; 757 bst->bs_wr_1 = au_himem_wr_1; 758 bst->bs_wr_2 = au_himem_wr_2; 759 bst->bs_wr_4 = au_himem_wr_4; 760 bst->bs_wr_8 = au_himem_wr_8; 761 bst->bs_sm_1 = au_himem_sm_1; 762 bst->bs_sm_2 = au_himem_sm_2; 763 bst->bs_sm_4 = au_himem_sm_4; 764 bst->bs_sm_8 = au_himem_sm_8; 765 bst->bs_sr_1 = au_himem_sr_1; 766 bst->bs_sr_2 = au_himem_sr_2; 767 bst->bs_sr_4 = au_himem_sr_4; 768 bst->bs_sr_8 = au_himem_sr_8; 769 bst->bs_c_1 = au_himem_c_1; 770 bst->bs_c_2 = au_himem_c_2; 771 bst->bs_c_4 = au_himem_c_4; 772 bst->bs_c_8 = au_himem_c_8; 773 774 bst->bs_rs_1 = au_himem_r_1; 775 bst->bs_rs_2 = au_himem_rs_2; 776 bst->bs_rs_4 = au_himem_rs_4; 777 bst->bs_rs_8 = au_himem_rs_8; 778 bst->bs_rms_1 = au_himem_rm_1; 779 bst->bs_rms_2 = au_himem_rms_2; 780 bst->bs_rms_4 = au_himem_rms_4; 781 bst->bs_rms_8 = au_himem_rms_8; 782 bst->bs_rrs_1 = au_himem_rr_1; 783 bst->bs_rrs_2 = au_himem_rrs_2; 784 bst->bs_rrs_4 = au_himem_rrs_4; 785 bst->bs_rrs_8 = au_himem_rrs_8; 786 bst->bs_ws_1 = au_himem_w_1; 787 bst->bs_ws_2 = au_himem_ws_2; 788 bst->bs_ws_4 = au_himem_ws_4; 789 bst->bs_ws_8 = au_himem_ws_8; 790 bst->bs_wms_1 = au_himem_wm_1; 791 bst->bs_wms_2 = au_himem_wms_2; 792 bst->bs_wms_4 = au_himem_wms_4; 793 bst->bs_wms_8 = au_himem_wms_8; 794 bst->bs_wrs_1 = au_himem_wr_1; 795 bst->bs_wrs_2 = au_himem_wrs_2; 796 bst->bs_wrs_4 = au_himem_wrs_4; 797 bst->bs_wrs_8 = au_himem_wrs_8; 798 } 799