1 /* 2 dstr.c (c) 1997-8 Grant R. Guenther <grant@torque.net> 3 Under the terms of the GNU General Public License. 4 5 dstr.c is a low-level protocol driver for the 6 DataStor EP2000 parallel to IDE adapter chip. 7 8 */ 9 10 #include <linux/module.h> 11 #include <linux/init.h> 12 #include <linux/delay.h> 13 #include <linux/kernel.h> 14 #include <linux/types.h> 15 #include <linux/wait.h> 16 #include <asm/io.h> 17 #include "pata_parport.h" 18 19 /* mode codes: 0 nybble reads, 8-bit writes 20 1 8-bit reads and writes 21 2 8-bit EPP mode 22 3 EPP-16 23 4 EPP-32 24 */ 25 26 #define j44(a,b) (((a>>3)&0x07)|((~a>>4)&0x08)|((b<<1)&0x70)|((~b)&0x80)) 27 28 #define P1 w2(5);w2(0xd);w2(5);w2(4); 29 #define P2 w2(5);w2(7);w2(5);w2(4); 30 #define P3 w2(6);w2(4);w2(6);w2(4); 31 32 /* cont = 0 - access the IDE register file 33 cont = 1 - access the IDE command set 34 */ 35 36 static int cont_map[2] = { 0x20, 0x40 }; 37 38 static int dstr_read_regr(struct pi_adapter *pi, int cont, int regr) 39 40 { int a, b, r; 41 42 r = regr + cont_map[cont]; 43 44 w0(0x81); P1; 45 if (pi->mode) { w0(0x11); } else { w0(1); } 46 P2; w0(r); P1; 47 48 switch (pi->mode) { 49 50 case 0: w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4); 51 return j44(a,b); 52 53 case 1: w0(0); w2(0x26); a = r0(); w2(4); 54 return a; 55 56 case 2: 57 case 3: 58 case 4: w2(0x24); a = r4(); w2(4); 59 return a; 60 61 } 62 return -1; 63 } 64 65 static void dstr_write_regr(struct pi_adapter *pi, int cont, int regr, int val) 66 67 { int r; 68 69 r = regr + cont_map[cont]; 70 71 w0(0x81); P1; 72 if (pi->mode >= 2) { w0(0x11); } else { w0(1); } 73 P2; w0(r); P1; 74 75 switch (pi->mode) { 76 77 case 0: 78 case 1: w0(val); w2(5); w2(7); w2(5); w2(4); 79 break; 80 81 case 2: 82 case 3: 83 case 4: w4(val); 84 break; 85 } 86 } 87 88 #define CCP(x) w0(0xff);w2(0xc);w2(4);\ 89 w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);w0(0x78);\ 90 w0(x);w2(5);w2(4); 91 92 static void dstr_connect(struct pi_adapter *pi) 93 94 { pi->saved_r0 = r0(); 95 pi->saved_r2 = r2(); 96 w2(4); CCP(0xe0); w0(0xff); 97 } 98 99 static void dstr_disconnect(struct pi_adapter *pi) 100 101 { CCP(0x30); 102 w0(pi->saved_r0); 103 w2(pi->saved_r2); 104 } 105 106 static void dstr_read_block(struct pi_adapter *pi, char *buf, int count) 107 108 { int k, a, b; 109 110 w0(0x81); P1; 111 if (pi->mode) { w0(0x19); } else { w0(9); } 112 P2; w0(0x82); P1; P3; w0(0x20); P1; 113 114 switch (pi->mode) { 115 116 case 0: for (k=0;k<count;k++) { 117 w2(6); a = r1(); w2(4); 118 w2(6); b = r1(); w2(4); 119 buf[k] = j44(a,b); 120 } 121 break; 122 123 case 1: w0(0); 124 for (k=0;k<count;k++) { 125 w2(0x26); buf[k] = r0(); w2(0x24); 126 } 127 w2(4); 128 break; 129 130 case 2: w2(0x24); 131 for (k=0;k<count;k++) buf[k] = r4(); 132 w2(4); 133 break; 134 135 case 3: w2(0x24); 136 for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w(); 137 w2(4); 138 break; 139 140 case 4: w2(0x24); 141 for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l(); 142 w2(4); 143 break; 144 145 } 146 } 147 148 static void dstr_write_block(struct pi_adapter *pi, char *buf, int count) 149 150 { int k; 151 152 w0(0x81); P1; 153 if (pi->mode) { w0(0x19); } else { w0(9); } 154 P2; w0(0x82); P1; P3; w0(0x20); P1; 155 156 switch (pi->mode) { 157 158 case 0: 159 case 1: for (k=0;k<count;k++) { 160 w2(5); w0(buf[k]); w2(7); 161 } 162 w2(5); w2(4); 163 break; 164 165 case 2: w2(0xc5); 166 for (k=0;k<count;k++) w4(buf[k]); 167 w2(0xc4); 168 break; 169 170 case 3: w2(0xc5); 171 for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]); 172 w2(0xc4); 173 break; 174 175 case 4: w2(0xc5); 176 for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]); 177 w2(0xc4); 178 break; 179 180 } 181 } 182 183 184 static void dstr_log_adapter(struct pi_adapter *pi) 185 186 { char *mode_string[5] = {"4-bit","8-bit","EPP-8", 187 "EPP-16","EPP-32"}; 188 189 dev_info(&pi->dev, "DataStor EP2000 at 0x%x, mode %d (%s), delay %d\n", 190 pi->port, pi->mode, mode_string[pi->mode], pi->delay); 191 } 192 193 static struct pi_protocol dstr = { 194 .owner = THIS_MODULE, 195 .name = "dstr", 196 .max_mode = 5, 197 .epp_first = 2, 198 .default_delay = 1, 199 .max_units = 1, 200 .write_regr = dstr_write_regr, 201 .read_regr = dstr_read_regr, 202 .write_block = dstr_write_block, 203 .read_block = dstr_read_block, 204 .connect = dstr_connect, 205 .disconnect = dstr_disconnect, 206 .log_adapter = dstr_log_adapter, 207 }; 208 209 MODULE_LICENSE("GPL"); 210 module_pata_parport_driver(dstr); 211