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