IOUSBMassStorageUFISubclass.cpp [plain text]
#include "IOUSBMassStorageUFISubclass.h"
#include <IOKit/storage/IOBlockStorageDriver.h>
#include <IOKit/IOSyncer.h>
#include <IOKit/usb/IOUFIStorageServices.h>
#include <IOKit/scsi/SCSICmds_INQUIRY_Definitions.h>
#include <IOKit/scsi/SCSICommandOperationCodes.h>
#include <IOKit/scsi/SCSITask.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include "Debugging.h"
#define kKeySwitchProperty "Keyswitch"
#define kAppleKeySwitchProperty "AppleKeyswitch"
#define super IOSCSIPrimaryCommandsDevice
enum
{
kIOUSBMassStorageUFIDevicePowerStateSleep = 0,
kIOUSBMassStorageUFIDevicePowerStateActive = 1,
kIOUSBMassStorageUFIDeviceNumPowerStates = 2
};
static IOPMPowerState sPowerStates[kIOUSBMassStorageUFIDeviceNumPowerStates] =
{
{ kIOPMPowerStateVersion1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ kIOPMPowerStateVersion1, IOPMPowerOn, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}
};
IOOptionBits gRestartShutdownFlag = 0;
OSDefineMetaClassAndStructors( IOUSBMassStorageUFISubclass, IOUSBMassStorageClass )
#pragma mark -
#pragma mark *** IOUSBMassStorageUFIDevice declaration ***
#pragma mark -
OSDefineMetaClassAndStructors( IOUSBMassStorageUFIDevice, IOSCSIPrimaryCommandsDevice )
#pragma mark -
#pragma mark *** Static Class Methods ***
#pragma mark -
void
IOUSBMassStorageUFIDevice::sProcessPoll ( void * theUFIDriver, void * refCon )
{
UNUSED( refCon );
IOUSBMassStorageUFIDevice * driver;
driver = (IOUSBMassStorageUFIDevice *) theUFIDriver;
require_nonzero ( driver, ErrorExit );
if( driver->fPollingMode != kPollingMode_Suspended )
{
driver->ProcessPoll();
if( driver->fPollingMode != kPollingMode_Suspended )
{
driver->EnablePolling();
}
}
driver->release();
ErrorExit:
return;
}
void
IOUSBMassStorageUFIDevice::AsyncReadWriteComplete ( SCSITaskIdentifier request )
{
void * clientData;
IOReturn status;
UInt64 actCount = 0;
IOUSBMassStorageUFIDevice * taskOwner;
if ( request == NULL )
{
PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::AsyncReadWriteComplete request==NULL." ) );
}
taskOwner = OSDynamicCast ( IOUSBMassStorageUFIDevice, IOSCSIPrimaryCommandsDevice::sGetOwnerForTask ( request ) );
if ( taskOwner == NULL )
{
PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::AsyncReadWriteComplete taskOwner==NULL." ) );
}
clientData = taskOwner->GetApplicationLayerReference( request );
if ( ( taskOwner->GetServiceResponse( request ) == kSCSIServiceResponse_TASK_COMPLETE ) &&
( taskOwner->GetTaskStatus( request ) == kSCSITaskStatus_GOOD ) )
{
status = kIOReturnSuccess;
}
else
{
STATUS_LOG ( ( 4, "%s[%p]::Error on read/write", taskOwner->getName(), taskOwner ) );
status = kIOReturnError;
}
if ( status == kIOReturnSuccess )
{
actCount = taskOwner->GetDataBuffer( request )->getLength();
}
taskOwner->ReleaseSCSITask( request );
IOUFIStorageServices::AsyncReadWriteComplete( clientData, status, actCount );
}
#pragma mark -
#pragma mark *** Class Methods ***
#pragma mark -
bool
IOUSBMassStorageUFIDevice::InitializeDeviceSupport ( void )
{
bool setupSuccessful = false;
fMediumPresent = false;
fMediumIsWriteProtected = true;
STATUS_LOG ( ( 6, "%s[%p]::InitializeDeviceSupport called", getName(), this ) );
ClearNotReadyStatus();
fPollingMode = kPollingMode_NewMedia;
fIOUSBMassStorageUFIDeviceReserved = ( IOUSBMassStorageUFIDeviceExpansionData * )
IOMalloc ( sizeof ( IOUSBMassStorageUFIDeviceExpansionData ) );
require_nonzero ( fIOUSBMassStorageUFIDeviceReserved, ErrorExit );
require ( ( DetermineDeviceCharacteristics( ) == true ), ErrorExit );
fPollingThread = thread_call_allocate (
( thread_call_func_t ) IOUSBMassStorageUFIDevice::sProcessPoll,
( thread_call_param_t ) this );
require_nonzero ( fPollingThread, ErrorExit );
bzero ( fIOUSBMassStorageUFIDeviceReserved,
sizeof ( IOUSBMassStorageUFIDeviceExpansionData ) );
InitializePowerManagement ( GetProtocolDriver ( ) );
STATUS_LOG ( ( 5, "%s[%p]::InitializeDeviceSupport setupSuccessful = %d", getName(), this, setupSuccessful ) );
setupSuccessful = true;
ErrorExit:
if ( setupSuccessful == false )
{
TerminateDeviceSupport();
}
return setupSuccessful;
}
void
IOUSBMassStorageUFIDevice::StartDeviceSupport ( void )
{
OSBoolean * shouldNotPoll = NULL;
shouldNotPoll = OSDynamicCast ( OSBoolean,
getProperty ( kAppleKeySwitchProperty ) );
if ( shouldNotPoll != NULL )
{
require ( shouldNotPoll->isFalse ( ), Exit );
}
EnablePolling ( );
Exit:
CreateStorageServiceNub ( );
}
void
IOUSBMassStorageUFIDevice::SuspendDeviceSupport ( void )
{
if( fPollingMode != kPollingMode_Suspended )
{
DisablePolling();
}
}
void
IOUSBMassStorageUFIDevice::ResumeDeviceSupport ( void )
{
if( fMediumPresent == false )
{
fPollingMode = kPollingMode_NewMedia;
EnablePolling();
}
}
void
IOUSBMassStorageUFIDevice::StopDeviceSupport ( void )
{
}
void
IOUSBMassStorageUFIDevice::TerminateDeviceSupport ( void )
{
STATUS_LOG ( ( 6, "%s[%p]::cleanUp called.", getName(), this ) );
if ( fPollingThread != NULL )
{
thread_call_free ( fPollingThread );
fPollingThread = NULL;
}
if ( fIOUSBMassStorageUFIDeviceReserved != NULL)
{
IODelete ( fIOUSBMassStorageUFIDeviceReserved, IOUSBMassStorageUFIDeviceExpansionData, 1 );
fIOUSBMassStorageUFIDeviceReserved = NULL;
}
}
bool
IOUSBMassStorageUFIDevice::ClearNotReadyStatus( void )
{
SCSI_Sense_Data senseBuffer;
IOMemoryDescriptor * bufferDesc;
SCSITaskIdentifier request;
bool driveReady = false;
bool result = true;
SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
STATUS_LOG ( ( 6, "%s[%p]::%s called", getName(), this, __FUNCTION__ ) );
bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer,
kSenseDefaultSize,
kIODirectionIn );
request = GetSCSITask();
do
{
if ( TEST_UNIT_READY ( request ) == true )
{
serviceResponse = SendCommand ( request, 0 );
}
else
{
PANIC_NOW( ( "IOUSBMassStorageUFIDevice::ClearNotReadyStatus malformed command" ) );
}
if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
{
bool validSense = false;
if ( GetTaskStatus( request ) == kSCSITaskStatus_CHECK_CONDITION )
{
validSense = GetAutoSenseData( request, &senseBuffer );
if ( validSense == false )
{
if ( REQUEST_SENSE( request, bufferDesc, kSenseDefaultSize ) == true )
{
serviceResponse = SendCommand ( request, 0 );
}
else
{
PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::ClearNotReadyStatus malformed command" ) );
}
if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
{
validSense = true;
}
}
if ( validSense == true )
{
if ( ( ( senseBuffer.SENSE_KEY & kSENSE_KEY_Mask ) == kSENSE_KEY_NOT_READY ) &&
( senseBuffer.ADDITIONAL_SENSE_CODE == 0x04 ) &&
( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER == 0x01 ) )
{
STATUS_LOG ( ( 5, "%s[%p]::drive not ready", getName(), this ) );
driveReady = false;
IOSleep ( 200 );
}
else if ( ( ( senseBuffer.SENSE_KEY & kSENSE_KEY_Mask ) == kSENSE_KEY_NOT_READY ) &&
( senseBuffer.ADDITIONAL_SENSE_CODE == 0x04 ) &&
( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER == 0x02 ) )
{
if ( START_STOP_UNIT( request, 0x00, 0x00, 0x01 ) == true )
{
serviceResponse = SendCommand( request, 0 );
}
}
else
{
driveReady = true;
STATUS_LOG ( (5, "%s[%p]::drive READY", getName(), this ) );
}
STATUS_LOG ( ( 5, "%s[%p]:: sense data: %01x, %02x, %02x", getName(), this,
( senseBuffer.SENSE_KEY & kSENSE_KEY_Mask ),
senseBuffer.ADDITIONAL_SENSE_CODE,
senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER ) );
}
}
else
{
driveReady = true;
}
}
else
{
IOSleep( 200 );
}
} while( ( driveReady == false ) && ( isInactive() == false ) );
bufferDesc->release();
ReleaseSCSITask ( request );
result = isInactive() ? false : true;
return result;
}
void
IOUSBMassStorageUFIDevice::EnablePolling( void )
{
AbsoluteTime time;
if ( ( fPollingMode != kPollingMode_Suspended ) &&
fPollingThread &&
( isInactive() == false ) )
{
retain();
clock_interval_to_deadline( 1000, kMillisecondScale, &time );
if (thread_call_enter_delayed( fPollingThread, time ))
{
release();
}
}
}
void
IOUSBMassStorageUFIDevice::DisablePolling( void )
{
fPollingMode = kPollingMode_Suspended;
if( thread_call_cancel( fPollingThread ) )
{
release();
}
}
bool
IOUSBMassStorageUFIDevice::DetermineDeviceCharacteristics( void )
{
SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
SCSITaskIdentifier request = NULL;
IOMemoryDescriptor * bufferDesc = NULL;
SCSICmd_INQUIRY_StandardData * inquiryBuffer = NULL;
UInt8 inquiryBufferCount = sizeof ( SCSICmd_INQUIRY_StandardData );
bool succeeded = false;
int loopCount;
char tempString [ kINQUIRY_PRODUCT_IDENTIFICATION_Length + 1 ]; OSString * string;
STATUS_LOG ( ( 6, "%s[%p]::DetermineDeviceCharacteristics called", getName(), this ) );
inquiryBuffer = ( SCSICmd_INQUIRY_StandardData * ) IOMalloc ( inquiryBufferCount );
if( inquiryBuffer == NULL )
{
STATUS_LOG ( ( 1, "%s[%p]: Couldn't allocate Inquiry buffer.", getName(), this ) );
goto ErrorExit;
}
bufferDesc = IOMemoryDescriptor::withAddress ( inquiryBuffer, inquiryBufferCount, kIODirectionIn );
if ( bufferDesc == NULL )
{
STATUS_LOG ( ( 1, "%s[%p]: Couldn't alloc Inquiry buffer: ", getName(), this ) );
goto ErrorExit;
}
request = GetSCSITask();
if ( request == NULL )
{
goto ErrorExit;
}
if ( INQUIRY ( request,
bufferDesc,
0,
inquiryBufferCount ) == true )
{
serviceResponse = SendCommand ( request, 0 );
}
else
{
PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::DetermineDeviceCharacteristics malformed command" ) );
goto ErrorExit;
}
if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) ||
( GetTaskStatus ( request ) != kSCSITaskStatus_GOOD ) )
{
STATUS_LOG ( ( 2, "%s[%p]: Inquiry completed with an error: ", getName(), this ) );
goto ErrorExit;
}
for ( loopCount = 0; loopCount < kINQUIRY_VENDOR_IDENTIFICATION_Length; loopCount++ )
{
tempString[loopCount] = inquiryBuffer->VENDOR_IDENTIFICATION[loopCount];
}
tempString[loopCount] = 0;
for ( loopCount = kINQUIRY_VENDOR_IDENTIFICATION_Length - 1; loopCount >= 0; loopCount-- )
{
if ( tempString[loopCount] != ' ' )
{
tempString[loopCount+1] = '\0';
break;
}
}
string = OSString::withCString ( tempString );
if ( string != NULL )
{
fDeviceCharacteristicsDictionary->setObject ( kIOPropertyVendorNameKey, string );
string->release();
}
for ( loopCount = 0; loopCount < kINQUIRY_PRODUCT_IDENTIFICATION_Length; loopCount++ )
{
tempString[loopCount] = inquiryBuffer->PRODUCT_IDENTIFICATION[loopCount];
}
tempString[loopCount] = 0;
for ( loopCount = kINQUIRY_PRODUCT_IDENTIFICATION_Length - 1; loopCount >= 0; loopCount-- )
{
if ( tempString[loopCount] != ' ' )
{
tempString[loopCount+1] = '\0';
break;
}
}
string = OSString::withCString ( tempString );
if ( string != NULL )
{
fDeviceCharacteristicsDictionary->setObject ( kIOPropertyProductNameKey, string );
string->release();
}
for ( loopCount = 0; loopCount < kINQUIRY_PRODUCT_REVISION_LEVEL_Length; loopCount++ )
{
tempString[loopCount] = inquiryBuffer->PRODUCT_REVISION_LEVEL[loopCount];
}
tempString[loopCount] = 0;
for ( loopCount = kINQUIRY_PRODUCT_REVISION_LEVEL_Length - 1; loopCount >= 0; loopCount-- )
{
if ( tempString[loopCount] != ' ' )
{
tempString[loopCount+1] = '\0';
break;
}
}
string = OSString::withCString ( tempString );
if ( string != NULL )
{
fDeviceCharacteristicsDictionary->setObject ( kIOPropertyProductRevisionLevelKey, string );
string->release();
}
succeeded = true;
ErrorExit:
STATUS_LOG ( ( 6, "%s[%p]::DetermineDeviceCharacteristics exiting", getName(), this ) );
if ( request )
{
ReleaseSCSITask ( request );
request = NULL;
}
if ( bufferDesc )
{
bufferDesc->release();
bufferDesc = NULL;
}
if ( inquiryBuffer )
{
IOFree ( ( void * ) inquiryBuffer, inquiryBufferCount );
inquiryBuffer = NULL;
}
return succeeded;
}
void
IOUSBMassStorageUFIDevice::SetMediumCharacteristics( UInt32 blockSize, UInt32 blockCount )
{
STATUS_LOG ( ( 6, "%s[%p]::SetMediumCharacteristics called", getName(), this ) );
STATUS_LOG ( ( 5, "%s[%p]::mediumBlockSize = %ld, blockCount = %ld", getName(), this, blockSize, blockCount ) );
fMediumBlockSize = blockSize;
fMediumBlockCount = blockCount;
STATUS_LOG ( ( 6, "%s[%p]::SetMediumCharacteristics exiting", getName(), this ) );
}
void
IOUSBMassStorageUFIDevice::ResetMediumCharacteristics ( void )
{
STATUS_LOG ( ( 6, "%s[%p]::ResetMediumCharacteristics called", getName(), this ) );
fMediumBlockSize = 0;
fMediumBlockCount = 0;
fMediumPresent = false;
fMediumIsWriteProtected = true;
STATUS_LOG ( ( 6, "%s[%p]::ResetMediumCharacteristics exiting", getName(), this ) );
}
void
IOUSBMassStorageUFIDevice::CreateStorageServiceNub ( void )
{
STATUS_LOG ( ( 6, "%s[%p]::CreateStorageServiceNub entering.", getName(), this ) );
IOService * nub = OSTypeAlloc ( IOUFIStorageServices );
if ( nub == NULL )
{
STATUS_LOG ( ( 1, "%s[%p]::CreateStorageServiceNub failed", getName(), this ) );
PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::CreateStorageServiceNub failed" ) );
return;
}
nub->init();
if ( !nub->attach( this ) )
{
PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::CreateStorageServiceNub unable to attach nub" ) );
return;
}
nub->registerService(kIOServiceAsynchronous);
STATUS_LOG ( ( 6, "%s[%p]::CreateStorageServiceNub exiting.", getName(), this ) );
nub->release();
}
void
IOUSBMassStorageUFIDevice::ProcessPoll ( void )
{
switch ( fPollingMode )
{
case kPollingMode_NewMedia:
{
PollForNewMedia();
}
break;
case kPollingMode_MediaRemoval:
{
PollForMediaRemoval();
}
break;
default:
{
STATUS_LOG ( ( 1, "%s[%p]:ProcessPoll Unknown polling mode.", getName(), this ) );
}
break;
}
}
void
IOUSBMassStorageUFIDevice::PollForNewMedia( void )
{
bool mediaFound = false;
UInt64 blockCount;
UInt64 blockSize;
fMediumPresent = false;
mediaFound = DetermineMediaPresence();
if ( mediaFound == false )
{
return;
}
if ( DetermineMediumCapacity ( &blockSize, &blockCount ) == false )
{
return;
}
SetMediumCharacteristics ( blockSize, blockCount );
fMediumIsWriteProtected = DetermineMediumWriteProtectState();
fMediumPresent = true;
messageClients ( kIOMessageMediaStateHasChanged,
( void * ) kIOMediaStateOnline,
sizeof( IOMediaState ) );
fPollingMode = kPollingMode_MediaRemoval;
}
bool
IOUSBMassStorageUFIDevice::DetermineMediaPresence ( void )
{
SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
SCSITaskIdentifier request = NULL;
bool mediaFound = false;
OSBoolean * keySwitchLocked = NULL;
STATUS_LOG ( ( 6, "%s[%p]::DetermineMediaPresence called", getName(), this ) );
keySwitchLocked = OSDynamicCast ( OSBoolean, getProperty ( kAppleKeySwitchProperty ) );
if ( keySwitchLocked != NULL )
{
if ( keySwitchLocked->isTrue ( ) )
{
return false;
}
}
request = GetSCSITask();
if ( request == NULL )
{
return false;
}
if ( TEST_UNIT_READY ( request ) == true )
{
serviceResponse = SendCommand( request, 10 * 1000 );
}
else
{
STATUS_LOG ( ( 1, "%s[%p]::DetermineMediaPresence malformed command", getName(), this ) );
goto CheckDone;
}
if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
{
bool validSense;
SCSI_Sense_Data senseBuffer;
validSense = GetAutoSenseData ( request, &senseBuffer );
if ( validSense == false )
{
IOMemoryDescriptor * bufferDesc;
bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer,
kSenseDefaultSize,
kIODirectionIn );
if( bufferDesc == NULL )
{
STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) );
goto CheckDone;
}
if ( REQUEST_SENSE( request, bufferDesc, kSenseDefaultSize ) == true )
{
serviceResponse = SendCommand( request, 0 );
}
else
{
STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) );
bufferDesc->release();
goto CheckDone;
}
bufferDesc->release();
if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) ||
( GetTaskStatus ( request ) != kSCSITaskStatus_GOOD ) )
{
STATUS_LOG ( ( 2, "%s[%p]: REQUEST_SENSE failed", getName(), this ) );
goto CheckDone;
}
}
if ( ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x04 ) &&
( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER == 0x02 ) )
{
if ( START_STOP_UNIT( request, 0x00,0x00, 1 ) == true )
{
serviceResponse = SendCommand( request, 0 );
}
goto CheckDone;
}
else if ( ( senseBuffer.ADDITIONAL_SENSE_CODE != 0x00 ) ||
( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER != 0x00 ) )
{
STATUS_LOG ( ( 2, "%s[%p]:: ASC = 0x%02x, ASCQ = 0x%02x",
getName(),
this,
senseBuffer.ADDITIONAL_SENSE_CODE,
senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER ) );
goto CheckDone;
}
}
else
{
STATUS_LOG ( ( 2, "%s[%p]:: serviceResponse = %d", getName(), this, serviceResponse ) );
goto CheckDone;
}
UInt8 formatBuffer[12];
IOMemoryDescriptor * formatDesc;
formatDesc = IOMemoryDescriptor::withAddress ( ( void * ) &formatBuffer[0],
12,
kIODirectionIn );
if ( formatDesc == NULL )
{
STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) );
goto CheckDone;
}
if ( READ_FORMAT_CAPACITIES ( request, formatDesc, 12 ) == true )
{
serviceResponse = SendCommand( request, 0 );
}
else
{
STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) ) ;
formatDesc->release();
goto CheckDone;
}
formatDesc->release();
if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
{
if ( GetTaskStatus ( request ) == kSCSITaskStatus_CHECK_CONDITION )
{
bool validSense;
SCSI_Sense_Data senseBuffer;
validSense = GetAutoSenseData ( request, &senseBuffer );
if ( validSense == false )
{
IOMemoryDescriptor * bufferDesc;
bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer,
kSenseDefaultSize,
kIODirectionIn );
if( bufferDesc == NULL )
{
STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) );
goto CheckDone;
}
if ( REQUEST_SENSE ( request, bufferDesc, kSenseDefaultSize ) == true )
{
serviceResponse = SendCommand( request, 0 );
}
else
{
STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) );
bufferDesc->release();
goto CheckDone;
}
bufferDesc->release();
if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) ||
( GetTaskStatus( request ) != kSCSITaskStatus_GOOD ) )
{
STATUS_LOG ( ( 2, "%s[%p]: REQUEST_SENSE failed", getName(), this ) );
goto CheckDone;
}
}
if ( ( ( senseBuffer.SENSE_KEY & kSENSE_KEY_Mask ) == kSENSE_KEY_ILLEGAL_REQUEST )
&& ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x20 ) )
{
mediaFound = true;
goto CheckDone;
}
}
else if ( GetTaskStatus( request ) != kSCSITaskStatus_GOOD )
{
goto CheckDone;
}
}
else
{
STATUS_LOG ( ( 2, "%s[%p]:: serviceResponse = %d", getName(), this, serviceResponse ) );
goto CheckDone;
}
STATUS_LOG ( ( 4, "%s[%p]:: Formats data: ", getName(), this ) );
for ( int i = 0; i < 12; i ++ )
{
STATUS_LOG ( ( 4, "%s[%p]:: %X : ", getName(), this, formatBuffer[i] ) );
}
if ( formatBuffer[8] == 0x01 )
{
STATUS_LOG ( ( 4, "%s[%p]: unformatted media was found.", getName(), this ) );
goto CheckDone;
}
else if ( formatBuffer[8] != 0x02 )
{
STATUS_LOG ( ( 5, "%s[%p]: no media was found.", getName(), this ) );
goto CheckDone;
}
STATUS_LOG ( ( 5, "%s[%p]: media was found.", getName(), this ) );
mediaFound = true;
CheckDone:
if( request != NULL )
{
ReleaseSCSITask( request );
request = NULL;
}
return mediaFound;
}
bool
IOUSBMassStorageUFIDevice::DetermineMediumCapacity ( UInt64 * blockSize,
UInt64 * blockCount )
{
SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
UInt32 capacityData[2];
IOMemoryDescriptor * bufferDesc = NULL;
SCSITaskIdentifier request = NULL;
bool result;
*blockSize = 0;
*blockCount = 0;
request = GetSCSITask();
if ( request == NULL )
{
result = false;
goto IsDone;
}
bufferDesc = IOMemoryDescriptor::withAddress ( capacityData, 8, kIODirectionIn );
if ( bufferDesc == NULL )
{
result = false;
goto IsDone;
}
if ( READ_CAPACITY ( request, bufferDesc, 0, 0x00, 0 ) == true )
{
serviceResponse = SendCommand( request, 0 );
}
else
{
STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) );
result = false;
goto IsDone;
}
if ( ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) &&
( GetTaskStatus( request ) == kSCSITaskStatus_GOOD ) )
{
*blockSize = ( UInt64 ) OSSwapBigToHostInt32 ( capacityData[1] );
*blockCount = ( UInt64 ) ( OSSwapBigToHostInt32 ( capacityData[0] ) + 1 );
STATUS_LOG ( ( 4, "%s[%p]: Media capacity: %lx and block size: %lx",
getName(), this, ( UInt32 ) *blockCount, ( UInt32 ) *blockSize ) );
result = true;
}
else
{
STATUS_LOG ( ( 2, "%s[%p]: Read Capacity failed", getName(), this ) );
result = false;
}
IsDone:
if ( request != NULL )
{
ReleaseSCSITask ( request );
}
if ( bufferDesc != NULL )
{
bufferDesc->release();
}
return result;
}
bool
IOUSBMassStorageUFIDevice::DetermineMediumWriteProtectState( void )
{
SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
UInt8 modeBuffer[72];
IOMemoryDescriptor * bufferDesc = NULL;
SCSITaskIdentifier request = NULL;
bool mediumIsProtected = true;
STATUS_LOG ( ( 6, "%s[%p]::checkWriteProtection called", getName(), this ) );
request = GetSCSITask();
if ( request == NULL )
{
return true;
}
bufferDesc = IOMemoryDescriptor::withAddress ( modeBuffer,
72,
kIODirectionIn );
if ( bufferDesc == NULL )
{
goto WriteProtectCheckDone;
}
if ( MODE_SENSE_10 ( request,
bufferDesc,
0,
0,
0x3F,
72 ) == true )
{
serviceResponse = SendCommand ( request, 0 );
}
else
{
STATUS_LOG ( ( 1, "%s[%p]::CheckWriteProtection malformed command", getName(), this ) );
goto WriteProtectCheckDone;
}
if ( ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) &&
( GetTaskStatus( request ) == kSCSITaskStatus_GOOD ) )
{
if ( ( modeBuffer[3] & 0x80 ) != 0 )
{
mediumIsProtected = true;
}
else
{
mediumIsProtected = false;
}
}
WriteProtectCheckDone:
if ( bufferDesc != NULL )
{
bufferDesc->release();
bufferDesc = NULL;
}
if ( request != NULL )
{
ReleaseSCSITask ( request );
request = NULL;
}
return mediumIsProtected;
}
void
IOUSBMassStorageUFIDevice::PollForMediaRemoval ( void )
{
SCSIServiceResponse serviceResponse= kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
SCSITaskIdentifier request = NULL;
bool mediaRemoved = false;
if ( isInactive() == true )
{
fPollingMode = kPollingMode_Suspended;
}
request = GetSCSITask();
if ( request == NULL )
{
goto Exit;
}
if ( TEST_UNIT_READY ( request ) == true )
{
serviceResponse = SendCommand( request, 0 );
}
else
{
PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::PollForMediaRemoval malformed command" ) );
goto RemoveCheckDone;
}
if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
{
bool validSense;
SCSI_Sense_Data senseBuffer;
IOMemoryDescriptor * bufferDesc;
validSense = GetAutoSenseData ( request, &senseBuffer );
if( validSense == false )
{
bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer,
kSenseDefaultSize,
kIODirectionIn );
if ( bufferDesc == NULL )
{
STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) );
goto RemoveCheckDone;
}
if ( REQUEST_SENSE( request, bufferDesc, kSenseDefaultSize ) == true )
{
serviceResponse = SendCommand( request, 0 );
}
else
{
PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::PollForMediaRemoval malformed command" ) );
bufferDesc->release();
goto RemoveCheckDone;
}
bufferDesc->release();
if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) ||
( GetTaskStatus( request ) != kSCSITaskStatus_GOOD ) )
{
STATUS_LOG ( ( 2, "%s[%p]: REQUEST_SENSE failed", getName(), this ) );
goto RemoveCheckDone;
}
}
if ( ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x28 ) ||
( senseBuffer.ADDITIONAL_SENSE_CODE == 0x3A ) )
{
mediaRemoved = true;
}
}
RemoveCheckDone:
if ( request != NULL )
{
ReleaseSCSITask( request );
request = NULL;
}
if ( mediaRemoved == true )
{
fPollingMode = kPollingMode_NewMedia;
messageClients( kIOMessageMediaStateHasChanged,
( void * ) kIOMediaStateOffline );
}
Exit:
return;
}
#pragma mark -
#pragma mark *** Power Management ***
#pragma mark -
UInt32
IOUSBMassStorageUFIDevice::GetNumberOfPowerStateTransitions ( void )
{
return ( kIOUSBMassStorageUFIDeviceNumPowerStates - 1 );
}
void
IOUSBMassStorageUFIDevice::InitializePowerManagement (
IOService * provider )
{
fCurrentPowerState = kIOUSBMassStorageUFIDevicePowerStateActive;
fProposedPowerState = kIOUSBMassStorageUFIDevicePowerStateActive;
super::InitializePowerManagement ( provider );
registerPowerDriver ( this, sPowerStates, kIOUSBMassStorageUFIDeviceNumPowerStates );
changePowerStateTo ( kIOUSBMassStorageUFIDevicePowerStateActive );
}
UInt32
IOUSBMassStorageUFIDevice::GetInitialPowerState ( void )
{
return kIOUSBMassStorageUFIDevicePowerStateActive;
}
void
IOUSBMassStorageUFIDevice::HandleCheckPowerState ( void )
{
if ( IsDeviceAccessEnabled ( ) )
{
super::HandleCheckPowerState ( kIOUSBMassStorageUFIDevicePowerStateActive );
}
}
void
IOUSBMassStorageUFIDevice::TicklePowerManager ( void )
{
( void ) super::TicklePowerManager ( kIOUSBMassStorageUFIDevicePowerStateActive );
}
void
IOUSBMassStorageUFIDevice::HandlePowerChange ( void )
{
STATUS_LOG ( ( 5, "IOUSBMassStorageUFIDevice::HandlePowerChange called\n" ) );
if ( gRestartShutdownFlag != 0 )
{
if ( fProposedPowerState <= kIOUSBMassStorageUFIDevicePowerStateSleep )
{
fCurrentPowerState = fProposedPowerState;
}
}
if ( ( fProposedPowerState != fCurrentPowerState ) &&
( isInactive ( ) == false ) )
{
switch ( fProposedPowerState )
{
case kIOUSBMassStorageUFIDevicePowerStateSleep:
{
STATUS_LOG ( ( 5, "case kIOUSBMassStorageUFIDevicePowerStateSleep\n" ) );
DisablePolling();
fCurrentPowerState = kIOUSBMassStorageUFIDevicePowerStateSleep;
}
break;
case kIOUSBMassStorageUFIDevicePowerStateActive:
{
STATUS_LOG ( ( 5, "case kIOUSBMassStorageUFIDevicePowerStateActive\n" ) );
fCurrentPowerState = kIOUSBMassStorageUFIDevicePowerStateActive;
if (fMediumPresent == true)
{
fPollingMode = kPollingMode_MediaRemoval;
}
else
{
fPollingMode = kPollingMode_NewMedia;
}
EnablePolling();
}
break;
default:
{
PANIC_NOW ( ( "Undefined power state issued\n" ) );
}
break;
}
}
if ( isInactive ( ) )
{
fCurrentPowerState = fProposedPowerState;
}
}
#pragma mark -
#pragma mark *** Client Requests Support ***
#pragma mark -
IOReturn
IOUSBMassStorageUFIDevice::IssueRead ( IOMemoryDescriptor * buffer,
UInt64 startBlock,
UInt64 blockCount )
{
SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
SCSITaskIdentifier request;
STATUS_LOG ( ( 6, "%s[%p]: syncRead Attempted", getName(), this ) );
request = GetSCSITask ( );
if ( READ_10 ( request,
buffer,
fMediumBlockSize,
0,
0,
0,
( SCSICmdField4Byte ) startBlock,
( SCSICmdField2Byte ) blockCount ) == false )
{
serviceResponse = SendCommand( request, 0 );
}
else
{
PANIC_NOW(( "IOUSBMassStorageUFIDevice::IssueRead malformed command" ) );
}
ReleaseSCSITask ( request );
if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
{
return kIOReturnSuccess;
}
else
{
return kIOReturnError;
}
}
IOReturn
IOUSBMassStorageUFIDevice::IssueRead ( IOMemoryDescriptor * buffer,
UInt64 startBlock,
UInt64 blockCount,
void * clientData )
{
IOReturn status = kIOReturnSuccess;
SCSITaskIdentifier request;
STATUS_LOG ( ( 6, "%s[%p]: asyncRead Attempted", getName(), this ) );
request = GetSCSITask();
if (READ_10( request,
buffer,
fMediumBlockSize,
0,
0,
0,
( SCSICmdField4Byte ) startBlock,
( SCSICmdField2Byte ) blockCount ) == true )
{
SetApplicationLayerReference( request, clientData );
STATUS_LOG ( ( 6, "%s[%p]::IssueRead send command.", getName(), this ) );
SendCommand( request, 0, &this->AsyncReadWriteComplete );
}
else
{
PANIC_NOW(( "IOUSBMassStorageUFIDevice::IssueWrite malformed command" ) );
status = kIOReturnError;
}
return status;
}
IOReturn
IOUSBMassStorageUFIDevice::IssueWrite ( IOMemoryDescriptor * buffer,
UInt64 startBlock,
UInt64 blockCount )
{
SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
SCSITaskIdentifier request;
STATUS_LOG ( ( 6, "%s[%p]: syncWrite Attempted", getName(), this ) );
request = GetSCSITask();
if ( WRITE_10 ( request,
buffer,
fMediumBlockSize,
0,
0,
0,
( SCSICmdField4Byte ) startBlock,
( SCSICmdField2Byte ) blockCount ) == true )
{
serviceResponse = SendCommand( request, 0 );
}
else
{
PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::IssueWrite malformed command" ) );
}
ReleaseSCSITask ( request );
if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
{
return kIOReturnSuccess;
}
else
{
return kIOReturnError;
}
}
IOReturn
IOUSBMassStorageUFIDevice::IssueWrite ( IOMemoryDescriptor * buffer,
UInt64 startBlock,
UInt64 blockCount,
void * clientData )
{
IOReturn status = kIOReturnSuccess;
SCSITaskIdentifier request;
STATUS_LOG ( ( 6, "%s[%p]:: asyncWrite Attempted", getName(), this ) );
request = GetSCSITask();
if ( WRITE_10 ( request,
buffer,
fMediumBlockSize,
0,
0,
0,
( SCSICmdField4Byte ) startBlock,
( SCSICmdField2Byte ) blockCount ) == true )
{
SetApplicationLayerReference ( request, clientData );
STATUS_LOG ( ( 6, "%s[%p]::IssueWrite send command.", getName(), this ) );
SendCommand ( request, 0, &this->AsyncReadWriteComplete );
}
else
{
PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::IssueWrite malformed command" ) );
}
return status;
}
IOReturn
IOUSBMassStorageUFIDevice::SyncReadWrite ( IOMemoryDescriptor * buffer,
UInt64 startBlock,
UInt64 blockCount,
UInt64 blockSize )
{
UNUSED ( blockSize );
IODirection direction;
IOReturn theErr;
direction = buffer->getDirection();
if ( direction == kIODirectionIn )
{
theErr = IssueRead( buffer, startBlock, blockCount );
}
else if ( direction == kIODirectionOut )
{
theErr = IssueWrite( buffer, startBlock, blockCount );
}
else
{
STATUS_LOG ( ( 1, "%s[%p]: doSyncReadWrite bad direction argument", getName(), this ) );
theErr = kIOReturnBadArgument;
}
return theErr;
}
IOReturn
IOUSBMassStorageUFIDevice::AsyncReadWrite ( IOMemoryDescriptor * buffer,
UInt64 startBlock,
UInt64 blockCount,
UInt64 blockSize,
void * clientData )
{
UNUSED ( blockSize );
IODirection direction;
IOReturn theErr;
direction = buffer->getDirection();
if ( direction == kIODirectionIn )
{
IssueRead( buffer, startBlock, blockCount, clientData );
theErr = kIOReturnSuccess;
}
else if ( direction == kIODirectionOut )
{
IssueWrite( buffer, startBlock, blockCount, clientData );
theErr = kIOReturnSuccess;
}
else
{
STATUS_LOG ( ( 1, "%s[%p]: doAsyncReadWrite bad direction argument", getName(), this ) );
theErr = kIOReturnBadArgument;
}
return theErr;
}
IOReturn
IOUSBMassStorageUFIDevice::EjectTheMedium ( void )
{
STATUS_LOG ( ( 6, "%s[%p]::EjectTheMedium called", getName(), this ) );
ResetMediumCharacteristics();
if ( fPollingMode != kPollingMode_MediaRemoval )
{
fPollingMode = kPollingMode_MediaRemoval;
EnablePolling();
}
return kIOReturnSuccess;
}
IOReturn
IOUSBMassStorageUFIDevice::FormatMedium ( UInt64 blockCount, UInt64 blockSize )
{
UNUSED ( blockCount );
UNUSED ( blockSize );
IOReturn theErr = kIOReturnSuccess;
STATUS_LOG ( ( 6, "%s[%p]::FormatMedium called", getName(), this ) );
return theErr;
}
UInt32
IOUSBMassStorageUFIDevice::GetFormatCapacities( UInt64 * capacities,
UInt32 capacitiesMaxCount ) const
{
UNUSED ( capacities );
UNUSED ( capacitiesMaxCount );
STATUS_LOG ( ( 6, "%s[%p]::doGetFormatCapacities called", getName(), this ) );
return 0;
}
#pragma mark -
#pragma mark *** Device Information Retrieval Methods ***
#pragma mark -
char *
IOUSBMassStorageUFIDevice::GetVendorString ( void )
{
OSString * vendorString;
STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
vendorString = ( OSString * ) fDeviceCharacteristicsDictionary->getObject( kIOPropertyVendorNameKey );
if ( vendorString != NULL )
{
return ( ( char * ) vendorString->getCStringNoCopy ( ) );
}
else
{
return ( char * ) "NULL STRING";
}
}
char *
IOUSBMassStorageUFIDevice::GetProductString ( void )
{
OSString * productString;
STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
productString = ( OSString * ) fDeviceCharacteristicsDictionary->getObject ( kIOPropertyProductNameKey );
if ( productString != NULL )
{
return ( ( char * ) productString->getCStringNoCopy ( ) );
}
else
{
return ( char * ) "NULL STRING";
}
}
char *
IOUSBMassStorageUFIDevice::GetRevisionString ( void )
{
OSString * revisionString;
STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
revisionString = ( OSString * ) fDeviceCharacteristicsDictionary->getObject ( kIOPropertyProductRevisionLevelKey );
if ( revisionString )
{
return ( ( char * ) revisionString->getCStringNoCopy ( ) );
}
else
{
return ( char * ) "NULL STRING";
}
}
OSDictionary *
IOUSBMassStorageUFIDevice::GetProtocolCharacteristicsDictionary ( void )
{
STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
return ( OSDictionary * ) getProperty( kIOPropertyProtocolCharacteristicsKey );
}
OSDictionary *
IOUSBMassStorageUFIDevice::GetDeviceCharacteristicsDictionary ( void )
{
STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
return fDeviceCharacteristicsDictionary;
}
#pragma mark -
#pragma mark *** Query methods to report device characteristics ***
#pragma mark -
UInt64
IOUSBMassStorageUFIDevice::ReportDeviceMaxBlocksReadTransfer ( void )
{
UInt64 maxBlockCount;
STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
maxBlockCount = 256;
return maxBlockCount;
}
UInt64
IOUSBMassStorageUFIDevice::ReportDeviceMaxBlocksWriteTransfer ( void )
{
UInt64 maxBlockCount;
STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
maxBlockCount = 256;
return maxBlockCount;
}
#pragma mark -
#pragma mark *** Query methods to report installed medium characteristics ***
#pragma mark -
UInt64
IOUSBMassStorageUFIDevice::ReportMediumBlockSize ( void )
{
STATUS_LOG ( ( 5, "%s[%p]::ReportMediumBlockSize blockSize = %ld", getName(), this, ( UInt32 ) fMediumBlockSize ) );
return fMediumBlockSize;
}
UInt64
IOUSBMassStorageUFIDevice::ReportMediumTotalBlockCount ( void )
{
STATUS_LOG ( ( 5, "%s[%p]::ReportMediumTotalBlockCount maxBlock = %ld", getName(), this, fMediumBlockCount ) );
return fMediumBlockCount;
}
bool
IOUSBMassStorageUFIDevice::ReportMediumWriteProtection ( void )
{
STATUS_LOG ( ( 5, "%s[%p]::ReportMediumWriteProtection isWriteProtected = %d.", getName(), this, fMediumIsWriteProtected ) );
return fMediumIsWriteProtected;
}
#pragma mark -
#pragma mark *** Command Builders Utility Methods ***
#pragma mark -
bool
IOUSBMassStorageUFIDevice::IsParameterValid ( SCSICmdField1Byte param,
SCSICmdField1Byte mask )
{
STATUS_LOG ( ( 6, "%s[%p]::IsParameterValid called", getName(), this ) );
if ( ( param | mask ) != mask )
{
STATUS_LOG ( ( 4, "%s[%p]:: param = %x not valid, mask = %x", getName(), this, param, mask ) );
return false;
}
return true;
}
bool
IOUSBMassStorageUFIDevice::IsParameterValid ( SCSICmdField2Byte param,
SCSICmdField2Byte mask )
{
STATUS_LOG ( ( 6, "%s[%p]::IsParameterValid called", getName(), this ) );
if ( ( param | mask ) != mask )
{
STATUS_LOG ( ( 4, "%s[%p]:: param = %x not valid, mask = %x", getName(), this, param, mask ) );
return false;
}
return true;
}
bool
IOUSBMassStorageUFIDevice::IsParameterValid ( SCSICmdField4Byte param,
SCSICmdField4Byte mask )
{
STATUS_LOG ( ( 6, "%s[%p]::IsParameterValid called", getName(), this ) );
if ( ( param | mask ) != mask )
{
STATUS_LOG ( ( 4, "%s[%p]:: param = %x not valid, mask = %x", getName(), this,
(unsigned int) param, (unsigned int) mask ) );
return false;
}
return true;
}
#pragma mark -
#pragma mark *** Command Builder Methods ***
#pragma mark -
bool
IOUSBMassStorageUFIDevice::FORMAT_UNIT(
SCSITaskIdentifier request,
IOMemoryDescriptor * dataBuffer,
IOByteCount defectListSize,
SCSICmdField1Byte TRACK_NUMBER,
SCSICmdField2Byte INTERLEAVE )
{
UNUSED ( TRACK_NUMBER );
STATUS_LOG ( ( 6, "%s[%p]::FORMAT_UNIT called", getName(), this ) );
if ( ResetForNewTask ( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if ( IsParameterValid ( INTERLEAVE, kSCSICmdFieldMask2Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: INTERLEAVE = %x not valid", getName(), this, INTERLEAVE ) );
return false;
}
if ( defectListSize > 0 )
{
if ( IsMemoryDescriptorValid( dataBuffer, defectListSize )
== false )
{
STATUS_LOG ( ( 4, "%s[%p]:: dataBuffer = %x not valid, defectListSize = %x",
getName(), this, dataBuffer, defectListSize ) );
return false;
}
}
SetCommandDescriptorBlock ( request,
kSCSICmd_FORMAT_UNIT,
0x00,
0x00,
( INTERLEAVE >> 8 ) & 0xFF,
INTERLEAVE & 0xFF,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_FromInitiatorToTarget );
SetDataBuffer ( request,
dataBuffer );
return true;
}
bool
IOUSBMassStorageUFIDevice::INQUIRY (
SCSITaskIdentifier request,
IOMemoryDescriptor *dataBuffer,
SCSICmdField1Byte PAGE_OR_OPERATION_CODE,
SCSICmdField1Byte ALLOCATION_LENGTH )
{
STATUS_LOG ( ( 6, "%s[%p]::INQUIRY called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if ( IsParameterValid ( PAGE_OR_OPERATION_CODE, kSCSICmdFieldMask1Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: PAGE_OR_OPERATION_CODE = %x not valid",
getName(), this, PAGE_OR_OPERATION_CODE ) );
return false;
}
if ( IsParameterValid ( ALLOCATION_LENGTH, kSCSICmdFieldMask1Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: ALLOCATION_LENGTH = %x not valid", getName(), this, ALLOCATION_LENGTH ) );
return false;
}
if ( IsMemoryDescriptorValid( dataBuffer, ALLOCATION_LENGTH ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: dataBuffer = %x not valid, ALLOCATION_LENGTH = %x",
getName(), this, dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_INQUIRY,
0x00,
PAGE_OR_OPERATION_CODE,
0x00,
ALLOCATION_LENGTH,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_FromTargetToInitiator );
SetDataBuffer ( request,
dataBuffer );
SetRequestedDataTransferCount ( request,
ALLOCATION_LENGTH );
return true;
}
bool
IOUSBMassStorageUFIDevice::MODE_SELECT_10 (
SCSITaskIdentifier request,
IOMemoryDescriptor *dataBuffer,
SCSICmdField1Bit PF,
SCSICmdField1Bit SP,
SCSICmdField2Byte PARAMETER_LIST_LENGTH )
{
STATUS_LOG ( ( 6, "%s[%p]::MODE_SELECT_10 called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if( IsParameterValid( PF, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: PF = %x not valid", getName(), this, PF ) );
return false;
}
if( IsParameterValid( SP, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: SP = %x not valid", getName(), this, SP ) );
return false;
}
if( IsParameterValid( PARAMETER_LIST_LENGTH, kSCSICmdFieldMask2Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: PARAMETER_LIST_LENGTH = %x not valid",
getName(), this, PARAMETER_LIST_LENGTH ) );
return false;
}
if( IsMemoryDescriptorValid( dataBuffer, PARAMETER_LIST_LENGTH ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: dataBuffer = %x not valid, PARAMETER_LIST_LENGTH = %x",
getName(), this, dataBuffer, PARAMETER_LIST_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_MODE_SELECT_10,
( PF << 4 ) | SP,
0x00,
0x00,
0x00,
0x00,
0x00,
( PARAMETER_LIST_LENGTH >> 8 ) & 0xFF,
PARAMETER_LIST_LENGTH & 0xFF,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_FromInitiatorToTarget );
SetDataBuffer ( request,
dataBuffer );
SetRequestedDataTransferCount ( request,
PARAMETER_LIST_LENGTH );
return true;
}
bool
IOUSBMassStorageUFIDevice::MODE_SENSE_10 (
SCSITaskIdentifier request,
IOMemoryDescriptor *dataBuffer,
SCSICmdField1Bit DBD,
SCSICmdField2Bit PC,
SCSICmdField6Bit PAGE_CODE,
SCSICmdField2Byte ALLOCATION_LENGTH )
{
STATUS_LOG ( ( 6, "%s[%p]::MODE_SENSE_10 called", getName(), this ) );
if ( ResetForNewTask ( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if( IsParameterValid ( DBD, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: DBD = %x not valid", getName(), this, DBD ) );
return false;
}
if( IsParameterValid ( PC, kSCSICmdFieldMask2Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: PC = %x not valid", getName(), this, PC ) );
return false;
}
if( IsParameterValid ( PAGE_CODE, kSCSICmdFieldMask6Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: PAGE_CODE = %x not valid", getName(), this, PAGE_CODE ) );
return false;
}
if( IsParameterValid ( ALLOCATION_LENGTH, kSCSICmdFieldMask2Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: ALLOCATION_LENGTH = %x not valid", getName(), this, ALLOCATION_LENGTH ) );
return false;
}
if( IsMemoryDescriptorValid ( dataBuffer, ALLOCATION_LENGTH ) == false )
{
STATUS_LOG ( (4, "%s[%p]:: dataBuffer = %x not valid, ALLOCATION_LENGTH = %x",
dataBuffer, ALLOCATION_LENGTH, getName(), this ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_MODE_SENSE_10,
( DBD << 3 ),
( PC << 6 ) | PAGE_CODE,
0x00,
0x00,
0x00,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_FromTargetToInitiator );
SetDataBuffer ( request,
dataBuffer );
SetRequestedDataTransferCount ( request,
ALLOCATION_LENGTH );
return true;
}
bool
IOUSBMassStorageUFIDevice::PREVENT_ALLOW_MEDIUM_REMOVAL(
SCSITaskIdentifier request,
SCSICmdField1Bit PREVENT )
{
STATUS_LOG ( ( 6, "%s[%p]::PREVENT_ALLOW_MEDIUM_REMOVAL called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if( IsParameterValid( PREVENT, kSCSICmdFieldMask2Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: PREVENT = %x not valid", getName(), this, PREVENT ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_PREVENT_ALLOW_MEDIUM_REMOVAL,
0x00,
0x00,
0x00,
PREVENT,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
IOUSBMassStorageUFIDevice::READ_10 (
SCSITaskIdentifier request,
IOMemoryDescriptor * dataBuffer,
UInt32 blockSize,
SCSICmdField1Bit DPO,
SCSICmdField1Bit FUA,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte TRANSFER_LENGTH )
{
UInt32 requestedByteCount;
STATUS_LOG ( ( 6, "%s[%p]::READ_10 called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if ( blockSize == 0 )
{
return false;
}
if ( dataBuffer == NULL )
{
return false;
}
else
{
requestedByteCount = TRANSFER_LENGTH * blockSize;
if ( dataBuffer->getLength() < requestedByteCount )
{
return false;
}
}
if ( IsParameterValid( DPO, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: DPO = %x not valid", getName(), this, DPO ) );
return false;
}
if ( IsParameterValid( FUA, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: FUA = %x not valid", getName(), this, FUA ) );
return false;
}
if ( IsParameterValid( RELADR, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) );
return false;
}
if ( IsParameterValid( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid",
getName(), this, LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid( TRANSFER_LENGTH, kSCSICmdFieldMask2Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: TRANSFER_LENGTH = %x not valid",
getName(), this, TRANSFER_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_10,
( DPO << 4 ) | ( FUA << 3 ) | RELADR,
( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
LOGICAL_BLOCK_ADDRESS & 0xFF,
0x00,
( TRANSFER_LENGTH >> 8 ) & 0xFF,
TRANSFER_LENGTH & 0xFF,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_FromTargetToInitiator );
SetDataBuffer ( request,
dataBuffer );
SetRequestedDataTransferCount ( request,
requestedByteCount );
return true;
}
bool
IOUSBMassStorageUFIDevice::READ_12 (
SCSITaskIdentifier request,
IOMemoryDescriptor * dataBuffer,
UInt32 blockSize,
SCSICmdField1Bit DPO,
SCSICmdField1Bit FUA,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField4Byte TRANSFER_LENGTH )
{
UInt32 requestedByteCount;
STATUS_LOG ( ( 6, "%s[%p]::READ_12 called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if ( blockSize == 0 )
{
return false;
}
if (dataBuffer == NULL )
{
return false;
}
else
{
requestedByteCount = TRANSFER_LENGTH * blockSize;
if ( dataBuffer->getLength() < requestedByteCount )
{
return false;
}
}
if( IsParameterValid( DPO, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: DPO = %x not valid", getName(), this, DPO ) );
return false;
}
if( IsParameterValid( FUA, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: FUA = %x not valid", getName(), this, FUA ) );
return false;
}
if( IsParameterValid( RELADR, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) );
return false;
}
if( IsParameterValid( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid",
getName(), this, LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if( IsParameterValid( TRANSFER_LENGTH, kSCSICmdFieldMask4Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: TRANSFER_LENGTH = %x not valid",
getName(), this, TRANSFER_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_12,
( DPO << 4 ) | ( FUA << 3 ) | RELADR,
( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
LOGICAL_BLOCK_ADDRESS & 0xFF,
( TRANSFER_LENGTH >> 24 ) & 0xFF,
( TRANSFER_LENGTH >> 16 ) & 0xFF,
( TRANSFER_LENGTH >> 8 ) & 0xFF,
TRANSFER_LENGTH & 0xFF,
0x00,
0x00 );
SetDataTransferDirection( request,
kSCSIDataTransfer_FromTargetToInitiator );
SetDataBuffer ( request,
dataBuffer );
SetRequestedDataTransferCount ( request,
requestedByteCount );
return true;
}
bool
IOUSBMassStorageUFIDevice::READ_CAPACITY (
SCSITaskIdentifier request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField1Bit PMI )
{
STATUS_LOG ( ( 6, "%s[%p]::READ_CAPACITY called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if ( dataBuffer == NULL )
{
return false;
}
if( IsParameterValid( RELADR, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) );
return false;
}
if( IsParameterValid( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid",
getName(), this, LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if( IsParameterValid( PMI, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: PMI = %x not valid", getName(), this, PMI ) );
return false;
}
SetCommandDescriptorBlock( request,
kSCSICmd_READ_CAPACITY,
RELADR,
( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
LOGICAL_BLOCK_ADDRESS & 0xFF,
0x00,
0x00,
PMI,
0x00 );
SetDataTransferDirection( request,
kSCSIDataTransfer_FromTargetToInitiator );
SetDataBuffer( request,
dataBuffer );
SetRequestedDataTransferCount( request, 8 );
return true;
}
bool
IOUSBMassStorageUFIDevice::READ_FORMAT_CAPACITIES(
SCSITaskIdentifier request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField2Byte ALLOCATION_LENGTH )
{
STATUS_LOG ( ( 6, "%s[%p]::READ_CAPACITY called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if ( dataBuffer == NULL )
{
return false;
}
if( IsParameterValid( ALLOCATION_LENGTH, kSCSICmdFieldMask2Byte ) == false )
{
STATUS_LOG ( (4, "%s[%p]:: ALLOCATION_LENGTH = %x not valid", getName(), this, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_FORMAT_CAPACITIES,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_FromTargetToInitiator );
SetDataBuffer ( request,
dataBuffer );
SetRequestedDataTransferCount( request,
ALLOCATION_LENGTH );
return true;
}
bool
IOUSBMassStorageUFIDevice::REQUEST_SENSE (
SCSITaskIdentifier request,
IOMemoryDescriptor *dataBuffer,
SCSICmdField1Byte ALLOCATION_LENGTH )
{
STATUS_LOG ( ( 6, "%s[%p]::REQUEST_SENSE called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if( IsParameterValid( ALLOCATION_LENGTH, kSCSICmdFieldMask1Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]ALLOCATION_LENGTH = %x not valid",
getName(), this, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_REQUEST_SENSE,
0x00,
0x00,
0x00,
ALLOCATION_LENGTH,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_FromTargetToInitiator );
SetDataBuffer ( request,
dataBuffer );
SetRequestedDataTransferCount ( request,
ALLOCATION_LENGTH );
return true;
}
bool
IOUSBMassStorageUFIDevice::REZERO_UNIT ( SCSITaskIdentifier request )
{
UNUSED ( request );
return false;
}
bool
IOUSBMassStorageUFIDevice::SEEK (
SCSITaskIdentifier request,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS )
{
UNUSED ( request );
UNUSED ( LOGICAL_BLOCK_ADDRESS );
return false;
}
bool
IOUSBMassStorageUFIDevice::SEND_DIAGNOSTICS (
SCSITaskIdentifier request,
SCSICmdField1Bit PF,
SCSICmdField1Bit SELF_TEST,
SCSICmdField1Bit DEF_OFL,
SCSICmdField1Bit UNIT_OFL )
{
STATUS_LOG ( ( 6, "%s[%p]::SEND_DIAGNOSTICS called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if( IsParameterValid( PF, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: PF = %x not valid", getName(), this, PF ) );
return false;
}
if( IsParameterValid ( SELF_TEST, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: SELF_TEST = %x not valid", getName(), this, SELF_TEST ) );
return false;
}
if( IsParameterValid( DEF_OFL, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: DEF_OFL = %x not valid", getName(), this, DEF_OFL ) );
return false;
}
if( IsParameterValid( UNIT_OFL, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: UNIT_OFL = %x not valid", getName(), this, UNIT_OFL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SEND_DIAGNOSTICS,
( PF << 4 ) |
( SELF_TEST << 2 ) | ( DEF_OFL << 1 ) | UNIT_OFL,
0x00,
0x00,
0x00,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_NoDataTransfer);
return true;
}
bool
IOUSBMassStorageUFIDevice::START_STOP_UNIT (
SCSITaskIdentifier request,
SCSICmdField1Bit IMMED,
SCSICmdField1Bit LOEJ,
SCSICmdField1Bit START )
{
STATUS_LOG ( ( 6, "%s[%p]::START_STOP_UNIT called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if( IsParameterValid( IMMED, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: IMMED = %x not valid", getName(), this, IMMED ) );
return false;
}
if( IsParameterValid( LOEJ, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: LOEJ = %x not valid", getName(), this, LOEJ ) );
return false;
}
if( IsParameterValid( START, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: START = %x not valid", getName(), this, START ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_START_STOP_UNIT,
IMMED,
0x00,
0x00,
( LOEJ << 1 ) | START,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
IOUSBMassStorageUFIDevice::TEST_UNIT_READY (
SCSITaskIdentifier request )
{
STATUS_LOG ( ( 6, "%s[%p]::TEST_UNIT_READY called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_TEST_UNIT_READY,
0x00,
0x00,
0x00,
0x00,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
IOUSBMassStorageUFIDevice::VERIFY(
SCSITaskIdentifier request,
SCSICmdField1Bit DPO,
SCSICmdField1Bit BYTCHK,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte VERIFICATION_LENGTH )
{
UNUSED( request );
UNUSED( DPO );
UNUSED( BYTCHK );
UNUSED( RELADR );
UNUSED( LOGICAL_BLOCK_ADDRESS );
UNUSED( VERIFICATION_LENGTH );
return false;
}
bool
IOUSBMassStorageUFIDevice::WRITE_10 (
SCSITaskIdentifier request,
IOMemoryDescriptor * dataBuffer,
UInt32 blockSize,
SCSICmdField1Bit DPO,
SCSICmdField1Bit FUA,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte TRANSFER_LENGTH )
{
UInt32 requestedByteCount;
STATUS_LOG ( ( 6, "%s[%p]::WRITE_10 called", getName(), this ) );
if ( ResetForNewTask( request ) == false )
{
STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
return false;
}
if ( blockSize == 0 )
{
return false;
}
if (dataBuffer == NULL )
{
return false;
}
else
{
requestedByteCount = TRANSFER_LENGTH * blockSize;
if ( dataBuffer->getLength() < requestedByteCount )
{
return false;
}
}
if( IsParameterValid ( DPO, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: DPO = %x not valid", getName(), this, DPO ) );
return false;
}
if( IsParameterValid ( FUA, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: FUA = %x not valid", getName(), this, FUA ) );
return false;
}
if( IsParameterValid ( RELADR, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) );
return false;
}
if( IsParameterValid ( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid",
getName(), this, LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if( IsParameterValid ( TRANSFER_LENGTH, kSCSICmdFieldMask2Byte ) == false )
{
STATUS_LOG ( ( 4, "%s[%p]:: TRANSFER_LENGTH = %x not valid",
getName(), this, TRANSFER_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_WRITE_10,
( DPO << 4 ) | ( FUA << 3 ) | RELADR,
( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
LOGICAL_BLOCK_ADDRESS & 0xFF,
0x00,
( TRANSFER_LENGTH >> 8 ) & 0xFF,
TRANSFER_LENGTH & 0xFF,
0x00 );
SetDataTransferDirection ( request,
kSCSIDataTransfer_FromInitiatorToTarget );
SetDataBuffer ( request,
dataBuffer );
SetRequestedDataTransferCount ( request,
requestedByteCount );
return true;
}
bool
IOUSBMassStorageUFIDevice::WRITE_12 (
SCSITaskIdentifier request,
IOMemoryDescriptor * dataBuffer,
UInt32 blockSize,
SCSICmdField1Bit DPO,
SCSICmdField1Bit EBP,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField4Byte TRANSFER_LENGTH )
{
UNUSED ( request );
UNUSED ( dataBuffer );
UNUSED ( blockSize );
UNUSED ( DPO );
UNUSED ( EBP );
UNUSED ( RELADR );
UNUSED ( LOGICAL_BLOCK_ADDRESS );
UNUSED ( TRANSFER_LENGTH );
return false;
}
bool
IOUSBMassStorageUFIDevice::WRITE_AND_VERIFY (
SCSITaskIdentifier request,
IOMemoryDescriptor * dataBuffer,
UInt32 blockSize,
SCSICmdField1Bit DPO,
SCSICmdField1Bit BYTCHK,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte TRANSFER_LENGTH )
{
UNUSED ( request );
UNUSED ( dataBuffer );
UNUSED ( blockSize );
UNUSED ( DPO );
UNUSED ( BYTCHK );
UNUSED ( RELADR );
UNUSED ( LOGICAL_BLOCK_ADDRESS );
UNUSED ( TRANSFER_LENGTH );
return false;
}
#pragma mark -
#pragma mark *** IOUSBMassStorageUFISubclass methods ***
#pragma mark -
bool
IOUSBMassStorageUFISubclass::BeginProvidedServices ( void )
{
IOUSBMassStorageUFIDevice * ufiDevice = OSTypeAlloc ( IOUSBMassStorageUFIDevice );
if( ufiDevice == NULL )
{
STATUS_LOG ( ( 1, "%s[%p]::BeginProvidedServices failed", getName(), this ) );
PANIC_NOW ( ( "IOUSBMassStorageUFISubclass::BeginProvidedServices failed" ) );
return false;
}
ufiDevice->init ( NULL );
if ( !ufiDevice->attach( this ) )
{
PANIC_NOW ( ( "IOUSBMassStorageUFISubclass::BeginProvidedServices unable to attach nub" ) );
return false;
}
if ( ufiDevice->start( this ) == false )
{
ufiDevice->detach( this );
}
STATUS_LOG ( ( 4, "%s[%p]::BeginProvidedServices exiting.", getName(), this ) );
ufiDevice->release();
return true;
}
bool
IOUSBMassStorageUFISubclass::EndProvidedServices ( void )
{
return true;
}