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

1     /* 
2     	bpck.c	(c) 1996-8  Grant R. Guenther <grant@torque.net>
3     		            Under the terms of the GNU General Public License.
4     
5     	bpck.c is a low-level protocol driver for the MicroSolutions 
6     	"backpack" parallel port IDE adapter.  
7     
8     */
9     
10     /* Changes:
11     
12     	1.01	GRG 1998.05.05 init_proto, release_proto, pi->delay 
13     	1.02    GRG 1998.08.15 default pi->delay returned to 4
14     
15     */
16     
17     #define	BPCK_VERSION	"1.02" 
18     
19     #include <linux/module.h>
20     #include <linux/delay.h>
21     #include <linux/kernel.h>
22     #include <linux/types.h>
23     #include <linux/wait.h>
24     #include <asm/io.h>
25     
26     #include "paride.h"
27     
28     #undef r2
29     #undef w2
30     
31     #define PC			pi->private
32     #define r2()			(PC=(in_p(2) & 0xff))
33     #define w2(byte)  		{out_p(2,byte); PC = byte;}
34     #define t2(pat)   		{PC ^= pat; out_p(2,PC);}
35     #define e2()			{PC &= 0xfe; out_p(2,PC);}
36     #define o2()			{PC |= 1; out_p(2,PC);}
37     
38     #define j44(l,h)     (((l>>3)&0x7)|((l>>4)&0x8)|((h<<1)&0x70)|(h&0x80))
39     
40     /* cont = 0 - access the IDE register file 
41        cont = 1 - access the IDE command set 
42        cont = 2 - use internal bpck register addressing
43     */
44     
45     static int  cont_map[3] = { 0x40, 0x48, 0 };
46     
47     static int bpck_read_regr( PIA *pi, int cont, int regr )
48     
49     {       int r, l, h;
50     
51     	r = regr + cont_map[cont];
52     
53     	switch (pi->mode) {
54     
55     	case 0: w0(r & 0xf); w0(r); t2(2); t2(4);
56     	        l = r1();
57             	t2(4);
58             	h = r1();
59             	return j44(l,h);
60     
61     	case 1: w0(r & 0xf); w0(r); t2(2);
62     	        e2(); t2(0x20);
63     		t2(4); h = r0();
64     	        t2(1); t2(0x20);
65     	        return h;
66     
67     	case 2:
68     	case 3:
69     	case 4: w0(r); w2(9); w2(0); w2(0x20);
70     		h = r4();
71     		w2(0);
72     		return h;
73     
74     	}
75     	return -1;
76     }	
77     
78     static void bpck_write_regr( PIA *pi, int cont, int regr, int val )
79     
80     {	int	r;
81     
82             r = regr + cont_map[cont];
83     
84     	switch (pi->mode) {
85     
86     	case 0:
87     	case 1: w0(r);
88     		t2(2);
89     		w0(val);
90     		o2(); t2(4); t2(1);
91     		break;
92     
93     	case 2:
94     	case 3:
95     	case 4: w0(r); w2(9); w2(0);
96     		w0(val); w2(1); w2(3); w2(0);
97     		break;
98     
99     	}
100     }
101     
102     /* These macros access the bpck registers in native addressing */
103     
104     #define WR(r,v)		bpck_write_regr(pi,2,r,v)
105     #define RR(r)		(bpck_read_regr(pi,2,r))
106     
107     static void bpck_write_block( PIA *pi, char * buf, int count )
108     
109     {	int i;
110     
111     	switch (pi->mode) {
112     
113     	case 0: WR(4,0x40);
114     		w0(0x40); t2(2); t2(1);
115     		for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
116     		WR(4,0);
117     		break;
118     
119     	case 1: WR(4,0x50);
120                     w0(0x40); t2(2); t2(1);
121                     for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
122                     WR(4,0x10);
123     		break;
124     
125     	case 2: WR(4,0x48);
126     		w0(0x40); w2(9); w2(0); w2(1);
127     		for (i=0;i<count;i++) w4(buf[i]);
128     		w2(0);
129     		WR(4,8);
130     		break;
131     
132             case 3: WR(4,0x48);
133                     w0(0x40); w2(9); w2(0); w2(1);
134                     for (i=0;i<count/2;i++) w4w(((u16 *)buf)[i]);
135                     w2(0);
136                     WR(4,8);
137                     break;
138      
139             case 4: WR(4,0x48);
140                     w0(0x40); w2(9); w2(0); w2(1);
141                     for (i=0;i<count/4;i++) w4l(((u32 *)buf)[i]);
142                     w2(0);
143                     WR(4,8);
144                     break;
145      	}
146     }
147     
148     static void bpck_read_block( PIA *pi, char * buf, int count )
149     
150     {	int i, l, h;
151     
152     	switch (pi->mode) {
153     
154           	case 0: WR(4,0x40);
155     		w0(0x40); t2(2);
156     		for (i=0;i<count;i++) {
157     		    t2(4); l = r1();
158     		    t2(4); h = r1();
159     		    buf[i] = j44(l,h);
160     		}
161     		WR(4,0);
162     		break;
163     
164     	case 1: WR(4,0x50);
165     		w0(0x40); t2(2); t2(0x20);
166           	        for(i=0;i<count;i++) { t2(4); buf[i] = r0(); }
167     	        t2(1); t2(0x20);
168     	        WR(4,0x10);
169     		break;
170     
171     	case 2: WR(4,0x48);
172     		w0(0x40); w2(9); w2(0); w2(0x20);
173     		for (i=0;i<count;i++) buf[i] = r4();
174     		w2(0);
175     		WR(4,8);
176     		break;
177     
178             case 3: WR(4,0x48);
179                     w0(0x40); w2(9); w2(0); w2(0x20);
180                     for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
181                     w2(0);
182                     WR(4,8);
183                     break;
184     
185             case 4: WR(4,0x48);
186                     w0(0x40); w2(9); w2(0); w2(0x20);
187                     for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
188                     w2(0);
189                     WR(4,8);
190                     break;
191     
192     	}
193     }
194     
195     static int bpck_probe_unit ( PIA *pi )
196     
197     {	int o1, o0, f7, id;
198     	int t, s;
199     
200     	id = pi->unit;
201     	s = 0;
202     	w2(4); w2(0xe); r2(); t2(2); 
203     	o1 = r1()&0xf8;
204     	o0 = r0();
205     	w0(255-id); w2(4); w0(id);
206     	t2(8); t2(8); t2(8);
207     	t2(2); t = r1()&0xf8;
208     	f7 = ((id % 8) == 7);
209     	if ((f7) || (t != o1)) { t2(2); s = r1()&0xf8; }
210     	if ((t == o1) && ((!f7) || (s == o1)))  {
211     		w2(0x4c); w0(o0);
212     		return 0;	
213     	}
214     	t2(8); w0(0); t2(2); w2(0x4c); w0(o0);
215     	return 1;
216     }
217     	
218     static void bpck_connect ( PIA *pi  )
219     
220     {       pi->saved_r0 = r0();
221     	w0(0xff-pi->unit); w2(4); w0(pi->unit);
222     	t2(8); t2(8); t2(8); 
223     	t2(2); t2(2);
224     	
225     	switch (pi->mode) {
226     
227     	case 0: t2(8); WR(4,0);
228     		break;
229     
230     	case 1: t2(8); WR(4,0x10);
231     		break;
232     
233     	case 2:
234             case 3:
235     	case 4: w2(0); WR(4,8);
236     		break;
237     
238     	}
239     
240     	WR(5,8);
241     
242     	if (pi->devtype == PI_PCD) {
243     		WR(0x46,0x10);		/* fiddle with ESS logic ??? */
244     		WR(0x4c,0x38);
245     		WR(0x4d,0x88);
246     		WR(0x46,0xa0);
247     		WR(0x41,0);
248     		WR(0x4e,8);
249     		}
250     }
251     
252     static void bpck_disconnect ( PIA *pi )
253     
254     {	w0(0); 
255     	if (pi->mode >= 2) { w2(9); w2(0); } else t2(2);
256     	w2(0x4c); w0(pi->saved_r0);
257     } 
258     
259     static void bpck_force_spp ( PIA *pi )
260     
261     /* This fakes the EPP protocol to turn off EPP ... */
262     
263     {       pi->saved_r0 = r0();
264             w0(0xff-pi->unit); w2(4); w0(pi->unit);
265             t2(8); t2(8); t2(8); 
266             t2(2); t2(2);
267     
268             w2(0); 
269             w0(4); w2(9); w2(0); 
270             w0(0); w2(1); w2(3); w2(0);     
271             w0(0); w2(9); w2(0);
272             w2(0x4c); w0(pi->saved_r0);
273     }
274     
275     #define TEST_LEN  16
276     
277     static int bpck_test_proto( PIA *pi, char * scratch, int verbose )
278     
279     {	int i, e, l, h, om;
280     	char buf[TEST_LEN];
281     
282     	bpck_force_spp(pi);
283     
284     	switch (pi->mode) {
285     
286     	case 0: bpck_connect(pi);
287     		WR(0x13,0x7f);
288     		w0(0x13); t2(2);
289     		for(i=0;i<TEST_LEN;i++) {
290                         t2(4); l = r1();
291                         t2(4); h = r1();
292                         buf[i] = j44(l,h);
293     		}
294     		bpck_disconnect(pi);
295     		break;
296     
297             case 1: bpck_connect(pi);
298     		WR(0x13,0x7f);
299                     w0(0x13); t2(2); t2(0x20);
300                     for(i=0;i<TEST_LEN;i++) { t2(4); buf[i] = r0(); }
301                     t2(1); t2(0x20);
302     		bpck_disconnect(pi);
303     		break;
304     
305     	case 2:
306     	case 3:
307     	case 4: om = pi->mode;
308     		pi->mode = 0;
309     		bpck_connect(pi);
310     		WR(7,3);
311     		WR(4,8);
312     		bpck_disconnect(pi);
313     
314     		pi->mode = om;
315     		bpck_connect(pi);
316     		w0(0x13); w2(9); w2(1); w0(0); w2(3); w2(0); w2(0xe0);
317     
318     		switch (pi->mode) {
319     		  case 2: for (i=0;i<TEST_LEN;i++) buf[i] = r4();
320     			  break;
321     		  case 3: for (i=0;i<TEST_LEN/2;i++) ((u16 *)buf)[i] = r4w();
322                               break;
323     		  case 4: for (i=0;i<TEST_LEN/4;i++) ((u32 *)buf)[i] = r4l();
324                               break;
325     		}
326     
327     		w2(0);
328     		WR(7,0);
329     		bpck_disconnect(pi);
330     
331     		break;
332     
333     	}
334     
335     	if (verbose) {
336     	    printk("%s: bpck: 0x%x unit %d mode %d: ",
337     		   pi->device,pi->port,pi->unit,pi->mode);
338     	    for (i=0;i<TEST_LEN;i++) printk("%3d",buf[i]);
339     	    printk("\n");
340     	}
341     
342     	e = 0;
343     	for (i=0;i<TEST_LEN;i++) if (buf[i] != (i+1)) e++;
344     	return e;
345     }
346     
347     static void bpck_read_eeprom ( PIA *pi, char * buf )
348     
349     {       int i,j,k,n,p,v,f, om, od;
350     
351     	bpck_force_spp(pi);
352     
353     	om = pi->mode;  od = pi->delay;
354     	pi->mode = 0; pi->delay = 6;
355     
356     	bpck_connect(pi);
357     	
358     	n = 0;
359     	WR(4,0);
360     	for (i=0;i<64;i++) {
361     	    WR(6,8);  
362     	    WR(6,0xc);
363     	    p = 0x100;
364     	    for (k=0;k<9;k++) {
365     		f = (((i + 0x180) & p) != 0) * 2;
366     		WR(6,f+0xc); 
367     		WR(6,f+0xd); 
368     		WR(6,f+0xc);
369     		p = (p >> 1);
370     	    }
371     	    for (j=0;j<2;j++) {
372     		v = 0;
373     		for (k=0;k<8;k++) {
374     		    WR(6,0xc); 
375     		    WR(6,0xd); 
376     		    WR(6,0xc); 
377     		    f = RR(0);
378     		    v = 2*v + (f == 0x84);
379     		}
380     		buf[2*i+1-j] = v;
381     	    }
382     	}
383     	WR(6,8);
384     	WR(6,0);
385     	WR(5,8);
386     
387     	bpck_disconnect(pi);
388     
389             if (om >= 2) {
390                     bpck_connect(pi);
391                     WR(7,3);
392                     WR(4,8);
393                     bpck_disconnect(pi);
394             }
395     
396     	pi->mode = om; pi->delay = od;
397     }
398     
399     static int bpck_test_port ( PIA *pi ) 	/* check for 8-bit port */
400     
401     {	int	i, r, m;
402     
403     	w2(0x2c); i = r0(); w0(255-i); r = r0(); w0(i);
404     	m = -1;
405     	if (r == i) m = 2;
406     	if (r == (255-i)) m = 0;
407     
408     	w2(0xc); i = r0(); w0(255-i); r = r0(); w0(i);
409     	if (r != (255-i)) m = -1;
410     	
411     	if (m == 0) { w2(6); w2(0xc); r = r0(); w0(0xaa); w0(r); w0(0xaa); }
412     	if (m == 2) { w2(0x26); w2(0xc); }
413     
414     	if (m == -1) return 0;
415     	return 5;
416     }
417     
418     static void bpck_log_adapter( PIA *pi, char * scratch, int verbose )
419     
420     {	char	*mode_string[5] = { "4-bit","8-bit","EPP-8",
421     				    "EPP-16","EPP-32" };
422     
423     #ifdef DUMP_EEPROM
424     	int i;
425     #endif
426     
427     	bpck_read_eeprom(pi,scratch);
428     
429     #ifdef DUMP_EEPROM
430     	if (verbose) {
431     	   for(i=0;i<128;i++)
432     		if ((scratch[i] < ' ') || (scratch[i] > '~'))
433     		    scratch[i] = '.';
434     	   printk("%s: bpck EEPROM: %64.64s\n",pi->device,scratch);
435     	   printk("%s:              %64.64s\n",pi->device,&scratch[64]);
436     	}
437     #endif
438     
439     	printk("%s: bpck %s, backpack %8.8s unit %d",
440     		pi->device,BPCK_VERSION,&scratch[110],pi->unit);
441     	printk(" at 0x%x, mode %d (%s), delay %d\n",pi->port,
442     		pi->mode,mode_string[pi->mode],pi->delay);
443     }
444     
445     static void bpck_init_proto( PIA *pi)
446     
447     {	MOD_INC_USE_COUNT;
448     }
449     
450     static void bpck_release_proto( PIA *pi)
451     
452     {       MOD_DEC_USE_COUNT;
453     }
454     
455     struct pi_protocol bpck = { "bpck",0,5,2,4,256,
456     			  bpck_write_regr,
457     			  bpck_read_regr,
458     			  bpck_write_block,
459     			  bpck_read_block,
460     			  bpck_connect,
461     			  bpck_disconnect,
462     			  bpck_test_port,
463     			  bpck_probe_unit,
464     		          bpck_test_proto,
465     			  bpck_log_adapter,
466     			  bpck_init_proto,
467     			  bpck_release_proto
468     			};
469     
470     #ifdef MODULE
471     
472     int	init_module(void)
473     
474     {	return pi_register(&bpck) - 1;
475     }
476     
477     void	cleanup_module(void)
478     
479     {	pi_unregister(&bpck);
480     }
481     
482     #endif
483     
484     /* end of bpck.c */
485