1fea25720SGraeme Russ #ifndef _ASM_IO_H 2fea25720SGraeme Russ #define _ASM_IO_H 3fea25720SGraeme Russ 4fea25720SGraeme Russ /* 5fea25720SGraeme Russ * This file contains the definitions for the x86 IO instructions 6fea25720SGraeme Russ * inb/inw/inl/outb/outw/outl and the "string versions" of the same 7fea25720SGraeme Russ * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" 8fea25720SGraeme Russ * versions of the single-IO instructions (inb_p/inw_p/..). 9fea25720SGraeme Russ * 10fea25720SGraeme Russ * This file is not meant to be obfuscating: it's just complicated 11fea25720SGraeme Russ * to (a) handle it all in a way that makes gcc able to optimize it 12fea25720SGraeme Russ * as well as possible and (b) trying to avoid writing the same thing 13fea25720SGraeme Russ * over and over again with slight variations and possibly making a 14fea25720SGraeme Russ * mistake somewhere. 15fea25720SGraeme Russ */ 16fea25720SGraeme Russ 17fea25720SGraeme Russ /* 18fea25720SGraeme Russ * Thanks to James van Artsdalen for a better timing-fix than 19fea25720SGraeme Russ * the two short jumps: using outb's to a nonexistent port seems 20fea25720SGraeme Russ * to guarantee better timings even on fast machines. 21fea25720SGraeme Russ * 22fea25720SGraeme Russ * On the other hand, I'd like to be sure of a non-existent port: 23fea25720SGraeme Russ * I feel a bit unsafe about using 0x80 (should be safe, though) 24fea25720SGraeme Russ * 25fea25720SGraeme Russ * Linus 26fea25720SGraeme Russ */ 27fea25720SGraeme Russ 28fea25720SGraeme Russ /* 29fea25720SGraeme Russ * Bit simplified and optimized by Jan Hubicka 30fea25720SGraeme Russ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999. 31fea25720SGraeme Russ * 32fea25720SGraeme Russ * isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added, 33fea25720SGraeme Russ * isa_read[wl] and isa_write[wl] fixed 34fea25720SGraeme Russ * - Arnaldo Carvalho de Melo <acme@conectiva.com.br> 35fea25720SGraeme Russ */ 36fea25720SGraeme Russ 37fea25720SGraeme Russ #define IO_SPACE_LIMIT 0xffff 38fea25720SGraeme Russ 39fea25720SGraeme Russ 40fea25720SGraeme Russ #ifdef __KERNEL__ 41fea25720SGraeme Russ 42fea25720SGraeme Russ 43fea25720SGraeme Russ /* 44fea25720SGraeme Russ * readX/writeX() are used to access memory mapped devices. On some 45fea25720SGraeme Russ * architectures the memory mapped IO stuff needs to be accessed 46fea25720SGraeme Russ * differently. On the x86 architecture, we just read/write the 47fea25720SGraeme Russ * memory location directly. 48fea25720SGraeme Russ */ 49fea25720SGraeme Russ 50fea25720SGraeme Russ #define readb(addr) (*(volatile unsigned char *) (addr)) 51fea25720SGraeme Russ #define readw(addr) (*(volatile unsigned short *) (addr)) 52fea25720SGraeme Russ #define readl(addr) (*(volatile unsigned int *) (addr)) 53fea25720SGraeme Russ #define __raw_readb readb 54fea25720SGraeme Russ #define __raw_readw readw 55fea25720SGraeme Russ #define __raw_readl readl 56fea25720SGraeme Russ 57fea25720SGraeme Russ #define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b)) 58fea25720SGraeme Russ #define writew(b,addr) (*(volatile unsigned short *) (addr) = (b)) 59fea25720SGraeme Russ #define writel(b,addr) (*(volatile unsigned int *) (addr) = (b)) 60fea25720SGraeme Russ #define __raw_writeb writeb 61fea25720SGraeme Russ #define __raw_writew writew 62fea25720SGraeme Russ #define __raw_writel writel 63fea25720SGraeme Russ 64fea25720SGraeme Russ #define memset_io(a,b,c) memset((a),(b),(c)) 65fea25720SGraeme Russ #define memcpy_fromio(a,b,c) memcpy((a),(b),(c)) 66fea25720SGraeme Russ #define memcpy_toio(a,b,c) memcpy((a),(b),(c)) 67fea25720SGraeme Russ 68fea25720SGraeme Russ /* 69fea25720SGraeme Russ * ISA space is 'always mapped' on a typical x86 system, no need to 70fea25720SGraeme Russ * explicitly ioremap() it. The fact that the ISA IO space is mapped 71fea25720SGraeme Russ * to PAGE_OFFSET is pure coincidence - it does not mean ISA values 72fea25720SGraeme Russ * are physical addresses. The following constant pointer can be 73fea25720SGraeme Russ * used as the IO-area pointer (it can be iounmapped as well, so the 74fea25720SGraeme Russ * analogy with PCI is quite large): 75fea25720SGraeme Russ */ 76fea25720SGraeme Russ #define isa_readb(a) readb((a)) 77fea25720SGraeme Russ #define isa_readw(a) readw((a)) 78fea25720SGraeme Russ #define isa_readl(a) readl((a)) 79fea25720SGraeme Russ #define isa_writeb(b,a) writeb(b,(a)) 80fea25720SGraeme Russ #define isa_writew(w,a) writew(w,(a)) 81fea25720SGraeme Russ #define isa_writel(l,a) writel(l,(a)) 82fea25720SGraeme Russ #define isa_memset_io(a,b,c) memset_io((a),(b),(c)) 83fea25720SGraeme Russ #define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),(b),(c)) 84fea25720SGraeme Russ #define isa_memcpy_toio(a,b,c) memcpy_toio((a),(b),(c)) 85fea25720SGraeme Russ 86fea25720SGraeme Russ 87fea25720SGraeme Russ static inline int check_signature(unsigned long io_addr, 88fea25720SGraeme Russ const unsigned char *signature, int length) 89fea25720SGraeme Russ { 90fea25720SGraeme Russ int retval = 0; 91fea25720SGraeme Russ do { 92fea25720SGraeme Russ if (readb(io_addr) != *signature) 93fea25720SGraeme Russ goto out; 94fea25720SGraeme Russ io_addr++; 95fea25720SGraeme Russ signature++; 96fea25720SGraeme Russ length--; 97fea25720SGraeme Russ } while (length); 98fea25720SGraeme Russ retval = 1; 99fea25720SGraeme Russ out: 100fea25720SGraeme Russ return retval; 101fea25720SGraeme Russ } 102fea25720SGraeme Russ 103fea25720SGraeme Russ /** 104fea25720SGraeme Russ * isa_check_signature - find BIOS signatures 105fea25720SGraeme Russ * @io_addr: mmio address to check 106fea25720SGraeme Russ * @signature: signature block 107fea25720SGraeme Russ * @length: length of signature 108fea25720SGraeme Russ * 109fea25720SGraeme Russ * Perform a signature comparison with the ISA mmio address io_addr. 110fea25720SGraeme Russ * Returns 1 on a match. 111fea25720SGraeme Russ * 112fea25720SGraeme Russ * This function is deprecated. New drivers should use ioremap and 113fea25720SGraeme Russ * check_signature. 114fea25720SGraeme Russ */ 115fea25720SGraeme Russ 116fea25720SGraeme Russ 117fea25720SGraeme Russ static inline int isa_check_signature(unsigned long io_addr, 118fea25720SGraeme Russ const unsigned char *signature, int length) 119fea25720SGraeme Russ { 120fea25720SGraeme Russ int retval = 0; 121fea25720SGraeme Russ do { 122fea25720SGraeme Russ if (isa_readb(io_addr) != *signature) 123fea25720SGraeme Russ goto out; 124fea25720SGraeme Russ io_addr++; 125fea25720SGraeme Russ signature++; 126fea25720SGraeme Russ length--; 127fea25720SGraeme Russ } while (length); 128fea25720SGraeme Russ retval = 1; 129fea25720SGraeme Russ out: 130fea25720SGraeme Russ return retval; 131fea25720SGraeme Russ } 132fea25720SGraeme Russ 133fea25720SGraeme Russ #endif /* __KERNEL__ */ 134fea25720SGraeme Russ 135fea25720SGraeme Russ #ifdef SLOW_IO_BY_JUMPING 136fea25720SGraeme Russ #define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:" 137fea25720SGraeme Russ #else 138fea25720SGraeme Russ #define __SLOW_DOWN_IO "\noutb %%al,$0x80" 139fea25720SGraeme Russ #endif 140fea25720SGraeme Russ 141fea25720SGraeme Russ #ifdef REALLY_SLOW_IO 142fea25720SGraeme Russ #define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO 143fea25720SGraeme Russ #else 144fea25720SGraeme Russ #define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO 145fea25720SGraeme Russ #endif 146fea25720SGraeme Russ 147fea25720SGraeme Russ 148fea25720SGraeme Russ /* 149fea25720SGraeme Russ * Talk about misusing macros.. 150fea25720SGraeme Russ */ 151fea25720SGraeme Russ #define __OUT1(s,x) \ 152fea25720SGraeme Russ static inline void out##s(unsigned x value, unsigned short port) { 153fea25720SGraeme Russ 154fea25720SGraeme Russ #define __OUT2(s,s1,s2) \ 155fea25720SGraeme Russ __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" 156fea25720SGraeme Russ 157fea25720SGraeme Russ 158fea25720SGraeme Russ #define __OUT(s,s1,x) \ 159fea25720SGraeme Russ __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \ 160fea25720SGraeme Russ __OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} 161fea25720SGraeme Russ 162fea25720SGraeme Russ #define __IN1(s) \ 163fea25720SGraeme Russ static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v; 164fea25720SGraeme Russ 165fea25720SGraeme Russ #define __IN2(s,s1,s2) \ 166fea25720SGraeme Russ __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" 167fea25720SGraeme Russ 168fea25720SGraeme Russ #define __IN(s,s1,i...) \ 169fea25720SGraeme Russ __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \ 170fea25720SGraeme Russ __IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } 171fea25720SGraeme Russ 172fea25720SGraeme Russ #define __INS(s) \ 173fea25720SGraeme Russ static inline void ins##s(unsigned short port, void * addr, unsigned long count) \ 174fea25720SGraeme Russ { __asm__ __volatile__ ("rep ; ins" #s \ 175fea25720SGraeme Russ : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } 176fea25720SGraeme Russ 177fea25720SGraeme Russ #define __OUTS(s) \ 178fea25720SGraeme Russ static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ 179fea25720SGraeme Russ { __asm__ __volatile__ ("rep ; outs" #s \ 180fea25720SGraeme Russ : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } 181fea25720SGraeme Russ 182fea25720SGraeme Russ #define RETURN_TYPE unsigned char 183fea25720SGraeme Russ __IN(b,"") 184fea25720SGraeme Russ #undef RETURN_TYPE 185fea25720SGraeme Russ #define RETURN_TYPE unsigned short 186fea25720SGraeme Russ __IN(w,"") 187fea25720SGraeme Russ #undef RETURN_TYPE 188fea25720SGraeme Russ #define RETURN_TYPE unsigned int 189fea25720SGraeme Russ __IN(l,"") 190fea25720SGraeme Russ #undef RETURN_TYPE 191fea25720SGraeme Russ 192fea25720SGraeme Russ __OUT(b,"b",char) 193fea25720SGraeme Russ __OUT(w,"w",short) 194fea25720SGraeme Russ __OUT(l,,int) 195fea25720SGraeme Russ 196fea25720SGraeme Russ __INS(b) 197fea25720SGraeme Russ __INS(w) 198fea25720SGraeme Russ __INS(l) 199fea25720SGraeme Russ 200fea25720SGraeme Russ __OUTS(b) 201fea25720SGraeme Russ __OUTS(w) 202fea25720SGraeme Russ __OUTS(l) 203fea25720SGraeme Russ 204fea25720SGraeme Russ static inline void sync(void) 205fea25720SGraeme Russ { 206fea25720SGraeme Russ } 207fea25720SGraeme Russ 208fea25720SGraeme Russ /* 209fea25720SGraeme Russ * Given a physical address and a length, return a virtual address 210fea25720SGraeme Russ * that can be used to access the memory range with the caching 211fea25720SGraeme Russ * properties specified by "flags". 212fea25720SGraeme Russ */ 213fea25720SGraeme Russ #define MAP_NOCACHE (0) 214fea25720SGraeme Russ #define MAP_WRCOMBINE (0) 215fea25720SGraeme Russ #define MAP_WRBACK (0) 216fea25720SGraeme Russ #define MAP_WRTHROUGH (0) 217fea25720SGraeme Russ 218fea25720SGraeme Russ static inline void * 219fea25720SGraeme Russ map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) 220fea25720SGraeme Russ { 221fea25720SGraeme Russ return (void *)paddr; 222fea25720SGraeme Russ } 223fea25720SGraeme Russ 224fea25720SGraeme Russ /* 225fea25720SGraeme Russ * Take down a mapping set up by map_physmem(). 226fea25720SGraeme Russ */ 227fea25720SGraeme Russ static inline void unmap_physmem(void *vaddr, unsigned long flags) 228fea25720SGraeme Russ { 229fea25720SGraeme Russ 230fea25720SGraeme Russ } 231fea25720SGraeme Russ 232fea25720SGraeme Russ static inline phys_addr_t virt_to_phys(void * vaddr) 233fea25720SGraeme Russ { 234fea25720SGraeme Russ return (phys_addr_t)(vaddr); 235fea25720SGraeme Russ } 236fea25720SGraeme Russ 237*8a487a44SSimon Glass /* 238*8a487a44SSimon Glass * TODO: The kernel offers some more advanced versions of barriers, it might 239*8a487a44SSimon Glass * have some advantages to use them instead of the simple one here. 240*8a487a44SSimon Glass */ 241*8a487a44SSimon Glass #define dmb() __asm__ __volatile__ ("" : : : "memory") 242*8a487a44SSimon Glass #define __iormb() dmb() 243*8a487a44SSimon Glass #define __iowmb() dmb() 244*8a487a44SSimon Glass 245fea25720SGraeme Russ #endif 246