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