IOFireWireController.cpp [plain text]
#import <IOKit/firewire/IOFWUtils.h>
#import <IOKit/firewire/IOFireWireController.h>
#import <IOKit/firewire/IOLocalConfigDirectory.h>
#import <IOKit/firewire/IOFireWireNub.h>
#import <IOKit/firewire/IOFireWireDevice.h>
#import <IOKit/firewire/IOFWLocalIsochPort.h>
#import <IOKit/firewire/IOFWDCLProgram.h>
#import <IOKit/firewire/IOFireWirePowerManager.h>
#import <IOKit/firewire/IOFWSimpleContiguousPhysicalAddressSpace.h>
#import <IOKit/pwr_mgt/RootDomain.h>
#import <IOKit/firewire/IOFWAsyncStreamListener.h>
#import <IOKit/firewire/IOFWPHYPacketListener.h>
#import <IOKit/firewire/IOFWUserObjectExporter.h>
#import <IOKit/firewire/IOFireWireMultiIsochReceive.h>
#import "IOFWAsyncStreamReceiver.h"
#import <IOKit/firewire/IOFWWorkLoop.h>
#import <IOKit/firewire/IOFireWireLink.h>
#import "FWDebugging.h"
#import "IOFireWireLocalNode.h"
#import "IOFWQEventSource.h"
#import "IOFireWireIRM.h"
#include <IOKit/firewire/IOFWUtils.h>
#import <IOKit/IOKitKeys.h>
#import <IOKit/IOBufferMemoryDescriptor.h>
#import <IOKit/IODeviceTreeSupport.h>
#import <IOKit/IOMessage.h>
#import <IOKit/IOTimerEventSource.h>
#import <IOKit/IOKitKeysPrivate.h>
#include <sys/sysctl.h>
class FireWireGlobals
{
public:
FireWireGlobals ( void ); virtual ~FireWireGlobals ( void ); };
static int FireWireSysctl ( struct sysctl_oid * oidp, void * arg1, int arg2, struct sysctl_req * req );
static FireWireGlobals gFireWireGlobals; UInt32 gFireWireDebugFlags = 0; SYSCTL_PROC ( _debug, OID_AUTO, FireWire, CTLFLAG_RW, 0, 0, FireWireSysctl, "FireWire", "FireWire debug interface" );
static int FireWireSysctl ( struct sysctl_oid * oidp, void * arg1, int arg2, struct sysctl_req * req )
{
int error = 0;
FireWireSysctlArgs fwArgs;
DEBUG_UNUSED ( oidp );
DEBUG_UNUSED ( arg1 );
DEBUG_UNUSED ( arg2 );
error = SYSCTL_IN ( req, &fwArgs, sizeof ( fwArgs ) );
if ( ( error == 0 ) && ( fwArgs.type == kFireWireTypeDebug ) )
{
if ( fwArgs.operation == kFireWireOperationGetFlags )
{
fwArgs.debugFlags = gFireWireDebugFlags;
error = SYSCTL_OUT ( req, &fwArgs, sizeof ( fwArgs ) );
}
else if ( fwArgs.operation == kFireWireOperationSetFlags )
{
gFireWireDebugFlags = fwArgs.debugFlags;
}
}
return error;
}
FireWireGlobals::FireWireGlobals ( void )
{
int debugFlags;
if ( PE_parse_boot_argn ( "firewire", &debugFlags, sizeof ( debugFlags ) ) )
{
gFireWireDebugFlags = debugFlags;
}
sysctl_register_oid ( &sysctl__debug_FireWire );
}
FireWireGlobals::~FireWireGlobals ( void )
{
sysctl_unregister_oid ( &sysctl__debug_FireWire );
}
#define kScanBusDelay 100
#define kBusResetStartTimeout 35000
#define kBusResetTimeout 1000
#define kSelfIDTimeout 1000
#define kNormalDevicePruneDelay 1000
#define kRepeatResetDelay 2000
#define kOnlyNodeDevicePruneDelay 3000
#define kWakeDevicePruneDelay 15000
#define kWakeDevicePruneDelayBusy 30000
#define kDeviceMaximuPruneTime 45000
#define kFireWireGenerationID "FireWire Generation ID"
#define kFireWireLoggingMode "Logging Mode Enabled"
#define kFWBusScanInProgress "-1"
#define FWAddressToID(addr) (addr & 63)
enum requestRefConBits
{
kRequestLabel = kFWAsynchTTotal-1, kRequestExtTCodeShift = 6,
kRequestExtTCodeMask = 0x3fffc0, kRequestIsComplete = 0x20000000, kRequestIsLock = 0x40000000,
kRequestIsQuad = 0x80000000
};
enum
{
kFWInvalidPort = 0xffffffff
};
const OSSymbol *gFireWireROM;
const OSSymbol *gFireWireNodeID;
const OSSymbol *gFireWireSelfIDs;
const OSSymbol *gFireWireUnit_Spec_ID;
const OSSymbol *gFireWireUnit_SW_Version;
const OSSymbol *gFireWireVendor_ID;
const OSSymbol *gFireWire_GUID;
const OSSymbol *gFireWireSpeed;
const OSSymbol *gFireWireVendor_Name;
const OSSymbol *gFireWireProduct_Name;
const OSSymbol *gFireWireModel_ID;
const OSSymbol *gFireWireTDM;
const IORegistryPlane * IOFireWireBus::gIOFireWirePlane = NULL;
#if __ppc__
enum
{
kFWPMSleepState = 0,
kFWPMWakeState = 1
};
#else
enum
{
kFWPMSleepState = 0,
kFWPMWakeState = 2
};
#endif
OSDefineMetaClassAndStructors(IOFireWireDuplicateGUIDList, OSObject);
IOFireWireDuplicateGUIDList * IOFireWireDuplicateGUIDList::create( void )
{
IOFireWireDuplicateGUIDList * me;
me = OSTypeAlloc( IOFireWireDuplicateGUIDList );
return me;
}
void IOFireWireDuplicateGUIDList::free()
{
IOFWDuplicateGUIDRec * GUIDRec;
IOFWDuplicateGUIDRec * GUIDtoFree;
GUIDRec = fFirstGUID;
while( GUIDRec )
{
GUIDtoFree = GUIDRec;
GUIDRec = GUIDRec->fNextGUID;
IOFree( GUIDtoFree, sizeof( IOFWDuplicateGUIDRec ) );
}
OSObject::free();
}
void IOFireWireDuplicateGUIDList::addDuplicateGUID( CSRNodeUniqueID guid, UInt32 gen )
{
IOFWDuplicateGUIDRec * newGUID;
if( !guid || findDuplicateGUID( guid, gen ) )
return;
newGUID = (IOFWDuplicateGUIDRec *) IOMalloc( sizeof(IOFWDuplicateGUIDRec));
FWKLOG(("addDuplicateGUID adding GUID %08x %08x.\n",(unsigned int )(guid >> 32),(unsigned int )(guid & 0xffffffff)));
IOLog("FireWire Error: Devices with identical unique ID: %08x %08x cannot be used.\n",(unsigned int )(guid >> 32),(unsigned int )(guid & 0xffffffff));
newGUID->fGUID = guid;
newGUID->fLastGenSeen = gen;
newGUID->fNextGUID = fFirstGUID;
fFirstGUID = newGUID;
}
void IOFireWireDuplicateGUIDList::removeDuplicateGUID( CSRNodeUniqueID guid )
{
IOFWDuplicateGUIDRec * GUIDRec;
IOFWDuplicateGUIDRec * prevGUID;
GUIDRec = fFirstGUID;
prevGUID = NULL;
while( GUIDRec )
{
if( GUIDRec->fGUID == guid )
{
if( prevGUID )
prevGUID->fNextGUID = GUIDRec->fNextGUID;
else
fFirstGUID = GUIDRec->fNextGUID;
FWKLOG(("removeDuplicateGUID removing GUID %08x %08x.\n",(unsigned int )(guid >> 32),(unsigned int )(guid & 0xffffffff)));
IOFree( GUIDRec, sizeof( IOFWDuplicateGUIDRec ) );
break;
}
prevGUID = GUIDRec;
GUIDRec = GUIDRec->fNextGUID;
}
}
bool IOFireWireDuplicateGUIDList::findDuplicateGUID( CSRNodeUniqueID guid, UInt32 gen )
{
IOFWDuplicateGUIDRec * GUIDRec;
GUIDRec = fFirstGUID;
while( GUIDRec )
{
if( GUIDRec->fGUID == guid )
{
FWKLOG(("findDuplicateGUID found GUID %08x %08x.\n",(unsigned int )(guid >> 32),(unsigned int )(guid & 0xffffffff)));
GUIDRec->fLastGenSeen = gen;
return( true );
}
GUIDRec = GUIDRec->fNextGUID;
}
return( false );
}
OSDefineMetaClassAndStructors(IOFireWireControllerAux, IOFireWireBusAux);
OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 0);
OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 1);
OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 2);
OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 3);
OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 4);
OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 5);
OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 6);
OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 7);
#pragma mark -
bool IOFireWireControllerAux::init( IOFireWireController * primary )
{
bool success = true;
success = IOFireWireBusAux::init();
fPrimary = primary;
fSessionRefExporter = IOFWUserObjectExporter::createWithOwner( this );
if( !fSessionRefExporter )
success = false ;
return success;
}
void IOFireWireControllerAux::free()
{
if( fSessionRefExporter )
{
fSessionRefExporter->release();
fSessionRefExporter = NULL;
}
IOFireWireBusAux::free();
}
IOFWDCLPool *
IOFireWireControllerAux::createDCLPool ( unsigned capacity ) const
{
return fPrimary->getLink()->createDCLPool( capacity ) ;
}
UInt8 IOFireWireControllerAux::getMaxRec( void )
{
return fMaxRec;
}
UInt64 IOFireWireControllerAux::getFireWirePhysicalAddressMask( void )
{
return 0x00000000FFFFFFFFULL;
}
UInt32 IOFireWireControllerAux::getFireWirePhysicalAddressBits( void )
{
return 32;
}
UInt64 IOFireWireControllerAux::getFireWirePhysicalBufferMask( void )
{
return 0x00000000FFFFFFFFULL;
}
UInt32 IOFireWireControllerAux::getFireWirePhysicalBufferBits( void )
{
return 32;
}
IOFWSimpleContiguousPhysicalAddressSpace *
IOFireWireControllerAux::createSimpleContiguousPhysicalAddressSpace( vm_size_t size, IODirection direction )
{
IOFWSimpleContiguousPhysicalAddressSpace * space;
space = OSTypeAlloc( IOFWSimpleContiguousPhysicalAddressSpace );
if( !space )
return NULL;
if( !space->init( fPrimary, size, direction ) )
{
space->release();
space = NULL;
}
return space;
}
IOFWSimplePhysicalAddressSpace *
IOFireWireControllerAux::createSimplePhysicalAddressSpace( vm_size_t size, IODirection direction )
{
IOFWSimplePhysicalAddressSpace * space;
space = OSTypeAlloc( IOFWSimplePhysicalAddressSpace );
if( !space )
return NULL;
if( !space->init( fPrimary, size, direction ) )
{
space->release();
space = NULL;
}
return space;
}
IOFWUserObjectExporter * IOFireWireControllerAux::getSessionRefExporter( void )
{
return fSessionRefExporter;
}
#pragma mark -
OSDefineMetaClassAndStructors( IOFireWireController, IOFireWireBus )
OSMetaClassDefineReservedUnused(IOFireWireController, 0);
OSMetaClassDefineReservedUnused(IOFireWireController, 1);
OSMetaClassDefineReservedUnused(IOFireWireController, 2);
OSMetaClassDefineReservedUnused(IOFireWireController, 3);
OSMetaClassDefineReservedUnused(IOFireWireController, 4);
OSMetaClassDefineReservedUnused(IOFireWireController, 5);
OSMetaClassDefineReservedUnused(IOFireWireController, 6);
OSMetaClassDefineReservedUnused(IOFireWireController, 7);
OSMetaClassDefineReservedUnused(IOFireWireController, 8);
#pragma mark -
bool IOFireWireController::init( IOFireWireLink *fwim )
{
bool success = true;
if( !IOFireWireBus::init() )
{
success = false;
}
if( success )
{
fAuxiliary = createAuxiliary();
if( fAuxiliary == NULL )
{
success = false;
}
}
if( success )
{
fwim->retain() ;
fFWIM = fwim;
fHubPort = kFWInvalidPort;
fOutOfTLabels = 0;
fOutOfTLabels10S = 0;
fOutOfTLabelsThreshold = 0;
fWaitingForSelfID = 0;
}
if( success )
{
gFireWireROM = OSSymbol::withCString("FireWire Device ROM");
if( gFireWireROM == NULL )
success = false;
}
if( success )
{
gFireWireNodeID = OSSymbol::withCString("FireWire Node ID");
if( gFireWireNodeID == NULL )
success = false;
}
if( success )
{
gFireWireSelfIDs = OSSymbol::withCString("FireWire Self IDs");
if( gFireWireSelfIDs == NULL )
success = false;
}
if( success )
{
gFireWireUnit_Spec_ID = OSSymbol::withCString("Unit_Spec_ID");
if( gFireWireUnit_Spec_ID == NULL )
success = false;
}
if( success )
{
gFireWireUnit_SW_Version = OSSymbol::withCString("Unit_SW_Version");
if( gFireWireUnit_SW_Version == NULL )
success = false;
}
if( success )
{
gFireWireVendor_ID = OSSymbol::withCString("Vendor_ID");
if( gFireWireVendor_ID == NULL )
success = false;
}
if( success )
{
gFireWire_GUID = OSSymbol::withCString("GUID");
if( gFireWire_GUID == NULL )
success = false;
}
if( success )
{
gFireWireSpeed = OSSymbol::withCString("FireWire Speed");
if( gFireWireSpeed == NULL )
success = false;
}
if( success )
{
gFireWireVendor_Name = OSSymbol::withCString("FireWire Vendor Name");
if( gFireWireVendor_Name == NULL )
success = false;
}
if( success )
{
gFireWireProduct_Name = OSSymbol::withCString("FireWire Product Name");
if( gFireWireProduct_Name == NULL )
success = false;
}
if( success )
{
gFireWireModel_ID = OSSymbol::withCString("Model_ID");
if( gFireWireModel_ID == NULL )
success = false;
}
if( success )
{
gFireWireTDM = OSSymbol::withCString("TDM");
if( gFireWireTDM == NULL )
success = false;
}
if( success )
{
if( gIOFireWirePlane == NULL )
{
gIOFireWirePlane = IORegistryEntry::makePlane( kIOFireWirePlane );
}
if( gIOFireWirePlane == NULL )
success = false;
}
if( success )
{
fLocalAddresses = OSSet::withCapacity( 5 ); if( fLocalAddresses == NULL )
success = false;
}
if( success )
{
fSpaceIterator = OSCollectionIterator::withCollection( fLocalAddresses );
if( fSpaceIterator == NULL )
success = false;
}
if( success )
{
fPHYPacketListeners = OSSet::withCapacity( 2 );
if( fPHYPacketListeners == NULL )
success = false;
}
if( success )
{
fPHYPacketListenersIterator = OSCollectionIterator::withCollection( fPHYPacketListeners );
if( fPHYPacketListenersIterator == NULL )
success = false;
}
if( success )
{
fLocalAsyncStreamReceivers = OSSet::withCapacity(2);
if( fLocalAsyncStreamReceivers == NULL )
success = false;
}
if( success )
{
fAllocatedChannels = OSSet::withCapacity(1); if( fAllocatedChannels == NULL )
success = false;
}
if( success )
{
fAllocChannelIterator = OSCollectionIterator::withCollection(fAllocatedChannels);
if( fAllocChannelIterator == NULL )
success = false;
}
if( success )
{
fIRMAllocations = OSSet::withCapacity(1);
if( fIRMAllocations == NULL )
success = false;
}
if( success )
{
fIRMAllocationsIterator = OSCollectionIterator::withCollection(fIRMAllocations);
if( fIRMAllocationsIterator == NULL )
success = false;
}
if( success )
{
fIRMAllocationsAllocated = OSSet::withCapacity(1);
if( fIRMAllocationsAllocated == NULL )
success = false;
}
if( success )
{
fLastTrans = kMaxPendingTransfers-1;
fDevicePruneDelay = kNormalDevicePruneDelay;
UInt32 bad = OSSwapHostToBigInt32(0xdeadbabe);
fBadReadResponse = IOBufferMemoryDescriptor::withBytes(&bad, sizeof(bad), kIODirectionOutIn);
if( fBadReadResponse == NULL )
success = false;
}
if( success )
{
fDelayedStateChangeCmdNeedAbort = false;
fDelayedStateChangeCmd = createDelayedCmd(1000 * kScanBusDelay, delayedStateChange, NULL);
if( fDelayedStateChangeCmd == NULL )
success = false;
}
if( success )
{
fBusResetStateChangeCmd = createDelayedCmd(1000 * kRepeatResetDelay, resetStateChange, NULL);
if( fBusResetStateChangeCmd == NULL )
success = false;
}
if( success )
{
fGUIDDups = IOFireWireDuplicateGUIDList::create();
if( fGUIDDups == NULL )
success = false;
}
if( success )
{
fBusPowerManager = IOFireWirePowerManager::createWithController( this );
if( fBusPowerManager == NULL )
{
IOLog( "IOFireWireController::start - failed to create bus power manager!\n" );
success = false;
}
}
if( success )
{
fNodeMustBeRootFlag = false;
fNodeMustNotBeRootFlag = false;
fForcedGapFlag = false;
}
return success;
}
IOFireWireBusAux * IOFireWireController::createAuxiliary( void )
{
IOFireWireControllerAux * auxiliary;
auxiliary = OSTypeAlloc( IOFireWireControllerAux );
if( auxiliary != NULL && !auxiliary->init(this) )
{
auxiliary->release();
auxiliary = NULL;
}
return auxiliary;
}
void IOFireWireController::free()
{
closeGate() ;
fInstantiated = false;
fNodeMustBeRootFlag = false;
fNodeMustNotBeRootFlag = false;
fForcedGapFlag = false;
if( fIRM != NULL )
{
fIRM->release();
fIRM = NULL;
}
if( fBusPowerManager != NULL )
{
fBusPowerManager->release();
fBusPowerManager = NULL;
}
if( fROMAddrSpace != NULL )
{
fROMAddrSpace->release();
fROMAddrSpace = NULL;
}
if( fRootDir != NULL )
{
fRootDir->release();
fRootDir = NULL;
}
if( fBadReadResponse != NULL )
{
fBadReadResponse->release();
fBadReadResponse = NULL;
}
if( fDelayedStateChangeCmd != NULL )
{
fDelayedStateChangeCmd->release();
fDelayedStateChangeCmd = NULL;
}
if( fBusResetStateChangeCmd != NULL )
{
fBusResetStateChangeCmd->release();
fBusResetStateChangeCmd = NULL;
}
if( fSpaceIterator != NULL )
{
fSpaceIterator->release();
fSpaceIterator = NULL;
}
if( fLocalAddresses != NULL )
{
fLocalAddresses->release();
fLocalAddresses = NULL;
}
if( fPHYPacketListenersIterator != NULL )
{
fPHYPacketListenersIterator->release();
fPHYPacketListenersIterator = NULL;
}
if( fPHYPacketListeners != NULL )
{
fPHYPacketListeners->release();
fPHYPacketListeners = NULL;
}
if( fLocalAsyncStreamReceivers != NULL )
{
fLocalAsyncStreamReceivers->release();
fLocalAsyncStreamReceivers = NULL;
}
if( fAllocChannelIterator != NULL )
{
fAllocChannelIterator->release();
fAllocChannelIterator = NULL;
}
if( fAllocatedChannels != NULL )
{
fAllocatedChannels->release();
fAllocatedChannels = NULL;
}
if( fIRMAllocationsIterator != NULL )
{
fIRMAllocationsIterator->release();
fIRMAllocationsIterator = NULL;
}
if( fIRMAllocations != NULL )
{
fIRMAllocations->release();
fIRMAllocations = NULL;
}
if( fIRMAllocationsAllocated != NULL )
{
fIRMAllocationsAllocated->release();
fIRMAllocationsAllocated = NULL;
}
{
IOFireWireLink * fwim = fFWIM ;
fFWIM = NULL ;
fwim->release() ;
fwim=NULL;
}
openGate() ;
destroyTimeoutQ();
destroyPendingQ();
if( fWorkLoop != NULL )
{
fWorkLoop->release();
fWorkLoop = NULL;
}
if( fAuxiliary != NULL )
{
fAuxiliary->release();
fAuxiliary = NULL;
}
if( fGUIDDups != NULL )
{
fGUIDDups->release();
fGUIDDups = NULL;
}
IOFireWireBus::free();
}
bool IOFireWireController::start( IOService * provider )
{
FWTrace_Start( kFWTController, kTPControllerStart, (uintptr_t)fFWIM, 0, 0, 0 );
fStarted = false;
if (!IOService::start(provider))
{
return false;
}
#ifdef __ppc__
IOService *parent = this;
while(parent) {
if(parent->inPlane(gIODTPlane))
break;
parent = parent->getProvider();
}
if(parent) {
IORegistryEntry * child;
IORegistryIterator * children;
children = IORegistryIterator::iterateOver(parent, gIODTPlane);
if ( children != 0 ) {
OSOrderedSet * set = children->iterateAll();
if(set != 0) {
OSIterator *iter = OSCollectionIterator::withCollection(set);
if(iter != 0) {
while ( (child = (IORegistryEntry *)iter->getNextObject()) ) {
child->detachAll(gIODTPlane);
}
iter->release();
}
set->release();
}
children->release();
}
}
#endif
fWorkLoop = fFWIM->getFireWireWorkLoop();
fWorkLoop->retain();
createPendingQ();
createTimeoutQ();
if ( !PE_parse_boot_argn("fwdebug_ignorenode", &fDebugIgnoreNode, sizeof(fDebugIgnoreNode)) ) {
fDebugIgnoreNode = kFWDebugIgnoreNodeNone;
} else {
IOLog("FireWire: Will ignore node 0x%x per boot-args.\n", (uint32_t)fDebugIgnoreNode);
}
fInstantiated = true;
fStartStatus = kIOReturnSuccess;
PMinit();
provider->joinPMtree(this);
unsigned long num_power_states = 0;
IOPMPowerState * power_state_table = fFWIM->getPowerStateTable( &num_power_states );
registerPowerDriver( this, power_state_table, num_power_states );
FWTrace( kFWTController, kTPControllerStart, (uintptr_t)fFWIM, kFWPMWakeState, 0, 0 );
changePowerStateTo( kFWPMWakeState );
FWTrace_End( kFWTController, kTPControllerStart, (uintptr_t)fFWIM, fStartStatus, 0, 0 );
return (fStartStatus == kIOReturnSuccess);
}
IOReturn IOFireWireController::poweredStart( void )
{
FWTrace_Start( kFWTController, kTPControllerPoweredStart, (uintptr_t)fFWIM, 0, 0, 0 );
IOReturn status = kIOReturnSuccess;
fStarted = true;
CSRNodeUniqueID guid = fFWIM->getGUID();
IOService * provider = getProvider();
if( provider->getProperty("DelegateCycleMaster") )
fDelegateCycleMaster = true;
OSData * hub_port_property = (OSData*)fFWIM->getProvider()->getProperty( "fwhub" );
if( hub_port_property )
{
fHubPort = *((UInt32 *)hub_port_property->getBytesNoCopy());
}
initSecurity();
fROMHeader[1] = OSSwapHostToBigInt32( kFWBIBBusName );
UInt32 characteristics = fFWIM->getBusCharacteristics();
fROMHeader[2] = OSSwapHostToBigInt32( characteristics & ~kFWBIBGeneration );
((IOFireWireControllerAux*)fAuxiliary)->fMaxRec = ((characteristics & kFWBIBMaxRec) >> kFWBIBMaxRecPhase);
fMaxRecvLog = ((characteristics & kFWBIBMaxRec) >> kFWBIBMaxRecPhase)+1;
fMaxSendLog = fFWIM->getMaxSendLog();
fROMHeader[3] = OSSwapHostToBigInt32( guid >> 32 );
fROMHeader[4] = OSSwapHostToBigInt32( guid & 0xffffffff );
fRootDir = IOLocalConfigDirectory::create();
if(!fRootDir)
{
FWTrace_End( kFWTController, kTPControllerPoweredStart, (uintptr_t)fFWIM, kIOReturnError, 1, 0 );
return kIOReturnError;
}
fRootDir->addEntry(kConfigGenerationKey, (UInt32)1);
fRootDir->addEntry(kConfigModuleVendorIdKey, kConfigUnitSpecAppleA27, OSString::withCString("Apple Computer, Inc."));
fRootDir->addEntry(kConfigModelIdKey, kConfigUnitSWVersMacintosh10, OSString::withCString("Macintosh"));
fRootDir->addEntry(kConfigNodeCapabilitiesKey, 0x000083C0);
UInt64 guid_big = OSSwapHostToBigInt64( guid );
OSData *t = OSData::withBytes(&guid_big, sizeof(guid_big));
if( t )
{
fRootDir->addEntry(kConfigNodeUniqueIdKey, t);
t->release();
t = NULL;
}
fTimer->enable();
IOFireWireLocalNode *localNode = OSTypeAlloc( IOFireWireLocalNode );
fLocalNode = localNode;
localNode->setConfigDirectory( fRootDir );
OSDictionary *propTable;
do {
OSObject * prop;
propTable = OSDictionary::withCapacity(8);
if (!propTable)
continue;
prop = OSNumber::withNumber(guid, 8*sizeof(guid));
if(prop) {
propTable->setObject(gFireWire_GUID, prop);
prop->release();
}
localNode->init(propTable);
localNode->attach(this);
localNode->registerService();
} while (false);
if(propTable) {
propTable->release(); propTable=NULL;
}
#ifdef LEGACY_SHUTDOWN
fPowerEventNotifier = registerPrioritySleepWakeInterest( systemShutDownHandler, this );
FWKLOGASSERT( fPowerEventNotifier != NULL );
#endif
fIRM = IOFireWireIRM::create(this);
FWPANICASSERT( fIRM != NULL );
fFWIM->enableAllInterrupts();
registerService();
FWTrace_End( kFWTController, kTPControllerPoweredStart, (uintptr_t)fFWIM, status, 0, 0 );
return status;
}
void IOFireWireController::stop( IOService * provider )
{
closeGate() ;
processBusReset();
suspendBus();
freeSecurity();
PMstop();
#ifdef LEGACY_SHUTDOWN
if( fPowerEventNotifier )
{
fPowerEventNotifier->remove();
fPowerEventNotifier = NULL;
}
#endif
if(fBusState == kAsleep) {
IOReturn sleepRes;
sleepRes = fWorkLoop->wake(&fBusState);
if(sleepRes != kIOReturnSuccess) {
IOLog("IOFireWireController::stop - Can't wake FireWire workloop, error 0x%x\n", sleepRes);
}
openGate();
}
freeAllAsyncStreamReceiver();
IOService::stop(provider);
openGate() ;
}
bool IOFireWireController::finalize( IOOptionBits options )
{
bool res;
closeGate() ;
res = IOService::finalize(options);
openGate() ;
return res;
}
bool IOFireWireController::requestTerminate( IOService * provider, IOOptionBits options )
{
OSIterator *childIterator;
childIterator = getClientIterator();
if( childIterator )
{
OSObject *child;
while( (child = childIterator->getNextObject()) )
{
IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child);
if(found && (found->getTerminationState() == kNotTerminated) && found->isOpen())
{
messageClient( kIOFWMessageServiceIsRequestingClose, found );
}
}
childIterator->release();
}
if(fLocalNode) {
fLocalNode->release();
fLocalNode = NULL;
}
return IOService::requestTerminate(provider, options);
}
IOReturn IOFireWireController::setPowerState( unsigned long powerStateOrdinal,
IOService* whatDevice )
{
FWTrace( kFWTController, kTPControllerSetPowerState, (uintptr_t)fFWIM, powerStateOrdinal, 0, 0 );
IOReturn res;
IOReturn sleepRes;
if( !fStarted && (powerStateOrdinal != kFWPMWakeState) )
{
return IOPMAckImplied;
}
if( !fInstantiated )
{
return IOPMAckImplied;
}
if( fBusState != kAsleep )
{
closeGate();
}
else
{
sleepRes = fWorkLoop->wake(&fBusState);
if(sleepRes != kIOReturnSuccess)
{
IOLog("Can't wake FireWire workloop, error 0x%x\n", sleepRes);
}
}
if( powerStateOrdinal == kFWPMWakeState )
{
fDevicePruneDelay = kWakeDevicePruneDelay;
fBusState = kRunning; if( fDelayedStateChangeCmdNeedAbort )
{
fDelayedStateChangeCmdNeedAbort = false;
fDelayedStateChangeCmd->cancel(kIOReturnAborted);
}
}
if(powerStateOrdinal == kFWPMSleepState )
{
fFWIM->setContender(false);
fFWIM->setRootHoldOff(false);
FWTrace(kFWTResetBusAction, kTPResetSetPowerState, (uintptr_t)fFWIM, powerStateOrdinal, 1, 0);
fFWIM->resetBus();
IOSleep(10); }
res = fFWIM->setLinkPowerState(powerStateOrdinal);
if( (powerStateOrdinal == kFWPMWakeState) && !fStarted )
{
if( res != IOPMAckImplied )
{
fStartStatus = kIOReturnError;
res = IOPMAckImplied;
}
else
{
fStartStatus = poweredStart();
}
}
if( (powerStateOrdinal == kFWPMWakeState) &&
(res == IOPMAckImplied) &&
(fStartStatus == kIOReturnSuccess) )
{
if ( kIOReturnSuccess != UpdateROM() )
IOLog(" %s %u: UpdateROM() got error\n", __FILE__, __LINE__ ) ;
FWTrace(kFWTResetBusAction, kTPResetSetPowerState, (uintptr_t)fFWIM, powerStateOrdinal, 2, 0);
fFWIM->resetBus(); }
if( powerStateOrdinal == kFWPMSleepState )
{
if( delayedStateCommandInUse() )
{
fDelayedStateChangeCmdNeedAbort = true;
}
if( fBusResetState == kResetStateDisabled )
{
fBusResetStateChangeCmd->cancel( kIOReturnAborted );
fBusResetState = kResetStateResetting;
}
fBusResetScheduled = false;
fBusState = kAsleep;
}
if( (fBusState == kAsleep) && (OSSwapBigToHostInt32(fROMHeader[1]) == kFWBIBBusName) )
{
sleepRes = fWorkLoop->sleep(&fBusState);
if(sleepRes != kIOReturnSuccess)
{
IOLog("Can't sleep FireWire workloop, error 0x%x\n", sleepRes);
}
}
else
{
openGate();
}
return res;
}
#ifdef LEGACY_SHUTDOWN
IOReturn IOFireWireController::systemShutDownHandler( void * target, void * refCon,
UInt32 messageType, IOService * service,
void * messageArgument, vm_size_t argSize )
{
IOReturn status = kIOReturnSuccess;
IOFireWireController * me = (IOFireWireController*)target;
me->closeGate();
switch( messageType )
{
case kIOMessageSystemWillPowerOff:
me->fFWIM->handleSystemShutDown( messageType );
status = kIOReturnSuccess;
break;
case kIOMessageSystemWillRestart:
me->fFWIM->handleSystemShutDown( messageType );
status = kIOReturnSuccess;
break;
default:
status = kIOReturnUnsupported;
break;
}
me->openGate();
return status;
}
#else
void IOFireWireController::systemWillShutdown( IOOptionBits specifier )
{
closeGate();
switch( specifier )
{
case kIOMessageSystemWillPowerOff:
fFWIM->handleSystemShutDown( specifier );
break;
case kIOMessageSystemWillRestart:
fFWIM->handleSystemShutDown( specifier );
break;
default:
break;
}
openGate();
IOService::systemWillShutdown( specifier );
}
#endif
IOReturn IOFireWireController::resetBus()
{
IOReturn res = kIOReturnSuccess;
closeGate();
switch( fBusResetState )
{
case kResetStateDisabled:
FWTrace(kFWTController, kTPControllerResetBus, (uintptr_t)fFWIM, fBusResetState, 0, 0);
fBusResetScheduled = true;
break;
case kResetStateArbitrated:
if( fBusResetDisabledCount == 0 )
{
FWTrace(kFWTController, kTPControllerResetBus, (uintptr_t)fFWIM, fBusResetState, 0, 0);
doBusReset();
}
else if( !fBusResetScheduled )
{
fBusResetScheduled = true;
if( delayedStateCommandInUse() )
{
fDelayedStateChangeCmd->cancel( kIOReturnAborted );
}
fBusState = kWaitingBusResetStart;
fDelayedStateChangeCmd->reinit( 1000 * kBusResetStartTimeout, delayedStateChange, NULL );
FWTrace(kFWTStateChangeAction, kTPStateChangeResetBus, (uintptr_t)fFWIM, fBusResetState, 0, 0);
fDelayedStateChangeCmd->submit();
}
break;
case kResetStateResetting:
FWTrace(kFWTController, kTPControllerResetBus, (uintptr_t)fFWIM, fBusResetState, 0, 0);
default:
FWTrace(kFWTController, kTPControllerResetBus, (uintptr_t)fFWIM, fBusResetState, 0, 0);
break;
}
openGate();
return res;
}
void IOFireWireController::resetStateChange(void *refcon, IOReturn status,
IOFireWireBus *bus, IOFWBusCommand *fwCmd)
{
IOFireWireController *me = (IOFireWireController *)bus;
if( status == kIOReturnTimeout )
{
#ifdef FWKLOGASSERT
FWKLOGASSERT( me->fBusResetState == kResetStateDisabled );
#endif
me->fBusResetState = kResetStateArbitrated;
if( me->fBusResetScheduled )
{
if( me->fBusResetDisabledCount == 0 )
{
FWTrace(kFWTResetBusAction, kTPResetResetStateChangeResetScheduled, (uintptr_t)(me->fFWIM), me->fBusResetState, 0, 0);
me->doBusReset();
}
else
{
if( me->delayedStateCommandInUse() )
{
me->fDelayedStateChangeCmd->cancel( kIOReturnAborted );
}
me->fBusState = kWaitingBusResetStart;
me->fDelayedStateChangeCmd->reinit( 1000 * kBusResetStartTimeout, delayedStateChange, NULL );
FWTrace(kFWTStateChangeAction, kTPStateChangeResetStateChange, (uintptr_t)(me->fFWIM), me->fBusResetState, 0, 0);
me->fDelayedStateChangeCmd->submit();
}
}
}
}
void IOFireWireController::doBusReset( void )
{
IOReturn status = kIOReturnSuccess;
bool useIBR = false;
if( fDelayedPhyPacket )
{
fFWIM->sendPHYPacket( fDelayedPhyPacket );
fDelayedPhyPacket = 0x00000000;
if( fGapCountMismatch )
{
useIBR = true;
}
}
FWKLOG(( "IOFireWireController::doBusReset\n" ));
fBusResetState = kResetStateResetting;
if( delayedStateCommandInUse() )
{
fDelayedStateChangeCmd->cancel(kIOReturnAborted);
}
fBusState = kWaitingBusReset;
fDelayedStateChangeCmd->reinit(1000 * kBusResetTimeout, delayedStateChange, NULL);
FWTrace(kFWTStateChangeAction, kTPStateChangeDoBusReset, (uintptr_t)fFWIM, fBusResetState, 0, 0);
fDelayedStateChangeCmd->submit();
status = fFWIM->resetBus( useIBR );
if( status == kIOReturnSuccess )
{
if( fWaitingForSelfID > kMaxWaitForValidSelfID )
{
fFWIM->notifyInvalidSelfIDs();
fWaitingForSelfID = 0;
}
}
else
{
fDelayedStateChangeCmd->cancel( kIOReturnAborted );
fBusState = kRunning;
}
}
void IOFireWireController::enterBusResetDisabledState( )
{
if( fBusResetState == kResetStateDisabled )
fBusResetStateChangeCmd->cancel( kIOReturnAborted );
fBusResetState = kResetStateDisabled;
fBusResetStateChangeCmd->reinit( 1000 * kRepeatResetDelay, resetStateChange, NULL );
fBusResetStateChangeCmd->submit();
}
IOReturn IOFireWireController::disableSoftwareBusResets( void )
{
IOReturn status = kIOReturnSuccess;
closeGate();
switch( fBusResetState )
{
case kResetStateDisabled:
fBusResetDisabledCount++;
break;
case kResetStateResetting:
status = kIOFireWireBusReset;
break;
case kResetStateArbitrated:
if( !fBusResetScheduled )
{
fBusResetDisabledCount++;
}
else
{
status = kIOFireWireBusReset;
}
break;
default:
break;
}
openGate();
return status;
}
void IOFireWireController::enableSoftwareBusResets( void )
{
closeGate();
#ifdef FWKLOGASSERT
FWKLOGASSERT( fBusResetDisabledCount != 0 );
#endif
if( fBusResetDisabledCount > 0 )
{
fBusResetDisabledCount--;
}
switch( fBusResetState )
{
case kResetStateArbitrated:
if( fBusResetDisabledCount == 0 && fBusResetScheduled )
{
doBusReset();
}
break;
case kResetStateResetting:
case kResetStateDisabled:
default:
break;
}
openGate();
}
IOReturn IOFireWireController::beginIOCriticalSection( void )
{
IOReturn status = kIOReturnSuccess;
status = disableSoftwareBusResets();
if( status == kIOReturnSuccess )
{
if( fIOCriticalSectionCount == 0 )
{
fFWIM->configureAsyncRobustness( true );
}
fIOCriticalSectionCount++;
}
return status;
}
void IOFireWireController::endIOCriticalSection( void )
{
if( fIOCriticalSectionCount != 0 )
{
enableSoftwareBusResets();
fIOCriticalSectionCount--;
if( fIOCriticalSectionCount == 0 )
{
fFWIM->configureAsyncRobustness( false );
}
}
}
void IOFireWireController::delayedStateChange(void *refcon, IOReturn status,
IOFireWireBus *bus, IOFWBusCommand *fwCmd)
{
IOFireWireController *me = (IOFireWireController *)bus;
if(status == kIOReturnTimeout) {
switch (me->fBusState) {
case kWaitingBusResetStart:
FWTrace(kFWTResetBusAction, kTPResetDelayedStateChangeWaitingBusReset, (uintptr_t)me->fFWIM, me->fBusState, 1, 0);
me->doBusReset();
break;
case kWaitingBusReset:
FWTrace(kFWTController, kTPControllerDelayedStateChange, (uintptr_t)(me->fFWIM), me->fBusState, 0, 0);
me->checkProgress();
me->enterBusResetDisabledState();
me->fBusState = kRunning;
FWTrace(kFWTResetBusAction, kTPResetDelayedStateChangeWaitingBusReset, (uintptr_t)me->fFWIM, me->fBusState, 2, 0);
me->resetBus();
break;
case kWaitingSelfIDs:
FWTrace(kFWTController, kTPControllerDelayedStateChange, (uintptr_t)(me->fFWIM), me->fBusState, 0, 0);
me->fBusState = kRunning;
me->fWaitingForSelfID++;
FWTrace(kFWTResetBusAction, kTPResetDelayedStateChangeWaitingBusReset, (uintptr_t)me->fFWIM, me->fBusState, 3, 0);
me->resetBus();
break;
case kWaitingScan:
FWTrace(kFWTController, kTPControllerDelayedStateChange, (uintptr_t)(me->fFWIM), me->fBusState, 0, 0);
me->fWaitingForSelfID = 0;
me->fBusState = kScanning;
me->startBusScan();
break;
case kWaitingPrune:
FWTrace(kFWTController, kTPControllerDelayedStateChange, (uintptr_t)me->fFWIM, me->fBusState, 0, 0);
me->fBusState = kRunning;
me->updatePlane();
break;
default:
FWTrace(kFWTController, kTPControllerDelayedStateChange, (uintptr_t)(me->fFWIM), me->fBusState, 0, 0);
IOLog("State change timeout, state is %d\n", me->fBusState);
break;
}
}
}
bool IOFireWireController::scanningBus() const
{
return fBusState == kWaitingSelfIDs || fBusState == kWaitingScan || fBusState == kScanning;
}
bool IOFireWireController::delayedStateCommandInUse() const
{
return (fBusState == kWaitingBusReset) || (fBusState == kWaitingSelfIDs) || (fBusState == kWaitingScan) || (fBusState == kWaitingPrune);
}
const AbsoluteTime * IOFireWireController::getResetTime() const
{
return &fResetTime;
}
void IOFireWireController::checkProgress( void )
{
fAfterResetHandledQ.checkProgress();
OSIterator * childIterator = getClientIterator();
if( childIterator )
{
OSObject *child;
while( (child = childIterator->getNextObject()))
{
IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child);
if( found && (found->getTerminationState() == kNotTerminated) && found->fNodeID == kFWBadNodeID )
{
AbsoluteTime now;
UInt32 milliDelta;
UInt64 nanoDelta;
AbsoluteTime resume_time = found->getResumeTime();
IOFWGetAbsoluteTime( &now );
SUB_ABSOLUTETIME( &now, &resume_time );
absolutetime_to_nanoseconds( now, &nanoDelta );
milliDelta = nanoDelta / 1000000;
if( milliDelta > kDeviceMaximuPruneTime )
{
terminateDevice( found );
}
}
}
childIterator->release();
}
}
void IOFireWireController::processBusReset( void )
{
FWKLOG(( "IOFireWireController::processBusReset\n" ));
IOFWGetAbsoluteTime(&fResetTime);
fBusResetScheduled = false;
enterBusResetDisabledState();
if( delayedStateCommandInUse() )
{
fDelayedStateChangeCmd->cancel( kIOReturnAborted );
}
fBusState = kWaitingSelfIDs;
checkProgress();
fDelayedStateChangeCmd->reinit( 1000 * kSelfIDTimeout, delayedStateChange, NULL );
FWTrace(kFWTStateChangeAction, kTPStateChangeProcessBusReset, (uintptr_t)fFWIM, fBusResetState, 0, 0);
fDelayedStateChangeCmd->submit();
}
void IOFireWireController::suspendBus( void )
{
FWKLOG(( "IOFireWireController::suspendBus\n" ));
FWKLOG(("IOFireWireController::suspendBus set generation to '%s' realGen=0x%lx\n", kFWBusScanInProgress, fBusGeneration));
setProperty( kFireWireGenerationID, kFWBusScanInProgress );
fRequestedHalfSizePackets = false;
fNodeMustNotBeRootFlag = false;
fNodeMustBeRootFlag = false;
fForcedGapFlag = false;
unsigned int i;
UInt32 oldgen = fBusGeneration;
fBusGeneration++;
fOutOfTLabels = 0;
fOutOfTLabels10S = 0;
fOutOfTLabelsThreshold = 0;
OSIterator * childIterator = getClientIterator();
if( childIterator )
{
OSObject * child;
while( (child = childIterator->getNextObject()) )
{
IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child);
if( found && (found->getTerminationState() == kNotTerminated) )
{
found->setNodeROM( oldgen, kFWBadNodeID, NULL );
}
else if( OSDynamicCast(IOFireWireLocalNode, child) )
{
((IOFireWireLocalNode *)child)->messageClients(kIOMessageServiceIsSuspended);
}
}
childIterator->release();
}
physicalAccessProcessBusReset();
bzero( fSpeedVector, sizeof(fSpeedVector) );
for( i=0; i<kMaxPendingTransfers; i++ )
{
AsyncPendingTrans *t = &fTrans[i];
if( t->fHandler )
{
IOFWAsyncCommand * cmd = t->fHandler;
cmd->gotPacket(kFWResponseBusResetError, NULL, 0);
}
else if( t->fAltHandler )
{
IOFWAsyncPHYCommand * cmd = OSDynamicCast( IOFWAsyncPHYCommand, t->fAltHandler );
if( cmd )
{
cmd->gotPacket( kFWResponseBusResetError );
}
}
}
if( fNodes[fRootNodeID] )
{
fNodes[fRootNodeID]->detachAll(gIOFireWirePlane);
}
for( i=0; i<=fRootNodeID; i++ )
{
if( fScans[i] )
{
fScans[i]->fCmd->release();
fScans[i]->fLockCmd->release();
IOFree(fScans[i], sizeof(*fScans[i]));
fScans[i] = NULL;
}
if(fNodes[i])
{
fNodes[i]->release();
fNodes[i] = NULL;
}
}
fTimeoutQ.busReset();
}
void IOFireWireController::processSelfIDs(UInt32 *IDs, int numIDs, UInt32 *ownIDs, int numOwnIDs)
{
int i;
UInt32 id;
UInt32 nodeID;
UInt16 irmID;
UInt16 ourID;
IOFireWireLocalNode * localNode;
FWKLOG(( "IOFireWireController::processSelfIDs entered\n" ));
FWTrace_Start(kFWTController, kTPControllerProcessSelfIDs, (uintptr_t)fFWIM, 0, 0, 0);
#if (DEBUGGING_LEVEL > 0)
for(i=0; i<numIDs; i++)
IOLog("ID %d: 0x%x <-> 0x%x\n", i, IDs[2*i], ~IDs[2*i+1]);
for(i=0; i<numOwnIDs; i++)
IOLog("Own ID %d: 0x%x <-> 0x%x\n", i, ownIDs[2*i], ~ownIDs[2*i+1]);
#endif
if( fBusState != kWaitingSelfIDs )
{
processBusReset();
}
suspendBus();
if( fBusState != kWaitingSelfIDs )
{
IOLog( "IOFireWireController::processSelfIDs - fBusState != kWaitingSelfIDs\n" );
}
if( fBusState == kWaitingSelfIDs )
{
fDelayedStateChangeCmd->cancel( kIOReturnAborted );
}
fBusState = kWaitingScan;
fRootNodeID = ourID = (OSSwapBigToHostInt32(*ownIDs) & kFWPhyPacketPhyID) >> kFWPhyPacketPhyIDPhase;
if( fRootNodeID > 0x3e )
fRootNodeID = 0x3e;
fLocalNodeID = ourID | (kFWLocalBusAddress>>kCSRNodeIDPhase);
fGapCountMismatch = false;
UInt32 gap_count = (OSSwapBigToHostInt32(*ownIDs) & kFWSelfID0GapCnt) >> kFWSelfID0GapCntPhase;
for( i = 0; i < numIDs; i++ )
{
UInt32 current_id = OSSwapBigToHostInt32(IDs[2*i]);
if( (current_id & kFWSelfIDPacketType) == 0 &&
((current_id & kFWSelfID0GapCnt) >> kFWSelfID0GapCntPhase) != gap_count )
{
fFWIM->sendPHYPacket( (kFWConfigurationPacketID << kFWPhyPacketIDPhase) |
(0x3f << kFWPhyConfigurationGapCntPhase) | kFWPhyConfigurationT );
fGapCountMismatch = true;
FWKLOG(( "IOFireWireController::processSelfIDs Found Gap Count Mismatch!\n" ));
break;
}
}
localNode = getLocalNode(this);
if(localNode)
{
localNode->setNodeProperties(fBusGeneration, fLocalNodeID, ownIDs, numOwnIDs,fFWIM->getPhySpeed() );
fNodes[ourID] = localNode;
localNode->retain();
}
SInt16 prevID = -1; UInt32 *idPtr = fSelfIDs;
bzero( fNodeIDs, sizeof(fNodeIDs) ) ;
fNumSelfIDs = numIDs;
for(i=0; i<numIDs; i++)
{
UInt32 id = OSSwapBigToHostInt32(IDs[2*i]);
UInt16 currID = (id & kFWPhyPacketPhyID) >> kFWPhyPacketPhyIDPhase;
UInt32 id_inverse = ~OSSwapBigToHostInt32( IDs[2*i+1] );
if(id != id_inverse)
{
IOLog("Bad SelfID packet %d: 0x%x != 0x%x!\n", i, (uint32_t)id, (uint32_t)id_inverse);
FWTrace(kFWTResetBusAction, kTPResetProcessSelfIDs, (uintptr_t)fFWIM, 1, id, 0 );
resetBus(); FWKLOG(( "IOFireWireController::processSelfIDs exited\n" ));
return;
}
if(currID != prevID)
{
if( prevID < ourID && currID > ourID )
{
int j;
fNodeIDs[ourID] = idPtr;
for(j=0; j<numOwnIDs; j++)
{
*idPtr++ = ownIDs[2*j];
}
fNumSelfIDs += numOwnIDs;
}
fNodeIDs[currID] = idPtr;
prevID = currID;
if((fRootNodeID < currID) && (currID <= 0x3e))
fRootNodeID = currID;
}
*idPtr++ = IDs[2*i];
}
if(prevID < ourID)
{
int j;
fNodeIDs[ourID] = idPtr;
for(j=0; j<numOwnIDs; j++)
{
*idPtr++ = ownIDs[2*j];
}
fNumSelfIDs += numOwnIDs;
}
fNodeIDs[fRootNodeID+1] = idPtr;
for(i = 0; i<=fRootNodeID; i++)
{
if ( NULL == fNodeIDs[i] )
{
IOLog("Missing self ID for node %d!\n", i ) ;
FWTrace(kFWTResetBusAction, kTPResetProcessSelfIDs, (uintptr_t)fFWIM, 2, i, 0 );
resetBus();
return; }
UInt32 host_id = OSSwapBigToHostInt32(*fNodeIDs[i]);
if( ((host_id & kFWPhyPacketPhyID) >> kFWPhyPacketPhyIDPhase) != (UInt32)i)
{
IOLog("No FireWire node %d (got ID packet 0x%x)!\n", i, (uint32_t)host_id);
FWTrace(kFWTResetBusAction, kTPResetProcessSelfIDs, (uintptr_t)fFWIM, 3, i, 0 );
resetBus();
return; }
}
OSObject * prop = OSData::withBytes( fSelfIDs, fNumSelfIDs * sizeof(UInt32));
setProperty(gFireWireSelfIDs, prop);
prop->release();
buildTopology(false);
#if (DEBUGGING_LEVEL > 0)
for(i=0; i<numIDs; i++) {
id = IDs[2*i];
if(id != ~IDs[2*i+1]) {
DEBUGLOG("Bad SelfID: 0x%x <-> 0x%x\n", id, ~IDs[2*i+1]);
continue;
}
DEBUGLOG("SelfID: 0x%x\n", id);
}
DEBUGLOG("Our ID: 0x%x\n", *ownIDs);
#endif
irmID = 0;
for(i=0; i<=fRootNodeID; i++) {
id = OSSwapBigToHostInt32(*fNodeIDs[i]);
nodeID = (id & kFWSelfIDPhyID) >> kFWSelfIDPhyIDPhase;
nodeID |= kFWLocalBusAddress>>kCSRNodeIDPhase;
if((id & (kFWSelfID0C | kFWSelfID0L)) == (kFWSelfID0C | kFWSelfID0L)) {
#if (DEBUGGING_LEVEL > 0)
IOLog("IRM contender: %lx\n", nodeID);
#endif
if(nodeID > irmID)
irmID = nodeID;
}
}
if(irmID != 0)
fIRMNodeID = irmID;
else
fIRMNodeID = kFWBadNodeID;
fBusMgr = false;
fIRM->processBusReset( fLocalNodeID, fIRMNodeID, fBusGeneration );
if(localNode) {
localNode->messageClients(kIOMessageServiceIsResumed);
}
FWTrace(kFWTStateChangeAction, kTPStateChangeProcessSelfIDs, (uintptr_t)fFWIM, fBusState, 0, 0);
fDelayedStateChangeCmd->reinit(1000 * kScanBusDelay, delayedStateChange, NULL);
fDelayedStateChangeCmd->submit();
FWTrace_End(kFWTController, kTPControllerProcessSelfIDs, (uintptr_t)fFWIM, 0, 0, 0);
FWKLOG(( "IOFireWireController::processSelfIDs exited\n" ));
}
void IOFireWireController::processCycle64Int()
{
if( fOutOfTLabels10S++ > 1 )
{
fOutOfTLabels10S = 0;
if( fOutOfTLabels > fOutOfTLabelsThreshold )
{
IOLog("IOFireWireController:: %d Out of Transaction Labels in last 3 minutes.\n",(int) fOutOfTLabels);
fOutOfTLabelsThreshold = fOutOfTLabels;
}
else
fOutOfTLabelsThreshold = fOutOfTLabelsThreshold >> 1;
fOutOfTLabels = 0;
}
}
bool IOFireWireController::AssignCycleMaster( )
{
IOReturn status = kIOReturnSuccess;
int i;
UInt32 contender, linkOn, otherContenderID = 0, newRoot = 0, data1;
Boolean otherContender = false, localContender = false, needReset = false, badIRM = false;
if( ((fRootNodeID & 63) == (fLocalNodeID & 63)) && fNodeMustBeRootFlag )
{
status = fFWIM->setContender( false );
if(status == kIOReturnSuccess)
{
data1 = (kFWConfigurationPacketID << kFWPhyPacketIDPhase) |
((fForcedRootNodeID & 63) << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR;
status = fFWIM->sendPHYPacket(data1);
if(kIOReturnSuccess == status)
needReset = true;
}
}
else if( fDelegateCycleMaster || fBadIRMsKnown || fNodeMustNotBeRootFlag )
{
for( i = 0; i <= fRootNodeID; i++ )
{
contender = (OSSwapBigToHostInt32(*fNodeIDs[i]) >> 11) & 0x1;
linkOn = (OSSwapBigToHostInt32(*fNodeIDs[i]) >> 22) & 0x1;
if (contender && linkOn )
{
if ( i == (fLocalNodeID & 63) )
{
if (contender)
localContender = true;
}
else
{
if( fScans[i] )
{
if( (not fScans[i]->fMustNotBeRoot) && (not fScans[i]->fIRMisBad) ) {
otherContender = true;
otherContenderID = i; }
}
}
}
}
if (otherContender)
{
if( (fRootNodeID & 63) == (fLocalNodeID & 63) && fDelegateCycleMaster )
{
status = fFWIM->setContender( false );
if( status == kIOReturnSuccess )
{
fFWIM->sendPHYPacket((kFWConfigurationPacketID << kFWPhyPacketIDPhase) |
((otherContenderID & 63) << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR );
needReset = true;
}
}
}
else if( ((fRootNodeID & 63) != (fLocalNodeID & 63)) && (localContender) && (not fDelegateCycleMaster))
{
status = fFWIM->setContender( true );
fFWIM->sendPHYPacket((kFWConfigurationPacketID << kFWPhyPacketIDPhase) |
((fLocalNodeID & 63) << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR );
needReset = true;
}
if( status == kIOReturnSuccess && fBadIRMsKnown )
{
badIRM = (!fScans[fIRMNodeID & 63]) && ((fLocalNodeID & 63) != (fIRMNodeID & 63));
if( fScans[fIRMNodeID & 63] && fScans[fIRMNodeID & 63]->fIRMisBad )
badIRM = true;
if( badIRM || (!localContender) && (!otherContender) )
{
if( !fDelegateCycleMaster )
{
newRoot = fLocalNodeID & 63;
fFWIM->setContender( true );
fFWIM->setRootHoldOff(true);
}
else if( otherContender )
newRoot = otherContenderID;
else
{
newRoot = fLocalNodeID & 63;
fFWIM->setContender( true );
fFWIM->setRootHoldOff(true);
}
if( badIRM )
IOLog("IOFireWireController unresponsive IRM at node %x, forcing root to node %x\n", (uint32_t) fIRMNodeID & 63, (uint32_t)newRoot );
fFWIM->sendPHYPacket((kFWConfigurationPacketID << kFWPhyPacketIDPhase) |
((newRoot & 63) << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR );
needReset = true;
}
}
}
if( status == kIOReturnSuccess )
{
if( needReset )
{
FWTrace(kFWTResetBusAction, kTPResetAssignCycleMaster, (uintptr_t)fFWIM, 0, 0, 0 );
fFWIM->resetBus();
IOSleep( 10 ); }
}
return( needReset );
}
void IOFireWireController::startBusScan()
{
int i;
FWTrace( kFWTController, kTPControllerStartBusScan, (uintptr_t)fFWIM, 0, 0, 0 );
FWKLOG(( "IOFireWireController::startBusScan entered\n" ));
OSObject * existProp = fFWIM->getProperty( "FWDSLimit" );
if( existProp )
{
fDSLimited = true;
}
else
{
fDSLimited = false;
}
fFWIM->sendPHYPacket(((fLocalNodeID & 0x3f) << kFWPhyPacketPhyIDPhase) | 0x003c0000);
IOFWIsochChannel *found;
fAllocChannelIterator->reset();
while( (found = (IOFWIsochChannel *)fAllocChannelIterator->getNextObject()) )
{
found->handleBusReset();
}
IOFireWireIRMAllocation *irmAllocationfound;
fIRMAllocationsIterator->reset();
while( (irmAllocationfound = (IOFireWireIRMAllocation *)fIRMAllocationsIterator->getNextObject()) )
{
irmAllocationfound->handleBusReset(fBusGeneration);
}
fNumROMReads = fRootNodeID+1;
for(i=0; i<=fRootNodeID; i++) {
UInt16 nodeID;
UInt32 id;
id = OSSwapBigToHostInt32(*fNodeIDs[i]);
nodeID = (id & kFWSelfIDPhyID) >> kFWSelfIDPhyIDPhase;
nodeID |= kFWLocalBusAddress>>kCSRNodeIDPhase;
if(nodeID == fLocalNodeID)
{
fNumROMReads--;
continue; }
if(true) { IOFWNodeScan *scan;
scan = (IOFWNodeScan *)IOMalloc(sizeof(*scan));
scan->fControl = this;
scan->fAddr.nodeID = nodeID;
scan->fAddr.addressHi = kCSRRegisterSpaceBaseAddressHi;
scan->fAddr.addressLo = kConfigBIBHeaderAddress;
scan->fSelfIDs = fNodeIDs[i];
scan->fNumSelfIDs = fNodeIDs[i+1] - fNodeIDs[i];
scan->fRead = 0;
scan->generation = fBusGeneration;
scan->fRetriesBumped = 0;
scan->fCmd = OSTypeAlloc( IOFWReadQuadCommand );
scan->fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand );
if( (id & (kFWSelfID0C | kFWSelfID0L)) == (kFWSelfID0C | kFWSelfID0L) )
{
scan->fContenderNeedsChecking = true;
}
else
scan->fContenderNeedsChecking = false;
scan->fIRMisBad = false;
scan->fIRMCheckingRead = false;
scan->fIRMCheckingLock = false;
FWKLOG(( "IOFireWireController::startBusScan node %lx speed was %lx\n",(UInt32)nodeID,(UInt32)FWSpeed( nodeID ) ));
if ( fDebugIgnoreNode != kFWDebugIgnoreNodeNone && ((fDebugIgnoreNode & kFWMaxNodesPerBus ) == (nodeID & kFWMaxNodesPerBus )) )
{
scan->speedChecking = false;
if( FWSpeed( nodeID ) & kFWSpeedUnknownMask )
setNodeSpeed(scan->fAddr.nodeID, kFWSpeed100MBit);
scan->fControl->readDeviceROM(scan, kIOReturnNotPermitted);
}
else
{
if( FWSpeed( nodeID ) & kFWSpeedUnknownMask )
{
setNodeSpeed(scan->fAddr.nodeID, fLocalNodeID, (FWSpeed(scan->fAddr.nodeID, fLocalNodeID) & ~kFWSpeedUnknownMask));
scan->fCmd->initAll(this, fBusGeneration, scan->fAddr, scan->fBuf, 1,
&readROMGlue, scan);
FWKLOG(( "IOFireWireController::startBusScan speedchecking\n" ));
scan->speedChecking = true; }
else
{
scan->fCmd->initAll(this, fBusGeneration, scan->fAddr, scan->fBuf, 1,
&readROMGlue, scan);
scan->fCmd->setMaxSpeed( kFWSpeed100MBit );
scan->speedChecking = false;
FWKLOG(( "IOFireWireController::startBusScan not speedchecking\n" ));
}
scan->fIRMBitBucketNew = 0xffffffff;
scan->fIRMBitBucketOld = 0xffffffff;
scan->fLockCmd->initAll(this, fBusGeneration, scan->fAddr, &scan->fIRMBitBucketOld, &scan->fIRMBitBucketNew, 1, &readROMGlue, scan);
FWTrace( kFWTController, kTPControllerStartBusScan, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 1 );
scan->fCmd->setRetries(kFWCmdZeroRetries); scan->fCmd->submit();
}
}
}
if(fNumROMReads == 0) {
FWTrace( kFWTController, kTPControllerStartBusScan, (uintptr_t)fFWIM, 0, 0, 2 );
finishedBusScan();
}
FWKLOG(( "IOFireWireController::startBusScan exited\n" ));
}
void IOFireWireController::readROMGlue(void *refcon, IOReturn status,
IOFireWireNub *device, IOFWCommand *fwCmd)
{
IOFWNodeScan *scan = (IOFWNodeScan *)refcon;
scan->fControl->readDeviceROM(scan, status);
}
void IOFireWireController::readDeviceROM(IOFWNodeScan *scan, IOReturn status)
{
bool done = true;
FWTrace( kFWTController, kTPControllerReadDeviceROM, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), status, 0 );
FWKLOG(( "IOFireWireController::readDeviceROM entered\n" ));
if(status != kIOReturnSuccess)
{
if(status == kIOFireWireBusReset)
{
scan->fCmd->release();
scan->fLockCmd->release();
IOFree(scan, sizeof(*scan));
FWKLOG(( "IOFireWireController::readDeviceROM exited\n" ));
return;
}
if( scan->fCmd->getAckCode() == kFWAckBusyX || scan->fCmd->getAckCode() == kFWAckBusyA || scan->fCmd->getAckCode() == kFWAckBusyB )
{
if( fDevicePruneDelay >= kWakeDevicePruneDelay && fDevicePruneDelay < kWakeDevicePruneDelayBusy )
fDevicePruneDelay = kWakeDevicePruneDelayBusy;
}
if( scan->fIRMCheckingRead || scan->fIRMCheckingLock )
{
if( (scan->fAddr.nodeID & 63) == (fIRMNodeID & 63) )
fBadIRMsKnown = true;
scan->fIRMisBad = true;
scan->fContenderNeedsChecking = false;
}
else
{
if( status == kIOReturnTimeout && scan->fRetriesBumped == 0 )
{
if ( scan->fCmd->getAckCode() == kFWAckPending && scan->fAddr.addressLo == kConfigBIBHeaderAddress )
{
FWKLOG(( "IOFireWireController::readDeviceROM Node 0x%x timed out on ack %d, setting setMaxRetries = %d\n", scan->fAddr.nodeID, scan->fCmd->getAckCode(), kFWCmdIncreasedRetries));
scan->fCmd->setRetries(kFWCmdIncreasedRetries);
scan->fRetriesBumped++;
FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 1 );
scan->fCmd->reinit(scan->fAddr, scan->fBuf, 1, &readROMGlue, scan, true);
scan->fCmd->submit();
return;
}
else
{
scan->fCmd->setRetries(kFWCmdReducedRetries);
scan->fRetriesBumped++;
FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 2 );
scan->fCmd->reinit(scan->fAddr, scan->fBuf, 1, &readROMGlue, scan, true);
scan->fCmd->submit();
return;
}
}
FWKLOG(( "IOFireWireController::readDeviceROM speedcheck %lx ; speed %lx\n", (UInt32)scan->speedChecking, (UInt32)FWSpeed( scan->fAddr.nodeID ) ));
if( scan->speedChecking && FWSpeed( scan->fAddr.nodeID ) > kFWSpeed100MBit )
{
if( scan->generation == fBusGeneration )
{
FWKLOG(( "IOFireWireController::readDeviceROM reseting speed for node %lx from local %lx\n", (UInt32)scan->fAddr.nodeID, (UInt32)fLocalNodeID));
if( fDSLimited )
{
setNodeSpeed(scan->fAddr.nodeID, fLocalNodeID, kFWSpeed100MBit);
}
else
{
setNodeSpeed(scan->fAddr.nodeID, fLocalNodeID, (FWSpeed(scan->fAddr.nodeID, fLocalNodeID) - 1));
}
scan->fCmd->reinit(scan->fAddr, scan->fBuf, 1, &readROMGlue, scan, true);
if ( scan->fAddr.addressLo == kConfigBIBHeaderAddress )
{
scan->fCmd->setRetries(kFWCmdZeroRetries);
scan->fRetriesBumped = 0;
}
else
{
scan->fCmd->setRetries(kFWCmdDefaultRetries);
scan->fRetriesBumped = 0;
}
FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 3 );
scan->fCmd->submit();
return;
}
}
if( (scan->fAddr.nodeID & 63) == (fIRMNodeID & 63) )
fBadIRMsKnown = true;
UInt32 nodeID = FWAddressToID(scan->fAddr.nodeID);
fNodes[nodeID] = createDummyRegistryEntry( scan );
fNumROMReads--;
if(fNumROMReads == 0)
{
FWTrace( kFWTController, kTPControllerReadDeviceROM, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), status, 1 );
finishedBusScan();
}
scan->fCmd->release();
scan->fLockCmd->release();
IOFree(scan, sizeof(*scan));
scan = NULL;
FWKLOG(( "IOFireWireController::readDeviceROM exited\n" ));
return;
}
}
if( scan->fRead == 0 )
{
UInt32 bib_quad = OSSwapBigToHostInt32( scan->fBuf[0] );
if( ((bib_quad & kConfigBusInfoBlockLength) >> kConfigBusInfoBlockLengthPhase) == 1)
{
scan->fROMSize = 4;
done = true;
}
else
{
scan->fROMSize = 20; scan->fRead = 8;
scan->fBuf[1] = OSSwapHostToBigInt32( kFWBIBBusName ); scan->fAddr.addressLo = kConfigROMBaseAddress+8;
scan->fCmd->reinit(scan->fAddr, scan->fBuf+2, 1,
&readROMGlue, scan, true);
scan->fCmd->setMaxSpeed( kFWSpeed100MBit );
scan->fCmd->setRetries( kFWCmdDefaultRetries );
scan->fCmd->setPingTime( true );
FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 4 );
scan->fCmd->submit();
done = false;
}
}
else if( scan->fRead < 16 )
{
if(scan->fROMSize > scan->fRead)
{
scan->fRead += 4;
scan->fAddr.addressLo = kConfigROMBaseAddress+scan->fRead;
scan->fCmd->reinit(scan->fAddr, scan->fBuf+scan->fRead/4, 1,
&readROMGlue, scan, true);
scan->fCmd->setMaxSpeed( kFWSpeed100MBit );
scan->fCmd->setRetries(kFWCmdDefaultRetries);
scan->fCmd->setPingTime( false );
FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 5 );
scan->fCmd->submit();
done = false;
}
else
{
done = true;
}
}
else if( scan->fContenderNeedsChecking && (FWSpeed( scan->fAddr.nodeID ) > kFWSpeed100MBit) )
{
if( ((scan->fAddr.nodeID & 63) == (fIRMNodeID & 63)) || fDelegateCycleMaster )
{
if( !scan->fIRMCheckingRead )
{
scan->fIRMCheckingRead = true;
scan->fAddr.addressLo = kCSRChannelsAvailable63_32;
scan->fCmd->reinit(scan->fAddr, &scan->fIRMBitBucketOld, 1,
&readROMGlue, scan, true);
scan->fCmd->setMaxSpeed( kFWSpeed100MBit );
scan->fCmd->setRetries(kFWCmdDefaultRetries);
FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 6 );
scan->fCmd->submit();
done = false;
}
else
{
scan->fIRMCheckingLock = true; scan->fContenderNeedsChecking = false; scan->fAddr.addressLo = kCSRChannelsAvailable63_32;
scan->fLockCmd->reinit( scan->generation, scan->fAddr, &scan->fIRMBitBucketOld, &scan->fIRMBitBucketNew, 1, &readROMGlue, scan);
scan->fLockCmd->setMaxSpeed( kFWSpeed100MBit );
scan->fLockCmd->setRetries(kFWCmdDefaultRetries);
FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 7 );
scan->fLockCmd->submit();
done = false;
}
}
}
if( done )
{
UInt32 nodeID = FWAddressToID(scan->fAddr.nodeID);
FWKLOG(( "IOFireWireController::readDeviceROM scan for ID %lx is %lx\n",nodeID,(long) scan ));
fScans[nodeID] = scan;
updateDevice( scan );
fNumROMReads--;
if(fNumROMReads == 0)
{
FWTrace( kFWTController, kTPControllerReadDeviceROM, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), status, 2 );
finishedBusScan();
}
}
FWKLOG(( "IOFireWireController::readDeviceROM exited\n" ));
}
bool IOFireWireController::checkForDuplicateGUID(IOFWNodeScan *scan, CSRNodeUniqueID *currentGUIDs )
{
CSRNodeUniqueID guid;
UInt32 nodeID;
UInt32 i;
nodeID = FWAddressToID(scan->fAddr.nodeID);
if(scan->fROMSize >= 20)
{
UInt32 guid_hi = OSSwapBigToHostInt32( scan->fBuf[3] );
UInt32 guid_lo = OSSwapBigToHostInt32( scan->fBuf[4] );
guid = ((CSRNodeUniqueID)guid_hi << 32) | guid_lo;
}
else
{
currentGUIDs[nodeID] = 0;
return false; }
currentGUIDs[nodeID] = guid;
if( !guid || fGUIDDups->findDuplicateGUID( guid, fBusGeneration ) )
return false;
for( i = 0; i< nodeID; i++ )
{
if( currentGUIDs[i] == guid )
{
fGUIDDups->addDuplicateGUID( guid, fBusGeneration );
return true;
}
}
return false;
}
void IOFireWireController::updateDevice(IOFWNodeScan *scan )
{
FWTrace( kFWTController, kTPControllerUpdateDevice, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 0 );
UInt32 bib_quad = OSSwapBigToHostInt32( scan->fBuf[2] );
if( !fBusMgr )
{
fBusMgr = bib_quad & kFWBIBBmc;
}
#if (DEBUGGING_LEVEL > 0)
IOLog("Update Device Finished reading ROM for node 0x%x\n", scan->fAddr.nodeID);
#endif
IOFireWireDevice * newDevice = NULL;
do
{
CSRNodeUniqueID guid;
OSIterator *childIterator;
UInt32 nodeID;
bool duplicate;
bool minimal = false;
nodeID = FWAddressToID(scan->fAddr.nodeID);
if(scan->fROMSize >= 20)
{
UInt32 guid_hi = OSSwapBigToHostInt32( scan->fBuf[3] );
UInt32 guid_lo = OSSwapBigToHostInt32( scan->fBuf[4] );
guid = ((CSRNodeUniqueID)guid_hi << 32) | guid_lo;
}
else
{
minimal = true;
guid = 0;
}
duplicate = fGUIDDups->findDuplicateGUID( guid, fBusGeneration );
if( (guid == 0) || duplicate )
{
fNodes[nodeID] = createDummyRegistryEntry( scan );
if( minimal )
{
OSObject * prop = OSData::withBytes( &scan->fBuf[0], scan->fROMSize );
if( prop != NULL )
{
fNodes[nodeID]->setProperty( gFireWireROM, prop );
prop->release();
}
}
else
{
OSObject * prop = OSNumber::withNumber( guid, 64 );
if( prop != NULL )
{
fNodes[nodeID]->setProperty( gFireWire_GUID, prop );
prop->release();
}
}
continue;
}
childIterator = getClientIterator();
if( childIterator)
{
OSObject *child;
while( (child = childIterator->getNextObject()))
{
IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child);
if( found )
{
found->lockForArbitration();
if( found->fUniqueID == guid && (found->getTerminationState() != kTerminated) )
{
newDevice = found;
break;
}
found->unlockForArbitration();
}
}
childIterator->release();
}
if(newDevice)
{
FWTrace( kFWTController, kTPControllerUpdateDeviceNewDevice, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, (uintptr_t)newDevice );
#if IOFIREWIREDEBUG > 0
IOLog("UpdateDevice Found old device 0x%p\n", newDevice);
#endif
if( newDevice->getTerminationState() == kNeedsTermination )
{
newDevice->setTerminationState( kNotTerminated );
}
newDevice->unlockForArbitration();
newDevice->setNodeROM(fBusGeneration, fLocalNodeID, scan);
newDevice->retain(); }
else
{
newDevice = fFWIM->createDeviceNub(guid, scan);
if (!newDevice)
continue;
FWTrace( kFWTController, kTPControllerUpdateDeviceCreateDevice, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, (uintptr_t)newDevice );
#if IOFIREWIREDEBUG > 0
IOLog("Update Device Creating new device 0x%p\n", newDevice);
#endif
ErrorLogCond( !newDevice, "IOFireWireController@%p::updateDevice Error creating device nub! (%p, %p)\n", this, fFWIM, newDevice );
newDevice->adjustBusy( 1 ); adjustBusy( 1 );
FWKLOG(( "IOFireWireController@%p::updateDevice adjustBusy(1)\n", this ));
if( !newDevice->attach(this) )
{
newDevice->adjustBusy( -1 ); adjustBusy( -1 ); FWKLOG(( "IOFireWireController@%p::updateDevice adjustBusy(-1)\n", this ));
continue;
}
newDevice->setRegistrationState( IOFireWireDevice::kDeviceNeedsRegisterService );
newDevice->setNodeROM( fBusGeneration, fLocalNodeID, scan );
}
fNodes[nodeID] = newDevice;
fNodes[nodeID]->retain();
} while (false);
if (newDevice)
newDevice->release();
}
IORegistryEntry * IOFireWireController::createDummyRegistryEntry( IOFWNodeScan *scan )
{
OSDictionary *propTable;
OSObject * prop;
propTable = OSDictionary::withCapacity(3);
prop = OSNumber::withNumber(scan->fAddr.nodeID, 16);
propTable->setObject(gFireWireNodeID, prop);
prop->release();
prop = OSNumber::withNumber((OSSwapBigToHostInt32(scan->fSelfIDs[0]) & kFWSelfID0SP) >> kFWSelfID0SPPhase, 32);
propTable->setObject(gFireWireSpeed, prop);
prop->release();
prop = OSData::withBytes(scan->fSelfIDs, scan->fNumSelfIDs*sizeof(UInt32));
propTable->setObject(gFireWireSelfIDs, prop);
prop->release();
IORegistryEntry * newPhy;
newPhy = OSTypeAlloc( IORegistryEntry );
if(newPhy)
{
if(!newPhy->init(propTable))
{
newPhy->release();
newPhy = NULL;
}
if(getSecurityMode() == kIOFWSecurityModeNormal) {
setNodeIDPhysicalFilter( scan->fAddr.nodeID & 0x3f, true );
}
if(propTable)
propTable->release();
}
return newPhy;
}
void IOFireWireController::finishedBusScan()
{
FWTrace_Start( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 0 );
static UInt32 gaps[26] = {63, 5, 7, 8, 10, 13, 16, 18, 21,
24, 26, 29, 32, 35, 37, 40, 43,
46, 48, 51, 54, 57, 59, 62, 63};
int i;
if( AssignCycleMaster() )
{
FWTrace_End( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 1 );
return;
}
fBadIRMsKnown = false;
{
CSRNodeUniqueID currentGUIDs[kFWMaxNodesPerBus];
for( i=0; i<=fRootNodeID; i++ )
{
if( fScans[i] )
{
if( checkForDuplicateGUID( fScans[i], currentGUIDs ) )
{
FWTrace(kFWTResetBusAction, kTPResetFinishedBusScan, (uintptr_t)fFWIM, fScans[i]->fAddr.nodeID, 1, 0 );
resetBus();
FWTrace_End( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 2 );
return; }
fScans[i]->fCmd->release();
fScans[i]->fLockCmd->release();
IOFree(fScans[i], sizeof(*fScans[i]));
fScans[i] = NULL;
}
else
{
currentGUIDs[i] = 0;
}
}
}
if( !fBusResetScheduled && !fBusMgr && fLocalNodeID == fIRMNodeID)
{
UInt32 * pingTimes;
int maxHops;
UInt32 maxPing = 0;
UInt32 pingGap=0, hopGap=0, newGap=0;
bool retoolGap = false;
if ( not fForcedGapFlag )
{
pingTimes = fFWIM->getPingTimes();
for( i=0; i<=fRootNodeID; i++ )
{
if( pingTimes[i] > maxPing )
maxPing = pingTimes[i];
}
maxHops = fRootNodeID;
if (maxHops > 25)
maxHops = 25;
if( maxPing > 245 )
maxPing = 245;
if( maxPing >= 29 )
pingGap = gaps [(maxPing - 20) / 9]; else
pingGap = 5;
hopGap = gaps[maxHops];
if( hopGap > pingGap )
newGap = hopGap;
else
newGap = pingGap;
fGapCount = newGap << kFWPhyConfigurationGapCntPhase;
}
else
{
if( fPreviousGap != (fForcedGapCount << kFWPhyConfigurationGapCntPhase) )
{
fGapCount = fForcedGapCount << kFWPhyConfigurationGapCntPhase;
retoolGap = true;
IOLog( "IOFireWireController::finishedBusScan retoold GAP %d\n", __LINE__ );
}
}
FWKLOG(("IOFireWireController MaxPingTime: 0x%lx PingGap: 0x%lx HopGap: 0x%lx Setting Gap to 0x%lx\n",maxPing, pingGap, hopGap, newGap));
FWTrace( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, pingGap, hopGap, newGap );
fGapCount = ( fForcedGapFlag ) ? fForcedGapCount << kFWPhyConfigurationGapCntPhase : newGap << kFWPhyConfigurationGapCntPhase;
if(fRootNodeID == 0)
{
fFWIM->setRootHoldOff(false);
}
else
{
fFWIM->sendPHYPacket((kFWConfigurationPacketID << kFWPhyPacketIDPhase) |
((fLocalNodeID & 63) << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR );
fFWIM->setRootHoldOff(true);
if(fRootNodeID != (fLocalNodeID & 63))
{
FWTrace(kFWTResetBusAction, kTPResetFinishedBusScan, (uintptr_t)fFWIM, 0, 2, 0 );
resetBus();
FWKLOG(( "IOFireWireController::finishedBusScan exited\n" ));
FWTrace_End( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 3 );
return; }
}
fFWIM->setCycleMaster(true);
if(fRootNodeID != 0)
{
for( i = 1; i <= fRootNodeID; i++ )
{
if( (OSSwapBigToHostInt32(*fNodeIDs[i]) & kFWSelfID0GapCnt) != (OSSwapBigToHostInt32(*fNodeIDs[i - 1]) & kFWSelfID0GapCnt) )
{
retoolGap = true;
break;
}
}
if( !retoolGap && !fDSLimited )
{
for( i = 0; i <= fRootNodeID; i++ )
{
if( ((OSSwapBigToHostInt32(*fNodeIDs[i]) & kFWSelfID0GapCnt) != fPreviousGap
&& (OSSwapBigToHostInt32(*fNodeIDs[i]) & kFWSelfID0GapCnt) != fGapCount)
|| ((OSSwapBigToHostInt32(*fNodeIDs[i]) & kFWSelfID0GapCnt) == 0) )
{
retoolGap = true;
break;
}
}
}
if( retoolGap )
{
fPreviousGap = fGapCount;
fDelayedPhyPacket = (kFWConfigurationPacketID << kFWPhyPacketIDPhase) |
((fLocalNodeID & 63) << kFWPhyPacketPhyIDPhase) |
kFWPhyConfigurationR | fGapCount | kFWPhyConfigurationT;
FWTrace(kFWTResetBusAction, kTPResetFinishedBusScan, (uintptr_t)fFWIM, fGapCount, 3, 0 );
resetBus();
FWKLOG(( "IOFireWireController::finishedBusScan exited\n" ));
FWTrace_End( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 4 );
return; }
}
}
if(fBusState == kScanning)
{
bool wouldTerminateDevice = false;
OSIterator * childIterator;
childIterator = getClientIterator();
if( childIterator )
{
OSObject *child;
while( (child = childIterator->getNextObject()))
{
IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child);
if( found && (found->getTerminationState() == kNotTerminated) && found->fNodeID == kFWBadNodeID )
{
wouldTerminateDevice = true;
}
}
childIterator->release();
}
if( (fRootNodeID == 0) && (fDevicePruneDelay < kOnlyNodeDevicePruneDelay) )
{
fDevicePruneDelay = kOnlyNodeDevicePruneDelay;
}
if( !wouldTerminateDevice )
{
fDevicePruneDelay = kNormalDevicePruneDelay;
}
fBusState = kWaitingPrune; fDelayedStateChangeCmd->reinit(1000 * fDevicePruneDelay, delayedStateChange, NULL); FWTrace(kFWTStateChangeAction, kTPStateChangeFinishedBusScan, (uintptr_t)fFWIM, fBusState, 0, 0 );
fDelayedStateChangeCmd->submit();
}
IOFWCmdQ &resetQ(getAfterResetHandledQ());
resetQ.executeQueue(true);
IOFWCommand *cmd;
while( (cmd = resetQ.fHead) )
{
cmd->cancel(kIOReturnTimeout);
}
FWKLOG(( "IOFireWireController::finishedBusScan exited\n" ));
FWTrace_End( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 0 );
}
UInt32 IOFireWireController::countNodeIDChildren( UInt16 nodeID, int hub_port, int * hubChildRemainder, bool * hubParentFlag )
{
UInt32 id0, idn;
UInt32 *idPtr;
int i;
int children = 0;
int ports;
UInt32 port;
int mask, shift;
if( hub_port > 2 )
{
IOLog( "IOFireWireController::countNodeIDChildren - hub_port = %d out of range.\n", hub_port );
}
i = nodeID & 63;
idPtr = fNodeIDs[i];
id0 = OSSwapBigToHostInt32(*idPtr++);
mask = kFWSelfID0P0;
shift = kFWSelfID0P0Phase;
for(ports=0; ports<3; ports++)
{
port = (id0 & mask) >> shift;
if(port == kFWSelfIDPortStatusChild)
{
children++;
}
if( ports == hub_port )
{
if( port == kFWSelfIDPortStatusChild )
{
if( hubChildRemainder != NULL )
*hubChildRemainder = children;
}
else if( port == kFWSelfIDPortStatusParent )
{
if( hubParentFlag != NULL )
*hubParentFlag = true;
}
}
mask >>= 2;
shift -= 2;
}
if(fNodeIDs[i+1] > idPtr)
{
idn = OSSwapBigToHostInt32(*idPtr++);
mask = kFWSelfIDNPa;
shift = kFWSelfIDNPaPhase;
for(ports=0; ports<8; ports++)
{
port = (idn & mask) >> shift;
if(port == kFWSelfIDPortStatusChild)
children++;
mask >>= 2;
shift -= 2;
}
if(fNodeIDs[i+1] > idPtr)
{
idn = OSSwapBigToHostInt32(*idPtr++);
mask = kFWSelfIDNPa;
shift = kFWSelfIDNPaPhase;
for(ports=0; ports<5; ports++)
{
port = (idn & mask) >> shift;
if(port == kFWSelfIDPortStatusChild)
children++;
mask >>= 2;
shift -= 2;
}
}
}
return children;
}
UInt32 IOFireWireController::getPortNumberFromIndex( UInt16 index )
{
UInt32 id0, idn;
UInt32 *idPtr;
int i;
int children = 0;
int ports;
UInt32 port;
int mask, shift;
i = fLocalNodeID & 63;
idPtr = fNodeIDs[i];
id0 = OSSwapBigToHostInt32(*idPtr++);
mask = kFWSelfID0P0;
shift = kFWSelfID0P0Phase;
for(ports=0; ports<3; ports++)
{
port = (id0 & mask) >> shift;
if(port == kFWSelfIDPortStatusChild)
{
if( index == children )
return ports;
children++;
}
mask >>= 2;
shift -= 2;
}
if(fNodeIDs[i+1] > idPtr)
{
idn = OSSwapBigToHostInt32(*idPtr++);
mask = kFWSelfIDNPa;
shift = kFWSelfIDNPaPhase;
for(ports=0; ports<8; ports++)
{
if(port == kFWSelfIDPortStatusChild)
{
if( index == children )
return ports;
children++;
}
mask >>= 2;
shift -= 2;
}
}
return 0xFFFFFFFF;
}
void IOFireWireController::buildTopology(bool doFWPlane)
{
FWTrace_Start( kFWTController, kTPControllerBuildTopology, (uintptr_t)fFWIM, (uintptr_t)doFWPlane, 0, 0 );
int i, maxDepth;
IORegistryEntry *root;
struct FWNodeScan
{
int nodeID;
int childrenRemaining;
int hubChildRemainder;
bool hubParentFlag;
IORegistryEntry *node;
};
FWNodeScan scanList[kFWMaxNodesPerBus];
FWNodeScan *level;
maxDepth = 0;
root = fNodes[fRootNodeID];
level = scanList;
for(i=fRootNodeID; i>=0; i--)
{
UInt32 id0;
UInt8 speedCode;
IORegistryEntry *node = fNodes[i];
int children = 0;
if( (i == (fLocalNodeID & 63)) && (fHubPort != kFWInvalidPort) )
{
bool hubParent = false;
int hubChildRemainder = 0;
children = countNodeIDChildren( i, fHubPort, &hubChildRemainder, &hubParent );
level->nodeID = i;
level->childrenRemaining = children;
level->hubChildRemainder = hubChildRemainder;
level->hubParentFlag = hubParent;
level->node = node;
}
else
{
children = countNodeIDChildren( i );
level->nodeID = i;
level->childrenRemaining = children;
level->hubChildRemainder = 0;
level->hubParentFlag = false;
level->node = node;
}
id0 = OSSwapBigToHostInt32(*fNodeIDs[i]);
speedCode = (id0 & kFWSelfID0SP) >> kFWSelfID0SPPhase;
if( !doFWPlane )
{
if( speedCode == kFWSpeedReserved )
speedCode = kFWSpeed800MBit | kFWSpeedUnknownMask; }
if( fDSLimited && !(speedCode & kFWSpeedUnknownMask) )
{
speedCode = kFWSpeed100MBit;
}
setNodeSpeed(i, i, speedCode);
if (i != fRootNodeID)
{
int parentNodeNum, scanNodeNum;
parentNodeNum = (level-1)->nodeID;
if(doFWPlane)
{
FWNodeScan * parent_level = (level-1);
if( parent_level->hubChildRemainder == parent_level->childrenRemaining )
{
if( parent_level->childrenRemaining == 0 )
{
IOLog( "IOFireWireController::buildTopology - parent child count is 0!\n" );
}
else
{
node->setProperty( "Built-in Hub", true );
}
}
else if( level->hubParentFlag )
{
parent_level->node->setProperty( "Built-in Hub", true );
}
if( (node != NULL) && (parent_level->node != NULL) )
{
node->attachToParent( parent_level->node, gIOFireWirePlane );
}
}
else
{
for (scanNodeNum = i + 1; scanNodeNum <= fRootNodeID; scanNodeNum++)
{
IOFWSpeed fwspeed = FWSpeed(parentNodeNum, scanNodeNum);
if ( fwspeed > 0xFF )
ErrorLog("Found oversized speed map entry during speed checking\n");
UInt8 scanSpeedCode = (UInt8)fwspeed;
UInt8 calcSpeedCode = scanSpeedCode;
if ( (speedCode & ~kFWSpeedUnknownMask) < (scanSpeedCode & ~kFWSpeedUnknownMask) )
{
calcSpeedCode = speedCode;
}
if( (speedCode & kFWSpeedUnknownMask) || (scanSpeedCode & kFWSpeedUnknownMask) )
{
calcSpeedCode |= kFWSpeedUnknownMask;
}
setNodeSpeed(i, scanNodeNum, calcSpeedCode);
}
}
}
if (i > 0)
{
while (level->childrenRemaining == 0)
{
level--;
if(level < scanList)
{
IOLog("SelfIDs don't build a proper tree (missing selfIDS?)!!\n");
return;
}
level->childrenRemaining--;
}
level++;
if(level - scanList > maxDepth)
{
maxDepth = level - scanList;
}
}
}
setNodeSpeed(fLocalNodeID, fLocalNodeID, (FWSpeed(fLocalNodeID, fLocalNodeID) & ~kFWSpeedUnknownMask));
#if (DEBUGGING_LEVEL > 0)
IOLog("MaxDepth:%d LocalNodeID:%x\n", maxDepth, fLocalNodeID);
IOLog("FireWire Speed map:\n");
for(i=0; i <= fRootNodeID; i++) {
int j;
for(j=0; j <= fRootNodeID; j++) {
IOLog("%-2x ", (unsigned int)FWSpeed(i, j) );
}
IOLog("\n");
}
#endif
#if 0
if( doFWPlane )
{
IOLog( "FireWire Hop Counts:\n" );
for( i=0; i <= fRootNodeID; i++ )
{
int j;
for( j=0; j <= fRootNodeID; j++ )
{
if ( j < i )
IOLog("_ ");
else
IOLog("%-2lu ", hopCount(i,j));
}
IOLog( "\n" );
}
}
#endif
if(doFWPlane && (root != NULL))
root->attachToParent(IORegistryEntry::getRegistryRoot(), gIOFireWirePlane);
FWTrace_End( kFWTController, kTPControllerBuildTopology, (uintptr_t)fFWIM, (uintptr_t)doFWPlane, 0, 0 );
}
void IOFireWireController::updatePlane()
{
FWTrace( kFWTController, kTPControllerUpdatePlane, (uintptr_t)fFWIM, 0, 0, 0 );
OSIterator *childIterator;
bool foundTDM = false;
fDevicePruneDelay = kNormalDevicePruneDelay;
childIterator = getClientIterator();
if( childIterator )
{
OSObject *child;
while( (child = childIterator->getNextObject()))
{
IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child);
if( found && (found->getTerminationState() == kNotTerminated) )
{
if( found->fNodeID == kFWBadNodeID )
{
FWTrace( kFWTController, kTPControllerUpdatePlane, (uintptr_t)fFWIM, (uintptr_t)found, 1, 0 );
terminateDevice( found );
}
else
{
OSString * tdm_string = OSDynamicCast( OSString, found->getProperty( gFireWireTDM ) );
if( (tdm_string != NULL) &&
(strncmp( "PPC", tdm_string->getCStringNoCopy(), 4 ) == 0) )
{
foundTDM = true;
}
}
}
}
childIterator->release();
}
OSObject * existProp = fFWIM->getProperty( "FWDSLimit" );
if( existProp && !foundTDM )
{
fFWIM->setLinkMode( kIOFWSetDSLimit, 0 );
FWTrace(kFWTResetBusAction, kTPResetUpdatePlane, (uintptr_t)fFWIM, 0, 0, 0 );
resetBus();
}
buildTopology(true);
messageClients( kIOFWMessageTopologyChanged );
char busGenerationStr[32];
snprintf(busGenerationStr, sizeof(busGenerationStr), "%x", (uint32_t)fBusGeneration);
setProperty( kFireWireGenerationID, busGenerationStr);
FWKLOG(("IOFireWireController::updatePlane reset generation to '%s'\n", busGenerationStr));
fUseHalfSizePackets = fRequestedHalfSizePackets;
}
void IOFireWireController::terminateDevice( IOFireWireDevice * device )
{
if( device->isOpen() )
{
device->lockForArbitration();
device->setTerminationState( kNeedsTermination );
device->unlockForArbitration();
messageClient( kIOFWMessageServiceIsRequestingClose, device );
}
else
{
device->lockForArbitration();
device->setTerminationState( kTerminated );
device->unlockForArbitration();
IOFireWireDevice::terminateDevice( device );
}
}
#pragma mark -
void IOFireWireController::setPhysicalAccessMode( IOFWPhysicalAccessMode mode )
{
closeGate();
if( mode == kIOFWPhysicalAccessEnabled &&
getSecurityMode() == kIOFWSecurityModeNormal )
{
fPhysicalAccessMode = kIOFWPhysicalAccessEnabled;
FWKLOG(( "IOFireWireController::setPhysicalAccessMode - enable physical access\n" ));
OSIterator * iterator = getClientIterator();
OSObject * child = NULL;
while( (child = iterator->getNextObject()) )
{
IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child);
if( found && (found->getTerminationState() == kNotTerminated) )
{
found->configurePhysicalFilter();
}
}
iterator->release();
}
if( mode == kIOFWPhysicalAccessDisabled )
{
fPhysicalAccessMode = kIOFWPhysicalAccessDisabled;
FWKLOG(( "IOFireWireController::setPhysicalAccessMode - disable physical access\n" ));
fFWIM->setNodeIDPhysicalFilter( kIOFWAllPhysicalFilters, false );
}
if( mode == kIOFWPhysicalAccessDisabledForGeneration &&
fPhysicalAccessMode != kIOFWPhysicalAccessDisabled )
{
fPhysicalAccessMode = kIOFWPhysicalAccessDisabledForGeneration;
FWKLOG(( "IOFireWireController::setPhysicalAccessMode - disable physical access for this bus generation\n" ));
fFWIM->setNodeIDPhysicalFilter( kIOFWAllPhysicalFilters, false );
}
openGate();
}
IOFWPhysicalAccessMode IOFireWireController::getPhysicalAccessMode( void )
{
return fPhysicalAccessMode;
}
void IOFireWireController::physicalAccessProcessBusReset( void )
{
if( fPhysicalAccessMode == kIOFWPhysicalAccessDisabledForGeneration &&
getSecurityMode() == kIOFWSecurityModeNormal )
{
fPhysicalAccessMode = kIOFWPhysicalAccessEnabled;
FWKLOG(( "IOFireWireController::physicalAccessProcessBusReset - re-enable physical access because of bus reset\n" ));
}
}
void IOFireWireController::setNodeIDPhysicalFilter( UInt16 nodeID, bool state )
{
if( fPhysicalAccessMode == kIOFWPhysicalAccessEnabled )
{
FWKLOG(( "IOFireWireController::setNodeIDPhysicalFilter - set physical access for node 0x%x to %d\n", nodeID, state ));
fFWIM->setNodeIDPhysicalFilter( nodeID, state );
}
}
bool IOFireWireController::isPhysicalAccessEnabledForNodeID( UInt16 nodeID )
{
return fFWIM->isPhysicalAccessEnabledForNodeID( nodeID );
}
#pragma mark -
IOService *IOFireWireController::findKeyswitchDevice( void )
{
IORegistryIterator * iter;
IORegistryEntry * entry = 0;
iter = IORegistryIterator::iterateOver( gIODTPlane,
kIORegistryIterateRecursively );
if ( iter )
{
while (( entry = iter->getNextObject() ))
{
if (( strncmp( entry->getName(), "keySwitch-gpio", 16 ) == 0 ) or
( strncmp( entry->getName(), "keySwitch", 11 ) == 0 ) or
( strncmp( entry->getName(), "KYLK", 5 ) == 0 ) )
break;
}
iter->release();
}
return OSDynamicCast( IOService, entry );
}
void IOFireWireController::initSecurity( void )
{
#ifdef kIOConsoleSecurityInterest
{
const OSSymbol * console_security_interest = OSSymbol::withCStringNoCopy( kIOConsoleSecurityInterest );
fConsoleLockNotifier = IOService::getServiceRoot()->registerInterest( console_security_interest, &IOFireWireController::consoleLockInterestHandler, this, NULL );
if( fConsoleLockNotifier == NULL )
{
fConsoleLockNotifier->enable(true);
}
}
#endif
bool waitForKeyswitch = false;
if( findKeyswitchDevice() )
waitForKeyswitch = true;
IOFWSecurityMode mode = kIOFWSecurityModeNormal;
#ifdef kIOConsoleSecurityInterest
{
IORegistryEntry * root = IORegistryEntry::getRegistryRoot();
OSObject * console_lock_property = NULL;
if( root )
{
console_lock_property = root->getProperty( kIOConsoleLockedKey );
}
OSBoolean * console_locked = NULL;
if( console_lock_property )
{
console_locked = OSDynamicCast( OSBoolean, console_lock_property );
}
if( console_locked && console_locked->isTrue() )
{
mode = kIOFWSecurityModeSecure;
}
}
#endif
{
char matchPath[32]; OSDictionary * optionsMatchDictionary = IOOFPathMatching( "/options", matchPath, 32 );
mach_timespec_t t = { 10, 0 }; IOService * options = IOService::waitForService( optionsMatchDictionary, &t );
if( options != NULL )
{
OSString * securityModeProperty = OSDynamicCast( OSString, options->getProperty("security-mode") );
if( securityModeProperty != NULL && strncmp( "none", securityModeProperty->getCStringNoCopy(), 5 ) != 0 )
{
mode = kIOFWSecurityModeSecurePermanent;
}
}
else
{
ErrorLog("FireWire unable to determine security-mode; defaulting to full-secure.\n");
mode = kIOFWSecurityModeSecurePermanent;
}
}
if( mode != kIOFWSecurityModeSecurePermanent )
{
UInt8 retryCount = 5;
do
{
OSIterator * iterator = NULL;
OSBoolean * keyswitchState = NULL;
OSDictionary * keyswitch_match_dict = keyswitch_match_dict = nameMatching("AppleKeyswitch");
if( keyswitch_match_dict )
{
iterator = getMatchingServices( keyswitch_match_dict );
if( iterator != NULL )
{
OSObject * obj = NULL;
waitForKeyswitch = false;
if( (obj = iterator->getNextObject()) )
{
IOService * service = (IOService*)obj;
keyswitchState = OSDynamicCast( OSBoolean, service->getProperty( "Keyswitch" ) );
if( keyswitchState->isTrue() )
{
mode = kIOFWSecurityModeSecure;
}
}
iterator->release();
iterator = NULL;
}
keyswitch_match_dict->release();
}
if( retryCount == 0 )
waitForKeyswitch = false;
retryCount--;
if( waitForKeyswitch )
{
IOLog("Waiting for AppleKeyswitch ...\n");
IOSleep(1000);
}
}while( waitForKeyswitch );
OSDictionary * name_match_dict = nameMatching( "AppleKeyswitch" );
if( name_match_dict )
{
fKeyswitchNotifier = addMatchingNotification( gIOMatchedNotification, name_match_dict,
(IOServiceMatchingNotificationHandler)&IOFireWireController::serverKeyswitchCallback,
this, 0 );
name_match_dict->release();
}
}
setSecurityMode( mode );
}
void IOFireWireController::freeSecurity( void )
{
if( fConsoleLockNotifier )
{
fConsoleLockNotifier->remove();
fConsoleLockNotifier = NULL;
}
if( fKeyswitchNotifier != NULL )
{
fKeyswitchNotifier->remove();
fKeyswitchNotifier = NULL;
}
}
IOReturn IOFireWireController::consoleLockInterestHandler( void * target, void * refCon,
UInt32 messageType, IOService * provider,
void * messageArgument, vm_size_t argSize )
{
IOFireWireController * me = OSDynamicCast( IOFireWireController, (OSObject *)target );
if ( me != NULL )
{
if( me->getSecurityMode() != kIOFWSecurityModeSecurePermanent )
{
IORegistryEntry * root = IORegistryEntry::getRegistryRoot();
OSObject * console_lock_property = NULL;
if( root )
{
console_lock_property = root->getProperty( kIOConsoleLockedKey );
}
OSBoolean * console_locked = NULL;
if( console_lock_property )
{
console_locked = OSDynamicCast( OSBoolean, console_lock_property );
}
if( console_locked && console_locked->isTrue() )
{
me->setSecurityMode( kIOFWSecurityModeSecure );
}
else
{
me->setSecurityMode( kIOFWSecurityModeNormal );
}
}
}
return kIOReturnSuccess;
}
bool IOFireWireController::serverKeyswitchCallback( void * target, void * refCon, IOService * service, IONotifier * notifier )
{
OSBoolean * keyswitchState = NULL;
IOFireWireController * me = NULL;
if( me != NULL )
{
me = OSDynamicCast( IOFireWireController, (OSObject *)target );
if ( me->getSecurityMode() != kIOFWSecurityModeSecurePermanent )
{
keyswitchState = OSDynamicCast( OSBoolean, service->getProperty( "Keyswitch" ) );
if( keyswitchState != NULL )
{
if( keyswitchState->isFalse() )
{
me->setSecurityMode( kIOFWSecurityModeNormal );
}
else if( keyswitchState->isTrue() )
{
me->setSecurityMode( kIOFWSecurityModeSecure );
}
}
}
}
return true;
}
void IOFireWireController::setSecurityMode( IOFWSecurityMode mode )
{
closeGate();
fSecurityMode = mode;
switch( fSecurityMode )
{
case kIOFWSecurityModeNormal:
FWKLOG(( "IOFireWireController::setSecurityMode - set mode to normal\n" ));
fFWIM->setSecurityMode( mode );
setPhysicalAccessMode( kIOFWPhysicalAccessEnabled );
break;
case kIOFWSecurityModeSecure:
case kIOFWSecurityModeSecurePermanent:
FWKLOG(( "IOFireWireController::setSecurityMode - set mode to secure\n" ));
fFWIM->setSecurityMode( mode );
setPhysicalAccessMode( kIOFWPhysicalAccessDisabled );
break;
default:
IOLog( "IOFireWireController::setSecurityMode - illegal security mode = 0x%x\n", fSecurityMode );
break;
}
openGate();
}
IOFWSecurityMode IOFireWireController::getSecurityMode( void )
{
return fSecurityMode;
}
#pragma mark -
IOLocalConfigDirectory * IOFireWireController::getRootDir() const
{
return fRootDir;
}
IOReturn IOFireWireController::AddUnitDirectory(IOLocalConfigDirectory *unitDir)
{
IOReturn res;
closeGate();
if ( isInactive() )
{
openGate() ;
return kIOReturnOffline ;
}
getRootDir()->addEntry(kConfigUnitDirectoryKey, unitDir);
res = UpdateROM();
if(res == kIOReturnSuccess)
{
FWTrace(kFWTResetBusAction, kTPResetAddUnitDirectory, (uintptr_t)fFWIM, 0, 0, 0 );
res = resetBus();
}
openGate();
return res;
}
IOReturn IOFireWireController::RemoveUnitDirectory(IOLocalConfigDirectory *unitDir)
{
IOReturn res;
closeGate();
getRootDir()->removeSubDir(unitDir);
res = UpdateROM();
if(res == kIOReturnSuccess)
{
FWTrace(kFWTResetBusAction, kTPResetRemoveUnitDirectory, (uintptr_t)fFWIM, 0, 0, 0 );
res = resetBus();
}
openGate();
return res;
}
IOReturn IOFireWireController::UpdateROM()
{
UInt32 * hack;
UInt32 crc;
unsigned int numQuads;
OSData * rom;
IOReturn ret;
UInt32 generation;
IOFireWireLocalNode * localNode;
UInt32 bib_quad = OSSwapBigToHostInt32( fROMHeader[2] );
generation = bib_quad & kFWBIBGeneration;
generation += (1 << kFWBIBGenerationPhase);
generation &= kFWBIBGeneration;
if(generation < (2 << kFWBIBGenerationPhase))
generation = (2 << kFWBIBGenerationPhase);
fROMHeader[2] = OSSwapHostToBigInt32((bib_quad & ~kFWBIBGeneration) | generation);
rom = OSData::withBytes(&fROMHeader, sizeof(fROMHeader));
fRootDir->incrementGeneration();
fRootDir->compile(rom);
hack = (UInt32 *)rom->getBytesNoCopy();
UInt32 bibQuads = sizeof(fROMHeader)/sizeof(UInt32) - 1;
crc = FWComputeCRC16 (hack + 1, bibQuads);
*hack = OSSwapHostToBigInt32(
(((sizeof(fROMHeader)/sizeof(UInt32)-1) << kConfigBusInfoBlockLengthPhase) & kConfigBusInfoBlockLength) |
((bibQuads << kConfigROMCRCLengthPhase) & kConfigROMCRCLength) |
((crc << kConfigROMCRCValuePhase) & kConfigROMCRCValue) );
localNode = getLocalNode(this);
if(localNode)
localNode->setProperty(gFireWireROM, rom);
numQuads = rom->getLength()/sizeof(UInt32) - 1;
#if 0
{
unsigned int i;
IOLog("--------- FW Local ROM: --------\n");
for(i=0; i<numQuads+1; i++)
IOLog("ROM[%d] = 0x%x\n", i, OSSwapBigToHostInt32(hack[i]));
}
#endif
if(fROMAddrSpace)
{
freeAddress( fROMAddrSpace );
fROMAddrSpace->release();
fROMAddrSpace = NULL;
}
fROMAddrSpace = IOFWPseudoAddressSpace::simpleReadFixed( this,
FWAddress(kCSRRegisterSpaceBaseAddressHi, kConfigROMBaseAddress),
(numQuads+1)*sizeof(UInt32), rom->getBytesNoCopy());
ret = allocAddress(fROMAddrSpace);
if(kIOReturnSuccess == ret)
{
ret = fFWIM->updateROM(rom);
}
rom->release();
return ret ;
}
#pragma mark -
AsyncPendingTrans *IOFireWireController::allocTrans(IOFWAsyncCommand *cmd)
{
return allocTrans( cmd, NULL );
}
AsyncPendingTrans *IOFireWireController::allocTrans( IOFWAsyncCommand * cmd, IOFWCommand * altcmd )
{
unsigned int i;
unsigned int tran;
tran = fLastTrans;
for(i=0; i<kMaxPendingTransfers; i++) {
AsyncPendingTrans *t;
tran++;
if(tran >= kMaxPendingTransfers)
tran = 0;
t = &fTrans[tran];
if(!t->fInUse) {
t->fHandler = cmd;
t->fAltHandler = altcmd;
t->fInUse = true;
t->fTCode = tran;
fLastTrans = tran;
return t;
}
}
if ( fOutOfTLabels == 0 && fOutOfTLabelsThreshold == 0 )
IOLog("IOFireWireController:: Out of Transaction Labels\n");
fOutOfTLabels++;
return NULL;
}
void IOFireWireController::freeTrans(AsyncPendingTrans *trans)
{
trans->fHandler = NULL;
trans->fAltHandler = NULL;
trans->fInUse = false;
}
IOReturn IOFireWireController::asyncRead( UInt32 generation,
UInt16 nodeID,
UInt16 addrHi,
UInt32 addrLo,
int speed,
int label,
int size,
IOFWAsyncCommand * cmd)
{
return asyncRead( generation,
nodeID,
addrHi,
addrLo,
speed,
label,
size,
cmd,
kIOFWReadFlagsNone );
}
IOReturn IOFireWireController::asyncRead( UInt32 generation,
UInt16 nodeID,
UInt16 addrHi,
UInt32 addrLo,
int speed,
int label,
int size,
IOFWAsyncCommand * cmd,
IOFWReadFlags flags )
{
FWTrace_Start(kFWTController, kTPControllerAsyncRead, (uintptr_t)fFWIM, (uintptr_t)cmd, (uintptr_t)((nodeID << 16) | addrHi), addrLo );
if( !checkGeneration(generation) )
{
FWTrace_End(kFWTController, kTPControllerAsyncRead, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOFireWireBusReset, 1 );
return kIOFireWireBusReset;
}
if( nodeID == fLocalNodeID )
{
UInt32 rcode;
IOMemoryDescriptor *buf;
IOByteCount offset;
IOFWSpeed temp = (IOFWSpeed)speed;
rcode = doReadSpace( nodeID,
temp,
FWAddress(addrHi, addrLo),
size,
&buf,
&offset,
NULL,
(IOFWRequestRefCon)label );
if(rcode == kFWResponseComplete)
{
void * bytes = IOMalloc( size );
buf->readBytes( offset, bytes, size );
cmd->gotPacket( rcode, bytes, size );
IOFree( bytes, size );
}
else
{
cmd->gotPacket( rcode, NULL, 0 );
}
FWTrace_End(kFWTController, kTPControllerAsyncRead, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOReturnSuccess, 2 );
return kIOReturnSuccess;
}
else
{
int actual_speed = speed;
if( addrHi == kCSRRegisterSpaceBaseAddressHi )
{
if( (addrLo == kCSRBandwidthAvailable) ||
(addrLo == kCSRChannelsAvailable31_0) ||
(addrLo == kCSRChannelsAvailable63_32) ||
(addrLo == kCSRBusManagerID) )
{
actual_speed = kFWSpeed100MBit;
}
}
IOReturn status = fFWIM->asyncRead( nodeID, addrHi, addrLo, actual_speed, label, size, cmd, flags );
FWTrace_End(kFWTController, kTPControllerAsyncRead, (uintptr_t)fFWIM, (uintptr_t)cmd, status, 3 );
return status;
}
}
IOReturn IOFireWireController::asyncWrite( UInt32 generation,
UInt16 nodeID,
UInt16 addrHi,
UInt32 addrLo,
int speed,
int label,
void * data,
int size,
IOFWAsyncCommand * cmd)
{
IOLog( "IOFireWireController::asyncWrite : DEPRECATED API\n" );
return kIOReturnUnsupported;
}
IOReturn IOFireWireController::asyncWrite( UInt32 generation,
UInt16 nodeID,
UInt16 addrHi,
UInt32 addrLo,
int speed,
int label,
IOMemoryDescriptor * buf,
IOByteCount offset,
int size,
IOFWAsyncCommand * cmd )
{
return asyncWrite( generation,
nodeID,
addrHi,
addrLo,
speed,
label,
buf,
offset,
size,
cmd,
kIOFWWriteFlagsNone );
}
IOReturn IOFireWireController::asyncWrite( UInt32 generation,
UInt16 nodeID,
UInt16 addrHi,
UInt32 addrLo,
int speed,
int label,
IOMemoryDescriptor * buf,
IOByteCount offset,
int size,
IOFWAsyncCommand * cmd,
IOFWWriteFlags flags )
{
FWTrace_Start(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, (uintptr_t)((nodeID << 16) | addrHi), addrLo );
if( !checkGeneration(generation) )
{
FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOFireWireBusReset, 1 );
return kIOFireWireBusReset;
}
if( nodeID == fLocalNodeID )
{
UInt32 rcode;
IOFWSpeed temp = (IOFWSpeed)speed;
void * bytes = IOMalloc( size );
buf->readBytes( offset, bytes, size );
rcode = doWriteSpace( nodeID,
temp,
FWAddress( addrHi, addrLo ),
size,
bytes,
(IOFWRequestRefCon)label );
IOFree( bytes, size );
cmd->gotPacket(rcode, NULL, 0);
FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOReturnSuccess, 2 );
return kIOReturnSuccess;
}
else
{
int actual_speed = speed;
if( addrHi == kCSRRegisterSpaceBaseAddressHi )
{
if( (addrLo == kCSRBandwidthAvailable) ||
(addrLo == kCSRChannelsAvailable31_0) ||
(addrLo == kCSRChannelsAvailable63_32) ||
(addrLo == kCSRBusManagerID) )
{
actual_speed = kFWSpeed100MBit;
}
}
IOReturn status = fFWIM->asyncWrite( nodeID,
addrHi,
addrLo,
actual_speed,
label,
buf,
offset,
size,
cmd,
flags );
FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, status, 3 );
return status;
}
}
IOReturn IOFireWireController::asyncPHYPacket( UInt32 generation, UInt32 data, UInt32 data2, IOFWAsyncPHYCommand * cmd )
{
IOReturn status = kIOReturnSuccess;
if( !checkGeneration(generation) )
{
status = kIOFireWireBusReset;
}
if( status == kIOReturnSuccess )
{
if( !(data & 0x40000000) )
{
status = kIOReturnBadArgument;
}
}
if( status == kIOReturnSuccess )
{
status = fFWIM->asyncPHYPacket( data, data2, cmd );
}
return status;
}
IOReturn IOFireWireController::asyncLock( UInt32 generation,
UInt16 nodeID,
UInt16 addrHi,
UInt32 addrLo,
int speed,
int label,
int type,
void * data,
int size,
IOFWAsyncCommand * cmd )
{
IOLog( "IOFireWireController::asyncLock : DEPRECATED API\n" );
return kIOReturnUnsupported;
}
IOReturn IOFireWireController::asyncLock( UInt32 generation,
UInt16 nodeID,
UInt16 addrHi,
UInt32 addrLo,
int speed,
int label,
int type,
IOMemoryDescriptor * buf,
IOByteCount offset,
int size,
IOFWAsyncCommand * cmd )
{
FWTrace_Start(kFWTController, kTPControllerAsyncLock, (uintptr_t)fFWIM, (uintptr_t)cmd, (uintptr_t)((nodeID << 16) | addrHi), addrLo );
if( !checkGeneration(generation) )
{
FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOFireWireBusReset, 1 );
return kIOFireWireBusReset;
}
if( nodeID == fLocalNodeID )
{
UInt32 rcode;
UInt32 retVals[2];
UInt32 retSize = size / 2;
IOFWSpeed temp = (IOFWSpeed)speed;
IOFWRequestRefCon refcon = (IOFWRequestRefCon)(label | kRequestIsLock | (type << kRequestExtTCodeShift));
void * bytes = IOMalloc( size );
buf->readBytes( offset, bytes, size );
rcode = doLockSpace( nodeID,
temp,
FWAddress(addrHi, addrLo),
size,
(const UInt32*)bytes,
retSize,
retVals,
type,
refcon );
IOFree( bytes, size );
cmd->gotPacket( rcode, retVals, retSize );
FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOReturnSuccess, 2 );
return kIOReturnSuccess;
}
else
{
int actual_speed = speed;
if( addrHi == kCSRRegisterSpaceBaseAddressHi )
{
if( (addrLo == kCSRBandwidthAvailable) ||
(addrLo == kCSRChannelsAvailable31_0) ||
(addrLo == kCSRChannelsAvailable63_32) ||
(addrLo == kCSRBusManagerID) )
{
actual_speed = kFWSpeed100MBit;
}
}
IOReturn status = fFWIM->asyncLock( nodeID,
addrHi,
addrLo,
actual_speed,
label,
type,
buf,
offset,
size,
cmd );
FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, status, 3 );
return status;
}
}
IOReturn IOFireWireController::handleAsyncTimeout(IOFWAsyncCommand *cmd)
{
return fFWIM->handleAsyncTimeout(cmd);
}
IOReturn IOFireWireController::handleAsyncCompletion( IOFWCommand *cmd, IOReturn status )
{
return fFWIM->handleAsyncCompletion( cmd, status );
}
IOReturn IOFireWireController::asyncStreamWrite(UInt32 generation,
int speed, int tag, int sync, int channel,
IOMemoryDescriptor *buf, IOByteCount offset,
int size, IOFWAsyncStreamCommand *cmd)
{
FWTrace_Start(kFWTController, kTPControllerAsyncStreamWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, channel, 0);
if(!checkGeneration(generation))
{
FWTrace_End(kFWTController, kTPControllerAsyncStreamWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, channel, kIOFireWireBusReset);
return (kIOFireWireBusReset);
}
IOReturn status = fFWIM->asyncStreamTransmit((UInt32)channel, speed, (UInt32) sync, (UInt32) tag, buf, offset, size, cmd);
FWTrace_End(kFWTController, kTPControllerAsyncStreamWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, channel, status);
return status;
}
IOFWAsyncStreamCommand * IOFireWireController::createAsyncStreamCommand( UInt32 generation,
UInt32 channel, UInt32 sync, UInt32 tag, IOMemoryDescriptor *hostMem,
UInt32 size, int speed, FWAsyncStreamCallback completion, void *refcon)
{
return createAsyncStreamCommand(generation, channel, sync, tag, hostMem, size, speed, completion, refcon, true);
}
IOFWAsyncStreamCommand * IOFireWireController::createAsyncStreamCommand( UInt32 generation,
UInt32 channel, UInt32 sync, UInt32 tag, IOMemoryDescriptor *hostMem,
UInt32 size, int speed,FWAsyncStreamCallback completion, void *refcon, bool failOnReset)
{
IOFWAsyncStreamCommand * cmd;
cmd = OSTypeAlloc( IOFWAsyncStreamCommand );
if(cmd) {
if(!cmd->initAll(this, generation, channel, sync, tag, hostMem,size,speed, completion, refcon, failOnReset)) {
cmd->release();
cmd = NULL;
}
}
return cmd;
}
IOFWAsyncPHYCommand * IOFireWireController::createAsyncPHYCommand( UInt32 generation,
UInt32 data1,
UInt32 data2,
FWAsyncPHYCallback completion,
void * refcon,
bool failOnReset )
{
IOFWAsyncPHYCommand * cmd;
cmd = OSTypeAlloc( IOFWAsyncPHYCommand );
if( cmd )
{
if( !cmd->initAll( this, generation, data1, data2, completion, refcon, failOnReset ) )
{
cmd->release();
cmd = NULL;
}
}
return cmd;
}
void IOFireWireController::processRcvPacket(UInt32 *data, int size, IOFWSpeed speed )
{
#if 0
int i;
kprintf("Received packet 0x%x size %d\n", data, size);
for(i=0; i<size; i++) {
kprintf("0x%x ", OSSwapBigToHostInt32(data[i]));
}
kprintf("\n");
#endif
UInt32 tCode, tLabel;
UInt32 quad0;
UInt16 sourceID;
UInt16 destID;
quad0 = *data;
tCode = (quad0 & kFWPacketTCode) >> kFWPacketTCodePhase;
tLabel = (quad0 & kFWAsynchTLabel) >> kFWAsynchTLabelPhase;
sourceID = (data[1] & kFWAsynchSourceID) >> kFWAsynchSourceIDPhase;
destID = (data[0] & kFWAsynchDestinationID) >> kFWAsynchDestinationIDPhase;
FWTrace(kFWTController, kTPControllerProcessRcvPacket, (uintptr_t)fFWIM, sourceID, tCode, 0);
switch (tCode)
{
case kFWTCodeWriteQuadlet :
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG("WriteQuadlet: addr 0x%x -> 0x%x:0x%x:0x%x\n", sourceID, destID,
(data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]);
#endif
processWriteRequest(sourceID, tLabel, data, &data[3], 4, speed);
break;
case kFWTCodePHYPacket:
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG( "PHY Packet: 0x%08lx %08lx\n", data[1], data[2] );
#endif
processPHYPacket( data[1], data[2] );
break;
case kFWTCodeWriteBlock :
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG("WriteBlock: addr 0x%x -> 0x%x:0x%x:0x%x\n", sourceID, destID,
(data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]);
#endif
processWriteRequest(sourceID, tLabel, data, &data[4],
(data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase, speed);
break;
case kFWTCodeWriteResponse :
if(fTrans[tLabel].fHandler) {
IOFWAsyncCommand * cmd = fTrans[tLabel].fHandler;
FWAddress commandAddress = cmd->getAddress();
if( sourceID == commandAddress.nodeID ){
cmd->setResponseSpeed( speed );
FWTrace(kFWTController, kTPControllerProcessRcvPacketWR, (uintptr_t)fFWIM, (uintptr_t)cmd, ((commandAddress.nodeID << 16) | commandAddress.addressHi), commandAddress.addressLo);
cmd->gotPacket((data[1] & kFWAsynchRCode)>>kFWAsynchRCodePhase, 0, 0);
}
else{
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG( "Response from wrong node ID!\n" );
#endif
}
}
else {
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG("WriteResponse: label %d isn't in use!!, data1 = 0x%x\n",
tLabel, data[1]);
#endif
}
break;
case kFWTCodeReadQuadlet :
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG("ReadQuadlet: addr 0x%x -> 0x%x:0x%x:0x%x\n", sourceID, destID,
(data[1] & kFWAsynchDestinationOffsetHigh) >>
kFWAsynchDestinationOffsetHighPhase, data[2]);
#endif
{
UInt32 ret;
FWAddress addr((data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]);
IOMemoryDescriptor *buf = NULL;
IOByteCount offset;
ret = doReadSpace(sourceID, speed, addr, 4,
&buf, &offset, NULL, (IOFWRequestRefCon)(tLabel | kRequestIsQuad));
FWTrace(kFWTController, kTPControllerProcessRcvPacketRQ, (uintptr_t)fFWIM, ret, ((addr.nodeID << 16) | addr.addressHi), addr.addressLo);
if(ret == kFWResponsePending)
break;
if( NULL != buf )
{
UInt32 quad = OSSwapHostToBigInt32(0xdeadbeef);
buf->readBytes( offset, &quad, 4 );
if ( destID != 0xffff ) fFWIM->asyncReadQuadResponse(sourceID, speed, tLabel, ret, quad );
else
DebugLog("Skipped asyncReadQuadResponse because destID=0x%x\n", destID);
}
else
{
if ( destID != 0xffff ) fFWIM->asyncReadQuadResponse(sourceID, speed, tLabel, ret, OSSwapHostToBigInt32(0xdeadbeef));
else
DebugLog("Skipped asyncReadQuadResponse because destID=0x%x\n", destID);
}
}
break;
case kFWTCodeReadBlock :
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG("ReadBlock: addr 0x%x -> 0x%x:0x%x:0x%x\n", sourceID, destID,
(data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2],
(data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase);
#endif
{
IOReturn ret;
int length = (data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase ;
FWAddress addr((data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]);
IOMemoryDescriptor * buf = NULL;
IODMACommand * dma_command = NULL;
IOByteCount offset;
ret = doReadSpace(sourceID, speed, addr, length, &buf, &offset, &dma_command, (IOFWRequestRefCon)(tLabel));
FWTrace(kFWTController, kTPControllerProcessRcvPacketRB, (uintptr_t)fFWIM, ret, ((addr.nodeID << 16) | addr.addressHi), addr.addressLo);
if(ret == kFWResponsePending)
break;
if(NULL != buf) {
if ( destID != 0xffff ) fFWIM->asyncReadResponse(sourceID, speed, tLabel, ret, buf, offset, length, dma_command );
else
DebugLog("Skipped asyncReadResponse because destID=0x%x\n", destID);
}
else {
if ( destID != 0xffff ) fFWIM->asyncReadResponse(sourceID, speed, tLabel, ret, fBadReadResponse, 0, 4, NULL);
else
DebugLog("Skipped asyncReadResponse because destID=0x%x\n", destID);
}
}
break;
case kFWTCodeReadQuadletResponse :
if(fTrans[tLabel].fHandler) {
IOFWAsyncCommand * cmd = fTrans[tLabel].fHandler;
FWAddress commandAddress = cmd->getAddress();
if( sourceID == commandAddress.nodeID )
{
cmd->setResponseSpeed( speed );
FWTrace(kFWTController, kTPControllerProcessRcvPacketRQR, (uintptr_t)fFWIM, (uintptr_t)cmd, ((commandAddress.nodeID << 16) | commandAddress.addressHi), commandAddress.addressLo);
cmd->gotPacket((data[1] & kFWAsynchRCode)>>kFWAsynchRCodePhase,
(const void*)(data+3), 4);
}
else
{
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG( "Response from wrong node ID!\n" );
#endif
}
}
else {
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG("ReadQuadletResponse: label %d isn't in use!!\n", tLabel);
#endif
}
break;
case kFWTCodeReadBlockResponse :
case kFWTCodeLockResponse :
if(fTrans[tLabel].fHandler) {
IOFWAsyncCommand * cmd = fTrans[tLabel].fHandler;
FWAddress commandAddress = cmd->getAddress();
if( sourceID == commandAddress.nodeID )
{
cmd->setResponseSpeed( speed );
FWTrace(kFWTController, kTPControllerProcessRcvPacketRBR, (uintptr_t)fFWIM, (uintptr_t)cmd, ((commandAddress.nodeID << 16) | commandAddress.addressHi), commandAddress.addressLo);
cmd->gotPacket((data[1] & kFWAsynchRCode)>>kFWAsynchRCodePhase,
(const void*)(data+4), (data[3] & kFWAsynchDataLength)>>kFWAsynchDataLengthPhase);
}
else
{
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG( "Response from wrong node ID!\n" );
#endif
}
}
else {
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG("ReadBlock/LockResponse: label %d isn't in use!!\n", tLabel);
#endif
}
break;
case kFWTCodeLock :
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG("Lock type %d: addr 0x%x -> 0x%x:0x%x:0x%x\n",
(data[3] & kFWAsynchExtendedTCode) >> kFWAsynchExtendedTCodePhase, sourceID, destID,
(data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase,
data[2]);
#endif
processLockRequest(sourceID, tLabel, data, &data[4],
(data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase, speed);
break;
case kFWTCodeIsochronousBlock :
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG("Async Stream Packet\n");
#endif
break;
default :
#if (DEBUGGING_LEVEL > 0)
DEBUGLOG("Unexpected tcode in Asyncrecv: %d\n", tCode);
#endif
break;
}
}
IOFWPhysicalAddressSpace *
IOFireWireController::createPhysicalAddressSpace(IOMemoryDescriptor *mem)
{
IOFWPhysicalAddressSpace *space;
space = OSTypeAlloc( IOFWPhysicalAddressSpace );
if(!space)
return NULL;
if(!space->initWithDesc(this, mem)) {
space->release();
space = NULL;
}
return space;
}
IOFWAsyncStreamListener *
IOFireWireController::createAsyncStreamListener( UInt32 channel, FWAsyncStreamReceiveCallback proc, void *refcon )
{
IOFWAsyncStreamListener * listener = OSTypeAlloc( IOFWAsyncStreamListener );
if( listener )
{
if(not listener->initAll( this, channel, proc, refcon ))
{
listener->release();
listener = NULL;
}
}
return listener;
}
void
IOFireWireController::removeAsyncStreamListener(IOFWAsyncStreamListener *listener)
{
IOFWAsyncStreamReceiver *receiver = listener->getReceiver();
receiver->removeListener(listener);
}
IOFWPseudoAddressSpace *
IOFireWireController::createPseudoAddressSpace(FWAddress *addr, UInt32 len,
FWReadCallback reader, FWWriteCallback writer, void *refcon)
{
IOFWPseudoAddressSpace *space;
space = OSTypeAlloc( IOFWPseudoAddressSpace );
if(!space)
return NULL;
if(!space->initAll(this, addr, len, reader, writer, refcon)) {
space->release();
space = NULL;
}
return space;
}
IOFWPseudoAddressSpace *
IOFireWireController::createInitialAddressSpace(UInt32 addressLo, UInt32 len,
FWReadCallback reader, FWWriteCallback writer, void *refcon)
{
IOFWPseudoAddressSpace *space;
space = OSTypeAlloc( IOFWPseudoAddressSpace );
if(!space)
return NULL;
if(!space->initFixed(this, FWAddress(kCSRRegisterSpaceBaseAddressHi, addressLo),
len, reader, writer, refcon)) {
space->release();
space = NULL;
}
return space;
}
IOFWAddressSpace *
IOFireWireController::getAddressSpace(FWAddress address)
{
closeGate();
IOFWAddressSpace * found;
fSpaceIterator->reset();
while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) {
if(found->contains(address))
break;
}
openGate();
return found;
}
IOFWAsyncStreamReceiver *
IOFireWireController::allocAsyncStreamReceiver(UInt32 channel, FWAsyncStreamReceiveCallback clientProc, void *refcon)
{
closeGate();
IOFWAsyncStreamReceiver * receiver = OSTypeAlloc( IOFWAsyncStreamReceiver );
if( receiver )
{
if( receiver->initAll( this, channel ) )
{
if( fLocalAsyncStreamReceivers->setObject( receiver ))
receiver->release();
}
else
{
receiver->release();
receiver = NULL;
}
}
openGate();
return receiver;
}
IOFWAsyncStreamReceiver *
IOFireWireController::getAsyncStreamReceiver( UInt32 channel )
{
closeGate();
IOFWAsyncStreamReceiver * found = NULL;
OSIterator *iterator = OSCollectionIterator::withCollection(fLocalAsyncStreamReceivers);
if( iterator != NULL )
{
found = NULL;
while( (found = OSDynamicCast(IOFWAsyncStreamReceiver, iterator->getNextObject())) )
{
if( found and found->listens(channel) )
break;
}
iterator->release();
}
openGate();
return found;
}
void
IOFireWireController::removeAsyncStreamReceiver( IOFWAsyncStreamReceiver *receiver )
{
closeGate();
fLocalAsyncStreamReceivers->removeObject(receiver);
openGate();
}
void
IOFireWireController::activateAsyncStreamReceivers( )
{
closeGate();
OSIterator *iterator = OSCollectionIterator::withCollection(fLocalAsyncStreamReceivers);
if( iterator != NULL )
{
IOFWAsyncStreamReceiver * found = NULL;
while( (found = OSDynamicCast(IOFWAsyncStreamReceiver, iterator->getNextObject())) )
{
if( found )
found->activate( getBroadcastSpeed() );
}
iterator->release();
}
openGate();
}
void
IOFireWireController::deactivateAsyncStreamReceivers( )
{
closeGate();
OSIterator *iterator = OSCollectionIterator::withCollection(fLocalAsyncStreamReceivers);
if( iterator != NULL )
{
IOFWAsyncStreamReceiver * found = NULL;
while( (found = OSDynamicCast(IOFWAsyncStreamReceiver, iterator->getNextObject())) )
{
if( found )
found->deactivate();
}
iterator->release();
}
openGate();
}
void
IOFireWireController::freeAllAsyncStreamReceiver()
{
closeGate();
OSIterator *iterator = OSCollectionIterator::withCollection(fLocalAsyncStreamReceivers);
if( iterator != NULL )
{
IOFWAsyncStreamReceiver * found = NULL;
while( (found = OSDynamicCast(IOFWAsyncStreamReceiver, iterator->getNextObject())) )
{
if( found )
removeAsyncStreamReceiver( found );
}
iterator->release();
}
openGate();
}
IOReturn IOFireWireController::allocAddress(IOFWAddressSpace *space)
{
IOReturn result = kIOReturnSuccess;
closeGate();
IOFWAddressSpace * found;
fSpaceIterator->reset();
while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject()))
{
if( space->isExclusive() || found->isExclusive() )
{
if( found->intersects( space ) )
{
result = kIOReturnExclusiveAccess;
}
}
}
if( result == kIOReturnSuccess )
{
if(!fLocalAddresses->setObject(space))
result = kIOReturnNoMemory;
else
result = kIOReturnSuccess;
}
openGate();
return result;
}
void IOFireWireController::freeAddress(IOFWAddressSpace *space)
{
closeGate();
fLocalAddresses->removeObject(space);
openGate();
}
IOReturn IOFireWireController::allocatePseudoAddress(FWAddress *addr, UInt32 lenDummy)
{
unsigned int i, len;
UInt8 * data;
UInt8 used = 1;
closeGate();
if( fAllocatedAddresses == NULL )
{
fAllocatedAddresses = OSData::withCapacity(4); fAllocatedAddresses->appendBytes(&used, 1); }
if( !fAllocatedAddresses )
{
openGate();
return kIOReturnNoMemory;
}
len = fAllocatedAddresses->getLength();
data = (UInt8*)fAllocatedAddresses->getBytesNoCopy();
for( i=0; i<len; i++ )
{
if( data[i] == 0 )
{
data[i] = 1;
addr->addressHi = i;
addr->addressLo = 0;
openGate();
return kIOReturnSuccess;
}
}
if( len >= 0xfffe )
{
openGate();
return kIOReturnNoMemory;
}
if( fAllocatedAddresses->appendBytes(&used, 1))
{
addr->addressHi = len;
addr->addressLo = 0;
openGate();
return kIOReturnSuccess;
}
openGate();
return kIOReturnNoMemory;
}
void IOFireWireController::freePseudoAddress(FWAddress addr, UInt32 lenDummy)
{
unsigned int len;
UInt8 * data;
closeGate();
assert( fAllocatedAddresses != NULL);
len = fAllocatedAddresses->getLength();
assert(addr.addressHi < len);
data = (UInt8*)fAllocatedAddresses->getBytesNoCopy();
assert(data[addr.addressHi]);
data[addr.addressHi] = 0;
openGate();
}
#if 0
IOReturn MyTestingFWMultiIsochReceiveListenerCallback(void *refcon, IOFireWireMultiIsochReceivePacket *pPacket)
{
DebugLog("AY_DEBUG: MyTestingFWMultiIsochReceiveListenerCallback\n");
pPacket->clientDone();
return kIOReturnSuccess;
}
#endif
void IOFireWireController::processWriteRequest(UInt16 sourceID, UInt32 tLabel,
UInt32 *hdr, void *buf, int len, IOFWSpeed speed)
{
UInt32 ret = kFWResponseAddressError;
FWAddress addr((hdr[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, hdr[2]);
IOFWAddressSpace * found;
#if 0
if ((addr.addressHi == 0xFFFF) && (addr.addressLo == 0xF0000A00) && (len == 4))
{
UInt32 add_chan = OSSwapBigToHostInt32(*((UInt32*) buf));
DebugLog("Got quadlet-write to special MultiIsochReceiver channel-add address: add_chan=%d\n",add_chan);
if (fFWIM)
{
IOReturn result;
IOFireWireMultiIsochReceiveListener *pListener = createMultiIsochReceiveListener(add_chan,MyTestingFWMultiIsochReceiveListenerCallback,this);
if (pListener)
{
result = pListener->Activate();
if (result != kIOReturnSuccess)
DebugLog("AY_DEBUG: pListener->Activate failed!\n");
}
else
{
DebugLog("AY_DEBUG: createMultiIsochReceiveListener failed!\n");
}
}
}
else if ((addr.addressHi == 0xFFFF) && (addr.addressLo == 0xF0000A04) && (len == 4))
{
}
else if ((addr.addressHi == 0xFFFF) && (addr.addressLo == 0xF0000A08) && (len == 4))
{
DebugLog("Got quadlet-write to special link-reset address\n");
if (fFWIM)
fFWIM->setLinkMode(kIOFWSetForceLinkReset,0);
}
#endif
fSpaceIterator->reset();
while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) {
ret = found->doWrite(sourceID, speed, addr, len, buf, (IOFWRequestRefCon)tLabel);
if(ret != kFWResponseAddressError)
break;
}
FWTrace(kFWTController, kTPControllerProcessWriteRequest, (uintptr_t)fFWIM, sourceID, ret, tLabel);
if ( ((hdr[0] & kFWAsynchDestinationID) >> kFWAsynchDestinationIDPhase) != 0xffff ) fFWIM->asyncWriteResponse(sourceID, speed, tLabel, ret, addr.addressHi);
else
DebugLog("Skipped asyncWriteResponse because destID=0x%x\n", (uint32_t)((hdr[0] & kFWAsynchDestinationID) >> kFWAsynchDestinationIDPhase));
}
void IOFireWireController::processLockRequest(UInt16 sourceID, UInt32 tLabel,
UInt32 *hdr, void *buf, int len, IOFWSpeed speed)
{
UInt32 oldVal[2];
UInt32 ret;
UInt32 outLen =sizeof(oldVal);
int type = (hdr[3] & kFWAsynchExtendedTCode) >> kFWAsynchExtendedTCodePhase;
FWAddress addr((hdr[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, hdr[2]);
IOFWRequestRefCon refcon = (IOFWRequestRefCon)(tLabel | kRequestIsLock | (type << kRequestExtTCodeShift));
ret = doLockSpace(sourceID, speed, addr, len, (const UInt32 *)buf, outLen, oldVal, type, refcon);
FWTrace(kFWTController, kTPControllerProcessLockRequest, (uintptr_t)fFWIM, ret, ((addr.nodeID << 16) & addr.addressHi), addr.addressLo);
if(ret != kFWResponsePending)
{
if ( ((hdr[0] & kFWAsynchDestinationID) >> kFWAsynchDestinationIDPhase) != 0xffff ) fFWIM->asyncLockResponse(sourceID, speed, tLabel, ret, type, oldVal, outLen);
else
DebugLog("Skipped asyncLockResponse because destID=0x%x\n", (uint32_t)((hdr[0] & kFWAsynchDestinationID) >> kFWAsynchDestinationIDPhase));
}
}
UInt32 IOFireWireController::doReadSpace(UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 len,
IOMemoryDescriptor **buf, IOByteCount * offset, IODMACommand **dma_command,
IOFWRequestRefCon refcon)
{
IOFWAddressSpace * found;
UInt32 ret = kFWResponseAddressError;
fSpaceIterator->reset();
while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) {
ret = found->doRead(nodeID, speed, addr, len, buf, offset,
refcon);
if(ret != kFWResponseAddressError)
break;
}
if( (dma_command != NULL) && (ret != kFWResponseAddressError) )
{
IOFWPhysicalAddressSpace * phys_space = OSDynamicCast( IOFWPhysicalAddressSpace, found );
if( phys_space )
{
*dma_command = phys_space->getDMACommand();
}
}
return ret;
}
UInt32 IOFireWireController::doWriteSpace(UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 len,
const void *buf, IOFWRequestRefCon refcon)
{
IOFWAddressSpace * found;
UInt32 ret = kFWResponseAddressError;
fSpaceIterator->reset();
while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) {
ret = found->doWrite(nodeID, speed, addr, len, buf, refcon);
if(ret != kFWResponseAddressError)
break;
}
return ret;
}
UInt32 IOFireWireController::doLockSpace(UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 inLen,
const UInt32 *newVal, UInt32 &outLen, UInt32 *oldVal, UInt32 type,
IOFWRequestRefCon refcon)
{
IOFWAddressSpace * found;
UInt32 ret = kFWResponseAddressError;
fSpaceIterator->reset();
while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) {
ret = found->doLock(nodeID, speed, addr, inLen, newVal, outLen, oldVal, type, refcon);
if(ret != kFWResponseAddressError)
break;
}
if(ret != kFWResponseComplete) {
oldVal[0] = OSSwapHostToBigInt32(0xdeadbabe);
outLen = 4;
}
return ret;
}
void IOFireWireController::handleARxReqIntComplete( void )
{
IOFWAddressSpace * found;
fSpaceIterator->reset();
while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject()) )
{
IOFWPseudoAddressSpace * space = OSDynamicCast( IOFWPseudoAddressSpace, found );
if( space != NULL )
{
space->handleARxReqIntComplete();
}
}
}
bool IOFireWireController::isLockRequest(IOFWRequestRefCon refcon)
{
return ((UInt64)refcon) & kRequestIsLock;
}
bool IOFireWireController::isQuadRequest(IOFWRequestRefCon refcon)
{
return ((UInt64)refcon) & kRequestIsQuad;
}
bool IOFireWireController::isCompleteRequest(IOFWRequestRefCon refcon)
{
return ((UInt64)refcon) & kRequestIsComplete;
}
UInt32 IOFireWireController::getExtendedTCode(IOFWRequestRefCon refcon)
{
return((UInt64)refcon & kRequestExtTCodeMask) >> kRequestExtTCodeShift;
}
IOReturn IOFireWireController::asyncReadResponse( UInt32 generation,
UInt16 nodeID,
int speed,
IOMemoryDescriptor * buf,
IOByteCount offset,
int size,
IOFWRequestRefCon refcon )
{
IOReturn result;
UInt64 params = (UInt64)refcon;
UInt32 label = params & kRequestLabel;
closeGate();
if( !checkGeneration(generation) )
{
result = kIOFireWireBusReset;
}
else if( params & kRequestIsQuad )
{
UInt32 quad = OSSwapHostToBigInt32(0xdeadbeef);
buf->readBytes( offset, &quad, 4 );
result = fFWIM->asyncReadQuadResponse( nodeID,
speed,
label,
kFWResponseComplete,
quad );
}
else
{
result = fFWIM->asyncReadResponse( nodeID,
speed,
label,
kFWResponseComplete,
buf,
offset,
size,
NULL );
}
openGate();
return result;
}
IOReturn IOFireWireController::asyncLockResponse( UInt32 generation,
UInt16 nodeID,
int speed,
IOMemoryDescriptor * buf,
IOByteCount offset,
int size,
IOFWRequestRefCon refcon )
{
FWTrace(kFWTController, kTPControllerAsyncLockResponse, (uintptr_t)fFWIM, nodeID, 0, 0);
IOReturn result;
UInt64 params = (UInt64)refcon;
UInt32 label = params & kRequestLabel;
closeGate();
if( !checkGeneration(generation) )
{
result = kIOFireWireBusReset;
}
else
{
void * bytes = IOMalloc( size );
buf->readBytes( offset, bytes, size );
result = fFWIM->asyncLockResponse( nodeID,
speed,
label,
kFWResponseComplete,
getExtendedTCode(refcon),
bytes,
size );
IOFree( bytes, size );
}
openGate();
return result;
}
IOFWDelayCommand * IOFireWireController::createDelayedCmd(UInt32 uSecDelay, FWBusCallback func, void *refcon)
{
IOFWDelayCommand *delay;
delay = OSTypeAlloc( IOFWDelayCommand );
if(!delay)
return NULL;
if(!delay->initWithDelay(this, uSecDelay, func, refcon))
{
delay->release();
return NULL;
}
return delay;
}
#pragma mark -
IOFWIsochChannel *IOFireWireController::createIsochChannel( bool doIRM,
UInt32 bandwidth,
IOFWSpeed prefSpeed,
FWIsochChannelForceStopNotificationProc stopProc,
void * stopRefCon )
{
IOFWIsochChannel *channel;
channel = OSTypeAlloc( IOFWIsochChannel );
if(!channel)
{
return NULL;
}
if( !channel->init(this, doIRM, bandwidth, prefSpeed, stopProc, stopRefCon) )
{
channel->release();
channel = NULL;
}
return channel;
}
IOFWLocalIsochPort *IOFireWireController::createLocalIsochPort( bool talking,
DCLCommand * opcodes,
DCLTaskInfo * info,
UInt32 startEvent,
UInt32 startState,
UInt32 startMask )
{
IOFWLocalIsochPort *port;
IODCLProgram *program;
program = fFWIM->createDCLProgram( talking, opcodes, info, startEvent, startState, startMask );
if(!program)
return NULL;
port = OSTypeAlloc( IOFWLocalIsochPort );
if( !port )
{
program->release();
return NULL;
}
if(!port->init(program, this))
{
port->release();
port = NULL;
}
return port;
}
void IOFireWireController::addAllocatedChannel(IOFWIsochChannel *channel)
{
closeGate();
fAllocatedChannels->setObject(channel);
openGate();
}
void IOFireWireController::removeAllocatedChannel(IOFWIsochChannel *channel)
{
closeGate();
fAllocatedChannels->removeObject(channel);
openGate();
}
void IOFireWireController::addToIRMAllocationSet(IOFireWireIRMAllocation *anObject)
{
closeGate();
fIRMAllocationsAllocated->setObject(anObject);
openGate();
}
void IOFireWireController::removeFromIRMAllocationSet(IOFireWireIRMAllocation *anObject)
{
closeGate();
fIRMAllocationsAllocated->removeObject(anObject);
openGate();
}
void IOFireWireController::addIRMAllocation(IOFireWireIRMAllocation *irmAllocation)
{
closeGate();
if( fIRMAllocationsAllocated->containsObject(irmAllocation) )
{
fIRMAllocations->setObject(irmAllocation);
}
openGate();
}
void IOFireWireController::removeIRMAllocation(IOFireWireIRMAllocation *irmAllocation)
{
closeGate();
fIRMAllocations->removeObject(irmAllocation);
openGate();
}
IOReturn IOFireWireController::allocateIRMBandwidthInGeneration(UInt32 bandwidthUnits, UInt32 generation)
{
IOReturn res;
UInt32 irmGeneration;
UInt16 irmNodeID;
IOFWCompareAndSwapCommand * fLockCmd;
FWAddress addr;
UInt32 expectedOldVal, newVal;
UInt32 actualOldVal;
bool lockSuccessful;
UInt32 retries = 2;
getIRMNodeID(irmGeneration, irmNodeID);
if (irmGeneration != generation)
return kIOFireWireBusReset;
addr.nodeID = irmNodeID;
addr.addressHi = 0xFFFF;
addr.addressLo = 0xF0000220;
expectedOldVal = OSSwapHostToBigInt32(0x00001333);
fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand );
if (!fLockCmd)
return kIOReturnNoMemory;
if (!fLockCmd->initAll(this,generation,addr, NULL, NULL,0,NULL,NULL))
{
fLockCmd->release();
return kIOReturnError;
}
while (retries > 0)
{
if (bandwidthUnits > OSSwapBigToHostInt32(expectedOldVal))
{
res = kIOFireWireIsochBandwidthNotAvailable;
break;
}
newVal = OSSwapHostToBigInt32(OSSwapBigToHostInt32(expectedOldVal) - bandwidthUnits);
res = fLockCmd->reinit(generation,addr, &expectedOldVal, &newVal,1,NULL,NULL);
if (res != kIOReturnSuccess)
break;
res = fLockCmd->submit();
if (res == kIOReturnSuccess)
lockSuccessful = fLockCmd->locked(&actualOldVal);
else
lockSuccessful = false;
DebugLog("allocateIRMBandwidthInGeneration: res = 0x%08X, expectedOldVal = 0x%08X, newVal = 0x%08X, lockSuccessful = %d, actualOldVal = 0x%08X\n",
res, OSSwapBigToHostInt32(expectedOldVal),OSSwapBigToHostInt32(newVal),lockSuccessful,OSSwapBigToHostInt32(actualOldVal));
if (res == kIOFireWireBusReset)
break;
else if (lockSuccessful)
break;
else
{
retries -= 1;
if (res == kIOReturnSuccess)
res = kIOFireWireIsochBandwidthNotAvailable;
expectedOldVal = actualOldVal;
}
}
fLockCmd->release();
return res;
}
IOReturn IOFireWireController::releaseIRMBandwidthInGeneration(UInt32 bandwidthUnits, UInt32 generation)
{
IOReturn res;
UInt32 irmGeneration;
UInt16 irmNodeID;
IOFWCompareAndSwapCommand * fLockCmd;
FWAddress addr;
UInt32 expectedOldVal, newVal;
UInt32 actualOldVal;
bool lockSuccessful;
UInt32 retries = 2;
getIRMNodeID(irmGeneration, irmNodeID);
if (irmGeneration != generation)
return kIOFireWireBusReset;
addr.nodeID = irmNodeID;
addr.addressHi = 0xFFFF;
addr.addressLo = kCSRBandwidthAvailable;
expectedOldVal = OSSwapHostToBigInt32(0);
fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand );
if (!fLockCmd)
return kIOReturnNoMemory;
if (!fLockCmd->initAll(this,generation,addr, NULL, NULL,0,NULL,NULL))
{
fLockCmd->release();
return kIOReturnError;
}
while (retries > 0)
{
#if 0
if ((bandwidthUnits + OSSwapBigToHostInt32(expectedOldVal)) > 0x00001333 )
{
res = kIOReturnNoResources;
break;
}
#endif
newVal = OSSwapHostToBigInt32(OSSwapBigToHostInt32(expectedOldVal) + bandwidthUnits);
res = fLockCmd->reinit(generation,addr, &expectedOldVal, &newVal,1,NULL,NULL);
if (res != kIOReturnSuccess)
break;
res = fLockCmd->submit();
if (res == kIOReturnSuccess)
lockSuccessful = fLockCmd->locked(&actualOldVal);
else
lockSuccessful = false;
DebugLog("releaseIRMBandwidthInGeneration: res = 0x%08X, expectedOldVal = 0x%08X, newVal = 0x%08X, lockSuccessful = %d, actualOldVal = 0x%08X\n",
res, OSSwapBigToHostInt32(expectedOldVal),OSSwapBigToHostInt32(newVal),lockSuccessful,OSSwapBigToHostInt32(actualOldVal));
if (res == kIOFireWireBusReset)
break;
else if (lockSuccessful)
break;
else
{
retries -= 1;
if (res == kIOReturnSuccess)
res = kIOReturnNoResources;
expectedOldVal = actualOldVal;
}
}
fLockCmd->release();
return res;
}
IOReturn IOFireWireController::allocateIRMChannelInGeneration(UInt8 isochChannel, UInt32 generation)
{
IOReturn res;
UInt32 irmGeneration;
UInt16 irmNodeID;
IOFWCompareAndSwapCommand * fLockCmd;
FWAddress addr;
UInt32 newValMask;
UInt32 expectedOldVal, newVal;
UInt32 actualOldVal;
bool lockSuccessful;
UInt32 retries = 2;
getIRMNodeID(irmGeneration, irmNodeID);
if (irmGeneration != generation)
return kIOFireWireBusReset;
addr.nodeID = irmNodeID;
addr.addressHi = 0xFFFF;
if( isochChannel < 32 )
{
addr.addressLo = kCSRChannelsAvailable31_0;
newValMask = OSSwapHostToBigInt32(~(1<<(31 - isochChannel)));
}
else if( isochChannel < 64 )
{
addr.addressLo = kCSRChannelsAvailable63_32;
newValMask = OSSwapHostToBigInt32(~(1 << (63 - isochChannel)));
}
else
return kIOReturnBadArgument;
expectedOldVal = OSSwapHostToBigInt32(0xFFFFFFFF);
fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand );
if (!fLockCmd)
return kIOReturnNoMemory;
if (!fLockCmd->initAll(this,generation,addr, NULL, NULL,0,NULL,NULL))
{
fLockCmd->release();
return kIOReturnError;
}
while (retries > 0)
{
if ((expectedOldVal & ~newValMask) == 0)
{
res = kIOFireWireChannelNotAvailable;
break;
}
newVal = expectedOldVal & newValMask;
res = fLockCmd->reinit(generation,addr, &expectedOldVal, &newVal,1,NULL,NULL);
if (res != kIOReturnSuccess)
break;
res = fLockCmd->submit();
if (res == kIOReturnSuccess)
lockSuccessful = fLockCmd->locked(&actualOldVal);
else
lockSuccessful = false;
DebugLog("allocateIRMChannelInGeneration: res = 0x%08X, expectedOldVal = 0x%08X, newVal = 0x%08X, lockSuccessful = %d, actualOldVal = 0x%08X\n",
res, OSSwapBigToHostInt32(expectedOldVal),OSSwapBigToHostInt32(newVal),lockSuccessful,OSSwapBigToHostInt32(actualOldVal));
if (res == kIOFireWireBusReset)
break;
else if (lockSuccessful)
break;
else
{
retries -= 1;
if (res == kIOReturnSuccess)
res = kIOFireWireChannelNotAvailable;
expectedOldVal = actualOldVal;
}
}
fLockCmd->release();
return res;
}
IOReturn IOFireWireController::releaseIRMChannelInGeneration(UInt8 isochChannel, UInt32 generation)
{
IOReturn res;
UInt32 irmGeneration;
UInt16 irmNodeID;
IOFWCompareAndSwapCommand * fLockCmd;
FWAddress addr;
UInt32 newValMask;
UInt32 expectedOldVal, newVal;
UInt32 actualOldVal;
bool lockSuccessful;
UInt32 retries = 2;
getIRMNodeID(irmGeneration, irmNodeID);
if (irmGeneration != generation)
return kIOFireWireBusReset;
addr.nodeID = irmNodeID;
addr.addressHi = 0xFFFF;
if( isochChannel < 32 )
{
addr.addressLo = kCSRChannelsAvailable31_0;
newValMask = OSSwapHostToBigInt32(1<<(31 - isochChannel));
}
else if( isochChannel < 64 )
{
addr.addressLo = kCSRChannelsAvailable63_32;
newValMask = OSSwapHostToBigInt32(1 << (63 - isochChannel));
}
else
return kIOReturnBadArgument;
expectedOldVal = OSSwapHostToBigInt32(0x00000000);
fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand );
if (!fLockCmd)
return kIOReturnNoMemory;
if (!fLockCmd->initAll(this,generation,addr, NULL, NULL,0,NULL,NULL))
{
fLockCmd->release();
return kIOReturnError;
}
while (retries > 0)
{
if ((expectedOldVal & newValMask) == newValMask)
{
res = kIOReturnNoResources;
break;
}
newVal = expectedOldVal | newValMask;
res = fLockCmd->reinit(generation,addr, &expectedOldVal, &newVal,1,NULL,NULL);
if (res != kIOReturnSuccess)
break;
res = fLockCmd->submit();
if (res == kIOReturnSuccess)
lockSuccessful = fLockCmd->locked(&actualOldVal);
else
lockSuccessful = false;
DebugLog("releaseIRMChannelInGeneration: res = 0x%08X, expectedOldVal = 0x%08X, newVal = 0x%08X, lockSuccessful = %d, actualOldVal = 0x%08X\n",
res, OSSwapBigToHostInt32(expectedOldVal),OSSwapBigToHostInt32(newVal),lockSuccessful,OSSwapBigToHostInt32(actualOldVal));
if (res == kIOFireWireBusReset)
break;
else if (lockSuccessful)
break;
else
{
retries -= 1;
if (res == kIOReturnSuccess)
res = kIOReturnNoResources;
expectedOldVal = actualOldVal;
}
}
fLockCmd->release();
return res;
}
IOFireWireIRMAllocation * IOFireWireController::createIRMAllocation(Boolean releaseIRMResourcesOnFree,
IOFireWireIRMAllocation::AllocationLostNotificationProc allocationLostProc,
void *pLostNotificationProcRefCon)
{
IOFireWireIRMAllocation * pIRMAllocation;
pIRMAllocation = OSTypeAlloc( IOFireWireIRMAllocation );
if( !pIRMAllocation )
return NULL;
if( !pIRMAllocation->init(this,releaseIRMResourcesOnFree,allocationLostProc,pLostNotificationProcRefCon))
{
pIRMAllocation->release();
pIRMAllocation = NULL;
}
return pIRMAllocation;
}
#pragma mark -
IOReturn IOFireWireController::activatePHYPacketListener( IOFWPHYPacketListener * listener )
{
IOReturn status = kIOReturnSuccess;
closeGate();
if( status == kIOReturnSuccess )
{
OSObject * prop = fFWIM->getProperty( "RcvPhyPkt" );
if( prop )
{
UInt32 value = ((OSNumber*)prop)->unsigned32BitValue();
if( value == 0 )
{
status = kIOReturnUnsupported;
}
}
}
if( status == kIOReturnSuccess )
{
if( !fPHYPacketListeners->setObject( listener ) )
{
status = kIOReturnNoMemory;
}
}
openGate();
return status;
}
void IOFireWireController::deactivatePHYPacketListener( IOFWPHYPacketListener * listener )
{
closeGate();
fPHYPacketListeners->removeObject( listener );
openGate();
}
void IOFireWireController::processPHYPacket( UInt32 data1, UInt32 data2 )
{
if( data1 & 0x40000000 )
{
IOFWPHYPacketListener * listener;
fPHYPacketListenersIterator->reset();
while( (listener = (IOFWPHYPacketListener *)fPHYPacketListenersIterator->getNextObject()) )
{
listener->processPHYPacket( data1, data2 );
}
}
}
IOFWPHYPacketListener *
IOFireWireController::createPHYPacketListener( FWPHYPacketCallback proc, void * refcon )
{
IOFWPHYPacketListener * listener = IOFWPHYPacketListener::createWithController( this );
if( listener )
{
listener->setCallback( proc );
listener->setRefCon( refcon );
}
return listener;
}
#pragma mark -
IOFireWireLocalNode * IOFireWireController::getLocalNode(IOFireWireController *control)
{
OSIterator *childIterator;
IOFireWireLocalNode *localNode = NULL;
childIterator = control->getClientIterator();
if( childIterator) {
OSObject * child;
while( (child = childIterator->getNextObject())) {
localNode = OSDynamicCast(IOFireWireLocalNode, child);
if(localNode) {
break;
}
}
childIterator->release();
}
return localNode;
}
IOFireWirePowerManager * IOFireWireController::getBusPowerManager( void )
{
return fBusPowerManager;
}
IOWorkLoop * IOFireWireController::getWorkLoop() const
{
return fWorkLoop;
}
IOFireWireLink * IOFireWireController::getLink() const
{
return fFWIM;
}
IOReturn IOFireWireController::getCycleTime(UInt32 &cycleTime)
{
IOReturn res;
res = fFWIM->getCycleTime(cycleTime);
return res;
}
IOReturn IOFireWireController::getCycleTimeAndUpTime( UInt32 &cycleTime, UInt64 &uptime )
{
IOReturn res;
res = fFWIM->getCycleTimeAndUpTime( cycleTime, uptime );
return res;
}
IOReturn IOFireWireController::getBusCycleTime(UInt32 &busTime, UInt32 &cycleTime)
{
IOReturn res;
UInt32 cycleSecs;
closeGate();
res = fFWIM->getBusCycleTime(busTime, cycleTime);
openGate();
if(res == kIOReturnSuccess) {
cycleSecs = cycleTime >> 25;
if((busTime & 0x7F) > cycleSecs) {
cycleSecs += 0x80;
}
busTime = (busTime & ~0x7F) + cycleSecs;
}
return res;
}
UInt32 IOFireWireController::hopCount(UInt16 nodeAAddress, UInt16 nodeBAddress )
{
nodeAAddress &= kFWMaxNodesPerBus;
nodeBAddress &= kFWMaxNodesPerBus;
UInt16 lowNode = nodeAAddress > nodeBAddress ? nodeBAddress : nodeAAddress;
struct FWNodeScan
{
int nodeID;
int childrenRemaining;
};
FWNodeScan scanList[fRootNodeID];
FWNodeScan *level;
level = scanList;
const unsigned int maxNodes = fRootNodeID+1;
UInt8 hopArray[maxNodes*(maxNodes+1)];
bzero(hopArray, sizeof(hopArray));
closeGate();
int i;
for( i = fRootNodeID; i >= lowNode; i-- )
{
level->nodeID = i;
level->childrenRemaining = countNodeIDChildren( i );
if (i != fRootNodeID)
{
int parentNodeNum, scanNodeNum;
parentNodeNum = (level-1)->nodeID;
for (scanNodeNum = i + 1; scanNodeNum <= fRootNodeID; scanNodeNum++)
{
UInt8 hops = hopArray[(maxNodes + 1)*parentNodeNum + scanNodeNum];
hopArray[(maxNodes + 1)*i + scanNodeNum] = hops + 1;
hopArray[(maxNodes + 1)*scanNodeNum + i] = hops + 1;
}
}
if (i > 0)
{
while (level->childrenRemaining == 0)
{
level--;
if(level < scanList)
{
ErrorLog("FireWire: SelfIDs don't build a proper tree for hop counts (missing selfIDS?)!!\n");
return 0xFFFFFFFF; }
level->childrenRemaining--;
}
level++;
}
}
openGate();
return hopArray[(maxNodes + 1)*nodeAAddress + nodeBAddress];
}
UInt32 IOFireWireController::hopCount( UInt16 nodeAAddress )
{
UInt32 hops = hopCount( nodeAAddress, fLocalNodeID );
return hops;
}
IOFWSpeed IOFireWireController::FWSpeed(UInt16 nodeAddress) const
{
return FWSpeed(nodeAddress, fLocalNodeID);
}
IOFWSpeed IOFireWireController::FWSpeed(UInt16 nodeA, UInt16 nodeB) const
{
unsigned int txSpeed = kFWSpeedInvalid;
nodeA &= kFWMaxNodesPerBus;
nodeB &= kFWMaxNodesPerBus;
if ( nodeA < kFWMaxNodesPerBus && nodeB < kFWMaxNodesPerBus )
{
if ( nodeA < nodeB )
txSpeed = fSpeedVector[nodeA + ((nodeB * (nodeB + 1))/2)];
else
txSpeed = fSpeedVector[nodeB + ((nodeA * (nodeA + 1))/2)];
}
else
{
unsigned int remoteNodeSpeed = kFWSpeedInvalid;
int i;
for ( i=0; i <= fRootNodeID; i++ )
{
remoteNodeSpeed = (unsigned int)FWSpeed(fLocalNodeID, i);
txSpeed = txSpeed > remoteNodeSpeed ? remoteNodeSpeed : txSpeed;
}
}
return (IOFWSpeed)txSpeed;
}
void IOFireWireController::setNodeSpeed( UInt16 nodeA, UInt16 nodeB, UInt8 speed )
{
nodeA &= kFWMaxNodesPerBus;
nodeB &= kFWMaxNodesPerBus;
if ( nodeA < kFWMaxNodesPerBus && nodeB < kFWMaxNodesPerBus )
{
if ( nodeA < nodeB )
fSpeedVector[nodeA + ((nodeB * (nodeB + 1))/2)] = speed;
else
fSpeedVector[nodeB + ((nodeA * (nodeA + 1))/2)] = speed;
}
}
void IOFireWireController::setNodeSpeed( UInt16 nodeAddress, UInt8 speed )
{
setNodeSpeed(nodeAddress, fLocalNodeID, speed);
}
void IOFireWireController::setNodeSpeed( UInt16 nodeAddress, IOFWSpeed speed )
{
if ( speed > 0xFF )
ErrorLog("FireWire: Trying to set speed map entry larger than 8 bits.\n");
setNodeSpeed(nodeAddress, fLocalNodeID, (UInt8)speed);
}
int IOFireWireController::maxPackLog(bool forSend, UInt16 nodeAddress) const
{
int log;
log = 9+FWSpeed(nodeAddress);
if( forSend )
{
if( log > fMaxSendLog )
{
log = fMaxSendLog;
}
}
else
{
if( log > fMaxSendLog )
{
log = fMaxRecvLog;
}
}
if( fUseHalfSizePackets )
{
if( log > 1 )
{
log--;
}
}
return log;
}
int IOFireWireController::maxPackLog(UInt16 nodeA, UInt16 nodeB) const
{
return 9+FWSpeed(nodeA, nodeB);
}
IOFireWireDevice * IOFireWireController::nodeIDtoDevice(UInt32 generation, UInt16 nodeID)
{
OSIterator *childIterator;
IOFireWireDevice * found = NULL;
if(!checkGeneration(generation))
{
return NULL;
}
childIterator = getClientIterator();
if( childIterator)
{
OSObject *child;
while( (child = childIterator->getNextObject()))
{
found = OSDynamicCast(IOFireWireDevice, child);
if( found && (found->getTerminationState() == kNotTerminated) && found->fNodeID == nodeID )
{
break;
}
}
childIterator->release();
}
return found;
}
UInt32 IOFireWireController::getGeneration() const
{
return fBusGeneration;
}
bool IOFireWireController::checkGeneration(UInt32 gen) const
{
return gen == fBusGeneration;
}
UInt16 IOFireWireController::getLocalNodeID() const
{
return fLocalNodeID;
}
IOReturn IOFireWireController::getIRMNodeID(UInt32 &generation, UInt16 &id)
{
closeGate();
generation = fBusGeneration;
id = fIRMNodeID;
openGate();
return kIOReturnSuccess;
}
IOReturn IOFireWireController::clipMaxRec2K( Boolean clipMaxRec )
{
IOReturn res;
closeGate();
res = fFWIM->clipMaxRec2K(clipMaxRec);
openGate();
return res;
}
IOReturn IOFireWireController::makeRoot(UInt32 generation, UInt16 nodeID)
{
IOReturn res = kIOReturnSuccess;
nodeID &= 63;
closeGate();
if(!checkGeneration(generation))
res = kIOFireWireBusReset;
else if( fRootNodeID != nodeID ) {
res = fFWIM->sendPHYPacket((kFWConfigurationPacketID << kFWPhyPacketIDPhase) |
(nodeID << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR);
if(kIOReturnSuccess == res)
{
FWTrace(kFWTResetBusAction, kTPResetMakeRoot, (uintptr_t)fFWIM, 0, 0, 0 );
res = resetBus();
}
}
openGate();
return res;
}
void IOFireWireController::nodeMustBeRoot( UInt32 nodeID )
{
fForcedRootNodeID = nodeID;
fNodeMustBeRootFlag = true;
}
void IOFireWireController::nodeMustNotBeRoot( UInt32 nodeID )
{
nodeID &= nodeID & 0x3f;
if( not fDelegateCycleMaster )
{
if( fScans[nodeID] )
{
fScans[nodeID]->fMustNotBeRoot = true;
fNodeMustNotBeRootFlag = true;
}
}
}
void IOFireWireController::setGapCount( UInt32 gapCount )
{
fForcedGapCount = gapCount;
fForcedGapFlag = true;
}
void IOFireWireController::useHalfSizePackets( void )
{
fUseHalfSizePackets = true;
fRequestedHalfSizePackets = true;
}
void IOFireWireController::disablePhyPortOnSleepForNodeID( UInt32 nodeID )
{
UInt32 childNodeID;
UInt32 childNumber = 0;
UInt32 childPort;
for( childNodeID = 0; childNodeID < (UInt32)(fLocalNodeID & 63); childNodeID++ )
{
if( childNodeID == nodeID )
{
childPort = getPortNumberFromIndex( childNumber );
if( childPort != 0xFFFFFFFF ) {
fFWIM->disablePHYPortOnSleep( 1 << childPort );
break;
}
}
if( hopCount( childNodeID, fLocalNodeID ) == 1 )
{
childNumber++;
}
}
}
#pragma mark -
void IOFireWireController::openGate()
{
fPendingQ.fSource->openGate();
}
void IOFireWireController::closeGate()
{
fPendingQ.fSource->closeGate();
}
bool IOFireWireController::inGate()
{
return fPendingQ.fSource->inGate();
}
#pragma mark -
IOFWCmdQ& IOFireWireController::getTimeoutQ()
{
return fTimeoutQ;
}
IOFWCmdQ& IOFireWireController::getPendingQ()
{
return fPendingQ;
}
IOFWCmdQ &IOFireWireController::getAfterResetHandledQ()
{
return fAfterResetHandledQ;
}
void IOFireWireController::enterLoggingMode( void )
{
if ( fFWIM->enterLoggingMode() )
{
setProperty(kFireWireLoggingMode, true);
setProperty( kFireWireGenerationID, "Suspended" ); }
}
IOFireWireMultiIsochReceiveListener *
IOFireWireController::createMultiIsochReceiveListener(UInt32 channel,
FWMultiIsochReceiveListenerCallback callback,
void *pCallbackRefCon,
FWMultiIsochReceiveListenerParams *pListenerParams)
{
return IOFireWireMultiIsochReceiveListener::create(this,channel,callback,pCallbackRefCon,pListenerParams);
}
IOReturn IOFireWireController::activateMultiIsochReceiveListener(IOFireWireMultiIsochReceiveListener *pListener)
{
return fFWIM->activateMultiIsochReceiveListener(pListener);
}
IOReturn IOFireWireController::deactivateMultiIsochReceiveListener(IOFireWireMultiIsochReceiveListener *pListener)
{
return fFWIM->deactivateMultiIsochReceiveListener(pListener);
}
void IOFireWireController::clientDoneWithMultiIsochReceivePacket(IOFireWireMultiIsochReceivePacket *pPacket)
{
fFWIM->clientDoneWithMultiIsochReceivePacket(pPacket);
}