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