2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
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 * We define port_t as unsigned long because otherwise
51 * we get warnings about converting pointers to small integers
54 #define port_t unsigned long
57 * Talk about misusing macros..
60 static inline void out##s(unsigned x value, unsigned short port) {
62 #define __OUT2(s,s1,s2) \
63 __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
65 #define __OUT(s,s1,x) \
66 __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
67 __OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \
70 static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
72 #define __IN2(s,s1,s2) \
73 __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
75 #define __IN(s,s1,i...) \
76 __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
77 __IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
80 static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
81 { __asm__ __volatile__ ("cld ; rep ; ins" #s \
82 : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
85 static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
86 { __asm__ __volatile__ ("cld ; rep ; outs" #s \
87 : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
89 #define RETURN_TYPE unsigned char
92 #define RETURN_TYPE unsigned short
95 #define RETURN_TYPE unsigned int