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