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