📄 rhine_main.c
字号:
static BOOL rhine_mii_read(PRHINE_INFO pInfo, U8 byIdx, PU16 pdata){ WORD ww;// BYTE byOrgMIIAD;// BYTE byOrgMIICR; PMAC_REGS pMacRegs=pInfo->pMacRegs;// byOrgMIIAD=readb(&pMacRegs->byMIIAD);// byOrgMIICR=readb(&pMacRegs->byMIICR); // disable MIICR_MAUTO, so that mii addr can be set normally SafeDisableMiiAutoPoll(pInfo); writeb(byIdx,&pMacRegs->byMIIAD); BYTE_REG_BITS_ON(MIICR_RCMD, &pMacRegs->byMIICR); for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { if (!(readb(&pMacRegs->byMIICR) & MIICR_RCMD)) break; } *pdata=readw(&pMacRegs->wMIIDATA); // for VT3043 only if (pInfo->chip_id==VT86C100A) mdelay(1); // restore MIICR// writeb(byOrgMIIAD, &pMacRegs->byMIIAD);// writeb(byOrgMIICR, &pMacRegs->byMIICR); EnableMiiAutoPoll(pMacRegs); if (ww == W_MAX_TIMEOUT) { return FALSE; } return TRUE;}static BOOL rhine_mii_write (PRHINE_INFO pInfo, BYTE byMiiAddr, WORD wData){ WORD ww;// BYTE byOrgMIIAD;// BYTE byOrgMIICR; PMAC_REGS pMacRegs=pInfo->pMacRegs; // keep original MIICR value// byOrgMIIAD=readb(&pMacRegs->byMIIAD);// byOrgMIICR=readb(&pMacRegs->byMIICR); // disable MIICR_MAUTO, so that mii addr can be set normally SafeDisableMiiAutoPoll(pInfo); // MII reg offset writeb(byMiiAddr, &pMacRegs->byMIIAD); // set MII data writew(wData,&pMacRegs->wMIIDATA); // turn on MIICR_WCMD BYTE_REG_BITS_ON(MIICR_WCMD, &pMacRegs->byMIICR); // W_MAX_TIMEOUT is the timeout period for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { udelay(5); if (!(readb(&pMacRegs->byMIICR) & MIICR_WCMD)) break; } // for VT3043 only if (pInfo->chip_id==VT86C100A) mdelay(1); // restore MIICR// writeb(byOrgMIIAD, &pMacRegs->byMIIAD);// writeb(byOrgMIICR, &pMacRegs->byMIICR); EnableMiiAutoPoll(pMacRegs); if (ww == W_MAX_TIMEOUT) { return FALSE; } return TRUE;}//// Get the media mode stored in EEPROM or module options//static U32 rhine_get_opt_media_mode(PRHINE_INFO pInfo) { PMAC_REGS pMacRegs=pInfo->pMacRegs; U8 byRevId=pInfo->byRevId; U32 status=0; if (byRevId<REV_ID_VT6105_A0) { if (BYTE_REG_BITS_IS_ON(CFGC_MEDEN,&pMacRegs->byCFGC)) { if (!BYTE_REG_BITS_IS_ON(BCR0_MED2,&pMacRegs->byBCR0)) { if (BYTE_REG_BITS_IS_ON(BCR1_MED1,&pMacRegs->byBCR1)) { if (BYTE_REG_BITS_IS_ON(BCR1_MED0,&pMacRegs->byBCR1)) status=RHINE_SPEED_100|RHINE_DUPLEX_FULL; else status=RHINE_SPEED_10|RHINE_DUPLEX_FULL; } else { if (BYTE_REG_BITS_IS_ON(BCR1_MED0,&pMacRegs->byBCR1)) status=RHINE_SPEED_100; else status=RHINE_SPEED_10; } pInfo->mii_status=status; return status; } status=RHINE_AUTONEG_ENABLE; pInfo->mii_status=status; return status; } } switch (pInfo->sOpts.spd_dpx) { case SPD_DPX_AUTO: status=RHINE_AUTONEG_ENABLE; break; case SPD_DPX_100_FULL: status=RHINE_SPEED_100|RHINE_DUPLEX_FULL; break; case SPD_DPX_10_FULL: status=RHINE_SPEED_10|RHINE_DUPLEX_FULL; break; case SPD_DPX_100_HALF: status=RHINE_SPEED_100; break; case SPD_DPX_10_HALF: status=RHINE_SPEED_10; break; } pInfo->mii_status=status; return status;}static void mii_set_auto_on(PRHINE_INFO pInfo){ U32 phy_id; U8 byRevId=pInfo->byRevId; rhine_mii_read(pInfo, MII_REG_PHYID2, (PU16) &phy_id); rhine_mii_read(pInfo, MII_REG_PHYID1, (PU16) &phy_id + 1); if (byRevId>=REV_ID_VT6102_A) { if ((byRevId>=REV_ID_VT6105_A0) || (((phy_id & 0xFFFFFFF0UL)==0x01018F20UL) && ((phy_id & 0xFUL)>4))) MII_REG_BITS_OFF(1, MII_REG_MODCFG, pInfo); if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR ,pInfo)) MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR ,pInfo); else MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, pInfo); } else MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, pInfo);}static void mii_set_auto_off(PRHINE_INFO pInfo){ U32 phy_id; U8 byRevId=pInfo->byRevId; rhine_mii_read(pInfo, MII_REG_PHYID2, (PU16)&phy_id); rhine_mii_read(pInfo, MII_REG_PHYID1, (PU16)&phy_id + 1); if ((byRevId>=REV_ID_VT6105_A0) || ((byRevId>=REV_ID_VT6102_A) && ((phy_id & 0xFFFFFFF0UL)==0x01018F20UL) && ((phy_id & 0xFUL)>4)) ) MII_REG_BITS_ON(1, MII_REG_MODCFG, pInfo); MII_REG_BITS_OFF(BMCR_AUTO, MII_REG_BMCR, pInfo);}//// This function check if MAC operation at Full duplex mode//static BOOL rhine_is_full_duplex (PRHINE_INFO pInfo){ U8 byRevId=pInfo->byRevId; PMAC_REGS pMacRegs=pInfo->pMacRegs; // if in AUTO-NEGO mode if (byRevId>=REV_ID_VT6105_A0) return BYTE_REG_BITS_IS_ON(MIISR_N_FDX, &pMacRegs->byMIISR); if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, pInfo)) { // if my TX_FD on, check both TX_FD if (MII_REG_BITS_IS_ON(ANAR_TXFD, MII_REG_ANAR, pInfo)) { // partner's TX_FD if (MII_REG_BITS_IS_ON(ANLPAR_TXFD, MII_REG_ANLPAR, pInfo)) return TRUE; } // if my T4 on, check both T4 if (MII_REG_BITS_IS_ON(ANAR_T4, MII_REG_ANAR, pInfo)) { // partner's T4 if (MII_REG_BITS_IS_ON(ANLPAR_T4, MII_REG_ANLPAR, pInfo)) return FALSE; } // if my TX_HD on, check both TX_HD if (MII_REG_BITS_IS_ON(ANAR_TX, MII_REG_ANAR, pInfo)) { // partner's TX_HD if (MII_REG_BITS_IS_ON(ANLPAR_TX, MII_REG_ANLPAR, pInfo)) return FALSE; } // if my 10_FD on, check both 10_FD if (MII_REG_BITS_IS_ON(ANAR_10FD, MII_REG_ANAR, pInfo)) { // partner's 10_FD if (MII_REG_BITS_IS_ON(ANLPAR_10FD, MII_REG_ANLPAR, pInfo)) return TRUE; } // if all above is not, then it would be 10_HD or no link // both case will be half duplex return FALSE; } // if in force mode else { if (!MII_REG_BITS_IS_ON(BMCR_FDX, MII_REG_BMCR, pInfo)) return FALSE; } return TRUE;}static void rhine_set_media_mode(PRHINE_INFO pInfo, U32 mii_status) { U8 byRevId=pInfo->byRevId; U32 curr_status; /* if (pInfo->mii_status & RHINE_AUTONEG_ENABLE) { MII_REG_BITS_ON(BMCR_RESET, MII_REG_BMCR,pInfo); }*/ curr_status=rhine_check_media_mode(pInfo) & (~RHINE_LINK_FAIL); //Enable or Disable PAUSE in ANAR if (byRevId>=REV_ID_VT6102_A) { if (pInfo->sOpts.flow_cntl==2) MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, pInfo); else if (pInfo->sOpts.flow_cntl==3) MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, pInfo); } //Check if new status is consisent with current status if (((mii_status & curr_status) & RHINE_AUTONEG_ENABLE) || (mii_status==curr_status)) { pInfo->mii_status=rhine_check_media_mode(pInfo); return; } // if connection type is AUTO if (mii_status & RHINE_AUTONEG_ENABLE) { // set duplex mode of MAC according to duplex mode of MII if (rhine_is_full_duplex(pInfo)) rhine_set_duplex(pInfo, TRUE); else rhine_set_duplex(pInfo, FALSE); MII_REG_BITS_ON(ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10, MII_REG_ANAR, pInfo); // enable AUTO-NEGO mode mii_set_auto_on(pInfo); } // if not, then // 1). turn off AUTO-NEGO // 2). set USER-FORCED speed (10/100) & duplex (half/full) mode of MII and MAC else if (byRevId<REV_ID_VT6102_A) { U16 wBMCR; // turn off AUTO-NEGO mii_set_auto_off(pInfo); // set loopback in MII to un-link in 100M mode, // in 10M mode set this bit cannot make it un-link // but it doesn't matter MII_REG_BITS_ON(BMCR_LBK, MII_REG_BMCR, pInfo); // read the original value of BMCR register rhine_mii_read(pInfo,MII_REG_BMCR, &wBMCR); // mask off AUTO-NEGO wBMCR &= ~(BMCR_AUTO); if (mii_status & RHINE_DUPLEX_FULL) { wBMCR |=BMCR_FDX; rhine_set_duplex(pInfo, TRUE); } else { wBMCR &=(~BMCR_FDX); rhine_set_duplex(pInfo, FALSE); } if (mii_status & RHINE_SPEED_100) wBMCR |=BMCR_SPEED; else wBMCR &=(~BMCR_SPEED); // write the setting to BMCR register rhine_mii_write(pInfo, MII_REG_BMCR, wBMCR); // delay to avoid link down from force-10M to force-100M (only for 3065 in Win95/Win98) if (byRevId >= REV_ID_VT6102_A) mdelay(200); // unset MII loopback to re-link MII_REG_BITS_OFF(BMCR_LBK, MII_REG_BMCR, pInfo); } //For VT6105 & VT6102 else { WORD wANAR; mii_set_auto_off(pInfo); rhine_mii_read(pInfo, MII_REG_ANAR, &wANAR); wANAR &= (~(ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10)); if (mii_status & RHINE_SPEED_100) { if (mii_status & RHINE_DUPLEX_FULL) { wANAR |=ANAR_TXFD; rhine_set_duplex(pInfo, TRUE); } else { wANAR |=ANAR_TX; rhine_set_duplex(pInfo, FALSE); } } else { if (mii_status & RHINE_DUPLEX_FULL) { wANAR |=ANAR_10FD; rhine_set_duplex(pInfo, TRUE); } else { wANAR |=ANAR_10; rhine_set_duplex(pInfo, FALSE); } } rhine_mii_write(pInfo,MII_REG_ANAR, wANAR); if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, pInfo)) MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, pInfo); else MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, pInfo); } mdelay(3000); pInfo->mii_status=rhine_check_media_mode(pInfo); }U32 rhine_check_media_mode(PRHINE_INFO pInfo) { PMAC_REGS pMacRegs=pInfo->pMacRegs; U32 status=0; if (BYTE_REG_BITS_IS_ON(MIISR_LNKFL, &pMacRegs->byMIISR)) status|=RHINE_LINK_FAIL; if (BYTE_REG_BITS_IS_ON(MIISR_SPEED, &pMacRegs->byMIISR)) status|=RHINE_SPEED_10; else status|=RHINE_SPEED_100; /* check duplex mode*/ /* if VT6105, check N_FDX bit in MII Status Register directly */ if (rhine_is_full_duplex(pInfo)) { rhine_set_duplex(pInfo,TRUE); status|=RHINE_DUPLEX_FULL; } else { rhine_set_duplex(pInfo,FALSE); } if (MII_REG_BITS_IS_ON(BMCR_AUTO,MII_REG_BMCR,pInfo)) { U16 w; rhine_mii_read(pInfo, MII_REG_ANAR, &w); if ((w & (ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10)) ==(ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10)) { status|=RHINE_AUTONEG_ENABLE; } } return status;}static void enable_flow_control_ability(PRHINE_INFO pInfo) { PMAC_REGS pMacRegs=pInfo->pMacRegs; U16 wANAR,wANLPAR; U8 byFlowCR; if (pInfo->byRevId<REV_ID_VT6102_A) return; rhine_mii_read(pInfo,MII_REG_ANAR,&wANAR); rhine_mii_read(pInfo,MII_REG_ANLPAR,&wANLPAR); if (pInfo->byRevId<REV_ID_VT6105_A0) byFlowCR=readb(&pMacRegs->byMISCCR0); else byFlowCR=readb(&pMacRegs->byFlowCR1); if (!(pInfo->mii_status & RHINE_DUPLEX_FULL)) { //Half duplex mode if (pInfo->byRevId<REV_ID_VT6105_A0) { byFlowCR&=~MISC_CR0_FDXRFEN; } else { byFlowCR&=~FLOWCR1_FDXTFCEN; byFlowCR&=~FLOWCR1_FDXRFCEN; } } else { //Full duplxe mode if (((wANAR & (ANAR_ASMDIR|ANAR_PAUSE))==ANAR_ASMDIR) && ((wANLPAR & (ANLPAR_ASMDIR|ANLPAR_PAUSE)) ==(ANLPAR_ASMDIR|ANLPAR_PAUSE))) { if (pInfo->byRevId<REV_ID_VT6105_A0) { byFlowCR&=~MISC_CR0_FDXRFEN; } else { byFlowCR|=FLOWCR1_FDXTFCEN; byFlowCR&=~FLOWCR1_FDXRFCEN; } } else if ((wANAR & ANAR_PAUSE) && (wANLPAR & ANLPAR_PAUSE)) { if (pInfo->byRevId<REV_ID_VT6105_A0) byFlowCR|=MISC_CR0_FDXRFEN; else byFlowCR|=(FLOWCR1_FDXTFCEN|FLOWCR1_FDXRFCEN); } else if (((wANAR & (ANAR_ASMDIR|ANAR_PAUSE))==(ANAR_ASMDIR|ANAR_PAUSE)) && ((wANLPAR & (ANLPAR_ASMDIR|ANLPAR_PAUSE)) ==ANLPAR_ASMDIR)) { if (pInfo->byRevId<REV_ID_VT6105_A0) byFlowCR|=MISC_CR0_FDXRFEN; else { byFlowCR&=~FLOWCR1_FDXTFCEN; byFlowCR|=FLOWCR1_FDXRFCEN; } } else { if (pInfo->byRevId<REV_ID_VT6105_A0) byFlowCR&=~MISC_CR0_FDXRFEN; else byFlowCR&=~(FLOWCR1_FDXTFCEN|FLOWCR1_FDXRFCEN); } } if (pInfo->byRevId< REV_ID_VT6105_A0) { byFlowCR &=~(MISC_CR0_HDXFEN|MISC_CR0_FDXTFEN); writeb(byFlowCR,&pMacRegs->byMISCCR0); } else { byFlowCR &=~FLOWCR1_HDXFCEN; writeb(byFlowCR,&pMacRegs->byFlowCR1); }}/**************************************************************************** ETHTOOL ioctl support routine****************************************************************************/#ifdef RHINE_ETHTOOL_IOCTL_SUPPORTstatic int rhine_ethtool_ioctl(struct net_device* dev, struct ifreq* ifr) { struct ethtool_cmd ecmd; PRHINE_INFO pInfo=(PRHINE_INFO) dev->priv; PMAC_REGS pMacRegs=pInfo->pMacRegs; if (copy_fr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -