IOSCSIProtocolInterface.cpp [plain text]
#include <IOKit/scsi-commands/IOSCSIProtocolInterface.h>
#if ( SCSI_PROTOCOL_INTERFACE_DEBUGGING_LEVEL >= 1 )
#define PANIC_NOW(x) IOPanic x
#else
#define PANIC_NOW(x)
#endif
#if ( SCSI_PROTOCOL_INTERFACE_DEBUGGING_LEVEL >= 2 )
#define ERROR_LOG(x) IOLog x
#else
#define ERROR_LOG(x)
#endif
#if ( SCSI_PROTOCOL_INTERFACE_DEBUGGING_LEVEL >= 3 )
#define STATUS_LOG(x) IOLog x
#else
#define STATUS_LOG(x)
#endif
#define SERIAL_STATUS_LOG(x) STATUS_LOG(x)
#define super IOService
OSDefineMetaClass ( IOSCSIProtocolInterface, IOService );
OSDefineAbstractStructors ( IOSCSIProtocolInterface, IOService );
enum
{
kThreadDelayInterval = 500, k100SecondsInMicroSeconds = 100 * 1000 * 1000
};
bool
IOSCSIProtocolInterface::start ( IOService * provider )
{
IOWorkLoop * workLoop;
STATUS_LOG ( ( "IOSCSIProtocolInterface::start.\n" ) );
workLoop = getWorkLoop ( );
if ( workLoop != NULL )
{
fCommandGate = IOCommandGate::commandGate ( this );
if ( fCommandGate != NULL )
{
workLoop->addEventSource ( fCommandGate );
}
else
{
return false;
}
}
else
{
return false;
}
fPowerAckInProgress = false;
fPowerTransitionInProgress = false;
fPowerManagementInitialized = false;
fUserClientExclusiveControlled = false;
fPowerManagementThread = thread_call_allocate (
( thread_call_func_t ) IOSCSIProtocolInterface::sPowerManagement,
( thread_call_param_t ) this );
if ( fPowerManagementThread == NULL )
{
STATUS_LOG ( ( "%s::thread allocation failed.\n", getName ( ) ) );
return false;
}
return true;
}
void
IOSCSIProtocolInterface::free ( void )
{
IOWorkLoop * workLoop;
if ( fCommandGate != NULL )
{
workLoop = getWorkLoop ( );
if ( workLoop != NULL )
{
workLoop->removeEventSource ( fCommandGate );
}
fCommandGate->release ( );
fCommandGate = NULL;
}
if ( fPowerManagementThread != NULL )
{
thread_call_free ( fPowerManagementThread );
fPowerManagementThread = NULL;
}
super::free ( );
}
#pragma mark -
#pragma mark - Power Management Support
UInt32
IOSCSIProtocolInterface::initialPowerStateForDomainState ( IOPMPowerFlags flags )
{
STATUS_LOG ( ( "%s::%s\n", getName ( ), __FUNCTION__ ) );
return GetInitialPowerState ( );
}
void
IOSCSIProtocolInterface::InitializePowerManagement ( IOService * provider )
{
STATUS_LOG ( ( "IOSCSIProtocolInterface::InitializePowerManagement.\n" ) );
PMinit ( );
provider->joinPMtree ( this );
setIdleTimerPeriod ( 5 * 60 );
makeUsable ( );
fPowerManagementInitialized = true;
}
bool
IOSCSIProtocolInterface::IsPowerManagementIntialized ( void )
{
STATUS_LOG ( ( "IOSCSIProtocolInterface::IsPowerManagementIntialized.\n" ) );
return fPowerManagementInitialized;
}
bool
IOSCSIProtocolInterface::finalize ( IOOptionBits options )
{
STATUS_LOG ( ( "IOSCSIProtocolInterface::finalize this = %p\n", this ) );
if ( fPowerManagementInitialized )
{
bool powerTransistionStillInProgress = true;
for ( ; ; )
{
powerTransistionStillInProgress = ( bool ) fCommandGate->runAction ( ( IOCommandGate::Action )
&IOSCSIProtocolInterface::sGetPowerTransistionInProgress );
if ( powerTransistionStillInProgress )
{
IOSleep ( 1 );
}
else
{
break;
}
}
fCommandGate->commandWakeup ( &fCurrentPowerState, false );
fCommandGate->runAction ( ( IOCommandGate::Action )
&IOSCSIProtocolInterface::sGetPowerTransistionInProgress );
STATUS_LOG ( ( "PMstop about to be called.\n" ) );
PMstop ( );
if ( fPowerManagementThread != NULL )
{
thread_call_cancel ( fPowerManagementThread );
}
fPowerManagementInitialized = false;
}
return super::finalize ( options );
}
bool
IOSCSIProtocolInterface::sGetPowerTransistionInProgress ( IOSCSIProtocolInterface * self )
{
return ( self->fPowerTransitionInProgress );
}
IOReturn
IOSCSIProtocolInterface::setPowerState (
UInt32 powerStateOrdinal,
IOService * whichDevice )
{
SERIAL_STATUS_LOG ( ( "%s::%s called\n", getName ( ), __FUNCTION__ ) );
SERIAL_STATUS_LOG ( ( "powerStateOrdinal = %ld\n", powerStateOrdinal ) );
return fCommandGate->runAction ( ( IOCommandGate::Action )
&IOSCSIProtocolInterface::sHandleSetPowerState,
( void * ) powerStateOrdinal );
}
IOReturn
IOSCSIProtocolInterface::sHandleSetPowerState (
IOSCSIProtocolInterface * self,
UInt32 powerStateOrdinal )
{
IOReturn returnValue = 0;
if ( self->isInactive ( ) == false )
{
self->HandleSetPowerState ( powerStateOrdinal );
returnValue = k100SecondsInMicroSeconds;
}
return returnValue;
}
void
IOSCSIProtocolInterface::HandleSetPowerState ( UInt32 powerStateOrdinal )
{
AbsoluteTime time;
SERIAL_STATUS_LOG ( ( "%s::%s called\n", getName ( ), __FUNCTION__ ) );
fProposedPowerState = powerStateOrdinal;
if ( ( fPowerTransitionInProgress == false ) || fPowerAckInProgress )
{
STATUS_LOG ( ( "IOSCSIProtocolInterface::%s starting transition\n", __FUNCTION__ ) );
fPowerTransitionInProgress = true;
clock_interval_to_deadline ( kThreadDelayInterval, kMillisecondScale, &time );
( void ) thread_call_enter_delayed ( fPowerManagementThread, time );
}
STATUS_LOG ( ( "IOSCSIProtocolInterface::%s exiting\n", __FUNCTION__ ) );
}
void
IOSCSIProtocolInterface::sPowerManagement ( thread_call_param_t whichDevice )
{
IOSCSIProtocolInterface * self;
STATUS_LOG ( ( "IOSCSIProtocolInterface::sPowerManagement called\n" ) );
self = ( IOSCSIProtocolInterface * ) whichDevice;
if ( self != NULL && ( self->isInactive ( ) == false ) )
{
self->retain ( );
self->HandlePowerChange ( );
self->fPowerAckInProgress = true;
self->acknowledgeSetPowerState ( );
self->fPowerAckInProgress = false;
self->fPowerTransitionInProgress = false;
self->release ( );
}
else
{
self->fPowerTransitionInProgress = false;
}
}
void
IOSCSIProtocolInterface::CheckPowerState ( void )
{
SERIAL_STATUS_LOG ( ( "%s::%s called\n", getName ( ), __FUNCTION__ ) );
TicklePowerManager ( );
fCommandGate->runAction ( ( IOCommandGate::Action )
&IOSCSIProtocolInterface::sHandleCheckPowerState );
}
void
IOSCSIProtocolInterface::sHandleCheckPowerState ( IOSCSIProtocolInterface * self )
{
self->HandleCheckPowerState ( );
}
void
IOSCSIProtocolInterface::HandleCheckPowerState ( UInt32 maxPowerState )
{
STATUS_LOG ( ( "IOSCSIProtocolInterface::%s called\n", __FUNCTION__ ) );
while ( fCurrentPowerState != maxPowerState )
{
fCommandGate->commandSleep ( &fCurrentPowerState, THREAD_UNINT );
}
}
bool
IOSCSIProtocolInterface::TicklePowerManager ( UInt32 maxPowerState )
{
STATUS_LOG ( ( "IOSCSIProtocolInterface::%s called\n", __FUNCTION__ ) );
return ( activityTickle ( kIOPMSuperclassPolicy1, maxPowerState ) );
}
bool
IOSCSIProtocolInterface::GetUserClientExclusivityState ( void )
{
bool state;
fCommandGate->runAction ( ( IOCommandGate::Action )
&IOSCSIProtocolInterface::sGetUserClientExclusivityState,
( void * ) &state );
return state;
}
void
IOSCSIProtocolInterface::sGetUserClientExclusivityState ( IOSCSIProtocolInterface * self,
bool * state )
{
*state = self->HandleGetUserClientExclusivityState ( );
}
bool
IOSCSIProtocolInterface::HandleGetUserClientExclusivityState ( void )
{
STATUS_LOG ( ( "IOSCSIProtocolInterface::%s called\n", __FUNCTION__ ) );
return fUserClientExclusiveControlled;
}
IOReturn
IOSCSIProtocolInterface::SetUserClientExclusivityState ( IOService * userClient, bool state )
{
IOReturn status = kIOReturnExclusiveAccess;
fCommandGate->runAction ( ( IOCommandGate::Action )
&IOSCSIProtocolInterface::sSetUserClientExclusivityState,
( void * ) &status,
( void * ) userClient,
( void * ) state );
return status;
}
void
IOSCSIProtocolInterface::sSetUserClientExclusivityState ( IOSCSIProtocolInterface * self,
IOReturn * status,
IOService * userClient,
bool state )
{
*status = self->HandleSetUserClientExclusivityState ( userClient, state );
}
IOReturn
IOSCSIProtocolInterface::HandleSetUserClientExclusivityState ( IOService * userClient,
bool state )
{
IOReturn status = kIOReturnExclusiveAccess;
STATUS_LOG ( ( "IOSCSIProtocolInterface::%s called\n", __FUNCTION__ ) );
if ( fUserClient == NULL )
{
STATUS_LOG ( ( "fUserClient is NULL\n" ) );
if ( state != false )
{
STATUS_LOG ( ( "state is true\n" ) );
fUserClient = userClient;
fUserClientExclusiveControlled = state;
status = kIOReturnSuccess;
}
else
{
STATUS_LOG ( ( "state is false\n" ) );
status = kIOReturnBadArgument;
}
}
else if ( fUserClient == userClient )
{
STATUS_LOG ( ( "fUserClient is same as userClient\n" ) );
if ( state == false )
{
STATUS_LOG ( ( "state is false\n" ) );
fUserClient = NULL;
fUserClientExclusiveControlled = state;
status = kIOReturnSuccess;
}
status = kIOReturnSuccess;
}
STATUS_LOG ( ( "HandleSetUserClientExclusivityState status = %d\n", status ) );
return status;
}
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 1 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 2 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 3 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 4 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 5 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 6 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 7 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 8 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 9 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 10 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 11 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 12 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 13 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 14 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 15 );
OSMetaClassDefineReservedUnused( IOSCSIProtocolInterface, 16 );