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