279 lines
8.4 KiB
C
279 lines
8.4 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 "beacon_frame.h"
|
||
|
#include "beacon.h"
|
||
|
#include "iot_errno.h"
|
||
|
#include "iot_io.h"
|
||
|
#include "mac_bcm_api.h"
|
||
|
#include "mpdu_frame.h"
|
||
|
#include "mac_tx_hw.h"
|
||
|
#include "mac_data_api.h"
|
||
|
#include "iot_pkt_api.h"
|
||
|
#include "mac_data.h"
|
||
|
#include "os_mem.h"
|
||
|
#include "mac_desc_engine.h"
|
||
|
#include "plc_mac_header.h"
|
||
|
#include "iot_crc.h"
|
||
|
#include "iot_utils.h"
|
||
|
#include "mac_msg.h"
|
||
|
#include "mac.h"
|
||
|
#include "mac_crc.h"
|
||
|
#include "iot_bitops.h"
|
||
|
#include "mac_peer.h"
|
||
|
#include "hw_desc.h"
|
||
|
#include "mac_stream.h"
|
||
|
#include "phy_bb.h"
|
||
|
#include "plc_mac_cfg.h"
|
||
|
#include "plc_utils.h"
|
||
|
|
||
|
#include "mac_pdev.h"
|
||
|
#include "mac_rf_pdev.h"
|
||
|
#include "mac_rf_vdev.h"
|
||
|
#include "sw_sched.h"
|
||
|
#include "mac_crypto.h"
|
||
|
|
||
|
#if HPLC_RF_DEV_SUPPORT
|
||
|
|
||
|
static uint32_t mac_check_rf_msdu_len(uint8_t proto, iot_pkt_t *msdu_buf)
|
||
|
{
|
||
|
uint32_t len = 0;
|
||
|
|
||
|
switch (proto)
|
||
|
{
|
||
|
#if SUPPORT_SMART_GRID
|
||
|
case PLC_PROTO_TYPE_SG:
|
||
|
{
|
||
|
len = sizeof(sg_sof_pb_520_t) - SG_SOF_PB_HDR_CRC_LEN -
|
||
|
SG_MAC_MSDU_CRC_LEN;
|
||
|
break;
|
||
|
}
|
||
|
#endif
|
||
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
||
|
case PLC_PROTO_TYPE_SPG:
|
||
|
{
|
||
|
len = sizeof(spg_sof_pb_520_t) - SPG_SOF_PB_HDR_CRC_LEN -
|
||
|
SPG_MAC_MSDU_CRC_LEN;
|
||
|
break;
|
||
|
}
|
||
|
#endif
|
||
|
#if SUPPORT_GREEN_PHY
|
||
|
case PLC_PROTO_TYPE_GP:
|
||
|
{
|
||
|
len = sizeof(gp_sof_pb_520_t) - GP_SOF_PB_HDR_CRC_LEN -
|
||
|
GP_MAC_MSDU_CRC_LEN;
|
||
|
break;
|
||
|
}
|
||
|
#endif
|
||
|
default:
|
||
|
IOT_ASSERT(0);
|
||
|
}
|
||
|
|
||
|
/* rf mpdu frame only support 1pb of 520 bytes */
|
||
|
if (iot_pkt_data_len(msdu_buf) > len) {
|
||
|
return ERR_FAIL;
|
||
|
}
|
||
|
|
||
|
return ERR_OK;
|
||
|
}
|
||
|
|
||
|
uint32_t mac_send_rf_msdu_ex_internal(pdevid_t pdev_id, vdevid_t vdev_id,
|
||
|
iot_pkt_t* msdu_buf, mac_tx_info *tx_info)
|
||
|
{
|
||
|
uint32_t ret = ERR_OK;
|
||
|
mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(pdev_id, RF_PDEV_ID);
|
||
|
if (!rf_pdev) {
|
||
|
return ERR_NOSUPP;
|
||
|
}
|
||
|
mac_vdev_t *vdev = NULL;
|
||
|
lid_t lid = tx_info->link_id;
|
||
|
uint8_t stream_trxn = IS_TX_STREAM;
|
||
|
#if PLC_SUPPORT_DBG_PKT_MODE
|
||
|
/* check meter dbg mode parameter valid */
|
||
|
if (tx_info->is_dbg_pkt) {
|
||
|
//check link id
|
||
|
if (lid > (lid_t)LID_CSMA_CAP3) {
|
||
|
lid = (lid_t)PLC_DBG_PKT_MODE_DEF_LID;
|
||
|
}
|
||
|
stream_trxn = IS_DBG_TX_STREAM;
|
||
|
/* fix debug pkt mode vdev id */
|
||
|
mac_pdev_t *pdev = get_pdev_ptr(pdev_id);
|
||
|
vdev_id = (vdevid_t)pdev->dbg_pkt_vdev_id;
|
||
|
IOT_ASSERT(vdev_id != (vdevid_t)PLC_INV_DBG_PKT_MODE_VDEV_ID);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
vdev = get_vdev_ptr(pdev_id, vdev_id);
|
||
|
mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(pdev_id,
|
||
|
RF_PDEV_ID, vdev->rf_vdev_id);
|
||
|
uint8_t *data = iot_pkt_data(msdu_buf);
|
||
|
uint8_t proto = (uint8_t)PHY_PROTO_TYPE_GET();
|
||
|
uint8_t retry_cnt = 0;
|
||
|
mac_peer_t *peer = NULL;
|
||
|
mac_stream_t *stream = NULL;
|
||
|
mac_msdu_frame_t *mac_frame = NULL;
|
||
|
#if ENA_RF_CSMA_BCN_HWQ
|
||
|
if (rf_vdev_get_node_role(rf_vdev) != PLC_DEV_ROLE_CCO) {
|
||
|
/* lid 3 to csma beacon */
|
||
|
if (lid == LID_CSMA_CAP3) {
|
||
|
lid = LID_CSMA_CAP2;
|
||
|
} else if (lid == LID_CSMA_CAP2) {
|
||
|
lid = LID_CSMA_CAP1;
|
||
|
} else if (lid == LID_CSMA_CAP1) {
|
||
|
lid = LID_CSMA_CAP0;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
uint32_t bcn_region_type = mac_get_bcn_region_type(lid);
|
||
|
mac_rf_queue_t swq_id;
|
||
|
uint32_t vdev_nid;
|
||
|
tei_t dtei = tx_info->receiver;
|
||
|
|
||
|
if (!vdev || !rf_vdev) {
|
||
|
return ERR_NOSUPP;
|
||
|
}
|
||
|
|
||
|
if (!vdev->is_up || vdev->stop_flag || rf_vdev->stop_flag) {
|
||
|
iot_printf("plc vdev %d or rf vdev %d not ready\n",
|
||
|
vdev_id, vdev->rf_vdev_id);
|
||
|
return ERR_NOT_READY;
|
||
|
}
|
||
|
|
||
|
if (rf_vdev->tx_rx_suspend) {
|
||
|
return ERR_FAIL;
|
||
|
}
|
||
|
|
||
|
if (mac_check_rf_msdu_len(proto, msdu_buf)) {
|
||
|
iot_printf("warning:rf msdu len = %lu exceed!\n",
|
||
|
iot_pkt_data_len(msdu_buf));
|
||
|
return ERR_FAIL;
|
||
|
}
|
||
|
|
||
|
/* check if has token for current sending */
|
||
|
if (ERR_NOMEM == mac_token_check(bcn_region_type, lid, 1)) {
|
||
|
iot_printf("warning:rf no msdu for send,lid=%d\n", lid);
|
||
|
/* TODO: add flash log and add no msdu send count */
|
||
|
return ERR_NOMEM;
|
||
|
}
|
||
|
|
||
|
if (ERR_OK != vdev_get_nid(vdev, (nid_t *)&vdev_nid)) {
|
||
|
iot_printf("warning:not nid for send,vid:%d,reduced:%d\r\n",\
|
||
|
vdev->vdev_id, vdev->mac_vdev_cfg.is_reduced_vdev);
|
||
|
return ERR_FAIL;
|
||
|
}
|
||
|
|
||
|
/* put crc len */
|
||
|
iot_pkt_put(msdu_buf, sizeof(uint32_t));
|
||
|
|
||
|
if (tx_info->is_encrypt) {
|
||
|
if (mac_crypto_check_msdu_buf(vdev, &msdu_buf, proto) != ERR_OK) {
|
||
|
tx_info->is_encrypt = 0;
|
||
|
IOT_ASSERT(ERR_OK == mac_crc_set_msdu_swcrc(proto, msdu_buf));
|
||
|
}
|
||
|
} else {
|
||
|
IOT_ASSERT(ERR_OK == mac_crc_set_msdu_swcrc(proto, msdu_buf));
|
||
|
}
|
||
|
|
||
|
retry_cnt = mac_msdu_retry_cnt_get(proto, data);
|
||
|
if (retry_cnt == 0)
|
||
|
{
|
||
|
/* if mac header retry cnt = 0
|
||
|
* use retry cnt in tx_info
|
||
|
*/
|
||
|
retry_cnt = (uint8_t)tx_info->retry_cnt;
|
||
|
if (retry_cnt == 0)
|
||
|
{
|
||
|
/* if tx_info retry cnt also = 0
|
||
|
* use retry cnt default value
|
||
|
*/
|
||
|
if (dtei != PLC_TEI_BCAST) {
|
||
|
retry_cnt = MAC_RF_DEF_RETRY_CNT;
|
||
|
} else {
|
||
|
retry_cnt = MAC_RF_BCAST_DEF_RETRY_CNT;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dtei != PLC_TEI_BCAST) {
|
||
|
retry_cnt = retry_cnt > MAC_RF_UCAST_MAX_RETRY_CNT ? \
|
||
|
MAC_RF_UCAST_MAX_RETRY_CNT : retry_cnt;
|
||
|
} else {
|
||
|
retry_cnt = retry_cnt > MAC_RF_BCAST_MAX_RETRY_CNT ? \
|
||
|
MAC_RF_BCAST_MAX_RETRY_CNT : retry_cnt;
|
||
|
}
|
||
|
|
||
|
if (dtei == PLC_TEI_BCAST) {
|
||
|
/* broadcast address return bcast peer */
|
||
|
peer = (mac_peer_t*)vdev->bcast_peer;
|
||
|
/* must be a bcast flag */
|
||
|
IOT_ASSERT(tx_info->bcast);
|
||
|
} else {
|
||
|
peer = find_peer(vdev, vdev_nid, dtei);
|
||
|
}
|
||
|
if (!peer) {
|
||
|
/* if the peer is not exist, create it right now */
|
||
|
ret = mac_peer_alloc(vdev, dtei, 0, 1, 0, 0, &peer);
|
||
|
if (ret) {
|
||
|
/* create peer failed */
|
||
|
IOT_ASSERT(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
stream = find_stream(peer, vdev_nid, dtei, lid, stream_trxn, IS_RF_STREAM);
|
||
|
if (!stream) {
|
||
|
/* if stream is not found create it now */
|
||
|
ret = mac_stream_alloc(peer, stream_trxn, lid, IS_RF_STREAM, &stream);
|
||
|
if (ret != ERR_OK && ret != ERR_EXIST) {
|
||
|
/* create stream failed */
|
||
|
IOT_ASSERT(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mac_desc_get(&g_mac_desc_eng, PLC_MAC_MSDU_FRAME_POOL, (void **)&mac_frame);
|
||
|
IOT_ASSERT(mac_frame);
|
||
|
mac_frame_list_init(mac_frame, msdu_buf, tx_info->bcast,
|
||
|
tx_info->phase, 0, retry_cnt, tx_info->is_dbg_pkt,
|
||
|
tx_info->tx_3_phase, !tx_info->same_vendor, tx_info->ppm_step,
|
||
|
tx_info->ppm_step_type);
|
||
|
mac_frame->need_encrypt = tx_info->is_encrypt;
|
||
|
mac_frame->key_idx = (uint8_t)tx_info->key_idx;
|
||
|
if (!stream->msdu.tx.mac_frame_list) {
|
||
|
stream->msdu.tx.mac_frame_list = mac_frame;
|
||
|
stream->msdu.tx.last_mac_frame = mac_frame;
|
||
|
stream->msdu.tx.mac_frame_num = 1;
|
||
|
} else {
|
||
|
/* TODO: put it at the end of list */
|
||
|
stream->msdu.tx.last_mac_frame->next = mac_frame;
|
||
|
stream->msdu.tx.last_mac_frame = mac_frame;
|
||
|
stream->msdu.tx.mac_frame_num++;
|
||
|
}
|
||
|
|
||
|
/* check if need to decrease token number */
|
||
|
mac_token_alloc(bcn_region_type, lid, 1);
|
||
|
|
||
|
swq_id = mac_rf_q_get_swq_type(bcn_region_type, lid, tx_info->is_dbg_pkt);
|
||
|
/* check if swq type is support */
|
||
|
if (swq_id == MAX_MAC_RF_QUE_NUM) {
|
||
|
/* swq type error */
|
||
|
IOT_ASSERT(0);
|
||
|
}
|
||
|
mac_swsch_append(mac_swsch_get_g_swq(swq_id, 1), PLC_PHASE_A, stream);
|
||
|
|
||
|
return mac_rf_swsch_trigger_tx(RF_PDEV_ID, rf_vdev->rf_vdev_id);
|
||
|
}
|
||
|
|
||
|
#endif /* HPLC_RF_DEV_SUPPORT */
|
||
|
|