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. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38410 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -40,7 +40,7 @@ static mutex gDeviceListLock;
|
||||
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 @@ usb_disk_transfer_data(disk_device *device, bool directionIn, void *data,
|
||||
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 @@ usb_disk_operation(device_lun *lun, uint8* operation,
|
||||
|
||||
// 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 @@ usb_disk_operation(device_lun *lun, uint8* operation,
|
||||
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 @@ usb_disk_send_diagnostic(device_lun *lun)
|
||||
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 @@ usb_disk_update_capacity(device_lun *lun)
|
||||
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, ¶meter, &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 @@ usb_disk_block_read(device_lun *lun, uint32 blockPosition, uint16 blockCount,
|
||||
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,18 +854,15 @@ usb_disk_block_write(device_lun *lun, uint32 blockPosition, uint16 blockCount,
|
||||
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);
|
||||
|
||||
TRACE("write result : %s\n", strerror(result));
|
||||
|
||||
do {
|
||||
snooze(10000);
|
||||
result = usb_disk_request_sense(lun);
|
||||
} while (result != B_OK);
|
||||
} while (result != B_OK);
|
||||
result = usb_disk_request_sense(lun);
|
||||
retry--;
|
||||
}
|
||||
|
||||
if (result == B_OK)
|
||||
lun->should_sync = true;
|
||||
|
||||
Reference in New Issue
Block a user