1 /* $NetBSD: bus.h,v 1.15 2007/03/04 06:00:55 christos 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 /* 320 * void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t); 321 * 322 * Get the kernel virtual address for the mapped bus space. 323 * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR. 324 * (XXX not enforced) 325 */ 326 #define bus_space_vaddr(t, h) ((void)(t), (void *)(h)) 327 328 /* flags for bus space map functions */ 329 #define BUS_SPACE_MAP_CACHEABLE 0x0001 330 #define BUS_SPACE_MAP_LINEAR 0x0002 331 #define BUS_SPACE_MAP_PREFETCHABLE 0x0004 332 #define BUS_SPACE_MAP_BUS1 0x0100 /* placeholders for bus functions... */ 333 #define BUS_SPACE_MAP_BUS2 0x0200 334 #define BUS_SPACE_MAP_BUS3 0x0400 335 #define BUS_SPACE_MAP_BUS4 0x0800 336 337 /* Internal flag: try to find and use a PROM maping for the device. */ 338 #define _SUN68K_BUS_MAP_USE_PROM BUS_SPACE_MAP_BUS1 339 340 /* flags for intr_establish() */ 341 #define BUS_INTR_ESTABLISH_FASTTRAP 1 342 #define BUS_INTR_ESTABLISH_SOFTINTR 2 343 344 /* flags for bus_space_barrier() */ 345 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 346 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 347 348 /* 349 * int bus_space_peek_N(bus_space_tag_t tag, 350 * bus_space_handle_t bsh, bus_size_t offset, u_intN_t *valuep); 351 * 352 * Cautiously read 1, 2, 4 or 8 byte quantity from bus space described 353 * by tag/handle/offset. 354 * If no hardware responds to the read access, the function returns a 355 * non-zero value. Otherwise the value read is placed in `valuep'. 356 */ 357 358 #define bus_space_peek_1(t, h, o, vp) \ 359 _bus_space_peek(t, h, o, sizeof(uint8_t), (void *)vp) 360 361 #define bus_space_peek_2(t, h, o, vp) \ 362 _bus_space_peek(t, h, o, sizeof(uint16_t), (void *)vp) 363 364 #define bus_space_peek_4(t, h, o, vp) \ 365 _bus_space_peek(t, h, o, sizeof(uint32_t), (void *)vp) 366 367 /* 368 * int bus_space_poke_N(bus_space_tag_t tag, 369 * bus_space_handle_t bsh, bus_size_t offset, uintN_t value); 370 * 371 * Cautiously write 1, 2, 4 or 8 byte quantity to bus space described 372 * by tag/handle/offset. 373 * If no hardware responds to the write access, the function returns a 374 * non-zero value. 375 */ 376 377 #define bus_space_poke_1(t, h, o, v) \ 378 _bus_space_poke(t, h, o, sizeof(uint8_t), v) 379 380 #define bus_space_poke_2(t, h, o, v) \ 381 _bus_space_poke(t, h, o, sizeof(uint16_t), v) 382 383 #define bus_space_poke_4(t, h, o, v) \ 384 _bus_space_poke(t, h, o, sizeof(uint32_t), v) 385 386 /* 387 * uintN_t bus_space_read_N(bus_space_tag_t tag, 388 * bus_space_handle_t bsh, bus_size_t offset); 389 * 390 * Read a 1, 2, 4, or 8 byte quantity from bus space 391 * described by tag/handle/offset. 392 */ 393 394 #define bus_space_read_1(t, h, o) \ 395 ((void)t, *(volatile uint8_t *)((h) + (o))) 396 397 #define bus_space_read_2(t, h, o) \ 398 ((void)t, *(volatile uint16_t *)((h) + (o))) 399 400 #define bus_space_read_4(t, h, o) \ 401 ((void)t, *(volatile uint32_t *)((h) + (o))) 402 403 #define bus_space_read_8(t, h, o) \ 404 ((void)t, *(volatile uint64_t *)((h) + (o))) 405 406 407 /* 408 * void bus_space_write_N(bus_space_tag_t tag, 409 * bus_space_handle_t bsh, bus_size_t offset, 410 * uintN_t value); 411 * 412 * Write the 1, 2, 4, or 8 byte value `value' to bus space 413 * described by tag/handle/offset. 414 */ 415 416 #define bus_space_write_1(t, h, o, v) do { \ 417 ((void)t, (void)(*(volatile uint8_t *)((h) + (o)) = (v))); \ 418 } while (0) 419 420 #define bus_space_write_2(t, h, o, v) do { \ 421 ((void)t, (void)(*(volatile uint16_t *)((h) + (o)) = (v))); \ 422 } while (0) 423 424 #define bus_space_write_4(t, h, o, v) do { \ 425 ((void)t, (void)(*(volatile uint32_t *)((h) + (o)) = (v))); \ 426 } while (0) 427 428 #define bus_space_write_8(t, h, o, v) do { \ 429 ((void)t, (void)(*(volatile uint64_t *)((h) + (o)) = (v))); \ 430 } while (0) 431 432 433 /* 434 * void bus_space_read_multi_N(bus_space_tag_t tag, 435 * bus_space_handle_t bsh, bus_size_t offset, 436 * uintN_t *addr, bus_size_t count); 437 * 438 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 439 * described by tag/handle/offset and copy into buffer provided. 440 */ 441 442 void bus_space_read_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 443 uint8_t *, bus_size_t); 444 void bus_space_read_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 445 uint16_t *, bus_size_t); 446 void bus_space_read_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 447 uint32_t *, bus_size_t); 448 void bus_space_read_multi_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 449 uint64_t *, bus_size_t); 450 451 extern __inline void 452 bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 453 uint8_t *a, bus_size_t c) 454 { 455 while (c-- > 0) 456 *a++ = bus_space_read_1(t, h, o); 457 } 458 459 extern __inline void 460 bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 461 uint16_t *a, bus_size_t c) 462 { 463 while (c-- > 0) 464 *a++ = bus_space_read_2(t, h, o); 465 } 466 467 extern __inline void 468 bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 469 uint32_t *a, bus_size_t c) 470 { 471 while (c-- > 0) 472 *a++ = bus_space_read_4(t, h, o); 473 } 474 475 extern __inline void 476 bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 477 uint64_t *a, bus_size_t c) 478 { 479 while (c-- > 0) 480 *a++ = bus_space_read_8(t, h, o); 481 } 482 483 484 /* 485 * void bus_space_write_multi_N(bus_space_tag_t tag, 486 * bus_space_handle_t bsh, bus_size_t offset, 487 * const u_intN_t *addr, bus_size_t count); 488 * 489 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer 490 * provided to bus space described by tag/handle/offset. 491 */ 492 void bus_space_write_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 493 const uint8_t *, bus_size_t); 494 void bus_space_write_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 495 const uint16_t *, bus_size_t); 496 void bus_space_write_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 497 const uint32_t *, bus_size_t); 498 void bus_space_write_multi_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 499 const uint64_t *, bus_size_t); 500 501 extern __inline void 502 bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 503 const uint8_t *a, bus_size_t c) 504 { 505 while (c-- > 0) 506 bus_space_write_1(t, h, o, *a++); 507 } 508 509 extern __inline void 510 bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 511 const uint16_t *a, bus_size_t c) 512 { 513 while (c-- > 0) 514 bus_space_write_2(t, h, o, *a++); 515 } 516 517 extern __inline void 518 bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 519 const uint32_t *a, bus_size_t c) 520 { 521 while (c-- > 0) 522 bus_space_write_4(t, h, o, *a++); 523 } 524 525 extern __inline void 526 bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 527 const uint64_t *a, bus_size_t c) 528 { 529 while (c-- > 0) 530 bus_space_write_8(t, h, o, *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 void bus_space_set_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 542 const uint8_t, bus_size_t); 543 void bus_space_set_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 544 const uint16_t, bus_size_t); 545 void bus_space_set_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 546 const uint32_t, bus_size_t); 547 void bus_space_set_multi_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 548 const uint64_t, bus_size_t); 549 550 extern __inline void 551 bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 552 const uint8_t v, bus_size_t c) 553 { 554 while (c-- > 0) 555 bus_space_write_1(t, h, o, v); 556 } 557 558 extern __inline void 559 bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 560 const uint16_t v, bus_size_t c) 561 { 562 while (c-- > 0) 563 bus_space_write_2(t, h, o, v); 564 } 565 566 extern __inline void 567 bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 568 const uint32_t v, bus_size_t c) 569 { 570 while (c-- > 0) 571 bus_space_write_4(t, h, o, v); 572 } 573 574 extern __inline void 575 bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 576 const uint64_t v, bus_size_t c) 577 { 578 while (c-- > 0) 579 bus_space_write_8(t, h, o, v); 580 } 581 582 583 /* 584 * void bus_space_read_region_N(bus_space_tag_t tag, 585 * bus_space_handle_t bsh, bus_size_t off, 586 * uintN_t *addr, bus_size_t count); 587 * 588 */ 589 void bus_space_read_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 590 uint8_t *, bus_size_t); 591 void bus_space_read_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 592 uint16_t *, bus_size_t); 593 void bus_space_read_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 594 uint32_t *, bus_size_t); 595 void bus_space_read_region_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 596 uint64_t *, bus_size_t); 597 598 extern __inline void 599 bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 600 uint8_t *a, bus_size_t c) 601 { 602 for (; c; a++, c--, o++) 603 *a = bus_space_read_1(t, h, o); 604 } 605 extern __inline void 606 bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 607 uint16_t *a, bus_size_t c) 608 { 609 for (; c; a++, c--, o += 2) 610 *a = bus_space_read_2(t, h, o); 611 } 612 extern __inline void 613 bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 614 uint32_t *a, bus_size_t c) 615 { 616 for (; c; a++, c--, o += 4) 617 *a = bus_space_read_4(t, h, o); 618 } 619 extern __inline void 620 bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 621 uint64_t *a, bus_size_t c) 622 { 623 for (; c; a++, c--, o += 8) 624 *a = bus_space_read_8(t, h, o); 625 } 626 627 /* 628 * void bus_space_write_region_N(bus_space_tag_t tag, 629 * bus_space_handle_t bsh, bus_size_t off, 630 * uintN_t *addr, bus_size_t count); 631 * 632 */ 633 void bus_space_write_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 634 const uint8_t *, bus_size_t); 635 void bus_space_write_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 636 const uint16_t *, bus_size_t); 637 void bus_space_write_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 638 const uint32_t *, bus_size_t); 639 void bus_space_write_region_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 640 const uint64_t *, bus_size_t); 641 642 extern __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 for (; c; a++, c--, o++) 647 bus_space_write_1(t, h, o, *a); 648 } 649 650 extern __inline void 651 bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 652 const uint16_t *a, bus_size_t c) 653 { 654 for (; c; a++, c--, o += 2) 655 bus_space_write_2(t, h, o, *a); 656 } 657 658 extern __inline void 659 bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 660 const uint32_t *a, bus_size_t c) 661 { 662 for (; c; a++, c--, o += 4) 663 bus_space_write_4(t, h, o, *a); 664 } 665 666 extern __inline void 667 bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 668 const uint64_t *a, bus_size_t c) 669 { 670 for (; c; a++, c--, o += 8) 671 bus_space_write_8(t, h, o, *a); 672 } 673 674 675 /* 676 * void bus_space_set_region_N(bus_space_tag_t tag, 677 * bus_space_handle_t bsh, bus_size_t off, 678 * uintN_t *addr, bus_size_t count); 679 * 680 */ 681 void bus_space_set_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 682 const uint8_t, bus_size_t); 683 void bus_space_set_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 684 const uint16_t, bus_size_t); 685 void bus_space_set_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 686 const uint32_t, bus_size_t); 687 void bus_space_set_region_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 688 const uint64_t, bus_size_t); 689 690 extern __inline void 691 bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 692 const uint8_t v, bus_size_t c) 693 { 694 for (; c; c--, o++) 695 bus_space_write_1(t, h, o, v); 696 } 697 698 extern __inline void 699 bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 700 const uint16_t v, bus_size_t c) 701 { 702 for (; c; c--, o += 2) 703 bus_space_write_2(t, h, o, v); 704 } 705 706 extern __inline void 707 bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 708 const uint32_t v, bus_size_t c) 709 { 710 for (; c; c--, o += 4) 711 bus_space_write_4(t, h, o, v); 712 } 713 714 extern __inline void 715 bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 716 const uint64_t v, bus_size_t c) 717 { 718 for (; c; c--, o += 8) 719 bus_space_write_8(t, h, o, v); 720 } 721 722 723 /* 724 * void bus_space_copy_region_N(bus_space_tag_t tag, 725 * bus_space_handle_t bsh1, bus_size_t off1, 726 * bus_space_handle_t bsh2, bus_size_t off2, 727 * bus_size_t count); 728 * 729 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting 730 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. 731 */ 732 void bus_space_copy_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 733 bus_space_handle_t, bus_size_t, bus_size_t); 734 void bus_space_copy_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 735 bus_space_handle_t, bus_size_t, bus_size_t); 736 void bus_space_copy_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 737 bus_space_handle_t, bus_size_t, bus_size_t); 738 void bus_space_copy_region_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 739 bus_space_handle_t, bus_size_t, bus_size_t); 740 741 extern __inline void 742 bus_space_copy_region_1(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, 743 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 744 { 745 for (; c; c--, o1++, o2++) 746 bus_space_write_1(t, h1, o1, bus_space_read_1(t, h2, o2)); 747 } 748 749 extern __inline void 750 bus_space_copy_region_2(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 for (; c; c--, o1 += 2, o2 += 2) 754 bus_space_write_2(t, h1, o1, bus_space_read_2(t, h2, o2)); 755 } 756 757 extern __inline void 758 bus_space_copy_region_4(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, 759 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 760 { 761 for (; c; c--, o1 += 4, o2 += 4) 762 bus_space_write_4(t, h1, o1, bus_space_read_4(t, h2, o2)); 763 } 764 765 extern __inline void 766 bus_space_copy_region_8(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, 767 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 768 { 769 for (; c; c--, o1 += 8, o2 += 8) 770 bus_space_write_8(t, h1, o1, bus_space_read_8(t, h2, o2)); 771 } 772 773 /* 774 * void bus_space_copyin(bus_space_tag_t tag, 775 * bus_space_handle_t bsh, bus_size_t off, 776 * void *addr, bus_size_t count); 777 * 778 * Copy `count' bytes from bus space starting at tag/bsh/off 779 * to kernel memory at addr using the most optimized transfer 780 * possible for the bus. 781 */ 782 783 #define bus_space_copyin(t, h, o, a, c) \ 784 ((void)t, w16copy((uint8_t *)((h) + (o)), (a), (c))) 785 786 /* 787 * void bus_space_copyout(bus_space_tag_t tag, 788 * bus_space_handle_t bsh, bus_size_t off, 789 * const void *addr, bus_size_t count); 790 * 791 * Copy `count' bytes to bus space starting at tag/bsh/off 792 * from kernel memory at addr using the most optimized transfer 793 * possible for the bus. 794 */ 795 796 #define bus_space_copyout(t, h, o, a, c) \ 797 ((void)t, w16copy((a), (uint8_t *)((h) + (o)), (c))) 798 799 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) 800 801 int find_prom_map(paddr_t, bus_type_t, int, vaddr_t *); 802 803 /*--------------------------------*/ 804 805 /* 806 * Flags used in various bus DMA methods. 807 */ 808 #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ 809 #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ 810 #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ 811 #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ 812 #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ 813 #define BUS_DMA_BUS2 0x020 814 #define BUS_DMA_BUS3 0x040 815 #define BUS_DMA_BUS4 0x080 816 #define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ 817 #define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ 818 #define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */ 819 820 /* For devices that have a 24-bit address space */ 821 #define BUS_DMA_24BIT BUS_DMA_BUS1 822 823 /* Internal flag: current DVMA address is equal to the KVA buffer address */ 824 #define _BUS_DMA_DIRECTMAP BUS_DMA_BUS2 825 826 /* 827 * Internal flag: current DVMA address has been double-mapped by hand 828 * to the KVA buffer address (without the pmap's help). 829 */ 830 #define _BUS_DMA_NOPMAP BUS_DMA_BUS3 831 832 /* Forwards needed by prototypes below. */ 833 struct mbuf; 834 struct uio; 835 836 /* 837 * Operations performed by bus_dmamap_sync(). 838 */ 839 #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ 840 #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ 841 #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ 842 #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ 843 844 typedef struct sun68k_bus_dma_tag *bus_dma_tag_t; 845 typedef struct sun68k_bus_dmamap *bus_dmamap_t; 846 847 #define BUS_DMA_TAG_VALID(t) ((t) != NULL) 848 849 /* 850 * bus_dma_segment_t 851 * 852 * Describes a single contiguous DMA transaction. Values 853 * are suitable for programming into DMA registers. 854 */ 855 struct sun68k_bus_dma_segment { 856 bus_addr_t ds_addr; /* DVMA address */ 857 bus_size_t ds_len; /* length of transfer */ 858 bus_size_t _ds_sgsize; /* size of allocated DVMA segment */ 859 void *_ds_mlist; /* page list when dmamem_alloc'ed */ 860 vaddr_t _ds_va; /* VA when dmamem_map'ed */ 861 }; 862 typedef struct sun68k_bus_dma_segment bus_dma_segment_t; 863 864 865 /* 866 * bus_dma_tag_t 867 * 868 * A machine-dependent opaque type describing the implementation of 869 * DMA for a given bus. 870 */ 871 struct sun68k_bus_dma_tag { 872 void *_cookie; /* cookie used in the guts */ 873 874 /* 875 * DMA mapping methods. 876 */ 877 int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, bus_size_t, 878 bus_size_t, int, bus_dmamap_t *); 879 void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); 880 int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, 881 struct proc *, int); 882 int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, 883 int); 884 int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, struct uio *, 885 int); 886 int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, 887 bus_dma_segment_t *, int, bus_size_t, int); 888 void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); 889 void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 890 bus_size_t, int); 891 892 /* 893 * DMA memory utility functions. 894 */ 895 int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, 896 bus_size_t, bus_dma_segment_t *, int, int *, int); 897 void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); 898 int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, int, size_t, 899 void **, int); 900 void (*_dmamem_unmap)(bus_dma_tag_t, void *, size_t); 901 paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, 902 int, int); 903 }; 904 905 #define bus_dmamap_create(t, s, n, m, b, f, p) \ 906 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) 907 #define bus_dmamap_destroy(t, p) \ 908 (*(t)->_dmamap_destroy)((t), (p)) 909 #define bus_dmamap_load(t, m, b, s, p, f) \ 910 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) 911 #define bus_dmamap_load_mbuf(t, m, b, f) \ 912 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) 913 #define bus_dmamap_load_uio(t, m, u, f) \ 914 (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) 915 #define bus_dmamap_load_raw(t, m, sg, n, s, f) \ 916 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) 917 #define bus_dmamap_unload(t, p) \ 918 (*(t)->_dmamap_unload)((t), (p)) 919 #define bus_dmamap_sync(t, p, o, l, ops) \ 920 (void)((t)->_dmamap_sync ? \ 921 (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0) 922 923 #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ 924 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) 925 #define bus_dmamem_free(t, sg, n) \ 926 (*(t)->_dmamem_free)((t), (sg), (n)) 927 #define bus_dmamem_map(t, sg, n, s, k, f) \ 928 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) 929 #define bus_dmamem_unmap(t, k, s) \ 930 (*(t)->_dmamem_unmap)((t), (k), (s)) 931 #define bus_dmamem_mmap(t, sg, n, o, p, f) \ 932 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) 933 934 #define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP 935 #define bus_dmatag_destroy(t) 936 937 /* 938 * bus_dmamap_t 939 * 940 * Describes a DMA mapping. 941 */ 942 struct sun68k_bus_dmamap { 943 /* 944 * PRIVATE MEMBERS: not for use by machine-independent code. 945 */ 946 bus_size_t _dm_size; /* largest DMA transfer mappable */ 947 int _dm_segcnt; /* number of segs this map can map */ 948 bus_size_t _dm_maxmaxsegsz; /* fixed largest possible segment */ 949 bus_size_t _dm_boundary; /* don't cross this */ 950 int _dm_flags; /* misc. flags */ 951 952 void *_dm_cookie; /* cookie for bus-specific functions */ 953 954 u_long _dm_align; /* DVMA alignment; must be a 955 multiple of the page size */ 956 u_long _dm_ex_start; /* constraints on DVMA map */ 957 u_long _dm_ex_end; /* allocations; used by the VME bus 958 driver and by the IOMMU driver 959 when mapping 24-bit devices */ 960 961 /* 962 * PUBLIC MEMBERS: these are used by machine-independent code. 963 */ 964 bus_size_t dm_maxsegsz; /* largest possible segment */ 965 bus_size_t dm_mapsize; /* size of the mapping */ 966 int dm_nsegs; /* # valid segments in mapping */ 967 bus_dma_segment_t dm_segs[1]; /* segments; variable length */ 968 }; 969 970 #ifdef _SUN68K_BUS_DMA_PRIVATE 971 int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, 972 bus_size_t, int, bus_dmamap_t *); 973 void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); 974 int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); 975 int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); 976 int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, bus_dma_segment_t *, 977 int, bus_size_t, int); 978 int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, 979 struct proc *, int); 980 void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); 981 void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t, 982 int); 983 984 int _bus_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, 985 bus_dma_segment_t *, int, int *, int); 986 void _bus_dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); 987 int _bus_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, int, size_t, 988 void **, int); 989 void _bus_dmamem_unmap(bus_dma_tag_t, void *, size_t); 990 paddr_t _bus_dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, 991 int); 992 993 int _bus_dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, 994 bus_size_t, bus_dma_segment_t *, int, int *, int, vaddr_t, vaddr_t); 995 996 vaddr_t _bus_dma_valloc_skewed(size_t, u_long, u_long, u_long); 997 #endif /* _SUN68K_BUS_DMA_PRIVATE */ 998 999 #endif /* _SUN68K_BUS_H_ */ 1000