io.h (4680B)
1 #ifndef _ASM_IO_H 2 #define _ASM_IO_H 3 4 #define SLOW_IO_BY_JUMPING 5 6 /* 7 * This file contains the definitions for the x86 IO instructions 8 * inb/inw/inl/outb/outw/outl and the "string versions" of the same 9 * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" 10 * versions of the single-IO instructions (inb_p/inw_p/..). 11 * 12 * This file is not meant to be obfuscating: it's just complicated 13 * to (a) handle it all in a way that makes gcc able to optimize it 14 * as well as possible and (b) trying to avoid writing the same thing 15 * over and over again with slight variations and possibly making a 16 * mistake somewhere. 17 */ 18 19 /* 20 * Thanks to James van Artsdalen for a better timing-fix than 21 * the two short jumps: using outb's to a nonexistent port seems 22 * to guarantee better timings even on fast machines. 23 * 24 * On the other hand, I'd like to be sure of a non-existent port: 25 * I feel a bit unsafe about using 0x80 (should be safe, though) 26 * 27 * Linus 28 */ 29 30 #ifdef SLOW_IO_BY_JUMPING 31 #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") 32 #else 33 #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") 34 #endif 35 36 #define SLOW_DOWN_IO __SLOW_DOWN_IO 37 38 /* 39 * Talk about misusing macros.. 40 */ 41 42 #define __OUT1(s,x) \ 43 extern inline void __out##s(unsigned x value, unsigned short port) { 44 45 #define __OUT2(s,s1,s2) \ 46 __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" 47 48 #define __OUT(s,s1,x) \ 49 __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \ 50 __OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \ 51 __OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \ 52 __OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; } 53 54 #define __IN1(s) \ 55 extern inline RETURN_TYPE __in##s(unsigned short port) { RETURN_TYPE _v; 56 57 #define __IN2(s,s1,s2) \ 58 __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" 59 60 #define __IN(s,s1,i...) \ 61 __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \ 62 __IN1(s##c) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \ 63 __IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \ 64 __IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; } 65 66 #define __INS(s) \ 67 extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \ 68 { __asm__ __volatile__ ("cld ; rep ; ins" #s \ 69 : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } 70 71 #define __OUTS(s) \ 72 extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ 73 { __asm__ __volatile__ ("cld ; rep ; outs" #s \ 74 : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } 75 76 #define RETURN_TYPE unsigned char 77 /* __IN(b,"b","0" (0)) */ 78 __IN(b,"") 79 #undef RETURN_TYPE 80 #define RETURN_TYPE unsigned short 81 /* __IN(w,"w","0" (0)) */ 82 __IN(w,"") 83 #undef RETURN_TYPE 84 #define RETURN_TYPE unsigned int 85 __IN(l,"") 86 #undef RETURN_TYPE 87 88 __OUT(b,"b",char) 89 __OUT(w,"w",short) 90 __OUT(l,,int) 91 92 __INS(b) 93 __INS(w) 94 __INS(l) 95 96 __OUTS(b) 97 __OUTS(w) 98 __OUTS(l) 99 100 /* 101 * Note that due to the way __builtin_constant_p() works, you 102 * - can't use it inside a inline function (it will never be true) 103 * - you don't have to worry about side effects within the __builtin.. 104 */ 105 #define outb(val,port) \ 106 ((__builtin_constant_p((port)) && (port) < 256) ? \ 107 __outbc((val),(port)) : \ 108 __outb((val),(port))) 109 110 #define inb(port) \ 111 ((__builtin_constant_p((port)) && (port) < 256) ? \ 112 __inbc(port) : \ 113 __inb(port)) 114 115 #define outb_p(val,port) \ 116 ((__builtin_constant_p((port)) && (port) < 256) ? \ 117 __outbc_p((val),(port)) : \ 118 __outb_p((val),(port))) 119 120 #define inb_p(port) \ 121 ((__builtin_constant_p((port)) && (port) < 256) ? \ 122 __inbc_p(port) : \ 123 __inb_p(port)) 124 125 #define outw(val,port) \ 126 ((__builtin_constant_p((port)) && (port) < 256) ? \ 127 __outwc((val),(port)) : \ 128 __outw((val),(port))) 129 130 #define inw(port) \ 131 ((__builtin_constant_p((port)) && (port) < 256) ? \ 132 __inwc(port) : \ 133 __inw(port)) 134 135 #define outw_p(val,port) \ 136 ((__builtin_constant_p((port)) && (port) < 256) ? \ 137 __outwc_p((val),(port)) : \ 138 __outw_p((val),(port))) 139 140 #define inw_p(port) \ 141 ((__builtin_constant_p((port)) && (port) < 256) ? \ 142 __inwc_p(port) : \ 143 __inw_p(port)) 144 145 #define outl(val,port) \ 146 ((__builtin_constant_p((port)) && (port) < 256) ? \ 147 __outlc((val),(port)) : \ 148 __outl((val),(port))) 149 150 #define inl(port) \ 151 ((__builtin_constant_p((port)) && (port) < 256) ? \ 152 __inlc(port) : \ 153 __inl(port)) 154 155 #define outl_p(val,port) \ 156 ((__builtin_constant_p((port)) && (port) < 256) ? \ 157 __outlc_p((val),(port)) : \ 158 __outl_p((val),(port))) 159 160 #define inl_p(port) \ 161 ((__builtin_constant_p((port)) && (port) < 256) ? \ 162 __inlc_p(port) : \ 163 __inl_p(port)) 164 165 #endif