1/* $Id: PeeCeeI.c,v 1.1.1.1 2007/08/03 18:52:18 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
10void 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
19void 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
50void 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
127void 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
154void 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
181void 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