2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: hal/halppc/generic/portio.c
5 * PURPOSE: Port I/O functions
6 * PROGRAMMER: Eric Kohl
15 /* FUNCTIONS ****************************************************************/
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/..).
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
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.
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)
43 #ifdef SLOW_IO_BY_JUMPING
44 #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
46 #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
49 #elif defined(_MSC_VER)
51 #ifdef SLOW_IO_BY_JUMPING
52 #define __SLOW_DOWN_IO __asm jmp 1f __asm jmp 1f 1f:
54 #define __SLOW_DOWN_IO __asm out 0x80, al
58 #error Unknown compiler for inline assembler
63 #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
65 #define SLOW_DOWN_IO __SLOW_DOWN_IO
68 extern int GetPhysByte(int Addr
);
69 extern void SetPhysByte(int Addr
, int Val
);
70 extern int GetPhysWord(int Addr
);
71 extern void SetPhysWord(int Addr
, int Val
);
72 extern int GetPhys(int Addr
);
73 extern void SetPhys(int Addr
, int Val
);
75 __asm__("\t.globl GetPhys\n"
80 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
84 "lwz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
94 __asm__("\t.globl GetPhysWord\n"
99 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
103 "lhz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
113 __asm__("\t.globl GetPhysByte\n"
118 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
122 "lbz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
132 __asm__("\t.globl SetPhys\n"
137 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
141 "stw 4,0(3)\n\t" /* Set actual value at phys addr r3 */
153 __asm__("\t.globl SetPhysWord\n"
158 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
162 "sth 4,0(3)\n\t" /* Set actual value at phys addr r3 */
174 __asm__("\t.globl SetPhysByte\n"
179 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
183 "stb 4,0(3)\n\t" /* Set actual value at phys addr r3 */
196 READ_PORT_BUFFER_UCHAR (PUCHAR Port
,
200 while(Count
--) { *Buffer
++ = GetPhysByte((ULONG
)Port
); }
204 READ_PORT_BUFFER_USHORT (PUSHORT Port
,
208 while(Count
--) { *Buffer
++ = GetPhysWord((ULONG
)Port
); }
212 READ_PORT_BUFFER_ULONG (PULONG Port
,
216 while(Count
--) { *Buffer
++ = GetPhys((ULONG
)Port
); }
220 READ_PORT_UCHAR (PUCHAR Port
)
222 return GetPhys((ULONG
)Port
);
226 READ_PORT_USHORT (PUSHORT Port
)
228 return GetPhysWord((ULONG
)Port
);
232 READ_PORT_ULONG (PULONG Port
)
234 return GetPhys((ULONG
)Port
);
238 WRITE_PORT_BUFFER_UCHAR (PUCHAR Port
,
242 while(Count
--) { SetPhysByte((ULONG
)Port
, *Buffer
++); }
246 WRITE_PORT_BUFFER_USHORT (PUSHORT Port
,
250 while(Count
--) { SetPhysWord((ULONG
)Port
, *Buffer
++); }
254 WRITE_PORT_BUFFER_ULONG (PULONG Port
,
258 while(Count
--) { SetPhys((ULONG
)Port
, *Buffer
++); }
262 WRITE_PORT_UCHAR (PUCHAR Port
,
265 SetPhysByte((ULONG
)Port
, Value
);
269 WRITE_PORT_USHORT (PUSHORT Port
,
272 SetPhysWord((ULONG
)Port
, Value
);
276 WRITE_PORT_ULONG (PULONG Port
,
279 SetPhys((ULONG
)Port
, Value
);