📄 skxmac2.c
字号:
XM_OUT16(IoC, Port, XM_IMSK, 0xffff); /* disable all IRQs */ XM_OUT32(IoC, Port, XM_MODE, 0x00000000); /* clear Mode Reg */ XM_OUT16(IoC, Port, XM_TX_CMD, 0x0000); /* reset TX CMD Reg */ XM_OUT16(IoC, Port, XM_RX_CMD, 0x0000); /* reset RX CMD Reg */ /* disable all PHY IRQs */ switch (pAC->GIni.GP[Port].PhyType) { case SK_PHY_BCOM: PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_INT_MASK, 0xffff); break; case SK_PHY_LONE: PHY_WRITE(IoC, pPrt, Port, PHY_LONE_INT_ENAB, 0x0); break; case SK_PHY_NAT: /* todo: National PHY_WRITE(IoC, pPrt, Port, PHY_NAT_INT_MASK, 0xffff); */ break; } /* clear the Hash Register */ SkXmClrHashAddr(pAC, IoC, Port); /* clear the Exact Match Address registers */ SkXmClrExactAddr(pAC, IoC, Port, 0, 15); SkXmClrSrcCheck(pAC, IoC, Port); /* flush the XMAC's Rx and Tx FIFOs */ SkXmFlushTxFifo(pAC, IoC, Port); SkXmFlushRxFifo(pAC, IoC, Port); pAC->GIni.GP[Port].PState = SK_PRT_STOP;}/****************************************************************************** * * SkXmHardRst() - Do a XMAC hardware reset * * Description: * The XMAC of the specified 'Port' and all connected devices * (PHY and SERDES) will receive a reset signal on its *Reset * pins. * External PHYs must be reset be clearing a bit in the GPIO * register (Timing requirements: Broadcom: 400ns, Level One: * none, National: 80ns). * * ATTENTION: * It is absolutely neccessary to reset the SW_RST Bit first * before calling this function. * * Returns: * nothing */void SkXmHardRst(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* port to stop (MAC_1 + n) */{ SK_U16 Word; int i; int TOut; SK_U32 Reg; for (i=0; i<4; i++) { /* TX_MFF_CTRL1 is a 32 bit register but only the lowest 16 */ /* bit contains buttoms to press */ SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), (SK_U16) MFF_CLR_MAC_RST); TOut = 0; do { TOut ++; if (TOut > 10000) { /* * Adapter seems to be in RESET state. * Registers cannot be written. */ return; } SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), (SK_U16) MFF_SET_MAC_RST); SK_IN16(IoC,MR_ADDR(Port,TX_MFF_CTRL1), &Word); } while ((Word & MFF_SET_MAC_RST) == 0); } /* For external PHYs there must be special handling */ if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { /* reset external PHY */ SK_IN32(IoC, B2_GP_IO, &Reg); if (Port == 0) { Reg |= GP_DIR_0; /* set to output */ Reg &= ~GP_IO_0; } else { Reg |= GP_DIR_2; /* set to output */ Reg &= ~GP_IO_2; } SK_OUT32(IoC, B2_GP_IO, Reg); /* short delay */ SK_IN32(IoC, B2_GP_IO, &Reg); } pAC->GIni.GP[Port].PState = SK_PRT_RESET;}/****************************************************************************** * * SkXmInitMac() - Initialize the XMAC II * * Description: * Initialize all the XMAC of the specified port. * The XMAC must be reset or stopped before calling this function. * * Note: * The XMACs 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_U16 SWord; int i; SK_U32 Reg; 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 & (SK_U16) MFF_SET_MAC_RST) { /* 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), (SK_U16) MFF_CLR_MAC_RST); /* * clear PHY reset */ if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { SK_IN32(IoC, B2_GP_IO, &Reg); if (Port == 0) { Reg |= GP_DIR_0; /* set to output */ Reg |= GP_IO_0; } else { Reg |= GP_DIR_2; /* set to output */ Reg |= GP_IO_2; } SK_OUT32(IoC, B2_GP_IO, Reg); /* enable GMII interface */ XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); /* optimize MDIO transfer by oppressing preamble */ XM_IN16(IoC, Port, XM_MMU_CMD, &SWord); XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE); /* Workaround BCOM Errata for the A1 type */ /* Write magic patterns to reserved registers */ PHY_READ(IoC, pPrt, Port, PHY_XMAC_ID1, &SWord); if (SWord == 0x6041) { i = 0; while (BcomRegA1Hack[i].PhyReg != 0) { PHY_WRITE(IoC, pPrt, Port, BcomRegA1Hack[i].PhyReg, BcomRegA1Hack[i].PhyVal); i++; } } /* Workaround BCOM Errata for the C0 type */ /* Write magic patterns to reserved registers */ if (SWord == 0x6044) { i = 0; while (BcomRegC0Hack[i].PhyReg != 0) { PHY_WRITE(IoC, pPrt, Port, BcomRegC0Hack[i].PhyReg, BcomRegC0Hack[i].PhyVal); i++; } } /* Workaround BCOM Errata (#10523) for all BCom PHYs*/ /* Disable Power Management after reset */ PHY_READ(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL, &SWord); PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL, SWord | PHY_B_AC_DIS_PM); /* * PHY LED initialization is performed in * SkGeXmitLED() (but not here). */ } /* Dummy read the Interrupt source register */ XM_IN16(IoC, Port, XM_ISRC, &SWord); /* * The autonegotiation process starts immediately after * clearing the reset. Autonegotiation process should be * started by the SIRQ, therefore stop it here immediately. */ SkXmInitPhy(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 programed to XMAC A * B2_MAC_3 = xx xx xx xx xx x2 is programed to XMAC B */ for (i = 0; i < 3; i++) { /* * The following 2 statements are together endianess * independant. 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, 0x05aa); if (pAC->GIni.GIMacsFound > 1) { switch (pAC->GIni.GIPortUsage) { case SK_RED_LINK: /* Configure Tx Request Threshold for red. link */ XM_OUT16(IoC, Port, XM_TX_THR, SK_XM_THR_REDL); break; case SK_MUL_LINK: /* Configure Tx Request Threshold for load bal. */ XM_OUT16(IoC, Port, XM_TX_THR, SK_XM_THR_MULL); break; case SK_JUMBO_LINK: /* Configure Tx Request Threshold for jumbo frames */ XM_OUT16(IoC, Port, XM_TX_THR, SK_XM_THR_JUMBO); break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG); break; } } else { /* Configure Tx Request Threshold for single port */ XM_OUT16(IoC, Port, XM_TX_THR, SK_XM_THR_SL); } /* * setup register defaults for the Rx Command Register * - Enable Automatic Frame Padding on Tx side */ XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD); /* * setup register defaults for the Rx Command Register, * program value of PRxCmd */ XM_OUT16(IoC, Port, XM_RX_CMD, pPrt->PRxCmd); /* * 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! */ pPrt->PState = SK_PRT_INIT; /* * 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 autonegotiation process * has been completed successfully. */}/****************************************************************************** * * SkXmInitDupMd() - Initialize the XMACs Duplex Mode * * Description: * This function initilaizes the XMACs Duplex Mode. * It should be called after successfully finishing * the Autonegotiation 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 propable not quick * enough at the 'XMAC' bus to burst 8kB. * The XMAC stopps 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, * therefore it seems to be that there is nothing * to do here. */ break; case SK_LMODE_STAT_UNKNOWN: default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG); break; }}/****************************************************************************** * * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port * * Description: * This function initilaizes the Pause Mode which should * be used for this port. * It should be called after successfully finishing * the Autonegotiation Process * * Returns: * nothing */void SkXmInitPauseMd(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; SK_U16 Word; SK_U32 DWord; pPrt = &pAC->GIni.GP[Port]; if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE || pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { /* Disable Pause Frame Reception */ XM_IN16(IoC, Port, XM_MMU_CMD, &Word); XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_IGN_PF); } else { /* * enabling pause frame reception is required for 1000BT * because the XMAC is not reset if the link is going down */ /* Enable Pause Frame Reception */ XM_IN16(IoC, Port, XM_MMU_CMD, &Word); XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~XM_MMU_IGN_PF); } if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC || pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { /* * Configure Pause Frame Generation * Use internal and external Pause Frame Generation. * Sending pause frames is edge triggert. Send a * Pause frame with the maximum pause time if * internal oder external FIFO full condition * occurs. Send a zero pause time frame to * start transmission again. */ /* XM_PAUSE_DA = '010000C28001' (default) */ /* XM_MAC_PTIME = 0xffff (maximum) */ /* remember this value is defined in big endian (!) */ XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff); /* Set Pause Mode in Mode Register */ XM_IN32(IoC, Port, XM_MODE, &DWord); XM_OUT32(IoC, Port, XM_MODE, DWord | XM_PAUSE_MODE); /* Set Pause Mode in MAC Rx FIFO */ SK_OUT16(IoC, MR_ADDR(Port,RX_MFF_CTRL1), MFF_ENA_PAUSE); } else { /* * disable pause frame generation is required for 1000BT * because the XMAC is not reset if the link is going down */ /* Disable Pause Mode in Mode Register */ XM_IN32(IoC, Port, XM_MODE, &DWord); XM_OUT32(IoC, Port, XM_MODE, DWord & ~XM_PAUSE_MODE); /* Disable Pause Mode in MAC Rx FIFO */ SK_OUT16(IoC, MR_ADDR(Port,RX_MFF_CTRL1), MFF_DIS_PAUSE); }}/****************************************************************************** * * SkXmInitPhy() - Initialize the XMAC II Phy registers * * Description: * Initialize all the XMACs Phy registers * * Note: * * Returns: * nothing */void SkXmInitPhy(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port, /* Port Index (MAC_1 + n) */SK_BOOL DoLoop) /* Should a Phy LOOback be set-up? */{ SK_GEPORT *pPrt; pPrt = &pAC->GIni.GP[Port]; switch (pPrt->PhyType) { case SK_PHY_XMAC: SkXmInitPhyXmac(pAC, IoC, Port, DoLoop); break; case SK_PHY_BCOM: SkXmInitPhyBcom(pAC, IoC, Port, DoLoop); break; case SK_PHY_LONE: SkXmInitPhyLone(pAC, IoC, Port, DoLoop); break; case SK_PHY_NAT: SkXmInitPhyNat(pAC, IoC, Port, DoLoop); break; }}/****************************************************************************** * * SkXmInitPhyXmac() - Initialize the XMAC II Phy registers * * Description: * Initialize all the XMACs Phy registers * * Note: * * Returns: * nothing */static void SkXmInitPhyXmac(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port, /* Port Index (MAC_1 + n) */SK_BOOL DoLoop) /* Should a Phy LOOback be set-up? */{ SK_GEPORT *pPrt; SK_U16 Crtl; pPrt = &pAC->GIni.GP[Port]; /* Autonegotiation ? */ if (pPrt->PLinkMode == SK_LMODE_HALF ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -