OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [parport/] [daisy.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * IEEE 1284.3 Parallel port daisy chain and multiplexor code
3
 *
4
 * Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version
9
 * 2 of the License, or (at your option) any later version.
10
 *
11
 * ??-12-1998: Initial implementation.
12
 * 31-01-1999: Make port-cloning transparent.
13
 * 13-02-1999: Move DeviceID technique from parport_probe.
14
 * 13-03-1999: Get DeviceID from non-IEEE 1284.3 devices too.
15
 * 22-02-2000: Count devices that are actually detected.
16
 *
17
 * Any part of this program may be used in documents licensed under
18
 * the GNU Free Documentation License, Version 1.1 or any later version
19
 * published by the Free Software Foundation.
20
 */
21
 
22
#include <linux/parport.h>
23
#include <linux/delay.h>
24
#include <asm/uaccess.h>
25
 
26
#undef DEBUG /* undef me for production */
27
 
28
#ifdef DEBUG
29
#define DPRINTK(stuff...) printk (stuff)
30
#else
31
#define DPRINTK(stuff...)
32
#endif
33
 
34
static struct daisydev {
35
        struct daisydev *next;
36
        struct parport *port;
37
        int daisy;
38
        int devnum;
39
} *topology = NULL;
40
 
41
static int numdevs = 0;
42
 
43
/* Forward-declaration of lower-level functions. */
44
static int mux_present (struct parport *port);
45
static int num_mux_ports (struct parport *port);
46
static int select_port (struct parport *port);
47
static int assign_addrs (struct parport *port);
48
 
49
/* Add a device to the discovered topology. */
50
static void add_dev (int devnum, struct parport *port, int daisy)
51
{
52
        struct daisydev *newdev;
53
        newdev = kmalloc (sizeof (struct daisydev), GFP_KERNEL);
54
        if (newdev) {
55
                newdev->port = port;
56
                newdev->daisy = daisy;
57
                newdev->devnum = devnum;
58
                newdev->next = topology;
59
                if (!topology || topology->devnum >= devnum)
60
                        topology = newdev;
61
                else {
62
                        struct daisydev *prev = topology;
63
                        while (prev->next && prev->next->devnum < devnum)
64
                                prev = prev->next;
65
                        newdev->next = prev->next;
66
                        prev->next = newdev;
67
                }
68
        }
69
}
70
 
71
/* Clone a parport (actually, make an alias). */
72
static struct parport *clone_parport (struct parport *real, int muxport)
73
{
74
        struct parport *extra = parport_register_port (real->base,
75
                                                       real->irq,
76
                                                       real->dma,
77
                                                       real->ops);
78
        if (extra) {
79
                extra->portnum = real->portnum;
80
                extra->physport = real;
81
                extra->muxport = muxport;
82
        }
83
 
84
        return extra;
85
}
86
 
87
/* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains.
88
 * Return value is number of devices actually detected. */
89
int parport_daisy_init (struct parport *port)
90
{
91
        int detected = 0;
92
        char *deviceid;
93
        static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
94
        int num_ports;
95
        int i;
96
 
97
        /* Because this is called before any other devices exist,
98
         * we don't have to claim exclusive access.  */
99
 
100
        /* If mux present on normal port, need to create new
101
         * parports for each extra port. */
102
        if (port->muxport < 0 && mux_present (port) &&
103
            /* don't be fooled: a mux must have 2 or 4 ports. */
104
            ((num_ports = num_mux_ports (port)) == 2 || num_ports == 4)) {
105
                /* Leave original as port zero. */
106
                port->muxport = 0;
107
                printk (KERN_INFO
108
                        "%s: 1st (default) port of %d-way multiplexor\n",
109
                        port->name, num_ports);
110
                for (i = 1; i < num_ports; i++) {
111
                        /* Clone the port. */
112
                        struct parport *extra = clone_parport (port, i);
113
                        if (!extra) {
114
                                if (signal_pending (current))
115
                                        break;
116
 
117
                                schedule ();
118
                                continue;
119
                        }
120
 
121
                        printk (KERN_INFO
122
                                "%s: %d%s port of %d-way multiplexor on %s\n",
123
                                extra->name, i + 1, th[i + 1], num_ports,
124
                                port->name);
125
 
126
                        /* Analyse that port too.  We won't recurse
127
                           forever because of the 'port->muxport < 0'
128
                           test above. */
129
                        parport_announce_port (extra);
130
                }
131
        }
132
 
133
        if (port->muxport >= 0)
134
                select_port (port);
135
 
136
        parport_daisy_deselect_all (port);
137
        detected += assign_addrs (port);
138
 
139
        /* Count the potential legacy device at the end. */
140
        add_dev (numdevs++, port, -1);
141
 
142
        /* Find out the legacy device's IEEE 1284 device ID. */
143
        deviceid = kmalloc (1000, GFP_KERNEL);
144
        if (deviceid) {
145
                if (parport_device_id (numdevs - 1, deviceid, 1000) > 2)
146
                        detected++;
147
 
148
                kfree (deviceid);
149
        }
150
 
151
        return detected;
152
}
153
 
154
/* Forget about devices on a physical port. */
155
void parport_daisy_fini (struct parport *port)
156
{
157
        struct daisydev *dev, *prev = topology;
158
        while (prev && prev->port == port) {
159
                topology = topology->next;
160
                kfree (prev);
161
                prev = topology;
162
        }
163
 
164
        while (prev) {
165
                dev = prev->next;
166
                if (dev && dev->port == port) {
167
                        prev->next = dev->next;
168
                        kfree (dev);
169
                }
170
                prev = prev->next;
171
        }
172
 
173
        /* Gaps in the numbering could be handled better.  How should
174
           someone enumerate through all IEEE1284.3 devices in the
175
           topology?. */
176
        if (!topology) numdevs = 0;
177
        return;
178
}
179
 
180
/**
181
 *      parport_open - find a device by canonical device number
182
 *      @devnum: canonical device number
183
 *      @name: name to associate with the device
184
 *      @pf: preemption callback
185
 *      @kf: kick callback
186
 *      @irqf: interrupt handler
187
 *      @flags: registration flags
188
 *      @handle: driver data
189
 *
190
 *      This function is similar to parport_register_device(), except
191
 *      that it locates a device by its number rather than by the port
192
 *      it is attached to.  See parport_find_device() and
193
 *      parport_find_class().
194
 *
195
 *      All parameters except for @devnum are the same as for
196
 *      parport_register_device().  The return value is the same as
197
 *      for parport_register_device().
198
 **/
199
 
200
struct pardevice *parport_open (int devnum, const char *name,
201
                                int (*pf) (void *), void (*kf) (void *),
202
                                void (*irqf) (int, void *, struct pt_regs *),
203
                                int flags, void *handle)
204
{
205
        struct parport *port = parport_enumerate ();
206
        struct pardevice *dev;
207
        int portnum;
208
        int muxnum;
209
        int daisynum;
210
 
211
        if (parport_device_coords (devnum,  &portnum, &muxnum, &daisynum))
212
                return NULL;
213
 
214
        while (port && ((port->portnum != portnum) ||
215
                        (port->muxport != muxnum)))
216
                port = port->next;
217
 
218
        if (!port)
219
                /* No corresponding parport. */
220
                return NULL;
221
 
222
        dev = parport_register_device (port, name, pf, kf,
223
                                       irqf, flags, handle);
224
        if (dev)
225
                dev->daisy = daisynum;
226
 
227
        /* Check that there really is a device to select. */
228
        if (daisynum >= 0) {
229
                int selected;
230
                parport_claim_or_block (dev);
231
                selected = port->daisy;
232
                parport_release (dev);
233
 
234
                if (selected != port->daisy) {
235
                        /* No corresponding device. */
236
                        parport_unregister_device (dev);
237
                        return NULL;
238
                }
239
        }
240
 
241
        return dev;
242
}
243
 
244
/**
245
 *      parport_close - close a device opened with parport_open()
246
 *      @dev: device to close
247
 *
248
 *      This is to parport_open() as parport_unregister_device() is to
249
 *      parport_register_device().
250
 **/
251
 
252
void parport_close (struct pardevice *dev)
253
{
254
        parport_unregister_device (dev);
255
}
256
 
257
/**
258
 *      parport_device_num - convert device coordinates
259
 *      @parport: parallel port number
260
 *      @mux: multiplexor port number (-1 for no multiplexor)
261
 *      @daisy: daisy chain address (-1 for no daisy chain address)
262
 *
263
 *      This tries to locate a device on the given parallel port,
264
 *      multiplexor port and daisy chain address, and returns its
265
 *      device number or -NXIO if no device with those coordinates
266
 *      exists.
267
 **/
268
 
269
int parport_device_num (int parport, int mux, int daisy)
270
{
271
        struct daisydev *dev = topology;
272
 
273
        while (dev && dev->port->portnum != parport &&
274
               dev->port->muxport != mux && dev->daisy != daisy)
275
                dev = dev->next;
276
 
277
        if (!dev)
278
                return -ENXIO;
279
 
280
        return dev->devnum;
281
}
282
 
283
/**
284
 *      parport_device_coords - convert canonical device number
285
 *      @devnum: device number
286
 *      @parport: pointer to storage for parallel port number
287
 *      @mux: pointer to storage for multiplexor port number
288
 *      @daisy: pointer to storage for daisy chain address
289
 *
290
 *      This function converts a device number into its coordinates in
291
 *      terms of which parallel port in the system it is attached to,
292
 *      which multiplexor port it is attached to if there is a
293
 *      multiplexor on that port, and which daisy chain address it has
294
 *      if it is in a daisy chain.
295
 *
296
 *      The caller must allocate storage for @parport, @mux, and
297
 *      @daisy.
298
 *
299
 *      If there is no device with the specified device number, -ENXIO
300
 *      is returned.  Otherwise, the values pointed to by @parport,
301
 *      @mux, and @daisy are set to the coordinates of the device,
302
 *      with -1 for coordinates with no value.
303
 *
304
 *      This function is not actually very useful, but this interface
305
 *      was suggested by IEEE 1284.3.
306
 **/
307
 
308
int parport_device_coords (int devnum, int *parport, int *mux, int *daisy)
309
{
310
        struct daisydev *dev = topology;
311
 
312
        while (dev && dev->devnum != devnum)
313
                dev = dev->next;
314
 
315
        if (!dev)
316
                return -ENXIO;
317
 
318
        if (parport) *parport = dev->port->portnum;
319
        if (mux) *mux = dev->port->muxport;
320
        if (daisy) *daisy = dev->daisy;
321
        return 0;
322
}
323
 
324
/* Send a daisy-chain-style CPP command packet. */
325
static int cpp_daisy (struct parport *port, int cmd)
326
{
327
        unsigned char s;
328
 
329
        parport_data_forward (port);
330
        parport_write_data (port, 0xaa); udelay (2);
331
        parport_write_data (port, 0x55); udelay (2);
332
        parport_write_data (port, 0x00); udelay (2);
333
        parport_write_data (port, 0xff); udelay (2);
334
        s = parport_read_status (port) & (PARPORT_STATUS_BUSY
335
                                          | PARPORT_STATUS_PAPEROUT
336
                                          | PARPORT_STATUS_SELECT
337
                                          | PARPORT_STATUS_ERROR);
338
        if (s != (PARPORT_STATUS_BUSY
339
                  | PARPORT_STATUS_PAPEROUT
340
                  | PARPORT_STATUS_SELECT
341
                  | PARPORT_STATUS_ERROR)) {
342
                DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff(%02x)\n",
343
                         port->name, s);
344
                return -ENXIO;
345
        }
346
 
347
        parport_write_data (port, 0x87); udelay (2);
348
        s = parport_read_status (port) & (PARPORT_STATUS_BUSY
349
                                          | PARPORT_STATUS_PAPEROUT
350
                                          | PARPORT_STATUS_SELECT
351
                                          | PARPORT_STATUS_ERROR);
352
        if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
353
                DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff87(%02x)\n",
354
                         port->name, s);
355
                return -ENXIO;
356
        }
357
 
358
        parport_write_data (port, 0x78); udelay (2);
359
        parport_write_data (port, cmd); udelay (2);
360
        parport_frob_control (port,
361
                              PARPORT_CONTROL_STROBE,
362
                              PARPORT_CONTROL_STROBE);
363
        udelay (1);
364
        parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
365
        udelay (1);
366
        s = parport_read_status (port);
367
        parport_write_data (port, 0xff); udelay (2);
368
 
369
        return s;
370
}
371
 
372
/* Send a mux-style CPP command packet. */
373
static int cpp_mux (struct parport *port, int cmd)
374
{
375
        unsigned char s;
376
        int rc;
377
 
378
        parport_data_forward (port);
379
        parport_write_data (port, 0xaa); udelay (2);
380
        parport_write_data (port, 0x55); udelay (2);
381
        parport_write_data (port, 0xf0); udelay (2);
382
        parport_write_data (port, 0x0f); udelay (2);
383
        parport_write_data (port, 0x52); udelay (2);
384
        parport_write_data (port, 0xad); udelay (2);
385
        parport_write_data (port, cmd); udelay (2);
386
 
387
        s = parport_read_status (port);
388
        if (!(s & PARPORT_STATUS_ACK)) {
389
                DPRINTK (KERN_DEBUG "%s: cpp_mux: aa55f00f52ad%02x(%02x)\n",
390
                         port->name, cmd, s);
391
                return -EIO;
392
        }
393
 
394
        rc = (((s & PARPORT_STATUS_SELECT   ? 1 : 0) << 0) |
395
              ((s & PARPORT_STATUS_PAPEROUT ? 1 : 0) << 1) |
396
              ((s & PARPORT_STATUS_BUSY     ? 0 : 1) << 2) |
397
              ((s & PARPORT_STATUS_ERROR    ? 0 : 1) << 3));
398
 
399
        return rc;
400
}
401
 
402
void parport_daisy_deselect_all (struct parport *port)
403
{
404
        cpp_daisy (port, 0x30);
405
}
406
 
407
int parport_daisy_select (struct parport *port, int daisy, int mode)
408
{
409
        switch (mode)
410
        {
411
                // For these modes we should switch to EPP mode:
412
                case IEEE1284_MODE_EPP:
413
                case IEEE1284_MODE_EPPSL:
414
                case IEEE1284_MODE_EPPSWE:
415
                        return (cpp_daisy (port, 0x20 + daisy) &
416
                                PARPORT_STATUS_ERROR);
417
 
418
                // For these modes we should switch to ECP mode:
419
                case IEEE1284_MODE_ECP:
420
                case IEEE1284_MODE_ECPRLE:
421
                case IEEE1284_MODE_ECPSWE:
422
                        return (cpp_daisy (port, 0xd0 + daisy) &
423
                                PARPORT_STATUS_ERROR);
424
 
425
                // Nothing was told for BECP in Daisy chain specification.
426
                // May be it's wise to use ECP?
427
                case IEEE1284_MODE_BECP:
428
                // Others use compat mode
429
                case IEEE1284_MODE_NIBBLE:
430
                case IEEE1284_MODE_BYTE:
431
                case IEEE1284_MODE_COMPAT:
432
                default:
433
                        return (cpp_daisy (port, 0xe0 + daisy) &
434
                                PARPORT_STATUS_ERROR);
435
        }
436
}
437
 
438
static int mux_present (struct parport *port)
439
{
440
        return cpp_mux (port, 0x51) == 3;
441
}
442
 
443
static int num_mux_ports (struct parport *port)
444
{
445
        return cpp_mux (port, 0x58);
446
}
447
 
448
static int select_port (struct parport *port)
449
{
450
        int muxport = port->muxport;
451
        return cpp_mux (port, 0x60 + muxport) == muxport;
452
}
453
 
454
static int assign_addrs (struct parport *port)
455
{
456
        unsigned char s, last_dev;
457
        unsigned char daisy;
458
        int thisdev = numdevs;
459
        int detected;
460
        char *deviceid;
461
 
462
        parport_data_forward (port);
463
        parport_write_data (port, 0xaa); udelay (2);
464
        parport_write_data (port, 0x55); udelay (2);
465
        parport_write_data (port, 0x00); udelay (2);
466
        parport_write_data (port, 0xff); udelay (2);
467
        s = parport_read_status (port) & (PARPORT_STATUS_BUSY
468
                                          | PARPORT_STATUS_PAPEROUT
469
                                          | PARPORT_STATUS_SELECT
470
                                          | PARPORT_STATUS_ERROR);
471
        if (s != (PARPORT_STATUS_BUSY
472
                  | PARPORT_STATUS_PAPEROUT
473
                  | PARPORT_STATUS_SELECT
474
                  | PARPORT_STATUS_ERROR)) {
475
                DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff(%02x)\n",
476
                         port->name, s);
477
                return 0;
478
        }
479
 
480
        parport_write_data (port, 0x87); udelay (2);
481
        s = parport_read_status (port) & (PARPORT_STATUS_BUSY
482
                                          | PARPORT_STATUS_PAPEROUT
483
                                          | PARPORT_STATUS_SELECT
484
                                          | PARPORT_STATUS_ERROR);
485
        if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
486
                DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff87(%02x)\n",
487
                         port->name, s);
488
                return 0;
489
        }
490
 
491
        parport_write_data (port, 0x78); udelay (2);
492
        last_dev = 0; /* We've just been speaking to a device, so we
493
                         know there must be at least _one_ out there. */
494
 
495
        for (daisy = 0; daisy < 4; daisy++) {
496
                parport_write_data (port, daisy);
497
                udelay (2);
498
                parport_frob_control (port,
499
                                      PARPORT_CONTROL_STROBE,
500
                                      PARPORT_CONTROL_STROBE);
501
                udelay (1);
502
                parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
503
                udelay (1);
504
 
505
                if (last_dev)
506
                        /* No more devices. */
507
                        break;
508
 
509
                last_dev = !(parport_read_status (port)
510
                             & PARPORT_STATUS_BUSY);
511
 
512
                add_dev (numdevs++, port, daisy);
513
        }
514
 
515
        parport_write_data (port, 0xff); udelay (2);
516
        detected = numdevs - thisdev;
517
        DPRINTK (KERN_DEBUG "%s: Found %d daisy-chained devices\n", port->name,
518
                 detected);
519
 
520
        /* Ask the new devices to introduce themselves. */
521
        deviceid = kmalloc (1000, GFP_KERNEL);
522
        if (!deviceid) return 0;
523
 
524
        for (daisy = 0; thisdev < numdevs; thisdev++, daisy++)
525
                parport_device_id (thisdev, deviceid, 1000);
526
 
527
        kfree (deviceid);
528
        return detected;
529
}
530
 
531
/* Find a device with a particular manufacturer and model string,
532
   starting from a given device number.  Like the PCI equivalent,
533
   'from' itself is skipped. */
534
 
535
/**
536
 *      parport_find_device - find a specific device
537
 *      @mfg: required manufacturer string
538
 *      @mdl: required model string
539
 *      @from: previous device number found in search, or %NULL for
540
 *             new search
541
 *
542
 *      This walks through the list of parallel port devices looking
543
 *      for a device whose 'MFG' string matches @mfg and whose 'MDL'
544
 *      string matches @mdl in their IEEE 1284 Device ID.
545
 *
546
 *      When a device is found matching those requirements, its device
547
 *      number is returned; if there is no matching device, a negative
548
 *      value is returned.
549
 *
550
 *      A new search it initiated by passing %NULL as the @from
551
 *      argument.  If @from is not %NULL, the search continues from
552
 *      that device.
553
 **/
554
 
555
int parport_find_device (const char *mfg, const char *mdl, int from)
556
{
557
        struct daisydev *d = topology; /* sorted by devnum */
558
 
559
        /* Find where to start. */
560
        while (d && d->devnum <= from)
561
                d = d->next;
562
 
563
        /* Search. */
564
        while (d) {
565
                struct parport_device_info *info;
566
                info = &d->port->probe_info[1 + d->daisy];
567
                if ((!mfg || !strcmp (mfg, info->mfr)) &&
568
                    (!mdl || !strcmp (mdl, info->model)))
569
                        break;
570
 
571
                d = d->next;
572
        }
573
 
574
        if (d)
575
                return d->devnum;
576
 
577
        return -1;
578
}
579
 
580
/**
581
 *      parport_find_class - find a device in a specified class
582
 *      @cls: required class
583
 *      @from: previous device number found in search, or %NULL for
584
 *             new search
585
 *
586
 *      This walks through the list of parallel port devices looking
587
 *      for a device whose 'CLS' string matches @cls in their IEEE
588
 *      1284 Device ID.
589
 *
590
 *      When a device is found matching those requirements, its device
591
 *      number is returned; if there is no matching device, a negative
592
 *      value is returned.
593
 *
594
 *      A new search it initiated by passing %NULL as the @from
595
 *      argument.  If @from is not %NULL, the search continues from
596
 *      that device.
597
 **/
598
 
599
int parport_find_class (parport_device_class cls, int from)
600
{
601
        struct daisydev *d = topology; /* sorted by devnum */
602
 
603
        /* Find where to start. */
604
        while (d && d->devnum <= from)
605
                d = d->next;
606
 
607
        /* Search. */
608
        while (d && d->port->probe_info[1 + d->daisy].class != cls)
609
                d = d->next;
610
 
611
        if (d)
612
                return d->devnum;
613
 
614
        return -1;
615
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.