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