#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/storage/IOStorage.h>
#define super IOService
OSDefineMetaClassAndAbstractStructors(IOStorage, IOService)
#ifndef __LP64__
#define kIOStorageAttributesUnsupported ( ( IOStorage::ExpansionData * ) 1 )
IOStorageAttributes gIOStorageAttributesUnsupported = { kIOStorageOptionReserved };
extern "C" void _ZN9IOStorage4readEP9IOServiceyP18IOMemoryDescriptor19IOStorageCompletion( IOStorage *, IOService *, UInt64, IOMemoryDescriptor *, IOStorageCompletion );
extern "C" void _ZN9IOStorage5writeEP9IOServiceyP18IOMemoryDescriptor19IOStorageCompletion( IOStorage *, IOService *, UInt64, IOMemoryDescriptor *, IOStorageCompletion );
extern "C" void _ZN9IOStorage4readEP9IOServiceyP18IOMemoryDescriptorP19IOStorageAttributesP19IOStorageCompletion( IOStorage *, IOService *, UInt64, IOMemoryDescriptor *, IOStorageAttributes *, IOStorageCompletion * );
extern "C" void _ZN9IOStorage5writeEP9IOServiceyP18IOMemoryDescriptorP19IOStorageAttributesP19IOStorageCompletion( IOStorage *, IOService *, UInt64, IOMemoryDescriptor *, IOStorageAttributes *, IOStorageCompletion * );
#define storageAttributes( storage ) ( ( OSMemberFunctionCast( void *, storage, ( void ( IOStorage::* )( IOService *, UInt64, IOMemoryDescriptor *, IOStorageCompletion ) ) &IOStorage::read ) == _ZN9IOStorage4readEP9IOServiceyP18IOMemoryDescriptor19IOStorageCompletion ) && \
( OSMemberFunctionCast( void *, storage, ( void ( IOStorage::* )( IOService *, UInt64, IOMemoryDescriptor *, IOStorageCompletion ) ) &IOStorage::write ) == _ZN9IOStorage5writeEP9IOServiceyP18IOMemoryDescriptor19IOStorageCompletion ) && \
( OSMemberFunctionCast( void *, storage, ( void ( IOStorage::* )( IOService *, UInt64, IOMemoryDescriptor *, IOStorageAttributes *, IOStorageCompletion * ) ) &IOStorage::read ) != _ZN9IOStorage4readEP9IOServiceyP18IOMemoryDescriptorP19IOStorageAttributesP19IOStorageCompletion ) && \
( OSMemberFunctionCast( void *, storage, ( void ( IOStorage::* )( IOService *, UInt64, IOMemoryDescriptor *, IOStorageAttributes *, IOStorageCompletion * ) ) &IOStorage::write ) != _ZN9IOStorage5writeEP9IOServiceyP18IOMemoryDescriptorP19IOStorageAttributesP19IOStorageCompletion ) )
#endif
class IOStorageSyncerLock
{
protected:
IOLock * _lock;
public:
inline IOStorageSyncerLock( )
{
_lock = IOLockAlloc( );
}
inline ~IOStorageSyncerLock( )
{
if ( _lock ) IOLockFree( _lock );
}
inline void lock( )
{
IOLockLock( _lock );
}
inline void unlock( )
{
IOLockUnlock( _lock );
}
inline void sleep( void * event )
{
IOLockSleep( _lock, event, THREAD_UNINT );
}
inline void wakeup( void * event )
{
IOLockWakeup( _lock, event, false );
}
};
static IOStorageSyncerLock gIOStorageSyncerLock;
class IOStorageSyncer
{
protected:
IOReturn _status;
bool _wakeup;
public:
IOStorageSyncer( )
{
_wakeup = false;
}
IOReturn wait( )
{
gIOStorageSyncerLock.lock( );
while ( _wakeup == false )
{
gIOStorageSyncerLock.sleep( this );
}
gIOStorageSyncerLock.unlock( );
return _status;
}
void signal( IOReturn status )
{
_status = status;
gIOStorageSyncerLock.lock( );
_wakeup = true;
gIOStorageSyncerLock.wakeup( this );
gIOStorageSyncerLock.unlock( );
}
};
static void storageCompletion(void * target,
void * parameter,
IOReturn status,
UInt64 actualByteCount)
{
if (parameter) *((UInt64 *)parameter) = actualByteCount;
((IOStorageSyncer *)target)->signal(status);
}
#ifndef __LP64__
bool IOStorage::init(OSDictionary * properties)
{
if ( super::init( properties ) == false )
{
return false;
}
if ( storageAttributes( this ) == false )
{
IOStorage::_expansionData = kIOStorageAttributesUnsupported;
}
if ( IOStorage::_expansionData )
{
OSDictionary * features;
features = OSDictionary::withCapacity( 1 );
if ( features )
{
setProperty( kIOStorageFeaturesKey, features );
features->release( );
}
}
return true;
}
void IOStorage::complete(IOStorageCompletion completion,
IOReturn status,
UInt64 actualByteCount)
{
complete( &completion, status, actualByteCount );
}
#endif
void IOStorage::complete(IOStorageCompletion * completion,
IOReturn status,
UInt64 actualByteCount)
{
if ( completion && completion->action )
{
( completion->action )( completion->target, completion->parameter, status, actualByteCount );
}
}
bool IOStorage::open(IOService * client,
IOOptionBits options,
IOStorageAccess access)
{
return super::open(client, options, (void *) access);
}
IOReturn IOStorage::read(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
#ifdef __LP64__
IOStorageAttributes * attributes,
#endif
UInt64 * actualByteCount)
{
IOStorageCompletion completion;
IOStorageSyncer syncer;
completion.target = &syncer;
completion.action = storageCompletion;
completion.parameter = actualByteCount;
#ifdef __LP64__
read(client, byteStart, buffer, attributes, &completion);
#else
read(client, byteStart, buffer, NULL, &completion);
#endif
return syncer.wait();
}
IOReturn IOStorage::write(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
#ifdef __LP64__
IOStorageAttributes * attributes,
#endif
UInt64 * actualByteCount)
{
IOStorageCompletion completion;
IOStorageSyncer syncer;
completion.target = &syncer;
completion.action = storageCompletion;
completion.parameter = actualByteCount;
#ifdef __LP64__
write(client, byteStart, buffer, attributes, &completion);
#else
write(client, byteStart, buffer, NULL, &completion);
#endif
return syncer.wait();
}
#ifndef __LP64__
void IOStorage::read(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
IOStorageCompletion completion)
{
if ( IOStorage::_expansionData == kIOStorageAttributesUnsupported )
{
read( client, byteStart, buffer, &gIOStorageAttributesUnsupported, &completion );
}
else
{
read( client, byteStart, buffer, NULL, &completion );
}
}
void IOStorage::write(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
IOStorageCompletion completion)
{
if ( IOStorage::_expansionData == kIOStorageAttributesUnsupported )
{
write( client, byteStart, buffer, &gIOStorageAttributesUnsupported, &completion );
}
else
{
write( client, byteStart, buffer, NULL, &completion );
}
}
void IOStorage::read(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
IOStorageAttributes * attributes,
IOStorageCompletion * completion)
{
if ( attributes && attributes->options )
{
complete( completion, kIOReturnUnsupported );
}
else
{
read( client, byteStart, buffer, completion ? *completion : ( IOStorageCompletion ) { 0 } );
}
}
void IOStorage::write(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
IOStorageAttributes * attributes,
IOStorageCompletion * completion)
{
if ( attributes && attributes->options )
{
complete( completion, kIOReturnUnsupported );
}
else
{
write( client, byteStart, buffer, completion ? *completion : ( IOStorageCompletion ) { 0 } );
}
}
#endif
IOReturn IOStorage::discard(IOService * client,
UInt64 byteStart,
UInt64 byteCount)
{
return kIOReturnUnsupported;
}
IOReturn IOStorage::unmap(IOService * client,
IOStorageExtent * extents,
UInt32 extentsCount,
UInt32 options)
{
return kIOReturnUnsupported;
}
OSMetaClassDefineReservedUsed(IOStorage, 0);
#ifdef __LP64__
OSMetaClassDefineReservedUnused(IOStorage, 1);
OSMetaClassDefineReservedUnused(IOStorage, 2);
OSMetaClassDefineReservedUnused(IOStorage, 3);
#else
OSMetaClassDefineReservedUsed(IOStorage, 1);
OSMetaClassDefineReservedUsed(IOStorage, 2);
OSMetaClassDefineReservedUsed(IOStorage, 3);
#endif
OSMetaClassDefineReservedUnused(IOStorage, 4);
OSMetaClassDefineReservedUnused(IOStorage, 5);
OSMetaClassDefineReservedUnused(IOStorage, 6);
OSMetaClassDefineReservedUnused(IOStorage, 7);
OSMetaClassDefineReservedUnused(IOStorage, 8);
OSMetaClassDefineReservedUnused(IOStorage, 9);
OSMetaClassDefineReservedUnused(IOStorage, 10);
OSMetaClassDefineReservedUnused(IOStorage, 11);
OSMetaClassDefineReservedUnused(IOStorage, 12);
OSMetaClassDefineReservedUnused(IOStorage, 13);
OSMetaClassDefineReservedUnused(IOStorage, 14);
OSMetaClassDefineReservedUnused(IOStorage, 15);