#include "BMacEnet.h"
#include "BMacEnetPrivate.h"
bool BMacEnet::miiReadWord(unsigned short *dataPtr, unsigned short reg,
unsigned char phy)
{
int i;
miiFrameUnion frame;
unsigned short phyreg;
bool ret = true;
do
{
miiWrite(MII_FRAME_PREAMBLE, MII_FRAME_SIZE);
if ( miiCheckZeroBit() == true )
{
ret = false;
break;
}
frame.data = MII_FRAME_READ;
frame.bit.regad = reg;
frame.bit.phyad = phy;
miiWrite(frame.data, 14);
miiOutThreeState();
if (miiCheckZeroBit() == false)
{
ret = false;
break;
}
phyreg = 0;
for (i = 0; i < 16; i++)
{
phyreg = miiReadBit() | (phyreg << 1);
}
if (dataPtr)
*dataPtr = phyreg;
miiOutThreeState();
if (miiCheckZeroBit() == true)
{
ret = false;
break;
}
}
while ( 0 );
return ret;
}
bool BMacEnet::miiWriteWord(unsigned short data, unsigned short reg,
unsigned char phy)
{
miiFrameUnion frame;
bool ret = true;
do
{
miiWrite(MII_FRAME_PREAMBLE, MII_FRAME_SIZE);
if (miiCheckZeroBit() == true)
{
ret = false;
break;
}
frame.data = MII_FRAME_WRITE;
frame.bit.regad = reg;
frame.bit.phyad = phy;
frame.bit.data = data;
miiWrite(frame.data, MII_FRAME_SIZE);
miiOutThreeState();
if (miiCheckZeroBit() == true)
{
ret = false;
break;
}
}
while ( 0 );
return ret;
}
void BMacEnet::miiWrite(unsigned int miiData, unsigned int dataSize)
{
int i;
u_int16_t regValue;
regValue = kMIFCSR_DataOutEnable;
for (i = dataSize; i > 0; i--)
{
int bit = ((miiData & 0x80000000) ? kMIFCSR_DataOut : 0);
regValue &= ~(kMIFCSR_Clock | kMIFCSR_DataOut) ;
regValue |= bit;
WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue);
IODelay(phyMIIDelay);
regValue |= kMIFCSR_Clock;
WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue );
IODelay(phyMIIDelay);
miiData = miiData << 1;
}
}
int BMacEnet::miiReadBit()
{
u_int16_t regValue;
u_int16_t regValueRead;
regValue = 0;
WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue);
IODelay(phyMIIDelay);
regValue |= kMIFCSR_Clock;
WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue);
IODelay(phyMIIDelay);
regValueRead = ReadBigMacRegister(ioBaseEnet, kMIFCSR);
IODelay(phyMIIDelay);
return ( (regValueRead & kMIFCSR_DataIn) ? 1 : 0 );
}
bool BMacEnet::miiCheckZeroBit()
{
u_int16_t regValue;
regValue = ReadBigMacRegister(ioBaseEnet, kMIFCSR);
return (((regValue & kMIFCSR_DataIn) == 0) ? true : false );
}
void BMacEnet::miiOutThreeState()
{
u_int16_t regValue;
regValue = 0;
WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue);
IODelay(phyMIIDelay);
regValue |= kMIFCSR_Clock;
WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue);
IODelay(phyMIIDelay);
}
bool BMacEnet::miiResetPHY(unsigned char phy)
{
int i = MII_RESET_TIMEOUT;
unsigned short mii_control;
miiWriteWord(MII_CONTROL_RESET, MII_CONTROL, phy);
IOSleep(MII_RESET_DELAY);
while (i > 0)
{
if (miiReadWord(&mii_control, MII_CONTROL, phy) == false)
return false;
if (!(mii_control & MII_CONTROL_RESET))
{
miiReadWord(&mii_control, MII_CONTROL, phy);
mii_control &= ~MII_CONTROL_ISOLATE;
miiWriteWord(mii_control, MII_CONTROL, phy);
return true;
}
IOSleep(MII_RESET_DELAY);
i -= MII_RESET_DELAY;
}
return false;
}
bool BMacEnet::miiWaitForLink(unsigned char phy)
{
int i = MII_LINK_TIMEOUT;
unsigned short mii_status;
while (i > 0)
{
if (miiReadWord(&mii_status, MII_STATUS, phy) == false)
return false;
if (mii_status & MII_STATUS_LINK_STATUS)
return true;
IOSleep(MII_LINK_DELAY);
i -= MII_LINK_DELAY;
}
return false;
}
bool BMacEnet::miiWaitForAutoNegotiation(unsigned char phy)
{
int i = MII_LINK_TIMEOUT;
unsigned short mii_status;
while (i > 0)
{
if (miiReadWord(&mii_status, MII_STATUS, phy) == false)
return false;
if (mii_status & MII_STATUS_NEGOTIATION_COMPLETE)
return true;
IOSleep(MII_LINK_DELAY);
i -= MII_LINK_DELAY;
}
return false;
}
void BMacEnet::miiRestartAutoNegotiation(unsigned char phy)
{
unsigned short mii_control;
miiReadWord(&mii_control, MII_CONTROL, phy);
mii_control |= MII_CONTROL_RESTART_NEGOTIATION;
miiWriteWord(mii_control, MII_CONTROL, phy);
#if 0
while (1)
{
miiReadWord(&mii_control, MII_CONTROL, phy);
if ((mii_control & MII_CONTROL_RESTART_NEGOTIATION) == 0)
break;
}
#endif
}
bool BMacEnet::miiFindPHY(unsigned char *phy)
{
int i;
*phy = 0xff;
for (i = 0; i < MII_MAX_PHY; i++)
{
if (miiReadWord(NULL, MII_STATUS, i) &&
miiReadWord(NULL, MII_CONTROL, i))
break;
}
if (i >= MII_MAX_PHY)
return false;
*phy = i;
return true;
}
bool BMacEnet::miiInitializePHY(unsigned char phy)
{
u_int16_t phyWord;
miiReadWord(&phyWord, MII_CONTROL, phy);
phyWord &= ~MII_CONTROL_AUTONEGOTIATION;
miiWriteWord(phyWord, MII_CONTROL, phy);
miiReadWord(&phyWord, MII_ADVERTISEMENT, phy);
phyWord |= (MII_ANAR_100BASETX_FD | MII_ANAR_100BASETX |
MII_ANAR_10BASET_FD | MII_ANAR_10BASET );
miiWriteWord(phyWord, MII_ADVERTISEMENT, phy);
miiReadWord(&phyWord, MII_CONTROL, phy);
phyWord |= MII_CONTROL_AUTONEGOTIATION;
miiWriteWord(phyWord, MII_CONTROL, phy);
miiRestartAutoNegotiation(phy);
return true;
}