1013 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1013 lines
		
	
	
		
			28 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 "os_types.h"
 | |
| #include "os_mem.h"
 | |
| #include "os_task.h"
 | |
| #include "os_event.h"
 | |
| 
 | |
| /* common includes */
 | |
| #include "iot_module.h"
 | |
| #include "iot_queue.h"
 | |
| #include "iot_errno.h"
 | |
| #include "iot_bitops.h"
 | |
| #include "iot_io.h"
 | |
| #include "iot_plc_pm_api.h"
 | |
| #include "iot_task_api.h"
 | |
| 
 | |
| /* mac module internal includes */
 | |
| #include "mac.h"
 | |
| #include "mac_msg.h"
 | |
| #include "beacon.h"
 | |
| #include "mac_vdev.h"
 | |
| #include "mac_pdev.h"
 | |
| #include "sw_sched.h"
 | |
| #include "mac_data.h"
 | |
| #include "mac_rx_hw.h"
 | |
| #include "mac_cert_test.h"
 | |
| #include "mac_sched.h"
 | |
| #include "mac_zc.h"
 | |
| #include "mac_ppm_scan.h"
 | |
| #include "mac_reset.h"
 | |
| #include "mac_pm.h"
 | |
| #include "mac_channel.h"
 | |
| #include "mac_check_spur_cco.h"
 | |
| #include "mac_check_spur_sta.h"
 | |
| 
 | |
| /* public api includes */
 | |
| #include "plc_fr.h"
 | |
| 
 | |
| #include "mac_pdev.h"
 | |
| #include "mac_dbg_pkt_mode.h"
 | |
| #include "mac_hplc_ext.h"
 | |
| #include "mac_channel_tools.h"
 | |
| #include "mac_hw_tsfm.h"
 | |
| #include "mac_rf_cert_test.h"
 | |
| #include "mac_rf_scan.h"
 | |
| 
 | |
| #if HPLC_RF_DEV_SUPPORT
 | |
| #include "mac_rf_rx_hw.h"
 | |
| #include "mac_rf_rx_buf_ring.h"
 | |
| #endif
 | |
| 
 | |
| /* define the quota of each mac message queue. 0 means disable quota.
 | |
|  * quota rule:
 | |
|  * 1. quota disabled queues first
 | |
|  * 2. then quota available queues
 | |
|  * 3. quota exhausted queues last
 | |
|  */
 | |
| static uint8_t g_mac_msg_q_quota[MAC_MSG_QUEUE_MAX_PRIO] =
 | |
| {
 | |
|     /* MAC_MSG_QUEUE_HP */
 | |
|     0,
 | |
|     /* MAC_MSG_QUEUE_MP */
 | |
|     2,
 | |
|     /* MAC_MSG_QUEUE_LP */
 | |
|     1
 | |
| };
 | |
| 
 | |
| static void mac_handle_msg_mac(mac_global_t * glb,mac_msg_t * msg)
 | |
| {
 | |
|     (void)glb;
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_MAC_WARM_RESET_WAR:
 | |
|     {
 | |
|         mac_warm_reset_war(msg->data1);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_MAC_DEBUG_TX_HANG:
 | |
|     {
 | |
|         mac_tx_hang_handle();
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_MAC_ZC_SET_FUNC_CMD:
 | |
|     {
 | |
|         mac_zc_set_func_cmd_internal(msg->data1 & 0xFF,
 | |
|             (msg->data1 >> 8) & 0xFF, msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| static void mac_handle_msg_cvg(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     uint8_t pdev_id, vdev_id, tmp, sn;
 | |
|     uint8_t stop_band_scan_flag = 0;
 | |
|     (void)glb;
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_CVG_START_BC:
 | |
|     {
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         mac_start_beacon_internal(pdev_id, vdev_id);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_STOP_BC:
 | |
|     {
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         mac_stop_beacon_internal(pdev_id, vdev_id);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_UPDATE_BC:
 | |
|     {
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         msg->data1 = mac_update_beacon_internal(pdev_id, vdev_id, msg->data2,
 | |
|             &tmp);
 | |
|         msg->data2 = (void *)((uint32_t)tmp);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_CREATE_VDEV:
 | |
|     {
 | |
|         pdev_id = (uint8_t)(msg->data1 & 0xFF);
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         msg->data1 = mac_create_vdev_internal(pdev_id, &vdev_id, msg->data2);
 | |
| #if PLC_SUPPORT_DBG_PKT_MODE
 | |
|         /* since the PLC_DEFAULT_VDEV == 0, then it must create cvg call
 | |
|          * vdev first.
 | |
|          */
 | |
|         //TODO: will fix create dbg pkt vdev in create vdev function
 | |
|         mac_create_dbg_pkt_vdev(pdev_id, msg->data2);
 | |
| #endif
 | |
|         msg->data2 = (void *)((uint32_t)vdev_id);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_START_VDEV:
 | |
|     {
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         msg->data1 = mac_start_vdev_internal(pdev_id, vdev_id, msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_SET_VDEV_CFG:
 | |
|     {
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         msg->data1 = mac_set_vdev_cfg_internal(pdev_id, vdev_id, msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_STOP_VDEV:
 | |
|     {
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         msg->data1 = mac_stop_vdev_internal(pdev_id, vdev_id);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_MSDU_SEND:
 | |
|     {
 | |
|         iot_pkt_t* msdu_buf;
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         msdu_buf = msg->data2;
 | |
|         mac_tx_info *tx_info = msg->data3;
 | |
|         if (tx_info->is_rf_data) {
 | |
|             msg->data1 = mac_send_rf_msdu_ex_internal(pdev_id, vdev_id,
 | |
|                 msdu_buf, msg->data3);
 | |
|         } else {
 | |
|             msg->data1 = mac_send_msdu_ex_internal(pdev_id, vdev_id,
 | |
|                 msdu_buf, msg->data3);
 | |
|         }
 | |
|         /* if no memery,then free buf */
 | |
|         if (ERR_OK != msg->data1) {
 | |
|             iot_pkt_free_tx_done(msdu_buf, IOT_PKT_STATE_TX_FAIL);
 | |
|             msg->data2 = NULL;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_CERT_MODE_SEL:
 | |
|     {
 | |
|         uint8_t mt_mode_sel = msg->data1 & 0xFF;
 | |
|         mac_cert_test_g_set(mt_mode_sel);
 | |
|         stop_band_scan_flag = 1;
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_CERT_BAND:
 | |
|     {
 | |
|         uint8_t band_id;
 | |
|         band_id = msg->data1 & 0xFF;
 | |
|         mac_cert_test_band_cfg(band_id);
 | |
|         stop_band_scan_flag = 1;
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_CERT_TONEMASK:
 | |
|     {
 | |
|         uint8_t tonemask_id;
 | |
|         tonemask_id = msg->data1 & 0xFF;
 | |
|         mac_cert_test_tonemast_cfg(tonemask_id);
 | |
|         stop_band_scan_flag = 1;
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_SET_PDEV_CFG:
 | |
|     {
 | |
|         cfg_data_tlv *tlv = (cfg_data_tlv *)msg->data2;
 | |
| 
 | |
|         pdev_id = msg->data1 & 0xFF;
 | |
|         msg->data1 = mac_set_pdev_cfg_internal(pdev_id, msg->data2);
 | |
|         if (tlv->type == PLC_PDEV_CFG_SET_BAND && msg->data1 == ERR_OK) {
 | |
|             stop_band_scan_flag = 1;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_START_ZC_NTB:
 | |
|     {
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         msg->data1 = mac_start_zc_ntb_collect_internal(pdev_id, vdev_id,
 | |
|             (iot_pkt_t *)msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_EXT_FRAME_SEND:
 | |
|     {
 | |
|         uint8_t ext_type;
 | |
|         pdev_id = (msg->data1 >> 24) & 0xFF;
 | |
|         sn = (msg->data1 >> 16) & 0xFF;
 | |
|         vdev_id = (msg->data1 >> 8) & 0xff;
 | |
|         ext_type = msg->data1 & 0xFF;
 | |
| 
 | |
|         mac_send_ext_frame_internal(ext_type, pdev_id, vdev_id, msg->data2,
 | |
|             msg->data3, sn);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_GET_PDEV_CFG:
 | |
|     {
 | |
|         pdev_id = msg->data1 & 0xFF;
 | |
|         msg->data1 = mac_get_pdev_cfg_internal(pdev_id, msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_HW_TSFM_SEND:
 | |
|     {
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         msg->data1 = mac_hw_tsfm_send_internal(pdev_id, vdev_id, msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_CERT_HPLC2RF:
 | |
|     {
 | |
|         uint8_t phr_mcs = (msg->data1 >> 16) & 0xFF;
 | |
|         uint8_t pld_mcs = (msg->data1 >> 8) & 0xFF ;
 | |
|         uint8_t pb_idx = msg->data1 & 0xFF;
 | |
|         mac_rf_cert_test_set_phy_hplc2rf_lp(phr_mcs, pld_mcs, pb_idx);
 | |
|         stop_band_scan_flag = 1;
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_CERT_SEC_MODE:
 | |
|     {
 | |
|         mac_cert_test_sec_mode_set((uint8_t)msg->data1);
 | |
|         stop_band_scan_flag = 1;
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_CERT_RF_CFG:
 | |
|     {
 | |
|         uint8_t rf_option, rf_channel;
 | |
|         rf_channel = msg->data1 & 0xFF;
 | |
|         rf_option = (msg->data1 >> 8) & 0xFF;
 | |
|         mac_rf_cert_test_option_channel_cfg(rf_option, rf_channel);
 | |
|         stop_band_scan_flag = 1;
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_CVG_GET_VDEV_CFG:
 | |
|     {
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         msg->data1 = mac_get_vdev_cfg_internal(pdev_id, vdev_id, msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID);
 | |
|     /* NOTE: if need stop band scan after some msg from cvg */
 | |
|     if (stop_band_scan_flag == 1 &&
 | |
|         !mac_scan_get_band_selected(&pdev->scan)) {
 | |
| #if STATIC_POWER_SAVE
 | |
|         /* stop power save */
 | |
|         mac_pm_stop(pdev);
 | |
| #endif
 | |
|         /* stop the scan to sync the bcn */
 | |
|         mac_scan_stop(&pdev->scan);
 | |
|         mac_scan_set_band_selected(&pdev->scan, true);
 | |
|         /* stop rf scan timer */
 | |
|         mac_rf_scan_stop();
 | |
|         /* set channel selected */
 | |
|         mac_rf_scan_set_channel_selected(1);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_dsr(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     (void)glb;
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_DSR_RX_TO_MSG:
 | |
|     {
 | |
|         void *pdev = msg->data2;
 | |
|         uint32_t ring_id = msg->data1 & 0xFFFF;
 | |
| 
 | |
| #if HPLC_RF_DEV_SUPPORT
 | |
|         if (msg->data1 & (1 << 16)) {
 | |
|             /* rf ring */
 | |
|             msg->data1 = mac_rf_rx_hw_mpdu_internal(pdev, ring_id,
 | |
|                 (uint32_t)msg->data3);
 | |
|             rx_buf_ring_t *rf_ring; //TODO: fix to rf rx ring context
 | |
| #if HW_PLATFORM == HW_PLATFORM_SIMU
 | |
|             rf_ring = &((mac_rf_pdev_t*)pdev)->simu.rx_ring[ring_id];
 | |
| #else
 | |
|             rf_ring = &((mac_rf_pdev_t*)pdev)->ring_hdl.ring[ring_id];
 | |
| #endif
 | |
|             if (ERR_OK == msg->data1) {
 | |
|                 /* TODO: this is assume in the same task of MAC */
 | |
|                 rf_ring->msg_delivered = 0;
 | |
|             }
 | |
|         } else
 | |
| #endif /* HPLC_RF_DEV_SUPPORT */
 | |
|         {
 | |
|             /* plc ring */
 | |
|             msg->data1 = mac_rx_hw_mpdu_internal(pdev, ring_id,
 | |
|                 (uint32_t)msg->data3);
 | |
|             rx_buf_ring_t *plc_ring;
 | |
| #if HW_PLATFORM == HW_PLATFORM_SIMU
 | |
|             plc_ring = &((mac_pdev_t*)pdev)->simu.rx_ring[ring_id];
 | |
| #else
 | |
|             plc_ring = &((mac_pdev_t*)pdev)->ring_hdl.ring[ring_id];
 | |
| #endif
 | |
|             if (ERR_OK == msg->data1) {
 | |
|                 /* TODO: this is assume in the same task of MAC */
 | |
|                 plc_ring->msg_delivered = 0;
 | |
|             }
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_timer(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     (void)glb;
 | |
|     mac_vdev_t *vdev;
 | |
|     uint8_t pdev_id, vdev_id;
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_SCHED_TX:
 | |
|     {
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         vdev = get_vdev_ptr(pdev_id, vdev_id);
 | |
|         if (vdev)
 | |
|             mac_sched_nn_tx(vdev);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_ZC_TRAIN_HW_TIMER:
 | |
|     {
 | |
|         mac_zc_train_hw_timeout_internal(msg->data1, msg->data2);
 | |
|         break;
 | |
|     }
 | |
| 
 | |
| #if !PM_USE_DSR
 | |
|     case MAC_MSG_ID_SYSTEM_SLEEP:
 | |
|     {
 | |
|         sleep_cfg_internal(msg->data2);
 | |
|         break;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
| #if K48_STA_MULTI_CHANNEL_SELECT_ENABLE
 | |
|     case MAC_MSG_ID_CHANNEL_SCAN_TIMER:
 | |
|     {
 | |
|         iot_mac_k48sta_switch_next_channel(msg->data2);
 | |
|         break;
 | |
|     }
 | |
| #endif
 | |
|     case MAC_MSG_ID_CCO_CHECK_SPUR_TIMER:
 | |
|     {
 | |
|         /* msg->data2 point to pdev */
 | |
|         mac_cco_check_spur_start(msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_STA_CHECK_SPUR_TIMER:
 | |
|     {
 | |
|         mac_sta_check_spur(msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_STA_PERIOD_CHECK_SPUR:
 | |
|     {
 | |
|         mac_sta_period_check_spur();
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_DEL_STREAM_TIMER:
 | |
|     {
 | |
|         mac_vdev_del_timeout_stream_internal(msg->data2, msg->data1);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_RF_SCAN_TIMER:
 | |
|     {
 | |
|         mac_rf_scan_next_target(msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_PPM_RECORD_TIMER:
 | |
|     {
 | |
|         mac_ppm_record_refresh_handle(msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_MAC_CERT_WAR_TIMER:
 | |
|     {
 | |
|         mac_cert_war_trans_handle();
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_sch(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     (void)glb;
 | |
|     uint8_t pdev_id, vdev_id;
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_SCH_TX:
 | |
|         /* call frame selection handler */
 | |
|         /* TODO: place call here ... */
 | |
|         pdev_id = (msg->data1 >> 8) & 0xFF;
 | |
|         vdev_id = msg->data1 & 0xFF;
 | |
|         mac_swsch_post_msdu(pdev_id,vdev_id);
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_pm(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     (void)glb;
 | |
|     uint8_t pdev_id, vdev_id;
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_PM_OFF:
 | |
|     {
 | |
|         if (msg->data1 == IOT_PLC_PM_MSG_POWER_COLLAPSED) {
 | |
|             for(pdev_id = 0; pdev_id < MAX_PDEV_NUM; pdev_id++) {
 | |
|                 for(vdev_id = 0; vdev_id < MAX_VDEV_NUM; vdev_id++) {
 | |
|                     mac_pdev_t *pdev = get_pdev_ptr(pdev_id);
 | |
|                     if(pdev->vdev[vdev_id]) {
 | |
|                         mac_pm_rx_power_off_internal(pdev_id, vdev_id);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         } else if (msg->data1 == IOT_PLC_PM_MSG_POWER_RECOVERED) {
 | |
|             for (pdev_id = 0; pdev_id < MAX_PDEV_NUM; pdev_id++) {
 | |
|                 for (vdev_id = 0; vdev_id < MAX_VDEV_NUM; vdev_id++) {
 | |
|                     mac_pdev_t *pdev = get_pdev_ptr(pdev_id);
 | |
|                     if (pdev->vdev[vdev_id]) {
 | |
|                         mac_pm_power_recover_internal(pdev_id, vdev_id);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case MAC_MSG_ID_PWR_CHANGE:
 | |
|     {
 | |
|         low_pwr_for_powroff_cfg_internal(msg->data1, msg->data2);
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_phy(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     (void)glb;
 | |
| 
 | |
|     switch (msg->id) {
 | |
| #if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_STA)
 | |
|     case MAC_MSG_ID_CHANNEL_TEST_STOP:
 | |
|         mac_channel_test_end_internal();
 | |
|         break;
 | |
| #endif
 | |
|     case MAC_MSG_ID_CHANNEL_ESTIMATED:
 | |
|         mac_check_spur_cert(msg->data1);
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_cli(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     (void)glb;
 | |
| 
 | |
|     switch (msg->id) {
 | |
| #if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_STA)
 | |
|     case MAC_MSG_ID_CHANNEL_DUMP_TEST:
 | |
|         mac_channel_dump_start_internal(msg->data2);
 | |
|         break;
 | |
| #endif
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* mac msg handling function */
 | |
| static inline void mac_handle_msg(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     switch (msg->type) {
 | |
|     case MAC_MSG_TYPE_CVG:
 | |
|         mac_handle_msg_cvg(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_DSR:
 | |
|         mac_handle_msg_dsr(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_TIMER:
 | |
|         mac_handle_msg_timer(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_SCH:
 | |
|         mac_handle_msg_sch(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_MAC:
 | |
|         mac_handle_msg_mac(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_PM:
 | |
|         mac_handle_msg_pm(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_PHY:
 | |
|         mac_handle_msg_phy(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_CLI:
 | |
|         mac_handle_msg_cli(glb, msg);
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     if (msg->sync) {
 | |
|         /* notify message sender that message handling is done. */
 | |
|         mac_msg_sync_t *msg_sync = (mac_msg_sync_t *)msg;
 | |
|         os_set_event(msg_sync->event);
 | |
|     } else {
 | |
|         /* free non-sync message. for sync message, message sender will
 | |
|          * free it.
 | |
|          */
 | |
|         mac_free_msg(msg);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_cvg_cancel(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_CVG_START_BC:
 | |
|     case MAC_MSG_ID_CVG_STOP_BC:
 | |
|     case MAC_MSG_ID_CVG_UPDATE_BC:
 | |
|     case MAC_MSG_ID_CVG_CREATE_VDEV:
 | |
|     case MAC_MSG_ID_CVG_START_VDEV:
 | |
|     case MAC_MSG_ID_CVG_SET_VDEV_CFG:
 | |
|     case MAC_MSG_ID_CVG_STOP_VDEV:
 | |
|     case MAC_MSG_ID_CVG_MSDU_SEND:
 | |
|     case MAC_MSG_ID_CVG_CERT_MODE_SEL:
 | |
|     case MAC_MSG_ID_CVG_CERT_BAND:
 | |
|     case MAC_MSG_ID_CVG_CERT_TONEMASK:
 | |
|     case MAC_MSG_ID_CVG_SET_PDEV_CFG:
 | |
|     case MAC_MSG_ID_CVG_START_ZC_NTB:
 | |
|     case MAC_MSG_ID_CVG_EXT_FRAME_SEND:
 | |
|     case MAC_MSG_ID_CVG_GET_PDEV_CFG:
 | |
|     case MAC_MSG_ID_CVG_HW_TSFM_SEND:
 | |
|     case MAC_MSG_ID_CVG_CERT_HPLC2RF:
 | |
|     case MAC_MSG_ID_CVG_CERT_SEC_MODE:
 | |
|     case MAC_MSG_ID_CVG_CERT_RF_CFG:
 | |
|     case MAC_MSG_ID_CVG_GET_VDEV_CFG:
 | |
|     {
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_mac_cancel(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_MAC_WARM_RESET_WAR:
 | |
|     case MAC_MSG_ID_MAC_DEBUG_TX_HANG:
 | |
|     case MAC_MSG_ID_MAC_ZC_SET_FUNC_CMD:
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_dsr_cancel(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_DSR_RX_TO_MSG:
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_timer_cancel(mac_global_t *glb,
 | |
|     mac_msg_t *msg)
 | |
| {
 | |
|     iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_SCHED_TX:
 | |
|         break;
 | |
| #if !PM_USE_DSR
 | |
|     case MAC_MSG_ID_SYSTEM_SLEEP:
 | |
|         break;
 | |
| #endif
 | |
|     case MAC_MSG_ID_ZC_TRAIN_HW_TIMER:
 | |
|         break;
 | |
| #if K48_STA_MULTI_CHANNEL_SELECT_ENABLE
 | |
|     case MAC_MSG_ID_CHANNEL_SCAN_TIMER:
 | |
|         break;
 | |
| #endif
 | |
|     case MAC_MSG_ID_CCO_CHECK_SPUR_TIMER:
 | |
|         break;
 | |
|     case MAC_MSG_ID_STA_CHECK_SPUR_TIMER:
 | |
|         break;
 | |
|     case MAC_MSG_ID_STA_PERIOD_CHECK_SPUR:
 | |
|         break;
 | |
|     case MAC_MSG_ID_DEL_STREAM_TIMER:
 | |
|         break;
 | |
|     case MAC_MSG_ID_RF_SCAN_TIMER:
 | |
|         break;
 | |
|     case MAC_MSG_ID_PPM_RECORD_TIMER:
 | |
|         break;
 | |
|     case MAC_MSG_ID_MAC_CERT_WAR_TIMER:
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_sch_cancel(mac_global_t *glb,
 | |
|     mac_msg_t *msg)
 | |
| {
 | |
|     iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_SCH_TX:
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_pm_cancel(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_PM_OFF:
 | |
|     case MAC_MSG_ID_PWR_CHANGE:
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_phy_cancel(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_CHANNEL_TEST_STOP:
 | |
|         break;
 | |
|     case MAC_MSG_ID_CHANNEL_ESTIMATED:
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_handle_msg_cli_cancel(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
 | |
| 
 | |
|     switch (msg->id) {
 | |
|     case MAC_MSG_ID_CHANNEL_DUMP_TEST:
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /* handle msg canceled case. message can be canceled due to various reasons.
 | |
|  * each message may have different cancelation operation required.
 | |
|  */
 | |
| void mac_handle_msg_cancel(mac_global_t *glb, mac_msg_t *msg)
 | |
| {
 | |
|     switch (msg->type) {
 | |
|     case MAC_MSG_TYPE_CVG:
 | |
|         mac_handle_msg_cvg_cancel(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_MAC:
 | |
|         mac_handle_msg_mac_cancel(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_DSR:
 | |
|         mac_handle_msg_dsr_cancel(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_TIMER:
 | |
|         mac_handle_msg_timer_cancel(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_SCH:
 | |
|         mac_handle_msg_sch_cancel(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_PM:
 | |
|         mac_handle_msg_pm_cancel(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_PHY:
 | |
|         mac_handle_msg_phy_cancel(glb, msg);
 | |
|         break;
 | |
|     case MAC_MSG_TYPE_CLI:
 | |
|         mac_handle_msg_cli_cancel(glb, msg);
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     mac_free_msg(msg);
 | |
| }
 | |
| 
 | |
| extern uint8_t mac_log_print_en;
 | |
| extern void mac_tx_csma_dump();
 | |
| 
 | |
| static void mac_main_task(void* arg)
 | |
| {
 | |
|     uint8_t i, j, tmp;
 | |
|     uint32_t dsr_event;
 | |
|     mac_global_t *glb = arg;
 | |
|     iot_msg_entry_t *entry;
 | |
|     mac_msg_t *msg;
 | |
|     mac_dsr_func_t dsr;
 | |
|     mac_msg_queue_t *pq;
 | |
|     uint8_t quota_disbled_q_cnt = 0;
 | |
|     uint8_t quota_enabled_q_cnt = 0;
 | |
|     uint8_t quota_exhausted_q_cnt = 0;
 | |
|     mac_msg_queue_t *quota_disbled_q[MAC_MSG_QUEUE_MAX_PRIO];
 | |
|     mac_msg_queue_t *quota_enabled_q[MAC_MSG_QUEUE_MAX_PRIO];
 | |
|     mac_msg_queue_t *quota_exhausted_q[MAC_MSG_QUEUE_MAX_PRIO];
 | |
| 
 | |
|     iot_printf("%s glb %p\n", __FUNCTION__, glb);
 | |
| 
 | |
|     /* check if quota enabled and disabled queue exist */
 | |
|     for (i = 0; i < MAC_MSG_QUEUE_MAX_PRIO; i++) {
 | |
|         pq = &glb->msg_q[i];
 | |
|         if (pq->quota_en) {
 | |
|             quota_enabled_q[quota_enabled_q_cnt] = pq;
 | |
|             quota_enabled_q_cnt++;
 | |
|         } else {
 | |
|             quota_disbled_q[quota_disbled_q_cnt] = pq;
 | |
|             quota_disbled_q_cnt++;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (;;) {
 | |
|         /* waiting for messages from various modules and dsr events from isr.
 | |
|          * always handle dsr event firstly.
 | |
|          */
 | |
|         dsr_event = os_wait_task_event_with_v(MAX_TIME);
 | |
| 
 | |
| handle_dsr:
 | |
|         i = 0;
 | |
|         while (dsr_event) {
 | |
|             tmp = dsr_event & 0xFF;
 | |
|             while (tmp) {
 | |
|                 j = iot_bitops_fls(tmp) - 1;
 | |
|                 tmp &= ~(0x1 << j);
 | |
|                 dsr = glb->dsr_table.entry[i + j].dsr;
 | |
|                 if (dsr) {
 | |
|                     dsr();
 | |
|                 }
 | |
|             }
 | |
|             dsr_event >>= 8;
 | |
|             i += 8;
 | |
|         }
 | |
| 
 | |
| handle_msg:
 | |
|         /* check quota disabled queue */
 | |
|         if (quota_disbled_q_cnt) {
 | |
|             /* check message queues based on priority */
 | |
|             for (i = 0; i < quota_disbled_q_cnt; i++) {
 | |
|                 pq = quota_disbled_q[i];
 | |
|                 entry = iot_msg_queue_get(&pq->q);
 | |
|                 if (entry) {
 | |
|                     /* get message and handle it */
 | |
|                     msg = container_of(entry, mac_msg_t, link);
 | |
|                     mac_handle_msg(glb, msg);
 | |
|                     /* check if any dsr event pending */
 | |
|                     dsr_event = os_wait_task_event_with_v(0);
 | |
|                     if (dsr_event)
 | |
|                         goto handle_dsr;
 | |
|                     /* always search from highest priority queue with quota
 | |
|                      * disabled.
 | |
|                      */
 | |
|                     goto handle_msg;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /* check quota enabled queue */
 | |
|         if (quota_enabled_q_cnt) {
 | |
|             quota_exhausted_q_cnt = 0;
 | |
|             /* check message queues based on priority */
 | |
|             for (i = 0; i < quota_enabled_q_cnt; i++) {
 | |
|                 pq = quota_enabled_q[i];
 | |
|                 /* check if quota available for this queue */
 | |
|                 if (pq->curr_quota == 0) {
 | |
|                     quota_exhausted_q[quota_exhausted_q_cnt] = pq;
 | |
|                     quota_exhausted_q_cnt++;
 | |
|                     continue;
 | |
|                 }
 | |
|                 entry = iot_msg_queue_get(&pq->q);
 | |
|                 if (entry) {
 | |
|                     /* get message and handle it */
 | |
|                     msg = container_of(entry, mac_msg_t, link);
 | |
|                     mac_handle_msg(glb, msg);
 | |
|                     pq->curr_quota--;
 | |
|                     /* check if any dsr event pending */
 | |
|                     dsr_event = os_wait_task_event_with_v(0);
 | |
|                     if (dsr_event)
 | |
|                         goto handle_dsr;
 | |
|                     /* always search from highest priority queue with quota
 | |
|                      * disabled.
 | |
|                      */
 | |
|                     goto handle_msg;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (quota_exhausted_q_cnt == quota_enabled_q_cnt) {
 | |
|                 /* no quota available queue exist, re-assign quota */
 | |
|                 for (i = 0; i < quota_enabled_q_cnt; i++) {
 | |
|                     pq = quota_enabled_q[i];
 | |
|                     pq->curr_quota = pq->quota;
 | |
|                 }
 | |
|                 /* always search from highest priority queue with quota
 | |
|                  * disabled.
 | |
|                  */
 | |
|                 goto handle_msg;
 | |
|             } else {
 | |
|                 /* check if any quota exhausted queue exist */
 | |
|                 for (i = 0; i < quota_exhausted_q_cnt; i++) {
 | |
|                     pq = quota_exhausted_q[i];
 | |
|                     entry = iot_msg_queue_get(&pq->q);
 | |
|                     if (entry) {
 | |
|                         /* get message and handle it */
 | |
|                         msg = container_of(entry, mac_msg_t, link);
 | |
|                         mac_handle_msg(glb, msg);
 | |
|                         /* check if any dsr event pending */
 | |
|                         dsr_event = os_wait_task_event_with_v(0);
 | |
|                         if (dsr_event)
 | |
|                             goto handle_dsr;
 | |
|                         /* always search from highest priority queue with
 | |
|                          * quota disabled.
 | |
|                          */
 | |
|                         goto handle_msg;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         if (mac_log_print_en) {
 | |
|             mac_tx_csma_dump();
 | |
|             mac_log_print_en = 0;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| uint32_t mac_start_task(mac_global_t *glb)
 | |
| {
 | |
|     uint8_t i;
 | |
|     uint32_t ret = 0;
 | |
|     os_task_h handle;
 | |
| 
 | |
|     /* initialize mac message queue */
 | |
|     for (i = 0; i < MAC_MSG_QUEUE_MAX_PRIO; i++) {
 | |
|         ret = iot_msg_queue_init(&glb->msg_q[i].q);
 | |
|         if (g_mac_msg_q_quota[i]) {
 | |
|             /* enable quota for this queue */
 | |
|             glb->msg_q[i].quota_en = 1;
 | |
|             glb->msg_q[i].quota = g_mac_msg_q_quota[i];
 | |
|             glb->msg_q[i].curr_quota = glb->msg_q[i].quota;
 | |
|         } else {
 | |
|             /* disable quota for this queue */
 | |
|             glb->msg_q[i].quota_en = 0;
 | |
|             glb->msg_q[i].quota = 0;
 | |
|             glb->msg_q[i].curr_quota = 0;
 | |
|         }
 | |
|         if (ret) {
 | |
|             for (; i > 0; i--) {
 | |
|                 iot_msg_queue_deinit(&glb->msg_q[i - 1].q);
 | |
|             }
 | |
|             goto out;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* start mac main task */
 | |
|     handle = os_create_task_ext(mac_main_task, glb, PLC_MAC_TASK_PRIO,
 | |
|         PLC_MAC_STACK_SIZE, __FUNCTION__);
 | |
| 
 | |
|     iot_printf("%s glb %p\n", __FUNCTION__, glb);
 | |
| 
 | |
|     if (handle == NULL) {
 | |
|         ret = ERR_NOMEM;
 | |
|         goto err_task;
 | |
|     } else {
 | |
|         glb->task_h = handle;
 | |
|     }
 | |
| 
 | |
|     goto out;
 | |
| 
 | |
| err_task:
 | |
|     for (i = 0; i < MAC_MSG_QUEUE_MAX_PRIO; i++)
 | |
|         iot_msg_queue_deinit(&glb->msg_q[i].q);
 | |
| out:
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| void mac_stop_task(mac_global_t *glb)
 | |
| {
 | |
|     iot_msg_entry_t *entry;
 | |
|     mac_msg_t *msg;
 | |
|     iot_msg_queue_t *pq;
 | |
|     uint8_t i;
 | |
| 
 | |
|     if (glb->task_h) {
 | |
|         /* delete mac main task */
 | |
|         os_delete_task(glb->task_h);
 | |
|         glb->task_h = NULL;
 | |
| 
 | |
|         for (i = 0; i < MAC_MSG_QUEUE_MAX_PRIO; i++) {
 | |
|             pq = &glb->msg_q[i].q;
 | |
|             entry = iot_msg_queue_get(pq);
 | |
|             while (entry) {
 | |
|                 /* get messages */
 | |
|                 msg = container_of(entry, mac_msg_t, link);
 | |
|                 mac_handle_msg_cancel(glb, msg);
 | |
|                 entry = iot_msg_queue_get(pq);
 | |
|             }
 | |
| 
 | |
|             /* deinit the mac message queue */
 | |
|             iot_msg_queue_deinit(pq);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     iot_printf("%s glb %p\n", __FUNCTION__, glb);
 | |
| }
 | |
| 
 | |
| void mac_boost_task_prio()
 | |
| {
 | |
|     os_set_task_prio_ext(p_mac_glb->task_h, PLC_TASK_HIGHEST_PRIO);
 | |
| }
 | |
| 
 | |
| void mac_restore_task_prio()
 | |
| {
 | |
|     os_set_task_prio_ext(p_mac_glb->task_h, PLC_MAC_TASK_PRIO);
 | |
| }
 |