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 */
 |