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