[haiku-commits] r38410 - haiku/trunk/src/add-ons/kernel/drivers/disk/usb/usb_floppy

  • From: pulkomandy@xxxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 28 Aug 2010 00:02:24 +0200 (CEST)

Author: pulkomandy
Date: 2010-08-28 00:02:24 +0200 (Sat, 28 Aug 2010)
New Revision: 38410
Changeset: http://dev.haiku-os.org/changeset/38410

Modified:
   haiku/trunk/src/add-ons/kernel/drivers/disk/usb/usb_floppy/usb_disk.cpp
Log:
Better error handling : do not enter an endless loop in cases of errors, but 
report them to the caller.
Note this leads to KDL if there is a write error, so it may not be the best way 
for a floppy...

This allows the driver to uninitialize properly when all devices are unplugged, 
which in turns permits updating the driver without rebooting to unload it.


Modified: 
haiku/trunk/src/add-ons/kernel/drivers/disk/usb/usb_floppy/usb_disk.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/disk/usb/usb_floppy/usb_disk.cpp     
2010-08-27 21:36:07 UTC (rev 38409)
+++ haiku/trunk/src/add-ons/kernel/drivers/disk/usb/usb_floppy/usb_disk.cpp     
2010-08-27 22:02:24 UTC (rev 38410)
@@ -40,7 +40,7 @@
 static char **gDeviceNames = NULL;
 
 static uint8 kDeviceIcon[] = {
-               0x6e, 0x63, 0x69, 0x66, 0x0c, 0x03, 0x01, 0x00, 0x00, 0x01, 
0x01, 0x00,
+       0x6e, 0x63, 0x69, 0x66, 0x0c, 0x03, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00,
        0x00, 0x6a, 0x02, 0x00, 0x16, 0x02, 0x38, 0x6a, 0xad, 0x38, 0xeb, 0x7a,
        0xbb, 0x77, 0x73, 0x3a, 0xde, 0x88, 0x48, 0xce, 0xdc, 0x4a, 0x75, 0xed,
        0x00, 0x8a, 0xff, 0x4b, 0x02, 0x00, 0x16, 0x02, 0x38, 0x6a, 0xad, 0x38,
@@ -195,11 +195,20 @@
 void
 usb_disk_interrupt(void* cookie, int32 status, void* data, uint32 length)
 {
-       if (length != 2)
-               TRACE_ALWAYS("interrupt of length %ld! (expected 2)\n", length);
        disk_device* dev = (disk_device*)cookie;
+       // We release the lock even if the interrupt is invalid. This way there
+       // is at least a chance for the driver to terminate properly.
        release_sem(dev->interruptLock);
 
+       if (length != 2) {
+               TRACE_ALWAYS("interrupt of length %ld! (expected 2)\n", length);
+               // In this case we do not reschedule the interrupt. This means 
the
+               // driver will be locked. The interrupt should perhaps be 
scheduled
+               // when starting a transfer instead. But getting there means 
something
+               // is really broken, so...
+               return;
+       }
+
        // Reschedule the interrupt for next time
        gUSBModule->queue_interrupt(dev->interrupt, dev->interruptBuffer, 2,
                usb_disk_interrupt, cookie);
@@ -245,9 +254,9 @@
 
                // There was an error, we have to do a request sense to reset 
the device
                if (operation[0] != SCSI_REQUEST_SENSE_6) {
-                       result = usb_disk_request_sense(lun);
+                       usb_disk_request_sense(lun);
                }
-               return B_ERROR;
+               return result;
        }
 
        // Step 2 : data phase : send or receive data
@@ -296,23 +305,6 @@
                result = usb_disk_request_sense(lun);
        }
        return result;
-       /*
-       switch (status.status) {
-               case 0:
-                       TRACE("Command finished ! Everything ok !\n");
-                       return B_OK;
-               default:
-                       TRACE("Interrupt returned non-zero code : %x/%x\n", 
status.status,
-                               status.misc);
-                       // Maybe we should pass the code to the caller ? But we 
can't handle
-                       // everything as errors at this level, for example test 
unit ready
-                       // will return a "not ready code if there is no disk, 
but this is
-                       // not an operation error.
-                       // The code is also available as data by sending a 
status request to
-                       // the drive, anyway.
-                       return B_OK;
-       }
-       */
 }
 
 
@@ -333,9 +325,11 @@
        status_t result = usb_disk_operation(lun, commandBlock, NULL,
                NULL, false);
 
-       while(result == B_DEV_NO_MEDIA) {
+       int retry = 100;
+       while(result == B_DEV_NO_MEDIA && retry > 0) {
                snooze(10000);
                result = usb_disk_request_sense(lun);
+               retry--;
        }
 
        if (result != B_OK)
@@ -525,16 +519,15 @@
        commandBlock[0] = SCSI_READ_CAPACITY_10;
        commandBlock[1] = lun->logical_unit_number << 5;
 
-       // Retry reading the capacity up to three times. The first try might 
only
-       // yield a unit attention telling us that the device or media status
-       // changed, which is more or less expected if it is the first operation
-       // on the device or the device only clears the unit atention for 
capacity
-       // reads.
-       do {
-               snooze(10000);
+       for (int tries = 0; tries < 5; tries++) {
                result = usb_disk_operation(lun, commandBlock, &parameter, 
&dataLength,
                        true);
-       } while (result != B_OK);
+               if (result == B_DEV_NO_MEDIA || result == B_TIMED_OUT
+                               || result == B_DEV_STALLED)
+                       snooze(10000);
+               else
+                       break;
+       }
 
        if (result != B_OK) {
                TRACE_ALWAYS("failed to update capacity\n");
@@ -829,12 +822,15 @@
        commandBlock[8] = blockCount >> 8;
        commandBlock[9] = blockCount;
 
-       status_t result;
-       do {
-               snooze(10000);
+       status_t result = B_OK;
+       for (int tries = 0; tries < 5; tries++) {
                result = usb_disk_operation(lun, commandBlock, buffer, length,
                        true);
-       } while (result != B_OK);
+               if (result == B_OK)
+                       break;
+               else
+                       snooze(10000);
+       }
        return result;
 }
 
@@ -858,19 +854,16 @@
        commandBlock[9] = blockCount;
 
        status_t result;
-       do {
+       result = usb_disk_operation(lun, commandBlock, buffer, length,
+               false);
+
+       int retry = 10;
+       while (result == B_DEV_NO_MEDIA && retry > 0) {
                snooze(10000);
-               result = usb_disk_operation(lun, commandBlock, buffer, length,
-                       false);
+               result = usb_disk_request_sense(lun);
+               retry--;
+       }
 
-               TRACE("write result : %s\n", strerror(result));
-
-               do {
-                       snooze(10000);
-                       result = usb_disk_request_sense(lun);
-               } while (result != B_OK);
-       } while (result != B_OK);
-
        if (result == B_OK)
                lun->should_sync = true;
        return result;


Other related posts:

  • » [haiku-commits] r38410 - haiku/trunk/src/add-ons/kernel/drivers/disk/usb/usb_floppy - pulkomandy