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