📄 ks8695end.c
字号:
uReg &= ~INT_WAN_MASK;
break;
}
KS8695_WRITE_REG(REG_INT_ENABLE, uReg);
/* reset corresponding register and wait for completion */
KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, DMA_SOFTRESET);
do
{
#ifndef NO_TASK_DELAY
taskDelay(1);
#else
delayEx(100000);
#endif
uReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
if (!(uReg & DMA_SOFTRESET))
break;
} while (--nTimeOut);
if (nTimeOut < 1) {
DRV_LOG(DRV_DEBUG_LOAD, "macReset: timeout error\n", 1, 2, 3, 4, 5, 6);
return ERROR;
}
/* clear statistic counters */
swResetSNMPInfo(pDrvCtrl);
return OK;
}
/*
* macConfigure
* This function is used to set MAC control register based on configurable
* option settings.
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure.
*
* Return(s)
* NONE
*/
void macConfigure(PEND_DEVICE pDrvCtrl)
{
UINT uRxReg, uTxReg;
DRV_LOG(DRV_DEBUG_LOAD, "macConfigure: timeout error\n", 1, 2, 3, 4, 5, 6);
/* read TX mode register */
uTxReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
/* clear PBL bits first */
uTxReg &= ~DMA_PBLTMASK; /* 29:24 */
if (DI.byTxPBL)
uTxReg |= ((UINT32)DI.byTxPBL << DMA_PBLTSHIFT);
if (DI.bTxChecksum) {
uTxReg |= (DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
}
else {
uTxReg &= ~(DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
}
if (DI.bTxFlowCtrl)
{
uTxReg |= DMA_FLOWCTRL;
}
else {
uTxReg &= ~DMA_FLOWCTRL;
}
uTxReg |= (DMA_PADDING | DMA_CRC);
/* write TX mode register */
KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uTxReg);
/* read RX mode register */
uRxReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
/* clear PBL bits first */
uRxReg &= ~DMA_PBLTMASK; /* 29:24 */
if (DI.byRxPBL)
uRxReg |= ((UINT32)DI.byRxPBL << DMA_PBLTSHIFT);
/* checksum */
if (DI.bRxChecksum) {
uRxReg |= (DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
}
else {
uRxReg &= ~(DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
}
/* flow control */
if (DI.bRxFlowCtrl)
{
uRxReg |= DMA_FLOWCTRL;
}
else {
uRxReg &= ~DMA_FLOWCTRL;
}
/* set unicast only, and let ks8695_set_multi function to set the rest */
uRxReg |= DMA_UNICAST;
/* write RX mode register */
KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uRxReg);
}
/*
* macSetStationAddress
* This function sets MAC address to given type (WAN, LAN or HPHA)
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE struct
* pMacAddress pointer to a byte array to hold MAC address (at least 6 bytes long)
*
* Return(s)
* NONE.
*/
void macSetStationAddress(PEND_DEVICE pDrvCtrl, uint8_t *pMacAddress)
{
UINT32 uLow, uHigh;
DRV_LOG(DRV_DEBUG_LOAD, "macSetStationAddress\n", 1, 2, 3, 4, 5, 6);
uLow = ((UINT32)pMacAddress[2] << 24);
uLow += ((UINT32)pMacAddress[3] << 16);
uLow += ((UINT32)pMacAddress[4] << 8);
uLow += pMacAddress[5];
uHigh = ((UINT32)pMacAddress[0] << 8) + pMacAddress[1];
KS8695_WRITE_REG(REG_STATION_LOW + DI.nOffset, uLow);
KS8695_WRITE_REG(REG_STATION_HIGH + DI.nOffset, uHigh);
}
/*
* swConfigurePort
* This function is used to configure a give port for LAN.
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE struct
* uPort port to start
*
* Return(s)
* NONE.
*/
void swConfigurePort(PEND_DEVICE pDrvCtrl, UINT uPort)
{
UINT uReg, uOff;
BOOLEAN bPort5 = FALSE;
if (uPort >= SW_MAX_LAN_PORTS) {
if (SW_MAX_LAN_PORTS == uPort) {
/* port 5 */
bPort5 = TRUE;
}
else {
/* out of range */
DRV_LOG(DRV_DEBUG_ERROR, "swConfigurePort: port out of range\n", 1, 2, 3, 4, 5, 6);
return;
}
}
#if defined(KS8695) || defined(KS8695X)
uOff = KS8695_SWITCH_PORT1 + uPort * 4;
#else
if (bPort5)
uOff = KS8695_SEP5C1;
else
uOff = KS8695_SEP1C1 + uPort * 0x0c;
#endif
uReg = 0;
uReg |= (UINT)DPI[uPort].usTag << 16;
if (!bPort5) {
/* connection media type */
/*uReg &= ~(SW_PORT_DISABLE_AUTONEG | SW_PORT_100BASE | SW_PORT_FULLDUPLEX);*/
if (SW_PHY_AUTO != DI.usCType[uPort]) {
uReg |= SW_PORT_DISABLE_AUTONEG;
if (SW_PHY_100BASE_TX == DI.usCType[uPort] ||
SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) {
uReg |= SW_PORT_100BASE;
}
if (SW_PHY_10BASE_T_FD == DI.usCType[uPort] ||
SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) {
uReg |= SW_PORT_FULLDUPLEX;
}
}
}
else {
/* Rx direct mode */
if (DI.bRxDirectMode) {
uReg |= SW_PORT_RX_DIRECT_MODE;
}
/* Tx Pre-tag mode */
if (DI.bTxRreTagMode) {
uReg |= SW_PORT_TX_PRETAG_MODE;
}
}
/* cross talk bit mask */
uReg |= ((UINT)(DPI[uPort].byCrossTalkMask & 0x1f)) << 8;
/* spanning tree */
if (SW_SPANNINGTREE_ALL == DPI[uPort].bySpanningTree) {
uReg |= SW_PORT_TX_SPANNINGTREE | SW_PORT_RX_SPANNINGTREE;
}
else {
if (SW_SPANNINGTREE_TX == DPI[uPort].bySpanningTree) {
uReg |= SW_PORT_TX_SPANNINGTREE;
}
if (SW_SPANNINGTREE_RX == DPI[uPort].bySpanningTree) {
uReg |= SW_PORT_RX_SPANNINGTREE;
}
}
if (DPI[uPort].byDisableSpanningTreeLearn) {
uReg |= SW_PORT_NO_SPANNINGTREE;
}
/* ingress broadcast storm protection */
if (DPI[uPort].byStormProtection) {
uReg |= SW_PORT_STORM_PROCTION;
}
/* ingress priority */
if (DPI[uPort].byIngressPriority) {
uReg |= SW_PORT_HI_PRIORITY;
}
if (DPI[uPort].byIngressPriorityTOS) {
uReg |= SW_PORT_TOS_ENABLE;
}
if (DPI[uPort].byIngressPriority802_1P) {
uReg |= SW_PORT_8021Q_ENABLE;
}
/* egress priority */
if (DPI[uPort].byEgressPriority) {
uReg |= SW_PORT_PRIOTIRY_ENABLE;
}
KS8695_WRITE_REG(uOff, uReg);
/* need 20 cpu clock delay for switch related registers */
SW_WRITE_DELAY();
}
#ifdef USE_READSNMPREG
/*
* swReadSNMPReg
* This function is used to read SNMP registers
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure.
* uIndex index of SNMP register to read
*
* Return(s)
* value read
*/
LOCAL UINT32 swReadSNMPReg(PEND_DEVICE pDrvCtrl, UINT uIndex)
{
#if defined(KS8695) || defined(KS8695X)
UINT uValue, uTimeout = 0;
if (uIndex >= 512)
uIndex = 511;
KS8695_WRITE_REG(KS8695_MANAGE_COUNTER, uIndex);
SW_WRITE_DELAY();
do {
uValue = KS8695_READ_REG(KS8695_MANAGE_DATA);
if (uValue & SW_SNMP_DATA_VALID) {
if (uValue & SW_SNMP_DATA_OVERFLOW) {
KS8695_WRITE_REG(KS8695_MANAGE_DATA, SW_SNMP_DATA_OVERFLOW);
}
/* clear status bits */
uValue &= 0x3fffffff;
return uValue;
}
SW_WRITE_DELAY();
}
while (uTimeout++ < 1000);
if (uValue & SW_SNMP_DATA_OVERFLOW) {
KS8695_WRITE_REG(KS8695_MANAGE_DATA, SW_SNMP_DATA_OVERFLOW);
}
#else
UINT32 reg, value, timeout = 0;
reg = KS8695_SEIAC_READ | KS8695_SEIAC_TAB_MIB | (KS8695_SEIAC_INDEX_MASK & uIndex);
do {
KS8695_WRITE_REG(KS8695_SEIAC, reg);
SW_WRITE_DELAY();
value = KS8695_READ_REG(KS8695_SEIADL);
if (value & SW_SNMP_DATA_VALID) {
if (value & SW_SNMP_DATA_OVERFLOW) {
reg = KS8695_SEIAC_WRITE | KS8695_SEIAC_TAB_MIB | (KS8695_SEIAC_INDEX_MASK & uIndex);
KS8695_WRITE_REG(KS8695_SEIAC, reg);
SW_WRITE_DELAY();
}
/* clear status bits */
value &= 0x3fffffff;
return value;
}
}
while (timeout++ < 1000);
#endif
logMsg("swReadSNMPReg: timeout error\n", 1, 2, 3, 4, 5, 6);
return 0;
}
#endif /*USE_READSNMPREG*/
/*
* swConfigure
* This function is used to config switch engine. It is assume that
* the BIST is performed already (by boot loader).
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure.
*
* Return(s)
* NONE
*/
void swConfigure(PEND_DEVICE pDrvCtrl)
{
UINT uReg, i;
DRV_LOG(DRV_DEBUG_LOAD, "swConfigure\n", 1, 2, 3, 4, 5, 6);
if (DMA_LAN == DI.usDMAId) {
/* read switch control 0 register */
uReg = KS8695_READ_REG(REG_SWITCH_CTRL0);
/* flow control for LAN ports */
if (DI.bPort5FlowCtrl)
{
/* flow control for port 5 */
uReg |= SW_CTRL0_ENABLE_PORT5;
}
else {
uReg &= ~SW_CTRL0_ENABLE_PORT5;
}
#if defined(KS8695) || defined(KS8695X)
if (DI.bPortsFlowCtrl)
{
/* four flow control for each LAN port */
uReg |= SW_CTRL0_ENABLE_PORTS;
}
else {
uReg &= ~SW_CTRL0_ENABLE_PORTS;
}
#else
#if 0
/* RLQ, need to verify */
for (i = 0; i < SW_MAX_LAN_PORTS; i++) {
forceFlowControl(pDrvCtrl, i, DI.bPortsFlowCtrl);
//if (!DI.bPortsFlowCtrl)
// backPressureEnable(pDrvCtrl, i, DI.bPortsFlowCtrl);
backPressureEnable(pDrvCtrl, i, TRUE);
}
#endif
#endif
/*RLQ, 11/20/2002, requested by Hock, backpressure will fix packet
* drop problem in half duplex mode
*/
uReg |= 0x00000020; /* bit 5 */
/* set flow control fairness mode based on LAN flow control settings, should use */
#if !defined(KS8695) && !defined(KS8695X)
/*RLQ, EXPE, 11/14/2003 */
uReg |= KS8695_SEC0_PASS_ALL_FRAMES;
#else
uReg |= KS8695_SWITCH_CTRL0_PASS_ALL_FRAMES;
#endif
/* read switch control 0 register */
KS8695_WRITE_REG(REG_SWITCH_CTRL0, uReg);
/* need 20 cpu clock delay for switch related registers */
SW_WRITE_DELAY();
/* configure LAN port 1-4 and Port 5 */
for (i = 0; i <= SW_MAX_LAN_PORTS; i++)
swConfigurePort(pDrvCtrl, i);
}
else {
DRV_LOG(DRV_DEBUG_ERROR, "swConfigure: not supported type\n", 1, 2, 3, 4, 5, 6);
}
}
/*
* macConfigureFlow
* This function is used to set mac flow control as a workaround for WAN port.
* option settings.
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure.
* bFlowCtrl flow control to set
*
* Return(s)
* NONE
*/
void macConfigureFlow(PEND_DEVICE pDrvCtrl, uint8_t bFlowCtrl)
{
UINT uRxReg, uTxReg;
BOOLEAN bTxStarted, bRxStarted;
DRV_LOG(DRV_DEBUG_LOAD, "macConfigureFlow\n", 1, 2, 3, 4, 5, 6);
/* need to stop mac engines if started */
bTxStarted = DI.bTxStarted;
bRxStarted = DI.bRxStarted;
if (bRxStarted)
macStartRx(pDrvCtrl, FALSE);
if (bTxStarted)
macStartTx(pDrvCtrl, FALSE);
/* read TX mode register */
uTxReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
if (bFlowCtrl)
{
uTxReg |= DMA_FLOWCTRL;
}
else {
uTxReg &= ~DMA_FLOWCTRL;
}
/* write TX mode register */
KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uTxReg);
/* read RX mode register */
uRxReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
if (bFlowCtrl)
{
uRxReg |= DMA_FLOWCTRL;
}
else {
uRxReg &= ~DMA_FLOWCTRL;
}
/* write RX mode register */
KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uRxReg);
if (bRxStarted)
macStartRx(pDrvCtrl, TRUE);
if (bTxStarted)
macStartTx(pDrvCtrl, TRUE);
}
/*
* macSetLoopback
* This function is used to set MAC lookback mode (for debugging purpose)
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure.
*
* Return(s)
* NONE
*/
void macSetLoopback(PEND_DEVICE pDrvCtrl, BOOLEAN bLoopback)
{
UINT uTxReg;
BOOLEAN bTxStarted, bRxStarted;
bTxStarted = DI.bTxStarted;
bRxStarted = DI.bRxStarted;
if (bRxStarted)
macStartRx(pDrvCtrl, FALSE);
if (bTxStarted)
macStartTx(pDrvCtrl, FALSE);
/* read TX mode register */
uTxReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
if (bLoopback)
{
uTxReg |= DMA_LOOPBACK;
}
else {
uTxReg &= ~DMA_LOOPBACK;
}
/* write TX mode register */
KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uTxReg);
if (bRxStarted)
macStartRx(pDrvCtrl, TRUE);
if (bTxStarted)
macStartTx(pDrvCtrl, TRUE);
}
/*
* macStartRx
* This routine will start/stop RX machine.
*
* Inputs:
* pDrvCtrl pointer to END_DEVICE data structure.
* bStart TRUE if start Rx machine, FALSE if stop it
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -