SCSITargetDevicePathManager.cpp [plain text]
#include <libkern/c++/OSDictionary.h>
#include <libkern/c++/OSNumber.h>
#include <libkern/c++/OSString.h>
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
#include "SCSITargetDevicePathManager.h"
#include "SCSITaskDefinition.h"
#define DEBUG 0
#define DEBUG_ASSERT_COMPONENT_NAME_STRING "SCSITargetDevicePathManager"
#if DEBUG
#define SCSI_PATH_MANAGER_DEBUGGING_LEVEL 0
#endif
#include "IOSCSIArchitectureModelFamilyDebugging.h"
#if ( SCSI_PATH_MANAGER_DEBUGGING_LEVEL >= 1 )
#define PANIC_NOW(x) IOPanic x
#else
#define PANIC_NOW(x)
#endif
#if ( SCSI_PATH_MANAGER_DEBUGGING_LEVEL >= 2 )
#define ERROR_LOG(x) IOLog x
#else
#define ERROR_LOG(x)
#endif
#if ( SCSI_PATH_MANAGER_DEBUGGING_LEVEL >= 3 )
#define STATUS_LOG(x) IOLog x; IOSleep(1)
#else
#define STATUS_LOG(x)
#endif
#define super OSObject
OSDefineMetaClassAndStructors ( SCSITargetDevicePath, OSObject );
#define kIOPropertyBytesTransmittedKey "Bytes Transmitted"
#define kIOPropertyBytesReceivedKey "Bytes Received"
#define kIOPropertyCommandsProcessedKey "Commands Processed"
SCSITargetDevicePath *
SCSITargetDevicePath::Create ( SCSITargetDevicePathManager * manager,
IOSCSIProtocolServices * initialPath )
{
SCSITargetDevicePath * path = NULL;
STATUS_LOG ( ( "SCSITargetDevicePath::Create\n" ) );
path = OSTypeAlloc ( SCSITargetDevicePath );
require_nonzero ( path, ErrorExit );
require ( path->InitWithObjects ( manager, initialPath ), ReleasePath );
return path;
ReleasePath:
require_nonzero_quiet ( path, ErrorExit );
path->release ( );
path = NULL;
ErrorExit:
return path;
}
bool
SCSITargetDevicePath::InitWithObjects (
SCSITargetDevicePathManager * manager,
IOSCSIProtocolServices * interface )
{
OSNumber * number = NULL;
OSString * string = NULL;
UInt32 domainID = 0;
bool result = false;
STATUS_LOG ( ( "SCSITargetDevicePath::InitWithObjects\n" ) );
super::init ( );
fInterface = interface;
fPathManager = manager;
fStatistics = OSDictionary::withCapacity ( 4 );
require_nonzero ( fStatistics, ErrorExit );
fDomainIdentifier = GetInterfaceDomainIdentifier ( interface );
require_nonzero ( fDomainIdentifier, ReleaseStatistics );
domainID = fDomainIdentifier->unsigned32BitValue ( );
fDomainIdentifier = OSNumber::withNumber ( domainID, 32 );
fStatistics->setObject ( kIOPropertySCSIDomainIdentifierKey, fDomainIdentifier );
number = OSNumber::withNumber ( ( UInt64 ) 0, 64 );
require_nonzero ( number, ReleaseStatistics );
fBytesTransmitted = number;
fStatistics->setObject ( kIOPropertyBytesTransmittedKey, number );
number = OSNumber::withNumber ( ( UInt64 ) 0, 64 );
require_nonzero ( number, ReleaseStatistics );
fBytesReceived = number;
fStatistics->setObject ( kIOPropertyBytesReceivedKey, number );
number = OSNumber::withNumber ( ( UInt64 ) 0, 64 );
require_nonzero ( number, ReleaseStatistics );
fCommandsProcessed = number;
fStatistics->setObject ( kIOPropertyCommandsProcessedKey, number );
fStatus = kIOPropertyPortStatusLinkEstablishedKey;
string = OSString::withCStringNoCopy ( fStatus );
require_nonzero ( string, ReleaseStatistics );
fPathStatus = string;
fStatistics->setObject ( kIOPropertyPortStatusKey, string );
STATUS_LOG ( ( "stats has %ld entries\n", fStatistics->getCount ( ) ) );
result = true;
return result;
ReleaseStatistics:
require_nonzero_quiet ( fStatistics, ErrorExit );
fStatistics->release ( );
fStatistics = NULL;
ErrorExit:
return result;
}
OSNumber *
SCSITargetDevicePath::GetInterfaceDomainIdentifier (
const IOSCSIProtocolServices * interface )
{
OSDictionary * dict = NULL;
OSNumber * number = NULL;
OSObject * obj = NULL;
obj = interface->getProperty ( kIOPropertyProtocolCharacteristicsKey, gIOServicePlane );
dict = OSDynamicCast ( OSDictionary, obj );
require_nonzero ( dict, ErrorExit );
obj = dict->getObject ( kIOPropertySCSIDomainIdentifierKey );
number = OSDynamicCast ( OSNumber, obj );
require_nonzero ( number, ErrorExit );
ErrorExit:
return number;
}
void
SCSITargetDevicePath::Activate ( void )
{
fStatus = kIOPropertyPortStatusLinkEstablishedKey;
fPathStatus->initWithCStringNoCopy ( fStatus );
}
void
SCSITargetDevicePath::Inactivate ( void )
{
fStatus = kIOPropertyPortStatusNoLinkEstablishedKey;
fPathStatus->initWithCStringNoCopy ( fStatus );
}
void
SCSITargetDevicePath::free ( void )
{
STATUS_LOG ( ( "+SCSITargetDevicePath::free\n" ) );
if ( fStatistics != NULL )
{
fStatistics->release ( );
fStatistics = NULL;
}
if ( fDomainIdentifier != NULL )
{
fDomainIdentifier->release ( );
fDomainIdentifier = NULL;
}
if ( fBytesTransmitted != NULL )
{
fBytesTransmitted->release ( );
fBytesTransmitted = NULL;
}
if ( fBytesReceived != NULL )
{
fBytesReceived->release ( );
fBytesReceived = NULL;
}
if ( fCommandsProcessed != NULL )
{
fCommandsProcessed->release ( );
fCommandsProcessed = NULL;
}
if ( fPathStatus != NULL )
{
fPathStatus->release ( );
fPathStatus = NULL;
}
super::free ( );
STATUS_LOG ( ( "-SCSITargetDevicePath::free\n" ) );
}
#undef super
#define super OSObject
OSDefineMetaClass ( SCSITargetDevicePathManager, OSObject );
OSDefineAbstractStructors ( SCSITargetDevicePathManager, OSObject );
bool
SCSITargetDevicePathManager::InitializePathManagerForTarget (
IOSCSITargetDevice * target,
IOSCSIProtocolServices * initialPath )
{
bool result = false;
STATUS_LOG ( ( "SCSITargetDevicePathManager::InitializePathManagerForTarget\n" ) );
super::init ( );
fStatistics = OSArray::withCapacity ( 1 );
require_nonzero ( fStatistics, ErrorExit );
fTarget = target;
result = true;
return result;
ReleaseStats:
require_nonzero_quiet ( fStatistics, ReleaseStats );
fStatistics->release ( );
fStatistics = NULL;
ErrorExit:
return result;
}
void
SCSITargetDevicePathManager::PathTaskCallback ( SCSITaskIdentifier request )
{
SCSITargetDevicePath * path = NULL;
SCSITargetDevicePathManager * manager = NULL;
IOSCSITargetDevice * target = NULL;
STATUS_LOG ( ( "SCSITargetDevicePathManager::PathTaskCallback\n" ) );
path = ( SCSITargetDevicePath * ) GetPathLayerReference ( request );
require_nonzero_quiet ( path, ErrorExit );
manager = path->GetPathManager ( );
require_nonzero ( manager, ErrorExit );
manager->TaskCompletion ( request, path );
ErrorExit:
target = ( IOSCSITargetDevice * ) IOSCSITargetDevice::GetTargetLayerReference ( request );
target->TargetTaskCompletion ( request );
}
void
SCSITargetDevicePathManager::TaskCompletion ( SCSITaskIdentifier request,
SCSITargetDevicePath * path )
{
UInt64 bytes = 0;
IOSCSITargetDevice * target = NULL;
STATUS_LOG ( ( "SCSITargetDevicePathManager::TaskCompletion\n" ) );
target = ( IOSCSITargetDevice * ) IOSCSITargetDevice::GetTargetLayerReference ( request );
if ( IsTransmit ( request, target, &bytes ) == true )
{
STATUS_LOG ( ( "path->AddBytesTransmitted\n" ) );
path->AddBytesTransmitted ( bytes );
}
else if ( IsReceive ( request, target, &bytes ) == true )
{
STATUS_LOG ( ( "path->AddBytesReceived\n" ) );
path->AddBytesReceived ( bytes );
}
STATUS_LOG ( ( "path->IncrementCommandsProcessed\n" ) );
path->IncrementCommandsProcessed ( );
}
bool
SCSITargetDevicePathManager::IsTransmit ( SCSITaskIdentifier request,
IOSCSITargetDevice * target,
UInt64 * bytes )
{
bool result = false;
if ( target->GetDataTransferDirection ( request ) == kSCSIDataTransfer_FromInitiatorToTarget )
{
result = true;
*bytes = target->GetRealizedDataTransferCount ( request );
}
return result;
}
bool
SCSITargetDevicePathManager::IsReceive ( SCSITaskIdentifier request,
IOSCSITargetDevice * target,
UInt64 * bytes )
{
bool result = false;
if ( target->GetDataTransferDirection ( request ) == kSCSIDataTransfer_FromTargetToInitiator )
{
result = true;
*bytes = target->GetRealizedDataTransferCount ( request );
}
return result;
}
bool
SCSITargetDevicePathManager::SetPathLayerReference (
SCSITaskIdentifier request,
void * newReference )
{
SCSITask * scsiRequest = NULL;
bool result = NULL;
scsiRequest = OSDynamicCast ( SCSITask, request );
if ( scsiRequest != NULL )
{
result = scsiRequest->SetPathLayerReference ( newReference );
}
return result;
}
void *
SCSITargetDevicePathManager::GetPathLayerReference ( SCSITaskIdentifier request )
{
SCSITask * scsiRequest = NULL;
void * result = NULL;
scsiRequest = OSDynamicCast ( SCSITask, request );
if ( scsiRequest != NULL )
{
result = scsiRequest->GetPathLayerReference ( );
}
return result;
}
UInt64
SCSITargetDevicePathManager::GetRequestedDataTransferCount (
SCSITaskIdentifier request )
{
SCSITask * scsiRequest = NULL;
UInt64 result = NULL;
scsiRequest = OSDynamicCast ( SCSITask, request );
if ( scsiRequest != NULL )
{
result = scsiRequest->GetRequestedDataTransferCount ( );
}
return result;
}
void
SCSITargetDevicePathManager::free ( void )
{
STATUS_LOG ( ( "+SCSITargetDevicePathManager::free\n" ) );
if ( fStatistics != NULL )
{
fStatistics->release ( );
fStatistics = NULL;
}
super::free ( );
STATUS_LOG ( ( "-SCSITargetDevicePathManager::free\n" ) );
}