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