Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] add Big Endian variants of ioread/iowrite

In the new io infrastructure, all of our operators are expecting the
underlying device to be little endian (because the PCI bus, their main
consumer, is LE).

However, there are a fair few devices and busses in the world that are
actually Big Endian. There's even evidence that some of these BE bus and
chip types are attached to LE systems. Thus, there's a need for a BE
equivalent of our io{read,write}{16,32} operations.

The attached patch adds this as io{read,write}{16,32}be. When it's in,
I'll add the first consume (the 53c700 SCSI chip driver).

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

James Bottomley and committed by
Linus Torvalds
dae409a2 c41f5eb3

+93
+68
arch/parisc/lib/iomap.c
··· 43 43 struct iomap_ops { 44 44 unsigned int (*read8)(void __iomem *); 45 45 unsigned int (*read16)(void __iomem *); 46 + unsigned int (*read16be)(void __iomem *); 46 47 unsigned int (*read32)(void __iomem *); 48 + unsigned int (*read32be)(void __iomem *); 47 49 void (*write8)(u8, void __iomem *); 48 50 void (*write16)(u16, void __iomem *); 51 + void (*write16be)(u16, void __iomem *); 49 52 void (*write32)(u32, void __iomem *); 53 + void (*write32be)(u32, void __iomem *); 50 54 void (*read8r)(void __iomem *, void *, unsigned long); 51 55 void (*read16r)(void __iomem *, void *, unsigned long); 52 56 void (*read32r)(void __iomem *, void *, unsigned long); ··· 126 122 static const struct iomap_ops ioport_ops = { 127 123 ioport_read8, 128 124 ioport_read16, 125 + ioport_read16, 126 + ioport_read32, 129 127 ioport_read32, 130 128 ioport_write8, 131 129 ioport_write16, 130 + ioport_write16, 131 + ioport_write32, 132 132 ioport_write32, 133 133 ioport_read8r, 134 134 ioport_read16r, ··· 154 146 return readw(addr); 155 147 } 156 148 149 + static unsigned int iomem_read16be(void __iomem *addr) 150 + { 151 + return __raw_readw(addr); 152 + } 153 + 157 154 static unsigned int iomem_read32(void __iomem *addr) 158 155 { 159 156 return readl(addr); 157 + } 158 + 159 + static unsigned int iomem_read32be(void __iomem *addr) 160 + { 161 + return __raw_readl(addr); 160 162 } 161 163 162 164 static void iomem_write8(u8 datum, void __iomem *addr) ··· 179 161 writew(datum, addr); 180 162 } 181 163 164 + static void iomem_write16be(u16 datum, void __iomem *addr) 165 + { 166 + __raw_writew(datum, addr); 167 + } 168 + 182 169 static void iomem_write32(u32 datum, void __iomem *addr) 183 170 { 184 171 writel(datum, addr); 172 + } 173 + 174 + static void iomem_write32be(u32 datum, void __iomem *addr) 175 + { 176 + __raw_writel(datum, addr); 185 177 } 186 178 187 179 static void iomem_read8r(void __iomem *addr, void *dst, unsigned long count) ··· 245 217 static const struct iomap_ops iomem_ops = { 246 218 iomem_read8, 247 219 iomem_read16, 220 + iomem_read16be, 248 221 iomem_read32, 222 + iomem_read32be, 249 223 iomem_write8, 250 224 iomem_write16, 225 + iomem_write16be, 251 226 iomem_write32, 227 + iomem_write32be, 252 228 iomem_read8r, 253 229 iomem_read16r, 254 230 iomem_read32r, ··· 285 253 return le16_to_cpup((u16 *)addr); 286 254 } 287 255 256 + unsigned int ioread16be(void __iomem *addr) 257 + { 258 + if (unlikely(INDIRECT_ADDR(addr))) 259 + return iomap_ops[ADDR_TO_REGION(addr)]->read16be(addr); 260 + return *((u16 *)addr); 261 + } 262 + 288 263 unsigned int ioread32(void __iomem *addr) 289 264 { 290 265 if (unlikely(INDIRECT_ADDR(addr))) 291 266 return iomap_ops[ADDR_TO_REGION(addr)]->read32(addr); 292 267 return le32_to_cpup((u32 *)addr); 268 + } 269 + 270 + unsigned int ioread32be(void __iomem *addr) 271 + { 272 + if (unlikely(INDIRECT_ADDR(addr))) 273 + return iomap_ops[ADDR_TO_REGION(addr)]->read32be(addr); 274 + return *((u32 *)addr); 293 275 } 294 276 295 277 void iowrite8(u8 datum, void __iomem *addr) ··· 324 278 } 325 279 } 326 280 281 + void iowrite16be(u16 datum, void __iomem *addr) 282 + { 283 + if (unlikely(INDIRECT_ADDR(addr))) { 284 + iomap_ops[ADDR_TO_REGION(addr)]->write16be(datum, addr); 285 + } else { 286 + *((u16 *)addr) = datum; 287 + } 288 + } 289 + 327 290 void iowrite32(u32 datum, void __iomem *addr) 328 291 { 329 292 if (unlikely(INDIRECT_ADDR(addr))) { 330 293 iomap_ops[ADDR_TO_REGION(addr)]->write32(datum, addr); 331 294 } else { 332 295 *((u32 *)addr) = cpu_to_le32(datum); 296 + } 297 + } 298 + 299 + void iowrite32be(u32 datum, void __iomem *addr) 300 + { 301 + if (unlikely(INDIRECT_ADDR(addr))) { 302 + iomap_ops[ADDR_TO_REGION(addr)]->write32be(datum, addr); 303 + } else { 304 + *((u32 *)addr) = datum; 333 305 } 334 306 } 335 307 ··· 470 406 471 407 EXPORT_SYMBOL(ioread8); 472 408 EXPORT_SYMBOL(ioread16); 409 + EXPORT_SYMBOL(ioread16be); 473 410 EXPORT_SYMBOL(ioread32); 411 + EXPORT_SYMBOL(ioread32be); 474 412 EXPORT_SYMBOL(iowrite8); 475 413 EXPORT_SYMBOL(iowrite16); 414 + EXPORT_SYMBOL(iowrite16be); 476 415 EXPORT_SYMBOL(iowrite32); 416 + EXPORT_SYMBOL(iowrite32be); 477 417 EXPORT_SYMBOL(ioread8_rep); 478 418 EXPORT_SYMBOL(ioread16_rep); 479 419 EXPORT_SYMBOL(ioread32_rep);
+5
include/asm-generic/iomap.h
··· 2 2 #define __GENERIC_IO_H 3 3 4 4 #include <linux/linkage.h> 5 + #include <asm/byteorder.h> 5 6 6 7 /* 7 8 * These are the "generic" interfaces for doing new-style ··· 27 26 */ 28 27 extern unsigned int fastcall ioread8(void __iomem *); 29 28 extern unsigned int fastcall ioread16(void __iomem *); 29 + extern unsigned int fastcall ioread16be(void __iomem *); 30 30 extern unsigned int fastcall ioread32(void __iomem *); 31 + extern unsigned int fastcall ioread32be(void __iomem *); 31 32 32 33 extern void fastcall iowrite8(u8, void __iomem *); 33 34 extern void fastcall iowrite16(u16, void __iomem *); 35 + extern void fastcall iowrite16be(u16, void __iomem *); 34 36 extern void fastcall iowrite32(u32, void __iomem *); 37 + extern void fastcall iowrite32be(u32, void __iomem *); 35 38 36 39 /* 37 40 * "string" versions of the above. Note that they
+20
lib/iomap.c
··· 58 58 { 59 59 IO_COND(addr, return inw(port), return readw(addr)); 60 60 } 61 + unsigned int fastcall ioread16be(void __iomem *addr) 62 + { 63 + IO_COND(addr, return inw(port), return be16_to_cpu(__raw_readw(addr))); 64 + } 61 65 unsigned int fastcall ioread32(void __iomem *addr) 62 66 { 63 67 IO_COND(addr, return inl(port), return readl(addr)); 64 68 } 69 + unsigned int fastcall ioread32be(void __iomem *addr) 70 + { 71 + IO_COND(addr, return inl(port), return be32_to_cpu(__raw_readl(addr))); 72 + } 65 73 EXPORT_SYMBOL(ioread8); 66 74 EXPORT_SYMBOL(ioread16); 75 + EXPORT_SYMBOL(ioread16be); 67 76 EXPORT_SYMBOL(ioread32); 77 + EXPORT_SYMBOL(ioread32be); 68 78 69 79 void fastcall iowrite8(u8 val, void __iomem *addr) 70 80 { ··· 84 74 { 85 75 IO_COND(addr, outw(val,port), writew(val, addr)); 86 76 } 77 + void fastcall iowrite16be(u16 val, void __iomem *addr) 78 + { 79 + IO_COND(addr, outw(val,port), __raw_writew(cpu_to_be16(val), addr)); 80 + } 87 81 void fastcall iowrite32(u32 val, void __iomem *addr) 88 82 { 89 83 IO_COND(addr, outl(val,port), writel(val, addr)); 90 84 } 85 + void fastcall iowrite32be(u32 val, void __iomem *addr) 86 + { 87 + IO_COND(addr, outl(val,port), __raw_writel(cpu_to_be32(val), addr)); 88 + } 91 89 EXPORT_SYMBOL(iowrite8); 92 90 EXPORT_SYMBOL(iowrite16); 91 + EXPORT_SYMBOL(iowrite16be); 93 92 EXPORT_SYMBOL(iowrite32); 93 + EXPORT_SYMBOL(iowrite32be); 94 94 95 95 /* 96 96 * These are the "repeat MMIO read/write" functions.