File: /usr/src/linux/drivers/block/paride/on26.c

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     /* Changes:
11     
12             1.01    GRG 1998.05.06 init_proto, release_proto
13     	1.02    GRG 1998.09.23 updates for the -E rev chip
14     	1.03    GRG 1998.12.14 fix for slave drives
15     	1.04    GRG 1998.12.20 yet another bug fix
16     
17     */
18     
19     #define ON26_VERSION      "1.04"
20     
21     #include <linux/module.h>
22     #include <linux/delay.h>
23     #include <linux/kernel.h>
24     #include <linux/types.h>
25     #include <linux/wait.h>
26     #include <asm/io.h>
27     
28     #include "paride.h"
29     
30     /* mode codes:  0  nybble reads, 8-bit writes
31                     1  8-bit reads and writes
32                     2  8-bit EPP mode
33     		3  EPP-16
34     		4  EPP-32
35     */
36     
37     #define j44(a,b)  (((a>>4)&0x0f)|(b&0xf0))
38     
39     #define P1	w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4);
40     #define P2	w2(5);w2(7);w2(5);w2(4);
41     
42     /* cont = 0 - access the IDE register file 
43        cont = 1 - access the IDE command set 
44     */
45     
46     static int on26_read_regr( PIA *pi, int cont, int regr )
47     
48     {       int     a, b, r;
49     
50     	r = (regr<<2) + 1 + cont;
51     
52             switch (pi->mode)  {
53     
54             case 0: w0(1); P1; w0(r); P2; w0(0); P1; 
55     		w2(6); a = r1(); w2(4);
56     		w2(6); b = r1(); w2(4);
57     		w2(6); w2(4); w2(6); w2(4);
58                     return j44(a,b);
59     
60             case 1: w0(1); P1; w0(r); P2; w0(0); P1;
61     		w2(0x26); a = r0(); w2(4); w2(0x26); w2(4);
62                     return a;
63     
64     	case 2:
65     	case 3:
66             case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
67     		w3(0); w3(0); w2(0x24); a = r4(); w2(4);
68     		w2(0x24); r4(); w2(4);
69                     return a;
70     
71             }
72             return -1;
73     }       
74     
75     static void on26_write_regr( PIA *pi, int cont, int regr, int val )
76     
77     {       int  r;
78     
79             r = (regr<<2) + 1 + cont;
80     
81             switch (pi->mode)  {
82     
83             case 0:
84             case 1: w0(1); P1; w0(r); P2; w0(0); P1;
85     		w0(val); P2; w0(val); P2;
86     		break;
87     
88     	case 2:
89     	case 3:
90             case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
91     		w3(0); w3(0); 
92     		w2(5); w4(val); w2(4);
93     		w2(5); w4(val); w2(4);
94                     break;
95             }
96     }
97     
98     #define  CCP(x)  w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
99     		 w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
100     
101     static void on26_connect ( PIA *pi )
102     
103     {       int	x;
104     
105     	pi->saved_r0 = r0();
106             pi->saved_r2 = r2();
107     
108             CCP(0x20);
109     	x = 8; if (pi->mode) x = 9;
110     
111     	w0(2); P1; w0(8); P2;
112     	w0(2); P1; w0(x); P2;
113     }
114     
115     static void on26_disconnect ( PIA *pi )
116     
117     {       if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); }
118     	              else { w0(4); P1; w0(4); P1; }
119     	CCP(0x30);
120             w0(pi->saved_r0);
121             w2(pi->saved_r2);
122     } 
123     
124     #define	RESET_WAIT  200
125     
126     static int on26_test_port( PIA *pi)  /* hard reset */
127     
128     {       int     i, m, d, x=0, y=0;
129     
130             pi->saved_r0 = r0();
131             pi->saved_r2 = r2();
132     
133             d = pi->delay;
134             m = pi->mode;
135             pi->delay = 5;
136             pi->mode = 0;
137     
138             w2(0xc);
139     
140             CCP(0x30); CCP(0); 
141     
142             w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);
143             i = ((r1() & 0xf0) << 4); w0(0x87);
144             i |= (r1() & 0xf0); w0(0x78);
145             w0(0x20);w2(4);w2(5);
146             i |= ((r1() & 0xf0) >> 4);
147             w2(4);w0(0xff);
148     
149             if (i == 0xb5f) {
150     
151                 w0(2); P1; w0(0);   P2;
152                 w0(3); P1; w0(0);   P2;
153                 w0(2); P1; w0(8);   P2; udelay(100);
154                 w0(2); P1; w0(0xa); P2; udelay(100);
155                 w0(2); P1; w0(8);   P2; udelay(1000);
156                 
157                 on26_write_regr(pi,0,6,0xa0);
158     
159                 for (i=0;i<RESET_WAIT;i++) {
160                     on26_write_regr(pi,0,6,0xa0);
161                     x = on26_read_regr(pi,0,7);
162                     on26_write_regr(pi,0,6,0xb0);
163                     y = on26_read_regr(pi,0,7);
164                     if (!((x&0x80)||(y&0x80))) break;
165                     mdelay(100);
166                 }
167     
168     	    if (i == RESET_WAIT) 
169     		printk("on26: Device reset failed (%x,%x)\n",x,y);
170     
171                 w0(4); P1; w0(4); P1;
172             }
173     
174             CCP(0x30);
175     
176             pi->delay = d;
177             pi->mode = m;
178             w0(pi->saved_r0);
179             w2(pi->saved_r2);
180     
181             return 5;
182     }
183     
184     
185     static void on26_read_block( PIA *pi, char * buf, int count )
186     
187     {       int     k, a, b;
188     
189             switch (pi->mode) {
190     
191             case 0: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1;
192     		udelay(10);
193     		for (k=0;k<count;k++) {
194                             w2(6); a = r1();
195                             w2(4); b = r1();
196                             buf[k] = j44(a,b);
197                     }
198     		w0(2); P1; w0(8); P2; 
199                     break;
200     
201             case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
202     		udelay(10);
203                     for (k=0;k<count/2;k++) {
204                             w2(0x26); buf[2*k] = r0();  
205     			w2(0x24); buf[2*k+1] = r0();
206                     }
207                     w0(2); P1; w0(9); P2;
208                     break;
209     
210             case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
211     		w3(0); w3(0); w2(0x24);
212     		udelay(10);
213                     for (k=0;k<count;k++) buf[k] = r4();
214                     w2(4);
215                     break;
216     
217             case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
218                     w3(0); w3(0); w2(0x24);
219                     udelay(10);
220                     for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
221                     w2(4);
222                     break;
223     
224             case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
225                     w3(0); w3(0); w2(0x24);
226                     udelay(10);
227                     for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
228                     w2(4);
229                     break;
230     
231             }
232     }
233     
234     static void on26_write_block( PIA *pi, char * buf, int count )
235     
236     {       int	k;
237     
238             switch (pi->mode) {
239     
240             case 0: 
241             case 1: w0(1); P1; w0(1); P2; 
242     		w0(2); P1; w0(0x18+pi->mode); P2; w0(0); P1;
243     		udelay(10);
244     		for (k=0;k<count/2;k++) {
245                             w2(5); w0(buf[2*k]); 
246     			w2(7); w0(buf[2*k+1]);
247                     }
248                     w2(5); w2(4);
249     		w0(2); P1; w0(8+pi->mode); P2;
250                     break;
251     
252             case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
253     		w3(0); w3(0); w2(0xc5);
254     		udelay(10);
255                     for (k=0;k<count;k++) w4(buf[k]);
256     		w2(0xc4);
257                     break;
258     
259             case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
260                     w3(0); w3(0); w2(0xc5);
261                     udelay(10);
262                     for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
263                     w2(0xc4);
264                     break;
265     
266             case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
267                     w3(0); w3(0); w2(0xc5);
268                     udelay(10);
269                     for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
270                     w2(0xc4);
271                     break;
272     
273             }
274     
275     }
276     
277     static void on26_log_adapter( PIA *pi, char * scratch, int verbose )
278     
279     {       char    *mode_string[5] = {"4-bit","8-bit","EPP-8",
280     				   "EPP-16","EPP-32"};
281     
282             printk("%s: on26 %s, OnSpec 90c26 at 0x%x, ",
283                     pi->device,ON26_VERSION,pi->port);
284             printk("mode %d (%s), delay %d\n",pi->mode,
285     		mode_string[pi->mode],pi->delay);
286     
287     }
288     
289     static void on26_init_proto( PIA *pi)
290     
291     {       MOD_INC_USE_COUNT;
292     }
293     
294     static void on26_release_proto( PIA *pi)
295     
296     {       MOD_DEC_USE_COUNT;
297     }
298     
299     struct pi_protocol on26 = {"on26",0,5,2,1,1,
300                                on26_write_regr,
301                                on26_read_regr,
302                                on26_write_block,
303                                on26_read_block,
304                                on26_connect,
305                                on26_disconnect,
306                                on26_test_port,
307                                0,
308                                0,
309                                on26_log_adapter,
310                                on26_init_proto,
311                                on26_release_proto
312                               };
313     
314     
315     #ifdef MODULE
316     
317     int     init_module(void)
318     
319     {       return pi_register( &on26 ) - 1;
320     }
321     
322     void    cleanup_module(void)
323     
324     {       pi_unregister( &on26 );
325     }
326     
327     #endif
328     
329     /* end of on26.c */
330     
331