IOFireWireUnit.cpp [plain text]
#define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme
#define DEBUGLOG kprintf
#include <IOKit/assert.h>
#include <IOKit/IOMessage.h>
#include <IOKit/firewire/IOFireWireUnit.h>
#include <IOKit/firewire/IOFireWireDevice.h>
#include <IOKit/firewire/IOFireWireController.h>
#include <IOKit/firewire/IOConfigDirectory.h>
#import <IOKit/firewire/IOFWSimpleContiguousPhysicalAddressSpace.h>
#include "FWDebugging.h"
OSDefineMetaClassAndStructors(IOFireWireUnitAux, IOFireWireNubAux);
OSMetaClassDefineReservedUnused(IOFireWireUnitAux, 0);
OSMetaClassDefineReservedUnused(IOFireWireUnitAux, 1);
OSMetaClassDefineReservedUnused(IOFireWireUnitAux, 2);
OSMetaClassDefineReservedUnused(IOFireWireUnitAux, 3);
#pragma mark -
bool IOFireWireUnitAux::init( IOFireWireUnit * primary )
{
bool success = true;
if( !IOFireWireNubAux::init( primary ) )
success = false;
if( success )
{
}
return success;
}
void IOFireWireUnitAux::free()
{
IOFireWireNubAux::free();
}
bool IOFireWireUnitAux::isPhysicalAccessEnabled( void )
{
IOFireWireUnit * unit = (IOFireWireUnit*)fPrimary;
IOFireWireDevice * device = unit->fDevice;
return device->isPhysicalAccessEnabled();
}
IOFWSimpleContiguousPhysicalAddressSpace * IOFireWireUnitAux::createSimpleContiguousPhysicalAddressSpace( vm_size_t size, IODirection direction )
{
IOFWSimpleContiguousPhysicalAddressSpace * space = IOFireWireNubAux::createSimpleContiguousPhysicalAddressSpace( size, direction );
if( space != NULL )
{
space->addTrustedNode( ((IOFireWireUnit*)fPrimary)->fDevice );
}
return space;
}
IOFWSimplePhysicalAddressSpace * IOFireWireUnitAux::createSimplePhysicalAddressSpace( vm_size_t size, IODirection direction )
{
IOFWSimplePhysicalAddressSpace * space = IOFireWireNubAux::createSimplePhysicalAddressSpace( size, direction );
if( space != NULL )
{
space->addTrustedNode( ((IOFireWireUnit*)fPrimary)->fDevice );
}
return space;
}
#pragma mark -
OSDefineMetaClassAndStructors(IOFireWireUnit, IOFireWireNub)
OSMetaClassDefineReservedUnused(IOFireWireUnit, 0);
OSMetaClassDefineReservedUnused(IOFireWireUnit, 1);
#pragma mark -
bool IOFireWireUnit::init( OSDictionary *propTable, IOConfigDirectory *directory )
{
if(!IOFireWireNub::init(propTable))
return false;
directory->retain();
fDirectory = directory;
return true;
}
IOFireWireNubAux * IOFireWireUnit::createAuxiliary( void )
{
IOFireWireUnitAux * auxiliary;
auxiliary = OSTypeAlloc( IOFireWireUnitAux );
if( auxiliary != NULL && !auxiliary->init(this) )
{
auxiliary->release();
auxiliary = NULL;
}
return auxiliary;
}
bool IOFireWireUnit::attach( IOService *provider )
{
fDevice = OSDynamicCast(IOFireWireDevice, provider);
if(!fDevice)
return false;
fDevice->retain();
if( !IOFireWireNub::attach(provider))
return (false);
fControl = fDevice->getController();
fControl->retain();
fDevice->getNodeIDGeneration(fGeneration, fNodeID, fLocalNodeID);
OSNumber * spec_id_number = (OSNumber*)getProperty( gFireWireUnit_Spec_ID );
OSNumber * sw_vers_number = (OSNumber*)getProperty( gFireWireUnit_SW_Version );
if( spec_id_number && sw_vers_number )
{
if( (spec_id_number->unsigned32BitValue() == kIOFWSpecID_AAPL) &&
(sw_vers_number->unsigned32BitValue() == kIOFWSWVers_KPF) )
{
fControl->enterLoggingMode();
}
}
return true;
}
void IOFireWireUnit::free()
{
if( fDevice != NULL )
{
fDevice->release();
fDevice = NULL;
}
IOFireWireNub::free();
}
IOReturn IOFireWireUnit::message( UInt32 mess,
IOService * provider,
void * argument )
{
if(provider == fDevice &&
(kIOMessageServiceIsRequestingClose == mess ||
kIOFWMessageServiceIsRequestingClose == mess))
{
fDevice->getNodeIDGeneration(fGeneration, fNodeID, fLocalNodeID);
if( isOpen() )
{
messageClients( mess );
}
return kIOReturnSuccess;
}
if(provider == fDevice &&
(kIOMessageServiceIsResumed == mess ||
kIOMessageServiceIsSuspended == mess))
{
fDevice->getNodeIDGeneration(fGeneration, fNodeID, fLocalNodeID);
messageClients( mess );
return kIOReturnSuccess;
}
if( kIOFWMessagePowerStateChanged == mess )
{
messageClients( mess );
return kIOReturnSuccess;
}
if( kIOFWMessageTopologyChanged == mess )
{
messageClients( mess );
return kIOReturnSuccess;
}
return IOService::message(mess, provider, argument );
}
bool IOFireWireUnit::matchPropertyTable( OSDictionary * table )
{
if (!IOFireWireNub::matchPropertyTable(table)) return false;
bool res = compareProperty(table, gFireWireUnit_Spec_ID) &&
compareProperty(table, gFireWireUnit_SW_Version) &&
compareProperty(table, gFireWireVendor_ID) &&
compareProperty(table, gFireWire_GUID);
return res;
}
#pragma mark -
bool IOFireWireUnit::handleOpen( IOService * forClient,
IOOptionBits options,
void * arg )
{
bool success = true;
if( isOpen() )
{
success = false;
}
if( success )
{
success = fDevice->open( this, options, arg );
}
if( success )
{
success = IOFireWireNub::handleOpen( forClient, options, arg );
}
return success;
}
void IOFireWireUnit::handleClose( IOService * forClient,
IOOptionBits options )
{
retain();
IOFireWireNub::handleClose(forClient, options);
fDevice->close( this, options );
if( getTerminationState() == kNeedsTermination )
{
setTerminationState( kTerminated );
retain();
thread_t thread;
if( kernel_thread_start((thread_continue_t)IOFireWireUnit::terminateUnitThreadFunc, this, &thread) == KERN_SUCCESS )
{
thread_deallocate(thread);
}
}
release();
}
void IOFireWireUnit::terminateUnit( void )
{
lockForArbitration();
retain();
if( isOpen() )
{
if( getTerminationState() == kNotTerminated )
{
setTerminationState( kNeedsTermination );
messageClients( kIOFWMessageServiceIsRequestingClose );
}
}
else
{
TerminationState state = getTerminationState();
FWKLOGASSERT( state != kNeedsTermination );
if( state == kNotTerminated )
{
setTerminationState( kTerminated );
retain();
thread_t thread;
if( kernel_thread_start((thread_continue_t)IOFireWireUnit::terminateUnitThreadFunc, this, &thread) == KERN_SUCCESS )
{
thread_deallocate(thread);
}
}
}
release();
unlockForArbitration();
}
void IOFireWireUnit::terminateUnitThreadFunc( void * refcon )
{
IOFireWireUnit *me = (IOFireWireUnit *)refcon;
FWKLOG(( "IOFireWireUnit::terminateUnitThreadFunc - entered terminate unit = 0x%08lx\n", me ));
me->fControl->closeGate();
me->lockForArbitration();
if( ( me->getTerminationState() == kTerminated) &&
!me->isInactive() && !me->isOpen() )
{
me->unlockForArbitration();
me->terminate();
}
else
{
me->unlockForArbitration();
}
me->fControl->openGate();
me->release();
FWKLOG(( "IOFireWireUnit::terminateUnitThreadFunc - exiting terminate unit = 0x%08lx\n", me ));
}
IOReturn IOFireWireUnit::setConfigDirectory( IOConfigDirectory * directory )
{
IOReturn status = kIOReturnSuccess;
TerminationState state = getTerminationState();
FWKLOGASSERT( state != kTerminated );
if( state == kNeedsTermination )
{
setTerminationState( kNotTerminated );
}
status = IOFireWireNub::setConfigDirectory( directory );
return status;
}
#pragma mark -
void IOFireWireUnit::setNodeFlags( UInt32 flags )
{
if( fDevice )
fDevice->setNodeFlags( flags );
}
void IOFireWireUnit::clearNodeFlags( UInt32 flags )
{
if( fDevice )
fDevice->clearNodeFlags( flags );
}
UInt32 IOFireWireUnit::getNodeFlags( void )
{
if( fDevice )
return fDevice->getNodeFlags();
else
return 0;
}
void IOFireWireUnit::setMaxSpeed( IOFWSpeed speed )
{
if( fDevice )
fDevice->setMaxSpeed( speed );
}
#pragma mark -
IOFWPhysicalAddressSpace * IOFireWireUnit::createPhysicalAddressSpace( IOMemoryDescriptor *mem )
{
IOFWPhysicalAddressSpace * space = fControl->createPhysicalAddressSpace(mem);
if( space != NULL )
{
space->addTrustedNode( fDevice );
}
return space;
}
IOFWPseudoAddressSpace * IOFireWireUnit::createPseudoAddressSpace( FWAddress * addr,
UInt32 len,
FWReadCallback reader,
FWWriteCallback writer,
void * refcon )
{
IOFWPseudoAddressSpace * space = fControl->createPseudoAddressSpace(addr, len, reader, writer, refcon);
if( space != NULL )
{
space->addTrustedNode( fDevice );
}
return space;
}