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#define FRIQ_VERSION "1.01"
29
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/delay.h>
33#include <linux/kernel.h>
34#include <linux/types.h>
35#include <linux/wait.h>
36#include <asm/io.h>
37
38#include "paride.h"
39
40#define CMD(x) w2(4);w0(0xff);w0(0xff);w0(0x73);w0(0x73);\
41 w0(0xc9);w0(0xc9);w0(0x26);w0(0x26);w0(x);w0(x);
42
43#define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
44
45
46
47
48
49static int cont_map[2] = { 0x08, 0x10 };
50
51static int friq_read_regr( PIA *pi, int cont, int regr )
52
53{ int h,l,r;
54
55 r = regr + cont_map[cont];
56
57 CMD(r);
58 w2(6); l = r1();
59 w2(4); h = r1();
60 w2(4);
61
62 return j44(l,h);
63
64}
65
66static void friq_write_regr( PIA *pi, int cont, int regr, int val)
67
68{ int r;
69
70 r = regr + cont_map[cont];
71
72 CMD(r);
73 w0(val);
74 w2(5);w2(7);w2(5);w2(4);
75}
76
77static void friq_read_block_int( PIA *pi, char * buf, int count, int regr )
78
79{ int h, l, k, ph;
80
81 switch(pi->mode) {
82
83 case 0: CMD(regr);
84 for (k=0;k<count;k++) {
85 w2(6); l = r1();
86 w2(4); h = r1();
87 buf[k] = j44(l,h);
88 }
89 w2(4);
90 break;
91
92 case 1: ph = 2;
93 CMD(regr+0xc0);
94 w0(0xff);
95 for (k=0;k<count;k++) {
96 w2(0xa4 + ph);
97 buf[k] = r0();
98 ph = 2 - ph;
99 }
100 w2(0xac); w2(0xa4); w2(4);
101 break;
102
103 case 2: CMD(regr+0x80);
104 for (k=0;k<count-2;k++) buf[k] = r4();
105 w2(0xac); w2(0xa4);
106 buf[count-2] = r4();
107 buf[count-1] = r4();
108 w2(4);
109 break;
110
111 case 3: CMD(regr+0x80);
112 for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
113 w2(0xac); w2(0xa4);
114 buf[count-2] = r4();
115 buf[count-1] = r4();
116 w2(4);
117 break;
118
119 case 4: CMD(regr+0x80);
120 for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
121 buf[count-4] = r4();
122 buf[count-3] = r4();
123 w2(0xac); w2(0xa4);
124 buf[count-2] = r4();
125 buf[count-1] = r4();
126 w2(4);
127 break;
128
129 }
130}
131
132static void friq_read_block( PIA *pi, char * buf, int count)
133
134{ friq_read_block_int(pi,buf,count,0x08);
135}
136
137static void friq_write_block( PIA *pi, char * buf, int count )
138
139{ int k;
140
141 switch(pi->mode) {
142
143 case 0:
144 case 1: CMD(8); w2(5);
145 for (k=0;k<count;k++) {
146 w0(buf[k]);
147 w2(7);w2(5);
148 }
149 w2(4);
150 break;
151
152 case 2: CMD(0xc8); w2(5);
153 for (k=0;k<count;k++) w4(buf[k]);
154 w2(4);
155 break;
156
157 case 3: CMD(0xc8); w2(5);
158 for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
159 w2(4);
160 break;
161
162 case 4: CMD(0xc8); w2(5);
163 for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
164 w2(4);
165 break;
166 }
167}
168
169static void friq_connect ( PIA *pi )
170
171{ pi->saved_r0 = r0();
172 pi->saved_r2 = r2();
173 w2(4);
174}
175
176static void friq_disconnect ( PIA *pi )
177
178{ CMD(0x20);
179 w0(pi->saved_r0);
180 w2(pi->saved_r2);
181}
182
183static int friq_test_proto( PIA *pi, char * scratch, int verbose )
184
185{ int j, k, r;
186 int e[2] = {0,0};
187
188 pi->saved_r0 = r0();
189 w0(0xff); udelay(20); CMD(0x3d);
190 udelay(500);
191 w0(pi->saved_r0);
192
193 friq_connect(pi);
194 for (j=0;j<2;j++) {
195 friq_write_regr(pi,0,6,0xa0+j*0x10);
196 for (k=0;k<256;k++) {
197 friq_write_regr(pi,0,2,k^0xaa);
198 friq_write_regr(pi,0,3,k^0x55);
199 if (friq_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
200 }
201 }
202 friq_disconnect(pi);
203
204 friq_connect(pi);
205 friq_read_block_int(pi,scratch,512,0x10);
206 r = 0;
207 for (k=0;k<128;k++) if (scratch[k] != k) r++;
208 friq_disconnect(pi);
209
210 if (verbose) {
211 printk("%s: friq: port 0x%x, mode %d, test=(%d,%d,%d)\n",
212 pi->device,pi->port,pi->mode,e[0],e[1],r);
213 }
214
215 return (r || (e[0] && e[1]));
216}
217
218
219static void friq_log_adapter( PIA *pi, char * scratch, int verbose )
220
221{ char *mode_string[6] = {"4-bit","8-bit",
222 "EPP-8","EPP-16","EPP-32"};
223
224 printk("%s: friq %s, Freecom IQ ASIC-2 adapter at 0x%x, ", pi->device,
225 FRIQ_VERSION,pi->port);
226 printk("mode %d (%s), delay %d\n",pi->mode,
227 mode_string[pi->mode],pi->delay);
228
229 pi->private = 1;
230 friq_connect(pi);
231 CMD(0x9e);
232 friq_disconnect(pi);
233
234}
235
236static void friq_release_proto( PIA *pi)
237{
238 if (pi->private) {
239 friq_connect(pi);
240 CMD(0x1d); CMD(0x1e);
241 friq_disconnect(pi);
242 pi->private = 0;
243 }
244}
245
246static struct pi_protocol friq = {
247 .owner = THIS_MODULE,
248 .name = "friq",
249 .max_mode = 5,
250 .epp_first = 2,
251 .default_delay = 1,
252 .max_units = 1,
253 .write_regr = friq_write_regr,
254 .read_regr = friq_read_regr,
255 .write_block = friq_write_block,
256 .read_block = friq_read_block,
257 .connect = friq_connect,
258 .disconnect = friq_disconnect,
259 .test_proto = friq_test_proto,
260 .log_adapter = friq_log_adapter,
261 .release_proto = friq_release_proto,
262};
263
264static int __init friq_init(void)
265{
266 return paride_register(&friq);
267}
268
269static void __exit friq_exit(void)
270{
271 paride_unregister(&friq);
272}
273
274MODULE_LICENSE("GPL");
275module_init(friq_init)
276module_exit(friq_exit)
277