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
60static __inline u_int8_t
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
68static __inline u_int8_t
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
76static __inline void
77insb(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
90static __inline u_int16_t
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
98static __inline u_int16_t
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
106static __inline void
107insw(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
120static __inline u_int32_t
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
128static __inline u_int32_t
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
136static __inline void
137insl(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
151static __inline void
152__outbc(unsigned port, u_int8_t data)
153{
154 __asm volatile("outb %0,%w1" : : "a" (data), "id" (port));
155}
156
157static __inline void
158__outb(unsigned port, u_int8_t data)
159{
160 __asm volatile("outb %0,%w1" : : "a" (data), "d" (port));
161}
162
163static __inline void
164outsb(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
177static __inline void
178__outwc(unsigned port, u_int16_t data)
179{
180 __asm volatile("outw %0,%w1" : : "a" (data), "id" (port));
181}
182
183static __inline void
184__outw(unsigned port, u_int16_t data)
185{
186 __asm volatile("outw %0,%w1" : : "a" (data), "d" (port));
187}
188
189static __inline void
190outsw(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
203static __inline void
204__outlc(unsigned port, u_int32_t data)
205{
206 __asm volatile("outl %0,%w1" : : "a" (data), "id" (port));
207}
208
209static __inline void
210__outl(unsigned port, u_int32_t data)
211{
212 __asm volatile("outl %0,%w1" : : "a" (data), "d" (port));
213}
214
215static __inline void
216outsl(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_ */