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(val: *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(val: *(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(val: *(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(val: 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(val: 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(val: 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 | |