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