1 /* $NetBSD: bus.h,v 1.17 2008/07/01 15:14:32 tsutsui 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 __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 __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 __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 __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 __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 __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 __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 __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 __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 __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 void bus_space_read_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 436 uint8_t *, bus_size_t); 437 void bus_space_read_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 438 uint16_t *, bus_size_t); 439 void bus_space_read_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 440 uint32_t *, bus_size_t); 441 void bus_space_read_multi_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 442 uint64_t *, bus_size_t); 443 444 extern __inline void 445 bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 446 uint8_t *a, bus_size_t c) 447 { 448 volatile uint8_t *p; 449 450 p = (volatile uint8_t *)(h + o); 451 while (c-- > 0) 452 *a++ = *p; 453 } 454 455 extern __inline void 456 bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 457 uint16_t *a, bus_size_t c) 458 { 459 volatile uint16_t *p; 460 461 p = (volatile uint16_t *)(h + o); 462 while (c-- > 0) 463 *a++ = *p; 464 } 465 466 extern __inline void 467 bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 468 uint32_t *a, bus_size_t c) 469 { 470 volatile uint32_t *p; 471 472 p = (volatile uint32_t *)(h + o); 473 while (c-- > 0) 474 *a++ = *p; 475 } 476 477 extern __inline void 478 bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 479 uint64_t *a, bus_size_t c) 480 { 481 volatile uint64_t *p; 482 483 p = (volatile uint64_t *)(h + o); 484 while (c-- > 0) 485 *a++ = *p; 486 } 487 488 489 /* 490 * void bus_space_write_multi_N(bus_space_tag_t tag, 491 * bus_space_handle_t bsh, bus_size_t offset, 492 * const u_intN_t *addr, bus_size_t count); 493 * 494 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer 495 * provided to bus space described by tag/handle/offset. 496 */ 497 void bus_space_write_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 498 const uint8_t *, bus_size_t); 499 void bus_space_write_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 500 const uint16_t *, bus_size_t); 501 void bus_space_write_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 502 const uint32_t *, bus_size_t); 503 void bus_space_write_multi_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 504 const uint64_t *, bus_size_t); 505 506 extern __inline void 507 bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 508 const uint8_t *a, bus_size_t c) 509 { 510 volatile uint8_t *p; 511 512 p = (volatile uint8_t *)(h + o); 513 while (c-- > 0) 514 *p = *a++; 515 } 516 517 extern __inline void 518 bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 519 const uint16_t *a, bus_size_t c) 520 { 521 volatile uint16_t *p; 522 523 p = (volatile uint16_t *)(h + o); 524 while (c-- > 0) 525 *p = *a++; 526 } 527 528 extern __inline void 529 bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 530 const uint32_t *a, bus_size_t c) 531 { 532 volatile uint32_t *p; 533 534 p = (volatile uint32_t *)(h + o); 535 while (c-- > 0) 536 *p = *a++; 537 } 538 539 extern __inline void 540 bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 541 const uint64_t *a, bus_size_t c) 542 { 543 volatile uint64_t *p; 544 545 p = (volatile uint64_t *)(h + o); 546 while (c-- > 0) 547 *p = *a++; 548 } 549 550 /* 551 * void bus_space_set_multi_N(bus_space_tag_t tag, 552 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val, 553 * bus_size_t count); 554 * 555 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 556 * by tag/handle/offset `count' times. 557 */ 558 void bus_space_set_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 559 const uint8_t, bus_size_t); 560 void bus_space_set_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 561 const uint16_t, bus_size_t); 562 void bus_space_set_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 563 const uint32_t, bus_size_t); 564 void bus_space_set_multi_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 565 const uint64_t, bus_size_t); 566 567 extern __inline void 568 bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 569 const uint8_t v, bus_size_t c) 570 { 571 volatile uint8_t *p; 572 573 p = (volatile uint8_t *)(h + o); 574 while (c-- > 0) 575 *p = v; 576 } 577 578 extern __inline void 579 bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 580 const uint16_t v, bus_size_t c) 581 { 582 volatile uint16_t *p; 583 584 p = (volatile uint16_t *)(h + o); 585 while (c-- > 0) 586 *p = v; 587 } 588 589 extern __inline void 590 bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 591 const uint32_t v, bus_size_t c) 592 { 593 volatile uint32_t *p; 594 595 p = (volatile uint32_t *)(h + o); 596 while (c-- > 0) 597 *p = v; 598 } 599 600 extern __inline void 601 bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 602 const uint64_t v, bus_size_t c) 603 { 604 volatile uint64_t *p; 605 606 p = (volatile uint64_t *)(h + o); 607 while (c-- > 0) 608 *p = v; 609 } 610 611 612 /* 613 * void bus_space_read_region_N(bus_space_tag_t tag, 614 * bus_space_handle_t bsh, bus_size_t off, 615 * uintN_t *addr, bus_size_t count); 616 * 617 */ 618 void bus_space_read_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 619 uint8_t *, bus_size_t); 620 void bus_space_read_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 621 uint16_t *, bus_size_t); 622 void bus_space_read_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 623 uint32_t *, bus_size_t); 624 void bus_space_read_region_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 625 uint64_t *, bus_size_t); 626 627 extern __inline void 628 bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 629 uint8_t *a, bus_size_t c) 630 { 631 volatile uint8_t *p; 632 633 p = (volatile uint8_t *)(h + o); 634 while (c-- > 0) 635 *a++ = *p++; 636 } 637 extern __inline void 638 bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 639 uint16_t *a, bus_size_t c) 640 { 641 volatile uint16_t *p; 642 643 p = (volatile uint16_t *)(h + o); 644 while (c-- > 0) 645 *a++ = *p++; 646 } 647 extern __inline void 648 bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 649 uint32_t *a, bus_size_t c) 650 { 651 volatile uint32_t *p; 652 653 p = (volatile uint32_t *)(h + o); 654 while (c-- > 0) 655 *a++ = *p++; 656 } 657 extern __inline void 658 bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 659 uint64_t *a, bus_size_t c) 660 { 661 volatile uint64_t *p; 662 663 p = (volatile uint64_t *)(h + o); 664 while (c-- > 0) 665 *a++ = *p++; 666 } 667 668 /* 669 * void bus_space_write_region_N(bus_space_tag_t tag, 670 * bus_space_handle_t bsh, bus_size_t off, 671 * uintN_t *addr, bus_size_t count); 672 * 673 */ 674 void bus_space_write_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 675 const uint8_t *, bus_size_t); 676 void bus_space_write_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 677 const uint16_t *, bus_size_t); 678 void bus_space_write_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 679 const uint32_t *, bus_size_t); 680 void bus_space_write_region_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 681 const uint64_t *, bus_size_t); 682 683 extern __inline void 684 bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 685 const uint8_t *a, bus_size_t c) 686 { 687 volatile uint8_t *p; 688 689 p = (volatile uint8_t *)(h + o); 690 while (c-- > 0) 691 *p++ = *a++; 692 } 693 694 extern __inline void 695 bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 696 const uint16_t *a, bus_size_t c) 697 { 698 volatile uint16_t *p; 699 700 p = (volatile uint16_t *)(h + o); 701 while (c-- > 0) 702 *p++ = *a++; 703 } 704 705 extern __inline void 706 bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 707 const uint32_t *a, bus_size_t c) 708 { 709 volatile uint32_t *p; 710 711 p = (volatile uint32_t *)(h + o); 712 while (c-- > 0) 713 *p++ = *a++; 714 } 715 716 extern __inline void 717 bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 718 const uint64_t *a, bus_size_t c) 719 { 720 volatile uint64_t *p; 721 722 p = (volatile uint64_t *)(h + o); 723 while (c-- > 0) 724 *p++ = *a++; 725 } 726 727 728 /* 729 * void bus_space_set_region_N(bus_space_tag_t tag, 730 * bus_space_handle_t bsh, bus_size_t off, 731 * uintN_t *addr, bus_size_t count); 732 * 733 */ 734 void bus_space_set_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 735 const uint8_t, bus_size_t); 736 void bus_space_set_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 737 const uint16_t, bus_size_t); 738 void bus_space_set_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 739 const uint32_t, bus_size_t); 740 void bus_space_set_region_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 741 const uint64_t, bus_size_t); 742 743 extern __inline void 744 bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 745 const uint8_t v, bus_size_t c) 746 { 747 volatile uint8_t *p; 748 749 p = (volatile uint8_t *)(h + o); 750 while (c-- > 0) 751 *p++ = v; 752 } 753 754 extern __inline void 755 bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 756 const uint16_t v, bus_size_t c) 757 { 758 volatile uint16_t *p; 759 760 p = (volatile uint16_t *)(h + o); 761 while (c-- > 0) 762 *p++ = v; 763 } 764 765 extern __inline void 766 bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 767 const uint32_t v, bus_size_t c) 768 { 769 volatile uint32_t *p; 770 771 p = (volatile uint32_t *)(h + o); 772 while (c-- > 0) 773 *p++ = v; 774 } 775 776 extern __inline void 777 bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 778 const uint64_t v, bus_size_t c) 779 { 780 volatile uint64_t *p; 781 782 p = (volatile uint64_t *)(h + o); 783 while (c-- > 0) 784 *p++ = v; 785 } 786 787 788 /* 789 * void bus_space_copy_region_N(bus_space_tag_t tag, 790 * bus_space_handle_t bsh1, bus_size_t off1, 791 * bus_space_handle_t bsh2, bus_size_t off2, 792 * bus_size_t count); 793 * 794 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting 795 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. 796 */ 797 void bus_space_copy_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 798 bus_space_handle_t, bus_size_t, bus_size_t); 799 void bus_space_copy_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 800 bus_space_handle_t, bus_size_t, bus_size_t); 801 void bus_space_copy_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 802 bus_space_handle_t, bus_size_t, bus_size_t); 803 void bus_space_copy_region_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 804 bus_space_handle_t, bus_size_t, bus_size_t); 805 806 extern __inline void 807 bus_space_copy_region_1(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, 808 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 809 { 810 volatile uint8_t *srcp, *dstp; 811 bus_size_t offset; 812 813 srcp = (volatile uint8_t *)(h1 + o1); 814 dstp = (volatile uint8_t *)(h2 + o2); 815 if (srcp >= dstp) { 816 /* src after dest; copy forward */ 817 for (offset = 0; c > 0; c--, offset++) 818 dstp[offset] = srcp[offset]; 819 } else { 820 /* dst after src; copy backward */ 821 for (offset = c; c > 0; c--, offset--) 822 dstp[offset] = srcp[offset]; 823 } 824 } 825 826 extern __inline void 827 bus_space_copy_region_2(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, 828 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 829 { 830 volatile uint16_t *srcp, *dstp; 831 bus_size_t offset; 832 833 srcp = (volatile uint16_t *)(h1 + o1); 834 dstp = (volatile uint16_t *)(h2 + o2); 835 if (srcp >= dstp) { 836 /* src after dest; copy forward */ 837 for (offset = 0; c > 0; c--, offset++) 838 dstp[offset] = srcp[offset]; 839 } else { 840 /* dst after src; copy backward */ 841 for (offset = c; c > 0; c--, offset--) 842 dstp[offset] = srcp[offset]; 843 } 844 } 845 846 extern __inline void 847 bus_space_copy_region_4(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, 848 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 849 { 850 volatile uint32_t *srcp, *dstp; 851 bus_size_t offset; 852 853 srcp = (volatile uint32_t *)(h1 + o1); 854 dstp = (volatile uint32_t *)(h2 + o2); 855 if (srcp >= dstp) { 856 /* src after dest; copy forward */ 857 for (offset = 0; c > 0; c--, offset++) 858 dstp[offset] = srcp[offset]; 859 } else { 860 /* dst after src; copy backward */ 861 for (offset = c; c > 0; c--, offset--) 862 dstp[offset] = srcp[offset]; 863 } 864 } 865 866 extern __inline void 867 bus_space_copy_region_8(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, 868 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 869 { 870 volatile uint64_t *srcp, *dstp; 871 bus_size_t offset; 872 873 srcp = (volatile uint64_t *)(h1 + o1); 874 dstp = (volatile uint64_t *)(h2 + o2); 875 if (srcp >= dstp) { 876 /* src after dest; copy forward */ 877 for (offset = 0; c > 0; c--, offset++) 878 dstp[offset] = srcp[offset]; 879 } else { 880 /* dst after src; copy backward */ 881 for (offset = c; c > 0; c--, offset--) 882 dstp[offset] = srcp[offset]; 883 } 884 } 885 886 /* 887 * void bus_space_copyin(bus_space_tag_t tag, 888 * bus_space_handle_t bsh, bus_size_t off, 889 * void *addr, bus_size_t count); 890 * 891 * Copy `count' bytes from bus space starting at tag/bsh/off 892 * to kernel memory at addr using the most optimized transfer 893 * possible for the bus. 894 */ 895 896 #define bus_space_copyin(t, h, o, a, c) \ 897 ((void)t, w16copy((uint8_t *)((h) + (o)), (a), (c))) 898 899 /* 900 * void bus_space_copyout(bus_space_tag_t tag, 901 * bus_space_handle_t bsh, bus_size_t off, 902 * const void *addr, bus_size_t count); 903 * 904 * Copy `count' bytes to bus space starting at tag/bsh/off 905 * from kernel memory at addr using the most optimized transfer 906 * possible for the bus. 907 */ 908 909 #define bus_space_copyout(t, h, o, a, c) \ 910 ((void)t, w16copy((a), (uint8_t *)((h) + (o)), (c))) 911 912 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) 913 914 int find_prom_map(paddr_t, bus_type_t, int, vaddr_t *); 915 916 /*--------------------------------*/ 917 918 /* 919 * Flags used in various bus DMA methods. 920 */ 921 #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ 922 #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ 923 #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ 924 #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ 925 #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ 926 #define BUS_DMA_BUS2 0x020 927 #define BUS_DMA_BUS3 0x040 928 #define BUS_DMA_BUS4 0x080 929 #define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ 930 #define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ 931 #define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */ 932 933 /* For devices that have a 24-bit address space */ 934 #define BUS_DMA_24BIT BUS_DMA_BUS1 935 936 /* Internal flag: current DVMA address is equal to the KVA buffer address */ 937 #define _BUS_DMA_DIRECTMAP BUS_DMA_BUS2 938 939 /* 940 * Internal flag: current DVMA address has been double-mapped by hand 941 * to the KVA buffer address (without the pmap's help). 942 */ 943 #define _BUS_DMA_NOPMAP BUS_DMA_BUS3 944 945 /* Forwards needed by prototypes below. */ 946 struct mbuf; 947 struct uio; 948 949 /* 950 * Operations performed by bus_dmamap_sync(). 951 */ 952 #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ 953 #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ 954 #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ 955 #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ 956 957 typedef struct sun68k_bus_dma_tag *bus_dma_tag_t; 958 typedef struct sun68k_bus_dmamap *bus_dmamap_t; 959 960 #define BUS_DMA_TAG_VALID(t) ((t) != NULL) 961 962 /* 963 * bus_dma_segment_t 964 * 965 * Describes a single contiguous DMA transaction. Values 966 * are suitable for programming into DMA registers. 967 */ 968 struct sun68k_bus_dma_segment { 969 bus_addr_t ds_addr; /* DVMA address */ 970 bus_size_t ds_len; /* length of transfer */ 971 bus_size_t _ds_sgsize; /* size of allocated DVMA segment */ 972 void *_ds_mlist; /* page list when dmamem_alloc'ed */ 973 vaddr_t _ds_va; /* VA when dmamem_map'ed */ 974 }; 975 typedef struct sun68k_bus_dma_segment bus_dma_segment_t; 976 977 978 /* 979 * bus_dma_tag_t 980 * 981 * A machine-dependent opaque type describing the implementation of 982 * DMA for a given bus. 983 */ 984 struct sun68k_bus_dma_tag { 985 void *_cookie; /* cookie used in the guts */ 986 987 /* 988 * DMA mapping methods. 989 */ 990 int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, bus_size_t, 991 bus_size_t, int, bus_dmamap_t *); 992 void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); 993 int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, 994 struct proc *, int); 995 int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, 996 int); 997 int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, struct uio *, 998 int); 999 int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, 1000 bus_dma_segment_t *, int, bus_size_t, int); 1001 void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); 1002 void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 1003 bus_size_t, int); 1004 1005 /* 1006 * DMA memory utility functions. 1007 */ 1008 int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, 1009 bus_size_t, bus_dma_segment_t *, int, int *, int); 1010 void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); 1011 int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, int, size_t, 1012 void **, int); 1013 void (*_dmamem_unmap)(bus_dma_tag_t, void *, size_t); 1014 paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, 1015 int, int); 1016 }; 1017 1018 #define bus_dmamap_create(t, s, n, m, b, f, p) \ 1019 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) 1020 #define bus_dmamap_destroy(t, p) \ 1021 (*(t)->_dmamap_destroy)((t), (p)) 1022 #define bus_dmamap_load(t, m, b, s, p, f) \ 1023 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) 1024 #define bus_dmamap_load_mbuf(t, m, b, f) \ 1025 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) 1026 #define bus_dmamap_load_uio(t, m, u, f) \ 1027 (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) 1028 #define bus_dmamap_load_raw(t, m, sg, n, s, f) \ 1029 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) 1030 #define bus_dmamap_unload(t, p) \ 1031 (*(t)->_dmamap_unload)((t), (p)) 1032 #define bus_dmamap_sync(t, p, o, l, ops) \ 1033 (void)((t)->_dmamap_sync ? \ 1034 (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0) 1035 1036 #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ 1037 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) 1038 #define bus_dmamem_free(t, sg, n) \ 1039 (*(t)->_dmamem_free)((t), (sg), (n)) 1040 #define bus_dmamem_map(t, sg, n, s, k, f) \ 1041 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) 1042 #define bus_dmamem_unmap(t, k, s) \ 1043 (*(t)->_dmamem_unmap)((t), (k), (s)) 1044 #define bus_dmamem_mmap(t, sg, n, o, p, f) \ 1045 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) 1046 1047 #define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP 1048 #define bus_dmatag_destroy(t) 1049 1050 /* 1051 * bus_dmamap_t 1052 * 1053 * Describes a DMA mapping. 1054 */ 1055 struct sun68k_bus_dmamap { 1056 /* 1057 * PRIVATE MEMBERS: not for use by machine-independent code. 1058 */ 1059 bus_size_t _dm_size; /* largest DMA transfer mappable */ 1060 int _dm_segcnt; /* number of segs this map can map */ 1061 bus_size_t _dm_maxmaxsegsz; /* fixed largest possible segment */ 1062 bus_size_t _dm_boundary; /* don't cross this */ 1063 int _dm_flags; /* misc. flags */ 1064 1065 void *_dm_cookie; /* cookie for bus-specific functions */ 1066 1067 u_long _dm_align; /* DVMA alignment; must be a 1068 multiple of the page size */ 1069 u_long _dm_ex_start; /* constraints on DVMA map */ 1070 u_long _dm_ex_end; /* allocations; used by the VME bus 1071 driver and by the IOMMU driver 1072 when mapping 24-bit devices */ 1073 1074 /* 1075 * PUBLIC MEMBERS: these are used by machine-independent code. 1076 */ 1077 bus_size_t dm_maxsegsz; /* largest possible segment */ 1078 bus_size_t dm_mapsize; /* size of the mapping */ 1079 int dm_nsegs; /* # valid segments in mapping */ 1080 bus_dma_segment_t dm_segs[1]; /* segments; variable length */ 1081 }; 1082 1083 #ifdef _SUN68K_BUS_DMA_PRIVATE 1084 int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, 1085 bus_size_t, int, bus_dmamap_t *); 1086 void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); 1087 int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); 1088 int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); 1089 int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, bus_dma_segment_t *, 1090 int, bus_size_t, int); 1091 int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, 1092 struct proc *, int); 1093 void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); 1094 void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t, 1095 int); 1096 1097 int _bus_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, 1098 bus_dma_segment_t *, int, int *, int); 1099 void _bus_dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); 1100 int _bus_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, int, size_t, 1101 void **, int); 1102 void _bus_dmamem_unmap(bus_dma_tag_t, void *, size_t); 1103 paddr_t _bus_dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, 1104 int); 1105 1106 int _bus_dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, 1107 bus_size_t, bus_dma_segment_t *, int, int *, int, vaddr_t, vaddr_t); 1108 1109 vaddr_t _bus_dma_valloc_skewed(size_t, u_long, u_long, u_long); 1110 #endif /* _SUN68K_BUS_DMA_PRIVATE */ 1111 1112 #endif /* _SUN68K_BUS_H_ */ 1113