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