2 * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause-NetBSDE
4 * Copyright (c) KATO Takenori, 1999.
6 * All rights reserved. Unpublished rights reserved under the copyright
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer as
15 * the first lines of this file unmodified.
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. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 /* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */
39 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
40 * All rights reserved.
42 * This code is derived from software contributed to The NetBSD Foundation
43 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
44 * NASA Ames Research Center.
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
55 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
56 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
57 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
58 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
59 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
60 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
62 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65 * POSSIBILITY OF SUCH DAMAGE.
69 * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
70 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
72 * Redistribution and use in source and binary forms, with or without
73 * modification, are permitted provided that the following conditions
75 * 1. Redistributions of source code must retain the above copyright
76 * notice, this list of conditions and the following disclaimer.
77 * 2. Redistributions in binary form must reproduce the above copyright
78 * notice, this list of conditions and the following disclaimer in the
79 * documentation and/or other materials provided with the distribution.
80 * 3. All advertising materials mentioning features or use of this software
81 * must display the following acknowledgement:
82 * This product includes software developed by Christopher G. Demetriou
83 * for the NetBSD Project.
84 * 4. The name of the author may not be used to endorse or promote products
85 * derived from this software without specific prior written permission
87 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
88 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
89 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
90 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
91 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
92 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
93 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
94 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
95 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
96 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
102 #include <machine/_bus.h>
103 #include <machine/cpufunc.h>
104 #include <machine/bus_dma.h>
106 #ifndef __GNUCLIKE_ASM
107 #error "no assembler code for your compiler"
111 * Values for the x86 bus space tag, not to be used directly by MI code.
113 #define X86_BUS_SPACE_IO 0 /* space is i/o space */
114 #define X86_BUS_SPACE_MEM 1 /* space is mem space */
116 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
117 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
118 #if defined(__amd64__)
119 #define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFFULL
121 #define BUS_SPACE_MAXSIZE 0xFFFFFFFF
123 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
124 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
125 #if defined(__amd64__) || defined(PAE)
126 #define BUS_SPACE_MAXADDR_48BIT 0xFFFFFFFFFFFFULL
127 #define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFULL
129 #define BUS_SPACE_MAXADDR 0xFFFFFFFF
132 #define BUS_SPACE_INVALID_DATA (~0)
133 #define BUS_SPACE_UNRESTRICTED (~0)
135 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
136 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
138 #if defined(KCSAN) && !defined(KCSAN_RUNTIME)
139 #include <sys/_cscan_bus.h>
143 * Map a region of device bus space into CPU virtual address space.
146 int bus_space_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size,
147 int flags, bus_space_handle_t *bshp);
150 * Unmap a region of device bus space.
153 void bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t bsh,
157 * Get a new handle for a subregion of an already-mapped area of bus space.
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);
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)
171 *nbshp = bsh + offset;
176 * Allocate a region of memory that is accessible to devices in bus space.
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);
185 * Free a region of bus space accessible memory.
188 static __inline void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
192 bus_space_free(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
193 bus_size_t size __unused)
199 * Read a 1, 2, 4, or 8 byte quantity from bus space
200 * described by tag/handle/offset.
202 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
203 bus_space_handle_t handle,
206 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
207 bus_space_handle_t handle,
210 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
211 bus_space_handle_t handle,
215 static __inline uint64_t bus_space_read_8(bus_space_tag_t tag,
216 bus_space_handle_t handle,
220 static __inline u_int8_t
221 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
225 if (tag == X86_BUS_SPACE_IO)
226 return (inb(handle + offset));
227 return (*(volatile u_int8_t *)(handle + offset));
230 static __inline u_int16_t
231 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
235 if (tag == X86_BUS_SPACE_IO)
236 return (inw(handle + offset));
237 return (*(volatile u_int16_t *)(handle + offset));
240 static __inline u_int32_t
241 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
245 if (tag == X86_BUS_SPACE_IO)
246 return (inl(handle + offset));
247 return (*(volatile u_int32_t *)(handle + offset));
251 static __inline uint64_t
252 bus_space_read_8(bus_space_tag_t tag, bus_space_handle_t handle,
256 if (tag == X86_BUS_SPACE_IO) /* No 8 byte IO space access on x86 */
257 return (BUS_SPACE_INVALID_DATA);
258 return (*(volatile uint64_t *)(handle + offset));
263 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
264 * described by tag/handle/offset and copy into buffer provided.
266 static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
267 bus_space_handle_t bsh,
268 bus_size_t offset, u_int8_t *addr,
271 static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
272 bus_space_handle_t bsh,
273 bus_size_t offset, u_int16_t *addr,
276 static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
277 bus_space_handle_t bsh,
278 bus_size_t offset, u_int32_t *addr,
282 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
283 bus_size_t offset, u_int8_t *addr, size_t count)
286 if (tag == X86_BUS_SPACE_IO)
287 insb(bsh + offset, addr, count);
289 #ifdef __GNUCLIKE_ASM
290 __asm __volatile(" \n\
291 1: movb (%2),%%al \n\
294 "=D" (addr), "=c" (count) :
295 "r" (bsh + offset), "0" (addr), "1" (count) :
302 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
303 bus_size_t offset, u_int16_t *addr, size_t count)
306 if (tag == X86_BUS_SPACE_IO)
307 insw(bsh + offset, addr, count);
309 #ifdef __GNUCLIKE_ASM
310 __asm __volatile(" \n\
311 1: movw (%2),%%ax \n\
314 "=D" (addr), "=c" (count) :
315 "r" (bsh + offset), "0" (addr), "1" (count) :
322 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
323 bus_size_t offset, u_int32_t *addr, size_t count)
326 if (tag == X86_BUS_SPACE_IO)
327 insl(bsh + offset, addr, count);
329 #ifdef __GNUCLIKE_ASM
330 __asm __volatile(" \n\
331 1: movl (%2),%%eax \n\
334 "=D" (addr), "=c" (count) :
335 "r" (bsh + offset), "0" (addr), "1" (count) :
341 #if 0 /* Cause a link error for bus_space_read_multi_8 */
342 #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!!
346 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
347 * described by tag/handle and starting at `offset' and copy into
350 static __inline void bus_space_read_region_1(bus_space_tag_t tag,
351 bus_space_handle_t bsh,
352 bus_size_t offset, u_int8_t *addr,
355 static __inline void bus_space_read_region_2(bus_space_tag_t tag,
356 bus_space_handle_t bsh,
357 bus_size_t offset, u_int16_t *addr,
360 static __inline void bus_space_read_region_4(bus_space_tag_t tag,
361 bus_space_handle_t bsh,
362 bus_size_t offset, u_int32_t *addr,
367 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
368 bus_size_t offset, u_int8_t *addr, size_t count)
371 if (tag == X86_BUS_SPACE_IO) {
372 int _port_ = bsh + offset;
373 #ifdef __GNUCLIKE_ASM
374 __asm __volatile(" \n\
379 "=D" (addr), "=c" (count), "=d" (_port_) :
380 "0" (addr), "1" (count), "2" (_port_) :
381 "%eax", "memory", "cc");
384 bus_space_handle_t _port_ = bsh + offset;
385 #ifdef __GNUCLIKE_ASM
386 __asm __volatile(" \n\
389 "=D" (addr), "=c" (count), "=S" (_port_) :
390 "0" (addr), "1" (count), "2" (_port_) :
397 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
398 bus_size_t offset, u_int16_t *addr, size_t count)
401 if (tag == X86_BUS_SPACE_IO) {
402 int _port_ = bsh + offset;
403 #ifdef __GNUCLIKE_ASM
404 __asm __volatile(" \n\
409 "=D" (addr), "=c" (count), "=d" (_port_) :
410 "0" (addr), "1" (count), "2" (_port_) :
411 "%eax", "memory", "cc");
414 bus_space_handle_t _port_ = bsh + offset;
415 #ifdef __GNUCLIKE_ASM
416 __asm __volatile(" \n\
419 "=D" (addr), "=c" (count), "=S" (_port_) :
420 "0" (addr), "1" (count), "2" (_port_) :
427 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
428 bus_size_t offset, u_int32_t *addr, size_t count)
431 if (tag == X86_BUS_SPACE_IO) {
432 int _port_ = bsh + offset;
433 #ifdef __GNUCLIKE_ASM
434 __asm __volatile(" \n\
439 "=D" (addr), "=c" (count), "=d" (_port_) :
440 "0" (addr), "1" (count), "2" (_port_) :
441 "%eax", "memory", "cc");
444 bus_space_handle_t _port_ = bsh + offset;
445 #ifdef __GNUCLIKE_ASM
446 __asm __volatile(" \n\
449 "=D" (addr), "=c" (count), "=S" (_port_) :
450 "0" (addr), "1" (count), "2" (_port_) :
456 #if 0 /* Cause a link error for bus_space_read_region_8 */
457 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
461 * Write the 1, 2, 4, or 8 byte value `value' to bus space
462 * described by tag/handle/offset.
465 static __inline void bus_space_write_1(bus_space_tag_t tag,
466 bus_space_handle_t bsh,
467 bus_size_t offset, u_int8_t value);
469 static __inline void bus_space_write_2(bus_space_tag_t tag,
470 bus_space_handle_t bsh,
471 bus_size_t offset, u_int16_t value);
473 static __inline void bus_space_write_4(bus_space_tag_t tag,
474 bus_space_handle_t bsh,
475 bus_size_t offset, u_int32_t value);
478 static __inline void bus_space_write_8(bus_space_tag_t tag,
479 bus_space_handle_t bsh,
480 bus_size_t offset, uint64_t value);
484 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
485 bus_size_t offset, u_int8_t value)
488 if (tag == X86_BUS_SPACE_IO)
489 outb(bsh + offset, value);
491 *(volatile u_int8_t *)(bsh + offset) = value;
495 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
496 bus_size_t offset, u_int16_t value)
499 if (tag == X86_BUS_SPACE_IO)
500 outw(bsh + offset, value);
502 *(volatile u_int16_t *)(bsh + offset) = value;
506 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
507 bus_size_t offset, u_int32_t value)
510 if (tag == X86_BUS_SPACE_IO)
511 outl(bsh + offset, value);
513 *(volatile u_int32_t *)(bsh + offset) = value;
518 bus_space_write_8(bus_space_tag_t tag, bus_space_handle_t bsh,
519 bus_size_t offset, uint64_t value)
522 if (tag == X86_BUS_SPACE_IO) /* No 8 byte IO space access on x86 */
525 *(volatile uint64_t *)(bsh + offset) = value;
530 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
531 * provided to bus space described by tag/handle/offset.
534 static __inline void bus_space_write_multi_1(bus_space_tag_t tag,
535 bus_space_handle_t bsh,
537 const u_int8_t *addr,
539 static __inline void bus_space_write_multi_2(bus_space_tag_t tag,
540 bus_space_handle_t bsh,
542 const u_int16_t *addr,
545 static __inline void bus_space_write_multi_4(bus_space_tag_t tag,
546 bus_space_handle_t bsh,
548 const u_int32_t *addr,
552 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
553 bus_size_t offset, const u_int8_t *addr, size_t count)
556 if (tag == X86_BUS_SPACE_IO)
557 outsb(bsh + offset, addr, count);
559 #ifdef __GNUCLIKE_ASM
560 __asm __volatile(" \n\
564 "=S" (addr), "=c" (count) :
565 "r" (bsh + offset), "0" (addr), "1" (count) :
566 "%eax", "memory", "cc");
572 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
573 bus_size_t offset, const u_int16_t *addr, size_t count)
576 if (tag == X86_BUS_SPACE_IO)
577 outsw(bsh + offset, addr, count);
579 #ifdef __GNUCLIKE_ASM
580 __asm __volatile(" \n\
584 "=S" (addr), "=c" (count) :
585 "r" (bsh + offset), "0" (addr), "1" (count) :
586 "%eax", "memory", "cc");
592 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
593 bus_size_t offset, const u_int32_t *addr, size_t count)
596 if (tag == X86_BUS_SPACE_IO)
597 outsl(bsh + offset, addr, count);
599 #ifdef __GNUCLIKE_ASM
600 __asm __volatile(" \n\
604 "=S" (addr), "=c" (count) :
605 "r" (bsh + offset), "0" (addr), "1" (count) :
606 "%eax", "memory", "cc");
611 #if 0 /* Cause a link error for bus_space_write_multi_8 */
612 #define bus_space_write_multi_8(t, h, o, a, c) \
613 !!! bus_space_write_multi_8 unimplemented !!!
617 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
618 * to bus space described by tag/handle starting at `offset'.
621 static __inline void bus_space_write_region_1(bus_space_tag_t tag,
622 bus_space_handle_t bsh,
624 const u_int8_t *addr,
626 static __inline void bus_space_write_region_2(bus_space_tag_t tag,
627 bus_space_handle_t bsh,
629 const u_int16_t *addr,
631 static __inline void bus_space_write_region_4(bus_space_tag_t tag,
632 bus_space_handle_t bsh,
634 const u_int32_t *addr,
638 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
639 bus_size_t offset, const u_int8_t *addr, size_t count)
642 if (tag == X86_BUS_SPACE_IO) {
643 int _port_ = bsh + offset;
644 #ifdef __GNUCLIKE_ASM
645 __asm __volatile(" \n\
650 "=d" (_port_), "=S" (addr), "=c" (count) :
651 "0" (_port_), "1" (addr), "2" (count) :
652 "%eax", "memory", "cc");
655 bus_space_handle_t _port_ = bsh + offset;
656 #ifdef __GNUCLIKE_ASM
657 __asm __volatile(" \n\
660 "=D" (_port_), "=S" (addr), "=c" (count) :
661 "0" (_port_), "1" (addr), "2" (count) :
668 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
669 bus_size_t offset, const u_int16_t *addr, size_t count)
672 if (tag == X86_BUS_SPACE_IO) {
673 int _port_ = bsh + offset;
674 #ifdef __GNUCLIKE_ASM
675 __asm __volatile(" \n\
680 "=d" (_port_), "=S" (addr), "=c" (count) :
681 "0" (_port_), "1" (addr), "2" (count) :
682 "%eax", "memory", "cc");
685 bus_space_handle_t _port_ = bsh + offset;
686 #ifdef __GNUCLIKE_ASM
687 __asm __volatile(" \n\
690 "=D" (_port_), "=S" (addr), "=c" (count) :
691 "0" (_port_), "1" (addr), "2" (count) :
698 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
699 bus_size_t offset, const u_int32_t *addr, size_t count)
702 if (tag == X86_BUS_SPACE_IO) {
703 int _port_ = bsh + offset;
704 #ifdef __GNUCLIKE_ASM
705 __asm __volatile(" \n\
710 "=d" (_port_), "=S" (addr), "=c" (count) :
711 "0" (_port_), "1" (addr), "2" (count) :
712 "%eax", "memory", "cc");
715 bus_space_handle_t _port_ = bsh + offset;
716 #ifdef __GNUCLIKE_ASM
717 __asm __volatile(" \n\
720 "=D" (_port_), "=S" (addr), "=c" (count) :
721 "0" (_port_), "1" (addr), "2" (count) :
727 #if 0 /* Cause a link error for bus_space_write_region_8 */
728 #define bus_space_write_region_8 \
729 !!! bus_space_write_region_8 unimplemented !!!
733 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
734 * by tag/handle/offset `count' times.
737 static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
738 bus_space_handle_t bsh,
740 u_int8_t value, size_t count);
741 static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
742 bus_space_handle_t bsh,
744 u_int16_t value, size_t count);
745 static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
746 bus_space_handle_t bsh,
748 u_int32_t value, size_t count);
751 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
752 bus_size_t offset, u_int8_t value, size_t count)
754 bus_space_handle_t addr = bsh + offset;
756 if (tag == X86_BUS_SPACE_IO)
761 *(volatile u_int8_t *)(addr) = value;
765 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
766 bus_size_t offset, u_int16_t value, size_t count)
768 bus_space_handle_t addr = bsh + offset;
770 if (tag == X86_BUS_SPACE_IO)
775 *(volatile u_int16_t *)(addr) = value;
779 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
780 bus_size_t offset, u_int32_t value, size_t count)
782 bus_space_handle_t addr = bsh + offset;
784 if (tag == X86_BUS_SPACE_IO)
789 *(volatile u_int32_t *)(addr) = value;
792 #if 0 /* Cause a link error for bus_space_set_multi_8 */
793 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
797 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
798 * by tag/handle starting at `offset'.
801 static __inline void bus_space_set_region_1(bus_space_tag_t tag,
802 bus_space_handle_t bsh,
803 bus_size_t offset, u_int8_t value,
805 static __inline void bus_space_set_region_2(bus_space_tag_t tag,
806 bus_space_handle_t bsh,
807 bus_size_t offset, u_int16_t value,
809 static __inline void bus_space_set_region_4(bus_space_tag_t tag,
810 bus_space_handle_t bsh,
811 bus_size_t offset, u_int32_t value,
815 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
816 bus_size_t offset, u_int8_t value, size_t count)
818 bus_space_handle_t addr = bsh + offset;
820 if (tag == X86_BUS_SPACE_IO)
821 for (; count != 0; count--, addr++)
824 for (; count != 0; count--, addr++)
825 *(volatile u_int8_t *)(addr) = value;
829 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
830 bus_size_t offset, u_int16_t value, size_t count)
832 bus_space_handle_t addr = bsh + offset;
834 if (tag == X86_BUS_SPACE_IO)
835 for (; count != 0; count--, addr += 2)
838 for (; count != 0; count--, addr += 2)
839 *(volatile u_int16_t *)(addr) = value;
843 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
844 bus_size_t offset, u_int32_t value, size_t count)
846 bus_space_handle_t addr = bsh + offset;
848 if (tag == X86_BUS_SPACE_IO)
849 for (; count != 0; count--, addr += 4)
852 for (; count != 0; count--, addr += 4)
853 *(volatile u_int32_t *)(addr) = value;
856 #if 0 /* Cause a link error for bus_space_set_region_8 */
857 #define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!!
861 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
862 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
865 static __inline void bus_space_copy_region_1(bus_space_tag_t tag,
866 bus_space_handle_t bsh1,
868 bus_space_handle_t bsh2,
869 bus_size_t off2, size_t count);
871 static __inline void bus_space_copy_region_2(bus_space_tag_t tag,
872 bus_space_handle_t bsh1,
874 bus_space_handle_t bsh2,
875 bus_size_t off2, size_t count);
877 static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
878 bus_space_handle_t bsh1,
880 bus_space_handle_t bsh2,
881 bus_size_t off2, size_t count);
884 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
885 bus_size_t off1, bus_space_handle_t bsh2,
886 bus_size_t off2, size_t count)
888 bus_space_handle_t addr1 = bsh1 + off1;
889 bus_space_handle_t addr2 = bsh2 + off2;
891 if (tag == X86_BUS_SPACE_IO) {
892 if (addr1 >= addr2) {
893 /* src after dest: copy forward */
894 for (; count != 0; count--, addr1++, addr2++)
895 outb(addr2, inb(addr1));
897 /* dest after src: copy backwards */
898 for (addr1 += (count - 1), addr2 += (count - 1);
899 count != 0; count--, addr1--, addr2--)
900 outb(addr2, inb(addr1));
903 if (addr1 >= addr2) {
904 /* src after dest: copy forward */
905 for (; count != 0; count--, addr1++, addr2++)
906 *(volatile u_int8_t *)(addr2) =
907 *(volatile u_int8_t *)(addr1);
909 /* dest after src: copy backwards */
910 for (addr1 += (count - 1), addr2 += (count - 1);
911 count != 0; count--, addr1--, addr2--)
912 *(volatile u_int8_t *)(addr2) =
913 *(volatile u_int8_t *)(addr1);
919 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
920 bus_size_t off1, bus_space_handle_t bsh2,
921 bus_size_t off2, size_t count)
923 bus_space_handle_t addr1 = bsh1 + off1;
924 bus_space_handle_t addr2 = bsh2 + off2;
926 if (tag == X86_BUS_SPACE_IO) {
927 if (addr1 >= addr2) {
928 /* src after dest: copy forward */
929 for (; count != 0; count--, addr1 += 2, addr2 += 2)
930 outw(addr2, inw(addr1));
932 /* dest after src: copy backwards */
933 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
934 count != 0; count--, addr1 -= 2, addr2 -= 2)
935 outw(addr2, inw(addr1));
938 if (addr1 >= addr2) {
939 /* src after dest: copy forward */
940 for (; count != 0; count--, addr1 += 2, addr2 += 2)
941 *(volatile u_int16_t *)(addr2) =
942 *(volatile u_int16_t *)(addr1);
944 /* dest after src: copy backwards */
945 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
946 count != 0; count--, addr1 -= 2, addr2 -= 2)
947 *(volatile u_int16_t *)(addr2) =
948 *(volatile u_int16_t *)(addr1);
954 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
955 bus_size_t off1, bus_space_handle_t bsh2,
956 bus_size_t off2, size_t count)
958 bus_space_handle_t addr1 = bsh1 + off1;
959 bus_space_handle_t addr2 = bsh2 + off2;
961 if (tag == X86_BUS_SPACE_IO) {
962 if (addr1 >= addr2) {
963 /* src after dest: copy forward */
964 for (; count != 0; count--, addr1 += 4, addr2 += 4)
965 outl(addr2, inl(addr1));
967 /* dest after src: copy backwards */
968 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
969 count != 0; count--, addr1 -= 4, addr2 -= 4)
970 outl(addr2, inl(addr1));
973 if (addr1 >= addr2) {
974 /* src after dest: copy forward */
975 for (; count != 0; count--, addr1 += 4, addr2 += 4)
976 *(volatile u_int32_t *)(addr2) =
977 *(volatile u_int32_t *)(addr1);
979 /* dest after src: copy backwards */
980 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
981 count != 0; count--, addr1 -= 4, addr2 -= 4)
982 *(volatile u_int32_t *)(addr2) =
983 *(volatile u_int32_t *)(addr1);
988 #if 0 /* Cause a link error for bus_space_copy_8 */
989 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!!
993 * Bus read/write barrier methods.
995 * void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
996 * bus_size_t offset, bus_size_t len, int flags);
999 * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than
1000 * prevent reordering by the compiler; all Intel x86 processors currently
1001 * retire operations outside the CPU in program order.
1003 static __inline void
1004 bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
1005 bus_size_t offset __unused, bus_size_t len __unused, int flags)
1007 #ifdef __GNUCLIKE_ASM
1008 if (flags & BUS_SPACE_BARRIER_READ)
1010 __asm __volatile("lock; addl $0,0(%%rsp)" : : : "memory");
1012 __asm __volatile("lock; addl $0,0(%%esp)" : : : "memory");
1015 __compiler_membar();
1019 #ifdef BUS_SPACE_NO_LEGACY
1022 #define inb(a) compiler_error
1023 #define inw(a) compiler_error
1024 #define inl(a) compiler_error
1025 #define outb(a, b) compiler_error
1026 #define outw(a, b) compiler_error
1027 #define outl(a, b) compiler_error
1031 * Stream accesses are the same as normal accesses on x86; there are no
1032 * supported bus systems with an endianess different from the host one.
1034 #define bus_space_read_stream_1(t, h, o) bus_space_read_1((t), (h), (o))
1035 #define bus_space_read_stream_2(t, h, o) bus_space_read_2((t), (h), (o))
1036 #define bus_space_read_stream_4(t, h, o) bus_space_read_4((t), (h), (o))
1038 #define bus_space_read_multi_stream_1(t, h, o, a, c) \
1039 bus_space_read_multi_1((t), (h), (o), (a), (c))
1040 #define bus_space_read_multi_stream_2(t, h, o, a, c) \
1041 bus_space_read_multi_2((t), (h), (o), (a), (c))
1042 #define bus_space_read_multi_stream_4(t, h, o, a, c) \
1043 bus_space_read_multi_4((t), (h), (o), (a), (c))
1045 #define bus_space_write_stream_1(t, h, o, v) \
1046 bus_space_write_1((t), (h), (o), (v))
1047 #define bus_space_write_stream_2(t, h, o, v) \
1048 bus_space_write_2((t), (h), (o), (v))
1049 #define bus_space_write_stream_4(t, h, o, v) \
1050 bus_space_write_4((t), (h), (o), (v))
1052 #define bus_space_write_multi_stream_1(t, h, o, a, c) \
1053 bus_space_write_multi_1((t), (h), (o), (a), (c))
1054 #define bus_space_write_multi_stream_2(t, h, o, a, c) \
1055 bus_space_write_multi_2((t), (h), (o), (a), (c))
1056 #define bus_space_write_multi_stream_4(t, h, o, a, c) \
1057 bus_space_write_multi_4((t), (h), (o), (a), (c))
1059 #define bus_space_set_multi_stream_1(t, h, o, v, c) \
1060 bus_space_set_multi_1((t), (h), (o), (v), (c))
1061 #define bus_space_set_multi_stream_2(t, h, o, v, c) \
1062 bus_space_set_multi_2((t), (h), (o), (v), (c))
1063 #define bus_space_set_multi_stream_4(t, h, o, v, c) \
1064 bus_space_set_multi_4((t), (h), (o), (v), (c))
1066 #define bus_space_read_region_stream_1(t, h, o, a, c) \
1067 bus_space_read_region_1((t), (h), (o), (a), (c))
1068 #define bus_space_read_region_stream_2(t, h, o, a, c) \
1069 bus_space_read_region_2((t), (h), (o), (a), (c))
1070 #define bus_space_read_region_stream_4(t, h, o, a, c) \
1071 bus_space_read_region_4((t), (h), (o), (a), (c))
1073 #define bus_space_write_region_stream_1(t, h, o, a, c) \
1074 bus_space_write_region_1((t), (h), (o), (a), (c))
1075 #define bus_space_write_region_stream_2(t, h, o, a, c) \
1076 bus_space_write_region_2((t), (h), (o), (a), (c))
1077 #define bus_space_write_region_stream_4(t, h, o, a, c) \
1078 bus_space_write_region_4((t), (h), (o), (a), (c))
1080 #define bus_space_set_region_stream_1(t, h, o, v, c) \
1081 bus_space_set_region_1((t), (h), (o), (v), (c))
1082 #define bus_space_set_region_stream_2(t, h, o, v, c) \
1083 bus_space_set_region_2((t), (h), (o), (v), (c))
1084 #define bus_space_set_region_stream_4(t, h, o, v, c) \
1085 bus_space_set_region_4((t), (h), (o), (v), (c))
1087 #define bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) \
1088 bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c))
1089 #define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \
1090 bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c))
1091 #define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \
1092 bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c))
1094 #endif /* KCSAN && !KCSAN_RUNTIME */
1096 #endif /* _X86_BUS_H_ */