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