1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * (c) 1998 Grant R. Guenther <grant@torque.net> 4 * 5 * fit3.c is a low-level protocol driver for newer models 6 * of the Fidelity International Technology parallel port adapter. 7 * This adapter is used in their TransDisk 3000 portable 8 * hard-drives, as well as CD-ROM, PD-CD and other devices. 9 * 10 * The TD-2000 and certain older devices use a different protocol. 11 * Try the fit2 protocol module with them. 12 */ 13 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/delay.h> 17 #include <linux/kernel.h> 18 #include <linux/types.h> 19 #include <linux/wait.h> 20 #include <asm/io.h> 21 #include "pata_parport.h" 22 23 #define j44(a, b) (((a >> 3) & 0x0f) | ((b << 1) & 0xf0)) 24 25 #define w7(byte) out_p(7, byte) 26 #define r7() (in_p(7) & 0xff) 27 28 /* 29 * cont = 0 - access the IDE register file 30 * cont = 1 - access the IDE command set 31 */ 32 33 static void fit3_write_regr(struct pi_adapter *pi, int cont, int regr, int val) 34 { 35 regr += cont << 3; 36 37 switch (pi->mode) { 38 case 0: 39 case 1: 40 w2(0xc); w0(regr); w2(0x8); w2(0xc); 41 w0(val); w2(0xd); 42 w0(0); w2(0xc); 43 break; 44 case 2: 45 w2(0xc); w0(regr); w2(0x8); w2(0xc); 46 w4(val); w4(0); 47 w2(0xc); 48 break; 49 } 50 } 51 52 static int fit3_read_regr(struct pi_adapter *pi, int cont, int regr) 53 { 54 int a, b; 55 56 regr += cont << 3; 57 58 switch (pi->mode) { 59 case 0: 60 w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc); 61 w2(0xd); a = r1(); 62 w2(0xf); b = r1(); 63 w2(0xc); 64 return j44(a, b); 65 case 1: 66 w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); 67 w2(0xec); w2(0xee); w2(0xef); a = r0(); 68 w2(0xc); 69 return a; 70 case 2: 71 w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); 72 w2(0xec); 73 a = r4(); b = r4(); 74 w2(0xc); 75 return a; 76 } 77 78 return -1; 79 } 80 81 static void fit3_read_block(struct pi_adapter *pi, char *buf, int count) 82 { 83 int k, a, b, c, d; 84 85 switch (pi->mode) { 86 case 0: 87 w2(0xc); w0(0x10); w2(0x8); w2(0xc); 88 for (k = 0; k < count / 2; k++) { 89 w2(0xd); a = r1(); 90 w2(0xf); b = r1(); 91 w2(0xc); c = r1(); 92 w2(0xe); d = r1(); 93 buf[2 * k] = j44(a, b); 94 buf[2 * k + 1] = j44(c, d); 95 } 96 w2(0xc); 97 break; 98 case 1: 99 w2(0xc); w0(0x90); w2(0x8); w2(0xc); 100 w2(0xec); w2(0xee); 101 for (k = 0; k < count / 2; k++) { 102 w2(0xef); a = r0(); 103 w2(0xee); b = r0(); 104 buf[2 * k] = a; 105 buf[2 * k + 1] = b; 106 } 107 w2(0xec); 108 w2(0xc); 109 break; 110 case 2: 111 w2(0xc); w0(0x90); w2(0x8); w2(0xc); 112 w2(0xec); 113 for (k = 0; k < count; k++) 114 buf[k] = r4(); 115 w2(0xc); 116 break; 117 } 118 } 119 120 static void fit3_write_block(struct pi_adapter *pi, char *buf, int count) 121 { 122 int k; 123 124 switch (pi->mode) { 125 case 0: 126 case 1: 127 w2(0xc); w0(0); w2(0x8); w2(0xc); 128 for (k = 0; k < count / 2; k++) { 129 w0(buf[2 * k]); w2(0xd); 130 w0(buf[2 * k + 1]); w2(0xc); 131 } 132 break; 133 case 2: 134 w2(0xc); w0(0); w2(0x8); w2(0xc); 135 for (k = 0; k < count; k++) 136 w4(buf[k]); 137 w2(0xc); 138 break; 139 } 140 } 141 142 static void fit3_connect(struct pi_adapter *pi) 143 { 144 pi->saved_r0 = r0(); 145 pi->saved_r2 = r2(); 146 w2(0xc); w0(0); w2(0xa); 147 if (pi->mode == 2) { 148 w2(0xc); w0(0x9); 149 w2(0x8); w2(0xc); 150 } 151 } 152 153 static void fit3_disconnect(struct pi_adapter *pi) 154 { 155 w2(0xc); w0(0xa); w2(0x8); w2(0xc); 156 w0(pi->saved_r0); 157 w2(pi->saved_r2); 158 } 159 160 static void fit3_log_adapter(struct pi_adapter *pi) 161 { 162 char *mode_string[3] = { "4-bit", "8-bit", "EPP"}; 163 164 dev_info(&pi->dev, 165 "FIT 3000 adapter at 0x%x, mode %d (%s), delay %d\n", 166 pi->port, pi->mode, mode_string[pi->mode], pi->delay); 167 } 168 169 static struct pi_protocol fit3 = { 170 .owner = THIS_MODULE, 171 .name = "fit3", 172 .max_mode = 3, 173 .epp_first = 2, 174 .default_delay = 1, 175 .max_units = 1, 176 .write_regr = fit3_write_regr, 177 .read_regr = fit3_read_regr, 178 .write_block = fit3_write_block, 179 .read_block = fit3_read_block, 180 .connect = fit3_connect, 181 .disconnect = fit3_disconnect, 182 .log_adapter = fit3_log_adapter, 183 }; 184 185 MODULE_LICENSE("GPL"); 186 MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>"); 187 MODULE_DESCRIPTION("Fidelity International Technology parallel port IDE adapter" 188 "(newer models) protocol driver"); 189 module_pata_parport_driver(fit3); 190