11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fit2.c        (c) 1998  Grant R. Guenther <grant@torque.net>
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                          Under the terms of the GNU General Public License.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fit2.c is a low-level protocol driver for the older version
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        of the Fidelity International Technology parallel port adapter.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	This adapter is used in their TransDisk 2000 and older TransDisk
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	3000 portable hard-drives.  As far as I can tell, this device
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	supports 4-bit mode _only_.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Newer models of the FIT products use an enhanced protocol.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	The "fit3" protocol module should support current drives.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FIT2_VERSION      "1.0"
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/wait.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "paride.h"
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define j44(a,b)                (((a>>4)&0x0f)|(b&0xf0))
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* cont = 0 - access the IDE register file
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   cont = 1 - access the IDE command set
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsNB:  The FIT adapter does not appear to use the control registers.
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsSo, we map ALT_STATUS to STATUS and NO-OP writes to the device
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscontrol register - this means that IDE reset will not work on these
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdevices.
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void  fit2_write_regr( PIA *pi, int cont, int regr, int val)
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{	if (cont == 1) return;
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	w2(0xc); w0(regr); w2(4); w0(val); w2(5); w0(0); w2(4);
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fit2_read_regr( PIA *pi, int cont, int regr )
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{	int  a, b, r;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cont) {
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  if (regr != 6) return 0xff;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  r = 7;
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else r = regr + 0x10;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	w2(0xc); w0(r); w2(4); w2(5);
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         w0(0); a = r1();
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         w0(1); b = r1();
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	w2(4);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return j44(a,b);
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fit2_read_block( PIA *pi, char * buf, int count )
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{	int  k, a, b, c, d;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	w2(0xc); w0(0x10);
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (k=0;k<count/4;k++) {
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w2(4); w2(5);
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w0(0); a = r1(); w0(1); b = r1();
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w0(3); c = r1(); w0(2); d = r1();
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		buf[4*k+0] = j44(a,b);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		buf[4*k+1] = j44(d,c);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                w2(4); w2(5);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                       a = r1(); w0(3); b = r1();
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                w0(1); c = r1(); w0(0); d = r1();
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                buf[4*k+2] = j44(d,c);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                buf[4*k+3] = j44(a,b);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	w2(4);
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fit2_write_block( PIA *pi, char * buf, int count )
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{	int k;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	w2(0xc); w0(0);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (k=0;k<count/2;k++) {
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w2(4); w0(buf[2*k]);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		w2(5); w0(buf[2*k+1]);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	w2(4);
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fit2_connect ( PIA *pi  )
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       pi->saved_r0 = r0();
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        pi->saved_r2 = r2();
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	w2(0xcc);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fit2_disconnect ( PIA *pi )
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       w0(pi->saved_r0);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        w2(pi->saved_r2);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fit2_log_adapter( PIA *pi, char * scratch, int verbose )
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       printk("%s: fit2 %s, FIT 2000 adapter at 0x%x, delay %d\n",
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                pi->device,FIT2_VERSION,pi->port,pi->delay);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pi_protocol fit2 = {
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner		= THIS_MODULE,
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "fit2",
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.max_mode	= 1,
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.epp_first	= 2,
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.default_delay	= 1,
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.max_units	= 1,
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.write_regr	= fit2_write_regr,
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_regr	= fit2_read_regr,
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.write_block	= fit2_write_block,
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_block	= fit2_read_block,
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.connect	= fit2_connect,
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.disconnect	= fit2_disconnect,
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.log_adapter	= fit2_log_adapter,
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init fit2_init(void)
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
141b4178ab58aa81f4ed3c75c48940682fe3b45d880Alexey Dobriyan	return paride_register(&fit2);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit fit2_exit(void)
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
146f4330002d11f032559954cbff68a5cad95b6d27fAlexey Dobriyan	paride_unregister(&fit2);
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(fit2_init)
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(fit2_exit)
152