1 /* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997 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 /* $FreeBSD$ */ 71 72 #ifndef _I386_BUS_H_ 73 #define _I386_BUS_H_ 74 75 #include <machine/cpufunc.h> 76 77 /* 78 * To remain compatible with NetBSD's interface, default to both memio and 79 * pio when neither of them is defined. 80 */ 81 #if !defined(_I386_BUS_PIO_H_) && !defined(_I386_BUS_MEMIO_H_) 82 #define _I386_BUS_PIO_H_ 83 #define _I386_BUS_MEMIO_H_ 84 #endif 85 86 /* 87 * Values for the i386 bus space tag, not to be used directly by MI code. 88 */ 89 #define I386_BUS_SPACE_IO 0 /* space is i/o space */ 90 #define I386_BUS_SPACE_MEM 1 /* space is mem space */ 91 92 /* 93 * Bus address and size types 94 */ 95 typedef u_int bus_addr_t; 96 typedef u_int bus_size_t; 97 98 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF 99 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF 100 #define BUS_SPACE_MAXSIZE (64 * 1024) /* Maximum supported size */ 101 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF 102 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF 103 #define BUS_SPACE_MAXADDR 0xFFFFFFFF 104 105 #define BUS_SPACE_UNRESTRICTED (~0) 106 107 /* 108 * Access methods for bus resources and address space. 109 */ 110 typedef int bus_space_tag_t; 111 typedef u_int bus_space_handle_t; 112 113 /* 114 * Map a region of device bus space into CPU virtual address space. 115 */ 116 117 #define BUS_SPACE_MAP_CACHEABLE 0x01 118 #define BUS_SPACE_MAP_LINEAR 0x02 119 120 int bus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, 121 int flags, bus_space_handle_t *bshp); 122 123 /* 124 * Unmap a region of device bus space. 125 */ 126 127 void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, 128 bus_size_t size); 129 130 /* 131 * Get a new handle for a subregion of an already-mapped area of bus space. 132 */ 133 134 int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, 135 bus_size_t offset, bus_size_t size, 136 bus_space_handle_t *nbshp); 137 138 /* 139 * Allocate a region of memory that is accessible to devices in bus space. 140 */ 141 142 int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, 143 bus_addr_t rend, bus_size_t size, bus_size_t align, 144 bus_size_t boundary, int flags, bus_addr_t *addrp, 145 bus_space_handle_t *bshp); 146 147 /* 148 * Free a region of bus space accessible memory. 149 */ 150 151 void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, 152 bus_size_t size); 153 154 #if defined(_I386_BUS_PIO_H_) || defined(_I386_BUS_MEMIO_H_) 155 156 /* 157 * Read a 1, 2, 4, or 8 byte quantity from bus space 158 * described by tag/handle/offset. 159 */ 160 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag, 161 bus_space_handle_t handle, 162 bus_size_t offset); 163 164 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag, 165 bus_space_handle_t handle, 166 bus_size_t offset); 167 168 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag, 169 bus_space_handle_t handle, 170 bus_size_t offset); 171 172 static __inline u_int8_t 173 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle, 174 bus_size_t offset) 175 { 176 #if defined (_I386_BUS_PIO_H_) 177 #if defined (_I386_BUS_MEMIO_H_) 178 if (tag == I386_BUS_SPACE_IO) 179 #endif 180 return (inb(handle + offset)); 181 #endif 182 #if defined (_I386_BUS_MEMIO_H_) 183 return (*(volatile u_int8_t *)(handle + offset)); 184 #endif 185 } 186 187 static __inline u_int16_t 188 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle, 189 bus_size_t offset) 190 { 191 #if defined(_I386_BUS_PIO_H_) 192 #if defined(_I386_BUS_MEMIO_H_) 193 if (tag == I386_BUS_SPACE_IO) 194 #endif 195 return (inw(handle + offset)); 196 #endif 197 #if defined(_I386_BUS_MEMIO_H_) 198 return (*(volatile u_int16_t *)(handle + offset)); 199 #endif 200 } 201 202 static __inline u_int32_t 203 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle, 204 bus_size_t offset) 205 { 206 #if defined(_I386_BUS_PIO_H_) 207 #if defined(_I386_BUS_MEMIO_H_) 208 if (tag == I386_BUS_SPACE_IO) 209 #endif 210 return (inl(handle + offset)); 211 #endif 212 #if defined(_I386_BUS_MEMIO_H_) 213 return (*(volatile u_int32_t *)(handle + offset)); 214 #endif 215 } 216 217 #if 0 /* Cause a link error for bus_space_read_8 */ 218 #define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!! 219 #endif 220 221 /* 222 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 223 * described by tag/handle/offset and copy into buffer provided. 224 */ 225 static __inline void bus_space_read_multi_1(bus_space_tag_t tag, 226 bus_space_handle_t bsh, 227 bus_size_t offset, u_int8_t *addr, 228 size_t count); 229 230 static __inline void bus_space_read_multi_2(bus_space_tag_t tag, 231 bus_space_handle_t bsh, 232 bus_size_t offset, u_int16_t *addr, 233 size_t count); 234 235 static __inline void bus_space_read_multi_4(bus_space_tag_t tag, 236 bus_space_handle_t bsh, 237 bus_size_t offset, u_int32_t *addr, 238 size_t count); 239 240 static __inline void 241 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 242 bus_size_t offset, u_int8_t *addr, size_t count) 243 { 244 #if defined(_I386_BUS_PIO_H_) 245 #if defined(_I386_BUS_MEMIO_H_) 246 if (tag == I386_BUS_SPACE_IO) 247 #endif 248 insb(bsh + offset, addr, count); 249 #endif 250 #if defined(_I386_BUS_MEMIO_H_) 251 #if defined(_I386_BUS_PIO_H_) 252 else 253 #endif 254 { 255 int __x __asm__("%eax"); 256 __asm __volatile(" \n\ 257 cld \n\ 258 1: movb (%1),%%al \n\ 259 stosb \n\ 260 loop 1b" : 261 "=&a" (__x) : 262 "r" (bsh + offset), "D" (addr), "c" (count) : 263 "%edi", "%ecx", "memory"); 264 } 265 #endif 266 } 267 268 static __inline void 269 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 270 bus_size_t offset, u_int16_t *addr, size_t count) 271 { 272 #if defined(_I386_BUS_PIO_H_) 273 #if defined(_I386_BUS_MEMIO_H_) 274 if (tag == I386_BUS_SPACE_IO) 275 #endif 276 insw(bsh + offset, addr, count); 277 #endif 278 #if defined(_I386_BUS_MEMIO_H_) 279 #if defined(_I386_BUS_PIO_H_) 280 else 281 #endif 282 { 283 int __x __asm__("%eax"); 284 __asm __volatile(" \n\ 285 cld \n\ 286 1: movw (%1),%%ax \n\ 287 stosw \n\ 288 loop 1b" : 289 "=&a" (__x) : 290 "r" (bsh + offset), "D" (addr), "c" (count) : 291 "%edi", "%ecx", "memory"); 292 } 293 #endif 294 } 295 296 static __inline void 297 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 298 bus_size_t offset, u_int32_t *addr, size_t count) 299 { 300 #if defined(_I386_BUS_PIO_H_) 301 #if defined(_I386_BUS_MEMIO_H_) 302 if (tag == I386_BUS_SPACE_IO) 303 #endif 304 insl(bsh + offset, addr, count); 305 #endif 306 #if defined(_I386_BUS_MEMIO_H_) 307 #if defined(_I386_BUS_PIO_H_) 308 else 309 #endif 310 { 311 int __x __asm__("%eax"); 312 __asm __volatile(" \n\ 313 cld \n\ 314 1: movl (%1),%%eax \n\ 315 stosl \n\ 316 loop 1b" : 317 "=&a" (__x) : 318 "r" (bsh + offset), "D" (addr), "c" (count) : 319 "%edi", "%ecx", "memory"); 320 } 321 #endif 322 } 323 324 #if 0 /* Cause a link error for bus_space_read_multi_8 */ 325 #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!! 326 #endif 327 328 /* 329 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 330 * described by tag/handle and starting at `offset' and copy into 331 * buffer provided. 332 */ 333 static __inline void bus_space_read_region_1(bus_space_tag_t tag, 334 bus_space_handle_t bsh, 335 bus_size_t offset, u_int8_t *addr, 336 size_t count); 337 338 static __inline void bus_space_read_region_2(bus_space_tag_t tag, 339 bus_space_handle_t bsh, 340 bus_size_t offset, u_int16_t *addr, 341 size_t count); 342 343 static __inline void bus_space_read_region_4(bus_space_tag_t tag, 344 bus_space_handle_t bsh, 345 bus_size_t offset, u_int32_t *addr, 346 size_t count); 347 348 349 static __inline void 350 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 351 bus_size_t offset, u_int8_t *addr, size_t count) 352 { 353 #if defined(_I386_BUS_PIO_H_) 354 #if defined(_I386_BUS_MEMIO_H_) 355 if (tag == I386_BUS_SPACE_IO) 356 #endif 357 { 358 int __x __asm__("%eax"); 359 __asm __volatile(" \n\ 360 cld \n\ 361 1: inb %w1,%%al \n\ 362 stosb \n\ 363 incl %1 \n\ 364 loop 1b" : 365 "=&a" (__x) : 366 "d" (bsh + offset), "D" (addr), "c" (count) : 367 "%edx", "%edi", "%ecx", "memory"); 368 } 369 #endif 370 #if defined(_I386_BUS_MEMIO_H_) 371 #if defined(_I386_BUS_PIO_H_) 372 else 373 #endif 374 { 375 __asm __volatile(" \n\ 376 cld \n\ 377 repne \n\ 378 movsb" : 379 : 380 "S" (bsh + offset), "D" (addr), "c" (count) : 381 "%esi", "%edi", "%ecx", "memory"); 382 } 383 #endif 384 } 385 386 static __inline void 387 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 388 bus_size_t offset, u_int16_t *addr, size_t count) 389 { 390 #if defined(_I386_BUS_PIO_H_) 391 #if defined(_I386_BUS_MEMIO_H_) 392 if (tag == I386_BUS_SPACE_IO) 393 #endif 394 { 395 int __x __asm__("%eax"); 396 __asm __volatile(" \n\ 397 cld \n\ 398 1: inw %w1,%%ax \n\ 399 stosw \n\ 400 addl $2,%1 \n\ 401 loop 1b" : 402 "=&a" (__x) : 403 "d" (bsh + offset), "D" (addr), "c" (count) : 404 "%edx", "%edi", "%ecx", "memory"); 405 } 406 #endif 407 #if defined(_I386_BUS_MEMIO_H_) 408 #if defined(_I386_BUS_PIO_H_) 409 else 410 #endif 411 { 412 __asm __volatile(" \n\ 413 cld \n\ 414 repne \n\ 415 movsw" : 416 : 417 "S" (bsh + offset), "D" (addr), "c" (count) : 418 "%esi", "%edi", "%ecx", "memory"); 419 } 420 #endif 421 } 422 423 static __inline void 424 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 425 bus_size_t offset, u_int32_t *addr, size_t count) 426 { 427 #if defined(_I386_BUS_PIO_H_) 428 #if defined(_I386_BUS_MEMIO_H_) 429 if (tag == I386_BUS_SPACE_IO) 430 #endif 431 { 432 int __x __asm__("%eax"); 433 __asm __volatile(" \n\ 434 cld \n\ 435 1: inl %w1,%%eax \n\ 436 stosl \n\ 437 addl $4,%1 \n\ 438 loop 1b" : 439 "=&a" (__x) : 440 "d" (bsh + offset), "D" (addr), "c" (count) : 441 "%edx", "%edi", "%ecx", "memory"); 442 } 443 #endif 444 #if defined(_I386_BUS_MEMIO_H_) 445 #if defined(_I386_BUS_PIO_H_) 446 else 447 #endif 448 { 449 __asm __volatile(" \n\ 450 cld \n\ 451 repne \n\ 452 movsl" : 453 : 454 "S" (bsh + offset), "D" (addr), "c" (count) : 455 "%esi", "%edi", "%ecx", "memory"); 456 } 457 #endif 458 } 459 460 #if 0 /* Cause a link error for bus_space_read_region_8 */ 461 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!! 462 #endif 463 464 /* 465 * Write the 1, 2, 4, or 8 byte value `value' to bus space 466 * described by tag/handle/offset. 467 */ 468 469 static __inline void bus_space_write_1(bus_space_tag_t tag, 470 bus_space_handle_t bsh, 471 bus_size_t offset, u_int8_t value); 472 473 static __inline void bus_space_write_2(bus_space_tag_t tag, 474 bus_space_handle_t bsh, 475 bus_size_t offset, u_int16_t value); 476 477 static __inline void bus_space_write_4(bus_space_tag_t tag, 478 bus_space_handle_t bsh, 479 bus_size_t offset, u_int32_t value); 480 481 static __inline void 482 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh, 483 bus_size_t offset, u_int8_t value) 484 { 485 #if defined(_I386_BUS_PIO_H_) 486 #if defined(_I386_BUS_MEMIO_H_) 487 if (tag == I386_BUS_SPACE_IO) 488 #endif 489 outb(bsh + offset, value); 490 #endif 491 #if defined(_I386_BUS_MEMIO_H_) 492 #if defined(_I386_BUS_PIO_H_) 493 else 494 #endif 495 *(volatile u_int8_t *)(bsh + offset) = value; 496 #endif 497 } 498 499 static __inline void 500 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh, 501 bus_size_t offset, u_int16_t value) 502 { 503 #if defined(_I386_BUS_PIO_H_) 504 #if defined(_I386_BUS_MEMIO_H_) 505 if (tag == I386_BUS_SPACE_IO) 506 #endif 507 outw(bsh + offset, value); 508 #endif 509 #if defined(_I386_BUS_MEMIO_H_) 510 #if defined(_I386_BUS_PIO_H_) 511 else 512 #endif 513 *(volatile u_int16_t *)(bsh + offset) = value; 514 #endif 515 } 516 517 static __inline void 518 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh, 519 bus_size_t offset, u_int32_t value) 520 { 521 #if defined(_I386_BUS_PIO_H_) 522 #if defined(_I386_BUS_MEMIO_H_) 523 if (tag == I386_BUS_SPACE_IO) 524 #endif 525 outl(bsh + offset, value); 526 #endif 527 #if defined(_I386_BUS_MEMIO_H_) 528 #if defined(_I386_BUS_PIO_H_) 529 else 530 #endif 531 *(volatile u_int32_t *)(bsh + offset) = value; 532 #endif 533 } 534 535 #if 0 /* Cause a link error for bus_space_write_8 */ 536 #define bus_space_write_8 !!! bus_space_write_8 not implemented !!! 537 #endif 538 539 /* 540 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer 541 * provided to bus space described by tag/handle/offset. 542 */ 543 544 static __inline void bus_space_write_multi_1(bus_space_tag_t tag, 545 bus_space_handle_t bsh, 546 bus_size_t offset, 547 const u_int8_t *addr, 548 size_t count); 549 static __inline void bus_space_write_multi_2(bus_space_tag_t tag, 550 bus_space_handle_t bsh, 551 bus_size_t offset, 552 const u_int16_t *addr, 553 size_t count); 554 555 static __inline void bus_space_write_multi_4(bus_space_tag_t tag, 556 bus_space_handle_t bsh, 557 bus_size_t offset, 558 const u_int32_t *addr, 559 size_t count); 560 561 static __inline void 562 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 563 bus_size_t offset, const u_int8_t *addr, size_t count) 564 { 565 #if defined(_I386_BUS_PIO_H_) 566 #if defined(_I386_BUS_MEMIO_H_) 567 if (tag == I386_BUS_SPACE_IO) 568 #endif 569 outsb(bsh + offset, addr, count); 570 #endif 571 #if defined(_I386_BUS_MEMIO_H_) 572 #if defined(_I386_BUS_PIO_H_) 573 else 574 #endif 575 { 576 int __x __asm__("%eax"); 577 __asm __volatile(" \n\ 578 cld \n\ 579 1: lodsb \n\ 580 movb %%al,(%1) \n\ 581 loop 1b" : 582 "=&a" (__x) : 583 "r" (bsh + offset), "S" (addr), "c" (count) : 584 "%esi", "%ecx"); 585 } 586 #endif 587 } 588 589 static __inline void 590 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 591 bus_size_t offset, const u_int16_t *addr, size_t count) 592 { 593 #if defined(_I386_BUS_PIO_H_) 594 #if defined(_I386_BUS_MEMIO_H_) 595 if (tag == I386_BUS_SPACE_IO) 596 #endif 597 outsw(bsh + offset, addr, count); 598 #endif 599 #if defined(_I386_BUS_MEMIO_H_) 600 #if defined(_I386_BUS_PIO_H_) 601 else 602 #endif 603 { 604 int __x __asm__("%eax"); 605 __asm __volatile(" \n\ 606 cld \n\ 607 1: lodsw \n\ 608 movw %%ax,(%1) \n\ 609 loop 1b" : 610 "=&a" (__x) : 611 "r" (bsh + offset), "S" (addr), "c" (count) : 612 "%esi", "%ecx"); 613 } 614 #endif 615 } 616 617 static __inline void 618 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 619 bus_size_t offset, const u_int32_t *addr, size_t count) 620 { 621 #if defined(_I386_BUS_PIO_H_) 622 #if defined(_I386_BUS_MEMIO_H_) 623 if (tag == I386_BUS_SPACE_IO) 624 #endif 625 outsl(bsh + offset, addr, count); 626 #endif 627 #if defined(_I386_BUS_MEMIO_H_) 628 #if defined(_I386_BUS_PIO_H_) 629 else 630 #endif 631 { 632 int __x __asm__("%eax"); 633 __asm __volatile(" \n\ 634 cld \n\ 635 1: lodsl \n\ 636 movl %%eax,(%1) \n\ 637 loop 1b" : 638 "=&a" (__x) : 639 "r" (bsh + offset), "S" (addr), "c" (count) : 640 "%esi", "%ecx"); 641 } 642 #endif 643 } 644 645 #if 0 /* Cause a link error for bus_space_write_multi_8 */ 646 #define bus_space_write_multi_8(t, h, o, a, c) \ 647 !!! bus_space_write_multi_8 unimplemented !!! 648 #endif 649 650 /* 651 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided 652 * to bus space described by tag/handle starting at `offset'. 653 */ 654 655 static __inline void bus_space_write_region_1(bus_space_tag_t tag, 656 bus_space_handle_t bsh, 657 bus_size_t offset, 658 const u_int8_t *addr, 659 size_t count); 660 static __inline void bus_space_write_region_2(bus_space_tag_t tag, 661 bus_space_handle_t bsh, 662 bus_size_t offset, 663 const u_int16_t *addr, 664 size_t count); 665 static __inline void bus_space_write_region_4(bus_space_tag_t tag, 666 bus_space_handle_t bsh, 667 bus_size_t offset, 668 const u_int32_t *addr, 669 size_t count); 670 671 static __inline void 672 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 673 bus_size_t offset, const u_int8_t *addr, size_t count) 674 { 675 #if defined(_I386_BUS_PIO_H_) 676 #if defined(_I386_BUS_MEMIO_H_) 677 if (tag == I386_BUS_SPACE_IO) 678 #endif 679 { 680 int __x __asm__("%eax"); 681 __asm __volatile(" \n\ 682 cld \n\ 683 1: lodsb \n\ 684 outb %%al,%w1 \n\ 685 incl %1 \n\ 686 loop 1b" : 687 "=&a" (__x) : 688 "d" (bsh + offset), "S" (addr), "c" (count) : 689 "%edx", "%esi", "%ecx", "memory"); 690 } 691 #endif 692 #if defined(_I386_BUS_MEMIO_H_) 693 #if defined(_I386_BUS_PIO_H_) 694 else 695 #endif 696 { 697 __asm __volatile(" \n\ 698 cld \n\ 699 repne \n\ 700 movsb" : 701 : 702 "D" (bsh + offset), "S" (addr), "c" (count) : 703 "%edi", "%esi", "%ecx", "memory"); 704 } 705 #endif 706 } 707 708 static __inline void 709 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 710 bus_size_t offset, const u_int16_t *addr, size_t count) 711 { 712 #if defined(_I386_BUS_PIO_H_) 713 #if defined(_I386_BUS_MEMIO_H_) 714 if (tag == I386_BUS_SPACE_IO) 715 #endif 716 { 717 int __x __asm__("%eax"); 718 __asm __volatile(" \n\ 719 cld \n\ 720 1: lodsw \n\ 721 outw %%ax,%w1 \n\ 722 addl $2,%1 \n\ 723 loop 1b" : 724 "=&a" (__x) : 725 "d" (bsh + offset), "S" (addr), "c" (count) : 726 "%edx", "%esi", "%ecx", "memory"); 727 } 728 #endif 729 #if defined(_I386_BUS_MEMIO_H_) 730 #if defined(_I386_BUS_PIO_H_) 731 else 732 #endif 733 { 734 __asm __volatile(" \n\ 735 cld \n\ 736 repne \n\ 737 movsw" : 738 : 739 "D" (bsh + offset), "S" (addr), "c" (count) : 740 "%edi", "%esi", "%ecx", "memory"); 741 } 742 #endif 743 } 744 745 static __inline void 746 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 747 bus_size_t offset, const u_int32_t *addr, size_t count) 748 { 749 #if defined(_I386_BUS_PIO_H_) 750 #if defined(_I386_BUS_MEMIO_H_) 751 if (tag == I386_BUS_SPACE_IO) 752 #endif 753 { 754 int __x __asm__("%eax"); 755 __asm __volatile(" \n\ 756 cld \n\ 757 1: lodsl \n\ 758 outl %%eax,%w1 \n\ 759 addl $4,%1 \n\ 760 loop 1b" : 761 "=&a" (__x) : 762 "d" (bsh + offset), "S" (addr), "c" (count) : 763 "%edx", "%esi", "%ecx", "memory"); 764 } 765 #endif 766 #if defined(_I386_BUS_MEMIO_H_) 767 #if defined(_I386_BUS_PIO_H_) 768 else 769 #endif 770 { 771 __asm __volatile(" \n\ 772 cld \n\ 773 repne \n\ 774 movsl" : 775 : 776 "D" (bsh + offset), "S" (addr), "c" (count) : 777 "%edi", "%esi", "%ecx", "memory"); 778 } 779 #endif 780 } 781 782 #if 0 /* Cause a link error for bus_space_write_region_8 */ 783 #define bus_space_write_region_8 \ 784 !!! bus_space_write_region_8 unimplemented !!! 785 #endif 786 787 /* 788 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 789 * by tag/handle/offset `count' times. 790 */ 791 792 static __inline void bus_space_set_multi_1(bus_space_tag_t tag, 793 bus_space_handle_t bsh, 794 bus_size_t offset, 795 u_int8_t value, size_t count); 796 static __inline void bus_space_set_multi_2(bus_space_tag_t tag, 797 bus_space_handle_t bsh, 798 bus_size_t offset, 799 u_int16_t value, size_t count); 800 static __inline void bus_space_set_multi_4(bus_space_tag_t tag, 801 bus_space_handle_t bsh, 802 bus_size_t offset, 803 u_int32_t value, size_t count); 804 805 static __inline void 806 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 807 bus_size_t offset, u_int8_t value, size_t count) 808 { 809 bus_addr_t addr = bsh + offset; 810 811 #if defined(_I386_BUS_PIO_H_) 812 #if defined(_I386_BUS_MEMIO_H_) 813 if (tag == I386_BUS_SPACE_IO) 814 #endif 815 while (count--) 816 outb(addr, value); 817 #endif 818 #if defined(_I386_BUS_MEMIO_H_) 819 #if defined(_I386_BUS_PIO_H_) 820 else 821 #endif 822 while (count--) 823 *(volatile u_int8_t *)(addr) = value; 824 #endif 825 } 826 827 static __inline void 828 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 829 bus_size_t offset, u_int16_t value, size_t count) 830 { 831 bus_addr_t addr = bsh + offset; 832 833 #if defined(_I386_BUS_PIO_H_) 834 #if defined(_I386_BUS_MEMIO_H_) 835 if (tag == I386_BUS_SPACE_IO) 836 #endif 837 while (count--) 838 outw(addr, value); 839 #endif 840 #if defined(_I386_BUS_MEMIO_H_) 841 #if defined(_I386_BUS_PIO_H_) 842 else 843 #endif 844 while (count--) 845 *(volatile u_int16_t *)(addr) = value; 846 #endif 847 } 848 849 static __inline void 850 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 851 bus_size_t offset, u_int32_t value, size_t count) 852 { 853 bus_addr_t addr = bsh + offset; 854 855 #if defined(_I386_BUS_PIO_H_) 856 #if defined(_I386_BUS_MEMIO_H_) 857 if (tag == I386_BUS_SPACE_IO) 858 #endif 859 while (count--) 860 outl(addr, value); 861 #endif 862 #if defined(_I386_BUS_MEMIO_H_) 863 #if defined(_I386_BUS_PIO_H_) 864 else 865 #endif 866 while (count--) 867 *(volatile u_int32_t *)(addr) = value; 868 #endif 869 } 870 871 #if 0 /* Cause a link error for bus_space_set_multi_8 */ 872 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!! 873 #endif 874 875 /* 876 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described 877 * by tag/handle starting at `offset'. 878 */ 879 880 static __inline void bus_space_set_region_1(bus_space_tag_t tag, 881 bus_space_handle_t bsh, 882 bus_size_t offset, u_int8_t value, 883 size_t count); 884 static __inline void bus_space_set_region_2(bus_space_tag_t tag, 885 bus_space_handle_t bsh, 886 bus_size_t offset, u_int16_t value, 887 size_t count); 888 static __inline void bus_space_set_region_4(bus_space_tag_t tag, 889 bus_space_handle_t bsh, 890 bus_size_t offset, u_int32_t value, 891 size_t count); 892 893 static __inline void 894 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 895 bus_size_t offset, u_int8_t value, size_t count) 896 { 897 bus_addr_t addr = bsh + offset; 898 899 #if defined(_I386_BUS_PIO_H_) 900 #if defined(_I386_BUS_MEMIO_H_) 901 if (tag == I386_BUS_SPACE_IO) 902 #endif 903 for (; count != 0; count--, addr++) 904 outb(addr, value); 905 #endif 906 #if defined(_I386_BUS_MEMIO_H_) 907 #if defined(_I386_BUS_PIO_H_) 908 else 909 #endif 910 for (; count != 0; count--, addr++) 911 *(volatile u_int8_t *)(addr) = value; 912 #endif 913 } 914 915 static __inline void 916 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 917 bus_size_t offset, u_int16_t value, size_t count) 918 { 919 bus_addr_t addr = bsh + offset; 920 921 #if defined(_I386_BUS_PIO_H_) 922 #if defined(_I386_BUS_MEMIO_H_) 923 if (tag == I386_BUS_SPACE_IO) 924 #endif 925 for (; count != 0; count--, addr += 2) 926 outw(addr, value); 927 #endif 928 #if defined(_I386_BUS_MEMIO_H_) 929 #if defined(_I386_BUS_PIO_H_) 930 else 931 #endif 932 for (; count != 0; count--, addr += 2) 933 *(volatile u_int16_t *)(addr) = value; 934 #endif 935 } 936 937 static __inline void 938 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 939 bus_size_t offset, u_int32_t value, size_t count) 940 { 941 bus_addr_t addr = bsh + offset; 942 943 #if defined(_I386_BUS_PIO_H_) 944 #if defined(_I386_BUS_MEMIO_H_) 945 if (tag == I386_BUS_SPACE_IO) 946 #endif 947 for (; count != 0; count--, addr += 4) 948 outl(addr, value); 949 #endif 950 #if defined(_I386_BUS_MEMIO_H_) 951 #if defined(_I386_BUS_PIO_H_) 952 else 953 #endif 954 for (; count != 0; count--, addr += 4) 955 *(volatile u_int32_t *)(addr) = value; 956 #endif 957 } 958 959 #if 0 /* Cause a link error for bus_space_set_region_8 */ 960 #define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!! 961 #endif 962 963 /* 964 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting 965 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. 966 */ 967 968 static __inline void bus_space_copy_region_1(bus_space_tag_t tag, 969 bus_space_handle_t bsh1, 970 bus_size_t off1, 971 bus_space_handle_t bsh2, 972 bus_size_t off2, size_t count); 973 974 static __inline void bus_space_copy_region_2(bus_space_tag_t tag, 975 bus_space_handle_t bsh1, 976 bus_size_t off1, 977 bus_space_handle_t bsh2, 978 bus_size_t off2, size_t count); 979 980 static __inline void bus_space_copy_region_4(bus_space_tag_t tag, 981 bus_space_handle_t bsh1, 982 bus_size_t off1, 983 bus_space_handle_t bsh2, 984 bus_size_t off2, size_t count); 985 986 static __inline void 987 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1, 988 bus_size_t off1, bus_space_handle_t bsh2, 989 bus_size_t off2, size_t count) 990 { 991 bus_addr_t addr1 = bsh1 + off1; 992 bus_addr_t addr2 = bsh2 + off2; 993 994 #if defined(_I386_BUS_PIO_H_) 995 #if defined(_I386_BUS_MEMIO_H_) 996 if (tag == I386_BUS_SPACE_IO) 997 #endif 998 { 999 if (addr1 >= addr2) { 1000 /* src after dest: copy forward */ 1001 for (; count != 0; count--, addr1++, addr2++) 1002 outb(addr2, inb(addr1)); 1003 } else { 1004 /* dest after src: copy backwards */ 1005 for (addr1 += (count - 1), addr2 += (count - 1); 1006 count != 0; count--, addr1--, addr2--) 1007 outb(addr2, inb(addr1)); 1008 } 1009 } 1010 #endif 1011 #if defined(_I386_BUS_MEMIO_H_) 1012 #if defined(_I386_BUS_PIO_H_) 1013 else 1014 #endif 1015 { 1016 if (addr1 >= addr2) { 1017 /* src after dest: copy forward */ 1018 for (; count != 0; count--, addr1++, addr2++) 1019 *(volatile u_int8_t *)(addr2) = 1020 *(volatile u_int8_t *)(addr1); 1021 } else { 1022 /* dest after src: copy backwards */ 1023 for (addr1 += (count - 1), addr2 += (count - 1); 1024 count != 0; count--, addr1--, addr2--) 1025 *(volatile u_int8_t *)(addr2) = 1026 *(volatile u_int8_t *)(addr1); 1027 } 1028 } 1029 #endif 1030 } 1031 1032 static __inline void 1033 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1, 1034 bus_size_t off1, bus_space_handle_t bsh2, 1035 bus_size_t off2, size_t count) 1036 { 1037 bus_addr_t addr1 = bsh1 + off1; 1038 bus_addr_t addr2 = bsh2 + off2; 1039 1040 #if defined(_I386_BUS_PIO_H_) 1041 #if defined(_I386_BUS_MEMIO_H_) 1042 if (tag == I386_BUS_SPACE_IO) 1043 #endif 1044 { 1045 if (addr1 >= addr2) { 1046 /* src after dest: copy forward */ 1047 for (; count != 0; count--, addr1 += 2, addr2 += 2) 1048 outw(addr2, inw(addr1)); 1049 } else { 1050 /* dest after src: copy backwards */ 1051 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); 1052 count != 0; count--, addr1 -= 2, addr2 -= 2) 1053 outw(addr2, inw(addr1)); 1054 } 1055 } 1056 #endif 1057 #if defined(_I386_BUS_MEMIO_H_) 1058 #if defined(_I386_BUS_PIO_H_) 1059 else 1060 #endif 1061 { 1062 if (addr1 >= addr2) { 1063 /* src after dest: copy forward */ 1064 for (; count != 0; count--, addr1 += 2, addr2 += 2) 1065 *(volatile u_int16_t *)(addr2) = 1066 *(volatile u_int16_t *)(addr1); 1067 } else { 1068 /* dest after src: copy backwards */ 1069 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); 1070 count != 0; count--, addr1 -= 2, addr2 -= 2) 1071 *(volatile u_int16_t *)(addr2) = 1072 *(volatile u_int16_t *)(addr1); 1073 } 1074 } 1075 #endif 1076 } 1077 1078 static __inline void 1079 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1, 1080 bus_size_t off1, bus_space_handle_t bsh2, 1081 bus_size_t off2, size_t count) 1082 { 1083 bus_addr_t addr1 = bsh1 + off1; 1084 bus_addr_t addr2 = bsh2 + off2; 1085 1086 #if defined(_I386_BUS_PIO_H_) 1087 #if defined(_I386_BUS_MEMIO_H_) 1088 if (tag == I386_BUS_SPACE_IO) 1089 #endif 1090 { 1091 if (addr1 >= addr2) { 1092 /* src after dest: copy forward */ 1093 for (; count != 0; count--, addr1 += 4, addr2 += 4) 1094 outl(addr2, inl(addr1)); 1095 } else { 1096 /* dest after src: copy backwards */ 1097 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); 1098 count != 0; count--, addr1 -= 4, addr2 -= 4) 1099 outl(addr2, inl(addr1)); 1100 } 1101 } 1102 #endif 1103 #if defined(_I386_BUS_MEMIO_H_) 1104 #if defined(_I386_BUS_PIO_H_) 1105 else 1106 #endif 1107 { 1108 if (addr1 >= addr2) { 1109 /* src after dest: copy forward */ 1110 for (; count != 0; count--, addr1 += 4, addr2 += 4) 1111 *(volatile u_int32_t *)(addr2) = 1112 *(volatile u_int32_t *)(addr1); 1113 } else { 1114 /* dest after src: copy backwards */ 1115 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); 1116 count != 0; count--, addr1 -= 4, addr2 -= 4) 1117 *(volatile u_int32_t *)(addr2) = 1118 *(volatile u_int32_t *)(addr1); 1119 } 1120 } 1121 #endif 1122 } 1123 1124 #endif /* defined(_I386_BUS_PIO_H_) || defined(_I386_MEM_IO_H_) */ 1125 1126 #if 0 /* Cause a link error for bus_space_copy_8 */ 1127 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!! 1128 #endif 1129 1130 /* 1131 * Bus read/write barrier methods. 1132 * 1133 * void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, 1134 * bus_size_t offset, bus_size_t len, int flags); 1135 * 1136 * Note: the i386 does not currently require barriers, but we must 1137 * provide the flags to MI code. 1138 */ 1139 #define bus_space_barrier(t, h, o, l, f) \ 1140 ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f))) 1141 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 1142 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 1143 1144 /* 1145 * Flags used in various bus DMA methods. 1146 */ 1147 #define BUS_DMA_WAITOK 0x00 /* safe to sleep (pseudo-flag) */ 1148 #define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */ 1149 #define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */ 1150 #define BUS_DMAMEM_NOSYNC 0x04 /* map memory to not require sync */ 1151 #define BUS_DMA_BUS1 0x10 /* placeholders for bus functions... */ 1152 #define BUS_DMA_BUS2 0x20 1153 #define BUS_DMA_BUS3 0x40 1154 #define BUS_DMA_BUS4 0x80 1155 1156 /* Forwards needed by prototypes below. */ 1157 struct mbuf; 1158 struct uio; 1159 1160 /* 1161 * bus_dmasync_op_t 1162 * 1163 * Operations performed by bus_dmamap_sync(). 1164 */ 1165 typedef enum { 1166 BUS_DMASYNC_PREREAD, 1167 BUS_DMASYNC_POSTREAD, 1168 BUS_DMASYNC_PREWRITE, 1169 BUS_DMASYNC_POSTWRITE 1170 } bus_dmasync_op_t; 1171 1172 /* 1173 * bus_dma_tag_t 1174 * 1175 * A machine-dependent opaque type describing the characteristics 1176 * of how to perform DMA mappings. This structure encapsultes 1177 * information concerning address and alignment restrictions, number 1178 * of S/G segments, amount of data per S/G segment, etc. 1179 */ 1180 typedef struct bus_dma_tag *bus_dma_tag_t; 1181 1182 /* 1183 * bus_dmamap_t 1184 * 1185 * DMA mapping instance information. 1186 */ 1187 typedef struct bus_dmamap *bus_dmamap_t; 1188 1189 /* 1190 * bus_dma_segment_t 1191 * 1192 * Describes a single contiguous DMA transaction. Values 1193 * are suitable for programming into DMA registers. 1194 */ 1195 typedef struct bus_dma_segment { 1196 bus_addr_t ds_addr; /* DMA address */ 1197 bus_size_t ds_len; /* length of transfer */ 1198 } bus_dma_segment_t; 1199 1200 /* 1201 * A function that returns 1 if the address cannot be accessed by 1202 * a device and 0 if it can be. 1203 */ 1204 typedef int bus_dma_filter_t(void *, bus_addr_t); 1205 1206 /* 1207 * Allocate a device specific dma_tag encapsulating the constraints of 1208 * the parent tag in addition to other restrictions specified: 1209 * 1210 * alignment: alignment for segments. 1211 * boundary: Boundary that segments cannot cross. 1212 * lowaddr: Low restricted address that cannot appear in a mapping. 1213 * highaddr: High restricted address that cannot appear in a mapping. 1214 * filtfunc: An optional function to further test if an address 1215 * within the range of lowaddr and highaddr cannot appear 1216 * in a mapping. 1217 * filtfuncarg: An argument that will be passed to filtfunc in addition 1218 * to the address to test. 1219 * maxsize: Maximum mapping size supported by this tag. 1220 * nsegments: Number of discontinuities allowed in maps. 1221 * maxsegsz: Maximum size of a segment in the map. 1222 * flags: Bus DMA flags. 1223 * dmat: A pointer to set to a valid dma tag should the return 1224 * value of this function indicate success. 1225 */ 1226 /* XXX Should probably allow specification of alignment */ 1227 int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignemnt, 1228 bus_size_t boundary, bus_addr_t lowaddr, 1229 bus_addr_t highaddr, bus_dma_filter_t *filtfunc, 1230 void *filtfuncarg, bus_size_t maxsize, int nsegments, 1231 bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat); 1232 1233 int bus_dma_tag_destroy(bus_dma_tag_t dmat); 1234 1235 /* 1236 * Allocate a handle for mapping from kva/uva/physical 1237 * address space into bus device space. 1238 */ 1239 int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp); 1240 1241 /* 1242 * Destroy a handle for mapping from kva/uva/physical 1243 * address space into bus device space. 1244 */ 1245 int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map); 1246 1247 /* 1248 * Allocate a piece of memory that can be efficiently mapped into 1249 * bus device space based on the constraints lited in the dma tag. 1250 * A dmamap to for use with dmamap_load is also allocated. 1251 */ 1252 int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, 1253 bus_dmamap_t *mapp); 1254 1255 /* 1256 * Free a piece of memory and it's allociated dmamap, that was allocated 1257 * via bus_dmamem_alloc. 1258 */ 1259 void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); 1260 1261 /* 1262 * A function that processes a successfully loaded dma map or an error 1263 * from a delayed load map. 1264 */ 1265 typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); 1266 1267 /* 1268 * Map the buffer buf into bus space using the dmamap map. 1269 */ 1270 int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 1271 bus_size_t buflen, bus_dmamap_callback_t *callback, 1272 void *callback_arg, int flags); 1273 1274 /* 1275 * Perform a syncronization operation on the given map. 1276 */ 1277 void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); 1278 #define bus_dmamap_sync(dmat, dmamap, op) \ 1279 if ((dmamap) != NULL) \ 1280 _bus_dmamap_sync(dmat, dmamap, op) 1281 1282 /* 1283 * Release the mapping held by map. 1284 */ 1285 void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map); 1286 #define bus_dmamap_unload(dmat, dmamap) \ 1287 if ((dmamap) != NULL) \ 1288 _bus_dmamap_unload(dmat, dmamap) 1289 1290 #endif /* _I386_BUS_H_ */ 1291