[PATCH/RFC] Hookable IO operations
Arnd Bergmann
arnd at arndb.de
Sat Nov 4 11:15:34 EST 2006
On Friday 03 November 2006 23:56, Benjamin Herrenschmidt wrote:
>
> > Did you never consider this, or did you make your mind up in the
> > process?
>
> I considered this and decided against it while doing the macro since I
> could get the hooks auto-generated easier as globals, but I can still
> change it, it's not that much bloat and might indeed look nicer.
I've just tried hacking something up, this is the best I could come up
with using the structure:
/* are these all we need, or did I miss any? */
struct ppc_io {
void (*writeb)(u8 val);
void (*writew)(u16 val);
void (*writel)(u32 val);
void (*writeq)(u64 val);
u8 (*readb)(void);
u16 (*readw)(void);
u32 (*readl)(void);
u64 (*readq)(void);
void (*outb)(u8 val);
void (*outw)(u16 val);
void (*outl)(u32 val);
void (*outq)(u64 val);
u8 (*inb)(void);
u16 (*inw)(void);
u32 (*inl)(void);
u64 (*inq)(void);
void (*memset_io)(volatile void __iomem *addr, int c, unsigned long n);
void (*memcpy_fromio)(void *dest,
const volatile void __iomem *src, unsigned long n);
void (*memcpy_toio)(volatile void __iomem *dest,
const void *src, unsigned long n);
} ppc_io;
/* all these should be static inline or extern */
void direct_writeb(u8 val);
void direct_writew(u16 val);
void direct_writel(u32 val);
void direct_writeq(u64 val);
u8 direct_readb(void);
u16 direct_readw(void);
u32 direct_readl(void);
u64 direct_readq(void);
void direct_outb(u8 val);
void direct_outw(u16 val);
void direct_outl(u32 val);
void direct_outq(u64 val);
u8 direct_inb(void);
u16 direct_inw(void);
u32 direct_inl(void);
u64 direct_inq(void);
void direct_memset_io(volatile void __iomem *addr, int c,
unsigned long n);
void direct_memcpy_fromio(void *dest,
const volatile void __iomem *src, unsigned long n);
void direct_memcpy_toio(volatile void __iomem *dest,
const void *src, unsigned long n);
/* a simple indirection more than your code, going
through the structure */
#ifdef CONFIG_INDIRECT_IO
#define ppc_io_indirect(x) ppc_io.x
#else
#define ppc_io_indirect(x) NULL
#endif
#define DEF_IO_OUT(name, arg) \
static inline void name(arg val) \
{ \
if (ppc_io_indirect(name)) \
return ppc_io.name(val); \
else \
return direct_ ## name(val); \
}
#define DEF_IO_IN(name, arg) \
static inline arg name(void) \
{ \
if (ppc_io_indirect(name)) \
return ppc_io.name(); \
else \
return direct_ ## name(); \
}
DEF_IO_OUT(writeb, u8)
DEF_IO_OUT(writew, u16)
DEF_IO_OUT(writel, u32)
DEF_IO_OUT(writeq, u64)
DEF_IO_IN(readb, u8)
DEF_IO_IN(readw, u16)
DEF_IO_IN(readl, u32)
DEF_IO_IN(readq, u64)
DEF_IO_OUT(outb, u8)
DEF_IO_OUT(outw, u16)
DEF_IO_OUT(outl, u32)
DEF_IO_OUT(outq, u64)
DEF_IO_IN(inb, u8)
DEF_IO_IN(inw, u16)
DEF_IO_IN(inl, u32)
DEF_IO_IN(inq, u64)
/* using variadic macros makes this somewhat simpler
* than writing the whole prototype */
#define memset_io(arg...) \
do { \
if (ppc_io_indirect(memset_io)) \
ppc_io.memset_io(arg); \
else \
direct_memset_io(arg); \
} while (0)
#define memcpy_fromio(arg...) \
do { \
if (ppc_io_indirect(memcpy_fromio)) \
ppc_io.memcpy_fromio(arg); \
else \
direct_memcpy_fromio(arg); \
} while (0)
#define memcpy_toio(arg...) \
do { \
if (ppc_io_indirect(memcpy_toio)) \
ppc_io.memcpy_toio(arg); \
else \
direct_memcpy_toio(arg); \
} while (0)
More information about the Linuxppc-dev
mailing list