xref: /openbsd/sys/arch/amd64/include/pio.h (revision e39f036f)
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