📄 skgesirq.c
字号:
return(SK_HW_PS_NONE); } pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7); if (AutoNeg) { /* Auto-Negotiation Over ? */ if ((PhyStat & PHY_ST_AN_OVER) != 0) { SkHWLinkUp(pAC, IoC, Port); Done = SkMacAutoNegDone(pAC, IoC, Port); if (Done != SK_AND_OK) { return(SK_HW_PS_RESTART); } 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 /* DEBUG */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Link sync, Port %d\n", Port)); SkHWLinkUp(pAC, IoC, Port); return(SK_HW_PS_LINK); } return(SK_HW_PS_NONE);} /* SkGePortCheckUpGmac */#ifdef OTHER_PHY/****************************************************************************** * * SkGePortCheckUpLone() - Check if the link is up on Level One PHY * * 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 Auto-negotiation 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 * auto-negotiation is done. */ SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat); StatSum |= PhyStat; SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); if ((PhyStat & PHY_ST_LSYNC) == 0) { /* Save Auto-negotiation Done bit */ pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);#ifdef DEBUG if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("AutoNeg done rescheduled Port %d\n", Port)); }#endif /* DEBUG */ return(SK_HW_PS_NONE); } if (AutoNeg) { if ((StatSum & PHY_ST_AN_OVER) != 0) { SkHWLinkUp(pAC, IoC, Port); Done = SkMacAutoNegDone(pAC, IoC, Port); if (Done != SK_AND_OK) { /* Get PHY parameters, for debugging only */ SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb); SkXmPhyRead(pAC, IoC, 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 */ SkXmPhyRead(pAC, IoC, 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 */ 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) { /* 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 /* DEBUG */ /* * Dummy Read interrupt status to prevent * extra link down/ups */ SkXmPhyRead(pAC, IoC, 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 on National PHY * * 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 */#endif /* OTHER_PHY *//****************************************************************************** * * SkGeSirqEvent() - 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, &pPrt->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 (pPrt->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: /* not possible for fiber */ if (!pAC->GIni.GICopperType) { break; } 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_SET_SPEED: if (pPrt->PhyType != SK_PHY_MARV_COPPER) { break; } Val8 = (SK_U8)Para.Para32[1]; if (pPrt->PLinkSpeed != Val8) { /* Set New Speed parameter */ pPrt->PLinkSpeed = 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, a FIFO flush restarts it */ SkMacFlushTxFifo(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: handles 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) != 0) { /* 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_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) { 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); }} /* SkPhyIsrBcom *//****************************************************************************** * * SkPhyIsrGmac() - PHY interrupt service routine * * Description: handles all interrupts from Marvell PHY * * Returns: N/A */static void SkPhyIsrGmac(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_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) { Para
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -