#include <ppc/proc_reg.h>
#include <IOKit/IOLib.h>
#include "USBKeyLargo.h"
#define super IOService
OSDefineMetaClassAndStructors(USBKeyLargo, IOService);
bool
USBKeyLargo::initForBus(UInt32 busNumber, SInt32 devID)
{
setProperty("usb", (UInt64)busNumber, 32);
setProperty("IOClass", "USBKeyLargo");
keyLargoDeviceId = devID;
initForPM(getProvider());
return true;
}
void USBKeyLargo::initForPM (IOService *provider)
{
PMinit(); provider->joinPMtree(this);
#define kNumberOfPowerStates 2
static IOPMPowerState ourPowerStates[kNumberOfPowerStates] = {
{1,0,0,0,0,0,0,0,0,0,0,0},
{1,IOPMDeviceUsable,IOPMClockNormal | IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0}
};
if (pm_vars != NULL)
registerPowerDriver(this, ourPowerStates, kNumberOfPowerStates);
return;
}
IOReturn USBKeyLargo::setPowerState(unsigned long powerStateOrdinal, IOService* whatDevice)
{
if (powerStateOrdinal >= kNumberOfPowerStates)
return IOPMAckImplied;
OSNumber *propertyValue;
propertyValue = OSDynamicCast( OSNumber, getProperty("usb"));
if (propertyValue == NULL)
return IOPMAckImplied;
if ( powerStateOrdinal == 0 ) {
kprintf("USBKeyLargo would be powered off here\n");
turnOffUSB(propertyValue->unsigned32BitValue());
}
if ( powerStateOrdinal == 1 ) {
kprintf("USBKeyLargo would be powered on here\n");
turnOnUSB(propertyValue->unsigned32BitValue());
}
return IOPMAckImplied;
}
void USBKeyLargo::turnOffUSB(UInt32 busNumber)
{
UInt32 regMask, regData;
KeyLargo *provider = OSDynamicCast(KeyLargo, getProvider());
if (provider == NULL) {
IOLog("USBKeyLargo::turnOffUSB missing provider, can not proceed");
return;
}
if (busNumber != 2) {
if (busNumber == 0) {
regMask = kKeyLargoFCR4USB0SleepBitsSet | kKeyLargoFCR4USB0SleepBitsClear;
regData = kKeyLargoFCR4USB0SleepBitsSet & ~kKeyLargoFCR4USB0SleepBitsClear;
} else {
regMask = kKeyLargoFCR4USB1SleepBitsSet | kKeyLargoFCR4USB1SleepBitsClear;
regData = kKeyLargoFCR4USB1SleepBitsSet & ~kKeyLargoFCR4USB1SleepBitsClear;
}
provider->safeWriteRegUInt32(kKeyLargoFCR4, regMask, regData);
} else { regMask = kIntrepidFCR3USB2SleepBitsSet | kIntrepidFCR3USB2SleepBitsClear;
regData = kIntrepidFCR3USB2SleepBitsSet & ~kIntrepidFCR3USB2SleepBitsClear;
provider->safeWriteRegUInt32(kKeyLargoFCR3, regMask, regData);
}
IODelay(1);
if (keyLargoDeviceId != kIntrepidDeviceId3e) {
if (busNumber != 2) {
regData = 0;
regMask = (busNumber == 0) ? kKeyLargoFCR0USB0CellEnable : kKeyLargoFCR0USB1CellEnable;
provider->safeWriteRegUInt32(kKeyLargoFCR0, regMask, regData);
}
}
IODelay(1);
if (busNumber != 2) {
regData = regMask = (busNumber == 0) ? (kKeyLargoFCR0USB0PadSuspend0 | kKeyLargoFCR0USB0PadSuspend1 ) :
(kKeyLargoFCR0USB1PadSuspend0 | kKeyLargoFCR0USB1PadSuspend1);
provider->safeWriteRegUInt32(kKeyLargoFCR0, regMask, regData);
} else { regData = regMask = (kIntrepidFCR1USB2PadSuspend0 | kIntrepidFCR1USB2PadSuspend1);
provider->safeWriteRegUInt32(kKeyLargoFCR1, regMask, regData);
}
IODelay(1);
return;
}
void USBKeyLargo::turnOnUSB(UInt32 busNumber)
{
UInt32 regMask, regData;
KeyLargo *provider = OSDynamicCast(KeyLargo, getProvider());
if (provider == NULL) {
IOLog("USBKeyLargo::turnOnUSB missing provider, cannot proceed");
return;
}
if (busNumber != 2) {
regData = 0; regMask = (busNumber == 0) ? (kKeyLargoFCR0USB0PadSuspend0 | kKeyLargoFCR0USB0PadSuspend1) :
(kKeyLargoFCR0USB1PadSuspend0 | kKeyLargoFCR0USB1PadSuspend1);
provider->safeWriteRegUInt32(kKeyLargoFCR0, regMask, regData);
} else { regData = 0; regMask = (kIntrepidFCR1USB2PadSuspend0 | kIntrepidFCR1USB2PadSuspend1);
provider->safeWriteRegUInt32(kKeyLargoFCR1, regMask, regData);
}
IODelay(1000);
if (busNumber != 2) {
regData = regMask = (busNumber == 0) ? (kKeyLargoFCR0USB0CellEnable) : (kKeyLargoFCR0USB1CellEnable);
provider->safeWriteRegUInt32(kKeyLargoFCR0, regMask, regData);
if (busNumber == 0) {
regMask = kKeyLargoFCR4USB0SleepBitsSet | kKeyLargoFCR4USB0SleepBitsClear;
regData = ~kKeyLargoFCR4USB0SleepBitsSet & kKeyLargoFCR4USB0SleepBitsClear;
} else {
regMask = kKeyLargoFCR4USB1SleepBitsSet | kKeyLargoFCR4USB1SleepBitsClear;
regData = ~kKeyLargoFCR4USB1SleepBitsSet & kKeyLargoFCR4USB1SleepBitsClear;
}
provider->safeWriteRegUInt32(kKeyLargoFCR4, regMask, regData);
} else { regData = regMask = kIntrepidFCR1USB2CellEnable;
provider->safeWriteRegUInt32(kKeyLargoFCR1, regMask, regData);
regMask = kIntrepidFCR3USB2SleepBitsSet | kIntrepidFCR3USB2SleepBitsClear;
regData = ~kIntrepidFCR3USB2SleepBitsSet & kIntrepidFCR3USB2SleepBitsClear;
provider->safeWriteRegUInt32(kKeyLargoFCR3, regMask, regData);
}
if (keyLargoDeviceId == kIntrepidDeviceId3e) {
UInt32 clockStopMask0, clockStopMask1;
volatile UInt32 clockStopStatus0, clockStopStatus1;
UInt32 count = 0;
static const OSSymbol *symReadIntrepidClockStopStatus;
if (!symReadIntrepidClockStopStatus)
symReadIntrepidClockStopStatus = OSSymbol::withCString("readIntrepidClockStopStatus");
if (busNumber == 0) {
clockStopMask0 = kIntrepidIsStoppedUSB0;
clockStopMask1 = kIntrepidIsStoppedUSB1PCI;
} else if (busNumber == 1) {
clockStopMask0 = kIntrepidIsStoppedUSB1;
clockStopMask1 = kIntrepidIsStoppedUSB1PCI;
} else if (busNumber == 2) {
clockStopMask0 = kIntrepidIsStoppedUSB2;
clockStopMask1 = kIntrepidIsStoppedUSB2PCI;
} else { clockStopMask0 = 0;
clockStopMask1 = 0;
}
do {
IODelay (500);
if (provider->callPlatformFunction (symReadIntrepidClockStopStatus, false, (void *)&clockStopStatus0,
(void *)&clockStopStatus1, (void *)0, (void *)0) != kIOReturnSuccess)
break;
if (count++ > 100) {
IOLog ("USBKeyLargo::turnOnUSB bus %ld - giving up after 100 tries\n", busNumber);
break;
}
} while ((clockStopStatus0 & clockStopMask0) || (clockStopStatus1 & clockStopMask1));
}
return;
}
unsigned long USBKeyLargo::maxCapabilityForDomainState(
IOPMPowerFlags domainState )
{
if( (domainState & IOPMPowerOn) || (domainState & IOPMSoftSleep) )
return( kNumberOfPowerStates - 1);
else
return( 0);
}