home *** CD-ROM | disk | FTP | other *** search
- #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
-
- #ifdef __i386__
- /* 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));
- }
- #endif /* architecture */
-
- /* 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));
- }
-
- #ifdef __i386__
- /* 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;
- }
- #endif /* architecture */
-
- /* 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;
- }
-
- #if defined(__i386__)
- 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;
- }
- #elif defined(__mc68000__)
- static inline void put_user_byte_io(char val,char *addr)
- {
- __asm__ __volatile__ ("moveb %0,%1"
- : /* no outputs */
- :"r" (val),"m" (*addr)
- : "memory");
- }
- #define outb_p(x,addr) put_user_byte_io((x),(char *)(addr))
- #define outb(x,addr) put_user_byte_io((x),(char *)(addr))
- #endif /* architecture */
-
- 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;
- }
-
- #if defined(__i386__)
- 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;
- }
- #elif defined(__mc68000__)
- static inline unsigned char get_user_byte_io(const char * addr)
- {
- register unsigned char _v;
-
- __asm__ __volatile__ ("moveb %1,%0":"=r" (_v):"m" (*addr));
- return _v;
- }
- #define inb_p(addr) get_user_byte_io((char *)(addr))
- #define inb(addr) get_user_byte_io((char *)(addr))
- #endif /* architecture */
-
- 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;
- }
-
- #ifdef __i386__
- /*
- * 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 /* i386 */
-
- #endif
-