IOMultiMemoryDescriptor.cpp [plain text]
#include <IOKit/IOLib.h>
#include <IOKit/IOMultiMemoryDescriptor.h>
#define super IOMemoryDescriptor
OSDefineMetaClassAndStructors(IOMultiMemoryDescriptor, IOMemoryDescriptor)
bool IOMultiMemoryDescriptor::initWithAddress(
void * ,
IOByteCount ,
IODirection )
{
return false;
}
bool IOMultiMemoryDescriptor::initWithAddress(
vm_address_t ,
IOByteCount ,
IODirection ,
task_t )
{
return false;
}
bool IOMultiMemoryDescriptor::initWithPhysicalAddress(
IOPhysicalAddress ,
IOByteCount ,
IODirection )
{
return false;
}
bool IOMultiMemoryDescriptor::initWithPhysicalRanges(
IOPhysicalRange * ,
UInt32 ,
IODirection ,
bool )
{
return false;
}
bool IOMultiMemoryDescriptor::initWithRanges(
IOVirtualRange * ,
UInt32 ,
IODirection ,
task_t ,
bool )
{
return false;
}
IOMultiMemoryDescriptor * IOMultiMemoryDescriptor::withDescriptors(
IOMemoryDescriptor ** descriptors,
UInt32 withCount,
IODirection withDirection,
bool asReference )
{
IOMultiMemoryDescriptor * me = new IOMultiMemoryDescriptor;
if ( me && me->initWithDescriptors(
descriptors,
withCount,
withDirection,
asReference ) == false )
{
me->release();
me = 0;
}
return me;
}
bool IOMultiMemoryDescriptor::initWithDescriptors(
IOMemoryDescriptor ** descriptors,
UInt32 withCount,
IODirection withDirection,
bool asReference )
{
assert(descriptors);
assert(withCount);
if ( _descriptors )
{
for ( unsigned index = 0; index < _descriptorsCount; index++ )
_descriptors[index]->release();
if ( _descriptorsIsAllocated )
IODelete(_descriptors, IOMemoryDescriptor *, _descriptorsCount);
} else {
if ( super::init() == false ) return false;
}
_descriptors = 0;
_descriptorsCount = withCount;
_descriptorsIsAllocated = asReference ? false : true;
_direction = withDirection;
_length = 0;
_mappings = 0;
_tag = 0;
if ( asReference )
{
_descriptors = descriptors;
}
else
{
_descriptors = IONew(IOMemoryDescriptor *, withCount);
if ( _descriptors == 0 ) return false;
bcopy( descriptors,
_descriptors,
withCount * sizeof(IOMemoryDescriptor *) );
}
for ( unsigned index = 0; index < withCount; index++ )
{
descriptors[index]->retain();
_length += descriptors[index]->getLength();
if ( _tag == 0 ) _tag = descriptors[index]->getTag();
assert(descriptors[index]->getDirection() == withDirection);
}
return true;
}
void IOMultiMemoryDescriptor::free()
{
if ( _descriptors )
{
for ( unsigned index = 0; index < _descriptorsCount; index++ )
_descriptors[index]->release();
if ( _descriptorsIsAllocated )
IODelete(_descriptors, IOMemoryDescriptor *, _descriptorsCount);
}
super::free();
}
IOReturn IOMultiMemoryDescriptor::prepare(IODirection forDirection)
{
unsigned index;
IOReturn status = kIOReturnInternalError;
IOReturn statusUndo;
if ( forDirection == kIODirectionNone )
{
forDirection = _direction;
}
for ( index = 0; index < _descriptorsCount; index++ )
{
status = _descriptors[index]->prepare(forDirection);
if ( status != kIOReturnSuccess ) break;
}
if ( status != kIOReturnSuccess )
{
for ( unsigned indexUndo = 0; indexUndo <= index; indexUndo++ )
{
statusUndo = _descriptors[index]->complete(forDirection);
assert(statusUndo == kIOReturnSuccess);
}
}
return status;
}
IOReturn IOMultiMemoryDescriptor::complete(IODirection forDirection)
{
IOReturn status;
IOReturn statusFinal = kIOReturnSuccess;
if ( forDirection == kIODirectionNone )
{
forDirection = _direction;
}
for ( unsigned index = 0; index < _descriptorsCount; index++ )
{
status = _descriptors[index]->complete(forDirection);
if ( status != kIOReturnSuccess ) statusFinal = status;
assert(status == kIOReturnSuccess);
}
return statusFinal;
}
IOPhysicalAddress IOMultiMemoryDescriptor::getPhysicalSegment(
IOByteCount offset,
IOByteCount * length )
{
assert(offset <= _length);
for ( unsigned index = 0; index < _descriptorsCount; index++ )
{
if ( offset < _descriptors[index]->getLength() )
{
return _descriptors[index]->getPhysicalSegment(offset, length);
}
offset -= _descriptors[index]->getLength();
}
if ( length ) *length = 0;
return 0;
}
IOPhysicalAddress IOMultiMemoryDescriptor::getSourceSegment(
IOByteCount offset,
IOByteCount * length )
{
assert(offset <= _length);
for ( unsigned index = 0; index < _descriptorsCount; index++ )
{
if ( offset < _descriptors[index]->getLength() )
{
return _descriptors[index]->getSourceSegment(offset, length);
}
offset -= _descriptors[index]->getLength();
}
if ( length ) *length = 0;
return 0;
}
void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount ,
IOByteCount * )
{
return 0;
}
IOByteCount IOMultiMemoryDescriptor::readBytes( IOByteCount offset,
void * bytes,
IOByteCount withLength )
{
IOByteCount bytesCopied = 0;
unsigned index;
for ( index = 0; index < _descriptorsCount; index++ )
{
if ( offset < _descriptors[index]->getLength() ) break;
offset -= _descriptors[index]->getLength();
}
for ( ; index < _descriptorsCount && withLength; index++)
{
IOByteCount copy = min(_descriptors[index]->getLength(), withLength);
IOByteCount copied = _descriptors[index]->readBytes(offset,bytes,copy);
bytesCopied += copied;
if ( copied != copy ) break;
bytes = ((UInt8 *) bytes) + copied;
withLength -= copied;
offset = 0;
}
return bytesCopied;
}
IOByteCount IOMultiMemoryDescriptor::writeBytes( IOByteCount offset,
const void * bytes,
IOByteCount withLength )
{
IOByteCount bytesCopied = 0;
unsigned index;
for ( index = 0; index < _descriptorsCount; index++ )
{
if ( offset < _descriptors[index]->getLength() ) break;
offset -= _descriptors[index]->getLength();
}
for ( ; index < _descriptorsCount && withLength; index++)
{
IOByteCount copy = min(_descriptors[index]->getLength(), withLength);
IOByteCount copied = _descriptors[index]->writeBytes(offset,bytes,copy);
bytesCopied += copied;
if ( copied != copy ) break;
bytes = ((UInt8 *) bytes) + copied;
withLength -= copied;
offset = 0;
}
return bytesCopied;
}