Commit | Line | Data |
---|---|---|
1da177e4 LT |
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/init.h> | |
21 | #include <linux/delay.h> | |
22 | #include <linux/kernel.h> | |
23 | #include <linux/types.h> | |
24 | #include <linux/wait.h> | |
25 | #include <asm/io.h> | |
26 | ||
27 | #include "paride.h" | |
28 | ||
29 | /* mode codes: 0 nybble reads, 8-bit writes | |
30 | 1 8-bit reads and writes | |
31 | 2 8-bit EPP mode | |
32 | */ | |
33 | ||
34 | #define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0)) | |
35 | ||
36 | #define P1 w2(5);w2(0xd);w2(0xd);w2(5);w2(4); | |
37 | #define P2 w2(5);w2(7);w2(7);w2(5);w2(4); | |
38 | ||
39 | /* cont = 0 - access the IDE register file | |
40 | cont = 1 - access the IDE command set | |
41 | */ | |
42 | ||
43 | static int cont_map[2] = { 0x08, 0x10 }; | |
44 | ||
45 | static int comm_read_regr( PIA *pi, int cont, int regr ) | |
46 | ||
47 | { int l, h, r; | |
48 | ||
49 | r = regr + cont_map[cont]; | |
50 | ||
51 | switch (pi->mode) { | |
52 | ||
53 | case 0: w0(r); P1; w0(0); | |
54 | w2(6); l = r1(); w0(0x80); h = r1(); w2(4); | |
55 | return j44(l,h); | |
56 | ||
57 | case 1: w0(r+0x20); P1; | |
58 | w0(0); w2(0x26); h = r0(); w2(4); | |
59 | return h; | |
60 | ||
61 | case 2: | |
62 | case 3: | |
10e705f8 | 63 | case 4: w3(r+0x20); (void)r1(); |
1da177e4 LT |
64 | w2(0x24); h = r4(); w2(4); |
65 | return h; | |
66 | ||
67 | } | |
68 | return -1; | |
69 | } | |
70 | ||
71 | static void comm_write_regr( PIA *pi, int cont, int regr, int val ) | |
72 | ||
73 | { int r; | |
74 | ||
75 | r = regr + cont_map[cont]; | |
76 | ||
77 | switch (pi->mode) { | |
78 | ||
79 | case 0: | |
80 | case 1: w0(r); P1; w0(val); P2; | |
81 | break; | |
82 | ||
83 | case 2: | |
84 | case 3: | |
10e705f8 | 85 | case 4: w3(r); (void)r1(); w4(val); |
1da177e4 LT |
86 | break; |
87 | } | |
88 | } | |
89 | ||
90 | static void comm_connect ( PIA *pi ) | |
91 | ||
92 | { pi->saved_r0 = r0(); | |
93 | pi->saved_r2 = r2(); | |
94 | w2(4); w0(0xff); w2(6); | |
95 | w2(4); w0(0xaa); w2(6); | |
96 | w2(4); w0(0x00); w2(6); | |
97 | w2(4); w0(0x87); w2(6); | |
98 | w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4); | |
99 | } | |
100 | ||
101 | static void comm_disconnect ( PIA *pi ) | |
102 | ||
103 | { w2(0); w2(0); w2(0); w2(4); | |
104 | w0(pi->saved_r0); | |
105 | w2(pi->saved_r2); | |
106 | } | |
107 | ||
108 | static void comm_read_block( PIA *pi, char * buf, int count ) | |
109 | ||
110 | { int i, l, h; | |
111 | ||
112 | switch (pi->mode) { | |
113 | ||
114 | case 0: w0(0x48); P1; | |
115 | for(i=0;i<count;i++) { | |
116 | w0(0); w2(6); l = r1(); | |
117 | w0(0x80); h = r1(); w2(4); | |
118 | buf[i] = j44(l,h); | |
119 | } | |
120 | break; | |
121 | ||
122 | case 1: w0(0x68); P1; w0(0); | |
123 | for(i=0;i<count;i++) { | |
124 | w2(0x26); buf[i] = r0(); w2(0x24); | |
125 | } | |
126 | w2(4); | |
127 | break; | |
128 | ||
10e705f8 | 129 | case 2: w3(0x68); (void)r1(); w2(0x24); |
1da177e4 LT |
130 | for (i=0;i<count;i++) buf[i] = r4(); |
131 | w2(4); | |
132 | break; | |
133 | ||
10e705f8 | 134 | case 3: w3(0x68); (void)r1(); w2(0x24); |
1da177e4 LT |
135 | for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w(); |
136 | w2(4); | |
137 | break; | |
138 | ||
10e705f8 | 139 | case 4: w3(0x68); (void)r1(); w2(0x24); |
1da177e4 LT |
140 | for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l(); |
141 | w2(4); | |
142 | break; | |
143 | ||
144 | } | |
145 | } | |
146 | ||
147 | /* NB: Watch out for the byte swapped writes ! */ | |
148 | ||
149 | static void comm_write_block( PIA *pi, char * buf, int count ) | |
150 | ||
151 | { int k; | |
152 | ||
153 | switch (pi->mode) { | |
154 | ||
155 | case 0: | |
156 | case 1: w0(0x68); P1; | |
157 | for (k=0;k<count;k++) { | |
158 | w2(5); w0(buf[k^1]); w2(7); | |
159 | } | |
160 | w2(5); w2(4); | |
161 | break; | |
162 | ||
10e705f8 | 163 | case 2: w3(0x48); (void)r1(); |
1da177e4 LT |
164 | for (k=0;k<count;k++) w4(buf[k^1]); |
165 | break; | |
166 | ||
10e705f8 | 167 | case 3: w3(0x48); (void)r1(); |
1da177e4 LT |
168 | for (k=0;k<count/2;k++) w4w(pi_swab16(buf,k)); |
169 | break; | |
170 | ||
10e705f8 | 171 | case 4: w3(0x48); (void)r1(); |
1da177e4 LT |
172 | for (k=0;k<count/4;k++) w4l(pi_swab32(buf,k)); |
173 | break; | |
174 | ||
175 | ||
176 | } | |
177 | } | |
178 | ||
179 | static void comm_log_adapter( PIA *pi, char * scratch, int verbose ) | |
180 | ||
181 | { char *mode_string[5] = {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"}; | |
182 | ||
183 | printk("%s: comm %s, DataStor Commuter at 0x%x, ", | |
184 | pi->device,COMM_VERSION,pi->port); | |
185 | printk("mode %d (%s), delay %d\n",pi->mode, | |
186 | mode_string[pi->mode],pi->delay); | |
187 | ||
188 | } | |
189 | ||
190 | static struct pi_protocol comm = { | |
191 | .owner = THIS_MODULE, | |
192 | .name = "comm", | |
193 | .max_mode = 5, | |
194 | .epp_first = 2, | |
195 | .default_delay = 1, | |
196 | .max_units = 1, | |
197 | .write_regr = comm_write_regr, | |
198 | .read_regr = comm_read_regr, | |
199 | .write_block = comm_write_block, | |
200 | .read_block = comm_read_block, | |
201 | .connect = comm_connect, | |
202 | .disconnect = comm_disconnect, | |
203 | .log_adapter = comm_log_adapter, | |
204 | }; | |
205 | ||
206 | static int __init comm_init(void) | |
207 | { | |
b4178ab5 | 208 | return paride_register(&comm); |
1da177e4 LT |
209 | } |
210 | ||
211 | static void __exit comm_exit(void) | |
212 | { | |
f4330002 | 213 | paride_unregister(&comm); |
1da177e4 LT |
214 | } |
215 | ||
216 | MODULE_LICENSE("GPL"); | |
217 | module_init(comm_init) | |
218 | module_exit(comm_exit) |