1 /* 2 fit3.c (c) 1998 Grant R. Guenther <grant@torque.net> 3 Under the terms of the GNU General Public License. 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 NB: The FIT adapters do not appear to support the control 14 registers. So, we map ALT_STATUS to STATUS and NO-OP writes 15 to the device control register - this means that IDE reset 16 will not work on these devices. 17 18 */ 19 20 #include <linux/module.h> 21 #include <linux/init.h> 22 #include <linux/delay.h> 23 #include <linux/kernel.h> 24 #include <linux/types.h> 25 #include <linux/wait.h> 26 #include <asm/io.h> 27 #include "pata_parport.h" 28 29 #define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0)) 30 31 #define w7(byte) {out_p(7,byte);} 32 #define r7() (in_p(7) & 0xff) 33 34 /* cont = 0 - access the IDE register file 35 cont = 1 - access the IDE command set 36 37 */ 38 39 static void fit3_write_regr(struct pi_adapter *pi, int cont, int regr, int val) 40 41 { if (cont == 1) return; 42 43 switch (pi->mode) { 44 45 case 0: 46 case 1: w2(0xc); w0(regr); w2(0x8); w2(0xc); 47 w0(val); w2(0xd); 48 w0(0); w2(0xc); 49 break; 50 51 case 2: w2(0xc); w0(regr); w2(0x8); w2(0xc); 52 w4(val); w4(0); 53 w2(0xc); 54 break; 55 56 } 57 } 58 59 static int fit3_read_regr(struct pi_adapter *pi, int cont, int regr) 60 61 { int a, b; 62 63 if (cont) { 64 if (regr != 6) return 0xff; 65 regr = 7; 66 } 67 68 switch (pi->mode) { 69 70 case 0: w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc); 71 w2(0xd); a = r1(); 72 w2(0xf); b = r1(); 73 w2(0xc); 74 return j44(a,b); 75 76 case 1: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); 77 w2(0xec); w2(0xee); w2(0xef); a = r0(); 78 w2(0xc); 79 return a; 80 81 case 2: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); 82 w2(0xec); 83 a = r4(); b = r4(); 84 w2(0xc); 85 return a; 86 87 } 88 return -1; 89 90 } 91 92 static void fit3_read_block(struct pi_adapter *pi, char *buf, int count) 93 94 { int k, a, b, c, d; 95 96 switch (pi->mode) { 97 98 case 0: w2(0xc); w0(0x10); w2(0x8); w2(0xc); 99 for (k=0;k<count/2;k++) { 100 w2(0xd); a = r1(); 101 w2(0xf); b = r1(); 102 w2(0xc); c = r1(); 103 w2(0xe); d = r1(); 104 buf[2*k ] = j44(a,b); 105 buf[2*k+1] = j44(c,d); 106 } 107 w2(0xc); 108 break; 109 110 case 1: w2(0xc); w0(0x90); w2(0x8); w2(0xc); 111 w2(0xec); w2(0xee); 112 for (k=0;k<count/2;k++) { 113 w2(0xef); a = r0(); 114 w2(0xee); b = r0(); 115 buf[2*k ] = a; 116 buf[2*k+1] = b; 117 } 118 w2(0xec); 119 w2(0xc); 120 break; 121 122 case 2: w2(0xc); w0(0x90); w2(0x8); w2(0xc); 123 w2(0xec); 124 for (k=0;k<count;k++) buf[k] = r4(); 125 w2(0xc); 126 break; 127 128 } 129 } 130 131 static void fit3_write_block(struct pi_adapter *pi, char *buf, int count) 132 133 { int k; 134 135 switch (pi->mode) { 136 137 case 0: 138 case 1: w2(0xc); w0(0); w2(0x8); w2(0xc); 139 for (k=0;k<count/2;k++) { 140 w0(buf[2*k ]); w2(0xd); 141 w0(buf[2*k+1]); w2(0xc); 142 } 143 break; 144 145 case 2: w2(0xc); w0(0); w2(0x8); w2(0xc); 146 for (k=0;k<count;k++) w4(buf[k]); 147 w2(0xc); 148 break; 149 } 150 } 151 152 static void fit3_connect(struct pi_adapter *pi) 153 154 { pi->saved_r0 = r0(); 155 pi->saved_r2 = r2(); 156 w2(0xc); w0(0); w2(0xa); 157 if (pi->mode == 2) { 158 w2(0xc); w0(0x9); w2(0x8); w2(0xc); 159 } 160 } 161 162 static void fit3_disconnect(struct pi_adapter *pi) 163 164 { w2(0xc); w0(0xa); w2(0x8); w2(0xc); 165 w0(pi->saved_r0); 166 w2(pi->saved_r2); 167 } 168 169 static void fit3_log_adapter(struct pi_adapter *pi) 170 171 { char *mode_string[3] = {"4-bit","8-bit","EPP"}; 172 173 dev_info(&pi->dev, "FIT 3000 adapter at 0x%x, mode %d (%s), delay %d\n", 174 pi->port, pi->mode, mode_string[pi->mode], pi->delay); 175 } 176 177 static struct pi_protocol fit3 = { 178 .owner = THIS_MODULE, 179 .name = "fit3", 180 .max_mode = 3, 181 .epp_first = 2, 182 .default_delay = 1, 183 .max_units = 1, 184 .write_regr = fit3_write_regr, 185 .read_regr = fit3_read_regr, 186 .write_block = fit3_write_block, 187 .read_block = fit3_read_block, 188 .connect = fit3_connect, 189 .disconnect = fit3_disconnect, 190 .log_adapter = fit3_log_adapter, 191 }; 192 193 MODULE_LICENSE("GPL"); 194 module_pata_parport_driver(fit3); 195