📄 skgesirq.c
字号:
AutoNeg = pPrt->PLinkMode != SK_LMODE_HALF && pPrt->PLinkMode != SK_LMODE_FULL; Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg); return(Rtv);} /* SkGePortCheckUp *//****************************************************************************** * * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY * * return: * 0 o.k. nothing needed * 1 Restart needed on this port * 2 Link came up */static int SkGePortCheckUpGmac(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */int Port, /* Port Index (MAC_1 + n) */SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ int Done; SK_U16 PhyStat; /* PHY Status */ SK_U16 PhySpecStat;/* PHY Specific Status */ SK_U16 ResAb; /* Master/Slave resolution */#ifndef SK_SLIM SK_EVPARA Para; int i; SK_U16 Word; /* I/O helper */ SK_U16 DspOffs; /* DSP Register Offset */ SK_U16 DspCtrl; /* DSP Control Value */ SK_U16 DspIncr; /* Increment to access MDI pair */#ifdef DEBUG SK_U16 LinkPartAb; /* Link Partner Ability */#endif /* DEBUG */#endif /* !SK_SLIM */#ifdef xDEBUG SK_U64 StartTime;#endif /* DEBUG */ pPrt = &pAC->GIni.GP[Port]; if (pPrt->PHWLinkUp) { return(SK_HW_PS_NONE); } /* Read PHY Status */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) { SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Phy1000BT: 0x%04X, ", ResAb)); if ((ResAb & PHY_B_1000S_MSF) != 0) { /* Error */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("Master/Slave Fault, ResAb: 0x%04X\n", ResAb)); pPrt->PAutoNegFail = SK_TRUE; pPrt->PMSStatus = SK_MS_STAT_FAULT; return(SK_HW_PS_RESTART); } } /* Read PHY Specific Status */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("PhySpecStat: 0x%04X\n", PhySpecStat));#if (defined(DEBUG) && !defined(SK_SLIM)) /* Read PHY Auto-Negotiation Expansion */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &LinkPartAb); if ((LinkPartAb & PHY_ANE_RX_PG) != 0 || (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) { /* Read PHY Next Page Link Partner */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Page received, NextPage: 0x%04X\n", Word)); }#endif /* DEBUG && !SK_SLIM */ if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) { /* Link down */ return(SK_HW_PS_NONE); }#ifndef SK_SLIM if (pAC->GIni.GICopperType) {#ifdef DEBUG if ((LinkPartAb & PHY_ANE_LP_CAP) == 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Link Partner is not AN able, AN Exp.: 0x%04X\n", Word)); } if ((LinkPartAb & PHY_ANE_PAR_DF) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Parallel Detection Fault, AN Exp.: 0x%04X\n", Word)); }#endif /* DEBUG */ if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) { if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0) { /* Downshift detected */ Para.Para64 = Port; SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Downshift detected, PhySpecStat: 0x%04X\n", PhySpecStat)); SK_ERR_LOG(pAC, SK_ERRCL_INFO, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG); } pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; } if ((PhySpecStat & PHY_M_PS_MDI_X_STAT) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("MDI Xover detected, PhyStat: 0x%04X\n", PhySpecStat)); } if (HW_HAS_NEWER_PHY(pAC)) { /* on PHY 88E1112 cable length is in Reg. 26, Page 5 */ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {#ifdef XXX /* select page 5 to access VCT DSP distance register */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 5); /* get VCT DSP distance */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL_2, &PhySpecStat); SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); pPrt->PCableLen = (SK_U8)(PhySpecStat & PHY_M_EC2_FO_AM_MSK);#endif DspOffs = 29; DspCtrl = 0x8754; DspIncr = 0x1000; } else { /* CHIP_ID_YUKON_EC_U || CHIP_ID_YUKON_EX || CHIP_ID_YUKON_SUPR */ DspOffs = 19; DspCtrl = 0x1018; DspIncr = 0x0001; /* select page 0xff to access VCT DSP distance register */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0x00ff); } for (Word = 0, i = 0; i < 4; i++) { /* select register for MDI pair 0..3 */ SkGmPhyWrite(pAC, IoC, Port, DspOffs, DspCtrl + i * DspIncr); /* get length for MDI pair 0..3 */ SkGmPhyRead(pAC, IoC, Port, DspOffs + 2, &PhySpecStat); Word += PhySpecStat; } pPrt->PCableLen = Word / 4; /* calculate the average */ /* set page register back to 0 */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); } else { /* CHIP_ID_YUKON || CHIP_ID_YUKON_LITE || CHIP_ID_YUKON_EC */ /* on these PHYs the rough estimated cable length is in Reg. 17 */ pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7); } }#ifdef xDEBUG SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("LinkUp Port %d, PHY register dump: 0x%04X\n", Port)); for (i = 0; i < PHY_MARV_PAGE_ADDR; i++) { /* dump all PHY register */ SkGmPhyRead(pAC, IoC, Port, i, &Word); } StartTime = SkOsGetTime(pAC); while (SkOsGetTime(pAC) - StartTime < SK_TICKS_PER_SEC / 2) { /* dummy PHY read */ SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word); }#endif /* DEBUG */#endif /* !SK_SLIM */ if (AutoNeg) { /* Auto-Negotiation Complete ? */ 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); } return(SK_HW_PS_LINK); } } else { /* !AutoNeg */#if (defined(DEBUG) && !defined(SK_SLIM)) if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("ERROR: LiPa auto detected on port %d\n", Port)); }#endif /* DEBUG && !SK_SLIM */ 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 *//****************************************************************************** * * SkGeSirqEvent() - Event Service Routine * * Description: * * Notes: */int SkGeSirqEvent(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 Event, /* Module specific Event */SK_EVPARA Para) /* Event specific Parameter */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ int Port; SK_U16 Word; SK_U32 Val32; int PortStat;#ifndef SK_SLIM SK_U8 Val8;#endif Port = (int)Para.Para32[0]; pPrt = &pAC->GIni.GP[Port]; SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("SIRQ HW Event: %u\n", Event)); switch (Event) { case SK_HWEV_WATIM: if (pPrt->PState == SK_PRT_RESET) { PortStat = SK_HW_PS_NONE; } else { /* 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) { Val32 = SK_WA_ACT_TIME; } else { Val32 = SK_WA_INA_TIME * 5; } /* Start workaround Errata #2 timer */ SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32, SKGE_HWAC, SK_HWEV_WATIM, Para); break; case SK_HWEV_PORT_START:#ifndef SK_SLIM if (pPrt->PHWLinkUp) { /* * Signal directly to RLMT to ensure correct * sequence of SWITCH and RESET event. */ SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); }#endif /* !SK_SLIM */ 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:#ifndef SK_SLIM if (pPrt->PHWLinkUp) { /* * Signal directly to RLMT to ensure correct * sequence of SWITCH and RESET event. */ SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); }#endif /* !SK_SLIM */ /* Stop Workaround Timer */ SkTimerStop(pAC, IoC, &pPrt->PWaTimer); SkHWLinkDown(pAC, IoC, Port); break;#ifndef SK_SLIM 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 < 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 Role (Master/Slave) 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;#endif /* !SK_SLIM */ case SK_HWEV_PAUSE_PACKET: /* get Rx GMAC FIFO Write Level */ SK_IN16(IoC, RX_GMF_WLEV, &Word); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Rx GMAC FIFO Level: 0x%03X\n", Word)); if (Word > (SK_U16)SK_ECU_LLPP) { /* to signal that a Pause ON Packet was sent */ pPrt->PPauseFlag = SK_FALSE; /* send one Pause Packet */ GM_IN16(IoC, Port, GM_GP_CTRL, &Word); /* this will generate also a Pause Packet IRQ */ GM_OUT16(IoC, Port, GM_GP_CTRL, Word | BIT_15S); /* clear bit 15 to be able to re-send one Pause Packet */ GM_OUT16(IoC, Port, GM_GP_CTRL, Word); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Send a Pause Packet\n")); } break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG); break; } return(0);} /* SkGeSirqEvent *//****************************************************************************** * * 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, /* I/O Context */int Port, /* Port Index (MAC_1 + n) */SK_U16 IStatus) /* Interrupt Status */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ SK_EVPARA Para;#ifdef xDEBUG int i; SK_U16 Word; SK_U32 DWord;#endif /* DEBUG */ pPrt = &pAC->GIni.GP[Port]; SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Port %d PHY IRQ, PhyIsrc: 0x%04X\n", Port, IStatus)); if ((IStatus & PHY_M_IS_LST_CHANGE) != 0) { Para.Para32[0] = (SK_U32)Port; if (pPrt->PHWLinkUp) {#ifdef xDEBUG SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &Word); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Link Status changed, PhySpecStat: 0x%04X, ", Word)); /* read the GMAC Interrupt source register */ SK_IN16(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &Word); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("GmacIrqSrc: 0x%02X\n", Word)); if (Word != 0 && (IStatus & PHY_M_IS_SYMB_ERROR) != 0) { /* read all MIB Counters */ for (i = 0; i < GM_MIB_CNT_SIZE; i++) { GM_IN32(IoC, Port, GM_MIB_CNT_BASE + 8*i, &DWord); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("MIB Addr 0x%04X: 0x%08X\n", BASE_GMAC_1 + GM_MIB_CNT_BASE + 8*i, DWord)); } }#endif /* DEBUG */ SkHWLinkDown(pAC, IoC, Port);#ifdef XXX SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("AutoNeg.Adv: 0x%04X\n", Word)); /* Set Auto-negotiation advertisement */ if (pAC->GIni.GIChipId != CHIP_ID_YUKON_FE && pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) { /* restore Asymmetric Pause bit */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, (SK_U16)(Word | PHY_M_AN_ASP)); }#endif /* XXX */ /* Signal to RLMT */ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } else { if ((IStatus & PHY_M_IS_AN_COMPL) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Auto-Negotiation completed\n")); } if ((IStatus & PHY_M_IS_LSP_CHANGE) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Link Speed changed\n")); } SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_WATIM, Para); } } if ((IStatus & PHY_M_IS_AN_ERROR) != 0) { /* the copper PHY makes 1 retry */ if (pAC->GIni.GICopperType) { /* not logged as error, it might be the first attempt */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Auto-Negotiation Error\n")); } else { /* Auto-Negotiation Error */ SK_ERR_LOG(pAC, SK_ERRCL_INFO, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG); } } if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) { /* FIFO Overflow/Underrun Error */ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG); }} /* SkPhyIsrGmac *//* End of File */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -