#import "FWDebugging.h"
#import "IOFWDCLPool.h"
#import "IOFWDCL.h"
#import "IOFireWireLibNuDCL.h"
#import "IOFWUserIsochPort.h"
#import <IOKit/IOLib.h>
#import <IOKit/IOMemoryDescriptor.h>
using namespace IOFireWireLib ;
#undef super
#define super OSObject
OSDefineMetaClassAndAbstractStructors( IOFWDCLPool, super ) ;
#if 0
extern bool findOffsetInRanges ( IOVirtualAddress address, unsigned rangeCount, IOVirtualRange ranges[], IOByteCount & outOffset ) ;
static bool
convertUserRanges (
IOVirtualRange userRanges[],
IOVirtualRange kernRanges[],
unsigned rangeCount,
IOVirtualRange allUserRanges[],
unsigned allUserRangeCount,
IOMemoryMap * bufferMap )
{
IOVirtualAddress kernBaseAddress = bufferMap->getVirtualAddress() ;
bool ok = true ;
unsigned index = 0 ;
while ( index < rangeCount && ok )
{
IOByteCount offset ;
ok = findOffsetInRanges( userRanges[ index ].address, allUserRangeCount, allUserRanges, offset ) ;
if ( ok )
{
kernRanges[ index ].address = kernBaseAddress + offset ;
kernRanges[ index ].length = userRanges[ index ].length ;
ok = ( kernRanges[ index ].address < kernBaseAddress + bufferMap->getLength() ) ;
}
++index ;
}
return ok ;
}
#endif
bool
IOFWDCLPool :: initWithLink ( IOFireWireLink& link, UInt32 capacity )
{
fLink = & link ;
fCurrentTag = 0 ;
fCurrentSync = 0 ;
fProgram = OSArray::withCapacity( capacity ) ;
if ( ! fProgram )
{
return false ;
}
return true ;
}
void
IOFWDCLPool :: setCurrentTagAndSync ( UInt8 tag, UInt8 sync )
{
fCurrentTag = tag ;
fCurrentSync = sync ;
}
void
IOFWDCLPool :: free ()
{
if ( fProgram )
{
fProgram->release() ;
fProgram = NULL ;
}
super::free() ;
}
IOFWReceiveDCL *
IOFWDCLPool :: appendReceiveDCL (
OSSet * updateSet,
UInt8 headerBytes,
UInt32 rangesCount,
IOVirtualRange ranges[] )
{
IOFWReceiveDCL * dcl = allocReceiveDCL() ;
if ( dcl && !dcl->initWithParams( updateSet, headerBytes, rangesCount, ranges ) )
{
dcl->release() ;
dcl = NULL ;
}
if ( dcl )
{
appendDCL( dcl ) ;
dcl->release() ;
}
return dcl ;
}
IOFWSendDCL *
IOFWDCLPool :: appendSendDCL (
OSSet * updateSet,
UInt32 rangesCount,
IOVirtualRange ranges[] )
{
IOFWSendDCL * dcl = allocSendDCL() ;
if ( dcl && !dcl->initWithParams( updateSet, rangesCount, ranges, fCurrentSync, fCurrentTag ) )
{
dcl->release() ;
dcl = NULL ;
}
if ( dcl )
{
appendDCL( dcl ) ;
dcl->release() ;
}
return dcl ;
}
IOFWSkipCycleDCL *
IOFWDCLPool :: appendSkipCycleDCL ()
{
IOFWSkipCycleDCL * dcl = allocSkipCycleDCL() ;
if ( dcl && !dcl->init() )
{
dcl->release() ;
dcl = NULL ;
}
if ( dcl )
{
appendDCL( dcl ) ;
dcl->release() ;
}
return dcl ;
}
const OSArray *
IOFWDCLPool :: getProgramRef () const
{
fProgram->retain () ;
return fProgram ;
}
void
IOFWDCLPool :: appendDCL( IOFWDCL * dcl )
{
if ( dcl )
{
fProgram->setObject( dcl ) ;
}
}
IOReturn
IOFWDCLPool :: importUserProgram (
IOMemoryDescriptor * userExportDesc,
unsigned bufferRangeCount,
IOVirtualRange bufferRanges[],
IOMemoryMap * bufferMap )
{
InfoLog("+IOFWDCLPool::importUserProgram\n") ;
IOByteCount exportLength = userExportDesc->getLength() ;
if ( exportLength == 0 )
{
DebugLog("export data length == 0\n") ;
return kIOReturnError ;
}
UInt8 * exportData = new UInt8[ exportLength ] ;
if ( !exportData )
{
DebugLog("couldn't allocate export data block\n") ;
return kIOReturnNoMemory ;
}
{
unsigned byteCount = userExportDesc->readBytes( 0, exportData, exportLength ) ;
if ( byteCount < exportLength )
{
return kIOReturnVMError ;
}
}
IOReturn error = kIOReturnSuccess ;
{
UInt8 * exportCursor = exportData ;
InfoLog("import DCLs, pass 1...\n") ;
while( !error && exportCursor < exportData + exportLength )
{
NuDCLSharedData * data = (NuDCLSharedData*)exportCursor ;
exportCursor += ( sizeof( *data ) + 4 ) & ~(size_t)0x3 ;
IOVirtualRange kernRanges[ data->rangeCount ] ;
IOVirtualAddress kernBaseAddress = bufferMap->getVirtualAddress() ;
for( unsigned index=0; index < data->rangeCount; ++index )
{
kernRanges[ index ].address = kernBaseAddress + (IOByteCount)data->ranges[ index ].address ;
kernRanges[ index ].length = data->ranges[ index ].length ;
}
if ( !error )
{
if ( data->update.count )
{
exportCursor += sizeof( UInt32 ) * (UInt32)data->update.count ;
}
switch( data->type )
{
case NuDCLSharedData::kSendType :
{
SendNuDCLSharedData * sendData = ( SendNuDCLSharedData * )exportCursor ;
exportCursor += ( sizeof( *sendData ) + 4 ) & ~(size_t)0x3 ;
if ( !appendSendDCL( NULL, data->rangeCount, kernRanges ) )
{
error = kIOReturnNoMemory ;
}
break ;
}
case NuDCLSharedData::kReceiveType :
{
ReceiveNuDCLSharedData * rcvData = ( ReceiveNuDCLSharedData * )exportCursor ;
exportCursor += ( sizeof( *rcvData ) + 4 ) & ~(size_t)0x3 ;
if ( !appendReceiveDCL( NULL, rcvData->headerBytes, data->rangeCount, kernRanges ) )
{
error = kIOReturnNoMemory ;
}
break ;
}
case NuDCLSharedData::kSkipCycleType :
{
if ( !appendSkipCycleDCL() )
{
error = kIOReturnNoMemory ;
}
break ;
}
default :
ErrorLog("invalid export data\n") ;
error = kIOReturnInternalError ;
break ;
}
}
}
InfoLog("...done error=%x\n", error ) ;
}
if ( !error )
{
InfoLog("import DCLs, pass 2...\n") ;
UInt8 * exportCursor = exportData ;
unsigned dclIndex = 0 ;
while( !error && exportCursor < ( exportData + exportLength ) )
{
IOFWDCL * theDCL = (IOFWDCL*)fProgram->getObject( dclIndex ) ;
IOByteCount dataSize ;
error = theDCL->importUserDCL( exportCursor, dataSize, bufferMap, fProgram ) ;
exportCursor += dataSize ;
++dclIndex ;
}
InfoLog("...done error=%x\n", error ) ;
}
delete exportData ;
return error ;
}
DCLCommand *
IOFWDCLPool::getProgram()
{
return 0 ;
}
OSMetaClassDefineReservedUnused ( IOFWDCLPool, 0);
OSMetaClassDefineReservedUnused ( IOFWDCLPool, 1);
OSMetaClassDefineReservedUnused ( IOFWDCLPool, 2);
OSMetaClassDefineReservedUnused ( IOFWDCLPool, 3);
OSMetaClassDefineReservedUnused ( IOFWDCLPool, 4);
OSMetaClassDefineReservedUnused ( IOFWDCLPool, 5);
OSMetaClassDefineReservedUnused ( IOFWDCLPool, 6);
OSMetaClassDefineReservedUnused ( IOFWDCLPool, 7);