?? lan9118.c
字號:
/* wait for read to complete w/ timeout
*/
for(i = 0U; i < 100U; i++) {
/* see if MII is finished yet
*/
if ((Lan_GetMacRegDW(dwLanBase, MII_ACC) & MII_ACC_MII_BUSY_) == 0UL)
{
/* get the read data from the MAC & return i
*/
result=((NGushort)Lan_GetMacRegDW(dwLanBase, MII_DATA));
goto DONE;
}
}
#ifdef SMC_DEBUG
OS_TEXT_OUT ("timeout waiting for MII write to finish\n");
#endif
DONE:
ngOSIntrCtl(ictrl);
return result;
}
/* Phy_SetRegW () writes a 16-bit phy register values */
void Phy_SetRegW(
const NGifnet * const netp,
const DWORD dwRegIndex, NGushort wVal)
{
PLAN9118_DATA pLan9118Data;
DWORD dwLanBase;
int ictrl; /* save previous interrupt state */
DWORD dwAddr=0UL;
NGuint i=0U;
dwLanBase = (DWORD) NG_ETHIF_DATA(((void *) netp), eif_base);
pLan9118Data = (PLAN9118_DATA) netp->if_devptr1;
ictrl = ngOSIntrCtl(NG_INTRCTL_DISABLE);
if(dwRegIndex==0UL) {
if((wVal&0x1200)==0x1200) {
pLan9118Data->wLastADVatRestart=pLan9118Data->wLastADV;
}
}
if(dwRegIndex==4UL) {
pLan9118Data->wLastADV=wVal;
}
/* confirm MII not busy
*/
if ((Lan_GetMacRegDW(dwLanBase, MII_ACC) & MII_ACC_MII_BUSY_) != 0UL)
{
#ifdef SMC_DEBUG
OS_TEXT_OUT ("MII is busy in Phy_SetRegW???\n");
#endif
goto DONE;
}
/* put the data to write in the MAC
*/
Lan_SetMacRegDW(dwLanBase, MII_DATA, (DWORD)wVal);
/* set the address, index & direction (write to PHY)
*/
dwAddr = ((pLan9118Data->dwPhyAddress&0x1FUL)<<11) | ((dwRegIndex & 0x1FUL)<<6) | MII_ACC_MII_WRITE_;
Lan_SetMacRegDW(dwLanBase, MII_ACC, dwAddr);
/* wait for write to complete w/ timeout
*/
for(i = 0U; i < 100U; i++) {
/* see if MII is finished yet
*/
if ((Lan_GetMacRegDW(dwLanBase, MII_ACC) & MII_ACC_MII_BUSY_) == 0UL)
{
goto DONE;
}
}
#ifdef SMC_DEBUG
OS_TEXT_OUT ("timeout waiting for MII write to finish\n");
#endif
DONE:
ngOSIntrCtl(ictrl);
}
#ifdef SMC_DEBUG
typedef struct _SHOW_REG
{
NGubyte szName[20];
DWORD dwOffset;
} SHOW_REG;
/*
FUNCTION: Lan_ShowRegs
This function is used to display the registers.
Except the phy.
*/
void Lan_ShowRegs(const DWORD dwLanBase)
{
/* Make these const struct's static to keep them off the stack.
Otherwise, gcc will try to use _memcpy() to initialize them,
which will *NOT* work in our RunTime environment.
*/
static const SHOW_REG sysCsr[] = {
{ "ID_REV", ID_REV },
{ "INT_CFG", INT_CFG },
{ "INT_STS", INT_STS },
{ "INT_EN", INT_EN },
{ "BYTE_TEST", BYTE_TEST },
{ "FIFO_INT", FIFO_INT },
{ "RX_CFG", RX_CFG },
{ "TX_CFG", TX_CFG },
{ "HW_CFG", HW_CFG },
{ "RX_DP_CTL", RX_DP_CTRL },
{ "RX_FIFO_INF", RX_FIFO_INF },
{ "TX_FIFO_INF", TX_FIFO_INF },
{ "PMT_CTRL", PMT_CTRL },
{ "GPIO_CFG", GPIO_CFG },
{ "GPT_CFG", GPT_CFG },
{ "GPT_CNT", GPT_CNT },
{ "ENDIAN", ENDIAN },
{ "FREE_RUN", FREE_RUN },
{ "RX_DROP", RX_DROP },
{ "MAC_CSR_CMD", MAC_CSR_CMD },
{ "MAC_CSR_DATA", MAC_CSR_DATA},
{ "AFC_CFG", AFC_CFG },
{ "E2P_CMD", E2P_CMD },
{ "E2P_DATA", E2P_DATA },
{ "TEST_REG_A", TEST_REG_A }};
static const SHOW_REG macCsr[] = {
{ "MAC_CR", MAC_CR },
{ "ADDRH", ADDRH },
{ "ADDRL", ADDRL },
{ "HASHH", HASHH },
{ "HASHL", HASHL },
{ "MII_ACC", MII_ACC },
{ "MII_DATA", MII_DATA },
{ "FLOW", FLOW },
{ "VLAN1", VLAN1 },
{ "VLAN2", VLAN2 },
{ "WUFF", WUFF },
{ "WUCSR", WUCSR }};
NGuint i, iNumSysRegs, iNumMacRegs;
DWORD dwOldMacCmdReg, dwOldMacDataReg;
char buf [256];
iNumSysRegs = (sizeof(sysCsr) / sizeof(SHOW_REG));
iNumMacRegs = (sizeof(macCsr) / sizeof(SHOW_REG));
/* preserve MAC cmd/data reg's */
dwOldMacCmdReg = GetRegDW(dwLanBase, MAC_CSR_CMD);
dwOldMacDataReg = GetRegDW(dwLanBase, MAC_CSR_DATA);
OS_TEXT_OUT ("\n");
OS_TEXT_OUT (" LAN91C118 CSR's\n");
OS_TEXT_OUT (" SYS CSR's MAC CSR's\n");
for (i = 0U; i < iNumMacRegs; i++)
{
sprintf (buf,
"%16s (0x%02lX) = 0x%08lX, %8s (0x%02lX) + 0x%08lX\n",
sysCsr[i].szName,
sysCsr[i].dwOffset,
GetRegDW(dwLanBase, sysCsr[i].dwOffset),
macCsr[i].szName,
macCsr[i].dwOffset,
Lan_GetMacRegDW(dwLanBase, macCsr[i].dwOffset));
OS_TEXT_OUT (buf);
/* restore original mac cmd/data reg's after each usage */
SetRegDW(dwLanBase, MAC_CSR_CMD, dwOldMacCmdReg);
SetRegDW(dwLanBase, MAC_CSR_DATA, dwOldMacDataReg);
}
for (i=iNumMacRegs; i<iNumSysRegs; i++)
{
sprintf (buf, "%16s (0x%02lX) = 0x%08lX\n",
sysCsr[i].szName,
sysCsr[i].dwOffset,
GetRegDW(dwLanBase, sysCsr[i].dwOffset));
OS_TEXT_OUT (buf);
}
}
#endif
/*
FUNCTION: Lan_Initialize
This function should be the first Lan_xxx function called
It begins to initialize the LAN9118_DATA structure.
It reads some ID values from the chip.
It resets the chip.
RETURN VALUE:
returns TRUE on Success,
returns FALSE on Failure,
*/
BOOLEAN Lan_Initialize(const NGifnet * const netp)
{
PLAN9118_DATA pLan9118Data;
BOOLEAN result=FALSE;
DWORD dwIdRev=0UL;
DWORD dwTimeout;
DWORD dwTemp;
DWORD dwLanBase;
#ifdef SMC_DEBUG
char buf [256];
#endif
pLan9118Data = (PLAN9118_DATA) netp->if_devptr1;
dwLanBase = (DWORD) NG_ETHIF_DATA(((void *) netp), eif_base);
#ifdef SMC_DEBUG
sprintf (buf, "-->Lan_Initialize(dwLanBase=0x%08lX,pLan9118Data=0x%08lX)\n",
dwLanBase,(DWORD)pLan9118Data);
OS_TEXT_OUT (buf);
#endif
if(pLan9118Data==NULL) {
goto DONE;
}
ngMemSet ((void *) pLan9118Data, 0, sizeof(LAN9118_DATA));
dwIdRev=GetRegDW(dwLanBase,ID_REV);
SetRegDW(dwLanBase,HW_CFG,HW_CFG_SRST_);
dwTimeout=1000UL;
do {
dwTemp=GetRegDW(dwLanBase,HW_CFG);
dwTimeout--;
} while((dwTimeout > 0UL) && (dwTemp & HW_CFG_SRST_));
if(dwTemp&HW_CFG_SRST_) {
#ifdef SMC_DEBUG
OS_TEXT_OUT(" Failed to complete reset.\n");
#endif
goto DONE;
}
pLan9118Data->dwIdRev=dwIdRev;
pLan9118Data->GpioSetting=0x00170700UL;
SetRegDW(dwLanBase,HW_CFG,0x00050000UL);
SetRegDW(dwLanBase,AFC_CFG,0x006E3740UL);
result=TRUE;
DONE:
#ifdef SMC_DEBUG
sprintf (buf,"<--Lan_Initialize, result=%s\n",result?"TRUE":"FALSE");
OS_TEXT_OUT (buf);
#endif
return result;
}
/* Phy_SetLink(netp) does link management settings */
void Phy_SetLink(const NGifnet * const netp)
{
if(NG_ETHIF_DATA(((void *) netp), eif_flags) & NG_ETHIFF_AUTONEG) {
NGushort wTemp;
NGushort eif_linkadv;
wTemp=Phy_GetRegW(netp, PHY_ANEG_ADV);
wTemp = (NGushort) (wTemp & (~PHY_ANEG_ADV_PAUSE_));
wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_ASYMP_);
wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_SYMP_);
wTemp= (NGushort) (wTemp & (~PHY_ANEG_ADV_SPEED_));
eif_linkadv = GetLinkAdv (netp);
if(eif_linkadv & NG_ETHIF_AUTONEG_10BASET) {
wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_10H_);
}
if(eif_linkadv & NG_ETHIF_AUTONEG_10BASET_FD) {
wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_10F_);
}
if(eif_linkadv & NG_ETHIF_AUTONEG_100BASETX) {
wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_100H_);
}
if(eif_linkadv & NG_ETHIF_AUTONEG_100BASETX_FD) {
wTemp=(NGushort) (wTemp | PHY_ANEG_ADV_100F_);
}
Phy_SetRegW(netp,PHY_ANEG_ADV,wTemp);
/* begin to establish link */
Phy_SetRegW(netp, PHY_BCR,
(NGushort) (PHY_BCR_AUTO_NEG_ENABLE_|
PHY_BCR_RESTART_AUTO_NEG_));
} else { // non-autonegotiate
NGubyte eif_linkcfg;
NGushort wTemp=(NGushort) 0;
eif_linkcfg = GetLinkCfg (netp);
if((eif_linkcfg == NG_ETHIF_LINK_10BASET_FD) || (eif_linkcfg == NG_ETHIF_LINK_100BASETX_FD)) {
wTemp=(NGushort) (wTemp | PHY_BCR_DUPLEX_MODE_);
}
if((eif_linkcfg == NG_ETHIF_LINK_100BASETX) || (eif_linkcfg == NG_ETHIF_LINK_100BASETX_FD)) {
wTemp=(NGushort) (wTemp | PHY_BCR_SPEED_SELECT_);
}
Phy_SetRegW(netp,PHY_BCR,wTemp);
}
}
/* Phy_GetLinkMode(netp) reads the current link settings */
void Phy_GetLinkMode(const NGifnet * const netp)
{
const LAN9118_DATA *pLan9118Data;
NGushort wRegVal=(NGushort) 0;
const NGushort wRegBSR=Phy_GetRegW(netp, PHY_BSR);
pLan9118Data = (PLAN9118_DATA) netp->if_devptr1;
SetLink (netp, (NGubyte) NG_ETHIF_LINK_DOWN);
if(wRegBSR&PHY_BSR_LINK_STATUS_) {
wRegVal=Phy_GetRegW(netp, PHY_BCR);
if(wRegVal&PHY_BCR_AUTO_NEG_ENABLE_) {
const NGushort wRegADV=pLan9118Data->wLastADVatRestart;
NGushort wRegLPA=Phy_GetRegW(netp, PHY_ANEG_LPA);
wRegLPA=(NGushort) (wRegLPA & wRegADV);
if(wRegLPA&PHY_ANEG_LPA_100FDX_) {
SetLink (netp, (NGubyte) NG_ETHIF_LINK_100BASETX_FD);
} else if(wRegLPA&PHY_ANEG_LPA_100HDX_) {
SetLink (netp, (NGubyte) NG_ETHIF_LINK_100BASETX);
} else if(wRegLPA&PHY_ANEG_LPA_10FDX_) {
SetLink (netp, (NGubyte) NG_ETHIF_LINK_10BASET_FD);
} else if(wRegLPA&PHY_ANEG_LPA_10HDX_) {
SetLink (netp, (NGubyte) NG_ETHIF_LINK_10BASET);
}
else {
}
} else {
if(wRegVal&PHY_BCR_SPEED_SELECT_) {
if(wRegVal&PHY_BCR_DUPLEX_MODE_) {
SetLink (netp, (NGubyte) NG_ETHIF_LINK_100BASETX_FD);
} else {
SetLink (netp, (NGubyte) NG_ETHIF_LINK_100BASETX);
}
} else {
if(wRegVal&PHY_BCR_DUPLEX_MODE_) {
SetLink (netp, (NGubyte) NG_ETHIF_LINK_10BASET_FD);
} else {
SetLink (netp, (NGubyte) NG_ETHIF_LINK_10BASET);
}
}
}
}
}
/* Phy_UpdateLinkMode(netp) detects any link changes */
void Phy_UpdateLinkMode(const NGifnet * const netp)
{
#ifdef SMC_DEBUG
char buffer [256];
#endif
DWORD dwLanBase;
DWORD dwTemp;
NGubyte bOldLink, bNewLink;
dwLanBase = (DWORD) NG_ETHIF_DATA(((void *) netp), eif_base);
bOldLink = GetLink (netp);
Phy_GetLinkMode(netp);
bNewLink = GetLink (netp);
if(bOldLink != bNewLink) {
if(bNewLink != NG_ETHIF_LINK_DOWN) {
DWORD dwRegVal=0UL;
switch(bNewLink) {
case NG_ETHIF_LINK_10BASET:
#ifdef SMC_DEBUG
OS_TEXT_OUT ("Link is now UP at 10Mbps HD\n");
#endif
break;
case NG_ETHIF_LINK_10BASET_FD:
#ifdef SMC_DEBUG
OS_TEXT_OUT ("Link is now UP at 10Mbps FD\n");
#endif
break;
case NG_ETHIF_LINK_100BASETX:
#ifdef SMC_DEBUG
OS_TEXT_OUT ("Link is now UP at 100Mbps HD\n");
#endif
break;
case NG_ETHIF_LINK_100BASETX_FD:
#ifdef SMC_DEBUG
OS_TEXT_OUT ("Link is now UP at 100Mbps FD\n");
#endif
break;
default:
#ifdef SMC_DEBUG
sprintf (buffer, "Link is now UP at Unknown Link Speed, eif_link=0x%08lX\n",
bNewLink);
OS_TEXT_OUT (buffer);
#endif
break;
}
dwRegVal=Lan_GetMacRegDW(dwLanBase,MAC_CR);
dwRegVal&=~(MAC_CR_FDPX_|MAC_CR_RCVOWN_);
switch(bNewLink) {
case NG_ETHIF_LINK_10BASET:
case NG_ETHIF_LINK_100BASETX:
dwRegVal|=MAC_CR_RCVOWN_;
break;
case NG_ETHIF_LINK_10BASET_FD:
case NG_ETHIF_LINK_100BASETX_FD:
dwRegVal|=MAC_CR_FDPX_;
break;
default:
break;
}
Lan_SetMacRegDW(dwLanBase, MAC_CR,dwRegVal);
if(NG_ETHIF_DATA(((void *) netp), eif_flags) & NG_ETHIFF_AUTONEG) {
NGushort linkPartner=(NGushort) 0;
NGushort localLink=(NGushort) 0;
localLink=Phy_GetRegW(netp,4UL);
linkPartner=Phy_GetRegW(netp,5UL);
switch(bNewLink) {
case NG_ETHIF_LINK_10BASET_FD:
case NG_ETHIF_LINK_100BASETX_FD:
if(((localLink&linkPartner)&((NGushort)0x0400U)) != ((NGushort)0U)) {
/* Enable PAUSE receive and transmit
*/
Lan_SetMacRegDW(dwLanBase,FLOW,0xFFFF0002UL);
dwTemp = GetRegDW(dwLanBase,AFC_CFG);
dwTemp |= 0x0000000FUL;
SetRegDW(dwLanBase,AFC_CFG,dwTemp);
} else if(((localLink&((NGushort)0x0C00U))==((NGushort)0x0C00U)) &&
((linkPartner&((NGushort)0x0C00U))==((NGushort)0x0800U)))
{
/* Enable PAUSE receive, disable PAUSE transmit
*/
Lan_SetMacRegDW(dwLanBase,FLOW,0xFFFF0002UL);
dwTemp = GetRegDW(dwLanBase,AFC_CFG);
dwTemp&=0xFFFFFFF0UL;
SetRegDW(dwLanBase,AFC_CFG,dwTemp);
} else {
/* Disable PAUSE receive and transmit
*/
Lan_SetMacRegDW(dwLanBase,FLOW,0UL);
dwTemp = GetRegDW(dwLanBase,AFC_CFG);
dwTemp&=0xFFFFFFF0UL;
SetRegDW(dwLanBase,AFC_CFG,dwTemp);
};break;
case NG_ETHIF_LINK_10BASET:
case NG_ETHIF_LINK_100BASETX:
Lan_SetMacRegDW(dwLanBase,FLOW,0UL);
dwTemp = GetRegDW(dwLanBase,AFC_CFG);
dwTemp|=0x0000000FUL;
SetRegDW(dwLanBase,AFC_CFG,dwTemp);
break;
default:
break;
}
#ifdef SMC_DEBUG
sprintf (buffer, "LAN9118: %s,%s,%s,%s,%s,%s",
(localLink&PHY_ANEG_ADV_ASYMP_)?"ASYMP":" ",
(localLink&PHY_ANEG_ADV_SYMP_)?"SYMP ":" ",
(localLink&PHY_ANEG_ADV_100F_)?"100FD":" ",
(localLink&PHY_ANEG_ADV_100H_)?"100HD":" ",
(localLink&PHY_ANEG_ADV_10F_)?"10FD ":" ",
(localLink&PHY_ANEG_ADV_10H_)?"10HD ":" ");
OS_TEXT_OUT (buffer);
sprintf (buffer, "Partner: %s,%s,%s,%s,%s,%s",
(linkPartner&PHY_ANEG_LPA_ASYMP_)?"ASYMP":" ",
(linkPartner&PHY_ANEG_LPA_SYMP_)?"SYMP ":" ",
(linkPartner&PHY_ANEG_LPA_100FDX_)?"100FD":" ",
(linkPartner&PHY_ANEG_LPA_100HDX_)?"100HD":" ",
(linkPartner&PHY_ANEG_LPA_10FDX_)?"10FD ":" ",
(linkPartner&PHY_ANEG_LPA_10HDX_)?"10HD ":" ");
OS_TEXT_OUT (buffer);
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -