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 #ifdef _KERNEL 185 static __inline u_int64_t 186 bus_space_read_8(bus_space_tag_t tag, bus_space_handle_t handle, 187 bus_size_t offset) 188 { 189 if (tag == X86_64_BUS_SPACE_IO) 190 panic("bus_space_read_8: illegal on I/O space"); 191 return (*(volatile u_int64_t *)(handle + offset)); 192 } 193 #endif 194 195 /* 196 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 197 * described by tag/handle/offset and copy into buffer provided. 198 */ 199 static __inline void bus_space_read_multi_1(bus_space_tag_t tag, 200 bus_space_handle_t bsh, 201 bus_size_t offset, u_int8_t *addr, 202 size_t count); 203 204 static __inline void bus_space_read_multi_2(bus_space_tag_t tag, 205 bus_space_handle_t bsh, 206 bus_size_t offset, u_int16_t *addr, 207 size_t count); 208 209 static __inline void bus_space_read_multi_4(bus_space_tag_t tag, 210 bus_space_handle_t bsh, 211 bus_size_t offset, u_int32_t *addr, 212 size_t count); 213 214 static __inline void 215 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 216 bus_size_t offset, u_int8_t *addr, size_t count) 217 { 218 219 if (tag == X86_64_BUS_SPACE_IO) 220 insb(bsh + offset, addr, count); 221 else { 222 __asm __volatile(" \n\ 223 cld \n\ 224 1: movb (%2),%%al \n\ 225 stosb \n\ 226 loop 1b" : 227 "=D" (addr), "=c" (count) : 228 "r" (bsh + offset), "0" (addr), "1" (count) : 229 "%eax", "memory"); 230 } 231 } 232 233 static __inline void 234 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 235 bus_size_t offset, u_int16_t *addr, size_t count) 236 { 237 238 if (tag == X86_64_BUS_SPACE_IO) 239 insw(bsh + offset, addr, count); 240 else { 241 __asm __volatile(" \n\ 242 cld \n\ 243 1: movw (%2),%%ax \n\ 244 stosw \n\ 245 loop 1b" : 246 "=D" (addr), "=c" (count) : 247 "r" (bsh + offset), "0" (addr), "1" (count) : 248 "%eax", "memory"); 249 } 250 } 251 252 static __inline void 253 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 254 bus_size_t offset, u_int32_t *addr, size_t count) 255 { 256 257 if (tag == X86_64_BUS_SPACE_IO) 258 insl(bsh + offset, addr, count); 259 else { 260 __asm __volatile(" \n\ 261 cld \n\ 262 1: movl (%2),%%eax \n\ 263 stosl \n\ 264 loop 1b" : 265 "=D" (addr), "=c" (count) : 266 "r" (bsh + offset), "0" (addr), "1" (count) : 267 "%eax", "memory"); 268 } 269 } 270 271 #if 0 /* Cause a link error for bus_space_read_multi_8 */ 272 #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!! 273 #endif 274 275 /* 276 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 277 * described by tag/handle and starting at `offset' and copy into 278 * buffer provided. 279 */ 280 static __inline void bus_space_read_region_1(bus_space_tag_t tag, 281 bus_space_handle_t bsh, 282 bus_size_t offset, u_int8_t *addr, 283 size_t count); 284 285 static __inline void bus_space_read_region_2(bus_space_tag_t tag, 286 bus_space_handle_t bsh, 287 bus_size_t offset, u_int16_t *addr, 288 size_t count); 289 290 static __inline void bus_space_read_region_4(bus_space_tag_t tag, 291 bus_space_handle_t bsh, 292 bus_size_t offset, u_int32_t *addr, 293 size_t count); 294 295 296 static __inline void 297 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 298 bus_size_t offset, u_int8_t *addr, size_t count) 299 { 300 301 if (tag == X86_64_BUS_SPACE_IO) { 302 int _port_ = bsh + offset; 303 __asm __volatile(" \n\ 304 cld \n\ 305 1: inb %w2,%%al \n\ 306 stosb \n\ 307 incl %2 \n\ 308 loop 1b" : 309 "=D" (addr), "=c" (count), "=d" (_port_) : 310 "0" (addr), "1" (count), "2" (_port_) : 311 "%eax", "memory", "cc"); 312 } else { 313 bus_space_handle_t _port_ = bsh + offset; 314 __asm __volatile(" \n\ 315 cld \n\ 316 repne \n\ 317 movsb" : 318 "=D" (addr), "=c" (count), "=S" (_port_) : 319 "0" (addr), "1" (count), "2" (_port_) : 320 "memory", "cc"); 321 } 322 } 323 324 static __inline void 325 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 326 bus_size_t offset, u_int16_t *addr, size_t count) 327 { 328 329 if (tag == X86_64_BUS_SPACE_IO) { 330 int _port_ = bsh + offset; 331 __asm __volatile(" \n\ 332 cld \n\ 333 1: inw %w2,%%ax \n\ 334 stosw \n\ 335 addl $2,%2 \n\ 336 loop 1b" : 337 "=D" (addr), "=c" (count), "=d" (_port_) : 338 "0" (addr), "1" (count), "2" (_port_) : 339 "%eax", "memory", "cc"); 340 } else { 341 bus_space_handle_t _port_ = bsh + offset; 342 __asm __volatile(" \n\ 343 cld \n\ 344 repne \n\ 345 movsw" : 346 "=D" (addr), "=c" (count), "=S" (_port_) : 347 "0" (addr), "1" (count), "2" (_port_) : 348 "memory", "cc"); 349 } 350 } 351 352 static __inline void 353 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 354 bus_size_t offset, u_int32_t *addr, size_t count) 355 { 356 357 if (tag == X86_64_BUS_SPACE_IO) { 358 int _port_ = bsh + offset; 359 __asm __volatile(" \n\ 360 cld \n\ 361 1: inl %w2,%%eax \n\ 362 stosl \n\ 363 addl $4,%2 \n\ 364 loop 1b" : 365 "=D" (addr), "=c" (count), "=d" (_port_) : 366 "0" (addr), "1" (count), "2" (_port_) : 367 "%eax", "memory", "cc"); 368 } else { 369 bus_space_handle_t _port_ = bsh + offset; 370 __asm __volatile(" \n\ 371 cld \n\ 372 repne \n\ 373 movsl" : 374 "=D" (addr), "=c" (count), "=S" (_port_) : 375 "0" (addr), "1" (count), "2" (_port_) : 376 "memory", "cc"); 377 } 378 } 379 380 #if 0 /* Cause a link error for bus_space_read_region_8 */ 381 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!! 382 #endif 383 384 /* 385 * Write the 1, 2, 4, or 8 byte value `value' to bus space 386 * described by tag/handle/offset. 387 */ 388 389 static __inline void bus_space_write_1(bus_space_tag_t tag, 390 bus_space_handle_t bsh, 391 bus_size_t offset, u_int8_t value); 392 393 static __inline void bus_space_write_2(bus_space_tag_t tag, 394 bus_space_handle_t bsh, 395 bus_size_t offset, u_int16_t value); 396 397 static __inline void bus_space_write_4(bus_space_tag_t tag, 398 bus_space_handle_t bsh, 399 bus_size_t offset, u_int32_t value); 400 401 static __inline void 402 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh, 403 bus_size_t offset, u_int8_t value) 404 { 405 406 if (tag == X86_64_BUS_SPACE_IO) 407 outb(bsh + offset, value); 408 else 409 *(volatile u_int8_t *)(bsh + offset) = value; 410 } 411 412 static __inline void 413 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh, 414 bus_size_t offset, u_int16_t value) 415 { 416 417 if (tag == X86_64_BUS_SPACE_IO) 418 outw(bsh + offset, value); 419 else 420 *(volatile u_int16_t *)(bsh + offset) = value; 421 } 422 423 static __inline void 424 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh, 425 bus_size_t offset, u_int32_t value) 426 { 427 428 if (tag == X86_64_BUS_SPACE_IO) 429 outl(bsh + offset, value); 430 else 431 *(volatile u_int32_t *)(bsh + offset) = value; 432 } 433 434 #ifdef _KERNEL 435 static __inline void 436 bus_space_write_8(bus_space_tag_t tag, bus_space_handle_t bsh, 437 bus_size_t offset, u_int64_t value) 438 { 439 if (tag == X86_64_BUS_SPACE_IO) 440 panic("bus_space_write_8: illegal on I/O space"); 441 *(volatile u_int64_t *)(bsh + offset) = value; 442 } 443 #endif 444 445 /* 446 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer 447 * provided to bus space described by tag/handle/offset. 448 */ 449 450 static __inline void bus_space_write_multi_1(bus_space_tag_t tag, 451 bus_space_handle_t bsh, 452 bus_size_t offset, 453 const u_int8_t *addr, 454 size_t count); 455 static __inline void bus_space_write_multi_2(bus_space_tag_t tag, 456 bus_space_handle_t bsh, 457 bus_size_t offset, 458 const u_int16_t *addr, 459 size_t count); 460 461 static __inline void bus_space_write_multi_4(bus_space_tag_t tag, 462 bus_space_handle_t bsh, 463 bus_size_t offset, 464 const u_int32_t *addr, 465 size_t count); 466 467 static __inline void 468 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 469 bus_size_t offset, const u_int8_t *addr, size_t count) 470 { 471 472 if (tag == X86_64_BUS_SPACE_IO) 473 outsb(bsh + offset, addr, count); 474 else { 475 __asm __volatile(" \n\ 476 cld \n\ 477 1: lodsb \n\ 478 movb %%al,(%2) \n\ 479 loop 1b" : 480 "=S" (addr), "=c" (count) : 481 "r" (bsh + offset), "0" (addr), "1" (count) : 482 "%eax", "memory", "cc"); 483 } 484 } 485 486 static __inline void 487 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 488 bus_size_t offset, const u_int16_t *addr, size_t count) 489 { 490 491 if (tag == X86_64_BUS_SPACE_IO) 492 outsw(bsh + offset, addr, count); 493 else { 494 __asm __volatile(" \n\ 495 cld \n\ 496 1: lodsw \n\ 497 movw %%ax,(%2) \n\ 498 loop 1b" : 499 "=S" (addr), "=c" (count) : 500 "r" (bsh + offset), "0" (addr), "1" (count) : 501 "%eax", "memory", "cc"); 502 } 503 } 504 505 static __inline void 506 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 507 bus_size_t offset, const u_int32_t *addr, size_t count) 508 { 509 510 if (tag == X86_64_BUS_SPACE_IO) 511 outsl(bsh + offset, addr, count); 512 else { 513 __asm __volatile(" \n\ 514 cld \n\ 515 1: lodsl \n\ 516 movl %%eax,(%2) \n\ 517 loop 1b" : 518 "=S" (addr), "=c" (count) : 519 "r" (bsh + offset), "0" (addr), "1" (count) : 520 "%eax", "memory", "cc"); 521 } 522 } 523 524 #if 0 /* Cause a link error for bus_space_write_multi_8 */ 525 #define bus_space_write_multi_8(t, h, o, a, c) \ 526 !!! bus_space_write_multi_8 unimplemented !!! 527 #endif 528 529 /* 530 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided 531 * to bus space described by tag/handle starting at `offset'. 532 */ 533 534 static __inline void bus_space_write_region_1(bus_space_tag_t tag, 535 bus_space_handle_t bsh, 536 bus_size_t offset, 537 const u_int8_t *addr, 538 size_t count); 539 static __inline void bus_space_write_region_2(bus_space_tag_t tag, 540 bus_space_handle_t bsh, 541 bus_size_t offset, 542 const u_int16_t *addr, 543 size_t count); 544 static __inline void bus_space_write_region_4(bus_space_tag_t tag, 545 bus_space_handle_t bsh, 546 bus_size_t offset, 547 const u_int32_t *addr, 548 size_t count); 549 550 static __inline void 551 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 552 bus_size_t offset, const u_int8_t *addr, size_t count) 553 { 554 555 if (tag == X86_64_BUS_SPACE_IO) { 556 int _port_ = bsh + offset; 557 __asm __volatile(" \n\ 558 cld \n\ 559 1: lodsb \n\ 560 outb %%al,%w0 \n\ 561 incl %0 \n\ 562 loop 1b" : 563 "=d" (_port_), "=S" (addr), "=c" (count) : 564 "0" (_port_), "1" (addr), "2" (count) : 565 "%eax", "memory", "cc"); 566 } else { 567 bus_space_handle_t _port_ = bsh + offset; 568 __asm __volatile(" \n\ 569 cld \n\ 570 repne \n\ 571 movsb" : 572 "=D" (_port_), "=S" (addr), "=c" (count) : 573 "0" (_port_), "1" (addr), "2" (count) : 574 "memory", "cc"); 575 } 576 } 577 578 static __inline void 579 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 580 bus_size_t offset, const u_int16_t *addr, size_t count) 581 { 582 583 if (tag == X86_64_BUS_SPACE_IO) { 584 int _port_ = bsh + offset; 585 __asm __volatile(" \n\ 586 cld \n\ 587 1: lodsw \n\ 588 outw %%ax,%w0 \n\ 589 addl $2,%0 \n\ 590 loop 1b" : 591 "=d" (_port_), "=S" (addr), "=c" (count) : 592 "0" (_port_), "1" (addr), "2" (count) : 593 "%eax", "memory", "cc"); 594 } else { 595 bus_space_handle_t _port_ = bsh + offset; 596 __asm __volatile(" \n\ 597 cld \n\ 598 repne \n\ 599 movsw" : 600 "=D" (_port_), "=S" (addr), "=c" (count) : 601 "0" (_port_), "1" (addr), "2" (count) : 602 "memory", "cc"); 603 } 604 } 605 606 static __inline void 607 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 608 bus_size_t offset, const u_int32_t *addr, size_t count) 609 { 610 611 if (tag == X86_64_BUS_SPACE_IO) { 612 int _port_ = bsh + offset; 613 __asm __volatile(" \n\ 614 cld \n\ 615 1: lodsl \n\ 616 outl %%eax,%w0 \n\ 617 addl $4,%0 \n\ 618 loop 1b" : 619 "=d" (_port_), "=S" (addr), "=c" (count) : 620 "0" (_port_), "1" (addr), "2" (count) : 621 "%eax", "memory", "cc"); 622 } else { 623 bus_space_handle_t _port_ = bsh + offset; 624 __asm __volatile(" \n\ 625 cld \n\ 626 repne \n\ 627 movsl" : 628 "=D" (_port_), "=S" (addr), "=c" (count) : 629 "0" (_port_), "1" (addr), "2" (count) : 630 "memory", "cc"); 631 } 632 } 633 634 #if 0 /* Cause a link error for bus_space_write_region_8 */ 635 #define bus_space_write_region_8 \ 636 !!! bus_space_write_region_8 unimplemented !!! 637 #endif 638 639 /* 640 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 641 * by tag/handle/offset `count' times. 642 */ 643 644 static __inline void bus_space_set_multi_1(bus_space_tag_t tag, 645 bus_space_handle_t bsh, 646 bus_size_t offset, 647 u_int8_t value, size_t count); 648 static __inline void bus_space_set_multi_2(bus_space_tag_t tag, 649 bus_space_handle_t bsh, 650 bus_size_t offset, 651 u_int16_t value, size_t count); 652 static __inline void bus_space_set_multi_4(bus_space_tag_t tag, 653 bus_space_handle_t bsh, 654 bus_size_t offset, 655 u_int32_t value, size_t count); 656 657 static __inline void 658 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 659 bus_size_t offset, u_int8_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 outb(addr, value); 666 else 667 while (count--) 668 *(volatile u_int8_t *)(addr) = value; 669 } 670 671 static __inline void 672 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 673 bus_size_t offset, u_int16_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 outw(addr, value); 680 else 681 while (count--) 682 *(volatile u_int16_t *)(addr) = value; 683 } 684 685 static __inline void 686 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 687 bus_size_t offset, u_int32_t value, size_t count) 688 { 689 bus_space_handle_t addr = bsh + offset; 690 691 if (tag == X86_64_BUS_SPACE_IO) 692 while (count--) 693 outl(addr, value); 694 else 695 while (count--) 696 *(volatile u_int32_t *)(addr) = value; 697 } 698 699 #if 0 /* Cause a link error for bus_space_set_multi_8 */ 700 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!! 701 #endif 702 703 /* 704 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described 705 * by tag/handle starting at `offset'. 706 */ 707 708 static __inline void bus_space_set_region_1(bus_space_tag_t tag, 709 bus_space_handle_t bsh, 710 bus_size_t offset, u_int8_t value, 711 size_t count); 712 static __inline void bus_space_set_region_2(bus_space_tag_t tag, 713 bus_space_handle_t bsh, 714 bus_size_t offset, u_int16_t value, 715 size_t count); 716 static __inline void bus_space_set_region_4(bus_space_tag_t tag, 717 bus_space_handle_t bsh, 718 bus_size_t offset, u_int32_t value, 719 size_t count); 720 721 static __inline void 722 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 723 bus_size_t offset, u_int8_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++) 729 outb(addr, value); 730 else 731 for (; count != 0; count--, addr++) 732 *(volatile u_int8_t *)(addr) = value; 733 } 734 735 static __inline void 736 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 737 bus_size_t offset, u_int16_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 += 2) 743 outw(addr, value); 744 else 745 for (; count != 0; count--, addr += 2) 746 *(volatile u_int16_t *)(addr) = value; 747 } 748 749 static __inline void 750 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 751 bus_size_t offset, u_int32_t value, size_t count) 752 { 753 bus_space_handle_t addr = bsh + offset; 754 755 if (tag == X86_64_BUS_SPACE_IO) 756 for (; count != 0; count--, addr += 4) 757 outl(addr, value); 758 else 759 for (; count != 0; count--, addr += 4) 760 *(volatile u_int32_t *)(addr) = value; 761 } 762 763 #if 0 /* Cause a link error for bus_space_set_region_8 */ 764 #define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!! 765 #endif 766 767 /* 768 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting 769 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. 770 */ 771 772 static __inline void bus_space_copy_region_1(bus_space_tag_t tag, 773 bus_space_handle_t bsh1, 774 bus_size_t off1, 775 bus_space_handle_t bsh2, 776 bus_size_t off2, size_t count); 777 778 static __inline void bus_space_copy_region_2(bus_space_tag_t tag, 779 bus_space_handle_t bsh1, 780 bus_size_t off1, 781 bus_space_handle_t bsh2, 782 bus_size_t off2, size_t count); 783 784 static __inline void bus_space_copy_region_4(bus_space_tag_t tag, 785 bus_space_handle_t bsh1, 786 bus_size_t off1, 787 bus_space_handle_t bsh2, 788 bus_size_t off2, size_t count); 789 790 static __inline void 791 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1, 792 bus_size_t off1, bus_space_handle_t bsh2, 793 bus_size_t off2, size_t count) 794 { 795 bus_space_handle_t addr1 = bsh1 + off1; 796 bus_space_handle_t addr2 = bsh2 + off2; 797 798 if (tag == X86_64_BUS_SPACE_IO) { 799 if (addr1 >= addr2) { 800 /* src after dest: copy forward */ 801 for (; count != 0; count--, addr1++, addr2++) 802 outb(addr2, inb(addr1)); 803 } else { 804 /* dest after src: copy backwards */ 805 for (addr1 += (count - 1), addr2 += (count - 1); 806 count != 0; count--, addr1--, addr2--) 807 outb(addr2, inb(addr1)); 808 } 809 } else { 810 if (addr1 >= addr2) { 811 /* src after dest: copy forward */ 812 for (; count != 0; count--, addr1++, addr2++) 813 *(volatile u_int8_t *)(addr2) = 814 *(volatile u_int8_t *)(addr1); 815 } else { 816 /* dest after src: copy backwards */ 817 for (addr1 += (count - 1), addr2 += (count - 1); 818 count != 0; count--, addr1--, addr2--) 819 *(volatile u_int8_t *)(addr2) = 820 *(volatile u_int8_t *)(addr1); 821 } 822 } 823 } 824 825 static __inline void 826 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1, 827 bus_size_t off1, bus_space_handle_t bsh2, 828 bus_size_t off2, size_t count) 829 { 830 bus_space_handle_t addr1 = bsh1 + off1; 831 bus_space_handle_t addr2 = bsh2 + off2; 832 833 if (tag == X86_64_BUS_SPACE_IO) { 834 if (addr1 >= addr2) { 835 /* src after dest: copy forward */ 836 for (; count != 0; count--, addr1 += 2, addr2 += 2) 837 outw(addr2, inw(addr1)); 838 } else { 839 /* dest after src: copy backwards */ 840 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); 841 count != 0; count--, addr1 -= 2, addr2 -= 2) 842 outw(addr2, inw(addr1)); 843 } 844 } else { 845 if (addr1 >= addr2) { 846 /* src after dest: copy forward */ 847 for (; count != 0; count--, addr1 += 2, addr2 += 2) 848 *(volatile u_int16_t *)(addr2) = 849 *(volatile u_int16_t *)(addr1); 850 } else { 851 /* dest after src: copy backwards */ 852 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); 853 count != 0; count--, addr1 -= 2, addr2 -= 2) 854 *(volatile u_int16_t *)(addr2) = 855 *(volatile u_int16_t *)(addr1); 856 } 857 } 858 } 859 860 static __inline void 861 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1, 862 bus_size_t off1, bus_space_handle_t bsh2, 863 bus_size_t off2, size_t count) 864 { 865 bus_space_handle_t addr1 = bsh1 + off1; 866 bus_space_handle_t addr2 = bsh2 + off2; 867 868 if (tag == X86_64_BUS_SPACE_IO) { 869 if (addr1 >= addr2) { 870 /* src after dest: copy forward */ 871 for (; count != 0; count--, addr1 += 4, addr2 += 4) 872 outl(addr2, inl(addr1)); 873 } else { 874 /* dest after src: copy backwards */ 875 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); 876 count != 0; count--, addr1 -= 4, addr2 -= 4) 877 outl(addr2, inl(addr1)); 878 } 879 } else { 880 if (addr1 >= addr2) { 881 /* src after dest: copy forward */ 882 for (; count != 0; count--, addr1 += 4, addr2 += 4) 883 *(volatile u_int32_t *)(addr2) = 884 *(volatile u_int32_t *)(addr1); 885 } else { 886 /* dest after src: copy backwards */ 887 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); 888 count != 0; count--, addr1 -= 4, addr2 -= 4) 889 *(volatile u_int32_t *)(addr2) = 890 *(volatile u_int32_t *)(addr1); 891 } 892 } 893 } 894 895 #if 0 /* Cause a link error for bus_space_copy_8 */ 896 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!! 897 #endif 898 899 /* 900 * Bus read/write barrier methods. 901 * 902 * void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, 903 * bus_size_t offset, bus_size_t len, int flags); 904 * 905 * 906 * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than 907 * prevent reordering by the compiler; all Intel x86 processors currently 908 * retire operations outside the CPU in program order. 909 */ 910 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 911 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 912 913 static __inline void 914 bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused, 915 bus_size_t offset __unused, bus_size_t len __unused, int flags) 916 { 917 if (flags & BUS_SPACE_BARRIER_READ) 918 __asm __volatile("lock; addl $0,0(%%rsp)" : : : "memory"); 919 else 920 __asm __volatile("" : : : "memory"); 921 } 922 923 /* 924 * Stream accesses are the same as normal accesses on amd64; there are no 925 * supported bus systems with an endianess different from the host one. 926 */ 927 #define bus_space_read_stream_1(t, h, o) bus_space_read_1((t), (h), (o)) 928 #define bus_space_read_stream_2(t, h, o) bus_space_read_2((t), (h), (o)) 929 #define bus_space_read_stream_4(t, h, o) bus_space_read_4((t), (h), (o)) 930 931 #define bus_space_read_multi_stream_1(t, h, o, a, c) \ 932 bus_space_read_multi_1((t), (h), (o), (a), (c)) 933 #define bus_space_read_multi_stream_2(t, h, o, a, c) \ 934 bus_space_read_multi_2((t), (h), (o), (a), (c)) 935 #define bus_space_read_multi_stream_4(t, h, o, a, c) \ 936 bus_space_read_multi_4((t), (h), (o), (a), (c)) 937 938 #define bus_space_write_stream_1(t, h, o, v) \ 939 bus_space_write_1((t), (h), (o), (v)) 940 #define bus_space_write_stream_2(t, h, o, v) \ 941 bus_space_write_2((t), (h), (o), (v)) 942 #define bus_space_write_stream_4(t, h, o, v) \ 943 bus_space_write_4((t), (h), (o), (v)) 944 945 #define bus_space_write_multi_stream_1(t, h, o, a, c) \ 946 bus_space_write_multi_1((t), (h), (o), (a), (c)) 947 #define bus_space_write_multi_stream_2(t, h, o, a, c) \ 948 bus_space_write_multi_2((t), (h), (o), (a), (c)) 949 #define bus_space_write_multi_stream_4(t, h, o, a, c) \ 950 bus_space_write_multi_4((t), (h), (o), (a), (c)) 951 952 #define bus_space_set_multi_stream_1(t, h, o, v, c) \ 953 bus_space_set_multi_1((t), (h), (o), (v), (c)) 954 #define bus_space_set_multi_stream_2(t, h, o, v, c) \ 955 bus_space_set_multi_2((t), (h), (o), (v), (c)) 956 #define bus_space_set_multi_stream_4(t, h, o, v, c) \ 957 bus_space_set_multi_4((t), (h), (o), (v), (c)) 958 959 #define bus_space_read_region_stream_1(t, h, o, a, c) \ 960 bus_space_read_region_1((t), (h), (o), (a), (c)) 961 #define bus_space_read_region_stream_2(t, h, o, a, c) \ 962 bus_space_read_region_2((t), (h), (o), (a), (c)) 963 #define bus_space_read_region_stream_4(t, h, o, a, c) \ 964 bus_space_read_region_4((t), (h), (o), (a), (c)) 965 966 #define bus_space_write_region_stream_1(t, h, o, a, c) \ 967 bus_space_write_region_1((t), (h), (o), (a), (c)) 968 #define bus_space_write_region_stream_2(t, h, o, a, c) \ 969 bus_space_write_region_2((t), (h), (o), (a), (c)) 970 #define bus_space_write_region_stream_4(t, h, o, a, c) \ 971 bus_space_write_region_4((t), (h), (o), (a), (c)) 972 973 #define bus_space_set_region_stream_1(t, h, o, v, c) \ 974 bus_space_set_region_1((t), (h), (o), (v), (c)) 975 #define bus_space_set_region_stream_2(t, h, o, v, c) \ 976 bus_space_set_region_2((t), (h), (o), (v), (c)) 977 #define bus_space_set_region_stream_4(t, h, o, v, c) \ 978 bus_space_set_region_4((t), (h), (o), (v), (c)) 979 980 #define bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) \ 981 bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c)) 982 #define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \ 983 bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c)) 984 #define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \ 985 bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c)) 986 987 #endif /* _CPU_BUS_DMA_H_ */ 988