2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id: io.h 13216 2002-02-13 06:22:32Z iaint $
10 * This file contains the definitions for the x86 IO instructions
11 * inb/inw/inl/outb/outw/outl and the "string versions" of the same
12 * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
13 * versions of the single-IO instructions (inb_p/inw_p/..).
15 * This file is not meant to be obfuscating: it's just complicated
16 * to (a) handle it all in a way that makes gcc able to optimize it
17 * as well as possible and (b) trying to avoid writing the same thing
18 * over and over again with slight variations and possibly making a
23 * Thanks to James van Artsdalen for a better timing-fix than
24 * the two short jumps: using outb's to a nonexistent port seems
25 * to guarantee better timings even on fast machines.
27 * On the other hand, I'd like to be sure of a non-existent port:
28 * I feel a bit unsafe about using 0x80 (should be safe, though)
34 * Bit simplified and optimized by Jan Hubicka
37 #ifdef SLOW_IO_BY_JUMPING
38 #define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
40 #define __SLOW_DOWN_IO "\noutb %%al,$0x80"
44 #define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
46 #define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
50 * Talk about misusing macros..
53 static inline void out##s(unsigned x value, unsigned short port) {
55 #define __OUT2(s,s1,s2) \
56 __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
58 #define __OUT(s,s1,x) \
59 __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
60 __OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \
63 static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
65 #define __IN2(s,s1,s2) \
66 __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
68 #define __IN(s,s1,i...) \
69 __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
70 __IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
73 static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
74 { __asm__ __volatile__ ("cld ; rep ; ins" #s \
75 : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
78 static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
79 { __asm__ __volatile__ ("cld ; rep ; outs" #s \
80 : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
82 #define RETURN_TYPE unsigned char
85 #define RETURN_TYPE unsigned short
88 #define RETURN_TYPE unsigned int