Files
kunlun/plc/halmac/vdev/mac_rf_vdev.c
2024-09-28 14:24:04 +08:00

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