bus_dma.h revision 78353
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: head/sys/sys/bus_dma.h 78353 2001-06-16 15:28:28Z alex $ */ 71 72#ifndef _I386_BUS_AT386_H_ 73#define _I386_BUS_AT386_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 */ 95typedef u_int bus_addr_t; 96typedef 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 */ 110typedef int bus_space_tag_t; 111typedef 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 120int 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 127void 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 134int 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 142int 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 151void 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 */ 160static __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 164static __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 168static __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 172static __inline u_int8_t 173bus_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 187static __inline u_int16_t 188bus_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 202static __inline u_int32_t 203bus_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 */ 225static __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 230static __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 235static __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 240static __inline void 241bus_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 __asm __volatile(" \n\ 256 cld \n\ 257 1: movb (%2),%%al \n\ 258 stosb \n\ 259 loop 1b" : 260 "=D" (addr), "=c" (count) : 261 "r" (bsh + offset), "0" (addr), "1" (count) : 262 "%eax", "memory"); 263 } 264#endif 265} 266 267static __inline void 268bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 269 bus_size_t offset, u_int16_t *addr, size_t count) 270{ 271#if defined(_I386_BUS_PIO_H_) 272#if defined(_I386_BUS_MEMIO_H_) 273 if (tag == I386_BUS_SPACE_IO) 274#endif 275 insw(bsh + offset, addr, count); 276#endif 277#if defined(_I386_BUS_MEMIO_H_) 278#if defined(_I386_BUS_PIO_H_) 279 else 280#endif 281 { 282 __asm __volatile(" \n\ 283 cld \n\ 284 1: movw (%2),%%ax \n\ 285 stosw \n\ 286 loop 1b" : 287 "=D" (addr), "=c" (count) : 288 "r" (bsh + offset), "0" (addr), "1" (count) : 289 "%eax", "memory"); 290 } 291#endif 292} 293 294static __inline void 295bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 296 bus_size_t offset, u_int32_t *addr, size_t count) 297{ 298#if defined(_I386_BUS_PIO_H_) 299#if defined(_I386_BUS_MEMIO_H_) 300 if (tag == I386_BUS_SPACE_IO) 301#endif 302 insl(bsh + offset, addr, count); 303#endif 304#if defined(_I386_BUS_MEMIO_H_) 305#if defined(_I386_BUS_PIO_H_) 306 else 307#endif 308 { 309 __asm __volatile(" \n\ 310 cld \n\ 311 1: movl (%2),%%eax \n\ 312 stosl \n\ 313 loop 1b" : 314 "=D" (addr), "=c" (count) : 315 "r" (bsh + offset), "0" (addr), "1" (count) : 316 "%eax", "memory"); 317 } 318#endif 319} 320 321#if 0 /* Cause a link error for bus_space_read_multi_8 */ 322#define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!! 323#endif 324 325/* 326 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 327 * described by tag/handle and starting at `offset' and copy into 328 * buffer provided. 329 */ 330static __inline void bus_space_read_region_1(bus_space_tag_t tag, 331 bus_space_handle_t bsh, 332 bus_size_t offset, u_int8_t *addr, 333 size_t count); 334 335static __inline void bus_space_read_region_2(bus_space_tag_t tag, 336 bus_space_handle_t bsh, 337 bus_size_t offset, u_int16_t *addr, 338 size_t count); 339 340static __inline void bus_space_read_region_4(bus_space_tag_t tag, 341 bus_space_handle_t bsh, 342 bus_size_t offset, u_int32_t *addr, 343 size_t count); 344 345 346static __inline void 347bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 348 bus_size_t offset, u_int8_t *addr, size_t count) 349{ 350#if defined(_I386_BUS_PIO_H_) 351#if defined(_I386_BUS_MEMIO_H_) 352 if (tag == I386_BUS_SPACE_IO) 353#endif 354 { 355 int _port_ = bsh + offset; \ 356 __asm __volatile(" \n\ 357 cld \n\ 358 1: inb %w2,%%al \n\ 359 stosb \n\ 360 incl %2 \n\ 361 loop 1b" : 362 "=D" (addr), "=c" (count), "=d" (_port_) : 363 "0" (addr), "1" (count), "2" (_port_) : 364 "%eax", "memory", "cc"); 365 } 366#endif 367#if defined(_I386_BUS_MEMIO_H_) 368#if defined(_I386_BUS_PIO_H_) 369 else 370#endif 371 { 372 int _port_ = bsh + offset; \ 373 __asm __volatile(" \n\ 374 cld \n\ 375 repne \n\ 376 movsb" : 377 "=D" (addr), "=c" (count), "=S" (_port_) : 378 "0" (addr), "1" (count), "2" (_port_) : 379 "memory", "cc"); 380 } 381#endif 382} 383 384static __inline void 385bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 386 bus_size_t offset, u_int16_t *addr, size_t count) 387{ 388#if defined(_I386_BUS_PIO_H_) 389#if defined(_I386_BUS_MEMIO_H_) 390 if (tag == I386_BUS_SPACE_IO) 391#endif 392 { 393 int _port_ = bsh + offset; \ 394 __asm __volatile(" \n\ 395 cld \n\ 396 1: inw %w2,%%ax \n\ 397 stosw \n\ 398 addl $2,%2 \n\ 399 loop 1b" : 400 "=D" (addr), "=c" (count), "=d" (_port_) : 401 "0" (addr), "1" (count), "2" (_port_) : 402 "%eax", "memory", "cc"); 403 } 404#endif 405#if defined(_I386_BUS_MEMIO_H_) 406#if defined(_I386_BUS_PIO_H_) 407 else 408#endif 409 { 410 int _port_ = bsh + offset; \ 411 __asm __volatile(" \n\ 412 cld \n\ 413 repne \n\ 414 movsw" : 415 "=D" (addr), "=c" (count), "=S" (_port_) : 416 "0" (addr), "1" (count), "2" (_port_) : 417 "memory", "cc"); 418 } 419#endif 420} 421 422static __inline void 423bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 424 bus_size_t offset, u_int32_t *addr, size_t count) 425{ 426#if defined(_I386_BUS_PIO_H_) 427#if defined(_I386_BUS_MEMIO_H_) 428 if (tag == I386_BUS_SPACE_IO) 429#endif 430 { 431 int _port_ = bsh + offset; \ 432 __asm __volatile(" \n\ 433 cld \n\ 434 1: inl %w2,%%eax \n\ 435 stosl \n\ 436 addl $4,%2 \n\ 437 loop 1b" : 438 "=D" (addr), "=c" (count), "=d" (_port_) : 439 "0" (addr), "1" (count), "2" (_port_) : 440 "%eax", "memory", "cc"); 441 } 442#endif 443#if defined(_I386_BUS_MEMIO_H_) 444#if defined(_I386_BUS_PIO_H_) 445 else 446#endif 447 { 448 int _port_ = bsh + offset; \ 449 __asm __volatile(" \n\ 450 cld \n\ 451 repne \n\ 452 movsl" : 453 "=D" (addr), "=c" (count), "=S" (_port_) : 454 "0" (addr), "1" (count), "2" (_port_) : 455 "memory", "cc"); 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 469static __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 473static __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 477static __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 481static __inline void 482bus_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 499static __inline void 500bus_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 517static __inline void 518bus_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 544static __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); 549static __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 555static __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 561static __inline void 562bus_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 __asm __volatile(" \n\ 577 cld \n\ 578 1: lodsb \n\ 579 movb %%al,(%2) \n\ 580 loop 1b" : 581 "=S" (addr), "=c" (count) : 582 "r" (bsh + offset), "0" (addr), "1" (count) : 583 "%eax", "memory", "cc"); 584 } 585#endif 586} 587 588static __inline void 589bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 590 bus_size_t offset, const u_int16_t *addr, size_t count) 591{ 592#if defined(_I386_BUS_PIO_H_) 593#if defined(_I386_BUS_MEMIO_H_) 594 if (tag == I386_BUS_SPACE_IO) 595#endif 596 outsw(bsh + offset, addr, count); 597#endif 598#if defined(_I386_BUS_MEMIO_H_) 599#if defined(_I386_BUS_PIO_H_) 600 else 601#endif 602 { 603 __asm __volatile(" \n\ 604 cld \n\ 605 1: lodsw \n\ 606 movw %%ax,(%2) \n\ 607 loop 1b" : 608 "=S" (addr), "=c" (count) : 609 "r" (bsh + offset), "0" (addr), "1" (count) : 610 "%eax", "memory", "cc"); 611 } 612#endif 613} 614 615static __inline void 616bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 617 bus_size_t offset, const u_int32_t *addr, size_t count) 618{ 619#if defined(_I386_BUS_PIO_H_) 620#if defined(_I386_BUS_MEMIO_H_) 621 if (tag == I386_BUS_SPACE_IO) 622#endif 623 outsl(bsh + offset, addr, count); 624#endif 625#if defined(_I386_BUS_MEMIO_H_) 626#if defined(_I386_BUS_PIO_H_) 627 else 628#endif 629 { 630 __asm __volatile(" \n\ 631 cld \n\ 632 1: lodsl \n\ 633 movl %%eax,(%2) \n\ 634 loop 1b" : 635 "=S" (addr), "=c" (count) : 636 "r" (bsh + offset), "0" (addr), "1" (count) : 637 "%eax", "memory", "cc"); 638 } 639#endif 640} 641 642#if 0 /* Cause a link error for bus_space_write_multi_8 */ 643#define bus_space_write_multi_8(t, h, o, a, c) \ 644 !!! bus_space_write_multi_8 unimplemented !!! 645#endif 646 647/* 648 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided 649 * to bus space described by tag/handle starting at `offset'. 650 */ 651 652static __inline void bus_space_write_region_1(bus_space_tag_t tag, 653 bus_space_handle_t bsh, 654 bus_size_t offset, 655 const u_int8_t *addr, 656 size_t count); 657static __inline void bus_space_write_region_2(bus_space_tag_t tag, 658 bus_space_handle_t bsh, 659 bus_size_t offset, 660 const u_int16_t *addr, 661 size_t count); 662static __inline void bus_space_write_region_4(bus_space_tag_t tag, 663 bus_space_handle_t bsh, 664 bus_size_t offset, 665 const u_int32_t *addr, 666 size_t count); 667 668static __inline void 669bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 670 bus_size_t offset, const u_int8_t *addr, size_t count) 671{ 672#if defined(_I386_BUS_PIO_H_) 673#if defined(_I386_BUS_MEMIO_H_) 674 if (tag == I386_BUS_SPACE_IO) 675#endif 676 { 677 int _port_ = bsh + offset; \ 678 __asm __volatile(" \n\ 679 cld \n\ 680 1: lodsb \n\ 681 outb %%al,%w0 \n\ 682 incl %0 \n\ 683 loop 1b" : 684 "=d" (_port_), "=S" (addr), "=c" (count) : 685 "0" (_port_), "1" (addr), "2" (count) : 686 "%eax", "memory", "cc"); 687 } 688#endif 689#if defined(_I386_BUS_MEMIO_H_) 690#if defined(_I386_BUS_PIO_H_) 691 else 692#endif 693 { 694 int _port_ = bsh + offset; \ 695 __asm __volatile(" \n\ 696 cld \n\ 697 repne \n\ 698 movsb" : 699 "=D" (_port_), "=S" (addr), "=c" (count) : 700 "0" (_port_), "1" (addr), "2" (count) : 701 "memory", "cc"); 702 } 703#endif 704} 705 706static __inline void 707bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 708 bus_size_t offset, const u_int16_t *addr, size_t count) 709{ 710#if defined(_I386_BUS_PIO_H_) 711#if defined(_I386_BUS_MEMIO_H_) 712 if (tag == I386_BUS_SPACE_IO) 713#endif 714 { 715 int _port_ = bsh + offset; \ 716 __asm __volatile(" \n\ 717 cld \n\ 718 1: lodsw \n\ 719 outw %%ax,%w0 \n\ 720 addl $2,%0 \n\ 721 loop 1b" : 722 "=d" (_port_), "=S" (addr), "=c" (count) : 723 "0" (_port_), "1" (addr), "2" (count) : 724 "%eax", "memory", "cc"); 725 } 726#endif 727#if defined(_I386_BUS_MEMIO_H_) 728#if defined(_I386_BUS_PIO_H_) 729 else 730#endif 731 { 732 int _port_ = bsh + offset; \ 733 __asm __volatile(" \n\ 734 cld \n\ 735 repne \n\ 736 movsw" : 737 "=D" (_port_), "=S" (addr), "=c" (count) : 738 "0" (_port_), "1" (addr), "2" (count) : 739 "memory", "cc"); 740 } 741#endif 742} 743 744static __inline void 745bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 746 bus_size_t offset, const u_int32_t *addr, size_t count) 747{ 748#if defined(_I386_BUS_PIO_H_) 749#if defined(_I386_BUS_MEMIO_H_) 750 if (tag == I386_BUS_SPACE_IO) 751#endif 752 { 753 int _port_ = bsh + offset; \ 754 __asm __volatile(" \n\ 755 cld \n\ 756 1: lodsl \n\ 757 outl %%eax,%w0 \n\ 758 addl $4,%0 \n\ 759 loop 1b" : 760 "=d" (_port_), "=S" (addr), "=c" (count) : 761 "0" (_port_), "1" (addr), "2" (count) : 762 "%eax", "memory", "cc"); 763 } 764#endif 765#if defined(_I386_BUS_MEMIO_H_) 766#if defined(_I386_BUS_PIO_H_) 767 else 768#endif 769 { 770 int _port_ = bsh + offset; \ 771 __asm __volatile(" \n\ 772 cld \n\ 773 repne \n\ 774 movsl" : 775 "=D" (_port_), "=S" (addr), "=c" (count) : 776 "0" (_port_), "1" (addr), "2" (count) : 777 "memory", "cc"); 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 792static __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); 796static __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); 800static __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 805static __inline void 806bus_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 827static __inline void 828bus_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 849static __inline void 850bus_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 880static __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); 884static __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); 888static __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 893static __inline void 894bus_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 915static __inline void 916bus_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 937static __inline void 938bus_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 968static __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 974static __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 980static __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 986static __inline void 987bus_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 1032static __inline void 1033bus_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 1078static __inline void 1079bus_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 * 1137 * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than 1138 * prevent reordering by the compiler; all Intel x86 processors currently 1139 * retire operations outside the CPU in program order. 1140 */ 1141#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 1142#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 1143 1144static __inline void 1145bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, 1146 bus_size_t offset, bus_size_t len, int flags) 1147{ 1148 if (flags & BUS_SPACE_BARRIER_READ) 1149 __asm __volatile("lock; addl $0,0(%%esp)" : : : "memory"); 1150 else 1151 __asm __volatile("" : : : "memory"); 1152} 1153 1154/* 1155 * Flags used in various bus DMA methods. 1156 */ 1157#define BUS_DMA_WAITOK 0x00 /* safe to sleep (pseudo-flag) */ 1158#define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */ 1159#define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */ 1160#define BUS_DMAMEM_NOSYNC 0x04 /* map memory to not require sync */ 1161#define BUS_DMA_BUS1 0x10 /* placeholders for bus functions... */ 1162#define BUS_DMA_BUS2 0x20 1163#define BUS_DMA_BUS3 0x40 1164#define BUS_DMA_BUS4 0x80 1165 1166/* Forwards needed by prototypes below. */ 1167struct mbuf; 1168struct uio; 1169 1170/* 1171 * bus_dmasync_op_t 1172 * 1173 * Operations performed by bus_dmamap_sync(). 1174 */ 1175typedef enum { 1176 BUS_DMASYNC_PREREAD, 1177 BUS_DMASYNC_POSTREAD, 1178 BUS_DMASYNC_PREWRITE, 1179 BUS_DMASYNC_POSTWRITE 1180} bus_dmasync_op_t; 1181 1182/* 1183 * bus_dma_tag_t 1184 * 1185 * A machine-dependent opaque type describing the characteristics 1186 * of how to perform DMA mappings. This structure encapsultes 1187 * information concerning address and alignment restrictions, number 1188 * of S/G segments, amount of data per S/G segment, etc. 1189 */ 1190typedef struct bus_dma_tag *bus_dma_tag_t; 1191 1192/* 1193 * bus_dmamap_t 1194 * 1195 * DMA mapping instance information. 1196 */ 1197typedef struct bus_dmamap *bus_dmamap_t; 1198 1199/* 1200 * bus_dma_segment_t 1201 * 1202 * Describes a single contiguous DMA transaction. Values 1203 * are suitable for programming into DMA registers. 1204 */ 1205typedef struct bus_dma_segment { 1206 bus_addr_t ds_addr; /* DMA address */ 1207 bus_size_t ds_len; /* length of transfer */ 1208} bus_dma_segment_t; 1209 1210/* 1211 * A function that returns 1 if the address cannot be accessed by 1212 * a device and 0 if it can be. 1213 */ 1214typedef int bus_dma_filter_t(void *, bus_addr_t); 1215 1216/* 1217 * Allocate a device specific dma_tag encapsulating the constraints of 1218 * the parent tag in addition to other restrictions specified: 1219 * 1220 * alignment: alignment for segments. 1221 * boundary: Boundary that segments cannot cross. 1222 * lowaddr: Low restricted address that cannot appear in a mapping. 1223 * highaddr: High restricted address that cannot appear in a mapping. 1224 * filtfunc: An optional function to further test if an address 1225 * within the range of lowaddr and highaddr cannot appear 1226 * in a mapping. 1227 * filtfuncarg: An argument that will be passed to filtfunc in addition 1228 * to the address to test. 1229 * maxsize: Maximum mapping size supported by this tag. 1230 * nsegments: Number of discontinuities allowed in maps. 1231 * maxsegsz: Maximum size of a segment in the map. 1232 * flags: Bus DMA flags. 1233 * dmat: A pointer to set to a valid dma tag should the return 1234 * value of this function indicate success. 1235 */ 1236/* XXX Should probably allow specification of alignment */ 1237int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, 1238 bus_size_t boundary, bus_addr_t lowaddr, 1239 bus_addr_t highaddr, bus_dma_filter_t *filtfunc, 1240 void *filtfuncarg, bus_size_t maxsize, int nsegments, 1241 bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat); 1242 1243int bus_dma_tag_destroy(bus_dma_tag_t dmat); 1244 1245/* 1246 * Allocate a handle for mapping from kva/uva/physical 1247 * address space into bus device space. 1248 */ 1249int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp); 1250 1251/* 1252 * Destroy a handle for mapping from kva/uva/physical 1253 * address space into bus device space. 1254 */ 1255int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map); 1256 1257/* 1258 * Allocate a piece of memory that can be efficiently mapped into 1259 * bus device space based on the constraints lited in the dma tag. 1260 * A dmamap to for use with dmamap_load is also allocated. 1261 */ 1262int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, 1263 bus_dmamap_t *mapp); 1264 1265/* 1266 * Free a piece of memory and it's allociated dmamap, that was allocated 1267 * via bus_dmamem_alloc. 1268 */ 1269void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); 1270 1271/* 1272 * A function that processes a successfully loaded dma map or an error 1273 * from a delayed load map. 1274 */ 1275typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); 1276 1277/* 1278 * Map the buffer buf into bus space using the dmamap map. 1279 */ 1280int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 1281 bus_size_t buflen, bus_dmamap_callback_t *callback, 1282 void *callback_arg, int flags); 1283 1284/* 1285 * Perform a syncronization operation on the given map. 1286 */ 1287void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); 1288#define bus_dmamap_sync(dmat, dmamap, op) \ 1289 if ((dmamap) != NULL) \ 1290 _bus_dmamap_sync(dmat, dmamap, op) 1291 1292/* 1293 * Release the mapping held by map. 1294 */ 1295void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map); 1296#define bus_dmamap_unload(dmat, dmamap) \ 1297 if ((dmamap) != NULL) \ 1298 _bus_dmamap_unload(dmat, dmamap) 1299 1300#endif /* _I386_BUS_AT386_H_ */ 1301