IOFWDCLProgram.cpp [plain text]
#import <IOKit/firewire/IOFWDCLProgram.h>
#import "FWDebugging.h"
OSDefineMetaClass( IODCLProgram, OSObject )
OSDefineAbstractStructors ( IODCLProgram, OSObject )
OSMetaClassDefineReservedUsed ( IODCLProgram, 0 ) ;
OSMetaClassDefineReservedUsed ( IODCLProgram, 1 ) ;
OSMetaClassDefineReservedUsed ( IODCLProgram, 2 ) ;
OSMetaClassDefineReservedUnused ( IODCLProgram, 3 ) ;
OSMetaClassDefineReservedUnused ( IODCLProgram, 4 ) ;
#undef super
#define super OSObject
static bool
getDCLDataBuffer(
const DCLCommand * dcl,
IOVirtualRange & outRange)
{
bool result = false ;
switch( dcl->opcode & ~kFWDCLOpFlagMask)
{
case kDCLSendPacketStartOp:
case kDCLSendPacketOp:
case kDCLReceivePacketStartOp:
case kDCLReceivePacketOp:
outRange.address = (IOVirtualAddress)((DCLTransferPacket*)dcl)->buffer ;
outRange.length = ((DCLTransferPacket*)dcl)->size ;
result = true ;
break ;
case kDCLPtrTimeStampOp:
outRange.address = (IOVirtualAddress)((DCLPtrTimeStamp*)dcl)->timeStampPtr ;
outRange.length = sizeof( *( ((DCLPtrTimeStamp*)dcl)->timeStampPtr) ) ;
result = true ;
break ;
default:
break ;
}
return result ;
}
void
IODCLProgram::generateBufferMap( DCLCommand * program )
{
DebugLog("// *** TEST: IODCLProgram<%p>::generateBufferMap - program = %p\n", this, program );
IOVirtualAddress lowAddress = (IOVirtualAddress)-1 ;
IOVirtualAddress highAddress = 0 ;
for( DCLCommand * dcl = program; dcl != NULL; dcl = dcl->pNextDCLCommand )
{
IOVirtualRange tempRange ;
if ( getDCLDataBuffer( dcl, tempRange ) )
{
lowAddress = MIN( lowAddress, trunc_page( tempRange.address ) ) ;
highAddress = MAX( highAddress, round_page( tempRange.address + tempRange.length ) ) ;
}
}
IOByteCount length = highAddress - lowAddress;
DebugLog("IODCLProgram<%p>::generateBufferMap - lowAddress = 0x%llx, highAddress = 0x%llx, length = 0x%x\n", this, lowAddress, highAddress, (UInt32)length ) ;
if ( lowAddress == 0 )
{
return ;
}
IOMemoryDescriptor * desc = IOMemoryDescriptor::withAddress( (void*)lowAddress, length, kIODirectionInOut ) ;
if( desc )
{
IOReturn tmp_status = desc->prepare();
if( tmp_status != kIOReturnSuccess )
{
desc->release() ;
desc = NULL ;
}
}
else
{
DebugLog("IODCLProgram<%p>::generateBufferMap - ERROR: desc = NULL\n", this ) ;
}
IODMACommand * dma_command = NULL;
if ( desc )
{
IOReturn status = kIOReturnSuccess;
DebugLog("IODCLProgram<%p>::generateBufferMap - created new desc = %p\n", this, desc );
if( status == kIOReturnSuccess )
{
IOMapper * mapper = copyMapper();
DebugLog("IODCLProgram<%p>::generateBufferMap - fDMACommand = withSpecification( mapper = %p, length = %lld )\n", this, mapper, length);
dma_command = IODMACommand::withSpecification( kIODMACommandOutputHost32, 32, length, (IODMACommand::MappingOptions)(IODMACommand::kMapped | IODMACommand::kIterateOnly), length, 0, mapper, NULL );
if( dma_command == NULL )
{
status = kIOReturnError;
}
if( mapper )
{
mapper->release();
mapper = NULL;
}
}
if( status == kIOReturnSuccess )
{
status = dma_command->setMemoryDescriptor( desc );
}
if( status == kIOReturnSuccess )
{
status = dma_command->prepare( 0, length, true );
}
if( status == kIOReturnSuccess )
{
fBufferMem = desc->map() ;
if( fBufferMem == NULL )
{
status = kIOReturnError;
}
DebugLog("IODCLProgram<%p>::generateBufferMap - created new fBufferMem = %p\n", this, fBufferMem );
}
if( status == kIOReturnSuccess )
{
fExpansionData->fDMACommand = dma_command;
}
else
{
DebugLog("IODCLProgram<%p>::generateBufferMap - failed with 0x%08x\n", this, status );
if( dma_command )
{
dma_command->release();
}
}
}
if( desc )
{
desc->release() ;
desc = NULL ;
}
DebugLog("IODCLProgram<%p>::generateBufferMap - fDMACommand = %p\n", this, fExpansionData->fDMACommand);
return;
}
IOReturn
IODCLProgram::virtualToPhysical(
IOVirtualRange ranges[],
unsigned rangeCount,
IOMemoryCursor::IOPhysicalSegment outSegments[],
unsigned & outPhysicalSegmentCount,
unsigned maxSegments )
{
DebugLog("// *** TEST: IODCLProgram<%p>::virtualToPhysical\n", this );
IOReturn status = kIOReturnSuccess;
outPhysicalSegmentCount = 0;
if( rangeCount > 0 )
{
IOVirtualAddress bufferMemBaseAddress = fBufferMem->getVirtualAddress() ;
unsigned rangeIndex = 0;
do
{
IOByteCount transferBytes = 0;
IOVirtualAddress offset = 0;
if( outPhysicalSegmentCount >= maxSegments )
{
DebugLog("IODCLProgram<%p>::virtualToPhysical - ERROR: outPhysicalSegmentCount (%d) >= maxSegments (%d)\n", this, outPhysicalSegmentCount, maxSegments );
status = kIOReturnDMAError;
}
if( status == kIOReturnSuccess )
{
transferBytes = ranges[ rangeIndex ].length;
offset = ranges[ rangeIndex ].address - bufferMemBaseAddress;
if( offset > fBufferMem->getLength() )
{
DebugLog("IODCLProgram<%p>::virtualToPhysical - ERROR: offset (%llu) > fBufferMem->getLength() (%llu)\n", this, offset, fBufferMem->getLength() );
status = kIOReturnDMAError;
}
}
#if 1
IODMACommand::Segment32 segs[ maxSegments ];
UInt32 numSegs = 0;
if( status == kIOReturnSuccess )
{
numSegs = maxSegments;
status = fExpansionData->fDMACommand->gen32IOVMSegments( &offset, segs, &numSegs );
if( status != kIOReturnSuccess )
{
DebugLog("IODCLProgram<%p>::virtualToPhysical - ERROR: gen32IOVMSegments failed with 0x%08x\n", this, status );
}
}
if( status == kIOReturnSuccess )
{
if( numSegs > maxSegments || numSegs == 0 )
{
DebugLog("IODCLProgram<%p>::virtualToPhysical - ERROR: numSegs = %u\n", this, numSegs );
status = kIOReturnNoResources;
}
}
if( status == kIOReturnSuccess )
{
for( unsigned i = 0; i < numSegs; i++ )
{
outSegments[outPhysicalSegmentCount+i].location = segs[i].fIOVMAddr;
outSegments[outPhysicalSegmentCount+i].length = min( segs[i].fLength, transferBytes );
}
outPhysicalSegmentCount += numSegs;
}
#else
while(( transferBytes > 0 ) && ( status == kIOReturnSuccess ))
{
outSegments[ outPhysicalSegmentCount ].location = fBufferMem->getPhysicalSegment( offset, & outSegments[ outPhysicalSegmentCount ].length );
outSegments[ outPhysicalSegmentCount ].length = min( outSegments[ outPhysicalSegmentCount ].length, transferBytes );
transferBytes -= outSegments[ outPhysicalSegmentCount ].length;
offset += outSegments[ outPhysicalSegmentCount ].length;
++outPhysicalSegmentCount;
}
#endif
} while (( ++rangeIndex < rangeCount ) && ( status == kIOReturnSuccess )) ;
}
return status ;
}
bool
IODCLProgram::init ( IOFireWireBus::DCLTaskInfo * info)
{
DebugLog("IODCLProgram<%p>::init - info = %p\n", this, info) ;
if ( ! super::init () )
return false ;
fExpansionData = new ExpansionData ;
if ( !fExpansionData )
{
return false ;
}
fExpansionData->resourceFlags = kFWDefaultIsochResourceFlags ;
bool success = true ;
if ( info )
{
if ( ( !info->unused0 && !info->unused1 && !info->unused2 && !info->unused3 && !info->unused4
&& ! info->unused5 ) && info->auxInfo )
{
DebugLog("IODCLProgram<%p>::init - auxInfo->version = %d\n", this, info->auxInfo->version) ;
switch( info->auxInfo->version )
{
case 0 :
{
fBufferMem = info->auxInfo->u.v0.bufferMemoryMap ;
if ( fBufferMem )
{
fBufferMem->retain() ;
}
break ;
}
case 1 :
case 2 :
{
fBufferMem = info->auxInfo->u.v1.bufferMemoryMap ; if ( fBufferMem )
{
fBufferMem->retain() ;
}
break ;
}
default :
ErrorLog( "unsupported version found in info->auxInfo!\n" ) ;
success = false ;
break ;
} ;
}
}
DebugLog("IODCLProgram<%p>::init - fBufferMem = %p\n", this, fBufferMem);
return success ;
}
void IODCLProgram::free()
{
if ( fExpansionData )
{
if( fExpansionData->fDMACommand )
{
fExpansionData->fDMACommand->complete();
fExpansionData->fDMACommand->release();
fExpansionData->fDMACommand = NULL;
}
delete fExpansionData ;
fExpansionData = NULL ;
}
if ( fBufferMem )
{
fBufferMem->release() ;
fBufferMem = NULL ;
}
OSObject::free();
}
IOReturn IODCLProgram::pause()
{
return kIOReturnSuccess;
}
IOReturn IODCLProgram::resume()
{
return kIOReturnSuccess;
}
void
IODCLProgram::setForceStopProc (
IOFWIsochChannel::ForceStopNotificationProc proc,
void * refCon,
IOFWIsochChannel * channel )
{
DebugLog("IODCLProgram::setForceStopProc\n") ;
}
void
IODCLProgram::setIsochResourceFlags ( IOFWIsochResourceFlags flags )
{
fExpansionData->resourceFlags = flags ;
}
IOFWIsochResourceFlags
IODCLProgram::getIsochResourceFlags () const
{
return fExpansionData->resourceFlags ;
}
IOMemoryMap *
IODCLProgram::getBufferMap() const
{
return fBufferMem ;
}