Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-2.6] / arch / sparc64 / lib / PeeCeeI.c
1 /*
2  * PeeCeeI.c: The emerging standard...
3  *
4  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
5  */
6
7 #include <asm/io.h>
8 #include <asm/byteorder.h>
9
10 void outsb(unsigned long __addr, const void *src, unsigned long count)
11 {
12         void __iomem *addr = (void __iomem *) __addr;
13         const u8 *p = src;
14
15         while (count--)
16                 outb(*p++, addr);
17 }
18
19 void outsw(unsigned long __addr, const void *src, unsigned long count)
20 {
21         void __iomem *addr = (void __iomem *) __addr;
22
23         if (count) {
24                 u16 *ps = (u16 *)src;
25                 u32 *pi;
26
27                 if (((u64)src) & 0x2) {
28                         u16 val = le16_to_cpup(ps);
29                         outw(val, addr);
30                         ps++;
31                         count--;
32                 }
33                 pi = (u32 *)ps;
34                 while (count >= 2) {
35                         u32 w = le32_to_cpup(pi);
36
37                         pi++;
38                         outw(w >> 0, addr);
39                         outw(w >> 16, addr);
40                         count -= 2;
41                 }
42                 ps = (u16 *)pi;
43                 if (count) {
44                         u16 val = le16_to_cpup(ps);
45                         outw(val, addr);
46                 }
47         }
48 }
49
50 void outsl(unsigned long __addr, const void *src, unsigned long count)
51 {
52         void __iomem *addr = (void __iomem *) __addr;
53
54         if (count) {
55                 if ((((u64)src) & 0x3) == 0) {
56                         u32 *p = (u32 *)src;
57                         while (count--) {
58                                 u32 val = cpu_to_le32p(p);
59                                 outl(val, addr);
60                                 p++;
61                         }
62                 } else {
63                         u8 *pb;
64                         u16 *ps = (u16 *)src;
65                         u32 l = 0, l2;
66                         u32 *pi;
67
68                         switch (((u64)src) & 0x3) {
69                         case 0x2:
70                                 count -= 1;
71                                 l = cpu_to_le16p(ps) << 16;
72                                 ps++;
73                                 pi = (u32 *)ps;
74                                 while (count--) {
75                                         l2 = cpu_to_le32p(pi);
76                                         pi++;
77                                         outl(((l >> 16) | (l2 << 16)), addr);
78                                         l = l2;
79                                 }
80                                 ps = (u16 *)pi;
81                                 l2 = cpu_to_le16p(ps);
82                                 outl(((l >> 16) | (l2 << 16)), addr);
83                                 break;
84
85                         case 0x1:
86                                 count -= 1;
87                                 pb = (u8 *)src;
88                                 l = (*pb++ << 8);
89                                 ps = (u16 *)pb;
90                                 l2 = cpu_to_le16p(ps);
91                                 ps++;
92                                 l |= (l2 << 16);
93                                 pi = (u32 *)ps;
94                                 while (count--) {
95                                         l2 = cpu_to_le32p(pi);
96                                         pi++;
97                                         outl(((l >> 8) | (l2 << 24)), addr);
98                                         l = l2;
99                                 }
100                                 pb = (u8 *)pi;
101                                 outl(((l >> 8) | (*pb << 24)), addr);
102                                 break;
103
104                         case 0x3:
105                                 count -= 1;
106                                 pb = (u8 *)src;
107                                 l = (*pb++ << 24);
108                                 pi = (u32 *)pb;
109                                 while (count--) {
110                                         l2 = cpu_to_le32p(pi);
111                                         pi++;
112                                         outl(((l >> 24) | (l2 << 8)), addr);
113                                         l = l2;
114                                 }
115                                 ps = (u16 *)pi;
116                                 l2 = cpu_to_le16p(ps);
117                                 ps++;
118                                 pb = (u8 *)ps;
119                                 l2 |= (*pb << 16);
120                                 outl(((l >> 24) | (l2 << 8)), addr);
121                                 break;
122                         }
123                 }
124         }
125 }
126
127 void insb(unsigned long __addr, void *dst, unsigned long count)
128 {
129         void __iomem *addr = (void __iomem *) __addr;
130
131         if (count) {
132                 u32 *pi;
133                 u8 *pb = dst;
134
135                 while ((((unsigned long)pb) & 0x3) && count--)
136                         *pb++ = inb(addr);
137                 pi = (u32 *)pb;
138                 while (count >= 4) {
139                         u32 w;
140
141                         w  = (inb(addr) << 24);
142                         w |= (inb(addr) << 16);
143                         w |= (inb(addr) << 8);
144                         w |= (inb(addr) << 0);
145                         *pi++ = w;
146                         count -= 4;
147                 }
148                 pb = (u8 *)pi;
149                 while (count--)
150                         *pb++ = inb(addr);
151         }
152 }
153
154 void insw(unsigned long __addr, void *dst, unsigned long count)
155 {
156         void __iomem *addr = (void __iomem *) __addr;
157
158         if (count) {
159                 u16 *ps = dst;
160                 u32 *pi;
161
162                 if (((unsigned long)ps) & 0x2) {
163                         *ps++ = le16_to_cpu(inw(addr));
164                         count--;
165                 }
166                 pi = (u32 *)ps;
167                 while (count >= 2) {
168                         u32 w;
169
170                         w  = (le16_to_cpu(inw(addr)) << 16);
171                         w |= (le16_to_cpu(inw(addr)) << 0);
172                         *pi++ = w;
173                         count -= 2;
174                 }
175                 ps = (u16 *)pi;
176                 if (count)
177                         *ps = le16_to_cpu(inw(addr));
178         }
179 }
180
181 void insl(unsigned long __addr, void *dst, unsigned long count)
182 {
183         void __iomem *addr = (void __iomem *) __addr;
184
185         if (count) {
186                 if ((((unsigned long)dst) & 0x3) == 0) {
187                         u32 *pi = dst;
188                         while (count--)
189                                 *pi++ = le32_to_cpu(inl(addr));
190                 } else {
191                         u32 l = 0, l2, *pi;
192                         u16 *ps;
193                         u8 *pb;
194
195                         switch (((unsigned long)dst) & 3) {
196                         case 0x2:
197                                 ps = dst;
198                                 count -= 1;
199                                 l = le32_to_cpu(inl(addr));
200                                 *ps++ = l;
201                                 pi = (u32 *)ps;
202                                 while (count--) {
203                                         l2 = le32_to_cpu(inl(addr));
204                                         *pi++ = (l << 16) | (l2 >> 16);
205                                         l = l2;
206                                 }
207                                 ps = (u16 *)pi;
208                                 *ps = l;
209                                 break;
210
211                         case 0x1:
212                                 pb = dst;
213                                 count -= 1;
214                                 l = le32_to_cpu(inl(addr));
215                                 *pb++ = l >> 24;
216                                 ps = (u16 *)pb;
217                                 *ps++ = ((l >> 8) & 0xffff);
218                                 pi = (u32 *)ps;
219                                 while (count--) {
220                                         l2 = le32_to_cpu(inl(addr));
221                                         *pi++ = (l << 24) | (l2 >> 8);
222                                         l = l2;
223                                 }
224                                 pb = (u8 *)pi;
225                                 *pb = l;
226                                 break;
227
228                         case 0x3:
229                                 pb = (u8 *)dst;
230                                 count -= 1;
231                                 l = le32_to_cpu(inl(addr));
232                                 *pb++ = l >> 24;
233                                 pi = (u32 *)pb;
234                                 while (count--) {
235                                         l2 = le32_to_cpu(inl(addr));
236                                         *pi++ = (l << 8) | (l2 >> 24);
237                                         l = l2;
238                                 }
239                                 ps = (u16 *)pi;
240                                 *ps++ = ((l >> 8) & 0xffff);
241                                 pb = (u8 *)ps;
242                                 *pb = l;
243                                 break;
244                         }
245                 }
246         }
247 }
248