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