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