UniNPowerSaver.cpp [plain text]
#include "UniNEnet.h"
#include "UniNEnetMII.h"
#include <libkern/OSByteOrder.h>
#define super IOEthernetController
static IOPMPowerState ourPowerStates[ kNumOfPowerStates ] =
{
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, IOPMDeviceUsable | IOPMMaxPerformance, IOPMPowerOn, IOPMPowerOn,
50, 0, 0, kUniNsettle_time, kUniNsettle_time, kUniNsettle_time,
kUniNsettle_time, 0 }
};
IOReturn UniNEnet::registerWithPolicyMaker( IOService *policyMaker )
{
IOReturn rc;
ELG( IOThreadSelf(), 0, 'RwPM', "registerWithPolicyMaker" );
if ( fBuiltin )
rc = policyMaker->registerPowerDriver( this, ourPowerStates, kNumOfPowerStates );
else rc = super::registerWithPolicyMaker( policyMaker );
return rc;
}
unsigned long UniNEnet::maxCapabilityForDomainState( IOPMPowerFlags domainState )
{
ELG( IOThreadSelf(), domainState, 'mx4d', "maxCapabilityForDomainState" );
if ( domainState & IOPMPowerOn )
return kNumOfPowerStates - 1;
return 0;
}
unsigned long UniNEnet::initialPowerStateForDomainState( IOPMPowerFlags domainState )
{
ELG( IOThreadSelf(), domainState, 'ip4d', "initialPowerStateForDomainState" );
if ( domainState & IOPMPowerOn )
return kNumOfPowerStates - 1;
return 0;
}
unsigned long UniNEnet::powerStateForDomainState(IOPMPowerFlags domainState )
{
ELG( IOThreadSelf(), domainState, 'ps4d', "powerStateForDomainState" );
if ( domainState & IOPMPowerOn )
return 1;
return 0;
}
IOReturn UniNEnet::setPowerState( unsigned long powerStateOrdinal,
IOService *whatDevice )
{
ELG( IOThreadSelf(), (currentPowerState << 16) | powerStateOrdinal, 'Pwr!', "setPowerState" );
if ( powerStateOrdinal >= kNumOfPowerStates )
return IOPMNoSuchState;
if ( powerStateOrdinal == currentPowerState )
return IOPMAckImplied;
return IOPMAckImplied;
}
void UniNEnet::stopPHY()
{
UInt32 val32;
UInt16 i, val16;
ELG( fWOL, fPHYType, '-Phy', "stopPHY" );
if ( !fBuiltin || (fPHYType == 0) )
return;
if ( fWOL == false )
{
if ( fPHYType == 0x5201 )
{
miiWriteWord( 0x0000, MII_BCM5201_INTERRUPT, kPHYAddr0 );
}
}
val32 = READ_REGISTER( MIFConfiguration );
val32 &= ~kMIFConfiguration_Poll_Enable;
WRITE_REGISTER( MIFConfiguration, val32 );
miiReadWord( &val16, MII_LINKPARTNER, kPHYAddr0 );
miiWriteWord( val16, MII_LINKPARTNER, kPHYAddr0 );
if ( fWOL )
{
WRITE_REGISTER( RxMACConfiguration, kRxMACConfiguration_Hash_Filter_Enable
| kRxMACConfiguration_Strip_FCS
| kRxMACConfiguration_Rx_Mac_Enable );
UInt16 *p16;
p16 = (UInt16*)myAddress.bytes;
WRITE_REGISTER( WOLMagicMatch[ 2 ], p16[ 0 ] ); WRITE_REGISTER( WOLMagicMatch[ 1 ], p16[ 1 ] );
WRITE_REGISTER( WOLMagicMatch[ 0 ], p16[ 2 ] );
WRITE_REGISTER( WOLPatternMatchCount, kWOLPatternMatchCount_M | kWOLPatternMatchCount_N );
val32 = kWOLWakeupCSR_Magic_Wakeup_Enable; if ( !(fXIFConfiguration & kXIFConfiguration_GMIIMODE) )
val32 |= kWOLWakeupCSR_Mode_MII; WRITE_REGISTER( WOLWakeupCSR, val32 );
}
else
{
WRITE_REGISTER( RxMACConfiguration, 0 );
IOSleep( 4 ); }
WRITE_REGISTER( TxMACConfiguration, 0 );
WRITE_REGISTER( XIFConfiguration, 0 );
WRITE_REGISTER( TxConfiguration, 0 );
WRITE_REGISTER( RxConfiguration, 0 );
if ( !fWOL )
{
WRITE_REGISTER( SoftwareReset, kSoftwareReset_TX | kSoftwareReset_RX );
i = 0;
do
{
IODelay( 10 );
if ( i++ >= 100 )
{
ALRT( 0, val32, 'Sft-', "stopPHY - timeout on SoftwareReset" );
break;
}
val32 = READ_REGISTER( SoftwareReset );
} while ( (val32 & (kSoftwareReset_TX | kSoftwareReset_RX)) != 0 );
WRITE_REGISTER( TxMACSoftwareResetCommand, kTxMACSoftwareResetCommand_Reset );
WRITE_REGISTER( RxMACSoftwareResetCommand, kRxMACSoftwareResetCommand_Reset );
switch ( fPHYType )
{
case 0x5400:
case 0x5401:
#if 0
miiWriteWord( MII_CONTROL_POWERDOWN, MII_CONTROL, kPHYAddr0 );
#endif
break;
case 0x5221:
miiReadWord( &val16, MII_BCM5221_TestRegister, kPHYAddr0 );
miiWriteWord( val16 | MII_BCM5221_ShadowRegEnableBit, MII_BCM5221_TestRegister, kPHYAddr0 );
miiReadWord( &val16, MII_BCM5221_AuxiliaryMode4, kPHYAddr0 );
miiWriteWord( val16 | MII_BCM5221_SetIDDQMode, MII_BCM5221_AuxiliaryMode4, kPHYAddr0 );
break;
case 0x5201:
#if 0
miiReadWord( &val16, MII_BCM5201_AUXMODE2, kPHYAddr0 );
miiWriteWord( val16 & ~MII_BCM5201_AUXMODE2_LOWPOWER,
MII_BCM5201_AUXMODE2, kPHYAddr0 );
#endif
miiWriteWord( MII_BCM5201_MULTIPHY_SUPERISOLATE,
MII_BCM5201_MULTIPHY,
kPHYAddr0 );
break;
case 0x5411:
case 0x5421:
default:
miiWriteWord( MII_CONTROL_POWERDOWN, MII_CONTROL, kPHYAddr0 );
break;
}
WRITE_REGISTER( MIFConfiguration, kMIFConfiguration_BB_Mode );
WRITE_REGISTER( MIFBitBangClock, 0x0000 );
WRITE_REGISTER( MIFBitBangData, 0x0000 );
WRITE_REGISTER( MIFBitBangOutputEnable, 0x0000 );
WRITE_REGISTER( XIFConfiguration, kXIFConfiguration_GMIIMODE
| kXIFConfiguration_MII_Int_Loopback );
val32 = READ_REGISTER( XIFConfiguration ); }
return;
}
void UniNEnet::startPHY()
{
UInt32 val32;
UInt16 val16;
ELG( this, fPHYType, 'Phy+', "startPHY" );
val32 = READ_REGISTER( TxConfiguration );
WRITE_REGISTER( TxConfiguration, val32 | kTxConfiguration_Tx_DMA_Enable );
val32 = READ_REGISTER( RxConfiguration );
WRITE_REGISTER( RxConfiguration, val32 | kRxConfiguration_Rx_DMA_Enable );
val32 = READ_REGISTER( TxMACConfiguration );
WRITE_REGISTER( TxMACConfiguration, val32 | kTxMACConfiguration_TxMac_Enable );
val32 = READ_REGISTER( RxMACConfiguration ); val32 |= kRxMACConfiguration_Rx_Mac_Enable | kRxMACConfiguration_Hash_Filter_Enable;
if ( fIsPromiscuous )
val32 &= ~kRxMACConfiguration_Strip_FCS;
else val32 |= kRxMACConfiguration_Strip_FCS;
WRITE_REGISTER( RxMACConfiguration, val32 );
if ( fPHYType == 0x5201 )
{
miiReadWord( &val16, MII_BCM5201_MULTIPHY, kPHYAddr0 );
miiWriteWord( val16 & ~MII_BCM5201_MULTIPHY_SUPERISOLATE,
MII_BCM5201_MULTIPHY, kPHYAddr0 );
#if 0
miiReadWord( &val16, MII_BCM5201_AUXMODE2, kPHYAddr0 );
miiWriteWord( val16 | MII_BCM5201_AUXMODE2_LOWPOWER,
MII_BCM5201_AUXMODE2, kPHYAddr0 );
#endif
}
WRITE_REGISTER( RxKick, fRxRingElements - 4 );
return;
}
bool UniNEnet::hardwareResetPHY()
{
IOReturn result;
result = keyLargo->callPlatformFunction( keyLargo_resetUniNEthernetPhy, false, 0, 0, 0, 0 );
ELG( keyLargo, result, 'RPhy', "hardwareResetPHY" );
if ( result != kIOReturnSuccess )
return false;
return true;
}
#ifdef NOT_YET
IOReturn UniNEnet::powerStateWillChangeTo( IOPMPowerFlags flags,
UInt32 stateNumber,
IOService* policyMaker )
{
IOReturn rc = IOPMAckImplied;
ELG( IOThreadSelf(), (stateNumber << 16) | (flags & 0xFFFF), 'Wil1', "powerStateWillChangeTo - before calling superclass." );
rc = super::powerStateWillChangeTo( flags, stateNumber, policyMaker );
ELG( stateNumber, rc, 'Wil2', "powerStateWillChangeTo - after calling superclass." );
return rc;
}
IOReturn UniNEnet::powerStateDidChangeTo( IOPMPowerFlags flags,
UInt32 stateNumber,
IOService* policyMaker )
{
IOReturn rc = IOPMAckImplied;
ELG( IOThreadSelf(), (stateNumber << 16) | (flags & 0xFFFF), 'Did1', "powerStateDidChangeTo - before calling superclass." );
rc = super::powerStateDidChangeTo( flags, stateNumber, policyMaker );
ELG( stateNumber, rc, 'Did2', "powerStateDidChangeTo - after calling superclass." );
return rc;
}
#endif // NOT_YET