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