Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | #ifndef _ASM_IO_H #define _ASM_IO_H /* * Thanks to James van Artsdalen for a better timing-fix than * the two short jumps: using outb's to a nonexistent port seems * to guarantee better timings even on fast machines. * * On the other hand, I'd like to be sure of a non-existent port: * I feel a bit unsafe about using 0x80. * * Linus */ #ifdef SLOW_IO_BY_JUMPING #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") #else #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") #endif #ifdef REALLY_SLOW_IO #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } #else #define SLOW_DOWN_IO __SLOW_DOWN_IO #endif /* This is the more general version of outb.. */ extern inline void __outb(unsigned char value, unsigned short port) { __asm__ __volatile__ ("outb %b0,%w1" : /* no outputs */ :"a" (value),"d" (port)); } /* this is used for constant port numbers < 256.. */ extern inline void __outbc(unsigned char value, unsigned short port) { __asm__ __volatile__ ("outb %b0,%1" : /* no outputs */ :"a" (value),"i" (port)); } /* general version of inb */ extern inline unsigned int __inb(unsigned short port) { unsigned int _v; __asm__ __volatile__ ("inb %w1,%b0" :"=a" (_v):"d" (port),"0" (0)); return _v; } /* inb with constant port nr 0-255 */ extern inline unsigned int __inbc(unsigned short port) { unsigned int _v; __asm__ __volatile__ ("inb %1,%b0" :"=a" (_v):"i" (port),"0" (0)); return _v; } extern inline void __outb_p(unsigned char value, unsigned short port) { __asm__ __volatile__ ("outb %b0,%w1" : /* no outputs */ :"a" (value),"d" (port)); SLOW_DOWN_IO; } extern inline void __outbc_p(unsigned char value, unsigned short port) { __asm__ __volatile__ ("outb %b0,%1" : /* no outputs */ :"a" (value),"i" (port)); SLOW_DOWN_IO; } extern inline unsigned int __inb_p(unsigned short port) { unsigned int _v; __asm__ __volatile__ ("inb %w1,%b0" :"=a" (_v):"d" (port),"0" (0)); SLOW_DOWN_IO; return _v; } extern inline unsigned int __inbc_p(unsigned short port) { unsigned int _v; __asm__ __volatile__ ("inb %1,%b0" :"=a" (_v):"i" (port),"0" (0)); SLOW_DOWN_IO; return _v; } /* * Note that due to the way __builtin_constant_p() works, you * - can't use it inside a inline function (it will never be true) * - you don't have to worry about side effects within the __builtin.. */ #define outb(val,port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __outbc((val),(port)) : \ __outb((val),(port))) #define inb(port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __inbc(port) : \ __inb(port)) #define outb_p(val,port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __outbc_p((val),(port)) : \ __outb_p((val),(port))) #define inb_p(port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __inbc_p(port) : \ __inb_p(port)) #endif |