IOFWPhysicalAddressSpace.cpp [plain text]
#include <IOKit/firewire/IOFWAddressSpace.h>
#include "FWDebugging.h"
OSDefineMetaClassAndStructors(IOFWPhysicalAddressSpaceAux, IOFWAddressSpaceAux);
OSMetaClassDefineReservedUnused(IOFWPhysicalAddressSpaceAux, 0);
OSMetaClassDefineReservedUnused(IOFWPhysicalAddressSpaceAux, 1);
OSMetaClassDefineReservedUnused(IOFWPhysicalAddressSpaceAux, 2);
OSMetaClassDefineReservedUnused(IOFWPhysicalAddressSpaceAux, 3);
OSMetaClassDefineReservedUnused(IOFWPhysicalAddressSpaceAux, 4);
OSMetaClassDefineReservedUnused(IOFWPhysicalAddressSpaceAux, 5);
OSMetaClassDefineReservedUnused(IOFWPhysicalAddressSpaceAux, 6);
OSMetaClassDefineReservedUnused(IOFWPhysicalAddressSpaceAux, 7);
OSMetaClassDefineReservedUnused(IOFWPhysicalAddressSpaceAux, 8);
OSMetaClassDefineReservedUnused(IOFWPhysicalAddressSpaceAux, 9);
#pragma mark -
OSDefineMetaClassAndStructors(IOFWPhysicalAddressSpace, IOFWAddressSpace)
bool IOFWPhysicalAddressSpace::initWithDesc(IOFireWireBus *control,
IOMemoryDescriptor *mem)
{
if(!IOFWAddressSpace::init(control))
return false;
fMem = mem;
fMem->retain();
fLen = mem->getLength();
return true;
}
IOFWAddressSpaceAux * IOFWPhysicalAddressSpace::createAuxiliary( void )
{
IOFWPhysicalAddressSpaceAux * auxiliary;
auxiliary = new IOFWPhysicalAddressSpaceAux;
if( auxiliary != NULL && !auxiliary->init(this) )
{
auxiliary->release();
auxiliary = NULL;
}
return auxiliary;
}
void IOFWPhysicalAddressSpace::free()
{
if(fMem)
fMem->release();
IOFWAddressSpace::free();
}
UInt32 IOFWPhysicalAddressSpace::doRead(UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 len,
IOMemoryDescriptor **buf, IOByteCount * offset, IOFWRequestRefCon refcon)
{
UInt32 res = kFWResponseAddressError;
vm_size_t pos;
IOPhysicalAddress phys;
if( !isTrustedNode( nodeID ) )
return kFWResponseAddressError;
if(addr.addressHi != 0)
return kFWResponseAddressError;
pos = 0;
while(pos < fLen)
{
bool found = false;
IOPhysicalLength lengthOfSegment;
phys = fMem->getPhysicalSegment(pos, &lengthOfSegment);
if( (addr.addressLo >= phys) && (addr.addressLo < (phys+lengthOfSegment)) )
{
UInt32 union_length = (lengthOfSegment - (addr.addressLo - phys));
if( len <= union_length )
{
found = true;
}
else
{
IOPhysicalAddress contiguous_address = (phys + lengthOfSegment);
vm_size_t contiguous_pos = (pos + lengthOfSegment);
UInt32 contiguous_length = len - union_length;
IOPhysicalAddress contig_phys;
while( contiguous_pos < fLen )
{
contig_phys = fMem->getPhysicalSegment( contiguous_pos, &lengthOfSegment );
if( contiguous_address != contig_phys )
{
break;
}
if( contiguous_length <= lengthOfSegment )
{
found = true;
break;
}
contiguous_length -= lengthOfSegment;
contiguous_pos += lengthOfSegment;
contiguous_address += lengthOfSegment;
}
}
}
if( found )
{
*offset = (pos + addr.addressLo - phys);
*buf = fMem;
res = kFWResponseComplete;
break;
}
pos += lengthOfSegment;
}
return res;
}
UInt32 IOFWPhysicalAddressSpace::doWrite(UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 len,
const void *buf, IOFWRequestRefCon refcon)
{
UInt32 res = kFWResponseAddressError;
vm_size_t pos;
IOPhysicalAddress phys;
if( !isTrustedNode( nodeID ) )
return kFWResponseAddressError;
if(addr.addressHi != 0)
return kFWResponseAddressError;
pos = 0;
while(pos < fLen)
{
bool found = false;
IOPhysicalLength lengthOfSegment;
phys = fMem->getPhysicalSegment(pos, &lengthOfSegment);
if( (addr.addressLo >= phys) && (addr.addressLo < (phys+lengthOfSegment)) )
{
UInt32 union_length = (lengthOfSegment - (addr.addressLo - phys));
if( len <= union_length )
{
found = true;
}
else
{
IOPhysicalAddress contiguous_address = (phys + lengthOfSegment);
vm_size_t contiguous_pos = (pos + lengthOfSegment);
UInt32 contiguous_length = len - union_length;
IOPhysicalAddress contig_phys;
while( contiguous_pos < fLen )
{
contig_phys = fMem->getPhysicalSegment( contiguous_pos, &lengthOfSegment );
if( contiguous_address != contig_phys )
{
break;
}
if( contiguous_length <= lengthOfSegment )
{
found = true;
break;
}
contiguous_length -= lengthOfSegment;
contiguous_pos += lengthOfSegment;
contiguous_address += lengthOfSegment;
}
}
}
if( found )
{
fMem->writeBytes( pos + (addr.addressLo - phys), buf, len);
res = kFWResponseComplete;
break;
}
pos += lengthOfSegment;
}
return res;
}