📄 skgeinit.c
字号:
*/static void SkGeInitBmu(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* IO context */int Port) /* Port Index (MAC_1 + n) */{ SK_GEPORT *pPrt; SK_U32 RxWm; SK_U32 TxWm; pPrt = &pAC->GIni.GP[Port]; RxWm = SK_BMU_RX_WM; TxWm = SK_BMU_TX_WM; if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) { /* for better performance */ RxWm /= 2; TxWm /= 2; } /* Rx Queue: Release all local resets and set the watermark */ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET); SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm); /* * Tx Queue: Release all local resets if the queue is used ! * set watermark */ if (pPrt->PXSQSize != 0) { SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET); SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm); } if (pPrt->PXAQSize != 0) { SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET); SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm); } /* * Do NOT enable the descriptor poll timers here, because * the descriptor addresses are not specified yet. */} /* SkGeInitBmu *//****************************************************************************** * * TestStopBit() - Test the stop bit of the queue * * Description: * Stopping a queue is not as simple as it seems to be. * If descriptor polling is enabled, it may happen * that RX/TX stop is done and SV idle is NOT set. * In this case we have to issue another stop command. * * Returns: * The queues control status register */static SK_U32 TestStopBit(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* IO Context */int QuIoOffs) /* Queue IO Address Offset */{ SK_U32 QuCsr; /* CSR contents */ SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) { /* Stop Descriptor overridden by start command */ SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP); SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); } return(QuCsr);} /* TestStopBit *//****************************************************************************** * * SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'. * * Description: * After calling this function the descriptor rings and Rx and Tx * queues of this port may be reconfigured. * * It is possible to stop the receive and transmit path separate or * both together. * * Dir = SK_STOP_TX Stops the transmit path only and resets the MAC. * The receive queue is still active and * the pending Rx frames may be still transferred * into the RxD. * SK_STOP_RX Stop the receive path. The tansmit path * has to be stopped once before. * SK_STOP_ALL SK_STOP_TX + SK_STOP_RX * * RstMode = SK_SOFT_RST Resets the MAC. The PHY is still alive. * SK_HARD_RST Resets the MAC and the PHY. * * Example: * 1) A Link Down event was signaled for a port. Therefore the activity * of this port should be stopped and a hardware reset should be issued * to enable the workaround of XMAC errata #2. But the received frames * should not be discarded. * ... * SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST); * (transfer all pending Rx frames) * SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST); * ... * * 2) An event was issued which request the driver to switch * the 'virtual active' link to an other already active port * as soon as possible. The frames in the receive queue of this * port may be lost. But the PHY must not be reset during this * event. * ... * SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST); * ... * * Extended Description: * If SK_STOP_TX is set, * o disable the MAC's receive and transmitter to prevent * from sending incomplete frames * o stop the port's transmit queues before terminating the * BMUs to prevent from performing incomplete PCI cycles * on the PCI bus * - The network Rx and Tx activity and PCI Tx transfer is * disabled now. * o reset the MAC depending on the RstMode * o Stop Interval Timer and Limit Counter of Tx Arbiter, * also disable Force Sync bit and Enable Alloc bit. * o perform a local reset of the port's Tx path * - reset the PCI FIFO of the async Tx queue * - reset the PCI FIFO of the sync Tx queue * - reset the RAM Buffer async Tx queue * - reset the RAM Buffer sync Tx queue * - reset the MAC Tx FIFO * o switch Link and Tx LED off, stop the LED counters * * If SK_STOP_RX is set, * o stop the port's receive queue * - The path data transfer activity is fully stopped now. * o perform a local reset of the port's Rx path * - reset the PCI FIFO of the Rx queue * - reset the RAM Buffer receive queue * - reset the MAC Rx FIFO * o switch Rx LED off, stop the LED counter * * If all ports are stopped, * o reset the RAM Interface. * * Notes: * o This function may be called during the driver states RESET_PORT and * SWITCH_PORT. */void SkGeStopPort(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* I/O context */int Port, /* port to stop (MAC_1 + n) */int Dir, /* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */{#ifndef SK_DIAG SK_EVPARA Para;#endif /* !SK_DIAG */ SK_GEPORT *pPrt; SK_U32 DWord; SK_U32 XsCsr; SK_U32 XaCsr; SK_U64 ToutStart; int i; int ToutCnt; pPrt = &pAC->GIni.GP[Port]; if ((Dir & SK_STOP_TX) != 0) { /* disable receiver and transmitter */ SkMacRxTxDisable(pAC, IoC, Port); /* stop both transmit queues */ /* * If the BMU is in the reset state CSR_STOP will terminate * immediately. */ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP); SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP); ToutStart = SkOsGetTime(pAC); ToutCnt = 0; do { /* * Clear packet arbiter timeout to make sure * this loop will terminate. */ SK_OUT16(IoC, B3_PA_CTRL, (Port == MAC_1) ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); /* * If the transfer stucks at the MAC the STOP command will not * terminate if we don't flush the XMAC's transmit FIFO ! */ SkMacFlushTxFifo(pAC, IoC, Port); XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff); XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff); if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) { /* * Timeout of 1/18 second reached. * This needs to be checked at 1/18 sec only. */ ToutCnt++; if (ToutCnt > 1) { /* Might be a problem when the driver event handler * calls StopPort again. XXX. */ /* Fatal Error, Loop aborted */ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018, SKERR_HWI_E018MSG);#ifndef SK_DIAG Para.Para64 = Port; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);#endif /* !SK_DIAG */ return; } /* * Cache incoherency workaround: Assume a start command * has been lost while sending the frame. */ ToutStart = SkOsGetTime(pAC); if ((XsCsr & CSR_STOP) != 0) { SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START); } if ((XaCsr & CSR_STOP) != 0) { SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START); } } /* * Because of the ASIC problem report entry from 21.08.1998 it is * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set. */ } while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE || (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); /* Reset the MAC depending on the RstMode */ if (RstMode == SK_SOFT_RST) { SkMacSoftRst(pAC, IoC, Port); } else { SkMacHardRst(pAC, IoC, Port); } /* Disable Force Sync bit and Enable Alloc bit */ SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); /* Stop Interval Timer and Limit Counter of Tx Arbiter */ SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L); SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L); /* Perform a local reset of the port's Tx path */ /* Reset the PCI FIFO of the async Tx queue */ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET); /* Reset the PCI FIFO of the sync Tx queue */ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET); /* Reset the RAM Buffer async Tx queue */ SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET); /* Reset the RAM Buffer sync Tx queue */ SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET); /* Reset Tx MAC FIFO */ if (pAC->GIni.GIGenesis) { /* Note: MFF_RST_SET does NOT reset the XMAC ! */ SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET); /* switch Link and Tx LED off, stop the LED counters */ /* Link LED is switched off by the RLMT and the Diag itself */ SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS); } else { /* Reset TX MAC FIFO */ SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); } } if ((Dir & SK_STOP_RX) != 0) { /* * The RX Stop Command will not terminate if no buffers * are queued in the RxD ring. But it will always reach * the Idle state. Therefore we can use this feature to * stop the transfer of received packets. */ /* stop the port's receive queue */ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP); i = 100; do { /* * Clear packet arbiter timeout to make sure * this loop will terminate */ SK_OUT16(IoC, B3_PA_CTRL, (Port == MAC_1) ? PA_CLR_TO_RX1 : PA_CLR_TO_RX2); DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff); /* timeout if i==0 (bug fix for #10748) */ if (--i == 0) { SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024, SKERR_HWI_E024MSG); break; } /* * because of the ASIC problem report entry from 21.08.98 * it is required to wait until CSR_STOP is reset and * CSR_SV_IDLE is set. */ } while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); /* The path data transfer activity is fully stopped now */ /* Perform a local reset of the port's Rx path */ /* Reset the PCI FIFO of the Rx queue */ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET); /* Reset the RAM Buffer receive queue */ SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET); /* Reset Rx MAC FIFO */ if (pAC->GIni.GIGenesis) { SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET); /* switch Rx LED off, stop the LED counter */ SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS); } else { /* Reset Rx MAC FIFO */ SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); } }} /* SkGeStopPort *//****************************************************************************** * * SkGeInit0() - Level 0 Initialization * * Description: * - Initialize the BMU address offsets * * Returns: * nothing */static void SkGeInit0(SK_AC *pAC, /* adapter context */SK_IOC IoC) /* IO context */{ int i; SK_GEPORT *pPrt; for (i = 0; i < SK_MAX_MACS; i++) { pPrt = &pAC->GIni.GP[i]; pPrt->PState = SK_PRT_RESET; pPrt->PRxQOff = QOffTab[i].RxQOff; pPrt->PXsQOff = QOffTab[i].XsQOff; pPrt->PXaQOff = QOffTab[i].XaQOff; pPrt->PCheckPar = SK_FALSE; pPrt->PIsave = 0; pPrt->PPrevShorts = 0; pPrt->PLinkResCt = 0; pPrt->PAutoNegTOCt = 0; pPrt->PPrevRx = 0; pPrt->PPrevFcs = 0; pPrt->PRxLim = SK_DEF_RX_WA_LIM; pPrt->PLinkMode = SK_LMODE_AUTOFULL; pPrt->PLinkSpeedCap = SK_LSPEED_CAP_1000MBPS; pPrt->PLinkSpeed = SK_LSPEED_1000MBPS; pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_UNKNOWN; pPrt->PLinkModeConf = SK_LMODE_AUTOSENSE; pPrt->PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; pPrt->PLinkBroken = SK_TRUE; /* See WA code */ pPrt->PLinkCap = (SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL | SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL); pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; pPrt->PFlowCtrlCap = SK_FLOW_MODE_SYM_OR_REM; pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; pPrt->PMSCap = 0; pPrt->PMSMode = SK_MS_MODE_AUTO; pPrt->PMSStatus = SK_MS_STAT_UNSET; pPrt->PAutoNegFail = SK_FALSE; pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; pPrt->PHWLinkUp = SK_FALSE; } pAC->GIni.GIPortUsage = SK_RED_LINK;} /* SkGeInit0*/#ifdef SK_PCI_RESET/****************************************************************************** * * SkGePciReset() - Reset PCI interface * * Description: * o Read PCI configuration. * o Change power state to 3. * o Change power state to 0. * o Restore PCI configuration. * * Returns: * 0: Success. * 1: Power state could not be changed to 3. */static int SkGePciReset(SK_AC *pAC, /* adapter context */SK_IOC IoC) /* IO context */{ int i; SK_U16 PmCtlSts; SK_U32 Bp1; SK_U32 Bp2; SK_U16 PciCmd; SK_U8 Cls; SK_U8 Lat; SK_U8 ConfigSpace[PCI_CFG_SIZE]; /* * Note: Switching to D3 state is like a software reset. * Switching from D3 to D0 is a hardware reset. * We have to save and restore the configuration space. */ for (i = 0; i < PCI_CFG_SIZE; i++) { SkPciReadCfgDWord(pAC, i*4, &ConfigSpace[i]); } /* We know the RAM Interface Arbiter is enabled. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -