1 /* $NetBSD: le_bus.c,v 1.17 2009/03/18 16:00:10 cegger Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Leo Weppelman. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: le_bus.c,v 1.17 2009/03/18 16:00:10 cegger Exp $"); 34 35 #include <sys/types.h> 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/malloc.h> 39 #include <sys/bswap.h> 40 #include <machine/cpu.h> 41 #include <machine/bus.h> 42 43 /* 44 * This file contains the common functions for using a litte endian (linear) 45 * bus on a big endian atari. 46 */ 47 48 /* Autoconf detection stuff */ 49 static int leb_bus_space_peek_1(bus_space_tag_t, 50 bus_space_handle_t, bus_size_t); 51 static int leb_bus_space_peek_2(bus_space_tag_t, 52 bus_space_handle_t, bus_size_t); 53 static int leb_bus_space_peek_4(bus_space_tag_t, 54 bus_space_handle_t, bus_size_t); 55 static int leb_bus_space_peek_8(bus_space_tag_t, 56 bus_space_handle_t, bus_size_t); 57 58 /* read (single) */ 59 static uint8_t leb_bus_space_read_1(bus_space_tag_t, 60 bus_space_handle_t, bus_size_t); 61 static uint16_t leb_bus_space_read_2(bus_space_tag_t, 62 bus_space_handle_t, bus_size_t); 63 static uint32_t leb_bus_space_read_4(bus_space_tag_t, 64 bus_space_handle_t, bus_size_t); 65 static uint64_t leb_bus_space_read_8(bus_space_tag_t, 66 bus_space_handle_t, bus_size_t); 67 68 /* write (single) */ 69 static void leb_bus_space_write_1(bus_space_tag_t, 70 bus_space_handle_t, bus_size_t, uint8_t); 71 static void leb_bus_space_write_2(bus_space_tag_t, 72 bus_space_handle_t, bus_size_t, uint16_t); 73 static void leb_bus_space_write_4(bus_space_tag_t, 74 bus_space_handle_t, bus_size_t, uint32_t); 75 static void leb_bus_space_write_8(bus_space_tag_t, 76 bus_space_handle_t, bus_size_t, uint64_t); 77 78 /* read (single) stream */ 79 static uint16_t leb_bus_space_read_stream_2(bus_space_tag_t, 80 bus_space_handle_t, bus_size_t); 81 static uint32_t leb_bus_space_read_stream_4(bus_space_tag_t, 82 bus_space_handle_t, bus_size_t); 83 static uint64_t leb_bus_space_read_stream_8(bus_space_tag_t, 84 bus_space_handle_t, bus_size_t); 85 86 /* write (single) stream */ 87 static void leb_bus_space_write_stream_2(bus_space_tag_t, 88 bus_space_handle_t, bus_size_t, uint16_t); 89 static void leb_bus_space_write_stream_4(bus_space_tag_t, 90 bus_space_handle_t, bus_size_t, uint32_t); 91 static void leb_bus_space_write_stream_8(bus_space_tag_t, 92 bus_space_handle_t, bus_size_t, uint64_t); 93 94 /* read multiple */ 95 static void leb_bus_space_read_multi_1(bus_space_tag_t, 96 bus_space_handle_t, bus_size_t, uint8_t *, 97 bus_size_t); 98 static void leb_bus_space_read_multi_2(bus_space_tag_t, 99 bus_space_handle_t, bus_size_t, uint16_t *, 100 bus_size_t); 101 static void leb_bus_space_read_multi_4(bus_space_tag_t, 102 bus_space_handle_t, bus_size_t, uint32_t *, 103 bus_size_t); 104 static void leb_bus_space_read_multi_8(bus_space_tag_t, 105 bus_space_handle_t, bus_size_t, uint64_t *, 106 bus_size_t); 107 108 /* write multiple */ 109 static void leb_bus_space_write_multi_1(bus_space_tag_t, 110 bus_space_handle_t, bus_size_t, 111 const uint8_t *, bus_size_t); 112 static void leb_bus_space_write_multi_2(bus_space_tag_t, 113 bus_space_handle_t, bus_size_t, 114 const uint16_t *, bus_size_t); 115 static void leb_bus_space_write_multi_4(bus_space_tag_t, 116 bus_space_handle_t, bus_size_t, 117 const uint32_t *, bus_size_t); 118 static void leb_bus_space_write_multi_8(bus_space_tag_t, 119 bus_space_handle_t, bus_size_t, 120 const uint64_t *, bus_size_t); 121 122 /* read multiple stream */ 123 static void leb_bus_space_read_multi_stream_2(bus_space_tag_t, 124 bus_space_handle_t, bus_size_t, uint16_t *, 125 bus_size_t); 126 static void leb_bus_space_read_multi_stream_4(bus_space_tag_t, 127 bus_space_handle_t, bus_size_t, uint32_t *, 128 bus_size_t); 129 static void leb_bus_space_read_multi_stream_8(bus_space_tag_t, 130 bus_space_handle_t, bus_size_t, uint64_t *, 131 bus_size_t); 132 133 /* write multiple stream */ 134 static void leb_bus_space_write_multi_stream_2(bus_space_tag_t, 135 bus_space_handle_t, bus_size_t, 136 const uint16_t *, bus_size_t); 137 static void leb_bus_space_write_multi_stream_4(bus_space_tag_t, 138 bus_space_handle_t, bus_size_t, 139 const uint32_t *, bus_size_t); 140 static void leb_bus_space_write_multi_stream_8(bus_space_tag_t, 141 bus_space_handle_t, bus_size_t, 142 const uint64_t *, bus_size_t); 143 144 /* read region */ 145 static void leb_bus_space_read_region_1(bus_space_tag_t, 146 bus_space_handle_t, bus_size_t, uint8_t *, 147 bus_size_t); 148 static void leb_bus_space_read_region_2(bus_space_tag_t, 149 bus_space_handle_t, bus_size_t, uint16_t *, 150 bus_size_t); 151 static void leb_bus_space_read_region_4(bus_space_tag_t, 152 bus_space_handle_t, bus_size_t, uint32_t *, 153 bus_size_t); 154 static void leb_bus_space_read_region_8(bus_space_tag_t, 155 bus_space_handle_t, bus_size_t, uint64_t *, 156 bus_size_t); 157 158 /* write region */ 159 static void leb_bus_space_write_region_1(bus_space_tag_t, 160 bus_space_handle_t, bus_size_t, 161 const uint8_t *, bus_size_t); 162 static void leb_bus_space_write_region_2(bus_space_tag_t, 163 bus_space_handle_t, bus_size_t, 164 const uint16_t *, bus_size_t); 165 static void leb_bus_space_write_region_4(bus_space_tag_t, 166 bus_space_handle_t, bus_size_t, 167 const uint32_t *, bus_size_t); 168 static void leb_bus_space_write_region_8(bus_space_tag_t, 169 bus_space_handle_t, bus_size_t, 170 const uint64_t *, bus_size_t); 171 172 /* read region stream */ 173 static void leb_bus_space_read_region_stream_2(bus_space_tag_t, 174 bus_space_handle_t, bus_size_t, uint16_t *, 175 bus_size_t); 176 static void leb_bus_space_read_region_stream_4(bus_space_tag_t, 177 bus_space_handle_t, bus_size_t, uint32_t *, 178 bus_size_t); 179 static void leb_bus_space_read_region_stream_8(bus_space_tag_t, 180 bus_space_handle_t, bus_size_t, uint64_t *, 181 bus_size_t); 182 183 /* write region */ 184 static void leb_bus_space_write_region_stream_2(bus_space_tag_t, 185 bus_space_handle_t, bus_size_t, 186 const uint16_t *, bus_size_t); 187 static void leb_bus_space_write_region_stream_4(bus_space_tag_t, 188 bus_space_handle_t, bus_size_t, 189 const uint32_t *, bus_size_t); 190 static void leb_bus_space_write_region_stream_8(bus_space_tag_t, 191 bus_space_handle_t, bus_size_t, 192 const uint64_t *, bus_size_t); 193 194 /* set multi */ 195 static void leb_bus_space_set_multi_1(bus_space_tag_t, 196 bus_space_handle_t, bus_size_t, uint8_t, 197 bus_size_t); 198 static void leb_bus_space_set_multi_2(bus_space_tag_t, 199 bus_space_handle_t, bus_size_t, uint16_t, 200 bus_size_t); 201 static void leb_bus_space_set_multi_4(bus_space_tag_t, 202 bus_space_handle_t, bus_size_t, uint32_t, 203 bus_size_t); 204 static void leb_bus_space_set_multi_8(bus_space_tag_t, 205 bus_space_handle_t, bus_size_t, uint64_t, 206 bus_size_t); 207 208 /* set region */ 209 static void leb_bus_space_set_region_1(bus_space_tag_t, 210 bus_space_handle_t, bus_size_t, uint8_t, 211 bus_size_t); 212 static void leb_bus_space_set_region_2(bus_space_tag_t, 213 bus_space_handle_t, bus_size_t, uint16_t, 214 bus_size_t); 215 static void leb_bus_space_set_region_4(bus_space_tag_t, 216 bus_space_handle_t, bus_size_t, uint32_t, 217 bus_size_t); 218 static void leb_bus_space_set_region_8(bus_space_tag_t, 219 bus_space_handle_t, bus_size_t, uint64_t, 220 bus_size_t); 221 222 /* 223 * Define these inline, to avoid function call overhead. 224 * XXX: Maybe move to an m68k include file? 225 */ 226 static uint16_t swap16(uint16_t v); 227 static uint32_t swap32(uint32_t v); 228 229 static inline uint16_t swap16(uint16_t v) 230 { 231 232 __asm volatile ("rolw #8, %0" : "=d"(v) : "0"(v)); 233 return v; 234 } 235 236 static inline uint32_t swap32(uint32_t v) 237 { 238 239 __asm volatile (" rolw #8, %0 \n" 240 " swap %0 \n" 241 " rolw #8, %0" : "=d"(v) : "0"(v)); 242 return v; 243 } 244 245 /* 246 * Don't force a function call overhead on these primitives... 247 */ 248 #define __read_1(h, o) *((volatile uint8_t *)((h) + (o))) 249 #define __read_2(h, o) swap16(*((volatile uint16_t *)((h) + (o)))) 250 #define __read_4(h, o) swap32(*((volatile uint32_t *)((h) + (o)))) 251 #define __read_8(h, o) bswap64(*((volatile uint64_t *)((h) + (o)))) 252 253 #define __write_1(h, o, v) *((volatile uint8_t *)((h) + (o))) = (v) 254 #define __write_2(h, o, v) *((volatile uint16_t *)((h) + (o))) = swap16(v) 255 #define __write_4(h, o, v) *((volatile uint32_t *)((h) + (o))) = swap32(v) 256 #define __write_8(h, o, v) *((volatile uint64_t *)((h) + (o))) = bswap64(v) 257 258 bus_space_tag_t 259 leb_alloc_bus_space_tag(bus_space_tag_t storage) 260 { 261 bus_space_tag_t leb_t; 262 263 /* 264 * Allow the caller to specify storage space for the tag. This 265 * is used during console config (when malloc() can't be used). 266 */ 267 if (storage != NULL) 268 leb_t = storage; 269 else { 270 if ((leb_t = malloc(sizeof(*leb_t), M_TEMP, M_NOWAIT)) == NULL) 271 return NULL; 272 } 273 memset(leb_t, 0, sizeof(*leb_t)); 274 275 leb_t->abs_p_1 = leb_bus_space_peek_1; 276 leb_t->abs_p_2 = leb_bus_space_peek_2; 277 leb_t->abs_p_4 = leb_bus_space_peek_4; 278 leb_t->abs_p_8 = leb_bus_space_peek_8; 279 leb_t->abs_r_1 = leb_bus_space_read_1; 280 leb_t->abs_r_2 = leb_bus_space_read_2; 281 leb_t->abs_r_4 = leb_bus_space_read_4; 282 leb_t->abs_r_8 = leb_bus_space_read_8; 283 leb_t->abs_rs_1 = leb_bus_space_read_1; 284 leb_t->abs_rs_2 = leb_bus_space_read_stream_2; 285 leb_t->abs_rs_4 = leb_bus_space_read_stream_4; 286 leb_t->abs_rs_8 = leb_bus_space_read_stream_8; 287 leb_t->abs_rm_1 = leb_bus_space_read_multi_1; 288 leb_t->abs_rm_2 = leb_bus_space_read_multi_2; 289 leb_t->abs_rm_4 = leb_bus_space_read_multi_4; 290 leb_t->abs_rm_8 = leb_bus_space_read_multi_8; 291 leb_t->abs_rms_1 = leb_bus_space_read_multi_1; 292 leb_t->abs_rms_2 = leb_bus_space_read_multi_stream_2; 293 leb_t->abs_rms_4 = leb_bus_space_read_multi_stream_4; 294 leb_t->abs_rms_8 = leb_bus_space_read_multi_stream_8; 295 leb_t->abs_rr_1 = leb_bus_space_read_region_1; 296 leb_t->abs_rr_2 = leb_bus_space_read_region_2; 297 leb_t->abs_rr_4 = leb_bus_space_read_region_4; 298 leb_t->abs_rr_8 = leb_bus_space_read_region_8; 299 leb_t->abs_rrs_1 = leb_bus_space_read_region_1; 300 leb_t->abs_rrs_2 = leb_bus_space_read_region_stream_2; 301 leb_t->abs_rrs_4 = leb_bus_space_read_region_stream_4; 302 leb_t->abs_rrs_8 = leb_bus_space_read_region_stream_8; 303 leb_t->abs_w_1 = leb_bus_space_write_1; 304 leb_t->abs_w_2 = leb_bus_space_write_2; 305 leb_t->abs_w_4 = leb_bus_space_write_4; 306 leb_t->abs_w_8 = leb_bus_space_write_8; 307 leb_t->abs_ws_1 = leb_bus_space_write_1; 308 leb_t->abs_ws_2 = leb_bus_space_write_stream_2; 309 leb_t->abs_ws_4 = leb_bus_space_write_stream_4; 310 leb_t->abs_ws_8 = leb_bus_space_write_stream_8; 311 leb_t->abs_wm_1 = leb_bus_space_write_multi_1; 312 leb_t->abs_wm_2 = leb_bus_space_write_multi_2; 313 leb_t->abs_wm_4 = leb_bus_space_write_multi_4; 314 leb_t->abs_wm_8 = leb_bus_space_write_multi_8; 315 leb_t->abs_wms_1 = leb_bus_space_write_multi_1; 316 leb_t->abs_wms_2 = leb_bus_space_write_multi_stream_2; 317 leb_t->abs_wms_4 = leb_bus_space_write_multi_stream_4; 318 leb_t->abs_wms_8 = leb_bus_space_write_multi_stream_8; 319 leb_t->abs_wr_1 = leb_bus_space_write_region_1; 320 leb_t->abs_wr_2 = leb_bus_space_write_region_2; 321 leb_t->abs_wr_4 = leb_bus_space_write_region_4; 322 leb_t->abs_wr_8 = leb_bus_space_write_region_8; 323 leb_t->abs_wrs_1 = leb_bus_space_write_region_1; 324 leb_t->abs_wrs_2 = leb_bus_space_write_region_stream_2; 325 leb_t->abs_wrs_4 = leb_bus_space_write_region_stream_4; 326 leb_t->abs_wrs_8 = leb_bus_space_write_region_stream_8; 327 leb_t->abs_sm_1 = leb_bus_space_set_multi_1; 328 leb_t->abs_sm_2 = leb_bus_space_set_multi_2; 329 leb_t->abs_sm_4 = leb_bus_space_set_multi_4; 330 leb_t->abs_sm_8 = leb_bus_space_set_multi_8; 331 leb_t->abs_sr_1 = leb_bus_space_set_region_1; 332 leb_t->abs_sr_2 = leb_bus_space_set_region_2; 333 leb_t->abs_sr_4 = leb_bus_space_set_region_4; 334 leb_t->abs_sr_8 = leb_bus_space_set_region_8; 335 336 return leb_t; 337 } 338 339 340 /* 341 * The various access functions 342 */ 343 344 /* 345 * int bus_space_peek_N(bus_space_tag_t tag, 346 * bus_space_handle_t sh, bus_size_t offset); 347 * 348 * Check if the address is suitable for reading N-byte quantities. 349 */ 350 static int 351 leb_bus_space_peek_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 352 { 353 354 return !badbaddr((void *)(h + o), 1); 355 } 356 357 static int 358 leb_bus_space_peek_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 359 { 360 361 return !badbaddr((void *)(h + o), 2); 362 } 363 364 static int 365 leb_bus_space_peek_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 366 { 367 368 return !badbaddr((void *)(h + o), 4); 369 } 370 371 static int 372 leb_bus_space_peek_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 373 { 374 375 return !badbaddr((void *)(h + o), 8); 376 } 377 378 /* 379 * uintX_t bus_space_read_N(bus_space_tag_t tag, 380 * bus_space_handle_t bsh, bus_size_t offset); 381 * 382 * Return an 1, 2, 4, or 8 byte value read from the bus_space described 383 * by tag/handle at `offset'. The value is converted to host-endian. 384 */ 385 static uint8_t 386 leb_bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 387 { 388 389 return __read_1(h, o); 390 } 391 392 static uint16_t 393 leb_bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 394 { 395 396 return __read_2(h, o); 397 } 398 399 static uint32_t 400 leb_bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 401 { 402 403 return __read_4(h, o); 404 } 405 406 static uint64_t 407 leb_bus_space_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 408 { 409 410 return __read_8(h, o); 411 } 412 413 /* 414 * uintX_t bus_space_write_N(bus_space_tag_t tag, 415 * bus_space_handle_t bsh, bus_size_t offset, uintX_t val); 416 * 417 * Write an 1, 2, 4, or 8 byte value to the bus_space described by tag/handle 418 * at `offset'. The value `val' is converted from host to bus endianness 419 * before being written. 420 */ 421 static void 422 leb_bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 423 uint8_t v) 424 { 425 426 __write_1(h, o, v); 427 } 428 429 static void 430 leb_bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 431 uint16_t v) 432 { 433 434 __write_2(h, o, v); 435 } 436 437 static void 438 leb_bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 439 uint32_t v) 440 { 441 442 __write_4(h, o, v); 443 } 444 445 static void 446 leb_bus_space_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 447 uint64_t v) 448 { 449 450 __write_8(h, o, v); 451 } 452 453 /* 454 * uintX_t bus_space_read_stream_N(bus_space_tag_t tag, 455 * bus_space_handle_t bsh, bus_size_t offset); 456 * 457 * Return an 1, 2, 4, or 8 byte value read from the bus_space described 458 * by tag/handle at `offset'. No endian conversion is done. 459 */ 460 static uint16_t 461 leb_bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, 462 bus_size_t o) 463 { 464 465 return *((volatile uint16_t *)(h + o)); 466 } 467 468 static uint32_t 469 leb_bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, 470 bus_size_t o) 471 { 472 473 return *((volatile uint32_t *)(h + o)); 474 } 475 476 static uint64_t 477 leb_bus_space_read_stream_8(bus_space_tag_t t, bus_space_handle_t h, 478 bus_size_t o) 479 { 480 481 return *((volatile uint64_t *)(h + o)); 482 } 483 484 /* 485 * uintX_t bus_space_write_stream_N(bus_space_tag_t tag, 486 * bus_space_handle_t bsh, bus_size_t offset, uintX_t val); 487 * 488 * Write an 1, 2, 4, or 8 byte value to the bus_space described by tag/handle 489 * at `offset'. No endian conversion is done. 490 */ 491 static void 492 leb_bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, 493 bus_size_t o, uint16_t v) 494 { 495 496 *((volatile uint16_t *)(h + o)) = v; 497 } 498 499 static void 500 leb_bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, 501 bus_size_t o, uint32_t v) 502 { 503 504 *((volatile uint32_t *)(h + o)) = v; 505 } 506 507 static void 508 leb_bus_space_write_stream_8(bus_space_tag_t t, bus_space_handle_t h, 509 bus_size_t o, uint64_t v) 510 { 511 512 *((volatile uint64_t *)(h + o)) = v; 513 } 514 515 /* 516 * void bus_space_read_multi_N(bus_space_tag_t tag, 517 * bus_space_handle_t bsh, bus_size_t offset, uintX_t *address, 518 * bus_size_t count); 519 * 520 * Read 'count' 1, 2, 4, or 8 byte values from the bus_space described by 521 * tag/handle at `offset' and store them in the address range starting at 522 * 'address'. The values are converted to CPU endian order before being 523 * being stored. 524 */ 525 static void 526 leb_bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, 527 bus_size_t o, uint8_t *a, bus_size_t c) 528 { 529 530 for (; c; a++, c--) 531 *a = __read_1(h, o); 532 } 533 static void 534 leb_bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, 535 bus_size_t o, uint16_t *a, bus_size_t c) 536 { 537 538 for (; c; a++, c--) 539 *a = __read_2(h, o); 540 } 541 542 static void 543 leb_bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, 544 bus_size_t o, uint32_t *a, bus_size_t c) 545 { 546 547 for (; c; a++, c--) 548 *a = __read_4(h, o); 549 } 550 551 static void 552 leb_bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, 553 bus_size_t o, uint64_t *a, bus_size_t c) 554 { 555 556 for (; c; a++, c--) 557 *a = __read_8(h, o); 558 } 559 560 /* 561 * void bus_space_write_multi_N(bus_space_tag_t tag, 562 * bus_space_handle_t bsh, bus_size_t offset, 563 * const uintX_t *address, bus_size_t count); 564 * 565 * Write 'count' 1, 2, 4, or 8 byte values from the address range starting 566 * at 'address' to the bus_space described by tag/handle at `offset'. 567 * The values are converted to bus endian order before being written to 568 * the bus. 569 */ 570 static void 571 leb_bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, 572 bus_size_t o, const uint8_t *a, bus_size_t c) 573 { 574 575 for (; c; a++, c--) 576 __write_1(h, o, *a); 577 } 578 579 static void 580 leb_bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, 581 bus_size_t o, const uint16_t *a, bus_size_t c) 582 { 583 584 for (; c; a++, c--) 585 __write_2(h, o, *a); 586 } 587 588 static void 589 leb_bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, 590 bus_size_t o, const uint32_t *a, bus_size_t c) 591 { 592 593 for (; c; a++, c--) 594 __write_4(h, o, *a); 595 } 596 597 static void 598 leb_bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, 599 bus_size_t o, const uint64_t *a, bus_size_t c) 600 { 601 602 for (; c; a++, c--) 603 __write_8(h, o, *a); 604 } 605 606 /* 607 * void bus_space_read_multi_stream_N(bus_space_tag_t tag, 608 * bus_space_handle_t bsh, bus_size_t offset, uintX_t *address, 609 * bus_size_t count); 610 * 611 * Read 'count' 1, 2, 4, or 8 byte values from the bus_space described by 612 * tag/handle at `offset' and store them in the address range starting at 613 * 'address'. No endian conversion is being done. 614 */ 615 static void 616 leb_bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, 617 bus_size_t o, uint16_t *a, bus_size_t c) 618 { 619 620 for (; c; a++, c--) 621 *a = *((volatile uint16_t *)(h + o)); 622 } 623 624 static void 625 leb_bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, 626 bus_size_t o, uint32_t *a, bus_size_t c) 627 { 628 629 for (; c; a++, c--) 630 *a = *((volatile uint32_t *)(h + o)); 631 } 632 633 static void 634 leb_bus_space_read_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, 635 bus_size_t o, uint64_t *a, bus_size_t c) 636 { 637 638 for (; c; a++, c--) 639 *a = *((volatile uint64_t *)(h + o)); 640 } 641 642 /* 643 * void bus_space_write_multi_stream_N(bus_space_tag_t tag, 644 * bus_space_handle_t bsh, bus_size_t offset, 645 * const uintX_t *address, bus_size_t count); 646 * 647 * Write 'count' 1, 2, 4, or 8 byte values from the address range starting 648 * at 'address' to the bus_space described by tag/handle at `offset'. 649 * No endian conversion is being done. 650 */ 651 static void 652 leb_bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, 653 bus_size_t o, const uint16_t *a, bus_size_t c) 654 { 655 656 for (; c; a++, c--) 657 *((volatile uint16_t *)(h + o)) = *a; 658 } 659 660 static void 661 leb_bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, 662 bus_size_t o, const uint32_t *a, bus_size_t c) 663 { 664 665 for (; c; a++, c--) 666 *((volatile uint32_t *)(h + o)) = *a; 667 } 668 669 static void 670 leb_bus_space_write_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, 671 bus_size_t o, const uint64_t *a, bus_size_t c) 672 { 673 674 for (; c; a++, c--) 675 *((volatile uint64_t *)(h + o)) = *a; 676 } 677 678 /* 679 * void bus_space_read_region_N(bus_space_tag_t tag, 680 * bus_space_handle_t bsh, bus_size_t offset, 681 * uintN_t *addr, bus_size_t count); 682 * 683 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 684 * described by tag/handle and starting at `offset' and copy into 685 * buffer provided. 686 */ 687 static void 688 leb_bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, 689 bus_size_t o, uint8_t *a, bus_size_t c) 690 { 691 692 for (; c; a++, o++, c--) 693 *a = __read_1(h, o); 694 } 695 696 static void 697 leb_bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, 698 bus_size_t o, uint16_t *a, bus_size_t c) 699 { 700 701 for (; c; a++, o += 2, c--) 702 *a = __read_2(h, o); 703 } 704 705 static void 706 leb_bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, 707 bus_size_t o, uint32_t *a, bus_size_t c) 708 { 709 710 for (; c; a++, o += 4, c--) 711 *a = __read_4(h, o); 712 } 713 714 static void 715 leb_bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, 716 bus_size_t o, uint64_t *a, bus_size_t c) 717 { 718 719 for (; c; a++, o += 8, c--) 720 *a = __read_8(h, o); 721 } 722 723 /* 724 * void bus_space_write_region_N(bus_space_tag_t tag, 725 * bus_space_handle_t bsh, bus_size_t offset, 726 * uintN_t *addr, bus_size_t count); 727 * 728 * Copy `count' 1, 2, 4, or 8 byte quantities from the buffer provided 729 * into the bus space described by tag/handle and starting at `offset'. 730 */ 731 static void 732 leb_bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, 733 bus_size_t o, const uint8_t *a, bus_size_t c) 734 { 735 736 for (; c; a++, o++, c--) 737 __write_1(h, o, *a); 738 } 739 740 static void 741 leb_bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, 742 bus_size_t o, const uint16_t *a, bus_size_t c) 743 { 744 745 for (; c; a++, o += 2, c--) 746 __write_2(h, o, *a); 747 } 748 749 static void 750 leb_bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, 751 bus_size_t o, const uint32_t *a, bus_size_t c) 752 { 753 754 for (; c; a++, o += 4, c--) 755 __write_4(h, o, *a); 756 } 757 758 static void 759 leb_bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, 760 bus_size_t o, const uint64_t *a, bus_size_t c) 761 { 762 763 for (; c; a++, o += 8, c--) 764 __write_8(h, o, *a); 765 } 766 767 /* 768 * void bus_space_read_region_stream_N(bus_space_tag_t tag, 769 * bus_space_handle_t bsh, bus_size_t offset, 770 * uintN_t *addr, bus_size_t count); 771 * 772 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 773 * described by tag/handle and starting at `offset' and copy into 774 * buffer provided. 775 * No endian conversion is being done. 776 */ 777 static void 778 leb_bus_space_read_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, 779 bus_size_t o, uint16_t *a, bus_size_t c) 780 { 781 782 for (; c; a++, o += 2, c--) 783 *a = *(volatile uint16_t *)(h + o); 784 } 785 786 static void 787 leb_bus_space_read_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, 788 bus_size_t o, uint32_t *a, bus_size_t c) 789 { 790 791 for (; c; a++, o += 4, c--) 792 *a = *(volatile uint32_t *)(h + o); 793 } 794 795 static void 796 leb_bus_space_read_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, 797 bus_size_t o, uint64_t *a, bus_size_t c) 798 { 799 800 for (; c; a++, o += 8, c--) 801 *a = *(volatile uint64_t *)(h + o); 802 } 803 804 /* 805 * void bus_space_write_region_stream_N(bus_space_tag_t tag, 806 * bus_space_handle_t bsh, bus_size_t offset, 807 * uintN_t *addr, bus_size_t count); 808 * 809 * Copy `count' 1, 2, 4, or 8 byte quantities from the buffer provided 810 * into the bus space described by tag/handle and starting at `offset'. 811 * No endian conversion is being done. 812 */ 813 static void 814 leb_bus_space_write_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, 815 bus_size_t o, const uint16_t *a, bus_size_t c) 816 { 817 818 for (; c; a++, o += 2, c--) 819 *((volatile uint16_t *)(h + o)) = *a; 820 } 821 822 static void 823 leb_bus_space_write_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, 824 bus_size_t o, const uint32_t *a, bus_size_t c) 825 { 826 827 for (; c; a++, o += 4, c--) 828 *((volatile uint32_t *)(h + o)) = *a; 829 } 830 831 static void 832 leb_bus_space_write_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, 833 bus_size_t o, const uint64_t *a, bus_size_t c) 834 { 835 836 for (; c; a++, o += 8, c--) 837 *((volatile uint64_t *)(h + o)) = *a; 838 } 839 840 /* 841 * void bus_space_set_multi_N(bus_space_tag_t tag, 842 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val, 843 * bus_size_t count); 844 * 845 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 846 * by tag/handle/offset `count' times. 847 */ 848 849 static void 850 leb_bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, 851 bus_size_t o, uint8_t v, bus_size_t c) 852 { 853 854 for (; c; c--) 855 __write_1(h, o, v); 856 } 857 858 static void 859 leb_bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, 860 bus_size_t o, uint16_t v, bus_size_t c) 861 { 862 863 v = swap16(v); 864 for (; c; c--) 865 *((volatile uint16_t *)(h + o)) = v; 866 } 867 868 static void 869 leb_bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, 870 bus_size_t o, uint32_t v, bus_size_t c) 871 { 872 873 v = swap32(v); 874 for (; c; c--) 875 *((volatile uint32_t *)(h + o)) = v; 876 } 877 878 static void 879 leb_bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, 880 bus_size_t o, uint64_t v, bus_size_t c) 881 { 882 883 v = bswap64(v); 884 for (; c; c--) 885 *((volatile uint64_t *)(h + o)) = v; 886 } 887 888 /* 889 * void bus_space_set_region_N(bus_space_tag_t tag, 890 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val, 891 * bus_size_t count); 892 * 893 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described 894 * by tag/handle starting at `offset'. 895 */ 896 static void 897 leb_bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, 898 bus_size_t o, uint8_t v, bus_size_t c) 899 { 900 901 for (; c; o++, c--) 902 __write_1(h, o, v); 903 } 904 905 static void 906 leb_bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, 907 bus_size_t o, uint16_t v, bus_size_t c) 908 { 909 910 v = swap16(v); 911 for (; c; o += 2, c--) 912 *((volatile uint16_t *)(h + o)) = v; 913 } 914 915 static void 916 leb_bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, 917 bus_size_t o, uint32_t v, bus_size_t c) 918 { 919 920 v = swap32(v); 921 for (; c; o += 4, c--) 922 *((volatile uint32_t *)(h + o)) = v; 923 } 924 925 static void 926 leb_bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, 927 bus_size_t o, uint64_t v, bus_size_t c) 928 { 929 930 v = bswap64(v); 931 for (; c; o += 8, c--) 932 *((volatile uint64_t *)(h + o)) = v; 933 } 934