AppleK2SATARoot.cpp [plain text]
#include <ppc/proc_reg.h>
#include "AppleK2SATARoot.h"
#include <IOKit/assert.h>
#include <IOKit/IOTypes.h>
#include <IOKit/IOLib.h>
#include <IOKit/pci/IOPCIDevice.h>
#include <libkern/OSByteOrder.h>
#include <libkern/OSAtomic.h>
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/IOPlatformExpert.h>
#include <IOKit/pwr_mgt/IOPM.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/ata/IOATATypes.h>
#include <kern/clock.h>
#ifdef DLOG
#undef DLOG
#endif
#ifdef K2_SATA_ROOT_DEBUG
#define DLOG(fmt, args...) IOLog(fmt, ## args)
#else
#define DLOG(fmt, args...)
#endif
#define kDeviceTypeString "pci-ide"
#define kDevicetypeKey "device_type"
#define kNameKey "name"
#define kNameString "s-ata"
#define kCompatibleKey "compatible"
#define kCompatibleString "k2-s-ata"
#define super IOService
OSDefineMetaClassAndStructors ( AppleK2SATARoot, IOService )
bool
AppleK2SATARoot::init(OSDictionary* properties)
{
DLOG("AppleK2SATARoot init start\n");
baseZeroMap = baseOneMap = baseTwoMap = baseThreeMap = baseFourMap = baseFiveMap = 0;
baseAddrZero = baseAddrOne = baseAddrTwo = baseAddrThree = baseAddrFour = baseAddrFive = 0;
nubIntSrc = 0;
if (super::init(properties) == false)
{
DLOG("AppleK2SATARoot: super::init() failed\n");
return false;
}
DLOG("AppleK2SATARoot init done\n");
return true;
}
IOService*
AppleK2SATARoot::probe(IOService* provider, SInt32* score)
{
OSData *compatibleEntry;
DLOG("AppleK2SATARoot starting probe\n");
compatibleEntry = OSDynamicCast( OSData, provider->getProperty( kCompatibleKey ) );
if ( compatibleEntry == 0 )
{
DLOG("AppleK2SATARoot failed getting compatible property\n");
return 0;
}
if ( compatibleEntry->isEqualTo( kCompatibleString, sizeof(kCompatibleString)-1 ) == false )
{
DLOG("AppleK2SATARoot compatible property doesn't match\n");
return 0;
}
IOPCIDevice* pciNub = (IOPCIDevice*) provider;
UInt8 functNum = pciNub->getFunctionNumber();
if( functNum > 0)
{
DLOG("AppleK2SATARoot function number = %X\n", functNum);
return 0;
}
return this;
}
bool
AppleK2SATARoot::start( IOService * provider )
{
DLOG("AppleK2SATARoot: starting\n");
static const IOPMPowerState powerStates[ 2 ] = {
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, IOPMPowerOn, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 }
};
IOPCIDevice *pciNub = (IOPCIDevice *)provider;
if( !super::start( provider))
return( false);
pciNub->setMemoryEnable(true);
pciNub->setBusMasterEnable( true );
baseFiveMap = getProvider()->mapDeviceMemoryWithIndex( 0 );
if( baseFiveMap == 0 )
{
DLOG("AppleK2SATARoot: Failed to get base address maps\n");
return false;
}
baseAddrFive = (UInt8*) baseFiveMap->getVirtualAddress();
DLOG("AppleK2SATARoot: baseAddrFive = %lx \n", (UInt32) baseAddrFive);
intController = new AppleK2SATAIC;
if( ! intController )
{
DLOG("AppleKiwiRoot: failed to create intController\n");
return false;
}
if( !intController->init(NULL) )
{
DLOG("AppleKiwiRoot: failed to init intController\n");
return false;
}
if( !intController->start(provider,baseAddrFive) )
{
DLOG("AppleKiwiRoot: failed to start intController\n");
return false;
}
isSleeping = false;
PMinit();
registerPowerDriver(this,(IOPMPowerState *)powerStates,2);
joinPMtree(this);
publishBelow(provider);
DLOG("AppleK2SATARoot: started\n");
return( true);
}
void
AppleK2SATARoot::free()
{
if( baseZeroMap )
{
baseZeroMap->release();
}
if( baseOneMap )
{
baseOneMap->release();
}
if( baseTwoMap )
{
baseTwoMap->release();
}
if( baseThreeMap)
{
baseThreeMap->release();
}
if( baseFourMap )
{
baseFourMap->release();
}
if( baseFiveMap )
{
baseFiveMap->release();
}
super::free();
}
AppleK2SATADevice *
AppleK2SATARoot::createNub( IORegistryEntry * from )
{
AppleK2SATADevice * nub;
nub = new AppleK2SATADevice;
if( nub && !nub->init( from, gIODTPlane ))
{
nub->free();
nub = 0;
}
return( nub);
}
void
AppleK2SATARoot::processNub(AppleK2SATADevice * nub)
{
nub->setDeviceMemory( getProvider()->getDeviceMemory());
}
void
AppleK2SATARoot::publishBelow( IORegistryEntry * root )
{
DLOG("AppleK2SATARoot publish below\n");
AppleK2SATADevice * nub;
OSCollectionIterator * kids = 0;
IORegistryEntry * next;
SInt32 nubCount = 0;
kids = IODTFindMatchingEntries( root, kIODTRecursive | kIODTExclusive, "('ata-disk','atapi-disk','disk')");
if( kids)
{
DLOG("AppleK2SATARoot found kids\n");
while( (next = (IORegistryEntry *)kids->getNextObject()))
{
if( 0 == (nub = createNub( next )))
continue;
if( !nub )
{
DLOG("AppleK2SATARoot failed to create nub\n");
return;
}
nubCount++;
nub->attach( this );
processNub(nub);
nub->registerService();
}
kids->release();
}
DLOG("AppleK2SATARoot nub count = %d \n", nubCount);
for( SInt32 i = 3; i >= nubCount; i--)
{
OSWriteLittleInt32( baseAddrFive, (i * 0x100) + 0x48, 0x3); DLOG( "K2 SATA Root disabling port %d not in use\n", i);
}
}
bool
AppleK2SATARoot::compareNubName( const IOService * nub,
OSString * name, OSString ** matched ) const
{
return( IODTCompareNubName( nub, name, matched )
|| nub->IORegistryEntry::compareName( name, matched ) );
}
IOReturn
AppleK2SATARoot::getNubResources( IOService * nub )
{
if( nub->getDeviceMemory())
return( kIOReturnSuccess );
IODTResolveAddressing( nub, "reg", getProvider()->getDeviceMemoryWithIndex(5) );
return( kIOReturnSuccess);
}
void
AppleK2SATARoot::sDeviceInterruptOccurred(OSObject * owner, IOInterruptEventSource *evtSrc, int count)
{
return;
}
IOReturn
AppleK2SATARoot::setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice )
{
if( powerStateOrdinal == 0
&& !(isSleeping) )
{
DLOG("AppleK2SATARoot power ordinal 0\n");
isSleeping = true;
}
if( powerStateOrdinal == 1
&& (isSleeping) )
{
DLOG("AppleK2SATARoot power ordinal 1\n");
isSleeping = false;
}
return IOPMAckImplied;
}
#pragma mark -
#ifdef DLOG
#undef DLOG
#endif
#undef super
#define super IOService
OSDefineMetaClassAndStructors ( AppleK2SATADevice, IOService )
IOService*
AppleK2SATADevice::matchLocation( IOService * )
{
return( this );
}
IOReturn
AppleK2SATADevice::getResources( void )
{
return( ((AppleK2SATARoot *)getProvider())->getNubResources( this ));
}
#pragma mark -
#ifdef DLOG
#undef DLOG
#endif
#ifdef K2SATA_IC_DEBUG
#define DLOG(fmt, args...) IOLog(fmt, ## args)
#else
#define DLOG(fmt, args...)
#endif
#undef super
#define super IOInterruptController
#define K2SATANumVectors 4
OSDefineMetaClassAndStructors(AppleK2SATAIC, IOInterruptController);
enum {
kIOSLICPowerStateCount = 2
};
bool
AppleK2SATAIC::start(IOService *provider, UInt8* inBar5)
{
if( !provider || !inBar5 )
return false;
if (!super::start(provider))
{
DLOG ("AppleK2SATAIC::start - super::start(provider) returned false\n");
return false;
}
interruptControllerName = (OSSymbol *)IODTInterruptControllerName( provider );
if (interruptControllerName == 0) {
DLOG ("AppleK2SATAIC::start - interruptControllerName is NULL\n");
return false;
}
UInt32 numVectors = K2SATANumVectors;
UInt32 sizeofVectors = numVectors * sizeof(IOInterruptVector);
vectors = (IOInterruptVector *)IOMalloc(sizeofVectors);
if (vectors == NULL) {
DLOG ("AppleK2SATAIC::start - cannot allocate vectors\n");
return false;
}
bzero(vectors, sizeofVectors);
for (unsigned int cnt = 0; cnt < numVectors ; cnt++) {
vectors[cnt].interruptLock = IOLockAlloc();
if (vectors[cnt].interruptLock == NULL) {
for (cnt = 0; cnt < numVectors; cnt++) {
if (vectors[cnt].interruptLock != NULL)
IOLockFree(vectors[cnt].interruptLock);
}
DLOG ("AppleK2SATAIC::start - cannot allocate lock for vectors[%d]\n", cnt);
return false;
}
}
provider->registerInterrupt(0, this, getInterruptHandlerAddress(), 0);
getPlatform()->registerInterruptController(interruptControllerName, this);
provider->enableInterrupt(0);
DLOG ("AppleK2SATAIC::start - finished\n");
return true;
}
IOReturn
AppleK2SATAIC::getInterruptType(IOService *nub, int source,
int *interruptType)
{
if (interruptType == 0) return kIOReturnBadArgument;
*interruptType = kIOInterruptTypeLevel;
return kIOReturnSuccess;
}
IOInterruptAction
AppleK2SATAIC::getInterruptHandlerAddress(void)
{
return (IOInterruptAction) &AppleK2SATAIC::handleInterrupt ;
}
IOReturn
AppleK2SATAIC::handleInterrupt( void* ,
IOService* ,
int )
{
long vectorNumber = 0;
IOInterruptVector *vector;
for(int i = 0; i < K2SATANumVectors; i++)
{
vectorNumber = i;
vector = &vectors[vectorNumber];
vector->interruptActive = 1;
sync();
isync();
if (!vector->interruptDisabledSoft) {
isync();
if (vector->interruptRegistered) {
vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
if (vector->interruptDisabledSoft) {
vector->interruptDisabledHard = 1;
disableVectorHard(vectorNumber, vector);
}
}
} else {
vector->interruptDisabledHard = 1;
disableVectorHard(vectorNumber, vector);
}
vector->interruptActive = 0;
}
return kIOReturnSuccess;
}
bool
AppleK2SATAIC::vectorCanBeShared(long vectorNumber, IOInterruptVector *vector)
{
return false;
}
void
AppleK2SATAIC::initVector(long vectorNumber, IOInterruptVector *vector)
{
return;
}
void
AppleK2SATAIC::disableVectorHard(long vectorNumber, IOInterruptVector *vector)
{
switch( vectorNumber )
{
default:
break; }
}
void
AppleK2SATAIC::enableVector(long vectorNumber, IOInterruptVector *vector)
{
switch( vectorNumber )
{
default:
break; }
}