650 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			650 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /****************************************************************************
 | ||
|  | 
 | ||
|  | 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); | ||
|  | } |