1 /*
2 fit2.c (c) 1998 Grant R. Guenther <grant@torque.net>
3 Under the terms of the GNU General Public License.
4
5 fit2.c is a low-level protocol driver for the older version
6 of the Fidelity International Technology parallel port adapter.
7 This adapter is used in their TransDisk 2000 and older TransDisk
8 3000 portable hard-drives. As far as I can tell, this device
9 supports 4-bit mode _only_.
10
11 Newer models of the FIT products use an enhanced protocol.
12 The "fit3" protocol module should support current drives.
13
14 */
15
16 #define FIT2_VERSION "1.0"
17
18 #include <linux/module.h>
19 #include <linux/delay.h>
20 #include <linux/kernel.h>
21 #include <linux/types.h>
22 #include <linux/wait.h>
23 #include <asm/io.h>
24
25 #include "paride.h"
26
27 #define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
28
29 /* cont = 0 - access the IDE register file
30 cont = 1 - access the IDE command set
31
32 NB: The FIT adapter does not appear to use the control registers.
33 So, we map ALT_STATUS to STATUS and NO-OP writes to the device
34 control register - this means that IDE reset will not work on these
35 devices.
36
37 */
38
fit2_write_regr(PIA * pi,int cont,int regr,int val)39 static void fit2_write_regr( PIA *pi, int cont, int regr, int val)
40
41 { if (cont == 1) return;
42 w2(0xc); w0(regr); w2(4); w0(val); w2(5); w0(0); w2(4);
43 }
44
fit2_read_regr(PIA * pi,int cont,int regr)45 static int fit2_read_regr( PIA *pi, int cont, int regr )
46
47 { int a, b, r;
48
49 if (cont) {
50 if (regr != 6) return 0xff;
51 r = 7;
52 } else r = regr + 0x10;
53
54 w2(0xc); w0(r); w2(4); w2(5);
55 w0(0); a = r1();
56 w0(1); b = r1();
57 w2(4);
58
59 return j44(a,b);
60
61 }
62
fit2_read_block(PIA * pi,char * buf,int count)63 static void fit2_read_block( PIA *pi, char * buf, int count )
64
65 { int k, a, b, c, d;
66
67 w2(0xc); w0(0x10);
68
69 for (k=0;k<count/4;k++) {
70
71 w2(4); w2(5);
72 w0(0); a = r1(); w0(1); b = r1();
73 w0(3); c = r1(); w0(2); d = r1();
74 buf[4*k+0] = j44(a,b);
75 buf[4*k+1] = j44(d,c);
76
77 w2(4); w2(5);
78 a = r1(); w0(3); b = r1();
79 w0(1); c = r1(); w0(0); d = r1();
80 buf[4*k+2] = j44(d,c);
81 buf[4*k+3] = j44(a,b);
82
83 }
84
85 w2(4);
86
87 }
88
fit2_write_block(PIA * pi,char * buf,int count)89 static void fit2_write_block( PIA *pi, char * buf, int count )
90
91 { int k;
92
93
94 w2(0xc); w0(0);
95 for (k=0;k<count/2;k++) {
96 w2(4); w0(buf[2*k]);
97 w2(5); w0(buf[2*k+1]);
98 }
99 w2(4);
100 }
101
fit2_connect(PIA * pi)102 static void fit2_connect ( PIA *pi )
103
104 { pi->saved_r0 = r0();
105 pi->saved_r2 = r2();
106 w2(0xcc);
107 }
108
fit2_disconnect(PIA * pi)109 static void fit2_disconnect ( PIA *pi )
110
111 { w0(pi->saved_r0);
112 w2(pi->saved_r2);
113 }
114
fit2_log_adapter(PIA * pi,char * scratch,int verbose)115 static void fit2_log_adapter( PIA *pi, char * scratch, int verbose )
116
117 { printk("%s: fit2 %s, FIT 2000 adapter at 0x%x, delay %d\n",
118 pi->device,FIT2_VERSION,pi->port,pi->delay);
119
120 }
121
fit2_init_proto(PIA * pi)122 static void fit2_init_proto( PIA *pi)
123
124 { MOD_INC_USE_COUNT;
125 }
126
fit2_release_proto(PIA * pi)127 static void fit2_release_proto( PIA *pi)
128
129 { MOD_DEC_USE_COUNT;
130 }
131
132 struct pi_protocol fit2 = {"fit2",0,1,2,1,1,
133 fit2_write_regr,
134 fit2_read_regr,
135 fit2_write_block,
136 fit2_read_block,
137 fit2_connect,
138 fit2_disconnect,
139 0,
140 0,
141 0,
142 fit2_log_adapter,
143 fit2_init_proto,
144 fit2_release_proto
145 };
146
147
148 #ifdef MODULE
149
init_module(void)150 int init_module(void)
151
152 { return pi_register( &fit2 ) - 1;
153 }
154
cleanup_module(void)155 void cleanup_module(void)
156
157 { pi_unregister( &fit2 );
158 }
159
160 #endif
161
162 /* end of fit2.c */
163 MODULE_LICENSE("GPL");
164