/******************************************************************************
 *
 * Copyright(c) 2007 - 2019 Realtek Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 *****************************************************************************/
#define _RTW_MP_C_
#include <drv_types.h>
#ifdef PLATFORM_FREEBSD
	#include <sys/unistd.h>		/* for RFHIGHPID */
#endif


#ifdef CONFIG_MP_VHT_HW_TX_MODE
#define CEILING_POS(X) ((X - (int)(X)) > 0 ? (int)(X + 1) : (int)(X))
#define CEILING_NEG(X) ((X - (int)(X)) < 0 ? (int)(X - 1) : (int)(X))
#define ceil(X) (((X) > 0) ? CEILING_POS(X) : CEILING_NEG(X))

int rtfloor(float x)
{
	int i = x - 2;
	while
	(++i <= x - 1)
		;
	return i;
}
#endif

#ifdef CONFIG_MP_INCLUDED
bool rtw_mp_is_cck_rate(u16 rate)
{
	return ((rate & 0x1ff) <= _11M_RATE_) ? true : false;
}

static void _init_mp_priv_(struct mp_priv *pmp_priv)
{
	WLAN_BSSID_EX *pnetwork;

	_rtw_memset(pmp_priv, 0, sizeof(struct mp_priv));

	pmp_priv->mode = MP_OFF;

	pmp_priv->channel = 1;
	pmp_priv->bandwidth = CHANNEL_WIDTH_20;
	pmp_priv->prime_channel_offset = CHAN_OFFSET_NO_EXT;
	//pmp_priv->rateidx = RATE_1M;
	pmp_priv->txpoweridx = 0;
	pmp_priv->antenna_tx = MP_ANTENNA_A;
	pmp_priv->antenna_rx = MP_ANTENNA_A;
	pmp_priv->antenna_trx = MP_ANTENNA_A;

	pmp_priv->check_mp_pkt = 0;

	pmp_priv->tx_pktcount = 0;

	pmp_priv->rx_bssidpktcount = 0;
	pmp_priv->rx_pktcount = 0;
	pmp_priv->rx_crcerrpktcount = 0;

	pmp_priv->network_macaddr[0] = 0x00;
	pmp_priv->network_macaddr[1] = 0xE0;
	pmp_priv->network_macaddr[2] = 0x4C;
	pmp_priv->network_macaddr[3] = 0x87;
	pmp_priv->network_macaddr[4] = 0x66;
	pmp_priv->network_macaddr[5] = 0x55;

	pmp_priv->bSetRxBssid = _FALSE;
	pmp_priv->bRTWSmbCfg = _FALSE;
	pmp_priv->bloopback = _FALSE;

	pmp_priv->bloadefusemap = _FALSE;
	pmp_priv->brx_filter_beacon = _FALSE;
	pmp_priv->mplink_brx = _FALSE;
	pmp_priv->mp_keep_btc_mode = BTC_MODE_MAX;

	pnetwork = &pmp_priv->mp_network.network;
	_rtw_memcpy(pnetwork->MacAddress, pmp_priv->network_macaddr, ETH_ALEN);

	pnetwork->Ssid.SsidLength = 8;
	_rtw_memcpy(pnetwork->Ssid.Ssid, "mp_871x", pnetwork->Ssid.SsidLength);

	pmp_priv->tx.payload = MP_TX_Payload_default_random;
#ifdef CONFIG_80211N_HT
	pmp_priv->tx.attrib.ht_en = 1;
#endif

	pmp_priv->mpt_ctx.mpt_rate_index = 1;

}


static void mp_init_xmit_attrib(struct mp_tx *pmptx, _adapter *padapter)
{
	struct pkt_attrib *pattrib;

	/* init xmitframe attribute */
	pattrib = &pmptx->attrib;
	_rtw_memset(pattrib, 0, sizeof(struct pkt_attrib));
	_rtw_memset(pmptx->desc, 0, TXDESC_SIZE);

	pattrib->ether_type = 0x8712;
#if 0
	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
#endif
	_rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);

	/*	pattrib->dhcp_pkt = 0;
	 *	pattrib->pktlen = 0; */
	pattrib->ack_policy = 0;
	/*	pattrib->pkt_hdrlen = ETH_HLEN; */
	pattrib->hdrlen = WLAN_HDR_A3_LEN;
	pattrib->subtype = WIFI_DATA;
	pattrib->priority = 0;
	pattrib->qsel = pattrib->priority;
	/*	do_queue_select(padapter, pattrib); */
	pattrib->nr_frags = 1;
	pattrib->encrypt = 0;
	pattrib->bswenc = _FALSE;
	pattrib->qos_en = _FALSE;

	pattrib->pktlen = 1500;
}

s32 init_mp_priv(_adapter *padapter)
{
	struct mp_priv *pmppriv = &padapter->mppriv;

	_init_mp_priv_(pmppriv);
	pmppriv->papdater = padapter;
	if (0) //(IS_HARDWARE_TYPE_8822C(padapter))
		pmppriv->mp_dm = 1;/* default enable dpk tracking */
	else
		pmppriv->mp_dm = 0;

	pmppriv->tx.stop = 1;
	pmppriv->bSetTxPower = 0;		/*for  manually set tx power*/
	pmppriv->bTxBufCkFail = _FALSE;
	pmppriv->pktInterval = 100;
	pmppriv->pktLength = 1000;
	pmppriv->bprocess_mp_mode = _FALSE;
	pmppriv->rtw_mp_tx_method = RTW_MP_PMACT_TX;
	pmppriv->rtw_mp_cur_phy = 0;
	pmppriv->rtw_mp_pmact_patt_idx = 0;
	pmppriv->rtw_mp_pmact_ppdu_type = 0;
	pmppriv->rtw_mp_dbcc = 0;
	pmppriv->pre_refcw_cck_pwridxa = 0;
	pmppriv->pre_refcw_cck_pwridxb = 0;
	pmppriv->pre_refcw_ofdm_pwridxa = 0;
	pmppriv->pre_refcw_ofdm_pwridxb = 0;
	pmppriv->rtw_mp_data_bandwidth = CHANNEL_WIDTH_20;

	pmppriv->rtw_mp_trxsc = 0;
	pmppriv->rtw_mp_stbc = 0;
	pmppriv->rtw_mp_he_sigb = 0;
	pmppriv->rtw_mp_he_sigb_dcm = 0;
	pmppriv->rtw_mp_plcp_gi = 1;
	pmppriv->rtw_mp_plcp_ltf = 0;
	pmppriv->rtw_mp_plcp_tx_time = 0;
	pmppriv->rtw_mp_plcp_tx_mode = 0;
	pmppriv->rtw_mp_plcp_tx_user = 1;
	pmppriv->rtw_mp_he_er_su_ru_106_en = 0;
	pmppriv->rtw_mp_ru_tone = MP_RU_TONE_26;

	pmppriv->mp_plcp_useridx = 0;
	pmppriv->mp_plcp_user[0].plcp_mcs = 0;
	pmppriv->mp_plcp_user[0].aid = 0;
	pmppriv->mp_plcp_user[0].coding = 0;
	pmppriv->mp_plcp_user[0].dcm = 0;
	pmppriv->mp_plcp_user[0].plcp_txlen = 1000;
	pmppriv->mp_plcp_user[0].ru_alloc = 0;
	pmppriv->mp_plcp_user[0].txbf = 0;
	pmppriv->mp_plcp_user[0].pwr_boost_db = 0;

	pmppriv->btc_path = BTC_MODE_WL;

	_rtw_memset(pmppriv->st_giltf, 0, sizeof(struct rtw_mp_giltf_data)*5);

	mp_init_xmit_attrib(&pmppriv->tx, padapter);
#if 0
	switch (GET_HAL_RFPATH(padapter)) {
	case RF_1T1R:
		pmppriv->antenna_tx = ANTENNA_A;
		pmppriv->antenna_rx = ANTENNA_A;
		break;
	case RF_1T2R:
	default:
		pmppriv->antenna_tx = ANTENNA_A;
		pmppriv->antenna_rx = ANTENNA_AB;
		break;
	case RF_2T2R:
		pmppriv->antenna_tx = ANTENNA_AB;
		pmppriv->antenna_rx = ANTENNA_AB;
		break;
	case RF_2T4R:
		pmppriv->antenna_tx = ANTENNA_BC;
		pmppriv->antenna_rx = ANTENNA_ABCD;
		break;
	}
#endif

	return _SUCCESS;
}

void free_mp_priv(struct mp_priv *pmp_priv)
{
	if (pmp_priv->pallocated_mp_xmitframe_buf) {
		rtw_mfree(pmp_priv->pallocated_mp_xmitframe_buf, 0);
		pmp_priv->pallocated_mp_xmitframe_buf = NULL;
	}
	pmp_priv->pmp_xmtframe_buf = NULL;
}

#if 0
static void PHY_IQCalibrate_default(
		_adapter *adapter,
		BOOLEAN	bReCovery
)
{
	RTW_INFO("%s\n", __func__);
}

static void PHY_LCCalibrate_default(
		_adapter *adapter
)
{
	RTW_INFO("%s\n", __func__);
}

static void PHY_SetRFPathSwitch_default(
		_adapter *adapter,
		BOOLEAN		bMain
)
{
	RTW_INFO("%s\n", __func__);
}
#endif

void mpt_InitHWConfig(_adapter *adapter)
{
#ifdef CONFIG_RTL8822B
	if (IS_HARDWARE_TYPE_8822B(adapter)) {
		u32 tmp_reg = 0;

		rtw_write16(adapter, REG_RXFLTMAP1_8822B, 0x2000);
		/* fixed wifi can't 2.4g tx suggest by Szuyitasi 20160504 */
		phy_set_bb_reg(adapter, 0x70, bMaskByte3, 0x0e);
		RTW_INFO(" 0x73 = 0x%x\n", phy_query_bb_reg(adapter, 0x70, bMaskByte3));
		phy_set_bb_reg(adapter, 0x1704, bMaskDWord, 0x0000ff00);
		RTW_INFO(" 0x1704 = 0x%x\n", phy_query_bb_reg(adapter, 0x1704, bMaskDWord));
		phy_set_bb_reg(adapter, 0x1700, bMaskDWord, 0xc00f0038);
		RTW_INFO(" 0x1700 = 0x%x\n", phy_query_bb_reg(adapter, 0x1700, bMaskDWord));
	}
#endif /* CONFIG_RTL8822B */
#ifdef CONFIG_RTL8821C
	if (IS_HARDWARE_TYPE_8821C(adapter))
		rtw_write16(adapter, REG_RXFLTMAP1_8821C, 0x2000);
#endif /* CONFIG_RTL8821C */
#if defined(CONFIG_RTL8822C)
	if( IS_HARDWARE_TYPE_8822C(adapter)) {
		rtw_write16(adapter, REG_RXFLTMAP1_8822C, 0x2000);
		/* 0x7D8[31] : time out enable when cca is not assert
			0x60D[7:0] : time out value (Unit : us)*/
		rtw_write8(adapter, 0x7db, 0xc0);
		RTW_INFO(" 0x7d8 = 0x%x\n", rtw_read8(adapter, 0x7d8));
		rtw_write8(adapter, 0x60d, 0x0c);
		RTW_INFO(" 0x60d = 0x%x\n", rtw_read8(adapter, 0x60d));
		phy_set_bb_reg(adapter, 0x1c44, BIT10, 0x1);
		RTW_INFO(" 0x1c44 = 0x%x\n", phy_query_bb_reg(adapter, 0x1c44, bMaskDWord));
	}
#endif
#if defined(CONFIG_RTL8814B)
	if(IS_HARDWARE_TYPE_8814B(adapter))
		rtw_write16(adapter, REG_RXFLTMAP1_8814B, 0x2000);
#endif

}

static void PHY_IQCalibrate(_adapter *padapter, u8 bReCovery)
{
	//halrf_iqk_trigger(adapter_to_phydm(padapter), bReCovery);
}

static void PHY_LCCalibrate(_adapter *padapter)
{
	//halrf_lck_trigger(adapter_to_phydm(padapter));
}

static u8 PHY_QueryRFPathSwitch(_adapter *padapter)
{
	u8 bmain = 0;


	return bmain;
}

static void  PHY_SetRFPathSwitch(_adapter *padapter , BOOLEAN bMain) {

}


static void phy_switch_rf_path_set(_adapter *padapter , u8 *prf_set_State) {
#ifdef CONFIG_RTL8821C
	struct dm_struct *phydm = adapter_to_phydm(padapter);

	if (IS_HARDWARE_TYPE_8821C(padapter)) {
		config_phydm_set_ant_path(phydm, *prf_set_State, phydm->current_ant_num_8821c);
		/* Do IQK when switching to BTG/WLG, requested by RF Binson */
		if (*prf_set_State == SWITCH_TO_BTG || *prf_set_State == SWITCH_TO_WLG)
			PHY_IQCalibrate(padapter, FALSE);
	}
#endif

}


s32
MPT_InitializeAdapter(
		_adapter *adapter,
		u8				Channel
)
{
	s32		rtStatus = _SUCCESS;
	PMPT_CONTEXT	pMptCtx = &adapter->mppriv.mpt_ctx;
	/*u32		ledsetting;*/

	pMptCtx->bMptDrvUnload = _FALSE;
	pMptCtx->bMassProdTest = _FALSE;
	pMptCtx->bMptIndexEven = _TRUE;	/* default gain index is -6.0db */
	pMptCtx->h2cReqNum = 0x0;
	/* init for BT MP */
	mpt_InitHWConfig(adapter);

	pMptCtx->bMptWorkItemInProgress = _FALSE;
	pMptCtx->CurrMptAct = NULL;
	pMptCtx->mpt_rf_path = RF_PATH_A;
	/* ------------------------------------------------------------------------- */
	/* Don't accept any packets */
	//rtw_write32(adapter, REG_RCR, 0);

	/* ledsetting = rtw_read32(adapter, REG_LEDCFG0); */
	/* rtw_write32(adapter, REG_LEDCFG0, ledsetting & ~LED0DIS); */

	/* rtw_write32(adapter, REG_LEDCFG0, 0x08080); */
	/*ledsetting = rtw_read32(adapter, REG_LEDCFG0);*/


	PHY_LCCalibrate(adapter);
	PHY_IQCalibrate(adapter, _FALSE);
	/* dm_check_txpowertracking(adapter_to_phydm(adapter));	*/ /* trigger thermal meter */

	PHY_SetRFPathSwitch(adapter, 1/*pHalData->bDefaultAntenna*/); /* default use Main */
#if 0
	pMptCtx->backup0xc50 = (u8)phy_query_bb_reg(adapter, rOFDM0_XAAGCCore1, bMaskByte0);
	pMptCtx->backup0xc58 = (u8)phy_query_bb_reg(adapter, rOFDM0_XBAGCCore1, bMaskByte0);
	pMptCtx->backup0xc30 = (u8)phy_query_bb_reg(adapter, rOFDM0_RxDetector1, bMaskByte0);
	pMptCtx->backup0x52_RF_A = (u8)phy_query_rf_reg(adapter, RF_PATH_A, RF_0x52, 0x000F0);
	pMptCtx->backup0x52_RF_B = (u8)phy_query_rf_reg(adapter, RF_PATH_B, RF_0x52, 0x000F0);
#endif	
	return	rtStatus;
}

/*-----------------------------------------------------------------------------
 * Function:	MPT_DeInitAdapter()
 *
 * Overview:	Extra DeInitialization for Mass Production Test.
 *
 * Input:		_adapter *adapter
 *
 * Output:		NONE
 *
 * Return:		NONE
 *
 * Revised History:
 *	When		Who		Remark
 *	05/08/2007	MHC		Create Version 0.
 *	05/18/2007	MHC		Add normal driver MPHalt code.
 *
 *---------------------------------------------------------------------------*/
void
MPT_DeInitAdapter(
		_adapter *adapter
)
{
	PMPT_CONTEXT		pMptCtx = &adapter->mppriv.mpt_ctx;
	pMptCtx->bMptDrvUnload = _TRUE;
}

static u8 mpt_ProStartTest(_adapter *padapter)
{
	PMPT_CONTEXT pMptCtx = &padapter->mppriv.mpt_ctx;

	pMptCtx->bMassProdTest = _TRUE;
	pMptCtx->is_start_cont_tx = _FALSE;
	pMptCtx->bCckContTx = _FALSE;
	pMptCtx->bOfdmContTx = _FALSE;
	pMptCtx->bSingleCarrier = _FALSE;
	pMptCtx->is_carrier_suppression = _FALSE;
	pMptCtx->is_single_tone = _FALSE;
	pMptCtx->HWTxmode = PACKETS_TX;

	return _SUCCESS;
}

void rtw_mp_cal_trigger(_adapter *padapter, u8 cal_tye)
{
	struct rtw_mp_cal_arg	*mp_cal_arg = NULL;
	struct mp_priv *pmppriv = &padapter->mppriv;

	mp_cal_arg = _rtw_malloc(sizeof(struct rtw_mp_cal_arg));
	if (mp_cal_arg)
		_rtw_memset((void *)mp_cal_arg, 0, sizeof(struct rtw_mp_cal_arg));
	else {
		RTW_ERR("%s,malloc fail ! ", __func__);
		return;
	}
	mp_cal_arg->cal_type = cal_tye;

	if (cal_tye == RTW_MP_CAL_DPK_TRACK) {
		if (rtw_mp_phl_calibration(padapter,
					mp_cal_arg,
					RTW_MP_CAL_CMD_TRIGGER_DPK_TRACKING))
			RTW_INFO("%s ok\n", __func__);
		else
			RTW_INFO("%s fail\n", __func__);
	} else {
		if (rtw_mp_phl_calibration(padapter,
					mp_cal_arg,
					RTW_MP_CAL_CMD_TRIGGER_CAL))
			RTW_INFO("%s ok\n", __func__);
		else
			RTW_INFO("%s fail\n", __func__);
	}
	if (mp_cal_arg)
		_rtw_mfree(mp_cal_arg, sizeof(struct rtw_mp_cal_arg));

	return;
}

void rtw_mp_cal_capab(_adapter *padapter, u8 cal_tye, u8 benable)
{
	struct rtw_mp_cal_arg	*mp_cal_arg = NULL;
	struct mp_priv *pmppriv = &padapter->mppriv;

	mp_cal_arg = _rtw_malloc(sizeof(struct rtw_mp_cal_arg));
	if (mp_cal_arg)
		_rtw_memset((void *)mp_cal_arg, 0, sizeof(struct rtw_mp_cal_arg));
	else {
		RTW_ERR("%s,malloc fail ! ", __func__);
		return;
	}

	mp_cal_arg->cal_type = cal_tye;
	mp_cal_arg->enable = benable;

	if (rtw_mp_phl_calibration(padapter, mp_cal_arg, RTW_MP_CAL_CMD_SET_CAPABILITY_CAL))
		RTW_INFO("%s ok\n", __func__);
	else
		RTW_INFO("%s fail\n", __func__);

	if (mp_cal_arg)
		_rtw_mfree(mp_cal_arg, sizeof(struct rtw_mp_cal_arg));

	return;
}

/*
 * General use
 */
s32 SetPowerTracking(_adapter *padapter, u8 enable)
{

	//hal_mpt_SetPowerTracking(padapter, enable);
	return 0;
}

void GetPowerTracking(_adapter *padapter, u8 *enable)
{
	//hal_mpt_GetPowerTracking(padapter, enable);
	return;
}

void rtw_mp_trigger_iqk(_adapter *padapter)
{
	rtw_mp_cal_trigger(padapter, RTW_MP_CAL_IQK);
}

void rtw_mp_trigger_lck(_adapter *padapter)
{
	rtw_mp_cal_trigger(padapter, RTW_MP_CAL_LCK);
}

void rtw_mp_trigger_dpk(_adapter *padapter)
{
	rtw_mp_cal_trigger(padapter, RTW_MP_CAL_DPK);
}

void rtw_mp_trigger_tssi(_adapter *padapter)
{
	rtw_mp_cal_trigger(padapter, RTW_MP_CAL_TSSI);
}

void rtw_mp_trigger_ch_rfk(_adapter *padapter)
{
	rtw_mp_cal_trigger(padapter, RTW_MP_CAL_CHL_RFK);
}

void rtw_mp_trigger_dack(_adapter *padapter)
{
	rtw_mp_cal_trigger(padapter, RTW_MP_CAL_DACK);
}

static void init_mp_data(_adapter *padapter)
{
#if 0	
	struct dm_struct *phydm = adapter_to_phydm(padapter);

	/*disable BCN*/
	v8 = rtw_read8(padapter, REG_BCN_CTRL);
	v8 &= ~EN_BCN_FUNCTION;
	rtw_write8(padapter, REG_BCN_CTRL, v8);

	phydm->rf_calibrate_info.txpowertrack_control = _FALSE;
#endif	
}

u32 mp_join(_adapter *padapter, u8 mode)
{
	WLAN_BSSID_EX bssid;
	struct sta_info *psta;
	u32 length;
	s32 res = _SUCCESS;
	u8 i = 0;
	struct mp_priv *pmppriv = &padapter->mppriv;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
	WLAN_BSSID_EX		*pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));

	/* 1. initialize a new WLAN_BSSID_EX */
	_rtw_memset(&bssid, 0, sizeof(WLAN_BSSID_EX));
	RTW_INFO("%s ,pmppriv->network_macaddr=%x %x %x %x %x %x\n", __func__,
		pmppriv->network_macaddr[0], pmppriv->network_macaddr[1], pmppriv->network_macaddr[2], pmppriv->network_macaddr[3], pmppriv->network_macaddr[4],
		 pmppriv->network_macaddr[5]);
	_rtw_memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN);

	if (mode == WIFI_FW_ADHOC_STATE) {
		bssid.Ssid.SsidLength = strlen("mp_pseudo_adhoc");
		_rtw_memcpy(bssid.Ssid.Ssid, (u8 *)"mp_pseudo_adhoc", bssid.Ssid.SsidLength);
		bssid.InfrastructureMode = Ndis802_11IBSS;
		bssid.IELength = 0;
		bssid.Configuration.DSConfig = pmppriv->channel;

	} else if (mode == WIFI_FW_STATION_STATE) {
		bssid.Ssid.SsidLength = strlen("mp_pseudo_STATION");
		_rtw_memcpy(bssid.Ssid.Ssid, (u8 *)"mp_pseudo_STATION", bssid.Ssid.SsidLength);
		bssid.InfrastructureMode = Ndis802_11Infrastructure;
		bssid.IELength = 0;
	}

	length = get_WLAN_BSSID_EX_sz(&bssid);
	if (length % 4)
		bssid.Length = ((length >> 2) + 1) << 2; /* round up to multiple of 4 bytes. */
	else
		bssid.Length = length;

	_rtw_spinlock_bh(&pmlmepriv->lock);

	if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
		goto end_of_mp_start_test;

	/* init mp_start_test status */
	for (i = 0; i < dvobj->iface_nums; i++) {
		_adapter *iface = NULL;
		struct mlme_priv *buddy_mlmepriv;

		iface = dvobj->padapters[i];
		buddy_mlmepriv = &iface->mlmepriv;

		if (iface == NULL)
			continue;
		if (rtw_is_adapter_up(iface) == _FALSE)
			continue;
		if (check_fwstate(buddy_mlmepriv, WIFI_ASOC_STATE) == _TRUE) {
#ifdef CONFIG_STA_CMD_DISPR
			rtw_disassoc_cmd(iface, 500, RTW_CMDF_WAIT_ACK);
#else /* !CONFIG_STA_CMD_DISPR */
			rtw_disassoc_cmd(iface, 500, 0);
			rtw_free_assoc_resources_cmd(iface, _TRUE, RTW_CMDF_WAIT_ACK);
#endif /* !CONFIG_STA_CMD_DISPR */
			rtw_indicate_disconnect(iface, 0, _FALSE);
		}
	}

	pmppriv->prev_fw_state = get_fwstate(pmlmepriv);
	/*pmlmepriv->fw_state = WIFI_MP_STATE;*/
	init_fwstate(pmlmepriv, WIFI_MP_STATE);
	set_fwstate(pmlmepriv, WIFI_UNDER_LINKING);

	/* 3 2. create a new psta for mp driver */
	/* clear psta in the cur_network, if any */
	psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress);
	if (psta)
		rtw_free_stainfo(padapter, psta);

	psta = rtw_alloc_stainfo(&padapter->stapriv, bssid.MacAddress);
	if (psta == NULL) {
		/*pmlmepriv->fw_state = pmppriv->prev_fw_state;*/
		init_fwstate(pmlmepriv, pmppriv->prev_fw_state);
		res = _FAIL;
		goto end_of_mp_start_test;
	}
	if (mode == WIFI_FW_ADHOC_STATE)
		set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
	else
		set_fwstate(pmlmepriv, WIFI_STATION_STATE);
	/* 3 3. join psudo AdHoc */
	tgt_network->join_res = 1;
	tgt_network->aid = psta->phl_sta->aid = 1;

	_rtw_memcpy(&padapter->registrypriv.dev_network, &bssid, length);
	rtw_update_registrypriv_dev_network(padapter);
	_rtw_memcpy(&tgt_network->network, &padapter->registrypriv.dev_network, padapter->registrypriv.dev_network.Length);
	_rtw_memcpy(pnetwork, &padapter->registrypriv.dev_network, padapter->registrypriv.dev_network.Length);

	rtw_indicate_connect(padapter);
	_clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
	set_fwstate(pmlmepriv, WIFI_ASOC_STATE);

end_of_mp_start_test:

	_rtw_spinunlock_bh(&pmlmepriv->lock);

	if (1) { /* (res == _SUCCESS) */
		/* set MSR to WIFI_FW_ADHOC_STATE */
		if (mode == WIFI_FW_ADHOC_STATE) {
			/* set msr to WIFI_FW_ADHOC_STATE */
			pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
			rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
			rtw_hal_rcr_set_chk_bssid(padapter, MLME_ADHOC_STARTED);
			pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
		} else {
			RTW_INFO("%s , pmppriv->network_macaddr =%x %x %x %x %x %x\n", __func__,
				pmppriv->network_macaddr[0], pmppriv->network_macaddr[1], pmppriv->network_macaddr[2], pmppriv->network_macaddr[3], pmppriv->network_macaddr[4],
				pmppriv->network_macaddr[5]);

			rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmppriv->network_macaddr);
		}
	}

	return res;
}
/* This function initializes the DUT to the MP test mode */
s32 mp_start_test(_adapter *padapter)
{
	struct mp_priv *pmppriv = &padapter->mppriv;
	s32 res = _SUCCESS;

	padapter->registrypriv.mp_mode = 1;
	init_mp_priv(padapter);

	init_mp_data(padapter);
#if 0
#ifdef CONFIG_PCI_HCI
	hal = GET_PHL_COM(adapter_to_dvobj(padapter));
	hal->pci_backdoor_ctrl = 0;
	rtw_pci_aspm_config(padapter);
#endif


	/* 3 0. update mp_priv */
	switch (GET_HAL_RFPATH(padapter)) {
		case RF_1T1R:
			pmppriv->antenna_tx = ANTENNA_A;
			pmppriv->antenna_rx = ANTENNA_A;
			break;
		case RF_1T2R:
		default:
			pmppriv->antenna_tx = ANTENNA_A;
			pmppriv->antenna_rx = ANTENNA_AB;
			break;
		case RF_2T2R:
			pmppriv->antenna_tx = ANTENNA_AB;
			pmppriv->antenna_rx = ANTENNA_AB;
			break;
		case RF_2T4R:
			pmppriv->antenna_tx = ANTENNA_AB;
			pmppriv->antenna_rx = ANTENNA_ABCD;
			break;
	}
#endif
	mpt_ProStartTest(padapter);

	mp_join(padapter, WIFI_FW_ADHOC_STATE);

	return res;
}
/* ------------------------------------------------------------------------------
 * This function change the DUT from the MP test mode into normal mode */
void mp_stop_test(_adapter *padapter)
{
	struct mp_priv *pmppriv = &padapter->mppriv;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
	struct sta_info *psta;
#ifdef CONFIG_PCI_HCI
	struct registry_priv  *registry_par = &padapter->registrypriv;
#endif

	if (pmppriv->mode == MP_ON) {
		pmppriv->bSetTxPower = 0;
		_rtw_spinlock_bh(&pmlmepriv->lock);
		if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _FALSE)
			goto end_of_mp_stop_test;

		/* 3 1. disconnect psudo AdHoc */
		rtw_indicate_disconnect(padapter, 0, _FALSE);

		/* 3 2. clear psta used in mp test mode.
		*	rtw_free_assoc_resources(padapter, _TRUE); */
		psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress);
		if (psta)
			rtw_free_stainfo(padapter, psta);

		/* 3 3. return to normal state (default:station mode) */
		/*pmlmepriv->fw_state = pmppriv->prev_fw_state; */ /* WIFI_STATION_STATE;*/
		init_fwstate(pmlmepriv, pmppriv->prev_fw_state);

		/* flush the cur_network */
		_rtw_memset(tgt_network, 0, sizeof(struct wlan_network));

		_clr_fwstate_(pmlmepriv, WIFI_MP_STATE);

end_of_mp_stop_test:

		_rtw_spinunlock_bh(&pmlmepriv->lock);

#if 0//def CONFIG_PCI_HCI
		hal = GET_PHL_COM(adapter_to_dvobj(padapter));
		hal->pci_backdoor_ctrl = registry_par->pci_aspm_config;
		rtw_pci_aspm_config(padapter);
#endif
	}
}

void SetChannel(_adapter *padapter)
{
#ifdef CONFIG_MP_INCLUDED
	rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SET_CH_BW);
#else
	//hal_mpt_SetChannel(adapter);
#endif	
}

void SetBandwidth(_adapter *padapter)
{
#ifdef CONFIG_MP_INCLUDED
	rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SET_CH_BW);
#else	
	//hal_mpt_SetBandwidth(adapter);
#endif
}

void SetAntenna(_adapter *padapter)
{
	mp_ant_path mp_trx_path = padapter->mppriv.antenna_trx;
	u8 cfg_rf_path = RF_PATH_A;

	switch (mp_trx_path) {
	case MP_ANTENNA_A:
		cfg_rf_path = RF_PATH_A;
		break;
	case MP_ANTENNA_B:
		cfg_rf_path = RF_PATH_B;
		break;
	case MP_ANTENNA_C:
		cfg_rf_path = RF_PATH_C;
		break;
	case MP_ANTENNA_D:
		cfg_rf_path = RF_PATH_D;
		break;
	case MP_ANTENNA_AB:
		cfg_rf_path = RF_PATH_AB;
		break;
	case MP_ANTENNA_AC:
		cfg_rf_path = RF_PATH_AC;
		break;
	case MP_ANTENNA_AD:
		cfg_rf_path = RF_PATH_AD;
		break;
	case MP_ANTENNA_BC:
		cfg_rf_path = RF_PATH_BC;
		break;
	case MP_ANTENNA_BD:
		cfg_rf_path = RF_PATH_BD;
		break;
	case MP_ANTENNA_CD:
		cfg_rf_path = RF_PATH_CD;
		break;
	case MP_ANTENNA_ABC:
		cfg_rf_path = RF_PATH_ABC;
		break;
	case MP_ANTENNA_BCD:
		cfg_rf_path = RF_PATH_BCD;
		break;
	case MP_ANTENNA_ABD:
		cfg_rf_path = RF_PATH_ABD;
		break;
	case MP_ANTENNA_ACD:
		cfg_rf_path = RF_PATH_ACD;
		break;
	case MP_ANTENNA_ABCD:
		cfg_rf_path = RF_PATH_ABCD;
		break;
	default:
		RTW_INFO("%s ,default Antenna Path A\n", __func__);
		break;
	}

	padapter->mppriv.antenna_trx = cfg_rf_path;
	rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SET_RF_TXRX_PATH);
}

int rtw_mp_txpoweridx(_adapter *adapter)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	struct mp_priv *pmppriv = &adapter->mppriv;
	u8 tx_nss = get_phy_tx_nss(adapter);
	u8 i = 0;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.txpwr_index = pmppriv->txpoweridx * TX_POWER_CODE_WORD_BASE;

	for (i = 0; i < tx_nss; i++) {
		ptxpwr_arg.rfpath = i;
		ptxpwr_arg.is_cck = rtw_mp_is_cck_rate(pmppriv->rateidx);

		rtw_mp_phl_txpower(adapter, &ptxpwr_arg, RTW_MP_TXPWR_CMD_SET_TXPWR_INDEX);
	}
	return _TRUE;
}

s16 rtw_mp_get_pwr_refcw(_adapter *adapter, u8 rfpath, u8 is_cck)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	struct mp_priv *pmppriv = &adapter->mppriv;
	s16 txpwr_refcw_idx;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));
	ptxpwr_arg.rfpath = rfpath;
	ptxpwr_arg.is_cck = is_cck;

	rtw_mp_phl_txpower(adapter, &ptxpwr_arg, RTW_MP_TXPWR_CMD_GET_TXPWR_REF_CW);
	txpwr_refcw_idx = ptxpwr_arg.txpwr_index / TX_POWER_CODE_WORD_BASE;

	RTW_INFO("%s ,pwr ref cw: %d\n", __func__, txpwr_refcw_idx);
	return txpwr_refcw_idx;
}

u16 rtw_mp_get_pwr_ref(_adapter *adapter, u8 rfpath)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	struct mp_priv *pmppriv = &adapter->mppriv;
	s16 txpwr_ref;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));
	ptxpwr_arg.rfpath = rfpath;
	ptxpwr_arg.is_cck = rtw_mp_is_cck_rate(pmppriv->rateidx);

	rtw_mp_phl_txpower(adapter,  &ptxpwr_arg, RTW_MP_TXPWR_CMD_GET_TXPWR_REF);
	txpwr_ref = ptxpwr_arg.txpwr_ref / TX_POWER_BASE;

	RTW_INFO("%s ,pwr ref: %d\n", __func__, txpwr_ref);
	return txpwr_ref;
}

u16 rtw_mp_get_pwrtab_dbm(_adapter *adapter, u8 rfpath)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	struct mp_priv *pmppriv = &adapter->mppriv;
	s16 txpwr_dbm;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));
	ptxpwr_arg.rfpath = rfpath;
	ptxpwr_arg.is_cck = rtw_mp_is_cck_rate(pmppriv->rateidx);
	ptxpwr_arg.rate = pmppriv->rateidx;
	ptxpwr_arg.dcm = 0;
	ptxpwr_arg.offset = 0;
	ptxpwr_arg.bandwidth = pmppriv->bandwidth;
	ptxpwr_arg.beamforming = 0;
	ptxpwr_arg.channel = pmppriv->channel;

	rtw_mp_phl_txpower(adapter,  &ptxpwr_arg, RTW_MP_TXPWR_CMD_READ_PWR_TABLE);
	txpwr_dbm = ptxpwr_arg.table_item / TX_POWER_BASE;

	RTW_INFO("%s ,read PwrTab dbm: %d\n", __func__, txpwr_dbm);
	return txpwr_dbm;
}


u16 rtw_mp_txpower_dbm(_adapter *adapter, u8 rf_path)
{
	struct mp_priv *pmppriv = &adapter->mppriv;
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	u16 tmp_power_ref = 0;
	u16 agc_cw_val = 0;
	s16 pre_pwr_refcw_idx = 0;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.txpwr = pmppriv->txpowerdbm;
	ptxpwr_arg.is_cck = rtw_mp_is_cck_rate(pmppriv->rateidx);
	ptxpwr_arg.rfpath = rf_path;

	rtw_mp_phl_txpower(adapter, &ptxpwr_arg, RTW_MP_TXPWR_CMD_SET_TXPWR);

	if (pmppriv->pre_refcw_cck_pwridxa == 0 || pmppriv->pre_refcw_cck_pwridxb == 0) {
		pmppriv->pre_refcw_cck_pwridxa = rtw_mp_get_pwr_refcw(adapter, RF_PATH_A, 1);
		pmppriv->pre_refcw_cck_pwridxb = rtw_mp_get_pwr_refcw(adapter, RF_PATH_B, 1);
	}
	if (pmppriv->pre_refcw_ofdm_pwridxa == 0 || pmppriv->pre_refcw_ofdm_pwridxb == 0) {
		pmppriv->pre_refcw_ofdm_pwridxa = rtw_mp_get_pwr_refcw(adapter, RF_PATH_A, 0);
		pmppriv->pre_refcw_ofdm_pwridxb = rtw_mp_get_pwr_refcw(adapter, RF_PATH_B, 0);
	}

	if (rf_path == RF_PATH_A && ptxpwr_arg.is_cck == true)
		pre_pwr_refcw_idx = pmppriv->pre_refcw_cck_pwridxa;
	else if (rf_path == RF_PATH_B && ptxpwr_arg.is_cck == true)
		pre_pwr_refcw_idx = pmppriv->pre_refcw_cck_pwridxb;
	else if (rf_path == RF_PATH_A && ptxpwr_arg.is_cck == false)
		pre_pwr_refcw_idx = pmppriv->pre_refcw_ofdm_pwridxa;
	else if (rf_path == RF_PATH_B && ptxpwr_arg.is_cck == false)
		pre_pwr_refcw_idx = pmppriv->pre_refcw_ofdm_pwridxb;

	tmp_power_ref = rtw_mp_get_pwr_ref(adapter, rf_path);
	RTW_INFO("%s () tmp_power_ref: %d !! pre_pwr_refcw_idx:%d, pwr offset %d\n",
							__func__, tmp_power_ref, pre_pwr_refcw_idx , pmppriv->txpoweridx);
	agc_cw_val = pmppriv->txpowerdbm - tmp_power_ref + pre_pwr_refcw_idx + pmppriv->txpoweridx;

	ptxpwr_arg.txpwr_index = (pre_pwr_refcw_idx + pmppriv->txpoweridx) * TX_POWER_CODE_WORD_BASE;
	rtw_mp_phl_txpower(adapter, &ptxpwr_arg, RTW_MP_TXPWR_CMD_SET_TXPWR_INDEX);

	return agc_cw_val;
}

void SetDataRate(_adapter *padapter)
{

	rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SET_RATE_IDX);

	return;
}

void SetTxAGCOffset(_adapter *adapter, u32 ulTxAGCOffset)
{
	u32 TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D, tmpAGC;

	TxAGCOffset_B = (ulTxAGCOffset & 0x000000ff);
	TxAGCOffset_C = ((ulTxAGCOffset & 0x0000ff00) >> 8);
	TxAGCOffset_D = ((ulTxAGCOffset & 0x00ff0000) >> 16);

	tmpAGC = (TxAGCOffset_D << 8 | TxAGCOffset_C << 4 | TxAGCOffset_B);
//	write_bbreg(adapter, rFPGA0_TxGainStage,
//		    (bXBTxAGC | bXCTxAGC | bXDTxAGC), tmpAGC);
}

void MP_PHY_SetRFPathSwitch(_adapter *adapter , BOOLEAN bMain)
{
	//PHY_SetRFPathSwitch(adapter, bMain);
	return;
}

void mp_phy_switch_rf_path_set(_adapter *adapter , u8 *pstate)
{

	//phy_switch_rf_path_set(adapter, pstate);
	return;

}

u8 MP_PHY_QueryRFPathSwitch(_adapter *adapter)
{
	//return PHY_QueryRFPathSwitch(adapter);
	return 0;
}

s32 SetThermalMeter(_adapter *adapter, u8 target_ther)
{
	//return hal_mpt_SetThermalMeter(adapter, target_ther);
	return 0;
}

#if 0
static void TriggerRFThermalMeter(_adapter *adapter)
{
	hal_mpt_TriggerRFThermalMeter(adapter);
}

static u8 ReadRFThermalMeter(_adapter *adapter)
{
	return hal_mpt_ReadRFThermalMeter(adapter);
}
#endif

void GetUuid(_adapter *adapter, u32 *uuid)
{
	struct rtw_mp_config_arg pmp_arg;
	u16 i = 0;

	_rtw_memset((void *)&pmp_arg, 0, sizeof(struct rtw_mp_config_arg));

	pmp_arg.mp_class = RTW_MP_CLASS_CONFIG;
	pmp_arg.cmd = RTW_MP_CONFIG_CMD_GET_UUID;
	RTW_INFO("%s, id: %d !!!\n", __func__, pmp_arg.cmd);

	rtw_mp_set_phl_cmd(adapter, (void*)&pmp_arg, sizeof(struct rtw_mp_config_arg));

	while (i != 100) {
		rtw_msleep_os(10);
		rtw_mp_get_phl_cmd(adapter, (void*)&pmp_arg, sizeof(struct rtw_mp_config_arg));

		if (pmp_arg.cmd_ok && pmp_arg.status == RTW_PHL_STATUS_SUCCESS) {
			*uuid = pmp_arg.uuid;
			RTW_INFO("%s, SET CMD OK, uuid = %d\n", __func__, pmp_arg.uuid);
			break;
		} else {
			if (i > 100) {
				RTW_INFO("%s,GET CMD FAIL !!! status %d\n", __func__, pmp_arg.status);
				break;
			}
			i++;
			rtw_msleep_os(10);
		}
	}
}

void GetThermalMeter(_adapter *adapter, u8 rfpath ,u8 *value)
{
	struct mp_priv	*pmppriv = &adapter->mppriv;
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	u16 i = 0;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.mp_class = RTW_MP_CLASS_TXPWR;
	ptxpwr_arg.cmd = RTW_MP_TXPWR_CMD_GET_THERMAL;
	ptxpwr_arg.rfpath = rfpath;

	rtw_mp_set_phl_cmd(adapter, (void*)&ptxpwr_arg, sizeof(struct rtw_mp_txpwr_arg));

	while (i != 100) {
		rtw_msleep_os(10);
		rtw_mp_get_phl_cmd(adapter, (void*)&ptxpwr_arg, sizeof(struct rtw_mp_txpwr_arg));

		if (ptxpwr_arg.cmd_ok && ptxpwr_arg.status == RTW_PHL_STATUS_SUCCESS) {
			*value = ptxpwr_arg.thermal;
			RTW_INFO("%s, SET CMD OK, thermal = %d\n", __func__, ptxpwr_arg.thermal);
			break;
		} else {
			if (i > 100) {
				RTW_INFO("%s,GET CMD FAIL !!! status %d\n", __func__, ptxpwr_arg.status);
					break;
				}
			i++;
			rtw_msleep_os(10);
		}
	}
}

void rtw_mp_singlecarrier_tx(_adapter *adapter, u8 bstart)
{
	RTW_INFO("Not Supported SetSingleCarrierTx \n");
}

void rtw_mp_singletone_tx(_adapter *adapter, u8 bstart)
{
	struct mp_priv *pmp_priv = &adapter->mppriv;

	rtw_mp_txpwr_level(adapter);
	rtw_phl_mp_tx_cmd(adapter, RTW_MP_TX_SINGLE_TONE, pmp_priv->rtw_mp_tx_method, bstart);
}

void rtw_mp_carriersuppr_tx(_adapter *adapter, u8 bstart)
{
	struct mp_priv *pmp_priv = &adapter->mppriv;

	rtw_mp_txpwr_level(adapter);
	rtw_phl_mp_tx_cmd(adapter, RTW_MP_TX_CCK_Carrier_Suppression, pmp_priv->rtw_mp_tx_method, bstart);
}

void rtw_mp_continuous_tx(_adapter *adapter, u8 bstart)
{
	struct mp_priv *pmp_priv = &adapter->mppriv;

	rtw_mp_txpwr_level(adapter);
	rtw_phl_mp_tx_cmd(adapter, RTW_MP_TX_CONTINUOUS, pmp_priv->rtw_mp_tx_method, bstart);
}

void rtw_mp_txpwr_level(_adapter *adapter)
{
	struct mp_priv *pmp_priv = &adapter->mppriv;
/*
	if (pmp_priv->bSetTxPower == 0)
		rtw_hal_set_tx_power_level(adapter, pmp_priv->channel);
*/

	return;
}

/* ------------------------------------------------------------------------------ */
static void dump_mpframe(_adapter *padapter, struct xmit_frame *pmpframe)
{
	/*rtw_hal_mgnt_xmit(padapter, pmpframe);*/
	rtw_mgnt_xmit(padapter, pmpframe);
}

static struct xmit_frame *alloc_mp_xmitframe(struct xmit_priv *pxmitpriv)
{
#if 0 /*CONFIG_CORE_XMITBUF*/
	struct xmit_frame	*pmpframe;
	struct xmit_buf	*pxmitbuf;

	pmpframe = rtw_alloc_xmitframe(pxmitpriv);
	if (pmpframe == NULL)
		return NULL;

	pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
	if (pxmitbuf == NULL) {
		rtw_free_xmitframe(pxmitpriv, pmpframe);
		return NULL;
	}

	pmpframe->frame_tag = MP_FRAMETAG;

	pmpframe->pxmitbuf = pxmitbuf;

	pmpframe->buf_addr = pxmitbuf->pbuf;

	pxmitbuf->priv_data = pmpframe;
#else
	struct xmit_frame *pmpframe;

	pmpframe = rtw_alloc_xmitframe(pxmitpriv, 0);
	if (pmpframe == NULL)
		return NULL;

	pmpframe->frame_tag = MP_FRAMETAG;
#endif

	return pmpframe;

}

static thread_return mp_xmit_packet_thread(thread_context context)
{
	struct xmit_frame	*pxmitframe;
	struct mp_tx		*pmptx;
	struct mp_priv	*pmp_priv;
	struct xmit_priv	*pxmitpriv;
	_adapter *padapter;

	pmp_priv = (struct mp_priv *)context;
	pmptx = &pmp_priv->tx;
	padapter = pmp_priv->papdater;
	pxmitpriv = &(padapter->xmitpriv);

	rtw_thread_enter("RTW_MP_THREAD");

	RTW_INFO("%s:pkTx Start\n", __func__);
	while (1) {
		pxmitframe = alloc_mp_xmitframe(pxmitpriv);

		if (pxmitframe == NULL) {
			if (pmptx->stop ||
			    RTW_CANNOT_RUN(adapter_to_dvobj(padapter)))
				goto exit;
			else {
				rtw_usleep_os(10);
				continue;
			}
		}
		_rtw_memcpy((u8 *)(pxmitframe->buf_addr + TXDESC_OFFSET), pmptx->buf, pmptx->write_size);
		_rtw_memcpy(&(pxmitframe->attrib), &(pmptx->attrib), sizeof(struct pkt_attrib));


		rtw_usleep_os(padapter->mppriv.pktInterval);
		dump_mpframe(padapter, pxmitframe);

		pmptx->sended++;
		pmp_priv->tx_pktcount++;

		if (pmptx->stop ||
		    RTW_CANNOT_RUN(adapter_to_dvobj(padapter)))
			goto exit;
		if ((pmptx->count != 0) &&
		    (pmptx->count == pmptx->sended))
			goto exit;

		flush_signals_thread();
	}

exit:
	/* RTW_INFO("%s:pkTx Exit\n", __func__); */
	rtw_mfree(pmptx->pallocated_buf, pmptx->buf_size);
	pmptx->pallocated_buf = NULL;
	pmptx->stop = 1;

	rtw_thread_exit(NULL);
	return 0;
}

void fill_txdesc_for_mp(_adapter *padapter, u8 *ptxdesc)
{
	struct mp_priv *pmp_priv = &padapter->mppriv;
	_rtw_memcpy(ptxdesc, pmp_priv->tx.desc, TXDESC_SIZE);
}

static void Rtw_MPSetMacTxEDCA(_adapter *padapter)
{
#if 0
	rtw_write32(padapter, 0x508 , 0x00a422); /* Disable EDCA BE Txop for MP pkt tx adjust Packet interval */
	/* RTW_INFO("%s:write 0x508~~~~~~ 0x%x\n", __func__,rtw_read32(padapter, 0x508)); */
	phy_set_mac_reg(padapter, 0x458 , bMaskDWord , 0x0);
	/*RTW_INFO("%s()!!!!! 0x460 = 0x%x\n" ,__func__, phy_query_bb_reg(padapter, 0x460, bMaskDWord));*/
	phy_set_mac_reg(padapter, 0x460 , bMaskLWord , 0x0); /* fast EDCA queue packet interval & time out value*/
	/*phy_set_mac_reg(padapter, ODM_EDCA_VO_PARAM ,bMaskLWord , 0x431C);*/
	/*phy_set_mac_reg(padapter, ODM_EDCA_BE_PARAM ,bMaskLWord , 0x431C);*/
	/*phy_set_mac_reg(padapter, ODM_EDCA_BK_PARAM ,bMaskLWord , 0x431C);*/
	RTW_INFO("%s()!!!!! 0x460 = 0x%x\n" , __func__, phy_query_bb_reg(padapter, 0x460, bMaskDWord));
#endif
}

u8 rtw_phl_mp_tx_cmd(_adapter *padapter, enum rtw_mp_tx_cmd cmdid,
							enum rtw_mp_tx_method tx_method, boolean bstart)
{
	struct mp_priv	*pmppriv = &padapter->mppriv;
	struct pkt_attrib *pattrib = &pmppriv->tx.attrib;
	struct rtw_mp_tx_arg tx_arg;
	u16 i = 0;
	u8 user_idx = pmppriv->mp_plcp_useridx;

	_rtw_memset((void *)&tx_arg, 0, sizeof(struct rtw_mp_tx_arg));
	tx_arg.mp_class = RTW_MP_CLASS_TX;
	tx_arg.tx_method = tx_method;
	tx_arg.cmd = cmdid;
	tx_arg.cmd_ok = 0;
	tx_arg.tx_ok = 0;
	tx_arg.data_rate = pmppriv->rateidx;
	tx_arg.is_cck = rtw_mp_is_cck_rate(pmppriv->rateidx);
	tx_arg.start_tx = bstart;
	tx_arg.tx_path = pmppriv->antenna_trx;
	tx_arg.gi = pmppriv->rtw_mp_plcp_gi;
	tx_arg.period = pmppriv->pktInterval;
	tx_arg.plcp_usr_idx = user_idx;
		tx_arg.stbc = pmppriv->rtw_mp_stbc;

	switch (cmdid) {
		case RTW_MP_TX_PACKETS:
			RTW_INFO("%s,SET MP_TX_PACKETS tx_method %d\n", __func__, tx_arg.tx_method);
			if (tx_method == RTW_MP_PMACT_TX) {
			tx_arg.tx_mode = RTW_MP_PMAC_PKTS_TX;
				tx_arg.tx_cnt = pmppriv->tx.count;

			} else if (tx_method == RTW_MP_FW_PMACT_TX) {
				tx_arg.tx_mode = RTW_MP_PMAC_FW_TRIG_TX;
				tx_arg.tx_cnt = 0;
				tx_arg.tx_time = 60;
			}

			break;
		case RTW_MP_TX_CONTINUOUS:
			RTW_INFO("%s,SET MP_TX_CONTINUOUS\n", __func__);
			tx_arg.tx_mode = RTW_MP_PMAC_CONT_TX;
			break;
		case RTW_MP_TX_SINGLE_TONE:
			RTW_INFO("%s,SET TX_OFDM_Single_Tone\n", __func__);
			tx_arg.tx_mode = RTW_MP_PMAC_OFDM_SINGLE_TONE_TX;
			break;
		case RTW_MP_TX_CCK_Carrier_Suppression:
			RTW_INFO("%s,SET TX_CCK_Carrier_Suppression\n", __func__);
			tx_arg.tx_mode = RTW_MP_PMAC_CCK_CARRIER_SIPPRESSION_TX;
			break;
		case RTW_MP_TX_CONFIG_PLCP_PATTERN:
			RTW_INFO("%s,SET MP_TX_CONFIG_PLCP_PATTERN\n", __func__);
			tx_arg.plcp_case_id = pmppriv->rtw_mp_pmact_patt_idx;
			tx_arg.plcp_ppdu_type = pmppriv->rtw_mp_pmact_ppdu_type;
			break;
		case RTW_MP_TX_CONFIG_PLCP_COMMON_INFO:
			tx_arg.dbw = pmppriv->rtw_mp_data_bandwidth;
			tx_arg.long_preamble_en = pmppriv->preamble;
			tx_arg.stbc = pmppriv->rtw_mp_stbc;
			tx_arg.gi = pmppriv->rtw_mp_plcp_gi;
			tx_arg.he_ltf_type = pmppriv->rtw_mp_plcp_ltf;
			tx_arg.he_mcs_sigb = pmppriv->rtw_mp_he_sigb;
			tx_arg.he_dcm_sigb = pmppriv->rtw_mp_he_sigb_dcm;
			tx_arg.bss_color = 0;
			tx_arg.he_er_u106ru_en = pmppriv->rtw_mp_he_er_su_ru_106_en;
			if (pmppriv->rtw_mp_tx_method == RTW_MP_FW_PMACT_TX) {
				pmppriv->rtw_mp_plcp_tx_time = 5484;
				pmppriv->rtw_mp_plcp_tx_mode = 1;
			}
			tx_arg.max_tx_time_0p4us = pmppriv->rtw_mp_plcp_tx_time;
			tx_arg.mode = pmppriv->rtw_mp_plcp_tx_mode;
			tx_arg.ppdu_type = pmppriv->rtw_mp_pmact_ppdu_type;
			tx_arg.cbw = pmppriv->bandwidth;
			tx_arg.txsc = pmppriv->rtw_mp_trxsc;
			tx_arg.n_user = pmppriv->rtw_mp_plcp_tx_user; 

			RTW_INFO("%s,SET TX_CONFIG_PLCP_COMMON_INFO\n", __func__);
			RTW_INFO("%s=============================\n", __func__);
			RTW_INFO("%s dbw = %d\n", __func__, tx_arg.dbw);
			RTW_INFO("%s long_preamble_en = %d\n", __func__, tx_arg.long_preamble_en);
			RTW_INFO("%s stbc = %d\n", __func__, tx_arg.stbc);
			RTW_INFO("%s gi = %d\n", __func__, tx_arg.gi);
			RTW_INFO("%s tb_l_len = %d\n", __func__, tx_arg.tb_l_len);
			RTW_INFO("%s he_ltf_type = %d\n", __func__, tx_arg.he_ltf_type);
			RTW_INFO("%s he_mcs_sigb = %d\n", __func__, tx_arg.he_mcs_sigb);
			RTW_INFO("%s he_dcm_sigb = %d\n", __func__, tx_arg.he_dcm_sigb);
			RTW_INFO("%s max_tx_time_0p4us = %d\n", __func__, tx_arg.max_tx_time_0p4us);
			RTW_INFO("%s bss_color = %d\n", __func__, tx_arg.bss_color);
			RTW_INFO("%s he_er_u106ru_en = %d\n", __func__, tx_arg.he_er_u106ru_en);
			RTW_INFO("%s mode = %d\n", __func__, tx_arg.mode);
			RTW_INFO("%s ppdu_type = %d\n", __func__, tx_arg.ppdu_type);
			RTW_INFO("%s cbw = %d\n", __func__, tx_arg.cbw);
			RTW_INFO("%s txsc = %d\n", __func__, tx_arg.txsc);
			RTW_INFO("%s n_user = %d\n", __func__, tx_arg.n_user);
			RTW_INFO("%s=============================\n", __func__);
			break;
		case RTW_MP_TX_CMD_PHY_OK:
			/*TBD. API not ready*/
			RTW_INFO("%s,SET MP_TX_CMD_PHY_OK\n", __func__);
			break;
		case RTW_MP_TX_CONFIG_PLCP_USER_INFO:
			tx_arg.plcp_usr_idx = user_idx;
			tx_arg.mcs = pmppriv->mp_plcp_user[user_idx].plcp_mcs;
			tx_arg.fec = pmppriv->mp_plcp_user[user_idx].coding;
			tx_arg.dcm = pmppriv->mp_plcp_user[user_idx].dcm;
			tx_arg.aid = pmppriv->mp_plcp_user[user_idx].aid;
			tx_arg.scrambler_seed = (rtw_random32() % 127) + 1;
			tx_arg.random_init_seed = (rtw_random32() % 127) + 1;
			tx_arg.apep = pmppriv->mp_plcp_user[user_idx].plcp_txlen;
			tx_arg.ru_alloc = pmppriv->mp_plcp_user[user_idx].ru_alloc;
			tx_arg.nss = pmppriv->mp_plcp_user[user_idx].plcp_nss + 1;
			tx_arg.pwr_boost_db = pmppriv->mp_plcp_user[user_idx].pwr_boost_db;
			tx_arg.fec = pmppriv->mp_plcp_user[user_idx].coding;

			RTW_INFO("%s,SET MP_TX_CONFIG_PLCP_USER_INFO\n", __func__);
			RTW_INFO("%s plcp_usr_idx = %d\n", __func__, tx_arg.plcp_usr_idx);
			RTW_INFO("%s mcs = %d\n", __func__, tx_arg.mcs);
			RTW_INFO("%s fec = %d\n", __func__, tx_arg.fec);
			RTW_INFO("%s dcm = %d\n", __func__, tx_arg.dcm);
			RTW_INFO("%s ascrambler_seed = %d\n", __func__, tx_arg.scrambler_seed);
			RTW_INFO("%s random_init_seed = %d\n", __func__, tx_arg.random_init_seed);
			RTW_INFO("%s apep = %d\n", __func__, tx_arg.apep);
			RTW_INFO("%s ru_alloc = %d\n", __func__, tx_arg.ru_alloc);
			RTW_INFO("%s nss = %d\n", __func__, tx_arg.nss);
			break;
		case RTW_MP_TX_MODE_SWITCH:
			if (pmppriv->rtw_mp_tx_method == RTW_MP_TMACT_TX)
			tx_arg.tx_mode = 0;/* mode: 0 = tmac, 1 = pmac */
			else
				tx_arg.tx_mode = 1;/* mode: 0 = tmac, 1 = pmac */
			RTW_INFO("%s,SET MP_TX_MODE_SWITCH\n", __func__);
			break;
		default:
				RTW_INFO("%s,SET MP_TX_MODE None\n", __func__);
			return 0;
	}

	rtw_mp_set_phl_cmd(padapter, (void*)&tx_arg, sizeof(struct rtw_mp_tx_arg));
	while (i != 100) {
		rtw_mp_get_phl_cmd(padapter, (void*)&tx_arg, sizeof(struct rtw_mp_tx_arg));
		if (tx_arg.cmd_ok && tx_arg.status == RTW_PHL_STATUS_SUCCESS) {
			RTW_INFO("%s,SET CMD OK\n", __func__);
			if (cmdid == RTW_MP_TX_CMD_PHY_OK) {
				RTW_INFO("%s, Get Tx Rpt OK CNT:%d\n", __func__, tx_arg.tx_ok);
				padapter->mppriv.tx.sended = tx_arg.tx_ok;
			}
			break;
		} else {
			if (i > 100) {
				RTW_INFO("%s,GET CMD FAIL !!! status %d\n", __func__, tx_arg.status);
				break;
			}
			i++;
			rtw_msleep_os(10);
		}
	}
	return (tx_arg.cmd_ok);
}


static thread_return mp_xmit_phl_packet_thread(thread_context context)
{

	struct mp_priv	*pmppriv = (struct mp_priv *)context;
	struct mp_tx	*pmptx = &pmppriv->tx;
	_adapter *padapter = pmppriv->papdater;
	struct pkt_attrib *pattrib = &pmppriv->tx.attrib;
	struct dvobj_priv	*dvobj = adapter_to_dvobj(padapter);
	struct rtw_trx_test_param test_param = {0};
	u16 i = 0;

	RTW_INFO("%s: Start !!\n", __func__);
	rtw_phl_trx_default_param(GET_PHL_INFO(dvobj), &test_param);

	test_param.tx_cap.f_rate = (u16)pmppriv->rateidx;
	test_param.tx_payload_size = pattrib->pktlen;
	test_param.tx_cap.f_gi_ltf = 0;
	test_param.tx_cap.f_stbc = 0;
	test_param.tx_cap.f_ldpc = 0;
	RTW_INFO("%s: Start !! tx method %d\n", __func__, pmppriv->rtw_mp_tx_method);
	while (1) {
		if (pmppriv->rtw_mp_tx_method == RTW_MP_TMACT_TX) {
			/*/if (rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_PACKETS, pmppriv->rtw_mp_tx_method, _TRUE)) {*/
			if (rtw_phl_trx_testsuite(GET_PHL_INFO(dvobj), &test_param) == 0)
				RTW_DBG("%s: rtw_phl_trx_testsuite!!\n", __func__);
			else
				rtw_usleep_os(10);
		}
				pmptx->sended++;
				pmppriv->tx_pktcount++;
		rtw_usleep_os(padapter->mppriv.pktInterval);

		if (pmptx->stop || RTW_CANNOT_RUN(adapter_to_dvobj(padapter)))
			goto exit;
		if ((pmptx->count != 0) && (pmptx->count == pmptx->sended))
			goto exit;
		flush_signals_thread();
	}
exit:
	pmptx->stop = 1;

	RTW_INFO("%s: Exit !!\n", __func__);
	rtw_thread_exit(NULL);
	return 0;
}

void rtw_set_phl_packet_tx(_adapter *padapter, u8 bStart)
{
	struct mp_priv *pmp_priv;
	u8 rfpath_i = 0;
	u8 tx_nss = get_phy_tx_nss(padapter);
	pmp_priv = &padapter->mppriv;


	for (rfpath_i = 0 ; rfpath_i < tx_nss; rfpath_i ++)
		rtw_mp_txpower_dbm(padapter, rfpath_i);

	RTW_INFO("%s: PACKET TX tx method %d!!\n", __func__, pmp_priv->rtw_mp_tx_method);

		if (bStart) {
		RTW_INFO("%s: !! tx method %d\n", __func__, pmp_priv->rtw_mp_tx_method);
			pmp_priv->tx.sended = 0;
			pmp_priv->tx.stop = 0;
			pmp_priv->tx_pktcount = 0;
		if (pmp_priv->rtw_mp_tx_method == RTW_MP_PMACT_TX ||
				pmp_priv->rtw_mp_tx_method == RTW_MP_FW_PMACT_TX) {
				RTW_INFO("%s: PLCP_USER_INFO & PLCP_COMMON_INFO!!\n", __func__);
				if (rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_CONFIG_PLCP_USER_INFO, pmp_priv->rtw_mp_tx_method, _TRUE) == true)
					RTW_INFO("%s: PLCP_USER_INFO done!!\n", __func__);
				rtw_msleep_os(100);
				if (rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_CONFIG_PLCP_COMMON_INFO, pmp_priv->rtw_mp_tx_method, _TRUE) == true)
					RTW_INFO("%s: RTW_MP_TX_CONFIG_PLCP_COMMON_INFO done!!\n", __func__);
				rtw_msleep_os(100);
		}

		if (pmp_priv->rtw_mp_tx_method == RTW_MP_FW_PMACT_TX) {
			if (rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_PACKETS, pmp_priv->rtw_mp_tx_method, _TRUE))
				RTW_INFO("%s: RTW_MP_FW_PMACT_TX!!\n", __func__);
			else
				RTW_INFO("%s: RTW_MP_FW_PMACT_TX fail!!\n", __func__);
		} else if (pmp_priv->rtw_mp_tx_method == RTW_MP_PMACT_TX) {
			if (rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_PACKETS, pmp_priv->rtw_mp_tx_method, _TRUE))
				RTW_DBG("%s: RTW_MP_TX_PACKETS!!\n", __func__);
		} else {
			pmp_priv->tx.PktTxThread = rtw_thread_start(
									mp_xmit_phl_packet_thread, pmp_priv, "RTW_MP_Tx_THREAD");
			if (pmp_priv->tx.PktTxThread == NULL)
				RTW_ERR("Create PktTx Thread Fail !!!!!\n");
		}
	}
		if (!bStart) {
			if (pmp_priv->rtw_mp_tx_method == RTW_MP_FW_PMACT_TX) {
				if (rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_PACKETS, pmp_priv->rtw_mp_tx_method, false)) {
					RTW_INFO("%s: RTW_MP_FW_TMACT_TX Stop TX!!\n", __func__);
					return;
				}
			} else if (pmp_priv->rtw_mp_tx_method == RTW_MP_PMACT_TX) {
				if (rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_PACKETS, pmp_priv->rtw_mp_tx_method, false)) {
					RTW_INFO("%s: RTW_MP_PMACT_TX Stop TX!!\n", __func__);
					return;
				}
			}
		}
}

void rtw_mp_set_packet_tx(_adapter *padapter)
{
	u8 *ptr, *pkt_start, *pkt_end;
	u32 pkt_size = 0, i = 0, idx = 0, tmp_idx = 0;
	struct rtw_ieee80211_hdr *hdr;
	u8 payload;
	s32 bmcast;
	struct pkt_attrib *pattrib;
	struct mp_priv *pmp_priv;

	pmp_priv = &padapter->mppriv;

	if (pmp_priv->tx.stop)
		return;
	pmp_priv->tx.sended = 0;
	pmp_priv->tx.stop = 0;
	pmp_priv->tx_pktcount = 0;

	/* 3 1. update_attrib() */
	pattrib = &pmp_priv->tx.attrib;
	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
	_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
	bmcast = IS_MCAST(pattrib->ra);
	if (bmcast)
		pattrib->psta = rtw_get_bcmc_stainfo(padapter);
	else
		pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));

	if (pattrib->psta == NULL) {
		RTW_INFO("%s:psta = NULL !!\n", __func__);
		return;
	}

	pattrib->mac_id = pattrib->psta->phl_sta->macid;
	pattrib->mbssid = 0;

	pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;

	/* 3 2. allocate xmit buffer */
	pkt_size = pattrib->last_txcmdsz;

	if (pmp_priv->tx.pallocated_buf)
		rtw_mfree(pmp_priv->tx.pallocated_buf, pmp_priv->tx.buf_size);
	pmp_priv->tx.write_size = pkt_size;
	pmp_priv->tx.buf_size = pkt_size + SZ_ALIGN_XMITFRAME_EXT;
	pmp_priv->tx.pallocated_buf = rtw_zmalloc(pmp_priv->tx.buf_size);
	if (pmp_priv->tx.pallocated_buf == NULL) {
		RTW_INFO("%s: malloc(%d) fail!!\n", __func__, pmp_priv->tx.buf_size);
		return;
	}
	pmp_priv->tx.buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pmp_priv->tx.pallocated_buf), SZ_ALIGN_XMITFRAME_EXT);
	ptr = pmp_priv->tx.buf;

	_rtw_memset(pmp_priv->tx.desc, 0, TXDESC_SIZE);
	pkt_start = ptr;
	pkt_end = pkt_start + pkt_size;

	/* 3 3. init TX descriptor */
#if defined(CONFIG_RTL8822B)
	if (IS_HARDWARE_TYPE_8822B(padapter))
		rtl8822b_prepare_mp_txdesc(padapter, pmp_priv);
#endif /* CONFIG_RTL8822B */

#if defined(CONFIG_RTL8822C)
	if (IS_HARDWARE_TYPE_8822C(padapter))
		rtl8822c_prepare_mp_txdesc(padapter, pmp_priv);
#endif /* CONFIG_RTL8822C */

#if defined(CONFIG_RTL8821C)
	if (IS_HARDWARE_TYPE_8821C(padapter))
		rtl8821c_prepare_mp_txdesc(padapter, pmp_priv);
#endif /* CONFIG_RTL8821C */

#if defined(CONFIG_RTL8814B)
	if (IS_HARDWARE_TYPE_8814B(padapter))
		rtl8814b_prepare_mp_txdesc(padapter, pmp_priv);
#endif /* CONFIG_RTL8814B */

	/* 3 4. make wlan header, make_wlanhdr() */
	hdr = (struct rtw_ieee80211_hdr *)pkt_start;
	set_frame_sub_type(&hdr->frame_ctl, pattrib->subtype);

	_rtw_memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); /* DA */
	_rtw_memcpy(hdr->addr2, pattrib->src, ETH_ALEN); /* SA */
	_rtw_memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); /* RA, BSSID */

	/* 3 5. make payload */
	ptr = pkt_start + pattrib->hdrlen;

	if (pmp_priv->mplink_btx == _TRUE) {
		_rtw_memcpy(ptr, pmp_priv->mplink_buf, pkt_end - ptr);
	} else {
		switch (pmp_priv->tx.payload) {
		case MP_TX_Payload_00:
			RTW_INFO("MP packet tx 0x00 payload!\n");
			payload = 0x00;
			_rtw_memset(ptr, 0x00, pkt_end - ptr);
			break;
		case MP_TX_Payload_5a:
			RTW_INFO("MP packet tx 0x5a payload!\n");
			payload = 0x5a;
			_rtw_memset(ptr, 0x5a, pkt_end - ptr);
			break;
		case MP_TX_Payload_a5:
			RTW_INFO("MP packet tx 0xa5 payload!\n");
			payload = 0xa5;
			_rtw_memset(ptr, 0xa5, pkt_end - ptr);
			break;
		case MP_TX_Payload_ff:
			RTW_INFO("MP packet tx 0xff payload!\n");
			payload = 0xff;
			_rtw_memset(ptr, 0xff, pkt_end - ptr);
			break;
		case MP_TX_Payload_prbs9:
			RTW_INFO("MP packet tx PRBS9 payload!\n");
			while (idx <= pkt_end - ptr) {
				int start = 0x02;
				int a = start;

				for (i = 0;; i++) {
						int newbit = (((a >> 8) ^ (a >> 4)) & 1);
						a = ((a << 1) | newbit) & 0x1ff;
						RTW_DBG("%x ", a);
						ptr[idx + i] = a;

						if (a == start) {
							RTW_INFO("payload repetition period is %d , end %d\n", i , idx);
							tmp_idx += i;
							break;
						}
						if (idx + i >= (pkt_end - ptr)) {
							tmp_idx += (idx + i);
							RTW_INFO(" repetition period payload end curr ptr %d\n", idx + i);
							break;
						}
				}
				idx = tmp_idx;
			}
			break;
		case MP_TX_Payload_default_random:
			RTW_INFO("MP packet tx default random payload!\n");
			for (i = 0; i < pkt_end - ptr; i++)
				ptr[i] = rtw_random32() % 0xFF;
			break;
		default:
			RTW_INFO("Config payload type default use 0x%x\n!", pmp_priv->tx.payload);
			_rtw_memset(ptr, pmp_priv->tx.payload, pkt_end - ptr);
			break;
		}
	}
	/* 3 6. start thread */
#ifdef PLATFORM_LINUX
	pmp_priv->tx.PktTxThread = rtw_thread_start(mp_xmit_packet_thread, pmp_priv, "RTW_MP_THREAD");
	if (pmp_priv->tx.PktTxThread == NULL)
		RTW_ERR("Create PktTx Thread Fail !!!!!\n");
#endif
#ifdef PLATFORM_FREEBSD
	{
		struct proc *p;
		struct thread *td;
		pmp_priv->tx.PktTxThread = kproc_kthread_add(mp_xmit_packet_thread, pmp_priv,
			&p, &td, RFHIGHPID, 0, "MPXmitThread", "MPXmitThread");

		if (pmp_priv->tx.PktTxThread < 0)
			RTW_INFO("Create PktTx Thread Fail !!!!!\n");
	}
#endif

	Rtw_MPSetMacTxEDCA(padapter);
	return;
}

void rtw_mp_reset_phy_count(_adapter *adapter)
{
	RTW_INFO("%s()!!!\n", __func__);
	rtw_mp_phl_config_arg(adapter, RTW_MP_CONFIG_CMD_SET_RESET_PHY_COUNT);
	rtw_mp_phl_config_arg(adapter, RTW_MP_CONFIG_CMD_SET_RESET_MAC_COUNT);
	rtw_mp_phl_config_arg(adapter, RTW_MP_CONFIG_CMD_SET_RESET_DRV_COUNT);
}

struct psd_init_regs {
	/* 3 wire */
	int reg_88c;
	int reg_c00;
	int reg_e00;
	int reg_1800;
	int reg_1a00;
	/* cck */
	int reg_800;
	int reg_808;
};

static int rtw_mp_psd_init(_adapter *padapter, struct psd_init_regs *regs)
{
	u8 rf_type = GET_HAL_RFPATH(adapter_to_dvobj(padapter));
#if 0
	switch (rf_type) {
	/* 1R */
	case RF_1T1R:
		if (rtw_hw_chk_proto_cap(padapter, PROTO_CAP_11AC)) {
			/* 11AC 1R PSD Setting 3wire & cck off */
			regs->reg_c00 = rtw_read32(padapter, 0xC00);
			phy_set_bb_reg(padapter, 0xC00, 0x3, 0x00);
			regs->reg_808 = rtw_read32(padapter, 0x808);
			phy_set_bb_reg(padapter, 0x808, 0x10000000, 0x0);
		} else {
			/* 11N 3-wire off 1 */
			regs->reg_88c = rtw_read32(padapter, 0x88C);
			phy_set_bb_reg(padapter, 0x88C, 0x300000, 0x3);
			/* 11N CCK off */
			regs->reg_800 = rtw_read32(padapter, 0x800);
			phy_set_bb_reg(padapter, 0x800, 0x1000000, 0x0);
		}
	break;

	/* 2R */
	case RF_1T2R:
	case RF_2T2R:
		if (rtw_hw_chk_proto_cap(padapter, PROTO_CAP_11AC)) {
			/* 11AC 2R PSD Setting 3wire & cck off */
			regs->reg_c00 = rtw_read32(padapter, 0xC00);
			regs->reg_e00 = rtw_read32(padapter, 0xE00);
			phy_set_bb_reg(padapter, 0xC00, 0x3, 0x00);
			phy_set_bb_reg(padapter, 0xE00, 0x3, 0x00);
			regs->reg_808 = rtw_read32(padapter, 0x808);
			phy_set_bb_reg(padapter, 0x808, 0x10000000, 0x0);
		} else {
			/* 11N 3-wire off 2 */
			regs->reg_88c = rtw_read32(padapter, 0x88C);
			phy_set_bb_reg(padapter, 0x88C, 0xF00000, 0xF);
			/* 11N CCK off */
			regs->reg_800 = rtw_read32(padapter, 0x800);
			phy_set_bb_reg(padapter, 0x800, 0x1000000, 0x0);
		}
	break;

	/* 3R */
	case RF_2T3R:
	case RF_3T3R:
		if (rtw_hw_chk_proto_cap(padapter, PROTO_CAP_11AC)) {
			/* 11AC 3R PSD Setting 3wire & cck off */
			regs->reg_c00 = rtw_read32(padapter, 0xC00);
			regs->reg_e00 = rtw_read32(padapter, 0xE00);
			regs->reg_1800 = rtw_read32(padapter, 0x1800);
			phy_set_bb_reg(padapter, 0xC00, 0x3, 0x00);
			phy_set_bb_reg(padapter, 0xE00, 0x3, 0x00);
			phy_set_bb_reg(padapter, 0x1800, 0x3, 0x00);
			regs->reg_808 = rtw_read32(padapter, 0x808);
			phy_set_bb_reg(padapter, 0x808, 0x10000000, 0x0);
		} else {
			RTW_ERR("%s: 11n don't support 3R\n", __func__);
			return -1;
		}
		break;

	/* 4R */
	case RF_2T4R:
	case RF_3T4R:
	case RF_4T4R:
		if (rtw_hw_chk_proto_cap(padapter, PROTO_CAP_11AC)) {
			/* 11AC 4R PSD Setting 3wire & cck off */
			regs->reg_c00 = rtw_read32(padapter, 0xC00);
			regs->reg_e00 = rtw_read32(padapter, 0xE00);
			regs->reg_1800 = rtw_read32(padapter, 0x1800);
			regs->reg_1a00 = rtw_read32(padapter, 0x1A00);
			phy_set_bb_reg(padapter, 0xC00, 0x3, 0x00);
			phy_set_bb_reg(padapter, 0xE00, 0x3, 0x00);
			phy_set_bb_reg(padapter, 0x1800, 0x3, 0x00);
			phy_set_bb_reg(padapter, 0x1A00, 0x3, 0x00);
			regs->reg_808 = rtw_read32(padapter, 0x808);
			phy_set_bb_reg(padapter, 0x808, 0x10000000, 0x0);
		} else {
			RTW_ERR("%s: 11n don't support 4R\n", __func__);
			return -1;
		}
		break;

	default:
		RTW_ERR("%s: unknown %d rf type\n", __func__,
			GET_HAL_RFPATH(adapter_to_dvobj(padapter)));
		return -1;
	}

	/* Set PSD points, 0=128, 1=256, 2=512, 3=1024 */
	if (rtw_hw_chk_proto_cap(padapter, PROTO_CAP_11AC))
		phy_set_bb_reg(padapter, 0x910, 0xC000, 3);
	else
		phy_set_bb_reg(padapter, 0x808, 0xC000, 3);
#endif
	RTW_INFO("%s: set %d rf type done\n", __func__,
		GET_HAL_RFPATH(adapter_to_dvobj(padapter)));
	return 0;
}

static int rtw_mp_psd_close(_adapter *padapter, struct psd_init_regs *regs)
{
	u8 rf_type = GET_HAL_RFPATH(adapter_to_dvobj(padapter));

#if 0
	if (!rtw_hw_chk_proto_cap(padapter, PROTO_CAP_11AC)) {
		/* 11n 3wire restore */
		rtw_write32(padapter, 0x88C, regs->reg_88c);
		/* 11n cck restore */
		rtw_write32(padapter, 0x800, regs->reg_800);
		RTW_INFO("%s: restore %d rf type\n", __func__, rf_type);
		return 0;
	}

	/* 11ac 3wire restore */
	switch (rf_type) {
	case RF_1T1R:
		rtw_write32(padapter, 0xC00, regs->reg_c00);
		break;
	case RF_1T2R:
	case RF_2T2R:
		rtw_write32(padapter, 0xC00, regs->reg_c00);
		rtw_write32(padapter, 0xE00, regs->reg_e00);
		break;
	case RF_2T3R:
	case RF_3T3R:
		rtw_write32(padapter, 0xC00, regs->reg_c00);
		rtw_write32(padapter, 0xE00, regs->reg_e00);
		rtw_write32(padapter, 0x1800, regs->reg_1800);
		break;
	case RF_2T4R:
	case RF_3T4R:
	case RF_4T4R:
		rtw_write32(padapter, 0xC00, regs->reg_c00);
		rtw_write32(padapter, 0xE00, regs->reg_e00);
		rtw_write32(padapter, 0x1800, regs->reg_1800);
		rtw_write32(padapter, 0x1A00, regs->reg_1a00);
		break;
	default:
		RTW_WARN("%s: unknown %d rf type\n", __func__, rf_type);
		break;
	}

	/* 11ac cck restore */
	rtw_write32(padapter, 0x808, regs->reg_808);
#endif	
	RTW_INFO("%s: restore %d rf type done\n", __func__, rf_type);
	return 0;
}

/* reg 0x808[9:0]: FFT data x
 * reg 0x808[22]:  0  -->  1  to get 1 FFT data y
 * reg 0x8B4[15:0]: FFT data y report */
static u32 rtw_GetPSDData(_adapter *adapter, u32 point)
{
	u32 psd_val = 0;
#if 0
#if defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C)
	u16 psd_reg = 0x910;
	u16 psd_regL = 0xF44;
#else
	u16 psd_reg = 0x808;
	u16 psd_regL = 0x8B4;
#endif

	psd_val = rtw_read32(adapter, psd_reg);

	psd_val &= 0xFFBFFC00;
	psd_val |= point;

	rtw_write32(adapter, psd_reg, psd_val);
	rtw_mdelay_os(1);
	psd_val |= 0x00400000;

	rtw_write32(adapter, psd_reg, psd_val);
	rtw_mdelay_os(1);

	psd_val = rtw_read32(adapter, psd_regL);
#if defined(CONFIG_RTL8821C)
	psd_val = (psd_val & 0x00FFFFFF) / 32;
#else
	psd_val &= 0x0000FFFF;
#endif
#endif
	return psd_val;
}

u8 rtw_mp_phl_psd_cmd(_adapter *padapter, struct rtw_mp_cal_arg	*psd_arg, u8 cmdid)
{
	struct mp_priv	*pmppriv = &padapter->mppriv;
	u16 i = 0;
	u32 cmd_size = sizeof(struct rtw_mp_cal_arg);

	psd_arg->mp_class = RTW_MP_CLASS_CAL;
	psd_arg->cmd = cmdid;

	rtw_mp_set_phl_cmd(padapter, (void*)psd_arg, cmd_size);
	while (i <= 100) {
		rtw_msleep_os(10);
		rtw_mp_get_phl_cmd(padapter, (void*)psd_arg, cmd_size);
		if (psd_arg->cmd_ok && psd_arg->status == RTW_PHL_STATUS_SUCCESS) {
			RTW_INFO("%s,SET CMD OK\n", __func__);
			return psd_arg->cmd_ok;
		} else {
			if (i > 100) {
				RTW_DBG("%s,GET CMD FAIL !!! status %d\n", __func__, psd_arg->status);
				break;
			}
			i++;
		}
	}
	return 0;
}

/*
 * pts	start_point_min		stop_point_max
 * 128	64			64 + 128 = 192
 * 256	128			128 + 256 = 384
 * 512	256			256 + 512 = 768
 * 1024	512			512 + 1024 = 1536
 *
 */
u32 mp_query_psd(_adapter *adapter, u8 *data)
{
	struct mp_priv *pmppriv = &adapter->mppriv;
	struct rtw_mp_cal_arg	*my_psd_arg = NULL;

	u32 i, psd_pts = 0, psd_start = 0, psd_stop = 0;
	u32 fft = 0, avg = 0, iq_path = 0;
	u32 psd_data = 0;

	my_psd_arg = _rtw_malloc(sizeof(struct rtw_mp_cal_arg));

	if (my_psd_arg)
		_rtw_memset((void *)my_psd_arg, 0, sizeof(struct rtw_mp_cal_arg));
	else {
		RTW_ERR("%s() psd_arg malloc fail !\n", __func__);
		return 0;
	}

	if (sscanf(data, "fft=%d,avg=%d,iq=%d", &fft, &avg, &iq_path) == 3) {

		my_psd_arg->path = pmppriv->antenna_trx;
		my_psd_arg->iq_path = iq_path;
		my_psd_arg->avg = avg;
		my_psd_arg->fft = fft;

		RTW_INFO("%s: PSD RF_Path:%d fft=%d,avg=%d,iq_path=%d !\n",
			__func__, pmppriv->antenna_trx, fft, avg, iq_path);

		if (rtw_mp_phl_psd_cmd(adapter, my_psd_arg, RTW_MP_CAL_CMD_PSD_INIT))
			RTW_INFO("PSD_INIT CMD OK!\n");
		else
			RTW_INFO("PSD_INIT CMD FAIL!\n");
	} else if (strncmp(data, "restore", 7) == 0) {

		my_psd_arg->path = pmppriv->antenna_trx;

		if (rtw_mp_phl_psd_cmd(adapter, my_psd_arg, RTW_MP_CAL_CMD_PSD_RESTORE))
			RTW_INFO("PSD_RESTORE CMD OK!\n");
		else
			RTW_INFO("PSD_RESTORE CMD FAIL!\n");
	} else {
		if (sscanf(data, "pts=%d,start=%d,stop=%d",
			&psd_pts, &psd_start, &psd_stop) == 3) {
			my_psd_arg->upoint = psd_pts;
			my_psd_arg->start_point = psd_start;
			my_psd_arg->stop_point = psd_stop;
		} else {
			my_psd_arg->upoint = 1280;
			my_psd_arg->start_point = 640;
			my_psd_arg->stop_point = 960;
			RTW_INFO("Default PSD setting!\n");
		}

		if (rtw_mp_phl_psd_cmd(adapter, my_psd_arg, RTW_MP_CAL_CMD_PSD_QUERY))
			RTW_INFO("PSD_QUERY CMD OK!\n");
		else
			RTW_INFO("PSD_QUERY CMD FAIL!\n");

		data[0] = '\0';
		i = 0;
		while (i < 320) {
			sprintf(data, "%s%x ", data, (my_psd_arg->outbuf[i]));
			i++;
		}
	}

	if (my_psd_arg)
		_rtw_mfree(my_psd_arg, sizeof(struct rtw_mp_cal_arg));

	return strlen(data) + 1;
}

u8
mpt_to_mgnt_rate(
		u32	MptRateIdx
)
{
	/* Mapped to MGN_XXX defined in MgntGen.h */
	switch (MptRateIdx) {
	/* CCK rate. */
	case	MPT_RATE_1M:
		return MGN_1M;
	case	MPT_RATE_2M:
		return MGN_2M;
	case	MPT_RATE_55M:
		return MGN_5_5M;
	case	MPT_RATE_11M:
		return MGN_11M;

	/* OFDM rate. */
	case	MPT_RATE_6M:
		return MGN_6M;
	case	MPT_RATE_9M:
		return MGN_9M;
	case	MPT_RATE_12M:
		return MGN_12M;
	case	MPT_RATE_18M:
		return MGN_18M;
	case	MPT_RATE_24M:
		return MGN_24M;
	case	MPT_RATE_36M:
		return MGN_36M;
	case	MPT_RATE_48M:
		return MGN_48M;
	case	MPT_RATE_54M:
		return MGN_54M;

	/* HT rate. */
	case	MPT_RATE_MCS0:
		return MGN_MCS0;
	case	MPT_RATE_MCS1:
		return MGN_MCS1;
	case	MPT_RATE_MCS2:
		return MGN_MCS2;
	case	MPT_RATE_MCS3:
		return MGN_MCS3;
	case	MPT_RATE_MCS4:
		return MGN_MCS4;
	case	MPT_RATE_MCS5:
		return MGN_MCS5;
	case	MPT_RATE_MCS6:
		return MGN_MCS6;
	case	MPT_RATE_MCS7:
		return MGN_MCS7;
	case	MPT_RATE_MCS8:
		return MGN_MCS8;
	case	MPT_RATE_MCS9:
		return MGN_MCS9;
	case	MPT_RATE_MCS10:
		return MGN_MCS10;
	case	MPT_RATE_MCS11:
		return MGN_MCS11;
	case	MPT_RATE_MCS12:
		return MGN_MCS12;
	case	MPT_RATE_MCS13:
		return MGN_MCS13;
	case	MPT_RATE_MCS14:
		return MGN_MCS14;
	case	MPT_RATE_MCS15:
		return MGN_MCS15;
	case	MPT_RATE_MCS16:
		return MGN_MCS16;
	case	MPT_RATE_MCS17:
		return MGN_MCS17;
	case	MPT_RATE_MCS18:
		return MGN_MCS18;
	case	MPT_RATE_MCS19:
		return MGN_MCS19;
	case	MPT_RATE_MCS20:
		return MGN_MCS20;
	case	MPT_RATE_MCS21:
		return MGN_MCS21;
	case	MPT_RATE_MCS22:
		return MGN_MCS22;
	case	MPT_RATE_MCS23:
		return MGN_MCS23;
	case	MPT_RATE_MCS24:
		return MGN_MCS24;
	case	MPT_RATE_MCS25:
		return MGN_MCS25;
	case	MPT_RATE_MCS26:
		return MGN_MCS26;
	case	MPT_RATE_MCS27:
		return MGN_MCS27;
	case	MPT_RATE_MCS28:
		return MGN_MCS28;
	case	MPT_RATE_MCS29:
		return MGN_MCS29;
	case	MPT_RATE_MCS30:
		return MGN_MCS30;
	case	MPT_RATE_MCS31:
		return MGN_MCS31;

	/* VHT rate. */
	case	MPT_RATE_VHT1SS_MCS0:
		return MGN_VHT1SS_MCS0;
	case	MPT_RATE_VHT1SS_MCS1:
		return MGN_VHT1SS_MCS1;
	case	MPT_RATE_VHT1SS_MCS2:
		return MGN_VHT1SS_MCS2;
	case	MPT_RATE_VHT1SS_MCS3:
		return MGN_VHT1SS_MCS3;
	case	MPT_RATE_VHT1SS_MCS4:
		return MGN_VHT1SS_MCS4;
	case	MPT_RATE_VHT1SS_MCS5:
		return MGN_VHT1SS_MCS5;
	case	MPT_RATE_VHT1SS_MCS6:
		return MGN_VHT1SS_MCS6;
	case	MPT_RATE_VHT1SS_MCS7:
		return MGN_VHT1SS_MCS7;
	case	MPT_RATE_VHT1SS_MCS8:
		return MGN_VHT1SS_MCS8;
	case	MPT_RATE_VHT1SS_MCS9:
		return MGN_VHT1SS_MCS9;
	case	MPT_RATE_VHT2SS_MCS0:
		return MGN_VHT2SS_MCS0;
	case	MPT_RATE_VHT2SS_MCS1:
		return MGN_VHT2SS_MCS1;
	case	MPT_RATE_VHT2SS_MCS2:
		return MGN_VHT2SS_MCS2;
	case	MPT_RATE_VHT2SS_MCS3:
		return MGN_VHT2SS_MCS3;
	case	MPT_RATE_VHT2SS_MCS4:
		return MGN_VHT2SS_MCS4;
	case	MPT_RATE_VHT2SS_MCS5:
		return MGN_VHT2SS_MCS5;
	case	MPT_RATE_VHT2SS_MCS6:
		return MGN_VHT2SS_MCS6;
	case	MPT_RATE_VHT2SS_MCS7:
		return MGN_VHT2SS_MCS7;
	case	MPT_RATE_VHT2SS_MCS8:
		return MGN_VHT2SS_MCS8;
	case	MPT_RATE_VHT2SS_MCS9:
		return MGN_VHT2SS_MCS9;
	case	MPT_RATE_VHT3SS_MCS0:
		return MGN_VHT3SS_MCS0;
	case	MPT_RATE_VHT3SS_MCS1:
		return MGN_VHT3SS_MCS1;
	case	MPT_RATE_VHT3SS_MCS2:
		return MGN_VHT3SS_MCS2;
	case	MPT_RATE_VHT3SS_MCS3:
		return MGN_VHT3SS_MCS3;
	case	MPT_RATE_VHT3SS_MCS4:
		return MGN_VHT3SS_MCS4;
	case	MPT_RATE_VHT3SS_MCS5:
		return MGN_VHT3SS_MCS5;
	case	MPT_RATE_VHT3SS_MCS6:
		return MGN_VHT3SS_MCS6;
	case	MPT_RATE_VHT3SS_MCS7:
		return MGN_VHT3SS_MCS7;
	case	MPT_RATE_VHT3SS_MCS8:
		return MGN_VHT3SS_MCS8;
	case	MPT_RATE_VHT3SS_MCS9:
		return MGN_VHT3SS_MCS9;
	case	MPT_RATE_VHT4SS_MCS0:
		return MGN_VHT4SS_MCS0;
	case	MPT_RATE_VHT4SS_MCS1:
		return MGN_VHT4SS_MCS1;
	case	MPT_RATE_VHT4SS_MCS2:
		return MGN_VHT4SS_MCS2;
	case	MPT_RATE_VHT4SS_MCS3:
		return MGN_VHT4SS_MCS3;
	case	MPT_RATE_VHT4SS_MCS4:
		return MGN_VHT4SS_MCS4;
	case	MPT_RATE_VHT4SS_MCS5:
		return MGN_VHT4SS_MCS5;
	case	MPT_RATE_VHT4SS_MCS6:
		return MGN_VHT4SS_MCS6;
	case	MPT_RATE_VHT4SS_MCS7:
		return MGN_VHT4SS_MCS7;
	case	MPT_RATE_VHT4SS_MCS8:
		return MGN_VHT4SS_MCS8;
	case	MPT_RATE_VHT4SS_MCS9:
		return MGN_VHT4SS_MCS9;

	case	MPT_RATE_LAST:	/* fully automatiMGN_VHT2SS_MCS1;	 */
	default:
		RTW_INFO("<===mpt_to_mgnt_rate(), Invalid Rate: %d!!\n", MptRateIdx);
		return 0x0;
	}
}


u8 rtw_mp_hwrate2mptrate(u8 rate)
{
	u8	ret_rate = MGN_1M;

	switch (rate) {
	case DESC_RATE1M:
		ret_rate = MPT_RATE_1M;
		break;
	case DESC_RATE2M:
		ret_rate = MPT_RATE_2M;
		break;
	case DESC_RATE5_5M:
		ret_rate = MPT_RATE_55M;
		break;
	case DESC_RATE11M:
		ret_rate = MPT_RATE_11M;
		break;
	case DESC_RATE6M:
		ret_rate = MPT_RATE_6M;
		break;
	case DESC_RATE9M:
		ret_rate = MPT_RATE_9M;
		break;
	case DESC_RATE12M:
		ret_rate = MPT_RATE_12M;
		break;
	case DESC_RATE18M:
		ret_rate = MPT_RATE_18M;
		break;
	case DESC_RATE24M:
		ret_rate = MPT_RATE_24M;
		break;
	case DESC_RATE36M:
		ret_rate = MPT_RATE_36M;
		break;
	case DESC_RATE48M:
		ret_rate = MPT_RATE_48M;
		break;
	case DESC_RATE54M:
		ret_rate = MPT_RATE_54M;
		break;
	case DESC_RATEMCS0:
		ret_rate = MPT_RATE_MCS0;
		break;
	case DESC_RATEMCS1:
		ret_rate = MPT_RATE_MCS1;
		break;
	case DESC_RATEMCS2:
		ret_rate = MPT_RATE_MCS2;
		break;
	case DESC_RATEMCS3:
		ret_rate = MPT_RATE_MCS3;
		break;
	case DESC_RATEMCS4:
		ret_rate = MPT_RATE_MCS4;
		break;
	case DESC_RATEMCS5:
		ret_rate = MPT_RATE_MCS5;
		break;
	case DESC_RATEMCS6:
		ret_rate = MPT_RATE_MCS6;
		break;
	case DESC_RATEMCS7:
		ret_rate = MPT_RATE_MCS7;
		break;
	case DESC_RATEMCS8:
		ret_rate = MPT_RATE_MCS8;
		break;
	case DESC_RATEMCS9:
		ret_rate = MPT_RATE_MCS9;
		break;
	case DESC_RATEMCS10:
		ret_rate = MPT_RATE_MCS10;
		break;
	case DESC_RATEMCS11:
		ret_rate = MPT_RATE_MCS11;
		break;
	case DESC_RATEMCS12:
		ret_rate = MPT_RATE_MCS12;
		break;
	case DESC_RATEMCS13:
		ret_rate = MPT_RATE_MCS13;
		break;
	case DESC_RATEMCS14:
		ret_rate = MPT_RATE_MCS14;
		break;
	case DESC_RATEMCS15:
		ret_rate = MPT_RATE_MCS15;
		break;
	case DESC_RATEMCS16:
		ret_rate = MPT_RATE_MCS16;
		break;
	case DESC_RATEMCS17:
		ret_rate = MPT_RATE_MCS17;
		break;
	case DESC_RATEMCS18:
		ret_rate = MPT_RATE_MCS18;
		break;
	case DESC_RATEMCS19:
		ret_rate = MPT_RATE_MCS19;
		break;
	case DESC_RATEMCS20:
		ret_rate = MPT_RATE_MCS20;
		break;
	case DESC_RATEMCS21:
		ret_rate = MPT_RATE_MCS21;
		break;
	case DESC_RATEMCS22:
		ret_rate = MPT_RATE_MCS22;
		break;
	case DESC_RATEMCS23:
		ret_rate = MPT_RATE_MCS23;
		break;
	case DESC_RATEMCS24:
		ret_rate = MPT_RATE_MCS24;
		break;
	case DESC_RATEMCS25:
		ret_rate = MPT_RATE_MCS25;
		break;
	case DESC_RATEMCS26:
		ret_rate = MPT_RATE_MCS26;
		break;
	case DESC_RATEMCS27:
		ret_rate = MPT_RATE_MCS27;
		break;
	case DESC_RATEMCS28:
		ret_rate = MPT_RATE_MCS28;
		break;
	case DESC_RATEMCS29:
		ret_rate = MPT_RATE_MCS29;
		break;
	case DESC_RATEMCS30:
		ret_rate = MPT_RATE_MCS30;
		break;
	case DESC_RATEMCS31:
		ret_rate = MPT_RATE_MCS31;
		break;
	case DESC_RATEVHTSS1MCS0:
		ret_rate = MPT_RATE_VHT1SS_MCS0;
		break;
	case DESC_RATEVHTSS1MCS1:
		ret_rate = MPT_RATE_VHT1SS_MCS1;
		break;
	case DESC_RATEVHTSS1MCS2:
		ret_rate = MPT_RATE_VHT1SS_MCS2;
		break;
	case DESC_RATEVHTSS1MCS3:
		ret_rate = MPT_RATE_VHT1SS_MCS3;
		break;
	case DESC_RATEVHTSS1MCS4:
		ret_rate = MPT_RATE_VHT1SS_MCS4;
		break;
	case DESC_RATEVHTSS1MCS5:
		ret_rate = MPT_RATE_VHT1SS_MCS5;
		break;
	case DESC_RATEVHTSS1MCS6:
		ret_rate = MPT_RATE_VHT1SS_MCS6;
		break;
	case DESC_RATEVHTSS1MCS7:
		ret_rate = MPT_RATE_VHT1SS_MCS7;
		break;
	case DESC_RATEVHTSS1MCS8:
		ret_rate = MPT_RATE_VHT1SS_MCS8;
		break;
	case DESC_RATEVHTSS1MCS9:
		ret_rate = MPT_RATE_VHT1SS_MCS9;
		break;
	case DESC_RATEVHTSS2MCS0:
		ret_rate = MPT_RATE_VHT2SS_MCS0;
		break;
	case DESC_RATEVHTSS2MCS1:
		ret_rate = MPT_RATE_VHT2SS_MCS1;
		break;
	case DESC_RATEVHTSS2MCS2:
		ret_rate = MPT_RATE_VHT2SS_MCS2;
		break;
	case DESC_RATEVHTSS2MCS3:
		ret_rate = MPT_RATE_VHT2SS_MCS3;
		break;
	case DESC_RATEVHTSS2MCS4:
		ret_rate = MPT_RATE_VHT2SS_MCS4;
		break;
	case DESC_RATEVHTSS2MCS5:
		ret_rate = MPT_RATE_VHT2SS_MCS5;
		break;
	case DESC_RATEVHTSS2MCS6:
		ret_rate = MPT_RATE_VHT2SS_MCS6;
		break;
	case DESC_RATEVHTSS2MCS7:
		ret_rate = MPT_RATE_VHT2SS_MCS7;
		break;
	case DESC_RATEVHTSS2MCS8:
		ret_rate = MPT_RATE_VHT2SS_MCS8;
		break;
	case DESC_RATEVHTSS2MCS9:
		ret_rate = MPT_RATE_VHT2SS_MCS9;
		break;
	case DESC_RATEVHTSS3MCS0:
		ret_rate = MPT_RATE_VHT3SS_MCS0;
		break;
	case DESC_RATEVHTSS3MCS1:
		ret_rate = MPT_RATE_VHT3SS_MCS1;
		break;
	case DESC_RATEVHTSS3MCS2:
		ret_rate = MPT_RATE_VHT3SS_MCS2;
		break;
	case DESC_RATEVHTSS3MCS3:
		ret_rate = MPT_RATE_VHT3SS_MCS3;
		break;
	case DESC_RATEVHTSS3MCS4:
		ret_rate = MPT_RATE_VHT3SS_MCS4;
		break;
	case DESC_RATEVHTSS3MCS5:
		ret_rate = MPT_RATE_VHT3SS_MCS5;
		break;
	case DESC_RATEVHTSS3MCS6:
		ret_rate = MPT_RATE_VHT3SS_MCS6;
		break;
	case DESC_RATEVHTSS3MCS7:
		ret_rate = MPT_RATE_VHT3SS_MCS7;
		break;
	case DESC_RATEVHTSS3MCS8:
		ret_rate = MPT_RATE_VHT3SS_MCS8;
		break;
	case DESC_RATEVHTSS3MCS9:
		ret_rate = MPT_RATE_VHT3SS_MCS9;
		break;
	case DESC_RATEVHTSS4MCS0:
		ret_rate = MPT_RATE_VHT4SS_MCS0;
		break;
	case DESC_RATEVHTSS4MCS1:
		ret_rate = MPT_RATE_VHT4SS_MCS1;
		break;
	case DESC_RATEVHTSS4MCS2:
		ret_rate = MPT_RATE_VHT4SS_MCS2;
		break;
	case DESC_RATEVHTSS4MCS3:
		ret_rate = MPT_RATE_VHT4SS_MCS3;
		break;
	case DESC_RATEVHTSS4MCS4:
		ret_rate = MPT_RATE_VHT4SS_MCS4;
		break;
	case DESC_RATEVHTSS4MCS5:
		ret_rate = MPT_RATE_VHT4SS_MCS5;
		break;
	case DESC_RATEVHTSS4MCS6:
		ret_rate = MPT_RATE_VHT4SS_MCS6;
		break;
	case DESC_RATEVHTSS4MCS7:
		ret_rate = MPT_RATE_VHT4SS_MCS7;
		break;
	case DESC_RATEVHTSS4MCS8:
		ret_rate = MPT_RATE_VHT4SS_MCS8;
		break;
	case DESC_RATEVHTSS4MCS9:
		ret_rate = MPT_RATE_VHT4SS_MCS9;
		break;

	default:
		RTW_INFO("hwrate_to_mrate(): Non supported Rate [%x]!!!\n", rate);
		break;
	}
	return ret_rate;
}

static u16 srate2herate(u8 *str)
{

	RTW_INFO("%s(): %s!!!\n", __func__, str);
	if (!strcmp(str, "1M")) return HRATE_CCK1;
	else if (!strcmp(str, "2M")) return HRATE_CCK2;
	else if (!strcmp(str, "5.5M")) return HRATE_CCK5_5;
	else if (!strcmp(str, "11M")) return HRATE_CCK11;
	else if (!strcmp(str, "6M")) return HRATE_OFDM6;
	else if (!strcmp(str, "9M")) return HRATE_OFDM9;
	else if (!strcmp(str, "12M")) return HRATE_OFDM12;
	else if (!strcmp(str, "18M")) return HRATE_OFDM18;
	else if (!strcmp(str, "24M")) return HRATE_OFDM24;
	else if (!strcmp(str, "36M")) return HRATE_OFDM36;
	else if (!strcmp(str, "48M")) return HRATE_OFDM48;
	else if (!strcmp(str, "54M")) return HRATE_OFDM54;
	else if (!strcmp(str, "HTMCS0")) return HRATE_MCS0;
	else if (!strcmp(str, "HTMCS1")) return HRATE_MCS1;
	else if (!strcmp(str, "HTMCS2")) return HRATE_MCS2;
	else if (!strcmp(str, "HTMCS3")) return HRATE_MCS3;
	else if (!strcmp(str, "HTMCS4")) return HRATE_MCS4;
	else if (!strcmp(str, "HTMCS5")) return HRATE_MCS5;
	else if (!strcmp(str, "HTMCS6")) return HRATE_MCS6;
	else if (!strcmp(str, "HTMCS7")) return HRATE_MCS7;
	else if (!strcmp(str, "HTMCS8")) return HRATE_MCS8;
	else if (!strcmp(str, "HTMCS9")) return HRATE_MCS9;
	else if (!strcmp(str, "HTMCS10")) return HRATE_MCS10;
	else if (!strcmp(str, "HTMCS11")) return HRATE_MCS11;
	else if (!strcmp(str, "HTMCS12")) return HRATE_MCS12;
	else if (!strcmp(str, "HTMCS13")) return HRATE_MCS13;
	else if (!strcmp(str, "HTMCS14")) return HRATE_MCS14;
	else if (!strcmp(str, "HTMCS15")) return HRATE_MCS15;
	else if (!strcmp(str, "HTMCS16")) return HRATE_MCS16;
	else if (!strcmp(str, "HTMCS17")) return HRATE_MCS17;
	else if (!strcmp(str, "HTMCS18")) return HRATE_MCS18;
	else if (!strcmp(str, "HTMCS19")) return HRATE_MCS19;
	else if (!strcmp(str, "HTMCS20")) return HRATE_MCS20;
	else if (!strcmp(str, "HTMCS21")) return HRATE_MCS21;
	else if (!strcmp(str, "HTMCS22")) return HRATE_MCS22;
	else if (!strcmp(str, "HTMCS23")) return HRATE_MCS23;
	else if (!strcmp(str, "HTMCS24")) return HRATE_MCS24;
	else if (!strcmp(str, "HTMCS25")) return HRATE_MCS25;
	else if (!strcmp(str, "HTMCS26")) return HRATE_MCS26;
	else if (!strcmp(str, "HTMCS27")) return HRATE_MCS27;
	else if (!strcmp(str, "HTMCS28")) return HRATE_MCS28;
	else if (!strcmp(str, "HTMCS29")) return HRATE_MCS29;
	else if (!strcmp(str, "HTMCS30")) return HRATE_MCS30;
	else if (!strcmp(str, "HTMCS31")) return HRATE_MCS31;
	else if (!strcmp(str, "VHT1MCS0")) return HRATE_VHT_NSS1_MCS0;
	else if (!strcmp(str, "VHT1MCS1")) return HRATE_VHT_NSS1_MCS1;
	else if (!strcmp(str, "VHT1MCS2")) return HRATE_VHT_NSS1_MCS2;
	else if (!strcmp(str, "VHT1MCS3")) return HRATE_VHT_NSS1_MCS3;
	else if (!strcmp(str, "VHT1MCS4")) return HRATE_VHT_NSS1_MCS4;
	else if (!strcmp(str, "VHT1MCS5")) return HRATE_VHT_NSS1_MCS5;
	else if (!strcmp(str, "VHT1MCS6")) return HRATE_VHT_NSS1_MCS6;
	else if (!strcmp(str, "VHT1MCS7")) return HRATE_VHT_NSS1_MCS7;
	else if (!strcmp(str, "VHT1MCS8")) return HRATE_VHT_NSS1_MCS8;
	else if (!strcmp(str, "VHT1MCS9")) return HRATE_VHT_NSS1_MCS9;
	else if (!strcmp(str, "VHT2MCS0")) return HRATE_VHT_NSS2_MCS0;
	else if (!strcmp(str, "VHT2MCS1")) return HRATE_VHT_NSS2_MCS1;
	else if (!strcmp(str, "VHT2MCS2")) return HRATE_VHT_NSS2_MCS2;
	else if (!strcmp(str, "VHT2MCS3")) return HRATE_VHT_NSS2_MCS3;
	else if (!strcmp(str, "VHT2MCS4")) return HRATE_VHT_NSS2_MCS4;
	else if (!strcmp(str, "VHT2MCS5")) return HRATE_VHT_NSS2_MCS5;
	else if (!strcmp(str, "VHT2MCS6")) return HRATE_VHT_NSS2_MCS6;
	else if (!strcmp(str, "VHT2MCS7")) return HRATE_VHT_NSS2_MCS7;
	else if (!strcmp(str, "VHT2MCS8")) return HRATE_VHT_NSS2_MCS8;
	else if (!strcmp(str, "VHT2MCS9")) return HRATE_VHT_NSS2_MCS9;
	else if (!strcmp(str, "VHT3MCS0")) return HRATE_VHT_NSS3_MCS0;
	else if (!strcmp(str, "VHT3MCS1")) return HRATE_VHT_NSS3_MCS1;
	else if (!strcmp(str, "VHT3MCS2")) return HRATE_VHT_NSS3_MCS2;
	else if (!strcmp(str, "VHT3MCS3")) return HRATE_VHT_NSS3_MCS3;
	else if (!strcmp(str, "VHT3MCS4")) return HRATE_VHT_NSS3_MCS4;
	else if (!strcmp(str, "VHT3MCS5")) return HRATE_VHT_NSS3_MCS5;
	else if (!strcmp(str, "VHT3MCS6")) return HRATE_VHT_NSS3_MCS6;
	else if (!strcmp(str, "VHT3MCS7")) return HRATE_VHT_NSS3_MCS7;
	else if (!strcmp(str, "VHT3MCS8")) return HRATE_VHT_NSS3_MCS8;
	else if (!strcmp(str, "VHT3MCS9")) return HRATE_VHT_NSS3_MCS9;
	else if (!strcmp(str, "VHT4MCS0")) return HRATE_VHT_NSS4_MCS0;
	else if (!strcmp(str, "VHT4MCS1")) return HRATE_VHT_NSS4_MCS1;
	else if (!strcmp(str, "VHT4MCS2")) return HRATE_VHT_NSS4_MCS2;
	else if (!strcmp(str, "VHT4MCS3")) return HRATE_VHT_NSS4_MCS3;
	else if (!strcmp(str, "VHT4MCS4")) return HRATE_VHT_NSS4_MCS4;
	else if (!strcmp(str, "VHT4MCS5")) return HRATE_VHT_NSS4_MCS5;
	else if (!strcmp(str, "VHT4MCS6")) return HRATE_VHT_NSS4_MCS6;
	else if (!strcmp(str, "VHT4MCS7")) return HRATE_VHT_NSS4_MCS7;
	else if (!strcmp(str, "VHT4MCS8")) return HRATE_VHT_NSS4_MCS8;
	else if (!strcmp(str, "VHT4MCS9")) return HRATE_VHT_NSS4_MCS9;
	else if (!strcmp(str, "HE1MCS0")) return HRATE_HE_NSS1_MCS0;
	else if (!strcmp(str, "HE1MCS1")) return HRATE_HE_NSS1_MCS1;
	else if (!strcmp(str, "HE1MCS2")) return HRATE_HE_NSS1_MCS2;
	else if (!strcmp(str, "HE1MCS3")) return HRATE_HE_NSS1_MCS3;
	else if (!strcmp(str, "HE1MCS4")) return HRATE_HE_NSS1_MCS4;
	else if (!strcmp(str, "HE1MCS5")) return HRATE_HE_NSS1_MCS5;
	else if (!strcmp(str, "HE1MCS6")) return HRATE_HE_NSS1_MCS6;
	else if (!strcmp(str, "HE1MCS7")) return HRATE_HE_NSS1_MCS7;
	else if (!strcmp(str, "HE1MCS8")) return HRATE_HE_NSS1_MCS8;
	else if (!strcmp(str, "HE1MCS9")) return HRATE_HE_NSS1_MCS9;
	else if (!strcmp(str, "HE1MCS10")) return HRATE_HE_NSS1_MCS10;
	else if (!strcmp(str, "HE1MCS11")) return HRATE_HE_NSS1_MCS11;
	else if (!strcmp(str, "HE2MCS0")) return HRATE_HE_NSS2_MCS0;
	else if (!strcmp(str, "HE2MCS1")) return HRATE_HE_NSS2_MCS1;
	else if (!strcmp(str, "HE2MCS2")) return HRATE_HE_NSS2_MCS2;
	else if (!strcmp(str, "HE2MCS3")) return HRATE_HE_NSS2_MCS3;
	else if (!strcmp(str, "HE2MCS4")) return HRATE_HE_NSS2_MCS4;
	else if (!strcmp(str, "HE2MCS5")) return HRATE_HE_NSS2_MCS5;
	else if (!strcmp(str, "HE2MCS6")) return HRATE_HE_NSS2_MCS6;
	else if (!strcmp(str, "HE2MCS7")) return HRATE_HE_NSS2_MCS7;
	else if (!strcmp(str, "HE2MCS8")) return HRATE_HE_NSS2_MCS8;
	else if (!strcmp(str, "HE2MCS9")) return HRATE_HE_NSS2_MCS9;
	else if (!strcmp(str, "HE2MCS10")) return HRATE_HE_NSS2_MCS10;
	else if (!strcmp(str, "HE2MCS11")) return HRATE_HE_NSS2_MCS11;
	else if (!strcmp(str, "HE3MCS0")) return HRATE_HE_NSS3_MCS0;
	else if (!strcmp(str, "HE3MCS1")) return HRATE_HE_NSS3_MCS1;
	else if (!strcmp(str, "HE3MCS2")) return HRATE_HE_NSS3_MCS2;
	else if (!strcmp(str, "HE3MCS3")) return HRATE_HE_NSS3_MCS3;
	else if (!strcmp(str, "HE3MCS4")) return HRATE_HE_NSS3_MCS4;
	else if (!strcmp(str, "HE3MCS5")) return HRATE_HE_NSS3_MCS5;
	else if (!strcmp(str, "HE3MCS6")) return HRATE_HE_NSS3_MCS6;
	else if (!strcmp(str, "HE3MCS7")) return HRATE_HE_NSS3_MCS7;
	else if (!strcmp(str, "HE3MCS8")) return HRATE_HE_NSS3_MCS8;
	else if (!strcmp(str, "HE3MCS9")) return HRATE_HE_NSS3_MCS9;
	else if (!strcmp(str, "HE3MCS10")) return HRATE_HE_NSS3_MCS10;
	else if (!strcmp(str, "HE3MCS11")) return HRATE_HE_NSS3_MCS11;
	else if (!strcmp(str, "HE4MCS0")) return HRATE_HE_NSS4_MCS0;
	else if (!strcmp(str, "HE4MCS1")) return HRATE_HE_NSS4_MCS1;
	else if (!strcmp(str, "HE4MCS2")) return HRATE_HE_NSS4_MCS2;
	else if (!strcmp(str, "HE4MCS3")) return HRATE_HE_NSS4_MCS3;
	else if (!strcmp(str, "HE4MCS4")) return HRATE_HE_NSS4_MCS4;
	else if (!strcmp(str, "HE4MCS5")) return HRATE_HE_NSS4_MCS5;
	else if (!strcmp(str, "HE4MCS6")) return HRATE_HE_NSS4_MCS6;
	else if (!strcmp(str, "HE4MCS7")) return HRATE_HE_NSS4_MCS7;
	else if (!strcmp(str, "HE4MCS8")) return HRATE_HE_NSS4_MCS8;
	else if (!strcmp(str, "HE4MCS9")) return HRATE_HE_NSS4_MCS9;
	else if (!strcmp(str, "HE4MCS10")) return HRATE_HE_NSS4_MCS10;
	else if (!strcmp(str, "HE4MCS11")) return HRATE_HE_NSS4_MCS11;
	return 0;
}

#define MP_RATE_STR_NUM 132
#define MP_RATE_STR_LEN 12
const char rtw_mp_rateidx_arrdef[MP_RATE_STR_NUM][MP_RATE_STR_LEN] = {
	"1M", "2M", "5.5M", "11M", "6M", "9M", "12M", "18M", "24M", "36M", "48M", "54M",
	"HTMCS0", "HTMCS1", "HTMCS2", "HTMCS3", "HTMCS4", "HTMCS5", "HTMCS6", "HTMCS7",
	"HTMCS8", "HTMCS9", "HTMCS10", "HTMCS11", "HTMCS12", "HTMCS13", "HTMCS14", "HTMCS15",
	"HTMCS16", "HTMCS17", "HTMCS18", "HTMCS19", "HTMCS20", "HTMCS21", "HTMCS22", "HTMCS23",
	"HTMCS24", "HTMCS25", "HTMCS26", "HTMCS27", "HTMCS28", "HTMCS29", "HTMCS30", "HTMCS31",
	"VHT1MCS0", "VHT1MCS1", "VHT1MCS2", "VHT1MCS3", "VHT1MCS4",
	"VHT1MCS5", "VHT1MCS6", "VHT1MCS7", "VHT1MCS8", "VHT1MCS9",
	"VHT2MCS0", "VHT2MCS1", "VHT2MCS2", "VHT2MCS3", "VHT2MCS4",
	"VHT2MCS5", "VHT2MCS6", "VHT2MCS7", "VHT2MCS8", "VHT2MCS9",
	"VHT3MCS0", "VHT3MCS1", "VHT3MCS2", "VHT3MCS3", "VHT3MCS4",
	"VHT3MCS5", "VHT3MCS6", "VHT3MCS7", "VHT3MCS8", "VHT3MCS9",
	"VHT4MCS0", "VHT4MCS1", "VHT4MCS2", "VHT4MCS3", "VHT4MCS4",
	"VHT4MCS5", "VHT4MCS6", "VHT4MCS7", "VHT4MCS8", "VHT4MCS9",
	"HE1MCS0", "HE1MCS1", "HE1MCS2", "HE1MCS3", "HE1MCS4", "HE1MCS5",
	"HE1MCS6", "HE1MCS7", "HE1MCS8", "HE1MCS9", "HE1MCS10", "HE1MCS11",
	"HE2MCS0", "HE2MCS1", "HE2MCS2", "HE2MCS3", "HE2MCS4", "HE2MCS5",
	"HE2MCS6", "HE2MCS7", "HE2MCS8", "HE2MCS9", "HE2MCS10", "HE2MCS11",
	"HE3MCS0", "HE3MCS1", "HE3MCS2", "HE3MCS3", "HE3MCS4", "HE3MCS5",
	"HE3MCS6", "HE3MCS7", "HE3MCS8", "HE3MCS9", "HE3MCS10", "HE3MCS11",
	"HE4MCS0", "HE4MCS1", "HE4MCS2", "HE4MCS3", "HE4MCS4", "HE4MCS5",
	"HE4MCS6", "HE4MCS7", "HE4MCS8", "HE4MCS9", "HE4MCS10", "HE4MCS11"};

u16 rtw_mp_rate_parse(_adapter *adapter, u8 *target_str)
{
	struct mp_priv	*pmppriv = &adapter->mppriv;

	u16 i = 0, mcs_idx_base = 0;
	u16 hrateidx = 0;
	u8 plcp_nss = 0, ppdu_type = 0;
	u8 user_idx = pmppriv->mp_plcp_useridx;

#if 1/*def CONFIG_80211AX_HE*/
	hrateidx = srate2herate(target_str);

	if (MP_IS_1T_HRATE(hrateidx))
		plcp_nss = MP_NSS1;
	else if (MP_IS_2T_HRATE(hrateidx))
		plcp_nss = MP_NSS2;
	else if (MP_IS_3T_HRATE(hrateidx))
		plcp_nss = MP_NSS3;
	else if (MP_IS_4T_HRATE(hrateidx))
		plcp_nss = MP_NSS4;
	RTW_INFO("%s , PLCP NSS idx = %d\n", __func__ , plcp_nss);

	if (MP_IS_CCK_HRATE(hrateidx))
		ppdu_type = RTW_MP_TYPE_CCK;
	else if (MP_IS_OFDM_HRATE(hrateidx)) {
		ppdu_type = RTW_MP_TYPE_LEGACY;
		mcs_idx_base = 4;
	} else if (MP_IS_HT_HRATE(hrateidx)) {
		ppdu_type = RTW_MP_TYPE_HT_MF;
		mcs_idx_base = 12;
	} else if (MP_IS_VHT_HRATE(hrateidx)) {
		if (plcp_nss == MP_NSS1)
			mcs_idx_base = 44;
		else if (plcp_nss == MP_NSS2)
			mcs_idx_base = 44 + 10;
		else if (plcp_nss == MP_NSS3)
			mcs_idx_base = 44 + 20;
		else if (plcp_nss == MP_NSS4)
			mcs_idx_base = 44 + 30;

		ppdu_type = RTW_MP_TYPE_VHT;
	} else if (MP_IS_HE_HRATE(hrateidx)) {
		if (plcp_nss == MP_NSS1)
			mcs_idx_base = 84;
		else if (plcp_nss == MP_NSS2)
			mcs_idx_base = 84 + 12;
		else if (plcp_nss == MP_NSS3)
			mcs_idx_base = 84 + 24;
		else if (plcp_nss == MP_NSS4)
			mcs_idx_base = 84+ 36;

		ppdu_type = RTW_MP_TYPE_HE_SU;
	}

	pmppriv->mp_plcp_user[user_idx].plcp_nss = plcp_nss;
	pmppriv->rtw_mp_pmact_ppdu_type = ppdu_type;
	rtw_update_giltf(adapter);
	rtw_mp_update_coding(adapter);

		for (i = 0; i <= MP_RATE_STR_NUM; i++) {
		if (strcmp(target_str, rtw_mp_rateidx_arrdef[i+ mcs_idx_base]) == 0) {
				pmppriv->mp_plcp_user[user_idx].plcp_mcs = i;
				RTW_INFO("%s , PLCP MCS = %d\n", __func__ , pmppriv->mp_plcp_user[user_idx].plcp_mcs);
					break;
				}
		}

	if (1) {
		printk("%s ,please input a Data RATE String as:", __func__);
		for (i = 0; i <= MP_RATE_STR_NUM; i++) {
			printk("%s ", rtw_mp_rateidx_arrdef[i]);
			if (i % 10 == 0)
				printk("\n");
			}
	}
	return hrateidx;
#else
	for (i = 0; i <= MP_RATE_STR_NUM; i++) {
		if (strcmp(targetStr, rtw_mp_rateidx_arrdef[i]) == 0) {
			RTW_INFO("%s , index = %d\n", __func__ , i);
			return i;
		}
	}

	printk("%s ,please input a Data RATE String as:", __func__);
	for (i = 0; i <= MP_RATE_STR_NUM; i++) {
		printk("%s ", rtw_mp_rateidx_arrdef[i]);
		if (i % 10 == 0)
			printk("\n");
	}
	return _FAIL;
#endif
}

u8 rtw_mp_mode_check(_adapter *adapter)
{
	_adapter *primary_adapter = GET_PRIMARY_ADAPTER(adapter);

	if (primary_adapter->registrypriv.mp_mode == 1 || primary_adapter->mppriv.bprocess_mp_mode == _TRUE)
		return _TRUE;
	else
		return _FALSE;
}

bool rtw_is_mp_tssitrk_on(_adapter *adapter)
{
	_adapter *primary_adapter = GET_PRIMARY_ADAPTER(adapter);

	return primary_adapter->mppriv.tssitrk_on;
}

u32 mpt_ProQueryCalTxPower(
	_adapter *adapter,
	u8		RfPath
)
{
	PMPT_CONTEXT		pMptCtx = &(adapter->mppriv.mpt_ctx);
#if 0
	u32			TxPower = 1;
	struct txpwr_idx_comp tic;
	u8 mgn_rate = mpt_to_mgnt_rate(pMptCtx->mpt_rate_index);
	RATE_SECTION rs = mgn_rate_to_rs(mgn_rate);

	TxPower = rtw_hal_get_tx_power_index(adapter, RfPath, rs, mgn_rate
		, pHalData->current_channel_bw, pHalData->current_band_type, pHalData->current_channel, &tic);

	dump_tx_power_index_inline(RTW_DBGDUMP, RfPath
		, pHalData->current_channel_bw, pHalData->current_channel
		, mgn_rate, TxPower, &tic);

	adapter->mppriv.txpoweridx = (u8)TxPower;
	if (RfPath == RF_PATH_A)
		pMptCtx->TxPwrLevel[RF_PATH_A] = (u8)TxPower;
	else if (RfPath == RF_PATH_B)
		pMptCtx->TxPwrLevel[RF_PATH_B] = (u8)TxPower;
	else if (RfPath == RF_PATH_C)
		pMptCtx->TxPwrLevel[RF_PATH_C] = (u8)TxPower;
	else if (RfPath == RF_PATH_D)
		pMptCtx->TxPwrLevel[RF_PATH_D] = (u8)TxPower;
	hal_mpt_SetTxPower(adapter);
		return TxPower;
#endif
	return 0;
}

u32 mpt_get_tx_power_finalabs_val(_adapter *padapter, u8 rf_path)
{
	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);

	u8 mgn_rate = mpt_to_mgnt_rate(pMptCtx->mpt_rate_index);
	u32 powerdbm = 0;

#ifdef CONFIG_80211AX_HE
	struct mp_priv	*pmppriv = &padapter->mppriv;
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	u16 i = 0;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.mp_class = RTW_MP_CLASS_TXPWR;
	ptxpwr_arg.cmd = RTW_MP_TXPWR_CMD_READ_PWR_TABLE;

	ptxpwr_arg.channel = pmppriv->channel;
	ptxpwr_arg.bandwidth = pmppriv->bandwidth;
	ptxpwr_arg.rate = pmppriv->rateidx;
	ptxpwr_arg.rfpath = pmppriv->antenna_tx;
	ptxpwr_arg.beamforming = 0;
	ptxpwr_arg.dcm = 0;
	ptxpwr_arg.offset = 0;

	rtw_mp_set_phl_cmd(padapter, (void*)&ptxpwr_arg, sizeof(struct rtw_mp_txpwr_arg));

	while (i != 100) {
		rtw_msleep_os(10);
		rtw_mp_get_phl_cmd(padapter, (void*)&ptxpwr_arg, sizeof(struct rtw_mp_txpwr_arg));
		if (ptxpwr_arg.cmd_ok && ptxpwr_arg.status == RTW_PHL_STATUS_SUCCESS) {
			powerdbm = ptxpwr_arg.table_item;
			RTW_INFO("%s,SET CMD OK\n", __func__);
			break;
		} else {
			if (i > 100) {
				RTW_INFO("%s,GET CMD FAIL !!! status %d\n", __func__, ptxpwr_arg.status);
					break;
				}
			i++;
		}
	}
#else
/*
	powerdbm = phy_get_tx_power_final_absolute_value(padapter, rf_path, mgn_rate, pHalData->current_channel_bw, pHalData->current_channel);
	RTW_INFO("bw=%d, ch=%d, rateid=%d, TSSI Power(dBm):%d\n",
		pHalData->current_channel_bw, pHalData->current_channel, mgn_rate ,powerdbm);
*/
#endif
	return powerdbm;
}

u8 rtw_mpt_set_power_limit_en(_adapter *padapter, bool en_val)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	u16 i = 0;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.mp_class = RTW_MP_CLASS_TXPWR;
	ptxpwr_arg.cmd = RTW_MP_TXPWR_CMD_SET_PWR_LMT_EN;

	ptxpwr_arg.pwr_lmt_en = en_val;

	rtw_mp_set_phl_cmd(padapter, (void*)&ptxpwr_arg, sizeof(struct rtw_mp_txpwr_arg));

	while (i != 10) {
		rtw_msleep_os(10);
		rtw_mp_get_phl_cmd(padapter, (void*)&ptxpwr_arg, sizeof(struct rtw_mp_txpwr_arg));
		if (ptxpwr_arg.cmd_ok && ptxpwr_arg.status == RTW_PHL_STATUS_SUCCESS) {
			RTW_INFO("%s,SET CMD OK\n", __func__);
			return ptxpwr_arg.cmd_ok;
		} else {
			if (i > 10) {
				RTW_INFO("%s,GET CMD FAIL !!! status %d\n", __func__, ptxpwr_arg.status);
				break;
			}
			i++;
		}
	}

	return 0;
}

bool rtw_mpt_get_power_limit_en(_adapter *padapter)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	u16 i = 0;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.mp_class = RTW_MP_CLASS_TXPWR;
	ptxpwr_arg.cmd = RTW_MP_TXPWR_CMD_GET_PWR_LMT_EN;
	ptxpwr_arg.pwr_lmt_en = _FALSE;

	rtw_mp_set_phl_cmd(padapter, (void*)&ptxpwr_arg, sizeof(struct rtw_mp_txpwr_arg));

	while (i != 10) {
		rtw_msleep_os(10);
		rtw_mp_get_phl_cmd(padapter, (void*)&ptxpwr_arg, sizeof(struct rtw_mp_txpwr_arg));
		if (ptxpwr_arg.cmd_ok && ptxpwr_arg.status == RTW_PHL_STATUS_SUCCESS) {
			RTW_INFO("%s, CMD OK\n", __func__);
			return ptxpwr_arg.pwr_lmt_en;
		} else {
			if (i > 10) {
				RTW_INFO("%s,GET CMD FAIL !!! status %d\n",
					__func__, ptxpwr_arg.status);
				break;
			}
			i++;
		}
	}

	return ptxpwr_arg.pwr_lmt_en;
}

void rtw_mp_get_phl_cmd(_adapter *padapter, void* buf, u32 buflen)
{
	struct dvobj_priv	*dvobj = adapter_to_dvobj(padapter);
	struct phl_info_t	*phl_info = (struct phl_info_t *)(dvobj->phl);
	struct rtw_mp_test_cmdbuf *cmdbuf = NULL;

	if (buflen > RTW_MAX_TEST_CMD_BUF) {
		RTW_ERR("%s, buflen %d over CMD BUF Size !\n", __func__, buflen);
		return;
	}

	cmdbuf = _rtw_malloc(sizeof(struct rtw_mp_test_cmdbuf));

	if (cmdbuf) {
		_rtw_memset((void *)cmdbuf, 0, sizeof(struct rtw_mp_test_cmdbuf));
		cmdbuf->type = 0;
		cmdbuf->len = buflen;
		_rtw_memcpy((void *)cmdbuf->buf, buf, buflen);
		rtw_phl_test_submodule_get_rpt(rtw_phl_get_com(phl_info), (void *)cmdbuf, sizeof(struct rtw_mp_test_cmdbuf));
		_rtw_memcpy((void *)buf, (void *)cmdbuf->buf, buflen);
	}
	if (cmdbuf)
		_rtw_mfree(cmdbuf, sizeof(struct rtw_mp_test_cmdbuf));
}

void rtw_mp_set_phl_cmd(_adapter *padapter, void* buf, u32 buflen)
{
	struct dvobj_priv	*dvobj = adapter_to_dvobj(padapter);
	struct phl_info_t	*phl_info = (struct phl_info_t *)(dvobj->phl);
	struct rtw_mp_test_cmdbuf *cmdbuf = NULL;

	if (buflen > RTW_MAX_TEST_CMD_BUF) {
		RTW_ERR("%s, buflen %d over CMD BUF Size !\n", __func__, buflen);
		return;
	}

	cmdbuf = _rtw_malloc(sizeof(struct rtw_mp_test_cmdbuf));

	if (cmdbuf) {
		_rtw_memset((void *)cmdbuf, 0, sizeof(struct rtw_mp_test_cmdbuf));

		cmdbuf->type = 0;
		cmdbuf->len = buflen;
		_rtw_memcpy((void *)cmdbuf->buf, buf, buflen);
		rtw_phl_test_submodule_cmd_process(rtw_phl_get_com(phl_info), (void*)cmdbuf, sizeof(struct rtw_mp_test_cmdbuf));
	}
	if (cmdbuf)
		_rtw_mfree(cmdbuf, sizeof(struct rtw_mp_test_cmdbuf));
}

u8 rtw_mp_phl_txpower(_adapter *padapter, struct rtw_mp_txpwr_arg	*ptxpwr_arg, u8 cmdid)
{
	struct mp_priv	*pmppriv = &padapter->mppriv;
	u16 i = 0;

	ptxpwr_arg->mp_class = RTW_MP_CLASS_TXPWR;
	ptxpwr_arg->cmd = cmdid;

	rtw_mp_set_phl_cmd(padapter, (void*)ptxpwr_arg,  sizeof(struct rtw_mp_txpwr_arg));

	while (i <= 10) {
		rtw_msleep_os(10);
		rtw_mp_get_phl_cmd(padapter, (void*)ptxpwr_arg,  sizeof(struct rtw_mp_txpwr_arg));
		if (ptxpwr_arg->cmd_ok && ptxpwr_arg->status == RTW_PHL_STATUS_SUCCESS) {
			RTW_INFO("%s,SET CMD OK\n", __func__);
			break;
		} else {
			if (i > 10) {
				RTW_DBG("%s,GET CMD FAIL !!! status %d\n", __func__, ptxpwr_arg->status);
				break;
			}
			i++;
		}
	}

	return ptxpwr_arg->cmd_ok;
}

bool rtw_mp_phl_config_arg(_adapter *padapter, enum rtw_mp_config_cmdid cmdid)
{
	struct mp_priv	*pmppriv = &padapter->mppriv;
	struct rtw_mp_config_arg pmp_arg;
	u16 i = 0;

	_rtw_memset((void *)&pmp_arg, 0, sizeof(struct rtw_mp_config_arg));

	pmp_arg.mp_class = RTW_MP_CLASS_CONFIG;
	pmp_arg.cmd = cmdid;
	RTW_INFO("%s, id: %d !!!\n", __func__, cmdid);

	switch (cmdid) {
	case RTW_MP_CONFIG_CMD_SET_CH_BW:
		pmp_arg.channel = pmppriv->channel;
		pmp_arg.bandwidth = pmppriv->bandwidth;
		pmp_arg.sc_idx = pmppriv->prime_channel_offset;
		break;
	case RTW_MP_CONFIG_CMD_SET_RATE_IDX:
		pmp_arg.rate_idx= pmppriv->rateidx;
		break;
	case RTW_MP_CONFIG_CMD_SET_RF_TXRX_PATH:
		pmp_arg.ant_tx = pmppriv->antenna_trx;
		pmp_arg.ant_rx = pmppriv->antenna_trx;
		break;
	case RTW_MP_CONFIG_CMD_STOP_DUT:
	case RTW_MP_CONFIG_CMD_START_DUT:
	case RTW_MP_CONFIG_CMD_SET_PHY_INDEX:
		pmp_arg.cur_phy = pmppriv->rtw_mp_cur_phy;
		break;
	case RTW_MP_CONFIG_CMD_SET_RESET_PHY_COUNT:
	case RTW_MP_CONFIG_CMD_SET_RESET_MAC_COUNT:
	case RTW_MP_CONFIG_CMD_SET_RESET_DRV_COUNT:
		pmp_arg.cur_phy = pmppriv->rtw_mp_cur_phy;
		break;
	case RTW_MP_CONFIG_CMD_SWITCH_BT_PATH:
		pmp_arg.btc_mode = pmppriv->btc_path;
		break;
	default:
		RTW_INFO("%s, No CMD case match !!!\n", __func__);
		return _FALSE;
	}

	rtw_mp_set_phl_cmd(padapter, (void*)&pmp_arg,  sizeof(struct rtw_mp_config_arg));
	while (1) {
		rtw_mp_get_phl_cmd(padapter, (void*)&pmp_arg,  sizeof(struct rtw_mp_config_arg));
		if (pmp_arg.cmd_ok && pmp_arg.status == RTW_PHL_STATUS_SUCCESS) {
			RTW_INFO("%s, %d GET CMD OK !!!\n", __func__, cmdid);
			break;
		} else {
			i++;
			rtw_msleep_os(10);
			if (i == 100) {
				RTW_INFO("%s, %d GET CMD FAIL !!!\n", __func__, cmdid);
				break;
			}
		}
	}
	return pmp_arg.cmd_ok;
}

void rtw_mp_phl_rx_physts(_adapter *padapter, struct rtw_mp_rx_arg *rx_arg, bool bstart)
{
	struct mp_priv *pmppriv = &padapter->mppriv;
	u8 i = 0;

	rx_arg->mp_class = RTW_MP_CLASS_RX;
	rx_arg->cmd = RTW_MP_RX_CMD_GET_PHYSTS;
	rx_arg->enable = bstart;

	rx_arg->cmd_ok = _FALSE;
	rtw_mp_set_phl_cmd(padapter, (void*)rx_arg,  sizeof(struct rtw_mp_rx_arg));

	while (i != 10) {
			rtw_msleep_os(100);
			rtw_mp_get_phl_cmd(padapter, (void*)rx_arg,  sizeof(struct rtw_mp_rx_arg));
			if (rx_arg->cmd_ok && rx_arg->status == RTW_PHL_STATUS_SUCCESS) {
				RTW_INFO("%s,GET CMD RX OK\n", __func__);
				break;
			} else {
				if (i > 10) {
					RTW_INFO("%s,GET CMD FAIL !!! status %d\n", __func__,rx_arg->status);
					break;
				}
				i++;
			}
	}
}

void rtw_mp_phl_rx_rssi(_adapter *padapter, struct rtw_mp_rx_arg *rx_arg)
{
	struct mp_priv *pmppriv = &padapter->mppriv;
	u8 i = 0;

	rx_arg->mp_class = RTW_MP_CLASS_RX;
	rx_arg->cmd = RTW_MP_RX_CMD_GET_RSSI;

	rx_arg->cmd_ok = _FALSE;
	rtw_mp_set_phl_cmd(padapter, (void*)rx_arg,  sizeof(struct rtw_mp_rx_arg));

	while (i != 10) {
			rtw_msleep_os(100);
			rtw_mp_get_phl_cmd(padapter, (void*)rx_arg,  sizeof(struct rtw_mp_rx_arg));
			if (rx_arg->cmd_ok && rx_arg->status == RTW_PHL_STATUS_SUCCESS) {
				RTW_INFO("%s,Path%d rssi:%d GET CMD RX OK\n", __func__, rx_arg->rf_path, rx_arg->rssi);
				break;
			} else {
				if (i > 10) {
					RTW_INFO("%s,GET CMD FAIL !!! status %d\n", __func__,rx_arg->status);
					break;
				}
				i++;
			}
	}
}

void rtw_mp_phl_rx_gain_offset(_adapter *padapter, struct rtw_mp_rx_arg *rx_arg, u8 path_num)
{
	struct mp_priv *pmppriv = &padapter->mppriv;
	u8 all_path_num = path_num;
	u8 rf_path = 0;

	rx_arg->mp_class = RTW_MP_CLASS_RX;
	rx_arg->cmd = RTW_MP_RX_CMD_SET_GAIN_OFFSET;

	if (path_num > 1) {
		path_num = 0;
		all_path_num -= 1;
	}

	for (rf_path = path_num; rf_path <= all_path_num; rf_path++) {
		u16 i = 0;

		rx_arg->rf_path = rf_path;
		rx_arg->cmd_ok = _FALSE;
		rtw_mp_set_phl_cmd(padapter, (void*)rx_arg,  sizeof(struct rtw_mp_rx_arg));

		while (i != 10) {
				rtw_msleep_os(100);
				rtw_mp_get_phl_cmd(padapter, (void*)rx_arg,  sizeof(struct rtw_mp_rx_arg));
				if (rx_arg->cmd_ok && rx_arg->status == RTW_PHL_STATUS_SUCCESS) {
					RTW_INFO("%s,rf path %d GET CMD RX OK\n", __func__, rx_arg->rf_path);
					break;
				} else {
					if (i > 10) {
						RTW_INFO("%s,GET CMD FAIL !!! status %d\n", __func__,rx_arg->status);
						break;
					}
					i++;
				}
		}
	}
}


void rtw_mp_phl_query_rx(_adapter *padapter, struct rtw_mp_rx_arg *rx_arg ,u8 rx_qurey_type)
{
	struct mp_priv *pmppriv = &padapter->mppriv;
	u8 rxcmd[2] = {0, 0};
	u8 cmd_idx = 0;

	rx_arg->mp_class = RTW_MP_CLASS_RX;
	rx_arg->rx_ok = 0;
	rx_arg->rx_err = 0;

	if (rx_qurey_type == 0) {
		rxcmd[0] = RTW_MP_RX_CMD_PHY_CRC_OK;
		rxcmd[1] = RTW_MP_RX_CMD_PHY_CRC_ERR;
	} else if (rx_qurey_type == 1) {
		rxcmd[0] = RTW_MP_RX_CMD_MAC_CRC_OK;
		rxcmd[1] = RTW_MP_RX_CMD_MAC_CRC_ERR;
	} else if (rx_qurey_type == 2) {
		rxcmd[0] = RTW_MP_RX_CMD_DRV_CRC_OK;
		rxcmd[1] = RTW_MP_RX_CMD_DRV_CRC_ERR;
	}

	for (cmd_idx = 0; cmd_idx < 2 ; cmd_idx++) {
		u16 i = 0;

		rx_arg->cmd = rxcmd[cmd_idx];
		rx_arg->cmd_ok = _FALSE;
		rtw_mp_set_phl_cmd(padapter, (void*)rx_arg,  sizeof(struct rtw_mp_rx_arg));

		while (i != 10) {
				rtw_msleep_os(100);
				rtw_mp_get_phl_cmd(padapter, (void*)rx_arg,  sizeof(struct rtw_mp_rx_arg));
				if (rx_arg->cmd_ok && rx_arg->status == RTW_PHL_STATUS_SUCCESS) {
					RTW_INFO("%s,GET CMD RX OK:%d ,RX ERR:%d\n", __func__, rx_arg->rx_ok, rx_arg->rx_err);
					break;
				} else {
					if (i > 10) {
						RTW_INFO("%s,GET CMD FAIL !!! status %d\n", __func__,rx_arg->status);
						break;
					}
					i++;
				}
		}
	}
}

void rtw_mp_set_crystal_cap(_adapter *padapter, u32 xcapvalue)
{
	struct rtw_mp_reg_arg cfg_arg;
	u8 sc_xo_idx = 1;
	u8 i = 0;

	cfg_arg.mp_class = RTW_MP_CLASS_REG;
	cfg_arg.cmd = RTW_MP_REG_CMD_SET_XCAP;

	for (i <=0 ; i <= sc_xo_idx; i++) {
		cfg_arg.cmd_ok = 0;
		cfg_arg.sc_xo = i;
		cfg_arg.io_value = xcapvalue;
		rtw_mp_set_phl_cmd(padapter, (void*)&cfg_arg,  sizeof(struct rtw_mp_reg_arg));

		while (i != 10) {
				rtw_msleep_os(10);
				rtw_mp_get_phl_cmd(padapter, (void*)&cfg_arg,  sizeof(struct rtw_mp_reg_arg));
				if (cfg_arg.cmd_ok && cfg_arg.status == RTW_PHL_STATUS_SUCCESS) {
					RTW_INFO("%s,SET CMD TX OK\n", __func__);
					break;
				} else {
					if (i > 10) {
						RTW_INFO("%s,GET CMD FAIL !!! status %d\n", __func__, cfg_arg.status);
						break;
				}
				i++;
			}
		}
	}

}

u8 rtw_mp_phl_calibration(_adapter *padapter, struct rtw_mp_cal_arg	*pcal_arg, u8 cmdid)
{
	struct mp_priv	*pmppriv = &padapter->mppriv;
	u16 i = 0;
	u32 cmd_size = sizeof(struct rtw_mp_cal_arg);

	pcal_arg->mp_class = RTW_MP_CLASS_CAL;
	pcal_arg->cmd = cmdid;

	rtw_mp_set_phl_cmd(padapter, (void*)pcal_arg, cmd_size);

	while (i <= 10) {
		rtw_msleep_os(10);
		rtw_mp_get_phl_cmd(padapter, (void*)pcal_arg, cmd_size);
		if (pcal_arg->cmd_ok && pcal_arg->status == RTW_PHL_STATUS_SUCCESS) {
			RTW_INFO("%s,SET CMD OK\n", __func__);
			break;
		} else {
			if (i > 10) {
				RTW_DBG("%s,GET CMD FAIL !!! status %d\n", __func__, pcal_arg->status);
				break;
			}
			i++;
		}
	}

	return pcal_arg->cmd_ok;
}

u8 rtw_mp_phl_reg(_adapter *padapter, struct rtw_mp_reg_arg	*reg_arg, u8 cmdid)
{
	struct mp_priv	*pmppriv = &padapter->mppriv;
	u16 i = 0;
	u32 cmd_size = sizeof(struct rtw_mp_reg_arg);

	reg_arg->mp_class = RTW_MP_CLASS_REG;
	reg_arg->cmd = cmdid;

	rtw_mp_set_phl_cmd(padapter, (void*)reg_arg, cmd_size);

	while (i <= 10) {
		rtw_msleep_os(10);
		rtw_mp_get_phl_cmd(padapter, (void*)reg_arg, cmd_size);
		if (reg_arg->cmd_ok && reg_arg->status == RTW_PHL_STATUS_SUCCESS) {
			RTW_INFO("%s,SET CMD OK\n", __func__);
			break;
		} else {
			if (i > 10) {
				RTW_DBG("%s,GET CMD FAIL !!! status %d\n", __func__, reg_arg->status);
				break;
			}
			i++;
		}
	}

	return reg_arg->cmd_ok;
}


u8 rtw_update_giltf(_adapter *padapter)
{
	struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv;
	u8 idx = 0;
	u8 ppdu_type = pmp_priv->rtw_mp_pmact_ppdu_type;
	u8 user_idx = pmp_priv->mp_plcp_useridx;

	RTW_INFO("%s: ppdu_type=%s\n", __func__ , PPDU_TYPE_STR(pmp_priv->rtw_mp_pmact_ppdu_type));
	if (ppdu_type == RTW_MP_TYPE_HT_MF || ppdu_type == RTW_MP_TYPE_HT_GF
										|| ppdu_type == RTW_MP_TYPE_VHT) {
		pmp_priv->st_giltf[0].gi = 0;
		pmp_priv->st_giltf[0].ltf = 0;
		strcpy(pmp_priv->st_giltf[0].type_str, "0.4");
		pmp_priv->st_giltf[1].gi = 1;
		pmp_priv->st_giltf[1].ltf = 0;
		strcpy(pmp_priv->st_giltf[1].type_str, "0.8");
		idx = 1;
	} else if (ppdu_type > RTW_MP_TYPE_VHT) {
		if (ppdu_type == RTW_MP_TYPE_HE_SU || ppdu_type == RTW_MP_TYPE_HE_ER_SU) {

			if (!pmp_priv->mp_plcp_user[user_idx].dcm && !pmp_priv->rtw_mp_stbc) {
				pmp_priv->st_giltf[0].gi = 1;
				pmp_priv->st_giltf[0].ltf = 0;
				strcpy(pmp_priv->st_giltf[0].type_str, "1x 0.8");
				pmp_priv->st_giltf[1].gi = 1;
				pmp_priv->st_giltf[1].ltf = 1;
				strcpy(pmp_priv->st_giltf[1].type_str, "2x 0.8");
				pmp_priv->st_giltf[2].gi = 2;
				pmp_priv->st_giltf[2].ltf = 1;
				strcpy(pmp_priv->st_giltf[2].type_str, "2x 1.6");
				pmp_priv->st_giltf[3].gi = 3;
				pmp_priv->st_giltf[3].ltf = 2;
				strcpy(pmp_priv->st_giltf[3].type_str, "4x 3.2");
				pmp_priv->st_giltf[4].gi = 1;
				pmp_priv->st_giltf[4].ltf = 2;
				strcpy(pmp_priv->st_giltf[4].type_str, "4x 0.8");
				idx = 4;
			} else {
				pmp_priv->st_giltf[0].gi = 1;
				pmp_priv->st_giltf[0].ltf = 0;
				strcpy(pmp_priv->st_giltf[0].type_str, "1x 0.8");
				pmp_priv->st_giltf[1].gi = 1;
				pmp_priv->st_giltf[1].ltf = 1;
				strcpy(pmp_priv->st_giltf[1].type_str, "2x 0.8");
				pmp_priv->st_giltf[2].gi = 2;
				pmp_priv->st_giltf[2].ltf = 1;
				strcpy(pmp_priv->st_giltf[2].type_str, "2x 1.6");
				pmp_priv->st_giltf[3].gi = 3;
				pmp_priv->st_giltf[3].ltf = 2;
				strcpy(pmp_priv->st_giltf[3].type_str, "4x 3.2");
				idx = 3;
			}
		}else if (ppdu_type == RTW_MP_TYPE_HE_MU_OFDMA) {
			pmp_priv->st_giltf[0].gi = 1;
			pmp_priv->st_giltf[0].ltf = 1;
			strcpy(pmp_priv->st_giltf[0].type_str, "2x 0.8");
			pmp_priv->st_giltf[1].gi = 2;
			pmp_priv->st_giltf[1].ltf = 1;
			strcpy(pmp_priv->st_giltf[1].type_str, "2x 1.6");
			pmp_priv->st_giltf[2].gi = 1;
			pmp_priv->st_giltf[2].ltf = 2;
			strcpy(pmp_priv->st_giltf[2].type_str, "4x 0.8");
			pmp_priv->st_giltf[3].gi = 3;
			pmp_priv->st_giltf[3].ltf = 2;
			strcpy(pmp_priv->st_giltf[3].type_str, "4x 3.2");
			idx = 3;
		} else if (ppdu_type == RTW_MP_TYPE_HE_TB) {
				pmp_priv->st_giltf[0].gi = 2;
				pmp_priv->st_giltf[0].ltf = 0;
				strcpy(pmp_priv->st_giltf[0].type_str, "1x 1.6");
				pmp_priv->st_giltf[1].gi = 2;
				pmp_priv->st_giltf[1].ltf = 1;
				strcpy(pmp_priv->st_giltf[1].type_str, "2x 1.6");
				pmp_priv->st_giltf[2].gi = 3;
				pmp_priv->st_giltf[2].ltf = 2;
				strcpy(pmp_priv->st_giltf[2].type_str, "4x 3.2");
				idx = 2;
			}
		}
	return idx;
}

void rtw_mp_update_coding(_adapter *padapter)
{
	struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv;
	u8 ppdu_type = pmp_priv->rtw_mp_pmact_ppdu_type;
	u8 user_idx = pmp_priv->mp_plcp_useridx;

	if (ppdu_type == RTW_MP_TYPE_HE_SU || pmp_priv->bandwidth >= CHANNEL_WIDTH_40 ||
		pmp_priv->rtw_mp_ru_tone >= MP_RU_TONE_484) {

		RTW_INFO("%s, PPDU HE SU , over 40M, RU Tone over 484\n", __func__);
		pmp_priv->mp_plcp_user[user_idx].coding = 1;/* 1 LDPC, 0 BCC */
	} else if (ppdu_type == RTW_MP_TYPE_HE_MU_OFDMA) {

		RTW_INFO("%s, PPDU HE MU\n", __func__);
		pmp_priv->mp_plcp_user[user_idx].coding = 0;/* 1 LDPC, 0 BCC */
	}

	RTW_INFO("%s, coding: %s\n", __func__, (pmp_priv->mp_plcp_user[user_idx].coding?"LDPC":"BCC"));
}

u8 rtw_mp_update_ru_tone(_adapter *padapter)
{
	struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv;
	u8 user_idx = pmp_priv->mp_plcp_useridx;
	u8 cur_coding = pmp_priv->mp_plcp_user[user_idx].coding;
	u8 ruidx = MP_RU_TONE_26;
	u8 i = 0 , j = 0;

	if (cur_coding == 0) {/* 1 LDPC, 0 BCC */
		ruidx = MP_RU_TONE_242;
		if (pmp_priv->rtw_mp_ru_tone < MP_RU_TONE_242)
			pmp_priv->rtw_mp_ru_tone = MP_RU_TONE_242;
	} else {
		ruidx = MP_RU_TONE_26;
	}

	for (i = 0; i <= 5; i++) {
		pmp_priv->ru_tone_sel_list[i] = ruidx++;
		if (ruidx > MP_RU_TONE_966)
			break;
	}
	return i;
}

u8 rtw_mp_update_ru_alloc(_adapter *padapter)
{
	struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv;
	u8 cur_tone = pmp_priv->rtw_mp_ru_tone;
	u8 i = 0;
	u8 alloc_start = 0, alloc_end = 0;
	u8 user_idx = pmp_priv->mp_plcp_useridx;

	switch (cur_tone) {
	case MP_RU_TONE_26:
					alloc_start = 0;
					alloc_end = 9;
					if (pmp_priv->bandwidth == CHANNEL_WIDTH_40)
						alloc_end = 18;

					if (pmp_priv->bandwidth == CHANNEL_WIDTH_80)
						alloc_end = 37;
					break;
	case MP_RU_TONE_52:
					alloc_start = 37;
					alloc_end = 41;
					if (pmp_priv->bandwidth == CHANNEL_WIDTH_40)
						alloc_end = 45;

					if (pmp_priv->bandwidth == CHANNEL_WIDTH_80)
						alloc_end = 53;

					break;
	case MP_RU_TONE_106:
					alloc_start = 53;
					alloc_end = 55;

					if (pmp_priv->bandwidth == CHANNEL_WIDTH_40)
						alloc_end = 57;

					if (pmp_priv->bandwidth == CHANNEL_WIDTH_80)
						alloc_end = 61;

					break;
	case MP_RU_TONE_242:
					alloc_start = 61;
					alloc_end = 61;
					if (pmp_priv->bandwidth == CHANNEL_WIDTH_40)
						alloc_end = 62;

					if (pmp_priv->bandwidth == CHANNEL_WIDTH_80)
						alloc_end = 64;

					break;
	case MP_RU_TONE_484:
					alloc_start = 65;
					alloc_end = 66;
					break;
	case MP_RU_TONE_966:
					alloc_start = 67;
					alloc_end = 67;
					break;
	};

	if (pmp_priv->mp_plcp_user[user_idx].ru_alloc < alloc_start ||
			pmp_priv->mp_plcp_user[user_idx].ru_alloc > alloc_end)
		pmp_priv->mp_plcp_user[user_idx].ru_alloc = alloc_start;

	for (i = 0; i < 68; i++) {
		if (alloc_start + i > alloc_end)
			break;
		pmp_priv->ru_alloc_list[i] = alloc_start + i;
		RTW_INFO("%s, Ru alloc:%d\n", __func__, pmp_priv->ru_alloc_list[i]);

	}
	return i;
}

u32 rtw_mp_get_tssi_de(_adapter *padapter, u8 rf_path)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	struct mp_priv *pmppriv = &padapter->mppriv;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.rfpath = rf_path;

	if (rtw_mp_phl_txpower(padapter, &ptxpwr_arg, RTW_MP_TXPWR_CMD_GET_TSSI))
		return ptxpwr_arg.tssi;
	else
		return 0;
}

s32 rtw_mp_get_online_tssi_de(_adapter *padapter, s32 out_pwr, s32 tgdbm, u8 rf_path)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	struct mp_priv *pmppriv = &padapter->mppriv;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.dbm = tgdbm;
	ptxpwr_arg.pout = out_pwr;
	ptxpwr_arg.rfpath = rf_path;

	if (rtw_mp_phl_txpower(padapter, &ptxpwr_arg, RTW_MP_TXPWR_CMD_GET_ONLINE_TSSI_DE))
		return ptxpwr_arg.online_tssi_de;
	else
		return 0;
}

u8 rtw_mp_set_tsside2verify(_adapter *padapter, u32 tssi_de, u8 rf_path)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	struct mp_priv *pmppriv = &padapter->mppriv;
	u8 tx_nss = get_phy_tx_nss(padapter);
	u8 i = 0;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.tssi = tssi_de;
	ptxpwr_arg.rfpath = rf_path;

	if (rtw_mp_phl_txpower(padapter, &ptxpwr_arg, RTW_MP_TXPWR_CMD_SET_TSSI))
		return true;
	else
		return false;
}

u8 rtw_mp_set_tssi_offset(_adapter *padapter, u32 tssi_offset, u8 rf_path)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	struct mp_priv *pmppriv = &padapter->mppriv;
	u8 tx_nss = get_phy_tx_nss(padapter);
	u8 i = 0;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.tssi_de_offset = tssi_offset;
	ptxpwr_arg.rfpath = rf_path;

	if (rtw_mp_phl_txpower(padapter, &ptxpwr_arg, RTW_MP_TXPWR_CMD_SET_TSSI_OFFSET))
		return true;
	else
		return false;
}

u8 rtw_mp_set_tssi_pwrtrk(_adapter *padapter, u8 tssi_state)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	ptxpwr_arg.txpwr_track_status = tssi_state;

	if (rtw_mp_phl_txpower(padapter, &ptxpwr_arg, RTW_MP_TXPWR_CMD_SET_PWR_TRACK_STATUS))
		return true;
	else
		return false;
}

u8 rtw_mp_get_tssi_pwrtrk(_adapter *padapter)
{
	struct rtw_mp_txpwr_arg	ptxpwr_arg;
	u8	tssi_state = RTW_MP_TSSI_OFF;

	_rtw_memset((void *)&ptxpwr_arg, 0, sizeof(struct rtw_mp_txpwr_arg));

	if (rtw_mp_phl_txpower(padapter, &ptxpwr_arg, RTW_MP_TXPWR_CMD_GET_PWR_TRACK_STATUS)) {
		tssi_state = ptxpwr_arg.txpwr_track_status;
		RTW_INFO("%s, get tssi_state = %d\n", __func__, tssi_state);
	} else
		RTW_INFO("%s, rtw_mp_phl_txpower fail\n", __func__);

	return tssi_state;
}

#endif
