File: /usr/src/linux/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 <linux/config.h>
8     
9     #ifdef CONFIG_PCI
10     
11     #include <asm/io.h>
12     #include <asm/byteorder.h>
13     
14     void 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     
22     void 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     
51     void 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     
126     void 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     
151     void 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     
176     void 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