11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Alpha IO and memory functions.
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Out-of-line versions of the i/o routines that redirect into the
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   platform-specific version.  Note that "platform-specific" may mean
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   "generic", which bumps through the machine vector.  */
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsioread8(void __iomem *addr)
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int ioread16(void __iomem *addr)
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int ioread32(void __iomem *addr)
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid iowrite8(u8 b, void __iomem *addr)
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid iowrite16(u16 b, void __iomem *addr)
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid iowrite32(u32 b, void __iomem *addr)
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr);
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ioread8);
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ioread16);
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ioread32);
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(iowrite8);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(iowrite16);
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(iowrite32);
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu8 inb(unsigned long port)
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ioread8(ioport_map(port, 1));
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu16 inw(unsigned long port)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ioread16(ioport_map(port, 2));
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu32 inl(unsigned long port)
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ioread32(ioport_map(port, 4));
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid outb(u8 b, unsigned long port)
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iowrite8(b, ioport_map(port, 1));
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid outw(u16 b, unsigned long port)
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iowrite16(b, ioport_map(port, 2));
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid outl(u32 b, unsigned long port)
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iowrite32(b, ioport_map(port, 4));
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(inb);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(inw);
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(inl);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(outb);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(outw);
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(outl);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu8 __raw_readb(const volatile void __iomem *addr)
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IO_CONCAT(__IO_PREFIX,readb)(addr);
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu16 __raw_readw(const volatile void __iomem *addr)
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IO_CONCAT(__IO_PREFIX,readw)(addr);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu32 __raw_readl(const volatile void __iomem *addr)
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IO_CONCAT(__IO_PREFIX,readl)(addr);
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu64 __raw_readq(const volatile void __iomem *addr)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IO_CONCAT(__IO_PREFIX,readq)(addr);
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __raw_writeb(u8 b, volatile void __iomem *addr)
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IO_CONCAT(__IO_PREFIX,writeb)(b, addr);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __raw_writew(u16 b, volatile void __iomem *addr)
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IO_CONCAT(__IO_PREFIX,writew)(b, addr);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __raw_writel(u32 b, volatile void __iomem *addr)
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IO_CONCAT(__IO_PREFIX,writel)(b, addr);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __raw_writeq(u64 b, volatile void __iomem *addr)
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IO_CONCAT(__IO_PREFIX,writeq)(b, addr);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__raw_readb);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__raw_readw);
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__raw_readl);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__raw_readq);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__raw_writeb);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__raw_writew);
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__raw_writel);
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__raw_writeq);
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu8 readb(const volatile void __iomem *addr)
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 ret = __raw_readb(addr);
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu16 readw(const volatile void __iomem *addr)
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 ret = __raw_readw(addr);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu32 readl(const volatile void __iomem *addr)
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 ret = __raw_readl(addr);
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu64 readq(const volatile void __iomem *addr)
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u64 ret = __raw_readq(addr);
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid writeb(u8 b, volatile void __iomem *addr)
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__raw_writeb(b, addr);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid writew(u16 b, volatile void __iomem *addr)
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__raw_writew(b, addr);
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid writel(u32 b, volatile void __iomem *addr)
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__raw_writel(b, addr);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid writeq(u64 b, volatile void __iomem *addr)
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__raw_writeq(b, addr);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(readb);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(readw);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(readl);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(readq);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(writeb);
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(writew);
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(writel);
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(writeq);
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read COUNT 8-bit bytes from port PORT into memory starting at SRC.
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ioread8_rep(void __iomem *port, void *dst, unsigned long count)
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while ((unsigned long)dst & 0x3) {
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!count)
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count--;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(unsigned char *)dst = ioread8(port);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dst += 1;
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (count >= 4) {
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int w;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 4;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w = ioread8(port);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w |= ioread8(port) << 8;
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w |= ioread8(port) << 16;
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w |= ioread8(port) << 24;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(unsigned int *)dst = w;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dst += 4;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (count) {
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		--count;
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(unsigned char *)dst = ioread8(port);
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dst += 1;
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid insb(unsigned long port, void *dst, unsigned long count)
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ioread8_rep(ioport_map(port, 1), dst, count);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ioread8_rep);
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(insb);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read COUNT 16-bit words from port PORT into memory starting at
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SRC.  SRC must be at least short aligned.  This is used by the
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IDE driver to read disk sectors.  Performance is important, but
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the interfaces seems to be slow: just using the inlined version
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the inw() breaks things.
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ioread16_rep(void __iomem *port, void *dst, unsigned long count)
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely((unsigned long)dst & 0x3)) {
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!count)
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON((unsigned long)dst & 0x1);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count--;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(unsigned short *)dst = ioread16(port);
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dst += 2;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (count >= 2) {
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int w;
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 2;
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w = ioread16(port);
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w |= ioread16(port) << 16;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(unsigned int *)dst = w;
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dst += 4;
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count) {
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(unsigned short*)dst = ioread16(port);
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid insw(unsigned long port, void *dst, unsigned long count)
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ioread16_rep(ioport_map(port, 2), dst, count);
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ioread16_rep);
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(insw);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read COUNT 32-bit words from port PORT into memory starting at
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SRC. Now works with any alignment in SRC. Performance is important,
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but the interfaces seems to be slow: just using the inlined version
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the inl() breaks things.
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ioread32_rep(void __iomem *port, void *dst, unsigned long count)
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely((unsigned long)dst & 0x3)) {
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (count--) {
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct S { int x __attribute__((packed)); };
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((struct S *)dst)->x = ioread32(port);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dst += 4;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Buffer 32-bit aligned.  */
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (count--) {
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*(unsigned int *)dst = ioread32(port);
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dst += 4;
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid insl(unsigned long port, void *dst, unsigned long count)
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ioread32_rep(ioport_map(port, 4), dst, count);
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ioread32_rep);
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(insl);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Like insb but in the opposite direction.
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Don't worry as much about doing aligned memory transfers:
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doing byte reads the "slow" way isn't nearly as slow as
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doing byte writes the slow way (no r-m-w cycle).
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid iowrite8_rep(void __iomem *port, const void *xsrc, unsigned long count)
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const unsigned char *src = xsrc;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (count--)
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iowrite8(*src++, port);
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid outsb(unsigned long port, const void *src, unsigned long count)
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iowrite8_rep(ioport_map(port, 1), src, count);
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(iowrite8_rep);
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(outsb);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Like insw but in the opposite direction.  This is used by the IDE
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driver to write disk sectors.  Performance is important, but the
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interfaces seems to be slow: just using the inlined version of the
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * outw() breaks things.
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid iowrite16_rep(void __iomem *port, const void *src, unsigned long count)
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely((unsigned long)src & 0x3)) {
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!count)
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON((unsigned long)src & 0x1);
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iowrite16(*(unsigned short *)src, port);
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		src += 2;
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		--count;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (count >= 2) {
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int w;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 2;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w = *(unsigned int *)src;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		src += 4;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iowrite16(w >>  0, port);
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iowrite16(w >> 16, port);
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count) {
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iowrite16(*(unsigned short *)src, port);
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid outsw(unsigned long port, const void *src, unsigned long count)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iowrite16_rep(ioport_map(port, 2), src, count);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(iowrite16_rep);
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(outsw);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Like insl but in the opposite direction.  This is used by the IDE
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driver to write disk sectors.  Works with any alignment in SRC.
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performance is important, but the interfaces seems to be slow:
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * just using the inlined version of the outl() breaks things.
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid iowrite32_rep(void __iomem *port, const void *src, unsigned long count)
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely((unsigned long)src & 0x3)) {
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (count--) {
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct S { int x __attribute__((packed)); };
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iowrite32(((struct S *)src)->x, port);
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			src += 4;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Buffer 32-bit aligned.  */
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (count--) {
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iowrite32(*(unsigned int *)src, port);
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			src += 4;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid outsl(unsigned long port, const void *src, unsigned long count)
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iowrite32_rep(ioport_map(port, 4), src, count);
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(iowrite32_rep);
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(outsl);
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copy data from IO memory space to "real" memory space.
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This needs to be optimized.
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid memcpy_fromio(void *to, const volatile void __iomem *from, long count)
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Optimize co-aligned transfers.  Everything else gets handled
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   a byte at a time. */
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 8;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*(u64 *)to = __raw_readq(from);
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count -= 8;
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			to += 8;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			from += 8;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (count >= 0);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count += 8;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 4;
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*(u32 *)to = __raw_readl(from);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count -= 4;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			to += 4;
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			from += 4;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (count >= 0);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count += 4;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 2;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*(u16 *)to = __raw_readw(from);
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count -= 2;
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			to += 2;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			from += 2;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (count >= 0);
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count += 2;
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (count > 0) {
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(u8 *) to = __raw_readb(from);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count--;
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to++;
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		from++;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(memcpy_fromio);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copy data from "real" memory space to IO memory space.
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This needs to be optimized.
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid memcpy_toio(volatile void __iomem *to, const void *from, long count)
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Optimize co-aligned transfers.  Everything else gets handled
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   a byte at a time. */
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* FIXME -- align FROM.  */
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 8;
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__raw_writeq(*(const u64 *)from, to);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count -= 8;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			to += 8;
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			from += 8;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (count >= 0);
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count += 8;
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 4;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__raw_writel(*(const u32 *)from, to);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count -= 4;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			to += 4;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			from += 4;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (count >= 0);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count += 4;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 2;
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__raw_writew(*(const u16 *)from, to);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count -= 2;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			to += 2;
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			from += 2;
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (count >= 0);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count += 2;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (count > 0) {
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__raw_writeb(*(const u8 *) from, to);
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count--;
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to++;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		from++;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(memcpy_toio);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "memset" on IO memory space.
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid _memset_c_io(volatile void __iomem *to, unsigned long c, long count)
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Handle any initial odd byte */
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count > 0 && ((u64)to & 1)) {
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__raw_writeb(c, to);
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to++;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count--;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Handle any initial odd halfword */
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 2 && ((u64)to & 2)) {
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__raw_writew(c, to);
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to += 2;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 2;
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Handle any initial odd word */
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 4 && ((u64)to & 4)) {
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__raw_writel(c, to);
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to += 4;
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 4;
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Handle all full-sized quadwords: we're aligned
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   (or have a small count) */
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count -= 8;
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 0) {
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__raw_writeq(c, to);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			to += 8;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count -= 8;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (count >= 0);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count += 8;
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The tail is word-aligned if we still have count >= 4 */
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 4) {
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__raw_writel(c, to);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to += 4;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 4;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The tail is half-word aligned if we have count >= 2 */
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count >= 2) {
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__raw_writew(c, to);
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to += 2;
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 2;
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* And finally, one last byte.. */
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count) {
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__raw_writeb(c, to);
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(_memset_c_io);
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* A version of memcpy used by the vga console routines to move data around
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   arbitrarily between screen and main memory.  */
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsscr_memcpyw(u16 *d, const u16 *s, unsigned int count)
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u16 __iomem *ios = (const u16 __iomem *) s;
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 __iomem *iod = (u16 __iomem *) d;
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int s_isio = __is_ioaddr(s);
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int d_isio = __is_ioaddr(d);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (s_isio) {
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (d_isio) {
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* FIXME: Should handle unaligned ops and
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   operation widening.  */
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count /= 2;
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			while (count--) {
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				u16 tmp = __raw_readw(ios++);
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				__raw_writew(tmp, iod++);
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy_fromio(d, ios, count);
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (d_isio)
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy_toio(iod, s, count);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(d, s, count);
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(scr_memcpyw);
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __iomem *ioport_map(unsigned long port, unsigned int size)
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IO_CONCAT(__IO_PREFIX,ioportmap) (port);
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ioport_unmap(void __iomem *addr)
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ioport_map);
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ioport_unmap);
631