395 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			395 lines
		
	
	
		
			11 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. | ||
|  | 
 | ||
|  | ****************************************************************************/ | ||
|  | #include "mac_rawdata_hw.h"
 | ||
|  | #include "hw_reg_api.h"
 | ||
|  | #include "phy_reg.h"
 | ||
|  | #include "iot_errno.h"
 | ||
|  | #include "mac_tx_hw.h"
 | ||
|  | #include "iot_io.h"
 | ||
|  | 
 | ||
|  | #if HW_PLATFORM >= HW_PLATFORM_FPGA
 | ||
|  | #include "mac_raw_reg.h"
 | ||
|  | #include "mac_sched_hw.h"
 | ||
|  | #include "phy_bb.h"
 | ||
|  | #include "plc_mpdu_header.h"
 | ||
|  | #include "mac_sys_reg.h"
 | ||
|  | #include "hw_reg_api.h"
 | ||
|  | #include "mac_desc_engine.h"
 | ||
|  | #include "plc_const.h"
 | ||
|  | 
 | ||
|  | void iot_raw_write_reg(uint32_t type, uint32_t addr, uint32_t val) | ||
|  | { | ||
|  | 
 | ||
|  |     if(type == RAW_REG_TYPE_MAC){ | ||
|  |         RGF_RAW_WRITE_REG(addr,val); | ||
|  |     }else if(type == RAW_REG_TYPE_PHY){ | ||
|  |         PHY_WRITE_REG(addr, val); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | uint32_t IRAM_ATTR iot_raw_read_reg(uint32_t type,  uint32_t addr) | ||
|  | { | ||
|  |     uint32_t val = 0; | ||
|  |     if(type == RAW_REG_TYPE_MAC){ | ||
|  |         val = RGF_RAW_READ_REG(addr); | ||
|  |     }else if(type == RAW_REG_TYPE_PHY){ | ||
|  |         val = PHY_READ_REG(addr); | ||
|  |     } | ||
|  | 
 | ||
|  |     return val; | ||
|  | } | ||
|  | 
 | ||
|  | void mac_rawdata_mode_enable(uint32_t enable) | ||
|  | { | ||
|  |     /* set mac raw mode */ | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_RAW_DATA_MODE_ADDR, enable); | ||
|  | } | ||
|  | 
 | ||
|  | void phy_rawdata_mode_enable(uint32_t enable) | ||
|  | { | ||
|  |     /* set bb raw mode */ | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_PHY,CFG_BB_RAW_DATA_MODE_CTRL_ADDR, \ | ||
|  |         enable); | ||
|  | } | ||
|  | 
 | ||
|  | void mac_rawdata_proto_set(uint32_t src_prot) | ||
|  | { | ||
|  |     /* set mac raw mode proto */ | ||
|  |     src_prot &= CFG_SW_TX_PROTO_MASK; | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_SW_TX_PROTO_ADDR, src_prot); | ||
|  | } | ||
|  | 
 | ||
|  | uint32_t iot_rawdata_hw_enable(uint8_t rawdata_enable) | ||
|  | { | ||
|  |     /* set mac raw mode */ | ||
|  |     mac_rawdata_mode_enable(rawdata_enable); | ||
|  | 
 | ||
|  |     /* set bb raw mode */ | ||
|  |     phy_rawdata_mode_enable(rawdata_enable); | ||
|  | 
 | ||
|  |     return ERR_OK; | ||
|  | } | ||
|  | 
 | ||
|  | uint32_t iot_rawdata_get_tx_fc_bytes(fc_trans_msg *rawfc) | ||
|  | { | ||
|  |     uint32_t idx=0; | ||
|  | #ifdef ENABLE_PRINT
 | ||
|  |     iot_printf("get_mac_tx_fc\n"); | ||
|  | #endif
 | ||
|  |     rawfc->org_fc[idx++]= iot_raw_read_reg(RAW_REG_TYPE_MAC,CFG_TX_RAW_FC_0_ADDR); | ||
|  |     rawfc->org_fc[idx++]= iot_raw_read_reg(RAW_REG_TYPE_MAC,CFG_TX_RAW_FC_1_ADDR); | ||
|  |     rawfc->org_fc[idx++]= iot_raw_read_reg(RAW_REG_TYPE_MAC,CFG_TX_RAW_FC_2_ADDR); | ||
|  |     rawfc->org_fc[idx++]= iot_raw_read_reg(RAW_REG_TYPE_MAC,CFG_TX_RAW_FC_3_ADDR); | ||
|  | 
 | ||
|  |     return ERR_OK; | ||
|  | } | ||
|  | 
 | ||
|  | uint32_t iot_rawdata_translate_tx_fc(fc_trans_msg *rawfc, \ | ||
|  |     uint32_t src_prot, uint32_t trans_prot) | ||
|  | { | ||
|  |     /*
 | ||
|  |      * consider two cases. 1. src_prot and trans_prot are same, but minor | ||
|  |      * version different.  2. src_prot and trans_prot are different. | ||
|  |      * 2nd case should not to hit, focus on case 1 currently. | ||
|  |     */ | ||
|  |     frame_control_t* src_sgfc = NULL; | ||
|  |     frame_control_t* trans_sgfc = NULL; | ||
|  | 
 | ||
|  |     spg_frame_control_t* src_spgfc = NULL; | ||
|  |     spg_frame_control_t* trans_spgfc = NULL; | ||
|  | 
 | ||
|  |     if(src_prot == trans_prot){ | ||
|  |         if(src_prot == PLC_PROTO_TYPE_SG){ | ||
|  |             src_sgfc = (frame_control_t*)rawfc->org_fc; | ||
|  |             trans_sgfc = (frame_control_t*)rawfc->trans_fc; | ||
|  | 
 | ||
|  |             /* real work should be bits adjustment in same prot family
 | ||
|  |              * currently just copy | ||
|  |             */ | ||
|  |            os_mem_cpy(trans_sgfc,src_sgfc,(RAW_FC_LEN_DW*sizeof(uint32_t)) ); | ||
|  | 
 | ||
|  |         }else if (src_prot == PLC_PROTO_TYPE_SPG){ | ||
|  |             src_spgfc = (spg_frame_control_t*)rawfc->org_fc; | ||
|  |             trans_spgfc = (spg_frame_control_t*)rawfc->trans_fc; | ||
|  | 
 | ||
|  |             /* real work should be bits adjustment in same prot family
 | ||
|  |              * currently just copy | ||
|  |             */ | ||
|  |             os_mem_cpy(trans_spgfc, src_spgfc,(RAW_FC_LEN_DW*sizeof(uint32_t))); | ||
|  |         }else{ | ||
|  |             IOT_ASSERT(0); | ||
|  |         } | ||
|  | 
 | ||
|  |     }else{ | ||
|  |         IOT_ASSERT(0); | ||
|  |     } | ||
|  | 
 | ||
|  |     return ERR_OK; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | uint32_t iot_rawdata_set_translate_tx_fc(fc_trans_msg *rawfc) | ||
|  | { | ||
|  |     uint32_t idx = 0; | ||
|  | #ifdef ENABLE_PRINT
 | ||
|  |     iot_printf("set_mac_tx_fc\n"); | ||
|  | #endif
 | ||
|  |     /* caculate crc data here */ | ||
|  | //       iot_rawdata_set_crc(rawfc);
 | ||
|  | 
 | ||
|  |     /* Set Data */ | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC,CFG_TX_SW_FC_0_ADDR,rawfc->trans_fc[idx++]); | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC,CFG_TX_SW_FC_1_ADDR,rawfc->trans_fc[idx++]); | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC,CFG_TX_SW_FC_2_ADDR,rawfc->trans_fc[idx++]); | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC,CFG_TX_SW_FC_3_ADDR,rawfc->trans_fc[idx++]); | ||
|  | 
 | ||
|  |     //iot_rawdata_modify_tx_fc(rawfc);
 | ||
|  | 
 | ||
|  |     /* Valid data */ | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC,CFG_SW_FC_VALID_ADDR, 1); | ||
|  | 
 | ||
|  | #ifdef RAWDATA_TIME_PROFILE_ENABLE
 | ||
|  |     /* log interrupt trigger time */ | ||
|  |     iot_rawdata_mark_timestamp(&rawfc->profile.rawdata_set_translate_fc_ticks); | ||
|  | #endif
 | ||
|  | 
 | ||
|  |     return ERR_OK; | ||
|  | } | ||
|  | 
 | ||
|  | void  mac_rawdata_sack_tx_isr_disable() | ||
|  | { | ||
|  |     uint32_t reg_intr_en = 0; | ||
|  | 
 | ||
|  |     /* handle mac intr */ | ||
|  |     reg_intr_en = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_ENA_ADDR); | ||
|  |     reg_intr_en &= (~MAC_TX_SACK_FC_MASK); | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_ENA_ADDR, reg_intr_en); | ||
|  | 
 | ||
|  |     return; | ||
|  | } | ||
|  | 
 | ||
|  | void mac_rawdata_sack_tx_isr_enable() | ||
|  | { | ||
|  |     uint32_t reg_intr_en = 0; | ||
|  |     uint32_t reg_int = 0; | ||
|  | 
 | ||
|  |     reg_int = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_PRI3_MASK_ADDR); | ||
|  |     reg_int |= MAC_TX_SACK_FC_MASK; | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_PRI3_MASK_ADDR, reg_int); | ||
|  | 
 | ||
|  |     reg_intr_en = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_ENA_ADDR); | ||
|  |     reg_intr_en |= MAC_TX_SACK_FC_MASK; | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_ENA_ADDR, reg_intr_en); | ||
|  | 
 | ||
|  |     return; | ||
|  | } | ||
|  | 
 | ||
|  | void mac_rawdata_sack_isr_cfg(uint32_t src_prot) | ||
|  | { | ||
|  |     /* disable sack tx rawdata isr */ | ||
|  |     mac_rawdata_sack_tx_isr_disable(); | ||
|  |     /* set rawdata mode */ | ||
|  |     mac_rawdata_proto_set(src_prot); | ||
|  |     /* enable sack tx rawdata isr */ | ||
|  |     mac_rawdata_sack_tx_isr_enable(); | ||
|  | } | ||
|  | 
 | ||
|  | void mac_rawdata_tx_start_isr_disable() | ||
|  | { | ||
|  |     uint32_t reg_intr_en = 0; | ||
|  | 
 | ||
|  |     /* handle mac intr */ | ||
|  |     reg_intr_en = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_ENA_ADDR); | ||
|  |     reg_intr_en &= (~MAC_TX_START_MASK); | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_ENA_ADDR, reg_intr_en); | ||
|  | 
 | ||
|  |     return; | ||
|  | } | ||
|  | 
 | ||
|  | void mac_rawdata_tx_start_isr_enable() | ||
|  | { | ||
|  |     uint32_t reg_intr_en = 0; | ||
|  |     uint32_t reg_int = 0; | ||
|  | 
 | ||
|  |     reg_int = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_PRI3_MASK_ADDR); | ||
|  |     reg_int |= MAC_TX_START_MASK; | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_PRI3_MASK_ADDR, reg_int); | ||
|  | 
 | ||
|  |     reg_intr_en = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_ENA_ADDR); | ||
|  |     reg_intr_en |= MAC_TX_START_MASK; | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_RAW_INT_ENA_ADDR, reg_intr_en); | ||
|  | 
 | ||
|  |     return; | ||
|  | } | ||
|  | 
 | ||
|  | void mac_rawdata_tx_war_isr_cfg(void) | ||
|  | { | ||
|  |     /* disable rawdata tx start isr */ | ||
|  |     mac_rawdata_tx_start_isr_disable(); | ||
|  | 
 | ||
|  |     /* enable rawdata tx start isr */ | ||
|  |     mac_rawdata_tx_start_isr_enable(); | ||
|  | } | ||
|  | 
 | ||
|  | void mac_rawdata_tx_start_isr_clr(void) | ||
|  | { | ||
|  |     uint32_t reg_intr_status = 0; | ||
|  |     reg_intr_status = iot_raw_read_reg(RAW_REG_TYPE_MAC, \ | ||
|  |                             CFG_RAW_INT_CLR_ADDR); | ||
|  |     reg_intr_status |= MAC_TX_START_INT_STATUS; | ||
|  |     iot_raw_write_reg(RAW_REG_TYPE_MAC, \ | ||
|  |                             CFG_RAW_INT_CLR_ADDR, reg_intr_status); | ||
|  | } | ||
|  | 
 | ||
|  | #else // HW_PLATFORM >= HW_PLATFORM_FPGA
 | ||
|  | 
 | ||
|  | void mac_rawdata_sack_isr_cfg(uint32_t src_prot) | ||
|  | { | ||
|  |     (void)src_prot; | ||
|  | } | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #if CPLC_IOT_CERT_SUPPORT
 | ||
|  | 
 | ||
|  | static uint32_t iot_rawdata_bb_tmi_reset() | ||
|  | { | ||
|  |     phy_rawdata_mode_bb_set_ps_tr(0, 0, 0); | ||
|  |     return 0; | ||
|  | } | ||
|  | 
 | ||
|  | static uint32_t mac_rawdata_fc_send(uint32_t hwqid, fc_trans_msg *p_msg, | ||
|  |     uint8_t *fc, uint8_t tmi, uint8_t ext_tmi) | ||
|  | { | ||
|  | #if HW_PLATFORM >= HW_PLATFORM_FPGA
 | ||
|  | 
 | ||
|  | #if CERT_TEST_DEBUG
 | ||
|  |     iot_printf("%s\n", __FUNCTION__); | ||
|  | #endif
 | ||
|  |     /* init p_msg org_fc and trans_fc */ | ||
|  |     os_mem_set(p_msg->org_fc, 0, 16); | ||
|  |     os_mem_set(p_msg->trans_fc, 0, 16); | ||
|  |     /* keep poolling until checkout fc*/ | ||
|  |     do{ | ||
|  |         /*read fc form fc reg*/ | ||
|  |         iot_rawdata_get_tx_fc_bytes(p_msg); | ||
|  |      /*until reg read fc =  write fc*/ | ||
|  |     }while(os_mem_cmp((uint8_t *)fc, (uint8_t *)p_msg->org_fc, 16)); | ||
|  | 
 | ||
|  | #if CERT_TEST_DEBUG > 1
 | ||
|  |     mem_dump((uint32_t*)fc, 4); | ||
|  |     mem_dump((uint32_t*)p_msg->org_fc, 4); | ||
|  | #endif
 | ||
|  |     /*translte fc when you want change the value of fc*/ | ||
|  |     iot_rawdata_translate_tx_fc(p_msg, 0, 0); | ||
|  |     /*set bb pb size(tmi) for war the hw bug*/ | ||
|  |     phy_rawdata_bb_set_tmi(PHY_PROTO_TYPE_GET(), tmi, ext_tmi); | ||
|  | 
 | ||
|  |     /*tx fc in rawdata mode*/ | ||
|  |     iot_rawdata_set_translate_tx_fc(p_msg); | ||
|  | 
 | ||
|  | #if MAC_TIMESTAMPING
 | ||
|  |     mac_pdev_t *pdev_t = g_mac_pdev[PLC_PDEV_ID]; | ||
|  |     pdev_t->mac_tx_sw_ntb = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #if 1     /* make sure tx done */
 | ||
|  |     volatile tx_dummy_node *dummy = NULL; | ||
|  |     mac_queue_ctxt_t *hwq_ctxt = &g_mac_pdev[0]->hwq_hdl; | ||
|  |     mac_desc_get(&g_mac_desc_eng, PLC_TX_DUMMY_NODE_POOL, (void**)&dummy); | ||
|  |     IOT_ASSERT(dummy); | ||
|  |     dummy->desc_type = DESC_TYPE_TX_DUMMY; | ||
|  |     mac_tx_hw_mpdu(hwq_ctxt, hwqid, (tx_mpdu_start*)dummy); | ||
|  | 
 | ||
|  |     uint32_t cur_ntb = 0; | ||
|  |     uint32_t start_ntb = mac_sched_get_ntb(NULL); | ||
|  |     do { | ||
|  |         cur_ntb = mac_sched_get_ntb(NULL); | ||
|  |         if (cur_ntb - start_ntb >= (25000 * 1000 * 3)) { | ||
|  |             iot_printf("tx timeout\n"); | ||
|  |             IOT_ASSERT(0); | ||
|  |         } | ||
|  |     } while (!dummy->tx_done); | ||
|  |     mac_tx_hw_mpdu_comp(hwqid, 1); | ||
|  | #endif
 | ||
|  | 
 | ||
|  |     /*disable rawdata mode*/ | ||
|  |     iot_rawdata_hw_enable(0); | ||
|  |     /*reset pb size(tmi), from war the hw bug out*/ | ||
|  |     iot_rawdata_bb_tmi_reset(); | ||
|  | #else
 | ||
|  |     (void)hwqid; | ||
|  |     (void)p_msg; | ||
|  |     (void)fc; | ||
|  |     (void)tmi; | ||
|  |     (void)ext_tmi; | ||
|  | #endif
 | ||
|  |     return 0; | ||
|  | } | ||
|  | 
 | ||
|  | void mac_rawdata_send_cert_mpdu(uint32_t hwqid, tx_mpdu_start *mpdu, | ||
|  |     fc_trans_msg *p_msg, void *fc, uint32_t tmi, uint32_t ext_tmi) | ||
|  | { | ||
|  |     /* modify proto type */ | ||
|  |     mpdu->proto_type = PHY_PROTO_TYPE_GET(); | ||
|  | 
 | ||
|  |     /* enable rawdata mode */ | ||
|  |     iot_rawdata_hw_enable(1); | ||
|  | 
 | ||
|  |     mac_queue_ctxt_t *hwq = &g_mac_pdev[0]->hwq_hdl; | ||
|  | 
 | ||
|  | #if CERT_TEST_DEBUG > 1
 | ||
|  |     mem_dump((uint32_t*)mpdu, sizeof(tx_mpdu_start)>>2); | ||
|  | #endif
 | ||
|  | 
 | ||
|  |     //adjust loopback time
 | ||
|  | 
 | ||
|  |     uint32_t time_st = mac_sched_get_ntb(NULL); | ||
|  |     uint32_t cifs_delay = mac_tx_hw_get_delay(); | ||
|  | 
 | ||
|  |     uint32_t cur_time = 0; | ||
|  |     int64_t time_span = 0; | ||
|  |     do { | ||
|  |         cur_time = mac_sched_get_ntb(NULL); | ||
|  |         time_span = cur_time - time_st; | ||
|  |         if (time_span < 0) { // wrap around
 | ||
|  |             time_span = (0x100000000LL) - time_st + cur_time; | ||
|  |         } | ||
|  |     } while (time_span<cifs_delay); | ||
|  | 
 | ||
|  |     /* send */ | ||
|  |     mac_tx_hw_mpdu(hwq, hwqid, mpdu); | ||
|  | 
 | ||
|  |     /*rawdata send mpdu*/ | ||
|  |     mac_rawdata_fc_send(hwqid, p_msg, (uint8_t *)fc, | ||
|  |         (uint8_t)tmi, (uint8_t)ext_tmi); | ||
|  | } | ||
|  | 
 | ||
|  | #else /* CPLC_IOT_CERT_SUPPORT */
 | ||
|  | 
 | ||
|  | void mac_rawdata_send_cert_mpdu(uint32_t hwqid, tx_mpdu_start *mpdu, | ||
|  |     fc_trans_msg *p_msg, void *fc, uint32_t tmi, uint32_t ext_tmi) | ||
|  | { | ||
|  |     (void)hwqid; | ||
|  |     (void)mpdu; | ||
|  |     (void)p_msg; | ||
|  |     (void)fc; | ||
|  |     (void)tmi; | ||
|  |     (void)ext_tmi; | ||
|  | } | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 |