xref: /linux/drivers/ata/pata_parport/on26.c (revision 84b9b44b)
1 /*
2         on26.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
3                               Under the terms of the GNU General Public License.
4 
5         on26.c is a low-level protocol driver for the
6         OnSpec 90c26 parallel to IDE adapter chip.
7 
8 */
9 
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/delay.h>
13 #include <linux/kernel.h>
14 #include <linux/types.h>
15 #include <linux/wait.h>
16 #include <asm/io.h>
17 #include "pata_parport.h"
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>>4)&0x0f)|(b&0xf0))
27 
28 #define P1	w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4);
29 #define P2	w2(5);w2(7);w2(5);w2(4);
30 
31 /* cont = 0 - access the IDE register file
32    cont = 1 - access the IDE command set
33 */
34 
35 static int on26_read_regr(struct pi_adapter *pi, int cont, int regr)
36 
37 {       int     a, b, r;
38 
39 	r = (regr<<2) + 1 + cont;
40 
41         switch (pi->mode)  {
42 
43         case 0: w0(1); P1; w0(r); P2; w0(0); P1;
44 		w2(6); a = r1(); w2(4);
45 		w2(6); b = r1(); w2(4);
46 		w2(6); w2(4); w2(6); w2(4);
47                 return j44(a,b);
48 
49         case 1: w0(1); P1; w0(r); P2; w0(0); P1;
50 		w2(0x26); a = r0(); w2(4); w2(0x26); w2(4);
51                 return a;
52 
53 	case 2:
54 	case 3:
55         case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
56 		w3(0); w3(0); w2(0x24); a = r4(); w2(4);
57 		w2(0x24); (void)r4(); w2(4);
58                 return a;
59 
60         }
61         return -1;
62 }
63 
64 static void on26_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
65 
66 {       int  r;
67 
68         r = (regr<<2) + 1 + cont;
69 
70         switch (pi->mode)  {
71 
72         case 0:
73         case 1: w0(1); P1; w0(r); P2; w0(0); P1;
74 		w0(val); P2; w0(val); P2;
75 		break;
76 
77 	case 2:
78 	case 3:
79         case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
80 		w3(0); w3(0);
81 		w2(5); w4(val); w2(4);
82 		w2(5); w4(val); w2(4);
83                 break;
84         }
85 }
86 
87 #define  CCP(x)  w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
88 		 w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
89 
90 static void on26_connect(struct pi_adapter *pi)
91 
92 {       int	x;
93 
94 	pi->saved_r0 = r0();
95         pi->saved_r2 = r2();
96 
97         CCP(0x20);
98 	x = 8; if (pi->mode) x = 9;
99 
100 	w0(2); P1; w0(8); P2;
101 	w0(2); P1; w0(x); P2;
102 }
103 
104 static void on26_disconnect(struct pi_adapter *pi)
105 
106 {       if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); }
107 	              else { w0(4); P1; w0(4); P1; }
108 	CCP(0x30);
109         w0(pi->saved_r0);
110         w2(pi->saved_r2);
111 }
112 
113 #define	RESET_WAIT  200
114 
115 static int on26_test_port(struct pi_adapter *pi)  /* hard reset */
116 
117 {       int     i, m, d, x=0, y=0;
118 
119         pi->saved_r0 = r0();
120         pi->saved_r2 = r2();
121 
122         d = pi->delay;
123         m = pi->mode;
124         pi->delay = 5;
125         pi->mode = 0;
126 
127         w2(0xc);
128 
129         CCP(0x30); CCP(0);
130 
131         w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);
132         i = ((r1() & 0xf0) << 4); w0(0x87);
133         i |= (r1() & 0xf0); w0(0x78);
134         w0(0x20);w2(4);w2(5);
135         i |= ((r1() & 0xf0) >> 4);
136         w2(4);w0(0xff);
137 
138         if (i == 0xb5f) {
139 
140             w0(2); P1; w0(0);   P2;
141             w0(3); P1; w0(0);   P2;
142             w0(2); P1; w0(8);   P2; udelay(100);
143             w0(2); P1; w0(0xa); P2; udelay(100);
144             w0(2); P1; w0(8);   P2; udelay(1000);
145 
146             on26_write_regr(pi,0,6,0xa0);
147 
148             for (i=0;i<RESET_WAIT;i++) {
149                 on26_write_regr(pi,0,6,0xa0);
150                 x = on26_read_regr(pi,0,7);
151                 on26_write_regr(pi,0,6,0xb0);
152                 y = on26_read_regr(pi,0,7);
153                 if (!((x&0x80)||(y&0x80))) break;
154                 mdelay(100);
155             }
156 
157 	    if (i == RESET_WAIT)
158 		dev_err(&pi->dev, "on26: Device reset failed (%x,%x)\n", x, y);
159 
160             w0(4); P1; w0(4); P1;
161         }
162 
163         CCP(0x30);
164 
165         pi->delay = d;
166         pi->mode = m;
167         w0(pi->saved_r0);
168         w2(pi->saved_r2);
169 
170         return 5;
171 }
172 
173 
174 static void on26_read_block(struct pi_adapter *pi, char *buf, int count)
175 
176 {       int     k, a, b;
177 
178         switch (pi->mode) {
179 
180         case 0: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1;
181 		udelay(10);
182 		for (k=0;k<count;k++) {
183                         w2(6); a = r1();
184                         w2(4); b = r1();
185                         buf[k] = j44(a,b);
186                 }
187 		w0(2); P1; w0(8); P2;
188                 break;
189 
190         case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
191 		udelay(10);
192                 for (k=0;k<count/2;k++) {
193                         w2(0x26); buf[2*k] = r0();
194 			w2(0x24); buf[2*k+1] = r0();
195                 }
196                 w0(2); P1; w0(9); P2;
197                 break;
198 
199         case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
200 		w3(0); w3(0); w2(0x24);
201 		udelay(10);
202                 for (k=0;k<count;k++) buf[k] = r4();
203                 w2(4);
204                 break;
205 
206         case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
207                 w3(0); w3(0); w2(0x24);
208                 udelay(10);
209                 for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
210                 w2(4);
211                 break;
212 
213         case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
214                 w3(0); w3(0); w2(0x24);
215                 udelay(10);
216                 for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
217                 w2(4);
218                 break;
219 
220         }
221 }
222 
223 static void on26_write_block(struct pi_adapter *pi, char *buf, int count)
224 
225 {       int	k;
226 
227         switch (pi->mode) {
228 
229         case 0:
230         case 1: w0(1); P1; w0(1); P2;
231 		w0(2); P1; w0(0x18+pi->mode); P2; w0(0); P1;
232 		udelay(10);
233 		for (k=0;k<count/2;k++) {
234                         w2(5); w0(buf[2*k]);
235 			w2(7); w0(buf[2*k+1]);
236                 }
237                 w2(5); w2(4);
238 		w0(2); P1; w0(8+pi->mode); P2;
239                 break;
240 
241         case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
242 		w3(0); w3(0); w2(0xc5);
243 		udelay(10);
244                 for (k=0;k<count;k++) w4(buf[k]);
245 		w2(0xc4);
246                 break;
247 
248         case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
249                 w3(0); w3(0); w2(0xc5);
250                 udelay(10);
251                 for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
252                 w2(0xc4);
253                 break;
254 
255         case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
256                 w3(0); w3(0); w2(0xc5);
257                 udelay(10);
258                 for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
259                 w2(0xc4);
260                 break;
261 
262         }
263 
264 }
265 
266 static void on26_log_adapter(struct pi_adapter *pi)
267 
268 {       char    *mode_string[5] = {"4-bit","8-bit","EPP-8",
269 				   "EPP-16","EPP-32"};
270 
271 	dev_info(&pi->dev, "OnSpec 90c26 at 0x%x, mode %d (%s), delay %d\n",
272 		pi->port, pi->mode, mode_string[pi->mode], pi->delay);
273 }
274 
275 static struct pi_protocol on26 = {
276 	.owner		= THIS_MODULE,
277 	.name		= "on26",
278 	.max_mode	= 5,
279 	.epp_first	= 2,
280 	.default_delay	= 1,
281 	.max_units	= 1,
282 	.write_regr	= on26_write_regr,
283 	.read_regr	= on26_read_regr,
284 	.write_block	= on26_write_block,
285 	.read_block	= on26_read_block,
286 	.connect	= on26_connect,
287 	.disconnect	= on26_disconnect,
288 	.test_port	= on26_test_port,
289 	.log_adapter	= on26_log_adapter,
290 };
291 
292 MODULE_LICENSE("GPL");
293 module_pata_parport_driver(on26);
294