#include <IOKit/storage/IOCDBlockStorageDriver.h>
#include <IOKit/storage/IOCDMedia.h>
#define super IOMedia
OSDefineMetaClassAndStructors(IOCDMedia, IOMedia)
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);
}
IOCDBlockStorageDriver * IOCDMedia::getProvider() const
{
return (IOCDBlockStorageDriver *) IOService::getProvider();
}
bool IOCDMedia::matchPropertyTable(OSDictionary * table, SInt32 * score)
{
if (super::matchPropertyTable(table, score) == false) return false;
return compareProperty(table, kIOCDMediaTOCKey ) &&
compareProperty(table, kIOCDMediaTypeKey);
}
void IOCDMedia::read(IOService * ,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
IOStorageAttributes * attributes,
IOStorageCompletion * completion)
{
if (isInactive())
{
complete(completion, kIOReturnNoMedia);
return;
}
if (_openLevel == kIOStorageAccessNone) {
complete(completion, kIOReturnNotOpen);
return;
}
if (_mediaSize == 0 || _preferredBlockSize == 0)
{
complete(completion, kIOReturnUnformattedMedia);
return;
}
if (buffer == 0)
{
complete(completion, kIOReturnBadArgument);
return;
}
if (_mediaSize < byteStart + buffer->getLength())
{
complete(completion, kIOReturnBadArgument);
return;
}
byteStart += _mediaBase;
getProvider()->readCD( this,
byteStart,
buffer,
(CDSectorArea) 0xF8, (CDSectorType) 0x00, #ifdef __LP64__
attributes,
completion );
#else
completion ? *completion : (IOStorageCompletion) { 0 } );
#endif
}
void IOCDMedia::write(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
IOStorageAttributes * attributes,
IOStorageCompletion * completion)
{
if (isInactive())
{
complete(completion, kIOReturnNoMedia);
return;
}
if (_openLevel == kIOStorageAccessNone) {
complete(completion, kIOReturnNotOpen);
return;
}
if (_openLevel == kIOStorageAccessReader) {
complete(completion, kIOReturnNotPrivileged);
return;
}
if (_isWritable == 0)
{
complete(completion, kIOReturnLockedWrite);
return;
}
if (_mediaSize == 0 || _preferredBlockSize == 0)
{
complete(completion, kIOReturnUnformattedMedia);
return;
}
if (buffer == 0)
{
complete(completion, kIOReturnBadArgument);
return;
}
if (_mediaSize < byteStart + buffer->getLength())
{
complete(completion, kIOReturnBadArgument);
return;
}
byteStart += _mediaBase;
getProvider()->writeCD(
this,
byteStart,
buffer,
(CDSectorArea) 0xF8, (CDSectorType) 0x00, #ifdef __LP64__
attributes,
completion );
#else
completion ? *completion : (IOStorageCompletion) { 0 } );
#endif
}
IOReturn IOCDMedia::readCD(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
CDSectorArea sectorArea,
CDSectorType sectorType,
#ifdef __LP64__
IOStorageAttributes * attributes,
#endif
UInt64 * actualByteCount)
{
IOStorageCompletion completion;
IOStorageSyncer syncer;
completion.target = &syncer;
completion.action = storageCompletion;
completion.parameter = actualByteCount;
#ifdef __LP64__
readCD(client, byteStart, buffer, sectorArea, sectorType, attributes, &completion);
#else
readCD(client, byteStart, buffer, sectorArea, sectorType, completion);
#endif
return syncer.wait();
}
void IOCDMedia::readCD(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
CDSectorArea sectorArea,
CDSectorType sectorType,
#ifdef __LP64__
IOStorageAttributes * attributes,
IOStorageCompletion * completion)
#else
IOStorageCompletion completion)
#endif
{
if (isInactive())
{
complete(completion, kIOReturnNoMedia);
return;
}
if (_openLevel == kIOStorageAccessNone) {
complete(completion, kIOReturnNotOpen);
return;
}
if (_mediaSize == 0 || _preferredBlockSize == 0)
{
complete(completion, kIOReturnUnformattedMedia);
return;
}
if (buffer == 0)
{
complete(completion, kIOReturnBadArgument);
return;
}
byteStart += _mediaBase;
getProvider()->readCD( this,
byteStart,
buffer,
sectorArea,
sectorType,
#ifdef __LP64__
attributes,
#endif
completion );
}
IOReturn IOCDMedia::readISRC(UInt8 track, CDISRC isrc)
{
if (isInactive())
{
return kIOReturnNoMedia;
}
return getProvider()->readISRC(track, isrc);
}
IOReturn IOCDMedia::readMCN(CDMCN mcn)
{
if (isInactive())
{
return kIOReturnNoMedia;
}
return getProvider()->readMCN(mcn);
}
CDTOC * IOCDMedia::getTOC()
{
if (isInactive())
{
return 0;
}
return getProvider()->getTOC();
}
IOReturn IOCDMedia::getSpeed(UInt16 * kilobytesPerSecond)
{
if (isInactive())
{
return kIOReturnNoMedia;
}
return getProvider()->getSpeed(kilobytesPerSecond);
}
IOReturn IOCDMedia::setSpeed(UInt16 kilobytesPerSecond)
{
if (isInactive())
{
return kIOReturnNoMedia;
}
return getProvider()->setSpeed(kilobytesPerSecond);
}
IOReturn IOCDMedia::readTOC(IOMemoryDescriptor * buffer,
CDTOCFormat format,
UInt8 formatAsTime,
UInt8 trackOrSessionNumber,
UInt16 * actualByteCount)
{
if (isInactive())
{
if (actualByteCount) *actualByteCount = 0;
return kIOReturnNoMedia;
}
if (buffer == 0)
{
if (actualByteCount) *actualByteCount = 0;
return kIOReturnBadArgument;
}
return getProvider()->readTOC(
buffer,
format,
formatAsTime,
trackOrSessionNumber,
actualByteCount );
}
IOReturn IOCDMedia::readDiscInfo(IOMemoryDescriptor * buffer,
UInt16 * actualByteCount)
{
if (isInactive())
{
if (actualByteCount) *actualByteCount = 0;
return kIOReturnNoMedia;
}
if (buffer == 0)
{
if (actualByteCount) *actualByteCount = 0;
return kIOReturnBadArgument;
}
return getProvider()->readDiscInfo(
buffer,
actualByteCount );
}
IOReturn IOCDMedia::readTrackInfo(IOMemoryDescriptor * buffer,
UInt32 address,
CDTrackInfoAddressType addressType,
UInt16 * actualByteCount)
{
if (isInactive())
{
if (actualByteCount) *actualByteCount = 0;
return kIOReturnNoMedia;
}
if (buffer == 0)
{
if (actualByteCount) *actualByteCount = 0;
return kIOReturnBadArgument;
}
return getProvider()->readTrackInfo(
buffer,
address,
addressType,
actualByteCount );
}
void IOCDMedia::writeCD(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
CDSectorArea sectorArea,
CDSectorType sectorType,
#ifdef __LP64__
IOStorageAttributes * attributes,
IOStorageCompletion * completion)
#else
IOStorageCompletion completion)
#endif
{
if (isInactive())
{
complete(completion, kIOReturnNoMedia);
return;
}
if (_openLevel == kIOStorageAccessNone) {
complete(completion, kIOReturnNotOpen);
return;
}
if (_openLevel == kIOStorageAccessReader) {
complete(completion, kIOReturnNotPrivileged);
return;
}
if (_isWritable == 0)
{
complete(completion, kIOReturnLockedWrite);
return;
}
if (_mediaSize == 0 || _preferredBlockSize == 0)
{
complete(completion, kIOReturnUnformattedMedia);
return;
}
if (buffer == 0)
{
complete(completion, kIOReturnBadArgument);
return;
}
byteStart += _mediaBase;
getProvider()->writeCD( this,
byteStart,
buffer,
sectorArea,
sectorType,
#ifdef __LP64__
attributes,
#endif
completion );
}
IOReturn IOCDMedia::writeCD(IOService * client,
UInt64 byteStart,
IOMemoryDescriptor * buffer,
CDSectorArea sectorArea,
CDSectorType sectorType,
#ifdef __LP64__
IOStorageAttributes * attributes,
#endif
UInt64 * actualByteCount)
{
IOStorageCompletion completion;
IOStorageSyncer syncer;
completion.target = &syncer;
completion.action = storageCompletion;
completion.parameter = actualByteCount;
#ifdef __LP64__
writeCD(client, byteStart, buffer, sectorArea, sectorType, attributes, &completion);
#else
writeCD(client, byteStart, buffer, sectorArea, sectorType, completion);
#endif
return syncer.wait();
}
#ifdef __LP64__
OSMetaClassDefineReservedUnused(IOCDMedia, 0);
OSMetaClassDefineReservedUnused(IOCDMedia, 1);
OSMetaClassDefineReservedUnused(IOCDMedia, 2);
OSMetaClassDefineReservedUnused(IOCDMedia, 3);
OSMetaClassDefineReservedUnused(IOCDMedia, 4);
OSMetaClassDefineReservedUnused(IOCDMedia, 5);
OSMetaClassDefineReservedUnused(IOCDMedia, 6);
#else
OSMetaClassDefineReservedUsed(IOCDMedia, 0);
OSMetaClassDefineReservedUsed(IOCDMedia, 1);
OSMetaClassDefineReservedUsed(IOCDMedia, 2);
OSMetaClassDefineReservedUsed(IOCDMedia, 3);
OSMetaClassDefineReservedUsed(IOCDMedia, 4);
OSMetaClassDefineReservedUsed(IOCDMedia, 5);
OSMetaClassDefineReservedUsed(IOCDMedia, 6);
#endif
OSMetaClassDefineReservedUnused(IOCDMedia, 7);
OSMetaClassDefineReservedUnused(IOCDMedia, 8);
OSMetaClassDefineReservedUnused(IOCDMedia, 9);
OSMetaClassDefineReservedUnused(IOCDMedia, 10);
OSMetaClassDefineReservedUnused(IOCDMedia, 11);
OSMetaClassDefineReservedUnused(IOCDMedia, 12);
OSMetaClassDefineReservedUnused(IOCDMedia, 13);
OSMetaClassDefineReservedUnused(IOCDMedia, 14);
OSMetaClassDefineReservedUnused(IOCDMedia, 15);