|
|
1.1 root 1: #ifndef __KERNEL_X86IO_H__
2: #define __KERNEL_X86IO_H__
3:
4: /*
5: * The system V DDI/DKI for Intel processors defines a C-language interface to
6: * the machine I/O instructions available through <sys/types.h>.
7: *
8: * For simplicity, this has been factored out into a separate file for this
9: * implementation, and <sys/types.h> pulls this file in.
10: */
11: /*
12: *-IMPORTS:
13: * <common/ccompat.h>
14: * __EXTERN_C_BEGIN__
15: * __EXTERN_C_END__
16: * __PROTO ()
17: * __NON_ISO ()
18: * __INLINE__
19: * <common/xdebug.h>
20: * __LOCAL__
21: * <common/__types.h>
22: * __uchar_t
23: * __ushort_t
24: * __ulong_t
25: */
26:
27: #include <common/ccompat.h>
28: #include <common/xdebug.h>
29: #include <common/__types.h>
30:
31:
32: /*
33: * Get these into a useful form in a similar manner to the way the spl... ()
34: * functions are defined in <sys/inline.h>
35: */
36:
37: #if __GNUC__ && (defined (i386) || _I386) /* 80386 with GNU CC */
38:
39: /*
40: * The Coherent 'as' assembler is a little stupid about which instruction
41: * forms it will accept.
42: */
43:
44: # define __GAS_OR_AS(g,a) g
45:
46:
47: /*
48: * Note that the definitions for the string-input instructions assume that
49: * ES: is equivalent to DS:.
50: */
51:
52: __LOCAL__ __INLINE__ __uchar_t __inb (int _port) {
53: __uchar_t _result;
54: __NON_ISO (asm) volatile (__GAS_OR_AS ("in %1,%0", "inb (%1)") :
55: "=a" (_result) : "d" ((__ushort_t) _port));
56: return _result;
57: }
58:
59: __LOCAL__ __INLINE__ __ulong_t __inl (int _port) {
60: __ulong_t _result;
61: __NON_ISO (asm) volatile (__GAS_OR_AS ("in %1,%0", "inl (%1)") :
62: "=a" (_result) : "d" ((__ushort_t) _port));
63: return _result;
64: }
65:
66: __LOCAL__ __INLINE__ __ushort_t __inw (int _port) {
67: __ushort_t _result;
68: __NON_ISO (asm) volatile (__GAS_OR_AS ("in %1,%0", "inw (%1)") :
69: "=a" (_result) : "d" ((__ushort_t) _port));
70: return _result;
71: }
72:
73: __LOCAL__ __INLINE__ void __outb (int _port, __uchar_t value) {
74: __NON_ISO (asm) volatile (__GAS_OR_AS ("out %1,%0", "outb (%0)") : :
75: "d" ((__ushort_t) _port), "a" (value));
76: }
77:
78: __LOCAL__ __INLINE__ void __outl (int _port, __ulong_t value) {
79: __NON_ISO (asm) volatile (__GAS_OR_AS ("out %1,%0", "outl (%0)") : :
80: "d" ((__ushort_t) _port), "a" (value));
81: }
82:
83: __LOCAL__ __INLINE__ void __outw (int _port, __ushort_t value) {
84: __NON_ISO (asm) volatile (__GAS_OR_AS ("out %1,%0", "outw (%0)") : :
85: "d" ((__ushort_t) _port), "a" (value));
86: }
87:
88: __LOCAL__ __INLINE__
89: void __repinsb (int _port, __uchar_t * _addr, int _cnt) {
90: __NON_ISO (asm) volatile ("mov %1,%%edi;rep;insb" : :
91: "d" ((__ushort_t) _port), "g" (_addr),
92: "c" (_cnt) : "di");
93: }
94:
95: __LOCAL__ __INLINE__
96: void __repinsd (int _port, __ulong_t * _addr, int _cnt) {
97: __NON_ISO (asm) volatile ("mov %1,%%edi;rep;insl" : :
98: "d" ((__ushort_t) _port), "g" (_addr),
99: "c" (_cnt) : "di");
100: }
101:
102: __LOCAL__ __INLINE__
103: void __repinsw (int _port, __ushort_t * _addr, int _cnt) {
104: __NON_ISO (asm) volatile ("mov %1,%%edi;rep;insw" : :
105: "d" ((__ushort_t) _port), "g" (_addr),
106: "c" (_cnt) : "di");
107: }
108:
109: __LOCAL__ __INLINE__
110: void __repoutsb (int _port, __uchar_t * _addr, int _cnt) {
111: __NON_ISO (asm) volatile ("mov %1,%%esi;rep;outsb" : :
112: "d" ((__ushort_t) _port), "g" (_addr),
113: "c" (_cnt) : "si");
114: }
115:
116: __LOCAL__ __INLINE__
117: void __repoutsd (int _port, __ulong_t * _addr, int _cnt) {
118: __NON_ISO (asm) volatile ("movl %1,%%esi;rep;outsl" : :
119: "d" ((__ushort_t) _port), "g" (_addr),
120: "c" (_cnt) : "si");
121: }
122:
123: __LOCAL__ __INLINE__
124: void __repoutsw (int _port, __ushort_t * _addr, int _cnt) {
125: __NON_ISO (asm) volatile ("movl %1,%%esi;rep;outsw" : :
126: "d" ((__ushort_t) _port), "g" (_addr),
127: "c" (_cnt) : "si");
128: }
129:
130: #define __FORWARD_inb__
131: #define __FORWARD_inl__
132: #define __FORWARD_inw__
133: #define __FORWARD_outb__
134: #define __FORWARD_outl__
135: #define __FORWARD_outw__
136: #define __FORWARD_repinsb__
137: #define __FORWARD_repinsd__
138: #define __FORWARD_repinsw__
139: #define __FORWARD_repoutsb__
140: #define __FORWARD_repoutsd__
141: #define __FORWARD_repoutsw__
142:
143: #elif __BORLANDC__
144:
145: void __emit__ (unsigned char __byte, ...);
146:
147: /*
148: * Note the use of the 0x66 operand-size override prefix below, which is built
149: * on the assumption that Borland generates 16-bit code segments.
150: */
151:
152: #define __REP__ 0xF3 /* repeat-prefix */
153:
154: #define __INB__ 0xEC
155: #define __INW__ 0xED
156: #define __INL__ 0x66, __INW__ /* size-override for 32-bit form */
157:
158: #define __OUTB__ 0xEE
159: #define __OUTW__ 0xEF
160: #define __OUTL__ 0x66, __OUTW__ /* size-override for 32-bit form */
161:
162: #define __INSB__ 0x6C
163: #define __INSW__ 0x6D
164: #define __INSL__ 0x65, __INSW__
165:
166: #define __OUTSB__ 0x6E
167: #define __OUTSW__ 0x6F /* word/long depending on CS: */
168: #define __OUTSL__ 0x66, __OUTSW__
169:
170:
171: /*
172: * If we are willing to restrict ourselves to i386's, Borland C++ 3.1 allows
173: * support for 32-bit register-pseudovariables if 386 code generation has
174: * been enabled.
175: *
176: * As it turns out, there are all kinds of bugs in the 386 support in BC++ 3.1
177: * but enough works that we can even get a far pointer into ES:whatever via
178: * a 32-bit register, as long as the intermediate register isn't _ESI or _EDI
179: * since _EAX = _ESI or _EAX = _EDI only moves the low 16 bits. Being able to
180: * load ES:whatever via a 32-bit register allows us to write macros that only
181: * reference each argument exactly once.
182: *
183: * While the 32-bit-pointer version still works in the near models, it's not
184: * exactly optimal, so we use a more straightforward version there.
185: */
186:
187: #define __inb(port) (_DX = (port), __emit__ (__INB__),\
188: (__uchar_t) _AL)
189: #define __inl(port) (_DX = (port), __emit__ (__INL__), _EAX)
190: #define __inw(port) (_DX = (port), __emit__ (__INW__), \
191: (__ushort_t) _AX)
192:
193: #define __outb(port,value) (_DX = (port), _AL = (value), \
194: __emit__ (__OUTB__))
195: #define __outl(port,value) (_DX = (port), _EAX = (value), \
196: __emit__ (__OUTL__))
197: #define __outw(port,value) (_DX = (port), _AX = (value), \
198: __emit__ (__OUTW__))
199:
200: #if defined (__LARGE__) || defined (__HUGE__) || defined (__COMPACT__)
201:
202: #define __repins(p,a,c) (_EDX = (long) (void __far *) (a), _EAX = _EDX,\
203: _ES = (unsigned) (_EAX >> 16),\
204: _DI = _DX, _CX = (c), _DX = (p))
205: #define __repouts(p,a,c) (_EDX = (long) (void _far *) (a), _EAX = _EDX,\
206: _ES = (unsigned) (_EAX >> 16),\
207: _SI = _DX, _CX = (c), _DX = (p))
208:
209: #else /* use simpler small-data versions */
210:
211: #define __repins(p,a,c) (_ES = _DS, _DI = (unsigned) (a), \
212: _CX = (c), _DX = (p))
213: #define __repouts(p,a,c) (_ES = _DS, _SI = (unsigned) (a), \
214: _CX = (c), _DX = (p))
215:
216: #endif
217:
218: #define __repinsb(p,a,c) (__repins (p, a, c),\
219: __emit__ (__REP__, __INSB__))
220: #define __repinsd(p,a,c) (__repins (p, a, c),\
221: __emit__ (__REP__, __INSL__))
222: #define __repinsw(p,a,c) (__repins (p, a, c),\
223: __emit__ (__REP__, __INSW__))
224:
225: #define __repoutsb(p,a,c) (__repouts (p, a, c),\
226: __emit__ (__REP__, __OUTSB__))
227: #define __repoutsd(p,a,c) (__repouts (p, a, c),\
228: __emit__ (__REP__, __OUTSL__))
229: #define __repoutsw(p,a,c) (__repouts (p, a, c),\
230: __emit__ (__REP__, __OUTSW__))
231:
232:
233: #define __FORWARD_inb__
234: #define __FORWARD_inl__
235: #define __FORWARD_inw__
236: #define __FORWARD_outb__
237: #define __FORWARD_outl__
238: #define __FORWARD_outw__
239: #define __FORWARD_repinsb__
240: #define __FORWARD_repinsd__
241: #define __FORWARD_repinsw__
242: #define __FORWARD_repoutsb__
243: #define __FORWARD_repoutsd__
244: #define __FORWARD_repoutsw__
245:
246: #elif __COHERENT__
247:
248: /*
249: * Under Coherent, the inb ()/inw ()/inl () and outb ()/outw ()/outl ()
250: * operations are already available under those names in the standard system.
251: *
252: * The rep... () operations are provided in a supplemental file that should be
253: * linked in if you are building a DDI/DKI kernel.
254: */
255:
256: #endif
257:
258:
259: __EXTERN_C_BEGIN__
260:
261: __uchar_t inb __PROTO ((int _port));
262: __ulong_t inl __PROTO ((int _port));
263: __ushort_t inw __PROTO ((int _port));
264: void outb __PROTO ((int _port, __uchar_t _value));
265: void outl __PROTO ((int _port, __ulong_t _value));
266: void outw __PROTO ((int _port, __ushort_t _value));
267: void repinsb __PROTO ((int _port, __uchar_t * _addr,
268: int _cnt));
269: void repinsd __PROTO ((int _port, __ulong_t * _addr,
270: int _cnt));
271: void repinsw __PROTO ((int _port, __ushort_t * _addr,
272: int _cnt));
273: void repoutsb __PROTO ((int _port, __uchar_t * _addr,
274: int _cnt));
275: void repoutsd __PROTO ((int _port, __ulong_t * _addr,
276: int _cnt));
277: void repoutsw __PROTO ((int _port, __ushort_t * _addr,
278: int _cnt));
279:
280: __EXTERN_C_END__
281:
282:
283: #ifdef __FORWARD_inb__
284: # define inb(port) __inb (port)
285: #endif
286:
287: #ifdef __FORWARD_inl__
288: # define inl(port) __inl (port)
289: #endif
290:
291: #ifdef __FORWARD_inw__
292: # define inw(port) __inw (port)
293: #endif
294:
295: #ifdef __FORWARD_outb__
296: # define outb(port,val) __outb (port, val)
297: #endif
298:
299: #ifdef __FORWARD_outl__
300: # define outl(port,val) __outl (port, val)
301: #endif
302:
303: #ifdef __FORWARD_outw__
304: # define outw(port,val) __outw (port, val)
305: #endif
306:
307: #ifdef __FORWARD_repinsb__
308: # define repinsb(p,a,c) __repinsb (p, a, c)
309: #endif
310:
311: #ifdef __FORWARD_repinsd__
312: # define repinsd(p,a,c) __repinsd (p, a, c)
313: #endif
314:
315: #ifdef __FORWARD_repinsw__
316: # define repinsw(p,a,c) __repinsw (p, a, c)
317: #endif
318:
319: #ifdef __FORWARD_repoutsb__
320: # define repoutsb(p,a,c) __repoutsb (p, a, c)
321: #endif
322:
323: #ifdef __FORWARD_repoutsd__
324: # define repoutsd(p,a,c) __repoutsd (p, a, c)
325: #endif
326:
327: #ifdef __FORWARD_repoutsw__
328: # define repoutsw(p,a,c) __repoutsw (p, a, c)
329: #endif
330:
331:
332: #undef __FORWARD_inb__
333: #undef __FORWARD_inl__
334: #undef __FORWARD_inw__
335: #undef __FORWARD_outb__
336: #undef __FORWARD_outl__
337: #undef __FORWARD_outw__
338: #undef __FORWARD_repinsb__
339: #undef __FORWARD_repinsd__
340: #undef __FORWARD_repinsw__
341: #undef __FORWARD_repoutsb__
342: #undef __FORWARD_repoutsd__
343: #undef __FORWARD_repoutsw__
344:
345: #endif /* ! defined (__KERNEL_X86IO_H__) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.