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