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