migrate substitution keywords to SVN
[reactos.git] / reactos / hal / halx86 / generic / portio.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/hal/x86/portio.c
6 * PURPOSE: Port I/O functions
7 * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
8 * UPDATE HISTORY:
9 * Created 18/10/99
10 */
11
12 #include <ddk/ntddk.h>
13
14
15 /* FUNCTIONS ****************************************************************/
16
17 /*
18 * This file contains the definitions for the x86 IO instructions
19 * inb/inw/inl/outb/outw/outl and the "string versions" of the same
20 * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
21 * versions of the single-IO instructions (inb_p/inw_p/..).
22 *
23 * This file is not meant to be obfuscating: it's just complicated
24 * to (a) handle it all in a way that makes gcc able to optimize it
25 * as well as possible and (b) trying to avoid writing the same thing
26 * over and over again with slight variations and possibly making a
27 * mistake somewhere.
28 */
29
30 /*
31 * Thanks to James van Artsdalen for a better timing-fix than
32 * the two short jumps: using outb's to a nonexistent port seems
33 * to guarantee better timings even on fast machines.
34 *
35 * On the other hand, I'd like to be sure of a non-existent port:
36 * I feel a bit unsafe about using 0x80 (should be safe, though)
37 *
38 * Linus
39 */
40
41 #if defined(__GNUC__)
42
43 #ifdef SLOW_IO_BY_JUMPING
44 #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
45 #else
46 #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
47 #endif
48
49 #elif defined(_MSC_VER)
50
51 #ifdef SLOW_IO_BY_JUMPING
52 #define __SLOW_DOWN_IO __asm jmp 1f __asm jmp 1f 1f:
53 #else
54 #define __SLOW_DOWN_IO __asm out 0x80, al
55 #endif
56
57 #else
58 #error Unknown compiler for inline assembler
59 #endif
60
61
62 #ifdef REALLY_SLOW_IO
63 #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
64 #else
65 #define SLOW_DOWN_IO __SLOW_DOWN_IO
66 #endif
67
68 VOID STDCALL
69 READ_PORT_BUFFER_UCHAR (PUCHAR Port,
70 PUCHAR Buffer,
71 ULONG Count)
72 {
73 #if defined(__GNUC__)
74 __asm__ __volatile__ ("cld ; rep ; insb\n\t"
75 : "=D" (Buffer), "=c" (Count)
76 : "d" (Port),"0" (Buffer),"1" (Count));
77 #elif defined(_MSC_VER)
78 __asm
79 {
80 mov edx, Port
81 mov edi, Buffer
82 mov ecx, Count
83 cld
84 rep ins byte ptr[edi], dx
85 }
86 #else
87 #error Unknown compiler for inline assembler
88 #endif
89 }
90
91 VOID STDCALL
92 READ_PORT_BUFFER_USHORT (PUSHORT Port,
93 PUSHORT Buffer,
94 ULONG Count)
95 {
96 #if defined(__GNUC__)
97 __asm__ __volatile__ ("cld ; rep ; insw"
98 : "=D" (Buffer), "=c" (Count)
99 : "d" (Port),"0" (Buffer),"1" (Count));
100 #elif defined(_MSC_VER)
101 __asm
102 {
103 mov edx, Port
104 mov edi, Buffer
105 mov ecx, Count
106 cld
107 rep ins word ptr[edi], dx
108 }
109 #else
110 #error Unknown compiler for inline assembler
111 #endif
112 }
113
114 VOID STDCALL
115 READ_PORT_BUFFER_ULONG (PULONG Port,
116 PULONG Buffer,
117 ULONG Count)
118 {
119 #if defined(__GNUC__)
120 __asm__ __volatile__ ("cld ; rep ; insl"
121 : "=D" (Buffer), "=c" (Count)
122 : "d" (Port),"0" (Buffer),"1" (Count));
123 #elif defined(_MSC_VER)
124 __asm
125 {
126 mov edx, Port
127 mov edi, Buffer
128 mov ecx, Count
129 cld
130 rep ins dword ptr[edi], dx
131 }
132 #else
133 #error Unknown compiler for inline assembler
134 #endif
135 }
136
137 UCHAR STDCALL
138 READ_PORT_UCHAR (PUCHAR Port)
139 {
140 UCHAR Value;
141
142 #if defined(__GNUC__)
143 __asm__("inb %w1, %0\n\t"
144 : "=a" (Value)
145 : "d" (Port));
146 #elif defined(_MSC_VER)
147 __asm
148 {
149 mov edx, Port
150 in al, dx
151 mov Value, al
152 }
153 #else
154 #error Unknown compiler for inline assembler
155 #endif
156
157 SLOW_DOWN_IO;
158 return(Value);
159 }
160
161 USHORT STDCALL
162 READ_PORT_USHORT (PUSHORT Port)
163 {
164 USHORT Value;
165
166 #if defined(__GNUC__)
167 __asm__("inw %w1, %0\n\t"
168 : "=a" (Value)
169 : "d" (Port));
170 #elif defined(_MSC_VER)
171 __asm
172 {
173 mov edx, Port
174 in ax, dx
175 mov Value, ax
176 }
177 #else
178 #error Unknown compiler for inline assembler
179 #endif
180 SLOW_DOWN_IO;
181 return(Value);
182 }
183
184 ULONG STDCALL
185 READ_PORT_ULONG (PULONG Port)
186 {
187 ULONG Value;
188
189 #if defined(__GNUC__)
190 __asm__("inl %w1, %0\n\t"
191 : "=a" (Value)
192 : "d" (Port));
193 #elif defined(_MSC_VER)
194 __asm
195 {
196 mov edx, Port
197 in eax, dx
198 mov Value, eax
199 }
200 #else
201 #error Unknown compiler for inline assembler
202 #endif
203 SLOW_DOWN_IO;
204 return(Value);
205 }
206
207 VOID STDCALL
208 WRITE_PORT_BUFFER_UCHAR (PUCHAR Port,
209 PUCHAR Buffer,
210 ULONG Count)
211 {
212 #if defined(__GNUC__)
213 __asm__ __volatile__ ("cld ; rep ; outsb"
214 : "=S" (Buffer), "=c" (Count)
215 : "d" (Port),"0" (Buffer),"1" (Count));
216 #elif defined(_MSC_VER)
217 __asm
218 {
219 mov edx, Port
220 mov esi, Buffer
221 mov ecx, Count
222 cld
223 rep outs
224 }
225 #else
226 #error Unknown compiler for inline assembler
227 #endif
228 }
229
230 VOID STDCALL
231 WRITE_PORT_BUFFER_USHORT (PUSHORT Port,
232 PUSHORT Buffer,
233 ULONG Count)
234 {
235 #if defined(__GNUC__)
236 __asm__ __volatile__ ("cld ; rep ; outsw"
237 : "=S" (Buffer), "=c" (Count)
238 : "d" (Port),"0" (Buffer),"1" (Count));
239 #elif defined(_MSC_VER)
240 __asm
241 {
242 mov edx, Port
243 mov esi, Buffer
244 mov ecx, Count
245 cld
246 rep outsw
247 }
248 #else
249 #error Unknown compiler for inline assembler
250 #endif
251 }
252
253 VOID STDCALL
254 WRITE_PORT_BUFFER_ULONG (PULONG Port,
255 PULONG Buffer,
256 ULONG Count)
257 {
258 #if defined(__GNUC__)
259 __asm__ __volatile__ ("cld ; rep ; outsl"
260 : "=S" (Buffer), "=c" (Count)
261 : "d" (Port),"0" (Buffer),"1" (Count));
262 #elif defined(_MSC_VER)
263 __asm
264 {
265 mov edx, Port
266 mov esi, Buffer
267 mov ecx, Count
268 cld
269 rep outsd
270 }
271 #else
272 #error Unknown compiler for inline assembler
273 #endif
274 }
275
276 VOID STDCALL
277 WRITE_PORT_UCHAR (PUCHAR Port,
278 UCHAR Value)
279 {
280 #if defined(__GNUC__)
281 __asm__("outb %0, %w1\n\t"
282 :
283 : "a" (Value),
284 "d" (Port));
285 #elif defined(_MSC_VER)
286 __asm
287 {
288 mov edx, Port
289 mov al, Value
290 out dx,al
291 }
292 #else
293 #error Unknown compiler for inline assembler
294 #endif
295 SLOW_DOWN_IO;
296 }
297
298 VOID STDCALL
299 WRITE_PORT_USHORT (PUSHORT Port,
300 USHORT Value)
301 {
302 #if defined(__GNUC__)
303 __asm__("outw %0, %w1\n\t"
304 :
305 : "a" (Value),
306 "d" (Port));
307 #elif defined(_MSC_VER)
308 __asm
309 {
310 mov edx, Port
311 mov ax, Value
312 out dx,ax
313 }
314 #else
315 #error Unknown compiler for inline assembler
316 #endif
317 SLOW_DOWN_IO;
318 }
319
320 VOID STDCALL
321 WRITE_PORT_ULONG (PULONG Port,
322 ULONG Value)
323 {
324 #if defined(__GNUC__)
325 __asm__("outl %0, %w1\n\t"
326 :
327 : "a" (Value),
328 "d" (Port));
329 #elif defined(_MSC_VER)
330 __asm
331 {
332 mov edx, Port
333 mov eax, Value
334 out dx,eax
335 }
336 #else
337 #error Unknown compiler for inline assembler
338 #endif
339 SLOW_DOWN_IO;
340 }
341
342 /* EOF */