Files
kunlun/plc/halmac/hw2/rx/mac_rx_buf_ring.c
2024-09-28 14:24:04 +08:00

1003 lines
30 KiB
C
Executable File

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "mac_rx_buf_ring.h"
#include "iot_errno.h"
#include "iot_utils.h"
#include "iot_io.h"
#include "plc_utils.h"
#include "plc_mac_cfg.h"
#include "mac.h"
#include "plc_fr.h"
#include "mac_rx_reg.h"
#include "hw_reg_api.h"
#include "rx_mpdu_start.h"
#include "rx_mpdu_end.h"
#include "rx_pb_start.h"
#include "rx_pb_end.h"
#include "plc_const.h"
#include "mac_sys_reg.h"
#include "hw_tonemap.h"
#include "phy_bb.h"
#include "mac_pdev.h" /* for WAR */
#include "mac_tmr_reg.h"
#include "phy_bb.h"
#include "phy_txrx_pwr.h"
#if DEBUG_INVAILD_ADDR
#include "iot_system_api.h"
#endif
#include "mac_rx_hw.h"
#if HW_PLATFORM >= HW_PLATFORM_FPGA
void mac_set_trans_done_selection(uint32_t cfg)
{
/* 1- select transdone after fifo empty.
* 0- select trans done after write fifo
*/
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_AHB_DBG_CTRL_ADDR);
REG_FIELD_SET(CFG_AHB_TRANS_DONE_SEL0, tmp, cfg);
RGF_MAC_WRITE_REG(CFG_AHB_DBG_CTRL_ADDR, tmp);
}
void mac_rx_abort_act_hang(uint32_t enable)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_TIMEOUT_ACT_ADDR);
REG_FIELD_SET(CFG_MAC_RX_ABORT_ACT, tmp, enable);
RGF_RX_WRITE_REG(CFG_RX_TIMEOUT_ACT_ADDR, tmp);
}
void mac_rx_timeout_act_hang(uint32_t enable)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_TIMEOUT_ACT_ADDR);
REG_FIELD_SET(CFG_RX_TIMEOUT_ACT, tmp, enable);
RGF_RX_WRITE_REG(CFG_RX_TIMEOUT_ACT_ADDR, tmp);
}
void mac_rx_set_filter(uint32_t filter_type, uint8_t en)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_FILTER_0_ADDR);
en = !!en;
switch (filter_type)
{
case CFG_BEACON_PHASE_FILTER_DIS_MASK:
{
REG_FIELD_SET(CFG_BEACON_PHASE_FILTER_DIS, tmp, en);
break;
}
case CFG_MPDU_DTEI_FILTER_DIS_MASK:
{
REG_FIELD_SET(CFG_MPDU_DTEI_FILTER_DIS, tmp, en);
break;
}
case CFG_NID_FILTER_DIS_MASK:
{
REG_FIELD_SET(CFG_NID_FILTER_DIS, tmp, en);
break;
}
case CFG_FC_CRCERR_FILTER_DIS_MASK:
{
REG_FIELD_SET(CFG_FC_CRCERR_FILTER_DIS, tmp, en);
break;
}
default:
break;
}
RGF_RX_WRITE_REG(CFG_RX_FILTER_0_ADDR, tmp);
return;
}
void mac_rx_set_sg_dt_filter(uint8_t dt0, uint8_t dt1, uint8_t dt2, uint8_t dt3)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_FILTER_1_ADDR);
REG_FIELD_SET(CFG_SG_DT_FILTER_BLACKLIST_0, tmp, dt0);
REG_FIELD_SET(CFG_SG_DT_FILTER_BLACKLIST_1, tmp, dt1);
REG_FIELD_SET(CFG_SG_DT_FILTER_BLACKLIST_2, tmp, dt2);
REG_FIELD_SET(CFG_SG_DT_FILTER_BLACKLIST_3, tmp, dt3);
RGF_RX_WRITE_REG(CFG_RX_FILTER_1_ADDR, tmp);
return;
}
uint32_t mac_rx_set_fcs_by_phy(uint32_t enable)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_CTRL_ADDR);
REG_FIELD_SET(CFG_RX_FC_CRC_FROM_PHY, tmp, enable);
RGF_RX_WRITE_REG(CFG_RX_CTRL_ADDR, tmp);
return 0;
}
uint32_t mac_rx_set_pbnum_from_phy(uint32_t pn_from_phy)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_CTRL_ADDR);
REG_FIELD_SET(CFG_RX_PBNUM_FROM_PHY, tmp, pn_from_phy);
RGF_RX_WRITE_REG(CFG_RX_CTRL_ADDR, tmp);
return 0;
}
uint32_t mac_rx_get_bcn_swcrc_cfg(void)
{
uint32_t tmp;
uint32_t is_sw_crc;
tmp = RGF_RX_READ_REG(CFG_RX_CTRL_ADDR);
is_sw_crc = REG_FIELD_GET(CFG_RX_BEACON_PLD_CRC_BY_SW, tmp);
return is_sw_crc;
}
void mac_rx_set_bcn_swcrc_cfg(uint32_t is_by_sw)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_CTRL_ADDR);
REG_FIELD_SET(CFG_RX_BEACON_PLD_CRC_BY_SW, tmp, is_by_sw);
RGF_RX_WRITE_REG(CFG_RX_CTRL_ADDR, tmp);
return;
}
uint32_t mac_rx_get_pb_hdr_to_buf_cfg(void)
{
uint32_t tmp;
uint32_t is_to_buf;
tmp = RGF_RX_READ_REG(CFG_RX_CTRL_ADDR);
is_to_buf = REG_FIELD_GET(CFG_PB_HDR_TO_BUFFER, tmp);
return is_to_buf;
}
void mac_rx_set_pb_hdr_to_buf_cfg(uint32_t is_to_buf)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_CTRL_ADDR);
REG_FIELD_SET(CFG_PB_HDR_TO_BUFFER, tmp, is_to_buf);
RGF_RX_WRITE_REG(CFG_RX_CTRL_ADDR, tmp);
return;
}
uint32_t rx_ring_get_overflow_status()
{
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_RX_INT_CTRL_ADDR);
return REG_FIELD_GET(RO_RX_DESC_OVERFLOW_INT_STATUS, tmp);
}
void rx_ring_clr_overflow_int(uint32_t rid)
{
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_RX_INT_CLR_ADDR);
switch (rid) {
case 0:
REG_FIELD_SET(CFG_RX_DESC_OVERFLOW_INT_CLR_0, tmp, 1);
break;
case 1:
REG_FIELD_SET(CFG_RX_DESC_OVERFLOW_INT_CLR_1, tmp, 1);
break;
case 2:
REG_FIELD_SET(CFG_RX_DESC_OVERFLOW_INT_CLR_2, tmp, 1);
break;
case 3:
REG_FIELD_SET(CFG_RX_DESC_OVERFLOW_INT_CLR_3, tmp, 1);
break;
case 4:
REG_FIELD_SET(CFG_RX_DESC_OVERFLOW_INT_CLR_4, tmp, 1);
break;
default:
IOT_ASSERT(0);
}
RGF_MAC_WRITE_REG(CFG_RX_INT_CLR_ADDR, tmp);
}
uint32_t IRAM_ATTR rx_ring_get_mpdu_int_status()
{
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_RX_INT_CTRL_ADDR);
return REG_FIELD_GET(RO_RX_MPDU_INT_STATUS, tmp);
}
void rx_ring_clr_mpdu_int(uint32_t rid)
{
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_RX_INT_CLR_ADDR);
switch (rid){
case 0:
REG_FIELD_SET(CFG_RX_MPDU_INT_CLR_0, tmp, 1);
break;
case 1:
REG_FIELD_SET(CFG_RX_MPDU_INT_CLR_1, tmp, 1);
break;
case 2:
REG_FIELD_SET(CFG_RX_MPDU_INT_CLR_2, tmp, 1);
break;
case 3:
REG_FIELD_SET(CFG_RX_MPDU_INT_CLR_3, tmp, 1);
break;
case 4:
REG_FIELD_SET(CFG_RX_MPDU_INT_CLR_4, tmp, 1);
break;
default:
IOT_ASSERT(0);
}
RGF_MAC_WRITE_REG(CFG_RX_INT_CLR_ADDR, tmp);
}
/* get ring rd idx */
uint32_t rx_ring_get_rd_idx(rx_buf_ring_t *rx_ring)
{
IOT_ASSERT(rx_ring);
switch (rx_ring->ring_id) {
case 0:
return RX_RING_GET_RD_IDX(0);
case 1:
return RX_RING_GET_RD_IDX(1);
case 2:
return RX_RING_GET_RD_IDX(2);
case 3:
return RX_RING_GET_RD_IDX(3);
case 4:
return RX_RING_GET_RD_IDX(4);
default:
IOT_ASSERT(0);
}
return 0;
}
/* set ring rd idx */
void rx_ring_set_rd_idx(rx_buf_ring_t *rx_ring, uint32_t value)
{
IOT_ASSERT(rx_ring);
switch (rx_ring->ring_id) {
case 0:
RX_RING_SET_RD_IDX(0, value);
break;
case 1:
RX_RING_SET_RD_IDX(1, value);
break;
case 2:
RX_RING_SET_RD_IDX(2, value);
break;
case 3:
RX_RING_SET_RD_IDX(3, value);
break;
case 4:
RX_RING_SET_RD_IDX(4, value);
break;
default:
IOT_ASSERT(0);
}
return;
}
/* get ring rd idx */
uint32_t rx_ring_get_wr_idx(rx_buf_ring_t *rx_ring)
{
IOT_ASSERT(rx_ring);
switch (rx_ring->ring_id) {
case 0:
return RX_RING_GET_MPDU_WR_IDX(0, 0);
case 1:
return RX_RING_GET_MPDU_WR_IDX(1, 0);
case 2:
return RX_RING_GET_MPDU_WR_IDX(2, 0);
case 3:
return RX_RING_GET_MPDU_WR_IDX(3, 1);
case 4:
return RX_RING_GET_MPDU_WR_IDX(4, 1);
default:
IOT_ASSERT(0);
}
return 0;
}
/* enable rx ring */
void mac_rx_ring_enable(rx_buf_ring_t *rx_ring, uint32_t enable)
{
uint32_t tmp;
IOT_ASSERT(rx_ring);
switch (rx_ring->ring_id) {
case 0:
tmp = RGF_RX_READ_REG(CFG_BUFFER_RING0_2_ADDR);
REG_FIELD_SET(CFG_RING0_EN, tmp, enable);
RGF_RX_WRITE_REG(CFG_BUFFER_RING0_2_ADDR, tmp);
break;
case 1:
tmp = RGF_RX_READ_REG(CFG_BUFFER_RING1_2_ADDR);
REG_FIELD_SET(CFG_RING1_EN, tmp, enable);
RGF_RX_WRITE_REG(CFG_BUFFER_RING1_2_ADDR, tmp);
break;
case 2:
tmp = RGF_RX_READ_REG(CFG_BUFFER_RING2_2_ADDR);
REG_FIELD_SET(CFG_RING2_EN, tmp, enable);
RGF_RX_WRITE_REG(CFG_BUFFER_RING2_2_ADDR, tmp);
break;
case 3:
tmp = RGF_RX_READ_REG(CFG_BUFFER_RING3_2_ADDR);
REG_FIELD_SET(CFG_RING3_EN, tmp, enable);
RGF_RX_WRITE_REG(CFG_BUFFER_RING3_2_ADDR, tmp);
break;
case 4:
tmp = RGF_RX_READ_REG(CFG_BUFFER_RING4_2_ADDR);
REG_FIELD_SET(CFG_RING4_EN, tmp, enable);
RGF_RX_WRITE_REG(CFG_BUFFER_RING4_2_ADDR, tmp);
break;
default:
IOT_ASSERT(0);
}
return;
}
uint8_t rx_ring_set_filter_sel(rx_buf_ring_t *rx_ring)
{
IOT_ASSERT(rx_ring);
switch (rx_ring->ring_id) {
case 0:
RX_RING_SET_FILTER_SEL(0, rx_ring->bufsz_filter_sel);
break;
case 1:
RX_RING_SET_FILTER_SEL(1, rx_ring->bufsz_filter_sel);
break;
case 2:
RX_RING_SET_FILTER_SEL(2, rx_ring->bufsz_filter_sel);
break;
case 3:
RX_RING_SET_FILTER_SEL(3, rx_ring->bufsz_filter_sel);
break;
case 4:
RX_RING_SET_FILTER_SEL(4, rx_ring->bufsz_filter_sel);
break;
default:
IOT_ASSERT(0);
}
return 0;
}
uint8_t rx_ring_set_filter(rx_buf_ring_t *rx_ring)
{
IOT_ASSERT(rx_ring);
switch(rx_ring->ring_id){
case 0:
RX_RING_SET_FILTER(0,rx_ring->filter);
break;
case 1:
RX_RING_SET_FILTER(1,rx_ring->filter);
break;
case 2:
RX_RING_SET_FILTER(2,rx_ring->filter);
break;
case 3:
RX_RING_SET_FILTER(3,rx_ring->filter);
break;
case 4:
RX_RING_SET_FILTER(4,rx_ring->filter);
break;
default:
IOT_ASSERT(0);
}
return 0;
}
/* fill in the ring cfg */
void rx_ring_fill_hw_cfg(rx_buf_ring_t *rx_ring)
{
IOT_ASSERT(rx_ring);
uint32_t tmp;
uint32_t offset = (CFG_BUFFER_RING1_0_ADDR - \
CFG_BUFFER_RING0_0_ADDR) * rx_ring->ring_id;
uint32_t ring_cfg_buf = CFG_BUFFER_RING0_1_ADDR + offset;
uint32_t ring_cfg_rx = CFG_BUFFER_RING0_2_ADDR + offset;
uint32_t ring_cfg_desc_pld = CFG_BUFFER_RING0_3_ADDR + offset;
/* set ring buf array ptr */
RGF_RX_WRITE_REG(CFG_BUFFER_RING0_0_ADDR + offset, \
(uint32_t)rx_ring->buf_list);
/* set ring sz and buf len */
tmp = RGF_RX_READ_REG(ring_cfg_buf);
REG_FIELD_SET(CFG_RING0_BUF_SIZE, tmp, \
iot_ceil(rx_ring->buf_sz, 4));
REG_FIELD_SET(CFG_RING0_BUF_NUM, tmp, rx_ring->ring_sz);
/* re-enable ring, disable clr wr idx */
REG_FIELD_SET(CFG_RING0_BUF_REENA_CLR_EN, tmp, 0);
RGF_RX_WRITE_REG(ring_cfg_buf, tmp);
rx_ring_set_filter_sel(rx_ring);
rx_ring_set_filter(rx_ring);
/* set rd idx = 0 as default */
tmp = RGF_RX_READ_REG(ring_cfg_rx);
REG_FIELD_SET(CFG_RING0_RD_IDX, tmp, 0);
RGF_RX_WRITE_REG(ring_cfg_rx, tmp);
/* set desc and payload offset */
tmp = RGF_RX_READ_REG(ring_cfg_desc_pld);
REG_FIELD_SET(CFG_RING0_DESC_EN, tmp, \
rx_ring->config[CONFIG_RX_DESC].enable);
REG_FIELD_SET(CFG_RING0_PAYLOAD_EN, tmp, \
rx_ring->config[CONFIG_PAYLOAD].enable);
REG_FIELD_SET(CFG_RING0_DESC_OFFSET, tmp, \
iot_ceil(rx_ring->config[CONFIG_RX_DESC].offset, 4));
REG_FIELD_SET(CFG_RING0_PAYLOAD_OFFSET, tmp, \
iot_ceil(rx_ring->config[CONFIG_PAYLOAD].offset, 4));
RGF_RX_WRITE_REG(ring_cfg_desc_pld, tmp);
}
void mac_rx_pb_timeout(uint32_t time_40ns)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_TIMEOUT_1_ADDR);
REG_FIELD_SET(CFG_RX_PB_TIMEOUT, tmp, time_40ns);
RGF_RX_WRITE_REG(CFG_RX_TIMEOUT_1_ADDR, tmp);
}
void mac_set_debug_reg(uint32_t value)
{
RGF_MAC_WRITE_REG(CFG_MAC_DBG_CTRL1_ADDR, value);
}
uint32_t mac_rx_get_debug_reg()
{
return RGF_MAC_READ_REG(CFG_MAC_DBG_BUS_ADDR);
}
/* TODO: remove when muti-band test*/
void mac_rx_set_delim(uint32_t proto_band_id, uint32_t rate_id)
{
IOT_ASSERT(rate_id == 0);
(void)rate_id;
uint32_t fc_num;
uint32_t preamble_value;
if (IOT_SUPPORT_TONE_MULTI_BAND021 == proto_band_id) {
uint32_t single_proto_band;
uint32_t addr_interv = CFG_SG_DELI_R0B1_ADDR - CFG_SG_DELI_R0B0_ADDR;
for (uint32_t hw_band_idx = 0; hw_band_idx < MAX_HW_BAND;
hw_band_idx++) {
single_proto_band = phy_hw_band_to_proto_band(hw_band_idx);
fc_num = phy_get_proto_band_fc_num_from_band_table(single_proto_band);
if (!fc_num) {
IOT_ASSERT(0);
}
preamble_value = (uint32_t)(DELIMITER_LENGTH_SG(fc_num));
/* SR QR XR */
RGF_TMR_WRITE_REG(CFG_SG_DELI_R0B0_ADDR + hw_band_idx * addr_interv,
preamble_value);
RGF_TMR_WRITE_REG(CFG_SG_DELI_R1B0_ADDR + hw_band_idx * addr_interv,
4 * preamble_value);
RGF_TMR_WRITE_REG(CFG_SG_DELI_R2B0_ADDR + hw_band_idx * addr_interv,
preamble_value);
}
} else {
fc_num = phy_get_proto_band_fc_num_from_band_table(proto_band_id);
if (!fc_num) {
IOT_ASSERT(0);
}
preamble_value = (uint32_t)(DELIMITER_LENGTH_SG(fc_num));
RGF_TMR_WRITE_REG(CFG_SG_DELI_R0B0_ADDR, preamble_value);
RGF_TMR_WRITE_REG(CFG_SG_DELI_R0B1_ADDR, preamble_value);
RGF_TMR_WRITE_REG(CFG_SG_DELI_R0B2_ADDR, preamble_value);
RGF_TMR_WRITE_REG(CFG_SG_DELI_R1B0_ADDR, 4 * preamble_value);
RGF_TMR_WRITE_REG(CFG_SG_DELI_R1B1_ADDR, 4 * preamble_value);
RGF_TMR_WRITE_REG(CFG_SG_DELI_R1B2_ADDR, 4 * preamble_value);
RGF_TMR_WRITE_REG(CFG_SG_DELI_R2B0_ADDR, preamble_value);
RGF_TMR_WRITE_REG(CFG_SG_DELI_R2B1_ADDR, preamble_value);
RGF_TMR_WRITE_REG(CFG_SG_DELI_R2B2_ADDR, preamble_value);
}
}
uint32_t mac_rx_get_delim(uint8_t phy_rate_id, uint32_t hw_band_id)
{
IOT_ASSERT(phy_rate_id == 0);
uint32_t addr_interv = CFG_SG_DELI_R1B0_ADDR - CFG_SG_DELI_R0B0_ADDR;
uint32_t tmp;
switch (hw_band_id) {
case HW_FULL_BAND :{
tmp = RGF_TMR_READ_REG(CFG_SG_DELI_R0B0_ADDR + \
phy_rate_id * addr_interv);
break;
}
case HW_LOW_BAND :{
tmp = RGF_TMR_READ_REG(CFG_SG_DELI_R0B1_ADDR + \
phy_rate_id * addr_interv);
break;
}
case HW_HIGH_BAND :{
tmp = RGF_TMR_READ_REG(CFG_SG_DELI_R0B2_ADDR + \
phy_rate_id * addr_interv);
break;
}
default :
IOT_ASSERT(0);
return 0;
}
return tmp & 0xFFFFFF;
}
void mac_rx_gp_proto_band_set(void)
{
uint32_t tmp = 0;
uint32_t symbnum_ppb = 0;
uint32_t fl_ppb = 0;
/* tmi0 configration */
/* band0 */
symbnum_ppb = phy_get_symppb_from_table(0, 0, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_STD_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI0_BAND0_ADDR);
REG_FIELD_SET(CFG_TMI0_BAND0_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI0_BAND0_ADDR,tmp);
/* band1 */
symbnum_ppb = phy_get_symppb_from_table(0, 0, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_STD_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI0_BAND1_ADDR);
REG_FIELD_SET(CFG_TMI0_BAND1_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI0_BAND1_ADDR,tmp);
/* band2 */
symbnum_ppb = phy_get_symppb_from_table(0, 0, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_STD_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI0_BAND2_ADDR);
REG_FIELD_SET(CFG_TMI0_BAND2_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI0_BAND2_ADDR,tmp);
/* band3 */
symbnum_ppb = phy_get_symppb_from_table(0, 0, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_STD_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI0_BAND3_ADDR);
REG_FIELD_SET(CFG_TMI0_BAND3_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI0_BAND3_ADDR,tmp);
/* tmi1 configration */
/* band0 */
symbnum_ppb = phy_get_symppb_from_table(0, 1, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_HS_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI1_BAND0_ADDR);
REG_FIELD_SET(CFG_TMI1_BAND0_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI1_BAND0_ADDR,tmp);
/* band1 */
symbnum_ppb = phy_get_symppb_from_table(0, 1, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_HS_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI1_BAND1_ADDR);
REG_FIELD_SET(CFG_TMI1_BAND1_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI1_BAND1_ADDR,tmp);
/* band2 */
symbnum_ppb = phy_get_symppb_from_table(0, 1, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_HS_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI1_BAND2_ADDR);
REG_FIELD_SET(CFG_TMI1_BAND2_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI1_BAND2_ADDR,tmp);
/* band3 */
symbnum_ppb = phy_get_symppb_from_table(0, 1, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_HS_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI1_BAND3_ADDR);
REG_FIELD_SET(CFG_TMI1_BAND3_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI1_BAND3_ADDR,tmp);
/* tmi2 configration */
/* band0 */
symbnum_ppb = phy_get_symppb_from_table(0, 2, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_MINI_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI2_BAND0_ADDR);
REG_FIELD_SET(CFG_TMI2_BAND0_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI2_BAND0_ADDR,tmp);
/* band1 */
symbnum_ppb = phy_get_symppb_from_table(0, 2, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_MINI_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI2_BAND1_ADDR);
REG_FIELD_SET(CFG_TMI2_BAND1_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI2_BAND1_ADDR,tmp);
/* band2 */
symbnum_ppb = phy_get_symppb_from_table(0, 2, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_MINI_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI2_BAND2_ADDR);
REG_FIELD_SET(CFG_TMI2_BAND2_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI2_BAND2_ADDR,tmp);
/* band3 */
symbnum_ppb = phy_get_symppb_from_table(0, 2, 0);
fl_ppb = (uint32_t)(FRAME_LENGTH_PER_PB_GP(symbnum_ppb, GI_MINI_ROBO)/1.28);
tmp = RGF_RX_READ_REG(CFG_TMI2_BAND3_ADDR);
REG_FIELD_SET(CFG_TMI2_BAND3_PBFL,tmp,fl_ppb);
RGF_RX_WRITE_REG(CFG_TMI2_BAND3_ADDR,tmp);
}
void mac_rx_set_phase_protection(uint32_t phy_force, uint32_t mac_force)
{
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_RX_PHASE_PROTECT_ADDR);
REG_FIELD_SET(CFG_RX_PHASE_FOR_PHY_PROTECT_EN, tmp, !!phy_force);
REG_FIELD_SET(CFG_RX_PHASE_FOR_MAC_PROTECT_EN, tmp, !!mac_force);
RGF_MAC_WRITE_REG(CFG_RX_PHASE_PROTECT_ADDR, tmp);
}
void mac_rx_set_last_pb_eco(uint8_t enable)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_ECO_ADDR);
REG_FIELD_SET(CFG_LAST_PB_ECO_SEL, tmp, !!enable);
RGF_RX_WRITE_REG(CFG_RX_ECO_ADDR, tmp);
return;
}
void mac_rx_set_pb_hdr_crc_opt(uint8_t value)
{
uint32_t tmp;
tmp = RGF_RX_READ_REG(CFG_RX_PB_OPT_ADDR);
REG_FIELD_SET(CFG_PB_HDR_CRC_OPT, tmp, !!value);
RGF_RX_WRITE_REG(CFG_RX_PB_OPT_ADDR, tmp);
return;
}
rx_buf_ring_t *mac_rx_get_ring(void *pdev, uint32_t index)
{
if (index >= MAX_PLC_RX_RING_NUM) {
IOT_ASSERT(0);
return NULL;
}
mac_pdev_t *pdev_ptr = (mac_pdev_t *)pdev;
IOT_ASSERT(pdev_ptr);
return &pdev_ptr->ring_hdl.ring[index];
}
uint32_t mac_rx_get_ring_buf_desc_size()
{
return sizeof(uint8_t *);
}
void mac_rx_set_ring_buf_list(uint8_t **buf_list, uint32_t ring_sz,
uint32_t index, iot_pkt_t *iot_pkt)
{
IOT_ASSERT(buf_list && (index < ring_sz));
buf_list[index] = iot_pkt_data(iot_pkt);
}
iot_pkt_t *mac_rx_get_ring_buf_list(rx_buf_ring_t *rx_ring)
{
IOT_ASSERT(rx_ring->buf_list[rx_ring->read_idx]);
/* the data just start after the iot_pkt_t structure */
return (iot_pkt_t*)(rx_ring->buf_list[rx_ring->read_idx] \
- sizeof(iot_pkt_t));
/* TODO: need set the actual len here?
* pb sz maybe smaller than
* the buf sz, current len should
* be the buf sz that when init
*/
}
#endif /* HW_PLATFORM >= HW_PLATFORM_FPGA */
void mac_rx_all_ring_enable(void *pdev)
{
rx_buf_ring_t *ring;
mac_pdev_t *pdev_ptr = (mac_pdev_t *)pdev;
IOT_ASSERT(pdev_ptr);
for (uint32_t i = 0; i < MAX_PLC_RX_RING_NUM; i++){
/* get ring pointer */
ring = mac_rx_get_ring(pdev, i);
/* enable ring */
if(ring->cfg_enabled == 1) {
mac_rx_ring_enable(ring, 1);
}
}
return;
}
void mac_rx_all_ring_disable(void *pdev)
{
rx_buf_ring_t *ring;
mac_pdev_t *pdev_ptr = (mac_pdev_t *)pdev;
IOT_ASSERT(pdev_ptr);
for (uint32_t i = 0; i < MAX_PLC_RX_RING_NUM; i++){
/* get ring pointer */
ring = mac_rx_get_ring(pdev, i);
if(ring->cfg_enabled == 1){
mac_rx_ring_enable(ring, 0);
if (pdev_ptr->rx) {
mac_rx_hw_mpdu_internal(pdev_ptr, i, MAX_RX_QUOTA_MS);
}
}
}
return;
}
uint32_t mac_rx_ring_ctxt_init(mac_rx_ring_ctxt_t *ring_ctxt)
{
uint32_t ret;
/* init only one rx ring temply */
ring_config config_sof[] =
{
{ CONFIG_RX_DESC, RX_ATTENTION_OFFSET, 1 },
{ CONFIG_RX_MPDU_START, 0, 0 },
{ CONFIG_RX_MPDU_END, 0, 0 },
{ CONFIG_RX_PB_START, 0, 0 },
{ CONFIG_RX_PB_END, 0, 0 },
{ CONFIG_FC, 0, 0 },
{ CONFIG_PAYLOAD, PB_PAYLOAD_OFFSET, 1 }
};
ring_ctxt->mpdu_pb_cb = NULL;
ret = rx_buf_ring_init(&ring_ctxt->ring[PLC_RING_0], \
PLC_RING_0, \
(uint32_t)PLC_SHORT_RX_BUF_COUNT, PLC_SHORT_BUF_SIZE, NULL, \
config_sof,0,0);
if (ERR_OK != ret) {
/* return error */
goto out;
}
/*init ring1 bufsize = 136*/
ret = rx_buf_ring_init(&ring_ctxt->ring[PLC_RING_1], \
PLC_RING_1, \
(uint32_t)PLC_SMALL_RX_BUF_COUNT, PLC_SMALL_BUF_SIZE, NULL, \
config_sof, 0, 0);
out:
return ret;
}
/* init and put on the buf_list */
uint32_t rx_buf_ring_init(rx_buf_ring_t *rx_ring, uint32_t ring_id, \
uint32_t ring_sz, uint32_t buf_sz, rx_low_watermark_callback cb, \
ring_config *cfg,uint8_t bufsz_filter_sel,uint8_t filter)
{
iot_pkt_t *iot_pkt;
uint8_t *data_ptr;
if(!rx_ring->buf_list){
rx_ring->buf_list =
(uint8_t**)os_mem_malloc(PLC_MAC_RX_RING_MID,
ring_sz * mac_rx_get_ring_buf_desc_size());
if (!rx_ring->buf_list) {
return ERR_NOMEM;
}
for (uint32_t i = 0; i < ring_sz; i++) {
iot_pkt = iot_pkt_alloc(buf_sz, PLC_MAC_RX_HW_MID);
if (!iot_pkt) {
/* alloc failed */
IOT_ASSERT(0);
return ERR_NOMEM;
}
else {
/* alloc successful */
/* set and check data field len */
data_ptr = iot_pkt_put(iot_pkt, buf_sz);
IOT_ASSERT(data_ptr);
mac_rx_set_ring_buf_list(rx_ring->buf_list, ring_sz,
i, iot_pkt);
}
}
}
rx_ring->read_idx = 0;
rx_ring->write_idx = 0;
rx_ring->ring_id = ring_id;
rx_ring->water_mark_buf_num = ring_sz << 2; // 1/4 of ring_sz
rx_ring->overflow = 0;
rx_ring->bufsz_filter_sel = bufsz_filter_sel;
rx_ring->filter = filter;
rx_ring->cb = cb;
rx_ring->buf_sz = buf_sz;
rx_ring->ring_sz = ring_sz;
rx_ring->config[CONFIG_RX_DESC] = cfg[CONFIG_RX_DESC];
rx_ring->config[CONFIG_PAYLOAD] = cfg[CONFIG_PAYLOAD];
rx_ring->cur_mpdu = NULL;
rx_ring->cfg_enabled = 1;
rx_ring_fill_hw_cfg(rx_ring);
return ERR_OK;
}
uint32_t peek_buf_for_desc(void *rx_buf)
{
uint32_t ret = ERR_OK;
rx_buf_hdr_t *rx_desc = (rx_buf_hdr_t *)rx_buf;
IOT_ASSERT(rx_desc);
if (rx_desc->pb_ed.rx_pb_done && rx_desc->pb_st.first_pb) {
/* for first pb */
if (rx_desc->att.rx_mpdu_done == 0) {
/* if hw not done with the whole mpdu */
ret = ERR_AGAIN;
}
}
return ret;
}
/* FW call this to reap data down and repurnish the buf */
uint32_t pop_buf_from_ring(rx_buf_ring_t *rx_ring, uint32_t num,
iot_pkt_t **buf_array)
{
uint32_t aval_num = 0;
uint32_t read_num = 0;
iot_pkt_t *p_buf = NULL;
uint8_t *rx_buf_addr;
if (!rx_ring)
{
return read_num;
}
/* read rd and wr idx */
rx_ring->write_idx = rx_ring_get_wr_idx(rx_ring);
rx_ring->read_idx = rx_ring_get_rd_idx(rx_ring);
(aval_num = (rx_ring->write_idx - rx_ring->read_idx)) < 0 ? \
aval_num += (rx_ring->ring_sz) : aval_num;
read_num = min(aval_num, num);
for (uint32_t i = 0; i < read_num; i++)
{
/* get the iot_pkt_t ptr */
p_buf = mac_rx_get_ring_buf_list(rx_ring);
#if MAC_RX_RING_WAIT_MPDU_DONE == 1
/* sometimes, the hw is not done with the whole mpdu but
* the rx pb done == 1, we need to wait the whole mpdu done
* before pop the buf
*/
if (peek_buf_for_desc(rx_ring->buf_list[rx_ring->read_idx]))
{
break;
}
#endif
/* reap the buf */
buf_array[i] = p_buf;
/* repurnish another buf */
p_buf = iot_pkt_alloc(rx_ring->buf_sz, PLC_MAC_RX_HW_MID);
if (!p_buf) {
//IOT_ASSERT(0);
return i;
}
rx_buf_addr = iot_pkt_put(p_buf, rx_ring->buf_sz);
IOT_ASSERT(rx_buf_addr);
/* clear the mpdu_done bit, sometimes HW move the
* wr idx without write to the rx buf when rx abort
* happen
*/
((rx_attention*)(iot_pkt_data(p_buf)))->rx_mpdu_done = 0;
mac_rx_set_ring_buf_list(rx_ring->buf_list, rx_ring->ring_sz,
rx_ring->read_idx, p_buf);
if (++rx_ring->read_idx == rx_ring->ring_sz) {
rx_ring->read_idx = 0;
}
rx_ring_set_rd_idx(rx_ring, rx_ring->read_idx);
}
return read_num;
}
void rx_buf_ring_set_callback(mac_rx_ring_ctxt_t *ring_ctxt, \
mac_recv_mpdu_pb_func_t cb)
{
ring_ctxt->mpdu_pb_cb = cb;
}
uint32_t rx_ring_set_watermark(rx_buf_ring_t *rx_ring, uint32_t num)
{
if (!rx_ring)
{
return ERR_INVAL;
}
if (num >= rx_ring->ring_sz)
{
return ERR_INVAL;
}
rx_ring->water_mark_buf_num = num;
return ERR_OK;
}
uint32_t rx_ring_get_watermark(rx_buf_ring_t *rx_ring)
{
IOT_ASSERT(rx_ring);
return rx_ring->water_mark_buf_num;
}
bool_t is_rx_ring_under_watermark(rx_buf_ring_t *rx_ring)
{
uint32_t wr_idx = rx_ring->write_idx;
uint32_t rd_idx = rx_ring->read_idx;
bool_t flag = false;
if ((wr_idx == 0) && (rd_idx == 0)) return false;
flag = (rd_idx + rx_ring->ring_sz - wr_idx) % (rx_ring->ring_sz) == 1;
return flag;
}
bool_t rx_ring_space_avaliable(rx_buf_ring_t *rx_ring, uint32_t num)
{
uint32_t wr_idx = rx_ring->write_idx + num;
uint32_t rd_idx = rx_ring->read_idx;
bool_t flag = false;
flag = (rd_idx + rx_ring->ring_sz - wr_idx) % (rx_ring->ring_sz) != 1;
if (flag == 0)
{
iot_printf("no space avaliable in rx ring, wr_idx:%d, rd_idx:%d\n", wr_idx, rd_idx);
}
return flag;
}
#if DEBUG_INVAILD_ADDR
/*debug rx buf is validation*/
uint32_t IRAM_ATTR mac_judge_ring_buf_validation()
{
mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID);
rx_buf_ring_t *ring;
uint32_t rx_int_status;
rx_int_status = rx_ring_get_mpdu_int_status();
for (uint32_t i = 0; i < MAX_PLC_RX_RING_NUM; i++)
{
if ((0x1 << i) & rx_int_status){
if (pdev->rx) {
ring = &pdev->ring_hdl.ring[i];
iot_pkt_t* p_buf = \
(iot_pkt_t*)(ring->buf_list[ring->read_idx] \
- sizeof(iot_pkt_t));
if (!iot_data_addr_legal(
(uint32_t) iot_pkt_block_ptr(p_buf,
IOT_PKT_BLOCK_HEAD))
|| !iot_data_addr_legal(
(uint32_t) iot_pkt_block_ptr(p_buf,
IOT_PKT_BLOCK_DATA))
|| !iot_data_addr_legal(
(uint32_t) iot_pkt_block_ptr(p_buf,
IOT_PKT_BLOCK_TAIL))
|| !iot_data_addr_legal(
(uint32_t) iot_pkt_block_ptr(p_buf,
IOT_PKT_BLOCK_END)))
{
/* record invaild addr and ring buf len */
uint32_t *p = (uint32_t *) (((uint8_t *)p_buf)
- ring->buf_sz - 16);
pdev->buf_addr = p;
pdev->buf_len = ring->buf_sz;
/* pull msg to dsr */
uint32_t value = 0;
value |= 1 << MAC_DSR_INVAILD_ADDR_ID;
if (value) {
/* deliver the DSR events to mac task context */
os_set_task_event_with_v_from_isr(p_mac_glb->task_h,\
value);
}
return ERR_INVAL;
}
}
}
}
return ERR_OK;
}
void mac_handle_invaild_addr()
{
iot_printf("%s\n", __FUNCTION__);
mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID);
IOT_ASSERT(pdev->buf_len && pdev->buf_addr);
mem_dump((uint32_t *)pdev->buf_addr, (pdev->buf_len >> 1) + 4);
IOT_ASSERT_DUMP(0, pdev->buf_addr, (pdev->buf_len >> 1) + 4);
}
#endif /* DEBUG_INVAILD_ADDR */