📄 skgesirq.c
字号:
/* Dummy read ISR to prevent extra link downs/ups. */ PHY_READ(IoC, pPrt, Port, PHY_BCOM_INT_STAT, &ExtStat); if ((ExtStat & ~0x1800) != 0) { CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "CheckUp2 - Stat: %x", (void *)ExtStat, (void *)NULL); }#endif /* DEBUG */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("AutoNeg done Port %d\n", Port)); return (SK_HW_PS_LINK); } } } else { /* !AutoNeg */ /* * 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#ifdef xDEBUG /* Dummy read ISR to prevent extra link downs/ups. */ PHY_READ(IoC, pPrt, Port, PHY_BCOM_INT_STAT, &ExtStat); if ((ExtStat & ~0x1800) != 0) { CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "CheckUp3 - Stat: %x", (void *)ExtStat, (void *)NULL); }#endif /* DEBUG */ 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);} /* SkGePortCheckUpBcom *//****************************************************************************** * * 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, /* Adapter Context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ int Done; SK_U16 Isrc; /* Interrupt source register */ SK_U16 LpAb; /* Link Partner Ability */ SK_U16 ExtStat; /* Extended Status Register */ SK_U16 PhyStat; /* Phy Status Register */ SK_U16 StatSum; SK_BOOL AutoNeg; /* Is Autonegotiation used ? */ SK_U8 NextMode; /* Next AutoSensing Mode */ 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);} /* SkGePortCheckUpLone*//****************************************************************************** * * 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, /* Adapter Context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ /* todo: National */ return (SK_HW_PS_NONE);} /* SkGePortCheckUpNat *//****************************************************************************** * * Event service routine * * Description: * * Notes: */int SkGeSirqEvent(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* Io Context */SK_U32 Event, /* Module specific Event */SK_EVPARA Para) /* Event specific Parameter */{ SK_U64 Octets; SK_GEPORT *pPrt; /* GIni Port struct pointer */ SK_U32 Port; SK_U32 Time; unsigned Len; int PortStat; SK_U8 Val8; Port = Para.Para32[0]; pPrt = & pAC->GIni.GP[Port]; switch (Event) { case SK_HWEV_WATIM: /* Check whether port came up */ PortStat = SkGePortCheckUp(pAC, IoC, Port); switch (PortStat) { case SK_HW_PS_RESTART: if (pPrt->PHWLinkUp) { /* * Set Link to down. */ SkHWLinkDown(pAC, IoC, Port); /* * Signal directly to RLMT to ensure correct * sequence of SWITCH and RESET event. */ SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, 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 (pPrt->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 (pPrt->PHWLinkUp) { /* * Signal directly to RLMT to ensure correct * sequence of SWITCH and RESET event. */ 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, &pPrt->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. */ SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); } /* Stop Workaround Timer */ SkTimerStop(pAC, IoC, &pPrt->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++) { pPrt->PPrevRx = 0; pPrt->PPrevFcs = 0; pPrt->PPrevShorts = 0; } break; case SK_HWEV_SET_LMODE: Val8 = (SK_U8)Para.Para32[1]; if (pPrt->PLinkModeConf != Val8) { /* Set New link mode */ pPrt->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 (pPrt->PFlowCtrlMode != Val8) { /* Set New Flow Control mode */ pPrt->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 (pPrt->PMSMode != Val8) { /* Set New link mode */ pPrt->PMSMode = 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_HALFDUP_CHK: /* * half duplex hangup workaround. See packet arbiter timeout * interrupt for description */ pPrt->HalfDupTimerActive = SK_FALSE; if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) { Len = sizeof(SK_U64); SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), pAC->Rlmt.Port[Port].Net->NetNumber); if (pPrt->LastOctets == Octets) { /* TX hanging, do a FIFO flush restarts it. */ SkXmFlushTxFifo(pAC, IoC, Port); } } break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG); break; } return (0);} /* SkGeSirqEvent *//****************************************************************************** * * SkPhyIsrBcom - PHY interrupt service routine * * Description: handle all interrupts from BCOM PHY * * Returns: N/A */static void SkPhyIsrBcom(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* Io Context */int Port, /* Port Num = PHY Num */SK_U16 IStatus) /* Interrupt Status */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ SK_EVPARA Para; pPrt = &pAC->GIni.GP[Port]; 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)) { Para.Para32[0] = (SK_U32)Port; SkHWLinkDown(pAC, IoC, Port); /* Signal to RLMT */ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); /* Start workaround Errata #2 timer */ SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, SKGE_HWAC, SK_HWEV_WATIM, Para); } if (IStatus & PHY_B_IS_NO_HDCL) { } 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 */ }} /* SkPhyIsrBcom *//****************************************************************************** * * SkPhyIsrLone - PHY interrupt service routine * * Description: handle all interrupts from LONE PHY * * Returns: N/A */static void SkPhyIsrLone(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* Io Context */int Port, /* Port Num = PHY Num */SK_U16 IStatus) /* Interrupt Status */{ 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 */ }} /* SkPhyIsrLone *//* End of File */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -