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