IOUFIStorageServices.cpp [plain text]
#include <IOKit/IOLib.h>
#include <IOKit/storage/IOBlockStorageDriver.h>
#include "IOUFIStorageServices.h"
#if ( SCSI_BLOCK_SERVICES_DEBUGGING_LEVEL >= 1 )
#define PANIC_NOW(x) IOPanic x
#else
#define PANIC_NOW(x)
#endif
#if ( SCSI_BLOCK_SERVICES_DEBUGGING_LEVEL >= 2 )
#define ERROR_LOG(x) IOLog x
#else
#define ERROR_LOG(x)
#endif
#if ( SCSI_BLOCK_SERVICES_DEBUGGING_LEVEL >= 3 )
#define STATUS_LOG(x) IOLog x
#else
#define STATUS_LOG(x)
#endif
#define kNumberRetries 4
struct BlockServicesClientData
{
IOUFIStorageServices * owner;
IOStorageCompletion completionData;
IOMemoryDescriptor * clientBuffer;
UInt32 clientStartingBlock;
UInt32 clientRequestedBlockCount;
UInt32 clientRequestedBlockSize;
UInt32 retriesLeft;
};
typedef struct BlockServicesClientData BlockServicesClientData;
#define super IOBlockStorageDevice
OSDefineMetaClassAndStructors ( IOUFIStorageServices, IOBlockStorageDevice );
bool
IOUFIStorageServices::attach( IOService * provider )
{
STATUS_LOG ( ( "IOUFIStorageServices: attach called\n" ) );
if ( !super::attach ( provider ) )
{
return false;
}
fProvider = OSDynamicCast ( IOUSBMassStorageUFIDevice, provider );
if ( fProvider == NULL )
{
ERROR_LOG ( ( "IOUFIStorageServices: attach; wrong provider type!\n" ) );
return false;
}
setProperty ( kIOPropertyProtocolCharacteristicsKey, fProvider->GetProtocolCharacteristicsDictionary ( ) );
setProperty ( kIOPropertyDeviceCharacteristicsKey, fProvider->GetDeviceCharacteristicsDictionary ( ) );
fMediaChanged = false;
fMediaPresent = false;
fMaxReadBlocks = fProvider->ReportDeviceMaxBlocksReadTransfer();
fMaxWriteBlocks = fProvider->ReportDeviceMaxBlocksWriteTransfer();
STATUS_LOG ( ( "IOUFIStorageServices: attach exiting\n" ) );
return true;
}
void
IOUFIStorageServices::detach( IOService * provider )
{
STATUS_LOG ( ( "IOUFIStorageServices: detach called\n" ) );
super::detach( provider );
STATUS_LOG ( ( "IOUFIStorageServices: detach exiting\n" ) );
}
IOReturn
IOUFIStorageServices::message( UInt32 type,
IOService * nub,
void * arg )
{
IOReturn status = kIOReturnSuccess;
ERROR_LOG ( ( "IOUFIStorageServices::message called\n" ) );
switch ( type )
{
case kIOMessageMediaStateHasChanged:
{
ERROR_LOG ( ( "type = kIOMessageMediaStateHasChanged, nub = %p\n", nub ) );
fMediaChanged = true;
fMediaPresent = true;
status = messageClients ( type, arg, sizeof ( IOMediaState ) );
ERROR_LOG ( ( "status = %ld\n", ( UInt32 ) status ) );
}
break;
default:
{
status = super::message ( type, nub, arg );
}
break;
}
return status;
}
void
IOUFIStorageServices::AsyncReadWriteComplete( void * clientData,
IOReturn status,
UInt64 actualByteCount )
{
IOUFIStorageServices * owner;
BlockServicesClientData * servicesData;
IOStorageCompletion returnData;
bool commandComplete = true;
servicesData = ( BlockServicesClientData * ) clientData;
returnData = servicesData->completionData;
owner = servicesData->owner;
STATUS_LOG(("IOUFIStorageServices: AsyncReadWriteComplete; command status %x\n", status ));
if ((( status != kIOReturnNotAttached ) && ( status != kIOReturnOffline ) &&
( status != kIOReturnSuccess )) && ( servicesData->retriesLeft > 0 ))
{
IOReturn requestStatus;
STATUS_LOG(("IOUFIStorageServices: AsyncReadWriteComplete; retry command\n"));
servicesData->retriesLeft--;
requestStatus = owner->fProvider->AsyncReadWrite(
servicesData->clientBuffer,
servicesData->clientStartingBlock,
servicesData->clientRequestedBlockCount,
servicesData->clientRequestedBlockSize,
clientData );
if ( requestStatus != kIOReturnSuccess )
{
commandComplete = true;
}
else
{
commandComplete = false;
}
}
if ( commandComplete == true )
{
IOFree ( clientData, sizeof ( BlockServicesClientData ) );
owner->fProvider->release();
owner->release();
IOStorage::complete ( returnData, status, actualByteCount );
}
}
IOReturn
IOUFIStorageServices::doAsyncReadWrite ( IOMemoryDescriptor * buffer,
UInt32 block,
UInt32 nblks,
IOStorageCompletion completion )
{
BlockServicesClientData * clientData;
IODirection direction;
IOReturn requestStatus;
UInt32 requestBlockSize;
if ( isInactive() != false )
{
return kIOReturnNotAttached;
}
direction = buffer->getDirection();
if (( direction != kIODirectionIn ) && ( direction != kIODirectionOut ))
{
return kIOReturnBadArgument;
}
clientData = (BlockServicesClientData *) IOMalloc( sizeof( BlockServicesClientData ) );
if ( clientData == NULL )
{
ERROR_LOG ( ( "IOUFIStorageServices: doAsyncReadWrite; clientData malloc failed!\n" ) );
return kIOReturnNoResources;
}
retain();
fProvider->retain();
requestBlockSize = fProvider->ReportMediumBlockSize();
STATUS_LOG ( ( "IOUFIStorageServices: doAsyncReadWrite; save completion data!\n" ) );
clientData->owner = this;
clientData->completionData = completion;
clientData->clientBuffer = buffer;
clientData->clientStartingBlock = block;
clientData->clientRequestedBlockCount = nblks;
clientData->clientRequestedBlockSize = requestBlockSize;
clientData->retriesLeft = kNumberRetries;
requestStatus = fProvider->AsyncReadWrite( buffer, (UInt64) block, (UInt64) nblks, (UInt64) requestBlockSize, (void *) clientData );
if( requestStatus != kIOReturnSuccess )
{
if( clientData != NULL )
{
IOFree( clientData, sizeof( BlockServicesClientData ) );
}
}
return requestStatus;
}
IOReturn
IOUFIStorageServices::doSyncReadWrite( IOMemoryDescriptor * buffer,
UInt32 block,
UInt32 nblks )
{
IOReturn result;
if ( isInactive() != false )
{
return kIOReturnNotAttached;
}
retain();
fProvider->retain();
result = fProvider->SyncReadWrite( buffer, block, nblks, fProvider->ReportMediumBlockSize() );
fProvider->release();
release();
return result;
}
IOReturn
IOUFIStorageServices::doEjectMedia( void )
{
IOReturn result;
fMediaPresent = false;
if ( isInactive() != false )
{
return kIOReturnNotAttached;
}
retain();
fProvider->retain();
result = fProvider->EjectTheMedium();
fProvider->release();
release();
return result;
}
IOReturn
IOUFIStorageServices::doFormatMedia( UInt64 byteCapacity )
{
IOReturn result;
if ( isInactive() != false )
{
return kIOReturnNotAttached;
}
retain();
fProvider->retain();
result = fProvider->FormatMedium( byteCapacity / ( fProvider->ReportMediumBlockSize() ),
fProvider->ReportMediumBlockSize() );
fProvider->release();
release();
return result;
}
UInt32
IOUFIStorageServices::doGetFormatCapacities( UInt64 * capacities,
UInt32 capacitiesMaxCount ) const
{
IOReturn result;
if ( isInactive() != false )
{
return kIOReturnNotAttached;
}
retain();
fProvider->retain();
result = fProvider->GetFormatCapacities ( capacities, capacitiesMaxCount );
fProvider->release();
release();
return result;
}
IOReturn
IOUFIStorageServices::doLockUnlockMedia ( bool doLock )
{
if ( isInactive() != false )
{
return kIOReturnNotAttached;
}
return kIOReturnSuccess;
}
IOReturn
IOUFIStorageServices::doSynchronizeCache ( void )
{
if ( isInactive() != false )
{
return kIOReturnNotAttached;
}
return kIOReturnSuccess;
}
char *
IOUFIStorageServices::getVendorString ( void )
{
return fProvider->GetVendorString ( );
}
char *
IOUFIStorageServices::getProductString ( void )
{
return fProvider->GetProductString ( );
}
char *
IOUFIStorageServices::getRevisionString ( void )
{
return fProvider->GetRevisionString ( );
}
char *
IOUFIStorageServices::getAdditionalDeviceInfoString ( void )
{
STATUS_LOG ( ( "%s::%s called\n", getName ( ), __FUNCTION__ ) );
return ( "No Additional Device Info" );
}
IOReturn
IOUFIStorageServices::reportBlockSize ( UInt64 * blockSize )
{
*blockSize = fProvider->ReportMediumBlockSize ( );
return kIOReturnSuccess;
}
IOReturn
IOUFIStorageServices::reportEjectability ( bool * isEjectable )
{
*isEjectable = true;
return kIOReturnSuccess;
}
IOReturn
IOUFIStorageServices::reportLockability ( bool * isLockable )
{
*isLockable = true;
return kIOReturnSuccess;
}
IOReturn
IOUFIStorageServices::reportPollRequirements ( bool * pollIsRequired,
bool * pollIsExpensive )
{
*pollIsRequired = false;
*pollIsExpensive = false;
return kIOReturnSuccess;
}
IOReturn
IOUFIStorageServices::reportMaxReadTransfer ( UInt64 blockSize,
UInt64 * max )
{
if ( fMaxReadBlocks == 0 )
{
*max = blockSize * 256;
}
else
{
*max = blockSize * fMaxReadBlocks;
}
return kIOReturnSuccess;
}
IOReturn
IOUFIStorageServices::reportMaxValidBlock ( UInt64 * maxBlock )
{
*maxBlock = ( fProvider->ReportMediumTotalBlockCount ( ) - 1 );
return kIOReturnSuccess;
}
IOReturn
IOUFIStorageServices::reportMaxWriteTransfer ( UInt64 blockSize,
UInt64 * max )
{
if ( fMaxWriteBlocks == 0 )
{
*max = blockSize * 256;
}
else
{
*max = blockSize * fMaxWriteBlocks;
}
return kIOReturnSuccess;
}
IOReturn
IOUFIStorageServices::reportMediaState ( bool * mediaPresent,
bool * changed )
{
STATUS_LOG ( ( "IOSCSIBlockCommandsDevice::reportMediaState.\n" ) );
*mediaPresent = fMediaPresent;
*changed = fMediaChanged;
if ( fMediaChanged )
{
fMediaChanged = !fMediaChanged;
}
return kIOReturnSuccess;
}
IOReturn
IOUFIStorageServices::reportRemovability ( bool * isRemovable )
{
*isRemovable = true;
return kIOReturnSuccess;
}
IOReturn
IOUFIStorageServices::reportWriteProtection ( bool * isWriteProtected )
{
*isWriteProtected = fProvider->ReportMediumWriteProtection();
return kIOReturnSuccess;
}
OSMetaClassDefineReservedUnused( IOUFIStorageServices, 1 );
OSMetaClassDefineReservedUnused( IOUFIStorageServices, 2 );
OSMetaClassDefineReservedUnused( IOUFIStorageServices, 3 );
OSMetaClassDefineReservedUnused( IOUFIStorageServices, 4 );
OSMetaClassDefineReservedUnused( IOUFIStorageServices, 5 );
OSMetaClassDefineReservedUnused( IOUFIStorageServices, 6 );
OSMetaClassDefineReservedUnused( IOUFIStorageServices, 7 );
OSMetaClassDefineReservedUnused( IOUFIStorageServices, 8 );