File: /usr/src/linux/include/asm-ia64/io.h

1     #ifndef _ASM_IA64_IO_H
2     #define _ASM_IA64_IO_H
3     
4     /*
5      * This file contains the definitions for the emulated 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 to
11      * (a) handle it all in a way that makes gcc able to optimize it as
12      * 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      * Copyright (C) 1998-2001 Hewlett-Packard Co
17      * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
18      * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
19      * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
20      */
21     
22     /* We don't use IO slowdowns on the ia64, but.. */
23     #define __SLOW_DOWN_IO	do { } while (0)
24     #define SLOW_DOWN_IO	do { } while (0)
25     
26     #define __IA64_UNCACHED_OFFSET	0xc000000000000000	/* region 6 */
27     
28     #define IO_SPACE_LIMIT 0xffff
29     
30     # ifdef __KERNEL__
31     
32     #include <asm/machvec.h>
33     #include <asm/page.h>
34     #include <asm/system.h>
35     
36     /*
37      * Change virtual addresses to physical addresses and vv.
38      */
39     static inline unsigned long
40     virt_to_phys (volatile void *address)
41     {
42     	return (unsigned long) address - PAGE_OFFSET;
43     }
44     
45     static inline void*
46     phys_to_virt(unsigned long address)
47     {
48     	return (void *) (address + PAGE_OFFSET);
49     }
50     
51     /*
52      * The following two macros are deprecated and scheduled for removal.
53      * Please use the PCI-DMA interface defined in <asm/pci.h> instead.
54      */
55     #define bus_to_virt	phys_to_virt
56     #define virt_to_bus	virt_to_phys
57     
58     # endif /* KERNEL */
59     
60     /*
61      * Memory fence w/accept.  This should never be used in code that is
62      * not IA-64 specific.
63      */
64     #define __ia64_mf_a()	__asm__ __volatile__ ("mf.a" ::: "memory")
65     
66     static inline const unsigned long
67     __ia64_get_io_port_base (void)
68     {
69     	extern unsigned long ia64_iobase;
70     
71     	return ia64_iobase;
72     }
73     
74     static inline void*
75     __ia64_mk_io_addr (unsigned long port)
76     {
77     	const unsigned long io_base = __ia64_get_io_port_base();
78     	unsigned long addr;
79     
80     	addr = io_base | ((port >> 2) << 12) | (port & 0xfff);
81     	return (void *) addr;
82     }
83     
84     /*
85      * For the in/out routines, we need to do "mf.a" _after_ doing the I/O access to ensure
86      * that the access has completed before executing other I/O accesses.  Since we're doing
87      * the accesses through an uncachable (UC) translation, the CPU will execute them in
88      * program order.  However, we still need to tell the compiler not to shuffle them around
89      * during optimization, which is why we use "volatile" pointers.
90      */
91     
92     static inline unsigned int
93     __ia64_inb (unsigned long port)
94     {
95     	volatile unsigned char *addr = __ia64_mk_io_addr(port);
96     	unsigned char ret;
97     
98     	ret = *addr;
99     	__ia64_mf_a();
100     	return ret;
101     }
102     
103     static inline unsigned int
104     __ia64_inw (unsigned long port)
105     {
106     	volatile unsigned short *addr = __ia64_mk_io_addr(port);
107     	unsigned short ret;
108     
109     	ret = *addr;
110     	__ia64_mf_a();
111     	return ret;
112     }
113     
114     static inline unsigned int
115     __ia64_inl (unsigned long port)
116     {
117     	volatile unsigned int *addr = __ia64_mk_io_addr(port);
118     	unsigned int ret;
119     
120     	ret = *addr;
121     	__ia64_mf_a();
122     	return ret;
123     }
124     
125     static inline void
126     __ia64_outb (unsigned char val, unsigned long port)
127     {
128     	volatile unsigned char *addr = __ia64_mk_io_addr(port);
129     
130     	*addr = val;
131     	__ia64_mf_a();
132     }
133     
134     static inline void
135     __ia64_outw (unsigned short val, unsigned long port)
136     {
137     	volatile unsigned short *addr = __ia64_mk_io_addr(port);
138     
139     	*addr = val;
140     	__ia64_mf_a();
141     }
142     
143     static inline void
144     __ia64_outl (unsigned int val, unsigned long port)
145     {
146     	volatile unsigned int *addr = __ia64_mk_io_addr(port);
147     
148     	*addr = val;
149     	__ia64_mf_a();
150     }
151     
152     static inline void
153     __insb (unsigned long port, void *dst, unsigned long count)
154     {
155     	unsigned char *dp = dst;
156     
157     	if (platform_inb == __ia64_inb) {
158     		volatile unsigned char *addr = __ia64_mk_io_addr(port);
159     
160     		__ia64_mf_a();
161     		while (count--)
162     			*dp++ = *addr;
163     		__ia64_mf_a();
164     	} else
165     		while (count--)
166     			*dp++ = platform_inb(port);
167     	return;
168     }
169     
170     static inline void
171     __insw (unsigned long port, void *dst, unsigned long count)
172     {
173     	unsigned short *dp = dst;
174     
175     	if (platform_inw == __ia64_inw) {
176     		volatile unsigned short *addr = __ia64_mk_io_addr(port);
177     
178     		__ia64_mf_a();
179     		while (count--)
180     			*dp++ = *addr;
181     		__ia64_mf_a();
182     	} else
183     		while (count--)
184     			*dp++ = platform_inw(port);
185     	return;
186     }
187     
188     static inline void
189     __insl (unsigned long port, void *dst, unsigned long count)
190     {
191     	unsigned int *dp = dst;
192     
193     	if (platform_inl == __ia64_inl) {
194     		volatile unsigned int *addr = __ia64_mk_io_addr(port);
195     
196     		__ia64_mf_a();
197     		while (count--)
198     			*dp++ = *addr;
199     		__ia64_mf_a();
200     	} else
201     		while (count--)
202     			*dp++ = platform_inl(port);
203     	return;
204     }
205     
206     static inline void
207     __outsb (unsigned long port, const void *src, unsigned long count)
208     {
209     	const unsigned char *sp = src;
210     
211     	if (platform_outb == __ia64_outb) {
212     		volatile unsigned char *addr = __ia64_mk_io_addr(port);
213     
214     		while (count--)
215     			*addr = *sp++;
216     		__ia64_mf_a();
217     	} else
218     		while (count--)
219     			platform_outb(*sp++, port);
220     	return;
221     }
222     
223     static inline void
224     __outsw (unsigned long port, const void *src, unsigned long count)
225     {
226     	const unsigned short *sp = src;
227     
228     	if (platform_outw == __ia64_outw) {
229     		volatile unsigned short *addr = __ia64_mk_io_addr(port);
230     
231     		while (count--)
232     			*addr = *sp++;
233     		__ia64_mf_a();
234     	} else
235     		while (count--)
236     			platform_outw(*sp++, port);
237     	return;
238     }
239     
240     static inline void
241     __outsl (unsigned long port, void *src, unsigned long count)
242     {
243     	const unsigned int *sp = src;
244     
245     	if (platform_outl == __ia64_outl) {
246     		volatile unsigned int *addr = __ia64_mk_io_addr(port);
247     
248     		while (count--)
249     			*addr = *sp++;
250     		__ia64_mf_a();
251     	} else
252     		while (count--)
253     			platform_outl(*sp++, port);
254     	return;
255     }
256     
257     /*
258      * Unfortunately, some platforms are broken and do not follow the
259      * IA-64 architecture specification regarding legacy I/O support.
260      * Thus, we have to make these operations platform dependent...
261      */
262     #define __inb		platform_inb
263     #define __inw		platform_inw
264     #define __inl		platform_inl
265     #define __outb		platform_outb
266     #define __outw		platform_outw
267     #define __outl		platform_outl
268     
269     #define inb		__inb
270     #define inw		__inw
271     #define inl		__inl
272     #define insb		__insb
273     #define insw		__insw
274     #define insl		__insl
275     #define outb		__outb
276     #define outw		__outw
277     #define outl		__outl
278     #define outsb		__outsb
279     #define outsw		__outsw
280     #define outsl		__outsl
281     
282     /*
283      * The address passed to these functions are ioremap()ped already.
284      */
285     static inline unsigned char
286     __readb (void *addr)
287     {
288     	return *(volatile unsigned char *)addr;
289     }
290     
291     static inline unsigned short
292     __readw (void *addr)
293     {
294     	return *(volatile unsigned short *)addr;
295     }
296     
297     static inline unsigned int
298     __readl (void *addr)
299     {
300     	return *(volatile unsigned int *) addr;
301     }
302     
303     static inline unsigned long
304     __readq (void *addr)
305     {
306     	return *(volatile unsigned long *) addr;
307     }
308     
309     static inline void
310     __writeb (unsigned char val, void *addr)
311     {
312     	*(volatile unsigned char *) addr = val;
313     }
314     
315     static inline void
316     __writew (unsigned short val, void *addr)
317     {
318     	*(volatile unsigned short *) addr = val;
319     }
320     
321     static inline void
322     __writel (unsigned int val, void *addr)
323     {
324     	*(volatile unsigned int *) addr = val;
325     }
326     
327     static inline void
328     __writeq (unsigned long val, void *addr)
329     {
330     	*(volatile unsigned long *) addr = val;
331     }
332     
333     #define readb(a)	__readb((void *)(a))
334     #define readw(a)	__readw((void *)(a))
335     #define readl(a)	__readl((void *)(a))
336     #define readq(a)	__readq((void *)(a))
337     #define __raw_readb	readb
338     #define __raw_readw	readw
339     #define __raw_readl	readl
340     #define __raw_readq	readq
341     #define writeb(v,a)	__writeb((v), (void *) (a))
342     #define writew(v,a)	__writew((v), (void *) (a))
343     #define writel(v,a)	__writel((v), (void *) (a))
344     #define writeq(v,a)	__writeq((v), (void *) (a))
345     #define __raw_writeb	writeb
346     #define __raw_writew	writew
347     #define __raw_writel	writel
348     #define __raw_writeq	writeq
349     
350     #ifndef inb_p
351     # define inb_p		inb
352     #endif
353     #ifndef inw_p
354     # define inw_p		inw
355     #endif
356     #ifndef inl_p
357     # define inl_p		inl
358     #endif
359     
360     #ifndef outb_p
361     # define outb_p		outb
362     #endif
363     #ifndef outw_p
364     # define outw_p		outw
365     #endif
366     #ifndef outl_p
367     # define outl_p		outl
368     #endif
369     
370     /*
371      * An "address" in IO memory space is not clearly either an integer or a pointer. We will
372      * accept both, thus the casts.
373      *
374      * On ia-64, we access the physical I/O memory space through the uncached kernel region.
375      */
376     static inline void *
377     ioremap (unsigned long offset, unsigned long size)
378     {
379     	return (void *) (__IA64_UNCACHED_OFFSET | (offset));
380     }
381     
382     static inline void
383     iounmap (void *addr)
384     {
385     }
386     
387     #define ioremap_nocache(o,s)	ioremap(o,s)
388     
389     # ifdef __KERNEL__
390     
391     /*
392      * String version of IO memory access ops:
393      */
394     extern void __ia64_memcpy_fromio (void *, unsigned long, long);
395     extern void __ia64_memcpy_toio (unsigned long, void *, long);
396     extern void __ia64_memset_c_io (unsigned long, unsigned long, long);
397     
398     #define memcpy_fromio(to,from,len) \
399       __ia64_memcpy_fromio((to),(unsigned long)(from),(len))
400     #define memcpy_toio(to,from,len) \
401       __ia64_memcpy_toio((unsigned long)(to),(from),(len))
402     #define memset_io(addr,c,len) \
403       __ia64_memset_c_io((unsigned long)(addr),0x0101010101010101UL*(u8)(c),(len))
404     
405     # endif /* __KERNEL__ */
406     #endif /* _ASM_IA64_IO_H */
407