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