1/* $NetBSD$ */ 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 _IA64_BUS_H_ 72#define _IA64_BUS_H_ 73 74#include <sys/systm.h> 75 76#include <machine/cpufunc.h> 77#include <machine/vmparam.h> 78 79#ifdef BUS_SPACE_DEBUG 80/* 81 * Macros for sanity-checking the aligned-ness of pointers passed to 82 * bus space ops. These are not strictly necessary on the x86, but 83 * could lead to performance improvements, and help catch problems 84 * with drivers that would creep up on other architectures. 85 */ 86#define __BUS_SPACE_ALIGNED_ADDRESS(p, t) \ 87 ((((u_long)(p)) & (sizeof(t)-1)) == 0) 88 89#define __BUS_SPACE_ADDRESS_SANITY(p, t, d) \ 90({ \ 91 if (__BUS_SPACE_ALIGNED_ADDRESS((p), t) == 0) { \ 92 printf("%s 0x%lx not aligned to %d bytes %s:%d\n", \ 93 d, (u_long)(p), sizeof(t), __FILE__, __LINE__); \ 94 } \ 95 (void) 0; \ 96}) 97 98#define BUS_SPACE_ALIGNED_POINTER(p, t) __BUS_SPACE_ALIGNED_ADDRESS(p, t) 99#else 100#define __BUS_SPACE_ADDRESS_SANITY(p,t,d) (void) 0 101#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) 102#endif /* BUS_SPACE_DEBUG */ 103 104/* 105 * bus_space_map flags 106 */ 107 108#define BUS_SPACE_MAP_CACHEABLE 0x01 109#define BUS_SPACE_MAP_LINEAR 0x02 110#define BUS_SPACE_MAP_PREFETCHABLE 0x04 111 112/* 113 * Derived from x86 implementation, ia64 has both i/o and mem spaces 114 * These values are for bus space tag. 115 */ 116#define IA64_BUS_SPACE_IO 0 /* space is i/o space */ 117#define IA64_BUS_SPACE_MEM 1 /* space is mem space */ 118 119#define __BUS_SPACE_HAS_STREAM_METHODS 1 120 121/* 122 * Bus address and size types 123 */ 124typedef u_long bus_addr_t; 125typedef u_long bus_size_t; 126 127/* 128 * Access methods for bus resources and address space. 129 */ 130typedef int bus_space_tag_t; 131typedef u_long bus_space_handle_t; 132 133/* map/unmap */ 134 135int ia64_bus_space_map(bus_space_tag_t, bus_addr_t, 136 bus_size_t, int, bus_space_handle_t *); 137void ia64_bus_space_unmap(bus_space_tag_t, bus_space_handle_t, 138 bus_size_t); 139int ia64_bus_space_subregion(bus_space_tag_t, bus_space_handle_t, 140 bus_size_t, bus_size_t, bus_space_handle_t *); 141#define bus_space_map(t, a, s, f, hp) \ 142 ia64_bus_space_map((t), (a), (s), (f), (hp)) 143#define bus_space_unmap(t, h, s) \ 144 ia64_bus_space_unmap((t), (h), (s)) 145#define bus_space_subregion(t, h, o, s, nhp) \ 146 ia64_bus_space_subregion((t), (h), (o), (s), (nhp)) 147 148/* vaddr */ 149 150#define bus_space_vaddr(t, h) \ 151 ((t) == IA64_BUS_SPACE_MEM ? (void *)(h) : (void *)0) 152 153/* map to user space */ 154 155paddr_t ia64_bus_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); 156 157#define bus_space_mmap(t, b, o, p, f) \ 158 ia64_bus_space_mmap((t), (b), (o), (p), (f)) 159 160/* alloc/free */ 161 162int ia64_bus_space_alloc(bus_space_tag_t, bus_addr_t, bus_addr_t, 163 bus_size_t, bus_size_t, bus_size_t, int, bus_addr_t *, 164 bus_space_handle_t *); 165void ia64_bus_space_free(bus_space_tag_t, bus_space_handle_t, bus_size_t); 166 167#define bus_space_alloc(t, rs, re, s, a, b, f, ap, hp) \ 168 ia64_bus_space__alloc((t), (rs), (re), (s), (a), (b), (f), (ap), (hp)) 169#define bus_space_free(t, h, s) \ 170 ia64_bus_space_free((t), (h), (s)) 171 172/* 173 * uintN_t bus_space_read_N(bus_space_tag_t tag, 174 * bus_space_handle_t bsh, bus_size_t offset); 175 * 176 * Read a 1, 2, 4, or 8 byte quantity from bus space 177 * described by tag/handle/offset. 178 */ 179 180#define bus_space_read_1(t, h, o) \ 181 ((t) == IA64_BUS_SPACE_IO ? (inb((h) + (o))) :\ 182 (*(volatile uint8_t *)((h) + (o)))) 183 184#define bus_space_read_2(t, h, o) \ 185 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"), \ 186 ((t) == IA64_BUS_SPACE_IO ? (inw((h) + (o))) : \ 187 (*(volatile uint16_t *)((h) + (o))))) 188 189#define bus_space_read_4(t, h, o) \ 190 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"), \ 191 ((t) == IA64_BUS_SPACE_IO ? (inl((h) + (o))) : \ 192 (*(volatile uint32_t *)((h) + (o))))) 193 194#define bus_space_read_8(t, h, o) \ 195 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"), \ 196 ((t) == IA64_BUS_SPACE_IO ? \ 197 ({ printf("%s: can't read 8bytes from I/O space\n", __FUNCTION__); 0;}) : \ 198 (*(volatile uint64_t *)((h) + (o))))) 199 200#define bus_space_read_stream_1 bus_space_read_1 201#define bus_space_read_stream_2 bus_space_read_2 202#define bus_space_read_stream_4 bus_space_read_4 203#define bus_space_read_stream_8 bus_space_read_8 204 205/* 206 * void bus_space_read_multi_N(bus_space_tag_t tag, 207 * bus_space_handle_t bsh, bus_size_t offset, 208 * uintN_t *addr, size_t count); 209 * 210 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 211 * described by tag/handle/offset and copy into buffer provided. 212 */ 213 214#define bus_space_read_multi_1(t, h, o, ptr, cnt) \ 215do { \ 216 if ((t) == IA64_BUS_SPACE_IO) { \ 217 insb((h) + (o), (ptr), (cnt)); \ 218 } else { \ 219 int __i; \ 220 volatile uint8_t *__p = (uint8_t *)((h) + (o)); \ 221 uint8_t *__dst = (ptr); \ 222 for (__i = 0; __i < (cnt); __i++) \ 223 *__dst++ = *__p; \ 224 } \ 225} while (/* CONSTCOND */ 0) 226 227#define bus_space_read_multi_2(t, h, o, ptr, cnt) \ 228do { \ 229 __BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer"); \ 230 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 231 if ((t) == IA64_BUS_SPACE_IO) { \ 232 insw((h) + (o), (ptr), (cnt)); \ 233 } else { \ 234 int __i; \ 235 volatile uint16_t *__p = (uint16_t *)((h) + (o)); \ 236 uint16_t *__dst = (ptr); \ 237 for (__i = 0; __i < (cnt); __i++) \ 238 *__dst++ = *__p; \ 239 } \ 240} while (/* CONSTCOND */ 0) 241 242#define bus_space_read_multi_4(t, h, o, ptr, cnt) \ 243do { \ 244 __BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer"); \ 245 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 246 if ((t) == IA64_BUS_SPACE_IO) { \ 247 insl((h) + (o), (ptr), (cnt)); \ 248 } else { \ 249 int __i; \ 250 volatile uint32_t *__p = (uint32_t *)((h) + (o)); \ 251 uint32_t *__dst = (ptr); \ 252 for (__i = 0; __i < (cnt); __i++) \ 253 *__dst++ = *__p; \ 254 } \ 255} while (/* CONSTCOND */ 0) 256 257#define bus_space_read_multi_8(t, h, o, ptr, cnt) \ 258do { \ 259 __BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer"); \ 260 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \ 261 if ((t) == IA64_BUS_SPACE_IO) { \ 262 printf("%s: can't read 8bytes from I/O space\n", \ 263 __FUNCTION__); \ 264 } else { \ 265 int __i; \ 266 volatile uint64_t *__p = (uint64_t *)((h) + (o)); \ 267 uint64_t *__dst = (ptr); \ 268 for (__i = 0; __i < (cnt); __i++) \ 269 *__dst++ = *__p; \ 270 } \ 271} while (/* CONSTCOND */ 0) 272 273#define bus_space_read_multi_stream_1 bus_space_read_multi_1 274#define bus_space_read_multi_stream_2 bus_space_read_multi_2 275#define bus_space_read_multi_stream_4 bus_space_read_multi_4 276#define bus_space_read_multi_stream_8 bus_space_read_multi_8 277 278 279/* 280 * void bus_space_read_region_N(bus_space_tag_t tag, 281 * bus_space_handle_t bsh, bus_size_t offset, 282 * uintN_t *addr, size_t count); 283 * 284 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 285 * described by tag/handle and starting at `offset' and copy into 286 * buffer provided. 287 */ 288 289#define bus_space_read_region_1(t, h, o, ptr, cnt) \ 290do { \ 291 if ((t) == IA64_BUS_SPACE_IO) { \ 292 int __i; \ 293 volatile bus_addr_t __port = (h) + (o); \ 294 uint8_t *__dst = (ptr); \ 295 for (__i = 0; __i < (cnt); __i++) { \ 296 *__dst++ = inb(__port); \ 297 __port++; \ 298 } \ 299 } else { \ 300 int __i; \ 301 volatile uint8_t *__p = (uint8_t *)((h) + (o)); \ 302 uint8_t *__dst = (ptr); \ 303 for (__i = 0; __i < (cnt); __i++) \ 304 *__dst++ = *__p++; \ 305 } \ 306} while (/* CONSTCOND */ 0) 307 308#define bus_space_read_region_2(t, h, o, ptr, cnt) \ 309do { \ 310 __BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer"); \ 311 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 312 if ((t) == IA64_BUS_SPACE_IO) { \ 313 int __i; \ 314 volatile bus_addr_t __port = (h) + (o); \ 315 uint8_t *__dst = (ptr); \ 316 for (__i = 0; __i < (cnt); __i++) { \ 317 *__dst++ = inb(__port); \ 318 __port += 2; \ 319 } \ 320 } else { \ 321 int __i; \ 322 volatile uint16_t *__p = (uint16_t *)((h) + (o)); \ 323 uint16_t *__dst = (ptr); \ 324 for (__i = 0; __i < (cnt); __i++) \ 325 *__dst++ = *__p++; \ 326 } \ 327} while (/* CONSTCOND */ 0) 328 329#define bus_space_read_region_4(t, h, o, ptr, cnt) \ 330do { \ 331 __BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer"); \ 332 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 333 if ((t) == IA64_BUS_SPACE_IO) { \ 334 int __i; \ 335 volatile bus_addr_t __port = (h) + (o); \ 336 uint8_t *__dst = (ptr); \ 337 for (__i = 0; __i < (cnt); __i++) { \ 338 *__dst++ = inb(__port); \ 339 __port += 4; \ 340 } \ 341 } else { \ 342 volatile uint32_t *__p = (uint32_t *)((h) + (o)); \ 343 uint32_t *__dst = (ptr); \ 344 for (__i = 0; __i < (cnt); __i++) \ 345 *__dst++ = *__p++; \ 346 } \ 347} while (/* CONSTCOND */ 0) 348 349#define bus_space_read_region_8(t, h, o, ptr, cnt) \ 350do { \ 351 __BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer"); \ 352 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \ 353 if ((t) == IA64_BUS_SPACE_IO) { \ 354 printf("%s: can't read 8bytes from I/O space\n", \ 355 __FUNCTION__); \ 356 } else { \ 357 volatile uint64_t *__p = (uint64_t *)((h) + (o)); \ 358 uint64_t *__dst = (ptr); \ 359 for (__i = 0; __i < (cnt); __i++) \ 360 *__dst++ = *__p++; \ 361 } \ 362} while (/* CONSTCOND */ 0) 363 364#define bus_space_read_region_stream_1 bus_space_read_region_1 365#define bus_space_read_region_stream_2 bus_space_read_region_2 366#define bus_space_read_region_stream_4 bus_space_read_region_4 367#define bus_space_read_region_stream_8 bus_space_read_region_8 368 369 370/* 371 * void bus_space_write_N(bus_space_tag_t tag, 372 * bus_space_handle_t bsh, bus_size_t offset, 373 * uintN_t value); 374 * 375 * Write the 1, 2, 4, or 8 byte value `value' to bus space 376 * described by tag/handle/offset. 377 */ 378 379#define bus_space_write_1(t, h, o, v) \ 380do { \ 381 if ((t) == IA64_BUS_SPACE_IO) \ 382 outb((h) + (o), (v)); \ 383 else \ 384 ((void)(*(volatile uint8_t *)((h) + (o)) = (v))); \ 385} while (/* CONSTCOND */ 0) 386 387#define bus_space_write_2(t, h, o, v) \ 388do { \ 389 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 390 if ((t) == IA64_BUS_SPACE_IO) \ 391 outw((h) + (o), (v)); \ 392 else \ 393 ((void)(*(volatile uint16_t *)((h) + (o)) = (v))); \ 394} while (/* CONSTCOND */ 0) 395 396#define bus_space_write_4(t, h, o, v) \ 397do { \ 398 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 399 if ((t) == IA64_BUS_SPACE_IO) \ 400 outl((h) + (o), (v)); \ 401 else \ 402 ((void)(*(volatile uint32_t *)((h) + (o)) = (v))); \ 403} while (/* CONSTCOND */ 0) 404 405#define bus_space_write_8(t, h, o, v) \ 406 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \ 407 if ((t) == IA64_BUS_SPACE_IO ? \ 408 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__); : \ 409 (*(volatile uint64_t *)((h) + (o)) = (v))) 410 411#define bus_space_write_stream_1 bus_space_write_1 412#define bus_space_write_stream_2 bus_space_write_2 413#define bus_space_write_stream_4 bus_space_write_4 414#define bus_space_write_stream_8 bus_space_write_8 415 416/* 417 * void bus_space_write_multi_N(bus_space_tag_t tag, 418 * bus_space_handle_t bsh, bus_size_t offset, 419 * const uintN_t *addr, size_t count); 420 * 421 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer 422 * provided to bus space described by tag/handle/offset. 423 */ 424 425#define bus_space_write_multi_1(t, h, o, ptr, cnt) \ 426do { \ 427 if ((t) == IA64_BUS_SPACE_IO) { \ 428 outsb((h) + (o), (ptr), (cnt)); \ 429 } else { \ 430 int __i; \ 431 volatile uint8_t *__p = (uint8_t *)((h) + (o)); \ 432 uint8_t *__src = (ptr); \ 433 for (__i = 0; __i < (cnt); __i++) \ 434 *__p = *__src++; \ 435 } \ 436} while (/* CONSTCOND */ 0) 437 438#define bus_space_write_multi_2(t, h, o, ptr, cnt) \ 439do { \ 440 __BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer"); \ 441 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 442 if ((t) == IA64_BUS_SPACE_IO) { \ 443 outsw((h) + (o), (ptr), (cnt)); \ 444 } else { \ 445 int __i; \ 446 volatile uint16_t *__p = (uint16_t *)((h) + (o)); \ 447 uint16_t *__src = (ptr); \ 448 for (__i = 0; __i < (cnt); __i++) \ 449 *__p = *__src++; \ 450 } \ 451} while (/* CONSTCOND */ 0) 452 453#define bus_space_write_multi_4(t, h, o, ptr, cnt) \ 454do { \ 455 __BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer"); \ 456 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 457 if ((t) == IA64_BUS_SPACE_IO) { \ 458 outsl((h) + (o), (ptr), (cnt)); \ 459 } else { \ 460 int __i; \ 461 volatile uint32_t *__p = (uint32_t *)((h) + (o)); \ 462 uint32_t *__src = (ptr); \ 463 for (__i = 0; __i < (cnt); __i++) \ 464 *__p = *__src++; \ 465 } \ 466} while (/* CONSTCOND */ 0) 467 468#define bus_space_write_multi_8(t, h, o, ptr, cnt) \ 469do { \ 470 __BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer"); \ 471 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \ 472 if ((t) == IA64_BUS_SPACE_IO) { \ 473 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__);\ 474 } else { \ 475 int __i; \ 476 volatile uint64_t *__p = (uint64_t *)((h) + (o)); \ 477 uint64_t *__src = (ptr); \ 478 for (__i = 0; __i < (cnt); __i++) \ 479 *__p = *__src++; \ 480 } \ 481} while (/* CONSTCOND */ 0) 482 483#define bus_space_write_multi_stream_1 bus_space_write_multi_1 484#define bus_space_write_multi_stream_2 bus_space_write_multi_2 485#define bus_space_write_multi_stream_4 bus_space_write_multi_4 486#define bus_space_write_multi_stream_8 bus_space_write_multi_8 487 488 489/* 490 * void bus_space_write_region_N(bus_space_tag_t tag, 491 * bus_space_handle_t bsh, bus_size_t offset, 492 * const uintN_t *addr, size_t count); 493 * 494 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided 495 * to bus space described by tag/handle starting at `offset'. 496 */ 497 498#define bus_space_write_region_1(t, h, o, ptr, cnt) \ 499do { \ 500 if ((t) == IA64_BUS_SPACE_IO) { \ 501 int __i; \ 502 volatile bus_addr_t __port = (h) + (o); \ 503 uint8_t *__src = (ptr); \ 504 for (__i = 0; __i < (cnt); __i++) { \ 505 outb(__port, *__src); \ 506 __port++; \ 507 __src++; \ 508 } \ 509 } else { \ 510 int __i; \ 511 volatile uint8_t *__p = (uint8_t *)((h) + (o)); \ 512 uint8_t *__src = (ptr); \ 513 for (__i = 0; __i < (cnt); __i++) \ 514 *__p++ = *__src++; \ 515 } \ 516} while (/* CONSTCOND */ 0) 517 518#define bus_space_write_region_2(t, h, o, ptr, cnt) \ 519do { \ 520 __BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer"); \ 521 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 522 if ((t) == IA64_BUS_SPACE_IO) { \ 523 int __i; \ 524 volatile bus_addr_t __port = (h) + (o); \ 525 uint16_t *__src = (ptr); \ 526 for (__i = 0; __i < (cnt); __i++) { \ 527 outw(__port, *__src); \ 528 __port += 2; \ 529 __src++; \ 530 } \ 531 } else { \ 532 int __i; \ 533 volatile uint16_t *__p = (uint16_t *)((h) + (o)); \ 534 uint16_t *__src = (ptr); \ 535 for (__i = 0; __i < (cnt); __i++) \ 536 *__p++ = *__src++; \ 537 } \ 538} while (/* CONSTCOND */ 0) 539 540#define bus_space_write_region_4(t, h, o, ptr, cnt) \ 541do { \ 542 __BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer"); \ 543 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 544 if ((t) == IA64_BUS_SPACE_IO) { \ 545 int __i; \ 546 volatile bus_addr_t __port = (h) + (o); \ 547 uint32_t *__src = (ptr); \ 548 for (__i = 0; __i < (cnt); __i++) { \ 549 outl(__port, *__src); \ 550 __port += 4; \ 551 __src++; \ 552 } \ 553 } else { \ 554 int __i; \ 555 volatile uint32_t *__p = (uint32_t *)(h) + (o); \ 556 uint32_t *__src = (ptr); \ 557 for (__i = 0; __i < (cnt); __i++) \ 558 *__p++ = *__src++; \ 559 } \ 560} while (/* CONSTCOND */ 0) 561 562#define bus_space_write_region_8(t, h, o, ptr, cnt) \ 563do { \ 564 __BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer"); \ 565 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \ 566 if ((t) == IA64_BUS_SPACE_IO) { \ 567 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__);\ 568 } else { \ 569 int __i; \ 570 volatile uint64_t *__p = (uint64_t *)((h) + (o)); \ 571 uint64_t *__src = (ptr); \ 572 for (__i = 0; __i < (cnt); __i++) \ 573 *__p++ = *__src++; \ 574 } \ 575} while (/* CONSTCOND */ 0) 576 577#define bus_space_write_region_stream_1 bus_space_write_region_1 578#define bus_space_write_region_stream_2 bus_space_write_region_2 579#define bus_space_write_region_stream_4 bus_space_write_region_4 580#define bus_space_write_region_stream_8 bus_space_write_region_8 581 582 583/* 584 * void bus_space_set_multi_N(bus_space_tag_t tag, 585 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val, 586 * size_t count); 587 * 588 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 589 * by tag/handle/offset `count' times. 590 */ 591 592static __inline void ia64_bus_space_set_multi_1(bus_space_tag_t, 593 bus_space_handle_t, bus_size_t, uint8_t, size_t); 594static __inline void ia64_bus_space_set_multi_2(bus_space_tag_t, 595 bus_space_handle_t, bus_size_t, uint16_t, size_t); 596static __inline void ia64_bus_space_set_multi_4(bus_space_tag_t, 597 bus_space_handle_t, bus_size_t, uint32_t, size_t); 598static __inline void ia64_bus_space_set_multi_8(bus_space_tag_t, 599 bus_space_handle_t, bus_size_t, uint64_t, size_t); 600 601#define bus_space_set_multi_1(t, h, o, v, c) \ 602 ia64_bus_space_set_multi_1((t), (h), (o), (v), (c)) 603 604#define bus_space_set_multi_2(t, h, o, v, c) \ 605do { \ 606 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 607 ia64_bus_space_set_multi_2((t), (h), (o), (v), (c)); \ 608} while (/* CONSTCOND */ 0) 609 610#define bus_space_set_multi_4(t, h, o, v, c) \ 611do { \ 612 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 613 ia64_bus_space_set_multi_4((t), (h), (o), (v), (c)); \ 614} while (/* CONSTCOND */ 0) 615 616#define bus_space_set_multi_8(t, h, o, v, c) \ 617do { \ 618 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \ 619 ia64_bus_space_set_multi_8((t), (h), (o), (v), (c)); \ 620} while (/* CONSTCOND */ 0) 621 622static __inline void 623ia64_bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, 624 bus_size_t o, uint8_t v, size_t c) 625{ 626 bus_addr_t addr = h + o; 627 628 if (t == IA64_BUS_SPACE_IO) 629 while (c--) 630 outb(addr, v); 631 else 632 while (c--) 633 *(volatile uint8_t *)(addr) = v; 634} 635 636static __inline void 637ia64_bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, 638 bus_size_t o, uint16_t v, size_t c) 639{ 640 bus_addr_t addr = h + o; 641 642 if (t == IA64_BUS_SPACE_IO) 643 while (c--) 644 outw(addr, v); 645 else 646 while (c--) 647 *(volatile uint16_t *)(addr) = v; 648} 649 650static __inline void 651ia64_bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, 652 bus_size_t o, uint32_t v, size_t c) 653{ 654 bus_addr_t addr = h + o; 655 656 if (t == IA64_BUS_SPACE_IO) 657 while (c--) 658 outl(addr, v); 659 else 660 while (c--) 661 *(volatile uint32_t *)(addr) = v; 662} 663 664static __inline void 665ia64_bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, 666 bus_size_t o, uint64_t v, size_t c) 667{ 668 bus_addr_t addr = h + o; 669 670 if (t == IA64_BUS_SPACE_IO) 671 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__); 672 else 673 while (c--) 674 *(volatile uint64_t *)(addr) = v; 675} 676 677 678/* 679 * void bus_space_set_region_N(bus_space_tag_t tag, 680 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val, 681 * size_t count); 682 * 683 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described 684 * by tag/handle starting at `offset'. 685 */ 686 687static __inline void ia64_bus_space_set_region_1(bus_space_tag_t, 688 bus_space_handle_t, bus_size_t, uint8_t, size_t); 689static __inline void ia64_bus_space_set_region_2(bus_space_tag_t, 690 bus_space_handle_t, bus_size_t, uint16_t, size_t); 691static __inline void ia64_bus_space_set_region_4(bus_space_tag_t, 692 bus_space_handle_t, bus_size_t, uint32_t, size_t); 693 694#define bus_space_set_region_1(t, h, o, v, c) \ 695 ia64_bus_space_set_region_1((t), (h), (o), (v), (c)) 696 697#define bus_space_set_region_2(t, h, o, v, c) \ 698do { \ 699 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 700 ia64_bus_space_set_region_2((t), (h), (o), (v), (c)); \ 701} while (/* CONSTCOND */ 0) 702 703#define bus_space_set_region_4(t, h, o, v, c) \ 704do { \ 705 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 706 ia64_bus_space_set_region_4((t), (h), (o), (v), (c)); \ 707} while (/* CONSTCOND */ 0) 708 709#define bus_space_set_region_8(t, h, o, v, c) \ 710do { \ 711 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \ 712 ia64_bus_space_set_region_8((t), (h), (o), (v), (c)); \ 713} while (/* CONSTCOND */ 0) 714 715static __inline void 716ia64_bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, 717 bus_size_t o, uint8_t v, size_t c) 718{ 719 bus_addr_t addr = h + o; 720 721 if (t == IA64_BUS_SPACE_IO) 722 for (; c != 0; c--, addr++) 723 outb(addr, v); 724 else 725 for (; c != 0; c--, addr++) 726 *(volatile uint8_t *)(addr) = v; 727} 728 729static __inline void 730ia64_bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, 731 bus_size_t o, uint16_t v, size_t c) 732{ 733 bus_addr_t addr = h + o; 734 735 if (t == IA64_BUS_SPACE_IO) 736 for (; c != 0; c--, addr += 2) 737 outw(addr, v); 738 else 739 for (; c != 0; c--, addr += 2) 740 *(volatile uint16_t *)(addr) = v; 741} 742 743static __inline void 744ia64_bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, 745 bus_size_t o, uint32_t v, size_t c) 746{ 747 bus_addr_t addr = h + o; 748 749 if (t == IA64_BUS_SPACE_IO) 750 for (; c != 0; c--, addr += 4) 751 outl(addr, v); 752 else 753 for (; c != 0; c--, addr += 4) 754 *(volatile uint32_t *)(addr) = v; 755} 756 757static __inline void 758ia64_bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, 759 bus_size_t o, uint64_t v, size_t c) 760{ 761 bus_addr_t addr = h + o; 762 763 if (t == IA64_BUS_SPACE_IO) 764 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__); 765 else 766 for (; c != 0; c--, addr += 8) 767 *(volatile uint32_t *)(addr) = v; 768} 769 770 771/* 772 * void bus_space_copy_region_N(bus_space_tag_t tag, 773 * bus_space_handle_t bsh1, bus_size_t off1, 774 * bus_space_handle_t bsh2, bus_size_t off2, 775 * size_t count); 776 * 777 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting 778 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. 779 */ 780 781static __inline void ia64_bus_space_copy_region_1(bus_space_tag_t, 782 bus_space_handle_t, bus_size_t, bus_space_handle_t, 783 bus_size_t, size_t); 784static __inline void ia64_bus_space_copy_region_2(bus_space_tag_t, 785 bus_space_handle_t, bus_size_t, bus_space_handle_t, 786 bus_size_t, size_t); 787static __inline void ia64_bus_space_copy_region_4(bus_space_tag_t, 788 bus_space_handle_t, bus_size_t, bus_space_handle_t, 789 bus_size_t, size_t); 790 791#define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \ 792 ia64_bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c)) 793 794#define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \ 795do { \ 796 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint16_t, "bus addr 1"); \ 797 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint16_t, "bus addr 2"); \ 798 ia64_bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c)); \ 799} while (/* CONSTCOND */ 0) 800 801#define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \ 802do { \ 803 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint32_t, "bus addr 1"); \ 804 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint32_t, "bus addr 2"); \ 805 ia64_bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c)); \ 806} while (/* CONSTCOND */ 0) 807 808#define bus_space_copy_region_8(t, h1, o1, h2, o2, c) \ 809do { \ 810 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint64_t, "bus addr 1"); \ 811 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint64_t, "bus addr 2"); \ 812 ia64_bus_space_copy_region_8((t), (h1), (o1), (h2), (o2), (c)); \ 813} while (/* CONSTCOND */ 0) 814 815static __inline void 816ia64_bus_space_copy_region_1(bus_space_tag_t t, 817 bus_space_handle_t h1, bus_size_t o1, 818 bus_space_handle_t h2, bus_size_t o2, size_t c) 819{ 820 bus_addr_t addr1 = h1 + o1; 821 bus_addr_t addr2 = h2 + o2; 822 823 if (t == IA64_BUS_SPACE_IO) { 824 if (addr1 >= addr2) { 825 /* src after dest: copy forward */ 826 for (; c != 0; c--, addr1++, addr2++) 827 outb(addr2, inb(addr1)); 828 } else { 829 /* dest after src: copy backwards */ 830 for (addr1 += (c - 1), addr2 += (c - 1); 831 c != 0; c--, addr1--, addr2--) 832 outb(addr2, inb(addr1)); 833 } 834 } else { 835 if (addr1 >= addr2) { 836 /* src after dest: copy forward */ 837 for (; c != 0; c--, addr1++, addr2++) 838 *(volatile uint8_t *)(addr2) = 839 *(volatile uint8_t *)(addr1); 840 } else { 841 /* dest after src: copy backwards */ 842 for (addr1 += (c - 1), addr2 += (c - 1); 843 c != 0; c--, addr1--, addr2--) 844 *(volatile uint8_t *)(addr2) = 845 *(volatile uint8_t *)(addr1); 846 } 847 } 848} 849 850static __inline void 851ia64_bus_space_copy_region_2(bus_space_tag_t t, 852 bus_space_handle_t h1, bus_size_t o1, 853 bus_space_handle_t h2, bus_size_t o2, size_t c) 854{ 855 bus_addr_t addr1 = h1 + o1; 856 bus_addr_t addr2 = h2 + o2; 857 858 if (t == IA64_BUS_SPACE_IO) { 859 if (addr1 >= addr2) { 860 /* src after dest: copy forward */ 861 for (; c != 0; c--, addr1 += 2, addr2 += 2) 862 outw(addr2, inw(addr1)); 863 } else { 864 /* dest after src: copy backwards */ 865 for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1); 866 c != 0; c--, addr1 -= 2, addr2 -= 2) 867 outw(addr2, inw(addr1)); 868 } 869 } else { 870 if (addr1 >= addr2) { 871 /* src after dest: copy forward */ 872 for (; c != 0; c--, addr1 += 2, addr2 += 2) 873 *(volatile uint16_t *)(addr2) = 874 *(volatile uint16_t *)(addr1); 875 } else { 876 /* dest after src: copy backwards */ 877 for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1); 878 c != 0; c--, addr1 -= 2, addr2 -= 2) 879 *(volatile uint16_t *)(addr2) = 880 *(volatile uint16_t *)(addr1); 881 } 882 } 883} 884 885static __inline void 886ia64_bus_space_copy_region_4(bus_space_tag_t t, 887 bus_space_handle_t h1, bus_size_t o1, 888 bus_space_handle_t h2, bus_size_t o2, size_t c) 889{ 890 bus_addr_t addr1 = h1 + o1; 891 bus_addr_t addr2 = h2 + o2; 892 893 if (t == IA64_BUS_SPACE_IO) { 894 if (addr1 >= addr2) { 895 /* src after dest: copy forward */ 896 for (; c != 0; c--, addr1 += 4, addr2 += 4) 897 outl(addr2, inl(addr1)); 898 } else { 899 /* dest after src: copy backwards */ 900 for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1); 901 c != 0; c--, addr1 -= 4, addr2 -= 4) 902 outl(addr2, inl(addr1)); 903 } 904 } else { 905 if (addr1 >= addr2) { 906 /* src after dest: copy forward */ 907 for (; c != 0; c--, addr1 += 4, addr2 += 4) 908 *(volatile uint32_t *)(addr2) = 909 *(volatile uint32_t *)(addr1); 910 } else { 911 /* dest after src: copy backwards */ 912 for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1); 913 c != 0; c--, addr1 -= 4, addr2 -= 4) 914 *(volatile uint32_t *)(addr2) = 915 *(volatile uint32_t *)(addr1); 916 } 917 } 918} 919 920static __inline void 921ia64_bus_space_copy_region_8(bus_space_tag_t t, 922 bus_space_handle_t h1, bus_size_t o1, 923 bus_space_handle_t h2, bus_size_t o2, size_t c) 924{ 925 bus_addr_t addr1 = h1 + o1; 926 bus_addr_t addr2 = h2 + o2; 927 928 if (t == IA64_BUS_SPACE_IO) { 929 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__); 930 } else { 931 if (addr1 >= addr2) { 932 /* src after dest: copy forward */ 933 for (; c != 0; c--, addr1 += 8, addr2 += 8) 934 *(volatile uint64_t *)(addr2) = 935 *(volatile uint64_t *)(addr1); 936 } else { 937 /* dest after src: copy backwards */ 938 for (addr1 += 8 * (c - 1), addr2 += 8 * (c - 1); 939 c != 0; c--, addr1 -= 8, addr2 -= 8) 940 *(volatile uint64_t *)(addr2) = 941 *(volatile uint64_t *)(addr1); 942 } 943 } 944} 945 946 947/* 948 * Bus read/write barrier methods. 949 * 950 * void bus_space_barrier(bus_space_tag_t tag, 951 * bus_space_handle_t bsh, bus_size_t offset, 952 * bus_size_t len, int flags); 953 * 954 * Note: the x86 does not currently require barriers, but we must 955 * provide the flags to MI code. 956 */ 957#define bus_space_barrier(t, h, o, l, f) \ 958 ia64_bus_space_barrier((t), (h), (o), (l), (f)) 959 960 961#define BUS_SPACE_BARRIER_READ 0x01 962#define BUS_SPACE_BARRIER_WRITE 0x02 963 964/* XXX to be investigated: are these used? */ 965#define BUS_SPACE_BARRIER_READ_BEFORE_READ 0x04 966#define BUS_SPACE_BARRIER_READ_BEFORE_WRITE 0x08 967#define BUS_SPACE_BARRIER_WRITE_BEFORE_READ 0x10 968#define BUS_SPACE_BARRIER_WRITE_BEFORE_WRITE 0x20 969#define BUS_SPACE_BARRIER_SYNC 0x40 970 971static __inline void 972ia64_bus_space_barrier(bus_space_tag_t t, bus_space_handle_t handle, 973 bus_size_t offset, bus_size_t length, int flags) 974{ 975 if (t == IA64_BUS_SPACE_IO) 976 return; 977 978 switch (flags) { 979 case BUS_SPACE_BARRIER_READ: 980 __asm volatile("mf" ::: "memory"); 981 break; 982 case BUS_SPACE_BARRIER_WRITE: 983 __asm volatile("mf" ::: "memory"); 984 break; 985 case BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE: 986 __asm volatile("mf" ::: "memory"); 987 break; 988 default: 989 printf("%s: Unknown barrier %d\n", __FUNCTION__, flags); 990 break; 991 } 992} 993 994 995/* 996 * Flags used in various bus DMA methods. 997 */ 998#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ 999#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ 1000#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ 1001#define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ 1002#define BUS_DMA_STREAMING 0x008 /* hint: sequential, unidirectional */ 1003#define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ 1004#define BUS_DMA_BUS2 0x020 1005#define BUS_DMA_BUS3 0x040 1006#define BUS_DMA_BUS4 0x080 1007#define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ 1008#define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ 1009#define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */ 1010 1011/* Forwards needed by prototypes below. */ 1012struct mbuf; 1013struct uio; 1014 1015/* 1016 * Operations performed by bus_dmamap_sync(). 1017 */ 1018#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ 1019#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ 1020#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ 1021#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ 1022 1023typedef struct ia64_bus_dma_tag *bus_dma_tag_t; 1024typedef struct ia64_bus_dmamap *bus_dmamap_t; 1025 1026#define BUS_DMA_TAG_VALID(t) ((t) != (bus_dma_tag_t)0) 1027 1028/* 1029 * bus_dma_segment_t 1030 * 1031 * Describes a single contiguous DMA transaction. Values 1032 * are suitable for programming into DMA registers. 1033 */ 1034struct ia64_bus_dma_segment { 1035 bus_addr_t ds_addr; /* DMA address */ 1036 bus_size_t ds_len; /* length of transfer */ 1037}; 1038typedef struct ia64_bus_dma_segment bus_dma_segment_t; 1039 1040/* 1041 * bus_dma_tag_t 1042 * 1043 * A machine-dependent opaque type describing the implementation of 1044 * DMA for a given bus. 1045 */ 1046 1047struct ia64_bus_dma_tag { 1048 /* 1049 * The `bounce threshold' is checked while we are loading 1050 * the DMA map. If the physical address of the segment 1051 * exceeds the threshold, an error will be returned. The 1052 * caller can then take whatever action is necessary to 1053 * bounce the transfer. If this value is 0, it will be 1054 * ignored. 1055 */ 1056 bus_addr_t _bounce_thresh; 1057 bus_addr_t _bounce_alloc_lo; 1058 bus_addr_t _bounce_alloc_hi; 1059 int (*_may_bounce)(bus_dma_tag_t, bus_dmamap_t, int, int *); 1060 1061 /* 1062 * DMA mapping methods. 1063 */ 1064 int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, 1065 bus_size_t, bus_size_t, int, bus_dmamap_t *); 1066 void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); 1067 int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, 1068 bus_size_t, struct proc *, int); 1069 int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, 1070 struct mbuf *, int); 1071 int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, 1072 struct uio *, int); 1073 int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, 1074 bus_dma_segment_t *, int, bus_size_t, int); 1075 void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); 1076 void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, 1077 bus_addr_t, bus_size_t, int); 1078 1079 /* 1080 * DMA memory utility functions. 1081 */ 1082 int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, 1083 bus_size_t, bus_dma_segment_t *, int, int *, int); 1084 void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); 1085 int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, 1086 int, size_t, void **, int); 1087 void (*_dmamem_unmap)(bus_dma_tag_t, void *, size_t); 1088 paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, 1089 int, off_t, int, int); 1090}; 1091 1092static __inline void bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, 1093 bus_addr_t, bus_size_t, int) __attribute__((__unused__)); 1094 1095#define bus_dmamap_create(t, s, n, m, b, f, p) \ 1096 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) 1097#define bus_dmamap_destroy(t, p) \ 1098 (*(t)->_dmamap_destroy)((t), (p)) 1099#define bus_dmamap_load(t, m, b, s, p, f) \ 1100 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) 1101#define bus_dmamap_load_mbuf(t, m, b, f) \ 1102 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) 1103#define bus_dmamap_load_uio(t, m, u, f) \ 1104 (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) 1105#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ 1106 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) 1107#define bus_dmamap_unload(t, p) \ 1108 (*(t)->_dmamap_unload)((t), (p)) 1109static __inline void 1110bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t p, bus_addr_t o, bus_size_t l, 1111 int ops) 1112{ 1113 /* if (ops & BUS_DMASYNC_POSTREAD) 1114 x86_lfence(); */ 1115 if (t->_dmamap_sync) 1116 (*t->_dmamap_sync)(t, p, o, l, ops); 1117} 1118 1119#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ 1120 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) 1121#define bus_dmamem_free(t, sg, n) \ 1122 (*(t)->_dmamem_free)((t), (sg), (n)) 1123#define bus_dmamem_map(t, sg, n, s, k, f) \ 1124 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) 1125#define bus_dmamem_unmap(t, k, s) \ 1126 (*(t)->_dmamem_unmap)((t), (k), (s)) 1127#define bus_dmamem_mmap(t, sg, n, o, p, f) \ 1128 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) 1129 1130/* 1131 * bus_dmamap_t 1132 * 1133 * Describes a DMA mapping. 1134 */ 1135struct ia64_bus_dmamap { 1136 /* 1137 * PRIVATE MEMBERS: not for use by machine-independent code. 1138 */ 1139 bus_size_t _dm_size; /* largest DMA transfer mappable */ 1140 int _dm_segcnt; /* number of segs this map can map */ 1141 bus_size_t _dm_maxmaxsegsz; /* fixed largest possible segment */ 1142 bus_size_t _dm_boundary; /* don't cross this */ 1143 bus_addr_t _dm_bounce_thresh; /* bounce threshold; see tag */ 1144 int _dm_flags; /* misc. flags */ 1145 1146 void *_dm_cookie; /* cookie for bus-specific functions */ 1147 1148 /* 1149 * PUBLIC MEMBERS: these are used by machine-independent code. 1150 */ 1151 bus_size_t dm_maxsegsz; /* largest possible segment */ 1152 bus_size_t dm_mapsize; /* size of the mapping */ 1153 int dm_nsegs; /* # valid segments in mapping */ 1154 bus_dma_segment_t dm_segs[1]; /* segments; variable length */ 1155}; 1156 1157#endif /* _IA64_BUS_H_ */ 1158