SCSIMultimediaCommands.cpp [plain text]
#include <IOKit/scsi-commands/SCSICommandOperationCodes.h>
#include <IOKit/scsi-commands/SCSIMultimediaCommands.h>
#if ( SCSI_MMC_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_MMC_COMMANDS_DEBUGGING_LEVEL >= 2 )
#define ERROR_LOG(x) IOLog x
#else
#define ERROR_LOG(x)
#endif
#if ( SCSI_MMC_COMMANDS_DEBUGGING_LEVEL >= 3 )
#define STATUS_LOG(x) IOLog x
#else
#define STATUS_LOG(x)
#endif
#define super SCSIPrimaryCommands
OSDefineMetaClassAndStructors ( SCSIMultimediaCommands, SCSIPrimaryCommands );
SCSIMultimediaCommands *
SCSIMultimediaCommands::CreateSCSIMultimediaCommandObject ( void )
{
return new SCSIMultimediaCommands;
}
#pragma mark -
#pragma mark MMC Command Methods
bool
SCSIMultimediaCommands::BLANK (
SCSITask * request,
SCSICmdField1Bit IMMED,
SCSICmdField3Bit BLANKING_TYPE,
SCSICmdField4Byte START_ADDRESS_TRACK_NUMBER,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::BLANK called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( IMMED, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "IMMED = %x not valid \n", IMMED ) );
return false;
}
if ( IsParameterValid ( BLANKING_TYPE, kSCSICmdFieldMask3Bit ) == false )
{
ERROR_LOG ( ( "BLANKING_TYPE = %x not valid \n",
BLANKING_TYPE ) );
return false;
}
if ( IsParameterValid ( START_ADDRESS_TRACK_NUMBER,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "START_ADDRESS_TRACK_NUMBER = %x not valid \n",
START_ADDRESS_TRACK_NUMBER ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_BLANK,
( IMMED << 4 ) | BLANKING_TYPE,
( START_ADDRESS_TRACK_NUMBER >> 24 ) & 0xFF,
( START_ADDRESS_TRACK_NUMBER >> 16 ) & 0xFF,
( START_ADDRESS_TRACK_NUMBER >> 8 ) & 0xFF,
START_ADDRESS_TRACK_NUMBER & 0xFF,
0x00,
0x00,
0x00,
0x00,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::CLOSE_TRACK_SESSION (
SCSITask * request,
SCSICmdField1Bit IMMED,
SCSICmdField1Bit SESSION,
SCSICmdField1Bit TRACK,
SCSICmdField2Byte TRACK_NUMBER,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::CLOSE_TRACK_SESSION called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( IMMED, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "IMMED = %x not valid \n", IMMED ) );
return false;
}
if ( IsParameterValid ( SESSION, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "SESSION = %x not valid \n", SESSION ) );
return false;
}
if ( IsParameterValid ( TRACK, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "TRACK = %x not valid \n", TRACK ) );
return false;
}
if ( IsParameterValid ( TRACK_NUMBER,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "TRACK_NUMBER = %x not valid \n",
TRACK_NUMBER ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_CLOSE_TRACK_SESSION,
IMMED,
( SESSION << 1 ) | TRACK,
0x00,
( TRACK_NUMBER >> 8 ) & 0xFF,
TRACK_NUMBER & 0xFF,
0x00,
0x00,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::FORMAT_UNIT (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
IOByteCount parameterListSize,
SCSICmdField1Bit FMT_DATA,
SCSICmdField1Bit CMP_LIST,
SCSICmdField3Bit FORMAT_CODE,
SCSICmdField2Byte INTERLEAVE_VALUE,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::FORMAT_UNIT called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( FMT_DATA, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "FMT_DATA = %x not valid \n", FMT_DATA ) );
return false;
}
if ( IsParameterValid ( CMP_LIST, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "CMP_LIST = %x not valid \n", CMP_LIST ) );
return false;
}
if ( IsParameterValid ( INTERLEAVE_VALUE,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "INTERLEAVE_VALUE = %x not valid \n",
INTERLEAVE_VALUE ) );
return false;
}
switch ( FORMAT_CODE )
{
case FORMAT_CODE_CD_RW:
{
STATUS_LOG ( ( "Using FORMAT_CODE_CD_RW\n" ) );
if ( INTERLEAVE_VALUE != INTERLEAVE_VALUE_CD_RW )
{
ERROR_LOG ( ( "INTERLEAVE_VALUE = %x not valid \n",
INTERLEAVE_VALUE ) );
return false;
}
break;
}
case FORMAT_CODE_DVD_RAM:
{
STATUS_LOG ( ( "Using FORMAT_CODE_DVD_RAM\n" ) );
if ( INTERLEAVE_VALUE != INTERLEAVE_VALUE_DVD_RAM )
{
ERROR_LOG ( ( "INTERLEAVE_VALUE = %x not valid \n",
INTERLEAVE_VALUE ) );
return false;
}
break;
}
default:
{
ERROR_LOG ( ( "FORMAT_CODE = %x not valid \n",
FORMAT_CODE ) );
return false;
}
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( FMT_DATA == FMT_DATA_PRESENT )
{
if ( parameterListSize == 0 )
{
ERROR_LOG ( ( "parameterListSize = %x not valid \n",
parameterListSize ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
parameterListSize ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, parameterListSize = %ld\n",
dataBuffer, parameterListSize ) );
return false;
}
}
SetCommandDescriptorBlock ( request,
kSCSICmd_FORMAT_UNIT,
( FMT_DATA << 4 ) | ( CMP_LIST << 3 ) | FORMAT_CODE,
0x00,
( INTERLEAVE_VALUE >> 8 ) & 0xFF,
INTERLEAVE_VALUE & 0xFF,
CONTROL );
if ( parameterListSize == 0 )
{
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
}
else
{
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromInitiatorToTarget,
dataBuffer,
parameterListSize );
}
return true;
}
bool
SCSIMultimediaCommands::GET_CONFIGURATION (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField2Bit RT,
SCSICmdField2Byte STARTING_FEATURE_NUMBER,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::GET_CONFIGURATION called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( RT, kSCSICmdFieldMask2Bit ) == false )
{
ERROR_LOG ( ( "RT = %x not valid \n", RT ) );
return false;
}
if ( IsParameterValid ( STARTING_FEATURE_NUMBER,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "STARTING_FEATURE_NUMBER = %x not valid \n",
STARTING_FEATURE_NUMBER ) );
return false;
}
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_GET_CONFIGURATION,
RT,
( STARTING_FEATURE_NUMBER >> 8 ) & 0xFF,
STARTING_FEATURE_NUMBER & 0xFF,
0x00,
0x00,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::GET_EVENT_STATUS_NOTIFICATION (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField1Bit IMMED,
SCSICmdField1Byte NOTIFICATION_CLASS_REQUEST,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::GET_EVENT_STATUS_NOTIFICATION called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( IMMED, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "IMMED = %x not valid \n", IMMED ) );
return false;
}
if ( IsParameterValid ( NOTIFICATION_CLASS_REQUEST,
kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "NOTIFICATION_CLASS_REQUEST = %x not valid \n",
NOTIFICATION_CLASS_REQUEST ) );
return false;
}
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_GET_EVENT_STATUS_NOTIFICATION,
IMMED,
0x00,
0x00,
NOTIFICATION_CLASS_REQUEST,
0x00,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::GET_PERFORMANCE (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField2Bit TOLERANCE,
SCSICmdField1Bit WRITE,
SCSICmdField2Bit EXCEPT,
SCSICmdField4Byte STARTING_LBA,
SCSICmdField2Byte MAXIMUM_NUMBER_OF_DESCRIPTORS,
SCSICmdField1Byte CONTROL )
{
UInt32 returnDataCount = 0;
STATUS_LOG ( ( "SCSIMultimediaCommands::GET_PERFORMANCE called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( TOLERANCE, kSCSICmdFieldMask2Bit ) == false )
{
ERROR_LOG ( ( "TOLERANCE = %x not valid \n", TOLERANCE ) );
return false;
}
if ( IsParameterValid ( WRITE, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "WRITE = %x not valid \n", WRITE ) );
return false;
}
if ( IsParameterValid ( EXCEPT, kSCSICmdFieldMask2Bit ) == false )
{
ERROR_LOG ( ( "EXCEPT = %x not valid \n", EXCEPT ) );
return false;
}
if ( IsParameterValid ( STARTING_LBA,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "STARTING_LBA = %x not valid \n",
STARTING_LBA ) );
return false;
}
if ( IsParameterValid ( MAXIMUM_NUMBER_OF_DESCRIPTORS,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "MAXIMUM_NUMBER_OF_DESCRIPTORS = %x not valid \n",
MAXIMUM_NUMBER_OF_DESCRIPTORS ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
returnDataCount = PERFORMANCE_HEADER_SIZE +
( PERFORMANCE_DESCRIPTOR_SIZE * MAXIMUM_NUMBER_OF_DESCRIPTORS );
if ( IsBufferAndCapacityValid ( dataBuffer, returnDataCount ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, returnDataCount = %ld\n",
dataBuffer, returnDataCount ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_GET_PERFORMANCE,
( TOLERANCE << 3 ) | ( WRITE << 2 ) | EXCEPT,
( STARTING_LBA >> 24 ) & 0xFF,
( STARTING_LBA >> 16 ) & 0xFF,
( STARTING_LBA >> 8 ) & 0xFF,
STARTING_LBA & 0xFF,
0x00,
0x00,
( MAXIMUM_NUMBER_OF_DESCRIPTORS >> 8 ) & 0xFF,
MAXIMUM_NUMBER_OF_DESCRIPTORS & 0xFF,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
returnDataCount );
return true;
}
bool
SCSIMultimediaCommands::LOAD_UNLOAD_MEDIUM (
SCSITask * request,
SCSICmdField1Bit IMMED,
SCSICmdField1Bit LO_UNLO,
SCSICmdField1Bit START,
SCSICmdField1Byte SLOT,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::LOAD_UNLOAD_MEDIUM called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( IMMED, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "IMMED = %x not valid \n", IMMED ) );
return false;
}
if ( IsParameterValid ( LO_UNLO, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "LO_UNLO = %x not valid \n", LO_UNLO ) );
return false;
}
if ( IsParameterValid ( START, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "START = %x not valid \n", START ) );
return false;
}
if ( IsParameterValid ( SLOT, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "SLOT = %x not valid \n", SLOT ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_LOAD_UNLOAD_MEDIUM,
IMMED,
0x00,
0x00,
( LO_UNLO << 1 ) | START,
0x00,
0x00,
0x00,
SLOT,
0x00,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::MECHANISM_STATUS (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::MECHANISM_STATUS called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_MECHANISM_STATUS,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::PAUSE_RESUME (
SCSITask * request,
SCSICmdField1Bit RESUME,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::PAUSE_RESUME called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( RESUME, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "RESUME = %x not valid \n", RESUME ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_PAUSE_RESUME,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
RESUME,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::PLAY_AUDIO_10 (
SCSITask * request,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte STARTING_LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte PLAY_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::PLAY_AUDIO_10 called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( RELADR != 0 )
{
ERROR_LOG ( ( "RELADR = %x not valid \n", RELADR ) );
return false;
}
if ( IsParameterValid ( STARTING_LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "STARTING_LOGICAL_BLOCK_ADDRESS = %x not valid \n",
STARTING_LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( PLAY_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "PLAY_LENGTH = %x not valid \n", PLAY_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_PLAY_AUDIO_10,
RELADR,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
STARTING_LOGICAL_BLOCK_ADDRESS & 0xFF,
0x00,
( PLAY_LENGTH >> 8 ) & 0xFF,
PLAY_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::PLAY_AUDIO_12 (
SCSITask * request,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte STARTING_LOGICAL_BLOCK_ADDRESS,
SCSICmdField4Byte PLAY_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::PLAY_AUDIO_12 called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( RELADR != 0 )
{
ERROR_LOG ( ( "RELADR = %x not valid \n", RELADR ) );
return false;
}
if ( IsParameterValid ( STARTING_LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "STARTING_LOGICAL_BLOCK_ADDRESS = %x not valid \n",
STARTING_LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( PLAY_LENGTH,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "PLAY_LENGTH = %x not valid \n", PLAY_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_PLAY_AUDIO_12,
RELADR,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
STARTING_LOGICAL_BLOCK_ADDRESS & 0xFF,
( PLAY_LENGTH >> 24 ) & 0xFF,
( PLAY_LENGTH >> 16 ) & 0xFF,
( PLAY_LENGTH >> 8 ) & 0xFF,
PLAY_LENGTH & 0xFF,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::PLAY_AUDIO_MSF (
SCSITask * request,
SCSICmdField3Byte STARTING_MSF,
SCSICmdField3Byte ENDING_MSF,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::PLAY_AUDIO_MSF called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( STARTING_MSF,
kSCSICmdFieldMask3Byte ) == false )
{
ERROR_LOG ( ( "STARTING_MSF = %x not valid \n",
STARTING_MSF ) );
return false;
}
if ( ( ( STARTING_MSF & 0xFF ) >= FRAMES_IN_A_SECOND ) ||
( ( ( STARTING_MSF >> 8 ) & 0xFF ) >= SECONDS_IN_A_MINUTE ) )
{
if ( STARTING_MSF != 0xFFFFFF )
{
ERROR_LOG ( ( "STARTING_MSF = %x not valid \n",
STARTING_MSF ) );
return false;
}
}
if ( IsParameterValid ( ENDING_MSF,
kSCSICmdFieldMask3Byte ) == false )
{
ERROR_LOG ( ( "ENDING_MSF = %x not valid \n", ENDING_MSF ) );
return false;
}
if ( ( ( ENDING_MSF & 0xFF ) >= FRAMES_IN_A_SECOND ) ||
( ( ( ENDING_MSF >> 8 ) & 0xFF ) >= SECONDS_IN_A_MINUTE ) )
{
ERROR_LOG ( ( "ENDING_MSF = %x not valid \n", ENDING_MSF ) );
return false;
}
if ( STARTING_MSF > ENDING_MSF )
{
ERROR_LOG ( ( "STARTING_MSF > ENDING_MSF : %x, %x\n",
STARTING_MSF, ENDING_MSF ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_PLAY_AUDIO_MSF,
0x00,
0x00,
( STARTING_MSF >> 16 ) & 0xFF,
( STARTING_MSF >> 8 ) & 0xFF,
STARTING_MSF & 0xFF,
( ENDING_MSF >> 16 ) & 0xFF,
( ENDING_MSF >> 8 ) & 0xFF,
ENDING_MSF & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::PLAY_CD (
SCSITask * request,
SCSICmdField3Bit EXPECTED_SECTOR_TYPE,
SCSICmdField1Bit CMSF,
SCSICmdField4Byte STARTING_LOGICAL_BLOCK_ADDRESS,
SCSICmdField4Byte PLAY_LENGTH_IN_BLOCKS,
SCSICmdField1Bit SPEED,
SCSICmdField1Bit PORT2,
SCSICmdField1Bit PORT1,
SCSICmdField1Bit COMPOSITE,
SCSICmdField1Bit AUDIO,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::PLAY_CD *OBSOLETE* called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( EXPECTED_SECTOR_TYPE > 5 )
{
ERROR_LOG ( ( "EXPECTED_SECTOR_TYPE = %x not valid \n",
EXPECTED_SECTOR_TYPE ) );
return false;
}
if ( CMSF == 0 )
{
STATUS_LOG ( ( "Using LBA Addressing Mode\n" ) );
if ( IsParameterValid ( STARTING_LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "STARTING_LOGICAL_BLOCK_ADDRESS = %x not valid \n",
STARTING_LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( PLAY_LENGTH_IN_BLOCKS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "PLAY_LENGTH_IN_BLOCKS = %x not valid \n",
PLAY_LENGTH_IN_BLOCKS ) );
return false;
}
}
else
{
STATUS_LOG ( ( "Using MSF Addressing Mode\n" ) );
if ( IsParameterValid ( STARTING_LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask3Byte ) == false )
{
ERROR_LOG ( ( "STARTING_LOGICAL_BLOCK_ADDRESS = %x not valid \n",
STARTING_LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( ( ( STARTING_LOGICAL_BLOCK_ADDRESS & 0xFF ) >= FRAMES_IN_A_SECOND ) ||
( ( ( STARTING_LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF ) >= SECONDS_IN_A_MINUTE ) )
{
ERROR_LOG ( ( "STARTING_LOGICAL_BLOCK_ADDRESS = %x not valid \n",
STARTING_LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( PLAY_LENGTH_IN_BLOCKS >> 8,
kSCSICmdFieldMask3Byte ) == false )
{
ERROR_LOG ( ( "PLAY_LENGTH_IN_BLOCKS = %x not valid \n",
PLAY_LENGTH_IN_BLOCKS ) );
return false;
}
if ( ( ( PLAY_LENGTH_IN_BLOCKS >> 8 & 0xFF ) >= FRAMES_IN_A_SECOND ) ||
( ( ( PLAY_LENGTH_IN_BLOCKS >> 16 ) & 0xFF ) >= SECONDS_IN_A_MINUTE ) )
{
ERROR_LOG ( ( "PLAY_LENGTH_IN_BLOCKS = %x not valid \n",
PLAY_LENGTH_IN_BLOCKS ) );
return false;
}
}
if ( IsParameterValid ( SPEED, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "SPEED = %x not valid \n", SPEED ) );
return false;
}
if ( IsParameterValid ( PORT2, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "PORT2 = %x not valid \n", PORT2 ) );
return false;
}
if ( IsParameterValid ( PORT1, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "PORT1 = %x not valid \n", PORT1 ) );
return false;
}
if ( IsParameterValid ( COMPOSITE, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "COMPOSITE = %x not valid \n", COMPOSITE ) );
return false;
}
if ( IsParameterValid ( AUDIO, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "AUDIO = %x not valid \n", AUDIO ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( CMSF == 0 )
{
SetCommandDescriptorBlock ( request,
kSCSICmd_PLAY_CD,
( EXPECTED_SECTOR_TYPE << 2 ) | ( CMSF << 1 ),
( STARTING_LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
STARTING_LOGICAL_BLOCK_ADDRESS & 0xFF,
( PLAY_LENGTH_IN_BLOCKS >> 24 ) & 0xFF,
( PLAY_LENGTH_IN_BLOCKS >> 16 ) & 0xFF,
( PLAY_LENGTH_IN_BLOCKS >> 8 ) & 0xFF,
PLAY_LENGTH_IN_BLOCKS & 0xFF,
( SPEED << 7 ) | ( PORT2 << 3 ) | ( PORT1 << 2 ) | ( COMPOSITE << 1 ) | AUDIO,
CONTROL );
}
else
{
SetCommandDescriptorBlock ( request,
kSCSICmd_PLAY_CD,
( EXPECTED_SECTOR_TYPE << 2 ) | ( CMSF << 1 ),
0x00,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
STARTING_LOGICAL_BLOCK_ADDRESS & 0xFF,
( PLAY_LENGTH_IN_BLOCKS >> 24 ) & 0xFF,
( PLAY_LENGTH_IN_BLOCKS >> 16 ) & 0xFF,
( PLAY_LENGTH_IN_BLOCKS >> 8 ) & 0xFF,
0x00,
( SPEED << 7 ) | ( PORT2 << 3 ) | ( PORT1 << 2 ) | ( COMPOSITE << 1 ) | AUDIO,
CONTROL );
}
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::READ_BUFFER_CAPACITY (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_BUFFER_CAPACITY *OBSOLETE* called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_BUFFER_CAPACITY,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::READ_CD (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField3Bit EXPECTED_SECTOR_TYPE,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte STARTING_LOGICAL_BLOCK_ADDRESS,
SCSICmdField3Byte TRANSFER_LENGTH,
SCSICmdField1Bit SYNC,
SCSICmdField2Bit HEADER_CODES,
SCSICmdField1Bit USER_DATA,
SCSICmdField1Bit EDC_ECC,
SCSICmdField2Bit ERROR_FIELD,
SCSICmdField3Bit SUBCHANNEL_SELECTION_BITS,
SCSICmdField1Byte CONTROL )
{
UInt32 blockSize;
UInt32 requestedByteCount;
bool validBlockSize;
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_CD called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( RELADR != 0 )
{
ERROR_LOG ( ( "RELADR = %x not valid \n", RELADR ) );
return false;
}
if ( IsParameterValid ( STARTING_LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "STARTING_LOGICAL_BLOCK_ADDRESS = %x not valid \n",
STARTING_LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( TRANSFER_LENGTH, kSCSICmdFieldMask3Byte ) == false )
{
ERROR_LOG ( ( "TRANSFER_LENGTH = %x not valid \n",
TRANSFER_LENGTH ) );
return false;
}
if ( IsParameterValid ( SUBCHANNEL_SELECTION_BITS,
kSCSICmdFieldMask3Bit ) == false )
{
ERROR_LOG ( ( "SUBCHANNEL_SELECTION_BITS = %x not valid \n",
SUBCHANNEL_SELECTION_BITS ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
validBlockSize = GetBlockSize ( &blockSize,
EXPECTED_SECTOR_TYPE,
SYNC,
HEADER_CODES,
USER_DATA,
EDC_ECC,
ERROR_FIELD );
if ( validBlockSize == false )
{
ERROR_LOG ( ( "blockSize = %x not valid \n", blockSize ) );
return false;
}
requestedByteCount = TRANSFER_LENGTH * blockSize;
STATUS_LOG ( ( "blockSize = %ld\n", blockSize ) );
STATUS_LOG ( ( "TRANSFER_LENGTH = %ld\n", TRANSFER_LENGTH ) );
STATUS_LOG ( ( "requestedByteCount = %ld\n", requestedByteCount ) );
if ( IsBufferAndCapacityValid ( dataBuffer, requestedByteCount ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, requestedByteCount = %ld\n",
dataBuffer, requestedByteCount ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_CD,
( EXPECTED_SECTOR_TYPE << 2 ) | RELADR,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( STARTING_LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
STARTING_LOGICAL_BLOCK_ADDRESS & 0xFF,
( TRANSFER_LENGTH >> 16 ) & 0xFF,
( TRANSFER_LENGTH >> 8 ) & 0xFF,
TRANSFER_LENGTH & 0xFF,
( SYNC << 7 ) | ( HEADER_CODES << 5 ) | ( USER_DATA << 4 ) | ( EDC_ECC << 3 ) | ( ERROR_FIELD << 1 ),
SUBCHANNEL_SELECTION_BITS,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
requestedByteCount );
return true;
}
bool
SCSIMultimediaCommands::READ_CD_MSF (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField3Bit EXPECTED_SECTOR_TYPE,
SCSICmdField3Byte STARTING_MSF,
SCSICmdField3Byte ENDING_MSF,
SCSICmdField1Bit SYNC,
SCSICmdField2Bit HEADER_CODES,
SCSICmdField1Bit USER_DATA,
SCSICmdField1Bit EDC_ECC,
SCSICmdField2Bit ERROR_FIELD,
SCSICmdField3Bit SUBCHANNEL_SELECTION_BITS,
SCSICmdField1Byte CONTROL )
{
UInt32 blockSize;
UInt32 requestedByteCount;
bool validBlockSize;
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_CD_MSF called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( STARTING_MSF,
kSCSICmdFieldMask3Byte ) == false )
{
ERROR_LOG ( ( "STARTING_MSF = %x not valid \n",
STARTING_MSF ) );
return false;
}
if ( ( ( STARTING_MSF & 0xFF ) >= FRAMES_IN_A_SECOND ) ||
( ( ( STARTING_MSF >> 8 ) & 0xFF ) >= SECONDS_IN_A_MINUTE ) )
{
ERROR_LOG ( ( "STARTING_MSF = %x not valid \n",
STARTING_MSF ) );
return false;
}
if ( IsParameterValid ( ENDING_MSF,
kSCSICmdFieldMask3Byte ) == false )
{
ERROR_LOG ( ( "ENDING_MSF = %x not valid \n",
ENDING_MSF ) );
return false;
}
if ( ( ( ENDING_MSF & 0xFF ) >= FRAMES_IN_A_SECOND ) ||
( ( ( ENDING_MSF >> 8 ) & 0xFF ) >= SECONDS_IN_A_MINUTE ) )
{
ERROR_LOG ( ( "ENDING_MSF = %x not valid \n",
ENDING_MSF ) );
return false;
}
if ( STARTING_MSF > ENDING_MSF )
{
ERROR_LOG ( ( "STARTING_MSF > ENDING_MSF : %x %x\n",
STARTING_MSF, ENDING_MSF ) );
return false;
}
if ( IsParameterValid ( SUBCHANNEL_SELECTION_BITS,
kSCSICmdFieldMask3Bit ) == false )
{
ERROR_LOG ( ( "SUBCHANNEL_SELECTION_BITS = %x not valid \n",
SUBCHANNEL_SELECTION_BITS ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
validBlockSize = GetBlockSize ( &blockSize,
EXPECTED_SECTOR_TYPE,
SYNC,
HEADER_CODES,
USER_DATA,
EDC_ECC,
ERROR_FIELD );
if ( validBlockSize == false )
{
ERROR_LOG ( ( "blockSize = %x not valid \n", blockSize ) );
return false;
}
requestedByteCount = ( ConvertMSFToLBA ( ENDING_MSF ) -
ConvertMSFToLBA ( STARTING_MSF ) ) * blockSize;
STATUS_LOG ( ( "requestedByteCount = %x\n", requestedByteCount ) );
if ( IsBufferAndCapacityValid ( dataBuffer,
requestedByteCount ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, requestedByteCount = %ld\n",
dataBuffer, requestedByteCount ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_CD_MSF,
EXPECTED_SECTOR_TYPE << 2,
0x00,
( STARTING_MSF >> 16 ) & 0xFF,
( STARTING_MSF >> 8 ) & 0xFF,
STARTING_MSF & 0xFF,
( ENDING_MSF >> 16 ) & 0xFF,
( ENDING_MSF >> 8 ) & 0xFF,
ENDING_MSF & 0xFF,
( SYNC << 7 ) | ( HEADER_CODES << 5 ) | ( USER_DATA << 4 ) | ( EDC_ECC << 3 ) | ( ERROR_FIELD << 1 ),
SUBCHANNEL_SELECTION_BITS,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
requestedByteCount );
return true;
}
bool
SCSIMultimediaCommands::READ_CAPACITY (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField1Bit PMI,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_CAPACITY called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( RELADR != 0 )
{
ERROR_LOG ( ( "RELADR = %x not valid \n", RELADR ) );
return false;
}
if ( LOGICAL_BLOCK_ADDRESS != 0 )
{
ERROR_LOG ( ( "LOGICAL_BLOCK_ADDRESS = %x not valid \n",
LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( PMI != 0 )
{
ERROR_LOG ( ( "PMI = %x not valid \n", PMI ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
READ_CAPACITY_MAX_DATA ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, READ_CAPACITY_MAX_DATA = %ld\n",
dataBuffer, READ_CAPACITY_MAX_DATA ) );
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,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
READ_CAPACITY_MAX_DATA );
return true;
}
bool
SCSIMultimediaCommands::READ_DISC_INFORMATION (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_DISC_INFORMATION called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_DISC_INFORMATION,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::READ_DVD_STRUCTURE (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField4Byte ADDRESS,
SCSICmdField1Byte LAYER_NUMBER,
SCSICmdField1Byte FORMAT,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField2Bit AGID,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_DVD_STRUCTURE called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "ADDRESS = %x not valid \n", ADDRESS ) );
return false;
}
if ( IsParameterValid ( LAYER_NUMBER,
kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "LAYER_NUMBER = %x not valid \n",
LAYER_NUMBER ) );
return false;
}
if ( IsParameterValid ( FORMAT, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "FORMAT = %x not valid \n", FORMAT ) );
return false;
}
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( AGID, kSCSICmdFieldMask2Bit ) == false )
{
ERROR_LOG ( ( "AGID = %x not valid \n", AGID ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_DVD_STRUCTURE,
0x00,
( ADDRESS >> 24 ) & 0xFF,
( ADDRESS >> 16 ) & 0xFF,
( ADDRESS >> 8 ) & 0xFF,
ADDRESS & 0xFF,
LAYER_NUMBER,
FORMAT,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
AGID << 6,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::READ_FORMAT_CAPACITIES (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_FORMAT_CAPACITIES called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_FORMAT_CAPACITIES,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::READ_HEADER (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField1Bit MSF,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_HEADER *OBSOLETE* called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( MSF, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "MSF = %x not valid \n", MSF ) );
return false;
}
if ( IsParameterValid ( LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "LOGICAL_BLOCK_ADDRESS = %x not valid \n",
LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_HEADER,
MSF << 1,
( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
LOGICAL_BLOCK_ADDRESS & 0xFF,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::READ_MASTER_CUE (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField1Byte SHEET_NUMBER,
SCSICmdField3Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_MASTER_CUE *OBSOLETE* called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( SHEET_NUMBER,
kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "SHEET_NUMBER = %x not valid \n",
SHEET_NUMBER ) );
return false;
}
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask3Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_MASTER_CUE,
0x00,
0x00,
0x00,
SHEET_NUMBER,
0x00,
( ALLOCATION_LENGTH >> 16 ) & 0xFF,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::READ_SUB_CHANNEL (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField1Bit MSF,
SCSICmdField1Bit SUBQ,
SCSICmdField1Byte SUB_CHANNEL_PARAMETER_LIST,
SCSICmdField1Byte TRACK_NUMBER,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_SUB_CHANNEL called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( MSF, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "MSF = %x not valid \n", MSF ) );
return false;
}
if ( IsParameterValid ( SUBQ, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "SUBQ = %x not valid \n", SUBQ ) );
return false;
}
if ( IsParameterValid ( SUB_CHANNEL_PARAMETER_LIST,
kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "SUB_CHANNEL_PARAMETER_LIST = %x not valid \n",
SUB_CHANNEL_PARAMETER_LIST ) );
return false;
}
if ( SUB_CHANNEL_PARAMETER_LIST == 3 )
{
if ( TRACK_NUMBER > MAX_TRACK_NUMBER )
{
ERROR_LOG ( ( "TRACK_NUMBER = %x not valid \n",
TRACK_NUMBER ) );
return false;
}
}
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_SUB_CHANNEL,
MSF << 1,
SUBQ << 6,
SUB_CHANNEL_PARAMETER_LIST,
0x00,
0x00,
( SUB_CHANNEL_PARAMETER_LIST == 3 ) ? TRACK_NUMBER : 0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::READ_TOC_PMA_ATIP (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField1Bit MSF,
SCSICmdField4Bit FORMAT,
SCSICmdField1Byte TRACK_SESSION_NUMBER,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_TOC_PMA_ATIP called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( MSF, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "MSF = %x not valid \n", MSF ) );
return false;
}
if ( ( FORMAT & kSCSICmdFieldMask4Bit ) > 5 )
{
ERROR_LOG ( ( "FORMAT = %x not valid \n", FORMAT ) );
return false;
}
if ( IsParameterValid ( TRACK_SESSION_NUMBER,
kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "TRACK_SESSION_NUMBER = %x not valid \n",
TRACK_SESSION_NUMBER ) );
return false;
}
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
if ( FORMAT <= 0x03 )
{
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_TOC_PMA_ATIP,
MSF << 1,
0x00,
0x00,
0x00,
0x00,
TRACK_SESSION_NUMBER,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
( FORMAT & 0x03 ) << 6 );
}
else
{
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_TOC_PMA_ATIP,
MSF << 1,
FORMAT,
0x00,
0x00,
0x00,
TRACK_SESSION_NUMBER,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
CONTROL );
}
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::READ_TRACK_INFORMATION (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField2Bit ADDRESS_NUMBER_TYPE,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS_TRACK_SESSION_NUMBER,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::READ_TRACK_INFORMATION called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( ADDRESS_NUMBER_TYPE,
kSCSICmdFieldMask2Bit ) == false )
{
ERROR_LOG ( ( "ADDRESS_NUMBER_TYPE = %x not valid \n",
ADDRESS_NUMBER_TYPE ) );
return false;
}
if ( IsParameterValid ( LOGICAL_BLOCK_ADDRESS_TRACK_SESSION_NUMBER,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "LOGICAL_BLOCK_ADDRESS_TRACK_SESSION_NUMBER = %x not valid \n",
LOGICAL_BLOCK_ADDRESS_TRACK_SESSION_NUMBER ) );
return false;
}
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_READ_TRACK_INFORMATION,
ADDRESS_NUMBER_TYPE,
( LOGICAL_BLOCK_ADDRESS_TRACK_SESSION_NUMBER >> 24 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS_TRACK_SESSION_NUMBER >> 16 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS_TRACK_SESSION_NUMBER >> 8 ) & 0xFF,
LOGICAL_BLOCK_ADDRESS_TRACK_SESSION_NUMBER & 0xFF,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::REPAIR_TRACK (
SCSITask * request,
SCSICmdField2Byte TRACK_NUMBER,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::REPAIR_TRACK *OBSOLETE* called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( TRACK_NUMBER,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "TRACK_NUMBER = %x not valid \n",
TRACK_NUMBER ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_REPAIR_TRACK,
0x00,
0x00,
0x00,
( TRACK_NUMBER >> 8 ) & 0xFF,
TRACK_NUMBER & 0xFF,
0x00,
0x00,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::REPORT_KEY (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte ALLOCATION_LENGTH,
SCSICmdField2Bit AGID,
SCSICmdField6Bit KEY_FORMAT,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::REPORT_KEY called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "LOGICAL_BLOCK_ADDRESS = %x not valid \n",
LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( ALLOCATION_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "ALLOCATION_LENGTH = %x not valid \n",
ALLOCATION_LENGTH ) );
return false;
}
if ( IsParameterValid ( AGID, kSCSICmdFieldMask2Bit ) == false )
{
ERROR_LOG ( ( "AGID = %x not valid \n", AGID ) );
return false;
}
if ( IsParameterValid ( KEY_FORMAT,
kSCSICmdFieldMask6Bit ) == false )
{
ERROR_LOG ( ( "KEY_FORMAT = %x not valid \n", KEY_FORMAT ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( KEY_FORMAT != 0x3F )
{
if ( IsBufferAndCapacityValid ( dataBuffer,
ALLOCATION_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, ALLOCATION_LENGTH = %ld\n",
dataBuffer, ALLOCATION_LENGTH ) );
return false;
}
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromTargetToInitiator,
dataBuffer,
ALLOCATION_LENGTH );
}
else
{
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
}
SetCommandDescriptorBlock ( request,
kSCSICmd_REPORT_KEY,
0x00,
( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
LOGICAL_BLOCK_ADDRESS & 0xFF,
0x00,
0x00,
( ALLOCATION_LENGTH >> 8 ) & 0xFF,
ALLOCATION_LENGTH & 0xFF,
( AGID << 6 ) | KEY_FORMAT,
CONTROL );
return true;
}
bool
SCSIMultimediaCommands::RESERVE_TRACK (
SCSITask * request,
SCSICmdField4Byte RESERVATION_SIZE,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::RESERVE_TRACK called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( RESERVATION_SIZE,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "RESERVATION_SIZE = %x not valid \n",
RESERVATION_SIZE ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_RESERVE_TRACK,
0x00,
0x00,
0x00,
0x00,
( RESERVATION_SIZE >> 24 ) & 0xFF,
( RESERVATION_SIZE >> 16 ) & 0xFF,
( RESERVATION_SIZE >> 8 ) & 0xFF,
RESERVATION_SIZE & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::SCAN (
SCSITask * request,
SCSICmdField1Bit DIRECT,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte SCAN_STARTING_ADDRESS_FIELD,
SCSICmdField2Bit TYPE,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::SCAN called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( DIRECT, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "DIRECT = %x not valid \n", DIRECT ) );
return false;
}
if ( RELADR != 0 )
{
ERROR_LOG ( ( "RELADR = %x not valid \n", RELADR ) );
return false;
}
switch ( TYPE )
{
case 0:
{
STATUS_LOG ( ( "Using LBA TYPE\n" ) );
if ( IsParameterValid ( SCAN_STARTING_ADDRESS_FIELD,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "SCAN_STARTING_ADDRESS_FIELD = %x not valid \n",
SCAN_STARTING_ADDRESS_FIELD ) );
return false;
}
break;
}
case 1:
{
STATUS_LOG ( ( "Using MSF TYPE\n" ) );
if ( IsParameterValid ( SCAN_STARTING_ADDRESS_FIELD,
kSCSICmdFieldMask3Byte ) == false )
{
ERROR_LOG ( ( "SCAN_STARTING_ADDRESS_FIELD = %x not valid \n",
SCAN_STARTING_ADDRESS_FIELD ) );
return false;
}
if ( ( ( SCAN_STARTING_ADDRESS_FIELD & 0xFF ) >= FRAMES_IN_A_SECOND ) ||
( ( ( SCAN_STARTING_ADDRESS_FIELD >> 8 ) & 0xFF ) >= SECONDS_IN_A_MINUTE ) )
{
ERROR_LOG ( ( "SCAN_STARTING_ADDRESS_FIELD = %x not valid \n",
SCAN_STARTING_ADDRESS_FIELD ) );
return false;
}
break;
}
case 2:
{
STATUS_LOG ( ( "Using Track Number TYPE\n" ) );
if ( SCAN_STARTING_ADDRESS_FIELD > MAX_TRACK_NUMBER )
{
ERROR_LOG ( ( "SCAN_STARTING_ADDRESS_FIELD = %x not valid \n",
SCAN_STARTING_ADDRESS_FIELD ) );
return false;
}
break;
}
default:
{
ERROR_LOG ( ( "TYPE = %x not valid \n", TYPE ) );
return false;
break;
}
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SCAN_MMC,
( DIRECT << 4 ) | RELADR,
( SCAN_STARTING_ADDRESS_FIELD >> 24 ) & 0xFF,
( SCAN_STARTING_ADDRESS_FIELD >> 16 ) & 0xFF,
( SCAN_STARTING_ADDRESS_FIELD >> 8 ) & 0xFF,
SCAN_STARTING_ADDRESS_FIELD & 0xFF,
0x00,
0x00,
0x00,
TYPE << 6,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::SEND_CUE_SHEET (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField3Byte CUE_SHEET_SIZE,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::SEND_CUE_SHEET called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( CUE_SHEET_SIZE,
kSCSICmdFieldMask3Byte ) == false )
{
ERROR_LOG ( ( "CUE_SHEET_SIZE = %x not valid \n",
CUE_SHEET_SIZE ) );
return false;
}
if ( CUE_SHEET_SIZE == 0 )
{
ERROR_LOG ( ( "CUE_SHEET_SIZE = %x not valid \n", CUE_SHEET_SIZE ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
CUE_SHEET_SIZE ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, CUE_SHEET_SIZE = %ld\n",
dataBuffer, CUE_SHEET_SIZE ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SEND_CUE_SHEET,
0x00,
0x00,
0x00,
0x00,
0x00,
( CUE_SHEET_SIZE >> 16 ) & 0xFF,
( CUE_SHEET_SIZE >> 8 ) & 0xFF,
CUE_SHEET_SIZE & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromInitiatorToTarget,
dataBuffer,
CUE_SHEET_SIZE );
return true;
}
bool
SCSIMultimediaCommands::SEND_DVD_STRUCTURE (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField1Byte FORMAT,
SCSICmdField2Byte STRUCTURE_DATA_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::SEND_DVD_STRUCTURE called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( FORMAT, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "FORMAT = %x not valid \n", FORMAT ) );
return false;
}
if ( IsParameterValid ( STRUCTURE_DATA_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "STRUCTURE_DATA_LENGTH = %x not valid \n",
STRUCTURE_DATA_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
STRUCTURE_DATA_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, STRUCTURE_DATA_LENGTH = %ld\n",
dataBuffer, STRUCTURE_DATA_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SEND_DVD_STRUCTURE,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
FORMAT,
( STRUCTURE_DATA_LENGTH >> 8 ) & 0xFF,
STRUCTURE_DATA_LENGTH & 0xFF,
0x00,
CONTROL );
if ( STRUCTURE_DATA_LENGTH == 0 )
{
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
}
else
{
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromInitiatorToTarget,
dataBuffer,
STRUCTURE_DATA_LENGTH );
}
return true;
}
bool
SCSIMultimediaCommands::SEND_EVENT (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField1Bit IMMED,
SCSICmdField2Byte PARAMETER_LIST_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::SEND_EVENT called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( IMMED, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "IMMED = %x not valid \n", IMMED ) );
return false;
}
if ( IsParameterValid ( PARAMETER_LIST_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "PARAMETER_LIST_LENGTH = %x not valid \n",
PARAMETER_LIST_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
PARAMETER_LIST_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, PARAMETER_LIST_LENGTH = %ld\n",
dataBuffer, PARAMETER_LIST_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SEND_EVENT,
IMMED,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
( PARAMETER_LIST_LENGTH >> 8 ) & 0xFF,
PARAMETER_LIST_LENGTH & 0xFF,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromInitiatorToTarget,
dataBuffer,
PARAMETER_LIST_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::SEND_KEY (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField2Byte PARAMETER_LIST_LENGTH,
SCSICmdField2Bit AGID,
SCSICmdField6Bit KEY_FORMAT,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::SEND_KEY called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( PARAMETER_LIST_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "PARAMETER_LIST_LENGTH = %x not valid \n",
PARAMETER_LIST_LENGTH ) );
return false;
}
if ( IsParameterValid ( AGID, kSCSICmdFieldMask2Bit ) == false )
{
ERROR_LOG ( ( "AGID = %x not valid \n", AGID ) );
return false;
}
if ( IsParameterValid ( KEY_FORMAT, kSCSICmdFieldMask6Bit ) == false )
{
ERROR_LOG ( ( "KEY_FORMAT = %x not valid \n", KEY_FORMAT ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( KEY_FORMAT != 0x3F )
{
if ( IsBufferAndCapacityValid ( dataBuffer,
PARAMETER_LIST_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, PARAMETER_LIST_LENGTH = %ld\n",
dataBuffer, PARAMETER_LIST_LENGTH ) );
return false;
}
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromInitiatorToTarget,
dataBuffer,
PARAMETER_LIST_LENGTH );
}
else
{
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SEND_KEY,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
( PARAMETER_LIST_LENGTH >> 8 ) & 0xFF,
PARAMETER_LIST_LENGTH & 0xFF,
( AGID << 6 ) | KEY_FORMAT,
CONTROL );
return true;
}
bool
SCSIMultimediaCommands::SEND_OPC_INFORMATION (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField1Bit DO_OPC,
SCSICmdField2Byte PARAMETER_LIST_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::SEND_OPC_INFORMATION called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( DO_OPC, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "DO_OPC = %x not valid \n", DO_OPC ) );
return false;
}
if ( IsParameterValid ( PARAMETER_LIST_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "PARAMETER_LIST_LENGTH = %x not valid \n",
PARAMETER_LIST_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
PARAMETER_LIST_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, PARAMETER_LIST_LENGTH = %ld\n",
dataBuffer, PARAMETER_LIST_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SEND_OPC_INFORMATION,
DO_OPC,
0x00,
0x00,
0x00,
0x00,
0x00,
( PARAMETER_LIST_LENGTH >> 8 ) & 0xFF,
PARAMETER_LIST_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromInitiatorToTarget,
dataBuffer,
PARAMETER_LIST_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::SET_CD_SPEED (
SCSITask * request,
SCSICmdField2Byte LOGICAL_UNIT_READ_SPEED,
SCSICmdField2Byte LOGICAL_UNIT_WRITE_SPEED,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::SET_CD_SPEED *OBSOLETE* called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( LOGICAL_UNIT_READ_SPEED,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "LOGICAL_UNIT_READ_SPEED = %x not valid \n",
LOGICAL_UNIT_READ_SPEED ) );
return false;
}
if ( IsParameterValid ( LOGICAL_UNIT_WRITE_SPEED,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "LOGICAL_UNIT_WRITE_SPEED = %x not valid \n",
LOGICAL_UNIT_WRITE_SPEED ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SET_CD_SPEED,
0x00,
( LOGICAL_UNIT_READ_SPEED >> 8 ) & 0xFF,
LOGICAL_UNIT_READ_SPEED & 0xFF,
( LOGICAL_UNIT_WRITE_SPEED >> 8 ) & 0xFF,
LOGICAL_UNIT_WRITE_SPEED & 0xFF,
0x00,
0x00,
0x00,
0x00,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::SET_READ_AHEAD (
SCSITask * request,
SCSICmdField4Byte TRIGGER_LOGICAL_BLOCK_ADDRESS,
SCSICmdField4Byte READ_AHEAD_LOGICAL_BLOCK_ADDRESS,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::SET_READ_AHEAD called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( TRIGGER_LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "TRIGGER_LOGICAL_BLOCK_ADDRESS = %x not valid \n",
TRIGGER_LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( READ_AHEAD_LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "READ_AHEAD_LOGICAL_BLOCK_ADDRESS = %x not valid \n",
READ_AHEAD_LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SET_READ_AHEAD,
0x00,
( TRIGGER_LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( TRIGGER_LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( TRIGGER_LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
TRIGGER_LOGICAL_BLOCK_ADDRESS & 0xFF,
( READ_AHEAD_LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( READ_AHEAD_LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( READ_AHEAD_LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
READ_AHEAD_LOGICAL_BLOCK_ADDRESS & 0xFF,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::SET_STREAMING (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
SCSICmdField2Byte PARAMETER_LIST_LENGTH,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::SET_STREAMING called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( PARAMETER_LIST_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "PARAMETER_LIST_LENGTH = %x not valid \n",
PARAMETER_LIST_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
if ( IsBufferAndCapacityValid ( dataBuffer,
PARAMETER_LIST_LENGTH ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, PARAMETER_LIST_LENGTH = %ld\n",
dataBuffer, PARAMETER_LIST_LENGTH ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SET_STREAMING,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
( PARAMETER_LIST_LENGTH >> 8 ) & 0xFF,
PARAMETER_LIST_LENGTH & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromInitiatorToTarget,
dataBuffer,
PARAMETER_LIST_LENGTH );
return true;
}
bool
SCSIMultimediaCommands::STOP_PLAY_SCAN (
SCSITask * request,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::STOP_PLAY_SCAN called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_STOP_PLAY_SCAN,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::SYNCHRONIZE_CACHE (
SCSITask * request,
SCSICmdField1Bit IMMED,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte NUMBER_OF_BLOCKS,
SCSICmdField1Byte CONTROL )
{
STATUS_LOG ( ( "SCSIMultimediaCommands::SYNCHRONIZE_CACHE called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( IsParameterValid ( IMMED, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "IMMED = %x not valid \n", IMMED ) );
return false;
}
if ( RELADR != 0 )
{
ERROR_LOG ( ( "RELADR = %x not valid \n", RELADR ) );
return false;
}
if ( LOGICAL_BLOCK_ADDRESS != 0 )
{
ERROR_LOG ( ( "LOGICAL_BLOCK_ADDRESS = %x not valid \n",
LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( NUMBER_OF_BLOCKS != 0 )
{
ERROR_LOG ( ( "NUMBER_OF_BLOCKS = %x not valid \n",
NUMBER_OF_BLOCKS ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_SYNCHRONIZE_CACHE,
( IMMED << 1 ) | RELADR,
( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF,
LOGICAL_BLOCK_ADDRESS & 0xFF,
0x00,
( NUMBER_OF_BLOCKS >> 8 ) & 0xFF,
NUMBER_OF_BLOCKS & 0xFF,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_NoDataTransfer );
return true;
}
bool
SCSIMultimediaCommands::WRITE_10 (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
UInt32 blockSize,
SCSICmdField1Bit DPO,
SCSICmdField1Bit FUA,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField2Byte TRANSFER_LENGTH,
SCSICmdField1Byte CONTROL )
{
UInt32 requestedByteCount;
STATUS_LOG ( ( "SCSIMultimediaCommands::WRITE_10 called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( blockSize == 0 )
{
ERROR_LOG ( ( "blockSize = %x not valid \n", blockSize ) );
return false;
}
if ( DPO != 0 )
{
ERROR_LOG ( ( "DPO = %x not valid \n", DPO ) );
return false;
}
if ( IsParameterValid ( FUA, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "FUA = %x not valid \n", FUA ) );
return false;
}
if ( RELADR != 0 )
{
ERROR_LOG ( ( "RELADR = %x not valid \n", RELADR ) );
return false;
}
if ( IsParameterValid ( LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "LOGICAL_BLOCK_ADDRESS = %x not valid \n",
LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( TRANSFER_LENGTH,
kSCSICmdFieldMask2Byte ) == false )
{
ERROR_LOG ( ( "TRANSFER_LENGTH = %x not valid \n",
TRANSFER_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
requestedByteCount = TRANSFER_LENGTH * blockSize;
if ( IsBufferAndCapacityValid ( dataBuffer,
requestedByteCount ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, requestedByteCount = %ld\n",
dataBuffer, requestedByteCount ) );
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,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromInitiatorToTarget,
dataBuffer,
requestedByteCount );
return true;
}
bool
SCSIMultimediaCommands::WRITE_AND_VERIFY_10 (
SCSITask * request,
IOMemoryDescriptor * dataBuffer,
UInt32 blockSize,
SCSICmdField1Bit DPO,
SCSICmdField1Bit BYT_CHK,
SCSICmdField1Bit RELADR,
SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS,
SCSICmdField4Byte TRANSFER_LENGTH,
SCSICmdField1Byte CONTROL )
{
UInt32 requestedByteCount;
STATUS_LOG ( ( "SCSIMultimediaCommands::WRITE_AND_VERIFY_10 called\n" ) );
DEBUG_ASSERT ( ( request != NULL ) );
if ( blockSize == 0 )
{
ERROR_LOG ( ( "blockSize = %x not valid \n", blockSize ) );
return false;
}
if ( DPO != 0 )
{
ERROR_LOG ( ( "DPO = %x not valid \n", DPO ) );
return false;
}
if ( BYT_CHK != 0 )
{
ERROR_LOG ( ( "BYT_CHK = %x not valid \n", BYT_CHK ) );
return false;
}
if ( RELADR != 0 )
{
ERROR_LOG ( ( "RELADR = %x not valid \n", RELADR ) );
return false;
}
if ( IsParameterValid ( LOGICAL_BLOCK_ADDRESS,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "LOGICAL_BLOCK_ADDRESS = %x not valid \n",
LOGICAL_BLOCK_ADDRESS ) );
return false;
}
if ( IsParameterValid ( TRANSFER_LENGTH,
kSCSICmdFieldMask4Byte ) == false )
{
ERROR_LOG ( ( "TRANSFER_LENGTH = %x not valid \n",
TRANSFER_LENGTH ) );
return false;
}
if ( IsParameterValid ( CONTROL, kSCSICmdFieldMask1Byte ) == false )
{
ERROR_LOG ( ( "CONTROL = %x not valid \n", CONTROL ) );
return false;
}
requestedByteCount = TRANSFER_LENGTH * blockSize;
if ( IsBufferAndCapacityValid ( dataBuffer,
requestedByteCount ) == false )
{
ERROR_LOG ( ( "dataBuffer = %x not valid, requestedByteCount = %ld\n",
dataBuffer, requestedByteCount ) );
return false;
}
SetCommandDescriptorBlock ( request,
kSCSICmd_WRITE_AND_VERIFY_10,
( DPO << 4 ) | ( BYT_CHK << 1 ) | 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,
CONTROL );
SetDataTransferControl ( request,
0,
kSCSIDataTransfer_FromInitiatorToTarget,
dataBuffer,
requestedByteCount );
return true;
}
bool
SCSIMultimediaCommands::GetBlockSize (
UInt32 * requestedByteCount,
SCSICmdField3Bit EXPECTED_SECTOR_TYPE,
SCSICmdField1Bit SYNC,
SCSICmdField2Bit HEADER_CODES,
SCSICmdField1Bit USER_DATA,
SCSICmdField1Bit EDC_ECC,
SCSICmdField2Bit ERROR_FIELD )
{
UInt32 userDataSize = 0;
UInt32 edcEccSize = 0;
UInt32 headerSize = 0;
UInt32 subHeaderSize = 0;
UInt32 syncSize = 0;
STATUS_LOG ( ( "SCSIMultimediaCommands::GetBlockSize called\n" ) );
DEBUG_ASSERT ( ( requestedByteCount != NULL ) );
if ( EXPECTED_SECTOR_TYPE > 5 )
{
ERROR_LOG ( ( "EXPECTED_SECTOR_TYPE = %x not valid \n",
EXPECTED_SECTOR_TYPE ) );
return false;
}
if ( IsParameterValid ( SYNC, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "SYNC = %x not valid \n", SYNC ) );
return false;
}
if ( IsParameterValid ( HEADER_CODES,
kSCSICmdFieldMask2Bit ) == false )
{
ERROR_LOG ( ( "HEADER_CODES = %x not valid \n",
HEADER_CODES ) );
return false;
}
if ( IsParameterValid ( USER_DATA,
kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "USER_DATA = %x not valid \n", USER_DATA ) );
return false;
}
if ( IsParameterValid ( EDC_ECC, kSCSICmdFieldMask1Bit ) == false )
{
ERROR_LOG ( ( "EDC_ECC = %x not valid \n", EDC_ECC ) );
return false;
}
if ( IsParameterValid ( ERROR_FIELD,
kSCSICmdFieldMask2Bit ) == false )
{
ERROR_LOG ( ( "ERROR_FIELD = %x not valid \n",
ERROR_FIELD ) );
return false;
}
switch ( ( SYNC << 4 ) | ( HEADER_CODES << 2 ) | ( USER_DATA << 1 ) | EDC_ECC )
{
case 0x00: case 0x01: case 0x05: case 0x09: case 0x0D: case 0x10: case 0x11: case 0x12: case 0x13: case 0x15: case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1D: {
ERROR_LOG ( ( "invalid flag combo\n" ) );
return false;
}
case 0x02: case 0x03: case 0x04: case 0x08: case 0x0A: case 0x0B: case 0x0C: case 0x0E: case 0x0F: case 0x14: case 0x1E: case 0x1F: {
break;
}
case 0x06: case 0x07: case 0x16: case 0x17: case 0x1C: {
if ( EXPECTED_SECTOR_TYPE > 3 )
{
ERROR_LOG ( ( "invalid flag combo for mode 2, form 1 and mode 2 form 2\n" ) );
return false;
}
break;
}
default:
{
return false;
}
}
headerSize = 4;
syncSize = 12;
switch ( EXPECTED_SECTOR_TYPE )
{
case 0: case 1: {
break;
}
case 2: {
userDataSize = 2048;
edcEccSize = 288;
subHeaderSize = 0;
break;
}
case 3: {
userDataSize = 2048 + 288;
edcEccSize = 0;
subHeaderSize = 0;
break;
}
case 4: {
userDataSize = 2048;
edcEccSize = 280;
subHeaderSize = 8;
break;
}
case 5: {
userDataSize = 2048 + 280;
edcEccSize = 0;
subHeaderSize = 8;
break;
}
default:
{
return false;
}
}
if ( ( EXPECTED_SECTOR_TYPE == 0 ) || ( EXPECTED_SECTOR_TYPE == 1 ) )
{
*requestedByteCount = 2352;
}
else
{
*requestedByteCount = 0;
if ( SYNC )
{
*requestedByteCount += syncSize;
}
if ( HEADER_CODES & 0x01 )
{
*requestedByteCount += headerSize;
}
if ( HEADER_CODES & 0x02 )
{
*requestedByteCount += subHeaderSize;
}
if ( USER_DATA )
{
*requestedByteCount += userDataSize;
}
if ( EDC_ECC )
{
*requestedByteCount += edcEccSize;
}
}
if ( ( ERROR_FIELD & 0x03 ) == 0x01 )
{
*requestedByteCount += C2_ERROR_BLOCK_DATA_SIZE;
}
else if ( ( ERROR_FIELD & 0x03 ) == 0x02 )
{
*requestedByteCount += C2_AND_BLOCK_ERROR_BITS_SIZE;
}
else if ( ERROR_FIELD != 0 )
{
ERROR_LOG ( ( "ERROR_FIELD is non-zero\n" ) );
return false;
}
return true;
}
SCSICmdField4Byte
SCSIMultimediaCommands::ConvertMSFToLBA (
SCSICmdField3Byte MSF )
{
SCSICmdField4Byte LBA;
STATUS_LOG ( ( "SCSIMultimediaCommands::ConvertMSFToLBA called\n" ) );
LBA = MSF >> 16; LBA *= SECONDS_IN_A_MINUTE; LBA += ( MSF >> 8 ) & 0xFF; LBA *= FRAMES_IN_A_SECOND; LBA += MSF & 0xFF;
if ( LBA < LBA_0_OFFSET )
{
ERROR_LOG ( ( "LBA was less than LBA_0_OFFSET, setting LBA to 0.\n" ) );
LBA = 0;
}
else
{
LBA -= LBA_0_OFFSET;
}
return LBA;
}