#include <sys/cdefs.h>
__BEGIN_DECLS
#include <ppc/proc_reg.h>
#include <ppc/machine_routines.h>
#include <mach/mach_types.h>
__END_DECLS
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/IOKitKeys.h>
#include "MacRISC4PE.h"
static unsigned long macRISC4Speed[] = { 0, 1 };
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/pwr_mgt/IOPMPagingPlexus.h>
#include <IOKit/pwr_mgt/IOPMPowerSource.h>
#include <pexpert/pexpert.h>
extern char *gIOMacRISC4PMTree;
#define super ApplePlatformExpert
OSDefineMetaClassAndStructors(MacRISC4PE, ApplePlatformExpert);
bool MacRISC4PE::start(IOService *provider)
{
long machineType;
char compatStr[128];
char tmpName[32];
OSData *tmpData;
IORegistryEntry *powerMgtEntry;
UInt32 *primInfo;
const OSSymbol *nameKey, *compatKey, *nameValueSymbol;
const OSData *nameValueData, *compatValueData;
OSDictionary *pluginDict, *platFuncDict;
bool result;
kprintf ("MacRISC4PE::start - entered\n");
setChipSetType(kChipSetTypeCore2001);
provider_name = provider->getName();
machineType = kMacRISC4TypeUnknown;
if (provider_name != NULL) {
if (0 == strncmp(provider_name, "PowerMac", strlen("PowerMac")))
machineType = kMacRISC4TypePowerMac;
else if (0 == strncmp(provider_name, "RackMac", strlen("RackMac")))
machineType = kMacRISC4TypePowerMac;
else if (0 == strncmp(provider_name, "PowerBook", strlen("PowerBook")))
machineType = kMacRISC4TypePowerBook;
else if (0 == strncmp(provider_name, "iBook", strlen("iBook")))
machineType = kMacRISC4TypePowerBook;
else IOLog ("AppleMacRISC4PE - warning: unknown machineType\n");
}
isPortable = (machineType == kMacRISC4TypePowerBook);
setMachineType(machineType);
tmpData = OSDynamicCast(OSData, provider->getProperty("clock-frequency"));
if (tmpData == 0) {
kprintf ("MacRISC4PE::start - no clock-frequency property\n");
return false;
}
macRISC4Speed[0] = *(unsigned long *)tmpData->getBytesNoCopy();
#if 0
uniNRegEntry = provider->childFromPath("uni-n", gIODTPlane);
if (uniNRegEntry == 0) {
kprintf ("MacRISC4PE::start - no uni-n\n");
return false;
}
tmpData = OSDynamicCast(OSData, uniNRegEntry->getProperty("device-rev"));
if (tmpData == 0) return false;
uniNVersion = ((unsigned long *)tmpData->getBytesNoCopy())[0];
#endif
powerMgtEntry = retrievePowerMgtEntry ();
if (powerMgtEntry == 0)
{
kprintf ("didn't find power mgt node\n");
return false;
}
tmpData = OSDynamicCast(OSData, powerMgtEntry->getProperty ("prim-info"));
if (tmpData != 0)
{
primInfo = (unsigned long *)tmpData->getBytesNoCopy();
if (primInfo != 0)
{
_pePMFeatures = primInfo[3];
_pePrivPMFeatures = primInfo[4];
_peNumBatteriesSupported = ((primInfo[6]>>16) & 0x000000FF);
kprintf ("Public PM Features: %0x.\n",_pePMFeatures);
kprintf ("Privat PM Features: %0x.\n",_pePrivPMFeatures);
kprintf ("Num Internal Batteries Supported: %0x.\n", _peNumBatteriesSupported);
}
}
pmmutex = IOLockAlloc();
if (pmmutex == NULL)
return false;
else
IOLockInit( pmmutex );
result = super::start(provider);
nameKey = OSSymbol::withCStringNoCopy("name");
compatKey = OSSymbol::withCStringNoCopy("compatible");
platFuncDict = OSDictionary::withCapacity(2);
if (platFuncDict) {
strcpy(tmpName, "IOPlatformFunctionNub");
nameValueSymbol = OSSymbol::withCString(tmpName);
nameValueData = OSData::withBytes(tmpName, strlen(tmpName)+1);
platFuncDict->setObject (nameKey, nameValueData);
platFuncDict->setObject (compatKey, nameValueData);
if (plFuncNub = IOPlatformExpert::createNub (platFuncDict)) {
if (!plFuncNub->attach( this ))
IOLog ("NUB ATTACH FAILED for IOPlatformFunctionNub\n");
plFuncNub->setName (nameValueSymbol);
plFuncNub->registerService();
}
platFuncDict->release();
nameValueSymbol->release();
nameValueData->release();
} else return false;
if (!strcmp (provider_name, "PowerMac7,2") )
strcpy (compatStr, "PowerMac7_2");
else strcpy (compatStr, "MacRISC4");
pluginDict = OSDictionary::withCapacity(2);
if (pluginDict) {
strcpy(tmpName, "IOPlatformPlugin");
nameValueSymbol = OSSymbol::withCString(tmpName);
nameValueData = OSData::withBytes(tmpName, strlen(tmpName)+1);
pluginDict->setObject (nameKey, nameValueData);
strcat (compatStr, "_PlatformPlugin");
compatValueData = OSData::withBytes(compatStr, strlen(compatStr)+1);
pluginDict->setObject (compatKey, compatValueData);
if (ioPPluginNub = IOPlatformExpert::createNub (pluginDict)) {
if (!ioPPluginNub->attach( this ))
kprintf ("NUB ATTACH FAILED\n");
ioPPluginNub->setName (nameValueSymbol);
ioPPluginNub->registerService();
}
pluginDict->release();
nameValueSymbol->release();
nameValueData->release();
compatValueData->release();
} else return false;
nameKey->release();
compatKey->release();
kprintf ("MacRISC4PE::start - done\n");
return result;
}
IORegistryEntry * MacRISC4PE::retrievePowerMgtEntry (void)
{
IORegistryEntry * theEntry = 0;
IORegistryEntry * anObj = 0;
IORegistryIterator * iter;
OSString * powerMgtNodeName;
iter = IORegistryIterator::iterateOver (IORegistryEntry::getPlane(kIODeviceTreePlane), kIORegistryIterateRecursively);
if (iter)
{
powerMgtNodeName = OSString::withCString("power-mgt");
anObj = iter->getNextObject ();
while (anObj)
{
if (anObj->compareName(powerMgtNodeName))
{
theEntry = anObj;
break;
}
anObj = iter->getNextObject();
}
powerMgtNodeName->release();
iter->release ();
}
return theEntry;
}
bool MacRISC4PE::platformAdjustService(IOService *service)
{
const OSSymbol *keySymbol;
OSSymbol *tmpSymbol;
bool result;
IORegistryEntry *parentIC;
OSData *parentICData;
if (IODTMatchNubWithKeys(service, "cpu"))
{
parentICData = OSDynamicCast(OSData, service->getProperty(kMacRISC4ParentICKey));
if (parentICData == 0)
{
parentIC = fromPath("mac-io/mpic", gIODTPlane);
parentICData = OSDynamicCast(OSData, parentIC->getProperty("AAPL,phandle"));
service->setProperty(kMacRISC4ParentICKey, parentICData);
}
service->setProperty ("cpu-device-type", "MacRISC4CPU");
return true;
}
if (IODTMatchNubWithKeys(service, "open-pic"))
{
keySymbol = OSSymbol::withCStringNoCopy("InterruptControllerName");
tmpSymbol = (OSSymbol *)IODTInterruptControllerName(service);
result = service->setProperty(keySymbol, tmpSymbol);
return true;
}
if (IODTMatchNubWithKeys(service, "K2-GMAC"))
{
service->setProperty("IOPMPCIConfigSpaceVolatile", kOSBooleanFalse);
return true;
}
if (!strcmp(service->getName(), "programmer-switch"))
{
service->setProperty("mask_NMI", service);
return true;
}
if (!strcmp(service->getName(), "pmu"))
{
OSArray *tmpArray;
OSCollectionIterator *extIntList, *extIntListOldWay;
IORegistryEntry *extInt;
OSObject *extIntControllerName;
OSObject *extIntControllerData;
service->setProperty("no-nvram", service);
extIntList = extIntListOldWay = NULL;
extIntList = IODTFindMatchingEntries(getProvider(), kIODTRecursive, "'pmu-interrupt'");
if (extIntList) {
extInt = (IORegistryEntry *)extIntList->getNextObject();
if (extInt)
kprintf ("pmu - got pmu-interrupt node new way - name '%s'\n", extInt->getName());
else {
extIntListOldWay = IODTFindMatchingEntries(getProvider(), kIODTRecursive, "'extint-gpio1'");
extInt = (IORegistryEntry *)extIntListOldWay->getNextObject();
if (extInt)
kprintf ("pmu - got pmu-interrupt node old way - name '%s'\n", extInt->getName());
else
panic ("MacRISC4PE::platformAdjustService - no interrupt information for pmu");
}
}
tmpArray = (OSArray *)extInt->getProperty(gIOInterruptControllersKey);
extIntControllerName = tmpArray->getObject(0);
tmpArray = (OSArray *)extInt->getProperty(gIOInterruptSpecifiersKey);
extIntControllerData = tmpArray->getObject(0);
tmpArray = (OSArray *)service->getProperty(gIOInterruptControllersKey);
tmpArray->replaceObject(4, extIntControllerName);
tmpArray = (OSArray *)service->getProperty(gIOInterruptSpecifiersKey);
tmpArray->replaceObject(4, extIntControllerData);
if (extIntList) extIntList->release();
if (extIntListOldWay) extIntListOldWay->release();
return true;
}
if (!strcmp(service->getName(), "via-pmu"))
{
service->setProperty("BusSpeedCorrect", this);
return true;
}
return true;
}
IOReturn MacRISC4PE::callPlatformFunction(const OSSymbol *functionName,
bool waitForFunction,
void *param1, void *param2,
void *param3, void *param4)
{
if (functionName == gGetDefaultBusSpeedsKey)
{
getDefaultBusSpeeds((long *)param1, (unsigned long **)param2);
return kIOReturnSuccess;
}
if (functionName->isEqualTo("PlatformIsPortable")) {
*(bool *) param1 = isPortable;
return kIOReturnSuccess;
}
return super::callPlatformFunction(functionName, waitForFunction, param1, param2, param3, param4);
}
void MacRISC4PE::getDefaultBusSpeeds(long *numSpeeds, unsigned long **speedList)
{
if ((numSpeeds == 0) || (speedList == 0)) return;
*numSpeeds = 1;
*speedList = macRISC4Speed;
}
void MacRISC4PE::PMInstantiatePowerDomains ( void )
{
IOPMUSBMacRISC4 * usbMacRISC4;
const OSSymbol *desc = OSSymbol::withCString("powertreedesc");
kprintf ("MacRISC4PE::PMInstantiatePowerDomains - getting pmtree property\n");
thePowerTree = OSDynamicCast(OSArray, getProperty(desc));
if( 0 == thePowerTree)
{
kprintf ("error retrieving power tree\n");
return;
}
kprintf ("MacRISC4PE::PMInstantiatePowerDomains - got pmtree property\n");
getProvider()->setProperty (desc, thePowerTree);
removeProperty(desc);
root = IOPMrootDomain::construct();
root->attach(this);
root->start(this);
root->setSleepSupported(kRootDomainSleepSupported);
if (NULL == root)
{
kprintf ("PMInstantiatePowerDomains - null ROOT\n");
return;
}
PMRegisterDevice (NULL, root);
usbMacRISC4 = new IOPMUSBMacRISC4;
if (usbMacRISC4)
{
usbMacRISC4->init ();
usbMacRISC4->attach (this);
usbMacRISC4->start (this);
PMRegisterDevice (root, usbMacRISC4);
}
slotsMacRISC4 = new IOPMSlotsMacRISC4;
if (slotsMacRISC4)
{
slotsMacRISC4->init ();
slotsMacRISC4->attach (this);
slotsMacRISC4->start (this);
PMRegisterDevice (root, slotsMacRISC4);
}
return;
}
extern const IORegistryPlane * gIOPowerPlane;
void MacRISC4PE::PMRegisterDevice(IOService * theNub, IOService * theDevice)
{
bool nodeFound = false;
IOReturn err = -1;
OSData * propertyPtr = 0;
const char * theProperty;
if (pmmutex != NULL)
IOLockLock(pmmutex);
multipleParentKeyValue = NULL;
numInstancesRegistered = 0;
nodeFound = CheckSubTree (thePowerTree, theNub, theDevice, NULL);
if (0 == numInstancesRegistered) {
while( theNub && (!theNub->inPlane(gIOPowerPlane)))
theNub = theNub->getProvider();
}
if (pmmutex != NULL)
IOLockUnlock(pmmutex);
if ( NULL != theNub )
err = theNub->addPowerChild (theDevice);
if ((err != IOPMNoErr) && (0 == numInstancesRegistered) && (theDevice != root)) {
root->addPowerChild (theDevice);
}
propertyPtr = OSDynamicCast(OSData,theDevice->getProperty("AAPL,slot-name"));
if ( propertyPtr ) {
theProperty = (const char *) propertyPtr->getBytesNoCopy();
if ( strncmp("SLOT-",theProperty,5) == 0 )
slotsMacRISC4->addPowerChild (theDevice);
}
return;
}