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