293 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			7.7 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_vdev_api.h"
 | |
| #include "mac_rf_vdev.h"
 | |
| #include "mac_rf_pdev.h"
 | |
| #include "iot_errno.h"
 | |
| #include "iot_mem_pool_api.h"
 | |
| #include "mac_msg.h"
 | |
| #include "mac.h"
 | |
| #include "mac_peer.h"
 | |
| #include "mac_tx_hw.h" /* for flush */
 | |
| #include "mac_desc_engine.h"
 | |
| #include "mac_rx_buf_ring.h"
 | |
| #include "iot_io.h"
 | |
| #include "mac_rx_hw.h"
 | |
| #include "hw_war.h"
 | |
| #include "mac_stream.h"
 | |
| #include "mac_rf_sched.h"
 | |
| #include "rf_rate_control.h"
 | |
| #include "mac_rf_tx_hw.h"
 | |
| #include "iot_system.h"
 | |
| #include "mac_rf_tx_power.h"
 | |
| 
 | |
| #if HPLC_RF_DEV_SUPPORT
 | |
| 
 | |
| #include "mac_rf_sched_hw.h"
 | |
| #include "mac_rf_rx_buf_ring.h"
 | |
| #include "mac_rf_common_hw.h"
 | |
| 
 | |
| tei_t rf_vdev_get_tei(mac_rf_vdev_t* rf_vdev)
 | |
| {
 | |
|     (void)rf_vdev;
 | |
|     mac_vdev_t *vdev = get_vdev_ptr(PLC_PDEV_ID, PLC_DEFAULT_VDEV);
 | |
|     return vdev_get_tei(vdev);
 | |
| }
 | |
| 
 | |
| void mac_rf_vdev_set_tei(mac_rf_vdev_t* rf_vdev, tei_t tei)
 | |
| {
 | |
|     IOT_ASSERT(rf_vdev);
 | |
|     mac_vdev_t *vdev = get_vdev_ptr(PLC_PDEV_ID, PLC_DEFAULT_VDEV);
 | |
|     vdev_set_tei(vdev, tei);
 | |
| }
 | |
| 
 | |
| uint8_t rf_vdev_get_node_role(mac_rf_vdev_t* rf_vdev)
 | |
| {
 | |
|     (void)rf_vdev;
 | |
|     mac_vdev_t *vdev = get_vdev_ptr(PLC_PDEV_ID, PLC_DEFAULT_VDEV);
 | |
|     return mac_vdev_cfg_get_node_role(vdev);
 | |
| }
 | |
| 
 | |
| void rf_vdev_set_ra(mac_rf_vdev_t *rf_vdev, rf_rate_control_func_t ra)
 | |
| {
 | |
|     IOT_ASSERT(rf_vdev);
 | |
|     rf_vdev->ra_cb = ra;
 | |
| }
 | |
| 
 | |
| uint32_t mac_rf_vdev_get_sync_nid(mac_rf_vdev_t *rf_vdev, nid_t *rf_sync_nid)
 | |
| {
 | |
|     if ((NULL == rf_vdev) || (NULL == rf_sync_nid)) {
 | |
|         IOT_ASSERT(0);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if (rf_vdev->rf_sync_nid_inited) {
 | |
|         *rf_sync_nid = mac_mask_input_nid(rf_vdev->rf_sync_nid);
 | |
| 
 | |
|         return ERR_OK;
 | |
|     } else {
 | |
|         *rf_sync_nid = PLC_NID_INVALID;
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void mac_rf_vdev_set_sync_nid(mac_rf_vdev_t *rf_vdev, uint32_t nid)
 | |
| {
 | |
|     if (rf_vdev == NULL) {
 | |
|         IOT_ASSERT(0);
 | |
|         return;
 | |
|     }
 | |
|     nid = mac_mask_input_nid(nid);
 | |
| 
 | |
|     rf_vdev->rf_sync_nid = nid;
 | |
|     rf_vdev->rf_sync_nid_inited = true;
 | |
|     iot_printf("rf set sync nid=0x%x\n", nid);
 | |
| }
 | |
| 
 | |
| void mac_rf_vdev_reset_sync_nid(mac_rf_vdev_t *rf_vdev)
 | |
| {
 | |
|     if (rf_vdev == NULL) {
 | |
|         IOT_ASSERT(0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     rf_vdev->rf_sync_nid_inited = false;
 | |
|     rf_vdev->rf_sync_nid = PLC_NID_INVALID;
 | |
| }
 | |
| 
 | |
| tei_t mac_rf_vdev_get_sync_proxy(mac_rf_vdev_t *rf_vdev)
 | |
| {
 | |
|     IOT_ASSERT(rf_vdev);
 | |
|     return rf_vdev->rf_sync_proxy;
 | |
| }
 | |
| 
 | |
| void mac_rf_vdev_set_sync_proxy(mac_rf_vdev_t *rf_vdev, tei_t proxy)
 | |
| {
 | |
|     if (rf_vdev == NULL) {
 | |
|         IOT_ASSERT(0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     rf_vdev->rf_sync_proxy = proxy;
 | |
| }
 | |
| 
 | |
| mac_rf_vdev_t *get_rf_vdev_ptr(uint32_t plc_pdev_id, uint32_t rf_pdev_id,
 | |
|     uint32_t rf_vdev_id)
 | |
| {
 | |
|     if (plc_pdev_id >= MAX_PDEV_NUM || rf_vdev_id >= MAX_RF_VDEV_NUM ||
 | |
|         rf_pdev_id >= MAX_RF_PDEV_NUM) {
 | |
|         IOT_ASSERT(0);
 | |
|         return NULL;
 | |
|     }
 | |
|     mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(plc_pdev_id, rf_pdev_id);
 | |
|     if (!rf_pdev) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return rf_pdev->rf_vdev[rf_vdev_id];
 | |
| }
 | |
| 
 | |
| uint32_t mac_create_rf_vdev_internal(uint8_t plc_pdev_id, uint8_t plc_vdev_id,
 | |
|     uint8_t rf_pdev_id, uint8_t *rf_vdev_id_created)
 | |
| {
 | |
|     uint32_t cur_rf_vdev_num;
 | |
|     uint8_t rf_vdev_id = MAX_RF_VDEV_NUM;
 | |
|     mac_rf_vdev_t *rf_vdev;
 | |
|     mac_rf_pdev_t *rf_pdev;
 | |
| 
 | |
|     if (plc_pdev_id >= MAX_PDEV_NUM) {
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
|     rf_pdev = get_rf_pdev_ptr(plc_pdev_id, rf_pdev_id);
 | |
|     if (!rf_pdev) {
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
| 
 | |
|     cur_rf_vdev_num = rf_pdev->cur_rf_vdev_num;
 | |
|     IOT_ASSERT(cur_rf_vdev_num + 1 <= MAX_RF_VDEV_NUM);
 | |
| 
 | |
|     for (uint8_t i = 0; i < MAX_RF_VDEV_NUM; i++) {
 | |
|         if (rf_pdev->rf_vdev[i] == NULL) {
 | |
|             rf_vdev_id = i;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     IOT_ASSERT(rf_vdev_id < MAX_RF_VDEV_NUM);
 | |
| 
 | |
|     rf_vdev = iot_mem_pool_alloc(&rf_pdev->rf_vdev_pool);
 | |
|     if (rf_vdev == NULL) {
 | |
|         return ERR_NOMEM;
 | |
|     }
 | |
|     os_mem_set(rf_vdev, 0, sizeof(*rf_vdev));
 | |
|     rf_pdev->rf_vdev[rf_vdev_id] = rf_vdev;
 | |
|     rf_pdev->cur_rf_vdev_num++;
 | |
| 
 | |
|     rf_vdev->rf_vdev_id = (vdevid_t)rf_vdev_id;
 | |
|     rf_vdev->parent_vdev_id = (vdevid_t)plc_vdev_id;
 | |
|     rf_vdev->ref_pdev_id = rf_pdev_id;
 | |
|     rf_vdev->stop_flag = 1;
 | |
| 
 | |
|     *rf_vdev_id_created = rf_vdev_id;
 | |
| 
 | |
|     mac_rf_sched_init(rf_vdev);
 | |
| 
 | |
|     mac_rf_ppm_init(rf_vdev, phy_get_cal_ppm_in_pib() << PLC_NTB_PPM_SHIFT);
 | |
| 
 | |
|     rf_ra_init(rf_vdev, RATE_ADAPTION_ENABLE);
 | |
| 
 | |
|     if (rf_vdev_get_node_role(rf_vdev) != PLC_DEV_ROLE_CCO) {
 | |
|         /* channel init */
 | |
|         mac_rf_scan_init(rf_pdev);
 | |
|     }
 | |
| 
 | |
|     /* init rf power cap */
 | |
|     mac_rf_fix_power_init();
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint32_t mac_start_rf_vdev_internal(uint8_t plc_pdev_id, uint8_t rf_pdev_id,
 | |
|     uint8_t rf_vdev_id, mac_vdev_start_cfg_t *cfg)
 | |
| {
 | |
|     uint64_t start_ntb;
 | |
|     mac_rf_vdev_t *rf_vdev;
 | |
|     mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(plc_pdev_id, rf_pdev_id);
 | |
|     (void)rf_pdev;
 | |
| 
 | |
|     if (cfg == NULL) {
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
|     rf_vdev = get_rf_vdev_ptr(plc_pdev_id, rf_pdev_id, rf_vdev_id);
 | |
|     if (rf_vdev == NULL) {
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
| 
 | |
|     if (rf_vdev->stop_flag == 0) {
 | |
|         return ERR_OK;
 | |
|     }
 | |
| 
 | |
|     rf_vdev->rf_start_cfg.mac_bc_rx_func = cfg->mac_bc_rx_func;
 | |
|     rf_vdev->rf_start_cfg.mac_data_rx_func = cfg->mac_data_rx_func;
 | |
|     rf_vdev->rf_start_cfg.mac_bp_end_alert_func = cfg->mac_bp_end_alert_func;
 | |
| 
 | |
|     /* clear stop flag */
 | |
|     rf_vdev->stop_flag = 0;
 | |
| 
 | |
|     /* rf schedule stop */
 | |
|     mac_rf_sched_stop(rf_vdev);
 | |
| 
 | |
|     start_ntb = mac_rf_sched_get_ntb64(rf_vdev);
 | |
|     mac_rf_sched_set_csma_only(rf_vdev, start_ntb, 0);
 | |
| 
 | |
|     /* rf enable rx ring */
 | |
|     mac_rf_rx_all_ring_enable(rf_pdev);
 | |
| 
 | |
|     if (rf_vdev_get_node_role(rf_vdev) != PLC_DEV_ROLE_CCO) {
 | |
|         /* mac rf scan start */
 | |
|         mac_rf_scan_next_target((void *)rf_pdev);
 | |
|     }
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint32_t mac_stop_rf_vdev_internal(uint8_t plc_pdev_id, uint8_t rf_pdev_id,
 | |
|     uint8_t rf_vdev_id)
 | |
| {
 | |
|     mac_rf_vdev_t *rf_vdev =
 | |
|         get_rf_vdev_ptr(plc_pdev_id, rf_pdev_id, rf_vdev_id);
 | |
|     mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(plc_pdev_id, rf_pdev_id);
 | |
|     (void)rf_pdev;
 | |
| 
 | |
|     if (rf_vdev == NULL)
 | |
|         return ERR_INVAL;
 | |
| 
 | |
|     if (rf_vdev->stop_flag)
 | |
|         return ERR_OK;
 | |
| 
 | |
|     /* set stop flag */
 | |
|     rf_vdev->stop_flag = 1;
 | |
|     rf_vdev->tx_rx_suspend = 0;
 | |
| 
 | |
|     os_mem_set(&rf_vdev->rf_start_cfg, 0, sizeof(rf_vdev->rf_start_cfg));
 | |
| 
 | |
|     /* rf schedule stop */
 | |
|     mac_rf_sched_stop(rf_vdev);
 | |
| 
 | |
|     /* rf disable rx ring */
 | |
|     mac_rf_rx_all_ring_disable(rf_pdev);
 | |
| 
 | |
|     /* flush all tdma/csma queue */
 | |
|     mac_rf_tx_flush_all_queue(&rf_pdev->hwq_hdl);
 | |
| 
 | |
|     if (rf_vdev_get_node_role(rf_vdev) != PLC_DEV_ROLE_CCO) {
 | |
|         mac_rf_vdev_reset_sync_nid(rf_vdev);
 | |
|         /* stop the mac rf scan */
 | |
|         mac_rf_scan_stop();
 | |
|         /* set channel selected */
 | |
|         mac_rf_scan_set_channel_selected(0);
 | |
|         /* disable hplc rf async tx */
 | |
|         mac_rf_set_hplc_rf_async_tx(0);
 | |
|     }
 | |
| 
 | |
|     /* init rf power cap */
 | |
|     mac_rf_fix_power_init();
 | |
| 
 | |
|     mac_rf_ppm_init(rf_vdev, phy_get_cal_ppm_in_pib() << PLC_NTB_PPM_SHIFT);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| #endif /* HPLC_RF_DEV_SUPPORT */
 |