1/*
2        comm.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
3                              Under the terms of the GNU General Public License.
4
5	comm.c is a low-level protocol driver for some older models
6	of the DataStor "Commuter" parallel to IDE adapter.  Some of
7	the parallel port devices marketed by Arista currently
8	use this adapter.
9*/
10
11/* Changes:
12
13	1.01	GRG 1998.05.05  init_proto, release_proto
14
15*/
16
17#define COMM_VERSION      "1.01"
18
19#include <linux/module.h>
20#include <linux/delay.h>
21#include <linux/kernel.h>
22#include <linux/types.h>
23#include <linux/wait.h>
24#include <asm/io.h>
25
26#include "paride.h"
27
28/* mode codes:  0  nybble reads, 8-bit writes
29                1  8-bit reads and writes
30                2  8-bit EPP mode
31*/
32
33#define j44(a,b)	(((a>>3)&0x0f)|((b<<1)&0xf0))
34
35#define P1	w2(5);w2(0xd);w2(0xd);w2(5);w2(4);
36#define P2	w2(5);w2(7);w2(7);w2(5);w2(4);
37
38/* cont = 0 - access the IDE register file
39   cont = 1 - access the IDE command set
40*/
41
42static int  cont_map[2] = { 0x08, 0x10 };
43
44static int comm_read_regr( PIA *pi, int cont, int regr )
45
46{       int     l, h, r;
47
48        r = regr + cont_map[cont];
49
50        switch (pi->mode)  {
51
52        case 0: w0(r); P1; w0(0);
53        	w2(6); l = r1(); w0(0x80); h = r1(); w2(4);
54                return j44(l,h);
55
56        case 1: w0(r+0x20); P1;
57        	w0(0); w2(0x26); h = r0(); w2(4);
58                return h;
59
60	case 2:
61	case 3:
62        case 4: w3(r+0x20); r1();
63        	w2(0x24); h = r4(); w2(4);
64                return h;
65
66        }
67        return -1;
68}
69
70static void comm_write_regr( PIA *pi, int cont, int regr, int val )
71
72{       int  r;
73
74        r = regr + cont_map[cont];
75
76        switch (pi->mode)  {
77
78        case 0:
79        case 1: w0(r); P1; w0(val); P2;
80		break;
81
82	case 2:
83	case 3:
84        case 4: w3(r); r1(); w4(val);
85                break;
86        }
87}
88
89static void comm_connect ( PIA *pi  )
90
91{       pi->saved_r0 = r0();
92        pi->saved_r2 = r2();
93        w2(4); w0(0xff); w2(6);
94        w2(4); w0(0xaa); w2(6);
95        w2(4); w0(0x00); w2(6);
96        w2(4); w0(0x87); w2(6);
97        w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4);
98}
99
100static void comm_disconnect ( PIA *pi )
101
102{       w2(0); w2(0); w2(0); w2(4);
103	w0(pi->saved_r0);
104        w2(pi->saved_r2);
105}
106
107static void comm_read_block( PIA *pi, char * buf, int count )
108
109{       int     i, l, h;
110
111        switch (pi->mode) {
112
113        case 0: w0(0x48); P1;
114                for(i=0;i<count;i++) {
115                        w0(0); w2(6); l = r1();
116                        w0(0x80); h = r1(); w2(4);
117                        buf[i] = j44(l,h);
118                }
119                break;
120
121        case 1: w0(0x68); P1; w0(0);
122                for(i=0;i<count;i++) {
123                        w2(0x26); buf[i] = r0(); w2(0x24);
124                }
125		w2(4);
126		break;
127
128	case 2: w3(0x68); r1(); w2(0x24);
129		for (i=0;i<count;i++) buf[i] = r4();
130		w2(4);
131		break;
132
133        case 3: w3(0x68); r1(); w2(0x24);
134                for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
135                w2(4);
136                break;
137
138        case 4: w3(0x68); r1(); w2(0x24);
139                for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
140                w2(4);
141                break;
142
143	}
144}
145
146/* NB: Watch out for the byte swapped writes ! */
147
148static void comm_write_block( PIA *pi, char * buf, int count )
149
150{       int	k;
151
152        switch (pi->mode) {
153
154        case 0:
155        case 1: w0(0x68); P1;
156        	for (k=0;k<count;k++) {
157                        w2(5); w0(buf[k^1]); w2(7);
158                }
159                w2(5); w2(4);
160                break;
161
162        case 2: w3(0x48); r1();
163                for (k=0;k<count;k++) w4(buf[k^1]);
164                break;
165
166        case 3: w3(0x48); r1();
167                for (k=0;k<count/2;k++) w4w(pi_swab16(buf,k));
168                break;
169
170        case 4: w3(0x48); r1();
171                for (k=0;k<count/4;k++) w4l(pi_swab32(buf,k));
172                break;
173
174
175        }
176}
177
178static void comm_log_adapter( PIA *pi, char * scratch, int verbose )
179
180{       char    *mode_string[5] = {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"};
181
182        printk("%s: comm %s, DataStor Commuter at 0x%x, ",
183                pi->device,COMM_VERSION,pi->port);
184        printk("mode %d (%s), delay %d\n",pi->mode,
185		mode_string[pi->mode],pi->delay);
186
187}
188
189static void comm_init_proto(PIA *pi)
190
191{       MOD_INC_USE_COUNT;
192}
193
194static void comm_release_proto(PIA *pi)
195
196{       MOD_DEC_USE_COUNT;
197}
198
199struct pi_protocol comm = {"comm",0,5,2,1,1,
200                           comm_write_regr,
201                           comm_read_regr,
202                           comm_write_block,
203                           comm_read_block,
204                           comm_connect,
205                           comm_disconnect,
206                           0,
207                           0,
208                           0,
209                           comm_log_adapter,
210                           comm_init_proto,
211                           comm_release_proto
212                          };
213
214
215#ifdef MODULE
216
217int     init_module(void)
218
219{       return pi_register( &comm ) - 1;
220}
221
222void    cleanup_module(void)
223
224{       pi_unregister( &comm );
225}
226
227#endif
228
229/* end of comm.c */
230MODULE_LICENSE("GPL");
231