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);
|
|
}
|