📄 ks8695end.c
字号:
LOCAL void ks8695_relink(PEND_DEVICE pDrvCtrl);LOCAL void ks8695_set_multi(PEND_DEVICE pDrvCtrl);LOCAL void macStopAll(PEND_DEVICE pDrvCtrl);LOCAL STATUS ks8695_ChipInit(PEND_DEVICE pDrvCtrl, UINT8 bResetPhy);LOCAL void ks8695_dump_reg(PEND_DEVICE pDrvCtrl, UINT32 offset, UINT32 range);LOCAL void ks8695_dump_reg_set(PEND_DEVICE pDrvCtrl, UINT32 set);LOCAL UINT32 swReadSNMPReg(PEND_DEVICE pDrvCtrl, UINT uIndex);/* RLQ, TEMP */LOCAL void ks8695IntTxComp(END_DEVICE *pDrvCtrl);LOCAL void ks8695IntRxAvail(END_DEVICE *pDrvCtrl);LOCAL void ks8695IntTxUnavail(END_DEVICE *pDrvCtrl);LOCAL void ks8695IntRxUnavail(END_DEVICE *pDrvCtrl);LOCAL void ks8695IntTxStop(END_DEVICE *pDrvCtrl);LOCAL void ks8695IntRxStop(END_DEVICE *pDrvCtrl);#ifdef DRV_DEBUGLOCAL void logValue(char *prompt, UINT32 value, int hex, UINT32 flag);#endifLOCAL void ks8695_watchdog(PEND_DEVICE pDrvCtrl);#ifndef KS8695void forceFlowControl(PEND_DEVICE pDrvCtrl, UINT uPort, UINT bOn);void backPressureEnable(PEND_DEVICE pDrvCtrl, UINT uPort, UINT bOn);#endifLOCAL UINT32 bPowerSaving = FALSE;LOCAL UINT32 bAllowPowerSaving = FALSE;#ifdef NO_TASK_DELAY/* * delayEx * This function is use to delay a little bit without using taskDelay. * * Argument(s) * count loop count to delay * * Return(s) * NONE. */LOCAL void delayEx(UINT32 count) { int i; while (count--) { i++; }}#endif#if 0/* * delayTicks * This function is use to delay given ticks. * * Argument(s) * ticks ticks to delay * * Return(s) * NONE. */LOCAL void delayTicks(UINT ticks) { ULONG currentTicks; if (ticks) { currentTicks = tickGet(); while (tickGet() < (currentTicks + ticks)); }}/* * delayOneSec * This function is use to delay a second. * * Argument(s) * NONE * * Return(s) * NONE. */LOCAL void delayOneSec(void){ delayTicks(sysClkRateGet());}#endif#ifdef DRV_DEBUG/* * logValue * This function is use to print register value using logging mechanims. * * Argument(s) * prompt pointer to the prompt string * value register value to prompt for debug * hex hex or decimal value * flag log bit flag * * Return(s) * NONE. */LOCAL void logValue(char *prompt, UINT32 value, int hex, UINT32 flag){ char buf[128]; if (hex) sprintf(buf, "%s=0x%08x\n", prompt, value); else sprintf(buf, "%s=%d\n", prompt, value); DRV_LOG(flag, buf, 1, 2, 3, 4, 5, 6);}#endif/* * printStr * This function is use to delay a second. * * Argument(s) * str pointer to a string to print out in sync manner (for debug) * * Return(s) * NONE. */LOCAL void printStr(char *str){ int i, len; len = strlen(str); if (len) { KS8695_WRITE_REG(REG_GPIO_DATA, 0x0000ffdf); for (i = 0; i < len; i++) { KS8695_WRITE_REG(REG_UART_TX_HOLDING, *(str + i)); } KS8695_WRITE_REG(REG_UART_TX_HOLDING,0x0a); KS8695_WRITE_REG(REG_UART_TX_HOLDING,0x0d); }}/* * ks8695_set_multi * This function is used to set Multicast and Promiscuous mode. It is * called whenever the multicast address list or the network interface * flags are updated. This routine is resposible for configuring the * hardware for proper multicast, promiscuous mode, and all-multi behavior. * * Argument(s) * pDrvCtrl pointer to END_DEVICE struct * * Return(s) * NONE. */LOCAL void ks8695_set_multi(PEND_DEVICE pDrvCtrl){ uint32_t uReg; BOOLEAN bRxStarted;#ifdef DEBUG_THIS /*if (END_FLAGS_GET(&pDrvCtrl->end)) printf("%s: flags=0x%08x\n", __FUNCTION__, (UINT32)END_FLAGS_GET(&pDrvCtrl->end));*/#endif bRxStarted = DI.bRxStarted; if (bRxStarted) macStartRx(pDrvCtrl, FALSE); /* read RX mode register in order to set hardware filter mode */ uReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset); uReg |= DMA_UNICAST | DMA_BROADCAST; uReg &= ~(DMA_PROMISCUOUS | DMA_MULTICAST); if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) { uReg |= DMA_PROMISCUOUS; } if (END_FLAGS_GET(&pDrvCtrl->end) & (IFF_ALLMULTI | IFF_MULTICAST)) { uReg |= DMA_MULTICAST; } KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uReg); if (bRxStarted) macStartRx(pDrvCtrl, TRUE); /*ks8695_relink(pDrvCtrl);*/}/* * ResetDma * This function is use to reset DMA in case Tx DMA was sucked due to * heavy traffic condition. * * Argument(s) * pDrvCtrl pointer to END_DEVICE struct * * Return(s) * 0 if success * negative value if failed */LOCAL __inline void ResetDma(PEND_DEVICE pDrvCtrl){ UINT uRxReg; if (KS8695_FLAGS_ISSET(&pDrvCtrl->end, IFF_RUNNING)) { logMsg("ResetDma, not running!\n", 1, 2, 3, 4, 5, 6); return; } logMsg("ResetDma\n", 1, 2, 3, 4, 5, 6); return; END_FLAGS_CLR(&pDrvCtrl->end, (IFF_UP | IFF_RUNNING)); macStopAll(pDrvCtrl); CleanRxRing(pDrvCtrl); InitRxRing(pDrvCtrl); CleanTxRing(pDrvCtrl); InitTxRing(pDrvCtrl); ReceiveBufferFill(pDrvCtrl); ks8695_ChipInit(pDrvCtrl, FALSE); KS8695_WRITE_REG(REG_INT_STATUS, DI.uIntMask); /* read RX mode register */ uRxReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset); if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) { uRxReg |= DMA_PROMISCUOUS; } if (END_FLAGS_GET(&pDrvCtrl->end) & (IFF_ALLMULTI | IFF_MULTICAST)) { uRxReg |= DMA_MULTICAST; } uRxReg |= DMA_BROADCAST; /* write RX mode register */ KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uRxReg); KS8695_WRITE_REG(REG_RXBASE + DI.nOffset, DI.RxDescDMA); KS8695_WRITE_REG(REG_TXBASE + DI.nOffset, DI.TxDescDMA); macEnableInterrupt(pDrvCtrl, TRUE); macStartRx(pDrvCtrl, TRUE); macStartTx(pDrvCtrl, TRUE); DI.bTxNoResource = FALSE; END_FLAGS_SET(&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));}/* * hook_irqs * This function is used to hook irqs associated to given DMA type * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure. * req request or free interrupts * * Return(s) * OK if success * ERROR if failed */LOCAL int hook_irqs(PEND_DEVICE pDrvCtrl, int req){ STATUS result; int i; switch (DI.usDMAId) { default: break; case DMA_WAN: if (DI.uLinkIntMask & INT_WAN_LINK) { if (req) { result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(31), ks8695IntLink, (int)pDrvCtrl); if (ERROR == result) { printf("%s: intConnect failed, %d\n", __FUNCTION__, 31); intEnable(INT_LVL_WMLCS); return result; } } else { intDisable(INT_LVL_WMLCS); } } break; } /* each DMA has 6 interrupt bits associated, except WAN which has one extra, INT_WAN_LINK */ for (i = 0; i < 6; i++) { if (DI.uIntMask & (1L << (DI.uIntShift + i))) { if (req) { switch ((1 << i)) { default: case INT_TX_BIT: result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntTxComp, (int)pDrvCtrl); break; case INT_RX_BIT: result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntRxAvail, (int)pDrvCtrl); break; case INT_TX_UNAVAIL_BIT: result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntTxUnavail, (int)pDrvCtrl); break; case INT_RX_UNAVAIL_BIT: result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntRxUnavail, (int)pDrvCtrl); break; case INT_TX_STOPPED_BIT: result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntTxStop, (int)pDrvCtrl); break; case INT_RX_STOPPED_BIT: result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntRxStop, (int)pDrvCtrl); break; } /*result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695Int, (int)pDrvCtrl);*/ if (ERROR == result) { /* disconnect any one connected first ? */ printf("%s: intConnect failed, %d\n", __FUNCTION__, (i + DI.uIntShift)); return result; } intEnable(i + DI.uIntShift); } else { intDisable(i + DI.uIntShift); } } } return OK;}/* * ks8695_dump_packet * This function is use to dump given packet for debugging. * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure. * data pointer to the beginning of the packet to dump * len length of the packet * flag debug flag * * Return(s) * NONE. */LOCAL __inline void ks8695_dump_packet(PEND_DEVICE pDrvCtrl, unsigned char *data, int len, UINT flag){ /* we may need to have locking mechamism to use this function, since Rx call it within INT context and Tx call it in normal context */ if (flag && len >= 18) { if (flag & DEBUG_PACKET_LEN) { printf("Pkt Len=%d\n", len); } if (flag & DEBUG_PACKET_HEADER) { printf("DA=%02x:%02x:%02x:%02x:%02x:%02x\n", *data, *(data + 1), *(data + 2), *(data + 3), *(data + 4), *(data + 5)); printf("SA=%02x:%02x:%02x:%02x:%02x:%02x\n", *(data + 6), *(data + 7), *(data + 8), *(data + 9), *(data + 10), *(data + 11)); printf("Type=%04x (%d)\n", ntohs(*(unsigned short *)(data + 12)), ntohs(*(unsigned short *)(data + 12))); } if (flag & DEBUG_PACKET_CONTENT) { int j = 0, k; /* skip DA/SA/TYPE */ data += ENET_HEADER_SIZE; len -= ENET_HEADER_SIZE; do { printf("\n %04d ", j); for (k = 0; (k < 16 && len); k++, data++, len--) { printf("%02x ", *data); } j += 16; } while (len > 0); /* last dump crc field */ /*printf("\nCRC=%04x\n", ntohl(*(unsigned int *)data));*/ printf("\n"); } }}/* * ks8695_dump_reg * This function is use to dump registers of given range! * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure. * offset register offset to dump * length length of registers to dump * * Return(s) * NONE. */LOCAL void ks8695_dump_reg(PEND_DEVICE pDrvCtrl, UINT32 offset, UINT32 length){ int i; UINT32 val; printf("-reg- --value(hex)-- --value(dec)---\n"); for (i = offset; i <= (offset + length); i += 4) { val = KS8695_READ_REG(i); printf("0x%04x 0x%08x %12d\n", i, val, val); }}/* * ks8695_dump_reg_set * This function is use to dump registers of given range! * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure. * set bit for which set to dump * * Return(s) * NONE. */LOCAL void ks8695_dump_reg_set(PEND_DEVICE pDrvCtrl, UINT32 set){ if (set & SET_DMA_DUMP) { ks8695_dump_reg(pDrvCtrl, DI.nOffset + REG_TXCTRL, REG_STATION_HIGH); } if (set & SET_DMA_STATION_DUMP) { ks8695_dump_reg(pDrvCtrl, DI.nOffset + REG_MAC0_LOW, (REG_MAC15_HIGH - REG_MAC0_LOW)); } if (set & SET_UART_DUMP) { ks8695_dump_reg(pDrvCtrl, REG_UART_RX_BUFFER, (REG_UART_STATUS - REG_UART_RX_BUFFER)); } if (set & SET_INT_DUMP) { /*ks8695_dump_reg(pDrvCtrl, REG_INT_CONTL, (REG_IRQ_PEND_PRIORITY - REG_INT_CONTL));*/ ks8695_dump_reg(pDrvCtrl, REG_INT_CONTL, (REG_INT_LAN_PRIORITY - REG_INT_CONTL)); } if (set & SET_TIMER_DUMP) { ks8695_dump_reg(pDrvCtrl, REG_TIMER_CTRL, (REG_TIMER0_PCOUNT -REG_TIMER_CTRL)); } if (set & SET_GPIO_DUMP) { ks8695_dump_reg(pDrvCtrl, REG_GPIO_MODE, (REG_GPIO_DATA - REG_GPIO_MODE)); } if (set & SET_SWITCH_DUMP) { ks8695_dump_reg(pDrvCtrl, REG_SWITCH_CTRL0, (REG_LAN34_POWERMAGR - REG_SWITCH_CTRL0)); } if (set & SET_MISC_DUMP) { ks8695_dump_reg(pDrvCtrl, REG_DEVICE_ID, (REG_WAN_PHY_STATUS - REG_DEVICE_ID)); } if (set & SET_SNMP_DUMP) {#if 0 UINT32 val; for (i = 0; i <= REG_SNMP_MAX ; i++) { val = swReadSNMPReg(pDrvCtrl, i); printf("0x%04x = %10d\n", i, val); }#endif }}/* * ks8695_relink * This function is use to setup link in case some dynamic configuration * is applied via ifconfig! if driver is opened! * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure. * * Return(s) * NONE. */LOCAL void ks8695_relink(PEND_DEVICE pDrvCtrl){ if (KS8695_FLAGS_ISSET(&pDrvCtrl->end, IFF_RUNNING)) { /* reset the flag even if auto nego is in progress to make sure we don't miss it!!! */ if (DMA_LAN != DI.usDMAId) { swDetectPhyConnection(pDrvCtrl, 0); } else { int i; for (i = 0; i < SW_MAX_LAN_PORTS; i++) { swDetectPhyConnection(pDrvCtrl, i); } } } else { printf("%s: not running\n", __FUNCTION__); }}/* * SoftwareInit * This function initializes the pDrvCtrl private data structure. * * Argument(s) * pDrvCtrl pointer to END_DEVICE structure * * Return(s) * OK if success * ERROR if failed */LOCAL int SoftwareInit(PEND_DEVICE pDrvCtrl){ /* Initial Receive Buffer Length */ if ((ETHERMTU + ENET_HEADER_SIZE + ETH_CRC_LENGTH + 2) < KS8695_MIN_FBUF - 4) { DI.uRxBufferLen = KS8695_MIN_FBUF; /* 0x600 */ } else if ((ETHERMTU + ENET_HEADER_SIZE + ETH_CRC_LENGTH + 2) <= BUFFER_1568 - 4) { DI.uRxBufferLen = BUFFER_1568; /* 0x620 */ } else { DI.uRxBufferLen = BUFFER_2048; /* 0x800 */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -