📄 skgesirq.c
字号:
/* Leave all as configured */ return(pPrt->PLinkModeConf); } if (pPrt->PLinkMode == SK_LMODE_AUTOFULL) { /* Return next mode AUTOBOTH */ return(SK_LMODE_AUTOBOTH); } /* Return default autofull */ return(SK_LMODE_AUTOFULL);} /* SkHWSenseGetNext *//****************************************************************************** * * SkHWSenseSetNext() - Autosensing Set next mode * * Description: sets the appropriate next mode * * Returns: N/A */void SkHWSenseSetNext(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port, /* Port Index (MAC_1 + n) */SK_U8 NewMode) /* New Mode to be written in sense mode */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ pPrt = &pAC->GIni.GP[Port]; pPrt->PAutoNegTimeOut = 0; if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { return; } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("AutoSensing: next mode %d on Port %d\n", (int)NewMode, Port)); pPrt->PLinkMode = NewMode; return;} /* SkHWSenseSetNext *//****************************************************************************** * * SkHWLinkDown() - Link Down handling * * Description: handles the hardware link down signal * * Returns: N/A */void SkHWLinkDown(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ pPrt = &pAC->GIni.GP[Port]; /* Disable all MAC interrupts */ SkMacIrqDisable(pAC, IoC, Port); /* Disable Receiver and Transmitter */ SkMacRxTxDisable(pAC, IoC, Port); /* Init default sense mode */ SkHWInitDefSense(pAC, IoC, Port); if (!pPrt->PHWLinkUp) { return; } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Link down Port %d\n", Port)); /* Set Link to DOWN */ pPrt->PHWLinkUp = SK_FALSE; /* Reset Port stati */ pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_INDETERMINATED; /* Re-init Phy especially when the AutoSense default is set now */ SkMacInitPhy(pAC, IoC, Port, SK_FALSE); /* GP0: used for workaround of Rev. C Errata 2 */ /* Do NOT signal to RLMT */ /* Do NOT start the timer here */} /* SkHWLinkDown *//****************************************************************************** * * SkHWLinkUp() - Link Up handling * * Description: handles the hardware link up signal * * Returns: N/A */void SkHWLinkUp(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ pPrt = &pAC->GIni.GP[Port]; if (pPrt->PHWLinkUp) { /* We do NOT need to proceed on active link */ return; } pPrt->PHWLinkUp = SK_TRUE; pPrt->PAutoNegFail = SK_FALSE; pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; if (pPrt->PLinkMode != SK_LMODE_AUTOHALF && pPrt->PLinkMode != SK_LMODE_AUTOFULL && pPrt->PLinkMode != SK_LMODE_AUTOBOTH) { /* Link is up and no Auto-negotiation should be done */ /* Link speed should be the configured one */ switch (pPrt->PLinkSpeed) { case SK_LSPEED_AUTO: /* default is 1000 Mbps */ case SK_LSPEED_1000MBPS: pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; break; case SK_LSPEED_100MBPS: pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS; break; case SK_LSPEED_10MBPS: pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS; break; } /* Set Link Mode Status */ if (pPrt->PLinkMode == SK_LMODE_FULL) { pPrt->PLinkModeStatus = SK_LMODE_STAT_FULL; } else { pPrt->PLinkModeStatus = SK_LMODE_STAT_HALF; } /* No flow control without auto-negotiation */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; /* enable Rx/Tx */ SkMacRxTxEnable(pAC, IoC, Port); }} /* SkHWLinkUp *//****************************************************************************** * * SkMacParity() - MAC parity workaround * * Description: handles MAC parity errors correctly * * Returns: N/A */static void SkMacParity(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index of the port failed */{ SK_EVPARA Para; SK_GEPORT *pPrt; /* GIni Port struct pointer */ SK_U32 TxMax; /* TxMax Counter */ pPrt = &pAC->GIni.GP[Port]; /* Clear IRQ Tx Parity Error */ if (pAC->GIni.GIGenesis) { SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR); } else { /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)((pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE)); } if (pPrt->PCheckPar) { if (Port == MAC_1) { SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG); } else { SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG); } Para.Para64 = Port; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = Port; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); return; } /* Check whether frames with a size of 1k were sent */ if (pAC->GIni.GIGenesis) { /* Snap statistic counters */ (void)SkXmUpdateStats(pAC, IoC, Port); (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax); } else { (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax); } if (TxMax > 0) { /* From now on check the parity */ pPrt->PCheckPar = SK_TRUE; }} /* SkMacParity *//****************************************************************************** * * SkGeHwErr() - Hardware Error service routine * * Description: handles all HW Error interrupts * * Returns: N/A */static void SkGeHwErr(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */SK_U32 HwStatus) /* Interrupt status word */{ SK_EVPARA Para; SK_U16 Word; if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) { /* PCI Errors occured */ if ((HwStatus & IS_IRQ_STAT) != 0) { SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG); } else { SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG); } /* Reset all bits in the PCI STATUS register */ SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); } if (pAC->GIni.GIGenesis) { if ((HwStatus & IS_NO_STAT_M1) != 0) { /* Ignore it */ /* This situation is also indicated in the descriptor */ SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT); } if ((HwStatus & IS_NO_STAT_M2) != 0) { /* Ignore it */ /* This situation is also indicated in the descriptor */ SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT); } if ((HwStatus & IS_NO_TIST_M1) != 0) { /* Ignore it */ /* This situation is also indicated in the descriptor */ SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST); } if ((HwStatus & IS_NO_TIST_M2) != 0) { /* Ignore it */ /* This situation is also indicated in the descriptor */ SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST); } } else { /* YUKON */ /* This is necessary only for Rx timing measurements */ if ((HwStatus & IS_IRQ_TIST_OV) != 0) { /* Clear Time Stamp Timer IRQ */ SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ); } if ((HwStatus & IS_IRQ_SENSOR) != 0) { /* Clear I2C IRQ */ SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); } } if ((HwStatus & IS_RAM_RD_PAR) != 0) { SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR); SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG); Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); } if ((HwStatus & IS_RAM_WR_PAR) != 0) { SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR); SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG); Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); } if ((HwStatus & IS_M1_PAR_ERR) != 0) { SkMacParity(pAC, IoC, MAC_1); } if ((HwStatus & IS_M2_PAR_ERR) != 0) { SkMacParity(pAC, IoC, MAC_2); } if ((HwStatus & IS_R1_PAR_ERR) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P); SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG); Para.Para64 = MAC_1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = MAC_1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } if ((HwStatus & IS_R2_PAR_ERR) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P); SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG); Para.Para64 = MAC_2; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = MAC_2; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); }} /* SkGeHwErr *//****************************************************************************** * * SkGeSirqIsr() - Special Interrupt Service Routine * * Description: handles all non data transfer specific interrupts (slow path) * * Returns: N/A */void SkGeSirqIsr(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */SK_U32 Istatus) /* Interrupt status word */{ SK_EVPARA Para; SK_U32 RegVal32; /* Read register value */ SK_GEPORT *pPrt; /* GIni Port struct pointer */ unsigned Len; SK_U64 Octets; SK_U16 PhyInt; SK_U16 PhyIMsk; int i; if ((Istatus & IS_HW_ERR) != 0) { /* read the HW Error Interrupt source */ SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); SkGeHwErr(pAC, IoC, RegVal32); } /* * Packet Timeout interrupts */ /* Check whether MACs are correctly initialized */ if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) && pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) { /* MAC 1 was not initialized but Packet timeout occured */ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004, SKERR_SIRQ_E004MSG); } if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) && pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) { /* MAC 2 was not initialized but Packet timeout occured */ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005, SKERR_SIRQ_E005MSG); } if ((Istatus & IS_PA_TO_RX1) != 0) { /* Means network is filling us up */ SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002, SKERR_SIRQ_E002MSG); SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1); } if ((Istatus & IS_PA_TO_RX2) != 0) { /* Means network is filling us up */ SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003, SKERR_SIRQ_E003MSG); SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2); } if ((Istatus & IS_PA_TO_TX1) != 0) { pPrt = &pAC->GIni.GP[0]; /* May be a normal situation in a server with a slow network */ SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1); /* * workaround: if in half duplex mode, check for Tx hangup. * Read number of TX'ed bytes, wait for 10 ms, then compare * the number with current value. If nothing changed, we assume * that Tx is hanging and do a FIFO flush (see event routine). */ if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && !pPrt->HalfDupTimerActive) { /* * many more pack. arb. timeouts may come in between, * we ignore those */ pPrt->HalfDupTimerActive = SK_TRUE; Len = sizeof(SK_U64); SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 0), pAC->Rlmt.Port[0].Net->NetNumber); pPrt->LastOctets = Octets; Para.Para32[0] = 0; SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); } } if ((Istatus & IS_PA_TO_TX2) != 0) { pPrt = &pAC->GIni.GP[1]; /* May be a normal situation in a server with a slow network */ SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2); /* workaround: see above */ if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && !pPrt->HalfDupTimerActive) { pPrt->HalfDupTimerActive = SK_TRUE; Len = sizeof(SK_U64); SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 1), pAC->Rlmt.Port[1].Net->NetNumber); pPrt->LastOctets = Octets; Para.Para32[0] = 1; SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); } } /* Check interrupts of the particular queues */ if ((Istatus & IS_R1_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C); SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006, SKERR_SIRQ_E006MSG); Para.Para64 = MAC_1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -