📄 nicmiiaccess.c
字号:
/*******************************************************************************
*** Note: Copy rights resevered to Beijing Pacific Linkair Communications Co.
***
*** File Name: NICMiiAccess.c
*** Purpose : Basic Access to MII PHY
***
*** Author : Guangzhao Tian
*** Modified : By Guangzhao Tian at 2000/9/11
***
**/
#include "NICMacro.h"
#include "NICWinReg.h"
#include "NICCommand.h"
#include "NICEeprom.h"
#include "NICData.h"
#include "NICHelper.h"
#include "NICMii.h"
#include "NICExport.h"
/*****************************************************************
*** Search for any PHY that is not known.
**/
BOOLEAN NIC_MIIFindPhy(IN PNIC_INFORMATION pAdapter )
{
USHORT MediaOptions = 0;
USHORT PhyManagement = 0;
UCHAR index;
/* Read the MEDIA OPTIONS to see what connectors are available*/
NIC_COMMAND(pAdapter->IoBaseAddress,COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
MediaOptions = NIC_READ_PORT_USHORT(pAdapter->IoBaseAddress,MEDIA_OPTIONS_REGISTER);
DebugMsg("MII Find Phy: Media Options from Reg Win 3 -- 0x%08X ! \n", MediaOptions);
if ( (MediaOptions & MEDIA_OPTIONS_MII_AVAILABLE ) ||
(MediaOptions & MEDIA_OPTIONS_100BASET4_AVAILABLE ) )
{
/* Drop everything, so we are not driving the data, and run the
clock through 32 cycles in case the PHY is trying to tell us
something. Then read the data line, since the PHY's pull-up
will read as a 1 if it's present. */
NIC_COMMAND(pAdapter->IoBaseAddress,COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,0);
for (index = 0; index < 32; index++)
{
NIC_DELAY(MII_WAITTIMES);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_CLOCK);
NIC_DELAY(MII_WAITTIMES);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,0);
}
PhyManagement = NIC_READ_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER);
if ( PhyManagement & PHY_DATA1) return TRUE;
else return FALSE;
}
return TRUE;
}
/****************************************************************************
*** Reads a particular MII PHY register given the proper offset.
**/
BOOLEAN NIC_MIIReadPhy(IN PNIC_INFORMATION pAdapter,IN USHORT RegisterAddress, OUT PUSHORT pInput)
{
USHORT PhyManagement = 0;
USHORT ReadCommand;
ULONG nThisBit;
NIC_MIISendPhyPreamble(pAdapter);
/* Bits 2..6 of the command word specify the register. */
ReadCommand = MII_PHY_READCOMMAND | ( (RegisterAddress & 0x1F) << 2 );
/*see the MII Management Frame Formats*/
for (nThisBit = 0x8000; nThisBit > 2; nThisBit >>= 1)
{
NIC_COMMAND(pAdapter->IoBaseAddress , COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
if (ReadCommand & nThisBit)
{
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_WRITE | PHY_DATA1);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,
PHY_WRITE | PHY_DATA1 | PHY_CLOCK); /*drive 1 to PHY*/
}
else
{
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_WRITE);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,
PHY_WRITE | PHY_CLOCK); /*drive 0 to PHY*/
}
NIC_DELAY(MII_WAITTIMES);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_WRITE);
NIC_DELAY(MII_WAITTIMES);
}
/* Now run one clock with nobody driving.to complete the rest 2 bit driving */
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,0);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_CLOCK);
NIC_DELAY(MII_WAITTIMES);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,0);
NIC_DELAY(MII_WAITTIMES);
/* Now run one clock, expecting the PHY to be driving a 0 on the data
line. If we read a 1, it has to be just his pull-up, and he's not
responding. */
PhyManagement = NIC_READ_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER);
if (PhyManagement & PHY_DATA1)
{ return FALSE; }
/* We think we are in sync. Now we read 16 bits of data from the PHY. */
for (nThisBit = 0x8000; nThisBit; nThisBit >>= 1)
{
/* Shift input up one to make room */
NIC_COMMAND(pAdapter->IoBaseAddress,COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER, PHY_CLOCK);
NIC_DELAY(MII_WAITTIMES);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,0);
NIC_DELAY(MII_WAITTIMES);
PhyManagement = NIC_READ_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER);
if (PhyManagement & PHY_DATA1) *pInput |= nThisBit;
else *pInput &= ~nThisBit;
}
/* OK now give it a couple of clocks with nobody driving. */
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,0);
for (nThisBit = 0; nThisBit < 2; nThisBit++)
{
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_CLOCK);
NIC_DELAY(MII_WAITTIMES);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER, 0);
NIC_DELAY(MII_WAITTIMES);
}
return TRUE;
}
/*****************************************************************************
***Writes to a particular MII PHY register given the proper offset.
**/
VOID NIC_MIIWritePhy( IN PNIC_INFORMATION pAdapter,IN USHORT RegAddr,IN USHORT Output )
{
ULONG index,index2;
USHORT wWritecmd[2];
wWritecmd[0] = 0;
wWritecmd[1] = 0;
NIC_MIISendPhyPreamble(pAdapter);
/* Bits 2..6 of the command word specify the register. */
wWritecmd[0] =MII_PHY_WRITECOMMAND |( (RegAddr & 0x1F) << 2 ) ;
wWritecmd[1] = Output;
NIC_COMMAND(pAdapter->IoBaseAddress,COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
for (index2 = 0; index2 < 2; index2++)
{
for (index = 0x8000; index; index >>= 1)
{
if (wWritecmd[index2] & index)
{
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress, PHYSICAL_MANAGEMENT_REGISTER,PHY_WRITE | PHY_DATA1);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress, PHYSICAL_MANAGEMENT_REGISTER,
PHY_WRITE | PHY_DATA1 | PHY_CLOCK);
}
else
{
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_WRITE);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_WRITE | PHY_CLOCK);
}
NIC_DELAY(MII_WAITTIMES);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress, PHYSICAL_MANAGEMENT_REGISTER,PHY_WRITE);
NIC_DELAY(MII_WAITTIMES);
}
}
/* OK now give it a couple of clocks with nobody driving. */
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,0);
for (index = 0; index < 2; index++)
{
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_CLOCK);
NIC_DELAY(MII_WAITTIMES);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,0);
NIC_DELAY(MII_WAITTIMES);
}
}
/********************************************************************************
*** Establishes the synchronization for each MII transaction. This
*** is done by sending thirty-two "1" bits.
**/
VOID NIC_MIISendPhyPreamble(IN PNIC_INFORMATION pAdapter)
{
UCHAR index;
/* Set up and send the preamble, a sequence of 32 "1" bits */
NIC_COMMAND(pAdapter->IoBaseAddress,COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_WRITE);
for (index = 0; index < 32; index++)
{
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_WRITE | PHY_DATA1);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,
PHY_WRITE | PHY_DATA1 | PHY_CLOCK);
NIC_DELAY(MII_WAITTIMES);
NIC_WRITE_PORT_USHORT(pAdapter->IoBaseAddress,PHYSICAL_MANAGEMENT_REGISTER,PHY_WRITE);
NIC_DELAY(MII_WAITTIMES);
}
}
/** Above are routines about MII Phy Accessging
*** End of NICMiiAccess.c
*****************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -