|
|
1.1 ! root 1: #ifndef _ASM_IO_H ! 2: #define _ASM_IO_H ! 3: ! 4: /* ! 5: * This file contains the definitions for the x86 IO instructions ! 6: * inb/inw/inl/outb/outw/outl and the "string versions" of the same ! 7: * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" ! 8: * versions of the single-IO instructions (inb_p/inw_p/..). ! 9: * ! 10: * This file is not meant to be obfuscating: it's just complicated ! 11: * to (a) handle it all in a way that makes gcc able to optimize it ! 12: * as well as possible and (b) trying to avoid writing the same thing ! 13: * over and over again with slight variations and possibly making a ! 14: * mistake somewhere. ! 15: */ ! 16: ! 17: /* ! 18: * Thanks to James van Artsdalen for a better timing-fix than ! 19: * the two short jumps: using outb's to a nonexistent port seems ! 20: * to guarantee better timings even on fast machines. ! 21: * ! 22: * On the other hand, I'd like to be sure of a non-existent port: ! 23: * I feel a bit unsafe about using 0x80 (should be safe, though) ! 24: * ! 25: * Linus ! 26: */ ! 27: ! 28: #ifdef SLOW_IO_BY_JUMPING ! 29: #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") ! 30: #else ! 31: #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") ! 32: #endif ! 33: ! 34: #ifdef REALLY_SLOW_IO ! 35: #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } ! 36: #else ! 37: #define SLOW_DOWN_IO __SLOW_DOWN_IO ! 38: #endif ! 39: ! 40: /* ! 41: * Change virtual addresses to physical addresses and vv. ! 42: * These are trivial on the 1:1 Linux/i386 mapping (but if we ever ! 43: * make the kernel segment mapped at 0, we need to do translation ! 44: * on the i386 as well) ! 45: */ ! 46: extern inline unsigned long virt_to_phys(volatile void * address) ! 47: { ! 48: return (unsigned long) address; ! 49: } ! 50: ! 51: extern inline void * phys_to_virt(unsigned long address) ! 52: { ! 53: return (void *) address; ! 54: } ! 55: ! 56: /* ! 57: * IO bus memory addresses are also 1:1 with the physical address ! 58: */ ! 59: #define virt_to_bus virt_to_phys ! 60: #define bus_to_virt phys_to_virt ! 61: ! 62: /* ! 63: * readX/writeX() are used to access memory mapped devices. On some ! 64: * architectures the memory mapped IO stuff needs to be accessed ! 65: * differently. On the x86 architecture, we just read/write the ! 66: * memory location directly. ! 67: */ ! 68: #define readb(addr) (*(volatile unsigned char *) (addr)) ! 69: #define readw(addr) (*(volatile unsigned short *) (addr)) ! 70: #define readl(addr) (*(volatile unsigned int *) (addr)) ! 71: ! 72: #define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b)) ! 73: #define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b)) ! 74: #define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) ! 75: ! 76: #define memset_io(a,b,c) memset((void *)(a),(b),(c)) ! 77: #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) ! 78: #define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) ! 79: ! 80: /* ! 81: * Again, i386 does not require mem IO specific function. ! 82: */ ! 83: ! 84: #define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),(void *)(b),(c),(d)) ! 85: ! 86: /* ! 87: * Talk about misusing macros.. ! 88: */ ! 89: ! 90: #define __OUT1(s,x) \ ! 91: extern inline void __out##s(unsigned x value, unsigned short port) { ! 92: ! 93: #define __OUT2(s,s1,s2) \ ! 94: __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" ! 95: ! 96: #define __OUT(s,s1,x) \ ! 97: __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \ ! 98: __OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \ ! 99: __OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \ ! 100: __OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; } ! 101: ! 102: #define __IN1(s) \ ! 103: extern inline RETURN_TYPE __in##s(unsigned short port) { RETURN_TYPE _v; ! 104: ! 105: #define __IN2(s,s1,s2) \ ! 106: __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" ! 107: ! 108: #define __IN(s,s1,i...) \ ! 109: __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \ ! 110: __IN1(s##c) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \ ! 111: __IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \ ! 112: __IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; } ! 113: ! 114: #define __INS(s) \ ! 115: extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \ ! 116: { __asm__ __volatile__ ("cld ; rep ; ins" #s \ ! 117: : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } ! 118: ! 119: #define __OUTS(s) \ ! 120: extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ ! 121: { __asm__ __volatile__ ("cld ; rep ; outs" #s \ ! 122: : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } ! 123: ! 124: #define RETURN_TYPE unsigned char ! 125: /* __IN(b,"b","0" (0)) */ ! 126: __IN(b,"") ! 127: #undef RETURN_TYPE ! 128: #define RETURN_TYPE unsigned short ! 129: /* __IN(w,"w","0" (0)) */ ! 130: __IN(w,"") ! 131: #undef RETURN_TYPE ! 132: #define RETURN_TYPE unsigned int ! 133: __IN(l,"") ! 134: #undef RETURN_TYPE ! 135: ! 136: __OUT(b,"b",char) ! 137: __OUT(w,"w",short) ! 138: __OUT(l,,int) ! 139: ! 140: __INS(b) ! 141: __INS(w) ! 142: __INS(l) ! 143: ! 144: __OUTS(b) ! 145: __OUTS(w) ! 146: __OUTS(l) ! 147: ! 148: /* ! 149: * Note that due to the way __builtin_constant_p() works, you ! 150: * - can't use it inside a inline function (it will never be true) ! 151: * - you don't have to worry about side effects within the __builtin.. ! 152: */ ! 153: #define outb(val,port) \ ! 154: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 155: __outbc((val),(port)) : \ ! 156: __outb((val),(port))) ! 157: ! 158: #define inb(port) \ ! 159: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 160: __inbc(port) : \ ! 161: __inb(port)) ! 162: ! 163: #define outb_p(val,port) \ ! 164: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 165: __outbc_p((val),(port)) : \ ! 166: __outb_p((val),(port))) ! 167: ! 168: #define inb_p(port) \ ! 169: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 170: __inbc_p(port) : \ ! 171: __inb_p(port)) ! 172: ! 173: #define outw(val,port) \ ! 174: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 175: __outwc((val),(port)) : \ ! 176: __outw((val),(port))) ! 177: ! 178: #define inw(port) \ ! 179: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 180: __inwc(port) : \ ! 181: __inw(port)) ! 182: ! 183: #define outw_p(val,port) \ ! 184: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 185: __outwc_p((val),(port)) : \ ! 186: __outw_p((val),(port))) ! 187: ! 188: #define inw_p(port) \ ! 189: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 190: __inwc_p(port) : \ ! 191: __inw_p(port)) ! 192: ! 193: #define outl(val,port) \ ! 194: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 195: __outlc((val),(port)) : \ ! 196: __outl((val),(port))) ! 197: ! 198: #define inl(port) \ ! 199: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 200: __inlc(port) : \ ! 201: __inl(port)) ! 202: ! 203: #define outl_p(val,port) \ ! 204: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 205: __outlc_p((val),(port)) : \ ! 206: __outl_p((val),(port))) ! 207: ! 208: #define inl_p(port) \ ! 209: ((__builtin_constant_p((port)) && (port) < 256) ? \ ! 210: __inlc_p(port) : \ ! 211: __inl_p(port)) ! 212: ! 213: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.