io.h
来自「linux 内核源代码」· C头文件 代码 · 共 749 行 · 第 1/2 页
H
749 行
#ifndef _ASM_POWERPC_IO_H#define _ASM_POWERPC_IO_H#ifdef __KERNEL__/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. *//* Check of existence of legacy devices */extern int check_legacy_ioport(unsigned long base_port);#define I8042_DATA_REG 0x60#define FDC_BASE 0x3f0/* only relevant for PReP */#define _PIDXR 0x279#define _PNPWRP 0xa79#define PNPBIOS_BASE 0xf000#include <linux/compiler.h>#include <asm/page.h>#include <asm/byteorder.h>#include <asm/synch.h>#include <asm/delay.h>#include <asm/mmu.h>#include <asm-generic/iomap.h>#ifdef CONFIG_PPC64#include <asm/paca.h>#endif#define SIO_CONFIG_RA 0x398#define SIO_CONFIG_RD 0x399#define SLOW_DOWN_IO/* 32 bits uses slightly different variables for the various IO * bases. Most of this file only uses _IO_BASE though which we * define properly based on the platform */#ifndef CONFIG_PCI#define _IO_BASE 0#define _ISA_MEM_BASE 0#define PCI_DRAM_OFFSET 0#elif defined(CONFIG_PPC32)#define _IO_BASE isa_io_base#define _ISA_MEM_BASE isa_mem_base#define PCI_DRAM_OFFSET pci_dram_offset#else#define _IO_BASE pci_io_base#define _ISA_MEM_BASE 0#define PCI_DRAM_OFFSET 0#endifextern unsigned long isa_io_base;extern unsigned long isa_mem_base;extern unsigned long pci_io_base;extern unsigned long pci_dram_offset;#if defined(CONFIG_PPC32) && defined(CONFIG_PPC_INDIRECT_IO)#error CONFIG_PPC_INDIRECT_IO is not yet supported on 32 bits#endif/* * * Low level MMIO accessors * * This provides the non-bus specific accessors to MMIO. Those are PowerPC * specific and thus shouldn't be used in generic code. The accessors * provided here are: * * in_8, in_le16, in_be16, in_le32, in_be32, in_le64, in_be64 * out_8, out_le16, out_be16, out_le32, out_be32, out_le64, out_be64 * _insb, _insw_ns, _insl_ns, _outsb, _outsw_ns, _outsl_ns * * Those operate directly on a kernel virtual address. Note that the prototype * for the out_* accessors has the arguments in opposite order from the usual * linux PCI accessors. Unlike those, they take the address first and the value * next. * * Note: I might drop the _ns suffix on the stream operations soon as it is * simply normal for stream operations to not swap in the first place. * */#ifdef CONFIG_PPC64#define IO_SET_SYNC_FLAG() do { local_paca->io_sync = 1; } while(0)#else#define IO_SET_SYNC_FLAG()#endif#define DEF_MMIO_IN(name, type, insn) \static inline type name(const volatile type __iomem *addr) \{ \ type ret; \ __asm__ __volatile__("sync;" insn ";twi 0,%0,0;isync" \ : "=r" (ret) : "r" (addr), "m" (*addr)); \ return ret; \}#define DEF_MMIO_OUT(name, type, insn) \static inline void name(volatile type __iomem *addr, type val) \{ \ __asm__ __volatile__("sync;" insn \ : "=m" (*addr) : "r" (val), "r" (addr)); \ IO_SET_SYNC_FLAG(); \}#define DEF_MMIO_IN_BE(name, size, insn) \ DEF_MMIO_IN(name, u##size, __stringify(insn)"%U2%X2 %0,%2")#define DEF_MMIO_IN_LE(name, size, insn) \ DEF_MMIO_IN(name, u##size, __stringify(insn)" %0,0,%1")#define DEF_MMIO_OUT_BE(name, size, insn) \ DEF_MMIO_OUT(name, u##size, __stringify(insn)"%U0%X0 %1,%0")#define DEF_MMIO_OUT_LE(name, size, insn) \ DEF_MMIO_OUT(name, u##size, __stringify(insn)" %1,0,%2")DEF_MMIO_IN_BE(in_8, 8, lbz);DEF_MMIO_IN_BE(in_be16, 16, lhz);DEF_MMIO_IN_BE(in_be32, 32, lwz);DEF_MMIO_IN_LE(in_le16, 16, lhbrx);DEF_MMIO_IN_LE(in_le32, 32, lwbrx);DEF_MMIO_OUT_BE(out_8, 8, stb);DEF_MMIO_OUT_BE(out_be16, 16, sth);DEF_MMIO_OUT_BE(out_be32, 32, stw);DEF_MMIO_OUT_LE(out_le16, 16, sthbrx);DEF_MMIO_OUT_LE(out_le32, 32, stwbrx);#ifdef __powerpc64__DEF_MMIO_OUT_BE(out_be64, 64, std);DEF_MMIO_IN_BE(in_be64, 64, ld);/* There is no asm instructions for 64 bits reverse loads and stores */static inline u64 in_le64(const volatile u64 __iomem *addr){ return swab64(in_be64(addr));}static inline void out_le64(volatile u64 __iomem *addr, u64 val){ out_be64(addr, swab64(val));}#endif /* __powerpc64__ *//* * Low level IO stream instructions are defined out of line for now */extern void _insb(const volatile u8 __iomem *addr, void *buf, long count);extern void _outsb(volatile u8 __iomem *addr,const void *buf,long count);extern void _insw_ns(const volatile u16 __iomem *addr, void *buf, long count);extern void _outsw_ns(volatile u16 __iomem *addr, const void *buf, long count);extern void _insl_ns(const volatile u32 __iomem *addr, void *buf, long count);extern void _outsl_ns(volatile u32 __iomem *addr, const void *buf, long count);/* The _ns naming is historical and will be removed. For now, just #define * the non _ns equivalent names */#define _insw _insw_ns#define _insl _insl_ns#define _outsw _outsw_ns#define _outsl _outsl_ns/* * memset_io, memcpy_toio, memcpy_fromio base implementations are out of line */extern void _memset_io(volatile void __iomem *addr, int c, unsigned long n);extern void _memcpy_fromio(void *dest, const volatile void __iomem *src, unsigned long n);extern void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n);/* * * PCI and standard ISA accessors * * Those are globally defined linux accessors for devices on PCI or ISA * busses. They follow the Linux defined semantics. The current implementation * for PowerPC is as close as possible to the x86 version of these, and thus * provides fairly heavy weight barriers for the non-raw versions * * In addition, they support a hook mechanism when CONFIG_PPC_INDIRECT_IO * allowing the platform to provide its own implementation of some or all * of the accessors. *//* * Include the EEH definitions when EEH is enabled only so they don't get * in the way when building for 32 bits */#ifdef CONFIG_EEH#include <asm/eeh.h>#endif/* Shortcut to the MMIO argument pointer */#define PCI_IO_ADDR volatile void __iomem */* Indirect IO address tokens: * * When CONFIG_PPC_INDIRECT_IO is set, the platform can provide hooks * on all IOs. (Note that this is all 64 bits only for now) * * To help platforms who may need to differenciate MMIO addresses in * their hooks, a bitfield is reserved for use by the platform near the * top of MMIO addresses (not PIO, those have to cope the hard way). * * This bit field is 12 bits and is at the top of the IO virtual * addresses PCI_IO_INDIRECT_TOKEN_MASK. * * The kernel virtual space is thus: * * 0xD000000000000000 : vmalloc * 0xD000080000000000 : PCI PHB IO space * 0xD000080080000000 : ioremap * 0xD0000fffffffffff : end of ioremap region * * Since the top 4 bits are reserved as the region ID, we use thus * the next 12 bits and keep 4 bits available for the future if the * virtual address space is ever to be extended. * * The direct IO mapping operations will then mask off those bits * before doing the actual access, though that only happen when * CONFIG_PPC_INDIRECT_IO is set, thus be careful when you use that * mechanism */#ifdef CONFIG_PPC_INDIRECT_IO#define PCI_IO_IND_TOKEN_MASK 0x0fff000000000000ul#define PCI_IO_IND_TOKEN_SHIFT 48#define PCI_FIX_ADDR(addr) \ ((PCI_IO_ADDR)(((unsigned long)(addr)) & ~PCI_IO_IND_TOKEN_MASK))#define PCI_GET_ADDR_TOKEN(addr) \ (((unsigned long)(addr) & PCI_IO_IND_TOKEN_MASK) >> \ PCI_IO_IND_TOKEN_SHIFT)#define PCI_SET_ADDR_TOKEN(addr, token) \do { \ unsigned long __a = (unsigned long)(addr); \ __a &= ~PCI_IO_IND_TOKEN_MASK; \ __a |= ((unsigned long)(token)) << PCI_IO_IND_TOKEN_SHIFT; \ (addr) = (void __iomem *)__a; \} while(0)#else#define PCI_FIX_ADDR(addr) (addr)#endif/* * Non ordered and non-swapping "raw" accessors */static inline unsigned char __raw_readb(const volatile void __iomem *addr){ return *(volatile unsigned char __force *)PCI_FIX_ADDR(addr);}static inline unsigned short __raw_readw(const volatile void __iomem *addr){ return *(volatile unsigned short __force *)PCI_FIX_ADDR(addr);}static inline unsigned int __raw_readl(const volatile void __iomem *addr){ return *(volatile unsigned int __force *)PCI_FIX_ADDR(addr);}static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr){ *(volatile unsigned char __force *)PCI_FIX_ADDR(addr) = v;}static inline void __raw_writew(unsigned short v, volatile void __iomem *addr){ *(volatile unsigned short __force *)PCI_FIX_ADDR(addr) = v;}static inline void __raw_writel(unsigned int v, volatile void __iomem *addr){ *(volatile unsigned int __force *)PCI_FIX_ADDR(addr) = v;}#ifdef __powerpc64__static inline unsigned long __raw_readq(const volatile void __iomem *addr){ return *(volatile unsigned long __force *)PCI_FIX_ADDR(addr);}static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr){ *(volatile unsigned long __force *)PCI_FIX_ADDR(addr) = v;}#endif /* __powerpc64__ *//* * * PCI PIO and MMIO accessors. * * * On 32 bits, PIO operations have a recovery mechanism in case they trigger * machine checks (which they occasionally do when probing non existing * IO ports on some platforms, like PowerMac and 8xx). * I always found it to be of dubious reliability and I am tempted to get * rid of it one of these days. So if you think it's important to keep it, * please voice up asap. We never had it for 64 bits and I do not intend * to port it over */#ifdef CONFIG_PPC32#define __do_in_asm(name, op) \static inline unsigned int name(unsigned int port) \{ \ unsigned int x; \ __asm__ __volatile__( \ "sync\n" \ "0:" op " %0,0,%1\n" \ "1: twi 0,%0,0\n" \ "2: isync\n" \ "3: nop\n" \ "4:\n" \ ".section .fixup,\"ax\"\n" \ "5: li %0,-1\n" \ " b 4b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 2\n" \ " .long 0b,5b\n" \ " .long 1b,5b\n" \ " .long 2b,5b\n" \ " .long 3b,5b\n" \ ".previous" \ : "=&r" (x) \ : "r" (port + _IO_BASE)); \ return x; \}#define __do_out_asm(name, op) \static inline void name(unsigned int val, unsigned int port) \{ \ __asm__ __volatile__( \ "sync\n" \ "0:" op " %0,0,%1\n" \ "1: sync\n" \ "2:\n" \ ".section __ex_table,\"a\"\n" \ " .align 2\n" \ " .long 0b,2b\n" \ " .long 1b,2b\n" \ ".previous" \ : : "r" (val), "r" (port + _IO_BASE)); \}__do_in_asm(_rec_inb, "lbzx")__do_in_asm(_rec_inw, "lhbrx")__do_in_asm(_rec_inl, "lwbrx")__do_out_asm(_rec_outb, "stbx")__do_out_asm(_rec_outw, "sthbrx")__do_out_asm(_rec_outl, "stwbrx")#endif /* CONFIG_PPC32 *//* The "__do_*" operations below provide the actual "base" implementation * for each of the defined acccessor. Some of them use the out_* functions * directly, some of them still use EEH, though we might change that in the * future. Those macros below provide the necessary argument swapping and * handling of the IO base for PIO. * * They are themselves used by the macros that define the actual accessors * and can be used by the hooks if any. * * Note that PIO operations are always defined in terms of their corresonding * MMIO operations. That allows platforms like iSeries who want to modify the * behaviour of both to only hook on the MMIO version and get both. It's also * possible to hook directly at the toplevel PIO operation if they have to * be handled differently */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?