1 /* $NetBSD: bus_space.h,v 1.23 2023/02/11 02:31:34 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (C) 1997 Scott Reynolds. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. The name of the author may not be used to endorse or promote products 45 * derived from this software without specific prior written permission 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 50 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 51 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 52 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 53 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 54 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 56 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 */ 58 59 #ifndef _NEXT68K_BUS_SPACE_H_ 60 #define _NEXT68K_BUS_SPACE_H_ 61 /* 62 * Addresses (in bus space). 63 */ 64 typedef u_long bus_addr_t; 65 typedef u_long bus_size_t; 66 67 #define PRIxBUSADDR "lx" 68 #define PRIxBUSSIZE "lx" 69 #define PRIuBUSSIZE "lu" 70 71 /* 72 * Access methods for bus resources and address space. 73 */ 74 typedef volatile char * bus_space_tag_t; 75 typedef u_long bus_space_handle_t; 76 77 #define PRIxBSH "lx" 78 79 /* 80 * Value for the next68k bus space tag, not to be used directly by MI code. 81 */ 82 #define NEXT68K_INTIO_BUS_SPACE ((bus_space_tag_t)intiobase) 83 84 /* 85 * Mapping and unmapping operations. 86 */ 87 88 int bus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, 89 bus_space_handle_t *); 90 91 #define bus_space_unmap(t, h, s) 92 93 #define bus_space_subregion(t, h, o, s, hp) \ 94 (*(hp)=(h)+(o)) 95 96 #define BUS_SPACE_MAP_CACHEABLE 0x01 97 #define BUS_SPACE_MAP_LINEAR 0x02 98 99 /* 100 * Allocation and deallocation operations. 101 */ 102 #define bus_space_alloc(t, rs, re, s, a, b, f, ap, hp) \ 103 (-1) 104 105 #define bus_space_free(t, h, s) 106 107 /* 108 * paddr_t bus_space_mmap(bus_space_tag_t t, bus_addr_t base, 109 * off_t offset, int prot, int flags); 110 * 111 * Mmap an area of bus space. 112 */ 113 114 paddr_t bus_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); 115 116 /* 117 * uintN_t bus_space_read_N(bus_space_tag_t tag, 118 * bus_space_handle_t bsh, bus_size_t offset); 119 * 120 * Read a 1, 2, 4, or 8 byte quantity from bus space 121 * described by tag/handle/offset. 122 */ 123 124 #define bus_space_read_1(t, h, o) \ 125 ((void) t, (*(volatile uint8_t *)((h) + (o)))) 126 127 #define bus_space_read_2(t, h, o) \ 128 ((void) t, (*(volatile uint16_t *)((h) + (o)))) 129 130 #define bus_space_read_4(t, h, o) \ 131 ((void) t, (*(volatile uint32_t *)((h) + (o)))) 132 133 /* 134 * void bus_space_read_multi_N(bus_space_tag_t tag, 135 * bus_space_handle_t bsh, bus_size_t offset, 136 * uintN_t *addr, size_t count); 137 * 138 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 139 * described by tag/handle/offset and copy into buffer provided. 140 */ 141 142 #define bus_space_read_multi_1(t, h, o, a, c) do { \ 143 (void) t; \ 144 __asm volatile (" \ 145 movl %0,%%a0 ; \ 146 movl %1,%%a1 ; \ 147 movl %2,%%d0 ; \ 148 1: movb %%a0@,%%a1@+ ; \ 149 subql #1,%%d0 ; \ 150 jne 1b" : \ 151 : \ 152 "r" ((h) + (o)), "g" (a), "g" (c) : \ 153 "a0","a1","d0","memory"); \ 154 } while (0); 155 156 #define bus_space_read_multi_2(t, h, o, a, c) do { \ 157 (void) t; \ 158 __asm volatile (" \ 159 movl %0,%%a0 ; \ 160 movl %1,%%a1 ; \ 161 movl %2,%%d0 ; \ 162 1: movw %%a0@,%%a1@+ ; \ 163 subql #1,%%d0 ; \ 164 jne 1b" : \ 165 : \ 166 "r" ((h) + (o)), "g" (a), "g" (c) : \ 167 "a0","a1","d0","memory"); \ 168 } while (0); 169 170 #define bus_space_read_multi_4(t, h, o, a, c) do { \ 171 (void) t; \ 172 __asm volatile (" \ 173 movl %0,%%a0 ; \ 174 movl %1,%%a1 ; \ 175 movl %2,%%d0 ; \ 176 1: movl %%a0@,%%a1@+ ; \ 177 subql #1,%%d0 ; \ 178 jne 1b" : \ 179 : \ 180 "r" ((h) + (o)), "g" (a), "g" (c) : \ 181 "a0","a1","d0","memory"); \ 182 } while (0); 183 184 /* 185 * void bus_space_read_region_N(bus_space_tag_t tag, 186 * bus_space_handle_t bsh, bus_size_t offset, 187 * uintN_t *addr, size_t count); 188 * 189 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 190 * described by tag/handle and starting at `offset' and copy into 191 * buffer provided. 192 */ 193 194 #define bus_space_read_region_1(t, h, o, a, c) do { \ 195 (void) t; \ 196 __asm volatile (" \ 197 movl %0,%%a0 ; \ 198 movl %1,%%a1 ; \ 199 movl %2,%%d0 ; \ 200 1: movb %%a0@+,%%a1@+ ; \ 201 subql #1,%%d0 ; \ 202 jne 1b" : \ 203 : \ 204 "r" ((h) + (o)), "g" (a), "g" (c) : \ 205 "a0","a1","d0","memory"); \ 206 } while (0); 207 208 #define bus_space_read_region_2(t, h, o, a, c) do { \ 209 (void) t; \ 210 __asm volatile (" \ 211 movl %0,%%a0 ; \ 212 movl %1,%%a1 ; \ 213 movl %2,%%d0 ; \ 214 1: movw %%a0@+,%%a1@+ ; \ 215 subql #1,%%d0 ; \ 216 jne 1b" : \ 217 : \ 218 "r" ((h) + (o)), "g" (a), "g" (c) : \ 219 "a0","a1","d0","memory"); \ 220 } while (0); 221 222 #define bus_space_read_region_4(t, h, o, a, c) do { \ 223 (void) t; \ 224 __asm volatile (" \ 225 movl %0,%%a0 ; \ 226 movl %1,%%a1 ; \ 227 movl %2,%%d0 ; \ 228 1: movl %%a0@+,%%a1@+ ; \ 229 subql #1,%%d0 ; \ 230 jne 1b" : \ 231 : \ 232 "r" ((h) + (o)), "g" (a), "g" (c) : \ 233 "a0","a1","d0","memory"); \ 234 } while (0); 235 236 /* 237 * void bus_space_write_N(bus_space_tag_t tag, 238 * bus_space_handle_t bsh, bus_size_t offset, 239 * uintN_t value); 240 * 241 * Write the 1, 2, 4, or 8 byte value `value' to bus space 242 * described by tag/handle/offset. 243 */ 244 245 #define bus_space_write_1(t, h, o, v) \ 246 ((void) t, ((void)(*(volatile uint8_t *)((h) + (o)) = (v)))) 247 248 #define bus_space_write_2(t, h, o, v) \ 249 ((void) t, ((void)(*(volatile uint16_t *)((h) + (o)) = (v)))) 250 251 #define bus_space_write_4(t, h, o, v) \ 252 ((void) t, ((void)(*(volatile uint32_t *)((h) + (o)) = (v)))) 253 254 /* 255 * void bus_space_write_multi_N(bus_space_tag_t tag, 256 * bus_space_handle_t bsh, bus_size_t offset, 257 * const uintN_t *addr, size_t count); 258 * 259 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer 260 * provided to bus space described by tag/handle/offset. 261 */ 262 263 #define bus_space_write_multi_1(t, h, o, a, c) do { \ 264 (void) t; \ 265 __asm volatile (" \ 266 movl %0,%%a0 ; \ 267 movl %1,%%a1 ; \ 268 movl %2,%%d0 ; \ 269 1: movb %%a1@+,%%a0@ ; \ 270 subql #1,%%d0 ; \ 271 jne 1b" : \ 272 : \ 273 "r" ((h) + (o)), "g" (a), "g" (c) : \ 274 "a0","a1","d0"); \ 275 } while (0); 276 277 #define bus_space_write_multi_2(t, h, o, a, c) do { \ 278 (void) t; \ 279 __asm volatile (" \ 280 movl %0,%%a0 ; \ 281 movl %1,%%a1 ; \ 282 movl %2,%%d0 ; \ 283 1: movw %%a1@+,%%a0@ ; \ 284 subql #1,%%d0 ; \ 285 jne 1b" : \ 286 : \ 287 "r" ((h) + (o)), "g" (a), "g" (c) : \ 288 "a0","a1","d0"); \ 289 } while (0); 290 291 #define bus_space_write_multi_4(t, h, o, a, c) do { \ 292 (void) t; \ 293 __asm volatile (" \ 294 movl %0,%%a0 ; \ 295 movl %1,%%a1 ; \ 296 movl %2,%%d0 ; \ 297 1: movl %%a1@+,%%a0@ ; \ 298 subql #1,%%d0 ; \ 299 jne 1b" : \ 300 : \ 301 "r" ((h) + (o)), "g" (a), "g" (c) : \ 302 "a0","a1","d0"); \ 303 } while (0); 304 305 /* 306 * void bus_space_write_region_N(bus_space_tag_t tag, 307 * bus_space_handle_t bsh, bus_size_t offset, 308 * const uintN_t *addr, size_t count); 309 * 310 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided 311 * to bus space described by tag/handle starting at `offset'. 312 */ 313 314 #define bus_space_write_region_1(t, h, o, a, c) do { \ 315 (void) t; \ 316 __asm volatile (" \ 317 movl %0,%%a0 ; \ 318 movl %1,%%a1 ; \ 319 movl %2,%%d0 ; \ 320 1: movb %%a1@+,%%a0@+ ; \ 321 subql #1,%%d0 ; \ 322 jne 1b" : \ 323 : \ 324 "r" ((h) + (o)), "g" (a), "g" (c) : \ 325 "a0","a1","d0"); \ 326 } while (0); 327 328 #define bus_space_write_region_2(t, h, o, a, c) do { \ 329 (void) t; \ 330 __asm volatile (" \ 331 movl %0,%%a0 ; \ 332 movl %1,%%a1 ; \ 333 movl %2,%%d0 ; \ 334 1: movw %%a1@+,%%a0@+ ; \ 335 subql #1,%%d0 ; \ 336 jne 1b" : \ 337 : \ 338 "r" ((h) + (o)), "g" (a), "g" (c) : \ 339 "a0","a1","d0"); \ 340 } while (0); 341 342 #define bus_space_write_region_4(t, h, o, a, c) do { \ 343 (void) t; \ 344 __asm volatile (" \ 345 movl %0,%%a0 ; \ 346 movl %1,%%a1 ; \ 347 movl %2,%%d0 ; \ 348 1: movl %%a1@+,%%a0@+ ; \ 349 subql #1,%%d0 ; \ 350 jne 1b" : \ 351 : \ 352 "r" ((h) + (o)), "g" (a), "g" (c) : \ 353 "a0","a1","d0"); \ 354 } while (0); 355 356 /* 357 * void bus_space_set_multi_N(bus_space_tag_t tag, 358 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val, 359 * size_t count); 360 * 361 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 362 * by tag/handle/offset `count' times. 363 */ 364 365 #define bus_space_set_multi_1(t, h, o, val, c) do { \ 366 (void) t; \ 367 __asm volatile (" \ 368 movl %0,%%a0 ; \ 369 movl %1,%%d1 ; \ 370 movl %2,%%d0 ; \ 371 1: movb %%d1,%%a0@ ; \ 372 subql #1,%%d0 ; \ 373 jne 1b" : \ 374 : \ 375 "r" ((h) + (o)), "g" (val), "g" (c) : \ 376 "a0","d0","d1"); \ 377 } while (0); 378 379 #define bus_space_set_multi_2(t, h, o, val, c) do { \ 380 (void) t; \ 381 __asm volatile (" \ 382 movl %0,%%a0 ; \ 383 movl %1,%%d1 ; \ 384 movl %2,%%d0 ; \ 385 1: movw %%d1,%%a0@ ; \ 386 subql #1,%%d0 ; \ 387 jne 1b" : \ 388 : \ 389 "r" ((h) + (o)), "g" (val), "g" (c) : \ 390 "a0","d0","d1"); \ 391 } while (0); 392 393 #define bus_space_set_multi_4(t, h, o, val, c) do { \ 394 (void) t; \ 395 __asm volatile (" \ 396 movl %0,%%a0 ; \ 397 movl %1,%%d1 ; \ 398 movl %2,%%d0 ; \ 399 1: movl %%d1,%%a0@ ; \ 400 subql #1,%%d0 ; \ 401 jne 1b" : \ 402 : \ 403 "r" ((h) + (o)), "g" (val), "g" (c) : \ 404 "a0","d0","d1"); \ 405 } while (0); 406 407 /* 408 * void bus_space_set_region_N(bus_space_tag_t tag, 409 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val, 410 * size_t count); 411 * 412 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described 413 * by tag/handle starting at `offset'. 414 */ 415 416 #define bus_space_set_region_1(t, h, o, val, c) do { \ 417 (void) t; \ 418 __asm volatile (" \ 419 movl %0,%%a0 ; \ 420 movl %1,%%d1 ; \ 421 movl %2,%%d0 ; \ 422 1: movb %%d1,%%a0@+ ; \ 423 subql #1,%%d0 ; \ 424 jne 1b" : \ 425 : \ 426 "r" ((h) + (o)), "g" (val), "g" (c) : \ 427 "a0","d0","d1"); \ 428 } while (0); 429 430 #define bus_space_set_region_2(t, h, o, val, c) do { \ 431 (void) t; \ 432 __asm volatile (" \ 433 movl %0,%%a0 ; \ 434 movl %1,%%d1 ; \ 435 movl %2,%%d0 ; \ 436 1: movw %%d1,%%a0@+ ; \ 437 subql #1,%%d0 ; \ 438 jne 1b" : \ 439 : \ 440 "r" ((h) + (o)), "g" (val), "g" (c) : \ 441 "a0","d0","d1"); \ 442 } while (0); 443 444 #define bus_space_set_region_4(t, h, o, val, c) do { \ 445 (void) t; \ 446 __asm volatile (" \ 447 movl %0,%%a0 ; \ 448 movl %1,%%d1 ; \ 449 movl %2,%%d0 ; \ 450 1: movl %%d1,%%a0@+ ; \ 451 subql #1,%%d0 ; \ 452 jne 1b" : \ 453 : \ 454 "r" ((h) + (o)), "g" (val), "g" (c) : \ 455 "a0","d0","d1"); \ 456 } while (0); 457 458 /* 459 * void bus_space_copy_N(bus_space_tag_t tag, 460 * bus_space_handle_t bsh1, bus_size_t off1, 461 * bus_space_handle_t bsh2, bus_size_t off2, 462 * size_t count); 463 * 464 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting 465 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. 466 */ 467 468 #define __NEXT68K_copy_region_N(BYTES) \ 469 static __inline void __CONCAT(bus_space_copy_region_,BYTES) \ 470 (bus_space_tag_t, \ 471 bus_space_handle_t, bus_size_t, \ 472 bus_space_handle_t, bus_size_t, \ 473 bus_size_t); \ 474 \ 475 static __inline void \ 476 __CONCAT(bus_space_copy_region_,BYTES)( \ 477 bus_space_tag_t t, \ 478 bus_space_handle_t h1, \ 479 bus_size_t o1, \ 480 bus_space_handle_t h2, \ 481 bus_size_t o2, \ 482 bus_size_t c) \ 483 { \ 484 bus_size_t o; \ 485 \ 486 if ((h1 + o1) >= (h2 + o2)) { \ 487 /* src after dest: copy forward */ \ 488 for (o = 0; c != 0; c--, o += BYTES) \ 489 __CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o, \ 490 __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \ 491 } else { \ 492 /* dest after src: copy backwards */ \ 493 for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES) \ 494 __CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o, \ 495 __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \ 496 } \ 497 } 498 __NEXT68K_copy_region_N(1) 499 __NEXT68K_copy_region_N(2) 500 __NEXT68K_copy_region_N(4) 501 502 #undef __NEXT68K_copy_region_N 503 504 /* 505 * Bus read/write barrier methods. 506 * 507 * void bus_space_barrier(bus_space_tag_t tag, 508 * bus_space_handle_t bsh, bus_size_t offset, 509 * bus_size_t len, int flags); 510 * 511 * Note: the 680x0 does not currently require barriers, but we must 512 * provide the flags to MI code. 513 */ 514 #define bus_space_barrier(t, h, o, l, f) \ 515 ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f))) 516 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 517 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 518 519 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) 520 521 #endif /* _NEXT68K_BUS_SPACE_H_ */ 522