172f2b0b2SOndrej Zary /* 272f2b0b2SOndrej Zary dstr.c (c) 1997-8 Grant R. Guenther <grant@torque.net> 372f2b0b2SOndrej Zary Under the terms of the GNU General Public License. 472f2b0b2SOndrej Zary 572f2b0b2SOndrej Zary dstr.c is a low-level protocol driver for the 672f2b0b2SOndrej Zary DataStor EP2000 parallel to IDE adapter chip. 772f2b0b2SOndrej Zary 872f2b0b2SOndrej Zary */ 972f2b0b2SOndrej Zary 1072f2b0b2SOndrej Zary /* Changes: 1172f2b0b2SOndrej Zary 1272f2b0b2SOndrej Zary 1.01 GRG 1998.05.06 init_proto, release_proto 1372f2b0b2SOndrej Zary 1472f2b0b2SOndrej Zary */ 1572f2b0b2SOndrej Zary 1672f2b0b2SOndrej Zary #define DSTR_VERSION "1.01" 1772f2b0b2SOndrej Zary 1872f2b0b2SOndrej Zary #include <linux/module.h> 1972f2b0b2SOndrej Zary #include <linux/init.h> 2072f2b0b2SOndrej Zary #include <linux/delay.h> 2172f2b0b2SOndrej Zary #include <linux/kernel.h> 2272f2b0b2SOndrej Zary #include <linux/types.h> 2372f2b0b2SOndrej Zary #include <linux/wait.h> 2472f2b0b2SOndrej Zary #include <asm/io.h> 2572f2b0b2SOndrej Zary 2672f2b0b2SOndrej Zary #include <linux/pata_parport.h> 2772f2b0b2SOndrej Zary 2872f2b0b2SOndrej Zary /* mode codes: 0 nybble reads, 8-bit writes 2972f2b0b2SOndrej Zary 1 8-bit reads and writes 3072f2b0b2SOndrej Zary 2 8-bit EPP mode 3172f2b0b2SOndrej Zary 3 EPP-16 3272f2b0b2SOndrej Zary 4 EPP-32 3372f2b0b2SOndrej Zary */ 3472f2b0b2SOndrej Zary 3572f2b0b2SOndrej Zary #define j44(a,b) (((a>>3)&0x07)|((~a>>4)&0x08)|((b<<1)&0x70)|((~b)&0x80)) 3672f2b0b2SOndrej Zary 3772f2b0b2SOndrej Zary #define P1 w2(5);w2(0xd);w2(5);w2(4); 3872f2b0b2SOndrej Zary #define P2 w2(5);w2(7);w2(5);w2(4); 3972f2b0b2SOndrej Zary #define P3 w2(6);w2(4);w2(6);w2(4); 4072f2b0b2SOndrej Zary 4172f2b0b2SOndrej Zary /* cont = 0 - access the IDE register file 4272f2b0b2SOndrej Zary cont = 1 - access the IDE command set 4372f2b0b2SOndrej Zary */ 4472f2b0b2SOndrej Zary 4572f2b0b2SOndrej Zary static int cont_map[2] = { 0x20, 0x40 }; 4672f2b0b2SOndrej Zary 47882ff0caSOndrej Zary static int dstr_read_regr(struct pi_adapter *pi, int cont, int regr) 4872f2b0b2SOndrej Zary 4972f2b0b2SOndrej Zary { int a, b, r; 5072f2b0b2SOndrej Zary 5172f2b0b2SOndrej Zary r = regr + cont_map[cont]; 5272f2b0b2SOndrej Zary 5372f2b0b2SOndrej Zary w0(0x81); P1; 5472f2b0b2SOndrej Zary if (pi->mode) { w0(0x11); } else { w0(1); } 5572f2b0b2SOndrej Zary P2; w0(r); P1; 5672f2b0b2SOndrej Zary 5772f2b0b2SOndrej Zary switch (pi->mode) { 5872f2b0b2SOndrej Zary 5972f2b0b2SOndrej Zary case 0: w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4); 6072f2b0b2SOndrej Zary return j44(a,b); 6172f2b0b2SOndrej Zary 6272f2b0b2SOndrej Zary case 1: w0(0); w2(0x26); a = r0(); w2(4); 6372f2b0b2SOndrej Zary return a; 6472f2b0b2SOndrej Zary 6572f2b0b2SOndrej Zary case 2: 6672f2b0b2SOndrej Zary case 3: 6772f2b0b2SOndrej Zary case 4: w2(0x24); a = r4(); w2(4); 6872f2b0b2SOndrej Zary return a; 6972f2b0b2SOndrej Zary 7072f2b0b2SOndrej Zary } 7172f2b0b2SOndrej Zary return -1; 7272f2b0b2SOndrej Zary } 7372f2b0b2SOndrej Zary 74882ff0caSOndrej Zary static void dstr_write_regr(struct pi_adapter *pi, int cont, int regr, int val) 7572f2b0b2SOndrej Zary 7672f2b0b2SOndrej Zary { int r; 7772f2b0b2SOndrej Zary 7872f2b0b2SOndrej Zary r = regr + cont_map[cont]; 7972f2b0b2SOndrej Zary 8072f2b0b2SOndrej Zary w0(0x81); P1; 8172f2b0b2SOndrej Zary if (pi->mode >= 2) { w0(0x11); } else { w0(1); } 8272f2b0b2SOndrej Zary P2; w0(r); P1; 8372f2b0b2SOndrej Zary 8472f2b0b2SOndrej Zary switch (pi->mode) { 8572f2b0b2SOndrej Zary 8672f2b0b2SOndrej Zary case 0: 8772f2b0b2SOndrej Zary case 1: w0(val); w2(5); w2(7); w2(5); w2(4); 8872f2b0b2SOndrej Zary break; 8972f2b0b2SOndrej Zary 9072f2b0b2SOndrej Zary case 2: 9172f2b0b2SOndrej Zary case 3: 9272f2b0b2SOndrej Zary case 4: w4(val); 9372f2b0b2SOndrej Zary break; 9472f2b0b2SOndrej Zary } 9572f2b0b2SOndrej Zary } 9672f2b0b2SOndrej Zary 9772f2b0b2SOndrej Zary #define CCP(x) w0(0xff);w2(0xc);w2(4);\ 9872f2b0b2SOndrej Zary w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);w0(0x78);\ 9972f2b0b2SOndrej Zary w0(x);w2(5);w2(4); 10072f2b0b2SOndrej Zary 101882ff0caSOndrej Zary static void dstr_connect(struct pi_adapter *pi) 10272f2b0b2SOndrej Zary 10372f2b0b2SOndrej Zary { pi->saved_r0 = r0(); 10472f2b0b2SOndrej Zary pi->saved_r2 = r2(); 10572f2b0b2SOndrej Zary w2(4); CCP(0xe0); w0(0xff); 10672f2b0b2SOndrej Zary } 10772f2b0b2SOndrej Zary 108882ff0caSOndrej Zary static void dstr_disconnect(struct pi_adapter *pi) 10972f2b0b2SOndrej Zary 11072f2b0b2SOndrej Zary { CCP(0x30); 11172f2b0b2SOndrej Zary w0(pi->saved_r0); 11272f2b0b2SOndrej Zary w2(pi->saved_r2); 11372f2b0b2SOndrej Zary } 11472f2b0b2SOndrej Zary 115882ff0caSOndrej Zary static void dstr_read_block(struct pi_adapter *pi, char *buf, int count) 11672f2b0b2SOndrej Zary 11772f2b0b2SOndrej Zary { int k, a, b; 11872f2b0b2SOndrej Zary 11972f2b0b2SOndrej Zary w0(0x81); P1; 12072f2b0b2SOndrej Zary if (pi->mode) { w0(0x19); } else { w0(9); } 12172f2b0b2SOndrej Zary P2; w0(0x82); P1; P3; w0(0x20); P1; 12272f2b0b2SOndrej Zary 12372f2b0b2SOndrej Zary switch (pi->mode) { 12472f2b0b2SOndrej Zary 12572f2b0b2SOndrej Zary case 0: for (k=0;k<count;k++) { 12672f2b0b2SOndrej Zary w2(6); a = r1(); w2(4); 12772f2b0b2SOndrej Zary w2(6); b = r1(); w2(4); 12872f2b0b2SOndrej Zary buf[k] = j44(a,b); 12972f2b0b2SOndrej Zary } 13072f2b0b2SOndrej Zary break; 13172f2b0b2SOndrej Zary 13272f2b0b2SOndrej Zary case 1: w0(0); 13372f2b0b2SOndrej Zary for (k=0;k<count;k++) { 13472f2b0b2SOndrej Zary w2(0x26); buf[k] = r0(); w2(0x24); 13572f2b0b2SOndrej Zary } 13672f2b0b2SOndrej Zary w2(4); 13772f2b0b2SOndrej Zary break; 13872f2b0b2SOndrej Zary 13972f2b0b2SOndrej Zary case 2: w2(0x24); 14072f2b0b2SOndrej Zary for (k=0;k<count;k++) buf[k] = r4(); 14172f2b0b2SOndrej Zary w2(4); 14272f2b0b2SOndrej Zary break; 14372f2b0b2SOndrej Zary 14472f2b0b2SOndrej Zary case 3: w2(0x24); 14572f2b0b2SOndrej Zary for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w(); 14672f2b0b2SOndrej Zary w2(4); 14772f2b0b2SOndrej Zary break; 14872f2b0b2SOndrej Zary 14972f2b0b2SOndrej Zary case 4: w2(0x24); 15072f2b0b2SOndrej Zary for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l(); 15172f2b0b2SOndrej Zary w2(4); 15272f2b0b2SOndrej Zary break; 15372f2b0b2SOndrej Zary 15472f2b0b2SOndrej Zary } 15572f2b0b2SOndrej Zary } 15672f2b0b2SOndrej Zary 157882ff0caSOndrej Zary static void dstr_write_block(struct pi_adapter *pi, char *buf, int count) 15872f2b0b2SOndrej Zary 15972f2b0b2SOndrej Zary { int k; 16072f2b0b2SOndrej Zary 16172f2b0b2SOndrej Zary w0(0x81); P1; 16272f2b0b2SOndrej Zary if (pi->mode) { w0(0x19); } else { w0(9); } 16372f2b0b2SOndrej Zary P2; w0(0x82); P1; P3; w0(0x20); P1; 16472f2b0b2SOndrej Zary 16572f2b0b2SOndrej Zary switch (pi->mode) { 16672f2b0b2SOndrej Zary 16772f2b0b2SOndrej Zary case 0: 16872f2b0b2SOndrej Zary case 1: for (k=0;k<count;k++) { 16972f2b0b2SOndrej Zary w2(5); w0(buf[k]); w2(7); 17072f2b0b2SOndrej Zary } 17172f2b0b2SOndrej Zary w2(5); w2(4); 17272f2b0b2SOndrej Zary break; 17372f2b0b2SOndrej Zary 17472f2b0b2SOndrej Zary case 2: w2(0xc5); 17572f2b0b2SOndrej Zary for (k=0;k<count;k++) w4(buf[k]); 17672f2b0b2SOndrej Zary w2(0xc4); 17772f2b0b2SOndrej Zary break; 17872f2b0b2SOndrej Zary 17972f2b0b2SOndrej Zary case 3: w2(0xc5); 18072f2b0b2SOndrej Zary for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]); 18172f2b0b2SOndrej Zary w2(0xc4); 18272f2b0b2SOndrej Zary break; 18372f2b0b2SOndrej Zary 18472f2b0b2SOndrej Zary case 4: w2(0xc5); 18572f2b0b2SOndrej Zary for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]); 18672f2b0b2SOndrej Zary w2(0xc4); 18772f2b0b2SOndrej Zary break; 18872f2b0b2SOndrej Zary 18972f2b0b2SOndrej Zary } 19072f2b0b2SOndrej Zary } 19172f2b0b2SOndrej Zary 19272f2b0b2SOndrej Zary 193*5b77db9cSOndrej Zary static void dstr_log_adapter(struct pi_adapter *pi) 19472f2b0b2SOndrej Zary 19572f2b0b2SOndrej Zary { char *mode_string[5] = {"4-bit","8-bit","EPP-8", 19672f2b0b2SOndrej Zary "EPP-16","EPP-32"}; 19772f2b0b2SOndrej Zary 198a4f2ff92SOndrej Zary printk("dstr %s, DataStor EP2000 at 0x%x, ", DSTR_VERSION, pi->port); 19972f2b0b2SOndrej Zary printk("mode %d (%s), delay %d\n",pi->mode, 20072f2b0b2SOndrej Zary mode_string[pi->mode],pi->delay); 20172f2b0b2SOndrej Zary 20272f2b0b2SOndrej Zary } 20372f2b0b2SOndrej Zary 20472f2b0b2SOndrej Zary static struct pi_protocol dstr = { 20572f2b0b2SOndrej Zary .owner = THIS_MODULE, 20672f2b0b2SOndrej Zary .name = "dstr", 20772f2b0b2SOndrej Zary .max_mode = 5, 20872f2b0b2SOndrej Zary .epp_first = 2, 20972f2b0b2SOndrej Zary .default_delay = 1, 21072f2b0b2SOndrej Zary .max_units = 1, 21172f2b0b2SOndrej Zary .write_regr = dstr_write_regr, 21272f2b0b2SOndrej Zary .read_regr = dstr_read_regr, 21372f2b0b2SOndrej Zary .write_block = dstr_write_block, 21472f2b0b2SOndrej Zary .read_block = dstr_read_block, 21572f2b0b2SOndrej Zary .connect = dstr_connect, 21672f2b0b2SOndrej Zary .disconnect = dstr_disconnect, 21772f2b0b2SOndrej Zary .log_adapter = dstr_log_adapter, 21872f2b0b2SOndrej Zary }; 21972f2b0b2SOndrej Zary 22072f2b0b2SOndrej Zary MODULE_LICENSE("GPL"); 2212c08ec0fSOndrej Zary module_pata_parport_driver(dstr); 222