Back to home page

OSCL-LXR

 
 

    


0001 /* 
0002     bpck.c  (c) 1996-8  Grant R. Guenther <grant@torque.net>
0003                     Under the terms of the GNU General Public License.
0004 
0005     bpck.c is a low-level protocol driver for the MicroSolutions 
0006     "backpack" parallel port IDE adapter.  
0007 
0008 */
0009 
0010 /* Changes:
0011 
0012     1.01    GRG 1998.05.05 init_proto, release_proto, pi->delay 
0013     1.02    GRG 1998.08.15 default pi->delay returned to 4
0014 
0015 */
0016 
0017 #define BPCK_VERSION    "1.02" 
0018 
0019 #include <linux/module.h>
0020 #include <linux/init.h>
0021 #include <linux/delay.h>
0022 #include <linux/kernel.h>
0023 #include <linux/types.h>
0024 #include <linux/wait.h>
0025 #include <asm/io.h>
0026 
0027 #include "paride.h"
0028 
0029 #undef r2
0030 #undef w2
0031 #undef PC
0032 
0033 #define PC          pi->private
0034 #define r2()            (PC=(in_p(2) & 0xff))
0035 #define w2(byte)        {out_p(2,byte); PC = byte;}
0036 #define t2(pat)         {PC ^= pat; out_p(2,PC);}
0037 #define e2()            {PC &= 0xfe; out_p(2,PC);}
0038 #define o2()            {PC |= 1; out_p(2,PC);}
0039 
0040 #define j44(l,h)     (((l>>3)&0x7)|((l>>4)&0x8)|((h<<1)&0x70)|(h&0x80))
0041 
0042 /* cont = 0 - access the IDE register file 
0043    cont = 1 - access the IDE command set 
0044    cont = 2 - use internal bpck register addressing
0045 */
0046 
0047 static int  cont_map[3] = { 0x40, 0x48, 0 };
0048 
0049 static int bpck_read_regr( PIA *pi, int cont, int regr )
0050 
0051 {       int r, l, h;
0052 
0053     r = regr + cont_map[cont];
0054 
0055     switch (pi->mode) {
0056 
0057     case 0: w0(r & 0xf); w0(r); t2(2); t2(4);
0058             l = r1();
0059             t2(4);
0060             h = r1();
0061             return j44(l,h);
0062 
0063     case 1: w0(r & 0xf); w0(r); t2(2);
0064             e2(); t2(0x20);
0065         t2(4); h = r0();
0066             t2(1); t2(0x20);
0067             return h;
0068 
0069     case 2:
0070     case 3:
0071     case 4: w0(r); w2(9); w2(0); w2(0x20);
0072         h = r4();
0073         w2(0);
0074         return h;
0075 
0076     }
0077     return -1;
0078 }   
0079 
0080 static void bpck_write_regr( PIA *pi, int cont, int regr, int val )
0081 
0082 {   int r;
0083 
0084         r = regr + cont_map[cont];
0085 
0086     switch (pi->mode) {
0087 
0088     case 0:
0089     case 1: w0(r);
0090         t2(2);
0091         w0(val);
0092         o2(); t2(4); t2(1);
0093         break;
0094 
0095     case 2:
0096     case 3:
0097     case 4: w0(r); w2(9); w2(0);
0098         w0(val); w2(1); w2(3); w2(0);
0099         break;
0100 
0101     }
0102 }
0103 
0104 /* These macros access the bpck registers in native addressing */
0105 
0106 #define WR(r,v)     bpck_write_regr(pi,2,r,v)
0107 #define RR(r)       (bpck_read_regr(pi,2,r))
0108 
0109 static void bpck_write_block( PIA *pi, char * buf, int count )
0110 
0111 {   int i;
0112 
0113     switch (pi->mode) {
0114 
0115     case 0: WR(4,0x40);
0116         w0(0x40); t2(2); t2(1);
0117         for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
0118         WR(4,0);
0119         break;
0120 
0121     case 1: WR(4,0x50);
0122                 w0(0x40); t2(2); t2(1);
0123                 for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
0124                 WR(4,0x10);
0125         break;
0126 
0127     case 2: WR(4,0x48);
0128         w0(0x40); w2(9); w2(0); w2(1);
0129         for (i=0;i<count;i++) w4(buf[i]);
0130         w2(0);
0131         WR(4,8);
0132         break;
0133 
0134         case 3: WR(4,0x48);
0135                 w0(0x40); w2(9); w2(0); w2(1);
0136                 for (i=0;i<count/2;i++) w4w(((u16 *)buf)[i]);
0137                 w2(0);
0138                 WR(4,8);
0139                 break;
0140  
0141         case 4: WR(4,0x48);
0142                 w0(0x40); w2(9); w2(0); w2(1);
0143                 for (i=0;i<count/4;i++) w4l(((u32 *)buf)[i]);
0144                 w2(0);
0145                 WR(4,8);
0146                 break;
0147     }
0148 }
0149 
0150 static void bpck_read_block( PIA *pi, char * buf, int count )
0151 
0152 {   int i, l, h;
0153 
0154     switch (pi->mode) {
0155 
0156         case 0: WR(4,0x40);
0157         w0(0x40); t2(2);
0158         for (i=0;i<count;i++) {
0159             t2(4); l = r1();
0160             t2(4); h = r1();
0161             buf[i] = j44(l,h);
0162         }
0163         WR(4,0);
0164         break;
0165 
0166     case 1: WR(4,0x50);
0167         w0(0x40); t2(2); t2(0x20);
0168                 for(i=0;i<count;i++) { t2(4); buf[i] = r0(); }
0169             t2(1); t2(0x20);
0170             WR(4,0x10);
0171         break;
0172 
0173     case 2: WR(4,0x48);
0174         w0(0x40); w2(9); w2(0); w2(0x20);
0175         for (i=0;i<count;i++) buf[i] = r4();
0176         w2(0);
0177         WR(4,8);
0178         break;
0179 
0180         case 3: WR(4,0x48);
0181                 w0(0x40); w2(9); w2(0); w2(0x20);
0182                 for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
0183                 w2(0);
0184                 WR(4,8);
0185                 break;
0186 
0187         case 4: WR(4,0x48);
0188                 w0(0x40); w2(9); w2(0); w2(0x20);
0189                 for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
0190                 w2(0);
0191                 WR(4,8);
0192                 break;
0193 
0194     }
0195 }
0196 
0197 static int bpck_probe_unit ( PIA *pi )
0198 
0199 {   int o1, o0, f7, id;
0200     int t, s;
0201 
0202     id = pi->unit;
0203     s = 0;
0204     w2(4); w2(0xe); r2(); t2(2); 
0205     o1 = r1()&0xf8;
0206     o0 = r0();
0207     w0(255-id); w2(4); w0(id);
0208     t2(8); t2(8); t2(8);
0209     t2(2); t = r1()&0xf8;
0210     f7 = ((id % 8) == 7);
0211     if ((f7) || (t != o1)) { t2(2); s = r1()&0xf8; }
0212     if ((t == o1) && ((!f7) || (s == o1)))  {
0213         w2(0x4c); w0(o0);
0214         return 0;   
0215     }
0216     t2(8); w0(0); t2(2); w2(0x4c); w0(o0);
0217     return 1;
0218 }
0219     
0220 static void bpck_connect ( PIA *pi  )
0221 
0222 {       pi->saved_r0 = r0();
0223     w0(0xff-pi->unit); w2(4); w0(pi->unit);
0224     t2(8); t2(8); t2(8); 
0225     t2(2); t2(2);
0226     
0227     switch (pi->mode) {
0228 
0229     case 0: t2(8); WR(4,0);
0230         break;
0231 
0232     case 1: t2(8); WR(4,0x10);
0233         break;
0234 
0235     case 2:
0236         case 3:
0237     case 4: w2(0); WR(4,8);
0238         break;
0239 
0240     }
0241 
0242     WR(5,8);
0243 
0244     if (pi->devtype == PI_PCD) {
0245         WR(0x46,0x10);      /* fiddle with ESS logic ??? */
0246         WR(0x4c,0x38);
0247         WR(0x4d,0x88);
0248         WR(0x46,0xa0);
0249         WR(0x41,0);
0250         WR(0x4e,8);
0251         }
0252 }
0253 
0254 static void bpck_disconnect ( PIA *pi )
0255 
0256 {   w0(0); 
0257     if (pi->mode >= 2) { w2(9); w2(0); } else t2(2);
0258     w2(0x4c); w0(pi->saved_r0);
0259 } 
0260 
0261 static void bpck_force_spp ( PIA *pi )
0262 
0263 /* This fakes the EPP protocol to turn off EPP ... */
0264 
0265 {       pi->saved_r0 = r0();
0266         w0(0xff-pi->unit); w2(4); w0(pi->unit);
0267         t2(8); t2(8); t2(8); 
0268         t2(2); t2(2);
0269 
0270         w2(0); 
0271         w0(4); w2(9); w2(0); 
0272         w0(0); w2(1); w2(3); w2(0);     
0273         w0(0); w2(9); w2(0);
0274         w2(0x4c); w0(pi->saved_r0);
0275 }
0276 
0277 #define TEST_LEN  16
0278 
0279 static int bpck_test_proto( PIA *pi, char * scratch, int verbose )
0280 
0281 {   int i, e, l, h, om;
0282     char buf[TEST_LEN];
0283 
0284     bpck_force_spp(pi);
0285 
0286     switch (pi->mode) {
0287 
0288     case 0: bpck_connect(pi);
0289         WR(0x13,0x7f);
0290         w0(0x13); t2(2);
0291         for(i=0;i<TEST_LEN;i++) {
0292                     t2(4); l = r1();
0293                     t2(4); h = r1();
0294                     buf[i] = j44(l,h);
0295         }
0296         bpck_disconnect(pi);
0297         break;
0298 
0299         case 1: bpck_connect(pi);
0300         WR(0x13,0x7f);
0301                 w0(0x13); t2(2); t2(0x20);
0302                 for(i=0;i<TEST_LEN;i++) { t2(4); buf[i] = r0(); }
0303                 t2(1); t2(0x20);
0304         bpck_disconnect(pi);
0305         break;
0306 
0307     case 2:
0308     case 3:
0309     case 4: om = pi->mode;
0310         pi->mode = 0;
0311         bpck_connect(pi);
0312         WR(7,3);
0313         WR(4,8);
0314         bpck_disconnect(pi);
0315 
0316         pi->mode = om;
0317         bpck_connect(pi);
0318         w0(0x13); w2(9); w2(1); w0(0); w2(3); w2(0); w2(0xe0);
0319 
0320         switch (pi->mode) {
0321           case 2: for (i=0;i<TEST_LEN;i++) buf[i] = r4();
0322               break;
0323           case 3: for (i=0;i<TEST_LEN/2;i++) ((u16 *)buf)[i] = r4w();
0324                           break;
0325           case 4: for (i=0;i<TEST_LEN/4;i++) ((u32 *)buf)[i] = r4l();
0326                           break;
0327         }
0328 
0329         w2(0);
0330         WR(7,0);
0331         bpck_disconnect(pi);
0332 
0333         break;
0334 
0335     }
0336 
0337     if (verbose) {
0338         printk("%s: bpck: 0x%x unit %d mode %d: ",
0339            pi->device,pi->port,pi->unit,pi->mode);
0340         for (i=0;i<TEST_LEN;i++) printk("%3d",buf[i]);
0341         printk("\n");
0342     }
0343 
0344     e = 0;
0345     for (i=0;i<TEST_LEN;i++) if (buf[i] != (i+1)) e++;
0346     return e;
0347 }
0348 
0349 static void bpck_read_eeprom ( PIA *pi, char * buf )
0350 
0351 {       int i, j, k, p, v, f, om, od;
0352 
0353     bpck_force_spp(pi);
0354 
0355     om = pi->mode;  od = pi->delay;
0356     pi->mode = 0; pi->delay = 6;
0357 
0358     bpck_connect(pi);
0359     
0360     WR(4,0);
0361     for (i=0;i<64;i++) {
0362         WR(6,8);  
0363         WR(6,0xc);
0364         p = 0x100;
0365         for (k=0;k<9;k++) {
0366         f = (((i + 0x180) & p) != 0) * 2;
0367         WR(6,f+0xc); 
0368         WR(6,f+0xd); 
0369         WR(6,f+0xc);
0370         p = (p >> 1);
0371         }
0372         for (j=0;j<2;j++) {
0373         v = 0;
0374         for (k=0;k<8;k++) {
0375             WR(6,0xc); 
0376             WR(6,0xd); 
0377             WR(6,0xc); 
0378             f = RR(0);
0379             v = 2*v + (f == 0x84);
0380         }
0381         buf[2*i+1-j] = v;
0382         }
0383     }
0384     WR(6,8);
0385     WR(6,0);
0386     WR(5,8);
0387 
0388     bpck_disconnect(pi);
0389 
0390         if (om >= 2) {
0391                 bpck_connect(pi);
0392                 WR(7,3);
0393                 WR(4,8);
0394                 bpck_disconnect(pi);
0395         }
0396 
0397     pi->mode = om; pi->delay = od;
0398 }
0399 
0400 static int bpck_test_port ( PIA *pi )   /* check for 8-bit port */
0401 
0402 {   int i, r, m;
0403 
0404     w2(0x2c); i = r0(); w0(255-i); r = r0(); w0(i);
0405     m = -1;
0406     if (r == i) m = 2;
0407     if (r == (255-i)) m = 0;
0408 
0409     w2(0xc); i = r0(); w0(255-i); r = r0(); w0(i);
0410     if (r != (255-i)) m = -1;
0411     
0412     if (m == 0) { w2(6); w2(0xc); r = r0(); w0(0xaa); w0(r); w0(0xaa); }
0413     if (m == 2) { w2(0x26); w2(0xc); }
0414 
0415     if (m == -1) return 0;
0416     return 5;
0417 }
0418 
0419 static void bpck_log_adapter( PIA *pi, char * scratch, int verbose )
0420 
0421 {   char    *mode_string[5] = { "4-bit","8-bit","EPP-8",
0422                     "EPP-16","EPP-32" };
0423 
0424 #ifdef DUMP_EEPROM
0425     int i;
0426 #endif
0427 
0428     bpck_read_eeprom(pi,scratch);
0429 
0430 #ifdef DUMP_EEPROM
0431     if (verbose) {
0432        for(i=0;i<128;i++)
0433         if ((scratch[i] < ' ') || (scratch[i] > '~'))
0434             scratch[i] = '.';
0435        printk("%s: bpck EEPROM: %64.64s\n",pi->device,scratch);
0436        printk("%s:              %64.64s\n",pi->device,&scratch[64]);
0437     }
0438 #endif
0439 
0440     printk("%s: bpck %s, backpack %8.8s unit %d",
0441         pi->device,BPCK_VERSION,&scratch[110],pi->unit);
0442     printk(" at 0x%x, mode %d (%s), delay %d\n",pi->port,
0443         pi->mode,mode_string[pi->mode],pi->delay);
0444 }
0445 
0446 static struct pi_protocol bpck = {
0447     .owner      = THIS_MODULE,
0448     .name       = "bpck",
0449     .max_mode   = 5,
0450     .epp_first  = 2,
0451     .default_delay  = 4,
0452     .max_units  = 255,
0453     .write_regr = bpck_write_regr,
0454     .read_regr  = bpck_read_regr,
0455     .write_block    = bpck_write_block,
0456     .read_block = bpck_read_block,
0457     .connect    = bpck_connect,
0458     .disconnect = bpck_disconnect,
0459     .test_port  = bpck_test_port,
0460     .probe_unit = bpck_probe_unit,
0461     .test_proto = bpck_test_proto,
0462     .log_adapter    = bpck_log_adapter,
0463 };
0464 
0465 static int __init bpck_init(void)
0466 {
0467     return paride_register(&bpck);
0468 }
0469 
0470 static void __exit bpck_exit(void)
0471 {
0472     paride_unregister(&bpck);
0473 }
0474 
0475 MODULE_LICENSE("GPL");
0476 module_init(bpck_init)
0477 module_exit(bpck_exit)