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

source code of linux/drivers/ata/pata_parport/epia.c