xref: /linux/drivers/ata/pata_parport/dstr.c (revision 3d0fe49454652117522f60bfbefb978ba0e5300b)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * (c) 1997-1998  Grant R. Guenther <grant@torque.net>
4  *
5  * dstr.c is a low-level protocol driver for the DataStor EP2000 parallel
6  * to IDE adapter chip.
7  */
8 
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/delay.h>
12 #include <linux/kernel.h>
13 #include <linux/types.h>
14 #include <linux/wait.h>
15 #include <asm/io.h>
16 #include "pata_parport.h"
17 
18 /*
19  * mode codes:  0  nybble reads, 8-bit writes
20  *		1  8-bit reads and writes
21  *		2  8-bit EPP mode
22  *		3  EPP-16
23  *		4  EPP-32
24  */
25 
26 #define j44(a, b)  (((a >> 3) & 0x07) | ((~a >> 4) & 0x08) | \
27 		    ((b << 1) & 0x70) | ((~b) & 0x80))
28 
29 #define P1	w2(5);w2(0xd);w2(5);w2(4);
30 #define P2	w2(5);w2(7);w2(5);w2(4);
31 #define P3      w2(6);w2(4);w2(6);w2(4);
32 
33 /*
34  * cont = 0 - access the IDE register file
35  * cont = 1 - access the IDE command set
36  */
37 static int  cont_map[2] = { 0x20, 0x40 };
38 
39 static int dstr_read_regr(struct pi_adapter *pi, int cont, int regr)
40 {
41 	int a, b, r;
42 
43 	r = regr + cont_map[cont];
44 
45 	w0(0x81); P1;
46 	if (pi->mode)
47 		w0(0x11);
48 	else
49 		w0(1);
50 	P2; w0(r); P1;
51 
52 	switch (pi->mode) {
53 	case 0:
54 		w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4);
55 		return j44(a, b);
56 	case 1:
57 		w0(0); w2(0x26); a = r0(); w2(4);
58 		return a;
59 	case 2:
60 	case 3:
61 	case 4:
62 		w2(0x24); a = r4(); w2(4);
63 		return a;
64 	}
65 
66 	return -1;
67 }
68 
69 static void dstr_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
70 {
71 	int  r = regr + cont_map[cont];
72 
73 	w0(0x81); P1;
74 	if (pi->mode >= 2)
75 		w0(0x11);
76 	else
77 		w0(1);
78 	P2; w0(r); P1;
79 
80 	switch (pi->mode)  {
81 	case 0:
82 	case 1:
83 		w0(val); w2(5); w2(7); w2(5); w2(4);
84 		break;
85 	case 2:
86 	case 3:
87 	case 4:
88 		w4(val);
89 		break;
90 	}
91 }
92 
93 #define  CCP(x)						\
94 	do {						\
95 		w0(0xff); w2(0xc); w2(4);		\
96 		w0(0xaa); w0(0x55); w0(0); w0(0xff);	\
97 		w0(0x87); w0(0x78);			\
98 		w0(x); w2(5); w2(4);			\
99 	} while (0)
100 
101 static void dstr_connect(struct pi_adapter *pi)
102 {
103 	pi->saved_r0 = r0();
104 	pi->saved_r2 = r2();
105 	w2(4); CCP(0xe0); w0(0xff);
106 }
107 
108 static void dstr_disconnect(struct pi_adapter *pi)
109 {
110 	CCP(0x30);
111 	w0(pi->saved_r0);
112 	w2(pi->saved_r2);
113 }
114 
115 static void dstr_read_block(struct pi_adapter *pi, char *buf, int count)
116 {
117 	int k, a, b;
118 
119         w0(0x81); P1;
120 	if (pi->mode)
121 		w0(0x19);
122 	else
123 		w0(9);
124 	P2; w0(0x82); P1; P3; w0(0x20); P1;
125 
126 	switch (pi->mode) {
127 	case 0:
128 		for (k = 0; k < count; k++) {
129 			w2(6); a = r1(); w2(4);
130 			w2(6); b = r1(); w2(4);
131 			buf[k] = j44(a, b);
132 		}
133 		break;
134 	case 1:
135 		w0(0);
136 		for (k = 0; k < count; k++) {
137 			w2(0x26);
138 			buf[k] = r0();
139 			w2(0x24);
140 		}
141 		w2(4);
142 		break;
143 	case 2:
144 		w2(0x24);
145 		for (k = 0; k < count; k++)
146 			buf[k] = r4();
147 		w2(4);
148 		break;
149 	case 3:
150 		w2(0x24);
151 		for (k = 0; k < count / 2; k++)
152 			((u16 *)buf)[k] = r4w();
153 		w2(4);
154 		break;
155 	case 4:
156 		w2(0x24);
157 		for (k = 0; k < count / 4; k++)
158 			((u32 *)buf)[k] = r4l();
159 		w2(4);
160 		break;
161 	}
162 }
163 
164 static void dstr_write_block(struct pi_adapter *pi, char *buf, int count)
165 {
166 	int k;
167 
168 	w0(0x81); P1;
169 	if (pi->mode)
170 		w0(0x19);
171 	else
172 		w0(9);
173 	P2; w0(0x82); P1; P3; w0(0x20); P1;
174 
175 	switch (pi->mode) {
176 	case 0:
177 	case 1:
178 		for (k = 0; k < count; k++) {
179 			w2(5);
180 			w0(buf[k]);
181 			w2(7);
182 		}
183 		w2(5); w2(4);
184 		break;
185 	case 2:
186 		w2(0xc5);
187 		for (k = 0; k < count; k++)
188 			w4(buf[k]);
189 		w2(0xc4);
190 		break;
191 	case 3:
192 		w2(0xc5);
193 		for (k = 0; k < count / 2; k++)
194 			w4w(((u16 *)buf)[k]);
195 		w2(0xc4);
196 		break;
197 	case 4:
198 		w2(0xc5);
199 		for (k = 0; k < count / 4; k++)
200 			w4l(((u32 *)buf)[k]);
201 		w2(0xc4);
202 		break;
203 	}
204 }
205 
206 static void dstr_log_adapter(struct pi_adapter *pi)
207 
208 {
209 	char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
210 
211 	dev_info(&pi->dev,
212 		 "DataStor EP2000 at 0x%x, mode %d (%s), delay %d\n",
213 		 pi->port, pi->mode, mode_string[pi->mode], pi->delay);
214 }
215 
216 static struct pi_protocol dstr = {
217 	.owner		= THIS_MODULE,
218 	.name		= "dstr",
219 	.max_mode	= 5,
220 	.epp_first	= 2,
221 	.default_delay	= 1,
222 	.max_units	= 1,
223 	.write_regr	= dstr_write_regr,
224 	.read_regr	= dstr_read_regr,
225 	.write_block	= dstr_write_block,
226 	.read_block	= dstr_read_block,
227 	.connect	= dstr_connect,
228 	.disconnect	= dstr_disconnect,
229 	.log_adapter	= dstr_log_adapter,
230 };
231 
232 MODULE_LICENSE("GPL");
233 MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
234 MODULE_DESCRIPTION("DataStor EP2000 parallel port IDE adapter protocol driver");
235 module_pata_parport_driver(dstr);
236