summaryrefslogtreecommitdiffstats
path: root/drivers/block/paride/on20.c
blob: c9b3fa35bc7dd08e2935609162aa9eb32f7e7ffc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* 
	on20.c	(c) 1996  Grant R. Guenther <grant@torque.net>
		          Under the terms of the GNU public license.

        on20.c is a low-level protocol driver for the
        Onspec 90c20 parallel to IDE adapter. 
*/

#define	ON20_VERSION	"1.0"

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/io.h>

#include "paride.h"

#define op(f)	w2(4);w0(f);w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4);
#define vl(v)	w2(4);w0(v);w2(5);w2(7);w2(5);w2(4);

#define j44(a,b)  (((a>>4)&0x0f)|(b&0xf0))

/* cont = 0 - access the IDE register file 
   cont = 1 - access the IDE command set 
*/

static int on20_read_regr( PIA *pi, int cont, int regr )

{	int h,l, r ;

        r = (regr<<2) + 1 + cont;

        op(1); vl(r); op(0);

	switch (pi->mode)  {

        case 0:  w2(4); w2(6); l = r1();
                 w2(4); w2(6); h = r1();
                 w2(4); w2(6); w2(4); w2(6); w2(4);
		 return j44(l,h);

	case 1:  w2(4); w2(0x26); r = r0(); 
                 w2(4); w2(0x26); w2(4);
		 return r;

	}
	return -1;
}	

static void on20_write_regr( PIA *pi, int cont, int regr, int val )

{	int r;

	r = (regr<<2) + 1 + cont;

	op(1); vl(r); 
	op(0); vl(val); 
	op(0); vl(val);
}

static void on20_connect ( PIA *pi)

{	pi->saved_r0 = r0();
        pi->saved_r2 = r2();

	w2(4);w0(0);w2(0xc);w2(4);w2(6);w2(4);w2(6);w2(4); 
	if (pi->mode) { op(2); vl(8); op(2); vl(9); }
	       else   { op(2); vl(0); op(2); vl(8); }
}

static void on20_disconnect ( PIA *pi )

{	w2(4);w0(7);w2(4);w2(0xc);w2(4);
        w0(pi->saved_r0);
        w2(pi->saved_r2);
} 

static void on20_read_block( PIA *pi, char * buf, int count )

{	int     k, l, h; 

	op(1); vl(1); op(0);

	for (k=0;k<count;k++) 
	    if (pi->mode) {
		w2(4); w2(0x26); buf[k] = r0();
	    } else {
		w2(6); l = r1(); w2(4);
		w2(6); h = r1(); w2(4);
		buf[k] = j44(l,h);
	    }
	w2(4);
}

static void on20_write_block(  PIA *pi, char * buf, int count )

{	int	k;

	op(1); vl(1); op(0);

	for (k=0;k<count;k++) { w2(5); w0(buf[k]); w2(7); }
	w2(4);
}

static void on20_log_adapter( PIA *pi, char * scratch, int verbose )

{       char    *mode_string[2] = {"4-bit","8-bit"};

        printk("%s: on20 %s, OnSpec 90c20 at 0x%x, ",
                pi->device,ON20_VERSION,pi->port);
        printk("mode %d (%s), delay %d\n",pi->mode,
		mode_string[pi->mode],pi->delay);

}

static void on20_inc_use ( void )

{       MOD_INC_USE_COUNT;
}

static void on20_dec_use ( void )

{       MOD_DEC_USE_COUNT;
}

struct pi_protocol on20 = {"on20",0,2,2,1,1,
                           on20_write_regr,
                           on20_read_regr,
                           on20_write_block,
                           on20_read_block,
                           on20_connect,
                           on20_disconnect,
                           0,
                           0,
                           0,
                           on20_log_adapter,
                           on20_inc_use, 
                           on20_dec_use 
                          };


#ifdef MODULE

int     init_module(void)

{       return pi_register( &on20 ) - 1;
}

void    cleanup_module(void)

{       pi_unregister( &on20 );
}

#endif

/* end of on20.c */