Line data Source code
1 : #ifndef _ASM_X86_IO_64_H
2 : #define _ASM_X86_IO_64_H
3 :
4 :
5 : /*
6 : * This file contains the definitions for the x86 IO instructions
7 : * inb/inw/inl/outb/outw/outl and the "string versions" of the same
8 : * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
9 : * versions of the single-IO instructions (inb_p/inw_p/..).
10 : *
11 : * This file is not meant to be obfuscating: it's just complicated
12 : * to (a) handle it all in a way that makes gcc able to optimize it
13 : * as well as possible and (b) trying to avoid writing the same thing
14 : * over and over again with slight variations and possibly making a
15 : * mistake somewhere.
16 : */
17 :
18 : /*
19 : * Thanks to James van Artsdalen for a better timing-fix than
20 : * the two short jumps: using outb's to a nonexistent port seems
21 : * to guarantee better timings even on fast machines.
22 : *
23 : * On the other hand, I'd like to be sure of a non-existent port:
24 : * I feel a bit unsafe about using 0x80 (should be safe, though)
25 : *
26 : * Linus
27 : */
28 :
29 : /*
30 : * Bit simplified and optimized by Jan Hubicka
31 : * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
32 : *
33 : * isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added,
34 : * isa_read[wl] and isa_write[wl] fixed
35 : * - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
36 : */
37 :
38 : extern void native_io_delay(void);
39 :
40 : extern int io_delay_type;
41 : extern void io_delay_init(void);
42 :
43 : #if defined(CONFIG_PARAVIRT)
44 : #include <asm/paravirt.h>
45 : #else
46 :
47 : static inline void slow_down_io(void)
48 : {
49 : native_io_delay();
50 : #ifdef REALLY_SLOW_IO
51 : native_io_delay();
52 : native_io_delay();
53 : native_io_delay();
54 : #endif
55 : }
56 : #endif
57 :
58 : /*
59 : * Talk about misusing macros..
60 : */
61 : #define __OUT1(s, x) \
62 : static inline void out##s(unsigned x value, unsigned short port) {
63 :
64 : #define __OUT2(s, s1, s2) \
65 : asm volatile ("out" #s " %" s1 "0,%" s2 "1"
66 :
67 : #ifndef REALLY_SLOW_IO
68 : #define REALLY_SLOW_IO
69 : #define UNSET_REALLY_SLOW_IO
70 : #endif
71 :
72 : #define __OUT(s, s1, x) \
73 : __OUT1(s, x) __OUT2(s, s1, "w") : : "a" (value), "Nd" (port)); \
74 : } \
75 : __OUT1(s##_p, x) __OUT2(s, s1, "w") : : "a" (value), "Nd" (port)); \
76 : slow_down_io(); \
77 : }
78 :
79 : #define __IN1(s) \
80 : static inline RETURN_TYPE in##s(unsigned short port) \
81 : { \
82 : RETURN_TYPE _v;
83 :
84 : #define __IN2(s, s1, s2) \
85 : asm volatile ("in" #s " %" s2 "1,%" s1 "0"
86 :
87 : #define __IN(s, s1, i...) \
88 : __IN1(s) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i); \
89 : return _v; \
90 : } \
91 : __IN1(s##_p) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i); \
92 : slow_down_io(); \
93 : return _v; }
94 :
95 : #ifdef UNSET_REALLY_SLOW_IO
96 : #undef REALLY_SLOW_IO
97 : #endif
98 :
99 : #define __INS(s) \
100 : static inline void ins##s(unsigned short port, void *addr, \
101 : unsigned long count) \
102 : { \
103 : asm volatile ("rep ; ins" #s \
104 : : "=D" (addr), "=c" (count) \
105 : : "d" (port), "0" (addr), "1" (count)); \
106 : }
107 :
108 : #define __OUTS(s) \
109 : static inline void outs##s(unsigned short port, const void *addr, \
110 : unsigned long count) \
111 : { \
112 : asm volatile ("rep ; outs" #s \
113 : : "=S" (addr), "=c" (count) \
114 : : "d" (port), "0" (addr), "1" (count)); \
115 : }
116 :
117 : #define RETURN_TYPE unsigned char
118 : __IN(b, "")
119 : #undef RETURN_TYPE
120 : #define RETURN_TYPE unsigned short
121 : __IN(w, "")
122 : #undef RETURN_TYPE
123 : #define RETURN_TYPE unsigned int
124 16 : __IN(l, "")
125 : #undef RETURN_TYPE
126 8 :
127 : __OUT(b, "b", char)
128 : __OUT(w, "w", short)
129 32 : __OUT(l, , int)
130 32 :
131 : __INS(b)
132 : __INS(w)
133 : __INS(l)
134 :
135 : __OUTS(b)
136 : __OUTS(w)
137 : __OUTS(l)
138 :
139 : #if defined(__KERNEL__) && defined(__x86_64__)
140 :
141 : #include <linux/vmalloc.h>
142 :
143 : #include <asm-generic/iomap.h>
144 :
145 : void __memcpy_fromio(void *, unsigned long, unsigned);
146 : void __memcpy_toio(unsigned long, const void *, unsigned);
147 :
148 : static inline void memcpy_fromio(void *to, const volatile void __iomem *from,
149 : unsigned len)
150 : {
151 : __memcpy_fromio(to, (unsigned long)from, len);
152 : }
153 :
154 : static inline void memcpy_toio(volatile void __iomem *to, const void *from,
155 : unsigned len)
156 : {
157 : __memcpy_toio((unsigned long)to, from, len);
158 : }
159 :
160 : void memset_io(volatile void __iomem *a, int b, size_t c);
161 :
162 : /*
163 : * ISA space is 'always mapped' on a typical x86 system, no need to
164 : * explicitly ioremap() it. The fact that the ISA IO space is mapped
165 : * to PAGE_OFFSET is pure coincidence - it does not mean ISA values
166 : * are physical addresses. The following constant pointer can be
167 : * used as the IO-area pointer (it can be iounmapped as well, so the
168 : * analogy with PCI is quite large):
169 : */
170 : #define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
171 :
172 : #define flush_write_buffers()
173 :
174 : /*
175 : * Convert a virtual cached pointer to an uncached pointer
176 : */
177 : #define xlate_dev_kmem_ptr(p) p
178 :
179 : #endif /* __KERNEL__ */
180 :
181 : #endif /* _ASM_X86_IO_64_H */
|