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, scratch, 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