diff options
Diffstat (limited to 'arch/x86/include/asm/io_64.h')
-rw-r--r-- | arch/x86/include/asm/io_64.h | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/arch/x86/include/asm/io_64.h b/arch/x86/include/asm/io_64.h new file mode 100644 index 000000000000..fea325a1122f --- /dev/null +++ b/arch/x86/include/asm/io_64.h | |||
@@ -0,0 +1,244 @@ | |||
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 | __IN(l, "") | ||
125 | #undef RETURN_TYPE | ||
126 | |||
127 | __OUT(b, "b", char) | ||
128 | __OUT(w, "w", short) | ||
129 | __OUT(l, , int) | ||
130 | |||
131 | __INS(b) | ||
132 | __INS(w) | ||
133 | __INS(l) | ||
134 | |||
135 | __OUTS(b) | ||
136 | __OUTS(w) | ||
137 | __OUTS(l) | ||
138 | |||
139 | #define IO_SPACE_LIMIT 0xffff | ||
140 | |||
141 | #if defined(__KERNEL__) && defined(__x86_64__) | ||
142 | |||
143 | #include <linux/vmalloc.h> | ||
144 | |||
145 | #ifndef __i386__ | ||
146 | /* | ||
147 | * Change virtual addresses to physical addresses and vv. | ||
148 | * These are pretty trivial | ||
149 | */ | ||
150 | static inline unsigned long virt_to_phys(volatile void *address) | ||
151 | { | ||
152 | return __pa(address); | ||
153 | } | ||
154 | |||
155 | static inline void *phys_to_virt(unsigned long address) | ||
156 | { | ||
157 | return __va(address); | ||
158 | } | ||
159 | #endif | ||
160 | |||
161 | /* | ||
162 | * Change "struct page" to physical address. | ||
163 | */ | ||
164 | #define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) | ||
165 | |||
166 | #include <asm-generic/iomap.h> | ||
167 | |||
168 | /* | ||
169 | * This one maps high address device memory and turns off caching for that area. | ||
170 | * it's useful if some control registers are in such an area and write combining | ||
171 | * or read caching is not desirable: | ||
172 | */ | ||
173 | extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size); | ||
174 | extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size); | ||
175 | extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size, | ||
176 | unsigned long prot_val); | ||
177 | |||
178 | /* | ||
179 | * The default ioremap() behavior is non-cached: | ||
180 | */ | ||
181 | static inline void __iomem *ioremap(resource_size_t offset, unsigned long size) | ||
182 | { | ||
183 | return ioremap_nocache(offset, size); | ||
184 | } | ||
185 | |||
186 | extern void iounmap(volatile void __iomem *addr); | ||
187 | |||
188 | extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); | ||
189 | |||
190 | /* | ||
191 | * ISA I/O bus memory addresses are 1:1 with the physical address. | ||
192 | */ | ||
193 | #define isa_virt_to_bus virt_to_phys | ||
194 | #define isa_page_to_bus page_to_phys | ||
195 | #define isa_bus_to_virt phys_to_virt | ||
196 | |||
197 | /* | ||
198 | * However PCI ones are not necessarily 1:1 and therefore these interfaces | ||
199 | * are forbidden in portable PCI drivers. | ||
200 | * | ||
201 | * Allow them on x86 for legacy drivers, though. | ||
202 | */ | ||
203 | #define virt_to_bus virt_to_phys | ||
204 | #define bus_to_virt phys_to_virt | ||
205 | |||
206 | void __memcpy_fromio(void *, unsigned long, unsigned); | ||
207 | void __memcpy_toio(unsigned long, const void *, unsigned); | ||
208 | |||
209 | static inline void memcpy_fromio(void *to, const volatile void __iomem *from, | ||
210 | unsigned len) | ||
211 | { | ||
212 | __memcpy_fromio(to, (unsigned long)from, len); | ||
213 | } | ||
214 | |||
215 | static inline void memcpy_toio(volatile void __iomem *to, const void *from, | ||
216 | unsigned len) | ||
217 | { | ||
218 | __memcpy_toio((unsigned long)to, from, len); | ||
219 | } | ||
220 | |||
221 | void memset_io(volatile void __iomem *a, int b, size_t c); | ||
222 | |||
223 | /* | ||
224 | * ISA space is 'always mapped' on a typical x86 system, no need to | ||
225 | * explicitly ioremap() it. The fact that the ISA IO space is mapped | ||
226 | * to PAGE_OFFSET is pure coincidence - it does not mean ISA values | ||
227 | * are physical addresses. The following constant pointer can be | ||
228 | * used as the IO-area pointer (it can be iounmapped as well, so the | ||
229 | * analogy with PCI is quite large): | ||
230 | */ | ||
231 | #define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET)) | ||
232 | |||
233 | #define flush_write_buffers() | ||
234 | |||
235 | #define BIO_VMERGE_BOUNDARY iommu_bio_merge | ||
236 | |||
237 | /* | ||
238 | * Convert a virtual cached pointer to an uncached pointer | ||
239 | */ | ||
240 | #define xlate_dev_kmem_ptr(p) p | ||
241 | |||
242 | #endif /* __KERNEL__ */ | ||
243 | |||
244 | #endif /* _ASM_X86_IO_64_H */ | ||