io.h
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. #ifndef _ASM_IO_H
  2. #define _ASM_IO_H
  3. #include <linux/config.h>
  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.  * Thanks to James van Artsdalen for a better timing-fix than
  18.  * the two short jumps: using outb's to a nonexistent port seems
  19.  * to guarantee better timings even on fast machines.
  20.  *
  21.  * On the other hand, I'd like to be sure of a non-existent port:
  22.  * I feel a bit unsafe about using 0x80 (should be safe, though)
  23.  *
  24.  * Linus
  25.  */
  26.  /*
  27.   *  Bit simplified and optimized by Jan Hubicka
  28.   *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
  29.   *
  30.   *  isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added,
  31.   *  isa_read[wl] and isa_write[wl] fixed
  32.   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  33.   */
  34. #define IO_SPACE_LIMIT 0xffff
  35. #define XQUAD_PORTIO_BASE 0xfe400000
  36. #define XQUAD_PORTIO_LEN  0x40000   /* 256k per quad. Only remapping 1st */
  37. #ifdef __KERNEL__
  38. #include <linux/vmalloc.h>
  39. /*
  40.  * Temporary debugging check to catch old code using
  41.  * unmapped ISA addresses. Will be removed in 2.4.
  42.  */
  43. #if CONFIG_DEBUG_IOVIRT
  44.   extern void *__io_virt_debug(unsigned long x, const char *file, int line);
  45.   extern unsigned long __io_phys_debug(unsigned long x, const char *file, int line);
  46.   #define __io_virt(x) __io_virt_debug((unsigned long)(x), __FILE__, __LINE__)
  47. //#define __io_phys(x) __io_phys_debug((unsigned long)(x), __FILE__, __LINE__)
  48. #else
  49.   #define __io_virt(x) ((void *)(x))
  50. //#define __io_phys(x) __pa(x)
  51. #endif
  52. /*
  53.  * Change virtual addresses to physical addresses and vv.
  54.  * These are pretty trivial
  55.  */
  56. static inline unsigned long virt_to_phys(volatile void * address)
  57. {
  58. return __pa(address);
  59. }
  60. static inline void * phys_to_virt(unsigned long address)
  61. {
  62. return __va(address);
  63. }
  64. /*
  65.  * Change "struct page" to physical address.
  66.  */
  67. #define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
  68. extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
  69. static inline void * ioremap (unsigned long offset, unsigned long size)
  70. {
  71. return __ioremap(offset, size, 0);
  72. }
  73. /*
  74.  * This one maps high address device memory and turns off caching for that area.
  75.  * it's useful if some control registers are in such an area and write combining
  76.  * or read caching is not desirable:
  77.  */
  78. static inline void * ioremap_nocache (unsigned long offset, unsigned long size)
  79. {
  80.         return __ioremap(offset, size, _PAGE_PCD);
  81. }
  82. extern void iounmap(void *addr);
  83. /*
  84.  * IO bus memory addresses are also 1:1 with the physical address
  85.  */
  86. #define virt_to_bus virt_to_phys
  87. #define bus_to_virt phys_to_virt
  88. #define page_to_bus page_to_phys
  89. /*
  90.  * readX/writeX() are used to access memory mapped devices. On some
  91.  * architectures the memory mapped IO stuff needs to be accessed
  92.  * differently. On the x86 architecture, we just read/write the
  93.  * memory location directly.
  94.  */
  95. #define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
  96. #define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
  97. #define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
  98. #define __raw_readb readb
  99. #define __raw_readw readw
  100. #define __raw_readl readl
  101. #define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
  102. #define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
  103. #define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
  104. #define __raw_writeb writeb
  105. #define __raw_writew writew
  106. #define __raw_writel writel
  107. #define memset_io(a,b,c) memset(__io_virt(a),(b),(c))
  108. #define memcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c))
  109. #define memcpy_toio(a,b,c) memcpy(__io_virt(a),(b),(c))
  110. /*
  111.  * ISA space is 'always mapped' on a typical x86 system, no need to
  112.  * explicitly ioremap() it. The fact that the ISA IO space is mapped
  113.  * to PAGE_OFFSET is pure coincidence - it does not mean ISA values
  114.  * are physical addresses. The following constant pointer can be
  115.  * used as the IO-area pointer (it can be iounmapped as well, so the
  116.  * analogy with PCI is quite large):
  117.  */
  118. #define __ISA_IO_base ((char *)(PAGE_OFFSET))
  119. #define isa_readb(a) readb(__ISA_IO_base + (a))
  120. #define isa_readw(a) readw(__ISA_IO_base + (a))
  121. #define isa_readl(a) readl(__ISA_IO_base + (a))
  122. #define isa_writeb(b,a) writeb(b,__ISA_IO_base + (a))
  123. #define isa_writew(w,a) writew(w,__ISA_IO_base + (a))
  124. #define isa_writel(l,a) writel(l,__ISA_IO_base + (a))
  125. #define isa_memset_io(a,b,c) memset_io(__ISA_IO_base + (a),(b),(c))
  126. #define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),__ISA_IO_base + (b),(c))
  127. #define isa_memcpy_toio(a,b,c) memcpy_toio(__ISA_IO_base + (a),(b),(c))
  128. /*
  129.  * Again, i386 does not require mem IO specific function.
  130.  */
  131. #define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(b),(c),(d))
  132. #define isa_eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (b)),(c),(d))
  133. static inline int check_signature(unsigned long io_addr,
  134. const unsigned char *signature, int length)
  135. {
  136. int retval = 0;
  137. do {
  138. if (readb(io_addr) != *signature)
  139. goto out;
  140. io_addr++;
  141. signature++;
  142. length--;
  143. } while (length);
  144. retval = 1;
  145. out:
  146. return retval;
  147. }
  148. static inline int isa_check_signature(unsigned long io_addr,
  149. const unsigned char *signature, int length)
  150. {
  151. int retval = 0;
  152. do {
  153. if (isa_readb(io_addr) != *signature)
  154. goto out;
  155. io_addr++;
  156. signature++;
  157. length--;
  158. } while (length);
  159. retval = 1;
  160. out:
  161. return retval;
  162. }
  163. /*
  164.  * Cache management
  165.  *
  166.  * This needed for two cases
  167.  * 1. Out of order aware processors
  168.  * 2. Accidentally out of order processors (PPro errata #51)
  169.  */
  170.  
  171. #if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE)
  172. static inline void flush_write_buffers(void)
  173. {
  174. __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory");
  175. }
  176. #define dma_cache_inv(_start,_size) flush_write_buffers()
  177. #define dma_cache_wback(_start,_size) flush_write_buffers()
  178. #define dma_cache_wback_inv(_start,_size) flush_write_buffers()
  179. #else
  180. /* Nothing to do */
  181. #define dma_cache_inv(_start,_size) do { } while (0)
  182. #define dma_cache_wback(_start,_size) do { } while (0)
  183. #define dma_cache_wback_inv(_start,_size) do { } while (0)
  184. #define flush_write_buffers()
  185. #endif
  186. #endif /* __KERNEL__ */
  187. #ifdef SLOW_IO_BY_JUMPING
  188. #define __SLOW_DOWN_IO "njmp 1fn1:tjmp 1fn1:"
  189. #else
  190. #define __SLOW_DOWN_IO "noutb %%al,$0x80"
  191. #endif
  192. #ifdef REALLY_SLOW_IO
  193. #define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
  194. #else
  195. #define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
  196. #endif
  197. #ifdef CONFIG_MULTIQUAD
  198. extern void *xquad_portio;    /* Where the IO area was mapped */
  199. #endif /* CONFIG_MULTIQUAD */
  200. /*
  201.  * Talk about misusing macros..
  202.  */
  203. #define __OUT1(s,x) 
  204. static inline void out##s(unsigned x value, unsigned short port) {
  205. #define __OUT2(s,s1,s2) 
  206. __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
  207. #ifdef CONFIG_MULTIQUAD
  208. /* Make the default portio routines operate on quad 0 for now */
  209. #define __OUT(s,s1,x) 
  210. __OUT1(s##_local,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } 
  211. __OUT1(s##_p_local,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} 
  212. __OUTQ0(s,s,x) 
  213. __OUTQ0(s,s##_p,x) 
  214. #else
  215. #define __OUT(s,s1,x) 
  216. __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } 
  217. __OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} 
  218. #endif /* CONFIG_MULTIQUAD */
  219. #ifdef CONFIG_MULTIQUAD
  220. #define __OUTQ0(s,ss,x)    /* Do the equivalent of the portio op on quad 0 */ 
  221. static inline void out##ss(unsigned x value, unsigned short port) { 
  222. if (xquad_portio) 
  223. write##s(value, (unsigned long) xquad_portio + port); 
  224. else               /* We're still in early boot, running on quad 0 */ 
  225. out##ss##_local(value, port); 
  226. #define __INQ0(s,ss)       /* Do the equivalent of the portio op on quad 0 */ 
  227. static inline RETURN_TYPE in##ss(unsigned short port) { 
  228. if (xquad_portio) 
  229. return read##s((unsigned long) xquad_portio + port); 
  230. else               /* We're still in early boot, running on quad 0 */ 
  231. return in##ss##_local(port); 
  232. }
  233. #endif /* CONFIG_MULTIQUAD */
  234. #define __IN1(s) 
  235. static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
  236. #define __IN2(s,s1,s2) 
  237. __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
  238. #ifdef CONFIG_MULTIQUAD
  239. #define __IN(s,s1,i...) 
  240. __IN1(s##_local) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } 
  241. __IN1(s##_p_local) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } 
  242. __INQ0(s,s) 
  243. __INQ0(s,s##_p) 
  244. #else
  245. #define __IN(s,s1,i...) 
  246. __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } 
  247. __IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } 
  248. #endif /* CONFIG_MULTIQUAD */
  249. #define __INS(s) 
  250. static inline void ins##s(unsigned short port, void * addr, unsigned long count) 
  251. { __asm__ __volatile__ ("rep ; ins" #s 
  252. : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
  253. #define __OUTS(s) 
  254. static inline void outs##s(unsigned short port, const void * addr, unsigned long count) 
  255. { __asm__ __volatile__ ("rep ; outs" #s 
  256. : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
  257. #define RETURN_TYPE unsigned char
  258. __IN(b,"")
  259. #undef RETURN_TYPE
  260. #define RETURN_TYPE unsigned short
  261. __IN(w,"")
  262. #undef RETURN_TYPE
  263. #define RETURN_TYPE unsigned int
  264. __IN(l,"")
  265. #undef RETURN_TYPE
  266. __OUT(b,"b",char)
  267. __OUT(w,"w",short)
  268. __OUT(l,,int)
  269. __INS(b)
  270. __INS(w)
  271. __INS(l)
  272. __OUTS(b)
  273. __OUTS(w)
  274. __OUTS(l)
  275. #endif