IOSCSIPeripheralDeviceNub.cpp [plain text]
#include <libkern/OSByteOrder.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IOMemoryDescriptor.h>
#include <IOKit/scsi-commands/SCSITask.h>
#include <IOKit/scsi-commands/SCSICmds_INQUIRY_Definitions.h>
#include <IOKit/scsi-commands/IOSCSIPeripheralDeviceNub.h>
#include "SCSITaskLib.h"
#include "SCSITaskLibPriv.h"
#include "SCSIPrimaryCommands.h"
#define DEBUG 0
#define DEBUG_ASSERT_COMPONENT_NAME_STRING "SCSI Peripheral Device Nub"
#if DEBUG
#define SCSI_PERIPHERAL_DEVICE_NUB_DEBUGGING_LEVEL 0
#endif
#include "IOSCSIArchitectureModelFamilyDebugging.h"
#if ( SCSI_PERIPHERAL_DEVICE_NUB_DEBUGGING_LEVEL >= 1 )
#define PANIC_NOW(x) IOPanic x
#else
#define PANIC_NOW(x)
#endif
#if ( SCSI_PERIPHERAL_DEVICE_NUB_DEBUGGING_LEVEL >= 2 )
#define ERROR_LOG(x) IOLog x
#else
#define ERROR_LOG(x)
#endif
#if ( SCSI_PERIPHERAL_DEVICE_NUB_DEBUGGING_LEVEL >= 3 )
#define STATUS_LOG(x) IOLog x
#else
#define STATUS_LOG(x)
#endif
#define super IOSCSIProtocolServices
OSDefineMetaClassAndStructors ( IOSCSIPeripheralDeviceNub, IOSCSIProtocolServices );
#define kMaxInquiryAttempts 8
#if 0
#pragma mark -
#pragma mark ₯ Public Methods
#pragma mark -
#endif
bool
IOSCSIPeripheralDeviceNub::init ( OSDictionary * propTable )
{
bool result = false;
require ( super::init ( propTable ), ErrorExit );
result = true;
ErrorExit:
return result;
}
bool
IOSCSIPeripheralDeviceNub::start ( IOService * provider )
{
OSDictionary * characterDict = NULL;
OSObject * obj = NULL;
bool result = false;
require ( super::start ( provider ), ErrorExit );
fProvider = OSDynamicCast ( IOSCSIPeripheralDeviceNub, provider );
require_quiet ( ( fProvider == NULL ), ErrorExit );
fProvider = OSDynamicCast ( IOSCSIProtocolInterface, provider );
require_nonzero_quiet ( fProvider, ErrorExit );
fSCSIPrimaryCommandObject = OSTypeAlloc ( SCSIPrimaryCommands );
require_nonzero ( fSCSIPrimaryCommandObject, ErrorExit );
require ( fProvider->open ( this ), ReleaseCommandObject );
STATUS_LOG ( ( "%s: Check for the SCSI Device Characteristics property from provider.\n", getName ( ) ) );
if ( ( fProvider->getProperty ( kIOPropertySCSIDeviceCharacteristicsKey ) ) == NULL )
{
STATUS_LOG ( ( "%s: No SCSI Device Characteristics property, set defaults.\n", getName ( ) ) );
fDefaultInquiryCount = 0;
}
else
{
STATUS_LOG ( ( "%s: Get the SCSI Device Characteristics property from provider.\n", getName ( ) ) );
characterDict = OSDynamicCast ( OSDictionary, ( fProvider->getProperty ( kIOPropertySCSIDeviceCharacteristicsKey ) ) );
STATUS_LOG ( ( "%s: set this SCSI Device Characteristics property.\n", getName ( ) ) );
setProperty ( kIOPropertySCSIDeviceCharacteristicsKey, characterDict );
STATUS_LOG ( ( "%s: check for the Inquiry Length property.\n", getName ( ) ) );
if ( characterDict->getObject ( kIOPropertySCSIInquiryLengthKey ) == NULL )
{
STATUS_LOG ( ( "%s: No Inquiry Length property, use default.\n", getName ( ) ) );
fDefaultInquiryCount = 0;
}
else
{
OSNumber * defaultInquiry;
STATUS_LOG ( ( "%s: Get Inquiry Length property.\n", getName ( ) ) );
defaultInquiry = OSDynamicCast ( OSNumber, characterDict->getObject ( kIOPropertySCSIInquiryLengthKey ) );
fDefaultInquiryCount = defaultInquiry->unsigned32BitValue ( );
}
}
STATUS_LOG ( ( "%s: default inquiry count is: %d\n", getName ( ), fDefaultInquiryCount ) );
require ( InterrogateDevice ( ), CloseProvider );
setProperty ( kIOMatchCategoryKey, kSCSITaskUserClientIniterKey );
characterDict = OSDynamicCast ( OSDictionary, fProvider->getProperty ( kIOPropertyProtocolCharacteristicsKey ) );
if ( characterDict == NULL )
{
characterDict = OSDictionary::withCapacity ( 1 );
}
else
{
characterDict->retain ( );
}
obj = fProvider->getProperty ( kIOPropertyPhysicalInterconnectTypeKey );
if ( obj != NULL )
{
characterDict->setObject ( kIOPropertyPhysicalInterconnectTypeKey, obj );
}
obj = fProvider->getProperty ( kIOPropertyPhysicalInterconnectLocationKey );
if ( obj != NULL )
{
characterDict->setObject ( kIOPropertyPhysicalInterconnectLocationKey, obj );
}
setProperty ( kIOPropertyProtocolCharacteristicsKey, characterDict );
characterDict->release ( );
registerService ( );
STATUS_LOG ( ( "%s: Registered and setup is complete\n", getName ( ) ) );
result = true;
return result;
CloseProvider:
fProvider->close ( this );
ReleaseCommandObject:
require_nonzero_quiet ( fSCSIPrimaryCommandObject, ErrorExit );
fSCSIPrimaryCommandObject->release ( );
fSCSIPrimaryCommandObject = NULL;
ErrorExit:
return result;
}
void
IOSCSIPeripheralDeviceNub::stop ( IOService * provider )
{
STATUS_LOG ( ("%s: stop called\n", getName( ) ) );
require_nonzero ( fProvider, ErrorExit );
require ( ( fProvider == provider ), ErrorExit );
require_nonzero ( fSCSIPrimaryCommandObject, ErrorExit );
fSCSIPrimaryCommandObject->release ( );
fSCSIPrimaryCommandObject = NULL;
super::stop ( provider );
ErrorExit:
return;
}
IOReturn
IOSCSIPeripheralDeviceNub::message ( UInt32 type,
IOService * nub,
void * arg )
{
IOReturn status = kIOReturnSuccess;
switch ( type )
{
case kIOMessageServiceIsRequestingClose:
{
STATUS_LOG ( ("%s: kIOMessageServiceIsRequestingClose called\n", getName( ) ) );
if ( fProvider )
{
STATUS_LOG ( ("%s: closing provider\n", getName( ) ) );
fProvider->close ( this );
}
}
break;
case kSCSIProtocolNotification_VerifyDeviceState:
{
messageClients ( kSCSIProtocolNotification_VerifyDeviceState, NULL, NULL );
status = kIOReturnSuccess;
}
break;
default:
{
STATUS_LOG ( ("%s: some message = %ld called\n", getName ( ), type ) );
status = super::message ( type, nub, arg );
}
break;
}
return status;
}
#if 0
#pragma mark -
#pragma mark ₯ Power Management Utility Methods
#pragma mark -
#endif
void
IOSCSIPeripheralDeviceNub::joinPMtree ( IOService * driver )
{
STATUS_LOG ( ( "%s%s::%s called%s\n", "\033[33m",
getName ( ), __FUNCTION__, "\033[0m" ) );
fProvider->joinPMtree ( driver );
STATUS_LOG ( ( "%s%s::%s finished%s\n", "\033[33m",
getName ( ), __FUNCTION__, "\033[0m" ) );
}
void
IOSCSIPeripheralDeviceNub::InitializePowerManagement ( IOService * provider )
{
STATUS_LOG ( ( "%s%s::%s not doing anything%s\n", "\033[33m",
getName ( ), __FUNCTION__, "\033[0m" ) );
}
#if 0
#pragma mark -
#pragma mark ₯ Property Table Utility Methods
#pragma mark -
#endif
bool
IOSCSIPeripheralDeviceNub::matchPropertyTable ( OSDictionary * table,
SInt32 * score )
{
bool returnValue = true;
bool isMatch = false;
SInt32 propertyScore = *score;
if ( propertyScore >= 5000 )
{
propertyScore = 4000;
}
if ( sCompareIOProperty ( this, table, kIOPropertySCSIPeripheralDeviceType, &isMatch ) )
{
if ( isMatch )
{
*score = kDefaultProbeRanking;
}
else
{
*score = kPeripheralDeviceTypeNoMatch;
returnValue = false;
}
if ( sCompareIOProperty ( this, table, kIOPropertySCSIVendorIdentification, &isMatch ) )
{
if ( isMatch )
{
*score = kFirstOrderRanking;
if ( sCompareIOProperty ( this, table,
kIOPropertySCSIProductIdentification, &isMatch ) )
{
if ( isMatch )
{
*score = kSecondOrderRanking;
if ( sCompareIOProperty ( this, table,
kIOPropertySCSIProductRevisionLevel, &isMatch ) )
{
if ( isMatch )
{
*score = kThirdOrderRanking;
}
else
{
*score = kPeripheralDeviceTypeNoMatch;
returnValue = false;
}
}
}
else
{
*score = kPeripheralDeviceTypeNoMatch;
returnValue = false;
}
}
}
else
{
*score = kPeripheralDeviceTypeNoMatch;
returnValue = false;
}
}
}
else
{
OSString * string;
string = OSDynamicCast ( OSString, table->getObject ( kIOMatchCategoryKey ) );
if ( string != NULL )
{
if ( strcmp ( string->getCStringNoCopy ( ), kIOPropertySCSITaskUserClientDevice ) )
{
*score = kDefaultProbeRanking - 100;
}
}
else
{
*score = kPeripheralDeviceTypeNoMatch;
returnValue = false;
}
}
if ( *score != 0 )
*score += propertyScore;
return returnValue;
}
bool
IOSCSIPeripheralDeviceNub::sCompareIOProperty (
IOService * object,
OSDictionary * table,
char * propertyKeyName,
bool * matches )
{
OSObject * tableObject = NULL;
OSObject * deviceObject = NULL;
bool returnValue = false;
*matches = false;
tableObject = table->getObject ( propertyKeyName );
deviceObject = object->getProperty ( propertyKeyName );
require_nonzero_quiet ( deviceObject, ErrorExit );
require_nonzero_quiet ( tableObject, ErrorExit );
returnValue = true;
*matches = deviceObject->isEqualTo ( tableObject );
ErrorExit:
return returnValue;
}
#if 0
#pragma mark -
#pragma mark ₯ Provided Services Methods
#pragma mark -
#endif
bool
IOSCSIPeripheralDeviceNub::SendSCSICommand (
SCSITaskIdentifier request,
SCSIServiceResponse * serviceResponse,
SCSITaskStatus * taskStatus )
{
return false;
}
SCSIServiceResponse
IOSCSIPeripheralDeviceNub::AbortSCSICommand ( SCSITaskIdentifier request )
{
return kSCSIServiceResponse_FUNCTION_REJECTED;
}
void
IOSCSIPeripheralDeviceNub::ExecuteCommand ( SCSITaskIdentifier request )
{
fProvider->ExecuteCommand ( request );
}
SCSIServiceResponse
IOSCSIPeripheralDeviceNub::AbortTask( UInt8 theLogicalUnit, SCSITaggedTaskIdentifier theTag )
{
return fProvider->AbortTask ( theLogicalUnit, theTag );
}
SCSIServiceResponse
IOSCSIPeripheralDeviceNub::AbortTaskSet( UInt8 theLogicalUnit )
{
return fProvider->AbortTaskSet ( theLogicalUnit );
}
SCSIServiceResponse
IOSCSIPeripheralDeviceNub::ClearACA( UInt8 theLogicalUnit )
{
return fProvider->ClearACA ( theLogicalUnit );
}
SCSIServiceResponse
IOSCSIPeripheralDeviceNub::ClearTaskSet( UInt8 theLogicalUnit )
{
return fProvider->ClearTaskSet( theLogicalUnit );
}
SCSIServiceResponse
IOSCSIPeripheralDeviceNub::LogicalUnitReset( UInt8 theLogicalUnit )
{
return fProvider->LogicalUnitReset( theLogicalUnit );
}
SCSIServiceResponse
IOSCSIPeripheralDeviceNub::TargetReset( void )
{
return fProvider->TargetReset();
}
SCSIServiceResponse
IOSCSIPeripheralDeviceNub::AbortCommand ( SCSITaskIdentifier abortTask )
{
return fProvider->AbortCommand ( abortTask );
}
bool
IOSCSIPeripheralDeviceNub::IsProtocolServiceSupported (
SCSIProtocolFeature feature,
void * serviceValue )
{
return fProvider->IsProtocolServiceSupported ( feature, serviceValue );
}
bool
IOSCSIPeripheralDeviceNub::HandleProtocolServiceFeature (
SCSIProtocolFeature feature,
void * serviceValue )
{
return fProvider->HandleProtocolServiceFeature ( feature, serviceValue );
}
#if 0
#pragma mark -
#pragma mark ₯ Private method declarations
#pragma mark -
#endif
void
IOSCSIPeripheralDeviceNub::TaskCallback ( SCSITaskIdentifier completedTask )
{
IOSyncer * fSyncLock = NULL;
SCSITask * scsiRequest = NULL;
SCSIServiceResponse serviceResponse;
STATUS_LOG ( ( "IOSCSIPeripheralDeviceNub::TaskCallback called\n.") );
scsiRequest = OSDynamicCast ( SCSITask, completedTask );
require_nonzero_string ( scsiRequest, ErrorExit, "SCSITask is NULL\n" );
fSyncLock = ( IOSyncer * ) scsiRequest->GetApplicationLayerReference ( );
require_nonzero_string ( fSyncLock, ErrorExit, "fSyncLock is NULL\n" );
serviceResponse = scsiRequest->GetServiceResponse ( );
fSyncLock->signal ( serviceResponse, false );
ErrorExit:
return;
}
SCSIServiceResponse
IOSCSIPeripheralDeviceNub::SendTask ( SCSITask * request )
{
SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
IOSyncer * fSyncLock = NULL;
fSyncLock = IOSyncer::create ( false );
require_nonzero_string ( fSyncLock, ErrorExit, "IOSyncer is NULL\n" );
fSyncLock->signal ( kIOReturnSuccess, false );
request->SetTaskCompletionCallback ( &IOSCSIPeripheralDeviceNub::TaskCallback );
request->SetApplicationLayerReference ( ( void * ) fSyncLock );
fSyncLock->reinit ( );
ExecuteCommand ( request );
serviceResponse = ( SCSIServiceResponse ) fSyncLock->wait ( false );
fSyncLock->release ( );
ErrorExit:
return serviceResponse;
}
bool
IOSCSIPeripheralDeviceNub::InterrogateDevice ( void )
{
OSString * string = NULL;
SCSICmd_INQUIRY_StandardData * inqData = NULL;
SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
SCSI_Sense_Data senseBuffer = { 0 };
IOMemoryDescriptor * bufferDesc = NULL;
SCSITask * request = NULL;
UInt8 inqDataCount = 0;
int index = 0;
bool result = false;
char tempString[17];
if ( fDefaultInquiryCount == 0 )
{
STATUS_LOG ( ( "%s: use sizeof(SCSICmd_INQUIRY_StandardData) for Inquiry.\n", getName ( ) ) );
inqDataCount = sizeof ( SCSICmd_INQUIRY_StandardData );
}
else
{
STATUS_LOG ( ( "%s: use fDefaultInquiryCount for Inquiry.\n", getName ( ) ) );
inqDataCount = fDefaultInquiryCount;
}
inqData = ( SCSICmd_INQUIRY_StandardData * ) IOMalloc ( inqDataCount );
require_nonzero ( inqData, ErrorExit );
bzero ( inqData, inqDataCount );
bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) inqData,
inqDataCount,
kIODirectionIn );
require_nonzero ( bufferDesc, ReleaseInquiryBuffer );
request = OSTypeAlloc ( SCSITask );
require_nonzero ( request, ReleaseBuffer );
request->ResetForNewTask ( );
fSCSIPrimaryCommandObject->TEST_UNIT_READY ( request, 0x00 );
serviceResponse = SendTask ( request );
if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
{
bool validSense = false;
if ( request->GetTaskStatus ( ) == kSCSITaskStatus_CHECK_CONDITION )
{
validSense = request->GetAutoSenseData ( &senseBuffer, sizeof ( senseBuffer ) );
if ( validSense == false )
{
request->ResetForNewTask ( );
fSCSIPrimaryCommandObject->REQUEST_SENSE ( request,
bufferDesc,
kSenseDefaultSize,
0 );
serviceResponse = SendTask ( request );
}
}
}
IOSleep ( 100 );
require ( ( isInactive ( ) == false ), ReleaseTask );
for ( index = 0; ( index < kMaxInquiryAttempts ) && ( isInactive ( ) == false ); index++ )
{
fSCSIPrimaryCommandObject->INQUIRY (
request,
bufferDesc,
0,
0,
0,
inqDataCount,
0 );
serviceResponse = SendTask ( request );
if ( ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) &&
( request->GetTaskStatus ( ) == kSCSITaskStatus_GOOD ) )
{
break;
}
else
{
IOSleep ( 1000 );
}
}
require ( ( index != kMaxInquiryAttempts ), ReleaseTask );
require ( isInactive ( ) == false, ReleaseTask );
setProperty ( kIOPropertySCSIPeripheralDeviceType,
( UInt64 ) ( inqData->PERIPHERAL_DEVICE_TYPE & kINQUIRY_PERIPHERAL_TYPE_Mask ),
kIOPropertySCSIPeripheralDeviceTypeSize );
for ( index = 0; index < kINQUIRY_VENDOR_IDENTIFICATION_Length; index++ )
{
tempString[index] = inqData->VENDOR_IDENTIFICATION[index];
}
tempString[index] = 0;
for ( index = kINQUIRY_VENDOR_IDENTIFICATION_Length - 1; index != 0; index-- )
{
if ( tempString[index] != ' ' )
{
tempString[index + 1] = '\0';
break;
}
}
string = OSString::withCString ( tempString );
if ( string != NULL )
{
setProperty ( kIOPropertySCSIVendorIdentification, string );
string->release ( );
}
for ( index = 0; index < kINQUIRY_PRODUCT_IDENTIFICATION_Length; index++ )
{
tempString[index] = inqData->PRODUCT_INDENTIFICATION[index];
}
tempString[index] = 0;
for ( index = kINQUIRY_PRODUCT_IDENTIFICATION_Length - 1; index != 0; index-- )
{
if ( tempString[index] != ' ' )
{
tempString[index+1] = '\0';
break;
}
}
string = OSString::withCString ( tempString );
if ( string != NULL )
{
setProperty ( kIOPropertySCSIProductIdentification, string );
string->release ( );
}
for ( index = 0; index < kINQUIRY_PRODUCT_REVISION_LEVEL_Length; index++ )
{
tempString[index] = inqData->PRODUCT_REVISION_LEVEL[index];
}
tempString[index] = 0;
for ( index = kINQUIRY_PRODUCT_REVISION_LEVEL_Length - 1; index != 0; index-- )
{
if ( tempString[index] != ' ' )
{
tempString[index+1] = '\0';
break;
}
}
string = OSString::withCString ( tempString );
if ( string != NULL )
{
setProperty ( kIOPropertySCSIProductRevisionLevel, string );
string->release ( );
}
result = true;
ReleaseTask:
require_nonzero_quiet ( request, ReleaseBuffer );
request->release ( );
request = NULL;
ReleaseBuffer:
require_nonzero_quiet ( bufferDesc, ReleaseInquiryBuffer );
bufferDesc->release ( );
bufferDesc = NULL;
ReleaseInquiryBuffer:
require_nonzero_quiet ( inqData, ErrorExit );
require_nonzero_quiet ( inqDataCount, ErrorExit );
IOFree ( ( void * ) inqData, inqDataCount );
inqData = NULL;
ErrorExit:
return result;
}
#if 0
#pragma mark -
#pragma mark ₯ VTable Padding
#pragma mark -
#endif
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 1 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 2 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 3 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 4 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 5 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 6 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 7 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 8 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 9 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 10 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 11 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 12 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 13 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 14 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 15 );
OSMetaClassDefineReservedUnused ( IOSCSIPeripheralDeviceNub, 16 );
#if 0
#pragma mark -
#pragma mark ₯ IOSCSILogicalUnitNub
#pragma mark -
#endif
OSDefineMetaClassAndStructors ( IOSCSILogicalUnitNub, IOSCSIPeripheralDeviceNub );
bool
IOSCSILogicalUnitNub::start ( IOService * provider )
{
OSDictionary * characterDict = NULL;
OSObject * obj = NULL;
bool result = false;
require ( super::start ( provider ), ErrorExit );
fProvider = OSDynamicCast ( IOSCSIPeripheralDeviceNub, provider );
require_nonzero_quiet ( ( fProvider == NULL ), ErrorExit );
fProvider = OSDynamicCast ( IOSCSIProtocolInterface, provider );
require_nonzero_quiet ( fProvider, ErrorExit );
fSCSIPrimaryCommandObject = OSTypeAlloc ( SCSIPrimaryCommands );
require_nonzero ( fSCSIPrimaryCommandObject, ErrorExit );
require ( fProvider->open ( this ), ReleaseCommandObject );
STATUS_LOG ( ( "%s: Check for the SCSI Device Characteristics property from provider.\n", getName ( ) ) );
if ( ( fProvider->getProperty ( kIOPropertySCSIDeviceCharacteristicsKey ) ) == NULL )
{
STATUS_LOG ( ( "%s: No SCSI Device Characteristics property, set defaults.\n", getName ( ) ) );
fDefaultInquiryCount = 0;
}
else
{
STATUS_LOG ( ( "%s: Get the SCSI Device Characteristics property from provider.\n", getName ( ) ) );
characterDict = OSDynamicCast ( OSDictionary, ( fProvider->getProperty ( kIOPropertySCSIDeviceCharacteristicsKey ) ) );
STATUS_LOG ( ( "%s: set this SCSI Device Characteristics property.\n", getName ( ) ) );
setProperty ( kIOPropertySCSIDeviceCharacteristicsKey, characterDict );
STATUS_LOG ( ( "%s: check for the Inquiry Length property.\n", getName ( ) ) );
if ( characterDict->getObject ( kIOPropertySCSIInquiryLengthKey ) == NULL )
{
STATUS_LOG ( ( "%s: No Inquiry Length property, use default.\n", getName ( ) ) );
fDefaultInquiryCount = 0;
}
else
{
OSNumber * defaultInquiry;
STATUS_LOG ( ( "%s: Get Inquiry Length property.\n", getName ( ) ) );
defaultInquiry = OSDynamicCast ( OSNumber, characterDict->getObject ( kIOPropertySCSIInquiryLengthKey ) );
fDefaultInquiryCount = defaultInquiry->unsigned32BitValue ( );
}
}
STATUS_LOG ( ( "%s: default inquiry count is: %d\n", getName ( ), fDefaultInquiryCount ) );
require ( InterrogateDevice ( ), CloseProvider );
setProperty ( kIOMatchCategoryKey, kSCSITaskUserClientIniterKey );
characterDict = OSDynamicCast ( OSDictionary, fProvider->getProperty ( kIOPropertyProtocolCharacteristicsKey ) );
if ( characterDict == NULL )
{
characterDict = OSDictionary::withCapacity ( 1 );
}
else
{
characterDict->retain ( );
}
obj = fProvider->getProperty ( kIOPropertyPhysicalInterconnectTypeKey );
if ( obj != NULL )
{
characterDict->setObject ( kIOPropertyPhysicalInterconnectTypeKey, obj );
}
obj = fProvider->getProperty ( kIOPropertyPhysicalInterconnectLocationKey );
if ( obj != NULL )
{
characterDict->setObject ( kIOPropertyPhysicalInterconnectLocationKey, obj );
}
setProperty ( kIOPropertyProtocolCharacteristicsKey, characterDict );
characterDict->release ( );
registerService ( );
STATUS_LOG ( ( "%s: Registered and setup is complete\n", getName ( ) ) );
result = true;
return result;
CloseProvider:
fProvider->close ( this );
ReleaseCommandObject:
require_nonzero_quiet ( fSCSIPrimaryCommandObject, ErrorExit );
fSCSIPrimaryCommandObject->release ( );
fSCSIPrimaryCommandObject = NULL;
ErrorExit:
return result;
}
void
IOSCSILogicalUnitNub::SetLogicalUnitNumber ( UInt8 newLUN )
{
OSNumber * logicalUnitNumber = NULL;
char unit[10];
STATUS_LOG ( ( "%s: SetLogicalUnitNumber to %d\n", getName ( ), newLUN ) );
fLogicalUnitNumber = newLUN;
sprintf ( unit, "%x", ( int ) fLogicalUnitNumber );
setLocation ( unit );
logicalUnitNumber = OSNumber::withNumber ( fLogicalUnitNumber, 64 );
if ( logicalUnitNumber != NULL )
{
setProperty ( kIOPropertySCSILogicalUnitNumberKey, logicalUnitNumber );
setProperty ( "IOUnit", logicalUnitNumber );
logicalUnitNumber->release ( );
logicalUnitNumber = NULL;
}
}
void
IOSCSILogicalUnitNub::ExecuteCommand ( SCSITaskIdentifier request )
{
STATUS_LOG ( ( "%s: ExecuteCommand for %d\n", getName ( ),
fLogicalUnitNumber ) );
if ( fLogicalUnitNumber != 0 )
{
SCSITask * scsiRequest;
scsiRequest = OSDynamicCast ( SCSITask, request );
if ( scsiRequest != NULL )
{
scsiRequest->SetLogicalUnitNumber ( fLogicalUnitNumber );
}
}
IOSCSIPeripheralDeviceNub::ExecuteCommand ( request );
}
SCSIServiceResponse
IOSCSILogicalUnitNub::AbortCommand ( SCSITaskIdentifier abortTask )
{
return IOSCSIPeripheralDeviceNub::AbortCommand ( abortTask );
}
#if 0
#pragma mark -
#pragma mark ₯ VTable Padding
#pragma mark -
#endif
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 1 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 2 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 3 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 4 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 5 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 6 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 7 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 8 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 9 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 10 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 11 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 12 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 13 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 14 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 15 );
OSMetaClassDefineReservedUnused ( IOSCSILogicalUnitNub, 16 );