650 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			650 lines
		
	
	
		
			22 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.
 | |
| 
 | |
| ****************************************************************************/
 | |
| 
 | |
| /* os shim includes */
 | |
| #include "iot_config.h"
 | |
| #include "os_types.h"
 | |
| 
 | |
| /* plc public api includes */
 | |
| #include "plc_fr.h"
 | |
| #include "plc_const.h"
 | |
| #include "iot_bitops.h"
 | |
| #include "iot_mem.h"
 | |
| 
 | |
| /* mac module internal includes */
 | |
| #include "mac.h"
 | |
| #include "mac_dsr.h"
 | |
| #include "mac_isr.h"
 | |
| #include "hw_reg_api.h"
 | |
| #include "mac_sys_reg.h"
 | |
| 
 | |
| /* driver includes */
 | |
| #include "iot_irq.h"
 | |
| 
 | |
| /* WAR */
 | |
| //#include "mac_tx_hw.h"
 | |
| 
 | |
| #include "mac_tx_power.h"
 | |
| #include "hw_phy_api.h"
 | |
| #include "mac_rx_buf_ring.h"
 | |
| #if HW_PLATFORM >= HW_PLATFORM_FPGA
 | |
| #include "mac_raw_reg.h"
 | |
| #include "mac_rawdata_hw.h"
 | |
| #include "plc_protocol.h"
 | |
| #include "phy_bb.h"
 | |
| #endif
 | |
| #include "mac_pdev.h"
 | |
| #include "mac_peer.h"
 | |
| #include "rx_mpdu_end.h"
 | |
| #include "hw_reg_api.h"
 | |
| #include "mac_rx_reg.h"
 | |
| #include "mac_rawdata_hw.h"
 | |
| #include "mac_sched_hw.h"
 | |
| #include "phy_rx_fd_reg.h"
 | |
| #include "phy_txrx_pwr.h"
 | |
| #include "phy_multi_ppm.h"
 | |
| 
 | |
| #include "mac_msdu.h"
 | |
| #include "mac_tx_power.h"
 | |
| #include "mpdu_header.h"
 | |
| #include "hw_war.h"
 | |
| 
 | |
| mac_isr_ctx_t   g_mac_isr_ctx_cpu1 = {0};
 | |
| mac_isr_ctx_t   *p_mac_isr_ctx_cpu1 = &g_mac_isr_ctx_cpu1;
 | |
| 
 | |
| /**
 | |
|  * Save sof rx information for SPG protocol
 | |
|  * to fix the bug responding sack error when rx a
 | |
|  * unicast sof frame.
 | |
|  */
 | |
| sof_rx_info_t g_sof_rx_info = {0};
 | |
| 
 | |
| #if ENA_WAR_244
 | |
| static void mac_rawdata_sack_tx_isr_callback(void)
 | |
| {
 | |
| #if ENA_WAR_244
 | |
|     uint32_t fc[4] = { 0 };
 | |
|     uint32_t tmp;
 | |
|     uint32_t sack_fc_org_status;
 | |
| #if SUPPORT_SOUTHERN_POWER_GRID
 | |
|     spg_frame_control_t *spg_sack_fc;
 | |
| #endif
 | |
| 
 | |
| #if SUPPORT_SMART_GRID
 | |
|     frame_control_t *sg_sack_fc;
 | |
| #endif
 | |
| 
 | |
|     /* clear bb record flag to record next sof */
 | |
|     if (!g_phy_cpu_share_ctxt.need_record_tei) {
 | |
|         g_phy_cpu_share_ctxt.need_record_tei = true;
 | |
|     } else {
 | |
|         /* TODO:we should prevent BB from sending this packet */
 | |
|         g_phy_cpu_share_ctxt.sack_err_occur_cnt++;
 | |
|     }
 | |
| 
 | |
| #if SUPPORT_SOUTHERN_POWER_GRID
 | |
|     if (PLC_PROTO_TYPE_SPG == PHY_PROTO_TYPE_GET()) {
 | |
|         sack_fc_org_status = (iot_raw_read_reg(RAW_REG_TYPE_MAC, \
 | |
|             CFG_TX_RAW_FC_0_ADDR) >> 12) & 0xF;
 | |
|         spg_sack_fc = (spg_frame_control_t *)fc;
 | |
| 
 | |
|         spg_sack_fc->delimiter_type = FC_DELIM_SACK;
 | |
|         spg_sack_fc->access_ind     = 1;
 | |
|         spg_sack_fc->snid           = RGF_MAC_READ_REG(CFG_MYNID_ADDR);
 | |
|         spg_sack_fc->vf.sack.dtei   = g_phy_cpu_share_ctxt.sof_src_tei;
 | |
|         spg_sack_fc->vf.sack.rx_pb  = g_sof_rx_info.att.pb_num;
 | |
|         spg_sack_fc->vf.sack.rx_status = sack_fc_org_status;
 | |
|         spg_sack_fc->vf.sack.version = SPG_STANDARD_VERSION;
 | |
|         /* form sack fc result field */
 | |
|         switch (spg_sack_fc->vf.sack.rx_pb) {
 | |
|             case 1:
 | |
|                 spg_sack_fc->vf.sack.rx_result = \
 | |
|                     (0x1 == (0x1 & spg_sack_fc->vf.sack.rx_status))?0:1;
 | |
|                 break;
 | |
|             case 2:
 | |
|                 spg_sack_fc->vf.sack.rx_result = \
 | |
|                     (0x3 == (0x3 & spg_sack_fc->vf.sack.rx_status))?0:1;
 | |
|                 break;
 | |
|             case 3:
 | |
|                 spg_sack_fc->vf.sack.rx_result = \
 | |
|                     (0x7 == (0x7 & spg_sack_fc->vf.sack.rx_status))?0:1;
 | |
|                 break;
 | |
|             case 4:
 | |
|                 spg_sack_fc->vf.sack.rx_result = \
 | |
|                     (0xF == (0xF & spg_sack_fc->vf.sack.rx_status))?0:1;
 | |
|                 break;
 | |
|             default:
 | |
|                 /* for other pb num, use the hw's result but only 1 bit */
 | |
|                 spg_sack_fc->vf.sack.rx_result &= 0x1;
 | |
|                 break;
 | |
|         }
 | |
| 
 | |
|         iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_0_ADDR, fc[0]);
 | |
|         iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_1_ADDR, fc[1]);
 | |
|         iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_2_ADDR, fc[2]);
 | |
|         iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_3_ADDR, fc[3]);
 | |
|     }
 | |
|     else
 | |
| #endif
 | |
| #if SUPPORT_SMART_GRID
 | |
|     if (PLC_PROTO_TYPE_SG == PHY_PROTO_TYPE_GET()) {
 | |
|         sack_fc_org_status = \
 | |
|             iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_RAW_FC_1_ADDR);
 | |
|         sg_sack_fc = (frame_control_t *)fc;
 | |
| 
 | |
|         sg_sack_fc->delimiter_type = FC_DELIM_SACK;
 | |
|         sg_sack_fc->network_type   = 0;
 | |
|         sg_sack_fc->nid            = RGF_MAC_READ_REG(CFG_MYNID_ADDR);
 | |
|         sg_sack_fc->vf.sack.stei   = RGF_MAC_READ_REG(CFG_MYTEI_ADDR);
 | |
|         sg_sack_fc->vf.sack.dtei   = g_phy_cpu_share_ctxt.sof_src_tei;
 | |
|         sg_sack_fc->vf.sack.rx_pb  = g_sof_rx_info.att.pb_num;
 | |
|         sg_sack_fc->vf.sack.rx_status =
 | |
|             ((sack_fc_org_status & 0x000000F0) >> 4);
 | |
|         sg_sack_fc->vf.sack.snr    = g_sof_rx_info.snr;
 | |
|         sg_sack_fc->vf.sack.version = SG_STANDARD_VERSION;
 | |
|         tmp = RGF_MAC_READ_REG(CFG_TX_CTRL_ADDR);
 | |
|         sg_sack_fc->vf.sack.load = REG_FIELD_GET(CFG_SG_STA_LOADING, tmp);
 | |
|         sg_sack_fc->vf.sack.ext_deli = REG_FIELD_GET(CFG_SG_SACK_VER, tmp);
 | |
|         /* form sack fc result field */
 | |
|         switch (sg_sack_fc->vf.sack.rx_pb) {
 | |
|             case 1:
 | |
|                 sg_sack_fc->vf.sack.rx_result = \
 | |
|                     (0x1 == (0x1 & sg_sack_fc->vf.sack.rx_status))?0:1;
 | |
|                 break;
 | |
|             case 2:
 | |
|                 sg_sack_fc->vf.sack.rx_result = \
 | |
|                     (0x3 == (0x3 & sg_sack_fc->vf.sack.rx_status))?0:1;
 | |
|                 break;
 | |
|             case 3:
 | |
|                 sg_sack_fc->vf.sack.rx_result = \
 | |
|                     (0x7 == (0x7 & sg_sack_fc->vf.sack.rx_status))?0:1;
 | |
|                 break;
 | |
|             case 4:
 | |
|                 sg_sack_fc->vf.sack.rx_result = \
 | |
|                     (0xF == (0xF & sg_sack_fc->vf.sack.rx_status))?0:1;
 | |
|                 break;
 | |
|             default:
 | |
|                 /* for other pb num, use the hw's result but only 1 bit */
 | |
|                 sg_sack_fc->vf.sack.rx_result &= 0x1;
 | |
|                 break;
 | |
|         }
 | |
| 
 | |
|         iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_0_ADDR, fc[0]);
 | |
|         iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_1_ADDR, fc[1]);
 | |
|         iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_2_ADDR, fc[2]);
 | |
|         iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_3_ADDR, fc[3]);
 | |
|     }
 | |
|     else
 | |
| #endif
 | |
|     {
 | |
|         //TODO: assert or don't do anything. don't del the case
 | |
|         (void)sack_fc_org_status;
 | |
|     }
 | |
| 
 | |
|     /* fc valid */
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_SW_FC_VALID_ADDR, 0x1);
 | |
|     g_phy_cpu_share_ctxt.tx_unicast_sack_ts = mac_sched_get_ntb(NULL);
 | |
|     /* clear interrupt status */
 | |
|     tmp = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_CLR_ADDR);
 | |
|     tmp |= MAC_TX_SACK_INT_STATUS;
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC,CFG_RAW_INT_CLR_ADDR, tmp);
 | |
| #endif
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if (ENA_WAR_NNCCO_FEAT)
 | |
| 
 | |
| void IRAM_ATTR mac_nncco_war_fill_fcinfo(void *fc)
 | |
| {
 | |
| #if HW_PLATFORM != HW_PLATFORM_SIMU
 | |
|     uint32_t proto = PHY_PROTO_TYPE_GET();
 | |
|     IOT_ASSERT(fc);
 | |
| #if SUPPORT_SMART_GRID
 | |
|         if (PLC_PROTO_TYPE_SG == proto) {
 | |
|             frame_control_t *cur_fc = (frame_control_t *)fc;
 | |
|             if (FC_DELIM_NNCCO == cur_fc->delimiter_type) {
 | |
|                 uint32_t recv_nid;
 | |
|                 uint64_t org_start_ntb;
 | |
|                 uint64_t curr_start_ntb;
 | |
|                 uint16_t curr_duration;
 | |
|                 uint16_t sbandoffset;
 | |
|                 uint64_t start_ntb_h24 = cur_fc->vf.nn_cco_sw.start_ntb_h24;
 | |
|                 org_start_ntb = (uint64_t)((start_ntb_h24 & 0xFFFFFF) << 32 | \
 | |
|                             cur_fc->vf.nn_cco_sw.start_ntb_l32);
 | |
|                 curr_start_ntb = mac_sched_get_ntb64(NULL);
 | |
|                 if (curr_start_ntb >= org_start_ntb) {
 | |
|                     sbandoffset = 0;
 | |
|                     if ((curr_start_ntb - org_start_ntb) >=
 | |
|                         MAC_MS_TO_NTB((uint64_t)cur_fc->vf.nn_cco_sw.duration)) {
 | |
|                         curr_duration = 0;
 | |
|                     } else {
 | |
|                         curr_duration = cur_fc->vf.nn_cco_sw.duration -
 | |
|                             (uint16_t)MAC_NTB_TO_MS(curr_start_ntb - org_start_ntb);
 | |
|                     }
 | |
|                 } else {
 | |
|                     sbandoffset =
 | |
|                         (uint16_t)MAC_NTB_TO_MS(org_start_ntb - curr_start_ntb);
 | |
|                     curr_duration = cur_fc->vf.nn_cco_sw.duration;
 | |
|                 }
 | |
| 
 | |
|                 recv_nid = cur_fc->vf.nn_cco_sw.receive_nid;
 | |
|                 cur_fc->vf.nn_cco.receive_nid = recv_nid;
 | |
|                 cur_fc->vf.nn_cco.duration    = curr_duration;
 | |
|                 cur_fc->vf.nn_cco.sbandoffset = sbandoffset;
 | |
|                 cur_fc->vf.nn_cco.self_rf_channel =
 | |
|                     g_phy_cpu_share_ctxt.rf_channel;
 | |
|                 cur_fc->vf.nn_cco.self_rf_option =
 | |
|                     g_phy_cpu_share_ctxt.rf_option;
 | |
|                 cur_fc->vf.nn_cco.resv1 = 0;
 | |
|                 cur_fc->vf.nn_cco.version = SG_STANDARD_VERSION;
 | |
|             }
 | |
|         }
 | |
| #endif
 | |
| 
 | |
| #if SUPPORT_SOUTHERN_POWER_GRID
 | |
|         if (PLC_PROTO_TYPE_SPG  == proto) {
 | |
|             spg_frame_control_t *cur_fc = (spg_frame_control_t *)fc;
 | |
|             if (FC_DELIM_NNCCO == cur_fc->delimiter_type) {
 | |
|                 uint64_t org_start_ntb;
 | |
|                 uint64_t last_start_ntb;
 | |
|                 uint64_t curr_start_ntb;
 | |
|                 uint16_t curr_duration;
 | |
|                 uint32_t bwth_end_flag;
 | |
|                 uint32_t bwth_end_offset;
 | |
|                 uint32_t bwth_start_offset;
 | |
| 
 | |
|                 uint64_t start_ntb_h24 = cur_fc->vf.nn_cco_sw.start_ntb_h24;
 | |
|                 org_start_ntb = (uint64_t)((start_ntb_h24 & 0xFFFFFF) << 32 | \
 | |
|                             cur_fc->vf.nn_cco_sw.start_ntb_l32);
 | |
|                 uint64_t last_offseth = cur_fc->vf.nn_cco_sw.last_offseth;
 | |
|                 last_start_ntb = org_start_ntb - \
 | |
|                     (uint64_t)((last_offseth & 0xff) << 8 | \
 | |
|                     cur_fc->vf.nn_cco_sw.last_offsetl);
 | |
| 
 | |
|                 IOT_ASSERT(last_start_ntb <= org_start_ntb);
 | |
| 
 | |
|                 curr_start_ntb = mac_sched_get_ntb64(NULL);
 | |
|                 /* last pb is not over */
 | |
|                 if (curr_start_ntb <= last_start_ntb) {
 | |
|                     bwth_end_flag = 0;
 | |
| 
 | |
|                     if ((last_start_ntb - curr_start_ntb) >=
 | |
|                         MAC_MS_TO_NTB((uint64_t)cur_fc->vf.nn_cco_sw.duration)) {
 | |
|                         curr_duration = 0;
 | |
|                     } else {
 | |
|                         curr_duration = cur_fc->vf.nn_cco_sw.duration -
 | |
|                             (uint16_t)MAC_NTB_TO_MS(last_start_ntb - curr_start_ntb);
 | |
|                     }
 | |
|                     bwth_end_offset = MAC_NTB_TO_MS(last_start_ntb - \
 | |
|                         curr_start_ntb) / 4;
 | |
|                     bwth_start_offset = MAC_NTB_TO_MS(org_start_ntb -\
 | |
|                         curr_start_ntb) / 4;
 | |
| 
 | |
|                 }
 | |
|                 /* last pb is over, but next pb is not start */
 | |
|                 else if (curr_start_ntb <= org_start_ntb) {
 | |
|                     curr_duration = 0;
 | |
|                     bwth_end_flag = 1;
 | |
|                     curr_duration = cur_fc->vf.nn_cco_sw.duration;
 | |
|                     bwth_end_offset = MAC_NTB_TO_MS(curr_start_ntb - \
 | |
|                         last_start_ntb) / 4;
 | |
|                     bwth_start_offset = MAC_NTB_TO_MS(org_start_ntb -\
 | |
|                         curr_start_ntb) / 4;
 | |
|                 }
 | |
|                 /* next pb is starting */
 | |
|                 else {
 | |
|                     bwth_end_flag = 1;
 | |
|                     bwth_start_offset = 0;
 | |
|                     bwth_end_offset = MAC_NTB_TO_MS(curr_start_ntb - \
 | |
|                         last_start_ntb) / 4;
 | |
|                     curr_duration = cur_fc->vf.nn_cco_sw.duration;
 | |
|                 }
 | |
| 
 | |
|                 cur_fc->vf.nn_cco.neighbor_network = \
 | |
|                     cur_fc->vf.nn_cco_sw.neighbor_network;
 | |
|                 cur_fc->vf.nn_cco.resv0 = 0;
 | |
|                 cur_fc->vf.nn_cco.conti_time = curr_duration / 40;
 | |
|                 cur_fc->vf.nn_cco.resv1 = 0;
 | |
|                 cur_fc->vf.nn_cco.bwth_end_flag = bwth_end_flag;
 | |
|                 cur_fc->vf.nn_cco.resv4 = 0;
 | |
|                 cur_fc->vf.nn_cco.bwth_end_shift = bwth_end_offset;
 | |
|                 cur_fc->vf.nn_cco.bwth_start_shift = bwth_start_offset;
 | |
|                 cur_fc->vf.nn_cco.resv = 0;
 | |
|                 /* spg fc version default value = 1 */
 | |
|                 cur_fc->vf.nn_cco.version = SPG_STANDARD_VERSION;
 | |
|                 cur_fc->vf.nn_cco.self_rf_channel =
 | |
|                     g_phy_cpu_share_ctxt.rf_channel;
 | |
|                 cur_fc->vf.nn_cco.self_rf_option =
 | |
|                     g_phy_cpu_share_ctxt.rf_option;
 | |
|             }
 | |
|         }
 | |
| #endif
 | |
| #else
 | |
|     (void)fc;
 | |
| #endif
 | |
|     return;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if (ENA_WAR_NNCCO_FEAT || ENA_WAR_SPG_TX_OK || ENA_MAC_TX_START_INT)
 | |
| static void mac_rawdata_tx_start_isr_callback(void)
 | |
| {
 | |
|     uint32_t fc[4];
 | |
|     /* tx fc need update */
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_NEED_UPD_ADDR, 0x1);
 | |
|     /* get original tx fc */
 | |
|     fc[0] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_RAW_FC_0_ADDR);
 | |
|     fc[1] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_RAW_FC_1_ADDR);
 | |
|     fc[2] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_RAW_FC_2_ADDR);
 | |
|     fc[3] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_RAW_FC_3_ADDR);
 | |
| 
 | |
|     uint32_t proto = PHY_PROTO_TYPE_GET();
 | |
|     uint8_t delimiter = \
 | |
|         (uint8_t)mac_get_delimi_from_fc(proto, fc);
 | |
| 
 | |
|     /* modify original tx fc */
 | |
|     if (FC_DELIM_BEACON == delimiter) {
 | |
|         //considering 40us delay between tx start and first sample on power line
 | |
|         mac_set_bcn_st(fc, (mac_sched_get_ntb(NULL) + \
 | |
|             MAC_SW_TX_BTS_DLY_NTB));
 | |
|     }
 | |
| 
 | |
|     /* for sack ext type, sync frame */
 | |
|     if (FC_DELIM_SACK == delimiter) {
 | |
|         mac_set_sync_st(fc, (mac_sched_get_ntb(NULL) + \
 | |
|             MAC_SW_TX_BTS_DLY_NTB));
 | |
|     }
 | |
| 
 | |
| #if ENA_WAR_NNCCO_FEAT
 | |
|     /* modify original tx fc */
 | |
|     mac_nncco_war_fill_fcinfo(fc);
 | |
| #endif
 | |
| 
 | |
| #if ENA_SYNC_DIFF_CCO_PPM
 | |
|     int32_t ppm_step = mac_get_clear_dbg_pkt_ppm_step(fc);
 | |
|     if (ppm_step) {
 | |
|         mac_modify_dbg_pkt_tx_ppm(ppm_step);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_0_ADDR, fc[0]);
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_1_ADDR, fc[1]);
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_2_ADDR, fc[2]);
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_3_ADDR, fc[3]);
 | |
| 
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA0_ADDR, fc[0]);
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA1_ADDR, fc[1]);
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA2_ADDR, fc[2]);
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA3_ADDR, fc[3]);
 | |
| 
 | |
|     /* set sw fc valid */
 | |
|     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_SW_FC_VALID_ADDR, 0x1);
 | |
|     /* clear interrupt status */
 | |
|     mac_rawdata_tx_start_isr_clr();
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if ENA_WAR_244
 | |
| #define RING_BASE_ADDR      (CFG_BUFFER_RING0_0_ADDR)
 | |
| #define RING_BASE_OFFSET    (CFG_BUFFER_RING1_0_ADDR - CFG_BUFFER_RING0_0_ADDR)
 | |
| #define RING_X_1_OFFSET     (CFG_BUFFER_RING0_1_ADDR - CFG_BUFFER_RING0_0_ADDR)
 | |
| #define RING_X_2_OFFSET     (CFG_BUFFER_RING0_2_ADDR - CFG_BUFFER_RING0_0_ADDR)
 | |
| #define RING_X_3_OFFSET     (CFG_BUFFER_RING0_3_ADDR - CFG_BUFFER_RING0_0_ADDR)
 | |
| 
 | |
| static uint32_t mac_rx_hw_isr_callback_cpu1(void)
 | |
| {
 | |
| #if HW_PLATFORM != HW_PLATFORM_SIMU
 | |
|     uint32_t rx_int_status = 0;
 | |
|     int32_t wid;
 | |
|     iot_pkt_t *p_buf;
 | |
|     uint8_t *tmp;
 | |
|     int8_t snr;
 | |
|     rx_mpdu_start *mpdu_st;
 | |
|     rx_mpdu_end *mpdu_ed;
 | |
|     uint8_t rx_pb_num;
 | |
|     rx_attention *att;
 | |
| #if SUPPORT_SOUTHERN_POWER_GRID
 | |
|     spg_frame_control_t *spg_fc;
 | |
| #endif
 | |
| #if SUPPORT_SMART_GRID
 | |
|     frame_control_t *sg_fc;
 | |
| #endif
 | |
|     uint8_t **buf_list;
 | |
|     uint32_t ring_sz;
 | |
|     uint32_t reg_value, reg_addr_base;
 | |
| 
 | |
|     rx_int_status = rx_ring_get_mpdu_int_status();
 | |
| 
 | |
|     /* call different ring's callback handler */
 | |
|     /* TODO: use pri order */
 | |
|     for (uint32_t i = 0; i < MAX_PLC_RX_RING_NUM; i++)
 | |
|     {
 | |
|         if ((0x1 << i) & rx_int_status) {
 | |
|             reg_value = RGF_RX_READ_REG(RING_BASE_ADDR
 | |
|                 + (i * RING_BASE_OFFSET) + RING_X_2_OFFSET);
 | |
|             if (0 == REG_FIELD_GET(CFG_RING0_EN, reg_value)) {
 | |
|                 continue;
 | |
|             }
 | |
|             reg_addr_base = RING_BASE_ADDR + (i * RING_BASE_OFFSET);
 | |
|             buf_list = (uint8_t **)RGF_RX_READ_REG(reg_addr_base);
 | |
|             wid = rx_ring_get_wr_idx_macro(i);
 | |
|             reg_value = RGF_RX_READ_REG(reg_addr_base + RING_X_1_OFFSET);
 | |
|             ring_sz = REG_FIELD_GET(CFG_RING0_BUF_NUM, reg_value);
 | |
| 
 | |
|             if (wid == 0) {
 | |
|                 /* handle wrap around */
 | |
|                 wid = ring_sz - 1;
 | |
|             }
 | |
|             else {
 | |
|                 /* get the last wr id */
 | |
|                 wid--;
 | |
|             }
 | |
|             if (!(wid < ring_sz)) {
 | |
|                 // get assert file and line
 | |
|                 assert_failed((unsigned char *)__FILE__, __LINE__);
 | |
|             }
 | |
|             p_buf = (iot_pkt_t*)(buf_list[wid] - sizeof(iot_pkt_t));
 | |
|             tmp = iot_pkt_data(p_buf);
 | |
|             mpdu_ed = (rx_mpdu_end *)(tmp + MPDU_END_OFFSET);
 | |
|             rx_pb_num = mpdu_ed->rx_buf_num;
 | |
|             if (rx_pb_num == 1) {
 | |
|                 mpdu_st = (rx_mpdu_start *)(tmp + MPDU_START_OFFSET);
 | |
|                 snr = mpdu_st->phy.avg_snr;
 | |
|             }
 | |
|             else if (rx_pb_num > 1) {
 | |
|                 /* multi-pb case */
 | |
|                 wid -= (rx_pb_num - 1);
 | |
|                 if (wid >= 0) {
 | |
|                 }
 | |
|                 else {
 | |
|                     /* wid < 0*/
 | |
|                     wid = wid + ring_sz;
 | |
|                 }
 | |
|                 if (!(wid < ring_sz)) {
 | |
|                     // get assert file and line
 | |
|                     assert_failed((unsigned char *)__FILE__, __LINE__);
 | |
|                 }
 | |
| 
 | |
|                 p_buf = (iot_pkt_t*)(buf_list[wid] - sizeof(iot_pkt_t));
 | |
|                 tmp = iot_pkt_data(p_buf);
 | |
|                 mpdu_st = (rx_mpdu_start *)(tmp + MPDU_START_OFFSET);
 | |
|                 snr = mpdu_st->phy.avg_snr;
 | |
|             }
 | |
|             else {
 | |
|                 /* abnormal case */
 | |
|                 break;
 | |
|             }
 | |
|             att = (rx_attention *)(tmp + RX_ATTENTION_OFFSET);
 | |
|             /* WAR:for bugid 244, fix sack result field always 0xf bug */
 | |
| #if SUPPORT_SOUTHERN_POWER_GRID
 | |
|             if (PLC_PROTO_TYPE_SPG == mpdu_st->rx_proto) {
 | |
|                 spg_fc = &mpdu_st->fc.spg_fc;
 | |
|                 g_sof_rx_info.fc[0] = *(uint32_t *)spg_fc;
 | |
|                 g_sof_rx_info.fc[1] = *((uint32_t *)spg_fc + 1);
 | |
|                 g_sof_rx_info.fc[2] = *((uint32_t *)spg_fc + 2);
 | |
|                 g_sof_rx_info.fc[3] = *((uint32_t *)spg_fc + 3);
 | |
|             }
 | |
|             else
 | |
| #endif
 | |
| #if SUPPORT_SMART_GRID
 | |
|             if (PLC_PROTO_TYPE_SG == mpdu_st->rx_proto) {
 | |
|                 sg_fc = &mpdu_st->fc.sg_fc;
 | |
|                 g_sof_rx_info.fc[0] = *(uint32_t *)sg_fc;
 | |
|                 g_sof_rx_info.fc[1] = *((uint32_t *)sg_fc + 1);
 | |
|                 g_sof_rx_info.fc[2] = *((uint32_t *)sg_fc + 2);
 | |
|                 g_sof_rx_info.fc[3] = *((uint32_t *)sg_fc + 3);
 | |
|             }
 | |
|             else
 | |
| #endif
 | |
|             {
 | |
|                 //TODO: assert or don't do anything. don't del the case
 | |
|             }
 | |
| 
 | |
|             g_sof_rx_info.att = *att;
 | |
|             g_sof_rx_info.snr = snr;
 | |
| 
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     return 0;
 | |
| #else
 | |
|     return 0;
 | |
| #endif
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if ENA_WAR_CTL
 | |
| static uint32_t mac_isr_handler_cpu1(uint32_t vector, iot_addrword_t data)
 | |
| {
 | |
|     (void)vector;
 | |
|     (void)data;
 | |
| 
 | |
| #if ENA_WAR_244
 | |
|     if (g_phy_cpu_share_ctxt.need_record_sof)
 | |
|     {
 | |
|         g_phy_cpu_share_ctxt.need_record_sof = 0;
 | |
|         mac_rx_hw_isr_callback_cpu1();
 | |
|     }
 | |
| #endif
 | |
|     return 0;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if ENA_WAR_CTL
 | |
| static uint32_t mac_war_isr_handler_cpu1(uint32_t vector, iot_addrword_t data)
 | |
| {
 | |
|     uint32_t sack_int_status;
 | |
|     (void)vector;
 | |
|     (void)data;
 | |
| 
 | |
|     /* read pending sack tx interrupt status and do handler */
 | |
|     sack_int_status = RGF_RAW_READ_REG(CFG_RAW_INT_STATUS_ADDR);
 | |
| #if ENA_WAR_244
 | |
|     if (MAC_TX_SACK_INT_STATUS & sack_int_status) {
 | |
|         mac_rawdata_sack_tx_isr_callback();
 | |
|     }
 | |
| #endif
 | |
| 
 | |
| #if (ENA_WAR_NNCCO_FEAT || ENA_WAR_SPG_TX_OK || ENA_MAC_TX_START_INT)
 | |
|     if (MAC_TX_START_INT_STATUS & sack_int_status) {
 | |
|         mac_rawdata_tx_start_isr_callback();
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static void mac_isr_reset_cpu1(void)
 | |
| {
 | |
| #if ENA_WAR_CTL
 | |
|     /* CPU1 don't call disable interrupt & clean up pending interrupt */
 | |
|     return;
 | |
| #else
 | |
|     return;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void mac_isr_enable_cpu1(uint8_t id)
 | |
| {
 | |
|     uint32_t int_mask;
 | |
| 
 | |
|     if (id <= MAC_ISR_MAX_ID) {
 | |
|         int_mask = 1 << (CFG_INT_ENABLE_MASK_OFFSET + id);
 | |
|         if (!(p_mac_isr_ctx_cpu1->isr_mask & int_mask)) {
 | |
|             p_mac_isr_ctx_cpu1->isr_mask |= int_mask;
 | |
|             RGF_MAC_WRITE_REG(CFG_INT_ENA_MASK_ADDR, \
 | |
|                 p_mac_isr_ctx_cpu1->isr_mask);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void mac_isr_disable_cpu1(uint8_t id)
 | |
| {
 | |
|     uint32_t int_mask;
 | |
| 
 | |
|     if (id <= MAC_ISR_MAX_ID) {
 | |
|         int_mask = 1 << (CFG_INT_ENABLE_MASK_OFFSET + id);
 | |
|         if (p_mac_isr_ctx_cpu1->isr_mask & int_mask) {
 | |
|             p_mac_isr_ctx_cpu1->isr_mask &= ~int_mask;
 | |
|             RGF_MAC_WRITE_REG(CFG_INT_ENA_MASK_ADDR, p_mac_isr_ctx_cpu1->isr_mask);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void mac_isr_start_cpu1(void)
 | |
| {
 | |
| #if ENA_WAR_CTL
 | |
|     iot_interrupt_unmask(p_mac_isr_ctx_cpu1->isr_0_h);
 | |
|     iot_interrupt_unmask(p_mac_isr_ctx_cpu1->isr_3_h);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void mac_isr_stop_cpu1(void)
 | |
| {
 | |
| #if ENA_WAR_CTL
 | |
|     iot_interrupt_mask(p_mac_isr_ctx_cpu1->isr_0_h);
 | |
|     iot_interrupt_mask(p_mac_isr_ctx_cpu1->isr_3_h);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void mac_isr_init_cpu1(void)
 | |
| {
 | |
|     iot_memset(p_mac_isr_ctx_cpu1, 0, sizeof(*p_mac_isr_ctx_cpu1));
 | |
| 
 | |
|     p_mac_isr_ctx_cpu1->dsr_callback = NULL;
 | |
| 
 | |
|     mac_isr_reset_cpu1();
 | |
| 
 | |
| #if ENA_WAR_CTL
 | |
|     /* allocate soc irq resource */
 | |
|     p_mac_isr_ctx_cpu1->isr_0_h = iot_interrupt_create(HAL_VECTOR_MAC_0,
 | |
|         HAL_INTR_PRI_7, (iot_addrword_t)NULL, mac_isr_handler_cpu1);
 | |
| #endif
 | |
| 
 | |
| #if ENA_WAR_CTL
 | |
|     p_mac_isr_ctx_cpu1->isr_3_h = iot_interrupt_create(HAL_VECTOR_MAC_3,
 | |
|         HAL_INTR_PRI_7, (iot_addrword_t)NULL, mac_war_isr_handler_cpu1);
 | |
| #endif
 | |
| 
 | |
|     /* set interrupt to cpu1 */
 | |
|     iot_interrupt_set_cpu(p_mac_isr_ctx_cpu1->isr_0_h, HAL_INTR_CPU_1);
 | |
|     iot_interrupt_set_cpu(p_mac_isr_ctx_cpu1->isr_3_h, HAL_INTR_CPU_1);
 | |
| 
 | |
|     /* attach soc irq resource */
 | |
|     iot_interrupt_attach(p_mac_isr_ctx_cpu1->isr_0_h);
 | |
|     iot_interrupt_attach(p_mac_isr_ctx_cpu1->isr_3_h);
 | |
| }
 |