1 /*- 2 * Copyright (c) 2005 Scott Long 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #ifndef _CPU_BUS_DMA_H_ 28 #define _CPU_BUS_DMA_H_ 29 30 #include <machine/cpufunc.h> 31 32 /* 33 * Bus address and size types 34 */ 35 36 typedef uint64_t bus_addr_t; 37 typedef uint64_t bus_size_t; 38 39 typedef uint64_t bus_space_tag_t; 40 typedef uint64_t bus_space_handle_t; 41 42 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFFUL 43 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFFUL 44 #define BUS_SPACE_MAXSIZE (64 * 1024) /* Maximum supported size */ 45 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFFUL 46 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFFUL 47 #define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFUL 48 49 #define BUS_SPACE_UNRESTRICTED (~0) /* nsegments */ 50 51 /* 52 * Values for the amd64 bus space tag, not to be used directly by MI code. 53 */ 54 #define X86_64_BUS_SPACE_IO 0 /* space is i/o space */ 55 #define X86_64_BUS_SPACE_MEM 1 /* space is mem space */ 56 57 /* 58 * Map a region of device bus space into CPU virtual address space. 59 */ 60 61 static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr, 62 bus_size_t size, int flags, 63 bus_space_handle_t *bshp); 64 65 static __inline int 66 bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr, 67 bus_size_t size __unused, int flags __unused, 68 bus_space_handle_t *bshp) 69 { 70 71 *bshp = addr; 72 return (0); 73 } 74 75 /* 76 * Unmap a region of device bus space. 77 */ 78 79 static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, 80 bus_size_t size); 81 82 static __inline void 83 bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused, 84 bus_size_t size __unused) 85 { 86 } 87 88 /* 89 * Get a new handle for a subregion of an already-mapped area of bus space. 90 */ 91 92 static __inline int bus_space_subregion(bus_space_tag_t t, 93 bus_space_handle_t bsh, 94 bus_size_t offset, bus_size_t size, 95 bus_space_handle_t *nbshp); 96 97 static __inline int 98 bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh, 99 bus_size_t offset, bus_size_t size __unused, 100 bus_space_handle_t *nbshp) 101 { 102 103 *nbshp = bsh + offset; 104 return (0); 105 } 106 107 static __inline void * 108 bus_space_kva(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t offset) 109 { 110 if (tag == X86_64_BUS_SPACE_IO) 111 return ((void *)0); 112 return ((void *)(handle + offset)); 113 } 114 115 /* 116 * Allocate a region of memory that is accessible to devices in bus space. 117 */ 118 119 int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, 120 bus_addr_t rend, bus_size_t size, bus_size_t align, 121 bus_size_t boundary, int flags, bus_addr_t *addrp, 122 bus_space_handle_t *bshp); 123 124 /* 125 * Free a region of bus space accessible memory. 126 */ 127 128 static __inline void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, 129 bus_size_t size); 130 131 static __inline void 132 bus_space_free(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused, 133 bus_size_t size __unused) 134 { 135 } 136 137 138 /* 139 * Read a 1, 2, 4, or 8 byte quantity from bus space 140 * described by tag/handle/offset. 141 */ 142 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag, 143 bus_space_handle_t handle, 144 bus_size_t offset); 145 146 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag, 147 bus_space_handle_t handle, 148 bus_size_t offset); 149 150 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag, 151 bus_space_handle_t handle, 152 bus_size_t offset); 153 154 static __inline u_int8_t 155 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle, 156 bus_size_t offset) 157 { 158 159 if (tag == X86_64_BUS_SPACE_IO) 160 return (inb(handle + offset)); 161 return (*(volatile u_int8_t *)(handle + offset)); 162 } 163 164 static __inline u_int16_t 165 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle, 166 bus_size_t offset) 167 { 168 169 if (tag == X86_64_BUS_SPACE_IO) 170 return (inw(handle + offset)); 171 return (*(volatile u_int16_t *)(handle + offset)); 172 } 173 174 static __inline u_int32_t 175 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle, 176 bus_size_t offset) 177 { 178 179 if (tag == X86_64_BUS_SPACE_IO) 180 return (inl(handle + offset)); 181 return (*(volatile u_int32_t *)(handle + offset)); 182 } 183 184 #if 0 /* Cause a link error for bus_space_read_8 */ 185 #define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!! 186 #endif 187 188 /* 189 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 190 * described by tag/handle/offset and copy into buffer provided. 191 */ 192 static __inline void bus_space_read_multi_1(bus_space_tag_t tag, 193 bus_space_handle_t bsh, 194 bus_size_t offset, u_int8_t *addr, 195 size_t count); 196 197 static __inline void bus_space_read_multi_2(bus_space_tag_t tag, 198 bus_space_handle_t bsh, 199 bus_size_t offset, u_int16_t *addr, 200 size_t count); 201 202 static __inline void bus_space_read_multi_4(bus_space_tag_t tag, 203 bus_space_handle_t bsh, 204 bus_size_t offset, u_int32_t *addr, 205 size_t count); 206 207 static __inline void 208 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 209 bus_size_t offset, u_int8_t *addr, size_t count) 210 { 211 212 if (tag == X86_64_BUS_SPACE_IO) 213 insb(bsh + offset, addr, count); 214 else { 215 __asm __volatile(" \n\ 216 cld \n\ 217 1: movb (%2),%%al \n\ 218 stosb \n\ 219 loop 1b" : 220 "=D" (addr), "=c" (count) : 221 "r" (bsh + offset), "0" (addr), "1" (count) : 222 "%eax", "memory"); 223 } 224 } 225 226 static __inline void 227 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 228 bus_size_t offset, u_int16_t *addr, size_t count) 229 { 230 231 if (tag == X86_64_BUS_SPACE_IO) 232 insw(bsh + offset, addr, count); 233 else { 234 __asm __volatile(" \n\ 235 cld \n\ 236 1: movw (%2),%%ax \n\ 237 stosw \n\ 238 loop 1b" : 239 "=D" (addr), "=c" (count) : 240 "r" (bsh + offset), "0" (addr), "1" (count) : 241 "%eax", "memory"); 242 } 243 } 244 245 static __inline void 246 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 247 bus_size_t offset, u_int32_t *addr, size_t count) 248 { 249 250 if (tag == X86_64_BUS_SPACE_IO) 251 insl(bsh + offset, addr, count); 252 else { 253 __asm __volatile(" \n\ 254 cld \n\ 255 1: movl (%2),%%eax \n\ 256 stosl \n\ 257 loop 1b" : 258 "=D" (addr), "=c" (count) : 259 "r" (bsh + offset), "0" (addr), "1" (count) : 260 "%eax", "memory"); 261 } 262 } 263 264 #if 0 /* Cause a link error for bus_space_read_multi_8 */ 265 #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!! 266 #endif 267 268 /* 269 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 270 * described by tag/handle and starting at `offset' and copy into 271 * buffer provided. 272 */ 273 static __inline void bus_space_read_region_1(bus_space_tag_t tag, 274 bus_space_handle_t bsh, 275 bus_size_t offset, u_int8_t *addr, 276 size_t count); 277 278 static __inline void bus_space_read_region_2(bus_space_tag_t tag, 279 bus_space_handle_t bsh, 280 bus_size_t offset, u_int16_t *addr, 281 size_t count); 282 283 static __inline void bus_space_read_region_4(bus_space_tag_t tag, 284 bus_space_handle_t bsh, 285 bus_size_t offset, u_int32_t *addr, 286 size_t count); 287 288 289 static __inline void 290 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 291 bus_size_t offset, u_int8_t *addr, size_t count) 292 { 293 294 if (tag == X86_64_BUS_SPACE_IO) { 295 int _port_ = bsh + offset; 296 __asm __volatile(" \n\ 297 cld \n\ 298 1: inb %w2,%%al \n\ 299 stosb \n\ 300 incl %2 \n\ 301 loop 1b" : 302 "=D" (addr), "=c" (count), "=d" (_port_) : 303 "0" (addr), "1" (count), "2" (_port_) : 304 "%eax", "memory", "cc"); 305 } else { 306 bus_space_handle_t _port_ = bsh + offset; 307 __asm __volatile(" \n\ 308 cld \n\ 309 repne \n\ 310 movsb" : 311 "=D" (addr), "=c" (count), "=S" (_port_) : 312 "0" (addr), "1" (count), "2" (_port_) : 313 "memory", "cc"); 314 } 315 } 316 317 static __inline void 318 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 319 bus_size_t offset, u_int16_t *addr, size_t count) 320 { 321 322 if (tag == X86_64_BUS_SPACE_IO) { 323 int _port_ = bsh + offset; 324 __asm __volatile(" \n\ 325 cld \n\ 326 1: inw %w2,%%ax \n\ 327 stosw \n\ 328 addl $2,%2 \n\ 329 loop 1b" : 330 "=D" (addr), "=c" (count), "=d" (_port_) : 331 "0" (addr), "1" (count), "2" (_port_) : 332 "%eax", "memory", "cc"); 333 } else { 334 bus_space_handle_t _port_ = bsh + offset; 335 __asm __volatile(" \n\ 336 cld \n\ 337 repne \n\ 338 movsw" : 339 "=D" (addr), "=c" (count), "=S" (_port_) : 340 "0" (addr), "1" (count), "2" (_port_) : 341 "memory", "cc"); 342 } 343 } 344 345 static __inline void 346 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 347 bus_size_t offset, u_int32_t *addr, size_t count) 348 { 349 350 if (tag == X86_64_BUS_SPACE_IO) { 351 int _port_ = bsh + offset; 352 __asm __volatile(" \n\ 353 cld \n\ 354 1: inl %w2,%%eax \n\ 355 stosl \n\ 356 addl $4,%2 \n\ 357 loop 1b" : 358 "=D" (addr), "=c" (count), "=d" (_port_) : 359 "0" (addr), "1" (count), "2" (_port_) : 360 "%eax", "memory", "cc"); 361 } else { 362 bus_space_handle_t _port_ = bsh + offset; 363 __asm __volatile(" \n\ 364 cld \n\ 365 repne \n\ 366 movsl" : 367 "=D" (addr), "=c" (count), "=S" (_port_) : 368 "0" (addr), "1" (count), "2" (_port_) : 369 "memory", "cc"); 370 } 371 } 372 373 #if 0 /* Cause a link error for bus_space_read_region_8 */ 374 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!! 375 #endif 376 377 /* 378 * Write the 1, 2, 4, or 8 byte value `value' to bus space 379 * described by tag/handle/offset. 380 */ 381 382 static __inline void bus_space_write_1(bus_space_tag_t tag, 383 bus_space_handle_t bsh, 384 bus_size_t offset, u_int8_t value); 385 386 static __inline void bus_space_write_2(bus_space_tag_t tag, 387 bus_space_handle_t bsh, 388 bus_size_t offset, u_int16_t value); 389 390 static __inline void bus_space_write_4(bus_space_tag_t tag, 391 bus_space_handle_t bsh, 392 bus_size_t offset, u_int32_t value); 393 394 static __inline void 395 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh, 396 bus_size_t offset, u_int8_t value) 397 { 398 399 if (tag == X86_64_BUS_SPACE_IO) 400 outb(bsh + offset, value); 401 else 402 *(volatile u_int8_t *)(bsh + offset) = value; 403 } 404 405 static __inline void 406 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh, 407 bus_size_t offset, u_int16_t value) 408 { 409 410 if (tag == X86_64_BUS_SPACE_IO) 411 outw(bsh + offset, value); 412 else 413 *(volatile u_int16_t *)(bsh + offset) = value; 414 } 415 416 static __inline void 417 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh, 418 bus_size_t offset, u_int32_t value) 419 { 420 421 if (tag == X86_64_BUS_SPACE_IO) 422 outl(bsh + offset, value); 423 else 424 *(volatile u_int32_t *)(bsh + offset) = value; 425 } 426 427 #if 0 /* Cause a link error for bus_space_write_8 */ 428 #define bus_space_write_8 !!! bus_space_write_8 not implemented !!! 429 #endif 430 431 /* 432 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer 433 * provided to bus space described by tag/handle/offset. 434 */ 435 436 static __inline void bus_space_write_multi_1(bus_space_tag_t tag, 437 bus_space_handle_t bsh, 438 bus_size_t offset, 439 const u_int8_t *addr, 440 size_t count); 441 static __inline void bus_space_write_multi_2(bus_space_tag_t tag, 442 bus_space_handle_t bsh, 443 bus_size_t offset, 444 const u_int16_t *addr, 445 size_t count); 446 447 static __inline void bus_space_write_multi_4(bus_space_tag_t tag, 448 bus_space_handle_t bsh, 449 bus_size_t offset, 450 const u_int32_t *addr, 451 size_t count); 452 453 static __inline void 454 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 455 bus_size_t offset, const u_int8_t *addr, size_t count) 456 { 457 458 if (tag == X86_64_BUS_SPACE_IO) 459 outsb(bsh + offset, addr, count); 460 else { 461 __asm __volatile(" \n\ 462 cld \n\ 463 1: lodsb \n\ 464 movb %%al,(%2) \n\ 465 loop 1b" : 466 "=S" (addr), "=c" (count) : 467 "r" (bsh + offset), "0" (addr), "1" (count) : 468 "%eax", "memory", "cc"); 469 } 470 } 471 472 static __inline void 473 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 474 bus_size_t offset, const u_int16_t *addr, size_t count) 475 { 476 477 if (tag == X86_64_BUS_SPACE_IO) 478 outsw(bsh + offset, addr, count); 479 else { 480 __asm __volatile(" \n\ 481 cld \n\ 482 1: lodsw \n\ 483 movw %%ax,(%2) \n\ 484 loop 1b" : 485 "=S" (addr), "=c" (count) : 486 "r" (bsh + offset), "0" (addr), "1" (count) : 487 "%eax", "memory", "cc"); 488 } 489 } 490 491 static __inline void 492 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 493 bus_size_t offset, const u_int32_t *addr, size_t count) 494 { 495 496 if (tag == X86_64_BUS_SPACE_IO) 497 outsl(bsh + offset, addr, count); 498 else { 499 __asm __volatile(" \n\ 500 cld \n\ 501 1: lodsl \n\ 502 movl %%eax,(%2) \n\ 503 loop 1b" : 504 "=S" (addr), "=c" (count) : 505 "r" (bsh + offset), "0" (addr), "1" (count) : 506 "%eax", "memory", "cc"); 507 } 508 } 509 510 #if 0 /* Cause a link error for bus_space_write_multi_8 */ 511 #define bus_space_write_multi_8(t, h, o, a, c) \ 512 !!! bus_space_write_multi_8 unimplemented !!! 513 #endif 514 515 /* 516 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided 517 * to bus space described by tag/handle starting at `offset'. 518 */ 519 520 static __inline void bus_space_write_region_1(bus_space_tag_t tag, 521 bus_space_handle_t bsh, 522 bus_size_t offset, 523 const u_int8_t *addr, 524 size_t count); 525 static __inline void bus_space_write_region_2(bus_space_tag_t tag, 526 bus_space_handle_t bsh, 527 bus_size_t offset, 528 const u_int16_t *addr, 529 size_t count); 530 static __inline void bus_space_write_region_4(bus_space_tag_t tag, 531 bus_space_handle_t bsh, 532 bus_size_t offset, 533 const u_int32_t *addr, 534 size_t count); 535 536 static __inline void 537 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 538 bus_size_t offset, const u_int8_t *addr, size_t count) 539 { 540 541 if (tag == X86_64_BUS_SPACE_IO) { 542 int _port_ = bsh + offset; 543 __asm __volatile(" \n\ 544 cld \n\ 545 1: lodsb \n\ 546 outb %%al,%w0 \n\ 547 incl %0 \n\ 548 loop 1b" : 549 "=d" (_port_), "=S" (addr), "=c" (count) : 550 "0" (_port_), "1" (addr), "2" (count) : 551 "%eax", "memory", "cc"); 552 } else { 553 bus_space_handle_t _port_ = bsh + offset; 554 __asm __volatile(" \n\ 555 cld \n\ 556 repne \n\ 557 movsb" : 558 "=D" (_port_), "=S" (addr), "=c" (count) : 559 "0" (_port_), "1" (addr), "2" (count) : 560 "memory", "cc"); 561 } 562 } 563 564 static __inline void 565 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 566 bus_size_t offset, const u_int16_t *addr, size_t count) 567 { 568 569 if (tag == X86_64_BUS_SPACE_IO) { 570 int _port_ = bsh + offset; 571 __asm __volatile(" \n\ 572 cld \n\ 573 1: lodsw \n\ 574 outw %%ax,%w0 \n\ 575 addl $2,%0 \n\ 576 loop 1b" : 577 "=d" (_port_), "=S" (addr), "=c" (count) : 578 "0" (_port_), "1" (addr), "2" (count) : 579 "%eax", "memory", "cc"); 580 } else { 581 bus_space_handle_t _port_ = bsh + offset; 582 __asm __volatile(" \n\ 583 cld \n\ 584 repne \n\ 585 movsw" : 586 "=D" (_port_), "=S" (addr), "=c" (count) : 587 "0" (_port_), "1" (addr), "2" (count) : 588 "memory", "cc"); 589 } 590 } 591 592 static __inline void 593 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 594 bus_size_t offset, const u_int32_t *addr, size_t count) 595 { 596 597 if (tag == X86_64_BUS_SPACE_IO) { 598 int _port_ = bsh + offset; 599 __asm __volatile(" \n\ 600 cld \n\ 601 1: lodsl \n\ 602 outl %%eax,%w0 \n\ 603 addl $4,%0 \n\ 604 loop 1b" : 605 "=d" (_port_), "=S" (addr), "=c" (count) : 606 "0" (_port_), "1" (addr), "2" (count) : 607 "%eax", "memory", "cc"); 608 } else { 609 bus_space_handle_t _port_ = bsh + offset; 610 __asm __volatile(" \n\ 611 cld \n\ 612 repne \n\ 613 movsl" : 614 "=D" (_port_), "=S" (addr), "=c" (count) : 615 "0" (_port_), "1" (addr), "2" (count) : 616 "memory", "cc"); 617 } 618 } 619 620 #if 0 /* Cause a link error for bus_space_write_region_8 */ 621 #define bus_space_write_region_8 \ 622 !!! bus_space_write_region_8 unimplemented !!! 623 #endif 624 625 /* 626 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 627 * by tag/handle/offset `count' times. 628 */ 629 630 static __inline void bus_space_set_multi_1(bus_space_tag_t tag, 631 bus_space_handle_t bsh, 632 bus_size_t offset, 633 u_int8_t value, size_t count); 634 static __inline void bus_space_set_multi_2(bus_space_tag_t tag, 635 bus_space_handle_t bsh, 636 bus_size_t offset, 637 u_int16_t value, size_t count); 638 static __inline void bus_space_set_multi_4(bus_space_tag_t tag, 639 bus_space_handle_t bsh, 640 bus_size_t offset, 641 u_int32_t value, size_t count); 642 643 static __inline void 644 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 645 bus_size_t offset, u_int8_t value, size_t count) 646 { 647 bus_space_handle_t addr = bsh + offset; 648 649 if (tag == X86_64_BUS_SPACE_IO) 650 while (count--) 651 outb(addr, value); 652 else 653 while (count--) 654 *(volatile u_int8_t *)(addr) = value; 655 } 656 657 static __inline void 658 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 659 bus_size_t offset, u_int16_t value, size_t count) 660 { 661 bus_space_handle_t addr = bsh + offset; 662 663 if (tag == X86_64_BUS_SPACE_IO) 664 while (count--) 665 outw(addr, value); 666 else 667 while (count--) 668 *(volatile u_int16_t *)(addr) = value; 669 } 670 671 static __inline void 672 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 673 bus_size_t offset, u_int32_t value, size_t count) 674 { 675 bus_space_handle_t addr = bsh + offset; 676 677 if (tag == X86_64_BUS_SPACE_IO) 678 while (count--) 679 outl(addr, value); 680 else 681 while (count--) 682 *(volatile u_int32_t *)(addr) = value; 683 } 684 685 #if 0 /* Cause a link error for bus_space_set_multi_8 */ 686 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!! 687 #endif 688 689 /* 690 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described 691 * by tag/handle starting at `offset'. 692 */ 693 694 static __inline void bus_space_set_region_1(bus_space_tag_t tag, 695 bus_space_handle_t bsh, 696 bus_size_t offset, u_int8_t value, 697 size_t count); 698 static __inline void bus_space_set_region_2(bus_space_tag_t tag, 699 bus_space_handle_t bsh, 700 bus_size_t offset, u_int16_t value, 701 size_t count); 702 static __inline void bus_space_set_region_4(bus_space_tag_t tag, 703 bus_space_handle_t bsh, 704 bus_size_t offset, u_int32_t value, 705 size_t count); 706 707 static __inline void 708 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 709 bus_size_t offset, u_int8_t value, size_t count) 710 { 711 bus_space_handle_t addr = bsh + offset; 712 713 if (tag == X86_64_BUS_SPACE_IO) 714 for (; count != 0; count--, addr++) 715 outb(addr, value); 716 else 717 for (; count != 0; count--, addr++) 718 *(volatile u_int8_t *)(addr) = value; 719 } 720 721 static __inline void 722 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 723 bus_size_t offset, u_int16_t value, size_t count) 724 { 725 bus_space_handle_t addr = bsh + offset; 726 727 if (tag == X86_64_BUS_SPACE_IO) 728 for (; count != 0; count--, addr += 2) 729 outw(addr, value); 730 else 731 for (; count != 0; count--, addr += 2) 732 *(volatile u_int16_t *)(addr) = value; 733 } 734 735 static __inline void 736 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 737 bus_size_t offset, u_int32_t value, size_t count) 738 { 739 bus_space_handle_t addr = bsh + offset; 740 741 if (tag == X86_64_BUS_SPACE_IO) 742 for (; count != 0; count--, addr += 4) 743 outl(addr, value); 744 else 745 for (; count != 0; count--, addr += 4) 746 *(volatile u_int32_t *)(addr) = value; 747 } 748 749 #if 0 /* Cause a link error for bus_space_set_region_8 */ 750 #define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!! 751 #endif 752 753 /* 754 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting 755 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. 756 */ 757 758 static __inline void bus_space_copy_region_1(bus_space_tag_t tag, 759 bus_space_handle_t bsh1, 760 bus_size_t off1, 761 bus_space_handle_t bsh2, 762 bus_size_t off2, size_t count); 763 764 static __inline void bus_space_copy_region_2(bus_space_tag_t tag, 765 bus_space_handle_t bsh1, 766 bus_size_t off1, 767 bus_space_handle_t bsh2, 768 bus_size_t off2, size_t count); 769 770 static __inline void bus_space_copy_region_4(bus_space_tag_t tag, 771 bus_space_handle_t bsh1, 772 bus_size_t off1, 773 bus_space_handle_t bsh2, 774 bus_size_t off2, size_t count); 775 776 static __inline void 777 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1, 778 bus_size_t off1, bus_space_handle_t bsh2, 779 bus_size_t off2, size_t count) 780 { 781 bus_space_handle_t addr1 = bsh1 + off1; 782 bus_space_handle_t addr2 = bsh2 + off2; 783 784 if (tag == X86_64_BUS_SPACE_IO) { 785 if (addr1 >= addr2) { 786 /* src after dest: copy forward */ 787 for (; count != 0; count--, addr1++, addr2++) 788 outb(addr2, inb(addr1)); 789 } else { 790 /* dest after src: copy backwards */ 791 for (addr1 += (count - 1), addr2 += (count - 1); 792 count != 0; count--, addr1--, addr2--) 793 outb(addr2, inb(addr1)); 794 } 795 } else { 796 if (addr1 >= addr2) { 797 /* src after dest: copy forward */ 798 for (; count != 0; count--, addr1++, addr2++) 799 *(volatile u_int8_t *)(addr2) = 800 *(volatile u_int8_t *)(addr1); 801 } else { 802 /* dest after src: copy backwards */ 803 for (addr1 += (count - 1), addr2 += (count - 1); 804 count != 0; count--, addr1--, addr2--) 805 *(volatile u_int8_t *)(addr2) = 806 *(volatile u_int8_t *)(addr1); 807 } 808 } 809 } 810 811 static __inline void 812 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1, 813 bus_size_t off1, bus_space_handle_t bsh2, 814 bus_size_t off2, size_t count) 815 { 816 bus_space_handle_t addr1 = bsh1 + off1; 817 bus_space_handle_t addr2 = bsh2 + off2; 818 819 if (tag == X86_64_BUS_SPACE_IO) { 820 if (addr1 >= addr2) { 821 /* src after dest: copy forward */ 822 for (; count != 0; count--, addr1 += 2, addr2 += 2) 823 outw(addr2, inw(addr1)); 824 } else { 825 /* dest after src: copy backwards */ 826 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); 827 count != 0; count--, addr1 -= 2, addr2 -= 2) 828 outw(addr2, inw(addr1)); 829 } 830 } else { 831 if (addr1 >= addr2) { 832 /* src after dest: copy forward */ 833 for (; count != 0; count--, addr1 += 2, addr2 += 2) 834 *(volatile u_int16_t *)(addr2) = 835 *(volatile u_int16_t *)(addr1); 836 } else { 837 /* dest after src: copy backwards */ 838 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); 839 count != 0; count--, addr1 -= 2, addr2 -= 2) 840 *(volatile u_int16_t *)(addr2) = 841 *(volatile u_int16_t *)(addr1); 842 } 843 } 844 } 845 846 static __inline void 847 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1, 848 bus_size_t off1, bus_space_handle_t bsh2, 849 bus_size_t off2, size_t count) 850 { 851 bus_space_handle_t addr1 = bsh1 + off1; 852 bus_space_handle_t addr2 = bsh2 + off2; 853 854 if (tag == X86_64_BUS_SPACE_IO) { 855 if (addr1 >= addr2) { 856 /* src after dest: copy forward */ 857 for (; count != 0; count--, addr1 += 4, addr2 += 4) 858 outl(addr2, inl(addr1)); 859 } else { 860 /* dest after src: copy backwards */ 861 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); 862 count != 0; count--, addr1 -= 4, addr2 -= 4) 863 outl(addr2, inl(addr1)); 864 } 865 } else { 866 if (addr1 >= addr2) { 867 /* src after dest: copy forward */ 868 for (; count != 0; count--, addr1 += 4, addr2 += 4) 869 *(volatile u_int32_t *)(addr2) = 870 *(volatile u_int32_t *)(addr1); 871 } else { 872 /* dest after src: copy backwards */ 873 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); 874 count != 0; count--, addr1 -= 4, addr2 -= 4) 875 *(volatile u_int32_t *)(addr2) = 876 *(volatile u_int32_t *)(addr1); 877 } 878 } 879 } 880 881 #if 0 /* Cause a link error for bus_space_copy_8 */ 882 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!! 883 #endif 884 885 /* 886 * Bus read/write barrier methods. 887 * 888 * void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, 889 * bus_size_t offset, bus_size_t len, int flags); 890 * 891 * 892 * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than 893 * prevent reordering by the compiler; all Intel x86 processors currently 894 * retire operations outside the CPU in program order. 895 */ 896 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 897 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 898 899 static __inline void 900 bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused, 901 bus_size_t offset __unused, bus_size_t len __unused, int flags) 902 { 903 if (flags & BUS_SPACE_BARRIER_READ) 904 __asm __volatile("lock; addl $0,0(%%rsp)" : : : "memory"); 905 else 906 __asm __volatile("" : : : "memory"); 907 } 908 909 /* 910 * Stream accesses are the same as normal accesses on amd64; there are no 911 * supported bus systems with an endianess different from the host one. 912 */ 913 #define bus_space_read_stream_1(t, h, o) bus_space_read_1((t), (h), (o)) 914 #define bus_space_read_stream_2(t, h, o) bus_space_read_2((t), (h), (o)) 915 #define bus_space_read_stream_4(t, h, o) bus_space_read_4((t), (h), (o)) 916 917 #define bus_space_read_multi_stream_1(t, h, o, a, c) \ 918 bus_space_read_multi_1((t), (h), (o), (a), (c)) 919 #define bus_space_read_multi_stream_2(t, h, o, a, c) \ 920 bus_space_read_multi_2((t), (h), (o), (a), (c)) 921 #define bus_space_read_multi_stream_4(t, h, o, a, c) \ 922 bus_space_read_multi_4((t), (h), (o), (a), (c)) 923 924 #define bus_space_write_stream_1(t, h, o, v) \ 925 bus_space_write_1((t), (h), (o), (v)) 926 #define bus_space_write_stream_2(t, h, o, v) \ 927 bus_space_write_2((t), (h), (o), (v)) 928 #define bus_space_write_stream_4(t, h, o, v) \ 929 bus_space_write_4((t), (h), (o), (v)) 930 931 #define bus_space_write_multi_stream_1(t, h, o, a, c) \ 932 bus_space_write_multi_1((t), (h), (o), (a), (c)) 933 #define bus_space_write_multi_stream_2(t, h, o, a, c) \ 934 bus_space_write_multi_2((t), (h), (o), (a), (c)) 935 #define bus_space_write_multi_stream_4(t, h, o, a, c) \ 936 bus_space_write_multi_4((t), (h), (o), (a), (c)) 937 938 #define bus_space_set_multi_stream_1(t, h, o, v, c) \ 939 bus_space_set_multi_1((t), (h), (o), (v), (c)) 940 #define bus_space_set_multi_stream_2(t, h, o, v, c) \ 941 bus_space_set_multi_2((t), (h), (o), (v), (c)) 942 #define bus_space_set_multi_stream_4(t, h, o, v, c) \ 943 bus_space_set_multi_4((t), (h), (o), (v), (c)) 944 945 #define bus_space_read_region_stream_1(t, h, o, a, c) \ 946 bus_space_read_region_1((t), (h), (o), (a), (c)) 947 #define bus_space_read_region_stream_2(t, h, o, a, c) \ 948 bus_space_read_region_2((t), (h), (o), (a), (c)) 949 #define bus_space_read_region_stream_4(t, h, o, a, c) \ 950 bus_space_read_region_4((t), (h), (o), (a), (c)) 951 952 #define bus_space_write_region_stream_1(t, h, o, a, c) \ 953 bus_space_write_region_1((t), (h), (o), (a), (c)) 954 #define bus_space_write_region_stream_2(t, h, o, a, c) \ 955 bus_space_write_region_2((t), (h), (o), (a), (c)) 956 #define bus_space_write_region_stream_4(t, h, o, a, c) \ 957 bus_space_write_region_4((t), (h), (o), (a), (c)) 958 959 #define bus_space_set_region_stream_1(t, h, o, v, c) \ 960 bus_space_set_region_1((t), (h), (o), (v), (c)) 961 #define bus_space_set_region_stream_2(t, h, o, v, c) \ 962 bus_space_set_region_2((t), (h), (o), (v), (c)) 963 #define bus_space_set_region_stream_4(t, h, o, v, c) \ 964 bus_space_set_region_4((t), (h), (o), (v), (c)) 965 966 #define bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) \ 967 bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c)) 968 #define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \ 969 bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c)) 970 #define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \ 971 bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c)) 972 973 #endif /* _CPU_BUS_DMA_H_ */ 974