]> git.hungrycats.org Git - linux/commitdiff
Add skeleton "generic IO mapping" infrastructure.
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 13 Sep 2004 04:32:00 +0000 (21:32 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 13 Sep 2004 04:32:00 +0000 (21:32 -0700)
Jeff wants to use this to clean up SATA and some network drivers.

12 files changed:
arch/alpha/Kconfig
arch/arm/Kconfig
arch/i386/Kconfig
arch/ia64/Kconfig
arch/ppc/Kconfig
arch/ppc64/Kconfig
arch/x86_64/Kconfig
include/asm-generic/iomap.h [new file with mode: 0644]
include/asm-i386/io.h
include/asm-ppc64/io.h
lib/Makefile
lib/iomap.c [new file with mode: 0644]

index 541bd7965909ef647c22cc3a077a9be2e299dd06..0e4855419a729e67b506971b40f055570c3e1c95 100644 (file)
@@ -32,6 +32,10 @@ config GENERIC_ISA_DMA
        bool
        default y
 
+config GENERIC_IOMAP
+       bool
+       default y
+
 source "init/Kconfig"
 
 
index 95aa273cdacfd47276614aa4dfe8c6b968041843..aa709d12ef58d131dfb32877c83c7ae2f895984e 100644 (file)
@@ -63,6 +63,10 @@ config GENERIC_BUST_SPINLOCK
 config GENERIC_ISA_DMA
        bool
 
+config GENERIC_IOMAP
+       bool
+       default y
+
 source "init/Kconfig"
 
 menu "System Type"
index 18c722a8e656a58c0037c81ff85381a58944320c..597a9969169ec5813dbad98c29d4be8597c8539f 100644 (file)
@@ -29,6 +29,10 @@ config GENERIC_ISA_DMA
        bool
        default y
 
+config GENERIC_IOMAP
+       bool
+       default y
+
 source "init/Kconfig"
 
 menu "Processor type and features"
index 4459907b0a8a133bb29bad4b3dc44bded4e49209..aa742c601da2fb713fd263317f3eb59b7712e316 100644 (file)
@@ -38,6 +38,10 @@ config EFI
        bool
        default y
 
+config GENERIC_IOMAP
+       bool
+       default y
+
 choice
        prompt "System type"
        default IA64_GENERIC
index 46139ac9756386a5376cf2d9d1c721f3ac7a4d25..81d55092fde022b6cc67bf970bde0a92f73e71c3 100644 (file)
@@ -35,6 +35,10 @@ config GENERIC_NVRAM
        bool
        default y
 
+config GENERIC_IOMAP
+       bool
+       default y
+
 source "init/Kconfig"
 
 menu "Processor"
index c11f5cc5605aa508d29d23f863aa8ea7acf78a29..706c53f58d0fc78532cc1fe8fff969a00bc04c3e 100644 (file)
@@ -24,6 +24,10 @@ config GENERIC_ISA_DMA
        bool
        default y
 
+config GENERIC_IOMAP
+       bool
+       default y
+
 config HAVE_DEC_LOCK
        bool
        default y
index a131337b9dac86f9a5c1d9c33abc87eb74562fb6..6f55f43975c174631aeeaaeefa9b6f30271931d5 100644 (file)
@@ -78,6 +78,10 @@ config GENERIC_ISA_DMA
        bool
        default y
 
+config GENERIC_IOMAP
+       bool
+       default y
+
 source "init/Kconfig"
 
 
diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
new file mode 100644 (file)
index 0000000..cbd9e7f
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __GENERIC_IO_H
+#define __GENERIC_IO_H
+
+#include <linux/linkage.h>
+
+/*
+ * These are the "generic" interfaces for doing new-style
+ * memory-mapped or PIO accesses. Architectures may do
+ * their own arch-optimized versions, these just act as
+ * wrappers around the old-style IO register access functions:
+ * read[bwl]/write[bwl]/in[bwl]/out[bwl]
+ *
+ * Don't include this directly, include it from <asm/io.h>.
+ */
+
+/*
+ * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
+ * access or a MMIO access, these functions don't care. The info is
+ * encoded in the hardware mapping set up by the mapping functions
+ * (or the cookie itself, depending on implementation and hw).
+ *
+ * The generic routines just encode the PIO/MMIO as part of the
+ * cookie, and coldly assume that the MMIO IO mappings are not
+ * in the low address range. Architectures for which this is not
+ * true can't use this generic implementation.
+ */
+extern unsigned int fastcall ioread8(void __iomem *);
+extern unsigned int fastcall ioread16(void __iomem *);
+extern unsigned int fastcall ioread32(void __iomem *);
+
+extern void fastcall iowrite8(u8, void __iomem *);
+extern void fastcall iowrite16(u16, void __iomem *);
+extern void fastcall iowrite32(u32, void __iomem *);
+
+/* Create a virtual mapping cookie for an IO port range */
+extern void __iomem *ioport_map(unsigned int port, unsigned int nr);
+extern void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+#endif
index 20a26b98ec6eeda79c04b36d64ee7ea5bc82793f..083e3b8f8c7f04c8b2040b194f95fa0ee9f5db12 100644 (file)
@@ -45,6 +45,8 @@
 
 #ifdef __KERNEL__
 
+#include <asm-generic/iomap.h>
+
 #include <linux/vmalloc.h>
 
 /**
index 33c2dfff98154f25218726e6785c6166a27a64a5..1e9cd557352eaa204c28dd2dc2ec21d566fb3daa 100644 (file)
@@ -18,6 +18,8 @@
 #include <asm/memory.h>
 #include <asm/delay.h>
 
+#include <asm-generic/iomap.h>
+
 #define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 *)(p), (a), (c))
 #define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 *)(p), (a), (c))
 #define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 *)(p), (a), (c))
index b62c9ef212edc96b6442238ff05fb550a46db7bf..bcd6e855e7477e83817dd551af6a77c73bf9f101 100644 (file)
@@ -10,6 +10,7 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+lib-$(CONFIG_GENERIC_IOMAP) += iomap.o
 
 ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 
   lib-y += dec_and_lock.o
diff --git a/lib/iomap.c b/lib/iomap.c
new file mode 100644 (file)
index 0000000..0873451
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Implement the default iomap interfaces
+ */
+#include <linux/pci.h>
+#include <asm/io.h>
+
+/*
+ * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
+ * access or a MMIO access, these functions don't care. The info is
+ * encoded in the hardware mapping set up by the mapping functions
+ * (or the cookie itself, depending on implementation and hw).
+ *
+ * The generic routines don't assume any hardware mappings, and just
+ * encode the PIO/MMIO as part of the cookie. They coldly assume that
+ * the MMIO IO mappings are not in the low address range.
+ *
+ * Architectures for which this is not true can't use this generic
+ * implementation and should do their own copy.
+ *
+ * We encode the physical PIO addresses (0-0xffff) into the
+ * pointer by offsetting them with a constant (0x10000) and
+ * assuming that all the low addresses are always PIO. That means
+ * we can do some sanity checks on the low bits, and don't
+ * need to just take things for granted.
+ */
+#define PIO_OFFSET     0x10000
+#define PIO_MASK       0x0ffff
+#define PIO_RESERVED   0x40000
+
+/*
+ * Ugly macros are a way of life.
+ */
+#define VERIFY_PIO(port) BUG_ON((port & ~PIO_MASK) != PIO_OFFSET)
+
+#define IO_COND(addr, is_pio, is_mmio) do {                    \
+       unsigned long port = (unsigned long __force)addr;       \
+       if (port < PIO_RESERVED) {                              \
+               VERIFY_PIO(port);                               \
+               port &= PIO_MASK;                               \
+               is_pio;                                         \
+       } else {                                                \
+               is_mmio;                                        \
+       }                                                       \
+} while (0)
+
+unsigned int fastcall ioread8(void __iomem *addr)
+{
+       IO_COND(addr, return inb(port), return readb(addr));
+}
+unsigned int fastcall ioread16(void __iomem *addr)
+{
+       IO_COND(addr, return inw(port), return readw(addr));
+}
+unsigned int fastcall ioread32(void __iomem *addr)
+{
+       IO_COND(addr, return inl(port), return readl(addr));
+}
+
+void fastcall iowrite8(u8 val, void __iomem *addr)
+{
+       IO_COND(addr, outb(val,port), writeb(val, addr));
+}
+void fastcall iowrite16(u16 val, void __iomem *addr)
+{
+       IO_COND(addr, outw(val,port), writew(val, addr));
+}
+void fastcall iowrite32(u32 val, void __iomem *addr)
+{
+       IO_COND(addr, outl(val,port), writel(val, addr));
+}
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned int port, unsigned int nr)
+{
+       if (port > PIO_MASK)
+               return NULL;
+       return (void __iomem *) (unsigned long) (port + PIO_OFFSET);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+       /* Nothing to do */
+}
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len || !start)
+               return NULL;
+       if (maxlen && len > maxlen)
+               len = maxlen;
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM) {
+               if (flags & IORESOURCE_CACHEABLE)
+                       return ioremap(start, len);
+               return ioremap_nocache(start, len);
+       }
+       /* What? */
+       return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+       IO_COND(addr, /* nothing */, iounmap(addr));
+}