1 /* $NetBSD: bus.h,v 1.2 2001/07/19 15:32:19 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997, 1998, 2001 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 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1996 Charles M. Hannum. All rights reserved. 42 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by Christopher G. Demetriou 55 * for the NetBSD Project. 56 * 4. The name of the author may not be used to endorse or promote products 57 * derived from this software without specific prior written permission 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 60 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 61 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 62 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 63 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 64 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 65 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 66 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 67 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 68 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 69 */ 70 71 #ifndef _SUN68K_BUS_H_ 72 #define _SUN68K_BUS_H_ 73 74 #define SUN68K_BUS_SPACE 0 75 76 /* 77 * Bus address and size types 78 */ 79 typedef u_long bus_space_handle_t; 80 typedef u_long bus_type_t; 81 typedef u_long bus_addr_t; 82 typedef u_long bus_size_t; 83 84 /* 85 * Access methods for bus resources and address space. 86 */ 87 typedef struct sun68k_bus_space_tag *bus_space_tag_t; 88 89 struct sun68k_bus_space_tag { 90 void *cookie; 91 bus_space_tag_t parent; 92 93 int (*sun68k_bus_map) __P(( 94 bus_space_tag_t, 95 bus_type_t, 96 bus_addr_t, 97 bus_size_t, 98 int, /*flags*/ 99 vaddr_t, /*preferred vaddr*/ 100 bus_space_handle_t *)); 101 int (*sun68k_bus_unmap) __P(( 102 bus_space_tag_t, 103 bus_space_handle_t, 104 bus_size_t)); 105 int (*sun68k_bus_subregion) __P(( 106 bus_space_tag_t, 107 bus_space_handle_t, 108 bus_size_t, /*offset*/ 109 bus_size_t, /*size*/ 110 bus_space_handle_t *)); 111 112 void (*sun68k_bus_barrier) __P(( 113 bus_space_tag_t, 114 bus_space_handle_t, 115 bus_size_t, /*offset*/ 116 bus_size_t, /*size*/ 117 int)); /*flags*/ 118 119 int (*sun68k_bus_mmap) __P(( 120 bus_space_tag_t, 121 bus_type_t, /**/ 122 bus_addr_t, /**/ 123 int, /*flags*/ 124 bus_space_handle_t *)); 125 126 void *(*sun68k_intr_establish) __P(( 127 bus_space_tag_t, 128 int, /*bus-specific intr*/ 129 int, /*device class level, 130 see machine/intr.h*/ 131 int, /*flags*/ 132 int (*) __P((void *)), /*handler*/ 133 void *)); /*handler arg*/ 134 135 int (*sun68k_bus_peek) __P(( 136 bus_space_tag_t, 137 bus_space_handle_t, 138 bus_size_t, /*offset*/ 139 size_t, /*probe size*/ 140 void *)); /*result ptr*/ 141 142 int (*sun68k_bus_poke) __P(( 143 bus_space_tag_t, 144 bus_space_handle_t, 145 bus_size_t, /*offset*/ 146 size_t, /*probe size*/ 147 u_int32_t)); /*value*/ 148 }; 149 150 #if 0 151 /* 152 * The following macro could be used to generate the bus_space*() functions 153 * but it uses a gcc extension and is ANSI-only. 154 #define PROTO_bus_space_xxx __P((bus_space_tag_t t, ...)) 155 #define RETURNTYPE_bus_space_xxx void * 156 #define BUSFUN(name, returntype, t, args...) \ 157 __inline__ RETURNTYPE_##name \ 158 bus_##name PROTO_##name \ 159 { \ 160 while (t->sun68k_##name == NULL) \ 161 t = t->parent; \ 162 return (*(t)->sun68k_##name)(t, args); \ 163 } 164 */ 165 #endif 166 167 /* 168 * Bus space function prototypes. 169 */ 170 static int bus_space_map __P(( 171 bus_space_tag_t, 172 bus_addr_t, 173 bus_size_t, 174 int, /*flags*/ 175 bus_space_handle_t *)); 176 static int bus_space_map2 __P(( 177 bus_space_tag_t, 178 bus_type_t, 179 bus_addr_t, 180 bus_size_t, 181 int, /*flags*/ 182 vaddr_t, /*preferred vaddr*/ 183 bus_space_handle_t *)); 184 static int bus_space_unmap __P(( 185 bus_space_tag_t, 186 bus_space_handle_t, 187 bus_size_t)); 188 static int bus_space_subregion __P(( 189 bus_space_tag_t, 190 bus_space_handle_t, 191 bus_size_t, 192 bus_size_t, 193 bus_space_handle_t *)); 194 static void bus_space_barrier __P(( 195 bus_space_tag_t, 196 bus_space_handle_t, 197 bus_size_t, 198 bus_size_t, 199 int)); 200 static int bus_space_mmap __P(( 201 bus_space_tag_t, 202 bus_type_t, /**/ 203 bus_addr_t, /**/ 204 int, /*flags*/ 205 bus_space_handle_t *)); 206 static void *bus_intr_establish __P(( 207 bus_space_tag_t, 208 int, /*bus-specific intr*/ 209 int, /*device class level, 210 see machine/intr.h*/ 211 int, /*flags*/ 212 int (*) __P((void *)), /*handler*/ 213 void *)); /*handler arg*/ 214 static int _bus_space_peek __P(( 215 bus_space_tag_t, 216 bus_space_handle_t, 217 bus_size_t, /*offset*/ 218 size_t, /*probe size*/ 219 void *)); /*result ptr*/ 220 static int _bus_space_poke __P(( 221 bus_space_tag_t, 222 bus_space_handle_t, 223 bus_size_t, /*offset*/ 224 size_t, /*probe size*/ 225 u_int32_t)); /*value*/ 226 227 /* This macro finds the first "upstream" implementation of method `f' */ 228 #define _BS_CALL(t,f) \ 229 while (t->f == NULL) \ 230 t = t->parent; \ 231 return (*(t)->f) 232 233 __inline__ int 234 bus_space_map(t, a, s, f, hp) 235 bus_space_tag_t t; 236 bus_addr_t a; 237 bus_size_t s; 238 int f; 239 bus_space_handle_t *hp; 240 { 241 _BS_CALL(t, sun68k_bus_map)((t), 0, (a), (s), (f), 0, (hp)); 242 } 243 244 __inline__ int 245 bus_space_map2(t, bt, a, s, f, v, hp) 246 bus_space_tag_t t; 247 bus_type_t bt; 248 bus_addr_t a; 249 bus_size_t s; 250 int f; 251 vaddr_t v; 252 bus_space_handle_t *hp; 253 { 254 _BS_CALL(t, sun68k_bus_map)(t, bt, a, s, f, v, hp); 255 } 256 257 __inline__ int 258 bus_space_unmap(t, h, s) 259 bus_space_tag_t t; 260 bus_space_handle_t h; 261 bus_size_t s; 262 { 263 _BS_CALL(t, sun68k_bus_unmap)(t, h, s); 264 } 265 266 __inline__ int 267 bus_space_subregion(t, h, o, s, hp) 268 bus_space_tag_t t; 269 bus_space_handle_t h; 270 bus_size_t o; 271 bus_size_t s; 272 bus_space_handle_t *hp; 273 { 274 _BS_CALL(t, sun68k_bus_subregion)(t, h, o, s, hp); 275 } 276 277 __inline__ int 278 bus_space_mmap(t, bt, a, f, hp) 279 bus_space_tag_t t; 280 bus_type_t bt; 281 bus_addr_t a; 282 int f; 283 bus_space_handle_t *hp; 284 { 285 _BS_CALL(t, sun68k_bus_mmap)(t, bt, a, f, hp); 286 } 287 288 __inline__ void * 289 bus_intr_establish(t, p, l, f, h, a) 290 bus_space_tag_t t; 291 int p; 292 int l; 293 int f; 294 int (*h)__P((void *)); 295 void *a; 296 { 297 _BS_CALL(t, sun68k_intr_establish)(t, p, l, f, h, a); 298 } 299 300 __inline__ void 301 bus_space_barrier(t, h, o, s, f) 302 bus_space_tag_t t; 303 bus_space_handle_t h; 304 bus_size_t o; 305 bus_size_t s; 306 int f; 307 { 308 _BS_CALL(t, sun68k_bus_barrier)(t, h, o, s, f); 309 } 310 311 __inline__ int 312 _bus_space_peek(t, h, o, s, vp) 313 bus_space_tag_t t; 314 bus_space_handle_t h; 315 bus_size_t o; 316 size_t s; 317 void *vp; 318 { 319 _BS_CALL(t, sun68k_bus_peek)(t, h, o, s, vp); 320 } 321 322 __inline__ int 323 _bus_space_poke(t, h, o, s, v) 324 bus_space_tag_t t; 325 bus_space_handle_t h; 326 bus_size_t o; 327 size_t s; 328 u_int32_t v; 329 { 330 _BS_CALL(t, sun68k_bus_poke)(t, h, o, s, v); 331 } 332 333 #if 0 334 int bus_space_alloc __P((bus_space_tag_t t, bus_addr_t rstart, 335 bus_addr_t rend, bus_size_t size, bus_size_t align, 336 bus_size_t boundary, int flags, bus_addr_t *addrp, 337 bus_space_handle_t *bshp)); 338 void bus_space_free __P((bus_space_tag_t t, bus_space_handle_t bsh, 339 bus_size_t size)); 340 #endif 341 342 /* flags for bus space map functions */ 343 #define BUS_SPACE_MAP_CACHEABLE 0x0001 344 #define BUS_SPACE_MAP_LINEAR 0x0002 345 #define BUS_SPACE_MAP_PREFETCHABLE 0x0004 346 #define BUS_SPACE_MAP_BUS1 0x0100 /* placeholders for bus functions... */ 347 #define BUS_SPACE_MAP_BUS2 0x0200 348 #define BUS_SPACE_MAP_BUS3 0x0400 349 #define BUS_SPACE_MAP_BUS4 0x0800 350 351 /* Internal flag: try to find and use a PROM maping for the device. */ 352 #define _SUN68K_BUS_MAP_USE_PROM BUS_SPACE_MAP_BUS1 353 354 /* flags for intr_establish() */ 355 #define BUS_INTR_ESTABLISH_FASTTRAP 1 356 #define BUS_INTR_ESTABLISH_SOFTINTR 2 357 358 /* flags for bus_space_barrier() */ 359 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 360 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 361 362 /* 363 * int bus_space_peek_N(bus_space_tag_t tag, 364 * bus_space_handle_t bsh, bus_size_t offset, u_intN_t *valuep); 365 * 366 * Cautiously read 1, 2, 4 or 8 byte quantity from bus space described 367 * by tag/handle/offset. 368 * If no hardware responds to the read access, the function returns a 369 * non-zero value. Otherwise the value read is placed in `valuep'. 370 */ 371 372 #define bus_space_peek_1(t, h, o, vp) \ 373 _bus_space_peek(t, h, o, sizeof(u_int8_t), (void *)vp) 374 375 #define bus_space_peek_2(t, h, o, vp) \ 376 _bus_space_peek(t, h, o, sizeof(u_int16_t), (void *)vp) 377 378 #define bus_space_peek_4(t, h, o, vp) \ 379 _bus_space_peek(t, h, o, sizeof(u_int32_t), (void *)vp) 380 381 /* 382 * int bus_space_poke_N(bus_space_tag_t tag, 383 * bus_space_handle_t bsh, bus_size_t offset, u_intN_t value); 384 * 385 * Cautiously write 1, 2, 4 or 8 byte quantity to bus space described 386 * by tag/handle/offset. 387 * If no hardware responds to the write access, the function returns a 388 * non-zero value. 389 */ 390 391 #define bus_space_poke_1(t, h, o, v) \ 392 _bus_space_poke(t, h, o, sizeof(u_int8_t), v) 393 394 #define bus_space_poke_2(t, h, o, v) \ 395 _bus_space_poke(t, h, o, sizeof(u_int16_t), v) 396 397 #define bus_space_poke_4(t, h, o, v) \ 398 _bus_space_poke(t, h, o, sizeof(u_int32_t), v) 399 400 /* 401 * u_intN_t bus_space_read_N __P((bus_space_tag_t tag, 402 * bus_space_handle_t bsh, bus_size_t offset)); 403 * 404 * Read a 1, 2, 4, or 8 byte quantity from bus space 405 * described by tag/handle/offset. 406 */ 407 408 #define bus_space_read_1(t, h, o) \ 409 ((void)t, *(volatile u_int8_t *)((h) + (o))) 410 411 #define bus_space_read_2(t, h, o) \ 412 ((void)t, *(volatile u_int16_t *)((h) + (o))) 413 414 #define bus_space_read_4(t, h, o) \ 415 ((void)t, *(volatile u_int32_t *)((h) + (o))) 416 417 #define bus_space_read_8(t, h, o) \ 418 ((void)t, *(volatile u_int64_t *)((h) + (o))) 419 420 421 /* 422 * void bus_space_write_N __P((bus_space_tag_t tag, 423 * bus_space_handle_t bsh, bus_size_t offset, 424 * u_intN_t value)); 425 * 426 * Write the 1, 2, 4, or 8 byte value `value' to bus space 427 * described by tag/handle/offset. 428 */ 429 430 #define bus_space_write_1(t, h, o, v) do { \ 431 ((void)t, (void)(*(volatile u_int8_t *)((h) + (o)) = (v))); \ 432 } while (0) 433 434 #define bus_space_write_2(t, h, o, v) do { \ 435 ((void)t, (void)(*(volatile u_int16_t *)((h) + (o)) = (v))); \ 436 } while (0) 437 438 #define bus_space_write_4(t, h, o, v) do { \ 439 ((void)t, (void)(*(volatile u_int32_t *)((h) + (o)) = (v))); \ 440 } while (0) 441 442 #define bus_space_write_8(t, h, o, v) do { \ 443 ((void)t, (void)(*(volatile u_int64_t *)((h) + (o)) = (v))); \ 444 } while (0) 445 446 447 /* 448 * void bus_space_read_multi_N __P((bus_space_tag_t tag, 449 * bus_space_handle_t bsh, bus_size_t offset, 450 * u_intN_t *addr, bus_size_t count)); 451 * 452 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 453 * described by tag/handle/offset and copy into buffer provided. 454 */ 455 456 void bus_space_read_multi_1 __P((bus_space_tag_t, 457 bus_space_handle_t, 458 bus_size_t, 459 u_int8_t *, 460 bus_size_t)); 461 462 void bus_space_read_multi_2 __P((bus_space_tag_t, 463 bus_space_handle_t, 464 bus_size_t, 465 u_int16_t *, 466 bus_size_t)); 467 468 void bus_space_read_multi_4 __P((bus_space_tag_t, 469 bus_space_handle_t, 470 bus_size_t, 471 u_int32_t *, 472 bus_size_t)); 473 474 void bus_space_read_multi_8 __P((bus_space_tag_t, 475 bus_space_handle_t, 476 bus_size_t, 477 u_int64_t *, 478 bus_size_t)); 479 480 extern __inline__ void 481 bus_space_read_multi_1(t, h, o, a, c) 482 bus_space_tag_t t; 483 bus_space_handle_t h; 484 bus_size_t o, c; 485 u_int8_t *a; 486 { 487 while (c-- > 0) 488 *a++ = bus_space_read_1(t, h, o); 489 } 490 491 extern __inline__ void 492 bus_space_read_multi_2(t, h, o, a, c) 493 bus_space_tag_t t; 494 bus_space_handle_t h; 495 bus_size_t o, c; 496 u_int16_t *a; 497 { 498 while (c-- > 0) 499 *a++ = bus_space_read_2(t, h, o); 500 } 501 502 extern __inline__ void 503 bus_space_read_multi_4(t, h, o, a, c) 504 bus_space_tag_t t; 505 bus_space_handle_t h; 506 bus_size_t o, c; 507 u_int32_t *a; 508 { 509 while (c-- > 0) 510 *a++ = bus_space_read_4(t, h, o); 511 } 512 513 extern __inline__ void 514 bus_space_read_multi_8(t, h, o, a, c) 515 bus_space_tag_t t; 516 bus_space_handle_t h; 517 bus_size_t o, c; 518 u_int64_t *a; 519 { 520 while (c-- > 0) 521 *a++ = bus_space_read_8(t, h, o); 522 } 523 524 525 /* 526 * void bus_space_write_multi_N __P((bus_space_tag_t tag, 527 * bus_space_handle_t bsh, bus_size_t offset, 528 * const u_intN_t *addr, bus_size_t count)); 529 * 530 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer 531 * provided to bus space described by tag/handle/offset. 532 */ 533 void bus_space_write_multi_1 __P((bus_space_tag_t, 534 bus_space_handle_t, 535 bus_size_t, 536 const u_int8_t *, 537 bus_size_t)); 538 void bus_space_write_multi_2 __P((bus_space_tag_t, 539 bus_space_handle_t, 540 bus_size_t, 541 const u_int16_t *, 542 bus_size_t)); 543 void bus_space_write_multi_4 __P((bus_space_tag_t, 544 bus_space_handle_t, 545 bus_size_t, 546 const u_int32_t *, 547 bus_size_t)); 548 void bus_space_write_multi_8 __P((bus_space_tag_t, 549 bus_space_handle_t, 550 bus_size_t, 551 const u_int64_t *, 552 bus_size_t)); 553 extern __inline__ void 554 bus_space_write_multi_1(t, h, o, a, c) 555 bus_space_tag_t t; 556 bus_space_handle_t h; 557 bus_size_t o, c; 558 const u_int8_t *a; 559 { 560 while (c-- > 0) 561 bus_space_write_1(t, h, o, *a++); 562 } 563 564 extern __inline__ void 565 bus_space_write_multi_2(t, h, o, a, c) 566 bus_space_tag_t t; 567 bus_space_handle_t h; 568 bus_size_t o, c; 569 const u_int16_t *a; 570 { 571 while (c-- > 0) 572 bus_space_write_2(t, h, o, *a++); 573 } 574 575 extern __inline__ void 576 bus_space_write_multi_4(t, h, o, a, c) 577 bus_space_tag_t t; 578 bus_space_handle_t h; 579 bus_size_t o, c; 580 const u_int32_t *a; 581 { 582 while (c-- > 0) 583 bus_space_write_4(t, h, o, *a++); 584 } 585 586 extern __inline__ void 587 bus_space_write_multi_8(t, h, o, a, c) 588 bus_space_tag_t t; 589 bus_space_handle_t h; 590 bus_size_t o, c; 591 const u_int64_t *a; 592 { 593 while (c-- > 0) 594 bus_space_write_8(t, h, o, *a++); 595 } 596 597 /* 598 * void bus_space_set_multi_N __P((bus_space_tag_t tag, 599 * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, 600 * bus_size_t count)); 601 * 602 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 603 * by tag/handle/offset `count' times. 604 */ 605 void bus_space_set_multi_1 __P((bus_space_tag_t, 606 bus_space_handle_t, 607 bus_size_t, 608 const u_int8_t, 609 bus_size_t)); 610 void bus_space_set_multi_2 __P((bus_space_tag_t, 611 bus_space_handle_t, 612 bus_size_t, 613 const u_int16_t, 614 bus_size_t)); 615 void bus_space_set_multi_4 __P((bus_space_tag_t, 616 bus_space_handle_t, 617 bus_size_t, 618 const u_int32_t, 619 bus_size_t)); 620 void bus_space_set_multi_8 __P((bus_space_tag_t, 621 bus_space_handle_t, 622 bus_size_t, 623 const u_int64_t, 624 bus_size_t)); 625 626 extern __inline__ void 627 bus_space_set_multi_1(t, h, o, v, c) 628 bus_space_tag_t t; 629 bus_space_handle_t h; 630 bus_size_t o, c; 631 const u_int8_t v; 632 { 633 while (c-- > 0) 634 bus_space_write_1(t, h, o, v); 635 } 636 637 extern __inline__ void 638 bus_space_set_multi_2(t, h, o, v, c) 639 bus_space_tag_t t; 640 bus_space_handle_t h; 641 bus_size_t o, c; 642 const u_int16_t v; 643 { 644 while (c-- > 0) 645 bus_space_write_2(t, h, o, v); 646 } 647 648 extern __inline__ void 649 bus_space_set_multi_4(t, h, o, v, c) 650 bus_space_tag_t t; 651 bus_space_handle_t h; 652 bus_size_t o, c; 653 const u_int32_t v; 654 { 655 while (c-- > 0) 656 bus_space_write_4(t, h, o, v); 657 } 658 659 extern __inline__ void 660 bus_space_set_multi_8(t, h, o, v, c) 661 bus_space_tag_t t; 662 bus_space_handle_t h; 663 bus_size_t o, c; 664 const u_int64_t v; 665 { 666 while (c-- > 0) 667 bus_space_write_8(t, h, o, v); 668 } 669 670 671 /* 672 * void bus_space_read_region_N __P((bus_space_tag_t tag, 673 * bus_space_handle_t bsh, bus_size_t off, 674 * u_intN_t *addr, bus_size_t count)); 675 * 676 */ 677 void bus_space_read_region_1 __P((bus_space_tag_t, 678 bus_space_handle_t, 679 bus_size_t, 680 u_int8_t *, 681 bus_size_t)); 682 void bus_space_read_region_2 __P((bus_space_tag_t, 683 bus_space_handle_t, 684 bus_size_t, 685 u_int16_t *, 686 bus_size_t)); 687 void bus_space_read_region_4 __P((bus_space_tag_t, 688 bus_space_handle_t, 689 bus_size_t, 690 u_int32_t *, 691 bus_size_t)); 692 void bus_space_read_region_8 __P((bus_space_tag_t, 693 bus_space_handle_t, 694 bus_size_t, 695 u_int64_t *, 696 bus_size_t)); 697 698 extern __inline__ void 699 bus_space_read_region_1(t, h, o, a, c) 700 bus_space_tag_t t; 701 bus_space_handle_t h; 702 bus_size_t o, c; 703 u_int8_t *a; 704 { 705 for (; c; a++, c--, o++) 706 *a = bus_space_read_1(t, h, o); 707 } 708 extern __inline__ void 709 bus_space_read_region_2(t, h, o, a, c) 710 bus_space_tag_t t; 711 bus_space_handle_t h; 712 bus_size_t o, c; 713 u_int16_t *a; 714 { 715 for (; c; a++, c--, o+=2) 716 *a = bus_space_read_2(t, h, o); 717 } 718 extern __inline__ void 719 bus_space_read_region_4(t, h, o, a, c) 720 bus_space_tag_t t; 721 bus_space_handle_t h; 722 bus_size_t o, c; 723 u_int32_t *a; 724 { 725 for (; c; a++, c--, o+=4) 726 *a = bus_space_read_4(t, h, o); 727 } 728 extern __inline__ void 729 bus_space_read_region_8(t, h, o, a, c) 730 bus_space_tag_t t; 731 bus_space_handle_t h; 732 bus_size_t o, c; 733 u_int64_t *a; 734 { 735 for (; c; a++, c--, o+=8) 736 *a = bus_space_read_8(t, h, o); 737 } 738 739 /* 740 * void bus_space_write_region_N __P((bus_space_tag_t tag, 741 * bus_space_handle_t bsh, bus_size_t off, 742 * u_intN_t *addr, bus_size_t count)); 743 * 744 */ 745 void bus_space_write_region_1 __P((bus_space_tag_t, 746 bus_space_handle_t, 747 bus_size_t, 748 const u_int8_t *, 749 bus_size_t)); 750 void bus_space_write_region_2 __P((bus_space_tag_t, 751 bus_space_handle_t, 752 bus_size_t, 753 const u_int16_t *, 754 bus_size_t)); 755 void bus_space_write_region_4 __P((bus_space_tag_t, 756 bus_space_handle_t, 757 bus_size_t, 758 const u_int32_t *, 759 bus_size_t)); 760 void bus_space_write_region_8 __P((bus_space_tag_t, 761 bus_space_handle_t, 762 bus_size_t, 763 const u_int64_t *, 764 bus_size_t)); 765 extern __inline__ void 766 bus_space_write_region_1(t, h, o, a, c) 767 bus_space_tag_t t; 768 bus_space_handle_t h; 769 bus_size_t o, c; 770 const u_int8_t *a; 771 { 772 for (; c; a++, c--, o++) 773 bus_space_write_1(t, h, o, *a); 774 } 775 776 extern __inline__ void 777 bus_space_write_region_2(t, h, o, a, c) 778 bus_space_tag_t t; 779 bus_space_handle_t h; 780 bus_size_t o, c; 781 const u_int16_t *a; 782 { 783 for (; c; a++, c--, o+=2) 784 bus_space_write_2(t, h, o, *a); 785 } 786 787 extern __inline__ void 788 bus_space_write_region_4(t, h, o, a, c) 789 bus_space_tag_t t; 790 bus_space_handle_t h; 791 bus_size_t o, c; 792 const u_int32_t *a; 793 { 794 for (; c; a++, c--, o+=4) 795 bus_space_write_4(t, h, o, *a); 796 } 797 798 extern __inline__ void 799 bus_space_write_region_8(t, h, o, a, c) 800 bus_space_tag_t t; 801 bus_space_handle_t h; 802 bus_size_t o, c; 803 const u_int64_t *a; 804 { 805 for (; c; a++, c--, o+=8) 806 bus_space_write_8(t, h, o, *a); 807 } 808 809 810 /* 811 * void bus_space_set_region_N __P((bus_space_tag_t tag, 812 * bus_space_handle_t bsh, bus_size_t off, 813 * u_intN_t *addr, bus_size_t count)); 814 * 815 */ 816 void bus_space_set_region_1 __P((bus_space_tag_t, 817 bus_space_handle_t, 818 bus_size_t, 819 const u_int8_t, 820 bus_size_t)); 821 void bus_space_set_region_2 __P((bus_space_tag_t, 822 bus_space_handle_t, 823 bus_size_t, 824 const u_int16_t, 825 bus_size_t)); 826 void bus_space_set_region_4 __P((bus_space_tag_t, 827 bus_space_handle_t, 828 bus_size_t, 829 const u_int32_t, 830 bus_size_t)); 831 void bus_space_set_region_8 __P((bus_space_tag_t, 832 bus_space_handle_t, 833 bus_size_t, 834 const u_int64_t, 835 bus_size_t)); 836 837 extern __inline__ void 838 bus_space_set_region_1(t, h, o, v, c) 839 bus_space_tag_t t; 840 bus_space_handle_t h; 841 bus_size_t o, c; 842 const u_int8_t v; 843 { 844 for (; c; c--, o++) 845 bus_space_write_1(t, h, o, v); 846 } 847 848 extern __inline__ void 849 bus_space_set_region_2(t, h, o, v, c) 850 bus_space_tag_t t; 851 bus_space_handle_t h; 852 bus_size_t o, c; 853 const u_int16_t v; 854 { 855 for (; c; c--, o+=2) 856 bus_space_write_2(t, h, o, v); 857 } 858 859 extern __inline__ void 860 bus_space_set_region_4(t, h, o, v, c) 861 bus_space_tag_t t; 862 bus_space_handle_t h; 863 bus_size_t o, c; 864 const u_int32_t v; 865 { 866 for (; c; c--, o+=4) 867 bus_space_write_4(t, h, o, v); 868 } 869 870 extern __inline__ void 871 bus_space_set_region_8(t, h, o, v, c) 872 bus_space_tag_t t; 873 bus_space_handle_t h; 874 bus_size_t o, c; 875 const u_int64_t v; 876 { 877 for (; c; c--, o+=8) 878 bus_space_write_8(t, h, o, v); 879 } 880 881 882 /* 883 * void bus_space_copy_region_N __P((bus_space_tag_t tag, 884 * bus_space_handle_t bsh1, bus_size_t off1, 885 * bus_space_handle_t bsh2, bus_size_t off2, 886 * bus_size_t count)); 887 * 888 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting 889 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. 890 */ 891 void bus_space_copy_region_1 __P((bus_space_tag_t, 892 bus_space_handle_t, 893 bus_size_t, 894 bus_space_handle_t, 895 bus_size_t, 896 bus_size_t)); 897 void bus_space_copy_region_2 __P((bus_space_tag_t, 898 bus_space_handle_t, 899 bus_size_t, 900 bus_space_handle_t, 901 bus_size_t, 902 bus_size_t)); 903 void bus_space_copy_region_4 __P((bus_space_tag_t, 904 bus_space_handle_t, 905 bus_size_t, 906 bus_space_handle_t, 907 bus_size_t, 908 bus_size_t)); 909 void bus_space_copy_region_8 __P((bus_space_tag_t, 910 bus_space_handle_t, 911 bus_size_t, 912 bus_space_handle_t, 913 bus_size_t, 914 bus_size_t)); 915 916 917 extern __inline__ void 918 bus_space_copy_region_1(t, h1, o1, h2, o2, c) 919 bus_space_tag_t t; 920 bus_space_handle_t h1, h2; 921 bus_size_t o1, o2; 922 bus_size_t c; 923 { 924 for (; c; c--, o1++, o2++) 925 bus_space_write_1(t, h1, o1, bus_space_read_1(t, h2, o2)); 926 } 927 928 extern __inline__ void 929 bus_space_copy_region_2(t, h1, o1, h2, o2, c) 930 bus_space_tag_t t; 931 bus_space_handle_t h1, h2; 932 bus_size_t o1, o2; 933 bus_size_t c; 934 { 935 for (; c; c--, o1+=2, o2+=2) 936 bus_space_write_2(t, h1, o1, bus_space_read_2(t, h2, o2)); 937 } 938 939 extern __inline__ void 940 bus_space_copy_region_4(t, h1, o1, h2, o2, c) 941 bus_space_tag_t t; 942 bus_space_handle_t h1, h2; 943 bus_size_t o1, o2; 944 bus_size_t c; 945 { 946 for (; c; c--, o1+=4, o2+=4) 947 bus_space_write_4(t, h1, o1, bus_space_read_4(t, h2, o2)); 948 } 949 950 extern __inline__ void 951 bus_space_copy_region_8(t, h1, o1, h2, o2, c) 952 bus_space_tag_t t; 953 bus_space_handle_t h1, h2; 954 bus_size_t o1, o2; 955 bus_size_t c; 956 { 957 for (; c; c--, o1+=8, o2+=8) 958 bus_space_write_8(t, h1, o1, bus_space_read_8(t, h2, o2)); 959 } 960 961 /* 962 * void bus_space_copyin __P((bus_space_tag_t tag, 963 * bus_space_handle_t bsh, bus_size_t off, 964 * void *addr, bus_size_t count)); 965 * 966 * Copy `count' bytes from bus space starting at tag/bsh/off 967 * to kernel memory at addr using the most optimized transfer 968 * possible for the bus. 969 */ 970 971 #define bus_space_copyin(t, h, o, a, c) \ 972 ((void)t, w16copy((u_int8_t *)((h) + (o)), (a), (c))) 973 974 /* 975 * void bus_space_copyout __P((bus_space_tag_t tag, 976 * bus_space_handle_t bsh, bus_size_t off, 977 * const void *addr, bus_size_t count)); 978 * 979 * Copy `count' bytes to bus space starting at tag/bsh/off 980 * from kernel memory at addr using the most optimized transfer 981 * possible for the bus. 982 */ 983 984 #define bus_space_copyout(t, h, o, a, c) \ 985 ((void)t, w16copy((a), (u_int8_t *)((h) + (o)), (c))) 986 987 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) 988 989 /*--------------------------------*/ 990 991 /* 992 * Flags used in various bus DMA methods. 993 */ 994 #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ 995 #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ 996 #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ 997 #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ 998 #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ 999 #define BUS_DMA_BUS2 0x020 1000 #define BUS_DMA_BUS3 0x040 1001 #define BUS_DMA_BUS4 0x080 1002 #define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ 1003 #define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ 1004 1005 /* For devices that have a 24-bit address space */ 1006 #define BUS_DMA_24BIT BUS_DMA_BUS1 1007 1008 /* Internal flag: current DVMA address is equal to the KVA buffer address */ 1009 #define _BUS_DMA_DIRECTMAP BUS_DMA_BUS2 1010 1011 /* 1012 * Internal flag: current DVMA address has been double-mapped by hand 1013 * to the KVA buffer address (without the pmap's help). 1014 */ 1015 #define _BUS_DMA_NOPMAP BUS_DMA_BUS3 1016 1017 /* Forwards needed by prototypes below. */ 1018 struct mbuf; 1019 struct uio; 1020 1021 /* 1022 * Operations performed by bus_dmamap_sync(). 1023 */ 1024 #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ 1025 #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ 1026 #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ 1027 #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ 1028 1029 typedef struct sun68k_bus_dma_tag *bus_dma_tag_t; 1030 typedef struct sun68k_bus_dmamap *bus_dmamap_t; 1031 1032 /* 1033 * bus_dma_segment_t 1034 * 1035 * Describes a single contiguous DMA transaction. Values 1036 * are suitable for programming into DMA registers. 1037 */ 1038 struct sun68k_bus_dma_segment { 1039 bus_addr_t ds_addr; /* DVMA address */ 1040 bus_size_t ds_len; /* length of transfer */ 1041 bus_size_t _ds_sgsize; /* size of allocated DVMA segment */ 1042 void *_ds_mlist; /* page list when dmamem_alloc'ed */ 1043 vaddr_t _ds_va; /* VA when dmamem_map'ed */ 1044 }; 1045 typedef struct sun68k_bus_dma_segment bus_dma_segment_t; 1046 1047 1048 /* 1049 * bus_dma_tag_t 1050 * 1051 * A machine-dependent opaque type describing the implementation of 1052 * DMA for a given bus. 1053 */ 1054 struct sun68k_bus_dma_tag { 1055 void *_cookie; /* cookie used in the guts */ 1056 1057 /* 1058 * DMA mapping methods. 1059 */ 1060 int (*_dmamap_create) __P((bus_dma_tag_t, bus_size_t, int, 1061 bus_size_t, bus_size_t, int, bus_dmamap_t *)); 1062 void (*_dmamap_destroy) __P((bus_dma_tag_t, bus_dmamap_t)); 1063 int (*_dmamap_load) __P((bus_dma_tag_t, bus_dmamap_t, void *, 1064 bus_size_t, struct proc *, int)); 1065 int (*_dmamap_load_mbuf) __P((bus_dma_tag_t, bus_dmamap_t, 1066 struct mbuf *, int)); 1067 int (*_dmamap_load_uio) __P((bus_dma_tag_t, bus_dmamap_t, 1068 struct uio *, int)); 1069 int (*_dmamap_load_raw) __P((bus_dma_tag_t, bus_dmamap_t, 1070 bus_dma_segment_t *, int, bus_size_t, int)); 1071 void (*_dmamap_unload) __P((bus_dma_tag_t, bus_dmamap_t)); 1072 void (*_dmamap_sync) __P((bus_dma_tag_t, bus_dmamap_t, 1073 bus_addr_t, bus_size_t, int)); 1074 1075 /* 1076 * DMA memory utility functions. 1077 */ 1078 int (*_dmamem_alloc) __P((bus_dma_tag_t, bus_size_t, bus_size_t, 1079 bus_size_t, bus_dma_segment_t *, int, int *, int)); 1080 void (*_dmamem_free) __P((bus_dma_tag_t, 1081 bus_dma_segment_t *, int)); 1082 int (*_dmamem_map) __P((bus_dma_tag_t, bus_dma_segment_t *, 1083 int, size_t, caddr_t *, int)); 1084 void (*_dmamem_unmap) __P((bus_dma_tag_t, caddr_t, size_t)); 1085 paddr_t (*_dmamem_mmap) __P((bus_dma_tag_t, bus_dma_segment_t *, 1086 int, off_t, int, int)); 1087 }; 1088 1089 #define bus_dmamap_create(t, s, n, m, b, f, p) \ 1090 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) 1091 #define bus_dmamap_destroy(t, p) \ 1092 (*(t)->_dmamap_destroy)((t), (p)) 1093 #define bus_dmamap_load(t, m, b, s, p, f) \ 1094 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) 1095 #define bus_dmamap_load_mbuf(t, m, b, f) \ 1096 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) 1097 #define bus_dmamap_load_uio(t, m, u, f) \ 1098 (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) 1099 #define bus_dmamap_load_raw(t, m, sg, n, s, f) \ 1100 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) 1101 #define bus_dmamap_unload(t, p) \ 1102 (*(t)->_dmamap_unload)((t), (p)) 1103 #define bus_dmamap_sync(t, p, o, l, ops) \ 1104 (void)((t)->_dmamap_sync ? \ 1105 (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0) 1106 1107 #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ 1108 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) 1109 #define bus_dmamem_free(t, sg, n) \ 1110 (*(t)->_dmamem_free)((t), (sg), (n)) 1111 #define bus_dmamem_map(t, sg, n, s, k, f) \ 1112 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) 1113 #define bus_dmamem_unmap(t, k, s) \ 1114 (*(t)->_dmamem_unmap)((t), (k), (s)) 1115 #define bus_dmamem_mmap(t, sg, n, o, p, f) \ 1116 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) 1117 1118 /* 1119 * bus_dmamap_t 1120 * 1121 * Describes a DMA mapping. 1122 */ 1123 struct sun68k_bus_dmamap { 1124 /* 1125 * PRIVATE MEMBERS: not for use by machine-independent code. 1126 */ 1127 bus_size_t _dm_size; /* largest DMA transfer mappable */ 1128 int _dm_segcnt; /* number of segs this map can map */ 1129 bus_size_t _dm_maxsegsz; /* largest possible segment */ 1130 bus_size_t _dm_boundary; /* don't cross this */ 1131 int _dm_flags; /* misc. flags */ 1132 1133 void *_dm_cookie; /* cookie for bus-specific functions */ 1134 1135 u_long _dm_align; /* DVMA alignment; must be a 1136 multiple of the page size */ 1137 u_long _dm_ex_start; /* constraints on DVMA map */ 1138 u_long _dm_ex_end; /* allocations; used by the VME bus 1139 driver and by the IOMMU driver 1140 when mapping 24-bit devices */ 1141 1142 /* 1143 * PUBLIC MEMBERS: these are used by machine-independent code. 1144 */ 1145 bus_size_t dm_mapsize; /* size of the mapping */ 1146 int dm_nsegs; /* # valid segments in mapping */ 1147 bus_dma_segment_t dm_segs[1]; /* segments; variable length */ 1148 }; 1149 1150 #ifdef _SUN68K_BUS_DMA_PRIVATE 1151 int _bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int, bus_size_t, 1152 bus_size_t, int, bus_dmamap_t *)); 1153 void _bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t)); 1154 int _bus_dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t, 1155 struct mbuf *, int)); 1156 int _bus_dmamap_load_uio __P((bus_dma_tag_t, bus_dmamap_t, 1157 struct uio *, int)); 1158 int _bus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t, 1159 bus_dma_segment_t *, int, bus_size_t, int)); 1160 int _bus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *, 1161 bus_size_t, struct proc *, int)); 1162 void _bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t)); 1163 void _bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 1164 bus_size_t, int)); 1165 1166 int _bus_dmamem_alloc __P((bus_dma_tag_t tag, bus_size_t size, 1167 bus_size_t alignment, bus_size_t boundary, 1168 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags)); 1169 void _bus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, 1170 int nsegs)); 1171 int _bus_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, 1172 int nsegs, size_t size, caddr_t *kvap, 1173 int flags)); 1174 void _bus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva, 1175 size_t size)); 1176 paddr_t _bus_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, 1177 int nsegs, off_t off, int prot, int flags)); 1178 1179 int _bus_dmamem_alloc_range __P((bus_dma_tag_t tag, bus_size_t size, 1180 bus_size_t alignment, bus_size_t boundary, 1181 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, 1182 vaddr_t low, vaddr_t high)); 1183 1184 vaddr_t _bus_dma_valloc_skewed(size_t, u_long, u_long, u_long); 1185 #endif /* _SUN68K_BUS_DMA_PRIVATE */ 1186 1187 #endif /* _SUN68K_BUS_H_ */ 1188