/**************************************************************************** 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 "iot_io.h" #include "mac_vdev.h" #include "mac_pdev.h" #include "iot_utils_api.h" #include "mac_tx_hw.h" #include "tx_desc_reg_api.h" #include "phy_chn.h" #include "mac_hplc_ext.h" #include "mac_desc_engine.h" #include "mac_rx_hw.h" #include "plc_mpdu_header.h" #include "mac_hplc_ext_api.h" #include "mac_task.h" uint32_t mac_send_ext_frame_internal(uint8_t ext_type, pdevid_t pdev_id, vdevid_t vdev_id, mac_tx_info *tx_info, uint8_t *addr, uint8_t sn) { #if PLC_MAC_TX_DEBUG_LOG iot_printf("%s\n", __FUNCTION__); #endif tx_mpdu_end *mpdu_end; tx_mpdu_start *mpdu; mac_queue_t swq_id; uint32_t hwqid; nid_t nid; uint32_t proto = PHY_PROTO_TYPE_GET(); void *fc; mac_pdev_t *pdev = g_mac_pdev[pdev_id]; mac_vdev_t *vdev = get_vdev_ptr(pdev_id, vdev_id); mac_desc_get(&g_mac_desc_eng, PLC_TX_MPDU_END_POOL, (void **)&mpdu_end); mac_desc_get(&g_mac_desc_eng, PLC_TX_MPDU_START_POOL, (void **)&mpdu); if (!(mpdu && mpdu_end)) { IOT_ASSERT(0); return ERR_NOMEM; } /* get nid */ vdev_get_nid(vdev, &nid); /* get swq type id */ if (!vdev_get_block_dbg_pkt_4_rx_only(vdev) && tx_info->is_dbg_pkt) { tx_info->link_id += LID_BCSMA_START; } swq_id = mac_q_get_swqid_from_phase_lid(&pdev->hwq_hdl, \ tx_info->phase, tx_info->link_id); /* check if the hwq already enabled */ hwqid = mac_q_create_hwqid_from_swqid(&pdev->hwq_hdl, swq_id); IOT_ASSERT(hwqid != INV_MAC_HWQ_ID); mac_tx_mpdu_fill_macinfo(mpdu, swq_id, 0, \ 0, 0, 0, 0, 0, 0, 0,\ 0, 0, mpdu_end, NULL, NULL, \ 0, 0, 0, 0, 0, 0, 0); mac_tx_mpdu_fill_phyinfo(\ mpdu, HW_DESC_TX_PORT_PLC, 128, tx_info->phase, \ phy_def_hw_band_id_get(), 0, 0, 0, 0); /* fill fc info */ fc = mac_tx_mpdu_start_get_fc_ptr(mpdu); mac_tx_mpdu_fill_proto(mpdu, PLC_PROTO_TYPE_RAWDATA); mac_tx_fill_extsackinfo(proto, fc, FC_DELIM_SACK, nid, ext_type, \ addr, vdev_get_tei(vdev), sn); return mac_tx_hw_mpdu(&pdev->hwq_hdl, \ hwqid, mpdu); } uint32_t mac_send_ext_frame(uint8_t ext_type, pdevid_t pdev_id, vdevid_t vdev_id, mac_tx_info *tx_info, uint8_t *addr, uint8_t sn) { uint32_t ret = 0; mac_msg_t *msg = mac_alloc_msg(); if (msg == NULL) { IOT_ASSERT(0); ret = ERR_NOMEM; goto out; } msg->type = MAC_MSG_TYPE_CVG; msg->id = MAC_MSG_ID_CVG_EXT_FRAME_SEND; msg->data1 = (((uint32_t)pdev_id) << 24) | (((uint32_t)sn) << 16) | \ (((uint32_t)vdev_id) << 8) | ext_type; msg->data2 = tx_info; msg->data3 = addr; mac_queue_msg(msg, MAC_MSG_QUEUE_HP); out: return ret; } uint32_t static mac_rx_ext_frame(mac_vdev_t *vdev, iot_pkt_t* buf) { if (vdev == NULL) goto err; if (vdev->start_cfg.mac_data_rx_func == NULL) goto err; if (buf == NULL) { IOT_ASSERT(0); return ERR_FAIL; } rx_buf_hdr_t *hdr = (rx_buf_hdr_t *)iot_pkt_data(buf); iot_pkt_pull(buf, sizeof(rx_buf_hdr_t)); rx_mpdu_start *mpdu_st = &hdr->mpdu_st; int8_t snr = mac_rx_mpdu_st_get_avg_snr(mpdu_st); uint8_t phase = mac_rx_mpdu_st_get_rx_phase(mpdu_st); mac_rx_info_t *rx_info = (mac_rx_info_t *)(iot_pkt_data(buf) - \ sizeof(mac_rx_info_t)); os_mem_cpy(rx_info->fc, mac_rx_mpdu_st_get_fc_addr(mpdu_st), \ sizeof(rx_info->fc)); rx_info->phy.snr = snr; rx_info->phy.phase = phase; rx_info->phy.band_id = (uint8_t)phy_band_id_get(); rx_info->phy.is_rf = 0; //TODO: rx_info->phy.channel_id = 0; //TODO: vdev->start_cfg.mac_data_rx_func(vdev->start_cfg.mac_callback_arg, buf); return ERR_OK; err: iot_pkt_free(buf); return ERR_INVAL; } uint32_t mac_ckq_rx_and_ppm_sync(mac_pdev_t *pdev, mac_vdev_t *vdev, rx_fc_msg_t *rx_fc_msg, iot_pkt_t *rx_buf) { if (!vdev) { vdev = pdev->vdev[PLC_DEFAULT_VDEV]; } /* ppm sync */ #if (PLC_SUPPORT_CCO_ROLE == 0) uint8_t *tmp = iot_pkt_block_ptr(rx_buf, IOT_PKT_BLOCK_DATA); rx_mpdu_start *mpdu_st = (rx_mpdu_start *)(tmp + MPDU_START_OFFSET); rx_mpdu_end *mpdu_ed = (rx_mpdu_end *)(tmp + MPDU_END_OFFSET); if (rx_fc_msg->sack_ext_deli == SACK_EXT_TYPE_SYNC && vdev_get_tei(vdev) == PLC_TEI_CTRL) { int16_t ppm_err = PLC_MAX_PPM_SUPPORT; uint32_t rate_mode = \ mac_rx_mpdu_st_get_rx_rate_mode(mpdu_st); uint32_t local_ts = \ mac_rx_mpdu_end_get_local_timestamp(mpdu_ed); uint8_t est_ppm = \ mac_rx_mpdu_st_get_estimated_ppm(mpdu_st); uint32_t ntb_ts = \ mac_rx_mpdu_end_get_ntb_timestamp(mpdu_ed); (void)ntb_ts; mac_ntb_ppm_sync(&vdev->mac_ppm, rate_mode, \ rx_fc_msg->time_stamp, local_ts, ntb_ts,\ est_ppm, &ppm_err, SYNC_PERIOD_MS, true); nid_t my_nid = 0; vdev_get_nid(vdev, &my_nid); (void)mac_multi_ppm_record(pdev->pdev_id, rx_fc_msg->nid, my_nid, rate_mode, rx_fc_msg->time_stamp, local_ts, ntb_ts, SYNC_PERIOD_MS, ppm_err); } #else (void)rx_fc_msg; #endif return mac_rx_ext_frame(vdev, rx_buf); }