IOMemoryCursor.cpp [plain text]
#define IOKIT_ENABLE_SHARED_PTR
#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOMemoryCursor.h>
#include <IOKit/IOMemoryDescriptor.h>
#include <libkern/OSByteOrder.h>
#undef super
#define super OSObject
OSDefineMetaClassAndStructors(IOMemoryCursor, OSObject)
OSSharedPtr<IOMemoryCursor>
IOMemoryCursor::withSpecification(SegmentFunction inSegFunc,
IOPhysicalLength inMaxSegmentSize,
IOPhysicalLength inMaxTransferSize,
IOPhysicalLength inAlignment)
{
OSSharedPtr<IOMemoryCursor> me = OSMakeShared<IOMemoryCursor>();
if (me && !me->initWithSpecification(inSegFunc,
inMaxSegmentSize,
inMaxTransferSize,
inAlignment)) {
return nullptr;
}
return me;
}
bool
IOMemoryCursor::initWithSpecification(SegmentFunction inSegFunc,
IOPhysicalLength inMaxSegmentSize,
IOPhysicalLength inMaxTransferSize,
IOPhysicalLength inAlignment)
{
#if 1
static UInt sMaxDBDMASegment;
if (!sMaxDBDMASegment) {
sMaxDBDMASegment = (UInt) - 1;
if (PE_parse_boot_argn("mseg", &sMaxDBDMASegment, sizeof(sMaxDBDMASegment))) {
IOLog("Setting MaxDBDMASegment to %d\n", sMaxDBDMASegment);
}
}
if (inMaxSegmentSize > sMaxDBDMASegment) {
inMaxSegmentSize = sMaxDBDMASegment;
}
#endif
if (!super::init()) {
return false;
}
if (!inSegFunc) {
return false;
}
if (inMaxTransferSize > UINT_MAX) {
return false;
}
outSeg = inSegFunc;
maxSegmentSize = inMaxSegmentSize;
if (inMaxTransferSize) {
maxTransferSize = inMaxTransferSize;
} else {
maxTransferSize = (IOPhysicalLength) - 1;
}
alignMask = inAlignment - 1;
assert(alignMask == 0);
return true;
}
UInt32
IOMemoryCursor::genPhysicalSegments(IOMemoryDescriptor *inDescriptor,
IOByteCount fromPosition,
void * inSegments,
UInt32 inMaxSegments,
UInt32 inMaxTransferSize,
IOByteCount *outTransferSize)
{
if (!inDescriptor) {
return 0;
}
if (!inMaxSegments) {
return 0;
}
if (!inMaxTransferSize) {
inMaxTransferSize = (typeof(inMaxTransferSize))maxTransferSize;
}
PhysicalSegment curSeg = { 0, 0 };
UInt curSegIndex = 0;
UInt curTransferSize = 0;
IOByteCount inDescriptorLength = inDescriptor->getLength();
PhysicalSegment seg = { 0, 0 };
while ((seg.location) || (fromPosition < inDescriptorLength)) {
if (!seg.location) {
seg.location = inDescriptor->getPhysicalSegment(
fromPosition, (IOByteCount*)&seg.length);
assert(seg.location);
assert(seg.length);
fromPosition += seg.length;
}
if (!curSeg.location) {
curTransferSize += seg.length;
curSeg = seg;
seg.location = 0;
} else if ((curSeg.location + curSeg.length == seg.location)) {
curTransferSize += seg.length;
curSeg.length += seg.length;
seg.location = 0;
}
if (!seg.location) {
if ((curSeg.length > maxSegmentSize)) {
seg.location = curSeg.location + maxSegmentSize;
seg.length = curSeg.length - maxSegmentSize;
curTransferSize -= seg.length;
curSeg.length -= seg.length;
}
if ((curTransferSize >= inMaxTransferSize)) {
curSeg.length -= curTransferSize - inMaxTransferSize;
curTransferSize = inMaxTransferSize;
break;
}
}
if (seg.location) {
if ((curSegIndex + 1 == inMaxSegments)) {
break;
}
(*outSeg)(curSeg, inSegments, curSegIndex++);
curSeg.location = 0;
}
}
if (curSeg.location) {
(*outSeg)(curSeg, inSegments, curSegIndex++);
}
if (outTransferSize) {
*outTransferSize = curTransferSize;
}
return curSegIndex;
}
#undef super
#define super IOMemoryCursor
OSDefineMetaClassAndStructors(IONaturalMemoryCursor, IOMemoryCursor)
void
IONaturalMemoryCursor::outputSegment(PhysicalSegment segment,
void * outSegments,
UInt32 outSegmentIndex)
{
((PhysicalSegment *) outSegments)[outSegmentIndex] = segment;
}
OSSharedPtr<IONaturalMemoryCursor>
IONaturalMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
IOPhysicalLength inMaxTransferSize,
IOPhysicalLength inAlignment)
{
OSSharedPtr<IONaturalMemoryCursor> me = OSMakeShared<IONaturalMemoryCursor>();
if (me && !me->initWithSpecification(inMaxSegmentSize,
inMaxTransferSize,
inAlignment)) {
return nullptr;
}
return me;
}
bool
IONaturalMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
IOPhysicalLength inMaxTransferSize,
IOPhysicalLength inAlignment)
{
return super::initWithSpecification(&IONaturalMemoryCursor::outputSegment,
inMaxSegmentSize,
inMaxTransferSize,
inAlignment);
}
#undef super
#define super IOMemoryCursor
OSDefineMetaClassAndStructors(IOBigMemoryCursor, IOMemoryCursor)
void
IOBigMemoryCursor::outputSegment(PhysicalSegment inSegment,
void * inSegments,
UInt32 inSegmentIndex)
{
IOPhysicalAddress * segment;
segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
#if IOPhysSize == 64
OSWriteBigInt64(segment, 0, inSegment.location);
OSWriteBigInt64(segment, sizeof(IOPhysicalAddress), inSegment.length);
#else
OSWriteBigInt(segment, 0, inSegment.location);
OSWriteBigInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
#endif
}
OSSharedPtr<IOBigMemoryCursor>
IOBigMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
IOPhysicalLength inMaxTransferSize,
IOPhysicalLength inAlignment)
{
OSSharedPtr<IOBigMemoryCursor> me = OSMakeShared<IOBigMemoryCursor>();
if (me && !me->initWithSpecification(inMaxSegmentSize,
inMaxTransferSize,
inAlignment)) {
return nullptr;
}
return me;
}
bool
IOBigMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
IOPhysicalLength inMaxTransferSize,
IOPhysicalLength inAlignment)
{
return super::initWithSpecification(&IOBigMemoryCursor::outputSegment,
inMaxSegmentSize,
inMaxTransferSize,
inAlignment);
}
#undef super
#define super IOMemoryCursor
OSDefineMetaClassAndStructors(IOLittleMemoryCursor, IOMemoryCursor)
void
IOLittleMemoryCursor::outputSegment(PhysicalSegment inSegment,
void * inSegments,
UInt32 inSegmentIndex)
{
IOPhysicalAddress * segment;
segment = &((PhysicalSegment *) inSegments)[inSegmentIndex].location;
#if IOPhysSize == 64
OSWriteLittleInt64(segment, 0, inSegment.location);
OSWriteLittleInt64(segment, sizeof(IOPhysicalAddress), inSegment.length);
#else
OSWriteLittleInt(segment, 0, inSegment.location);
OSWriteLittleInt(segment, sizeof(IOPhysicalAddress), inSegment.length);
#endif
}
OSSharedPtr<IOLittleMemoryCursor>
IOLittleMemoryCursor::withSpecification(IOPhysicalLength inMaxSegmentSize,
IOPhysicalLength inMaxTransferSize,
IOPhysicalLength inAlignment)
{
OSSharedPtr<IOLittleMemoryCursor> me = OSMakeShared<IOLittleMemoryCursor>();
if (me && !me->initWithSpecification(inMaxSegmentSize,
inMaxTransferSize,
inAlignment)) {
return nullptr;
}
return me;
}
bool
IOLittleMemoryCursor::initWithSpecification(IOPhysicalLength inMaxSegmentSize,
IOPhysicalLength inMaxTransferSize,
IOPhysicalLength inAlignment)
{
return super::initWithSpecification(&IOLittleMemoryCursor::outputSegment,
inMaxSegmentSize,
inMaxTransferSize,
inAlignment);
}