USBMassStorageClassBulkOnly.cpp [plain text]
#include "IOUSBMassStorageClass.h"
#include "IOUSBMassStorageClassTimestamps.h"
#include "Debugging.h"
enum
{
kBulkOnlyCommandSent = 1,
kBulkOnlyCheckCBWBulkStall,
kBulkOnlyClearCBWBulkStall,
kBulkOnlyBulkIOComplete,
kBulkOnlyCheckBulkStall,
kBulkOnlyClearBulkStall,
kBulkOnlyCheckBulkStallPostCSW,
kBulkOnlyClearBulkStallPostCSW,
kBulkOnlyStatusReceived,
kBulkOnlyStatusReceived2ndTime,
kBulkOnlyResetCompleted,
kBulkOnlyClearBulkInCompleted,
kBulkOnlyClearBulkOutCompleted
};
#pragma mark -
#pragma mark Protocol Services Methods
#pragma mark -
IOReturn IOUSBMassStorageClass::AbortSCSICommandForBulkOnlyProtocol (
SCSITaskIdentifier request )
{
UNUSED ( request );
return kIOReturnError;
}
IOReturn IOUSBMassStorageClass::SendSCSICommandForBulkOnlyProtocol (
SCSITaskIdentifier request )
{
IOReturn status;
BulkOnlyRequestBlock * theBulkOnlyRB;
theBulkOnlyRB = GetBulkOnlyRequestBlock();
bzero ( theBulkOnlyRB, sizeof ( BulkOnlyRequestBlock ) );
theBulkOnlyRB->request = request;
theBulkOnlyRB->boCompletion.target = this;
theBulkOnlyRB->boCompletion.action = &this->BulkOnlyUSBCompletionAction;
theBulkOnlyRB->boCompletion.parameter = theBulkOnlyRB;
STATUS_LOG ( ( 6, "%s[%p]: SendSCSICommandForBulkOnlyProtocol send CBW", getName(), this ) );
status = BulkOnlySendCBWPacket ( theBulkOnlyRB, kBulkOnlyCommandSent );
STATUS_LOG ( ( 5, "%s[%p]: SendSCSICommandForBulkOnlyProtocol send CBW returned %x", getName(), this, status ) );
return status;
}
#pragma mark -
#pragma mark Bulk Only Protocol Specific Commands
IOReturn
IOUSBMassStorageClass::BulkDeviceResetDevice (
BulkOnlyRequestBlock * boRequestBlock,
UInt32 nextExecutionState )
{
IOReturn status = kIOReturnDeviceError;
if ( fTerminating == true )
{
goto Exit;
}
if ( ( fUseUSBResetNotBOReset == true ) || ( fConsecutiveResetCount > 0 ) )
{
STATUS_LOG ( ( 4, "%s[%p]: BulkDeviceResetDevice Escalating to DeviceReset", getName(), this, status ) );
(void) ResetDeviceNow ( false );
status = kIOReturnSuccess;
goto Exit;
}
bzero ( &fUSBDeviceRequest, sizeof ( IOUSBDevRequest ) );
fUSBDeviceRequest.bmRequestType = USBmakebmRequestType ( kUSBNone, kUSBClass, kUSBInterface );
fUSBDeviceRequest.bRequest = 0xFF;
fUSBDeviceRequest.wValue = 0;
fUSBDeviceRequest.wIndex = GetInterfaceReference()->GetInterfaceNumber();
fUSBDeviceRequest.wLength = 0;
fUSBDeviceRequest.pData = NULL;
boRequestBlock->currentState = nextExecutionState;
status = GetInterfaceReference()->DeviceRequest ( &fUSBDeviceRequest, &boRequestBlock->boCompletion );
Exit:
STATUS_LOG ( ( 4, "%s[%p]: BulkDeviceResetDevice returned %x", getName(), this, status ) );
return status;
}
#pragma mark -
#pragma mark SendSCSICommand Helper methods
void
IOUSBMassStorageClass::BulkOnlyUSBCompletionAction (
void * target,
void * parameter,
IOReturn status,
UInt32 bufferSizeRemaining)
{
IOUSBMassStorageClass * theMSC;
BulkOnlyRequestBlock * boRequestBlock;
theMSC = ( IOUSBMassStorageClass * ) target;
boRequestBlock = ( BulkOnlyRequestBlock * ) parameter;
theMSC->BulkOnlyExecuteCommandCompletion ( boRequestBlock,
status,
bufferSizeRemaining );
}
IOReturn
IOUSBMassStorageClass::BulkOnlySendCBWPacket (
BulkOnlyRequestBlock * boRequestBlock,
UInt32 nextExecutionState )
{
IOReturn status = kIOReturnError;
require ( ( fBulkOnlyCBWMemoryDescriptor != NULL ), Exit );
boRequestBlock->boPhaseDesc = fBulkOnlyCBWMemoryDescriptor;
boRequestBlock->boCBW.cbwSignature = kCommandBlockWrapperSignature;
boRequestBlock->boCBW.cbwTag = GetNextBulkOnlyCommandTag();
boRequestBlock->boCBW.cbwTransferLength = HostToUSBLong(
GetRequestedDataTransferCount(boRequestBlock->request));
if (GetDataTransferDirection(boRequestBlock->request) ==
kSCSIDataTransfer_FromTargetToInitiator)
{
boRequestBlock->boCBW.cbwFlags = kCBWFlagsDataIn;
}
else if (GetDataTransferDirection(boRequestBlock->request) ==
kSCSIDataTransfer_FromInitiatorToTarget)
{
boRequestBlock->boCBW.cbwFlags = kCBWFlagsDataOut;
}
else
{
boRequestBlock->boCBW.cbwFlags = 0;
}
boRequestBlock->boCBW.cbwLUN = GetLogicalUnitNumber( boRequestBlock->request ) & kCBWLUNMask; boRequestBlock->boCBW.cbwCDBLength = GetCommandDescriptorBlockSize( boRequestBlock->request ); GetCommandDescriptorBlock( boRequestBlock->request, &boRequestBlock->boCBW.cbwCDB );
RecordUSBTimeStamp ( UMC_TRACE ( kBOCBWDescription ),
( uintptr_t ) this,
( uintptr_t ) boRequestBlock->request,
( unsigned int ) boRequestBlock->boCBW.cbwLUN,
( unsigned int ) boRequestBlock->boCBW.cbwTag );
boRequestBlock->currentState = nextExecutionState;
require ( ( fBulkOutPipe != NULL ), Exit );
STATUS_LOG ( ( 6, "%s[%p]: BulkOnlySendCBWPacket sent", getName(), this ) );
status = GetBulkOutPipe()->Write( boRequestBlock->boPhaseDesc,
GetTimeoutDuration( boRequestBlock->request ), GetTimeoutDuration( boRequestBlock->request ),
&boRequestBlock->boCompletion );
STATUS_LOG ( ( 5, "%s[%p]: BulkOnlySendCBWPacket returned %x", getName(), this, status ) );
RecordUSBTimeStamp ( UMC_TRACE ( kBOCBWBulkOutWriteResult ), ( uintptr_t ) this, status,
( uintptr_t ) boRequestBlock->boCBW.cbwLUN, ( uintptr_t ) boRequestBlock->request );
if ( status == kIOUSBPipeStalled )
{
STATUS_LOG ( ( 5, "%s[%p]: BulkOnlySendCBWPacket could not be queued, returned", getName(), this ) );
boRequestBlock->currentState = kBulkOnlyCheckCBWBulkStall;
status = GetStatusEndpointStatus ( GetBulkOutPipe(), &boRequestBlock->boGetStatusBuffer, &boRequestBlock->boCompletion );
}
Exit:
return status;
}
IOReturn
IOUSBMassStorageClass::BulkOnlyTransferData (
BulkOnlyRequestBlock * boRequestBlock,
UInt32 nextExecutionState )
{
IOReturn status = kIOReturnError;
boRequestBlock->currentState = nextExecutionState;
#ifndef EMBEDDED
requireMaxBusStall ( 10000 );
fRequiredMaxBusStall = 10000;
#endif // EMBEDDED
if ( GetDataTransferDirection ( boRequestBlock->request ) == kSCSIDataTransfer_FromTargetToInitiator )
{
status = GetBulkInPipe()->Read(
GetDataBuffer( boRequestBlock->request ),
GetTimeoutDuration( boRequestBlock->request ), GetTimeoutDuration( boRequestBlock->request ),
GetRequestedDataTransferCount( boRequestBlock->request ),
&boRequestBlock->boCompletion );
}
else if ( GetDataTransferDirection(boRequestBlock->request) == kSCSIDataTransfer_FromInitiatorToTarget )
{
status = GetBulkOutPipe()->Write(
GetDataBuffer ( boRequestBlock->request ),
GetTimeoutDuration ( boRequestBlock->request ), GetTimeoutDuration ( boRequestBlock->request ),
GetRequestedDataTransferCount ( boRequestBlock->request ),
&boRequestBlock->boCompletion );
}
#ifndef EMBEDDED
if ( status != kIOReturnSuccess )
{
requireMaxBusStall ( 0 );
fRequiredMaxBusStall = 0;
}
#endif
STATUS_LOG ( ( 5, "%s[%p]: BulkOnlyTransferData returned %x", getName(), this, status ) );
return status;
}
IOReturn
IOUSBMassStorageClass::BulkOnlyReceiveCSWPacket (
BulkOnlyRequestBlock * boRequestBlock,
UInt32 nextExecutionState )
{
IOReturn status = kIOReturnError;
require ( ( fBulkOnlyCSWMemoryDescriptor != NULL ), Exit );
boRequestBlock->boPhaseDesc = fBulkOnlyCSWMemoryDescriptor;
boRequestBlock->currentState = nextExecutionState;
status = GetBulkInPipe()->Read ( boRequestBlock->boPhaseDesc,
GetTimeoutDuration( boRequestBlock->request ), GetTimeoutDuration( boRequestBlock->request ),
&boRequestBlock->boCompletion );
STATUS_LOG ( ( 5, "%s[%p]: BulkOnlyReceiveCSWPacket returned %x", getName(), this, status ) );
Exit:
return status;
}
void
IOUSBMassStorageClass::BulkOnlyExecuteCommandCompletion (
BulkOnlyRequestBlock * boRequestBlock,
IOReturn resultingStatus,
UInt32 bufferSizeRemaining)
{
IOReturn status = kIOReturnError;
bool commandInProgress = false;
bool abortCommand = false;
STATUS_LOG ( ( 4, "%s[%p]: BulkOnlyExecuteCommandCompletion Entered with boRequestBlock=%p currentState=%d resultingStatus=0x%x", getName(), this, boRequestBlock, boRequestBlock->currentState, resultingStatus ) );
#ifndef EMBEDDED
if ( reserved == NULL )
{
PANIC_NOW ( ( "IOUSBMassStorageClass::BulkOnlyExecuteCommandCompletion callback after driver has been freed" ) );
return;
}
if ( fRequiredMaxBusStall != 0 )
{
requireMaxBusStall ( 0 );
fRequiredMaxBusStall = 0;
}
#endif // EMBEDDED
if ( ( boRequestBlock->request == NULL ) || ( fBulkOnlyCommandStructInUse == false ) )
{
STATUS_LOG ( ( 4, "%s[%p]: boRequestBlock->request is NULL, returned %x", getName(), this, resultingStatus ) );
RecordUSBTimeStamp ( UMC_TRACE ( kBODoubleCompleteion ), ( uintptr_t ) this, NULL, NULL, NULL );
return;
}
if ( ( GetInterfaceReference() == NULL ) || ( fTerminating == true ) )
{
STATUS_LOG ( ( 4, "%s[%p]: Completion during termination", getName(), this ) );
RecordUSBTimeStamp ( UMC_TRACE ( kBOCompletionDuringTermination ), ( uintptr_t ) this, NULL, NULL, NULL );
goto Exit;
}
RecordUSBTimeStamp ( UMC_TRACE ( kBOCompletion ), ( uintptr_t ) this, resultingStatus,
( uintptr_t ) boRequestBlock->currentState, ( uintptr_t ) boRequestBlock->request );
if ( ( resultingStatus == kIOReturnNotResponding ) || ( resultingStatus == kIOReturnAborted ) )
{
STATUS_LOG ( ( 5, "%s[%p]: BulkOnlyExecuteCommandCompletion previous command returned %x", getName(), this, resultingStatus ) );
(void) ResetDeviceNow ( false );
commandInProgress = true;
goto Exit;
}
switch ( boRequestBlock->currentState )
{
case kBulkOnlyCommandSent:
{
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyCommandSent returned %x cbwTag=0x%08x", getName(), this, resultingStatus, boRequestBlock->boCBW.cbwTag ) );
if ( resultingStatus == kIOUSBPipeStalled )
{
if ( fUseUSBResetNotBOReset )
{
(void) ResetDeviceNow ( false );
status = kIOReturnSuccess;
}
else
{
boRequestBlock->currentState = kBulkOnlyCheckCBWBulkStall;
status = GetStatusEndpointStatus( GetBulkOutPipe(), &boRequestBlock->boGetStatusBuffer, &boRequestBlock->boCompletion );
}
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
break;
}
if ( resultingStatus != kIOReturnSuccess )
{
(void) ResetDeviceNow ( false );
status = kIOReturnSuccess;
if( status == kIOReturnSuccess )
{
commandInProgress = true;
}
break;
}
if ( ( GetDataTransferDirection ( boRequestBlock->request ) == kSCSIDataTransfer_NoDataTransfer ) ||
( GetRequestedDataTransferCount ( boRequestBlock->request ) == 0 ) )
{
status = BulkOnlyReceiveCSWPacket ( boRequestBlock, kBulkOnlyStatusReceived );
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
else
{
status = BulkOnlyTransferData ( boRequestBlock, kBulkOnlyBulkIOComplete );
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
}
break;
case kBulkOnlyCheckCBWBulkStall:
{
STATUS_LOG ( ( 5, "%s[%p]: IOUSBMassStorageClass::BulkOnlyExecuteCommandCompletion - kBulkOnlyCheckCBWBulkStall returned %x stalled=0x%x", getName(), this, resultingStatus, boRequestBlock->boGetStatusBuffer[0] ) );
if ( ( boRequestBlock->boGetStatusBuffer[0] & 1 ) == 1 )
{
STATUS_LOG ( ( 5, "%s[%p]: IOUSBMassStorageClass::BulkOnlyExecuteCommandCompletion - will try to clear endpoint", getName(), this ) );
boRequestBlock->currentState = kBulkOnlyClearCBWBulkStall;
status = ClearFeatureEndpointStall ( GetBulkOutPipe(), &boRequestBlock->boCompletion );
STATUS_LOG ( ( 5, "%s[%p]: IOUSBMassStorageClass::BulkOnlyExecuteCommandCompletion - ClearFeatureEndpointStall returned status = %x", getName(), this, status ) );
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
else
{
STATUS_LOG ( ( 5, "%s[%p]: IOUSBMassStorageClass::BulkOnlyExecuteCommandCompletion - will reset", getName(), this ) );
SetRealizedDataTransferCount ( boRequestBlock->request, 0 );
status = BulkDeviceResetDevice( boRequestBlock, kBulkOnlyResetCompleted );
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
}
break;
case kBulkOnlyClearCBWBulkStall:
{
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyClearCBWBulkStall returned %x", getName(), this, resultingStatus ) );
SetRealizedDataTransferCount ( boRequestBlock->request, 0 );
status = kIOReturnError;
}
break;
case kBulkOnlyBulkIOComplete:
{
status = resultingStatus;
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyBulkIOComplete returned %x", getName(), this, resultingStatus ) );
if ( ( resultingStatus == kIOUSBPipeStalled ) || ( resultingStatus == kIOReturnSuccess ) )
{
UInt64 realizedDataTransferCount = GetRequestedDataTransferCount ( boRequestBlock->request ) - bufferSizeRemaining;
SetRealizedDataTransferCount ( boRequestBlock->request, realizedDataTransferCount );
STATUS_LOG ( ( 5, "%s[%p]: bufferSizeRemaining=0x%x realizedDataTransferCount=0x%x", getName(), this, bufferSizeRemaining, realizedDataTransferCount ) );
}
if ( resultingStatus == kIOReturnSuccess )
{
status = BulkOnlyReceiveCSWPacket ( boRequestBlock, kBulkOnlyStatusReceived );
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
else if ( resultingStatus == kIOReturnOverrun )
{
SetRealizedDataTransferCount ( boRequestBlock->request,
GetRequestedDataTransferCount ( boRequestBlock->request ) );
(void) ResetDeviceNow ( false );
commandInProgress = true;
}
else
{
if ( ( resultingStatus == kIOReturnDeviceError )
|| ( resultingStatus == kIOUSBHighSpeedSplitError ) )
{
(void) ResetDeviceNow ( false );
status = kIOReturnSuccess;
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
else if ( resultingStatus == kIOUSBTransactionTimeout )
{
status = BulkDeviceResetDevice( boRequestBlock, kBulkOnlyResetCompleted );
if( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
else
{
if ( GetDataTransferDirection ( boRequestBlock->request ) == kSCSIDataTransfer_FromTargetToInitiator )
{
fPotentiallyStalledPipe = GetBulkInPipe();
}
else if ( GetDataTransferDirection ( boRequestBlock->request ) == kSCSIDataTransfer_FromInitiatorToTarget )
{
fPotentiallyStalledPipe = GetBulkOutPipe();
}
else
{
fPotentiallyStalledPipe = GetControlPipe();
}
boRequestBlock->currentState = kBulkOnlyCheckBulkStall;
STATUS_LOG ( ( 5, "%s[%p]: Checking status for endpoint %d", getName(), this, fPotentiallyStalledPipe ? fPotentiallyStalledPipe->GetEndpointNumber() : -1 ) );
status = GetStatusEndpointStatus ( fPotentiallyStalledPipe, &boRequestBlock->boGetStatusBuffer, &boRequestBlock->boCompletion );
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
}
}
break;
case kBulkOnlyCheckBulkStall:
case kBulkOnlyCheckBulkStallPostCSW:
{
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyCheckBulkStall returned %x stalled %x for endpoint %d", getName(), this, resultingStatus, boRequestBlock->boGetStatusBuffer[0], fPotentiallyStalledPipe ? fPotentiallyStalledPipe->GetEndpointNumber() : -1 ) );
if ( ( boRequestBlock->boGetStatusBuffer[0] & 1 ) == 1 )
{
if ( boRequestBlock->currentState == kBulkOnlyCheckBulkStall )
{
boRequestBlock->currentState = kBulkOnlyClearBulkStall;
}
else
{
boRequestBlock->currentState = kBulkOnlyClearBulkStallPostCSW;
}
status = ClearFeatureEndpointStall ( fPotentiallyStalledPipe, &boRequestBlock->boCompletion );
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
else
{
status = BulkDeviceResetDevice( boRequestBlock, kBulkOnlyResetCompleted );
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
}
break;
case kBulkOnlyClearBulkStall:
case kBulkOnlyClearBulkStallPostCSW:
{
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyClearBulkStall returned %x", getName(), this, resultingStatus ) );
if ( boRequestBlock->currentState == kBulkOnlyClearBulkStall )
{
status = BulkOnlyReceiveCSWPacket( boRequestBlock, kBulkOnlyStatusReceived );
}
else
{
status = BulkOnlyReceiveCSWPacket( boRequestBlock, kBulkOnlyStatusReceived2ndTime );
}
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
break;
case kBulkOnlyStatusReceived:
{
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyStatusReceived returned %x cswTag=0x%08x", getName(), this, resultingStatus, boRequestBlock->boCSW.cswTag ) );
if ( resultingStatus == kIOUSBPipeStalled)
{
boRequestBlock->currentState = kBulkOnlyCheckBulkStallPostCSW;
status = GetStatusEndpointStatus ( GetBulkInPipe(), &boRequestBlock->boGetStatusBuffer, &boRequestBlock->boCompletion );
if ( status == kIOReturnSuccess )
{
fPotentiallyStalledPipe = GetBulkInPipe();
commandInProgress = true;
}
}
else if ( resultingStatus != kIOReturnSuccess)
{
status = BulkOnlyReceiveCSWPacket ( boRequestBlock, kBulkOnlyStatusReceived2ndTime );
if ( status != kIOReturnSuccess )
{
status = BulkDeviceResetDevice( boRequestBlock, kBulkOnlyResetCompleted );
}
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
else if ( ( boRequestBlock->boCSW.cswTag == boRequestBlock->boCBW.cbwTag ) || fKnownCSWTagMismatchIssues )
{
switch( boRequestBlock->boCSW.cswStatus )
{
case kCSWCommandPassedError:
{
status = kIOReturnSuccess;
}
break;
case kCSWCommandFailedError:
{
STATUS_LOG ( ( 4, "%s[%p]: kBulkOnlyStatusReceived kCSWCommandFailedError", getName(), this ) );
status = kIOReturnError;
}
break;
case kCSWPhaseError:
{
STATUS_LOG ( ( 4, "%s[%p]: kBulkOnlyStatusReceived kCSWPhaseError", getName(), this ) );
status = BulkDeviceResetDevice( boRequestBlock, kBulkOnlyResetCompleted );
if( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
break;
default:
{
STATUS_LOG ( ( 4, "%s[%p]: kBulkOnlyStatusReceived default", getName(), this ) );
status = kIOReturnError;
}
break;
}
}
else
{
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyStatusReceived tag mismatch", getName(), this ) );
status = kIOReturnError;
}
}
break;
case kBulkOnlyStatusReceived2ndTime:
{
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyStatusReceived2ndTime returned %x", getName(), this, resultingStatus ) );
if ( resultingStatus != kIOReturnSuccess)
{
status = BulkDeviceResetDevice( boRequestBlock, kBulkOnlyResetCompleted );
}
else
{
boRequestBlock->currentState = kBulkOnlyStatusReceived;
BulkOnlyExecuteCommandCompletion( boRequestBlock,
resultingStatus,
bufferSizeRemaining );
status = kIOReturnSuccess;
}
if( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
break;
case kBulkOnlyResetCompleted:
{
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyResetCompleted returned %x", getName(), this, resultingStatus ) );
if ( resultingStatus != kIOReturnSuccess)
{
(void) ResetDeviceNow ( false );
commandInProgress = true;
break;
}
boRequestBlock->currentState = kBulkOnlyClearBulkInCompleted;
status = ClearFeatureEndpointStall ( GetBulkInPipe(), &boRequestBlock->boCompletion );
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
break;
case kBulkOnlyClearBulkInCompleted:
{
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyClearBulkInCompleted returned %x", getName(), this, resultingStatus ) );
boRequestBlock->currentState = kBulkOnlyClearBulkOutCompleted;
status = ClearFeatureEndpointStall ( GetBulkOutPipe(), &boRequestBlock->boCompletion );
if ( status == kIOReturnSuccess )
{
commandInProgress = true;
}
}
break;
case kBulkOnlyClearBulkOutCompleted:
{
STATUS_LOG ( ( 5, "%s[%p]: kBulkOnlyClearBulkOutCompleted returned %x", getName(), this, resultingStatus ) );
SetRealizedDataTransferCount ( boRequestBlock->request, 0 );
abortCommand = true;
}
break;
default:
{
SetRealizedDataTransferCount ( boRequestBlock->request, 0 );
status = kIOReturnError;
}
break;
}
Exit:
if ( commandInProgress == false )
{
if ( abortCommand == true )
{
AbortCurrentSCSITask ( );
}
else
{
SCSITaskIdentifier request = boRequestBlock->request;
ReleaseBulkOnlyRequestBlock ( boRequestBlock );
CompleteSCSICommand ( request, status );
}
}
STATUS_LOG ( ( 5, "%s[%p]: BulkOnlyExecuteCommandCompletion Returning with currentState=%d", getName(), this, boRequestBlock->currentState ) );
}