1 /* 2 * PeeCeeI.c: The emerging standard... 3 * 4 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) 5 */ 6 7 #include <linux/module.h> 8 9 #include <asm/io.h> 10 #include <asm/byteorder.h> 11 12 void outsb(unsigned long __addr, const void *src, unsigned long count) 13 { 14 void __iomem *addr = (void __iomem *) __addr; 15 const u8 *p = src; 16 17 while (count--) 18 outb(*p++, addr); 19 } 20 EXPORT_SYMBOL(outsb); 21 22 void outsw(unsigned long __addr, const void *src, unsigned long count) 23 { 24 void __iomem *addr = (void __iomem *) __addr; 25 26 while (count--) { 27 __raw_writew(*(u16 *)src, addr); 28 src += sizeof(u16); 29 } 30 } 31 EXPORT_SYMBOL(outsw); 32 33 void outsl(unsigned long __addr, const void *src, unsigned long count) 34 { 35 void __iomem *addr = (void __iomem *) __addr; 36 u32 l, l2; 37 38 if (!count) 39 return; 40 41 switch (((unsigned long)src) & 0x3) { 42 case 0x0: 43 /* src is naturally aligned */ 44 while (count--) { 45 __raw_writel(*(u32 *)src, addr); 46 src += sizeof(u32); 47 } 48 break; 49 case 0x2: 50 /* 2-byte alignment */ 51 while (count--) { 52 l = (*(u16 *)src) << 16; 53 l |= *(u16 *)(src + sizeof(u16)); 54 __raw_writel(l, addr); 55 src += sizeof(u32); 56 } 57 break; 58 case 0x1: 59 /* Hold three bytes in l each time, grab a byte from l2 */ 60 l = (*(u8 *)src) << 24; 61 l |= (*(u16 *)(src + sizeof(u8))) << 8; 62 src += sizeof(u8) + sizeof(u16); 63 while (count--) { 64 l2 = *(u32 *)src; 65 l |= (l2 >> 24); 66 __raw_writel(l, addr); 67 l = l2 << 8; 68 src += sizeof(u32); 69 } 70 break; 71 case 0x3: 72 /* Hold a byte in l each time, grab 3 bytes from l2 */ 73 l = (*(u8 *)src) << 24; 74 src += sizeof(u8); 75 while (count--) { 76 l2 = *(u32 *)src; 77 l |= (l2 >> 8); 78 __raw_writel(l, addr); 79 l = l2 << 24; 80 src += sizeof(u32); 81 } 82 break; 83 } 84 } 85 EXPORT_SYMBOL(outsl); 86 87 void insb(unsigned long __addr, void *dst, unsigned long count) 88 { 89 void __iomem *addr = (void __iomem *) __addr; 90 91 if (count) { 92 u32 *pi; 93 u8 *pb = dst; 94 95 while ((((unsigned long)pb) & 0x3) && count--) 96 *pb++ = inb(addr); 97 pi = (u32 *)pb; 98 while (count >= 4) { 99 u32 w; 100 101 w = (inb(addr) << 24); 102 w |= (inb(addr) << 16); 103 w |= (inb(addr) << 8); 104 w |= (inb(addr) << 0); 105 *pi++ = w; 106 count -= 4; 107 } 108 pb = (u8 *)pi; 109 while (count--) 110 *pb++ = inb(addr); 111 } 112 } 113 EXPORT_SYMBOL(insb); 114 115 void insw(unsigned long __addr, void *dst, unsigned long count) 116 { 117 void __iomem *addr = (void __iomem *) __addr; 118 119 if (count) { 120 u16 *ps = dst; 121 u32 *pi; 122 123 if (((unsigned long)ps) & 0x2) { 124 *ps++ = le16_to_cpu(inw(addr)); 125 count--; 126 } 127 pi = (u32 *)ps; 128 while (count >= 2) { 129 u32 w; 130 131 w = (le16_to_cpu(inw(addr)) << 16); 132 w |= (le16_to_cpu(inw(addr)) << 0); 133 *pi++ = w; 134 count -= 2; 135 } 136 ps = (u16 *)pi; 137 if (count) 138 *ps = le16_to_cpu(inw(addr)); 139 } 140 } 141 EXPORT_SYMBOL(insw); 142 143 void insl(unsigned long __addr, void *dst, unsigned long count) 144 { 145 void __iomem *addr = (void __iomem *) __addr; 146 147 if (count) { 148 if ((((unsigned long)dst) & 0x3) == 0) { 149 u32 *pi = dst; 150 while (count--) 151 *pi++ = le32_to_cpu(inl(addr)); 152 } else { 153 u32 l = 0, l2, *pi; 154 u16 *ps; 155 u8 *pb; 156 157 switch (((unsigned long)dst) & 3) { 158 case 0x2: 159 ps = dst; 160 count -= 1; 161 l = le32_to_cpu(inl(addr)); 162 *ps++ = l; 163 pi = (u32 *)ps; 164 while (count--) { 165 l2 = le32_to_cpu(inl(addr)); 166 *pi++ = (l << 16) | (l2 >> 16); 167 l = l2; 168 } 169 ps = (u16 *)pi; 170 *ps = l; 171 break; 172 173 case 0x1: 174 pb = dst; 175 count -= 1; 176 l = le32_to_cpu(inl(addr)); 177 *pb++ = l >> 24; 178 ps = (u16 *)pb; 179 *ps++ = ((l >> 8) & 0xffff); 180 pi = (u32 *)ps; 181 while (count--) { 182 l2 = le32_to_cpu(inl(addr)); 183 *pi++ = (l << 24) | (l2 >> 8); 184 l = l2; 185 } 186 pb = (u8 *)pi; 187 *pb = l; 188 break; 189 190 case 0x3: 191 pb = (u8 *)dst; 192 count -= 1; 193 l = le32_to_cpu(inl(addr)); 194 *pb++ = l >> 24; 195 pi = (u32 *)pb; 196 while (count--) { 197 l2 = le32_to_cpu(inl(addr)); 198 *pi++ = (l << 8) | (l2 >> 24); 199 l = l2; 200 } 201 ps = (u16 *)pi; 202 *ps++ = ((l >> 8) & 0xffff); 203 pb = (u8 *)ps; 204 *pb = l; 205 break; 206 } 207 } 208 } 209 } 210 EXPORT_SYMBOL(insl); 211 212