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

744 lines
27 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 "os_utils.h"
#include "os_mem_api.h"
#include "iot_config.h"
#include "mac_pdev.h"
#include "mpdu_frame.h"
#include "mpdu_header.h"
#include "iot_errno.h"
#include "iot_pkt.h"
#include "iot_io.h"
#include "iot_system.h"
#include "plc_protocol.h"
#include "mac_msg.h" /* for msg send */
#include "rx_desc_reg_api.h"
#include "mac_peer.h"
#include "mac_stream.h"
#include "mac_sched.h"
#include "mac_hplc_ext_api.h"
#include "mac_rx_hw.h"
#include "mac_cert_test.h"
#include "mac_check_spur_sta.h"
#include "mac_cmn_hw.h"
#include "mac_crc.h"
#if HPLC_RF_DEV_SUPPORT
#include "phy_bb.h"
#include "rf_hw_tonemap.h"
#include "mac_rf_rx_hw.h"
#include "mac_rf_rx_buf_ring.h"
#include "rf_rx_desc_reg_api.h"
#include "mac_rf_sched.h"
#include "phy_rf_chn.h"
#if (HW_PLATFORM == HW_PLATFORM_SIMU)
void mac_rf_rx_desc_plc_to_rf(iot_pkt_t *rx_pkt)
{
rf_rx_buf_hdr_t rf_desc = {0};
rx_buf_hdr_t *plc_desc;
plc_desc = (rx_buf_hdr_t *)iot_pkt_data(rx_pkt);
/* attention */
mac_rf_rx_att_set_rx_mpdu_done(&rf_desc.att,
mac_rx_att_get_rx_mpdu_done(&plc_desc->att));
/* mpdu start */
os_mem_cpy(mac_rf_rx_mpdu_st_get_phr_addr(&rf_desc.mpdu_st),
mac_rx_mpdu_st_get_fc_addr(&plc_desc->mpdu_st), FC_LEN);
mac_rf_rx_mpdu_st_set_avg_snr(&rf_desc.mpdu_st,
mac_rx_mpdu_st_get_avg_snr(&plc_desc->mpdu_st));
/* mpdu end */
mac_rf_rx_mpdu_end_set_ntb_timestamp(&rf_desc.mpdu_ed,
mac_rx_mpdu_end_get_ntb_timestamp(&plc_desc->mpdu_ed));
mac_rf_rx_mpdu_end_set_local_timestamp(&rf_desc.mpdu_ed,
mac_rx_mpdu_end_get_local_timestamp(&plc_desc->mpdu_ed));
/* pb start */
mac_rf_rx_pb_st_set_msdu_start(&rf_desc.pb_st,
mac_rx_pb_st_get_msdu_start(&plc_desc->pb_st));
mac_rf_rx_pb_st_set_msdu_end(&rf_desc.pb_st,
mac_rx_pb_st_get_msdu_end(&plc_desc->pb_st));
mac_rf_rx_pb_st_set_pb_ssn(&rf_desc.pb_st,
mac_rx_pb_st_get_ssn(&plc_desc->pb_st));
mac_rf_rx_pb_st_set_first_pb(&rf_desc.pb_st,
mac_rx_pb_st_get_first_pb(&plc_desc->pb_st));
mac_rf_rx_pb_st_set_last_pb(&rf_desc.pb_st,
mac_rx_pb_st_get_last_pb(&plc_desc->pb_st));
mac_rf_rx_pb_st_set_rx_pb_cnt(&rf_desc.pb_st,
mac_rx_att_get_pb_num(&plc_desc->att));
/* pb end */
mac_rf_rx_pb_end_set_rx_bcn_pld_crc_err(&rf_desc.pb_ed,
mac_rx_pb_end_get_rx_beacon_pld_crc_err(&plc_desc->pb_ed));
mac_rf_rx_pb_end_set_rx_pb_crc_err(&rf_desc.pb_ed,
mac_rx_pb_end_get_rx_pb_crc_err(&plc_desc->pb_ed));
mac_rf_rx_pb_end_set_pb_crc(&rf_desc.pb_ed,
mac_rx_pb_end_get_pb_crc(&plc_desc->pb_ed));
mac_rf_rx_pb_end_set_rx_pb_done(&rf_desc.pb_ed,
mac_rx_pb_end_get_rx_pb_done(&plc_desc->pb_ed));
os_mem_cpy(plc_desc, &rf_desc, sizeof(*plc_desc));
}
#endif
static int32_t mac_rf_cal_rf_64ppm(rf_rx_attention *att, int32_t ppm_hz)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
IOT_ASSERT(att);
int32_t freq = phy_rf_get_channel_freq_by_id(att->option, att->channel_id);
int64_t tmp = (int64_t)ppm_hz << (PPM_CALC_MILLION_SHIFT +
PLC_NTB_PPM_SHIFT);
return (int32_t)(tmp/freq);
#else
(void)att;
return ppm_hz;
#endif
}
uint32_t mac_rf_desc_get_pb_head_from_rx_pb_st(uint8_t proto,
void *pb_st)
{
uint32_t pb_header = 0;
IOT_ASSERT(pb_st);
#if SUPPORT_SMART_GRID
if (PLC_PROTO_TYPE_SG == proto) {
sg_sof_pb_hdr_t *sg_pb_head = (sg_sof_pb_hdr_t *)&pb_header;
sg_pb_head->mac_frame_start =
(uint8_t)mac_rf_rx_pb_st_get_msdu_start(pb_st);
sg_pb_head->mac_frame_end =
(uint8_t)mac_rf_rx_pb_st_get_msdu_end(pb_st);
sg_pb_head->seq = (uint8_t)mac_rf_rx_pb_st_get_pb_ssn(pb_st);
} else
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
if (PLC_PROTO_TYPE_SPG == proto) {
spg_sof_pb_hdr_t *spg_pb_head = (spg_sof_pb_hdr_t *)&pb_header;
spg_pb_head->seq = (uint16_t)mac_rf_rx_pb_st_get_pb_ssn(pb_st);
} else
#endif
{
//do not delete this case
}
return pb_header;
}
uint32_t mac_rf_rx_hw_mpdu_internal(void *pdev_in, uint32_t ring_id,
uint32_t quota_ms)
{
uint8_t delimiter_type = 0xFF;
uint8_t proto = (uint8_t)PHY_PROTO_TYPE_GET();
uint32_t is_retry_mpdu = 0;
uint32_t ret, cur_ts;
nid_t nid;
tei_t my_tei;
mac_vdev_t *plc_vdev;
mac_peer_t *peer;
mac_stream_t *stream;
mac_rf_pdev_t *rf_pdev;
mac_rf_vdev_t *rf_vdev;
iot_pkt_t *iot_pkt_array[1] = { 0 };
iot_pkt_t *cur_pkt_buf;
rx_buf_ring_t *ring;
mac_rx_info_t *rx_info;
rf_rx_attention *att;
rf_rx_mpdu_start *mpdu_st;
rf_rx_mpdu_end *mpdu_ed;
rf_rx_pb_start *pb_st;
rf_rx_pb_end *pb_ed;
uint8_t *payload;
rx_fc_msg_t rx_fc_msg = { 0 };
uint8_t is_vdev_found;
uint8_t is_not_my_ucast, is_hwcrc_err;
uint8_t *data;
uint32_t pbsz;
int8_t rssi;
int8_t snr;
int32_t ppm;
uint8_t cert_mode;
rf_pdev = (mac_rf_pdev_t*)pdev_in;
#if HW_PLATFORM == HW_PLATFORM_SIMU
ring = &rf_pdev->simu.rx_ring[ring_id];
#else
ring = &rf_pdev->ring_hdl.ring[ring_id];
#endif
cur_ts = os_boot_time32();
do {
/* check ring buffer is empty */
if (0 == rf_pop_buf_from_ring(ring, 1, iot_pkt_array)) {
break;
}
cur_pkt_buf = iot_pkt_array[0];
if (g_fw_mode != FTM_MODE && (rf_pdev->rf_vdev[0]->stop_flag ||
rf_pdev->rf_vdev[0]->tx_rx_suspend)) {
goto rf_free_pkt;
}
#if (HW_PLATFORM == HW_PLATFORM_SIMU)
mac_rf_rx_desc_plc_to_rf(cur_pkt_buf);
#endif
data = iot_pkt_data(cur_pkt_buf);
att = (rf_rx_attention *)(data + RF_RX_ATTENTION_OFFSET);
mpdu_st = (rf_rx_mpdu_start *)(data + RF_RX_MPDU_START_OFFSET);
mpdu_ed = (rf_rx_mpdu_end *)(data + RF_RX_MPDU_END_OFFSET);
pb_st = (rf_rx_pb_start *)(data + RF_RX_PB_START_OFFSET);
pb_ed = (rf_rx_pb_end *)(data + RF_RX_PB_END_OFFSET);
payload = data + RF_RX_PB_PAYLOAD_OFFSET;
if (!mac_rf_rx_pb_end_get_rx_pb_done(pb_ed)) {
iot_printf("-----RF: Not done PB!-----\n");
goto rf_free_pkt;
}
/* for sg rf protocol, 1mpdu contains 1pb */
if (!mac_rf_rx_att_get_rx_mpdu_done(att)) {
//TODO: add mpdu not done cnt
goto rf_free_pkt;
}
/* check rx exception */
if (mac_rf_rx_att_get_rx_status(att)) {
mac_rf_rx_debug_log_exception(iot_pkt_array[0]);
goto rf_free_pkt;
}
/* record ppm hz */
ppm = mac_rf_rx_mpdu_st_get_rx_ppmhz(mpdu_st);
/* record 1/64 ppm to mpdu */
mac_rf_rx_mpdu_st_set_rx_ppmhz(mpdu_st, mac_rf_cal_rf_64ppm(att, ppm));
//TODO: check ring overflow
/* process the pb if ring pb callback exist */
if (rf_pdev->ring_hdl.mpdu_pb_cb) {
ret = rf_pdev->ring_hdl.mpdu_pb_cb(rf_pdev, cur_pkt_buf);
if (CON_PKT_NOT_FREE == ret) {
/* cert mode loopback */
ring->cur_mpdu = NULL;
continue;
} else if(CON_PKT_FREE == ret) {
/* cert mode other test case */
goto rf_free_pkt;
} else if (CON_PKT_NOT_CARE == ret) {
/* continue rx path */
}
}
mac_rf_get_rx_frm_msg_from_fc(proto,
mac_rf_rx_mpdu_st_get_phr_addr(mpdu_st), &rx_fc_msg);
nid = mac_get_nid_from_fc(proto,
mac_rf_rx_mpdu_st_get_phr_addr(mpdu_st));
#if (ENA_RX_DIFF_NID_BCAST)
if ((FC_DELIM_SOF == delimiter_type)
&& (PLC_TEI_BCAST == rx_fc_msg.dst_tei)
&& !mac_get_cert_test_mode()) {
/* if bcast then force nid = local nid to rx in the
* same vdev.
*/
mac_vdev_t *dft_vdev = find_vdev_by_nid(PLC_PDEV_ID, nid);
if (NULL == dft_vdev) {
//TODO: maybe use reduced vdev
dft_vdev = get_vdev_ptr(PLC_PDEV_ID, PLC_PDEV_ID);
}
vdev_get_nid(dft_vdev, &nid);
}
#endif
/* sta spur check */
/* pb ok and fc valid */
if (pb_ed->rx_pb_crc_err == 0 &&
mac_rx_hw_check_fc_valid(
(uint32_t *)mac_rf_rx_mpdu_st_get_phr_addr(mpdu_st))) {
mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID);
/* sta check spur restart */
mac_sta_check_spur_timer_restart(
&pdev->mac_check_spur_ctxt, (nid == mac_get_hw_nid()));
}
delimiter_type = (uint8_t)mac_get_rx_delimiter_from_fc(proto,
mac_rf_rx_mpdu_st_get_phr_addr(mpdu_st));
/* get plc vdev by nid */
plc_vdev = find_vdev_by_nid(PLC_PDEV_ID, nid);
if (plc_vdev) {
rf_vdev = rf_pdev->rf_vdev[0];
} else {
rf_vdev = NULL;
}
peer = NULL;
stream = NULL;
is_vdev_found = 0;
is_not_my_ucast = 0;
is_hwcrc_err = 0;
cert_mode = mac_get_cert_test_mode();
if (plc_vdev &&
(mac_vdev_cfg_get_node_role(plc_vdev) != PLC_DEV_ROLE_CCO)) {
mac_rf_scan_update_rx_status(plc_vdev, &rf_pdev->rf_scan,
rx_fc_msg.nid, (uint8_t)att->channel_id);
}
switch (delimiter_type) {
case FC_DELIM_SOF:
{
pbsz = phy_rf_get_pbsz(rx_fc_msg.rf_pb_sz_idx);
if (!rf_vdev) {
/* vdev not found, drop this SOF by force crc error */
mac_rf_rx_pb_end_set_rx_pb_crc_err(pb_ed, 1);
goto rf_handle_sof;
} else {
is_vdev_found = 1;
}
if (mac_rf_rx_pb_st_get_pb_ssn(pb_st) != 0 ||
mac_rf_rx_pb_st_get_msdu_start(pb_st) != 1 ||
mac_rf_rx_pb_st_get_msdu_end(pb_st) != 1) {
mac_rf_rx_pb_end_set_rx_pb_crc_err(pb_ed, 1);
goto rf_handle_sof;
}
/* fix spg msdu_start/msdu_end */
if (PLC_PROTO_TYPE_SPG == proto) {
/**
* sof msdu_start and msdu_end
* fields always 0 in SPG protocol
*/
if (0 == mac_rf_rx_pb_st_get_pb_ssn(pb_st)) {
mac_rf_rx_pb_st_set_msdu_start(pb_st, 1);
}
/* spg must be used long mpdu tx */
if (mac_rf_rx_pb_st_get_last_pb(pb_st) &&
(mac_rf_rx_pb_st_get_rx_pb_cnt(pb_st) ==
(mac_rf_rx_pb_st_get_pb_ssn(pb_st) + 1))){
mac_rf_rx_pb_st_set_msdu_end(pb_st, 1);
}
}
/* find peer information */
if (rx_fc_msg.dst_tei != PLC_TEI_BCAST) {
my_tei = vdev_get_tei(plc_vdev);
/* check unicast is dircet self */
if (rx_fc_msg.dst_tei != my_tei) {
if (mac_rf_rx_pb_end_get_rx_pb_crc_err(pb_ed)) {
/* if pb error, not check and handle sof */
goto rf_handle_sof;
}
uint8_t is_drop_chk = 0;
/* for cco, if the networking is not started
* (nid is not set), try to receive all unicast packets
*/
if (mac_vdev_cfg_get_node_role(plc_vdev)
== PLC_DEV_ROLE_CCO) {
nid_t tmp_nid;
if (ERR_OK == vdev_get_nid(plc_vdev, &tmp_nid)) {
is_drop_chk = 1;
}
} else {
is_drop_chk = (PLC_PROTO_TYPE_SPG == proto) ?
(vdev_get_tei(plc_vdev) != 0) : 1;
}
/* check mac header dtei */
if (is_drop_chk) {
if (mac_msdu_is_std_mac_header(payload)) {
tei_t mac_hd_dtei =
((mac_header_t *)payload)->org_dest_tei;
if ((mac_hd_dtei != PLC_TEI_INVAL)
&& (mac_hd_dtei != my_tei)) {
/* set pb error force drop this pb */
mac_rf_rx_pb_end_set_rx_pb_crc_err(pb_ed, 1);
is_not_my_ucast = 1;
goto rf_handle_sof;
}
} else {
/* for mac_short_header, not contain the dtei,
* need drop it.
*/
mac_rf_rx_pb_end_set_rx_pb_crc_err(pb_ed, 1);
is_not_my_ucast = 1;
goto rf_handle_sof;
}
}
}
peer = find_peer(plc_vdev, nid, (tei_t)rx_fc_msg.src_tei);
} else {
/* for bacast */
peer = plc_vdev->bcast_peer;
}
mac_rf_rx_debug_log_sof_info(rx_fc_msg, mpdu_st, mpdu_ed,
pb_st, pb_ed, att);
#if ENA_SW_PBCRC_CHECK
if (mac_rf_rx_pb_end_get_rx_pb_crc_err(pb_ed) == 0) {
uint32_t pb_head =
mac_rf_desc_get_pb_head_from_rx_pb_st(proto, pb_st);
uint32_t crc_cal;
crc_cal = mac_crc_get_pb_swcrc(proto, &pb_head,
payload, pbsz, FC_DELIM_SOF);
if (crc_cal != mac_rf_rx_pb_end_get_pb_crc(pb_ed)) {
iot_printf("crccal:0x%x, getcrc:0x%x\n", crc_cal,
mac_rf_rx_pb_end_get_pb_crc(pb_ed));
pb_ed->rx_pb_crc_err = 1;
is_hwcrc_err = 1;
goto rf_handle_sof;
}
}
#endif
if (!peer) {
/* if the peer is not exist, create it right now */
ret = mac_peer_alloc(plc_vdev, (tei_t)rx_fc_msg.src_tei,
0, 1, 0, 0, &peer);
if (ret) {
/* create peer failed */
IOT_ASSERT(0);
}
}
/* find stream information */
stream = find_stream(peer, nid, (tei_t)rx_fc_msg.src_tei,
(lid_t)rx_fc_msg.lid, IS_RX_STREAM, IS_RF_STREAM);
if (!stream) {
/* if stream is not found create it now */
ret = mac_stream_alloc(peer, IS_RX_STREAM, (lid_t)rx_fc_msg.lid,
IS_RF_STREAM, &stream);
if ((ret != ERR_OK) && (ret != ERR_EXIST)) {
/* create stream failed */
IOT_ASSERT(0);
}
}
is_retry_mpdu = rx_fc_msg.retry;
rf_handle_sof:
if (mac_rf_rx_pb_end_get_rx_pb_crc_err(pb_ed)) {
ppm = mac_rf_rx_mpdu_st_get_rx_ppmhz(mpdu_st);
iot_printf("rf sof pb dropped: is_hwcrc_err:%d, "
"not_my_ucast:%d, vdev_found:%d,"
"phrmcs:%d, pldmcs:%d, pbidx:%d, "
"dtei:%d, stei:%d, nid:0x%x, snr:%d, rssi:%d, "
"hwppm:%d - %d\n",
is_hwcrc_err, is_not_my_ucast, is_vdev_found,
att->phr_mcs, att->pld_mcs, pb_st->pb_sz_idx,
rx_fc_msg.dst_tei, rx_fc_msg.src_tei,
rx_fc_msg.nid, mpdu_st->avg_snr, mpdu_st->rssi,
/* 1/64 ppm */
ppm,
/* ppm */
ppm >> PLC_NTB_PPM_SHIFT
);
goto rf_free_pkt;
} else {
reorder_buf_insert(&stream->msdu.rx.reorder_buf,
cur_pkt_buf,
mac_rf_rx_pb_st_get_pb_ssn(pb_st),
mac_rf_rx_pb_st_get_msdu_start(pb_st),
mac_rf_rx_pb_st_get_msdu_end(pb_st),
is_retry_mpdu,
pbsz
);
}
break;
}
case FC_DELIM_BEACON:
{
uint32_t local_ts = mac_rf_rx_mpdu_end_get_local_timestamp(mpdu_ed);
uint32_t ntb_ts = mac_rf_rx_mpdu_end_get_ntb_timestamp(mpdu_ed);
snr = mac_rf_rx_mpdu_st_get_avg_snr(mpdu_st);
uint8_t is_chk_bcn_ppm = 1;
uint8_t is_self_nid = 0;
mac_rf_rx_debug_log_bcn_info(&rx_fc_msg, mpdu_st, mpdu_ed, pb_ed);
if (!mac_rx_hw_check_fc_valid(
(uint32_t *)mac_rf_rx_mpdu_st_get_phr_addr(mpdu_st))) {
goto rf_free_pkt;
}
if (!plc_vdev) {
/* force first vdev, and upload all bcn */
plc_vdev = get_vdev_ptr(PLC_PDEV_ID, PLC_PDEV_ID);
rf_vdev = rf_pdev->rf_vdev[0];
}
if ((nid != PLC_NID_INVALID) && (rf_vdev_get_node_role(rf_vdev)
== PLC_DEV_ROLE_STA)) {
/* if STA mode we need to sync the crystal disparity */
nid_t sync_nid;
tei_t sync_proxy = mac_rf_vdev_get_sync_proxy(rf_vdev);
nid_t my_nid;
tei_t my_proxy = vdev_get_proxy_tei(plc_vdev);
mac_rf_vdev_get_sync_nid(rf_vdev, &sync_nid);
vdev_get_nid(plc_vdev, &my_nid);
if (my_nid == PLC_NID_INVALID && sync_nid == PLC_NID_INVALID) {
/* for sync nid not set case set first seen nid to
* be sync. Because at some large ppm case, the BCN
* PLD always CRC error and CVG can't decide which
* one to join, if CVG find this one is the correct
* one, CVG should notify mac the preferred the nid
* through PLC_VDEV_CFG_SET_PREFER_NID.
*/
if (nid != PLC_NID_INVALID && !vdev_is_bl_nid(plc_vdev, nid)
&& rx_fc_msg.src_tei != PLC_TEI_INVAL) {
mac_rf_vdev_set_sync_nid(rf_vdev, nid);
mac_rf_vdev_set_sync_proxy(rf_vdev,
(tei_t)rx_fc_msg.src_tei);
}
}
/* get rf ppm from wphy interface */
int16_t rfppm = (int16_t)mac_rf_rx_mpdu_st_get_rx_ppmhz(mpdu_st);
if (my_nid == nid) {
/* sync with joined network if available */
if (rx_fc_msg.src_tei == my_proxy) {
int16_t ppm_err = PLC_MAX_MAC_NTB_PPM;
mac_rf_ntb_ppm_sync(rf_vdev,
rx_fc_msg.time_stamp, local_ts, ntb_ts,
vdev_get_bc_period_ms(plc_vdev, proto),
&ppm_err, rfppm);
(void)ppm_err;
is_chk_bcn_ppm = 0;
}
is_self_nid = 1;
} else if (nid == sync_nid) {
/* sync with target nid */
if (rx_fc_msg.src_tei == sync_proxy) {
int16_t ppm_err = PLC_MAX_MAC_NTB_PPM;
/* if sta's nid is current syncing nid, and
* proxy and phase is match or is not assoc,
* just sync the crystal's freq disparity btw
* the nodes and the self node, we assume all
* the nodes in the network are all synced
*/
/* we are focus on the
* network, so we use SW calculation
* which is more accurate
*/
mac_rf_ntb_ppm_sync(rf_vdev,
rx_fc_msg.time_stamp, local_ts, ntb_ts,
vdev_get_bc_period_ms(plc_vdev, proto),
&ppm_err, rfppm);
(void)ppm_err;
}
}
}
//TODO: add sta sync the crystal disparity code
if (mac_rf_rx_pb_end_get_rx_pb_crc_err(pb_ed)) {
//TODO: add rx bcn pb error cnt
if (rx_fc_msg.src_tei == PLC_TEI_CCO) {
mac_sched_cco_snr_rx(plc_vdev, nid, snr,
(uint8_t)mac_rf_rx_att_get_channel_id(att),
(uint8_t)mac_rf_rx_att_get_option(att), 1,
BEACON_FREQ_BAND_ID_INVALID);
}
/* free the error pb */
goto rf_free_pkt;
}
pbsz = phy_rf_get_pbsz(rx_fc_msg.rf_pb_sz_idx);
if (rf_vdev->rf_start_cfg.mac_bc_rx_func) {
BUILD_BUG_ON(sizeof(mac_rx_info_t) < (RF_RX_PB_PAYLOAD_OFFSET
- sizeof(*att) - FC_LEN));
rx_info = (mac_rx_info_t *)iot_pkt_pull(cur_pkt_buf,
RF_RX_PB_PAYLOAD_OFFSET - sizeof(*rx_info));
uint8_t *bcn_pld = iot_pkt_pull(cur_pkt_buf, sizeof(*rx_info));
if (NULL == iot_pkt_set_tail(cur_pkt_buf, bcn_pld + pbsz)) {
IOT_ASSERT_DUMP(0, (uint32_t *)cur_pkt_buf, 17);
goto rf_free_pkt;
}
/* todo: mac_convert_fc_rf_to_hplc() */
os_mem_cpy(rx_info->fc, mac_rf_rx_mpdu_st_get_phr_addr(mpdu_st),
FC_LEN);
rssi = mac_rf_rx_mpdu_st_get_rssi(mpdu_st);
if (rssi != INV_RSSI_RF) {
rssi = min(MAX_RSSI_RF, rssi);
rssi = max(MIN_RSSI_RF, rssi);
}
rx_info->delta_ntb = rx_fc_msg.time_stamp
- mac_rf_rx_mpdu_end_get_ntb_timestamp(mpdu_ed);
rx_info->phy.is_rf = 1;
rx_info->phy.band_id = BEACON_FREQ_BAND_ID_INVALID;
rx_info->phy.channel_id = (uint8_t)att->channel_id;
rx_info->phy.rf_option = (uint8_t)att->option;
rx_info->phy.phase = PLC_PHASE_ALL;
rx_info->phy.snr = snr;
rx_info->phy.rssi = rssi;
if ((mac_vdev_cfg_get_node_role(plc_vdev) != PLC_DEV_ROLE_CCO)
&& !cert_mode && is_self_nid) {
if (is_chk_bcn_ppm && plc_vdev->bcn_ctx.sta.ntb_sync_done) {
int16_t tmp_ppm;
mac_ntb_record_ctxt_t tmp_ntb_record;
os_mem_cpy(&tmp_ntb_record, &rf_vdev->sync_ntb_record,
sizeof(tmp_ntb_record));
tmp_ppm = mac_ppm_cal(&tmp_ntb_record,
rx_fc_msg.time_stamp, local_ts, ntb_ts, 1);
if (IOT_ABS(tmp_ppm) > RF_SYNC_NTB_MAX_PPM) {
rx_info->delta_ntb = 0;
} else {
os_mem_cpy(&rf_vdev->sync_ntb_record,
&tmp_ntb_record, sizeof(tmp_ntb_record));
}
} else {
os_mem_cpy(&rf_vdev->sync_ntb_record,
&rf_vdev->mac_rf_ppm,
sizeof(rf_vdev->sync_ntb_record));
}
}
mac_beacon_rx((uint8_t)proto, plc_vdev, cur_pkt_buf);
//TODO: add rx bcn ok cnt
} else {
goto rf_free_pkt;
}
break;
}
case FC_DELIM_SACK:
{
//TODO: later will handle rf ckq rx
//if ((rx_fc_msg.sack_ext_deli == SACK_EXT_TYPE_SYNC) ||
// (rx_fc_msg.sack_ext_deli == SACK_EXT_TYPE_SEARCH)) {
// mac_ckq_rx_and_ppm_sync(pdev, vdev, &rx_fc_msg,
// iot_pkt_array[0]);
// goto rf_free_pkt;
//} else
/* todo: mac_convert_fc_rf_to_hplc() */
{
if (!rf_vdev) {
/* vdev not found, drop this SACK
*/
goto rf_free_pkt;
}
if (rx_fc_msg.dst_tei != vdev_get_tei(plc_vdev)) {
/* if not dest for me, drop it */
goto rf_free_pkt;
}
peer = find_peer(plc_vdev, nid, (tei_t)rx_fc_msg.src_tei);
if (!peer) {
/* if the peer is not exist,
* create it right now
*/
ret = mac_peer_alloc(plc_vdev, (tei_t)rx_fc_msg.src_tei,
0, 1, 0, 0, &peer);
if (ret) {
/* create peer failed */
IOT_ASSERT(0);
}
}
/* update the rate info in peer */
if (rf_vdev->ra_cb) {
rf_vdev->ra_cb(peer, &rx_fc_msg);
}
/* TODO: confirm should free temp peer or not */
mac_peer_del_temp_peer(peer);
goto rf_free_pkt;
}
break;
}
default:
{
iot_printf("-----RF: Unknown MPDU-----\n");
goto rf_free_pkt;
}
}
continue;
rf_free_pkt:
iot_pkt_free(cur_pkt_buf);
} while ((uint32_t)(os_boot_time32() - cur_ts) < quota_ms);
return 0;
}
uint32_t mac_rf_rx_hw_mpdu(void *pdev, uint32_t ring_id, uint32_t quota_ms)
{
uint32_t ret = ERR_OK;
rx_buf_ring_t *ring; //TODO: fix to rf ring buffer context
#if HW_PLATFORM == HW_PLATFORM_SIMU
ring = &((mac_rf_pdev_t*)pdev)->simu.rx_ring[ring_id];
#else
ring = &((mac_rf_pdev_t*)pdev)->ring_hdl.ring[ring_id];
#endif
if (!ring->msg_delivered) {
/* if not delivered, queue the msg */
mac_msg_t *msg = mac_alloc_msg();
if (msg == NULL) {
IOT_ASSERT(0);
ret = ERR_NOMEM;
goto out;
}
msg->type = MAC_MSG_TYPE_DSR;
msg->id = MAC_MSG_ID_DSR_RX_TO_MSG;
/* bit0~bit15: ring id.
* bit16: indicate ring type. 0 - plc ring, 1 - rf ring.
*/
msg->data1 = (1 << 16) | (ring_id & 0xFFFF);
msg->data2 = pdev;
msg->data3 = (void*)quota_ms;
mac_queue_msg(msg, MAC_MSG_QUEUE_MP);
/* TODO: this is assume in the same task of MAC */
ring->msg_delivered = 1;
}
out:
return ret;
}
#else
uint32_t mac_rf_rx_hw_mpdu_internal(void *pdev_in, uint32_t ring_id,
uint32_t quota_ms)
{
(void)pdev_in;
(void)ring_id;
(void)quota_ms;
return 0;
}
#endif /* HPLC_RF_DEV_SUPPORT */