[PATCH] parport: daisy chain end detection fix
Marko Kohtala [Fri, 6 Jan 2006 08:19:45 +0000 (00:19 -0800)]
Daisy chain end detection failed at least with older daisy chain devices that
do not implement the last device signal.

Signed-off-by: Marko Kohtala <marko.kohtala@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

drivers/parport/daisy.c

index 075c7eb..6915114 100644 (file)
@@ -436,7 +436,7 @@ static int select_port (struct parport *port)
 
 static int assign_addrs (struct parport *port)
 {
-       unsigned char s, last_dev;
+       unsigned char s;
        unsigned char daisy;
        int thisdev = numdevs;
        int detected;
@@ -472,10 +472,13 @@ static int assign_addrs (struct parport *port)
        }
 
        parport_write_data (port, 0x78); udelay (2);
-       last_dev = 0; /* We've just been speaking to a device, so we
-                        know there must be at least _one_ out there. */
+       s = parport_read_status (port);
 
-       for (daisy = 0; daisy < 4; daisy++) {
+       for (daisy = 0;
+            (s & (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT))
+                    == (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT)
+                    && daisy < 4;
+            ++daisy) {
                parport_write_data (port, daisy);
                udelay (2);
                parport_frob_control (port,
@@ -485,14 +488,18 @@ static int assign_addrs (struct parport *port)
                parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
                udelay (1);
 
-               if (last_dev)
-                       /* No more devices. */
-                       break;
+               add_dev (numdevs++, port, daisy);
 
-               last_dev = !(parport_read_status (port)
-                            & PARPORT_STATUS_BUSY);
+               /* See if this device thought it was the last in the
+                * chain. */
+               if (!(s & PARPORT_STATUS_BUSY))
+                       break;
 
-               add_dev (numdevs++, port, daisy);
+               /* We are seeing pass through status now. We see
+                  last_dev from next device or if last_dev does not
+                  work status lines from some non-daisy chain
+                  device. */
+               s = parport_read_status (port);
        }
 
        parport_write_data (port, 0xff); udelay (2);