4b61bfc05c9599e98907ed5cf2e531f5f8ae4098
1 /* $Id: portio.c 23907 2006-09-04 05:52:23Z arty $
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)
16 /* FUNCTIONS ****************************************************************/
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/..).
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
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.
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)
44 #ifdef SLOW_IO_BY_JUMPING
45 #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
47 #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
50 #elif defined(_MSC_VER)
52 #ifdef SLOW_IO_BY_JUMPING
53 #define __SLOW_DOWN_IO __asm jmp 1f __asm jmp 1f 1f:
55 #define __SLOW_DOWN_IO __asm out 0x80, al
59 #error Unknown compiler for inline assembler
64 #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
66 #define SLOW_DOWN_IO __SLOW_DOWN_IO
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
);
76 __asm__("\t.globl GetPhys\n"
81 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
85 "lwz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
95 __asm__("\t.globl GetPhysWord\n"
100 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
104 "lhz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
114 __asm__("\t.globl GetPhysByte\n"
119 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
123 "lbz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
133 __asm__("\t.globl SetPhys\n"
138 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
142 "stw 4,0(3)\n\t" /* Set actual value at phys addr r3 */
154 __asm__("\t.globl SetPhysWord\n"
159 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
163 "sth 4,0(3)\n\t" /* Set actual value at phys addr r3 */
175 __asm__("\t.globl SetPhysByte\n"
180 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
184 "stb 4,0(3)\n\t" /* Set actual value at phys addr r3 */
197 READ_PORT_BUFFER_UCHAR (PUCHAR Port
,
201 while(Count
--) { *Buffer
++ = GetPhysByte((ULONG
)Port
); }
205 READ_PORT_BUFFER_USHORT (PUSHORT Port
,
209 while(Count
--) { *Buffer
++ = GetPhysWord((ULONG
)Port
); }
213 READ_PORT_BUFFER_ULONG (PULONG Port
,
217 while(Count
--) { *Buffer
++ = GetPhys((ULONG
)Port
); }
221 READ_PORT_UCHAR (PUCHAR Port
)
223 return GetPhys((ULONG
)Port
);
227 READ_PORT_USHORT (PUSHORT Port
)
229 return GetPhysWord((ULONG
)Port
);
233 READ_PORT_ULONG (PULONG Port
)
235 return GetPhys((ULONG
)Port
);
239 WRITE_PORT_BUFFER_UCHAR (PUCHAR Port
,
243 while(Count
--) { SetPhysByte((ULONG
)Port
, *Buffer
++); }
247 WRITE_PORT_BUFFER_USHORT (PUSHORT Port
,
251 while(Count
--) { SetPhysWord((ULONG
)Port
, *Buffer
++); }
255 WRITE_PORT_BUFFER_ULONG (PULONG Port
,
259 while(Count
--) { SetPhys((ULONG
)Port
, *Buffer
++); }
263 WRITE_PORT_UCHAR (PUCHAR Port
,
266 SetPhysByte((ULONG
)Port
, Value
);
270 WRITE_PORT_USHORT (PUSHORT Port
,
273 SetPhysWord((ULONG
)Port
, Value
);
277 WRITE_PORT_ULONG (PULONG Port
,
280 SetPhys((ULONG
)Port
, Value
);