1 /* $NetBSD: le_bus.c,v 1.23 2023/01/06 10:28:27 tsutsui 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.23 2023/01/06 10:28:27 tsutsui Exp $"); 34 35 #include <sys/types.h> 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kmem.h> 39 #include <sys/bswap.h> 40 #include <machine/cpu.h> 41 #include <sys/bus.h> 42 43 /* 44 * This file contains the common functions for using a little 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 kmem_alloc() can't be used). 266 */ 267 if (storage != NULL) 268 leb_t = storage; 269 else { 270 leb_t = kmem_alloc(sizeof(*leb_t), KM_SLEEP); 271 } 272 memset(leb_t, 0, sizeof(*leb_t)); 273 274 leb_t->abs_p_1 = leb_bus_space_peek_1; 275 leb_t->abs_p_2 = leb_bus_space_peek_2; 276 leb_t->abs_p_4 = leb_bus_space_peek_4; 277 leb_t->abs_p_8 = leb_bus_space_peek_8; 278 leb_t->abs_r_1 = leb_bus_space_read_1; 279 leb_t->abs_r_2 = leb_bus_space_read_2; 280 leb_t->abs_r_4 = leb_bus_space_read_4; 281 leb_t->abs_r_8 = leb_bus_space_read_8; 282 leb_t->abs_rs_1 = leb_bus_space_read_1; 283 leb_t->abs_rs_2 = leb_bus_space_read_stream_2; 284 leb_t->abs_rs_4 = leb_bus_space_read_stream_4; 285 leb_t->abs_rs_8 = leb_bus_space_read_stream_8; 286 leb_t->abs_rm_1 = leb_bus_space_read_multi_1; 287 leb_t->abs_rm_2 = leb_bus_space_read_multi_2; 288 leb_t->abs_rm_4 = leb_bus_space_read_multi_4; 289 leb_t->abs_rm_8 = leb_bus_space_read_multi_8; 290 leb_t->abs_rms_1 = leb_bus_space_read_multi_1; 291 leb_t->abs_rms_2 = leb_bus_space_read_multi_stream_2; 292 leb_t->abs_rms_4 = leb_bus_space_read_multi_stream_4; 293 leb_t->abs_rms_8 = leb_bus_space_read_multi_stream_8; 294 leb_t->abs_rr_1 = leb_bus_space_read_region_1; 295 leb_t->abs_rr_2 = leb_bus_space_read_region_2; 296 leb_t->abs_rr_4 = leb_bus_space_read_region_4; 297 leb_t->abs_rr_8 = leb_bus_space_read_region_8; 298 leb_t->abs_rrs_1 = leb_bus_space_read_region_1; 299 leb_t->abs_rrs_2 = leb_bus_space_read_region_stream_2; 300 leb_t->abs_rrs_4 = leb_bus_space_read_region_stream_4; 301 leb_t->abs_rrs_8 = leb_bus_space_read_region_stream_8; 302 leb_t->abs_w_1 = leb_bus_space_write_1; 303 leb_t->abs_w_2 = leb_bus_space_write_2; 304 leb_t->abs_w_4 = leb_bus_space_write_4; 305 leb_t->abs_w_8 = leb_bus_space_write_8; 306 leb_t->abs_ws_1 = leb_bus_space_write_1; 307 leb_t->abs_ws_2 = leb_bus_space_write_stream_2; 308 leb_t->abs_ws_4 = leb_bus_space_write_stream_4; 309 leb_t->abs_ws_8 = leb_bus_space_write_stream_8; 310 leb_t->abs_wm_1 = leb_bus_space_write_multi_1; 311 leb_t->abs_wm_2 = leb_bus_space_write_multi_2; 312 leb_t->abs_wm_4 = leb_bus_space_write_multi_4; 313 leb_t->abs_wm_8 = leb_bus_space_write_multi_8; 314 leb_t->abs_wms_1 = leb_bus_space_write_multi_1; 315 leb_t->abs_wms_2 = leb_bus_space_write_multi_stream_2; 316 leb_t->abs_wms_4 = leb_bus_space_write_multi_stream_4; 317 leb_t->abs_wms_8 = leb_bus_space_write_multi_stream_8; 318 leb_t->abs_wr_1 = leb_bus_space_write_region_1; 319 leb_t->abs_wr_2 = leb_bus_space_write_region_2; 320 leb_t->abs_wr_4 = leb_bus_space_write_region_4; 321 leb_t->abs_wr_8 = leb_bus_space_write_region_8; 322 leb_t->abs_wrs_1 = leb_bus_space_write_region_1; 323 leb_t->abs_wrs_2 = leb_bus_space_write_region_stream_2; 324 leb_t->abs_wrs_4 = leb_bus_space_write_region_stream_4; 325 leb_t->abs_wrs_8 = leb_bus_space_write_region_stream_8; 326 leb_t->abs_sm_1 = leb_bus_space_set_multi_1; 327 leb_t->abs_sm_2 = leb_bus_space_set_multi_2; 328 leb_t->abs_sm_4 = leb_bus_space_set_multi_4; 329 leb_t->abs_sm_8 = leb_bus_space_set_multi_8; 330 leb_t->abs_sr_1 = leb_bus_space_set_region_1; 331 leb_t->abs_sr_2 = leb_bus_space_set_region_2; 332 leb_t->abs_sr_4 = leb_bus_space_set_region_4; 333 leb_t->abs_sr_8 = leb_bus_space_set_region_8; 334 335 return leb_t; 336 } 337 338 339 /* 340 * The various access functions 341 */ 342 343 /* 344 * int bus_space_peek_N(bus_space_tag_t tag, 345 * bus_space_handle_t sh, bus_size_t offset); 346 * 347 * Check if the address is suitable for reading N-byte quantities. 348 */ 349 static int 350 leb_bus_space_peek_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 351 { 352 353 return !badbaddr((void *)(h + o), 1); 354 } 355 356 static int 357 leb_bus_space_peek_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 358 { 359 360 return !badbaddr((void *)(h + o), 2); 361 } 362 363 static int 364 leb_bus_space_peek_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 365 { 366 367 return !badbaddr((void *)(h + o), 4); 368 } 369 370 static int 371 leb_bus_space_peek_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 372 { 373 374 return !badbaddr((void *)(h + o), 8); 375 } 376 377 /* 378 * uintX_t bus_space_read_N(bus_space_tag_t tag, 379 * bus_space_handle_t bsh, bus_size_t offset); 380 * 381 * Return an 1, 2, 4, or 8 byte value read from the bus_space described 382 * by tag/handle at `offset'. The value is converted to host-endian. 383 */ 384 static uint8_t 385 leb_bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 386 { 387 388 return __read_1(h, o); 389 } 390 391 static uint16_t 392 leb_bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 393 { 394 395 return __read_2(h, o); 396 } 397 398 static uint32_t 399 leb_bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 400 { 401 402 return __read_4(h, o); 403 } 404 405 static uint64_t 406 leb_bus_space_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 407 { 408 409 return __read_8(h, o); 410 } 411 412 /* 413 * uintX_t bus_space_write_N(bus_space_tag_t tag, 414 * bus_space_handle_t bsh, bus_size_t offset, uintX_t val); 415 * 416 * Write an 1, 2, 4, or 8 byte value to the bus_space described by tag/handle 417 * at `offset'. The value `val' is converted from host to bus endianness 418 * before being written. 419 */ 420 static void 421 leb_bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 422 uint8_t v) 423 { 424 425 __write_1(h, o, v); 426 } 427 428 static void 429 leb_bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 430 uint16_t v) 431 { 432 433 __write_2(h, o, v); 434 } 435 436 static void 437 leb_bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 438 uint32_t v) 439 { 440 441 __write_4(h, o, v); 442 } 443 444 static void 445 leb_bus_space_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 446 uint64_t v) 447 { 448 449 __write_8(h, o, v); 450 } 451 452 /* 453 * uintX_t bus_space_read_stream_N(bus_space_tag_t tag, 454 * bus_space_handle_t bsh, bus_size_t offset); 455 * 456 * Return an 1, 2, 4, or 8 byte value read from the bus_space described 457 * by tag/handle at `offset'. No endian conversion is done. 458 */ 459 static uint16_t 460 leb_bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, 461 bus_size_t o) 462 { 463 464 return *((volatile uint16_t *)(h + o)); 465 } 466 467 static uint32_t 468 leb_bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, 469 bus_size_t o) 470 { 471 472 return *((volatile uint32_t *)(h + o)); 473 } 474 475 static uint64_t 476 leb_bus_space_read_stream_8(bus_space_tag_t t, bus_space_handle_t h, 477 bus_size_t o) 478 { 479 480 return *((volatile uint64_t *)(h + o)); 481 } 482 483 /* 484 * uintX_t bus_space_write_stream_N(bus_space_tag_t tag, 485 * bus_space_handle_t bsh, bus_size_t offset, uintX_t val); 486 * 487 * Write an 1, 2, 4, or 8 byte value to the bus_space described by tag/handle 488 * at `offset'. No endian conversion is done. 489 */ 490 static void 491 leb_bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, 492 bus_size_t o, uint16_t v) 493 { 494 495 *((volatile uint16_t *)(h + o)) = v; 496 } 497 498 static void 499 leb_bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, 500 bus_size_t o, uint32_t v) 501 { 502 503 *((volatile uint32_t *)(h + o)) = v; 504 } 505 506 static void 507 leb_bus_space_write_stream_8(bus_space_tag_t t, bus_space_handle_t h, 508 bus_size_t o, uint64_t v) 509 { 510 511 *((volatile uint64_t *)(h + o)) = v; 512 } 513 514 /* 515 * void bus_space_read_multi_N(bus_space_tag_t tag, 516 * bus_space_handle_t bsh, bus_size_t offset, uintX_t *address, 517 * bus_size_t count); 518 * 519 * Read 'count' 1, 2, 4, or 8 byte values from the bus_space described by 520 * tag/handle at `offset' and store them in the address range starting at 521 * 'address'. The values are converted to CPU endian order before being 522 * being stored. 523 */ 524 static void 525 leb_bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, 526 bus_size_t o, uint8_t *a, bus_size_t c) 527 { 528 529 for (; c; a++, c--) 530 *a = __read_1(h, o); 531 } 532 static void 533 leb_bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, 534 bus_size_t o, uint16_t *a, bus_size_t c) 535 { 536 537 for (; c; a++, c--) 538 *a = __read_2(h, o); 539 } 540 541 static void 542 leb_bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, 543 bus_size_t o, uint32_t *a, bus_size_t c) 544 { 545 546 for (; c; a++, c--) 547 *a = __read_4(h, o); 548 } 549 550 static void 551 leb_bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, 552 bus_size_t o, uint64_t *a, bus_size_t c) 553 { 554 555 for (; c; a++, c--) 556 *a = __read_8(h, o); 557 } 558 559 /* 560 * void bus_space_write_multi_N(bus_space_tag_t tag, 561 * bus_space_handle_t bsh, bus_size_t offset, 562 * const uintX_t *address, bus_size_t count); 563 * 564 * Write 'count' 1, 2, 4, or 8 byte values from the address range starting 565 * at 'address' to the bus_space described by tag/handle at `offset'. 566 * The values are converted to bus endian order before being written to 567 * the bus. 568 */ 569 static void 570 leb_bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, 571 bus_size_t o, const uint8_t *a, bus_size_t c) 572 { 573 574 for (; c; a++, c--) 575 __write_1(h, o, *a); 576 } 577 578 static void 579 leb_bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, 580 bus_size_t o, const uint16_t *a, bus_size_t c) 581 { 582 583 for (; c; a++, c--) 584 __write_2(h, o, *a); 585 } 586 587 static void 588 leb_bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, 589 bus_size_t o, const uint32_t *a, bus_size_t c) 590 { 591 592 for (; c; a++, c--) 593 __write_4(h, o, *a); 594 } 595 596 static void 597 leb_bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, 598 bus_size_t o, const uint64_t *a, bus_size_t c) 599 { 600 601 for (; c; a++, c--) 602 __write_8(h, o, *a); 603 } 604 605 /* 606 * void bus_space_read_multi_stream_N(bus_space_tag_t tag, 607 * bus_space_handle_t bsh, bus_size_t offset, uintX_t *address, 608 * bus_size_t count); 609 * 610 * Read 'count' 1, 2, 4, or 8 byte values from the bus_space described by 611 * tag/handle at `offset' and store them in the address range starting at 612 * 'address'. No endian conversion is being done. 613 */ 614 static void 615 leb_bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, 616 bus_size_t o, uint16_t *a, bus_size_t c) 617 { 618 619 for (; c; a++, c--) 620 *a = *((volatile uint16_t *)(h + o)); 621 } 622 623 static void 624 leb_bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, 625 bus_size_t o, uint32_t *a, bus_size_t c) 626 { 627 628 for (; c; a++, c--) 629 *a = *((volatile uint32_t *)(h + o)); 630 } 631 632 static void 633 leb_bus_space_read_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, 634 bus_size_t o, uint64_t *a, bus_size_t c) 635 { 636 637 for (; c; a++, c--) 638 *a = *((volatile uint64_t *)(h + o)); 639 } 640 641 /* 642 * void bus_space_write_multi_stream_N(bus_space_tag_t tag, 643 * bus_space_handle_t bsh, bus_size_t offset, 644 * const uintX_t *address, bus_size_t count); 645 * 646 * Write 'count' 1, 2, 4, or 8 byte values from the address range starting 647 * at 'address' to the bus_space described by tag/handle at `offset'. 648 * No endian conversion is being done. 649 */ 650 static void 651 leb_bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, 652 bus_size_t o, const uint16_t *a, bus_size_t c) 653 { 654 655 for (; c; a++, c--) 656 *((volatile uint16_t *)(h + o)) = *a; 657 } 658 659 static void 660 leb_bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, 661 bus_size_t o, const uint32_t *a, bus_size_t c) 662 { 663 664 for (; c; a++, c--) 665 *((volatile uint32_t *)(h + o)) = *a; 666 } 667 668 static void 669 leb_bus_space_write_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, 670 bus_size_t o, const uint64_t *a, bus_size_t c) 671 { 672 673 for (; c; a++, c--) 674 *((volatile uint64_t *)(h + o)) = *a; 675 } 676 677 /* 678 * void bus_space_read_region_N(bus_space_tag_t tag, 679 * bus_space_handle_t bsh, bus_size_t offset, 680 * uintN_t *addr, bus_size_t count); 681 * 682 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 683 * described by tag/handle and starting at `offset' and copy into 684 * buffer provided. 685 */ 686 static void 687 leb_bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, 688 bus_size_t o, uint8_t *a, bus_size_t c) 689 { 690 691 for (; c; a++, o++, c--) 692 *a = __read_1(h, o); 693 } 694 695 static void 696 leb_bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, 697 bus_size_t o, uint16_t *a, bus_size_t c) 698 { 699 700 for (; c; a++, o += 2, c--) 701 *a = __read_2(h, o); 702 } 703 704 static void 705 leb_bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, 706 bus_size_t o, uint32_t *a, bus_size_t c) 707 { 708 709 for (; c; a++, o += 4, c--) 710 *a = __read_4(h, o); 711 } 712 713 static void 714 leb_bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, 715 bus_size_t o, uint64_t *a, bus_size_t c) 716 { 717 718 for (; c; a++, o += 8, c--) 719 *a = __read_8(h, o); 720 } 721 722 /* 723 * void bus_space_write_region_N(bus_space_tag_t tag, 724 * bus_space_handle_t bsh, bus_size_t offset, 725 * uintN_t *addr, bus_size_t count); 726 * 727 * Copy `count' 1, 2, 4, or 8 byte quantities from the buffer provided 728 * into the bus space described by tag/handle and starting at `offset'. 729 */ 730 static void 731 leb_bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, 732 bus_size_t o, const uint8_t *a, bus_size_t c) 733 { 734 735 for (; c; a++, o++, c--) 736 __write_1(h, o, *a); 737 } 738 739 static void 740 leb_bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, 741 bus_size_t o, const uint16_t *a, bus_size_t c) 742 { 743 744 for (; c; a++, o += 2, c--) 745 __write_2(h, o, *a); 746 } 747 748 static void 749 leb_bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, 750 bus_size_t o, const uint32_t *a, bus_size_t c) 751 { 752 753 for (; c; a++, o += 4, c--) 754 __write_4(h, o, *a); 755 } 756 757 static void 758 leb_bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, 759 bus_size_t o, const uint64_t *a, bus_size_t c) 760 { 761 762 for (; c; a++, o += 8, c--) 763 __write_8(h, o, *a); 764 } 765 766 /* 767 * void bus_space_read_region_stream_N(bus_space_tag_t tag, 768 * bus_space_handle_t bsh, bus_size_t offset, 769 * uintN_t *addr, bus_size_t count); 770 * 771 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 772 * described by tag/handle and starting at `offset' and copy into 773 * buffer provided. 774 * No endian conversion is being done. 775 */ 776 static void 777 leb_bus_space_read_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, 778 bus_size_t o, uint16_t *a, bus_size_t c) 779 { 780 781 for (; c; a++, o += 2, c--) 782 *a = *(volatile uint16_t *)(h + o); 783 } 784 785 static void 786 leb_bus_space_read_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, 787 bus_size_t o, uint32_t *a, bus_size_t c) 788 { 789 790 for (; c; a++, o += 4, c--) 791 *a = *(volatile uint32_t *)(h + o); 792 } 793 794 static void 795 leb_bus_space_read_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, 796 bus_size_t o, uint64_t *a, bus_size_t c) 797 { 798 799 for (; c; a++, o += 8, c--) 800 *a = *(volatile uint64_t *)(h + o); 801 } 802 803 /* 804 * void bus_space_write_region_stream_N(bus_space_tag_t tag, 805 * bus_space_handle_t bsh, bus_size_t offset, 806 * uintN_t *addr, bus_size_t count); 807 * 808 * Copy `count' 1, 2, 4, or 8 byte quantities from the buffer provided 809 * into the bus space described by tag/handle and starting at `offset'. 810 * No endian conversion is being done. 811 */ 812 static void 813 leb_bus_space_write_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, 814 bus_size_t o, const uint16_t *a, bus_size_t c) 815 { 816 817 for (; c; a++, o += 2, c--) 818 *((volatile uint16_t *)(h + o)) = *a; 819 } 820 821 static void 822 leb_bus_space_write_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, 823 bus_size_t o, const uint32_t *a, bus_size_t c) 824 { 825 826 for (; c; a++, o += 4, c--) 827 *((volatile uint32_t *)(h + o)) = *a; 828 } 829 830 static void 831 leb_bus_space_write_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, 832 bus_size_t o, const uint64_t *a, bus_size_t c) 833 { 834 835 for (; c; a++, o += 8, c--) 836 *((volatile uint64_t *)(h + o)) = *a; 837 } 838 839 /* 840 * void bus_space_set_multi_N(bus_space_tag_t tag, 841 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val, 842 * bus_size_t count); 843 * 844 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 845 * by tag/handle/offset `count' times. 846 */ 847 848 static void 849 leb_bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, 850 bus_size_t o, uint8_t v, bus_size_t c) 851 { 852 853 for (; c; c--) 854 __write_1(h, o, v); 855 } 856 857 static void 858 leb_bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, 859 bus_size_t o, uint16_t v, bus_size_t c) 860 { 861 862 v = swap16(v); 863 for (; c; c--) 864 *((volatile uint16_t *)(h + o)) = v; 865 } 866 867 static void 868 leb_bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, 869 bus_size_t o, uint32_t v, bus_size_t c) 870 { 871 872 v = swap32(v); 873 for (; c; c--) 874 *((volatile uint32_t *)(h + o)) = v; 875 } 876 877 static void 878 leb_bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, 879 bus_size_t o, uint64_t v, bus_size_t c) 880 { 881 882 v = bswap64(v); 883 for (; c; c--) 884 *((volatile uint64_t *)(h + o)) = v; 885 } 886 887 /* 888 * void bus_space_set_region_N(bus_space_tag_t tag, 889 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val, 890 * bus_size_t count); 891 * 892 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described 893 * by tag/handle starting at `offset'. 894 */ 895 static void 896 leb_bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, 897 bus_size_t o, uint8_t v, bus_size_t c) 898 { 899 900 for (; c; o++, c--) 901 __write_1(h, o, v); 902 } 903 904 static void 905 leb_bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, 906 bus_size_t o, uint16_t v, bus_size_t c) 907 { 908 909 v = swap16(v); 910 for (; c; o += 2, c--) 911 *((volatile uint16_t *)(h + o)) = v; 912 } 913 914 static void 915 leb_bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, 916 bus_size_t o, uint32_t v, bus_size_t c) 917 { 918 919 v = swap32(v); 920 for (; c; o += 4, c--) 921 *((volatile uint32_t *)(h + o)) = v; 922 } 923 924 static void 925 leb_bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, 926 bus_size_t o, uint64_t v, bus_size_t c) 927 { 928 929 v = bswap64(v); 930 for (; c; o += 8, c--) 931 *((volatile uint64_t *)(h + o)) = v; 932 } 933