home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / include / asm-mips / io.h < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-15  |  6.6 KB  |  242 lines

  1. #ifndef __ASM_MIPS_IO_H
  2. #define __ASM_MIPS_IO_H
  3.  
  4. #include <asm/mipsregs.h>
  5. #include <asm/mipsconfig.h>
  6.  
  7. /*
  8.  * This file contains the definitions for the MIPS counterpart of the
  9.  * x86 in/out instructions. This heap of macros and C results in much
  10.  * better code than the approach of doing it in plain C, though that's
  11.  * probably not needed.
  12.  *
  13.  *   Ralf
  14.  *
  15.  * This file contains the definitions for the x86 IO instructions
  16.  * inb/inw/inl/outb/outw/outl and the "string versions" of the same
  17.  * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
  18.  * versions of the single-IO instructions (inb_p/inw_p/..).
  19.  *
  20.  * This file is not meant to be obfuscating: it's just complicated
  21.  * to (a) handle it all in a way that makes gcc able to optimize it
  22.  * as well as possible and (b) trying to avoid writing the same thing
  23.  * over and over again with slight variations and possibly making a
  24.  * mistake somewhere.
  25.  */
  26.  
  27. /*
  28.  * Thanks to James van Artsdalen for a better timing-fix than
  29.  * the two short jumps: using outb's to a nonexistent port seems
  30.  * to guarantee better timings even on fast machines.
  31.  *
  32.  * On the other hand, I'd like to be sure of a non-existent port:
  33.  * I feel a bit unsafe about using 0x80 (should be safe, though)
  34.  *
  35.  *        Linus
  36.  */
  37.  
  38. #define __SLOW_DOWN_IO \
  39.     __asm__ __volatile__( \
  40.         "sb\t$0,0x80(%0)" \
  41.         : : "r" (PORT_BASE));
  42.  
  43. #ifdef REALLY_SLOW_IO
  44. #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
  45. #else
  46. #define SLOW_DOWN_IO __SLOW_DOWN_IO
  47. #endif
  48.  
  49. /*
  50.  * Talk about misusing macros..
  51.  */
  52.  
  53. #define __OUT1(s) \
  54. extern inline void __out##s(unsigned int value, unsigned int port) {
  55.  
  56. #define __OUT2(m) \
  57. __asm__ __volatile__ ("s" #m "\t%0,%1(%2)"
  58.  
  59. #define __OUT(m,s) \
  60. __OUT1(s) __OUT2(m) : : "r" (value), "i" (0), "r" (PORT_BASE+port)); } \
  61. __OUT1(s##c) __OUT2(m) : : "r" (value), "i" (port), "r" (PORT_BASE)); } \
  62. __OUT1(s##_p) __OUT2(m) : : "r" (value), "i" (0), "r" (PORT_BASE+port)); \
  63.     SLOW_DOWN_IO; } \
  64. __OUT1(s##c_p) __OUT2(m) : : "r" (value), "i" (port), "r" (PORT_BASE)); \
  65.     SLOW_DOWN_IO; }
  66.  
  67. #define __IN1(s) \
  68. extern inline unsigned int __in##s(unsigned int port) { unsigned int _v;
  69.  
  70. #define __IN2(m) \
  71. __asm__ __volatile__ ("l" #m "u\t%0,%1(%2)\n\t"
  72.  
  73. #define __IN(m,s) \
  74. __IN1(s) __IN2(m) STR(FILL_LDS) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); return _v; } \
  75. __IN1(s##c) __IN2(m) STR(FILL_LDS) : "=r" (_v) : "i" (port), "r" (PORT_BASE)); return _v; } \
  76. __IN1(s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); SLOW_DOWN_IO; return _v; } \
  77. __IN1(s##c_p) __IN2(m) : "=r" (_v) : "i" (port), "r" (PORT_BASE)); SLOW_DOWN_IO; return _v; }
  78.  
  79. #define __INS1(s) \
  80. extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) {
  81.  
  82. #define __INS2(m) \
  83. __asm__ __volatile__ ( \
  84.     ".set\tnoreorder\n\t" \
  85.     ".set\tnoat\n" \
  86.     "1:\tl" #m "u\t$1,%4(%5)\n\t" \
  87.     "subu\t%1,%1,1\n\t" \
  88.     "s" #m "\t$1,(%0)\n\t" \
  89.     "bne\t$0,%1,1b\n\t" \
  90.     "addiu\t%0,%0,%6\n\t" \
  91.     ".set\tat\n\t" \
  92.     ".set\treorder"
  93.  
  94. #define __INS(m,s,i) \
  95. __INS1(s) __INS2(m) \
  96.     : "=r" (addr), "=r" (count) \
  97.     : "0" (addr), "1" (count), "i" (0), "r" (PORT_BASE+port), "I" (i) \
  98.     : "$1");} \
  99. __INS1(s##c) __INS2(m) \
  100.     : "=r" (addr), "=r" (count) \
  101.     : "0" (addr), "1" (count), "i" (port), "r" (PORT_BASE), "I" (i) \
  102.     : "$1");}
  103.  
  104. #define __OUTS1(s) \
  105. extern inline void __outs##s(unsigned int port, const void * addr, unsigned long count) {
  106.  
  107. #define __OUTS2(m) \
  108. __asm__ __volatile__ ( \
  109.         ".set\tnoreorder\n\t" \
  110.         ".set\tnoat\n" \
  111.         "1:\tl" #m "u\t$1,(%0)\n\t" \
  112.         "subu\t%1,%1,1\n\t" \
  113.         "s" #m "\t$1,%4(%5)\n\t" \
  114.         "bne\t$0,%1,1b\n\t" \
  115.         "addiu\t%0,%0,%6\n\t" \
  116.         ".set\tat\n\t" \
  117.         ".set\treorder"
  118.  
  119. #define __OUTS(m,s,i) \
  120. __OUTS1(s) __OUTS2(m) \
  121.     : "=r" (addr), "=r" (count) \
  122.     : "0" (addr), "1" (count), "i" (0), "r" (PORT_BASE+port), "I" (i) \
  123.     : "$1");} \
  124. __OUTS1(s##c) __OUTS2(m) \
  125.     : "=r" (addr), "=r" (count) \
  126.     : "0" (addr), "1" (count), "i" (port), "r" (PORT_BASE), "I" (i) \
  127.     : "$1");}
  128.  
  129. __IN(b,b)
  130. __IN(h,w)
  131. __IN(w,l)
  132.  
  133. __OUT(b,b)
  134. __OUT(h,w)
  135. __OUT(w,l)
  136.  
  137. __INS(b,b,1)
  138. __INS(h,w,2)
  139. __INS(w,l,4)
  140.  
  141. __OUTS(b,b,1)
  142. __OUTS(h,w,2)
  143. __OUTS(w,l,4)
  144.  
  145. /*
  146.  * Note that due to the way __builtin_constant_p() works, you
  147.  *  - can't use it inside a inline function (it will never be true)
  148.  *  - you don't have to worry about side effects within the __builtin..
  149.  */
  150. #define outb(val,port) \
  151. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  152.     __outbc((val),(port)) : \
  153.     __outb((val),(port)))
  154.  
  155. #define inb(port) \
  156. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  157.     __inbc(port) : \
  158.     __inb(port))
  159.  
  160. #define outb_p(val,port) \
  161. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  162.     __outbc_p((val),(port)) : \
  163.     __outb_p((val),(port)))
  164.  
  165. #define inb_p(port) \
  166. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  167.     __inbc_p(port) : \
  168.     __inb_p(port))
  169.  
  170. #define outw(val,port) \
  171. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  172.     __outwc((val),(port)) : \
  173.     __outw((val),(port)))
  174.  
  175. #define inw(port) \
  176. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  177.     __inwc(port) : \
  178.     __inw(port))
  179.  
  180. #define outw_p(val,port) \
  181. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  182.     __outwc_p((val),(port)) : \
  183.     __outw_p((val),(port)))
  184.  
  185. #define inw_p(port) \
  186. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  187.     __inwc_p(port) : \
  188.     __inw_p(port))
  189.  
  190. #define outl(val,port) \
  191. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  192.     __outlc((val),(port)) : \
  193.     __outl((val),(port)))
  194.  
  195. #define inl(port) \
  196. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  197.     __inlc(port) : \
  198.     __inl(port))
  199.  
  200. #define outl_p(val,port) \
  201. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  202.     __outlc_p((val),(port)) : \
  203.     __outl_p((val),(port)))
  204.  
  205. #define inl_p(port) \
  206. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  207.     __inlc_p(port) : \
  208.     __inl_p(port))
  209.  
  210.  
  211. #define outsb(port,addr,count) \
  212. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  213.     __outsbc((port),(addr),(count)) : \
  214.     __outsb ((port),(addr),(count)))
  215.  
  216. #define insb(port,addr,count) \
  217. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  218.     __insbc((port),(addr),(count)) : \
  219.     __insb((port),(addr),(count)))
  220.  
  221. #define outsw(port,addr,count) \
  222. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  223.     __outswc((port),(addr),(count)) : \
  224.     __outsw ((port),(addr),(count)))
  225.  
  226. #define insw(port,addr,count) \
  227. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  228.     __inswc((port),(addr),(count)) : \
  229.     __insw((port),(addr),(count)))
  230.  
  231. #define outsl(port,addr,count) \
  232. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  233.     __outslc((port),(addr),(count)) : \
  234.     __outsl ((port),(addr),(count)))
  235.  
  236. #define insl(port,addr,count) \
  237. ((__builtin_constant_p((port)) && (port) < 32768) ? \
  238.     __inslc((port),(addr),(count)) : \
  239.     __insl((port),(addr),(count)))
  240.  
  241. #endif /* __ASM_MIPS_IO_H */
  242.