IOFWDCLProgram.cpp [plain text]
#import <IOKit/firewire/IOFWDCLProgram.h>
#import "FWDebugging.h"
OSDefineMetaClass( IODCLProgram, OSObject )
OSDefineAbstractStructors ( IODCLProgram, OSObject )
OSMetaClassDefineReservedUsed ( IODCLProgram, 0 ) ;
OSMetaClassDefineReservedUsed ( IODCLProgram, 1 ) ;
OSMetaClassDefineReservedUnused ( 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 )
{
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 ) ) ;
}
}
DebugLog("IODCLProgram::generateBufferMap lowAddress=%x highAddress=%x\n", lowAddress, highAddress ) ;
if ( lowAddress == 0 )
{
return ;
}
IOMemoryDescriptor * desc = IOMemoryDescriptor::withAddress( (void*)lowAddress, highAddress - lowAddress, kIODirectionOutIn ) ;
DebugLogCond(!desc, "couldn't make memory descriptor!\n") ;
if ( desc && kIOReturnSuccess != desc->prepare() )
{
ErrorLog("couldn't prepare memory descriptor\n") ;
desc->release() ;
desc = NULL ;
}
if ( desc )
{
fBufferMem = desc->map() ;
desc->release() ;
DebugLogCond(!fBufferMem, "couldn't make mapping\n") ;
}
}
IOReturn
IODCLProgram::virtualToPhysical(
IOVirtualRange ranges[],
unsigned rangeCount,
IOMemoryCursor::IOPhysicalSegment outSegments[],
unsigned & outPhysicalSegmentCount,
unsigned maxSegments )
{
outPhysicalSegmentCount = 0 ;
if ( rangeCount == 0 )
return kIOReturnSuccess ;
IOVirtualAddress bufferMemBaseAddress = fBufferMem->getVirtualAddress() ;
unsigned rangeIndex=0;
do
{
if ( outPhysicalSegmentCount >= maxSegments )
return kIOReturnDMAError ;
IOByteCount transferBytes = ranges[ rangeIndex ].length ;
IOVirtualAddress offset = ranges[ rangeIndex ].address - bufferMemBaseAddress ;
while( transferBytes > 0 )
{
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 ;
}
} while ( ++rangeIndex < rangeCount ) ;
return kIOReturnSuccess ;
}
bool
IODCLProgram::init ( IOFireWireBus::DCLTaskInfo * 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 )
{
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 ;
} ;
}
}
return success ;
}
void IODCLProgram::free()
{
if ( fExpansionData )
{
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 ;
}