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