import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / drivers / block / paride / fit3.c
1 /* 
2         fit3.c        (c) 1998  Grant R. Guenther <grant@torque.net>
3                           Under the terms of the GNU General Public License.
4
5         fit3.c is a low-level protocol driver for newer models 
6         of the Fidelity International Technology parallel port adapter.  
7         This adapter is used in their TransDisk 3000 portable 
8         hard-drives, as well as CD-ROM, PD-CD and other devices.
9
10         The TD-2000 and certain older devices use a different protocol.
11         Try the fit2 protocol module with them.
12
13         NB:  The FIT adapters do not appear to support the control 
14         registers.  So, we map ALT_STATUS to STATUS and NO-OP writes 
15         to the device control register - this means that IDE reset 
16         will not work on these devices.
17
18 */
19
20 #define FIT3_VERSION      "1.0"
21
22 #include <linux/module.h>
23 #include <linux/delay.h>
24 #include <linux/kernel.h>
25 #include <linux/types.h>
26 #include <linux/wait.h>
27 #include <asm/io.h>
28
29 #include "paride.h"
30
31 #define j44(a,b)                (((a>>3)&0x0f)|((b<<1)&0xf0))
32
33 #define w7(byte)                {out_p(7,byte);}
34 #define r7()                    (in_p(7) & 0xff)
35
36 /* cont = 0 - access the IDE register file 
37    cont = 1 - access the IDE command set 
38
39 */
40
41 static void  fit3_write_regr( PIA *pi, int cont, int regr, int val)
42
43 {       if (cont == 1) return;
44
45         switch (pi->mode) {
46
47         case 0:
48         case 1: w2(0xc); w0(regr); w2(0x8); w2(0xc); 
49                 w0(val); w2(0xd); 
50                 w0(0);   w2(0xc);
51                 break;
52
53         case 2: w2(0xc); w0(regr); w2(0x8); w2(0xc);
54                 w4(val); w4(0);
55                 w2(0xc);
56                 break;
57
58         }
59 }
60
61 static int fit3_read_regr( PIA *pi, int cont, int regr )
62
63 {       int  a, b;
64
65         if (cont) {
66           if (regr != 6) return 0xff;
67           regr = 7;
68         } 
69
70         switch (pi->mode) {
71
72         case 0: w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc);
73                 w2(0xd); a = r1();
74                 w2(0xf); b = r1(); 
75                 w2(0xc);
76                 return j44(a,b);
77
78         case 1: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
79                 w2(0xec); w2(0xee); w2(0xef); a = r0(); 
80                 w2(0xc);
81                 return a;
82
83         case 2: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); 
84                 w2(0xec); 
85                 a = r4(); b = r4(); 
86                 w2(0xc);
87                 return a;
88
89         }
90         return -1; 
91
92 }
93
94 static void fit3_read_block( PIA *pi, char * buf, int count )
95
96 {       int  k, a, b, c, d;
97
98         switch (pi->mode) {
99
100         case 0: w2(0xc); w0(0x10); w2(0x8); w2(0xc);
101                 for (k=0;k<count/2;k++) {
102                     w2(0xd); a = r1();
103                     w2(0xf); b = r1();
104                     w2(0xc); c = r1();
105                     w2(0xe); d = r1();
106                     buf[2*k  ] = j44(a,b);
107                     buf[2*k+1] = j44(c,d);
108                 }
109                 w2(0xc);
110                 break;
111
112         case 1: w2(0xc); w0(0x90); w2(0x8); w2(0xc); 
113                 w2(0xec); w2(0xee);
114                 for (k=0;k<count/2;k++) {
115                     w2(0xef); a = r0();
116                     w2(0xee); b = r0();
117                     buf[2*k  ] = a;
118                     buf[2*k+1] = b;
119                 }
120                 w2(0xec); 
121                 w2(0xc);
122                 break;
123
124         case 2: w2(0xc); w0(0x90); w2(0x8); w2(0xc); 
125                 w2(0xec);
126                 for (k=0;k<count;k++) buf[k] = r4();
127                 w2(0xc);
128                 break;
129
130         }
131 }
132
133 static void fit3_write_block( PIA *pi, char * buf, int count )
134
135 {       int k;
136
137         switch (pi->mode) {
138
139         case 0:
140         case 1: w2(0xc); w0(0); w2(0x8); w2(0xc);
141                 for (k=0;k<count/2;k++) {
142                     w0(buf[2*k  ]); w2(0xd);
143                     w0(buf[2*k+1]); w2(0xc);
144                 }
145                 break;
146
147         case 2: w2(0xc); w0(0); w2(0x8); w2(0xc); 
148                 for (k=0;k<count;k++) w4(buf[k]);
149                 w2(0xc);
150                 break;
151         }
152 }
153
154 static void fit3_connect ( PIA *pi  )
155
156 {       pi->saved_r0 = r0();
157         pi->saved_r2 = r2();
158         w2(0xc); w0(0); w2(0xa);
159         if (pi->mode == 2) { 
160                 w2(0xc); w0(0x9); w2(0x8); w2(0xc); 
161                 }
162 }
163
164 static void fit3_disconnect ( PIA *pi )
165
166 {       w2(0xc); w0(0xa); w2(0x8); w2(0xc);
167         w0(pi->saved_r0);
168         w2(pi->saved_r2);
169
170
171 static void fit3_log_adapter( PIA *pi, char * scratch, int verbose )
172
173 {       char    *mode_string[3] = {"4-bit","8-bit","EPP"};
174
175         printk("%s: fit3 %s, FIT 3000 adapter at 0x%x, "
176                "mode %d (%s), delay %d\n",
177                 pi->device,FIT3_VERSION,pi->port,
178                 pi->mode,mode_string[pi->mode],pi->delay);
179
180 }
181
182 static void fit3_init_proto(PIA *pi)
183
184 {       MOD_INC_USE_COUNT;
185 }
186
187 static void fit3_release_proto(PIA *pi)
188
189 {       MOD_DEC_USE_COUNT;
190 }
191
192 struct pi_protocol fit3 = {"fit3",0,3,2,1,1,
193                            fit3_write_regr,
194                            fit3_read_regr,
195                            fit3_write_block,
196                            fit3_read_block,
197                            fit3_connect,
198                            fit3_disconnect,
199                            0,
200                            0,
201                            0,
202                            fit3_log_adapter,
203                            fit3_init_proto,
204                            fit3_release_proto
205                           };
206
207
208 #ifdef MODULE
209
210 int     init_module(void)
211
212 {       return pi_register( &fit3 ) - 1;
213 }
214
215 void    cleanup_module(void)
216
217 {       pi_unregister( &fit3 );
218 }
219
220 #endif
221
222 /* end of fit3.c */
223 MODULE_LICENSE("GPL");