SegmentOptions segmentOptions =
{
.fStructSize = sizeof(segmentOptions),
- .fNumAddressBits = fNumAddressBits,
+ .fNumAddressBits = (uint8_t)fNumAddressBits,
.fMaxSegmentSize = fMaxSegmentSize,
.fMaxTransferSize = fMaxTransferSize,
.fAlignment = fAlignMask + 1,
fInternalState->fNewMD = true;
mem->retain();
fMemory = mem;
-
- mem->dmaCommandOperation(kIOMDSetDMAActive, this, 0);
+ if (!fMapper) mem->dmaCommandOperation(kIOMDSetDMAActive, this, 0);
if (autoPrepare) {
err = prepare();
if (err) {
IOReturn
IODMACommand::clearMemoryDescriptor(bool autoComplete)
{
- if (fActive && !autoComplete)
- return (kIOReturnNotReady);
+ if (fActive && !autoComplete) return (kIOReturnNotReady);
- if (fMemory) {
- while (fActive)
- complete();
- fMemory->dmaCommandOperation(kIOMDSetDMAInactive, this, 0);
+ if (fMemory)
+ {
+ while (fActive) complete();
+ if (!fMapper) fMemory->dmaCommandOperation(kIOMDSetDMAInactive, this, 0);
fMemory->release();
fMemory = 0;
}
IODMACommandInternal * state = target->reserved;
- if (target->fNumAddressBits && (target->fNumAddressBits < 64) && (state->fLocalMapperAlloc || !target->fMapper))
+ if (target->fNumAddressBits && (target->fNumAddressBits < 64) && (state->fLocalMapperAllocValid || !target->fMapper))
maxPhys = (1ULL << target->fNumAddressBits);
else
maxPhys = 0;
address = segment.fIOVMAddr;
length = segment.fLength;
- assert(address);
assert(length);
if (!state->fMisaligned)
op &= ~kWalkPreflight;
- state->fDoubleBuffer = (state->fMisaligned || (kWalkDoubleBuffer & op));
+ state->fDoubleBuffer = (state->fMisaligned || state->fForceDoubleBuffer);
+ state->fForceDoubleBuffer = false;
if (state->fDoubleBuffer)
state->fCopyPageCount = atop_64(round_page(state->fPreparedLength));
state->fNextRemapPage = NULL;
state->fCopyMD = 0;
state->fLocalMapperAlloc = 0;
+ state->fLocalMapperAllocValid = false;
state->fLocalMapperAllocLength = 0;
state->fLocalMapper = (fMapper && (fMapper != IOMapper::gSystem));
mapArgs.fMapSpec.numAddressBits = fNumAddressBits ? fNumAddressBits : 64;
mapArgs.fLength = state->fPreparedLength;
const IOMemoryDescriptor * md = state->fCopyMD;
- if (md) { mapArgs.fOffset = 0; }
- else
+ if (md) { mapArgs.fOffset = 0; } else
{
md = fMemory;
mapArgs.fOffset = state->fPreparedOffset;
if (kIOReturnSuccess == ret)
{
state->fLocalMapperAlloc = mapArgs.fAlloc;
+ state->fLocalMapperAllocValid = true;
state->fLocalMapperAllocLength = mapArgs.fAllocLength;
state->fMapContig = mapArgs.fMapContig;
}
{
IODMACommandInternal * state = fInternalState;
IOReturn ret = kIOReturnSuccess;
+ IOMemoryDescriptor * copyMD;
if (fActive < 1)
return kIOReturnNotReady;
if (!--fActive)
{
+ copyMD = state->fCopyMD;
+ if (copyMD) copyMD->retain();
+
if (IS_NONCOHERENT(fMappingOptions) && invalidateCache)
{
- if (state->fCopyMD)
+ if (copyMD)
{
- state->fCopyMD->performOperation(kIOMemoryIncoherentIOFlush, 0, state->fPreparedLength);
+ copyMD->performOperation(kIOMemoryIncoherentIOFlush, 0, state->fPreparedLength);
}
else
{
op |= kWalkSyncIn;
ret = walkAll(op);
}
- if (state->fLocalMapperAlloc)
+
+ if (state->fLocalMapperAllocValid)
{
- if (state->fLocalMapperAllocLength)
+ IOMDDMAMapArgs mapArgs;
+ bzero(&mapArgs, sizeof(mapArgs));
+ mapArgs.fMapper = fMapper;
+ mapArgs.fCommand = this;
+ mapArgs.fAlloc = state->fLocalMapperAlloc;
+ mapArgs.fAllocLength = state->fLocalMapperAllocLength;
+ const IOMemoryDescriptor * md = copyMD;
+ if (md) { mapArgs.fOffset = 0; }
+ else
{
- fMapper->iovmUnmapMemory(getIOMemoryDescriptor(), this,
- state->fLocalMapperAlloc, state->fLocalMapperAllocLength);
+ md = fMemory;
+ mapArgs.fOffset = state->fPreparedOffset;
}
+
+ ret = md->dmaCommandOperation(kIOMDDMAUnmap, &mapArgs, sizeof(mapArgs));
+
state->fLocalMapperAlloc = 0;
+ state->fLocalMapperAllocValid = false;
state->fLocalMapperAllocLength = 0;
}
-
+ if (copyMD) copyMD->release();
state->fPrepared = false;
}
op = 0;
if (kForceDoubleBuffer & options)
{
- if (state->fDoubleBuffer)
- return kIOReturnSuccess;
- if (state->fCursor)
- state->fCursor = false;
- else
- ret = walkAll(kWalkComplete);
+ if (state->fDoubleBuffer) return kIOReturnSuccess;
+ ret = complete(false /* invalidateCache */, true /* synchronize */);
+ state->fCursor = false;
+ state->fForceDoubleBuffer = true;
+ ret = prepare(state->fPreparedOffset, state->fPreparedLength, false /* flushCache */, true /* synchronize */);
- op |= kWalkPrepare | kWalkPreflight | kWalkDoubleBuffer;
+ return (ret);
}
else if (state->fCursor)
return kIOReturnSuccess;
return kIOReturnOverrun;
if ((offset == internalState->fPreparedOffset) || (offset != state->fOffset) || internalState->fNewMD) {
- state->fOffset = 0;
- state->fIOVMAddr = 0;
- internalState->fNextRemapPage = NULL;
- internalState->fNewMD = false;
- state->fMapped = (0 != fMapper);
- mdOp = kIOMDFirstSegment;
+ state->fOffset = 0;
+ internalState->fIOVMAddrValid = state->fIOVMAddr = 0;
+ internalState->fNextRemapPage = NULL;
+ internalState->fNewMD = false;
+ state->fMapped = (0 != fMapper);
+ mdOp = kIOMDFirstSegment;
};
UInt32 segIndex = 0;
UInt32 numSegments = *numSegmentsP;
Segment64 curSeg = { 0, 0 };
+ bool curSegValid = false;
addr64_t maxPhys;
if (fNumAddressBits && (fNumAddressBits < 64))
maxPhys = 0;
maxPhys--;
- while (state->fIOVMAddr || (state->fOffset < memLength))
+ while (internalState->fIOVMAddrValid || (state->fOffset < memLength))
{
// state = next seg
- if (!state->fIOVMAddr) {
+ if (!internalState->fIOVMAddrValid) {
IOReturn rtn;
state->fOffset = offset;
state->fLength = memLength - offset;
- if (internalState->fMapContig && internalState->fLocalMapperAlloc)
+ if (internalState->fMapContig && internalState->fLocalMapperAllocValid)
{
- state->fIOVMAddr = internalState->fLocalMapperAlloc + offset;
+ state->fIOVMAddr = internalState->fLocalMapperAlloc + offset - internalState->fPreparedOffset;
rtn = kIOReturnSuccess;
#if 0
{
if (rtn == kIOReturnSuccess)
{
- assert(state->fIOVMAddr);
+ internalState->fIOVMAddrValid = true;
assert(state->fLength);
- if ((curSeg.fIOVMAddr + curSeg.fLength) == state->fIOVMAddr) {
+ if (curSegValid && ((curSeg.fIOVMAddr + curSeg.fLength) == state->fIOVMAddr)) {
UInt64 length = state->fLength;
offset += length;
curSeg.fLength += length;
- state->fIOVMAddr = 0;
+ internalState->fIOVMAddrValid = state->fIOVMAddr = 0;
}
}
else if (rtn == kIOReturnOverrun)
- state->fIOVMAddr = state->fLength = 0; // At end
+ internalState->fIOVMAddrValid = state->fIOVMAddr = state->fLength = 0; // At end
else
return rtn;
}
// seg = state, offset = end of seg
- if (!curSeg.fIOVMAddr)
+ if (!curSegValid)
{
- UInt64 length = state->fLength;
- offset += length;
- curSeg.fIOVMAddr = state->fIOVMAddr;
- curSeg.fLength = length;
- state->fIOVMAddr = 0;
+ UInt64 length = state->fLength;
+ offset += length;
+ curSeg.fIOVMAddr = state->fIOVMAddr;
+ curSeg.fLength = length;
+ curSegValid = true;
+ internalState->fIOVMAddrValid = state->fIOVMAddr = 0;
}
- if (!state->fIOVMAddr)
+ if (!internalState->fIOVMAddrValid)
{
// maxPhys
if ((kWalkClient & op) && (curSeg.fIOVMAddr + curSeg.fLength - 1) > maxPhys)
{
if (internalState->fCursor)
{
- curSeg.fIOVMAddr = 0;
+ curSegValid = curSeg.fIOVMAddr = 0;
ret = kIOReturnMessageTooLarge;
break;
}
DEBG("trunc %qx, %qx-> %qx\n", curSeg.fIOVMAddr, curSeg.fLength, newLength);
remain = curSeg.fLength - newLength;
state->fIOVMAddr = newLength + curSeg.fIOVMAddr;
+ internalState->fIOVMAddrValid = true;
curSeg.fLength = newLength;
state->fLength = remain;
offset -= remain;
curSeg.fIOVMAddr = ptoa_64(vm_page_get_phys_page(remap))
+ (addr & PAGE_MASK);
+ curSegValid = true;
internalState->fNextRemapPage = vm_page_get_next(remap);
newLength = PAGE_SIZE - (addr & PAGE_MASK);
{
remain = curSeg.fLength - newLength;
state->fIOVMAddr = addr + newLength;
+ internalState->fIOVMAddrValid = true;
curSeg.fLength = newLength;
state->fLength = remain;
offset -= remain;
leftover += curSeg.fLength - fMaxSegmentSize;
curSeg.fLength = fMaxSegmentSize;
state->fIOVMAddr = curSeg.fLength + curSeg.fIOVMAddr;
+ internalState->fIOVMAddrValid = true;
}
// alignment current length
leftover += reduce;
curSeg.fLength -= reduce;
state->fIOVMAddr = curSeg.fLength + curSeg.fIOVMAddr;
+ internalState->fIOVMAddrValid = true;
}
// alignment next address
leftover += reduce;
curSeg.fLength -= reduce;
state->fIOVMAddr = curSeg.fLength + curSeg.fIOVMAddr;
+ internalState->fIOVMAddrValid = true;
}
if (leftover)
if (misaligned)
{
if (misaligned) DEBG("cursor misaligned %qx:%qx\n", curSeg.fIOVMAddr, curSeg.fLength);
- curSeg.fIOVMAddr = 0;
+ curSegValid = curSeg.fIOVMAddr = 0;
ret = kIOReturnNotAligned;
break;
}
{
curSeg.fLength -= (offset - memLength);
offset = memLength;
- state->fIOVMAddr = state->fLength = 0; // At end
+ internalState->fIOVMAddrValid = state->fIOVMAddr = state->fLength = 0; // At end
break;
}
}
- if (state->fIOVMAddr) {
+ if (internalState->fIOVMAddrValid) {
if ((segIndex + 1 == numSegments))
break;
ret = (*outSegFunc)(reference, this, curSeg, segmentsP, segIndex++);
- curSeg.fIOVMAddr = 0;
+ curSegValid = curSeg.fIOVMAddr = 0;
if (kIOReturnSuccess != ret)
break;
}
}
- if (curSeg.fIOVMAddr) {
+ if (curSegValid) {
ret = (*outSegFunc)(reference, this, curSeg, segmentsP, segIndex++);
}
if (target->fNumAddressBits && (target->fNumAddressBits < 64)
&& ((segment.fIOVMAddr + segment.fLength - 1) >> target->fNumAddressBits)
- && (target->reserved->fLocalMapperAlloc || !target->fMapper))
+ && (target->reserved->fLocalMapperAllocValid || !target->fMapper))
{
DEBG("kIOReturnMessageTooLarge(fNumAddressBits) %qx, %qx\n", segment.fIOVMAddr, segment.fLength);
ret = kIOReturnMessageTooLarge;