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#define FIT3_VERSION "1.0" 21 22#include <linux/module.h> 23#include <linux/delay.h> 24#include <linux/kernel.h> 25#include <linux/types.h> 26#include <linux/wait.h> 27#include <asm/io.h> 28 29#include "paride.h" 30 31#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0)) 32 33#define w7(byte) {out_p(7,byte);} 34#define r7() (in_p(7) & 0xff) 35 36/* cont = 0 - access the IDE register file 37 cont = 1 - access the IDE command set 38 39*/ 40 41static void fit3_write_regr( PIA *pi, int cont, int regr, int val) 42 43{ if (cont == 1) return; 44 45 switch (pi->mode) { 46 47 case 0: 48 case 1: w2(0xc); w0(regr); w2(0x8); w2(0xc); 49 w0(val); w2(0xd); 50 w0(0); w2(0xc); 51 break; 52 53 case 2: w2(0xc); w0(regr); w2(0x8); w2(0xc); 54 w4(val); w4(0); 55 w2(0xc); 56 break; 57 58 } 59} 60 61static int fit3_read_regr( PIA *pi, int cont, int regr ) 62 63{ int a, b; 64 65 if (cont) { 66 if (regr != 6) return 0xff; 67 regr = 7; 68 } 69 70 switch (pi->mode) { 71 72 case 0: w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc); 73 w2(0xd); a = r1(); 74 w2(0xf); b = r1(); 75 w2(0xc); 76 return j44(a,b); 77 78 case 1: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); 79 w2(0xec); w2(0xee); w2(0xef); a = r0(); 80 w2(0xc); 81 return a; 82 83 case 2: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); 84 w2(0xec); 85 a = r4(); b = r4(); 86 w2(0xc); 87 return a; 88 89 } 90 return -1; 91 92} 93 94static void fit3_read_block( PIA *pi, char * buf, int count ) 95 96{ int k, a, b, c, d; 97 98 switch (pi->mode) { 99 100 case 0: w2(0xc); w0(0x10); w2(0x8); w2(0xc); 101 for (k=0;k<count/2;k++) { 102 w2(0xd); a = r1(); 103 w2(0xf); b = r1(); 104 w2(0xc); c = r1(); 105 w2(0xe); d = r1(); 106 buf[2*k ] = j44(a,b); 107 buf[2*k+1] = j44(c,d); 108 } 109 w2(0xc); 110 break; 111 112 case 1: w2(0xc); w0(0x90); w2(0x8); w2(0xc); 113 w2(0xec); w2(0xee); 114 for (k=0;k<count/2;k++) { 115 w2(0xef); a = r0(); 116 w2(0xee); b = r0(); 117 buf[2*k ] = a; 118 buf[2*k+1] = b; 119 } 120 w2(0xec); 121 w2(0xc); 122 break; 123 124 case 2: w2(0xc); w0(0x90); w2(0x8); w2(0xc); 125 w2(0xec); 126 for (k=0;k<count;k++) buf[k] = r4(); 127 w2(0xc); 128 break; 129 130 } 131} 132 133static void fit3_write_block( PIA *pi, char * buf, int count ) 134 135{ int k; 136 137 switch (pi->mode) { 138 139 case 0: 140 case 1: w2(0xc); w0(0); w2(0x8); w2(0xc); 141 for (k=0;k<count/2;k++) { 142 w0(buf[2*k ]); w2(0xd); 143 w0(buf[2*k+1]); w2(0xc); 144 } 145 break; 146 147 case 2: w2(0xc); w0(0); w2(0x8); w2(0xc); 148 for (k=0;k<count;k++) w4(buf[k]); 149 w2(0xc); 150 break; 151 } 152} 153 154static void fit3_connect ( PIA *pi ) 155 156{ pi->saved_r0 = r0(); 157 pi->saved_r2 = r2(); 158 w2(0xc); w0(0); w2(0xa); 159 if (pi->mode == 2) { 160 w2(0xc); w0(0x9); w2(0x8); w2(0xc); 161 } 162} 163 164static void fit3_disconnect ( PIA *pi ) 165 166{ w2(0xc); w0(0xa); w2(0x8); w2(0xc); 167 w0(pi->saved_r0); 168 w2(pi->saved_r2); 169} 170 171static void fit3_log_adapter( PIA *pi, char * scratch, int verbose ) 172 173{ char *mode_string[3] = {"4-bit","8-bit","EPP"}; 174 175 printk("%s: fit3 %s, FIT 3000 adapter at 0x%x, " 176 "mode %d (%s), delay %d\n", 177 pi->device,FIT3_VERSION,pi->port, 178 pi->mode,mode_string[pi->mode],pi->delay); 179 180} 181 182static void fit3_init_proto(PIA *pi) 183 184{ MOD_INC_USE_COUNT; 185} 186 187static void fit3_release_proto(PIA *pi) 188 189{ MOD_DEC_USE_COUNT; 190} 191 192struct pi_protocol fit3 = {"fit3",0,3,2,1,1, 193 fit3_write_regr, 194 fit3_read_regr, 195 fit3_write_block, 196 fit3_read_block, 197 fit3_connect, 198 fit3_disconnect, 199 0, 200 0, 201 0, 202 fit3_log_adapter, 203 fit3_init_proto, 204 fit3_release_proto 205 }; 206 207 208#ifdef MODULE 209 210int init_module(void) 211 212{ return pi_register( &fit3 ) - 1; 213} 214 215void cleanup_module(void) 216 217{ pi_unregister( &fit3 ); 218} 219 220#endif 221 222/* end of fit3.c */ 223MODULE_LICENSE("GPL"); 224