Home | History | Annotate | Download | only in asm-x86
      1 #ifndef _ASM_IO_H
      2 #define _ASM_IO_H
      3 
      4 #include <linux/string.h>
      5 #include <linux/compiler.h>
      6 
      7 /*
      8  * This file contains the definitions for the x86 IO instructions
      9  * inb/inw/inl/outb/outw/outl and the "string versions" of the same
     10  * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
     11  * versions of the single-IO instructions (inb_p/inw_p/..).
     12  *
     13  * This file is not meant to be obfuscating: it's just complicated
     14  * to (a) handle it all in a way that makes gcc able to optimize it
     15  * as well as possible and (b) trying to avoid writing the same thing
     16  * over and over again with slight variations and possibly making a
     17  * mistake somewhere.
     18  */
     19 
     20 /*
     21  * Thanks to James van Artsdalen for a better timing-fix than
     22  * the two short jumps: using outb's to a nonexistent port seems
     23  * to guarantee better timings even on fast machines.
     24  *
     25  * On the other hand, I'd like to be sure of a non-existent port:
     26  * I feel a bit unsafe about using 0x80 (should be safe, though)
     27  *
     28  *		Linus
     29  */
     30 
     31  /*
     32   *  Bit simplified and optimized by Jan Hubicka
     33   *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
     34   *
     35   *  isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added,
     36   *  isa_read[wl] and isa_write[wl] fixed
     37   *  - Arnaldo Carvalho de Melo <acme (at) conectiva.com.br>
     38   */
     39 
     40 #define IO_SPACE_LIMIT 0xffff
     41 
     42 #define XQUAD_PORTIO_BASE 0xfe400000
     43 #define XQUAD_PORTIO_QUAD 0x40000  /* 256k per quad. */
     44 
     45 #ifdef __KERNEL__
     46 
     47 #include <asm-generic/iomap.h>
     48 
     49 #include <linux/vmalloc.h>
     50 
     51 /*
     52  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
     53  * access
     54  */
     55 #define xlate_dev_mem_ptr(p)	__va(p)
     56 
     57 /*
     58  * Convert a virtual cached pointer to an uncached pointer
     59  */
     60 #define xlate_dev_kmem_ptr(p)	p
     61 
     62 /**
     63  *	virt_to_phys	-	map virtual addresses to physical
     64  *	@address: address to remap
     65  *
     66  *	The returned physical address is the physical (CPU) mapping for
     67  *	the memory address given. It is only valid to use this function on
     68  *	addresses directly mapped or allocated via kmalloc.
     69  *
     70  *	This function does not give bus mappings for DMA transfers. In
     71  *	almost all conceivable cases a device driver should not be using
     72  *	this function
     73  */
     74 
     75 static inline unsigned long virt_to_phys(volatile void * address)
     76 {
     77 	return __pa(address);
     78 }
     79 
     80 /**
     81  *	phys_to_virt	-	map physical address to virtual
     82  *	@address: address to remap
     83  *
     84  *	The returned virtual address is a current CPU mapping for
     85  *	the memory address given. It is only valid to use this function on
     86  *	addresses that have a kernel mapping
     87  *
     88  *	This function does not handle bus mappings for DMA transfers. In
     89  *	almost all conceivable cases a device driver should not be using
     90  *	this function
     91  */
     92 
     93 static inline void * phys_to_virt(unsigned long address)
     94 {
     95 	return __va(address);
     96 }
     97 
     98 /*
     99  * Change "struct page" to physical address.
    100  */
    101 #define page_to_phys(page)    ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
    102 
    103 extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
    104 
    105 /**
    106  * ioremap     -   map bus memory into CPU space
    107  * @offset:    bus address of the memory
    108  * @size:      size of the resource to map
    109  *
    110  * ioremap performs a platform specific sequence of operations to
    111  * make bus memory CPU accessible via the readb/readw/readl/writeb/
    112  * writew/writel functions and the other mmio helpers. The returned
    113  * address is not guaranteed to be usable directly as a virtual
    114  * address.
    115  *
    116  * If the area you are trying to map is a PCI BAR you should have a
    117  * look at pci_iomap().
    118  */
    119 
    120 static inline void __iomem * ioremap(unsigned long offset, unsigned long size)
    121 {
    122 	return __ioremap(offset, size, 0);
    123 }
    124 
    125 extern void __iomem * ioremap_nocache(unsigned long offset, unsigned long size);
    126 extern void iounmap(volatile void __iomem *addr);
    127 
    128 /*
    129  * bt_ioremap() and bt_iounmap() are for temporary early boot-time
    130  * mappings, before the real ioremap() is functional.
    131  * A boot-time mapping is currently limited to at most 16 pages.
    132  */
    133 extern void *bt_ioremap(unsigned long offset, unsigned long size);
    134 extern void bt_iounmap(void *addr, unsigned long size);
    135 extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
    136 
    137 /* Use early IO mappings for DMI because it's initialized early */
    138 #define dmi_ioremap bt_ioremap
    139 #define dmi_iounmap bt_iounmap
    140 #define dmi_alloc alloc_bootmem
    141 
    142 /*
    143  * ISA I/O bus memory addresses are 1:1 with the physical address.
    144  */
    145 #define isa_virt_to_bus virt_to_phys
    146 #define isa_page_to_bus page_to_phys
    147 #define isa_bus_to_virt phys_to_virt
    148 
    149 /*
    150  * However PCI ones are not necessarily 1:1 and therefore these interfaces
    151  * are forbidden in portable PCI drivers.
    152  *
    153  * Allow them on x86 for legacy drivers, though.
    154  */
    155 #define virt_to_bus virt_to_phys
    156 #define bus_to_virt phys_to_virt
    157 
    158 /*
    159  * readX/writeX() are used to access memory mapped devices. On some
    160  * architectures the memory mapped IO stuff needs to be accessed
    161  * differently. On the x86 architecture, we just read/write the
    162  * memory location directly.
    163  */
    164 
    165 static inline unsigned char readb(const volatile void __iomem *addr)
    166 {
    167 	return *(volatile unsigned char __force *) addr;
    168 }
    169 static inline unsigned short readw(const volatile void __iomem *addr)
    170 {
    171 	return *(volatile unsigned short __force *) addr;
    172 }
    173 static inline unsigned int readl(const volatile void __iomem *addr)
    174 {
    175 	return *(volatile unsigned int __force *) addr;
    176 }
    177 #define readb_relaxed(addr) readb(addr)
    178 #define readw_relaxed(addr) readw(addr)
    179 #define readl_relaxed(addr) readl(addr)
    180 #define __raw_readb readb
    181 #define __raw_readw readw
    182 #define __raw_readl readl
    183 
    184 static inline void writeb(unsigned char b, volatile void __iomem *addr)
    185 {
    186 	*(volatile unsigned char __force *) addr = b;
    187 }
    188 static inline void writew(unsigned short b, volatile void __iomem *addr)
    189 {
    190 	*(volatile unsigned short __force *) addr = b;
    191 }
    192 static inline void writel(unsigned int b, volatile void __iomem *addr)
    193 {
    194 	*(volatile unsigned int __force *) addr = b;
    195 }
    196 #define __raw_writeb writeb
    197 #define __raw_writew writew
    198 #define __raw_writel writel
    199 
    200 #define mmiowb()
    201 
    202 static inline void
    203 memset_io(volatile void __iomem *addr, unsigned char val, int count)
    204 {
    205 	memset((void __force *)addr, val, count);
    206 }
    207 
    208 static inline void
    209 memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
    210 {
    211 	__memcpy(dst, (const void __force *)src, count);
    212 }
    213 
    214 static inline void
    215 memcpy_toio(volatile void __iomem *dst, const void *src, int count)
    216 {
    217 	__memcpy((void __force *)dst, src, count);
    218 }
    219 
    220 /*
    221  * ISA space is 'always mapped' on a typical x86 system, no need to
    222  * explicitly ioremap() it. The fact that the ISA IO space is mapped
    223  * to PAGE_OFFSET is pure coincidence - it does not mean ISA values
    224  * are physical addresses. The following constant pointer can be
    225  * used as the IO-area pointer (it can be iounmapped as well, so the
    226  * analogy with PCI is quite large):
    227  */
    228 #define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
    229 
    230 /*
    231  *	Cache management
    232  *
    233  *	This needed for two cases
    234  *	1. Out of order aware processors
    235  *	2. Accidentally out of order processors (PPro errata #51)
    236  */
    237 
    238 #if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE)
    239 
    240 static inline void flush_write_buffers(void)
    241 {
    242 	__asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory");
    243 }
    244 
    245 #else
    246 
    247 #define flush_write_buffers() do { } while (0)
    248 
    249 #endif
    250 
    251 #endif /* __KERNEL__ */
    252 
    253 static inline void native_io_delay(void)
    254 {
    255 	asm volatile("outb %%al,$0x80" : : : "memory");
    256 }
    257 
    258 #if defined(CONFIG_PARAVIRT)
    259 #include <asm/paravirt.h>
    260 #else
    261 
    262 static inline void slow_down_io(void) {
    263 	native_io_delay();
    264 #ifdef REALLY_SLOW_IO
    265 	native_io_delay();
    266 	native_io_delay();
    267 	native_io_delay();
    268 #endif
    269 }
    270 
    271 #endif
    272 
    273 #ifdef CONFIG_X86_NUMAQ
    274 extern void *xquad_portio;    /* Where the IO area was mapped */
    275 #define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)
    276 #define __BUILDIO(bwl,bw,type) \
    277 static inline void out##bwl##_quad(unsigned type value, int port, int quad) { \
    278 	if (xquad_portio) \
    279 		write##bwl(value, XQUAD_PORT_ADDR(port, quad)); \
    280 	else \
    281 		out##bwl##_local(value, port); \
    282 } \
    283 static inline void out##bwl(unsigned type value, int port) { \
    284 	out##bwl##_quad(value, port, 0); \
    285 } \
    286 static inline unsigned type in##bwl##_quad(int port, int quad) { \
    287 	if (xquad_portio) \
    288 		return read##bwl(XQUAD_PORT_ADDR(port, quad)); \
    289 	else \
    290 		return in##bwl##_local(port); \
    291 } \
    292 static inline unsigned type in##bwl(int port) { \
    293 	return in##bwl##_quad(port, 0); \
    294 }
    295 #else
    296 #define __BUILDIO(bwl,bw,type) \
    297 static inline void out##bwl(unsigned type value, int port) { \
    298 	out##bwl##_local(value, port); \
    299 } \
    300 static inline unsigned type in##bwl(int port) { \
    301 	return in##bwl##_local(port); \
    302 }
    303 #endif
    304 
    305 
    306 #define BUILDIO(bwl,bw,type) \
    307 static inline void out##bwl##_local(unsigned type value, int port) { \
    308 	__asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \
    309 } \
    310 static inline unsigned type in##bwl##_local(int port) { \
    311 	unsigned type value; \
    312 	__asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \
    313 	return value; \
    314 } \
    315 static inline void out##bwl##_local_p(unsigned type value, int port) { \
    316 	out##bwl##_local(value, port); \
    317 	slow_down_io(); \
    318 } \
    319 static inline unsigned type in##bwl##_local_p(int port) { \
    320 	unsigned type value = in##bwl##_local(port); \
    321 	slow_down_io(); \
    322 	return value; \
    323 } \
    324 __BUILDIO(bwl,bw,type) \
    325 static inline void out##bwl##_p(unsigned type value, int port) { \
    326 	out##bwl(value, port); \
    327 	slow_down_io(); \
    328 } \
    329 static inline unsigned type in##bwl##_p(int port) { \
    330 	unsigned type value = in##bwl(port); \
    331 	slow_down_io(); \
    332 	return value; \
    333 } \
    334 static inline void outs##bwl(int port, const void *addr, unsigned long count) { \
    335 	__asm__ __volatile__("rep; outs" #bwl : "+S"(addr), "+c"(count) : "d"(port)); \
    336 } \
    337 static inline void ins##bwl(int port, void *addr, unsigned long count) { \
    338 	__asm__ __volatile__("rep; ins" #bwl : "+D"(addr), "+c"(count) : "d"(port)); \
    339 }
    340 
    341 BUILDIO(b,b,char)
    342 BUILDIO(w,w,short)
    343 BUILDIO(l,,int)
    344 
    345 #endif
    346