Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | epia.c (c) 1997-8 Grant R. Guenther <grant@torque.net> | |
3 | Under the terms of the GNU General Public License. | |
4 | ||
5 | epia.c is a low-level protocol driver for Shuttle Technologies | |
6 | EPIA parallel to IDE adapter chip. This device is now obsolete | |
7 | and has been replaced with the EPAT chip, which is supported | |
8 | by epat.c, however, some devices based on EPIA are still | |
9 | available. | |
10 | ||
11 | */ | |
12 | ||
13 | /* Changes: | |
14 | ||
15 | 1.01 GRG 1998.05.06 init_proto, release_proto | |
16 | 1.02 GRG 1998.06.17 support older versions of EPIA | |
17 | ||
18 | */ | |
19 | ||
20 | #define EPIA_VERSION "1.02" | |
21 | ||
22 | #include <linux/module.h> | |
23 | #include <linux/init.h> | |
24 | #include <linux/delay.h> | |
25 | #include <linux/kernel.h> | |
26 | #include <linux/types.h> | |
27 | #include <linux/wait.h> | |
28 | #include <asm/io.h> | |
29 | ||
30 | #include "paride.h" | |
31 | ||
32 | /* mode codes: 0 nybble reads on port 1, 8-bit writes | |
33 | 1 5/3 reads on ports 1 & 2, 8-bit writes | |
34 | 2 8-bit reads and writes | |
35 | 3 8-bit EPP mode | |
36 | 4 16-bit EPP | |
37 | 5 32-bit EPP | |
38 | */ | |
39 | ||
40 | #define j44(a,b) (((a>>4)&0x0f)+(b&0xf0)) | |
41 | #define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0)) | |
42 | ||
43 | /* cont = 0 IDE register file | |
44 | cont = 1 IDE control registers | |
45 | */ | |
46 | ||
47 | static int cont_map[2] = { 0, 0x80 }; | |
48 | ||
49 | static int epia_read_regr( PIA *pi, int cont, int regr ) | |
50 | ||
51 | { int a, b, r; | |
52 | ||
53 | regr += cont_map[cont]; | |
54 | ||
55 | switch (pi->mode) { | |
56 | ||
57 | case 0: r = regr^0x39; | |
58 | w0(r); w2(1); w2(3); w0(r); | |
59 | a = r1(); w2(1); b = r1(); w2(4); | |
60 | return j44(a,b); | |
61 | ||
62 | case 1: r = regr^0x31; | |
63 | w0(r); w2(1); w0(r&0x37); | |
64 | w2(3); w2(5); w0(r|0xf0); | |
65 | a = r1(); b = r2(); w2(4); | |
66 | return j53(a,b); | |
67 | ||
68 | case 2: r = regr^0x29; | |
69 | w0(r); w2(1); w2(0X21); w2(0x23); | |
70 | a = r0(); w2(4); | |
71 | return a; | |
72 | ||
73 | case 3: | |
74 | case 4: | |
75 | case 5: w3(regr); w2(0x24); a = r4(); w2(4); | |
76 | return a; | |
77 | ||
78 | } | |
79 | return -1; | |
80 | } | |
81 | ||
82 | static void epia_write_regr( PIA *pi, int cont, int regr, int val) | |
83 | ||
84 | { int r; | |
85 | ||
86 | regr += cont_map[cont]; | |
87 | ||
88 | switch (pi->mode) { | |
89 | ||
90 | case 0: | |
91 | case 1: | |
92 | case 2: r = regr^0x19; | |
93 | w0(r); w2(1); w0(val); w2(3); w2(4); | |
94 | break; | |
95 | ||
96 | case 3: | |
97 | case 4: | |
98 | case 5: r = regr^0x40; | |
99 | w3(r); w4(val); w2(4); | |
100 | break; | |
101 | } | |
102 | } | |
103 | ||
104 | #define WR(r,v) epia_write_regr(pi,0,r,v) | |
105 | #define RR(r) (epia_read_regr(pi,0,r)) | |
106 | ||
107 | /* The use of register 0x84 is entirely unclear - it seems to control | |
108 | some EPP counters ... currently we know about 3 different block | |
109 | sizes: the standard 512 byte reads and writes, 12 byte writes and | |
110 | 2048 byte reads (the last two being used in the CDrom drivers. | |
111 | */ | |
112 | ||
113 | static void epia_connect ( PIA *pi ) | |
114 | ||
115 | { pi->saved_r0 = r0(); | |
116 | pi->saved_r2 = r2(); | |
117 | ||
118 | w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0); | |
119 | w2(1); w2(4); | |
120 | if (pi->mode >= 3) { | |
121 | w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4); | |
122 | w2(0x24); w2(0x26); w2(4); | |
123 | } | |
124 | WR(0x86,8); | |
125 | } | |
126 | ||
127 | static void epia_disconnect ( PIA *pi ) | |
128 | ||
129 | { /* WR(0x84,0x10); */ | |
130 | w0(pi->saved_r0); | |
131 | w2(1); w2(4); | |
132 | w0(pi->saved_r0); | |
133 | w2(pi->saved_r2); | |
134 | } | |
135 | ||
136 | static void epia_read_block( PIA *pi, char * buf, int count ) | |
137 | ||
138 | { int k, ph, a, b; | |
139 | ||
140 | switch (pi->mode) { | |
141 | ||
142 | case 0: w0(0x81); w2(1); w2(3); w0(0xc1); | |
143 | ph = 1; | |
144 | for (k=0;k<count;k++) { | |
145 | w2(2+ph); a = r1(); | |
146 | w2(4+ph); b = r1(); | |
147 | buf[k] = j44(a,b); | |
148 | ph = 1 - ph; | |
149 | } | |
150 | w0(0); w2(4); | |
151 | break; | |
152 | ||
153 | case 1: w0(0x91); w2(1); w0(0x10); w2(3); | |
154 | w0(0x51); w2(5); w0(0xd1); | |
155 | ph = 1; | |
156 | for (k=0;k<count;k++) { | |
157 | w2(4+ph); | |
158 | a = r1(); b = r2(); | |
159 | buf[k] = j53(a,b); | |
160 | ph = 1 - ph; | |
161 | } | |
162 | w0(0); w2(4); | |
163 | break; | |
164 | ||
165 | case 2: w0(0x89); w2(1); w2(0x23); w2(0x21); | |
166 | ph = 1; | |
167 | for (k=0;k<count;k++) { | |
168 | w2(0x24+ph); | |
169 | buf[k] = r0(); | |
170 | ph = 1 - ph; | |
171 | } | |
172 | w2(6); w2(4); | |
173 | break; | |
174 | ||
175 | case 3: if (count > 512) WR(0x84,3); | |
176 | w3(0); w2(0x24); | |
177 | for (k=0;k<count;k++) buf[k] = r4(); | |
178 | w2(4); WR(0x84,0); | |
179 | break; | |
180 | ||
181 | case 4: if (count > 512) WR(0x84,3); | |
182 | w3(0); w2(0x24); | |
183 | for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w(); | |
184 | w2(4); WR(0x84,0); | |
185 | break; | |
186 | ||
187 | case 5: if (count > 512) WR(0x84,3); | |
188 | w3(0); w2(0x24); | |
189 | for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l(); | |
190 | w2(4); WR(0x84,0); | |
191 | break; | |
192 | ||
193 | } | |
194 | } | |
195 | ||
196 | static void epia_write_block( PIA *pi, char * buf, int count ) | |
197 | ||
198 | { int ph, k, last, d; | |
199 | ||
200 | switch (pi->mode) { | |
201 | ||
202 | case 0: | |
203 | case 1: | |
204 | case 2: w0(0xa1); w2(1); w2(3); w2(1); w2(5); | |
205 | ph = 0; last = 0x8000; | |
206 | for (k=0;k<count;k++) { | |
207 | d = buf[k]; | |
208 | if (d != last) { last = d; w0(d); } | |
209 | w2(4+ph); | |
210 | ph = 1 - ph; | |
211 | } | |
212 | w2(7); w2(4); | |
213 | break; | |
214 | ||
215 | case 3: if (count < 512) WR(0x84,1); | |
216 | w3(0x40); | |
217 | for (k=0;k<count;k++) w4(buf[k]); | |
218 | if (count < 512) WR(0x84,0); | |
219 | break; | |
220 | ||
221 | case 4: if (count < 512) WR(0x84,1); | |
222 | w3(0x40); | |
223 | for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]); | |
224 | if (count < 512) WR(0x84,0); | |
225 | break; | |
226 | ||
227 | case 5: if (count < 512) WR(0x84,1); | |
228 | w3(0x40); | |
229 | for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]); | |
230 | if (count < 512) WR(0x84,0); | |
231 | break; | |
232 | ||
233 | } | |
234 | ||
235 | } | |
236 | ||
237 | static int epia_test_proto( PIA *pi, char * scratch, int verbose ) | |
238 | ||
239 | { int j, k, f; | |
240 | int e[2] = {0,0}; | |
241 | ||
242 | epia_connect(pi); | |
243 | for (j=0;j<2;j++) { | |
244 | WR(6,0xa0+j*0x10); | |
245 | for (k=0;k<256;k++) { | |
246 | WR(2,k^0xaa); | |
247 | WR(3,k^0x55); | |
248 | if (RR(2) != (k^0xaa)) e[j]++; | |
249 | } | |
250 | WR(2,1); WR(3,1); | |
251 | } | |
252 | epia_disconnect(pi); | |
253 | ||
254 | f = 0; | |
255 | epia_connect(pi); | |
256 | WR(0x84,8); | |
257 | epia_read_block(pi,scratch,512); | |
258 | for (k=0;k<256;k++) { | |
259 | if ((scratch[2*k] & 0xff) != ((k+1) & 0xff)) f++; | |
260 | if ((scratch[2*k+1] & 0xff) != ((-2-k) & 0xff)) f++; | |
261 | } | |
262 | WR(0x84,0); | |
263 | epia_disconnect(pi); | |
264 | ||
265 | if (verbose) { | |
266 | printk("%s: epia: port 0x%x, mode %d, test=(%d,%d,%d)\n", | |
267 | pi->device,pi->port,pi->mode,e[0],e[1],f); | |
268 | } | |
269 | ||
270 | return (e[0] && e[1]) || f; | |
271 | ||
272 | } | |
273 | ||
274 | ||
275 | static void epia_log_adapter( PIA *pi, char * scratch, int verbose ) | |
276 | ||
277 | { char *mode_string[6] = {"4-bit","5/3","8-bit", | |
278 | "EPP-8","EPP-16","EPP-32"}; | |
279 | ||
280 | printk("%s: epia %s, Shuttle EPIA at 0x%x, ", | |
281 | pi->device,EPIA_VERSION,pi->port); | |
282 | printk("mode %d (%s), delay %d\n",pi->mode, | |
283 | mode_string[pi->mode],pi->delay); | |
284 | ||
285 | } | |
286 | ||
287 | static struct pi_protocol epia = { | |
288 | .owner = THIS_MODULE, | |
289 | .name = "epia", | |
290 | .max_mode = 6, | |
291 | .epp_first = 3, | |
292 | .default_delay = 1, | |
293 | .max_units = 1, | |
294 | .write_regr = epia_write_regr, | |
295 | .read_regr = epia_read_regr, | |
296 | .write_block = epia_write_block, | |
297 | .read_block = epia_read_block, | |
298 | .connect = epia_connect, | |
299 | .disconnect = epia_disconnect, | |
300 | .test_proto = epia_test_proto, | |
301 | .log_adapter = epia_log_adapter, | |
302 | }; | |
303 | ||
304 | static int __init epia_init(void) | |
305 | { | |
b4178ab5 | 306 | return paride_register(&epia); |
1da177e4 LT |
307 | } |
308 | ||
309 | static void __exit epia_exit(void) | |
310 | { | |
f4330002 | 311 | paride_unregister(&epia); |
1da177e4 LT |
312 | } |
313 | ||
314 | MODULE_LICENSE("GPL"); | |
315 | module_init(epia_init) | |
316 | module_exit(epia_exit) |