Back to home page

OSCL-LXR

 
 

    


0001 /* 
0002         epat.c  (c) 1997-8  Grant R. Guenther <grant@torque.net>
0003                             Under the terms of the GNU General Public License.
0004 
0005     This is the low level protocol driver for the EPAT parallel
0006         to IDE adapter from Shuttle Technologies.  This adapter is
0007         used in many popular parallel port disk products such as the
0008         SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk.
0009     
0010 */
0011 
0012 /* Changes:
0013 
0014         1.01    GRG 1998.05.06 init_proto, release_proto
0015         1.02    Joshua b. Jore CPP(renamed), epat_connect, epat_disconnect
0016 
0017 */
0018 
0019 #define EPAT_VERSION      "1.02"
0020 
0021 #include <linux/module.h>
0022 #include <linux/init.h>
0023 #include <linux/delay.h>
0024 #include <linux/kernel.h>
0025 #include <linux/types.h>
0026 #include <linux/wait.h>
0027 #include <asm/io.h>
0028 
0029 #include "paride.h"
0030 
0031 #define j44(a,b)        (((a>>4)&0x0f)+(b&0xf0))
0032 #define j53(a,b)        (((a>>3)&0x1f)+((b<<4)&0xe0))
0033 
0034 static int epatc8;
0035 
0036 module_param(epatc8, int, 0);
0037 MODULE_PARM_DESC(epatc8, "support for the Shuttle EP1284 chip, "
0038     "used in any recent Imation SuperDisk (LS-120) drive.");
0039 
0040 /* cont =  0   IDE register file
0041    cont =  1   IDE control registers
0042    cont =  2   internal EPAT registers
0043 */
0044 
0045 static int cont_map[3] = { 0x18, 0x10, 0 };
0046 
0047 static void epat_write_regr( PIA *pi, int cont, int regr, int val)
0048 
0049 {   int r;
0050 
0051     r = regr + cont_map[cont];
0052 
0053     switch (pi->mode) {
0054 
0055     case 0:
0056     case 1:
0057     case 2: w0(0x60+r); w2(1); w0(val); w2(4);
0058         break;
0059 
0060     case 3:
0061     case 4:
0062     case 5: w3(0x40+r); w4(val);
0063         break;
0064 
0065     }
0066 }
0067 
0068 static int epat_read_regr( PIA *pi, int cont, int regr )
0069 
0070 {   int  a, b, r;
0071 
0072     r = regr + cont_map[cont];
0073 
0074     switch (pi->mode) {
0075 
0076     case 0: w0(r); w2(1); w2(3); 
0077         a = r1(); w2(4); b = r1();
0078         return j44(a,b);
0079 
0080     case 1: w0(0x40+r); w2(1); w2(4);
0081         a = r1(); b = r2(); w0(0xff);
0082         return j53(a,b);
0083 
0084     case 2: w0(0x20+r); w2(1); w2(0x25);
0085         a = r0(); w2(4);
0086         return a;
0087 
0088     case 3:
0089     case 4:
0090     case 5: w3(r); w2(0x24); a = r4(); w2(4);
0091         return a;
0092 
0093     }
0094     return -1;  /* never gets here */
0095 }
0096 
0097 static void epat_read_block( PIA *pi, char * buf, int count )
0098 
0099 {   int  k, ph, a, b;
0100 
0101     switch (pi->mode) {
0102 
0103     case 0: w0(7); w2(1); w2(3); w0(0xff);
0104         ph = 0;
0105         for(k=0;k<count;k++) {
0106             if (k == count-1) w0(0xfd);
0107             w2(6+ph); a = r1();
0108             if (a & 8) b = a; 
0109               else { w2(4+ph); b = r1(); }
0110             buf[k] = j44(a,b);
0111             ph =  1 - ph;
0112         }
0113         w0(0); w2(4);
0114         break;
0115 
0116     case 1: w0(0x47); w2(1); w2(5); w0(0xff);
0117         ph = 0;
0118         for(k=0;k<count;k++) {
0119             if (k == count-1) w0(0xfd); 
0120             w2(4+ph);
0121             a = r1(); b = r2();
0122             buf[k] = j53(a,b);
0123             ph = 1 - ph;
0124         }
0125         w0(0); w2(4);
0126         break;
0127 
0128     case 2: w0(0x27); w2(1); w2(0x25); w0(0);
0129         ph = 0;
0130         for(k=0;k<count-1;k++) {
0131             w2(0x24+ph);
0132             buf[k] = r0();
0133             ph = 1 - ph;
0134         }
0135         w2(0x26); w2(0x27); buf[count-1] = r0(); 
0136         w2(0x25); w2(4);
0137         break;
0138 
0139     case 3: w3(0x80); w2(0x24);
0140         for(k=0;k<count-1;k++) buf[k] = r4();
0141         w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
0142         w2(4);
0143         break;
0144 
0145     case 4: w3(0x80); w2(0x24);
0146         for(k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
0147         buf[count-2] = r4();
0148         w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
0149         w2(4);
0150         break;
0151 
0152     case 5: w3(0x80); w2(0x24);
0153         for(k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
0154         for(k=count-4;k<count-1;k++) buf[k] = r4();
0155         w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
0156         w2(4);
0157         break;
0158 
0159     }
0160 }
0161 
0162 static void epat_write_block( PIA *pi, char * buf, int count )   
0163 
0164 {   int ph, k;
0165 
0166     switch (pi->mode) {
0167 
0168     case 0:
0169     case 1:
0170     case 2: w0(0x67); w2(1); w2(5);
0171         ph = 0;
0172         for(k=0;k<count;k++) {
0173             w0(buf[k]);
0174             w2(4+ph);
0175             ph = 1 - ph;
0176         }
0177         w2(7); w2(4);
0178         break;
0179 
0180     case 3: w3(0xc0); 
0181         for(k=0;k<count;k++) w4(buf[k]);
0182         w2(4);
0183         break;
0184 
0185     case 4: w3(0xc0); 
0186         for(k=0;k<(count/2);k++) w4w(((u16 *)buf)[k]);
0187         w2(4);
0188         break;
0189 
0190     case 5: w3(0xc0); 
0191         for(k=0;k<(count/4);k++) w4l(((u32 *)buf)[k]);
0192         w2(4);
0193         break;
0194 
0195     }
0196 }
0197 
0198 /* these macros access the EPAT registers in native addressing */
0199 
0200 #define WR(r,v)     epat_write_regr(pi,2,r,v)
0201 #define RR(r)       (epat_read_regr(pi,2,r))
0202 
0203 /* and these access the IDE task file */
0204 
0205 #define WRi(r,v)         epat_write_regr(pi,0,r,v)
0206 #define RRi(r)           (epat_read_regr(pi,0,r))
0207 
0208 /* FIXME:  the CPP stuff should be fixed to handle multiple EPATs on a chain */
0209 
0210 #define CPP(x)  w2(4);w0(0x22);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
0211                 w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
0212 
0213 static void epat_connect ( PIA *pi )
0214 
0215 {       pi->saved_r0 = r0();
0216         pi->saved_r2 = r2();
0217 
0218     /* Initialize the chip */
0219     CPP(0);
0220 
0221     if (epatc8) {
0222         CPP(0x40);CPP(0xe0);
0223         w0(0);w2(1);w2(4);
0224         WR(0x8,0x12);WR(0xc,0x14);WR(0x12,0x10);
0225         WR(0xe,0xf);WR(0xf,4);
0226         /* WR(0xe,0xa);WR(0xf,4); */
0227         WR(0xe,0xd);WR(0xf,0);
0228         /* CPP(0x30); */
0229     }
0230 
0231         /* Connect to the chip */
0232     CPP(0xe0);
0233         w0(0);w2(1);w2(4); /* Idle into SPP */
0234         if (pi->mode >= 3) {
0235           w0(0);w2(1);w2(4);w2(0xc);
0236           /* Request EPP */
0237           w0(0x40);w2(6);w2(7);w2(4);w2(0xc);w2(4);
0238         }
0239 
0240     if (!epatc8) {
0241         WR(8,0x10); WR(0xc,0x14); WR(0xa,0x38); WR(0x12,0x10);
0242     }
0243 }
0244 
0245 static void epat_disconnect (PIA *pi)
0246 {   CPP(0x30);
0247     w0(pi->saved_r0);
0248     w2(pi->saved_r2);
0249 }
0250 
0251 static int epat_test_proto( PIA *pi, char * scratch, int verbose )
0252 
0253 {       int     k, j, f, cc;
0254     int e[2] = {0,0};
0255 
0256         epat_connect(pi);
0257     cc = RR(0xd);
0258     epat_disconnect(pi);
0259 
0260     epat_connect(pi);
0261     for (j=0;j<2;j++) {
0262         WRi(6,0xa0+j*0x10);
0263             for (k=0;k<256;k++) {
0264                 WRi(2,k^0xaa);
0265                 WRi(3,k^0x55);
0266                 if (RRi(2) != (k^0xaa)) e[j]++;
0267                 }
0268         }
0269         epat_disconnect(pi);
0270 
0271         f = 0;
0272         epat_connect(pi);
0273         WR(0x13,1); WR(0x13,0); WR(0xa,0x11);
0274         epat_read_block(pi,scratch,512);
0275     
0276         for (k=0;k<256;k++) {
0277             if ((scratch[2*k] & 0xff) != k) f++;
0278             if ((scratch[2*k+1] & 0xff) != (0xff-k)) f++;
0279         }
0280         epat_disconnect(pi);
0281 
0282         if (verbose)  {
0283             printk("%s: epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n",
0284            pi->device,pi->port,pi->mode,cc,e[0],e[1],f);
0285     }
0286     
0287         return (e[0] && e[1]) || f;
0288 }
0289 
0290 static void epat_log_adapter( PIA *pi, char * scratch, int verbose )
0291 
0292 {   int ver;
0293         char    *mode_string[6] = 
0294            {"4-bit","5/3","8-bit","EPP-8","EPP-16","EPP-32"};
0295 
0296     epat_connect(pi);
0297     WR(0xa,0x38);       /* read the version code */
0298         ver = RR(0xb);
0299         epat_disconnect(pi);
0300 
0301     printk("%s: epat %s, Shuttle EPAT chip %x at 0x%x, ",
0302         pi->device,EPAT_VERSION,ver,pi->port);
0303     printk("mode %d (%s), delay %d\n",pi->mode,
0304         mode_string[pi->mode],pi->delay);
0305 
0306 }
0307 
0308 static struct pi_protocol epat = {
0309     .owner      = THIS_MODULE,
0310     .name       = "epat",
0311     .max_mode   = 6,
0312     .epp_first  = 3,
0313     .default_delay  = 1,
0314     .max_units  = 1,
0315     .write_regr = epat_write_regr,
0316     .read_regr  = epat_read_regr,
0317     .write_block    = epat_write_block,
0318     .read_block = epat_read_block,
0319     .connect    = epat_connect,
0320     .disconnect = epat_disconnect,
0321     .test_proto = epat_test_proto,
0322     .log_adapter    = epat_log_adapter,
0323 };
0324 
0325 static int __init epat_init(void)
0326 {
0327 #ifdef CONFIG_PARIDE_EPATC8
0328     epatc8 = 1;
0329 #endif
0330     return paride_register(&epat);
0331 }
0332 
0333 static void __exit epat_exit(void)
0334 {
0335     paride_unregister(&epat);
0336 }
0337 
0338 MODULE_LICENSE("GPL");
0339 module_init(epat_init)
0340 module_exit(epat_exit)