1 /* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1996 Charles M. Hannum. All rights reserved. 42 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 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 Christopher G. Demetriou 55 * for the NetBSD Project. 56 * 4. The name of the author may not be used to endorse or promote products 57 * derived from this software without specific prior written permission 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 60 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 61 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 62 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 63 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 64 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 65 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 66 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 67 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 68 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 69 */ 70 /* $Id$ */ 71 72 #ifndef _I386_BUS_H_ 73 #define _I386_BUS_H_ 74 75 #include <machine/cpufunc.h> 76 77 /* 78 * Values for the i386 bus space tag, not to be used directly by MI code. 79 */ 80 #define I386_BUS_SPACE_IO 0 /* space is i/o space */ 81 #define I386_BUS_SPACE_MEM 1 /* space is mem space */ 82 83 /* 84 * Bus address and size types 85 */ 86 typedef u_long bus_addr_t; 87 typedef u_long bus_size_t; 88 89 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF 90 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF 91 #define BUS_SPACE_MAXSIZE (64 * 1024) /* Maximum supported size */ 92 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF 93 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF 94 #define BUS_SPACE_MAXADDR 0xFFFFFFFF 95 96 /* 97 * Access methods for bus resources and address space. 98 */ 99 typedef int bus_space_tag_t; 100 typedef u_long bus_space_handle_t; 101 102 /* 103 * Map a region of device bus space into CPU virtual address space. 104 */ 105 106 #define BUS_SPACE_MAP_CACHEABLE 0x01 107 #define BUS_SPACE_MAP_LINEAR 0x02 108 109 int bus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, 110 int flags, bus_space_handle_t *bshp); 111 112 /* 113 * Unmap a region of device bus space. 114 */ 115 116 void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, 117 bus_size_t size); 118 119 /* 120 * Get a new handle for a subregion of an already-mapped area of bus space. 121 */ 122 123 int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, 124 bus_size_t offset, bus_size_t size, 125 bus_space_handle_t *nbshp); 126 127 /* 128 * Allocate a region of memory that is accessible to devices in bus space. 129 */ 130 131 int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, 132 bus_addr_t rend, bus_size_t size, bus_size_t align, 133 bus_size_t boundary, int flags, bus_addr_t *addrp, 134 bus_space_handle_t *bshp); 135 136 /* 137 * Free a region of bus space accessible memory. 138 */ 139 140 void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, 141 bus_size_t size); 142 143 #if defined(_I386_BUS_PIO_H_) || defined(_I386_BUS_MEMIO_H_) 144 145 /* 146 * Read a 1, 2, 4, or 8 byte quantity from bus space 147 * described by tag/handle/offset. 148 */ 149 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag, 150 bus_space_handle_t handle, 151 bus_size_t offset); 152 153 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag, 154 bus_space_handle_t handle, 155 bus_size_t offset); 156 157 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag, 158 bus_space_handle_t handle, 159 bus_size_t offset); 160 161 static __inline u_int8_t 162 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle, 163 bus_size_t offset) 164 { 165 #if defined (_I386_BUS_PIO_H_) 166 #if defined (_I386_BUS_MEMIO_H_) 167 if (tag == I386_BUS_SPACE_IO) 168 #endif 169 return (inb(handle + offset)); 170 #endif 171 #if defined (_I386_BUS_MEMIO_H_) 172 return (*(volatile u_int8_t *)(handle + offset)); 173 #endif 174 } 175 176 static __inline u_int16_t 177 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle, 178 bus_size_t offset) 179 { 180 #if defined(_I386_BUS_PIO_H_) 181 #if defined(_I386_BUS_MEMIO_H_) 182 if (tag == I386_BUS_SPACE_IO) 183 #endif 184 return (inw(handle + offset)); 185 #endif 186 #if defined(_I386_BUS_MEMIO_H_) 187 return (*(volatile u_int16_t *)(handle + offset)); 188 #endif 189 } 190 191 static __inline u_int32_t 192 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle, 193 bus_size_t offset) 194 { 195 #if defined(_I386_BUS_PIO_H_) 196 #if defined(_I386_BUS_MEMIO_H_) 197 if (tag == I386_BUS_SPACE_IO) 198 #endif 199 return (inl(handle + offset)); 200 #endif 201 #if defined(_I386_BUS_MEMIO_H_) 202 return (*(volatile u_int32_t *)(handle + offset)); 203 #endif 204 } 205 206 #if 0 /* Cause a link error for bus_space_read_8 */ 207 #define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!! 208 #endif 209 210 /* 211 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 212 * described by tag/handle/offset and copy into buffer provided. 213 */ 214 static __inline void bus_space_read_multi_1(bus_space_tag_t tag, 215 bus_space_handle_t bsh, 216 bus_size_t offset, u_int8_t *addr, 217 size_t count); 218 219 static __inline void bus_space_read_multi_2(bus_space_tag_t tag, 220 bus_space_handle_t bsh, 221 bus_size_t offset, u_int16_t *addr, 222 size_t count); 223 224 static __inline void bus_space_read_multi_4(bus_space_tag_t tag, 225 bus_space_handle_t bsh, 226 bus_size_t offset, u_int32_t *addr, 227 size_t count); 228 229 static __inline void 230 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 231 bus_size_t offset, u_int8_t *addr, size_t count) 232 { 233 #if defined(_I386_BUS_PIO_H_) 234 #if defined(_I386_BUS_MEMIO_H_) 235 if (tag == I386_BUS_SPACE_IO) 236 #endif 237 insb(bsh + offset, addr, count); 238 #endif 239 #if defined(_I386_BUS_MEMIO_H_) 240 #if defined(_I386_BUS_PIO_H_) 241 else 242 #endif 243 { 244 int __x __asm__("%eax"); 245 __asm __volatile(" 246 cld ; 247 1: movb (%1),%%al ; 248 stosb ; 249 loop 1b" : 250 "=&a" (__x) : 251 "r" (bsh + offset), "D" (addr), "c" (count) : 252 "%edi", "%ecx", "memory"); 253 } 254 #endif 255 } 256 257 static __inline void 258 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 259 bus_size_t offset, u_int16_t *addr, size_t count) 260 { 261 #if defined(_I386_BUS_PIO_H_) 262 #if defined(_I386_BUS_MEMIO_H_) 263 if (tag == I386_BUS_SPACE_IO) 264 #endif 265 insw(bsh + offset, addr, count); 266 #endif 267 #if defined(_I386_BUS_MEMIO_H_) 268 #if defined(_I386_BUS_PIO_H_) 269 else 270 #endif 271 { 272 int __x __asm__("%eax"); 273 __asm __volatile(" 274 cld ; 275 1: movw (%1),%%ax ; 276 stosw ; 277 loop 1b" : 278 "=&a" (__x) : 279 "r" (bsh + offset), "D" (addr), "c" (count) : 280 "%edi", "%ecx", "memory"); 281 } 282 #endif 283 } 284 285 static __inline void 286 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 287 bus_size_t offset, u_int32_t *addr, size_t count) 288 { 289 #if defined(_I386_BUS_PIO_H_) 290 #if defined(_I386_BUS_MEMIO_H_) 291 if (tag == I386_BUS_SPACE_IO) 292 #endif 293 insl(bsh + offset, addr, count); 294 #endif 295 #if defined(_I386_BUS_MEMIO_H_) 296 #if defined(_I386_BUS_PIO_H_) 297 else 298 #endif 299 { 300 int __x __asm__("%eax"); 301 __asm __volatile(" 302 cld ; 303 1: movl (%1),%%eax ; 304 stosl ; 305 loop 1b" : 306 "=&a" (__x) : 307 "r" (bsh + offset), "D" (addr), "c" (count) : 308 "%edi", "%ecx", "memory"); 309 } 310 #endif 311 } 312 313 #if 0 /* Cause a link error for bus_space_read_multi_8 */ 314 #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!! 315 #endif 316 317 /* 318 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 319 * described by tag/handle and starting at `offset' and copy into 320 * buffer provided. 321 */ 322 static __inline void bus_space_read_region_1(bus_space_tag_t tag, 323 bus_space_handle_t bsh, 324 bus_size_t offset, u_int8_t *addr, 325 size_t count); 326 327 static __inline void bus_space_read_region_2(bus_space_tag_t tag, 328 bus_space_handle_t bsh, 329 bus_size_t offset, u_int16_t *addr, 330 size_t count); 331 332 static __inline void bus_space_read_region_4(bus_space_tag_t tag, 333 bus_space_handle_t bsh, 334 bus_size_t offset, u_int32_t *addr, 335 size_t count); 336 337 338 static __inline void 339 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 340 bus_size_t offset, u_int8_t *addr, size_t count) 341 { 342 #if defined(_I386_BUS_PIO_H_) 343 #if defined(_I386_BUS_MEMIO_H_) 344 if (tag == I386_BUS_SPACE_IO) 345 #endif 346 { 347 int __x __asm__("%eax"); 348 __asm __volatile(" 349 cld ; 350 1: inb %w1,%%al ; 351 stosb ; 352 incl %1 ; 353 loop 1b" : 354 "=&a" (__x) : 355 "d" (bsh + offset), "D" (addr), "c" (count) : 356 "%edx", "%edi", "%ecx", "memory"); 357 } 358 #endif 359 #if defined(_I386_BUS_MEMIO_H_) 360 #if defined(_I386_BUS_PIO_H_) 361 else 362 #endif 363 { 364 __asm __volatile(" 365 cld ; 366 repne ; 367 movsb" : 368 : 369 "S" (bsh + offset), "D" (addr), "c" (count) : 370 "%esi", "%edi", "%ecx", "memory"); 371 } 372 #endif 373 } 374 375 static __inline void 376 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 377 bus_size_t offset, u_int16_t *addr, size_t count) 378 { 379 #if defined(_I386_BUS_PIO_H_) 380 #if defined(_I386_BUS_MEMIO_H_) 381 if (tag == I386_BUS_SPACE_IO) 382 #endif 383 { 384 int __x __asm__("%eax"); 385 __asm __volatile(" 386 cld ; 387 1: inw %w1,%%ax ; 388 stosw ; 389 addl $2,%1 ; 390 loop 1b" : 391 "=&a" (__x) : 392 "d" (bsh + offset), "D" (addr), "c" (count) : 393 "%edx", "%edi", "%ecx", "memory"); 394 } 395 #endif 396 #if defined(_I386_BUS_MEMIO_H_) 397 #if defined(_I386_BUS_PIO_H_) 398 else 399 #endif 400 { 401 __asm __volatile(" 402 cld ; 403 repne ; 404 movsw" : 405 : 406 "S" (bsh + offset), "D" (addr), "c" (count) : 407 "%esi", "%edi", "%ecx", "memory"); 408 } 409 #endif 410 } 411 412 static __inline void 413 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 414 bus_size_t offset, u_int32_t *addr, size_t count) 415 { 416 #if defined(_I386_BUS_PIO_H_) 417 #if defined(_I386_BUS_MEMIO_H_) 418 if (tag == I386_BUS_SPACE_IO) 419 #endif 420 { 421 int __x __asm__("%eax"); 422 __asm __volatile(" 423 cld ; 424 1: inl %w1,%%eax ; 425 stosl ; 426 addl $4,%1 ; 427 loop 1b" : 428 "=&a" (__x) : 429 "d" (bsh + offset), "D" (addr), "c" (count) : 430 "%edx", "%edi", "%ecx", "memory"); 431 } 432 #endif 433 #if defined(_I386_BUS_MEMIO_H_) 434 #if defined(_I386_BUS_PIO_H_) 435 else 436 #endif 437 { 438 __asm __volatile(" 439 cld ; 440 repne ; 441 movsl" : 442 : 443 "S" (bsh + offset), "D" (addr), "c" (count) : 444 "%esi", "%edi", "%ecx", "memory"); 445 } 446 #endif 447 } 448 449 #if 0 /* Cause a link error for bus_space_read_region_8 */ 450 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!! 451 #endif 452 453 /* 454 * Write the 1, 2, 4, or 8 byte value `value' to bus space 455 * described by tag/handle/offset. 456 */ 457 458 static __inline void bus_space_write_1(bus_space_tag_t tag, 459 bus_space_handle_t bsh, 460 bus_size_t offset, u_int8_t value); 461 462 static __inline void bus_space_write_2(bus_space_tag_t tag, 463 bus_space_handle_t bsh, 464 bus_size_t offset, u_int16_t value); 465 466 static __inline void bus_space_write_4(bus_space_tag_t tag, 467 bus_space_handle_t bsh, 468 bus_size_t offset, u_int32_t value); 469 470 static __inline void 471 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh, 472 bus_size_t offset, u_int8_t value) 473 { 474 #if defined(_I386_BUS_PIO_H_) 475 #if defined(_I386_BUS_MEMIO_H_) 476 if (tag == I386_BUS_SPACE_IO) 477 #endif 478 outb(bsh + offset, value); 479 #endif 480 #if defined(_I386_BUS_MEMIO_H_) 481 #if defined(_I386_BUS_PIO_H_) 482 else 483 #endif 484 *(volatile u_int8_t *)(bsh + offset) = value; 485 #endif 486 } 487 488 static __inline void 489 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh, 490 bus_size_t offset, u_int16_t value) 491 { 492 #if defined(_I386_BUS_PIO_H_) 493 #if defined(_I386_BUS_MEMIO_H_) 494 if (tag == I386_BUS_SPACE_IO) 495 #endif 496 outw(bsh + offset, value); 497 #endif 498 #if defined(_I386_BUS_MEMIO_H_) 499 #if defined(_I386_BUS_PIO_H_) 500 else 501 #endif 502 *(volatile u_int16_t *)(bsh + offset) = value; 503 #endif 504 } 505 506 static __inline void 507 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh, 508 bus_size_t offset, u_int32_t value) 509 { 510 #if defined(_I386_BUS_PIO_H_) 511 #if defined(_I386_BUS_MEMIO_H_) 512 if (tag == I386_BUS_SPACE_IO) 513 #endif 514 outl(bsh + offset, value); 515 #endif 516 #if defined(_I386_BUS_MEMIO_H_) 517 #if defined(_I386_BUS_PIO_H_) 518 else 519 #endif 520 *(volatile u_int32_t *)(bsh + offset) = value; 521 #endif 522 } 523 524 #if 0 /* Cause a link error for bus_space_write_8 */ 525 #define bus_space_write_8 !!! bus_space_write_8 not implemented !!! 526 #endif 527 528 /* 529 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer 530 * provided to bus space described by tag/handle/offset. 531 */ 532 533 static __inline void bus_space_write_multi_1(bus_space_tag_t tag, 534 bus_space_handle_t bsh, 535 bus_size_t offset, 536 const u_int8_t *addr, 537 size_t count); 538 static __inline void bus_space_write_multi_2(bus_space_tag_t tag, 539 bus_space_handle_t bsh, 540 bus_size_t offset, 541 const u_int16_t *addr, 542 size_t count); 543 544 static __inline void bus_space_write_multi_4(bus_space_tag_t tag, 545 bus_space_handle_t bsh, 546 bus_size_t offset, 547 const u_int32_t *addr, 548 size_t count); 549 550 static __inline void 551 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 552 bus_size_t offset, const u_int8_t *addr, size_t count) 553 { 554 #if defined(_I386_BUS_PIO_H_) 555 #if defined(_I386_BUS_MEMIO_H_) 556 if (tag == I386_BUS_SPACE_IO) 557 #endif 558 outsb(bsh + offset, addr, count); 559 #endif 560 #if defined(_I386_BUS_MEMIO_H_) 561 #if defined(_I386_BUS_PIO_H_) 562 else 563 #endif 564 { 565 int __x __asm__("%eax"); 566 __asm __volatile(" 567 cld ; 568 1: lodsb ; 569 movb %%al,(%1) ; 570 loop 1b" : 571 "=&a" (__x) : 572 "r" (bsh + offset), "S" (addr), "c" (count) : 573 "%esi", "%ecx"); 574 } 575 #endif 576 } 577 578 static __inline void 579 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 580 bus_size_t offset, const u_int16_t *addr, size_t count) 581 { 582 #if defined(_I386_BUS_PIO_H_) 583 #if defined(_I386_BUS_MEMIO_H_) 584 if (tag == I386_BUS_SPACE_IO) 585 #endif 586 outsw(bsh + offset, addr, count); 587 #endif 588 #if defined(_I386_BUS_MEMIO_H_) 589 #if defined(_I386_BUS_PIO_H_) 590 else 591 #endif 592 { 593 int __x __asm__("%eax"); 594 __asm __volatile(" 595 cld ; 596 1: lodsw ; 597 movw %%ax,(%1) ; 598 loop 1b" : 599 "=&a" (__x) : 600 "r" (bsh + offset), "S" (addr), "c" (count) : 601 "%esi", "%ecx"); 602 } 603 #endif 604 } 605 606 static __inline void 607 bus_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 #if defined(_I386_BUS_PIO_H_) 611 #if defined(_I386_BUS_MEMIO_H_) 612 if (tag == I386_BUS_SPACE_IO) 613 #endif 614 outsl(bsh + offset, addr, count); 615 #endif 616 #if defined(_I386_BUS_MEMIO_H_) 617 #if defined(_I386_BUS_PIO_H_) 618 else 619 #endif 620 { 621 int __x __asm__("%eax"); 622 __asm __volatile(" 623 cld ; 624 1: lodsl ; 625 movl %%eax,(%1) ; 626 loop 1b" : 627 "=&a" (__x) : 628 "r" (bsh + offset), "S" (addr), "c" (count) : 629 "%esi", "%ecx"); 630 } 631 #endif 632 } 633 634 #if 0 /* Cause a link error for bus_space_write_multi_8 */ 635 #define bus_space_write_multi_8(t, h, o, a, c) \ 636 !!! bus_space_write_multi_8 unimplemented !!! 637 #endif 638 639 /* 640 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided 641 * to bus space described by tag/handle starting at `offset'. 642 */ 643 644 static __inline void bus_space_write_region_1(bus_space_tag_t tag, 645 bus_space_handle_t bsh, 646 bus_size_t offset, 647 const u_int8_t *addr, 648 size_t count); 649 static __inline void bus_space_write_region_2(bus_space_tag_t tag, 650 bus_space_handle_t bsh, 651 bus_size_t offset, 652 const u_int16_t *addr, 653 size_t count); 654 static __inline void bus_space_write_region_4(bus_space_tag_t tag, 655 bus_space_handle_t bsh, 656 bus_size_t offset, 657 const u_int32_t *addr, 658 size_t count); 659 660 static __inline void 661 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 662 bus_size_t offset, const u_int8_t *addr, size_t count) 663 { 664 #if defined(_I386_BUS_PIO_H_) 665 #if defined(_I386_BUS_MEMIO_H_) 666 if (tag == I386_BUS_SPACE_IO) 667 #endif 668 { 669 int __x __asm__("%eax"); 670 __asm __volatile(" 671 cld ; 672 1: lodsb ; 673 outb %%al,%w1 ; 674 incl %1 ; 675 loop 1b" : 676 "=&a" (__x) : 677 "d" (bsh + offset), "S" (addr), "c" (count) : 678 "%edx", "%esi", "%ecx", "memory"); 679 } 680 #endif 681 #if defined(_I386_BUS_MEMIO_H_) 682 #if defined(_I386_BUS_PIO_H_) 683 else 684 #endif 685 { 686 __asm __volatile(" 687 cld ; 688 repne ; 689 movsb" : 690 : 691 "D" (bsh + offset), "S" (addr), "c" (count) : 692 "%edi", "%esi", "%ecx", "memory"); 693 } 694 #endif 695 } 696 697 static __inline void 698 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 699 bus_size_t offset, const u_int16_t *addr, size_t count) 700 { 701 #if defined(_I386_BUS_PIO_H_) 702 #if defined(_I386_BUS_MEMIO_H_) 703 if (tag == I386_BUS_SPACE_IO) 704 #endif 705 { 706 int __x __asm__("%eax"); 707 __asm __volatile(" 708 cld ; 709 1: lodsw ; 710 outw %%ax,%w1 ; 711 addl $2,%1 ; 712 loop 1b" : 713 "=&a" (__x) : 714 "d" (bsh + offset), "S" (addr), "c" (count) : 715 "%edx", "%esi", "%ecx", "memory"); 716 } 717 #endif 718 #if defined(_I386_BUS_MEMIO_H_) 719 #if defined(_I386_BUS_PIO_H_) 720 else 721 #endif 722 { 723 __asm __volatile(" 724 cld ; 725 repne ; 726 movsw" : 727 : 728 "D" (bsh + offset), "S" (addr), "c" (count) : 729 "%edi", "%esi", "%ecx", "memory"); 730 } 731 #endif 732 } 733 734 static __inline void 735 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 736 bus_size_t offset, const u_int32_t *addr, size_t count) 737 { 738 #if defined(_I386_BUS_PIO_H_) 739 #if defined(_I386_BUS_MEMIO_H_) 740 if (tag == I386_BUS_SPACE_IO) 741 #endif 742 { 743 int __x __asm__("%eax"); 744 __asm __volatile(" 745 cld ; 746 1: lodsl ; 747 outl %%eax,%w1 ; 748 addl $4,%1 ; 749 loop 1b" : 750 "=&a" (__x) : 751 "d" (bsh + offset), "S" (addr), "c" (count) : 752 "%edx", "%esi", "%ecx", "memory"); 753 } 754 #endif 755 #if defined(_I386_BUS_MEMIO_H_) 756 #if defined(_I386_BUS_PIO_H_) 757 else 758 #endif 759 { 760 __asm __volatile(" 761 cld ; 762 repne ; 763 movsl" : 764 : 765 "D" (bsh + offset), "S" (addr), "c" (count) : 766 "%edi", "%esi", "%ecx", "memory"); 767 } 768 #endif 769 } 770 771 #if 0 /* Cause a link error for bus_space_write_region_8 */ 772 #define bus_space_write_region_8 \ 773 !!! bus_space_write_region_8 unimplemented !!! 774 #endif 775 776 /* 777 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 778 * by tag/handle/offset `count' times. 779 */ 780 781 static __inline void bus_space_set_multi_1(bus_space_tag_t tag, 782 bus_space_handle_t bsh, 783 bus_size_t offset, 784 u_int8_t value, size_t count); 785 static __inline void bus_space_set_multi_2(bus_space_tag_t tag, 786 bus_space_handle_t bsh, 787 bus_size_t offset, 788 u_int16_t value, size_t count); 789 static __inline void bus_space_set_multi_4(bus_space_tag_t tag, 790 bus_space_handle_t bsh, 791 bus_size_t offset, 792 u_int32_t value, size_t count); 793 794 static __inline void 795 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, 796 bus_size_t offset, u_int8_t value, size_t count) 797 { 798 bus_addr_t addr = bsh + offset; 799 800 #if defined(_I386_BUS_PIO_H_) 801 #if defined(_I386_BUS_MEMIO_H_) 802 if (tag == I386_BUS_SPACE_IO) 803 #endif 804 while (count--) 805 outb(addr, value); 806 #endif 807 #if defined(_I386_BUS_MEMIO_H_) 808 #if defined(_I386_BUS_PIO_H_) 809 else 810 #endif 811 while (count--) 812 *(volatile u_int8_t *)(addr) = value; 813 #endif 814 } 815 816 static __inline void 817 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, 818 bus_size_t offset, u_int16_t value, size_t count) 819 { 820 bus_addr_t addr = bsh + offset; 821 822 #if defined(_I386_BUS_PIO_H_) 823 #if defined(_I386_BUS_MEMIO_H_) 824 if (tag == I386_BUS_SPACE_IO) 825 #endif 826 while (count--) 827 outw(addr, value); 828 #endif 829 #if defined(_I386_BUS_MEMIO_H_) 830 #if defined(_I386_BUS_PIO_H_) 831 else 832 #endif 833 while (count--) 834 *(volatile u_int16_t *)(addr) = value; 835 #endif 836 } 837 838 static __inline void 839 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, 840 bus_size_t offset, u_int32_t value, size_t count) 841 { 842 bus_addr_t addr = bsh + offset; 843 844 #if defined(_I386_BUS_PIO_H_) 845 #if defined(_I386_BUS_MEMIO_H_) 846 if (tag == I386_BUS_SPACE_IO) 847 #endif 848 while (count--) 849 outl(addr, value); 850 #endif 851 #if defined(_I386_BUS_MEMIO_H_) 852 #if defined(_I386_BUS_PIO_H_) 853 else 854 #endif 855 while (count--) 856 *(volatile u_int32_t *)(addr) = value; 857 #endif 858 } 859 860 #if 0 /* Cause a link error for bus_space_set_multi_8 */ 861 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!! 862 #endif 863 864 /* 865 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described 866 * by tag/handle starting at `offset'. 867 */ 868 869 static __inline void bus_space_set_region_1(bus_space_tag_t tag, 870 bus_space_handle_t bsh, 871 bus_size_t offset, u_int8_t value, 872 size_t count); 873 static __inline void bus_space_set_region_2(bus_space_tag_t tag, 874 bus_space_handle_t bsh, 875 bus_size_t offset, u_int16_t value, 876 size_t count); 877 static __inline void bus_space_set_region_4(bus_space_tag_t tag, 878 bus_space_handle_t bsh, 879 bus_size_t offset, u_int32_t value, 880 size_t count); 881 882 static __inline void 883 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, 884 bus_size_t offset, u_int8_t value, size_t count) 885 { 886 bus_addr_t addr = bsh + offset; 887 888 #if defined(_I386_BUS_PIO_H_) 889 #if defined(_I386_BUS_MEMIO_H_) 890 if (tag == I386_BUS_SPACE_IO) 891 #endif 892 for (; count != 0; count--, addr++) 893 outb(addr, value); 894 #endif 895 #if defined(_I386_BUS_MEMIO_H_) 896 #if defined(_I386_BUS_PIO_H_) 897 else 898 #endif 899 for (; count != 0; count--, addr++) 900 *(volatile u_int8_t *)(addr) = value; 901 #endif 902 } 903 904 static __inline void 905 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, 906 bus_size_t offset, u_int16_t value, size_t count) 907 { 908 bus_addr_t addr = bsh + offset; 909 910 #if defined(_I386_BUS_PIO_H_) 911 #if defined(_I386_BUS_MEMIO_H_) 912 if (tag == I386_BUS_SPACE_IO) 913 #endif 914 for (; count != 0; count--, addr += 2) 915 outw(addr, value); 916 #endif 917 #if defined(_I386_BUS_MEMIO_H_) 918 #if defined(_I386_BUS_PIO_H_) 919 else 920 #endif 921 for (; count != 0; count--, addr += 2) 922 *(volatile u_int16_t *)(addr) = value; 923 #endif 924 } 925 926 static __inline void 927 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, 928 bus_size_t offset, u_int32_t value, size_t count) 929 { 930 bus_addr_t addr = bsh + offset; 931 932 #if defined(_I386_BUS_PIO_H_) 933 #if defined(_I386_BUS_MEMIO_H_) 934 if (tag == I386_BUS_SPACE_IO) 935 #endif 936 for (; count != 0; count--, addr += 4) 937 outl(addr, value); 938 #endif 939 #if defined(_I386_BUS_MEMIO_H_) 940 #if defined(_I386_BUS_PIO_H_) 941 else 942 #endif 943 for (; count != 0; count--, addr += 4) 944 *(volatile u_int32_t *)(addr) = value; 945 #endif 946 } 947 948 #if 0 /* Cause a link error for bus_space_set_region_8 */ 949 #define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!! 950 #endif 951 952 /* 953 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting 954 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. 955 */ 956 957 static __inline void bus_space_copy_region_1(bus_space_tag_t tag, 958 bus_space_handle_t bsh1, 959 bus_size_t off1, 960 bus_space_handle_t bsh2, 961 bus_size_t off2, size_t count); 962 963 static __inline void bus_space_copy_region_2(bus_space_tag_t tag, 964 bus_space_handle_t bsh1, 965 bus_size_t off1, 966 bus_space_handle_t bsh2, 967 bus_size_t off2, size_t count); 968 969 static __inline void bus_space_copy_region_4(bus_space_tag_t tag, 970 bus_space_handle_t bsh1, 971 bus_size_t off1, 972 bus_space_handle_t bsh2, 973 bus_size_t off2, size_t count); 974 975 static __inline void 976 bus_space_copy_region_1(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_addr_t addr1 = bsh1 + off1; 981 bus_addr_t addr2 = bsh2 + off2; 982 983 #if defined(_I386_BUS_PIO_H_) 984 #if defined(_I386_BUS_MEMIO_H_) 985 if (tag == I386_BUS_SPACE_IO) 986 #endif 987 { 988 if (addr1 >= addr2) { 989 /* src after dest: copy forward */ 990 for (; count != 0; count--, addr1++, addr2++) 991 outb(addr2, inb(addr1)); 992 } else { 993 /* dest after src: copy backwards */ 994 for (addr1 += (count - 1), addr2 += (count - 1); 995 count != 0; count--, addr1--, addr2--) 996 outb(addr2, inb(addr1)); 997 } 998 } 999 #endif 1000 #if defined(_I386_BUS_MEMIO_H_) 1001 #if defined(_I386_BUS_PIO_H_) 1002 else 1003 #endif 1004 { 1005 if (addr1 >= addr2) { 1006 /* src after dest: copy forward */ 1007 for (; count != 0; count--, addr1++, addr2++) 1008 *(volatile u_int8_t *)(addr2) = 1009 *(volatile u_int8_t *)(addr1); 1010 } else { 1011 /* dest after src: copy backwards */ 1012 for (addr1 += (count - 1), addr2 += (count - 1); 1013 count != 0; count--, addr1--, addr2--) 1014 *(volatile u_int8_t *)(addr2) = 1015 *(volatile u_int8_t *)(addr1); 1016 } 1017 } 1018 #endif 1019 } 1020 1021 static __inline void 1022 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1, 1023 bus_size_t off1, bus_space_handle_t bsh2, 1024 bus_size_t off2, size_t count) 1025 { 1026 bus_addr_t addr1 = bsh1 + off1; 1027 bus_addr_t addr2 = bsh2 + off2; 1028 1029 #if defined(_I386_BUS_PIO_H_) 1030 #if defined(_I386_BUS_MEMIO_H_) 1031 if (tag == I386_BUS_SPACE_IO) 1032 #endif 1033 { 1034 if (addr1 >= addr2) { 1035 /* src after dest: copy forward */ 1036 for (; count != 0; count--, addr1 += 2, addr2 += 2) 1037 outw(addr2, inw(addr1)); 1038 } else { 1039 /* dest after src: copy backwards */ 1040 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); 1041 count != 0; count--, addr1 -= 2, addr2 -= 2) 1042 outw(addr2, inw(addr1)); 1043 } 1044 } 1045 #endif 1046 #if defined(_I386_BUS_MEMIO_H_) 1047 #if defined(_I386_BUS_PIO_H_) 1048 else 1049 #endif 1050 { 1051 if (addr1 >= addr2) { 1052 /* src after dest: copy forward */ 1053 for (; count != 0; count--, addr1 += 2, addr2 += 2) 1054 *(volatile u_int16_t *)(addr2) = 1055 *(volatile u_int16_t *)(addr1); 1056 } else { 1057 /* dest after src: copy backwards */ 1058 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); 1059 count != 0; count--, addr1 -= 2, addr2 -= 2) 1060 *(volatile u_int16_t *)(addr2) = 1061 *(volatile u_int16_t *)(addr1); 1062 } 1063 } 1064 #endif 1065 } 1066 1067 static __inline void 1068 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1, 1069 bus_size_t off1, bus_space_handle_t bsh2, 1070 bus_size_t off2, size_t count) 1071 { 1072 bus_addr_t addr1 = bsh1 + off1; 1073 bus_addr_t addr2 = bsh2 + off2; 1074 1075 #if defined(_I386_BUS_PIO_H_) 1076 #if defined(_I386_BUS_MEMIO_H_) 1077 if (tag == I386_BUS_SPACE_IO) 1078 #endif 1079 { 1080 if (addr1 >= addr2) { 1081 /* src after dest: copy forward */ 1082 for (; count != 0; count--, addr1 += 4, addr2 += 4) 1083 outl(addr2, inl(addr1)); 1084 } else { 1085 /* dest after src: copy backwards */ 1086 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); 1087 count != 0; count--, addr1 -= 4, addr2 -= 4) 1088 outl(addr2, inl(addr1)); 1089 } 1090 } 1091 #endif 1092 #if defined(_I386_BUS_MEMIO_H_) 1093 #if defined(_I386_BUS_PIO_H_) 1094 else 1095 #endif 1096 { 1097 if (addr1 >= addr2) { 1098 /* src after dest: copy forward */ 1099 for (; count != 0; count--, addr1 += 4, addr2 += 4) 1100 *(volatile u_int32_t *)(addr2) = 1101 *(volatile u_int32_t *)(addr1); 1102 } else { 1103 /* dest after src: copy backwards */ 1104 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); 1105 count != 0; count--, addr1 -= 4, addr2 -= 4) 1106 *(volatile u_int32_t *)(addr2) = 1107 *(volatile u_int32_t *)(addr1); 1108 } 1109 } 1110 #endif 1111 } 1112 1113 #endif /* defined(_I386_BUS_PIO_H_) || defined(_I386_MEM_IO_H_) */ 1114 1115 #if 0 /* Cause a link error for bus_space_copy_8 */ 1116 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!! 1117 #endif 1118 1119 /* 1120 * Bus read/write barrier methods. 1121 * 1122 * void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, 1123 * bus_size_t offset, bus_size_t len, int flags); 1124 * 1125 * Note: the i386 does not currently require barriers, but we must 1126 * provide the flags to MI code. 1127 */ 1128 #define bus_space_barrier(t, h, o, l, f) \ 1129 ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f))) 1130 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 1131 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 1132 1133 /* 1134 * Flags used in various bus DMA methods. 1135 */ 1136 #define BUS_DMA_WAITOK 0x00 /* safe to sleep (pseudo-flag) */ 1137 #define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */ 1138 #define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */ 1139 #define BUS_DMAMEM_NOSYNC 0x04 /* map memory to not require sync */ 1140 #define BUS_DMA_BUS1 0x10 /* placeholders for bus functions... */ 1141 #define BUS_DMA_BUS2 0x20 1142 #define BUS_DMA_BUS3 0x40 1143 #define BUS_DMA_BUS4 0x80 1144 1145 /* Forwards needed by prototypes below. */ 1146 struct mbuf; 1147 struct uio; 1148 1149 /* 1150 * bus_dmasync_op_t 1151 * 1152 * Operations performed by bus_dmamap_sync(). 1153 */ 1154 typedef enum { 1155 BUS_DMASYNC_PREREAD, 1156 BUS_DMASYNC_POSTREAD, 1157 BUS_DMASYNC_PREWRITE, 1158 BUS_DMASYNC_POSTWRITE, 1159 } bus_dmasync_op_t; 1160 1161 /* 1162 * bus_dma_tag_t 1163 * 1164 * A machine-dependent opaque type describing the characteristics 1165 * of how to perform DMA mappings. This structure encapsultes 1166 * information concerning address and alignment restrictions, number 1167 * of S/G segments, amount of data per S/G segment, etc. 1168 */ 1169 typedef struct bus_dma_tag *bus_dma_tag_t; 1170 1171 /* 1172 * bus_dmamap_t 1173 * 1174 * DMA mapping instance information. 1175 */ 1176 typedef struct bus_dmamap *bus_dmamap_t; 1177 1178 /* 1179 * bus_dma_segment_t 1180 * 1181 * Describes a single contiguous DMA transaction. Values 1182 * are suitable for programming into DMA registers. 1183 */ 1184 typedef struct bus_dma_segment { 1185 bus_addr_t ds_addr; /* DMA address */ 1186 bus_size_t ds_len; /* length of transfer */ 1187 } bus_dma_segment_t; 1188 1189 /* 1190 * A function that returns 1 if the address cannot be accessed by 1191 * a device and 0 if it can be. 1192 */ 1193 typedef int bus_dma_filter_t(void *, bus_addr_t); 1194 1195 /* 1196 * Allocate a device specific dma_tag encapsulating the constraints of 1197 * the parent tag in addition to other restrictions specified: 1198 * 1199 * boundary: Boundary that segments cannot cross. 1200 * lowaddr: Low restricted address that cannot appear in a mapping. 1201 * highaddr: High restricted address that cannot appear in a mapping. 1202 * filtfunc: An optional function to further test if an address 1203 * within the range of lowaddr and highaddr cannot appear 1204 * in a mapping. 1205 * filtfuncarg: An argument that will be passed to filtfunc in addition 1206 * to the address to test. 1207 * flags: Bus DMA flags. 1208 * dmat: A pointer to set to a valid dma tag should the return 1209 * value of this function indicate success. 1210 */ 1211 int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t boundary, 1212 bus_addr_t lowaddr, bus_addr_t highaddr, 1213 bus_dma_filter_t *filtfunc, void *filtfuncarg, 1214 bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, 1215 int flags, bus_dma_tag_t *dmat); 1216 1217 int bus_dma_tag_destroy(bus_dma_tag_t dmat); 1218 1219 /* 1220 * Allocate a handle for mapping from kva/uva/physical 1221 * address space into bus device space. 1222 * 1223 * maxsize: Maximum mapping size supported by this handle. 1224 * nsegments: Number of discontinuities allowed in the map. 1225 * maxsegsz: Maximum size of a segment in the map. 1226 */ 1227 int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp); 1228 1229 /* 1230 * Destroy a handle for mapping from kva/uva/physical 1231 * address space into bus device space. 1232 */ 1233 int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map); 1234 1235 /* 1236 * A function that processes a successfully loaded dma map or an error 1237 * from a delayed load map. 1238 */ 1239 typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); 1240 1241 /* 1242 * Map the buffer buf into bus space using the dmamap map. 1243 */ 1244 int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 1245 bus_size_t buflen, bus_dmamap_callback_t *callback, 1246 void *callback_arg, int flags); 1247 1248 /* 1249 * Perform a syncronization operation on the given map. 1250 */ 1251 void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); 1252 #define bus_dmamap_sync(dmat, dmamap, op) \ 1253 if ((dmamap) != NULL) \ 1254 _bus_dmamap_sync(dmat, dmamap, op) 1255 1256 /* 1257 * Release the mapping held by map. 1258 */ 1259 void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map); 1260 #define bus_dmamap_unload(dmat, dmamap) \ 1261 if ((dmamap) != NULL) \ 1262 _bus_dmamap_unload(dmat, dmamap) 1263 1264 #endif /* _I386_BUS_H_ */ 1265