📄 skxmac2.c
字号:
* * Note: * The XMAC's Rx and Tx state machine is still disabled when returning. * * Returns: * nothing */void SkXmInitMac(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; SK_U32 Reg; int i; SK_U16 SWord; pPrt = &pAC->GIni.GP[Port]; if (pPrt->PState == SK_PRT_STOP) { /* Port State: SK_PRT_STOP */ /* Verify that the reset bit is cleared */ SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); if ((SWord & MFF_SET_MAC_RST) != 0) { /* PState does not match HW state */ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); /* Correct it */ pPrt->PState = SK_PRT_RESET; } } if (pPrt->PState == SK_PRT_RESET) { /* * clear HW reset * Note: The SW reset is self clearing, therefore there is * nothing to do here. */ SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); /* Ensure that XMAC reset release is done (errata from LReinbold?) */ SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); /* Clear PHY reset */ if (pPrt->PhyType != SK_PHY_XMAC) { SK_IN32(IoC, B2_GP_IO, &Reg); if (Port == 0) { Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */ } else { Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */ } SK_OUT32(IoC, B2_GP_IO, Reg); /* Enable GMII interface */ XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); /* read Id from external PHY (all have the same address) */ SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1); /* * Optimize MDIO transfer by suppressing preamble. * Must be done AFTER first access to BCOM chip. */ XM_IN16(IoC, Port, XM_MMU_CMD, &SWord); XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE); if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) { /* * Workaround BCOM Errata for the C0 type. * Write magic patterns to reserved registers. */ i = 0; while (BcomRegC0Hack[i].PhyReg != 0) { SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg, BcomRegC0Hack[i].PhyVal); i++; } } else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) { /* * Workaround BCOM Errata for the A1 type. * Write magic patterns to reserved registers. */ i = 0; while (BcomRegA1Hack[i].PhyReg != 0) { SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg, BcomRegA1Hack[i].PhyVal); i++; } } /* * Workaround BCOM Errata (#10523) for all BCom PHYs. * Disable Power Management after reset. */ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, (SK_U16)(SWord | PHY_B_AC_DIS_PM)); /* PHY LED initialization is done in SkGeXmitLED() */ } /* Dummy read the Interrupt source register */ XM_IN16(IoC, Port, XM_ISRC, &SWord); /* * The auto-negotiation process starts immediately after * clearing the reset. The auto-negotiation process should be * started by the SIRQ, therefore stop it here immediately. */ SkMacInitPhy(pAC, IoC, Port, SK_FALSE);#if 0 /* temp. code: enable signal detect */ /* WARNING: do not override GMII setting above */ XM_OUT16(pAC, Port, XM_HW_CFG, XM_HW_COM4SIG);#endif } /* * configure the XMACs Station Address * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B */ for (i = 0; i < 3; i++) { /* * The following 2 statements are together endianess * independent. Remember this when changing. */ SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord); } /* Tx Inter Packet Gap (XM_TX_IPG): use default */ /* Tx High Water Mark (XM_TX_HI_WM): use default */ /* Tx Low Water Mark (XM_TX_LO_WM): use default */ /* Host Request Threshold (XM_HT_THR): use default */ /* Rx Request Threshold (XM_RX_THR): use default */ /* Rx Low Water Mark (XM_RX_LO_WM): use default */ /* configure Rx High Water Mark (XM_RX_HI_WM) */ XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM); /* Configure Tx Request Threshold */ SWord = SK_XM_THR_SL; /* for single port */ if (pAC->GIni.GIMacsFound > 1) { switch (pAC->GIni.GIPortUsage) { case SK_RED_LINK: SWord = SK_XM_THR_REDL; /* redundant link */ break; case SK_MUL_LINK: SWord = SK_XM_THR_MULL; /* load balancing */ break; case SK_JUMBO_LINK: SWord = SK_XM_THR_JUMBO; /* jumbo frames */ break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG); break; } } XM_OUT16(IoC, Port, XM_TX_THR, SWord); /* setup register defaults for the Tx Command Register */ XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD); /* setup register defaults for the Rx Command Register */ SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK; if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { SWord |= XM_RX_BIG_PK_OK; } if (pPrt->PLinkModeConf == SK_LMODE_HALF) { /* * If in manual half duplex mode the other side might be in * full duplex mode, so ignore if a carrier extension is not seen * on frames received */ SWord |= XM_RX_DIS_CEXT; } XM_OUT16(IoC, Port, XM_RX_CMD, SWord); /* * setup register defaults for the Mode Register * - Don't strip error frames to avoid Store & Forward * on the Rx side. * - Enable 'Check Station Address' bit * - Enable 'Check Address Array' bit */ XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE); /* * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) * - Enable all bits excepting 'Octets Rx OK Low CntOv' * and 'Octets Rx OK Hi Cnt Ov'. */ XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK); /* * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) * - Enable all bits excepting 'Octets Tx OK Low CntOv' * and 'Octets Tx OK Hi Cnt Ov'. */ XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK); /* * Do NOT init XMAC interrupt mask here. * All interrupts remain disable until link comes up! */ /* * Any additional configuration changes may be done now. * The last action is to enable the Rx and Tx state machine. * This should be done after the auto-negotiation process * has been completed successfully. */} /* SkXmInitMac *//****************************************************************************** * * SkGmInitMac() - Initialize the GMAC * * Description: * Initialize the GMAC of the specified port. * The GMAC must be reset or stopped before calling this function. * * Note: * The GMAC's Rx and Tx state machine is still disabled when returning. * * Returns: * nothing */void SkGmInitMac(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; int i; SK_U16 SWord; SK_U32 DWord; pPrt = &pAC->GIni.GP[Port]; if (pPrt->PState == SK_PRT_STOP) { /* Port State: SK_PRT_STOP */ /* Verify that the reset bit is cleared */ SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord); if ((DWord & GMC_RST_SET) != 0) { /* PState does not match HW state */ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); /* Correct it */ pPrt->PState = SK_PRT_RESET; } } if (pPrt->PState == SK_PRT_RESET) { /* set GPHY Control reset */ SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); /* set GMAC Control reset */ SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); /* clear GMAC Control reset */ SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR); /* set GMAC Control reset */ SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); /* set HWCFG_MODE */ DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE | (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB); /* set GPHY Control reset */ SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET); /* release GPHY Control reset */ SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR); /* clear GMAC Control reset */ SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); /* Dummy read the Interrupt source register */ SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);#ifndef VCPU /* read Id from PHY */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1); SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);#endif /* VCPU */ } (void)SkGmResetCounter(pAC, IoC, Port); SWord = 0; /* speed settings */ switch (pPrt->PLinkSpeed) { case SK_LSPEED_AUTO: case SK_LSPEED_1000MBPS: SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100; break; case SK_LSPEED_100MBPS: SWord |= GM_GPCR_SPEED_100; break; case SK_LSPEED_10MBPS: break; } /* duplex settings */ if (pPrt->PLinkMode != SK_LMODE_HALF) { /* set full duplex */ SWord |= GM_GPCR_DUP_FULL; } /* flow control settings */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: /* disable auto-negotiation for flow-control */ SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS; break; case SK_FLOW_MODE_LOC_SEND: SWord |= GM_GPCR_FC_RX_DIS; break; case SK_FLOW_MODE_SYMMETRIC: /* TBD */ case SK_FLOW_MODE_SYM_OR_REM: /* enable auto-negotiation for flow-control and */ /* enable Rx and Tx of pause frames */ break; } /* Auto-negotiation ? */ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { /* disable auto-update for speed, duplex and flow-control */ SWord |= GM_GPCR_AU_ALL_DIS; } /* setup General Purpose Control Register */ GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); /* setup Transmit Control Register */ GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR); /* setup Receive Control Register */ GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | GM_RXCR_CRC_DIS); /* setup Transmit Flow Control Register */ GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff); /* setup Transmit Parameter Register */#ifdef VCPU GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);#endif /* VCPU */ SWord = JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26); GM_OUT16(IoC, Port, GM_TX_PARAM, SWord); /* configure the Serial Mode Register */#ifdef VCPU GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);#endif /* VCPU */ SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH; if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { /* enable jumbo mode (Max. Frame Length = 9018) */ SWord |= GM_SMOD_JUMBO_ENA; } GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord); /* * configure the GMACs Station Addresses * in PROM you can find our addresses at: * B2_MAC_1 = xx xx xx xx xx x0 virtual address * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort */ for (i = 0; i < 3; i++) { /* * The following 2 statements are together endianess * independent. Remember this when changing. */ /* physical address: will be used for pause frames */ SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);#ifdef WA_DEV_16 /* WA for deviation #16 */ if (pAC->GIni.GIChipRev == 0) { /* swap the address bytes */ SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8); /* write to register in reversed order */ GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord); } else { GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); }#else GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);#endif /* WA_DEV_16 */ /* virtual address: will be used for data */ SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord); GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord); /* reset Multicast filtering Hash registers 1-3 */ GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0); } /* reset Multicast filtering Hash register 4 */ GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0); /* enable interrupt mask for counter overflows */ GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0); GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0); GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0); /* read General Purpose Status */ GM_IN16(IoC, Port, GM_GP_STAT, &SWord); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("MAC Stat Reg=0x%04X\n", SWord));#ifdef SK_DIAG c_print("MAC Stat Reg=0x%04X\n", SWord);#endif /* SK_DIAG */} /* SkGmInitMac *//****************************************************************************** * * SkXmInitDupMd() - Initialize the XMACs Duplex Mode * * Description: * This function initializes the XMACs Duplex Mode. * It should be called after successfully finishing * the Auto-negotiation Process * * Returns: * nothing */void SkXmInitDupMd(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ switch (pAC->GIni.GP[Port].PLinkModeStatus) { case SK_LMODE_STAT_AUTOHALF: case SK_LMODE_STAT_HALF: /* Configuration Actions for Half Duplex Mode */ /* * XM_BURST = default value. We are probable not quick * enough at the 'XMAC' bus to burst 8kB. * The XMAC stops bursting if no transmit frames * are available or the burst limit is exceeded. */ /* XM_TX_RT_LIM = default value (15) */ /* XM_TX_STIME = default value (0xff = 4096 bit times) */ break; case SK_LMODE_STAT_AUTOFULL: case SK_LMODE_STAT_FULL: /* Configuration Actions for Full Duplex Mode */ /* * The duplex mode is configured by the PHY,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -