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