:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / hal / halx86 / 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 #ifdef SLOW_IO_BY_JUMPING
42 #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
43 #else
44 #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
45 #endif
46
47 #ifdef REALLY_SLOW_IO
48 #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
49 #else
50 #define SLOW_DOWN_IO __SLOW_DOWN_IO
51 #endif
52
53 VOID STDCALL
54 READ_PORT_BUFFER_UCHAR (PUCHAR Port,
55                         PUCHAR Buffer,
56                         ULONG Count)
57 {
58    __asm__ __volatile__ ("cld ; rep ; insb\n\t" 
59                          : "=D" (Buffer), "=c" (Count) 
60                          : "d" (Port),"0" (Buffer),"1" (Count));
61 }
62
63 VOID STDCALL
64 READ_PORT_BUFFER_USHORT (PUSHORT Port,
65                          PUSHORT Buffer,
66                          ULONG Count)
67 {
68    __asm__ __volatile__ ("cld ; rep ; insw"
69                          : "=D" (Buffer), "=c" (Count) 
70                          : "d" (Port),"0" (Buffer),"1" (Count));
71 }
72
73 VOID STDCALL
74 READ_PORT_BUFFER_ULONG (PULONG Port,
75                         PULONG Buffer,
76                         ULONG Count)
77 {
78    __asm__ __volatile__ ("cld ; rep ; insl"
79                          : "=D" (Buffer), "=c" (Count) 
80                          : "d" (Port),"0" (Buffer),"1" (Count));
81 }
82
83 UCHAR STDCALL
84 READ_PORT_UCHAR (PUCHAR Port)
85 {
86    UCHAR Value;
87    
88    __asm__("inb %w1, %0\n\t"
89            : "=a" (Value)
90            : "d" (Port));
91    SLOW_DOWN_IO;
92    return(Value);
93 }
94
95 USHORT STDCALL
96 READ_PORT_USHORT (PUSHORT Port)
97 {
98    USHORT Value;
99    
100    __asm__("inw %w1, %0\n\t"
101            : "=a" (Value)
102            : "d" (Port));
103    SLOW_DOWN_IO;
104    return(Value);
105 }
106
107 ULONG STDCALL
108 READ_PORT_ULONG (PULONG Port)
109 {
110    ULONG Value;
111    
112    __asm__("inl %w1, %0\n\t"
113            : "=a" (Value)
114            : "d" (Port));
115    SLOW_DOWN_IO;
116    return(Value);
117 }
118
119 VOID STDCALL
120 WRITE_PORT_BUFFER_UCHAR (PUCHAR Port,
121                          PUCHAR Buffer,
122                          ULONG Count)
123 {
124    __asm__ __volatile__ ("cld ; rep ; outsb" 
125                          : "=S" (Buffer), "=c" (Count) 
126                          : "d" (Port),"0" (Buffer),"1" (Count));
127 }
128
129 VOID STDCALL
130 WRITE_PORT_BUFFER_USHORT (PUSHORT Port,
131                           PUSHORT Buffer,
132                           ULONG Count)
133 {
134    __asm__ __volatile__ ("cld ; rep ; outsw"
135                          : "=S" (Buffer), "=c" (Count) 
136                          : "d" (Port),"0" (Buffer),"1" (Count));
137 }
138
139 VOID STDCALL
140 WRITE_PORT_BUFFER_ULONG (PULONG Port,
141                          PULONG Buffer,
142                          ULONG Count)
143 {
144    __asm__ __volatile__ ("cld ; rep ; outsl" 
145                          : "=S" (Buffer), "=c" (Count) 
146                          : "d" (Port),"0" (Buffer),"1" (Count));
147 }
148
149 VOID STDCALL
150 WRITE_PORT_UCHAR (PUCHAR Port,
151                   UCHAR Value)
152 {
153    __asm__("outb %0, %w1\n\t"
154            : 
155            : "a" (Value),
156              "d" (Port));
157    SLOW_DOWN_IO;
158 }
159
160 VOID STDCALL
161 WRITE_PORT_USHORT (PUSHORT Port,
162                    USHORT Value)
163 {
164    __asm__("outw %0, %w1\n\t"
165            : 
166            : "a" (Value),
167              "d" (Port));
168    SLOW_DOWN_IO;
169 }
170
171 VOID STDCALL
172 WRITE_PORT_ULONG (PULONG Port,
173                   ULONG Value)
174 {
175    __asm__("outl %0, %w1\n\t"
176            : 
177            : "a" (Value),
178              "d" (Port));
179    SLOW_DOWN_IO;
180 }
181
182 /* EOF */