IOFireWireLibIsochPort.cpp [plain text]
#import "IOFireWireLibIsochPort.h"
#import "IOFireWireLibDevice.h"
#import "IOFireWireLibNuDCLPool.h"
#import "IOFireWireLibNuDCL.h"
#import "IOFireWireLibCoalesceTree.h"
#import <IOKit/iokitmig.h>
#import <mach/mach.h>
#import <System/libkern/OSCrossEndian.h>
#define IOFIREWIREISOCHPORTIMP_INTERFACE \
& IsochPortCOM::SGetSupported, \
& IsochPortCOM::SAllocatePort, \
& IsochPortCOM::SReleasePort, \
& IsochPortCOM::SStart, \
& IsochPortCOM::SStop, \
& IsochPortCOM::SSetRefCon, \
& IsochPortCOM::SGetRefCon
namespace IOFireWireLib {
RemoteIsochPort::Interface RemoteIsochPortCOM::sInterface =
{
INTERFACEIMP_INTERFACE,
1, 0,
IOFIREWIREISOCHPORTIMP_INTERFACE,
& RemoteIsochPortCOM::SSetGetSupportedHandler,
& RemoteIsochPortCOM::SSetAllocatePortHandler,
& RemoteIsochPortCOM::SSetReleasePortHandler,
& RemoteIsochPortCOM::SSetStartHandler,
& RemoteIsochPortCOM::SSetStopHandler,
} ;
Boolean
GetDCLDataBuffer(
DCLCommand* dcl,
IOVirtualAddress* outDataBuffer,
IOByteCount* outDataLength)
{
Boolean result = false ;
switch(dcl->opcode & ~kFWDCLOpFlagMask)
{
case kDCLSendPacketStartOp:
case kDCLSendPacketOp:
case kDCLReceivePacketStartOp:
case kDCLReceivePacketOp:
*outDataBuffer = (IOVirtualAddress)((DCLTransferPacket*)dcl)->buffer ;
*outDataLength = ((DCLTransferPacket*)dcl)->size ;
result = true ;
break ;
case kDCLSendBufferOp:
case kDCLReceiveBufferOp:
break ;
case kDCLPtrTimeStampOp:
*outDataBuffer = (IOVirtualAddress)((DCLPtrTimeStamp*)dcl)->timeStampPtr ;
*outDataLength = sizeof( *( ((DCLPtrTimeStamp*)dcl)->timeStampPtr) ) ;
result = true ;
break ;
default:
break ;
}
return result ;
}
IOByteCount
GetDCLSize(
DCLCommand* dcl)
{
IOByteCount result = 0 ;
switch(dcl->opcode & ~kFWDCLOpFlagMask)
{
case kDCLSendPacketStartOp:
case kDCLSendPacketOp:
case kDCLReceivePacketStartOp:
case kDCLReceivePacketOp:
result = sizeof(UserExportDCLTransferPacket) ;
break ;
case kDCLSendBufferOp:
case kDCLReceiveBufferOp:
result = sizeof(UserExportDCLTransferBuffer) ;
break ;
case kDCLCallProcOp:
result = sizeof(UserExportDCLCallProc) ;
break ;
case kDCLLabelOp:
result = sizeof(UserExportDCLLabel) ;
break ;
case kDCLJumpOp:
result = sizeof(UserExportDCLJump) ;
break ;
case kDCLSetTagSyncBitsOp:
result = sizeof(UserExportDCLSetTagSyncBits) ;
break ;
case kDCLUpdateDCLListOp:
result = sizeof(UserExportDCLUpdateDCLList) ;
break ;
case kDCLPtrTimeStampOp:
result = sizeof(UserExportDCLPtrTimeStamp) ;
break;
case kDCLSkipCycleOp:
result = sizeof(UserExportDCLCommand) ;
break;
}
return result ;
}
#pragma mark -
IsochPort::IsochPort( const IUnknownVTbl & interface, Device & device, bool talking, bool allocateKernPort )
: IOFireWireIUnknown( interface ),
mDevice( device ),
mKernPortRef( 0 ),
mTalking( talking )
{
mDevice.AddRef() ;
}
IsochPort::~IsochPort()
{
if ( mKernPortRef )
{
IOReturn error = kIOReturnSuccess;
uint32_t outputCnt = 0;
const uint64_t inputs[1]={(const uint64_t)mKernPortRef};
error = IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
kReleaseUserObject,
inputs,1,NULL,&outputCnt);
DebugLogCond( error, "Couldn't release kernel port" ) ;
}
mDevice.Release() ;
}
IOReturn
IsochPort::GetSupported(
IOFWSpeed& maxSpeed,
UInt64& chanSupported )
{
uint32_t outputCnt = 3;
uint64_t outputVal[3];
const uint64_t inputs[1]={(const uint64_t)mKernPortRef};
IOReturn result = IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
kIsochPort_GetSupported,
inputs,1,
outputVal,&outputCnt);
maxSpeed = (IOFWSpeed)(outputVal[0] & 0xFFFFFFFF);
chanSupported = ((outputVal[1] & 0xFFFFFFFF)<<32)+(outputVal[2] & 0xFFFFFFFF);
return result;
}
IOReturn
IsochPort::AllocatePort( IOFWSpeed speed, UInt32 chan )
{
uint32_t outputCnt = 0;
const uint64_t inputs[2] = {speed, chan};
return IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
mDevice.MakeSelectorWithObject( kIsochPort_AllocatePort_d, mKernPortRef ),
inputs,2,
NULL,&outputCnt);
}
IOReturn
IsochPort::ReleasePort()
{
uint32_t outputCnt = 0;
return IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
mDevice.MakeSelectorWithObject( kIsochPort_ReleasePort_d, mKernPortRef ),
NULL,0,
NULL,&outputCnt);
}
IOReturn
IsochPort::Start()
{
uint32_t outputCnt = 0;
return IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
mDevice.MakeSelectorWithObject( kIsochPort_Start_d, mKernPortRef ),
NULL,0,
NULL,&outputCnt);
}
IOReturn
IsochPort::Stop()
{
uint32_t outputCnt = 0;
return IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
mDevice.MakeSelectorWithObject( kIsochPort_Stop_d, mKernPortRef ),
NULL,0,
NULL,&outputCnt);
}
#pragma mark -
IsochPortCOM::IsochPortCOM( const IUnknownVTbl & interface, Device& userclient, bool talking, bool allocateKernPort )
: IsochPort( interface, userclient, talking, allocateKernPort )
{
}
IsochPortCOM::~IsochPortCOM()
{
}
IOReturn
IsochPortCOM::SGetSupported(
IOFireWireLibIsochPortRef self,
IOFWSpeed* maxSpeed,
UInt64* chanSupported )
{
return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->GetSupported(*maxSpeed, *chanSupported) ;
}
IOReturn
IsochPortCOM::SAllocatePort(
IOFireWireLibIsochPortRef self,
IOFWSpeed speed,
UInt32 chan )
{
return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->AllocatePort(speed, chan) ;
}
IOReturn
IsochPortCOM::SReleasePort(
IOFireWireLibIsochPortRef self)
{
return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->ReleasePort() ;
}
IOReturn
IsochPortCOM::SStart(
IOFireWireLibIsochPortRef self)
{
return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->Start() ;
}
IOReturn
IsochPortCOM::SStop(
IOFireWireLibIsochPortRef self)
{
return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->Stop() ;
}
void
IsochPortCOM::SSetRefCon(
IOFireWireLibIsochPortRef self,
void* inRefCon)
{
IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->SetRefCon(inRefCon) ;
}
void*
IsochPortCOM::SGetRefCon(
IOFireWireLibIsochPortRef self)
{
return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->GetRefCon() ;
}
Boolean
IsochPortCOM::SGetTalking(
IOFireWireLibIsochPortRef self)
{
return IOFireWireIUnknown::InterfaceMap<IsochPortCOM>::GetThis(self)->GetTalking() ;
}
#pragma mark -
RemoteIsochPort::RemoteIsochPort( const IUnknownVTbl & interface, Device& userclient, bool talking )
: IsochPortCOM( interface, userclient, talking ),
mGetSupportedHandler(0),
mAllocatePortHandler(0),
mReleasePortHandler(0),
mStartHandler(0),
mStopHandler(0),
mRefInterface( reinterpret_cast<IOFireWireIsochPortInterface**>(& GetInterface()) )
{
}
IOReturn
RemoteIsochPort::GetSupported(
IOFWSpeed& maxSpeed,
UInt64& chanSupported)
{
if (mGetSupportedHandler)
return (*mGetSupportedHandler)(mRefInterface, & maxSpeed, & chanSupported) ;
else
return kIOReturnUnsupported ; }
IOReturn
RemoteIsochPort::AllocatePort(
IOFWSpeed speed,
UInt32 chan )
{
if (mAllocatePortHandler)
return (*mAllocatePortHandler)(mRefInterface, speed, chan) ;
else
return kIOReturnSuccess ;
}
IOReturn
RemoteIsochPort::ReleasePort()
{
if (mReleasePortHandler)
return (*mReleasePortHandler)(mRefInterface) ;
else
return kIOReturnSuccess ;
}
IOReturn
RemoteIsochPort::Start()
{
if (mStartHandler)
return (*mStartHandler)(mRefInterface) ;
else
return kIOReturnSuccess ;
}
IOReturn
RemoteIsochPort::Stop()
{
if (mStopHandler)
return (*mStopHandler)(mRefInterface) ;
else
return kIOReturnSuccess ;
}
IOFireWireLibIsochPortGetSupportedCallback
RemoteIsochPort::SetGetSupportedHandler(
IOFireWireLibIsochPortGetSupportedCallback inHandler)
{
IOFireWireLibIsochPortGetSupportedCallback oldHandler = mGetSupportedHandler ;
mGetSupportedHandler = inHandler ;
return oldHandler ;
}
IOFireWireLibIsochPortAllocateCallback
RemoteIsochPort::SetAllocatePortHandler(
IOFireWireLibIsochPortAllocateCallback inHandler)
{
IOFireWireLibIsochPortAllocateCallback oldHandler = mAllocatePortHandler ;
mAllocatePortHandler = inHandler ;
return oldHandler ;
}
IOFireWireLibIsochPortCallback
RemoteIsochPort::SetReleasePortHandler(
IOFireWireLibIsochPortCallback inHandler)
{
IOFireWireLibIsochPortCallback oldHandler = mReleasePortHandler ;
mReleasePortHandler = inHandler ;
return oldHandler ;
}
IOFireWireLibIsochPortCallback
RemoteIsochPort::SetStartHandler(
IOFireWireLibIsochPortCallback inHandler)
{
IOFireWireLibIsochPortCallback oldHandler = mStartHandler ;
mStartHandler = inHandler ;
return oldHandler ;
}
IOFireWireLibIsochPortCallback
RemoteIsochPort::SetStopHandler(
IOFireWireLibIsochPortCallback inHandler)
{
IOFireWireLibIsochPortCallback oldHandler = mStopHandler ;
mStopHandler = inHandler ;
return oldHandler ;
}
#pragma mark -
RemoteIsochPortCOM::RemoteIsochPortCOM( Device& userclient, bool talking )
: RemoteIsochPort( reinterpret_cast<const IUnknownVTbl &>( sInterface ), userclient, talking )
{
}
RemoteIsochPortCOM::~RemoteIsochPortCOM()
{
}
IUnknownVTbl**
RemoteIsochPortCOM::Alloc( Device& userclient, bool talking )
{
RemoteIsochPortCOM* me = nil ;
try {
me = new RemoteIsochPortCOM( userclient, talking ) ;
} catch(...) {
}
return (nil==me) ? nil : reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ;
}
HRESULT
RemoteIsochPortCOM::QueryInterface(REFIID iid, void ** ppv )
{
HRESULT result = S_OK ;
*ppv = nil ;
CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ;
if ( CFEqual(interfaceID, IUnknownUUID) || CFEqual(interfaceID, kIOFireWireRemoteIsochPortInterfaceID) )
{
*ppv = & GetInterface() ;
AddRef() ;
}
else
{
*ppv = nil ;
result = E_NOINTERFACE ;
}
CFRelease(interfaceID) ;
return result ;
}
IOFireWireLibIsochPortGetSupportedCallback
RemoteIsochPortCOM::SSetGetSupportedHandler(
PortRef self,
IOFireWireLibIsochPortGetSupportedCallback inHandler)
{
return IOFireWireIUnknown::InterfaceMap<RemoteIsochPortCOM>::GetThis(self)->SetGetSupportedHandler(inHandler) ;
}
IOFireWireLibIsochPortAllocateCallback
RemoteIsochPortCOM::SSetAllocatePortHandler(
PortRef self,
IOFireWireLibIsochPortAllocateCallback inHandler)
{
return IOFireWireIUnknown::InterfaceMap<RemoteIsochPortCOM>::GetThis(self)->SetAllocatePortHandler(inHandler) ;
}
IOFireWireLibIsochPortCallback
RemoteIsochPortCOM::SSetReleasePortHandler(
PortRef self,
IOFireWireLibIsochPortCallback inHandler)
{
return IOFireWireIUnknown::InterfaceMap<RemoteIsochPortCOM>::GetThis(self)->SetReleasePortHandler(inHandler) ;
}
IOFireWireLibIsochPortCallback
RemoteIsochPortCOM::SSetStartHandler(
PortRef self,
IOFireWireLibIsochPortCallback inHandler)
{
return IOFireWireIUnknown::InterfaceMap<RemoteIsochPortCOM>::GetThis(self)->SetStartHandler(inHandler) ;
}
IOFireWireLibIsochPortCallback
RemoteIsochPortCOM::SSetStopHandler(
PortRef self,
IOFireWireLibIsochPortCallback inHandler)
{
return IOFireWireIUnknown::InterfaceMap<RemoteIsochPortCOM>::GetThis(self)->SetStopHandler(inHandler) ;
}
#pragma mark -
LocalIsochPortCOM::Interface LocalIsochPortCOM::sInterface =
{
INTERFACEIMP_INTERFACE
,4,0
,IOFIREWIREISOCHPORTIMP_INTERFACE
,& LocalIsochPortCOM::SModifyJumpDCL
,& LocalIsochPortCOM::SPrintDCLProgram
,& LocalIsochPortCOM::SModifyTransferPacketDCLSize
,& LocalIsochPortCOM::SModifyTransferPacketDCLBuffer
,& LocalIsochPortCOM::SModifyTransferPacketDCL
,& LocalIsochPortCOM::S_SetFinalizeCallback
, & LocalIsochPortCOM::S_SetResourceUsageFlags
, & LocalIsochPortCOM::S_Notify
} ;
LocalIsochPort::LocalIsochPort( const IUnknownVTbl & interface, Device & userclient, bool talking,
DCLCommand* program, UInt32 startEvent, UInt32 startState, UInt32 startMask,
IOVirtualRange userProgramRanges[], UInt32 userProgramRangeCount,
IOVirtualRange userBufferRanges[], UInt32 userBufferRangeCount, IOFWIsochPortOptions options )
: IsochPortCOM( interface, userclient, talking, false )
, mDCLProgram( program )
, mExpectedStopTokens(0)
, mDeferredReleaseCount(0)
, mFinalizeCallback(nil)
, mBufferRanges( nil )
, mBufferAddressRanges( nil )
, mStarted( false )
{
if ( !program )
{
DebugLog( "no DCL program!\n" ) ;
throw kIOReturnBadArgument ;
}
IOReturn error = kIOReturnSuccess ;
CoalesceTree bufferTree ;
if ( userBufferRanges )
{
for( unsigned index=0; index < userBufferRangeCount; ++index )
bufferTree.CoalesceRange( userBufferRanges[index]) ;
}
IOByteCount programExportBytes = 0 ;
IOVirtualAddress programData = 0 ;
LocalIsochPortAllocateParams params ;
{
params.programExportBytes = 0 ;
params.programData = 0 ;
}
if ( program->opcode == kDCLNuDCLLeaderOp )
{
if( !error )
{
NuDCLPool* pool = reinterpret_cast<NuDCLPool*>( reinterpret_cast< DCLNuDCLLeader* >( program )->program ) ;
params.version = kDCLExportDataNuDCLRosettaVersion ;
pool->CoalesceBuffers( bufferTree ) ;
mBufferRangeCount = bufferTree.GetCount() ;
mBufferRanges = new IOVirtualRange[ mBufferRangeCount ] ;
if ( !mBufferRanges )
{
error = kIOReturnNoMemory ;
}
else
{
bufferTree.GetCoalesceList( mBufferRanges ) ;
mBufferAddressRanges = new IOAddressRange[ mBufferRangeCount ] ;
if ( !mBufferAddressRanges )
{
error = kIOReturnNoMemory ;
}
else
for (unsigned int i=0;i<mBufferRangeCount;i++)
{
mBufferAddressRanges[i].address = mBufferRanges[i].address;
mBufferAddressRanges[i].length = mBufferRanges[i].length;
}
programExportBytes = pool->Export( &programData, mBufferRanges, mBufferRangeCount ) ;
params.programExportBytes = programExportBytes ;
params.programData = programData;
}
}
}
else
{
unsigned programCount = 0 ;
params.version = kDCLExportDataLegacyVersion ;
for( DCLCommand * dcl = mDCLProgram; dcl != nil; dcl = dcl->pNextDCLCommand )
{
IOVirtualRange tempRange ;
if ( GetDCLDataBuffer ( dcl, & tempRange.address, & tempRange.length ) )
{
bufferTree.CoalesceRange ( tempRange ) ;
}
++programCount ;
}
InfoLog("program count is %d\n", programCount) ;
if ( !error )
{
error = ExportDCLs( &programData, &programExportBytes ) ;
params.programData = programData;
params.programExportBytes = programExportBytes;
}
if ( !error )
{
mBufferRangeCount = bufferTree.GetCount() ;
mBufferRanges = new IOVirtualRange[ mBufferRangeCount ] ;
if ( !mBufferRanges )
{
error = kIOReturnNoMemory ;
}
else
{
bufferTree.GetCoalesceList( mBufferRanges ) ;
mBufferAddressRanges = new IOAddressRange[ mBufferRangeCount ] ;
if ( !mBufferAddressRanges )
{
error = kIOReturnNoMemory ;
}
else
for (unsigned int i=0;i<mBufferRangeCount;i++)
{
mBufferAddressRanges[i].address = mBufferRanges[i].address;
mBufferAddressRanges[i].length = mBufferRanges[i].length;
}
}
}
}
if ( error )
{
throw error ;
}
params.bufferRanges = (mach_vm_address_t)mBufferAddressRanges ;
params.bufferRangeCount = mBufferRangeCount ;
params.talking = mTalking ;
params.startEvent = startEvent ;
params.startState = startState ;
params.startMask = startMask ;
params.userObj = (mach_vm_address_t) this ;
params.options = options ;
#if 0
params.options |= kFWIsochEnableRobustness;
#endif
InfoLog("startEvent=%x, startState=%x, startMask=%x\n", params.startEvent, params.startState, params.startMask) ;
#ifndef __LP64__
ROSETTA_ONLY(
{
params.version = OSSwapInt32( params.version );
params.talking = params.talking; params.startEvent = OSSwapInt32( params.startEvent );
params.startState = OSSwapInt32( params.startState );
params.startMask = OSSwapInt32( params.startMask );
params.programExportBytes = OSSwapInt32( params.programExportBytes );
params.programData = OSSwapInt64( params.programData );
for( UInt32 i = 0; i < params.bufferRangeCount; i++ )
{
IOAddressRange *pAddressRange = (IOAddressRange*) (params.bufferRanges+(i*sizeof(IOAddressRange)));
pAddressRange->address = OSSwapInt64( pAddressRange->address );
pAddressRange->length = OSSwapInt64( pAddressRange->length );
}
params.bufferRangeCount = OSSwapInt32( params.bufferRangeCount );
params.bufferRanges = OSSwapInt64(params.bufferRanges );
params.options = (IOFWIsochPortOptions)OSSwapInt32( params.options | kFWIsochBigEndianUpdates );
params.userObj = (mach_vm_address_t)OSSwapInt64((mach_vm_address_t)params.userObj );
}
);
#endif
uint32_t outputCnt = 0;
size_t outputStructSize = sizeof( UserObjectHandle ) ;
error = IOConnectCallMethod(mDevice.GetUserClientConnection(),
kLocalIsochPort_Allocate,
NULL,0,
& params,sizeof (params),
NULL,&outputCnt,
&mKernPortRef,&outputStructSize);
#ifndef __LP64__
ROSETTA_ONLY(
{
mKernPortRef = (UserObjectHandle)OSSwapInt32( (UInt32)mKernPortRef );
}
);
#endif
if (error)
{
DebugLog ( "Couldn't create local isoch port (error=%x)\nCheck your buffers!\n", error ) ;
DebugLog ( "Found buffers:\n" ) ;
#if IOFIREWIRELIBDEBUG
for( unsigned index=0; index < mBufferRangeCount; ++index )
{
#ifdef __LP64__
DebugLog ( "\%u: <0x%x>-<0x%x>\n", index, (unsigned)mBufferRanges[index].address,
(unsigned)mBufferRanges[index].address + mBufferRanges[index].length ) ;
#else
DebugLog ( "\%u: <0x%x>-<0x%lx>\n", index, (unsigned)mBufferRanges[index].address,
(unsigned)mBufferRanges[index].address + mBufferRanges[index].length ) ;
#endif
}
#endif
throw error ;
}
{
uint64_t refrncData[kOSAsyncRef64Count];
refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) & LocalIsochPort::s_DCLStopTokenCallProcHandler;
refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long)this;
uint32_t outputCnt = 0;
const uint64_t inputs[1]={(const uint64_t)mKernPortRef};
error = IOConnectCallAsyncScalarMethod(mDevice.GetUserClientConnection(),
kSetAsyncRef_DCLCallProc,
mDevice.GetIsochAsyncPort(),
refrncData,kOSAsyncRef64Count,
inputs,1,
NULL,&outputCnt);
if( error )
{
throw error ;
}
}
if ( params.programData )
{
vm_deallocate( mach_task_self (), (vm_address_t) programData, programExportBytes ) ; }
pthread_mutex_init ( & mMutex, nil ) ;
}
LocalIsochPort::~LocalIsochPort ()
{
delete[] mBufferRanges ;
delete[] mBufferAddressRanges;
pthread_mutex_destroy( & mMutex ) ;
}
ULONG
LocalIsochPort::Release ()
{
Lock () ;
if ( mExpectedStopTokens > 0 )
{
Unlock () ;
++ mDeferredReleaseCount ;
return mRefCount ;
}
Unlock () ;
return IsochPortCOM::Release() ;
}
IOReturn
LocalIsochPort::Start()
{
IOReturn error = IsochPort::Start() ;
if ( !error )
{
Lock() ;
mStarted = true ;
Unlock() ;
}
return error ;
}
IOReturn
LocalIsochPort::Stop ()
{
Lock() ;
if ( mStarted )
{
mStarted = false ;
++mExpectedStopTokens ;
InfoLog("waiting for %lu stop tokens\n", mExpectedStopTokens) ;
}
Unlock() ;
return IsochPortCOM::Stop() ; }
IOReturn
LocalIsochPort::ModifyJumpDCL ( DCLJump* inJump, DCLLabel* inLabel )
{
inJump->pJumpDCLLabel = inLabel ;
uint32_t outputCnt = 0;
const uint64_t inputs[2] = {inJump->compilerData, inLabel->compilerData};
IOReturn result = IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
mDevice.MakeSelectorWithObject( kLocalIsochPort_ModifyJumpDCL_d, mKernPortRef ),
inputs,2,
NULL,&outputCnt);
return result ;
}
IOReturn
LocalIsochPort::ModifyTransferPacketDCLSize ( DCLTransferPacket* dcl, IOByteCount newSize )
{
return kIOReturnUnsupported ;
}
void
LocalIsochPort::s_DCLStopTokenCallProcHandler ( void * self, IOReturn e )
{
((LocalIsochPort*)self)->DCLStopTokenCallProcHandler(e) ;
}
void
LocalIsochPort::DCLStopTokenCallProcHandler( IOReturn )
{
if ( mExpectedStopTokens > 0 )
{
Lock() ;
mExpectedStopTokens-- ;
Unlock() ;
if ( mExpectedStopTokens == 0 )
{
if ( mFinalizeCallback )
(*mFinalizeCallback)(mRefCon) ;
UInt32 release_count = mDeferredReleaseCount;
while ( release_count > 0 )
{
--release_count ;
Release() ;
}
}
}
}
#if 0
void
LocalIsochPort::S_DCLKernelCallout( DCLCallProc * dcl )
{
(*dcl->proc)(dcl->procData) ;
uint32_t outputCnt = 0;
const uint64_t inputs[1]={(const uint64_t)dcl->compilerData};
IOReturn result = IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
Device::MakeSelectorWithObject( kLocalIsochPort_RunDCLUpdateList_d, port->mKernPortRef ),
inputs,1,
NULL,&outputCnt);
}
void
LocalIsochPort::S_NuDCLKernelCallout ( NuDCL * dcl )
{
(*dcl->fData.callback)(dcl->fData.refcon, (NuDCLRef)dcl) ;
uint32_t outputCnt = 0;
const uint64_t inputs[1]={(const uint64_t)dcl->fExportIndex};
IOReturn result = IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
Device::MakeSelectorWithObject( kLocalIsochPort_RunNuDCLUpdateList_d, mKernPortRef ),
inputs,1,
NULL,&outputCnt);
}
#endif
IOReturn
LocalIsochPort::SetResourceUsageFlags (
IOFWIsochResourceFlags flags )
{
uint32_t outputCnt = 0;
const uint64_t inputs[1]={(const uint64_t)flags};
return IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
mDevice.MakeSelectorWithObject( kIsochPort_SetIsochResourceFlags_d, mKernPortRef ),
inputs,1,
NULL,&outputCnt);
}
IOReturn
LocalIsochPort::ExportDCLs( IOVirtualAddress * exportBuffer, IOByteCount * exportBytes )
{
IOReturn error = kIOReturnSuccess ;
*exportBytes = 0 ;
for( DCLCommand * dcl = mDCLProgram; dcl != NULL; dcl = dcl->pNextDCLCommand )
{
*exportBytes += GetDCLSize( dcl ) ;
switch ( dcl->opcode & ~kFWDCLOpFlagMask )
{
case kDCLUpdateDCLListOp :
{
*exportBytes += sizeof( mach_vm_address_t ) * ((DCLUpdateDCLList*)dcl)->numDCLCommands ;
break ;
}
case kDCLCallProcOp :
{
*exportBytes += sizeof( uint64_t[kOSAsyncRef64Count]) ;
break ;
}
}
}
error = vm_allocate( mach_task_self (), exportBuffer, *exportBytes, true ) ;
if ( !*exportBuffer && !error )
{
error = kIOReturnNoMemory ;
}
{
unsigned offset = 0 ;
IOVirtualAddress buffer = *exportBuffer ;
InfoLog("exporting DCLs, pass 1...\n") ;
for( DCLCommand * dcl = mDCLProgram; dcl != NULL ; dcl = dcl->pNextDCLCommand )
{
unsigned size = GetDCLSize( dcl ) ;
dcl->compilerData = offset ;
switch(dcl->opcode & ~kFWDCLOpFlagMask)
{
case kDCLSendPacketStartOp:
case kDCLSendPacketOp:
case kDCLReceivePacketStartOp:
case kDCLReceivePacketOp:
{
UserExportDCLTransferPacket *pUserExportDCLTransferPacket = (UserExportDCLTransferPacket*) buffer;
pUserExportDCLTransferPacket->pClientDCLStruct = (mach_vm_address_t) dcl;
pUserExportDCLTransferPacket->pNextDCLCommand = (mach_vm_address_t) ((DCLTransferPacket*)dcl)->pNextDCLCommand;
pUserExportDCLTransferPacket->compilerData = ((DCLTransferPacket*)dcl)->compilerData;
pUserExportDCLTransferPacket->opcode = ((DCLTransferPacket*)dcl)->opcode;
pUserExportDCLTransferPacket->buffer = (mach_vm_address_t) ((DCLTransferPacket*)dcl)->buffer;
pUserExportDCLTransferPacket->size = ((DCLTransferPacket*)dcl)->size;
}
break ;
case kDCLSendBufferOp:
case kDCLReceiveBufferOp:
{
UserExportDCLTransferBuffer *pUserExportDCLTransferBuffer = (UserExportDCLTransferBuffer*) buffer;
pUserExportDCLTransferBuffer->pClientDCLStruct = (mach_vm_address_t) dcl;
pUserExportDCLTransferBuffer->pNextDCLCommand = (mach_vm_address_t) ((DCLTransferBuffer*)dcl)->pNextDCLCommand;
pUserExportDCLTransferBuffer->compilerData = ((DCLTransferBuffer*)dcl)->compilerData;
pUserExportDCLTransferBuffer->opcode = ((DCLTransferBuffer*)dcl)->opcode;
pUserExportDCLTransferBuffer->buffer = (mach_vm_address_t) ((DCLTransferBuffer*)dcl)->buffer;
pUserExportDCLTransferBuffer->size = ((DCLTransferBuffer*)dcl)->size;
pUserExportDCLTransferBuffer->packetSize = ((DCLTransferBuffer*)dcl)->packetSize;
pUserExportDCLTransferBuffer->reserved = ((DCLTransferBuffer*)dcl)->reserved;
pUserExportDCLTransferBuffer->bufferOffset = ((DCLTransferBuffer*)dcl)->bufferOffset;
}
break ;
case kDCLCallProcOp:
{
UserExportDCLCallProc *pUserExportDCLCallProc = (UserExportDCLCallProc*) buffer;
pUserExportDCLCallProc->pClientDCLStruct = (mach_vm_address_t) dcl;
pUserExportDCLCallProc->pNextDCLCommand = (mach_vm_address_t) ((DCLCallProc*)dcl)->pNextDCLCommand;
pUserExportDCLCallProc->compilerData = ((DCLCallProc*)dcl)->compilerData;
pUserExportDCLCallProc->opcode = ((DCLCallProc*)dcl)->opcode;
pUserExportDCLCallProc->proc = (mach_vm_address_t) ((DCLCallProc*)dcl)->proc;
pUserExportDCLCallProc->procData = (uint64_t)dcl ;
size += sizeof( uint64_t[kOSAsyncRef64Count]) ;
}
break ;
case kDCLLabelOp:
{
UserExportDCLLabel *pUserExportDCLLabel = (UserExportDCLLabel*) buffer;
pUserExportDCLLabel->pClientDCLStruct = (mach_vm_address_t) dcl;
pUserExportDCLLabel->pNextDCLCommand = (mach_vm_address_t) ((DCLLabel*)dcl)->pNextDCLCommand;
pUserExportDCLLabel->compilerData = ((DCLLabel*)dcl)->compilerData;
pUserExportDCLLabel->opcode = ((DCLLabel*)dcl)->opcode;
}
break ;
case kDCLJumpOp:
{
UserExportDCLJump *pUserExportDCLJump = (UserExportDCLJump*) buffer;
pUserExportDCLJump->pClientDCLStruct = (mach_vm_address_t) dcl;
pUserExportDCLJump->pNextDCLCommand = (mach_vm_address_t) ((DCLJump*)dcl)->pNextDCLCommand;
pUserExportDCLJump->compilerData = ((DCLJump*)dcl)->compilerData;
pUserExportDCLJump->opcode = ((DCLJump*)dcl)->opcode;
pUserExportDCLJump->pJumpDCLLabel = (mach_vm_address_t) ((DCLJump*)dcl)->pJumpDCLLabel;
}
break ;
case kDCLSetTagSyncBitsOp:
{
UserExportDCLSetTagSyncBits *pUserExportDCLSetTagSyncBits = (UserExportDCLSetTagSyncBits*) buffer;
pUserExportDCLSetTagSyncBits->pClientDCLStruct = (mach_vm_address_t) dcl;
pUserExportDCLSetTagSyncBits->pNextDCLCommand = (mach_vm_address_t) ((DCLSetTagSyncBits*)dcl)->pNextDCLCommand;
pUserExportDCLSetTagSyncBits->compilerData = ((DCLSetTagSyncBits*)dcl)->compilerData;
pUserExportDCLSetTagSyncBits->opcode = ((DCLSetTagSyncBits*)dcl)->opcode;
pUserExportDCLSetTagSyncBits->tagBits = ((DCLSetTagSyncBits*)dcl)->tagBits;
pUserExportDCLSetTagSyncBits->syncBits = ((DCLSetTagSyncBits*)dcl)->syncBits;
}
break ;
case kDCLUpdateDCLListOp:
{
UserExportDCLUpdateDCLList *pUserExportDCLUpdateDCLList = (UserExportDCLUpdateDCLList*) buffer;
pUserExportDCLUpdateDCLList->pClientDCLStruct = (mach_vm_address_t) dcl;
pUserExportDCLUpdateDCLList->pNextDCLCommand = (mach_vm_address_t) ((DCLUpdateDCLList*)dcl)->pNextDCLCommand;
pUserExportDCLUpdateDCLList->compilerData = ((DCLUpdateDCLList*)dcl)->compilerData;
pUserExportDCLUpdateDCLList->opcode = ((DCLUpdateDCLList*)dcl)->opcode;
pUserExportDCLUpdateDCLList->dclCommandList = (mach_vm_address_t) ((DCLUpdateDCLList*)dcl)->dclCommandList;
pUserExportDCLUpdateDCLList->numDCLCommands = ((DCLUpdateDCLList*)dcl)->numDCLCommands;
size += ( sizeof( mach_vm_address_t ) * ((DCLUpdateDCLList*)dcl)->numDCLCommands ) ;
}
break ;
case kDCLPtrTimeStampOp:
{
UserExportDCLPtrTimeStamp *pUserExportDCLPtrTimeStamp = (UserExportDCLPtrTimeStamp*) buffer;
pUserExportDCLPtrTimeStamp->pClientDCLStruct = (mach_vm_address_t) dcl;
pUserExportDCLPtrTimeStamp->pNextDCLCommand = (mach_vm_address_t) ((DCLPtrTimeStamp*)dcl)->pNextDCLCommand;
pUserExportDCLPtrTimeStamp->compilerData = ((DCLPtrTimeStamp*)dcl)->compilerData;
pUserExportDCLPtrTimeStamp->opcode = ((DCLPtrTimeStamp*)dcl)->opcode;
pUserExportDCLPtrTimeStamp->timeStampPtr = (mach_vm_address_t) ((DCLPtrTimeStamp*)dcl)->timeStampPtr;
}
break ;
case kDCLSkipCycleOp:
{
UserExportDCLCommand *pUserExportDCLCommand = (UserExportDCLCommand*) buffer;
pUserExportDCLCommand->pClientDCLStruct = (mach_vm_address_t) dcl;
pUserExportDCLCommand->pNextDCLCommand = (mach_vm_address_t) ((DCLCommand*)dcl)->pNextDCLCommand;
pUserExportDCLCommand->compilerData = ((DCLCommand*)dcl)->compilerData;
pUserExportDCLCommand->opcode = ((DCLCommand*)dcl)->opcode;
pUserExportDCLCommand->operands[0] = ((DCLCommand*)dcl)->operands[0];
}
break ;
}
buffer += size ;
offset += size ;
}
InfoLog("...done\n") ;
}
{
unsigned offset = 0 ;
InfoLog("exporting DCLs, pass 2... export size=%d bytes\n", (int)*exportBytes ) ;
while( offset < *exportBytes )
{
UserExportDCLCommand * dcl = (UserExportDCLCommand*)(*exportBuffer + offset ) ;
DCLCommand *pClientDCL = (DCLCommand *) dcl->pClientDCLStruct;
{
unsigned opcode = dcl->opcode & ~kFWDCLOpFlagMask ;
assert( opcode <= 15 || opcode == 20 ) ;
}
unsigned size = GetDCLSize( pClientDCL ) ;
switch ( dcl->opcode & ~kFWDCLOpFlagMask )
{
case kDCLUpdateDCLListOp :
{
mach_vm_address_t* list = (mach_vm_address_t*)( ((UserExportDCLUpdateDCLList*)dcl) + 1 ) ;
for( unsigned index=0; index < ((UserExportDCLUpdateDCLList*)dcl)->numDCLCommands; ++index )
{
list[ index ] = (mach_vm_address_t) ((DCLUpdateDCLList*)pClientDCL)->dclCommandList[ index ]->compilerData ;
}
size += sizeof( mach_vm_address_t ) * ((DCLUpdateDCLList*)pClientDCL)->numDCLCommands ;
break ;
}
case kDCLJumpOp :
{
((UserExportDCLJump*)dcl)->pJumpDCLLabel = (mach_vm_address_t) ((DCLJump*)pClientDCL)->pJumpDCLLabel->compilerData ;
break ;
}
case kDCLCallProcOp :
{
size += sizeof( uint64_t[kOSAsyncRef64Count]) ;
break ;
}
default :
break ;
}
#ifndef __LP64__
ROSETTA_ONLY(
{
switch(dcl->opcode & ~kFWDCLOpFlagMask)
{
case kDCLSendPacketStartOp:
case kDCLSendPacketOp:
case kDCLReceivePacketStartOp:
case kDCLReceivePacketOp:
((UserExportDCLTransferPacket*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLTransferPacket*)dcl)->pNextDCLCommand );
((UserExportDCLTransferPacket*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLTransferPacket*)dcl)->compilerData );
((UserExportDCLTransferPacket*)dcl)->opcode = OSSwapInt32( ((UserExportDCLTransferPacket*)dcl)->opcode );
((UserExportDCLTransferPacket*)dcl)->buffer = (mach_vm_address_t)OSSwapInt64( ((UserExportDCLTransferPacket*)dcl)->buffer );
((UserExportDCLTransferPacket*)dcl)->size = OSSwapInt32( ((UserExportDCLTransferPacket*)dcl)->size );
break ;
case kDCLSendBufferOp:
case kDCLReceiveBufferOp:
((UserExportDCLTransferBuffer*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLTransferBuffer*)dcl)->pNextDCLCommand );
((UserExportDCLTransferBuffer*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLTransferBuffer*)dcl)->compilerData );
((UserExportDCLTransferBuffer*)dcl)->opcode = OSSwapInt32( ((UserExportDCLTransferBuffer*)dcl)->opcode );
((UserExportDCLTransferBuffer*)dcl)->buffer = (mach_vm_address_t)OSSwapInt64(((UserExportDCLTransferBuffer*)dcl)->buffer );
((UserExportDCLTransferBuffer*)dcl)->size = OSSwapInt32( ((UserExportDCLTransferBuffer*)dcl)->size );
((UserExportDCLTransferBuffer*)dcl)->packetSize = OSSwapInt16( ((UserExportDCLTransferBuffer*)dcl)->packetSize );
((UserExportDCLTransferBuffer*)dcl)->reserved = OSSwapInt16( ((UserExportDCLTransferBuffer*)dcl)->reserved );
((UserExportDCLTransferBuffer*)dcl)->bufferOffset = OSSwapInt32( ((UserExportDCLTransferBuffer*)dcl)->bufferOffset );
break ;
case kDCLCallProcOp:
((UserExportDCLCallProc*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLCallProc*)dcl)->pNextDCLCommand );
((UserExportDCLCallProc*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLCallProc*)dcl)->compilerData );
((UserExportDCLCallProc*)dcl)->opcode = OSSwapInt32( ((UserExportDCLCallProc*)dcl)->opcode );
((UserExportDCLCallProc*)dcl)->proc = (mach_vm_address_t)OSSwapInt64(((UserExportDCLCallProc*)dcl)->proc );
((UserExportDCLCallProc*)dcl)->procData = OSSwapInt64( ((UserExportDCLCallProc*)dcl)->procData );
break ;
case kDCLLabelOp:
((UserExportDCLLabel*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLLabel*)dcl)->pNextDCLCommand );
((UserExportDCLLabel*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLLabel*)dcl)->compilerData );
((UserExportDCLLabel*)dcl)->opcode = OSSwapInt32( ((UserExportDCLLabel*)dcl)->opcode );
break ;
case kDCLJumpOp:
((UserExportDCLJump*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64( ((UserExportDCLJump*)dcl)->pNextDCLCommand );
((UserExportDCLJump*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLJump*)dcl)->compilerData );
((UserExportDCLJump*)dcl)->opcode = OSSwapInt32( ((UserExportDCLJump*)dcl)->opcode );
((UserExportDCLJump*)dcl)->pJumpDCLLabel = (mach_vm_address_t)OSSwapInt64(((UserExportDCLJump*)dcl)->pJumpDCLLabel );
break ;
case kDCLSetTagSyncBitsOp:
((UserExportDCLSetTagSyncBits*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLSetTagSyncBits*)dcl)->pNextDCLCommand );
((UserExportDCLSetTagSyncBits*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLSetTagSyncBits*)dcl)->compilerData );
((UserExportDCLSetTagSyncBits*)dcl)->opcode = OSSwapInt32( ((UserExportDCLSetTagSyncBits*)dcl)->opcode );
((UserExportDCLSetTagSyncBits*)dcl)->tagBits = OSSwapInt16( ((UserExportDCLSetTagSyncBits*)dcl)->tagBits );
((UserExportDCLSetTagSyncBits*)dcl)->syncBits = OSSwapInt16( ((UserExportDCLSetTagSyncBits*)dcl)->syncBits );
break ;
case kDCLUpdateDCLListOp:
((UserExportDCLUpdateDCLList*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLUpdateDCLList*)dcl)->pNextDCLCommand );
((UserExportDCLUpdateDCLList*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLUpdateDCLList*)dcl)->compilerData );
((UserExportDCLUpdateDCLList*)dcl)->opcode = OSSwapInt32( ((UserExportDCLUpdateDCLList*)dcl)->opcode );
{
mach_vm_address_t * list = (mach_vm_address_t *)( ((UserExportDCLUpdateDCLList*)dcl) + 1 ) ;
for( unsigned index=0; index < ((UserExportDCLUpdateDCLList*)dcl)->numDCLCommands; ++index )
{
list[ index ] = (mach_vm_address_t)OSSwapInt64(list[ index ] );
}
}
((UserExportDCLUpdateDCLList*)dcl)->dclCommandList = (mach_vm_address_t)OSSwapInt64(((UserExportDCLUpdateDCLList*)dcl)->dclCommandList );
((UserExportDCLUpdateDCLList*)dcl)->numDCLCommands = OSSwapInt32( ((UserExportDCLUpdateDCLList*)dcl)->numDCLCommands );
break ;
case kDCLPtrTimeStampOp:
((UserExportDCLPtrTimeStamp*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLPtrTimeStamp*)dcl)->pNextDCLCommand );
((UserExportDCLPtrTimeStamp*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLPtrTimeStamp*)dcl)->compilerData );
((UserExportDCLPtrTimeStamp*)dcl)->opcode = OSSwapInt32( ((UserExportDCLPtrTimeStamp*)dcl)->opcode );
((UserExportDCLPtrTimeStamp*)dcl)->timeStampPtr = (mach_vm_address_t)OSSwapInt64(((UserExportDCLPtrTimeStamp*)dcl)->timeStampPtr );
break;
case kDCLSkipCycleOp:
((UserExportDCLCommand*)dcl)->pNextDCLCommand = (mach_vm_address_t)OSSwapInt64(((UserExportDCLCommand*)dcl)->pNextDCLCommand );
((UserExportDCLCommand*)dcl)->compilerData = OSSwapInt32( ((UserExportDCLCommand*)dcl)->compilerData );
((UserExportDCLCommand*)dcl)->opcode = OSSwapInt32( ((UserExportDCLCommand*)dcl)->opcode );
((UserExportDCLCommand*)dcl)->operands[0] = OSSwapInt32( ((UserExportDCLCommand*)dcl)->operands[0] );
break;
}
}
);
#endif
offset += size ;
}
InfoLog("...done\n") ;
}
{
unsigned count = 0 ;
for( DCLCommand * dcl = mDCLProgram; dcl != nil; dcl = dcl->pNextDCLCommand )
{
dcl->compilerData = ++count ; }
}
return error ;
}
IOReturn
LocalIsochPort::Notify (
IOFWDCLNotificationType notificationType,
void ** inDCLList,
UInt32 numDCLs )
{
IOReturn error = kIOReturnSuccess ;
switch( notificationType )
{
case kFWNuDCLModifyNotification:
{
IOByteCount dataSize = 0 ;
for( unsigned index=0; index < numDCLs; ++index )
{
dataSize += 4 + ((NuDCL**)inDCLList)[ index ]->Export( NULL, NULL, 0 ) ;
}
UInt8 *data;
error = vm_allocate ( mach_task_self (), (vm_address_t *) &data, dataSize, true ) ;
if (error)
break;
{
UInt8 * exportCursor = data ;
for( unsigned index=0; index < numDCLs; ++index )
{
NuDCL * dcl = ((NuDCL**)inDCLList)[ index ] ;
*(UInt32*)exportCursor = dcl->GetExportIndex() ;
#ifndef __LP64__
ROSETTA_ONLY(
{
*(UInt32*)exportCursor = OSSwapInt32(*(UInt32*)exportCursor);
}
);
#endif
exportCursor += sizeof( UInt32 ) ;
dcl->Export( (IOVirtualAddress*) & exportCursor, mBufferRanges, mBufferRangeCount ) ;
}
}
uint32_t outputCnt = 0;
const uint64_t inputs[4] = {notificationType, numDCLs, (uint64_t) data, dataSize};
error = IOConnectCallScalarMethod(mDevice.GetUserClientConnection(),
Device::MakeSelectorWithObject( kLocalIsochPort_Notify_d, mKernPortRef ),
inputs,4,NULL,&outputCnt);
vm_deallocate( mach_task_self (), (vm_address_t) data, dataSize ) ;
break ;
}
case kFWNuDCLModifyJumpNotification:
{
unsigned pairCount = numDCLs << 1 ;
unsigned dcls[ pairCount ] ;
{
unsigned index = 0 ;
unsigned pairIndex=0;
while( pairIndex < pairCount )
{
NuDCL * theDCL = ((NuDCL**)inDCLList)[ index++ ] ;
dcls[ pairIndex ] = theDCL->GetExportIndex() ;
#ifndef __LP64__
ROSETTA_ONLY(
{
dcls[ pairIndex ] = OSSwapInt32(dcls[ pairIndex ]);
}
);
#endif
pairIndex += 1;
if (theDCL->GetBranch())
dcls[ pairIndex ] = theDCL->GetBranch()->GetExportIndex() ;
else
dcls[ pairIndex ] = 0;
#ifndef __LP64__
ROSETTA_ONLY(
{
dcls[ pairIndex ] = OSSwapInt32(dcls[ pairIndex ]);
}
);
#endif
pairIndex += 1;
}
}
uint32_t outputCnt = 0;
size_t outputStructSize = 0 ;
const uint64_t inputs[2] = {notificationType, numDCLs};
error = IOConnectCallMethod(mDevice.GetUserClientConnection(),
Device::MakeSelectorWithObject( kLocalIsochPort_Notify_d, mKernPortRef ),
inputs,2,
dcls,sizeof( dcls ),
NULL,&outputCnt,
NULL,&outputStructSize);
break ;
}
case kFWNuDCLUpdateNotification:
{
unsigned dcls[ numDCLs ] ;
for( unsigned index=0; index < numDCLs; ++index )
{
dcls[ index ] = ((NuDCL*)inDCLList[ index ])->GetExportIndex() ;
#ifndef __LP64__
ROSETTA_ONLY(
{
dcls[ index ] = OSSwapInt32(dcls[ index ]);
}
);
#endif
}
uint32_t outputCnt = 0;
size_t outputStructSize = 0 ;
const uint64_t inputs[2] = {notificationType, numDCLs};
error = IOConnectCallMethod(mDevice.GetUserClientConnection(),
Device::MakeSelectorWithObject( kLocalIsochPort_Notify_d, mKernPortRef ),
inputs,2,
dcls,sizeof( dcls ),
NULL,&outputCnt,
NULL,&outputStructSize);
break ;
}
case kFWDCLUpdateNotification:
case kFWDCLModifyNotification:
{
error = kIOReturnUnsupported ;
}
default:
error = kIOReturnBadArgument ;
}
return error ;
}
#pragma mark -
LocalIsochPortCOM::LocalIsochPortCOM( Device& userclient, bool talking, DCLCommand* program, UInt32 startEvent,
UInt32 startState, UInt32 startMask, IOVirtualRange programRanges[], UInt32 programRangeCount,
IOVirtualRange bufferRanges[], UInt32 bufferRangeCount, IOFWIsochPortOptions options )
: LocalIsochPort( reinterpret_cast<const IUnknownVTbl &>( sInterface ), userclient, talking, program,
startEvent, startState, startMask, programRanges,
programRangeCount, bufferRanges, bufferRangeCount, options )
{
}
LocalIsochPortCOM::~LocalIsochPortCOM()
{
}
IUnknownVTbl**
LocalIsochPortCOM::Alloc( Device & userclient, Boolean talking, DCLCommand * program,
UInt32 startEvent, UInt32 startState, UInt32 startMask,
IOVirtualRange programRanges[], UInt32 programRangeCount,
IOVirtualRange bufferRanges[], UInt32 bufferRangeCount,
IOFWIsochPortOptions options )
{
LocalIsochPortCOM* me = nil ;
try
{
me = new LocalIsochPortCOM ( userclient, (bool)talking, program, startEvent, startState, startMask,
programRanges, programRangeCount, bufferRanges, bufferRangeCount, options ) ;
}
catch(...)
{
}
return ( nil == me ) ? nil : reinterpret_cast < IUnknownVTbl ** > ( & me->GetInterface () ) ;
}
HRESULT
LocalIsochPortCOM::QueryInterface ( REFIID iid, void ** ppv )
{
HRESULT result = S_OK ;
CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ;
*ppv = nil ;
if ( CFEqual(interfaceID, IUnknownUUID)
|| CFEqual(interfaceID, kIOFireWireLocalIsochPortInterfaceID )
|| CFEqual( interfaceID, kIOFireWireLocalIsochPortInterfaceID_v2 )
#if 0
|| CFEqual( interfaceID, kIOFireWireLocalIsochPortInterfaceID_v3 ) #endif
|| CFEqual( interfaceID, kIOFireWireLocalIsochPortInterfaceID_v4 )
|| CFEqual( interfaceID, kIOFireWireLocalIsochPortInterfaceID_v5 )
)
{
* ppv = & GetInterface () ;
AddRef () ;
}
else
{
DebugLog("unknown local isoch port interface UUID\n") ;
* ppv = nil ;
result = E_NOINTERFACE ;
}
:: CFRelease ( interfaceID ) ;
return result ;
}
IOReturn
LocalIsochPortCOM::SModifyJumpDCL(
IOFireWireLibLocalIsochPortRef self,
DCLJump * jump,
DCLLabel * label)
{
return IOFireWireIUnknown::InterfaceMap< LocalIsochPortCOM >::GetThis ( self )->ModifyJumpDCL ( jump, label ) ;
}
void
LocalIsochPortCOM::SPrintDCLProgram (
IOFireWireLibLocalIsochPortRef self ,
const DCLCommand * program ,
UInt32 length )
{
DeviceCOM::SPrintDCLProgram ( nil, program, length ) ;
}
IOReturn
LocalIsochPortCOM::SModifyTransferPacketDCLSize (
PortRef self,
DCLTransferPacket * dcl,
IOByteCount newSize )
{
IOReturn error = kIOReturnBadArgument ;
switch ( dcl->opcode )
{
case kDCLSendPacketStartOp:
case kDCLSendPacketOp:
case kDCLReceivePacketStartOp:
case kDCLReceivePacketOp:
case kDCLReceiveBufferOp:
error = IOFireWireIUnknown::InterfaceMap<LocalIsochPortCOM>::GetThis( self )->ModifyTransferPacketDCLSize( dcl, newSize ) ;
}
return error ;
}
IOReturn
LocalIsochPortCOM::SModifyTransferPacketDCLBuffer (
PortRef self,
DCLTransferPacket * dcl,
void * newBuffer )
{
return kIOReturnUnsupported ;
}
IOReturn
LocalIsochPortCOM::SModifyTransferPacketDCL ( PortRef self, DCLTransferPacket * dcl, void * newBuffer, IOByteCount newSize )
{
return kIOReturnUnsupported ;
}
IOReturn
LocalIsochPortCOM::S_SetFinalizeCallback(
IOFireWireLibLocalIsochPortRef self,
IOFireWireLibIsochPortFinalizeCallback finalizeCallback )
{
LocalIsochPortCOM * me = IOFireWireIUnknown::InterfaceMap< LocalIsochPortCOM >::GetThis( self ) ;
me->mFinalizeCallback = finalizeCallback ;
return kIOReturnSuccess ;
}
IOReturn
LocalIsochPortCOM::S_SetResourceUsageFlags (
IOFireWireLibLocalIsochPortRef self,
IOFWIsochResourceFlags flags )
{
return IOFireWireIUnknown::InterfaceMap< LocalIsochPortCOM >::GetThis( self )->SetResourceUsageFlags( flags ) ;
}
IOReturn
LocalIsochPortCOM::S_Notify(
IOFireWireLibLocalIsochPortRef self,
IOFWDCLNotificationType notificationType,
void ** inDCLList,
UInt32 numDCLs )
{
return IOFireWireIUnknown::InterfaceMap< LocalIsochPortCOM >::GetThis( self )->Notify( notificationType, inDCLList, numDCLs ) ;
}
}