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