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