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