📄 cpmac.c
字号:
if ((rx_bd_head[ii].buff = (char *) PHYS(tmp)) == NULL) { return SBL_ERESCRUNCH; } rx_bd_head[ii].buff_params = 0; /* clears the buffer offset. */ rx_bd_head[ii].buff_params = RX_BUFF_SZ & MASK(15, 0); rx_bd_head[ii].ctrl_n_len = 0; rx_bd_head[ii].ctrl_n_len |= BD_OWNS; } /* Set the RX DMA HDP. Only 1 channel (0) is used. */ /* debug. */ if (REG32_R(CPMAC_A_RX_DMAHDP(0), 31, 0) != 0) { sys_printf("\nPanic: RX DMA HDP is not cleared before setting !"); for (;;); } REG32_W(CPMAC_A_RX_DMAHDP(0), PHYS(rx_bd_head)); /* Set the Free Buffer Count reg, for flow control. */ REG32_W(CPMAC_A_RX_FBUFF(0), RX_BD_COUNT); return SBL_SUCCESS;}/* Returns: * SBL_SUCCESS: Success. * SBL_ETIMEOUT: Timeout to tx. * SBL_ELKDN: Link is down. * SBL_ERESCRUNCH: TX BD not free. * * buff status: * - buff passed by caller should be in KSEG1. * - If tx successful, buff is freed. * - If link goes down after updating tx BD, or timeout happens buff is locked. * Can not be reused (by caller). * - If resource crunch, buff can be reused (by caller). */Status cpmac_tx(char *buff, u4 pkt_sz){ BuffDesc *tx_bd; u4 ii, pp; u4 ret = FALSE;#ifdef CPMAC_DEBUG sys_printf("Entered CpMac Tx\n");#endif if ((cpmac_st->link_state = lk_st(0)) == LK_DN) { return SBL_ELKDN; } /* TX BD update should be in uncached region. */ tx_bd = &cpmac_st->tx[0];#ifdef CPMAC_DEBUG sys_printf("TX BD: 0x%08x\n",tx_bd); sys_printf("TX BF: 0x%08x\n",buff);#endif if (!(tx_bd->ctrl_n_len & BD_OWNS)) { /* Free. Update and send the buffer. */ tx_bd->buff = (char *)PHYS(buff); tx_bd->next = PHYS(0); /* PHYS is a placeholder. */ tx_bd->buff_params = 0; /* This clears the buffer offset. */ tx_bd->ctrl_n_len = 0; /* This clears the control bits, holding the last tx status. */ tx_bd->buff_params = tx_bd->ctrl_n_len = pkt_sz & MASK(15, 0); tx_bd->ctrl_n_len |= BD_SOP | BD_EOP | BD_OWNS; bd_dbg(&cpmac_st->tx[0]); FlushDCache(); /* Start the tx process. */ REG32_W(CPMAC_A_TX_DMAHDP(0), PHYS(tx_bd)); } else { /* debug. */ sys_printf("\nNo free TX BD found !"); return SBL_ERESCRUNCH; } /* Tx process has been started. Pend till it's complete. */ for (ii = 0; ii < TX_DELAY/TRX_MIN_DELAY; ii++) { pp = 0; while(pp++ < TRX_MIN_DELAY) { if (!IS_OWNS(tx_bd)) { ret = TRUE; break; } } /* while */ if (ret == TRUE) break; if ((cpmac_st->link_state = lk_st(0)) == LK_DN) return SBL_ELKDN; } /* for */ if (ret == TRUE) { #if CPMAC_DEBUG sys_printf("TX delay: ii: %d, pp: %d", ii, pp); #endif pp = 0; while (pp++ < 50) { if (REG32_R(CPMAC_A_TX_DMAHDP(0), 31, 0) == 0) break; } if (pp == 50) { sys_printf("\nPanic: TX DMA HDP is not cleared still !"); for (;;); } /* _free((void *)KSEG0(buff)); */ return SBL_SUCCESS; } return SBL_ETIMEOUT;}/* * SBL_SUCCESS: * SBL_ELKDN: * SBL_ETIMEOUT: * SBL_EFAILURE: failed to malloc buffers for rx. Caller should exit. */Status cpmac_rx(char **buff, u4 *len){ BuffDesc *rx_bd; /* sys_wb_invalidate_dchache(); */ rx_bd = cpmac_st->rx_next; /* rx_next is always uncached. */ *buff = NULL; /* debug. */ if (rx_bd == NULL) { sys_printf("\nPanic: rx_next not updated !"); for (;;); } if (IS_OWNS(rx_bd)) { /* No pkts pending. */ if ((cpmac_st->link_state = lk_st(0)) == LK_DN) { return SBL_ELKDN; } return SBL_ETIMEOUT; } /* * Pkt received. process to return it. NOTE: return one by one. */ bd_dbg(rx_bd); /* Debug. This should not be there if the buff size is max and hw is * correct. */ if (!IS_SOP(rx_bd) || !IS_EOP(rx_bd)) { sys_printf("\nERR: SOP missing OR rx pkt spans multiple buffs. " "Not supported currently."); return SBL_EFAILURE; } /* not sensing overrun; pass crc (as MBP reg disables); teardown. */ /* fetch buffer pointer and packet length to return to caller. */ *buff = (char *)(KSEG1(rx_bd->buff));#ifdef CPMAC_DEBUG sys_printf("Address in cpmac_rx: 0x%08x\n", *buff);#endif *len = rx_bd->ctrl_n_len & MASK(15, 0); /* Debug. */ if ((rx_bd->ctrl_n_len & MASK(15, 0)) != (rx_bd->buff_params & MASK(15, 0))) { sys_printf("\nPanic: rx sz mismatch"); for (;;); } if (IS_EOQ(rx_bd)) { /* debug. see if the RX DMA HDP is cleared. */ if (REG32_R(CPMAC_A_RX_DMAHDP(0), 31, 0) != 0) { sys_printf("\nPanic: RX DMA HDP is not cleared still !"); for (;;); } /* debug. check for misaligned, which is not supported currently. */ if (rx_bd->next) { sys_printf("\nPanic: Misaligned rx while not supported !"); for (;;); } /* Initialize the RX BDs, malloc buffers, start rx and finally, * set cpmac_st->rx_next to the head. * Pass the head of the BDs to init routine. */ if (SBL_SUCCESS != cpmac_rx_bd_init(cpmac_st->rx)) { return SBL_EFAILURE; } cpmac_st->rx_next = &cpmac_st->rx[0]; } else { (cpmac_st->rx_next)++; /* debug */ if (cpmac_st->rx_next != (BuffDesc *)KSEG1(rx_bd->next)) { sys_printf("\nPanic: rx bd next ptr not updated correctly !"); for (;;); } } return SBL_SUCCESS; }void bd_dbg(BuffDesc *bd){#if CPMAC_DEBUG bd = (BuffDesc *)KSEG1(bd); /* stay explicit for erroneous conditions. */ sys_printf("\nnext:0x%x", (u4)bd->next); sys_printf(" buff:0x%08x", (u4)bd->buff); sys_printf(" Off:%d (BD_OFFSET:%d)", (bd->buff_params & MASK(31, 16)) >> 16, BD_OFFSET); sys_printf(" BLen:%d", bd->buff_params & MASK(15, 0)); sys_printf(" PLen:%d", bd->ctrl_n_len & MASK(15, 0)); sys_printf(" Ctrl:0x%04x\n", (bd->ctrl_n_len & MASK(31, 16)) >> 16);#endif}BOOL lk_st(u4 itf){ /* debug. */ if (itf != 0) { sys_printf("Panic: itf requested is not 0 !"); for (;;); } return TRUE;}void cpmac_stats(void){ sys_printf("\nRxGoodFrames: %d", REG32_R(CPMAC_A_ST_RX_GOODFRAMES, 31, 0)); sys_printf("\t\tRxBroadcast : %d", REG32_R(CPMAC_A_ST_RX_BROADCAST, 31, 0)); sys_printf("\nRxMulticast : %d", REG32_R(CPMAC_A_ST_RX_MULTICAST, 31, 0)); sys_printf("\t\tRxPause : %d", REG32_R(CPMAC_A_ST_RX_PAUSE, 31, 0)); sys_printf("\nRxCRC : %d", REG32_R(CPMAC_A_ST_RX_ERR_CRC, 31, 0)); sys_printf("\t\tRxAlignCodeE: %d", REG32_R(CPMAC_A_ST_RX_ERR_ALIGNC, 31, 0)); sys_printf("\nRxOversized : %d", REG32_R(CPMAC_A_ST_RX_OVERSIZED, 31, 0)); sys_printf("\t\tRxJabber : %d", REG32_R(CPMAC_A_ST_RX_JABBER, 31, 0)); sys_printf("\nRxUndersized: %d", REG32_R(CPMAC_A_ST_RX_UNDERSIZED, 31, 0)); sys_printf("\t\tRxFragments : %d", REG32_R(CPMAC_A_ST_RX_FRAGMENTS, 31, 0)); sys_printf("\nRxFiltered : %d", REG32_R(CPMAC_A_ST_RX_FILTERED, 31, 0)); sys_printf("\t\tRxQOSFilter : %d", REG32_R(CPMAC_A_ST_RX_QOSFILTERED, 31, 0)); sys_printf("\nRxOctets : %d", REG32_R(CPMAC_A_ST_RX_OCTETS, 31, 0)); sys_printf("\t\tTxGoodFrames: %d", REG32_R(CPMAC_A_ST_TX_GOODFRAMES, 31, 0)); sys_printf("\nTxBroadcast : %d", REG32_R(CPMAC_A_ST_TX_BROADCAST, 31, 0)); sys_printf("\t\tTxMulticast : %d", REG32_R(CPMAC_A_ST_TX_MULTICAST, 31, 0)); sys_printf("\nTxPause : %d", REG32_R(CPMAC_A_ST_TX_PAUSE, 31, 0)); sys_printf("\t\tTxDeffered : %d", REG32_R(CPMAC_A_ST_TX_DEFFERED, 31, 0)); sys_printf("\nTxCollision : %d", REG32_R(CPMAC_A_ST_TX_COLLISION, 31, 0)); sys_printf("\t\tTxSingleColl: %d", REG32_R(CPMAC_A_ST_TX_SINGLECOLL, 31, 0)); sys_printf("\nTxMultiColl : %d", REG32_R(CPMAC_A_ST_TX_MULTICOLL, 31, 0)); sys_printf("\t\tTxExcessColl: %d", REG32_R(CPMAC_A_ST_TX_EXCESSCOLL, 31, 0)); sys_printf("\nTxLateColl : %d", REG32_R(CPMAC_A_ST_TX_LATECOLL, 31, 0)); sys_printf("\t\tTxUnderrun : %d", REG32_R(CPMAC_A_ST_TX_UNDERRUN, 31, 0)); sys_printf("\nTxCarSenseEr: %d", REG32_R(CPMAC_A_ST_TX_CARRSENSEER, 31, 0)); sys_printf("\t\tTxOctets : %d", REG32_R(CPMAC_A_ST_TX_OCTETS, 31, 0)); sys_printf("\nTxO_64 : %d", REG32_R(CPMAC_A_ST_TX_OC_64, 31, 0)); sys_printf("\t\tTxO_65_127 : %d", REG32_R(CPMAC_A_ST_TX_OC_65_127, 31, 0)); sys_printf("\nTxO_128_155 : %d", REG32_R(CPMAC_A_ST_TX_OC_128_255, 31, 0)); sys_printf("\t\tTxO_256_511 : %d", REG32_R(CPMAC_A_ST_TX_OC_256_511, 31, 0)); sys_printf("\nTxO_512_1023: %d", REG32_R(CPMAC_A_ST_TX_OC_512_1023, 31, 0)); sys_printf("\t\tTxO_1024_U : %d", REG32_R(CPMAC_A_ST_TX_OC_1024_U, 31, 0)); sys_printf("\nTxNetOctets : %d", REG32_R(CPMAC_A_ST_TX_NETOCTETS, 31, 0)); sys_printf("\t\tRxSOFovrun : %d", REG32_R(CPMAC_A_ST_RX_SOF_OVRUN, 31, 0)); sys_printf("\nRxMOFovrun : %d", REG32_R(CPMAC_A_ST_TX_MOF_OVRUN, 31, 0)); sys_printf("\t\tRxDMAovrun : %d", REG32_R(CPMAC_A_ST_TX_DMA_OVRUN, 31, 0));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -