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