1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * (c) 1997-1998 Grant R. Guenther <grant@torque.net> 4 * 5 * This is the low level protocol driver for the EPAT parallel 6 * to IDE adapter from Shuttle Technologies. This adapter is 7 * used in many popular parallel port disk products such as the 8 * SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk. 9 */ 10 11 #include <linux/module.h> 12 #include <linux/init.h> 13 #include <linux/delay.h> 14 #include <linux/kernel.h> 15 #include <linux/types.h> 16 #include <linux/wait.h> 17 #include <asm/io.h> 18 #include "pata_parport.h" 19 20 #define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0)) 21 #define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0)) 22 23 static int epatc8; 24 25 module_param(epatc8, int, 0); 26 MODULE_PARM_DESC(epatc8, 27 "support for the Shuttle EP1284 chip, " 28 "used in any recent Imation SuperDisk (LS-120) drive."); 29 30 /* 31 * cont = 0 IDE register file 32 * cont = 1 IDE control registers 33 * cont = 2 internal EPAT registers 34 */ 35 static int cont_map[3] = { 0x18, 0x10, 0 }; 36 37 static void epat_write_regr(struct pi_adapter *pi, int cont, int regr, int val) 38 { 39 int r = regr + cont_map[cont]; 40 41 switch (pi->mode) { 42 case 0: 43 case 1: 44 case 2: 45 w0(0x60+r); w2(1); w0(val); w2(4); 46 break; 47 case 3: 48 case 4: 49 case 5: 50 w3(0x40+r); w4(val); 51 break; 52 } 53 } 54 55 static int epat_read_regr(struct pi_adapter *pi, int cont, int regr) 56 { 57 int a, b, r; 58 59 r = regr + cont_map[cont]; 60 61 switch (pi->mode) { 62 63 case 0: 64 w0(r); w2(1); w2(3); 65 a = r1(); w2(4); b = r1(); 66 return j44(a, b); 67 case 1: 68 w0(0x40+r); w2(1); w2(4); 69 a = r1(); b = r2(); w0(0xff); 70 return j53(a, b); 71 case 2: 72 w0(0x20+r); w2(1); w2(0x25); 73 a = r0(); w2(4); 74 return a; 75 case 3: 76 case 4: 77 case 5: 78 w3(r); w2(0x24); a = r4(); w2(4); 79 return a; 80 } 81 82 return -1; /* never gets here */ 83 } 84 85 static void epat_read_block(struct pi_adapter *pi, char *buf, int count) 86 { 87 int k, ph, a, b; 88 89 switch (pi->mode) { 90 91 case 0: 92 w0(7); w2(1); w2(3); w0(0xff); 93 ph = 0; 94 for (k = 0; k < count; k++) { 95 if (k == count-1) 96 w0(0xfd); 97 w2(6 + ph); a = r1(); 98 if (a & 8) { 99 b = a; 100 } else { 101 w2(4+ph); b = r1(); 102 } 103 buf[k] = j44(a, b); 104 ph = 1 - ph; 105 } 106 w0(0); w2(4); 107 break; 108 109 case 1: 110 w0(0x47); w2(1); w2(5); w0(0xff); 111 ph = 0; 112 for (k = 0; k < count; k++) { 113 if (k == count - 1) 114 w0(0xfd); 115 w2(4 + ph); 116 a = r1(); b = r2(); 117 buf[k] = j53(a, b); 118 ph = 1 - ph; 119 } 120 w0(0); w2(4); 121 break; 122 123 case 2: 124 w0(0x27); w2(1); w2(0x25); w0(0); 125 ph = 0; 126 for (k = 0; k < count - 1; k++) { 127 w2(0x24 + ph); 128 buf[k] = r0(); 129 ph = 1 - ph; 130 } 131 w2(0x26); w2(0x27); 132 buf[count - 1] = r0(); 133 w2(0x25); w2(4); 134 break; 135 136 case 3: 137 w3(0x80); w2(0x24); 138 for (k = 0; k < count - 1; k++) 139 buf[k] = r4(); 140 w2(4); w3(0xa0); w2(0x24); 141 buf[count - 1] = r4(); 142 w2(4); 143 break; 144 145 case 4: 146 w3(0x80); w2(0x24); 147 for (k = 0; k < count / 2 - 1; k++) 148 ((u16 *)buf)[k] = r4w(); 149 buf[count - 2] = r4(); 150 w2(4); w3(0xa0); w2(0x24); 151 buf[count - 1] = r4(); 152 w2(4); 153 break; 154 155 case 5: 156 w3(0x80); w2(0x24); 157 for (k = 0; k < count / 4 - 1; k++) 158 ((u32 *)buf)[k] = r4l(); 159 for (k = count - 4; k < count - 1; k++) 160 buf[k] = r4(); 161 w2(4); w3(0xa0); w2(0x24); 162 buf[count - 1] = r4(); 163 w2(4); 164 break; 165 } 166 } 167 168 static void epat_write_block(struct pi_adapter *pi, char *buf, int count) 169 { 170 int ph, k; 171 172 switch (pi->mode) { 173 case 0: 174 case 1: 175 case 2: 176 w0(0x67); w2(1); w2(5); 177 ph = 0; 178 for (k = 0; k < count; k++) { 179 w0(buf[k]); 180 w2(4 + ph); 181 ph = 1 - ph; 182 } 183 w2(7); w2(4); 184 break; 185 case 3: 186 w3(0xc0); 187 for (k = 0; k < count; k++) 188 w4(buf[k]); 189 w2(4); 190 break; 191 case 4: 192 w3(0xc0); 193 for (k = 0; k < count / 2; k++) 194 w4w(((u16 *)buf)[k]); 195 w2(4); 196 break; 197 case 5: 198 w3(0xc0); 199 for (k = 0; k < count / 4; k++) 200 w4l(((u32 *)buf)[k]); 201 w2(4); 202 break; 203 } 204 } 205 206 /* these macros access the EPAT registers in native addressing */ 207 208 #define WR(r, v) epat_write_regr(pi, 2, r, v) 209 #define RR(r) epat_read_regr(pi, 2, r) 210 211 /* and these access the IDE task file */ 212 213 #define WRi(r, v) epat_write_regr(pi, 0, r, v) 214 #define RRi(r) epat_read_regr(pi, 0, r) 215 216 /* FIXME: the CPP stuff should be fixed to handle multiple EPATs on a chain */ 217 218 #define CPP(x) \ 219 do { \ 220 w2(4); w0(0x22); w0(0xaa); \ 221 w0(0x55); w0(0); w0(0xff); \ 222 w0(0x87); w0(0x78); w0(x); \ 223 w2(4); w2(5); w2(4); w0(0xff); \ 224 } while (0) 225 226 static void epat_connect(struct pi_adapter *pi) 227 { 228 pi->saved_r0 = r0(); 229 pi->saved_r2 = r2(); 230 231 /* Initialize the chip */ 232 CPP(0); 233 234 if (epatc8) { 235 CPP(0x40); CPP(0xe0); 236 w0(0); w2(1); w2(4); 237 WR(0x8, 0x12); 238 WR(0xc, 0x14); 239 WR(0x12, 0x10); 240 WR(0xe, 0xf); 241 WR(0xf, 4); 242 /* WR(0xe,0xa);WR(0xf,4); */ 243 WR(0xe, 0xd); 244 WR(0xf, 0); 245 /* CPP(0x30); */ 246 } 247 248 /* Connect to the chip */ 249 CPP(0xe0); 250 w0(0); w2(1); w2(4); /* Idle into SPP */ 251 if (pi->mode >= 3) { 252 w0(0); w2(1); w2(4); w2(0xc); 253 /* Request EPP */ 254 w0(0x40); w2(6); w2(7); w2(4); w2(0xc); w2(4); 255 } 256 257 if (!epatc8) { 258 WR(8, 0x10); 259 WR(0xc, 0x14); 260 WR(0xa, 0x38); 261 WR(0x12, 0x10); 262 } 263 } 264 265 static void epat_disconnect(struct pi_adapter *pi) 266 { 267 CPP(0x30); 268 w0(pi->saved_r0); 269 w2(pi->saved_r2); 270 } 271 272 static int epat_test_proto(struct pi_adapter *pi) 273 { 274 int k, j, f, cc; 275 int e[2] = { 0, 0 }; 276 char scratch[512]; 277 278 epat_connect(pi); 279 cc = RR(0xd); 280 epat_disconnect(pi); 281 282 epat_connect(pi); 283 for (j=0;j<2;j++) { 284 WRi(6, 0xa0 + j * 0x10); 285 for (k = 0; k < 256; k++) { 286 WRi(2, k ^ 0xaa); 287 WRi(3, k ^ 0x55); 288 if (RRi(2) != (k ^ 0xaa)) 289 e[j]++; 290 } 291 } 292 epat_disconnect(pi); 293 294 f = 0; 295 epat_connect(pi); 296 WR(0x13, 1); WR(0x13, 0); WR(0xa, 0x11); 297 epat_read_block(pi, scratch, 512); 298 299 for (k = 0; k < 256; k++) { 300 if ((scratch[2 * k] & 0xff) != k) 301 f++; 302 if ((scratch[2 * k + 1] & 0xff) != 0xff - k) 303 f++; 304 } 305 epat_disconnect(pi); 306 307 dev_dbg(&pi->dev, 308 "epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n", 309 pi->port, pi->mode, cc, e[0], e[1], f); 310 311 return (e[0] && e[1]) || f; 312 } 313 314 static void epat_log_adapter(struct pi_adapter *pi) 315 { 316 int ver; 317 char *mode_string[6] = 318 { "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; 319 320 epat_connect(pi); 321 WR(0xa, 0x38); /* read the version code */ 322 ver = RR(0xb); 323 epat_disconnect(pi); 324 325 dev_info(&pi->dev, 326 "Shuttle EPAT chip %x at 0x%x, mode %d (%s), delay %d\n", 327 ver, pi->port, pi->mode, mode_string[pi->mode], pi->delay); 328 } 329 330 static struct pi_protocol epat = { 331 .owner = THIS_MODULE, 332 .name = "epat", 333 .max_mode = 6, 334 .epp_first = 3, 335 .default_delay = 1, 336 .max_units = 1, 337 .write_regr = epat_write_regr, 338 .read_regr = epat_read_regr, 339 .write_block = epat_write_block, 340 .read_block = epat_read_block, 341 .connect = epat_connect, 342 .disconnect = epat_disconnect, 343 .test_proto = epat_test_proto, 344 .log_adapter = epat_log_adapter, 345 }; 346 347 static int __init epat_init(void) 348 { 349 #ifdef CONFIG_PATA_PARPORT_EPATC8 350 epatc8 = 1; 351 #endif 352 return pata_parport_register_driver(&epat); 353 } 354 355 static void __exit epat_exit(void) 356 { 357 pata_parport_unregister_driver(&epat); 358 } 359 360 MODULE_LICENSE("GPL"); 361 MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>"); 362 MODULE_DESCRIPTION("Shuttle Technologies EPAT parallel port IDE adapter " 363 "protocol driver"); 364 module_init(epat_init) 365 module_exit(epat_exit) 366