1 /* $OpenBSD: pio.h,v 1.5 2015/04/25 21:31:24 guenther Exp $ */
2 /* $NetBSD: pio.h,v 1.2 2003/02/27 11:22:46 fvdl Exp $ */
3
4 /*-
5 * Copyright (c) 1998 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Charles M. Hannum.
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 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifndef _MACHINE_PIO_H_
34 #define _MACHINE_PIO_H_
35
36 /*
37 * Functions to provide access to x86 programmed I/O instructions.
38 *
39 * The in[bwl]() and out[bwl]() functions are split into two varieties: one to
40 * use a small, constant, 8-bit port number, and another to use a large or
41 * variable port number. The former can be compiled as a smaller instruction.
42 */
43
44
45 #ifdef __OPTIMIZE__
46
47 #define __use_immediate_port(port) \
48 (__builtin_constant_p((port)) && (port) < 0x100)
49
50 #else
51
52 #define __use_immediate_port(port) 0
53
54 #endif
55
56
57 #define inb(port) \
58 (/* CONSTCOND */ __use_immediate_port(port) ? __inbc(port) : __inb(port))
59
60 static __inline u_int8_t
__inbc(unsigned port)61 __inbc(unsigned port)
62 {
63 u_int8_t data;
64 __asm volatile("inb %w1,%0" : "=a" (data) : "id" (port));
65 return data;
66 }
67
68 static __inline u_int8_t
__inb(unsigned port)69 __inb(unsigned port)
70 {
71 u_int8_t data;
72 __asm volatile("inb %w1,%0" : "=a" (data) : "d" (port));
73 return data;
74 }
75
76 static __inline void
insb(unsigned port,void * addr,int cnt)77 insb(unsigned port, void *addr, int cnt)
78 {
79 void *dummy1;
80 int dummy2;
81 __asm volatile("repne\n\tinsb" :
82 "=D" (dummy1), "=c" (dummy2) :
83 "d" (port), "0" (addr), "1" (cnt) :
84 "memory");
85 }
86
87 #define inw(port) \
88 (/* CONSTCOND */ __use_immediate_port(port) ? __inwc(port) : __inw(port))
89
90 static __inline u_int16_t
__inwc(unsigned port)91 __inwc(unsigned port)
92 {
93 u_int16_t data;
94 __asm volatile("inw %w1,%0" : "=a" (data) : "id" (port));
95 return data;
96 }
97
98 static __inline u_int16_t
__inw(unsigned port)99 __inw(unsigned port)
100 {
101 u_int16_t data;
102 __asm volatile("inw %w1,%0" : "=a" (data) : "d" (port));
103 return data;
104 }
105
106 static __inline void
insw(unsigned port,void * addr,int cnt)107 insw(unsigned port, void *addr, int cnt)
108 {
109 void *dummy1;
110 int dummy2;
111 __asm volatile("repne\n\tinsw" :
112 "=D" (dummy1), "=c" (dummy2) :
113 "d" (port), "0" (addr), "1" (cnt) :
114 "memory");
115 }
116
117 #define inl(port) \
118 (/* CONSTCOND */ __use_immediate_port(port) ? __inlc(port) : __inl(port))
119
120 static __inline u_int32_t
__inlc(unsigned port)121 __inlc(unsigned port)
122 {
123 u_int32_t data;
124 __asm volatile("inl %w1,%0" : "=a" (data) : "id" (port));
125 return data;
126 }
127
128 static __inline u_int32_t
__inl(unsigned port)129 __inl(unsigned port)
130 {
131 u_int32_t data;
132 __asm volatile("inl %w1,%0" : "=a" (data) : "d" (port));
133 return data;
134 }
135
136 static __inline void
insl(unsigned port,void * addr,int cnt)137 insl(unsigned port, void *addr, int cnt)
138 {
139 void *dummy1;
140 int dummy2;
141 __asm volatile("repne\n\tinsl" :
142 "=D" (dummy1), "=c" (dummy2) :
143 "d" (port), "0" (addr), "1" (cnt) :
144 "memory");
145 }
146
147 #define outb(port, data) \
148 (/* CONSTCOND */__use_immediate_port(port) ? __outbc(port, data) : \
149 __outb(port, data))
150
151 static __inline void
__outbc(unsigned port,u_int8_t data)152 __outbc(unsigned port, u_int8_t data)
153 {
154 __asm volatile("outb %0,%w1" : : "a" (data), "id" (port));
155 }
156
157 static __inline void
__outb(unsigned port,u_int8_t data)158 __outb(unsigned port, u_int8_t data)
159 {
160 __asm volatile("outb %0,%w1" : : "a" (data), "d" (port));
161 }
162
163 static __inline void
outsb(unsigned port,const void * addr,int cnt)164 outsb(unsigned port, const void *addr, int cnt)
165 {
166 void *dummy1;
167 int dummy2;
168 __asm volatile("repne\n\toutsb" :
169 "=S" (dummy1), "=c" (dummy2) :
170 "d" (port), "0" (addr), "1" (cnt));
171 }
172
173 #define outw(port, data) \
174 (/* CONSTCOND */ __use_immediate_port(port) ? __outwc(port, data) : \
175 __outw(port, data))
176
177 static __inline void
__outwc(unsigned port,u_int16_t data)178 __outwc(unsigned port, u_int16_t data)
179 {
180 __asm volatile("outw %0,%w1" : : "a" (data), "id" (port));
181 }
182
183 static __inline void
__outw(unsigned port,u_int16_t data)184 __outw(unsigned port, u_int16_t data)
185 {
186 __asm volatile("outw %0,%w1" : : "a" (data), "d" (port));
187 }
188
189 static __inline void
outsw(unsigned port,const void * addr,int cnt)190 outsw(unsigned port, const void *addr, int cnt)
191 {
192 void *dummy1;
193 int dummy2;
194 __asm volatile("repne\n\toutsw" :
195 "=S" (dummy1), "=c" (dummy2) :
196 "d" (port), "0" (addr), "1" (cnt));
197 }
198
199 #define outl(port, data) \
200 (/* CONSTCOND */ __use_immediate_port(port) ? __outlc(port, data) : \
201 __outl(port, data))
202
203 static __inline void
__outlc(unsigned port,u_int32_t data)204 __outlc(unsigned port, u_int32_t data)
205 {
206 __asm volatile("outl %0,%w1" : : "a" (data), "id" (port));
207 }
208
209 static __inline void
__outl(unsigned port,u_int32_t data)210 __outl(unsigned port, u_int32_t data)
211 {
212 __asm volatile("outl %0,%w1" : : "a" (data), "d" (port));
213 }
214
215 static __inline void
outsl(unsigned port,const void * addr,int cnt)216 outsl(unsigned port, const void *addr, int cnt)
217 {
218 void *dummy1;
219 int dummy2;
220 __asm volatile("repne\n\toutsl" :
221 "=S" (dummy1), "=c" (dummy2) :
222 "d" (port), "0" (addr), "1" (cnt));
223 }
224
225 #endif /* _MACHINE_PIO_H_ */
226