diff options
Diffstat (limited to 'drivers/block/paride/epia.c')
-rw-r--r-- | drivers/block/paride/epia.c | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/drivers/block/paride/epia.c b/drivers/block/paride/epia.c new file mode 100644 index 000000000000..0f2e0c292d82 --- /dev/null +++ b/drivers/block/paride/epia.c | |||
@@ -0,0 +1,316 @@ | |||
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 | { | ||
306 | return pi_register(&epia)-1; | ||
307 | } | ||
308 | |||
309 | static void __exit epia_exit(void) | ||
310 | { | ||
311 | pi_unregister(&epia); | ||
312 | } | ||
313 | |||
314 | MODULE_LICENSE("GPL"); | ||
315 | module_init(epia_init) | ||
316 | module_exit(epia_exit) | ||