IOFireWireLibPhysicalAddressSpace.cpp [plain text]
#import "IOFireWireLibPhysicalAddressSpace.h"
#import "IOFireWireLibDevice.h"
#import <exception>
namespace IOFireWireLib {
PhysicalAddressSpace::Interface PhysicalAddressSpace::sInterface =
{
INTERFACEIMP_INTERFACE,
1, 0, & PhysicalAddressSpace::SGetPhysicalSegments,
& PhysicalAddressSpace::SGetPhysicalSegment,
& PhysicalAddressSpace::SGetPhysicalAddress,
SGetFWAddress,
SGetBuffer,
SGetBufferSize
} ;
HRESULT
PhysicalAddressSpace::QueryInterface(REFIID iid, void **ppv)
{
HRESULT result = S_OK ;
*ppv = nil ;
CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ;
if ( CFEqual(interfaceID, IUnknownUUID) || CFEqual(interfaceID, kIOFireWirePhysicalAddressSpaceInterfaceID) )
{
*ppv = & GetInterface() ;
AddRef() ;
}
else
{
*ppv = nil ;
result = E_NOINTERFACE ;
}
CFRelease(interfaceID) ;
return result ;
}
IUnknownVTbl**
PhysicalAddressSpace::Alloc(
Device& inUserClient,
UserObjectHandle inAddrSpaceRef,
UInt32 inSize,
void* inBackingStore,
UInt32 inFlags)
{
PhysicalAddressSpace* me = nil ;
try {
me = new PhysicalAddressSpace(inUserClient, inAddrSpaceRef, inSize, inBackingStore, inFlags) ;
} catch (...) {
}
return ( nil == me ) ? nil : reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ;
}
#pragma mark -
void
PhysicalAddressSpace::SGetPhysicalSegments(
IOFireWireLibPhysicalAddressSpaceRef self,
UInt32* ioSegmentCount,
IOByteCount outSegments[],
IOPhysicalAddress outAddresses[])
{
IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->GetPhysicalSegments(ioSegmentCount, outSegments, outAddresses) ;
}
IOPhysicalAddress
PhysicalAddressSpace::SGetPhysicalSegment(
IOFireWireLibPhysicalAddressSpaceRef self,
IOByteCount offset,
IOByteCount* length)
{
return IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->GetPhysicalSegment(offset, length) ;
}
IOPhysicalAddress
PhysicalAddressSpace::SGetPhysicalAddress(
IOFireWireLibPhysicalAddressSpaceRef self)
{
return IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->mSegments[0].location ;
}
void
PhysicalAddressSpace::SGetFWAddress(IOFireWireLibPhysicalAddressSpaceRef self, FWAddress* outAddr )
{
bcopy(& IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->mFWAddress, outAddr, sizeof(*outAddr)) ;
}
void*
PhysicalAddressSpace::SGetBuffer(IOFireWireLibPhysicalAddressSpaceRef self)
{
return IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->mBackingStore ;
}
const UInt32
PhysicalAddressSpace::SGetBufferSize(IOFireWireLibPhysicalAddressSpaceRef self)
{
return IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->mSize ;
}
#pragma mark -
PhysicalAddressSpace::PhysicalAddressSpace( Device& inUserClient, UserObjectHandle inKernPhysicalAddrSpaceRef,
UInt32 inSize, void* inBackingStore, UInt32 inFlags)
: IOFireWireIUnknown( reinterpret_cast<const IUnknownVTbl &>( sInterface ) ),
mUserClient(inUserClient),
mKernPhysicalAddrSpaceRef(inKernPhysicalAddrSpaceRef),
mSize(inSize),
mBackingStore(inBackingStore),
mSegments( NULL ),
mSegmentCount(0)
{
inUserClient.AddRef() ;
if (!mKernPhysicalAddrSpaceRef)
throw kIOReturnNoMemory ;
IOReturn error = ::IOConnectMethodScalarIScalarO( mUserClient.GetUserClientConnection(),
mUserClient.MakeSelectorWithObject( kPhysicalAddrSpace_GetSegmentCount_d,
mKernPhysicalAddrSpaceRef ),
0, 1, & mSegmentCount) ;
if ( error || mSegmentCount == 0)
throw error ;
mSegments = new PhysicalSegment[mSegmentCount] ;
if (!mSegments)
{
throw kIOReturnNoMemory ;
}
error = ::IOConnectMethodScalarIScalarO( mUserClient.GetUserClientConnection(),
kPhysicalAddrSpace_GetSegments, 3, 1, mKernPhysicalAddrSpaceRef,
mSegmentCount, mSegments, & mSegmentCount) ;
if (error)
{
throw error ;
}
mFWAddress = FWAddress(0, mSegments[0].location, 0) ;
}
PhysicalAddressSpace::~PhysicalAddressSpace()
{
IOConnectMethodScalarIScalarO( mUserClient.GetUserClientConnection(),
kReleaseUserObject, 1, 0, mKernPhysicalAddrSpaceRef ) ;
delete[] mSegments ;
mUserClient.Release() ;
}
void
PhysicalAddressSpace::GetPhysicalSegments(
UInt32* ioSegmentCount,
IOByteCount outSegmentLengths[],
IOPhysicalAddress outSegments[])
{
*ioSegmentCount = *ioSegmentCount <? mSegmentCount ;
for( unsigned index=0; index < *ioSegmentCount; ++index )
{
outSegments[ index ] = mSegments[ index ].location ;
outSegmentLengths[ index ] = mSegments[ index ].length ;
}
}
IOPhysicalAddress
PhysicalAddressSpace::GetPhysicalSegment(
IOByteCount offset,
IOByteCount* length)
{
IOPhysicalAddress result = 0 ;
if (mSegmentCount > 0)
{
IOByteCount traversed = mSegments[0].length ;
UInt32 currentSegment = 0 ;
while((traversed <= offset) && (currentSegment < mSegmentCount))
{
traversed += mSegments[ currentSegment ].length ;
++currentSegment ;
}
if ( currentSegment <= mSegmentCount )
{
*length = mSegments[ currentSegment ].length ;
result = mSegments[ currentSegment ].location ;
}
}
return result ;
}
}