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