AppleIntelPIIXMultiATADriver.cpp [plain text]
#include <IOKit/IOLib.h>
#include <IOKit/pci/IOPCIDevice.h>
#include "AppleIntelPIIXMultiATADriver.h"
#include "AppleIntelPIIXATAController.h"
#include "AppleIntelPIIXATAKeys.h"
#define super IOService
OSDefineMetaClassAndStructors( AppleIntelPIIXMultiATADriver, IOService )
IOService *
AppleIntelPIIXMultiATADriver::probe( IOService * provider,
SInt32 * score )
{
IOPCIDevice * pciDevice;
if ( super::probe( provider, score ) == 0 )
{
return 0;
}
pciDevice = OSDynamicCast( IOPCIDevice, provider );
if ( pciDevice == 0 )
{
return 0;
}
if ( (pciDevice->configRead16( kIOPCIConfigCommand ) &
kIOPCICommandIOSpace) == 0 )
{
return 0;
}
return this;
}
bool
AppleIntelPIIXMultiATADriver::start( IOService * provider )
{
if ( super::start(provider) != true )
{
IOLog("%s: super start failed\n", getName());
return false;
}
_pciConfigLock = IOLockAlloc();
if ( _pciConfigLock == 0 )
{
IOLog("%s: lock allocation failed\n", getName());
return false;
}
_provider = OSDynamicCast( IOPCIDevice, provider );
if ( _provider == 0 )
{
IOLog("%s: provider is not IOPCIDevice\n", getName());
return false;
}
_provider->retain();
_nubs = createControllerNubs();
if ( _nubs == 0 )
{
IOLog("%s: unable to create controller nubs\n", getName());
return false;
}
_openNubs = OSSet::withCapacity( _nubs->getCount() );
if ( _openNubs == 0 )
{
IOLog("%s: OSSet allocation failed\n", getName());
return false;
}
return true;
}
void
AppleIntelPIIXMultiATADriver::free()
{
if ( _nubs )
{
_nubs->release();
_nubs = 0;
}
if ( _openNubs )
{
_openNubs->release();
_openNubs = 0;
}
if ( _provider )
{
_provider->release();
_provider = 0;
}
if ( _pciConfigLock )
{
IOLockFree( _pciConfigLock );
_pciConfigLock = 0;
}
super::free();
}
OSSet *
AppleIntelPIIXMultiATADriver::createControllerNubs()
{
OSSet * nubSet;
OSArray * channels;
OSDictionary * channelInfo;
AppleIntelPIIXATAController * nub;
do {
nubSet = OSSet::withCapacity(4);
if ( nubSet == 0 )
break;
channels = OSDynamicCast( OSArray, getProperty( kATAChannelsKey ) );
if ( channels == 0 )
break;
for ( UInt32 i = 0; i < 2; i++)
{
channelInfo = OSDynamicCast( OSDictionary, channels->getObject(i) );
if ( channelInfo == 0 )
break;
nub = new AppleIntelPIIXATAController;
if ( nub )
{
if ( nub->init( this, channelInfo ) &&
nub->attach( this ) &&
nubSet->setObject( nub ) )
{
nub->registerService();
}
nub->release();
}
}
}
while ( false );
if ( nubSet && (nubSet->getCount() == 0) )
{
nubSet->release();
nubSet = 0;
}
return nubSet;
}
bool
AppleIntelPIIXMultiATADriver::handleOpen( IOService * client,
IOOptionBits options,
void * arg )
{
bool ret = true;
if ( ( _nubs->containsObject( client ) == false ) ||
( _openNubs->containsObject( client ) == true ) )
return false;
if ( _openNubs->getCount() == 0 )
ret = _provider->open( this );
if ( ret )
{
_openNubs->setObject( client );
if ( arg ) *((IOService **) arg) = _provider;
}
return ret;
}
void
AppleIntelPIIXMultiATADriver::handleClose( IOService * client,
IOOptionBits options )
{
if ( _openNubs->containsObject( client ) == false ) return;
_openNubs->removeObject( client );
if ( _openNubs->getCount() == 0 )
_provider->close( this );
}
bool
AppleIntelPIIXMultiATADriver::handleIsOpen( const IOService * client ) const
{
if ( client )
return _openNubs->containsObject( client );
else
return ( _openNubs->getCount() != 0 );
}
void
AppleIntelPIIXMultiATADriver::pciConfigWrite8( UInt8 offset,
UInt8 data,
UInt8 mask )
{
union {
UInt32 b32;
UInt8 b8[4];
} u;
UInt8 byte = offset & 0x03;
IOLockLock( _pciConfigLock );
u.b32 = _provider->configRead32( offset );
u.b8[byte] &= ~mask;
u.b8[byte] |= (mask & data);
_provider->configWrite32( offset, u.b32 );
IOLockUnlock( _pciConfigLock );
}
void
AppleIntelPIIXMultiATADriver::pciConfigWrite16( UInt8 offset,
UInt16 data,
UInt16 mask )
{
union {
UInt32 b32;
UInt16 b16[2];
} u;
UInt8 word = (offset >> 1) & 0x01;
IOLockLock( _pciConfigLock );
u.b32 = _provider->configRead32( offset );
u.b16[word] &= ~mask;
u.b16[word] |= (mask & data);
_provider->configWrite32( offset, u.b32 );
IOLockUnlock( _pciConfigLock );
}
bool
AppleIntelPIIXMultiATADriver::serializeProperties( OSSerialize * s ) const
{
AppleIntelPIIXMultiATADriver * self;
char timingString[80];
if ( _provider )
{
sprintf( timingString, "0x40=%08lx 0x44=%08lx 0x48=%08lx 0x54=%04x",
_provider->configRead32( 0x40 ),
_provider->configRead32( 0x44 ),
_provider->configRead32( 0x48 ),
_provider->configRead16( 0x54 ) );
self = (AppleIntelPIIXMultiATADriver *) this;
self->setProperty( "PCI Timing Registers", timingString );
}
return super::serializeProperties(s);
}