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