UniNPowerSaver.cpp [plain text]
#include <libkern/OSByteOrder.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include "UniNEnet.h"
#include "UniNEnetMII.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;
if ( fBuiltin )
rc = policyMaker->registerPowerDriver( this, ourPowerStates, kNumOfPowerStates );
else rc = super::registerWithPolicyMaker( policyMaker );
ELG( IOThreadSelf(), rc, 'RwPM', "registerWithPolicyMaker" );
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', "UniNEnet::powerStateForDomainState" );
if ( domainState & IOPMPowerOn )
return 1;
return 0;
}
void UniNEnet::stopPHY()
{
UInt32 val32;
UInt16 i, val16;
ELG( fWOL, fPHYType, '-Phy', "UniNEnet::stopPHY" );
if ( !fBuiltin || (fPHYType == 0) )
return;
if ( fWOL == false )
{ if ( fPHYType == 0x5201 )
miiWriteWord( 0x0000, MII_BCM5201_INTERRUPT );
}
val32 = READ_REGISTER( MIFConfiguration );
val32 &= ~kMIFConfiguration_Poll_Enable;
WRITE_REGISTER( MIFConfiguration, val32 );
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 );
fTxConfiguration &= ~kTxConfiguration_Tx_DMA_Enable;
WRITE_REGISTER( TxConfiguration, fTxConfiguration );
fRxConfiguration &= ~kRxConfiguration_Rx_DMA_Enable;
WRITE_REGISTER( RxConfiguration, fRxConfiguration );
if ( !fWOL )
{
WRITE_REGISTER( SoftwareReset, kSoftwareReset_TX | kSoftwareReset_RX );
i = 0;
do
{
IODelay( 10 );
if ( i++ >= 100 )
{
ALRT( 0, val32, 'Sft-', "UniNEnet::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 );
#endif
break;
case 0x5221:
miiReadWord( &val16, MII_BCM5221_TestRegister );
miiWriteWord( val16 | MII_BCM5221_ShadowRegEnableBit, MII_BCM5221_TestRegister );
miiReadWord( &val16, MII_BCM5221_AuxiliaryMode4 );
miiWriteWord( val16 | MII_BCM5221_SetIDDQMode, MII_BCM5221_AuxiliaryMode4 );
break;
case 0x5241:
miiReadWord( &val16, MII_BCM5221_TestRegister );
miiWriteWord( val16 | MII_BCM5221_ShadowRegEnableBit, MII_BCM5221_TestRegister );
miiReadWord( &val16, MII_BCM5221_AuxiliaryMode4 );
miiWriteWord( val16 | MII_BCM5241_StandbyPowerMode, MII_BCM5221_AuxiliaryMode4 );
break;
case 0x5201:
#if 0
miiReadWord( &val16, MII_BCM5201_AUXMODE2 );
miiWriteWord( val16 & ~MII_BCM5201_AUXMODE2_LOWPOWER, MII_BCM5201_AUXMODE2 );
#endif
miiWriteWord( MII_BCM5201_MULTIPHY_SUPERISOLATE, MII_BCM5201_MULTIPHY );
break;
case 0x5411:
case 0x5421:
default:
miiWriteWord( MII_CONTROL_POWERDOWN, MII_CONTROL );
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()
{
UInt16 val16;
ELG( this, fPHYType, 'Phy+', "startPHY" );
fTxConfiguration |= kTxConfiguration_Tx_DMA_Enable;
WRITE_REGISTER( TxConfiguration, fTxConfiguration );
fRxConfiguration |= kRxConfiguration_Rx_DMA_Enable;
WRITE_REGISTER( RxConfiguration, fRxConfiguration );
fTxMACConfiguration |= kTxMACConfiguration_TxMac_Enable;
WRITE_REGISTER( TxMACConfiguration, fTxMACConfiguration );
fRxMACConfiguration |= kRxMACConfiguration_Rx_Mac_Enable | kRxMACConfiguration_Hash_Filter_Enable;
if ( fIsPromiscuous )
fRxMACConfiguration &= ~kRxMACConfiguration_Strip_FCS;
else fRxMACConfiguration |= kRxMACConfiguration_Strip_FCS;
WRITE_REGISTER( RxMACConfiguration, fRxMACConfiguration );
if ( fPHYType == 0x5201 )
{
miiReadWord( &val16, MII_BCM5201_MULTIPHY );
miiWriteWord( val16 & ~MII_BCM5201_MULTIPHY_SUPERISOLATE, MII_BCM5201_MULTIPHY );
#if 0
miiReadWord( &val16, MII_BCM5201_AUXMODE2 );
miiWriteWord( val16 | MII_BCM5201_AUXMODE2_LOWPOWER, MII_BCM5201_AUXMODE2 );
#endif
}
WRITE_REGISTER( RxKick, fRxRingElements - 4 ); return;
}
#ifdef NOT_YET
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;
}
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