📄 ks8695end.c
字号:
#ifdef DEBUG_THIS printf("%s: RxBufLen=%d, original len=%d\n", __FUNCTION__, DI.uRxBufferLen, (ETHERMTU + ENET_HEADER_SIZE + 2));#endif /* please update link status within watchdog routine */ DI.bLinkChanged[0] = TRUE; if (DMA_LAN == DI.usDMAId) { /* if LAN driver, 3 more ports */ DI.bLinkChanged[1] = TRUE; DI.bLinkChanged[2] = TRUE; DI.bLinkChanged[3] = TRUE; } return OK;}/* * SetDefaults * This function is used to set initial defaults before Parse routine. * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure. * * Return(s) * NONE. */LOCAL void SetDefaults(PEND_DEVICE pDrvCtrl){#ifdef DEBUG_THIS /*printf("%s\n", __FUNCTION__);*/#endif /* Transmit Descriptor Count */ DI.nTxDescTotal = TXDESC_DEFAULT; /* 128 | 32 | 32(d) */ /* Receive Descriptor Count */ DI.nRxDescTotal = RXDESC_DEFAULT; /* 128 | 32 | 32(d) */ /* Transmit Checksum Offload Enable configuration */ DI.bTxChecksum = TXCHECKSUM_DEFAULT; /* enabled */ /* Receive Checksum Offload Enable */ DI.bRxChecksum = RXCHECKSUM_DEFAULT; /* enabled */ /* Flow Control */ DI.bRxFlowCtrl = FLOWCONTROL_DEFAULT; /* enabled */ /* currently Tx control flow shares the setting of Rx control flow */ DI.bTxFlowCtrl = DI.bRxFlowCtrl; /* Programmable Burst Length */ DI.byTxPBL = PBL_DEFAULT; /* Tx PBL size */ DI.byRxPBL = PBL_DEFAULT; /* Rx PBL size */ /* Perform PHY PowerDown Reset instead of soft reset, the Option function can be overwritten by user later */ DI.bPowerDownReset = TRUE;#ifdef PACKET_DUMP /* for debug only */ DI.uDebugDumpTxPkt = 0xff; DI.uDebugDumpRxPkt = 0xff;#endif pDrvCtrl->nWatchdogDelay = sysClkRateGet() * 5; /* every 5 secs */}/* * CheckConfigurations * This function checks all command line paramters for valid user * input. If an invalid value is given, or if no user specified * value exists, a default value is used. * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure. * * Return(s) * NONE. */LOCAL void CheckConfigurations(PEND_DEVICE pDrvCtrl){ int i;#ifdef DEBUG_THIS /*printf("%s: (unit=%d)\n", __FUNCTION__, pDrvCtrl->unit);*/#endif /* Tx coalescing, currently can only be used if buffer unavailable bit is set */ DI.nTransmitCoalescing = (DI.nTxDescTotal >> 3); /* User speed and/or duplex options */ DI.usCType[0] = SW_PHY_DEFAULT; if (DMA_LAN == DI.usDMAId) { /*TEMP, currently assume all other ports share same configuration with first one, will add more options for LAN ports later */ for (i = 1; i < SW_MAX_LAN_PORTS; i++) { DI.usCType[i] = DI.usCType[0]; } /* initialize some variables which do not have user configurable options */ for (i = 0; i <= SW_MAX_LAN_PORTS; i++) { DPI[i].byCrossTalkMask = 0x1f; DPI[i].bySpanningTree = SW_SPANNINGTREE_ALL; DPI[i].byDisableSpanningTreeLearn = FALSE; } /* set default as direct mode for port 5, so no lookup table is checking */ DI.bRxDirectMode = FALSE; DI.bTxRreTagMode = FALSE; DI.bPort5FlowCtrl = DI.bRxFlowCtrl; DI.bPortsFlowCtrl = DI.bRxFlowCtrl; }}/* * gpioConfigure * This function is use to configure GPIO pins required for extra LEDs * as speed indicators. * * Argument(s) * pDrvCtrl pionter to END_DEVICE data structure. * * Return(s) * NONE */void gpioConfigure(PEND_DEVICE pDrvCtrl){ UINT32 uReg; uReg = KS8695_READ_REG(REG_GPIO_MODE); switch (DI.usDMAId) {#ifdef KS8695 case DMA_HPNA: return;#endif case DMA_LAN: uReg |= 0xf0; /* GPIO 4-7 for port 1 - 4, configure them as output */ break; default: case DMA_WAN: uReg |= 0x08; /* GPIO 3 for WAN port */ break; } KS8695_WRITE_REG(REG_GPIO_MODE, uReg);}/* * gpioSet * This function is use to set/reset given GPIO pin corresponding to the port. * * Argument(s) * pDrvCtrl pionter to END_DEVICE data structure. * uPort port for the tag to insert * bSet enable/disable LED * * Return(s) * NONE */void gpioSet(PEND_DEVICE pDrvCtrl, UINT uPort, UINT bSet){ UINT32 uReg;#ifdef DEBUG_THIS /*printf("%s: port %d, %s\n", __FUNCTION__, uPort, bSet ? "100" : "10");*/#endif uReg = KS8695_READ_REG(REG_GPIO_DATA); switch (DI.usDMAId) {#ifdef KS8695 case DMA_HPNA: return;#endif case DMA_LAN: if (bSet) uReg &= ~(1 << (uPort + 4)); /* low for LED on */ else uReg |= (1 << (uPort + 4)); /* high for LED off */ break; default: case DMA_WAN: if (bSet) uReg &= ~0x08; /* low for LED on */ else uReg |= 0x08; /* high for LED off */ break; } KS8695_WRITE_REG(REG_GPIO_DATA, uReg);}/* * swGetPhyStatus * This function is used to get the status of auto negotiation. * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure. * uPort port to query * * Return(s) * TRUE if connected * FALSE otherwise */int swGetPhyStatus(PEND_DEVICE pDrvCtrl, UINT uPort){ UINT uReg, uOff, uShift = 0; DRV_LOG(DRV_DEBUG_LOG_PHY, "swGetPhyStatus\n", 1, 2, 3, 4, 5, 6); switch (DI.usDMAId) {#ifdef KS8695 case DMA_HPNA: /* temp */ uReg = KS8695_READ_REG(REG_MISC_CONTROL); DI.usLinkSpeed[uPort] = (uReg & 0x00000002) ? SPEED_100 : SPEED_10; DI.bHalfDuplex[uPort] = (uReg & 0x00000001) ? FULL_DUPLEX : HALF_DUPLEX; /* note that there is no register bit corresponding to HPNA's link status therefore don't report it */ DI.bLinkActive[uPort] = TRUE; return TRUE;#endif case DMA_WAN: uOff = REG_WAN_CONTROL; uShift = 16; break; default: case DMA_LAN: switch (uPort) { case SW_PORT_4: uOff = REG_SWITCH_AUTO1; break; break; case SW_PORT_3: uOff = REG_SWITCH_AUTO1; break; uShift = 16; break; case SW_PORT_2: uOff = REG_SWITCH_AUTO0; break; case SW_PORT_1: default: uOff = REG_SWITCH_AUTO0; uShift = 16; break; } } uReg = KS8695_READ_REG(uOff); /* if not linked yet */ if (!(uReg & ((UINT)SW_AUTONEGO_STAT_LINK << uShift))) { DI.bLinkActive[uPort] = FALSE; DI.usLinkSpeed[uPort] = SPEED_UNKNOWN; DI.bHalfDuplex[uPort] = 0; gpioSet(pDrvCtrl, uPort, FALSE); return FALSE; } DI.bLinkActive[uPort] = TRUE; if (SW_PHY_AUTO == DI.usCType[uPort]) { /* if auto nego complete */ if ((UINT)SW_AUTONEGO_COMPLETE << uShift) { /* clear auto nego restart bit */ uReg &= ~((UINT)SW_AUTONEGO_RESTART << uShift); KS8695_WRITE_REG(uOff, uReg); SW_WRITE_DELAY(); DI.usLinkSpeed[uPort] = (uReg & ((UINT)SW_AUTONEGO_STAT_SPEED << uShift)) ? SPEED_100 : SPEED_10; DI.bHalfDuplex[uPort] = (uReg & ((UINT)SW_AUTONEGO_STAT_DUPLEX << uShift)) ? FULL_DUPLEX : HALF_DUPLEX; DI.bAutoNegoInProgress[uPort] = FALSE; gpioSet(pDrvCtrl, uPort, SPEED_100 == DI.usLinkSpeed[uPort]); /*RLQ, need to verify real duplex mode instead report it correct here */ /* duplex bit may not right if partner doesn't support all mode, do further detection */ if ((uReg & (SW_AUTONEGO_PART_100FD | SW_AUTONEGO_PART_100HD | SW_AUTONEGO_PART_10FD | SW_AUTONEGO_PART_10HD) << uShift) != (SW_AUTONEGO_PART_100FD | SW_AUTONEGO_PART_100HD | SW_AUTONEGO_PART_10FD | SW_AUTONEGO_PART_10HD)) { if (SPEED_100 == DI.usLinkSpeed[uPort]) { if ((uReg & (SW_AUTONEGO_PART_100FD << uShift))) { DI.bHalfDuplexDetected[uPort] = FULL_DUPLEX;#ifndef KS8695 forceFlowControl(pDrvCtrl, uPort, TRUE); backPressureEnable(pDrvCtrl, uPort, FALSE);#endif } else { DI.bHalfDuplexDetected[uPort] = HALF_DUPLEX;#ifndef KS8695 forceFlowControl(pDrvCtrl, uPort, FALSE); backPressureEnable(pDrvCtrl, uPort, TRUE);#endif } } else { if ((uReg & (SW_AUTONEGO_PART_10FD << uShift))) { DI.bHalfDuplexDetected[uPort] = FULL_DUPLEX;#ifndef KS8695 forceFlowControl(pDrvCtrl, uPort, TRUE); backPressureEnable(pDrvCtrl, uPort, FALSE);#endif } else { DI.bHalfDuplexDetected[uPort] = HALF_DUPLEX;#ifndef KS8695 forceFlowControl(pDrvCtrl, uPort, FALSE); backPressureEnable(pDrvCtrl, uPort, TRUE);#endif } } } /* software workaround for flow control, need to know partner's flow control */ if (DMA_WAN == DI.usDMAId) { /* currently do it to WAN only, there is no problem to LAN, will do HPNA later */ uint8_t bFlowCtrl; /* we need to check partner's control flow setting for the matching, if not, changes ours */ bFlowCtrl = ((SW_AUTONEGO_PART_PAUSE << uShift) & uReg) ? TRUE : FALSE; if (bFlowCtrl != DI.bRxFlowCtrl) { /* Tx same as Rx, so test Rx should be enough */ /* need to change ours accordingly, which will overwrite current one */ macConfigureFlow(pDrvCtrl, bFlowCtrl); } }#ifdef DEBUG_THIS printf("%s> Auto Nego completed\n", __FUNCTION__);#endif } else {#ifdef DEBUG_THIS /* auto nego in progress */ printf("%s> Auto Nego in progress...\n", __FUNCTION__);#endif /* wait for next timer */ DI.bLinkActive[uPort] = FALSE; DI.usLinkSpeed[uPort] = SPEED_UNKNOWN; DI.bHalfDuplex[uPort] = 0; } } else {#ifdef DEBUG_THIS printf("%s: media type=%d, port=%d\n", __FUNCTION__, DI.usCType[uPort], uPort);#endif /* manually connection */ if (SW_PHY_10BASE_T_FD == DI.usCType[uPort] || SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) { DI.bHalfDuplex[uPort] = FULL_DUPLEX;#ifndef KS8695 forceFlowControl(pDrvCtrl, uPort, TRUE); backPressureEnable(pDrvCtrl, uPort, FALSE);#endif } else { DI.bHalfDuplex[uPort] = HALF_DUPLEX;#ifndef KS8695 forceFlowControl(pDrvCtrl, uPort, FALSE); backPressureEnable(pDrvCtrl, uPort, TRUE);#endif } if (SW_PHY_100BASE_TX_FD == DI.usCType[uPort] || SW_PHY_100BASE_TX == DI.usCType[uPort]) { DI.usLinkSpeed[uPort] = SPEED_100; gpioSet(pDrvCtrl, uPort, TRUE); } else { DI.usLinkSpeed[uPort] = SPEED_10; gpioSet(pDrvCtrl, uPort, FALSE); } /* software workaround for flow control, need to know partner's flow control */ if (DMA_WAN == DI.usDMAId) { /* currently do it to WAN only, there is no problem to LAN, will do HPNA later */ macConfigureFlow(pDrvCtrl, FULL_DUPLEX == DI.bHalfDuplex[uPort] ? TRUE : FALSE); } } return TRUE;}/* * swDetectPhyConnection * This function is used to start auto negotiation * * Argument(s) * pDrvCtrl pointer to END_DEVICE struct * uPort port to start * * Return(s) * NONE. */LOCAL void swDetectPhyConnection(PEND_DEVICE pDrvCtrl, UINT uPort){ if (LINK_SELECTION_FORCED != DI.byDisableAutoNego[uPort] && !DI.bAutoNegoInProgress[uPort] && DI.bLinkChanged[uPort]) { swAutoNegoStart(pDrvCtrl, uPort); DI.bLinkChanged[uPort] = FALSE; DI.bLinkActive[uPort] = FALSE; } swGetPhyStatus(pDrvCtrl, uPort);}/* * swPhyReset * This function is used to reset phy chipset (powerdown or soft reset). * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure. * uPort port to start * * Return(s) * NONE */void swPhyReset(PEND_DEVICE pDrvCtrl, UINT uPort){ UINT uReg, uShift = 0; UINT uPowerReg; UINT uReg1;#ifdef DEBUG_THIS /*printf("%s\n", __FUNCTION__);*/#endif /* IEEE spec. of auto nego bit */ uReg1 = BIT(7); switch (DI.usDMAId) {#ifdef KS8695 case DMA_HPNA: return;#endif case DMA_WAN: uPowerReg = REG_WAN_POWERMAGR; break; default: case DMA_LAN: switch (uPort) { case SW_PORT_4: uPowerReg = REG_LAN34_POWERMAGR; break; case SW_PORT_3: uPowerReg = REG_LAN34_POWERMAGR; uShift = 16; break; case SW_PORT_2: uPowerReg = REG_LAN12_POWERMAGR; break; case SW_PORT_1: default: uPowerReg = REG_LAN12_POWERMAGR; uShift = 16; break; } }#ifdef DEBUG_THIS /*printf("%s: reg=0x%04x, shift=%d, val=0x%08x\n", __FUNCTION__, uPowerReg, uShift, KS8695_READ_REG(uPowerReg));*/#endif if (DI.bPowerDownReset) { uReg = KS8695_READ_REG(uPowerReg); KS8695_WRITE_REG(uPowerReg, uReg | ((UINT)POWER_POWERDOWN << uShift));#ifndef NO_TASK_DELAY taskDelay(8);#else delayEx(800000);#endif uReg &= ~((UINT)POWER_POWERDOWN << uShift); /* turn off IEEE auto nego */ uReg &= ~(uReg1 << uShift); KS8695_WRITE_REG(uPowerReg, uReg); /* need 20 cpu clock delay for switch related registers */ SW_WRITE_DELAY(); } else { uReg = KS8695_READ_REG(uPowerReg); /* turn off IEEE auto nego */ uReg &= ~(uReg1 << uShift); KS8695_WRITE_REG(uPowerReg, uReg); /* need 20 cpu clock delay for switch related registers */ SW_WRITE_DELAY(); }}/* * macReset * This function will execute a soft reset the chipset. * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure. * * Return(s) * OK if success * ERROR otherwise */int macReset(PEND_DEVICE pDrvCtrl){ int nTimeOut = 200; UINT32 uReg;#ifdef DEBUG_THIS /*printf("%s\n", __FUNCTION__);*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -