#include "UniNEnet.h"
#include "UniNEnetMII.h"
#include <libkern/OSByteOrder.h>
bool UniNEnet::miiReadWord( UInt16 *dataPtr, UInt16 reg )
{
UInt32 i;
UInt32 miiReg;
if ( phyId == 0xFF )
{
ALRT( miiReg, phyId << 16 | reg, 'IdR-', "miiReadWord - phyId not established yet." );
return false;
}
WRITE_REGISTER( MIFBitBangFrame_Output,
kMIFBitBangFrame_Output_ST_default
| kMIFBitBangFrame_Output_OP_read
| phyId << kMIFBitBangFrame_Output_PHYAD_shift
| reg << kMIFBitBangFrame_Output_REGAD_shift
| kMIFBitBangFrame_Output_TA_MSB );
for ( i = 0; i < 20; i++ )
{
miiReg = READ_REGISTER( MIFBitBangFrame_Output );
if ( miiReg & kMIFBitBangFrame_Output_TA_LSB )
{
ELG( miiReg, phyId << 16 | reg, 'miiR', "miiReadWord" );
*dataPtr = (UInt16) miiReg;
return true;
}
IODelay( 10 );
}
ELG( miiReg, phyId << 16 | reg, 'miR-', "miiReadWord - failed" );
return false;
}
bool UniNEnet::miiWriteWord( UInt16 data, UInt16 reg )
{
UInt32 i;
UInt32 miiReg;
if ( phyId == 0xFF )
{
ALRT( miiReg, phyId << 16 | reg, 'IdW-', "miiWriteWord - phyId not established yet." );
return false;
}
WRITE_REGISTER( MIFBitBangFrame_Output,
kMIFBitBangFrame_Output_ST_default
| kMIFBitBangFrame_Output_OP_write
| phyId << kMIFBitBangFrame_Output_PHYAD_shift
| reg << kMIFBitBangFrame_Output_REGAD_shift
| kMIFBitBangFrame_Output_TA_MSB
| data );
for ( i = 0; i < 20; i++ )
{
miiReg = READ_REGISTER( MIFBitBangFrame_Output );
if ( miiReg & kMIFBitBangFrame_Output_TA_LSB )
{
ELG( data, phyId << 16 | reg, 'miiW', "miiWriteWord" );
return true;
}
IODelay( 10 );
}
ELG( data, phyId << 16 | reg, 'miW-', "miiWriteWord - failed" );
return false;
}
bool UniNEnet::miiResetPHY()
{
int i = MII_RESET_TIMEOUT;
UInt16 mii_control;
ELG( i, phyId, 'RstP', "miiResetPHY" );
miiWriteWord( MII_CONTROL_RESET, MII_CONTROL ); IOSleep( MII_RESET_DELAY );
while ( i > 0 )
{
if ( miiReadWord( &mii_control, MII_CONTROL ) == false )
return false;
if ( !(mii_control & MII_CONTROL_RESET) )
{
miiReadWord( &mii_control, MII_CONTROL );
mii_control &= ~MII_CONTROL_ISOLATE;
miiWriteWord( mii_control, MII_CONTROL );
return true;
}
IOSleep( MII_RESET_DELAY );
i -= MII_RESET_DELAY;
}
return false;
}
bool UniNEnet::miiWaitForAutoNegotiation()
{
int i = MII_LINK_TIMEOUT;
UInt16 mii_status;
ELG( i, phyId, 'miWA', "miiWaitForAutoNegotiation" );
while ( i > 0 )
{
if ( miiReadWord( &mii_status, MII_STATUS ) == false )
return false;
if ( mii_status & MII_STATUS_NEGOTIATION_COMPLETE )
return true;
IOSleep( MII_LINK_DELAY );
i -= MII_LINK_DELAY;
}
return false;
}
bool UniNEnet::miiFindPHY()
{
int i;
UInt16 phyWord;
ELG( phyId, MII_MAX_PHY, 'miFP', "miiFindPHY" );
i = 0;
if ( fK2 ) i = 1;
for ( ; i < MII_MAX_PHY; i++ )
{ phyId = i;
if ( miiReadWord( &phyWord, MII_STATUS ) == false ) continue;
if ( miiReadWord( &fPHYControl, MII_CONTROL ) == false ) continue;
if ( phyWord == 0xFFFF && fPHYControl == 0xFFFF ) continue;
return true;
}
phyId = 0xFF;
return false;
}
bool UniNEnet::miiInitializePHY()
{
UInt16 phyWord;
ELG( fPHYType, phyId, 'miIP', "miiInitializePHY" );
miiReadWord( &phyWord, MII_CONTROL );
phyWord &= ~MII_CONTROL_AUTONEGOTIATION;
miiWriteWord( phyWord, MII_CONTROL );
miiReadWord( &phyWord, MII_ADVERTISEMENT );
phyWord |= MII_ANAR_100BASETX_FD | MII_ANAR_100BASETX
| MII_ANAR_10BASET_FD | MII_ANAR_10BASET
| MII_ANAR_PAUSE;
miiWriteWord( phyWord, MII_ADVERTISEMENT );
if ( fPHYType == 0x1011 )
{ ELG( 0, 0, 'mrvl', "miiInitializePHY" );
miiReadWord( &phyWord, MII_1000BASETCONTROL );
phyWord |= MII_1000BASETCONTROL_FULLDUPLEXCAP
| MII_1000BASETCONTROL_HALFDUPLEXCAP;
miiWriteWord( phyWord, MII_1000BASETCONTROL );
miiReadWord( &phyWord, MII_CONTROL );
phyWord |= MII_CONTROL_AUTONEGOTIATION
| MII_CONTROL_RESTART_NEGOTIATION
| MII_CONTROL_RESET;
miiWriteWord( phyWord, MII_CONTROL );
IOSleep( 1 );
return true;
}
miiReadWord( &phyWord, MII_CONTROL );
phyWord |= MII_CONTROL_AUTONEGOTIATION;
miiWriteWord( phyWord, MII_CONTROL );
miiReadWord( &phyWord, MII_CONTROL );
phyWord |= MII_CONTROL_RESTART_NEGOTIATION;
miiWriteWord( phyWord, MII_CONTROL );
#if 0
while ( 1 )
{
miiReadWord( &phyWord, MII_CONTROL );
if ( (phyWord & MII_CONTROL_RESTART_NEGOTIATION) == 0 )
break;
}
#endif
return true;
}