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 
42 static int  cont_map[2] = { 0x08, 0x10 };
43 
comm_read_regr(PIA * pi,int cont,int regr)44 static 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 
comm_write_regr(PIA * pi,int cont,int regr,int val)70 static 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 
comm_connect(PIA * pi)89 static 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 
comm_disconnect(PIA * pi)100 static 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 
comm_read_block(PIA * pi,char * buf,int count)107 static 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 
comm_write_block(PIA * pi,char * buf,int count)148 static 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 
comm_log_adapter(PIA * pi,char * scratch,int verbose)178 static 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 
comm_init_proto(PIA * pi)189 static void comm_init_proto(PIA *pi)
190 
191 {       MOD_INC_USE_COUNT;
192 }
193 
comm_release_proto(PIA * pi)194 static void comm_release_proto(PIA *pi)
195 
196 {       MOD_DEC_USE_COUNT;
197 }
198 
199 struct 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 
init_module(void)217 int     init_module(void)
218 
219 {       return pi_register( &comm ) - 1;
220 }
221 
cleanup_module(void)222 void    cleanup_module(void)
223 
224 {       pi_unregister( &comm );
225 }
226 
227 #endif
228 
229 /* end of comm.c */
230 MODULE_LICENSE("GPL");
231