📄 skgesirq.c
字号:
/****************************************************************************** * * SkGePortCheckUpLone - Check if the link is up * * return: * 0 o.k. nothing needed * 1 Restart needed on this port * 2 Link came up */static int SkGePortCheckUpLone(SK_AC *pAC, /* Adapters context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ SK_BOOL AutoNeg; /* Is Autonegotiation used ? */ SK_U16 Isrc; /* Interrupt source register */ SK_U16 LpAb; /* Link Partner Ability */ SK_U8 NextMode; /* Next AutoSensing Mode */ SK_U16 ExtStat; /* Extended Status Register */ SK_U16 PhyStat; /* Phy Status Register */ SK_U16 StatSum; int Done; pPrt = &pAC->GIni.GP[Port]; if (pPrt->PHWLinkUp) { return(SK_HW_PS_NONE) ; } StatSum = pPrt->PIsave; pPrt->PIsave = 0; /* Now wait for each ports link */ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { AutoNeg = SK_FALSE; } else { AutoNeg = SK_TRUE; } /* * here we usually can check whether the link is in sync and * autonegotiation is done. */ XM_IN16(IoC, Port, XM_ISRC, &Isrc) ; PHY_READ(IoC, pPrt, Port, PHY_LONE_STAT, &PhyStat); StatSum |= PhyStat; SkXmAutoNegLipaLone(pAC, IoC, Port, PhyStat); if ((PhyStat & PHY_ST_LSYNC) == 0){ /* * Save Autonegotiation Done bit */ pPrt->PIsave = (SK_U16) (StatSum & PHY_ST_AN_OVER);#ifdef DEBUG if (pPrt->PIsave & PHY_ST_AN_OVER) { SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("AutoNeg done rescheduled Port %d\n", Port)); }#endif return(SK_HW_PS_NONE) ; } if (AutoNeg) { if (StatSum & PHY_ST_AN_OVER) { SkHWLinkUp(pAC, IoC, Port) ; Done = SkXmAutoNegDone(pAC,IoC,Port); if (Done != SK_AND_OK) { /* Get PHY parameters, for debuging only */ PHY_READ(IoC, pPrt, Port, PHY_LONE_AUNE_LP, &LpAb); PHY_READ(IoC, pPrt, Port, PHY_LONE_1000T_STAT, &ExtStat); SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", Port, LpAb, ExtStat)); /* Try next possible mode */ NextMode = SkHWSenseGetNext(pAC, IoC, Port); SkHWLinkDown(pAC, IoC, Port) ; if (Done == SK_AND_DUP_CAP) { /* GoTo next mode */ SkHWSenseSetNext(pAC, IoC, Port, NextMode); } return(SK_HW_PS_RESTART) ; } else { /* * Dummy Read interrupt status to prevent * extra link down/ups */ PHY_READ(IoC, pPrt, Port, PHY_LONE_INT_STAT, &ExtStat); SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("AutoNeg done Port %d\n", Port)); return(SK_HW_PS_LINK) ; } } /* * AutoNeg not done, but HW link is up. Check for timeouts */ pPrt->PAutoNegTimeOut ++; if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { /* * Timeout occured. * What do we need now? */ SK_DBG_MSG(pAC,SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("AutoNeg timeout Port %d\n", Port)); if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { /* * Timeout occured * Set Link manually up. */ SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); SK_DBG_MSG(pAC,SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Set manual full duplex Port %d\n", Port)); } /* * Do the restart */ return(SK_HW_PS_RESTART) ; } } else { /* * Link is up and we don't need more. */#ifdef DEBUG if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("ERROR: Lipa auto detected on port %d\n", Port)); }#endif /* * Dummy Read interrupt status to prevent * extra link down/ups */ PHY_READ(IoC, pPrt, Port, PHY_LONE_INT_STAT, &ExtStat); SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_IRQ, ("Link sync(GP), Port %d\n", Port)); SkHWLinkUp(pAC, IoC, Port) ; return(SK_HW_PS_LINK) ; } return(SK_HW_PS_NONE) ;}/****************************************************************************** * * SkGePortCheckUpNat - Check if the link is up * * return: * 0 o.k. nothing needed * 1 Restart needed on this port * 2 Link came up */static int SkGePortCheckUpNat(SK_AC *pAC, /* Adapters context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ /* todo: National */ return(SK_HW_PS_NONE) ;}/****************************************************************************** * * Event service routine * * Description: * * Notes: */int SkGeSirqEvent(SK_AC *pAC, /* Adapters context */SK_IOC IoC, /* Io Context */SK_U32 Event, /* Module specific Event */SK_EVPARA Para) /* Event specific Parameter */{ SK_U32 Port; SK_U32 Time; SK_U8 Val8 ; int PortStat; Port = Para.Para32[0]; switch (Event) { case SK_HWEV_WATIM: /* Check whether port came up */ PortStat = SkGePortCheckUp(pAC, IoC, Port); switch (PortStat) { case SK_HW_PS_RESTART: if (pAC->GIni.GP[Port].PHWLinkUp) { /* * Set Link to down. */ SkHWLinkDown(pAC, IoC, Port); /* * Signal directly to RLMT to ensure correct * sequence of SWITCH and RESET event. */ Para.Para32[0] = (SK_U32) Port; SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); /* Start workaround Errata #2 timer */ SkTimerStart(pAC, IoC, &pAC->GIni.GP[Port].PWaTimer, SK_WA_INA_TIME, SKGE_HWAC, SK_HWEV_WATIM, Para); } /* Restart needed */ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); break; case SK_HW_PS_LINK: /* Signal to RLMT */ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para); break; } /* Start again the check Timer */ if (pAC->GIni.GP[Port].PHWLinkUp) { Time = SK_WA_ACT_TIME; } else { Time = SK_WA_INA_TIME; } /* todo: still needed for non-Xmac-PHYs ??? */ /* Start workaround Errata #2 timer */ SkTimerStart(pAC, IoC, &pAC->GIni.GP[Port].PWaTimer, Time, SKGE_HWAC, SK_HWEV_WATIM, Para); break; case SK_HWEV_PORT_START: if (pAC->GIni.GP[Port].PHWLinkUp) { /* * Signal directly to RLMT to ensure correct * sequence of SWITCH and RESET event. */ Para.Para32[0] = (SK_U32) Port; SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); } SkHWLinkDown(pAC, IoC, Port) ; /* Schedule Port RESET */ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); /* Start workaround Errata #2 timer */ SkTimerStart(pAC, IoC, &pAC->GIni.GP[Port].PWaTimer, SK_WA_INA_TIME,SKGE_HWAC,SK_HWEV_WATIM,Para); break; case SK_HWEV_PORT_STOP: if (pAC->GIni.GP[Port].PHWLinkUp) { /* * Signal directly to RLMT to ensure correct * sequence of SWITCH and RESET event. */ Para.Para32[0] = (SK_U32) Port; SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); } /* Stop Workaround Timer */ SkTimerStop(pAC, IoC, &pAC->GIni.GP[Port].PWaTimer) ; SkHWLinkDown(pAC, IoC, Port) ; break; case SK_HWEV_UPDATE_STAT: /* We do NOT need to update any statistics */ break; case SK_HWEV_CLEAR_STAT: /* We do NOT need to clear any statistics */ for (Port = 0; Port < (SK_U32) pAC->GIni.GIMacsFound; Port++) { pAC->GIni.GP[Port].PPrevRx = 0; pAC->GIni.GP[Port].PPrevFcs = 0; pAC->GIni.GP[Port].PPrevShorts = 0; } break; case SK_HWEV_SET_LMODE: Val8 = (SK_U8) Para.Para32[1]; if (pAC->GIni.GP[Port].PLinkModeConf != Val8) { /* Set New link mode */ pAC->GIni.GP[Port].PLinkModeConf = Val8; /* Restart Port */ SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); } break; case SK_HWEV_SET_FLOWMODE: Val8 = (SK_U8) Para.Para32[1]; if (pAC->GIni.GP[Port].PFlowCtrlMode != Val8) { /* Set New Flow Control mode */ pAC->GIni.GP[Port].PFlowCtrlMode = Val8; /* Restart Port */ SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); } break; case SK_HWEV_SET_ROLE: Val8 = (SK_U8) Para.Para32[1]; if (pAC->GIni.GP[Port].PMSMode != Val8) { /* Set New link mode */ pAC->GIni.GP[Port].PMSMode = Val8; /* Restart Port */ SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); } break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG); break; } return(0) ;}/****************************************************************************** * * SkPhyIsrBcom - PHY interrupt service routine * * Description: handle all interrupts from BCOM PHY * * Returns: N/A */static void SkPhyIsrBcom(SK_AC *pAC, /* Adapters context */SK_IOC IoC, /* Io Context */int Port, /* Port Num = PHY Num */SK_U16 IStatus) /* Interrupts masked with PHY-Mask */{ SK_EVPARA Para; if (IStatus & PHY_B_IS_PSE) { /* incorrectable pair swap error */ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E022, SKERR_SIRQ_E022MSG) ; } if (IStatus & PHY_B_IS_MDXI_SC) { /* not used */ } if (IStatus & PHY_B_IS_HCT) { /* not used */ } if (IStatus & PHY_B_IS_LCT) { /* not used */ } if (IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) { SkHWLinkDown(pAC, IoC, Port); /* Signal to RLMT */ Para.Para32[0] = (SK_U32) Port; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); /* Start workaround Errata #2 timer */ SkTimerStart(pAC, IoC, &pAC->GIni.GP[Port].PWaTimer, SK_WA_INA_TIME,SKGE_HWAC,SK_HWEV_WATIM,Para); } if (IStatus & PHY_B_IS_NO_HDCL) { /* not used */ } if (IStatus & PHY_B_IS_NO_HDC) { /* not used */ } if (IStatus & PHY_B_IS_NEG_USHDC) { /* not used */ } if (IStatus & PHY_B_IS_SCR_S_ER) { /* not used */ } if (IStatus & PHY_B_IS_RRS_CHANGE) { /* not used */ } if (IStatus & PHY_B_IS_LRS_CHANGE) { /* not used */ } if (IStatus & PHY_B_IS_DUP_CHANGE) { /* not used */ } if (IStatus & PHY_B_IS_LSP_CHANGE) { /* not used */ } if (IStatus & PHY_B_IS_CRC_ER) { /* not used */ }}/****************************************************************************** * * SkPhyIsrLone - PHY interrupt service routine * * Description: handle all interrupts from LONE PHY * * Returns: N/A */static void SkPhyIsrLone(SK_AC *pAC, /* Adapters context */SK_IOC IoC, /* Io Context */int Port, /* Port Num = PHY Num */SK_U16 IStatus) /* Interrupts masked with PHY-Mask */{ SK_EVPARA Para; if (IStatus & PHY_L_IS_CROSS) { /* not used */ } if (IStatus & PHY_L_IS_POL) { /* not used */ } if (IStatus & PHY_L_IS_SS) { /* not used */ } if (IStatus & PHY_L_IS_CFULL) { /* not used */ } if (IStatus & PHY_L_IS_AN_C) { /* not used */ } if (IStatus & PHY_L_IS_SPEED) { /* not used */ } if (IStatus & PHY_L_IS_CFULL) { /* not used */ } if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) { SkHWLinkDown(pAC, IoC, Port); /* Signal to RLMT */ Para.Para32[0] = (SK_U32) Port; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); /* Start workaround Errata #2 timer */ SkTimerStart(pAC, IoC, &pAC->GIni.GP[Port].PWaTimer, SK_WA_INA_TIME,SKGE_HWAC,SK_HWEV_WATIM,Para); } if (IStatus & PHY_L_IS_MDINT) { /* not used */ }}/* End of File */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -