ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / block / paride / paride.c
1 /* 
2         paride.c  (c) 1997-8  Grant R. Guenther <grant@torque.net>
3                               Under the terms of the GNU General Public License.
4
5         This is the base module for the family of device drivers
6         that support parallel port IDE devices.  
7
8 */
9
10 /* Changes:
11
12         1.01    GRG 1998.05.03  Use spinlocks
13         1.02    GRG 1998.05.05  init_proto, release_proto, ktti
14         1.03    GRG 1998.08.15  eliminate compiler warning
15         1.04    GRG 1998.11.28  added support for FRIQ 
16         1.05    TMW 2000.06.06  use parport_find_number instead of
17                                 parport_enumerate
18         1.06    TMW 2001.03.26  more sane parport-or-not resource management
19 */
20
21 #define PI_VERSION      "1.06"
22
23 #include <linux/module.h>
24 #include <linux/config.h>
25 #include <linux/kmod.h>
26 #include <linux/types.h>
27 #include <linux/kernel.h>
28 #include <linux/ioport.h>
29 #include <linux/string.h>
30 #include <linux/spinlock.h>
31 #include <linux/wait.h>
32
33 #ifdef CONFIG_PARPORT_MODULE
34 #define CONFIG_PARPORT
35 #endif
36
37 #ifdef CONFIG_PARPORT
38 #include <linux/parport.h>
39 #endif
40
41 #include "paride.h"
42
43 MODULE_LICENSE("GPL");
44
45 #define MAX_PROTOS      32
46
47 static struct pi_protocol *protocols[MAX_PROTOS];
48
49 static spinlock_t pi_spinlock = SPIN_LOCK_UNLOCKED;
50
51 void pi_write_regr(PIA * pi, int cont, int regr, int val)
52 {
53         pi->proto->write_regr(pi, cont, regr, val);
54 }
55
56 EXPORT_SYMBOL(pi_write_regr);
57
58 int pi_read_regr(PIA * pi, int cont, int regr)
59 {
60         return pi->proto->read_regr(pi, cont, regr);
61 }
62
63 EXPORT_SYMBOL(pi_read_regr);
64
65 void pi_write_block(PIA * pi, char *buf, int count)
66 {
67         pi->proto->write_block(pi, buf, count);
68 }
69
70 EXPORT_SYMBOL(pi_write_block);
71
72 void pi_read_block(PIA * pi, char *buf, int count)
73 {
74         pi->proto->read_block(pi, buf, count);
75 }
76
77 EXPORT_SYMBOL(pi_read_block);
78
79 #ifdef CONFIG_PARPORT
80
81 static void pi_wake_up(void *p)
82 {
83         PIA *pi = (PIA *) p;
84         unsigned long flags;
85         void (*cont) (void) = NULL;
86
87         spin_lock_irqsave(&pi_spinlock, flags);
88
89         if (pi->claim_cont && !parport_claim(pi->pardev)) {
90                 cont = pi->claim_cont;
91                 pi->claim_cont = NULL;
92                 pi->claimed = 1;
93         }
94
95         spin_unlock_irqrestore(&pi_spinlock, flags);
96
97         wake_up(&(pi->parq));
98
99         if (cont)
100                 cont();
101 }
102
103 #endif
104
105 int pi_schedule_claimed(PIA * pi, void (*cont) (void))
106 {
107 #ifdef CONFIG_PARPORT
108         unsigned long flags;
109
110         spin_lock_irqsave(&pi_spinlock, flags);
111         if (pi->pardev && parport_claim(pi->pardev)) {
112                 pi->claim_cont = cont;
113                 spin_unlock_irqrestore(&pi_spinlock, flags);
114                 return 0;
115         }
116         pi->claimed = 1;
117         spin_unlock_irqrestore(&pi_spinlock, flags);
118 #endif
119         return 1;
120 }
121 EXPORT_SYMBOL(pi_schedule_claimed);
122
123 void pi_do_claimed(PIA * pi, void (*cont) (void))
124 {
125         if (pi_schedule_claimed(pi, cont))
126                 cont();
127 }
128
129 EXPORT_SYMBOL(pi_do_claimed);
130
131 static void pi_claim(PIA * pi)
132 {
133         if (pi->claimed)
134                 return;
135         pi->claimed = 1;
136 #ifdef CONFIG_PARPORT
137         if (pi->pardev)
138                 wait_event(pi->parq,
139                            !parport_claim((struct pardevice *) pi->pardev));
140 #endif
141 }
142
143 void pi_unclaim(PIA * pi)
144 {
145         pi->claimed = 0;
146 #ifdef CONFIG_PARPORT
147         if (pi->pardev)
148                 parport_release((struct pardevice *) (pi->pardev));
149 #endif
150 }
151
152 EXPORT_SYMBOL(pi_unclaim);
153
154 void pi_connect(PIA * pi)
155 {
156         pi_claim(pi);
157         pi->proto->connect(pi);
158 }
159
160 EXPORT_SYMBOL(pi_connect);
161
162 void pi_disconnect(PIA * pi)
163 {
164         pi->proto->disconnect(pi);
165         pi_unclaim(pi);
166 }
167
168 EXPORT_SYMBOL(pi_disconnect);
169
170 static void pi_unregister_parport(PIA * pi)
171 {
172 #ifdef CONFIG_PARPORT
173         if (pi->pardev) {
174                 parport_unregister_device((struct pardevice *) (pi->pardev));
175                 pi->pardev = NULL;
176         }
177 #endif
178 }
179
180 void pi_release(PIA * pi)
181 {
182         pi_unregister_parport(pi);
183 #ifndef CONFIG_PARPORT
184         if (pi->reserved)
185                 release_region(pi->port, pi->reserved);
186 #endif                          /* !CONFIG_PARPORT */
187         if (pi->proto->release_proto)
188                 pi->proto->release_proto(pi);
189         module_put(pi->proto->owner);
190 }
191
192 EXPORT_SYMBOL(pi_release);
193
194 static int default_test_proto(PIA * pi, char *scratch, int verbose)
195 {
196         int j, k;
197         int e[2] = { 0, 0 };
198
199         pi->proto->connect(pi);
200
201         for (j = 0; j < 2; j++) {
202                 pi_write_regr(pi, 0, 6, 0xa0 + j * 0x10);
203                 for (k = 0; k < 256; k++) {
204                         pi_write_regr(pi, 0, 2, k ^ 0xaa);
205                         pi_write_regr(pi, 0, 3, k ^ 0x55);
206                         if (pi_read_regr(pi, 0, 2) != (k ^ 0xaa))
207                                 e[j]++;
208                 }
209         }
210         pi->proto->disconnect(pi);
211
212         if (verbose)
213                 printk("%s: %s: port 0x%x, mode  %d, test=(%d,%d)\n",
214                        pi->device, pi->proto->name, pi->port,
215                        pi->mode, e[0], e[1]);
216
217         return (e[0] && e[1]);  /* not here if both > 0 */
218 }
219
220 static int pi_test_proto(PIA * pi, char *scratch, int verbose)
221 {
222         int res;
223
224         pi_claim(pi);
225         if (pi->proto->test_proto)
226                 res = pi->proto->test_proto(pi, scratch, verbose);
227         else
228                 res = default_test_proto(pi, scratch, verbose);
229         pi_unclaim(pi);
230
231         return res;
232 }
233
234 int pi_register(PIP * pr)
235 {
236         int k;
237
238         for (k = 0; k < MAX_PROTOS; k++)
239                 if (protocols[k] && !strcmp(pr->name, protocols[k]->name)) {
240                         printk("paride: %s protocol already registered\n",
241                                pr->name);
242                         return 0;
243                 }
244         k = 0;
245         while ((k < MAX_PROTOS) && (protocols[k]))
246                 k++;
247         if (k == MAX_PROTOS) {
248                 printk("paride: protocol table full\n");
249                 return 0;
250         }
251         protocols[k] = pr;
252         pr->index = k;
253         printk("paride: %s registered as protocol %d\n", pr->name, k);
254         return 1;
255 }
256
257 EXPORT_SYMBOL(pi_register);
258
259 void pi_unregister(PIP * pr)
260 {
261         if (!pr)
262                 return;
263         if (protocols[pr->index] != pr) {
264                 printk("paride: %s not registered\n", pr->name);
265                 return;
266         }
267         protocols[pr->index] = 0;
268 }
269
270 EXPORT_SYMBOL(pi_unregister);
271
272 static int pi_register_parport(PIA * pi, int verbose)
273 {
274 #ifdef CONFIG_PARPORT
275
276         struct parport *port;
277
278         port = parport_find_base(pi->port);
279         if (!port)
280                 return 0;
281
282         pi->pardev = parport_register_device(port,
283                                              pi->device, NULL,
284                                              pi_wake_up, NULL, 0, (void *) pi);
285         parport_put_port(port);
286         if (!pi->pardev)
287                 return 0;
288
289         init_waitqueue_head(&pi->parq);
290
291         if (verbose)
292                 printk("%s: 0x%x is %s\n", pi->device, pi->port, port->name);
293
294         pi->parname = (char *) port->name;
295 #endif
296
297         return 1;
298 }
299
300 static int pi_probe_mode(PIA * pi, int max, char *scratch, int verbose)
301 {
302         int best, range;
303
304         if (pi->mode != -1) {
305                 if (pi->mode >= max)
306                         return 0;
307                 range = 3;
308                 if (pi->mode >= pi->proto->epp_first)
309                         range = 8;
310                 if ((range == 8) && (pi->port % 8))
311                         return 0;
312                 pi->reserved = range;
313                 return (!pi_test_proto(pi, scratch, verbose));
314         }
315         best = -1;
316         for (pi->mode = 0; pi->mode < max; pi->mode++) {
317                 range = 3;
318                 if (pi->mode >= pi->proto->epp_first)
319                         range = 8;
320                 if ((range == 8) && (pi->port % 8))
321                         break;
322                 pi->reserved = range;
323                 if (!pi_test_proto(pi, scratch, verbose))
324                         best = pi->mode;
325         }
326         pi->mode = best;
327         return (best > -1);
328 }
329
330 static int pi_probe_unit(PIA * pi, int unit, char *scratch, int verbose)
331 {
332         int max, s, e;
333
334         s = unit;
335         e = s + 1;
336
337         if (s == -1) {
338                 s = 0;
339                 e = pi->proto->max_units;
340         }
341
342         if (!pi_register_parport(pi, verbose))
343                 return 0;
344
345         if (pi->proto->test_port) {
346                 pi_claim(pi);
347                 max = pi->proto->test_port(pi);
348                 pi_unclaim(pi);
349         } else
350                 max = pi->proto->max_mode;
351
352         if (pi->proto->probe_unit) {
353                 pi_claim(pi);
354                 for (pi->unit = s; pi->unit < e; pi->unit++)
355                         if (pi->proto->probe_unit(pi)) {
356                                 pi_unclaim(pi);
357                                 if (pi_probe_mode(pi, max, scratch, verbose))
358                                         return 1;
359                                 pi_unregister_parport(pi);
360                                 return 0;
361                         }
362                 pi_unclaim(pi);
363                 pi_unregister_parport(pi);
364                 return 0;
365         }
366
367         if (!pi_probe_mode(pi, max, scratch, verbose)) {
368                 pi_unregister_parport(pi);
369                 return 0;
370         }
371         return 1;
372
373 }
374
375 int pi_init(PIA * pi, int autoprobe, int port, int mode,
376         int unit, int protocol, int delay, char *scratch,
377         int devtype, int verbose, char *device)
378 {
379         int p, k, s, e;
380         int lpts[7] = { 0x3bc, 0x378, 0x278, 0x268, 0x27c, 0x26c, 0 };
381
382         s = protocol;
383         e = s + 1;
384
385         if (!protocols[0])
386                 request_module("paride_protocol");
387
388         if (autoprobe) {
389                 s = 0;
390                 e = MAX_PROTOS;
391         } else if ((s < 0) || (s >= MAX_PROTOS) || (port <= 0) ||
392                    (!protocols[s]) || (unit < 0) ||
393                    (unit >= protocols[s]->max_units)) {
394                 printk("%s: Invalid parameters\n", device);
395                 return 0;
396         }
397
398         for (p = s; p < e; p++) {
399                 struct pi_protocol *proto = protocols[p];
400                 if (!proto)
401                         continue;
402                 /* still racy */
403                 if (!try_module_get(proto->owner))
404                         continue;
405                 pi->proto = proto;
406                 pi->private = 0;
407                 if (proto->init_proto && proto->init_proto(pi) < 0) {
408                         pi->proto = NULL;
409                         module_put(proto->owner);
410                         continue;
411                 }
412                 if (delay == -1)
413                         pi->delay = pi->proto->default_delay;
414                 else
415                         pi->delay = delay;
416                 pi->devtype = devtype;
417                 pi->device = device;
418
419                 pi->parname = NULL;
420                 pi->pardev = NULL;
421                 init_waitqueue_head(&pi->parq);
422                 pi->claimed = 0;
423                 pi->claim_cont = NULL;
424
425                 pi->mode = mode;
426                 if (port != -1) {
427                         pi->port = port;
428                         if (pi_probe_unit(pi, unit, scratch, verbose))
429                                 break;
430                         pi->port = 0;
431                 } else {
432                         k = 0;
433                         while ((pi->port = lpts[k++]))
434                                 if (pi_probe_unit
435                                     (pi, unit, scratch, verbose))
436                                         break;
437                         if (pi->port)
438                                 break;
439                 }
440                 if (pi->proto->release_proto)
441                         pi->proto->release_proto(pi);
442                 module_put(proto->owner);
443         }
444
445         if (!pi->port) {
446                 if (autoprobe)
447                         printk("%s: Autoprobe failed\n", device);
448                 else
449                         printk("%s: Adapter not found\n", device);
450                 return 0;
451         }
452 #ifndef CONFIG_PARPORT
453         if (!request_region(pi->port, pi->reserved, pi->device)) {
454                 printk(KERN_WARNING "paride: Unable to request region 0x%x\n",
455                        pi->port);
456                 return 0;
457         }
458 #endif                          /* !CONFIG_PARPORT */
459
460         if (pi->parname)
461                 printk("%s: Sharing %s at 0x%x\n", pi->device,
462                        pi->parname, pi->port);
463
464         pi->proto->log_adapter(pi, scratch, verbose);
465
466         return 1;
467 }
468
469 EXPORT_SYMBOL(pi_init);