IOFWRingBufferQ.cpp [plain text]
#import "IOFWRingBufferQ.h"
#import "FWDebugging.h"
#import <IOKit/IOTypes.h>
#define super OSObject
OSDefineMetaClassAndStructors( IOFWRingBufferQ, OSObject ) ;
IOFWRingBufferQ * IOFWRingBufferQ::withAddressRange( mach_vm_address_t address, mach_vm_size_t length, IOOptionBits options, task_t task)
{
DebugLog("IOFWRingBufferQ::withAddressRange\n");
IOFWRingBufferQ * that = OSTypeAlloc( IOFWRingBufferQ );
if ( that )
{
if ( that->initQ( address, length, options, task ) )
return that;
DebugLog("IOFWRingBufferQ::withAddressRange failed initQ\n");
that->release();
}
return 0;
}
bool IOFWRingBufferQ::initQ( mach_vm_address_t address, mach_vm_size_t length, IOOptionBits options, task_t task )
{
DebugLog("IOFWRingBufferQ::initQ\n");
fMemDescriptor = IOMemoryDescriptor::withAddressRange( address, length, options, task );
if ( !fMemDescriptor )
return false;
if ( fMemDescriptor->prepare( (IODirection)(options & kIOMemoryDirectionMask) ) != kIOReturnSuccess )
return false;
fMemDescriptorPrepared = true;
fFrontOffset = NULL;
fQueueLength = 0;
fBufferSize = fMemDescriptor->getLength();
return true;
}
void IOFWRingBufferQ::free()
{
if ( fMemDescriptorPrepared )
fMemDescriptor->complete();
if ( fMemDescriptor )
fMemDescriptor->release();
super::free();
}
bool IOFWRingBufferQ::isEmpty( void )
{
return (fQueueLength == 0);
}
bool IOFWRingBufferQ::dequeueBytes( IOByteCount size )
{
return dequeueBytesWithCopy(NULL, size);
}
bool IOFWRingBufferQ::dequeueBytesWithCopy( void * copy, IOByteCount size )
{
bool success = true;
IOByteCount paddingBytes = 0;
if ( copy )
{
if ( front(copy, size, &paddingBytes) )
{
fFrontOffset = ( fFrontOffset + paddingBytes + size ) % fBufferSize; fQueueLength = fQueueLength - paddingBytes - size; }
else
success = false;
}
else
{
IOByteCount theRealFrontOffset = frontEntryOffset( size, &paddingBytes ); fFrontOffset = theRealFrontOffset + size; fQueueLength = fQueueLength - paddingBytes - size;
}
DebugLog("<<< IOFWRingBufferQ::dequeueBytesWithCopy BSize: %u Length: %u Front: %u Size: %u Copy: %p\n", fBufferSize, fQueueLength, fFrontOffset, size, copy);
return success;
}
IOByteCount IOFWRingBufferQ::readBytes(IOByteCount offset, void * bytes, IOByteCount withLength)
{
return fMemDescriptor->readBytes( offset, bytes, withLength );
}
bool IOFWRingBufferQ::enqueueBytes( void * bytes, IOByteCount size )
{
bool success = true;
IOByteCount offset = 0;
IOByteCount paddingBytes = 0;
if ( success = willFitAtEnd(size, &offset, &paddingBytes) )
{
if ( bytes )
{
fQueueLength = fQueueLength + size + paddingBytes; if ( fMemDescriptor->writeBytes(offset, bytes, size) == 0 ) success = false;
}
else
{
success = false;
}
}
DebugLog(">>> IOFWRingBufferQ::enqueueBytes BSize: %u Length: %u Front: %u Insert: %u/%u\n", fBufferSize, fQueueLength, fFrontOffset, offset, paddingBytes);
return success;
}
bool IOFWRingBufferQ::isSpaceAvailable( IOByteCount size, IOByteCount * offset )
{
#if 0
FireLog("[");
UInt16 i;
UInt16 drawBufferWidth = 64;
UInt32 drawBufferSize = fBufferSize;
UInt32 drawBufAvail = drawBufferWidth * (fBufferSize-fQueueLength) / drawBufferSize;
UInt32 drawStartOff = drawBufferWidth * fFrontOffset / drawBufferSize;
UInt32 drawDestOff = drawBufferWidth * endOffset / drawBufferSize;
if ( drawStartOff != 0 ) drawStartOff--;
if ( drawDestOff != 0 ) drawDestOff--;
bool drawFilled = drawStartOff > drawDestOff ? true : false;
for ( i=0; i < drawBufferWidth; i++ )
{
if ( i == drawStartOff )
FireLog("s");
else if ( i == drawDestOff )
FireLog("d");
else if ( drawFilled )
FireLog("o");
else if ( drawBufAvail <= (drawBufferWidth/2) )
FireLog("?");
else
FireLog(".");
if ( i == drawStartOff )
drawFilled = true;
if ( i == drawDestOff )
drawFilled = false;
}
FireLog("]\n");
FireLog("-- Units Available: %lu StartPtr: %lu DestinationPtr: %lu --\n", drawBufAvail, drawStartOff, drawDestOff );
#endif
return willFitAtEnd(size, offset, NULL);
}
bool IOFWRingBufferQ::front( void * copy, IOByteCount size, IOByteCount * paddingBytes )
{
bool success = true;
if ( isEmpty() )
{
success = false;
}
else
{
if ( copy )
{
IOByteCount frontOffset = frontEntryOffset( size, paddingBytes ); if ( fMemDescriptor->readBytes(frontOffset, copy, size) == 0 )
success = false;
}
else
{
success = false;
}
}
return success;
}
IOByteCount IOFWRingBufferQ::spaceAvailable( void )
{
return fBufferSize - fQueueLength;
}
bool IOFWRingBufferQ::willFitAtEnd( IOByteCount sizeOfEntry, IOByteCount * offset, IOByteCount * paddingBytes )
{
bool success = true;
if ( paddingBytes )
*paddingBytes = 0;
IOByteCount endOffset = (fFrontOffset + fQueueLength) % fBufferSize;
if ( fQueueLength < fBufferSize ) {
if ( endOffset >= fFrontOffset ) {
if ( sizeOfEntry > (fBufferSize - endOffset) )
{
IOByteCount padding = fBufferSize - endOffset;
if ( paddingBytes )
*paddingBytes = padding;
endOffset = (fFrontOffset + fQueueLength + padding) % fBufferSize;
if ( sizeOfEntry > fFrontOffset )
success = false; }
}
else {
if ( sizeOfEntry > (fBufferSize - fQueueLength) )
success = false; }
}
else if ( fQueueLength > fBufferSize )
{
success = false;
}
else
{
success = false;
}
if ( offset )
*offset = endOffset;
DebugLog("IOFWRingBufferQ::willFitAtEnd BSize: %u Length: %u Front: %u Insert: %u EntrySize: %u\n", fBufferSize, fQueueLength, fFrontOffset, endOffset, sizeOfEntry);
return success;
}
IOByteCount IOFWRingBufferQ::frontEntryOffset( IOByteCount sizeOfEntry, IOByteCount * paddingBytes )
{
IOByteCount frontEntryOffset = fFrontOffset;
IOByteCount endOffset = (fFrontOffset + fQueueLength) % fBufferSize;
if ( paddingBytes )
*paddingBytes = 0;
if ( !isEmpty() ) {
if ( fFrontOffset >= endOffset ) {
if ( sizeOfEntry > (fBufferSize - fFrontOffset) )
{
IOByteCount padding = fBufferSize - fFrontOffset;
if ( paddingBytes )
*paddingBytes = padding;
frontEntryOffset = (fFrontOffset + padding) % fBufferSize;
DebugLogCond( (sizeOfEntry > endOffset), "IOFWRingBufferQ::frontEntryOffset Front entry cannot occur within queue starting at buffer index zero!\n");
}
}
else {
DebugLogCond( (sizeOfEntry > fQueueLength), "IOFWRingBufferQ::frontEntryOffset Front entry cannot occur within queue!\n");
}
}
else
{
DebugLog("IOFWRingBufferQ::frontEntryOffset Queue is empty!\n");
}
return frontEntryOffset;
}