IOFireWireSBP2LSIWorkaroundDescriptor.cpp [plain text]
#if __ppc__
#include <IOKit/IOLib.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include "FWDebugging.h"
#include <IOKit/sbp2/IOFireWireSBP2LSIWorkaroundDescriptor.h>
#include <IOKit/sbp2/IOFireWireSBP2ORB.h>
#define kMinPacketSize 16
#define kLowestPacketLimit 256
class IOFireWireSBP2LSIRange : public OSObject
{
OSDeclareDefaultStructors(IOFireWireSBP2LSIRange)
protected:
IOFireWireSBP2LSIWorkaroundDescriptor * parentDesc;
public:
void * buffer;
IOMemoryDescriptor * memory;
IOPhysicalAddress address;
IOByteCount length;
IOByteCount offset;
virtual void initWithParent( IOFireWireSBP2LSIWorkaroundDescriptor * desc );
virtual void markForBuffering( void );
virtual IOReturn allocateBuffer( IODirection direction );
virtual IOReturn syncBufferForInput( void );
virtual IOReturn syncBufferForOutput( void );
};
OSDefineMetaClassAndStructors(IOFireWireSBP2LSIRange, OSObject)
void IOFireWireSBP2LSIRange::initWithParent( IOFireWireSBP2LSIWorkaroundDescriptor * desc )
{
parentDesc = desc;
buffer = NULL;
}
void IOFireWireSBP2LSIRange::markForBuffering( void )
{
buffer = (void*)0xffffffff;
address = NULL;
}
IOReturn IOFireWireSBP2LSIRange::allocateBuffer( IODirection )
{
IOReturn status = kIOReturnSuccess;
if( buffer == ((void*)0xffffffff) )
{
buffer = parentDesc->bufferAllocatorNewBuffer( &address );
if( !buffer )
status = kIOReturnNoMemory;
}
return status;
}
IOReturn IOFireWireSBP2LSIRange::syncBufferForInput( void )
{
IOReturn status = kIOReturnSuccess;
if( buffer )
{
memory->writeBytes( offset, buffer, length );
}
return status;
}
IOReturn IOFireWireSBP2LSIRange::syncBufferForOutput( void )
{
IOReturn status = kIOReturnSuccess;
if( buffer )
{
memory->readBytes( offset, buffer, length );
}
return status;
}
OSDefineMetaClassAndStructors(IOFireWireSBP2LSIWorkaroundDescriptor, IOGeneralMemoryDescriptor)
OSMetaClassDefineReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 0);
OSMetaClassDefineReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 1);
OSMetaClassDefineReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 2);
OSMetaClassDefineReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 3);
OSMetaClassDefineReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 4);
OSMetaClassDefineReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 5);
OSMetaClassDefineReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 6);
OSMetaClassDefineReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 7);
OSMetaClassDefineReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 8);
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::rangeAllocatorInitialize( UInt32 rangeCount )
{
IOReturn status = kIOReturnSuccess;
FWLSILOGALLOC( ("LSILOG : allocating %ld permanent ranges\n", rangeCount) );
if( status == kIOReturnSuccess )
{
fAllocatedRangesCount = 0;
fPermanentRanges = OSArray::withCapacity( rangeCount ? rangeCount : 1 );
if( !fPermanentRanges )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
UInt32 i;
for( i = 0;
status == kIOReturnSuccess && i < rangeCount;
i++ )
{
IOFireWireSBP2LSIRange * range = NULL;
if( status == kIOReturnSuccess )
{
range = new IOFireWireSBP2LSIRange;
if( !range )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
if( !fPermanentRanges->setObject( i, range ) )
status = kIOReturnError;
}
if( range )
range->release();
}
FWKLOGASSERT( rangeCount == i );
}
FWLSILOGALLOC( ("LSILOG : successfully allocated %ld permanent ranges, status = 0x%08lx\n",
fPermanentRanges->getCount(), status) );
return status;
}
void IOFireWireSBP2LSIWorkaroundDescriptor::rangeAllocatorDeallocateAllRanges( void )
{
FWLSILOGALLOC( ("LSILOG : reset allocated ranges count. new allocCount = 0\n") );
fAllocatedRangesCount = 0;
}
IOFireWireSBP2LSIRange * IOFireWireSBP2LSIWorkaroundDescriptor::rangeAllocatorNewRange( void )
{
IOFireWireSBP2LSIRange * range = NULL;
if( fAllocatedRangesCount < fPermanentRanges->getCount() )
{
range = (IOFireWireSBP2LSIRange *)
fPermanentRanges->getObject( fAllocatedRangesCount );
range->retain();
fAllocatedRangesCount++;
FWLSILOGALLOC( ("LSILOG : allocating from permanent ranges. new allocCount = %ld\n",
fAllocatedRangesCount ) );
}
else if( !fFixedCapacity ) {
FWLSILOGALLOC( ("LSILOG : creating new range\n") );
range = new IOFireWireSBP2LSIRange;
}
return range;
}
void IOFireWireSBP2LSIWorkaroundDescriptor::rangeAllocatorFree( void )
{
FWLSILOGALLOC( ("LSILOG : free all ranges\n") );
if( fPermanentRanges )
fPermanentRanges->release(); }
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::bufferAllocatorInitialize
( IOByteCount requestedBufferSize )
{
IOReturn status = kIOReturnSuccess;
IOByteCount bufferSize = ((requestedBufferSize + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1));
UInt32 pageCount = bufferSize / PAGE_SIZE;
FWKLOGASSERT( (PAGE_SIZE % (kMinPacketSize*2)) == 0 );
FWLSILOGALLOC( ("LSILOG : allocating %ld permanent pages of buffer\n", pageCount) );
if( status == kIOReturnSuccess )
{
fAllocatedBytesCount = 0;
fBufferDescriptors = OSArray::withCapacity( pageCount ? pageCount : 1 );
if( !fBufferDescriptors )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
UInt32 i;
for( i = 0;
status == kIOReturnSuccess && i < pageCount;
i++ )
{
::IOBufferMemoryDescriptor * bufferDesc = NULL;
if( status == kIOReturnSuccess )
{
bufferDesc = ::IOBufferMemoryDescriptor::withOptions( kIODirectionOutIn | kIOMemoryUnshared, PAGE_SIZE, PAGE_SIZE );
if( !bufferDesc )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = bufferDesc->prepare();
}
if( status == kIOReturnSuccess )
{
if( !fBufferDescriptors->setObject( i, bufferDesc ) )
status = kIOReturnError;
}
if( bufferDesc )
bufferDesc->release();
}
FWKLOGASSERT( pageCount == i );
fPermanentPages = i;
}
FWLSILOGALLOC( ("LSILOG : successfully allocated %ld permanent pages, status = 0x%08lx\n",
fPermanentPages, status) );
return status;
}
void IOFireWireSBP2LSIWorkaroundDescriptor::bufferAllocatorDeallocateAllBuffers( void )
{
fAllocatedBytesCount = 0;
FWLSILOGALLOC( ("LSILOG : reset allocated bytes count. new allocByteCount = 0\n") );
FWLSILOGALLOC( ("LSILOG : freeing %ld pages of non-permanent buffer\n",
fBufferDescriptors->getCount() - fPermanentPages) );
UInt32 i = 0;
while( (i = fBufferDescriptors->getCount()) > fPermanentPages )
{
fBufferDescriptors->removeObject(i-1);
}
}
void * IOFireWireSBP2LSIWorkaroundDescriptor::bufferAllocatorNewBuffer(
IOPhysicalAddress * address )
{
IOReturn status = kIOReturnSuccess;
void * buffer = NULL;
::IOBufferMemoryDescriptor * bufferDesc = NULL;
UInt32 aligned_page = fAllocatedBytesCount & ~(PAGE_SIZE-1);
UInt32 page = aligned_page / PAGE_SIZE;
UInt32 offset = fAllocatedBytesCount - aligned_page;
fAllocatedBytesCount += kMinPacketSize*2;
FWKLOGASSERT( page == ((fAllocatedBytesCount) & ~(PAGE_SIZE-1)) );
if( page < fBufferDescriptors->getCount() )
{
bufferDesc = (::IOBufferMemoryDescriptor *)
fBufferDescriptors->getObject( page );
FWLSILOGALLOC( ("LSILOG : allocating from permanent pages. new allocByteCount = %ld\n",
fAllocatedBytesCount) );
}
else if( !fFixedCapacity )
{
FWLSILOGALLOC( ("LSILOG : creating new page. new allocByteCount = %ld\n",
fAllocatedBytesCount) );
bufferDesc = ::IOBufferMemoryDescriptor::withOptions( kIODirectionOutIn | kIOMemoryUnshared, PAGE_SIZE, PAGE_SIZE );
if( !bufferDesc )
status = kIOReturnNoMemory;
if( status == kIOReturnSuccess )
{
bufferDesc->prepare();
}
if( status == kIOReturnSuccess )
{
if( !fBufferDescriptors->setObject( page, bufferDesc ) )
status = kIOReturnError;
}
if( bufferDesc )
bufferDesc->release();
}
if( status == kIOReturnSuccess )
{
IOByteCount seg_size = 0;
*address = bufferDesc->getPhysicalSegment( 0, &seg_size ) + offset;
buffer = (void*)((UInt32)bufferDesc->getBytesNoCopy() + offset);
}
FWLSILOGALLOC( ("LSILOG : return buffer = 0x%lx\n", buffer) );
return buffer;
}
void IOFireWireSBP2LSIWorkaroundDescriptor::bufferAllocatorFree( void )
{
FWLSILOGALLOC( ("LSILOG : free all pages\n") );
if( fBufferDescriptors )
fBufferDescriptors->release(); }
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::rangeTableAllocatorInitialize
( UInt32 entries )
{
IOReturn status = kIOReturnSuccess;
if( status == kIOReturnSuccess )
{
fRangeTableSize = sizeof( IOPhysicalRange ) * entries;
fRangeTable = (IOPhysicalRange*) IOMalloc( fRangeTableSize );
if( fRangeTable == NULL )
status = kIOReturnError;
}
FWLSILOGALLOC( ("LSILOG : created %d entry range table. status = 0x%08lx\n",
entries, status) );
return status;
}
IOPhysicalRange * IOFireWireSBP2LSIWorkaroundDescriptor::rangeTableAllocatorNewTable
( UInt32 entries )
{
IOReturn status = kIOReturnSuccess;
IOPhysicalRange * buffer = NULL;
UInt32 requestedSize = sizeof( IOPhysicalRange ) * entries;
if( requestedSize <= fRangeTableSize )
{
FWLSILOGALLOC( ("LSILOG : requested entry count = %ld. using existing range table\n",
entries) );
buffer = fRangeTable;
}
else if( !fFixedCapacity )
{
FWLSILOGALLOC( ("LSILOG : requested entry count = %ld. creating new range table\n",
entries) );
if( fRangeTable )
{
IOFree( fRangeTable, fRangeTableSize );
fRangeTable = NULL;
}
fRangeTable = (IOPhysicalRange*) IOMalloc( requestedSize );
if( !fRangeTable )
status = kIOReturnNoMemory;
if( status == kIOReturnSuccess )
{
buffer = fRangeTable;
}
}
FWLSILOGALLOC( ("LSILOG : return rangeTable = 0x%08lx\n", buffer) );
return buffer;
}
void IOFireWireSBP2LSIWorkaroundDescriptor::rangeTableAllocatorFree( void )
{
FWLSILOGALLOC( ("LSILOG : free range table\n") );
if( fRangeTable )
{
IOFree( fRangeTable, fRangeTableSize );
fRangeTable = NULL;
}
}
bool IOFireWireSBP2LSIWorkaroundDescriptor::initWithAddress(
void * ,
IOByteCount ,
IODirection )
{
return false;
}
bool IOFireWireSBP2LSIWorkaroundDescriptor::initWithAddress(
vm_address_t ,
IOByteCount ,
IODirection ,
task_t )
{
return false;
}
bool IOFireWireSBP2LSIWorkaroundDescriptor::initWithPhysicalAddress(
IOPhysicalAddress ,
IOByteCount ,
IODirection )
{
return false;
}
bool IOFireWireSBP2LSIWorkaroundDescriptor::initWithPhysicalRanges(
IOPhysicalRange * ,
UInt32 ,
IODirection ,
bool )
{
return false;
}
bool IOFireWireSBP2LSIWorkaroundDescriptor::initWithRanges
( IOVirtualRange * ranges,
UInt32 withCount,
IODirection withDirection,
task_t withTask,
bool asReference )
{
return IOGeneralMemoryDescriptor::initWithRanges( ranges, withCount, withDirection, withTask, asReference );
}
IOFireWireSBP2LSIWorkaroundDescriptor * IOFireWireSBP2LSIWorkaroundDescriptor::withCapacity
( UInt32 maxElements, IOByteCount permanentBufferSpace, bool fixedCapacity )
{
IOFireWireSBP2LSIWorkaroundDescriptor *me = new IOFireWireSBP2LSIWorkaroundDescriptor;
if( me && !me->initWithCapacity( maxElements, permanentBufferSpace, fixedCapacity ) )
{
me->release();
me = NULL;
}
return me;
}
bool IOFireWireSBP2LSIWorkaroundDescriptor::initWithCapacity
( UInt32 permanentRanges, IOByteCount permanentBufferSpace, bool fixedCapacity )
{
IOReturn status = kIOReturnSuccess;
if( status == kIOReturnSuccess )
{
fFixedCapacity = fixedCapacity;
status = rangeAllocatorInitialize( permanentRanges );
}
if( status == kIOReturnSuccess )
{
status = bufferAllocatorInitialize( permanentBufferSpace );
}
if( status == kIOReturnSuccess )
{
fRanges = OSArray::withCapacity( permanentRanges ? permanentRanges : 1 );
if( !fRanges )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
status = rangeTableAllocatorInitialize( permanentRanges );
}
return ( status == kIOReturnSuccess );
}
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::resetToInitialCapacity( void )
{
IOReturn status = kIOReturnSuccess;
if( fOriginalDesc )
fOriginalDesc->release();
bufferAllocatorDeallocateAllBuffers();
if( fRanges )
fRanges->flushCollection();
rangeAllocatorDeallocateAllRanges();
return status;
}
IOFireWireSBP2LSIWorkaroundDescriptor * IOFireWireSBP2LSIWorkaroundDescriptor::withDescriptor
( IOMemoryDescriptor * desc, IOByteCount offset, IOByteCount len,
IODirection direction )
{
IOReturn status = kIOReturnSuccess;
IOFireWireSBP2LSIWorkaroundDescriptor *me = NULL;
if( status == kIOReturnSuccess )
{
me = new IOFireWireSBP2LSIWorkaroundDescriptor;
if( !me )
status = kIOReturnNoMemory;
}
if( status == kIOReturnSuccess )
{
if( !me->initWithCapacity( 0, 0, false ) )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
if( !me->initWithDescriptor( desc, offset, len, direction ) )
status = kIOReturnError;
}
if( me && status != kIOReturnSuccess )
{
me->release();
me = NULL;
}
return me;
}
bool IOFireWireSBP2LSIWorkaroundDescriptor::initWithDescriptor
( IOMemoryDescriptor * desc, IOByteCount offset, IOByteCount length,
IODirection direction )
{
IOReturn status = kIOReturnSuccess;
UInt32 count = 0;
IOPhysicalRange * rangeTable = NULL;
if( status == kIOReturnSuccess )
{
status = resetToInitialCapacity();
}
if( status == kIOReturnSuccess )
{
fDirection = direction;
fOriginalDesc = desc;
fOffset = offset;
if( !desc )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
fOriginalDesc->retain();
}
if( status == kIOReturnSuccess )
{
fLength = length;
if( fLength == 0 )
fLength = desc->getLength();
}
if( status == kIOReturnSuccess )
{
if( fLength < kMinPacketSize )
status = kIOReturnError;
}
if( status == kIOReturnSuccess )
{
status = initializeRangesArray();
}
#if LSILOGGING
{
FWLSILOG( ("LSILOG : original descriptor\n") );
for( UInt32 i = 0; i < fRanges->getCount(); i++ )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject(i);
FWLSILOG( ("LSILOG : range #%ld addr = 0x%08lx len = %d buffered = %s\n",
i, range->address, range->length, range->buffer == NULL ? "no" : "yes") );
#if 0
if( i % 10 == 0 )
IOSleep(1000);
#endif
}
}
#endif
if( status == kIOReturnSuccess )
{
status = recalculateSmallSegments();
}
#if 0
{
FWLSILOG( ("LSILOG : descriptor after recalculateSmallSegments\n") );
for( UInt32 i = 0; i < fRanges->getCount(); i++ )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject(i);
FWLSILOG( ("LSILOG : range #%ld addr = 0x%08lx len = %d buffered = %s\n",
i, range->address, range->length, range->buffer == NULL ? "no" : "yes") );
#if 0
if( i % 10 == 0 )
IOSleep(1000);
#endif
}
}
#endif
if( status == kIOReturnSuccess )
{
status = splitLargeSegments();
}
#if 0
{
FWLSILOG( ("LSILOG : descriptor after splitLargeSegments\n") );
for( UInt32 i = 0; i < fRanges->getCount(); i++ )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject(i);
FWLSILOG( ("LSILOG : range #%ld addr = 0x%08lx len = %d buffered = %s\n",
i, range->address, range->length, range->buffer == NULL ? "no" : "yes") );
#if 0
if( i % 10 == 0 )
IOSleep(1000);
#endif
}
}
#endif
if( status == kIOReturnSuccess )
{
status = resegmentOddLengthSegments();
}
#if 0
{
FWLSILOG( ("LSILOG : descriptor after resegmentOddLengthSegments\n") );
for( UInt32 i = 0; i < fRanges->getCount(); i++ )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject(i);
FWLSILOG( ("LSILOG : range #%ld addr = 0x%08lx len = %d buffered = %s\n",
i, range->address, range->length, range->buffer == NULL ? "no" : "yes") );
#if 0
if( i % 10 == 0 )
IOSleep(1000);
#endif
}
}
#endif
if( status == kIOReturnSuccess )
{
status = initializeBuffers();
FWLSILOGALLOC( ("LSILOG : attempted to initialize buffers. status = 0x%08lx\n", status) );
}
#if LSILOGGING
{
FWLSILOG( ("LSILOG : fixed descriptor\n") );
for( UInt32 i = 0; i < fRanges->getCount(); i++ )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject(i);
FWLSILOG( ("LSILOG : range #%ld addr = 0x%08lx len = %d buffered = %s\n",
i, range->address, range->length, range->buffer == NULL ? "no" : "yes") );
#if 0
if( i % 10 == 0 )
IOSleep(1000);
#endif
}
}
#endif
if( status == kIOReturnSuccess )
{
count = fRanges->getCount();
rangeTable = rangeTableAllocatorNewTable( count );
if( !rangeTable )
status = kIOReturnError;
FWLSILOGALLOC( ("LSILOG : attempted to allocate range table. status = 0x%08lx\n", status) );
}
if( status == kIOReturnSuccess )
{
for( UInt32 i = 0; i < count; i++ )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject( i );
if( !range )
{
status = kIOReturnError;
break;
}
rangeTable[i].address = range->address;
rangeTable[i].length = range->length;
}
FWLSILOGALLOC( ("LSILOG : attempted to fillout range table. status = 0x%08lx\n", status) );
}
if( status == kIOReturnSuccess )
{
if( !IOGeneralMemoryDescriptor::initWithPhysicalRanges
( rangeTable, count, fDirection, true ) )
status = kIOReturnError;
FWLSILOGALLOC( ("LSILOG : attempted to initialize decriptor. status = 0x%08lx\n", status) );
}
return ( status == kIOReturnSuccess );
}
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::initializeRangesArray( void )
{
IOReturn status = kIOReturnSuccess;
IOPhysicalAddress phys = NULL;
IOByteCount seg_length = 0;
IOByteCount i;
UInt32 seg_count;
i = fOffset;
seg_count = 0;
while( (status == kIOReturnSuccess) &&
(phys = fOriginalDesc->getPhysicalSegment( i, &seg_length )) )
{
FWLSILOGALLOC( ("LSILOG : creating range for segment %ld. offset = 0x%08lx, len = %ld\n",
seg_count, i, seg_length) );
if( i + seg_length > fLength )
seg_length = fLength - i;
IOFireWireSBP2LSIRange * range = rangeAllocatorNewRange();
if( !range )
status = kIOReturnNoMemory;
if( status == kIOReturnSuccess )
{
range->memory = fOriginalDesc;
range->address = phys;
range->length = seg_length;
range->offset = i;
range->initWithParent( this );
if( !fRanges->setObject( seg_count, range ) )
status = kIOReturnError;
}
if( range )
{
range->release();
range = NULL;
}
FWLSILOGALLOC( ("LSILOG : finished creating range for segment %ld. status = 0x%08lx\n",
seg_count, status) );
i += seg_length;
seg_count++;
}
return status;
}
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::recalculateSmallSegments( void )
{
IOReturn status = kIOReturnSuccess;
UInt32 i = 0;
while( i < fRanges->getCount() )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject(i);
if( range->length < kMinPacketSize )
{
IOByteCount bytesNeeded = (kMinPacketSize - range->length);
if( i == (fRanges->getCount() - 1) )
{
IOFireWireSBP2LSIRange * prevRange =
(IOFireWireSBP2LSIRange*)fRanges->getObject(i-1);
if( prevRange->length < (kMinPacketSize*2) )
{
prevRange->markForBuffering(); prevRange->length += range->length;
FWLSILOGALLOC( ("LSILOG : range #%ld - added %ld bytes to previous range\n", i, range->length) );
fRanges->removeObject(i); }
else
{
prevRange->length -= bytesNeeded;
range->markForBuffering(); range->length = kMinPacketSize;
FWLSILOGALLOC( ("LSILOG : range #%ld - stole %ld bytes from previous range\n", i, bytesNeeded) );
}
i++; }
else
{
IOFireWireSBP2LSIRange * nextRange =
(IOFireWireSBP2LSIRange*)fRanges->getObject(i+1);
if( range->length + nextRange->length >= kMinPacketSize )
{
nextRange->length -= bytesNeeded; nextRange->address += bytesNeeded;
range->length = kMinPacketSize; range->markForBuffering();
FWLSILOGALLOC( ("LSILOG : range #%ld - stole %ld bytes from next range\n", i, bytesNeeded) );
i++; }
else
{
range->length += nextRange->length; range->markForBuffering();
FWLSILOGALLOC( ("LSILOG : range #%ld - stole all %ld bytes from next range\n", i, nextRange->length) );
fRanges->removeObject(i+1);
}
}
}
else
{
FWLSILOGALLOC( ("LSILOG : range #%ld - range has enough bytes\n", i) );
i++;
}
#if 0
IOSleep(500);
#endif
}
return status;
}
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::splitLargeSegments( void )
{
IOReturn status = kIOReturnSuccess;
UInt32 i = 0;
while( i < fRanges->getCount() )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject(i);
if( range->length > kFWSBP2MaxPageClusterSize )
{
IOFireWireSBP2LSIRange * nextRange = NULL;
if( status == kIOReturnSuccess )
{
nextRange = rangeAllocatorNewRange();
if( nextRange )
status = kIOReturnSuccess;
}
if( status == kIOReturnSuccess )
{
nextRange->memory = fOriginalDesc;
nextRange->address = range->address + kFWSBP2MaxPageClusterSize;
nextRange->length = range->length - kFWSBP2MaxPageClusterSize;
range->length = kFWSBP2MaxPageClusterSize;
nextRange->initWithParent( this );
if( !fRanges->setObject( i+1, nextRange ) )
status = kIOReturnError;
}
if( nextRange )
{
nextRange->release();
nextRange = NULL;
}
}
i++;
}
return status;
}
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::resegmentOddLengthSegments( void )
{
IOReturn status = kIOReturnSuccess;
UInt32 i = 0;
while( i < fRanges->getCount() )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject(i);
UInt32 finalPacketSize = range->length % kLowestPacketLimit;
if( finalPacketSize != 0 && finalPacketSize < kMinPacketSize )
{
IOFireWireSBP2LSIRange * nextRange = NULL;
if( status == kIOReturnSuccess )
{
nextRange = rangeAllocatorNewRange();
if( nextRange )
status = kIOReturnSuccess;
}
if( status == kIOReturnSuccess )
{
range->length -= kMinPacketSize;
nextRange->memory = fOriginalDesc;
nextRange->address = range->address + range->length;
nextRange->length = kMinPacketSize;
nextRange->initWithParent( this );
if( !fRanges->setObject( i+1, nextRange ) )
status = kIOReturnError;
}
if( nextRange )
{
nextRange->release();
nextRange = NULL;
}
}
i++;
}
return status;
}
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::initializeBuffers( void )
{
IOReturn status = kIOReturnSuccess;
UInt32 count = fRanges->getCount();
UInt32 offset = fOffset;
for( UInt32 i = 0; i < count; i++ )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject(i);
range->offset = offset;
offset += range->length;
status = range->allocateBuffer( fDirection );
if( status != kIOReturnSuccess )
break;
}
return status;
}
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::syncBuffersForOutput( void )
{
IOReturn status = kIOReturnSuccess;
UInt32 count = fRanges->getCount();
for( UInt32 i = 0; i < count; i++ )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject( i );
status = range->syncBufferForOutput();
if( status != kIOReturnSuccess )
break;
}
return status;
}
IOReturn IOFireWireSBP2LSIWorkaroundDescriptor::syncBuffersForInput( void )
{
IOReturn status = kIOReturnSuccess;
UInt32 count = fRanges->getCount();
for( UInt32 i = 0; i < count; i++ )
{
IOFireWireSBP2LSIRange * range = (IOFireWireSBP2LSIRange*)fRanges->getObject( i );
status = range->syncBufferForInput();
if( status != kIOReturnSuccess )
break;
}
return status;
}
void IOFireWireSBP2LSIWorkaroundDescriptor::free( void )
{
if( fOriginalDesc )
fOriginalDesc->release();
rangeTableAllocatorFree();
bufferAllocatorFree();
if( fRanges )
fRanges->release();
rangeAllocatorFree();
IOGeneralMemoryDescriptor::free();
}
#endif