SCSIReducedBlockCommands.cpp [plain text]
#include <IOKit/scsi-commands/SCSICommandOperationCodes.h>
#include "SCSIReducedBlockCommands.h"
#if ( SCSI_RBC_COMMANDS_DEBUGGING_LEVEL >= 1 )
#define PANIC_NOW(x) IOPanic x
#define DEBUG_ASSERT(x) assert x
#else
#define PANIC_NOW(x)
#define DEBUG_ASSERT(x)
#endif
#if ( SCSI_RBC_COMMANDS_DEBUGGING_LEVEL >= 2 )
#define ERROR_LOG(x) IOLog x
#else
#define ERROR_LOG(x)
#endif
#if ( SCSI_RBC_COMMANDS_DEBUGGING_LEVEL >= 3 )
#define STATUS_LOG(x) IOLog x
#else
#define STATUS_LOG(x)
#endif
#define READ_CAPACITY_DATA_SIZE 8
#define super SCSIPrimaryCommands
OSDefineMetaClassAndStructors ( SCSIReducedBlockCommands, SCSIPrimaryCommands );
SCSIReducedBlockCommands *
SCSIReducedBlockCommands::CreateSCSIReducedBlockCommandObject ( void )
{
return new SCSIReducedBlockCommands;
}
#pragma mark -
#pragam mark RBC Command Methods
bool
SCSIReducedBlockCommands::FORMAT_UNIT (
SCSITask * request,
SCSICmdField1Bit IMMED,
SCSICmdField1Bit PROGRESS,
SCSICmdField1Bit PERCENT_TIME,
SCSICmdField1Bit INCREMENT )
{
STATUS_LOG ( ( "SCSIReducedBlockCommands::FORMAT_UNIT called\n" ) );
if ( IsParameterValid ( IMMED, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( "IMMED = %x not valid\n", IMMED ) );
return false;
}
if ( IsParameterValid ( PROGRESS, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( "PROGRESS = %x not valid\n", PROGRESS ) );
return false;
}
if ( IsParameterValid ( PERCENT_TIME, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( "PERCENT_TIME = %x not valid\n", PERCENT_TIME ) );
return false;
}
if ( IsParameterValid ( INCREMENT, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( "INCREMENT = %x not valid\n", INCREMENT ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_FORMAT_UNIT,
0x00,
( IMMED << 3 ) | ( PROGRESS << 2 ) |
( PERCENT_TIME << 1 ) | INCREMENT,
0x00,
0x00,
0x00 );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIReducedBlockCommands::READ_10 (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
UInt32 blockSize,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte TRANSFER_LENGTH )
{
UInt32 requestedByteCount;
STATUS_LOG ( ( "SCSIReducedBlockCommands::READ_10 called\n" ) );
if ( blockSize == 0 )
{
STATUS_LOG ( ( "blockSize = %x not valid\n" ) );
return false;
}
if ( IsParameterValid ( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
{
STATUS_LOG ( ( "LOGICAL_BLOCK_ADDRESS = %x not valid\n", LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( TRANSFER_LENGTH, kSCSICmdFieldMask2Byte ) == false )
{
STATUS_LOG ( ( "TRANSFER_LENGTH = %x not valid\n", TRANSFER_LENGTH ) );
return false;
}
requestedByteCount = TRANSFER_LENGTH * blockSize;
if ( IsBufferAndCapacityValid ( dataBuffer, requestedByteCount ) == false )
{
STATUS_LOG ( ( "dataBuffer = %x not valid, requestedByteCount = %x\n", dataBuffer, requestedByteCount ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_10,
0x00,
( 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 );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
requestedByteCount );
return true;
}
bool
SCSIReducedBlockCommands::READ_CAPACITY (
SCSITask * request,
IOMemoryDescriptor * dataBuffer )
{
STATUS_LOG ( ( "SCSIReducedBlockCommands::READ_CAPACITY called\n" ) );
if ( IsBufferAndCapacityValid ( dataBuffer, READ_CAPACITY_DATA_SIZE ) == false )
{
STATUS_LOG ( ( "dataBuffer = %x not valid, READ_CAPACITY_DATA_SIZE = %x\n", dataBuffer, READ_CAPACITY_DATA_SIZE ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_CAPACITY,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00 );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
READ_CAPACITY_DATA_SIZE );
return true;
}
bool
SCSIReducedBlockCommands::START_STOP_UNIT (
SCSITask * request,
SCSICmdField1Bit IMMED,
SCSICmdField4Bit POWER_CONDITIONS,
SCSICmdField1Bit LOEJ,
SCSICmdField1Bit START )
{
STATUS_LOG ( ( "SCSIReducedBlockCommands::START_STOP_UNIT called\n" ) );
if ( IsParameterValid ( IMMED, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( "IMMED = %x not valid\n", IMMED ) );
return false;
}
if ( IsParameterValid ( POWER_CONDITIONS, kSCSICmdFieldMask4Bit ) == false )
{
STATUS_LOG ( ( "POWER_CONDITIONS = %x not valid\n", POWER_CONDITIONS ) );
return false;
}
if ( IsParameterValid ( LOEJ, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( "LOEJ = %x not valid\n", LOEJ ) );
return false;
}
if ( IsParameterValid ( START, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( "START = %x not valid\n", START ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_START_STOP_UNIT,
IMMED,
0x00,
0x00,
( POWER_CONDITIONS << 4 ) | ( LOEJ << 1 ) | START,
0x00 );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIReducedBlockCommands::SYNCHRONIZE_CACHE (
SCSITask * request )
{
STATUS_LOG ( ( "SCSIReducedBlockCommands::SYNCRONIZE_CACHE called\n" ) );
SetCommandDescriptorBlock ( request,
kSCSICmd_SYNCHRONIZE_CACHE,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00 );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIReducedBlockCommands::WRITE_10 (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
UInt32 blockSize,
SCSICmdField1Bit FUA,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte TRANSFER_LENGTH )
{
UInt32 requestedByteCount;
STATUS_LOG ( ( "SCSIReducedBlockCommands::WRITE_10 called\n" ) );
if ( blockSize == 0 )
{
STATUS_LOG ( ( "blockSize = %x not valid\n", blockSize ) );
return false;
}
if ( IsParameterValid ( FUA, kSCSICmdFieldMask1Bit ) == false )
{
STATUS_LOG ( ( "FUA = %x not valid\n", FUA ) );
return false;
}
if ( IsParameterValid ( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
{
STATUS_LOG ( ( "LOGICAL_BLOCK_ADDRESS = %x not valid\n", LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( TRANSFER_LENGTH, kSCSICmdFieldMask2Byte ) == false )
{
STATUS_LOG ( ( "TRANSFER_LENGTH = %x not valid\n", TRANSFER_LENGTH ) );
return false;
}
requestedByteCount = TRANSFER_LENGTH * blockSize;
if ( IsBufferAndCapacityValid ( dataBuffer, requestedByteCount ) == false )
{
STATUS_LOG ( ( "dataBuffer = %x not valid, requestedByteCount = %x\n", dataBuffer, requestedByteCount ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_WRITE_10,
( FUA << 3 ),
( 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 );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromInitiatorToTarget,
dataBuffer,
requestedByteCount );
return true;
}
bool
SCSIReducedBlockCommands::VERIFY (
SCSITask * request,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte VERIFICATION_LENGTH )
{
STATUS_LOG ( ( "SCSIReducedBlockCommands::VERIFY called\n" ) );
if ( IsParameterValid ( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
{
STATUS_LOG ( ( "LOGICAL_BLOCK_ADDRESS = %x not valid\n", LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( VERIFICATION_LENGTH, kSCSICmdFieldMask2Byte ) == false )
{
STATUS_LOG ( ( "VERIFICATION_LENGTH = %x not valid\n", VERIFICATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_VERIFY_10,
0x00,
( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
LOGICAL_BLOCK_ADDRESS & 0xFF,
0x00,
( VERIFICATION_LENGTH >> 8 ) & 0xFF,
VERIFICATION_LENGTH & 0xFF,
0x00 );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;