Added freeldr and hal from PPC branch, along with needed headers and
[reactos.git] / reactos / hal / halppc / generic / portio.c
1 /* $Id: portio.c 23907 2006-09-04 05:52:23Z arty $
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 <hal.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS ****************************************************************/
17
18 /*
19 * This file contains the definitions for the x86 IO instructions
20 * inb/inw/inl/outb/outw/outl and the "string versions" of the same
21 * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
22 * versions of the single-IO instructions (inb_p/inw_p/..).
23 *
24 * This file is not meant to be obfuscating: it's just complicated
25 * to (a) handle it all in a way that makes gcc able to optimize it
26 * as well as possible and (b) trying to avoid writing the same thing
27 * over and over again with slight variations and possibly making a
28 * mistake somewhere.
29 */
30
31 /*
32 * Thanks to James van Artsdalen for a better timing-fix than
33 * the two short jumps: using outb's to a nonexistent port seems
34 * to guarantee better timings even on fast machines.
35 *
36 * On the other hand, I'd like to be sure of a non-existent port:
37 * I feel a bit unsafe about using 0x80 (should be safe, though)
38 *
39 * Linus
40 */
41
42 #if defined(__GNUC__)
43
44 #ifdef SLOW_IO_BY_JUMPING
45 #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
46 #else
47 #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
48 #endif
49
50 #elif defined(_MSC_VER)
51
52 #ifdef SLOW_IO_BY_JUMPING
53 #define __SLOW_DOWN_IO __asm jmp 1f __asm jmp 1f 1f:
54 #else
55 #define __SLOW_DOWN_IO __asm out 0x80, al
56 #endif
57
58 #else
59 #error Unknown compiler for inline assembler
60 #endif
61
62
63 #ifdef REALLY_SLOW_IO
64 #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
65 #else
66 #define SLOW_DOWN_IO __SLOW_DOWN_IO
67 #endif
68
69 extern int GetPhysByte(int Addr);
70 extern void SetPhysByte(int Addr, int Val);
71 extern int GetPhysWord(int Addr);
72 extern void SetPhysWord(int Addr, int Val);
73 extern int GetPhys(int Addr);
74 extern void SetPhys(int Addr, int Val);
75
76 __asm__("\t.globl GetPhys\n"
77 "GetPhys:\t\n"
78 "mflr 0\n\t"
79 "stwu 0,-16(1)\n\t"
80 "mfmsr 5\n\t"
81 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
82 "mtmsr 6\n\t"
83 "isync\n\t"
84 "sync\n\t"
85 "lwz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
86 "mtmsr 5\n\t"
87 "isync\n\t"
88 "sync\n\t"
89 "lwz 0,0(1)\n\t"
90 "addi 1,1,16\n\t"
91 "mtlr 0\n\t"
92 "blr"
93 );
94
95 __asm__("\t.globl GetPhysWord\n"
96 "GetPhysWord:\t\n"
97 "mflr 0\n\t"
98 "stwu 0,-16(1)\n\t"
99 "mfmsr 5\n\t"
100 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
101 "mtmsr 6\n\t"
102 "isync\n\t"
103 "sync\n\t"
104 "lhz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
105 "mtmsr 5\n\t"
106 "isync\n\t"
107 "sync\n\t"
108 "lwz 0,0(1)\n\t"
109 "addi 1,1,16\n\t"
110 "mtlr 0\n\t"
111 "blr"
112 );
113
114 __asm__("\t.globl GetPhysByte\n"
115 "GetPhysByte:\t\n"
116 "mflr 0\n\t"
117 "stwu 0,-16(1)\n\t"
118 "mfmsr 5\n\t"
119 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
120 "mtmsr 6\n\t"
121 "isync\n\t"
122 "sync\n\t"
123 "lbz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
124 "mtmsr 5\n\t"
125 "isync\n\t"
126 "sync\n\t"
127 "lwz 0,0(1)\n\t"
128 "addi 1,1,16\n\t"
129 "mtlr 0\n\t"
130 "blr"
131 );
132
133 __asm__("\t.globl SetPhys\n"
134 "SetPhys:\t\n"
135 "mflr 0\n\t"
136 "stwu 0,-16(1)\n\t"
137 "mfmsr 5\n\t"
138 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
139 "mtmsr 6\n\t"
140 "sync\n\t"
141 "eieio\n\t"
142 "stw 4,0(3)\n\t" /* Set actual value at phys addr r3 */
143 "dcbst 0,3\n\t"
144 "mtmsr 5\n\t"
145 "sync\n\t"
146 "eieio\n\t"
147 "mr 3,4\n\t"
148 "lwz 0,0(1)\n\t"
149 "addi 1,1,16\n\t"
150 "mtlr 0\n\t"
151 "blr"
152 );
153
154 __asm__("\t.globl SetPhysWord\n"
155 "SetPhysWord:\t\n"
156 "mflr 0\n\t"
157 "stwu 0,-16(1)\n\t"
158 "mfmsr 5\n\t"
159 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
160 "mtmsr 6\n\t"
161 "sync\n\t"
162 "eieio\n\t"
163 "sth 4,0(3)\n\t" /* Set actual value at phys addr r3 */
164 "dcbst 0,3\n\t"
165 "mtmsr 5\n\t"
166 "sync\n\t"
167 "eieio\n\t"
168 "mr 3,4\n\t"
169 "lwz 0,0(1)\n\t"
170 "addi 1,1,16\n\t"
171 "mtlr 0\n\t"
172 "blr"
173 );
174
175 __asm__("\t.globl SetPhysByte\n"
176 "SetPhysByte:\t\n"
177 "mflr 0\n\t"
178 "stwu 0,-16(1)\n\t"
179 "mfmsr 5\n\t"
180 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
181 "mtmsr 6\n\t"
182 "sync\n\t"
183 "eieio\n\t"
184 "stb 4,0(3)\n\t" /* Set actual value at phys addr r3 */
185 "dcbst 0,3\n\t"
186 "mtmsr 5\n\t"
187 "sync\n\t"
188 "eieio\n\t"
189 "mr 3,4\n\t"
190 "lwz 0,0(1)\n\t"
191 "addi 1,1,16\n\t"
192 "mtlr 0\n\t"
193 "blr"
194 );
195
196 VOID STDCALL
197 READ_PORT_BUFFER_UCHAR (PUCHAR Port,
198 PUCHAR Buffer,
199 ULONG Count)
200 {
201 while(Count--) { *Buffer++ = GetPhysByte((ULONG)Port); }
202 }
203
204 VOID STDCALL
205 READ_PORT_BUFFER_USHORT (PUSHORT Port,
206 PUSHORT Buffer,
207 ULONG Count)
208 {
209 while(Count--) { *Buffer++ = GetPhysWord((ULONG)Port); }
210 }
211
212 VOID STDCALL
213 READ_PORT_BUFFER_ULONG (PULONG Port,
214 PULONG Buffer,
215 ULONG Count)
216 {
217 while(Count--) { *Buffer++ = GetPhys((ULONG)Port); }
218 }
219
220 UCHAR STDCALL
221 READ_PORT_UCHAR (PUCHAR Port)
222 {
223 return GetPhys((ULONG)Port);
224 }
225
226 USHORT STDCALL
227 READ_PORT_USHORT (PUSHORT Port)
228 {
229 return GetPhysWord((ULONG)Port);
230 }
231
232 ULONG STDCALL
233 READ_PORT_ULONG (PULONG Port)
234 {
235 return GetPhys((ULONG)Port);
236 }
237
238 VOID STDCALL
239 WRITE_PORT_BUFFER_UCHAR (PUCHAR Port,
240 PUCHAR Buffer,
241 ULONG Count)
242 {
243 while(Count--) { SetPhysByte((ULONG)Port, *Buffer++); }
244 }
245
246 VOID STDCALL
247 WRITE_PORT_BUFFER_USHORT (PUSHORT Port,
248 PUSHORT Buffer,
249 ULONG Count)
250 {
251 while(Count--) { SetPhysWord((ULONG)Port, *Buffer++); }
252 }
253
254 VOID STDCALL
255 WRITE_PORT_BUFFER_ULONG (PULONG Port,
256 PULONG Buffer,
257 ULONG Count)
258 {
259 while(Count--) { SetPhys((ULONG)Port, *Buffer++); }
260 }
261
262 VOID STDCALL
263 WRITE_PORT_UCHAR (PUCHAR Port,
264 UCHAR Value)
265 {
266 SetPhysByte((ULONG)Port, Value);
267 }
268
269 VOID STDCALL
270 WRITE_PORT_USHORT (PUSHORT Port,
271 USHORT Value)
272 {
273 SetPhysWord((ULONG)Port, Value);
274 }
275
276 VOID STDCALL
277 WRITE_PORT_ULONG (PULONG Port,
278 ULONG Value)
279 {
280 SetPhys((ULONG)Port, Value);
281 }
282
283 /* EOF */