import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / 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 MODULE_LICENSE("GPL");