/*
 ***************************************************************************
 * MediaTek Inc.
 *
 * All rights reserved. source code is an unpublished work and the
 * use of a copyright notice does not imply otherwise. This source code
 * contains confidential trade secret material of MediaTek. Any attemp
 * or participation in deciphering, decoding, reverse engineering or in any
 * way altering the source code is stricitly prohibited, unless the prior
 * written consent of MediaTek, Inc. is obtained.
 ***************************************************************************

	Module Name:
	andes_mt.c
*/

#include	"rt_config.h"

#ifdef RTMP_SDIO_SUPPORT
INT32 AndesMTSendCmdMsgToSdio(PRTMP_ADAPTER pAd)
{
	INT32 Ret = 0;
	struct MCU_CTRL *ctl = &pAd->MCUCtrl;
	PNDIS_PACKET NetPkt = NULL;
	struct cmd_msg *msg = NULL;

	while ((msg = AndesDequeueCmdMsg(ctl, &ctl->txq_sdio)) != NULL) {
		if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD)
				|| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)
				|| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_SUSPEND)) {
			if (!msg->need_wait)
				AndesFreeCmdMsg(msg);
			continue;
		}

		if (AndesQueueLen(ctl, &ctl->ackq) > 0) {
			AndesQueueHeadCmdMsg(&ctl->txq_sdio, msg, msg->state);
			Ret = NDIS_STATUS_FAILURE;
			continue;
		}

		NetPkt = msg->net_pkt;

		/* send to SDIO host */
		Ret = MTSDIOCmdTx(pAd, GET_OS_PKT_DATAPTR(NetPkt), 
											GET_OS_PKT_LEN(NetPkt));

		if (Ret)
		{
			msg->state = tx_sdio_fail;
			DBGPRINT(RT_DEBUG_ERROR, ("kick out cmd to sdio host fail\n"));
			RTMP_OS_COMPLETE(&msg->tx_sdio_done);
			break;
		}
		else
		{
			msg->state = tx_sdio_ok;
			DBGPRINT(RT_DEBUG_TRACE, ("kick out cmd to sdio host ok\n"));
		}

		RTMP_OS_COMPLETE(&msg->tx_sdio_done);
	}

	return Ret;
}


static INT32 AndesMTSdioSubmitCmdMsgToSDIOWorker(PRTMP_ADAPTER pAd, struct cmd_msg *msg)
{
	INT32 Ret = 0;
	struct MCU_CTRL *ctl = &pAd->MCUCtrl;
	POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;

	AndesQueueTailCmdMsg(&ctl->txq_sdio, msg, msg->state);

	MTSDIOAddWorkerTaskList(pAd);
	queue_work(pObj->SdioWq, &pObj->SdioWork); 
	
	/* Wait for SDIO tx timeout */
	if (!AndesWaitForSdioCompleteTimeout(msg, msg->tx_sdio_timeout)) {
		DBGPRINT(RT_DEBUG_ERROR, ("%s: Wait for SDIO tx timeout(%d)\n", __FUNCTION__,
											msg->tx_sdio_timeout));

		AndesUnlinkCmdMsg(msg, &ctl->txq_sdio);
		Ret = -1;
	}
	else
	{
		if (msg->state == tx_sdio_ok)
		{
			Ret = 0;
		}
		else
		{
			Ret = -1;
		}
	}

	return Ret;
}


INT32 AndesMTSdioKickOutCmdMsg(PRTMP_ADAPTER pAd, struct cmd_msg *msg)
{
	struct MCU_CTRL *ctl = &pAd->MCUCtrl;
	INT32 Ret = 0;
	PNDIS_PACKET net_pkt = msg->net_pkt;

	if (!OS_TEST_BIT(MCU_INIT, &ctl->flags))
		return -1;

	if (msg->state != tx_retransmit) {
		/* 
 		 * append to meet block unit and zero four bytes padding 
 		 * when using sdio block mode 
 		 */
		memset(OS_PKT_TAIL_BUF_EXTEND(net_pkt, ctl->SDIOPadSize), 0x00, SDIO_END_PADDING);
	}

	Ret = AndesMTSdioSubmitCmdMsgToSDIOWorker(pAd, msg);

	if (msg->need_wait)
		AndesQueueTailCmdMsg(&ctl->ackq, msg, wait_cmd_out_and_ack);
	else
		AndesQueueTailCmdMsg(&ctl->kickq, msg, wait_cmd_out);

	if (Ret) {
		if (!msg->need_wait) {
			AndesUnlinkCmdMsg(msg, &ctl->kickq);
			AndesQueueTailCmdMsg(&ctl->tx_doneq, msg, tx_kickout_fail);
			AndesIncErrorCount(ctl, error_tx_kickout_fail);
		} else {
			AndesUnlinkCmdMsg(msg, &ctl->ackq);
			msg->state = tx_kickout_fail;
			AndesIncErrorCount(ctl, error_tx_kickout_fail);
			RTMP_OS_COMPLETE(&msg->ack_done);
		}

		DBGPRINT(RT_DEBUG_ERROR, ("%s:submit cmd msg to SDIO host fail(%d)\n", __FUNCTION__, Ret));
	}

	return Ret;
}


INT32 AndesMTSdioChkCrc(RTMP_ADAPTER *pAd, UINT32 checksum_len)
{


}


UINT16 AndesMTSdioGetCrc(RTMP_ADAPTER *pAd)
{




}
#endif


#ifdef RTMP_USB_SUPPORT
INT32 AndesMTUsbChkCrc(RTMP_ADAPTER *ad, UINT32 checksum_len)
{
	int ret = 0;
	UINT8 cmd[8];
	RTMP_CHIP_CAP *cap = &ad->chipCap;

	DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__));

	NdisMoveMemory(cmd, &cap->rom_patch_offset, 4);
	NdisMoveMemory(&cmd[4], &checksum_len, 4);

	ret = RTUSB_VendorRequest(ad,
							  USBD_TRANSFER_DIRECTION_OUT,
							  DEVICE_VENDOR_REQUEST_OUT,
							  0x01,
							  0x20,
							  0x00,
							  cmd,
							  8);

	return ret;

}


UINT16 AndesMTUsbGetCrc(RTMP_ADAPTER *ad)
{
	//int ret = 0;
	UINT16 crc, count = 0;

	while (1) {

		/*ret = */RTUSB_VendorRequest(ad,
								 (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
								 DEVICE_VENDOR_REQUEST_IN,
								 0x01,
								 0x21,
								 0x00,
								 &crc,
								 2);

		if (crc != 0xFFFF)
			break;

		RtmpOsMsDelay(100);

		if (count++ > 100) {
			DBGPRINT(RT_DEBUG_ERROR, ("Query CRC over %d times\n", count));
			break;
		}
	}

	return crc;
}


INT32 AndesMTUSBKickOutCmdMsg(PRTMP_ADAPTER ad, struct cmd_msg *msg)
{
	struct MCU_CTRL *ctl = &ad->MCUCtrl;
	POS_COOKIE pObj = (POS_COOKIE)ad->OS_Cookie;
	int ret = 0;
	PNDIS_PACKET net_pkt = msg->net_pkt;
	RTMP_CHIP_CAP *pChipCap = &ad->chipCap;

	if (msg->state != tx_retransmit) {
		/* append four zero bytes padding when usb aggregate enable */
		memset(OS_PKT_TAIL_BUF_EXTEND(net_pkt, USB_END_PADDING), 0x00, USB_END_PADDING);
	}

	RTUSB_FILL_BULK_URB(msg->urb, pObj->pUsb_Dev,
						usb_sndbulkpipe(pObj->pUsb_Dev, pChipCap->CommandBulkOutAddr),
						GET_OS_PKT_DATAPTR(net_pkt), GET_OS_PKT_LEN(net_pkt), UsbKickOutCmdMsgComplete, net_pkt);

	if (msg->need_wait)
		AndesQueueTailCmdMsg(&ctl->ackq, msg, wait_cmd_out_and_ack);
	else
		AndesQueueTailCmdMsg(&ctl->kickq, msg, wait_cmd_out);

	if (!OS_TEST_BIT(MCU_INIT, &ctl->flags))
		return -1;
	OS_SET_BIT(MCU_TX_IN_PROGRESS, &ctl->flags);

#ifdef USB_IOT_WORKAROUND2
	if (ad->bUSBIOTReady)
		usb_iot_add_padding(msg->urb, msg->usb_iot_w2_buf, NULL);
#endif
	ret = RTUSB_SUBMIT_URB(msg->urb);

	if (ret) {
		OS_CLEAR_BIT(MCU_TX_IN_PROGRESS, &ctl->flags);
		if (!msg->need_wait) {
			AndesUnlinkCmdMsg(msg, &ctl->kickq);
			AndesQueueTailCmdMsg(&ctl->tx_doneq, msg, tx_kickout_fail);
			AndesIncErrorCount(ctl, error_tx_kickout_fail);
		} else {
			AndesUnlinkCmdMsg(msg, &ctl->ackq);
			msg->state = tx_kickout_fail;
			AndesIncErrorCount(ctl, error_tx_kickout_fail);
			RTMP_OS_COMPLETE(&msg->ack_done);
		}

		DBGPRINT(RT_DEBUG_ERROR, ("%s:submit urb fail(%d)\n", __FUNCTION__, ret));
	}

	return ret;
}
#endif /* RTMP_USB_SUPPORT */

#ifdef RTMP_PCI_SUPPORT
INT32 AndesMTPciKickOutCmdMsg(PRTMP_ADAPTER pAd, struct cmd_msg *msg)
{
	int ret = NDIS_STATUS_SUCCESS;
	unsigned long flags = 0;
	ULONG FreeNum;
	PNDIS_PACKET net_pkt = msg->net_pkt;
	UINT32 SwIdx = 0;
	UCHAR *pSrcBufVA;
	UINT SrcBufLen = 0;
	PACKET_INFO PacketInfo;
	TXD_STRUC *pTxD;
	struct MCU_CTRL *ctl = &pAd->MCUCtrl;
#ifdef RT_BIG_ENDIAN
	TXD_STRUC *pDestTxD;
	UCHAR tx_hw_info[TXD_SIZE];
#endif

	if (!OS_TEST_BIT(MCU_INIT, &ctl->flags))
		return -1;

	FreeNum = GET_CTRLRING_FREENO(pAd);

	if (FreeNum == 0) {
		DBGPRINT(RT_DEBUG_WARN, ("%s FreeNum == 0 (TxCpuIdx = %d, TxDmaIdx = %d, TxSwFreeIdx = %d)\n",
		__FUNCTION__, pAd->CtrlRing.TxCpuIdx, pAd->CtrlRing.TxDmaIdx, pAd->CtrlRing.TxSwFreeIdx));
		return NDIS_STATUS_FAILURE;
	}

	RTMP_SPIN_LOCK_IRQSAVE(&pAd->CtrlRingLock, &flags);

	RTMP_QueryPacketInfo(net_pkt, &PacketInfo, &pSrcBufVA, &SrcBufLen);

	if (pSrcBufVA == NULL) {
		RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->CtrlRingLock, &flags);
		return NDIS_STATUS_FAILURE;
	}

	SwIdx = pAd->CtrlRing.TxCpuIdx;

#ifdef RT_BIG_ENDIAN
	pDestTxD  = (TXD_STRUC *)pAd->CtrlRing.Cell[SwIdx].AllocVa;
	NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE);
 	pTxD = (TXD_STRUC *)&tx_hw_info[0];
#else
	pTxD  = (TXD_STRUC *)pAd->CtrlRing.Cell[SwIdx].AllocVa;
#endif

#ifdef RT_BIG_ENDIAN
	RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
#endif /* RT_BIG_ENDIAN */

	pAd->CtrlRing.Cell[SwIdx].pNdisPacket = net_pkt;
	pAd->CtrlRing.Cell[SwIdx].pNextNdisPacket = NULL;

	pAd->CtrlRing.Cell[SwIdx].PacketPa = PCI_MAP_SINGLE(pAd, (pSrcBufVA) , (SrcBufLen), 0, RTMP_PCI_DMA_TODEVICE);

	pTxD->LastSec0 = 1;
	pTxD->LastSec1 = 0;
	pTxD->SDLen0 = SrcBufLen;
	pTxD->SDLen1 = 0;
	pTxD->SDPtr0 = pAd->CtrlRing.Cell[SwIdx].PacketPa;
	pTxD->Burst = 0;
	pTxD->DMADONE = 0;

#ifdef RT_BIG_ENDIAN
	RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
	WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
#endif

	/* flush dcache if no consistent memory is supported */
	RTMP_DCACHE_FLUSH(SrcBufPA, SrcBufLen);
	RTMP_DCACHE_FLUSH(pAd->CtrlRing.Cell[SwIdx].AllocPa, TXD_SIZE);

   	/* Increase TX_CTX_IDX, but write to register later.*/
	INC_RING_INDEX(pAd->CtrlRing.TxCpuIdx, MGMT_RING_SIZE);

	if (msg->need_wait)
		AndesQueueTailCmdMsg(&ctl->ackq, msg, wait_ack);
	else
		AndesQueueTailCmdMsg(&ctl->tx_doneq, msg, tx_done);

	if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) {
		RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->CtrlRingLock, &flags);
		return -1;
	}

	RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_cidx_addr, pAd->CtrlRing.TxCpuIdx);

	RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->CtrlRingLock, &flags);

	return ret;
}
#endif /* RTMP_PCI_SUPPORT */

VOID AndesMTFillCmdHeader(struct cmd_msg *msg, PNDIS_PACKET net_pkt)
{
	FW_TXD *fw_txd;
	RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv;
	struct MCU_CTRL *Ctl = &pAd->MCUCtrl;

	if ((Ctl->Stage == FW_NO_INIT) || (Ctl->Stage == FW_DOWNLOAD) || (Ctl->Stage == ROM_PATCH_DOWNLOAD))
		fw_txd = (FW_TXD *)OS_PKT_HEAD_BUF_EXTEND(net_pkt, 12);
	else if (Ctl->Stage == FW_RUN_TIME)
		fw_txd = (FW_TXD *)OS_PKT_HEAD_BUF_EXTEND(net_pkt, sizeof(*fw_txd));
	else
	{
		DBGPRINT(RT_DEBUG_OFF, ("%s: Unknown Control Stage(%d)\n", __FUNCTION__,
								Ctl->Stage));
		return;
	}

	fw_txd->fw_txd_0.field.length = GET_OS_PKT_LEN(net_pkt);
	fw_txd->fw_txd_0.field.pq_id = msg->pq_id;
	fw_txd->fw_txd_1.field.cid = msg->cmd_type;
	fw_txd->fw_txd_1.field.pkt_type_id = PKT_ID_CMD;
	fw_txd->fw_txd_1.field.set_query = msg->set_query;
	fw_txd->fw_txd_1.field.seq_num = msg->seq;
	fw_txd->fw_txd_2.field.ext_cid =  msg->ext_cmd_type;

	if ((msg->cmd_type == EXT_CID) && ((msg->set_query == CMD_SET) || (msg->set_query == CMD_QUERY))
									&& (msg->need_rsp == TRUE))
	{
		fw_txd->fw_txd_2.field.ext_cid_option = EXT_CID_OPTION_NEED_ACK;
	}
	else
	{
		fw_txd->fw_txd_2.field.ext_cid_option = EXT_CID_OPTION_NO_NEED_ACK;
	}

	fw_txd->fw_txd_0.word = cpu2le32(fw_txd->fw_txd_0.word);
	fw_txd->fw_txd_1.word = cpu2le32(fw_txd->fw_txd_1.word);
	fw_txd->fw_txd_2.word = cpu2le32(fw_txd->fw_txd_2.word);

#ifdef CONFIG_TRACE_SUPPORT
	TRACE_MCU_CMD_INFO(fw_txd->fw_txd_0.field.length, fw_txd->fw_txd_0.field.pq_id,
						fw_txd->fw_txd_1.field.cid, fw_txd->fw_txd_1.field.pkt_type_id,
						fw_txd->fw_txd_1.field.set_query, fw_txd->fw_txd_1.field.seq_num,
						fw_txd->fw_txd_2.field.ext_cid, fw_txd->fw_txd_2.field.ext_cid_option,
						(char *)(GET_OS_PKT_DATAPTR(net_pkt)), GET_OS_PKT_LEN(net_pkt));
#endif /* CONFIG_TRACE_SUPPORT */
}


INT32 CmdInitAccessRegWrite(RTMP_ADAPTER *ad, UINT32 address, UINT32 data)
{
	struct cmd_msg *msg;
	struct _INIT_CMD_ACCESS_REG access_reg;
	INT32 ret = 0;

	DBGPRINT(RT_DEBUG_INFO, ("%s: address = %x, data = %x\n", __FUNCTION__, address, data));

	msg = AndesAllocCmdMsg(ad, sizeof(struct _INIT_CMD_ACCESS_REG));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, INIT_CMD_ACCESS_REG, CMD_SET, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);

	memset(&access_reg, 0x00, sizeof(access_reg));

	access_reg.ucSetQuery = 1;
	access_reg.u4Address = cpu2le32(address);
	access_reg.u4Data = cpu2le32(data);

	AndesAppendCmdMsg(msg, (char *)&access_reg, sizeof(access_reg));

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


static VOID CmdInitAccessRegReadCb(struct cmd_msg *msg, char *data, UINT16 len)
{
	struct _INIT_EVENT_ACCESS_REG *access_reg = (struct _INIT_EVENT_ACCESS_REG *)data;

	NdisMoveMemory(msg->rsp_payload, &access_reg->u4Data, len - 4);
	*((UINT32 *)(msg->rsp_payload)) = le2cpu32(*((UINT32 *)msg->rsp_payload));
}


INT32 CmdInitAccessRegRead(RTMP_ADAPTER *pAd, UINT32 address, UINT32 *data)
{
	struct cmd_msg *msg;
	struct _INIT_CMD_ACCESS_REG access_reg;
	INT32 ret = 0;

	DBGPRINT(RT_DEBUG_INFO, ("%s: address = %x\n", __FUNCTION__, address));

	msg = AndesAllocCmdMsg(pAd, sizeof(struct _INIT_CMD_ACCESS_REG));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, INIT_CMD_ACCESS_REG, CMD_QUERY, EXT_CMD_NA, TRUE, 0,
							TRUE, TRUE, 8, (CHAR *)data, CmdInitAccessRegReadCb);

	memset(&access_reg, 0x00, sizeof(access_reg));

	access_reg.ucSetQuery = 0;
	access_reg.u4Address = cpu2le32(address);

	AndesAppendCmdMsg(msg, (char *)&access_reg, sizeof(access_reg));

	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


static VOID CmdReStartDLRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	FW_RXD_2 Status;
	Status = *(FW_RXD_2 *)Data;

	
	switch (Status.field.ext_eid)
	{
		case WIFI_FW_DOWNLOAD_SUCCESS:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFI FW Download Success\n", __FUNCTION__));
			break;
		case WIFI_FW_DOWNLOAD_INVALID_PARAM:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Invalid Parameter\n", __FUNCTION__));
			break;
		case WIFI_FW_DOWNLOAD_INVALID_CRC:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Invalid CRC\n", __FUNCTION__));
			break;
		case WIFI_FW_DOWNLOAD_DECRYPTION_FAIL:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Decryption Fail\n", __FUNCTION__));
			break;
		case WIFI_FW_DOWNLOAD_UNKNOWN_CMD:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Unknown CMD\n", __FUNCTION__));
			break;
		case WIFI_FW_DOWNLOAD_TIMEOUT:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Timeout\n", __FUNCTION__));
			break;
		default:
			DBGPRINT(RT_DEBUG_OFF, ("%s: Unknow Status(%u)\n", __FUNCTION__, Status.field.ext_eid));
			break;
	}
}


static VOID CmdSecKeyRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	P_EVENT_SEC_ADDREMOVE_STRUC_T EvtSecKey;
	UINT32 Status;
	UINT32 WlanIndex;

	EvtSecKey = (struct _EVENT_SEC_ADDREMOVE_STRUC_T *)Data;

	Status = le2cpu32(EvtSecKey->u4Status);
	WlanIndex = le2cpu32(EvtSecKey->u4WlanIdx);

	if (Status != 0) {
		DBGPRINT(RT_DEBUG_ERROR, ("%s, error set key, wlan idx(%d), status: 0x%x\n", __FUNCTION__, WlanIndex, Status));
	} else {
		DBGPRINT(RT_DEBUG_TRACE, ("%s, wlan idx(%d), status: 0x%x\n", __FUNCTION__, WlanIndex, Status));
	}
}

#if 1 /* Leonardo: TODO: Should be removed */
static VOID CmdPsRetrieveRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{

	P_EXT_EVENT_AP_PS_RETRIEVE_T EvtPsCapatibility;
	UINT32 Status;

    EvtPsCapatibility = (P_EXT_EVENT_AP_PS_RETRIEVE_T)Data;
        Status = le2cpu32(EvtPsCapatibility->u4Param1);

   DBGPRINT(RT_DEBUG_ERROR, ("%s Disable FW PS Supportstatus:%x !!!!!\n",__FUNCTION__,Status));

}
#endif

#ifdef MT_PS
#if defined(MT7603) && defined(RTMP_PCI_SUPPORT)
static VOID CmdPsRetrieveStartRspFromCR(RTMP_ADAPTER *pAd, char *Data, UINT16 Len)
{
	MAC_TABLE_ENTRY *pEntry;
	P_EXT_EVENT_AP_PS_RETRIEVE_T EvtPsRetrieveStart;
	UINT32 WlanIdx;
	STA_TR_ENTRY *tr_entry;
	NDIS_STATUS token_status;
	unsigned char q_idx;
	struct tx_swq_fifo *ps_fifo_swq;
	UINT deq_qid;
	//unsigned long IrqFlags;

   EvtPsRetrieveStart = (P_EXT_EVENT_AP_PS_RETRIEVE_T)Data;
   WlanIdx = le2cpu32(EvtPsRetrieveStart->u4Param1);

   if (!(VALID_TR_WCID(WlanIdx))) {
		DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("---->%s INVALID_TR_WCID(WlanIndex)\n", __FUNCTION__));
		goto NEXT;
   }

   pEntry = &pAd->MacTab.Content[WlanIdx];
	tr_entry = &pAd->MacTab.tr_entry[WlanIdx];	
	if (IS_ENTRY_NONE(pEntry))
	{
		DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("---->%s Entry(wcid=%d) left.\n", __FUNCTION__, WlanIdx));
		goto NEXT;
	}
   
	DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("---->%s: Start to send TOKEN frames, WlanIdx=%d\n", __FUNCTION__, WlanIdx));

	if (tr_entry->ps_state != APPS_RETRIEVE_START_PS)
	{
		DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("---->%s Entry(wcid=%d) ps state(%d) is not APPS_RETRIEVE_START_PS\n", __FUNCTION__, WlanIdx, tr_entry->ps_state));
		goto NEXT;
	}

	tr_entry->ps_state = APPS_RETRIEVE_GOING;
	CheckSkipTX(pAd, pEntry);
	tr_entry->ps_qbitmap = 0;

	for (q_idx = 0; q_idx < NUM_OF_TX_RING; q_idx++)
	{
		UINT16 IsEmpty = IS_TXRING_EMPTY(pAd, q_idx);

		if (!IsEmpty)
		{
			token_status = RtmpEnqueueTokenFrame(pAd, &(pEntry->Addr[0]), 0, WlanIdx, 0, q_idx);
			if (!token_status)
				tr_entry->ps_qbitmap |= (1 << q_idx);
			else
				DBGPRINT(RT_DEBUG_ERROR, ("%s(%d) Fail:	Send TOKEN Frame, AC=%d\n", __FUNCTION__, __LINE__, q_idx));
		}
	}

	if (tr_entry->ps_qbitmap == 0)
	{
		q_idx = QID_AC_VO;

		token_status = RtmpEnqueueTokenFrame(pAd, &(pEntry->Addr[0]), 0, WlanIdx, 0, q_idx);
		
		if (!token_status)
			tr_entry->ps_qbitmap |= (1 << q_idx);
	}

	if (tr_entry->ps_qbitmap == 0)
	{
		tr_entry->ps_state = APPS_RETRIEVE_WAIT_EVENT;
		tr_entry->token_enq_all_fail = TRUE;
		RTEnqueueInternalCmd(pAd, CMDTHREAD_PS_CLEAR, (VOID *)&WlanIdx, sizeof(UINT32));
		DBGPRINT(RT_DEBUG_WARN | DBG_FUNC_PS, ("%s(%d): (ps_state = %d) token_enq_all_fail!! ==> send CMDTHREAD_PS_CLEAR cmd.\n", 
			__FUNCTION__, __LINE__, tr_entry->ps_state));
	}
	else
	{
		tr_entry->token_enq_all_fail = FALSE;
	}
   
NEXT:
	ps_fifo_swq = &pAd->apps_cr_q;
	deq_qid = ps_fifo_swq->deqIdx;
	while (ps_fifo_swq->swq[deq_qid] != 0) {
		WlanIdx = ps_fifo_swq->swq[deq_qid];
		pEntry = &pAd->MacTab.Content[WlanIdx];
   tr_entry = &pAd->MacTab.tr_entry[WlanIdx];

		if (pEntry->PsMode == PWR_ACTIVE) {
			ps_fifo_swq->swq[deq_qid]  = 0;
			INC_RING_INDEX(ps_fifo_swq->deqIdx, TX_SWQ_FIFO_LEN);	
			tr_entry->ps_state = APPS_RETRIEVE_IDLE;
			MtHandleRxPsPoll(pAd, &pEntry->Addr[0], WlanIdx, TRUE);
			deq_qid = ps_fifo_swq->deqIdx;
		} else {
			if (MtStartPSRetrieve(pAd, ps_fifo_swq->swq[deq_qid]) == TRUE) {
				ps_fifo_swq->swq[deq_qid]  = 0;
				INC_RING_INDEX(ps_fifo_swq->deqIdx, TX_SWQ_FIFO_LEN);	
				tr_entry->ps_state = APPS_RETRIEVE_START_PS;
			}
			break;
		}
	}
}
#endif /* MT7603 && RTMP_PCI_SUPPORT  */

VOID AndesPsRetrieveStartRsp(RTMP_ADAPTER *pAd, char *Data, UINT16 Len)
	{
	MAC_TABLE_ENTRY *pEntry;
	P_EXT_EVENT_AP_PS_RETRIEVE_T EvtPsRetrieveStart;
	UINT32 WlanIdx;
	STA_TR_ENTRY *tr_entry;
	NDIS_STATUS token_status;
	unsigned char q_idx;

	EvtPsRetrieveStart = (P_EXT_EVENT_AP_PS_RETRIEVE_T)Data;
	WlanIdx = le2cpu32(EvtPsRetrieveStart->u4Param1);

	if (!(VALID_TR_WCID(WlanIdx))) {
		DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("---->%s INVALID_TR_WCID(WlanIndex)\n", __FUNCTION__));
      return;
   }

	pEntry = &pAd->MacTab.Content[WlanIdx];
	tr_entry = &pAd->MacTab.tr_entry[WlanIdx];
	if (IS_ENTRY_NONE(pEntry))
	{
		DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("---->%s Entry(wcid=%d) left.\n", __FUNCTION__, WlanIdx));
		return;
	}

	DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("---->%s: Start to send TOKEN frames, WlanIdx=%d\n", __FUNCTION__, WlanIdx));

   tr_entry->ps_state = APPS_RETRIEVE_GOING;
	tr_entry->ps_qbitmap = 0;

	for (q_idx = 0; q_idx < NUM_OF_TX_RING; q_idx++)
	   {
		   //UINT16 IsEmpty = IS_TXRING_EMPTY(pAd, q_idx);
		   UINT16 IsEmpty = (pAd->TxRing[q_idx].TxDmaIdx == pAd->TxRing[q_idx].TxCpuIdx) ? 1: 0;

		   if (!IsEmpty)
		   {
			   token_status = RtmpEnqueueTokenFrame(pAd, &(pEntry->Addr[0]), 0, WlanIdx, 0, q_idx);

   if (!token_status)
			   {
				   tr_entry->ps_qbitmap |= (1 << q_idx);
			   }
   else
			   {
				   DBGPRINT(RT_DEBUG_ERROR, ("%s(%d) Fail: Send TOKEN Frame, AC=%d\n", __FUNCTION__, __LINE__, q_idx));
			   }
		   }
	   }

	   if (tr_entry->ps_qbitmap == 0)
	   {
		   q_idx = QID_AC_VO;

		   token_status = RtmpEnqueueTokenFrame(pAd, &(pEntry->Addr[0]), 0, WlanIdx, 0, q_idx); 	   

   if (!token_status)
			   tr_entry->ps_qbitmap |= (1 << q_idx);
	   }

	   if (tr_entry->ps_qbitmap == 0)
	   {
		   tr_entry->ps_state = APPS_RETRIEVE_WAIT_EVENT;
		   tr_entry->token_enq_all_fail = TRUE;
		   RTEnqueueInternalCmd(pAd, CMDTHREAD_PS_CLEAR, (VOID *)&WlanIdx, sizeof(UINT32));
		   DBGPRINT(RT_DEBUG_WARN | DBG_FUNC_PS, ("%s(%d): (ps_state = %d) token_enq_all_fail!! ==> send CMDTHREAD_PS_CLEAR cmd.\n", 
			   __FUNCTION__, __LINE__, tr_entry->ps_state)); 
	   }
   else
	   {
		   tr_entry->token_enq_all_fail = FALSE;
	   }
}

static VOID CmdPsRetrieveStartRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	RTMP_ADAPTER *ad = NULL;

	ad = (RTMP_ADAPTER *)msg->priv;

	DBGPRINT(RT_DEBUG_ERROR, ("------> %s(%d)\n", __FUNCTION__, __LINE__));
#ifdef RTMP_PCI_SUPPORT
	AndesPsRetrieveStartRsp(ad, Data, Len);
#endif /* RTMP_PCI_SUPPORT */
	
#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT)
	/*
		We need to move AndesPsRetrieveStartRsp to cmd thread for CR read/write.
	*/
	RTEnqueueInternalCmd(ad, CMDTHREAD_PS_RETRIEVE_RSP, Data, Len);
#endif /* defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) */
	DBGPRINT(RT_DEBUG_ERROR, ("<------ %s(%d)\n", __FUNCTION__, __LINE__));
}


static VOID CmdPsClearRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	//UINT8 Status;
    MAC_TABLE_ENTRY *pEntry;
	//QUEUE_ENTRY *pQEntry;
	P_CMD_AP_PS_CLEAR_STRUC_T EvtPsClear;
	RTMP_ADAPTER *ad = (RTMP_ADAPTER *)msg->priv;
	STA_TR_ENTRY *tr_entry;
	//unsigned long IrqFlags;
	//struct wtbl_entry tb_entry;
	UINT32 WlanIndex;
	//union WTBL_1_DW3 *dw3 = (union WTBL_1_DW3 *)&tb_entry.wtbl_1.wtbl_1_d3.word;
	unsigned char q_idx = 0;

	EvtPsClear = (struct _CMD_AP_PS_CLEAR_STRUC_T *)Data;
	WlanIndex = le2cpu32(EvtPsClear->u4WlanIdx);
        pEntry = &ad->MacTab.Content[WlanIndex];
	tr_entry = &ad->MacTab.tr_entry[WlanIndex];


	if (ad->MacTab.tr_entry[WlanIndex].PsMode == PWR_ACTIVE)
      tr_entry->ps_state = APPS_RETRIEVE_IDLE;
   else
      tr_entry->ps_state = APPS_RETRIEVE_DONE;

   DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("wcid=%d, Receive Event of CmdPsClear tr_entry->ps_state=%d\n", WlanIndex,tr_entry->ps_state));

	if(tr_entry->token_enq_all_fail)
	{
		tr_entry->token_enq_all_fail = FALSE;

		if (tr_entry->ps_queue.Number) 
			MtEnqTxSwqFromPsQueue(ad, q_idx, tr_entry);

		for (q_idx = 0; q_idx < NUM_OF_TX_RING; q_idx++)
		{
			if (q_idx < WMM_QUE_NUM)
				tr_entry->TokenCount[q_idx] = tr_entry->tx_queue[q_idx].Number;
			else
				break;
		}
	}

#ifdef RTMP_MAC_PCI
#ifdef DOT11_N_SUPPORT
   SendRefreshBAR(ad, pEntry);
#endif /* DOT11_N_SUPPORT */
#endif /* RTMP_MAC_PCI */
   if (tr_entry->ps_state == APPS_RETRIEVE_IDLE)
      MtHandleRxPsPoll(ad, &pEntry->Addr[0], WlanIndex, TRUE);
#ifdef UAPSD_SUPPORT
	else
	{
		if (tr_entry->bEospNullSnd)
		{
			//UINT32	AcQueId;

			tr_entry->bEospNullSnd = FALSE;
			/* sanity Check for UAPSD condition */
			if (tr_entry->EospNullUp >= 8)
				tr_entry->EospNullUp = 1; /* shout not be here */

			/* get the AC ID of incoming packet */
			//AcQueId = WMM_UP2AC_MAP[tr_entry->EospNullUp];
			
			/* bQosNull = bEOSP = TRUE = 1 */

			/*
				Use management queue to tx QoS Null frame to avoid delay so
				us_of_frame is not used.
			*/
			RtmpEnqueueNullFrame(ad, pEntry->Addr, pEntry->CurrTxRate,
								pEntry->Aid, pEntry->func_tb_idx, TRUE, TRUE, tr_entry->EospNullUp);

#ifdef UAPSD_DEBUG
			DBGPRINT(RT_DEBUG_ERROR, ("%s: send a EOSP QoS Null frame!\n", __FUNCTION__));
#endif /* UAPSD_DEBUG */
		}
		else if (pEntry->UAPSDTxNum != 0)
		{
			RTMPDeQueuePacket(ad, TRUE, NUM_OF_TX_RING, pEntry->wcid, pEntry->UAPSDTxNum);
		}
	}
#endif /* UAPSD_SUPPORT */
}
#endif /* MT_PS */

static VOID CmdStartDLRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	UINT8 Status;

	Status = *Data;

	switch (Status)
	{
		case WIFI_FW_DOWNLOAD_SUCCESS:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFI FW Download Success\n", __FUNCTION__));
			break;
		case WIFI_FW_DOWNLOAD_INVALID_PARAM:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Invalid Parameter\n", __FUNCTION__));
			break;
		case WIFI_FW_DOWNLOAD_INVALID_CRC:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Invalid CRC\n", __FUNCTION__));
			break;
		case WIFI_FW_DOWNLOAD_DECRYPTION_FAIL:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Decryption Fail\n", __FUNCTION__));
			break;
		case WIFI_FW_DOWNLOAD_UNKNOWN_CMD:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Unknown CMD\n", __FUNCTION__));
			break;
		case WIFI_FW_DOWNLOAD_TIMEOUT:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Timeout\n", __FUNCTION__));
			break;
		default:
			DBGPRINT(RT_DEBUG_OFF, ("%s: Unknow Status(%d)\n", __FUNCTION__, Status));
			break;
	}
}

INT32 CmdSecKeyReq(RTMP_ADAPTER *ad, UINT8 AddRemove, UINT8 Keytype, UINT8 *pAddr, UINT8 Alg, UINT8 KeyID, UINT8 KeyLen, UINT8 WlanIdx, UINT8 *KeyMaterial)
{
	struct cmd_msg *msg;
	struct _CMD_SEC_ADDREMOVE_KEY_STRUC_T CmdSecKey;
	int ret = 0;

	msg = AndesAllocCmdMsg(ad, sizeof(struct _CMD_SEC_ADDREMOVE_KEY_STRUC_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_SEC_ADDREMOVE_KEY, FALSE, 0, FALSE, TRUE, sizeof(struct _EVENT_SEC_ADDREMOVE_STRUC_T), NULL, CmdSecKeyRsp);

	memset(&CmdSecKey, 0x00, sizeof(CmdSecKey));

	CmdSecKey.ucAddRemove = AddRemove;
	CmdSecKey.ucKeyType = Keytype;
	memcpy(CmdSecKey.aucPeerAddr, pAddr, 6);
	CmdSecKey.ucAlgorithmId = Alg;
	CmdSecKey.ucKeyId = KeyID;
	CmdSecKey.ucKeyLen = KeyLen;
	memcpy(CmdSecKey.aucKeyMaterial, KeyMaterial, KeyLen);
	CmdSecKey.ucWlanIndex = WlanIdx;
	AndesAppendCmdMsg(msg, (char *)&CmdSecKey, sizeof(CmdSecKey));

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}

INT32 CmdPsRetrieveReq(RTMP_ADAPTER *ad, UINT32 enable)
{
   	struct cmd_msg *msg;
      struct _CMD_AP_PS_RETRIEVE_T CmdPsCapatibility;

      int ret = 0;

      msg = AndesAllocCmdMsg(ad, sizeof(struct _CMD_AP_PS_RETRIEVE_T));

      if (!msg)
      {
         ret = NDIS_STATUS_RESOURCES;
         goto error;
      }

      AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_AP_PWR_SAVING_CAPABILITY, TRUE, 0, TRUE, TRUE, sizeof(struct _CMD_AP_PS_RETRIEVE_T), NULL, CmdPsRetrieveRsp);

      NdisZeroMemory(&CmdPsCapatibility, sizeof(CmdPsCapatibility));

      CmdPsCapatibility.u4Option=  cpu2le32(0);
      CmdPsCapatibility.u4Param1=  cpu2le32(enable);

      AndesAppendCmdMsg(msg, (char *)&CmdPsCapatibility, sizeof(CmdPsCapatibility));
      ret = AndesSendCmdMsg(ad, msg);

error:
      DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
   	return ret;
}

#ifdef MT_PS
INT32 CmdPsRetrieveStartReq(RTMP_ADAPTER *ad, UINT32 WlanIdx)
{
   struct cmd_msg *msg;
   struct _EXT_CMD_AP_PWS_START_T CmdApPwsStart;

   int ret = 0;

   /*how to handle memory allocate failure? */
   msg = AndesAllocCmdMsg(ad, sizeof(struct _EXT_CMD_AP_PWS_START_T));
   if (!msg)
   {
      ret = NDIS_STATUS_RESOURCES;
	DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("%s:(ret = %d)\n", __FUNCTION__, ret));
      goto error;
   }

   DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d): RTEnqueueInternalCmd comming!! WlanIdx: %x\n",__FUNCTION__, __LINE__,WlanIdx));

   AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_PS_RETRIEVE_START, TRUE, 0, TRUE, TRUE, sizeof(struct _EXT_CMD_AP_PWS_START_T), NULL, CmdPsRetrieveStartRsp);

   NdisZeroMemory(&CmdApPwsStart, sizeof(CmdApPwsStart));

   CmdApPwsStart.u4WlanIdx= cpu2le32(WlanIdx);

   AndesAppendCmdMsg(msg, (char *)&CmdApPwsStart, sizeof(CmdApPwsStart));
   msg->wcid = WlanIdx;
   ret = AndesSendCmdMsg(ad, msg);

error:
   	return ret;
}



INT32 CmdPsClearReq(RTMP_ADAPTER *ad, UINT32 wlanidx, BOOLEAN p_wait)
{
	struct cmd_msg *msg;
	struct _CMD_AP_PS_CLEAR_STRUC_T CmdPsClear;
	int ret = 0;

	msg = AndesAllocCmdMsg(ad, sizeof(struct _CMD_AP_PS_CLEAR_STRUC_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
	DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("%s:(ret = %d)\n", __FUNCTION__, ret));
		goto error;
	}

	DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d): RTEnqueueInternalCmd comming!! WlanIdx: %x\n",__FUNCTION__, __LINE__,wlanidx));

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_PWR_SAVING, TRUE, 0, TRUE, TRUE, sizeof(struct _CMD_AP_PS_CLEAR_STRUC_T), NULL, CmdPsClearRsp);

	NdisZeroMemory(&CmdPsClear, sizeof(CmdPsClear));

	CmdPsClear.u4WlanIdx = cpu2le32(wlanidx);
	CmdPsClear.u4Status = cpu2le32(0);

	AndesAppendCmdMsg(msg, (char *)&CmdPsClear, sizeof(CmdPsClear));
	msg->wcid = wlanidx;
	ret = AndesSendCmdMsg(ad, msg);

error:
	return ret;
}
#endif /* MT_PS */

static INT32 CmdRestartDLReq(RTMP_ADAPTER *ad)
{
	struct cmd_msg *msg;
	int ret = 0;

	msg = AndesAllocCmdMsg(ad, 0);

	if (!msg) {
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, MT_RESTART_DL_REQ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdReStartDLRsp);

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}

/*Nobody uses it currently*/
#if 0
static VOID CmdPatchSemRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv;
	struct MCU_CTRL *Ctl = &pAd->MCUCtrl;

	Ctl->SemStatus = *Data;

	DBGPRINT(RT_DEBUG_OFF,("Patch SEM Status=%d\n", Ctl->SemStatus));
}


static INT32 CmdPatchSemGet(RTMP_ADAPTER *ad, UINT32 Semaphore)
{
	struct cmd_msg *msg;
	int ret = 0;
	UINT32 value;

	msg = AndesAllocCmdMsg(ad, 4);

	if (!msg) {
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, MT_PATCH_SEM_CONTROL, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdPatchSemRsp);

	/* Semaphore */
	value = cpu2le32(Semaphore);
	AndesAppendCmdMsg(msg, (char *)&value, 4);

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}

static VOID CmdHIFLoopbackRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	UINT8 Status;

	Status = *Data;

	printk("HIF Loopback status=%d\n", Status);
	switch (Status)
	{
		case TARGET_ADDRESS_LEN_SUCCESS:
			DBGPRINT(RT_DEBUG_INFO, ("%s: Request target address and length success\n", __FUNCTION__));
			break;
		default:
			DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Status(%d)\n", __FUNCTION__, Status));
			break;
	}
}


static INT32 CmdHIFLoopbackReq(RTMP_ADAPTER *ad, UINT32 enable, UINT32 qidx)
{
	struct cmd_msg *msg;
	int ret = 0;
	UINT32 value;

	msg = AndesAllocCmdMsg(ad, 4);

	if (!msg) {
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, MT_HIF_LOOPBACK, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdHIFLoopbackRsp);

	/* start enable */
	enable = (qidx << 16) | (enable & 0xffff);
	value = cpu2le32(enable);
	printk("loopback value=0x%x\n", value);

	AndesAppendCmdMsg(msg, (char *)&value, 4);

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}
#endif

static VOID CmdAddrellLenRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	UINT8 Status;

	Status = *Data;

	switch (Status)
	{
		case TARGET_ADDRESS_LEN_SUCCESS:
			DBGPRINT(RT_DEBUG_INFO, ("%s: Request target address and length success\n", __FUNCTION__));
			break;
		default:
			DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Status(%d)\n", __FUNCTION__, Status));
			break;
	}
}


static INT32 CmdAddressLenReq(RTMP_ADAPTER *ad, UINT32 address, UINT32 len, UINT32 data_mode)
{
	struct cmd_msg *msg;
	int ret = 0;
	UINT32 value;

	DBGPRINT(RT_DEBUG_TRACE, ("Start address = %x, DL length = %d, Data mode = %x\n",
									address, len, data_mode));
	msg = AndesAllocCmdMsg(ad, 12);

	if (!msg) {
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	if (address == ROM_PATCH_START_ADDRESS)
		AndesInitCmdMsg(msg, P1_Q0, MT_PATCH_START_REQ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdAddrellLenRsp);
	else
		AndesInitCmdMsg(msg, P1_Q0, MT_TARGET_ADDRESS_LEN_REQ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdAddrellLenRsp);

	/* start address */
	value = cpu2le32(address);
	AndesAppendCmdMsg(msg, (char *)&value, 4);

	/* dl length */
	value = cpu2le32(len);
	AndesAppendCmdMsg(msg, (char *)&value, 4);

	/* data mode */
	value = cpu2le32(data_mode);
	AndesAppendCmdMsg(msg, (char *)&value, 4);

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}

static INT32 CmdFwScatter(RTMP_ADAPTER *ad, UINT8 *dl_payload, UINT32 dl_len, UINT32 count)
{
	struct cmd_msg *msg;
	int ret = 0;

	msg = AndesAllocCmdMsg(ad, dl_len);

	if (!msg) {
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, 0xC000, MT_FW_SCATTER, CMD_NA, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);

	AndesAppendCmdMsg(msg, (char *)dl_payload, dl_len);

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(scatter = %d, ret = %d)\n", __FUNCTION__, count, ret));
	return ret;
}

static INT32 CmdFwScatters(RTMP_ADAPTER *ad, UINT8 *image, UINT32 image_len)
{
	INT32 sent_len;
	UINT32 cur_len = 0, count = 0;
	RTMP_CHIP_CAP *cap = &ad->chipCap;
	int ret = 0;

	while (1)
	{
		INT32 sent_len_max = MT_UPLOAD_FW_UNIT - cap->cmd_header_len;
		sent_len = (image_len - cur_len) >=  sent_len_max ? sent_len_max : (image_len - cur_len);

		if (sent_len > 0) {
			ret = CmdFwScatter(ad, image + cur_len, sent_len, count);
			count++;
			if (ret)
				goto error;
			cur_len += sent_len;
		} else {
			break;
		}
	}

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


static VOID CmdPatchFinishRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	UINT8 Status;

	Status = *Data;

	switch (Status)
	{
		case WIFI_FW_DOWNLOAD_SUCCESS:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFI ROM Patch Download Success\n", __FUNCTION__));
			break;
		default:
			DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi ROM Patch Fail (%d)\n", __FUNCTION__, Status));
			break;
	}
}


static INT32 CmdPatchFinishReq(RTMP_ADAPTER *ad)
{
	struct cmd_msg *msg;
	int ret = 0;

	DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__));

	msg = AndesAllocCmdMsg(ad, 0);

	if (!msg) {
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, MT_PATCH_FINISH_REQ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdPatchFinishRsp);

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


static INT32 CmdFwStartReq(RTMP_ADAPTER *ad, UINT32 override, UINT32 address)
{
	struct cmd_msg *msg;
	int ret = 0;
	UINT32 value;

	DBGPRINT(RT_DEBUG_OFF, ("%s: override = %d, address = %d\n", __FUNCTION__, override, address));

	msg = AndesAllocCmdMsg(ad, 8);

	if (!msg) {
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, MT_FW_START_REQ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdStartDLRsp);

	/* override */
	value = cpu2le32(override);
	AndesAppendCmdMsg(msg, (char *)&value, 4);

	/* entry point address */
	value = cpu2le32(address);

	AndesAppendCmdMsg(msg, (char *)&value, 4);

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


INT32 CmdChPrivilege(RTMP_ADAPTER *ad, UINT8 Action, UINT8 control_chl, UINT8 central_chl,
							UINT8 BW, UINT8 TXStream, UINT8 RXStream)
{
	struct cmd_msg *msg;
	struct _CMD_CH_PRIVILEGE_T ch_privilege;
	INT32 ret = 0;
	struct MCU_CTRL *Ctl = &ad->MCUCtrl;

	if (central_chl == 0)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("%s: central channel = 0 is invalid\n", __FUNCTION__));
		return -1;
	}

	DBGPRINT(RT_DEBUG_INFO, ("%s: control_chl = %d, central_chl = %d, BW = %d,	\
								TXStream = %d, RXStream = %d\n", __FUNCTION__,	\
							control_chl, central_chl, BW, TXStream, RXStream));

	msg = AndesAllocCmdMsg(ad, sizeof(struct _CMD_CH_PRIVILEGE_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, CMD_CH_PRIVILEGE, CMD_SET, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);

	memset(&ch_privilege, 0x00, sizeof(ch_privilege));

	ch_privilege.ucAction = Action;
	ch_privilege.ucPrimaryChannel = control_chl;

	if (BW == BAND_WIDTH_20)
	{
		ch_privilege.ucRfSco = CMD_CH_PRIV_SCO_SCN;
	}
	else if (BW == BAND_WIDTH_40)
	{
		if (control_chl < central_chl)
			ch_privilege.ucRfSco = CMD_CH_PRIV_SCO_SCA;
		else
			ch_privilege.ucRfSco = CMD_CH_PRIV_SCO_SCB;
	}
	else
	{
		DBGPRINT(RT_DEBUG_ERROR, ("unknown bandwidth = %d\n", BW));
	}

	if (central_chl > 14)
		ch_privilege.ucRfBand =  CMD_CH_PRIV_BAND_A;
	else
		ch_privilege.ucRfBand = CMD_CH_PRIV_BAND_G;

	ch_privilege.ucRfChannelWidth = CMD_CH_PRIV_CH_WIDTH_20_40;

	ch_privilege.ucReqType = CMD_CH_PRIV_REQ_JOIN;

	AndesAppendCmdMsg(msg, (char *)&ch_privilege, sizeof(ch_privilege));

	if (IS_MT7603(ad) || IS_MT7628(ad))
	{
		UINT32 Value;
		RTMP_IO_READ32(ad, RMAC_RMCR, &Value);

		if (Value & RMAC_RMCR_RX_STREAM_0)
			Ctl->RxStream0 = 1;

		if (Value & RMAC_RMCR_RX_STREAM_1)
			Ctl->RxStream1 = 1;

		Value |= RMAC_RMCR_RX_STREAM_0;
		Value |= RMAC_RMCR_RX_STREAM_1;
		RTMP_IO_WRITE32(ad, RMAC_RMCR, Value);
	}

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


static VOID CmdMultipleMacRegAccessWriteCb(struct cmd_msg *msg, 
											char *data, UINT16 len)
{
	EXT_EVENT_MULTI_CR_ACCESS_WR_T *EventMultiCRAccessWR
								= (EXT_EVENT_MULTI_CR_ACCESS_WR_T *)(data + 20);

	EventMultiCRAccessWR->u4Status = le2cpu32(EventMultiCRAccessWR->u4Status);

	if (EventMultiCRAccessWR->u4Status)
		DBGPRINT(RT_DEBUG_ERROR, ("%s: fail\n", __FUNCTION__));
}


INT32 CmdMultipleMacRegAccessWrite(RTMP_ADAPTER *pAd, RTMP_REG_PAIR *RegPair, 
														UINT32 Num)
{
	struct cmd_msg *msg;
	CMD_MULTI_CR_ACCESS_T MultiCR;
	INT32 Ret;
	UINT32 Index;

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_MULTI_CR_ACCESS_T) * Num);

	if (!msg)
	{
		Ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_MULTIPLE_REG_ACCESS, 
				TRUE, 0, TRUE, TRUE, 32, NULL, CmdMultipleMacRegAccessWriteCb);

	for (Index = 0; Index < Num; Index++)
	{
		memset(&MultiCR, 0x00, sizeof(MultiCR));
		MultiCR.u4Type = cpu2le32(MAC_CR);
		MultiCR.u4Addr = cpu2le32(RegPair[Index].Register);
		MultiCR.u4Data = cpu2le32(RegPair[Index].Value);
//		DBGPRINT(RT_DEBUG_TRACE, ("%s: offset: = %x\n", __FUNCTION__,MultiCR.u4Addr));	
	
		AndesAppendCmdMsg(msg, (char *)&MultiCR, sizeof(MultiCR));
	}

	Ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, Ret));
	return Ret;
}


static VOID CmdMultipleRfRegAccessWriteCb(struct cmd_msg *msg, 
											char *data, UINT16 len)
{
	EXT_EVENT_MULTI_CR_ACCESS_WR_T *EventMultiCRAccessWR
								= (EXT_EVENT_MULTI_CR_ACCESS_WR_T *)(data + 20);

	EventMultiCRAccessWR->u4Status = le2cpu32(EventMultiCRAccessWR->u4Status);

	if (EventMultiCRAccessWR->u4Status)
		DBGPRINT(RT_DEBUG_ERROR, ("%s: fail\n", __FUNCTION__));
}


INT32 CmdMultipleRfRegAccessWrite(RTMP_ADAPTER *pAd, MT_RF_REG_PAIR *RegPair, 
														UINT32 Num)
{
	struct cmd_msg *msg;
	CMD_MULTI_CR_ACCESS_T MultiCR;
	INT32 Ret;
	UINT32 Index;

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_MULTI_CR_ACCESS_T) * Num);

	if (!msg)
	{
		Ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_MULTIPLE_REG_ACCESS, 
				TRUE, 0, TRUE, TRUE, 32, NULL, CmdMultipleRfRegAccessWriteCb);

	for (Index = 0; Index < Num; Index++)
	{
		memset(&MultiCR, 0x00, sizeof(MultiCR));
		MultiCR.u4Type = cpu2le32((RF_CR & 0xff) | 
							((RegPair->WiFiStream & 0xffffff) << 8));
		MultiCR.u4Addr = cpu2le32(RegPair[Index].Register);
		MultiCR.u4Data = cpu2le32(RegPair[Index].Value);
	
		AndesAppendCmdMsg(msg, (char *)&MultiCR, sizeof(MultiCR));
	}

	Ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, Ret));
	return Ret;
}


static VOID CmdMultipleRfRegAccessReadCb(struct cmd_msg *msg, 
											char *data, UINT16 len)
{
	UINT32 Index;
	UINT32 Num = (len -20) / sizeof(EXT_EVENT_MULTI_CR_ACCESS_RD_T);
	EXT_EVENT_MULTI_CR_ACCESS_RD_T *EventMultiCRAccessRD
								= (EXT_EVENT_MULTI_CR_ACCESS_RD_T *)(data + 20);
	MT_RF_REG_PAIR *RegPair = (MT_RF_REG_PAIR *)msg->rsp_payload;

	for (Index = 0; Index < Num; Index++)
	{
		RegPair->WiFiStream = (le2cpu32(EventMultiCRAccessRD->u4Type) 
								& (0xffffff << 8)) >> 8;
		RegPair->Register = le2cpu32(EventMultiCRAccessRD->u4Addr);
		RegPair->Value = le2cpu32(EventMultiCRAccessRD->u4Data);

		EventMultiCRAccessRD++;
		RegPair++;
	}
}


INT32 CmdMultiPleRfRegAccessRead(RTMP_ADAPTER *pAd, MT_RF_REG_PAIR *RegPair, 
														UINT32 Num)
{
	struct cmd_msg *msg;
	CMD_MULTI_CR_ACCESS_T MultiCR;
	INT32 Ret;
	UINT32 Index;

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_MULTI_CR_ACCESS_T) * Num);

	if (!msg)
	{
		Ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_MULTIPLE_REG_ACCESS, 
				TRUE, 0, TRUE, TRUE, (UINT16)(12 * Num) + 20, (char *)RegPair,
				CmdMultipleRfRegAccessReadCb);

	for (Index = 0; Index < Num; Index++)
	{
		memset(&MultiCR, 0x00, sizeof(MultiCR));
		MultiCR.u4Type = cpu2le32((RF_CR & 0xff) | 
							((RegPair->WiFiStream & 0xffffff) << 8));
		MultiCR.u4Addr = cpu2le32(RegPair[Index].Register);
	
		AndesAppendCmdMsg(msg, (char *)&MultiCR, sizeof(MultiCR));
	}

	Ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, Ret));
	return Ret;
}


static VOID CmdMultipleMacRegAccessReadCb(struct cmd_msg *msg, 
											char *data, UINT16 len)
{
	UINT32 Index;
	UINT32 Num = (len - 20) / sizeof(EXT_EVENT_MULTI_CR_ACCESS_RD_T);
	EXT_EVENT_MULTI_CR_ACCESS_RD_T *EventMultiCRAccessRD
								= (EXT_EVENT_MULTI_CR_ACCESS_RD_T *)(data + 20);
	RTMP_REG_PAIR *RegPair = (RTMP_REG_PAIR *)msg->rsp_payload;

	for (Index = 0; Index < Num; Index++)
	{
		RegPair->Register = le2cpu32(EventMultiCRAccessRD->u4Addr);
		RegPair->Value = le2cpu32(EventMultiCRAccessRD->u4Data);

		EventMultiCRAccessRD++;
		RegPair++;
	}
}


INT32 CmdMultiPleMacRegAccessRead(RTMP_ADAPTER *pAd, RTMP_REG_PAIR *RegPair, 
														UINT32 Num)
{
	struct cmd_msg *msg;
	CMD_MULTI_CR_ACCESS_T MultiCR;
	INT32 Ret;
	UINT32 Index;

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_MULTI_CR_ACCESS_T) * Num);

	if (!msg)
	{
		Ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_MULTIPLE_REG_ACCESS, 
				TRUE, 0, TRUE, TRUE, (UINT16)(12 * Num) + 20, (char *)RegPair,
				CmdMultipleMacRegAccessReadCb);

	for (Index = 0; Index < Num; Index++)
	{
		memset(&MultiCR, 0x00, sizeof(MultiCR));
		MultiCR.u4Type = cpu2le32(MAC_CR);
		MultiCR.u4Addr = cpu2le32(RegPair[Index].Register);
	
		AndesAppendCmdMsg(msg, (char *)&MultiCR, sizeof(MultiCR));
	}

	Ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, Ret));
	return Ret;
}


INT32 CmdAccessRegWrite(RTMP_ADAPTER *ad, UINT32 address, UINT32 data)
{
	struct cmd_msg *msg;
	struct _CMD_ACCESS_REG_T access_reg;
	INT32 ret = 0;

	DBGPRINT(RT_DEBUG_INFO, ("%s: address = %x, data = %x\n", __FUNCTION__, address, data));

	msg = AndesAllocCmdMsg(ad, sizeof(struct _CMD_ACCESS_REG_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, CMD_ACCESS_REG, CMD_SET, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);

	memset(&access_reg, 0x00, sizeof(access_reg));

	access_reg.u4Address = cpu2le32(address);
	access_reg.u4Data = cpu2le32(data);

	AndesAppendCmdMsg(msg, (char *)&access_reg, sizeof(access_reg));

	ret = AndesSendCmdMsg(ad, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


static VOID CmdAccessRegReadCb(struct cmd_msg *msg, char *data, UINT16 len)
{
	struct _CMD_ACCESS_REG_T *access_reg = (struct _CMD_ACCESS_REG_T *)data;

	DBGPRINT(RT_DEBUG_INFO, ("%s\n", __FUNCTION__));
	
	NdisMoveMemory(msg->rsp_payload, &access_reg->u4Data, len - 4);
	*((UINT32 *)(msg->rsp_payload)) = le2cpu32(*((UINT32 *)msg->rsp_payload));
}


INT32 CmdAccessRegRead(RTMP_ADAPTER *pAd, UINT32 address, UINT32 *data)
{
	struct cmd_msg *msg;
	struct _CMD_ACCESS_REG_T access_reg;
	INT32 ret = 0;

	msg = AndesAllocCmdMsg(pAd, sizeof(struct _CMD_ACCESS_REG_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, CMD_ACCESS_REG, CMD_QUERY, EXT_CMD_NA, TRUE, 0,
							TRUE, TRUE, 8, (CHAR *)data, CmdAccessRegReadCb);

	memset(&access_reg, 0x00, sizeof(access_reg));

	access_reg.u4Address = cpu2le32(address);

	AndesAppendCmdMsg(msg, (char *)&access_reg, sizeof(access_reg));

	ret = AndesSendCmdMsg(pAd, msg);

	DBGPRINT(RT_DEBUG_INFO, ("%s: address = %x, value = %x\n", __FUNCTION__, address, *data));
error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


INT32 CmdRFRegAccessWrite(RTMP_ADAPTER *pAd, UINT32 RFIdx, UINT32 Offset, UINT32 Value)
{
	struct cmd_msg *msg;
	struct _CMD_RF_REG_ACCESS_T RFRegAccess;
	INT32 ret = 0;

	DBGPRINT(RT_DEBUG_INFO, ("%s: RFIdx = %d, Offset = %x, Value = %x\n", __FUNCTION__,\
										RFIdx, Offset, Value));

	msg = AndesAllocCmdMsg(pAd, sizeof(struct _CMD_RF_REG_ACCESS_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_RF_REG_ACCESS, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);

	memset(&RFRegAccess, 0x00, sizeof(RFRegAccess));

	RFRegAccess.WiFiStream = cpu2le32(RFIdx);
	RFRegAccess.Address = cpu2le32(Offset);
	RFRegAccess.Data = cpu2le32(Value);

	AndesAppendCmdMsg(msg, (char *)&RFRegAccess, sizeof(RFRegAccess));

	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


static VOID CmdRFRegAccessReadCb(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	struct _CMD_RF_REG_ACCESS_T *RFRegAccess = (struct _CMD_RF_REG_ACCESS_T *)Data;

	NdisMoveMemory(msg->rsp_payload, &RFRegAccess->Data, Len - 8);
	*((UINT32 *)msg->rsp_payload) = le2cpu32(*((UINT32 *)msg->rsp_payload));
}


INT32 CmdRFRegAccessRead(RTMP_ADAPTER *pAd, UINT32 RFIdx, UINT32 Offset, UINT32 *Value)
{
	struct cmd_msg *msg;
	struct _CMD_RF_REG_ACCESS_T RFRegAccess;
	INT32 ret = 0;

	DBGPRINT(RT_DEBUG_INFO, ("%s: RFIdx = %d, Offset = %x\n", __FUNCTION__, RFIdx, Offset));

	msg = AndesAllocCmdMsg(pAd, sizeof(struct _CMD_RF_REG_ACCESS_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_RF_REG_ACCESS, TRUE, 0,
							TRUE, TRUE, 12, (CHAR *)Value, CmdRFRegAccessReadCb);

	memset(&RFRegAccess, 0x00, sizeof(RFRegAccess));

	RFRegAccess.WiFiStream = cpu2le32(RFIdx);
	RFRegAccess.Address = cpu2le32(Offset);

	AndesAppendCmdMsg(msg, (char *)&RFRegAccess, sizeof(RFRegAccess));

	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


VOID CmdIOWrite32(RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 Value)
{
	struct MCU_CTRL *Ctl = &pAd->MCUCtrl;
	RTMP_REG_PAIR RegPair;

	if (Ctl->Stage == FW_RUN_TIME)
	{
		RegPair.Register = Offset;
		RegPair.Value = Value;
		CmdMultipleMacRegAccessWrite(pAd, &RegPair, 1);
	}
#ifdef E2P_WITHOUT_FW_SUPPORT	
        else if (Ctl->Stage == FW_NO_INIT)
        {
		RTMP_IO_WRITE32(pAd, Offset, Value);
        }
#endif /* E2P_WITHOUT_FW_SUPPORT */		
	else
	{
		CmdInitAccessRegWrite(pAd, Offset, Value);
	}
} 


VOID CmdIORead32(struct _RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 *Value)
{

	struct MCU_CTRL *Ctl = &pAd->MCUCtrl;
	RTMP_REG_PAIR RegPair;
	RegPair.Value = 0;

	if (Ctl->Stage == FW_RUN_TIME)
	{
		RegPair.Register = Offset;
		CmdMultiPleMacRegAccessRead(pAd, &RegPair, 1);
		*Value = RegPair.Value;
	}
#ifdef E2P_WITHOUT_FW_SUPPORT	
	else if (Ctl->Stage == FW_NO_INIT)
	{
		RTMP_IO_READ32(pAd, Offset, Value);
	}
#endif /* E2P_WITHOUT_FW_SUPPORT */	
	else
	{
		CmdInitAccessRegRead(pAd, Offset, Value); 
	}
}

static VOID EventExtCmdResult(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	struct _EVENT_EXT_CMD_RESULT_T *EventExtCmdResult = (struct _EVENT_EXT_CMD_RESULT_T *)Data;
	RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv;

	DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.ucExTenCID = 0x%x\n",
									__FUNCTION__, EventExtCmdResult->ucExTenCID));

	EventExtCmdResult->u4Status = le2cpu32(EventExtCmdResult->u4Status);

	DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.u4Status = 0x%x\n",
									__FUNCTION__, EventExtCmdResult->u4Status));

	RTMP_OS_TXRXHOOK_CALL(WLAN_CALIB_TEST_RSP, NULL, (UCHAR)EventExtCmdResult->u4Status, pAd);
}


VOID EventExtCmdResultHandler(RTMP_ADAPTER *pAd, char *Data, UINT16 Len)
{
	struct _EVENT_EXT_CMD_RESULT_T *EventExtCmdResult = (struct _EVENT_EXT_CMD_RESULT_T *)Data;
	//RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv;

	DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.ucExTenCID = 0x%x\n",
									__FUNCTION__, EventExtCmdResult->ucExTenCID));

	EventExtCmdResult->u4Status = le2cpu32(EventExtCmdResult->u4Status);

	DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.u4Status = 0x%x\n",
									__FUNCTION__, EventExtCmdResult->u4Status));

	RTMP_OS_TXRXHOOK_CALL(WLAN_CALIB_TEST_RSP, NULL, (UCHAR)EventExtCmdResult->u4Status, pAd);
}


INT32 CmdIcapOverLap(RTMP_ADAPTER *pAd, UINT32 IcapLen)
{
    struct cmd_msg *msg;
    struct _CMD_TEST_CTRL_T TestCtrl;
    INT32 ret = 0;

    DBGPRINT(RT_DEBUG_INFO, ("%s: IcapLen = %d\n", __FUNCTION__, IcapLen));

    msg = AndesAllocCmdMsg(pAd, sizeof(TestCtrl));

    if (!msg) {
        ret = NDIS_STATUS_RESOURCES;
        goto error;
    }

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_RF_TEST, TRUE, 0,
							TRUE, TRUE, 8, NULL, EventExtCmdResult);

    memset(&TestCtrl, 0x00, sizeof(TestCtrl));

    TestCtrl.ucAction = 0;

	TestCtrl.ucIcapLen = (UINT8)IcapLen;
    
	TestCtrl.u.u4OpMode = OPERATION_ICAP_OVERLAP;

    AndesAppendCmdMsg(msg, (char *)&TestCtrl, sizeof(TestCtrl));

    ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


INT32 CmdRfTest(RTMP_ADAPTER *pAd, UINT8 Action, UINT8 Mode, UINT8 CalItem)
{
    struct cmd_msg *msg;
    struct _CMD_TEST_CTRL_T TestCtrl;
    INT32 ret = 0;

    DBGPRINT(RT_DEBUG_INFO, ("%s: Action = %d Mode = %d CalItem = %d\n", __FUNCTION__, Action, Mode, CalItem));

    msg = AndesAllocCmdMsg(pAd, sizeof(TestCtrl));

    if (!msg) {
        ret = NDIS_STATUS_RESOURCES;
        goto error;
    }

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_RF_TEST, TRUE, 0,
							TRUE, TRUE, 8, NULL, EventExtCmdResult);

    memset(&TestCtrl, 0x00, sizeof(TestCtrl));

    TestCtrl.ucAction = Action;
    TestCtrl.u.u4OpMode = (UINT32)Mode;

    if (Action == ACTION_IN_RFTEST) {
        /* set Cal Items */
        TestCtrl.u.rRfATInfo.u4FuncIndex = 1;
        TestCtrl.u.rRfATInfo.u4FuncData = (UINT32)CalItem;
    }

    AndesAppendCmdMsg(msg, (char *)&TestCtrl, sizeof(TestCtrl));

    ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;

}

INT32 CmdRadioOnOffCtrl(RTMP_ADAPTER *pAd, UINT8 On)
{
	struct cmd_msg *msg;
	struct _EXT_CMD_RADIO_ON_OFF_CTRL_T RadioOnOffCtrl;
	INT32 ret = 0;

	DBGPRINT(RT_DEBUG_INFO, ("%s: On = %d\n", __FUNCTION__, On));

	msg = AndesAllocCmdMsg(pAd, sizeof(RadioOnOffCtrl));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_RADIO_ON_OFF_CTRL, TRUE, 0,
							TRUE, TRUE, 8, NULL, EventExtCmdResult);

	memset(&RadioOnOffCtrl, 0x00, sizeof(RadioOnOffCtrl));

	if (On == WIFI_RADIO_ON)
		RadioOnOffCtrl.ucWiFiRadioCtrl = WIFI_RADIO_ON;
	else if (On == WIFI_RADIO_OFF)
		RadioOnOffCtrl.ucWiFiRadioCtrl = WIFI_RADIO_OFF;
	else
		DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown state On = %d\n", __FUNCTION__, On));

	AndesAppendCmdMsg(msg, (char *)&RadioOnOffCtrl, sizeof(RadioOnOffCtrl));

	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


INT32 CmdWiFiRxDisable(RTMP_ADAPTER *pAd, UINT RxDisable)
{
	struct cmd_msg *msg;
	struct _EXT_CMD_WIFI_RX_DISABLE_T WiFiRxDisable;
	INT32 ret = 0;

	DBGPRINT(RT_DEBUG_INFO, ("%s: WiFiRxDisable = %d\n", __FUNCTION__, RxDisable));

	if (RxDisable != WIFI_RX_DISABLE)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("Error: %s: RxDisable = %d\n", __FUNCTION__, RxDisable));
		return ret;
	}

	msg = AndesAllocCmdMsg(pAd, sizeof(WiFiRxDisable));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_WIFI_RX_DISABLE, TRUE, 0,
							TRUE, TRUE, 8, NULL, EventExtCmdResult);

	memset(&WiFiRxDisable, 0x00, sizeof(WiFiRxDisable));

	WiFiRxDisable.ucWiFiRxDisableCtrl = (UINT8)RxDisable;

	AndesAppendCmdMsg(msg, (char *)&WiFiRxDisable, sizeof(WiFiRxDisable));

	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


//NoA
INT32 CmdP2pNoaOffloadCtrl(RTMP_ADAPTER *ad, UINT8 enable)
{
      struct cmd_msg *msg;
      struct _EXT_CMD_NOA_CTRL_T extCmdNoaCtrl;		
      int ret = 0;

      msg = AndesAllocCmdMsg(ad, sizeof(struct _EXT_CMD_NOA_CTRL_T));

      if (!msg)
      {
         ret = NDIS_STATUS_RESOURCES;
         goto error;
      }

      AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_NOA_OFFLOAD_CTRL, 
			TRUE, 0, TRUE, TRUE, 
			sizeof(struct _EXT_CMD_NOA_CTRL_T), NULL, EventExtCmdResult);

      NdisZeroMemory(&extCmdNoaCtrl, sizeof(extCmdNoaCtrl));

		extCmdNoaCtrl.ucMode1 = (UINT8)cpu2le32(enable);
      //extCmdNoaCtrl.ucMode0 = cpu2le32(enable);

      AndesAppendCmdMsg(msg, (char *)&extCmdNoaCtrl, sizeof(extCmdNoaCtrl));
      ret = AndesSendCmdMsg(ad, msg);

error:
      DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
        return ret;
}

#ifdef SINGLE_SKU_V2
enum {
	SKU_CCK_1_2=0,
	SKU_CCK_55_11,
	SKU_OFDM_6_9,
	SKU_OFDM_12_18,
	SKU_OFDM_24_36,
	SKU_OFDM_48,
	SKU_OFDM_54,
	SKU_HT20_0_8,
	SKU_HT20_32,
	SKU_HT20_1_2_9_10,
	SKU_HT20_3_4_11_12,
	SKU_HT20_5_13,
	SKU_HT20_6_14,
	SKU_HT20_7_15,	
	SKU_HT40_0_8,
	SKU_HT40_32,
	SKU_HT40_1_2_9_10,
	SKU_HT40_3_4_11_12,
	SKU_HT40_5_13,
	SKU_HT40_6_14,
	SKU_HT40_7_15,
};
static VOID mt_FillSkuParameter(RTMP_ADAPTER *pAd,UINT8 channel,UINT8 *txPowerSku)
{
	CH_POWER *ch, *ch_temp;
	UCHAR start_ch;
	//UCHAR base_pwr = pAd->DefaultTargetPwr;
	UINT8 j;
	
	DlListForEachSafe(ch, ch_temp, &pAd->SingleSkuPwrList, CH_POWER, List)
	{
		start_ch = ch->StartChannel;
		if ( channel >= start_ch )
		{
			for ( j = 0; j < ch->num; j++ )
			{
				if ( channel == ch->Channel[j] )
				{

					txPowerSku[SKU_CCK_1_2] 	= ch->PwrCCK[0] ? ch->PwrCCK[0] : 0xff;
					txPowerSku[SKU_CCK_55_11] 	= ch->PwrCCK[2] ? ch->PwrCCK[2] : 0xff;
					txPowerSku[SKU_OFDM_6_9] 	= ch->PwrOFDM[0] ? ch->PwrOFDM[0] : 0xff;
					txPowerSku[SKU_OFDM_12_18]= ch->PwrOFDM[2] ? ch->PwrOFDM[2] : 0xff;
					txPowerSku[SKU_OFDM_24_36]= ch->PwrOFDM[4] ? ch->PwrOFDM[4] : 0xff;
					txPowerSku[SKU_OFDM_48] 	= ch->PwrOFDM[6] ? ch->PwrOFDM[6] : 0xff;
					txPowerSku[SKU_OFDM_54] 	= ch->PwrOFDM[7] ? ch->PwrOFDM[7] : 0xff;
					txPowerSku[SKU_HT20_0_8] 	= ch->PwrHT20[0] ? ch->PwrHT20[2] : 0xff;
					txPowerSku[SKU_HT20_32] 	= 0xff;
					txPowerSku[SKU_HT20_1_2_9_10] = ch->PwrHT20[1] ? ch->PwrHT20[1] : 0xff;
					txPowerSku[SKU_HT20_3_4_11_12] = ch->PwrHT20[3] ? ch->PwrHT20[3] : 0xff;
					txPowerSku[SKU_HT20_5_13] 	= ch->PwrHT20[5] ? ch->PwrHT20[5]  : 0xff;
					txPowerSku[SKU_HT20_6_14] 	= ch->PwrHT20[6] ? ch->PwrHT20[6]  : 0xff;
					txPowerSku[SKU_HT20_7_15] 	= ch->PwrHT20[7] ? ch->PwrHT20[7]  : 0xff;
					txPowerSku[SKU_HT40_0_8] 	= ch->PwrHT40[0] ? ch->PwrHT40[0]  : 0xff;
					txPowerSku[SKU_HT40_32] 	= 0xff;
					txPowerSku[SKU_HT40_1_2_9_10] = ch->PwrHT40[1] ?  ch->PwrHT40[1] : 0xff;
					txPowerSku[SKU_HT40_3_4_11_12] = ch->PwrHT40[3] ?  ch->PwrHT40[3] : 0xff;
					txPowerSku[SKU_HT40_5_13] 	= ch->PwrHT40[5] ?  ch->PwrHT40[5] : 0xff;
					txPowerSku[SKU_HT40_6_14] 	= ch->PwrHT40[6] ?  ch->PwrHT40[6] : 0xff;
					txPowerSku[SKU_HT40_7_15] 	= ch->PwrHT40[7] ?  ch->PwrHT40[7] : 0xff;
					break;
				}
			}
		}
	}
}
#endif

INT32 CmdChannelSwitch(RTMP_ADAPTER *pAd, UINT8 control_chl, UINT8 central_chl,
							UINT8 BW, UINT8 TXStream, UINT8 RXStream)
{
	struct cmd_msg *msg;
	struct _EXT_CMD_CHAN_SWITCH_T CmdChanSwitch;
	INT32 ret = 0,i=0;
#ifdef RTMP_SDIO_SUPPORT 
	return 0;
#endif /*leonardo for SDIO FPGA pass*/

	if (central_chl == 0)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("%s: central channel = 0 is invalid\n", __FUNCTION__));
		return -1;
	}


	DBGPRINT(RT_DEBUG_INFO, ("%s: control_chl = %d, central_chl = %d, BW = %d,	\
								TXStream = %d, RXStream = %d\n", __FUNCTION__,	\
							control_chl, central_chl, BW, TXStream, RXStream));

	msg = AndesAllocCmdMsg(pAd, sizeof(CmdChanSwitch));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	
	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_CHANNEL_SWITCH, TRUE, 0,
							TRUE, TRUE, 8, NULL, EventExtCmdResult);

	memset(&CmdChanSwitch, 0x00, sizeof(CmdChanSwitch));

	CmdChanSwitch.ucCtrlCh = control_chl;
	CmdChanSwitch.ucCentralCh = central_chl;
	CmdChanSwitch.ucBW = BW;
	CmdChanSwitch.ucTxStreamNum = TXStream;
	CmdChanSwitch.ucRxStreamNum = RXStream;

	for(i=0;i<SKU_SIZE;i++)
	{
		CmdChanSwitch.aucTxPowerSKU[i]=0xff;
	}
 
#ifdef SINGLE_SKU_V2
	if  (pAd->SKUEn)
	mt_FillSkuParameter(pAd,central_chl,CmdChanSwitch.aucTxPowerSKU);
#endif	
	AndesAppendCmdMsg(msg, (char *)&CmdChanSwitch, sizeof(CmdChanSwitch));

	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


static VOID EventExtNicCapability(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	struct _EXT_EVENT_NIC_CAPABILITY_T *ExtEventNicCapability = (EXT_EVENT_NIC_CAPABILITY *)Data;
	UINT32 Loop;

	DBGPRINT(RT_DEBUG_OFF, ("The data code of firmware:"));

	for (Loop = 0; Loop < 16; Loop++)
	{
		DBGPRINT(RT_DEBUG_OFF, ("%c", ExtEventNicCapability->aucDateCode[Loop]));
	}

	DBGPRINT(RT_DEBUG_OFF, ("\nThe version code of firmware:"));

	for (Loop = 0; Loop < 12; Loop++)
	{
		DBGPRINT(RT_DEBUG_OFF, ("%c", ExtEventNicCapability->aucVersionCode[Loop]));
	}
}


INT32 CmdNicCapability(RTMP_ADAPTER *pAd)
{
	struct cmd_msg *msg;
	INT32 ret = 0;

	msg = AndesAllocCmdMsg(pAd, 0);

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_NIC_CAPABILITY, TRUE, 0,
							TRUE, TRUE, 28, NULL, EventExtNicCapability);

	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


INT32 CmdFwLog2Host(RTMP_ADAPTER *pAd, UINT8 FWLog2HostCtrl)
{

	struct cmd_msg *msg;
	INT32 Ret = 0;
	EXT_CMD_FW_LOG_2_HOST_CTRL_T CmdFwLog2HostCtrl;

	msg = AndesAllocCmdMsg(pAd, sizeof(CmdFwLog2HostCtrl));

	if (!msg)
	{
		Ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_FW_LOG_2_HOST, 
						FALSE, 0, FALSE, FALSE, 0, NULL, NULL);
	
	memset(&CmdFwLog2HostCtrl, 0x00, sizeof(CmdFwLog2HostCtrl));

	CmdFwLog2HostCtrl.ucFwLog2HostCtrl = FWLog2HostCtrl;

	AndesAppendCmdMsg(msg, (char *)&CmdFwLog2HostCtrl, 
									sizeof(CmdFwLog2HostCtrl));

	Ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, Ret));
	return Ret;
}

#ifdef BCN_OFFLOAD_SUPPORT
static VOID ExtEventBcnUpdateHandler(RTMP_ADAPTER *pAd, UINT8 *Data, UINT32 Length)
{
    if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
        (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) ||
        (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
        (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
    {
        return;
    }

    RTMP_UPDATE_BCN(pAd);
}
#endif

#ifdef THERMAL_PROTECT_SUPPORT
static VOID EventThermalProtect(RTMP_ADAPTER *pAd, UINT8 *Data, UINT32 Length)
{
	EXT_EVENT_THERMAL_PROTECT_T *EvtThermalProtect;
	UINT8 HLType;
    UINT32 ret;

	EvtThermalProtect = (EXT_EVENT_THERMAL_PROTECT_T *)Data;

	HLType = EvtThermalProtect->ucHLType;
	pAd->last_thermal_pro_temp = EvtThermalProtect->cCurrentTemp;

	DBGPRINT(RT_DEBUG_OFF, ("%s: HLType = %d, CurrentTemp = %d\n", __FUNCTION__, HLType, pAd->last_thermal_pro_temp));

    RTMP_SEM_EVENT_WAIT(&pAd->AutoRateLock, ret);
	if (HLType == HIGH_TEMP_THD)
	{
		pAd->force_one_tx_stream = TRUE;
		DBGPRINT(RT_DEBUG_OFF, ("Switch TX to 1 stram\n"));
	}
	else
	{
		pAd->force_one_tx_stream = FALSE;
		DBGPRINT(RT_DEBUG_OFF, ("Switch TX to 2 stram\n"));
	}

    pAd->switch_tx_stream = TRUE;
    pAd->fgThermalProtectToggle = TRUE;

    RTMP_SEM_EVENT_UP(&pAd->AutoRateLock);
}


INT32 CmdThermalProtect(RTMP_ADAPTER *ad, UINT8 HighEn, CHAR HighTempTh, UINT8 LowEn, CHAR LowTempTh)
{
	struct cmd_msg *msg;
	INT32 ret = 0;
	EXT_CMD_THERMAL_PROTECT_T ThermalProtect;

	msg = AndesAllocCmdMsg(ad, sizeof(EXT_CMD_THERMAL_PROTECT_T));

	if (!msg)
	{
         ret = NDIS_STATUS_RESOURCES;
         goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_THERMAL_PROTECT, TRUE, 0, TRUE, TRUE, 8, NULL, EventExtCmdResult);

	NdisZeroMemory(&ThermalProtect, sizeof(ThermalProtect));

	ThermalProtect.ucHighEnable = HighEn;
	ThermalProtect.cHighTempThreshold = HighTempTh;
	ThermalProtect.ucLowEnable = LowEn;
	ThermalProtect.cLowTempThreshold = LowTempTh;

	ad->thermal_pro_high_criteria = HighTempTh;
	ad->thermal_pro_high_en = HighEn;
	ad->thermal_pro_low_criteria = LowTempTh;
	ad->thermal_pro_low_en = LowEn;

	AndesAppendCmdMsg(msg, (char *)&ThermalProtect, sizeof(ThermalProtect));
	ret = AndesSendCmdMsg(ad, msg);

error:
      DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
   	return ret;
}
#endif

#ifdef BCN_OFFLOAD_SUPPORT
/*****************************************
    ExT_CID = 0x33
*****************************************/
INT32 CmdBcnUpdateSet(RTMP_ADAPTER *pAd, CMD_BCN_UPDATE_T bcn_update)
{
    struct cmd_msg *msg;
    INT32 ret=0,size=0;

    size = sizeof(CMD_BCN_UPDATE_T);

    msg = AndesAllocCmdMsg(pAd, size);

    if (!msg)
    {
        ret = NDIS_STATUS_RESOURCES;
        goto error;
    }

    AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_BCN_UPDATE, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);

    AndesAppendCmdMsg(msg, (char *)&bcn_update, size);

    ret = AndesSendCmdMsg(pAd, msg);

error:
    DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret));
    return ret;
}
#endif

#define TOP_MISC2 0x1134
#define SW_SYN0 0x81021250
static NDIS_STATUS AndesMTLoadFwMethod1(RTMP_ADAPTER *ad)
{
	UINT32 value, loop, dl_len;
	UINT32 ret = 0;
	RTMP_CHIP_CAP *cap = &ad->chipCap;
#ifdef RTMP_PCI_SUPPORT
	POS_COOKIE obj = (POS_COOKIE)ad->OS_Cookie;
#endif /* RTMP_PCI_SUPPORT */
	struct MCU_CTRL *Ctl = &ad->MCUCtrl;
#ifdef RTMP_PCI_SUPPORT
	UINT32 RemapBase, RemapOffset;
	UINT32 RestoreValue;
#endif

	if (cap->load_code_method == BIN_FILE_METHOD) {
		DBGPRINT(RT_DEBUG_OFF, ("load fw image from /lib/firmware/%s\n", cap->fw_bin_file_name));
#ifdef RTMP_PCI_SUPPORT
		OS_LOAD_CODE_FROM_BIN(&cap->FWImageName, cap->fw_bin_file_name, obj->pci_dev, &cap->fw_len);
#endif
	} else {
		cap->FWImageName = cap->fw_header_image;
	}

	if (!cap->FWImageName) {
		if (cap->load_code_method == BIN_FILE_METHOD) {
			DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->fw_bin_file_name, cap->load_code_method));
		} else {
			DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image, load_method(%d)\n",
				__FUNCTION__, cap->load_code_method));
		}
		ret = NDIS_STATUS_FAILURE;
		goto done;
	}

	Ctl->Stage = FW_DOWNLOAD;

	DBGPRINT(RT_DEBUG_OFF, ("FW Version:"));
	for (loop = 0; loop < 10; loop++)
		DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + cap->fw_len - 29 + loop)));
	DBGPRINT(RT_DEBUG_OFF, ("\n"));

	DBGPRINT(RT_DEBUG_OFF, ("FW Build Date:"));
	for (loop = 0; loop < 15; loop++)
		DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + cap->fw_len - 19 + loop)));
	DBGPRINT(RT_DEBUG_OFF, ("\n"));

	dl_len = (*(cap->FWImageName + cap->fw_len - 1) << 24) |
				(*(cap->FWImageName + cap->fw_len - 2) << 16) |
				(*(cap->FWImageName + cap->fw_len -3) << 8) |
				*(cap->FWImageName + cap->fw_len - 4);

	dl_len += 4; /* including crc value */

	DBGPRINT(RT_DEBUG_INFO, ("\ndownload len = %d\n", dl_len));

#ifdef RTMP_PCI_SUPPORT
	if (IS_MT7603(ad))
	{
		RTMP_IO_READ32(ad, MCU_PCIE_REMAP_1, &RestoreValue);
		RemapBase = GET_REMAP_1_BASE(0x50012498) << 18;
		RemapOffset = GET_REMAP_1_OFFSET(0x50012498);
		RTMP_IO_WRITE32(ad, MCU_PCIE_REMAP_1, RemapBase);
		RTMP_IO_WRITE32(ad, 0x40000 + RemapOffset, 0x5);
		RTMP_IO_WRITE32(ad, 0x40000 + RemapOffset, 0x5);
		RtmpusecDelay(1);
		RTMP_IO_WRITE32(ad, MCU_PCIE_REMAP_1, RestoreValue);
	}
#endif

#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT)
	/* switch to bypass mode */
	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value &= ~SCH_REG4_BYPASS_MODE_MASK;
	value |= SCH_REG4_BYPASS_MODE(1);

#ifdef RTMP_PCI_SUPPORT
	value &= ~SCH_REG4_FORCE_QID_MASK;
	value |= SCH_REG4_FORCE_QID(5);
#endif

#ifdef RTMP_USB_SUPPORT
	value &= ~SCH_REG4_FORCE_QID_MASK;
	value |= SCH_REG4_FORCE_QID(8);
#endif

	RTMP_IO_WRITE32(ad, SCH_REG4, value);
#endif

	/* optional CMD procedure */
	/* CMD restart download flow request */
	RTMP_IO_READ32(ad, TOP_MISC2, &value);
	DBGPRINT(RT_DEBUG_INFO, ("TOP_MSIC = %x\n", value));

	/* check ram code if running, if it is, need to do optional cmd procedure */
	if ((value & 0x02) == 0x02) {

#ifdef LOAD_FW_ONE_TIME
		ret = NDIS_STATUS_SUCCESS;
		Ctl->Stage = FW_RUN_TIME;
		ad->FWLoad = 1;
		goto done;
#else /* LOAD_FW_ONE_TIME */
		ret = CmdRestartDLReq(ad);

		if (ret)
			goto done;
#endif /* !LOAD_FW_ONE_TIME */
	}

	/* check rom code if ready */
	loop = 0;

	do
	{
		RTMP_IO_READ32(ad, TOP_MISC2, &value);
		if((value & 0x01) == 0x01 && !(value & 0x02))
			break;
		RtmpOsMsDelay(1);
		loop++;
	} while (loop <= 500);

	if (loop > 500) {
		DBGPRINT(RT_DEBUG_ERROR, ("%s: rom code is not ready(TOP_MISC2 = %d)\n", __FUNCTION__, value));
		goto done;
	}

	/* standard CMD procedure */
	/* 1. Config PDA phase */
	ret = CmdAddressLenReq(ad, FW_CODE_START_ADDRESS1, dl_len, TARGET_ADDR_LEN_NEED_RSP);

	if (ret)
		goto done;

	/* 2. Loading firmware image phase */
	ret = CmdFwScatters(ad, cap->FWImageName, dl_len);

	if (ret)
		goto done;

	/* 3. Firmware start negotiation phase */
	ret = CmdFwStartReq(ad, 1, FW_CODE_START_ADDRESS1);

	/* 4. check Firmware running */
	for (loop = 0; loop < 500; loop++)
	{
		RTMP_IO_READ32(ad, TOP_MISC2, &value);
		DBGPRINT(RT_DEBUG_INFO, ("TOP_MSIC = %x\n", value));
		if ((value & 0x02) == 0x02)
			break;

		RtmpOsMsDelay(1);
	}

	if (loop == 500)
	{
		ret = NDIS_STATUS_FAILURE;
		DBGPRINT(RT_DEBUG_OFF, ("firmware loading failure\n"));
		Ctl->Stage = FW_NO_INIT;
	}
	else
	{
		Ctl->Stage = FW_RUN_TIME;
	}

done:

#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT)
	/* Switch to normal mode */
	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value &= ~SCH_REG4_BYPASS_MODE_MASK;
	value |= SCH_REG4_BYPASS_MODE(0);
	value &= ~SCH_REG4_FORCE_QID_MASK;
	value |= SCH_REG4_FORCE_QID(0);
	RTMP_IO_WRITE32(ad, SCH_REG4, value);

	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value |= (1 << 8);
	RTMP_IO_WRITE32(ad, SCH_REG4, value);
	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value &= ~(1 << 8);
	RTMP_IO_WRITE32(ad, SCH_REG4, value);
#endif

	return ret;
}


static NDIS_STATUS AndesMTLoadFwMethod2(RTMP_ADAPTER *ad)
{
	UINT32 value, loop, ilm_dl_len, dlm_dl_len;
	UINT8 ilm_feature_set, dlm_feature_set;
	UINT8 ilm_chip_info, dlm_chip_info;
	UINT32 ilm_target_addr, dlm_target_addr;
	UINT32 ret = 0;
	RTMP_CHIP_CAP *cap = &ad->chipCap;
#ifdef RTMP_PCI_SUPPORT
	POS_COOKIE obj = (POS_COOKIE)ad->OS_Cookie;
#endif /* RTMP_PCI_SUPPORT */
	struct MCU_CTRL *Ctl = &ad->MCUCtrl;

	if (cap->load_code_method == BIN_FILE_METHOD) {
		DBGPRINT(RT_DEBUG_OFF, ("load fw image from /lib/firmware/%s\n", cap->fw_bin_file_name));
#ifdef RTMP_PCI_SUPPORT
		OS_LOAD_CODE_FROM_BIN(&cap->FWImageName, cap->fw_bin_file_name, obj->pci_dev, &cap->fw_len);
#endif
	} else {
		cap->FWImageName = cap->fw_header_image;
	}

	if (!cap->FWImageName) {
		if (cap->load_code_method == BIN_FILE_METHOD) {
			DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->fw_bin_file_name, cap->load_code_method));
		} else {
			DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image, load_method(%d)\n",
				__FUNCTION__, cap->load_code_method));
		}
		ret = NDIS_STATUS_FAILURE;
		goto done;
	}

	Ctl->Stage = FW_DOWNLOAD;

	ilm_target_addr = (*(cap->FWImageName + cap->fw_len - (33 + 36)) << 24) |
				(*(cap->FWImageName + cap->fw_len - (34 + 36)) << 16) |
				(*(cap->FWImageName + cap->fw_len -(35 + 36)) << 8) |
				*(cap->FWImageName + cap->fw_len - (36 + 36));

	DBGPRINT(RT_DEBUG_TRACE, ("ILM target address = %x\n", ilm_target_addr));

	ilm_chip_info = *(cap->FWImageName + cap->fw_len - (32 + 36));
	DBGPRINT(RT_DEBUG_TRACE, ("\nILM chip information = %x\n", ilm_chip_info));

	ilm_feature_set = *(cap->FWImageName + cap->fw_len - (31 + 36));
	DBGPRINT(RT_DEBUG_TRACE, ("\nILM feature set = %x\n", ilm_feature_set));

	DBGPRINT(RT_DEBUG_TRACE, ("\nILM Build Date:"));

	for (loop = 0; loop < 8; loop++)
		DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + cap->fw_len - (20 + 36) + loop)));

	ilm_dl_len = (*(cap->FWImageName + cap->fw_len - (1 + 36)) << 24) |
				(*(cap->FWImageName + cap->fw_len - (2 + 36)) << 16) |
				(*(cap->FWImageName + cap->fw_len -(3 + 36)) << 8) |
				*(cap->FWImageName + cap->fw_len - (4 + 36));

	ilm_dl_len += 4; /* including crc value */

	DBGPRINT(RT_DEBUG_TRACE, ("\nILM download len = %d\n", ilm_dl_len));

	dlm_target_addr = (*(cap->FWImageName + cap->fw_len - 33) << 24) |
				(*(cap->FWImageName + cap->fw_len - 34) << 16) |
				(*(cap->FWImageName + cap->fw_len - 35) << 8) |
				*(cap->FWImageName + cap->fw_len - 36);

	DBGPRINT(RT_DEBUG_TRACE, ("DLM target address = %x\n", dlm_target_addr));

	dlm_chip_info = *(cap->FWImageName + cap->fw_len - 32);
	DBGPRINT(RT_DEBUG_TRACE, ("\nDLM chip information = %x\n", dlm_chip_info));

	dlm_feature_set = *(cap->FWImageName + cap->fw_len - 31);
	DBGPRINT(RT_DEBUG_TRACE, ("\nDLM feature set = %x\n", dlm_feature_set));

	DBGPRINT(RT_DEBUG_TRACE, ("DLM Build Date:"));

	for (loop = 0; loop < 8; loop++)
		DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + cap->fw_len - 20 + loop)));

	dlm_dl_len = (*(cap->FWImageName + cap->fw_len - 1) << 24) |
				(*(cap->FWImageName + cap->fw_len - 2) << 16) |
				(*(cap->FWImageName + cap->fw_len - 3) << 8) |
				*(cap->FWImageName + cap->fw_len - 4);

	dlm_dl_len += 4; /* including crc value */

	DBGPRINT(RT_DEBUG_TRACE, ("\nDLM download len = %d\n", dlm_dl_len));

#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT)
	/* switch to bypass mode */
	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value &= ~SCH_REG4_BYPASS_MODE_MASK;
	value |= SCH_REG4_BYPASS_MODE(1);

#ifdef RTMP_PCI_SUPPORT
	value &= ~SCH_REG4_FORCE_QID_MASK;
	value |= SCH_REG4_FORCE_QID(5);
#endif

#ifdef RTMP_USB_SUPPORT
	value &= ~SCH_REG4_FORCE_QID_MASK;
	value |= SCH_REG4_FORCE_QID(8);
#endif

	RTMP_IO_WRITE32(ad, SCH_REG4, value);
#endif

	/* optional CMD procedure */
	/* CMD restart download flow request */
#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT)
	RTMP_IO_READ32(ad, SW_SYN0, &value);
	DBGPRINT(RT_DEBUG_TRACE, ("SW_SYN0 = %x\n", value));

	/* check ram code if running, if it is, need to do optional cmd procedure */
	if ((value & 0x03) == 0x03) {
		ret = CmdRestartDLReq(ad);

		if (ret)
			goto done;
	}

	/* check rom code if ready */
	loop = 0;

	do
	{
		RTMP_IO_READ32(ad, SW_SYN0, &value);
		if ((value & 0x01) == 0x01)
			break;
		RtmpOsMsDelay(1);
		loop++;
	} while (loop <= 500);

	if (loop > 500) {
		DBGPRINT(RT_DEBUG_ERROR, ("%s: rom code is not ready(SW_SYN0 = %d)\n", __FUNCTION__, value));
		goto done;
	}
#endif

	/*  ILM */
	/* standard CMD procedure */
	/* 1. Config PDA phase */
	ret = CmdAddressLenReq(ad, ilm_target_addr, ilm_dl_len,
				(ilm_feature_set & FW_FEATURE_SET_ENCRY) |
				(FW_FEATURE_SET_KEY(GET_FEATURE_SET_KEY(ilm_feature_set))) |
				((ilm_feature_set & FW_FEATURE_SET_ENCRY) ? FW_FEATURE_RESET_IV: 0) |
				TARGET_ADDR_LEN_NEED_RSP);

	if (ret)
		goto done;


	/* 2. Loading ilm firmware image phase */
	ret = CmdFwScatters(ad, cap->FWImageName, ilm_dl_len);

	if (ret)
		goto done;

	/*  DLM */
	/* standard CMD procedure */
	/* 1. Config PDA phase */
	ret = CmdAddressLenReq(ad, dlm_target_addr, dlm_dl_len,
				(dlm_feature_set & FW_FEATURE_SET_ENCRY) |
				(FW_FEATURE_SET_KEY(GET_FEATURE_SET_KEY(dlm_feature_set))) |
				((dlm_feature_set & FW_FEATURE_SET_ENCRY) ? FW_FEATURE_RESET_IV: 0) |
				TARGET_ADDR_LEN_NEED_RSP);

	if (ret)
		goto done;

	/* 2. Loading dlm firmware image phase */
	ret = CmdFwScatters(ad, cap->FWImageName + ilm_dl_len, dlm_dl_len);

	if (ret)
		goto done;

	/* 3. Firmware start negotiation phase */
	ret = CmdFwStartReq(ad, 0, 0);


#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT)
	/* 4. check Firmware running */
	for (loop = 0; loop < 500; loop++)
	{
		RTMP_IO_READ32(ad, SW_SYN0, &value);
		DBGPRINT(RT_DEBUG_TRACE, ("SW_SYN0 = %x\n", value));
		if ((value & 0x03) == 0x03)
			break;

		RtmpOsMsDelay(1);
	}

	if (loop == 500)
	{
		ret = NDIS_STATUS_FAILURE;
		DBGPRINT(RT_DEBUG_OFF, ("firmware loading failure\n"));
		Ctl->Stage = FW_NO_INIT;
	}
	else
	{

		Ctl->Stage = FW_RUN_TIME;
	}
#endif
#ifdef RTMP_SDIO_SUPPORT 

	RtmpOsMsDelay(1000);
	Ctl->Stage = FW_RUN_TIME;
	
	printk("%s: &pAd->MCUCtrl=%p\n",__FUNCTION__,Ctl); 
	printk("%s(): findish download fw ya! \n", __FUNCTION__); 
#endif


done:

#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT)
	/* Switch to normal mode */
	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value &= ~SCH_REG4_BYPASS_MODE_MASK;
	value |= SCH_REG4_BYPASS_MODE(0);
	value &= ~SCH_REG4_FORCE_QID_MASK;
	value |= SCH_REG4_FORCE_QID(0);
	RTMP_IO_WRITE32(ad, SCH_REG4, value);

	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value |= (1 << 8);
	RTMP_IO_WRITE32(ad, SCH_REG4, value);
	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value &= ~(1 << 8);
	RTMP_IO_WRITE32(ad, SCH_REG4, value);
#endif

	return ret;
}


NDIS_STATUS AndesMTLoadFw(RTMP_ADAPTER *pAd)
{
	UINT32 Ret;
	RTMP_CHIP_CAP *Cap = &pAd->chipCap;

	if (Cap->DownLoadType == DownLoadTypeA)
	{
		Ret = AndesMTLoadFwMethod1(pAd);
	}
	else if (Cap->DownLoadType == DownLoadTypeB)
	{
		Ret = AndesMTLoadFwMethod2(pAd);
	}
	else
	{
		DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Download type(%d)\n", __FUNCTION__, Cap->DownLoadType));
		Ret = -1;
	}

	return Ret;
}


NDIS_STATUS AndesMTLoadRomPatch(RTMP_ADAPTER *ad)
{
	UINT32 value, loop;
	UINT32 ret;
	RTMP_CHIP_CAP *cap = &ad->chipCap;
	RTMP_CHIP_OP *pChipOps = &ad->chipOps;
	//POS_COOKIE obj = (POS_COOKIE)ad->OS_Cookie;
	struct MCU_CTRL *Ctl = &ad->MCUCtrl;
	UINT32 patch_len = 0, total_checksum = 0;

	if (cap->load_code_method == BIN_FILE_METHOD) {
		DBGPRINT(RT_DEBUG_OFF, ("load fw image from /lib/firmware/%s\n", cap->fw_bin_file_name));
		DBGPRINT(RT_DEBUG_ERROR, ("%s:Not support now(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->rom_patch_bin_file_name, cap->load_code_method));
	} else {
		cap->rom_patch = cap->rom_patch_header_image;
	}

	if (!cap->rom_patch) {
		if (cap->load_code_method == BIN_FILE_METHOD) {
			DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->fw_bin_file_name, cap->load_code_method));
		} else {
			DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image, load_method(%d)\n",
				__FUNCTION__, cap->load_code_method));
		}
		ret = NDIS_STATUS_FAILURE;
		goto done;
	}

	Ctl->Stage = ROM_PATCH_DOWNLOAD;

	DBGPRINT(RT_DEBUG_TRACE, ("Build Date:"));

	for (loop = 0; loop < 16; loop++)
		DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + loop)));

	DBGPRINT(RT_DEBUG_OFF, ("\n"));

	DBGPRINT(RT_DEBUG_OFF, ("platform = \n"));

	for (loop = 0; loop < 4; loop++)
		DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + 16 + loop)));

	DBGPRINT(RT_DEBUG_OFF, ("\n"));

	DBGPRINT(RT_DEBUG_OFF, ("hw/sw version = \n"));

	for (loop = 0; loop < 4; loop++)
		DBGPRINT(RT_DEBUG_OFF, ("%02x", *(cap->rom_patch + 20 + loop)));

	DBGPRINT(RT_DEBUG_OFF, ("\n"));

	DBGPRINT(RT_DEBUG_OFF, ("patch version = \n"));

	for (loop = 0; loop < 4; loop++)
		DBGPRINT(RT_DEBUG_OFF, ("%02x", *(cap->rom_patch + 24 + loop)));

	DBGPRINT(RT_DEBUG_OFF, ("\n"));

	total_checksum = *(cap->rom_patch + 28) | (*(cap->rom_patch + 29) << 8);

	patch_len = cap->rom_patch_len - PATCH_INFO_SIZE;

	DBGPRINT(RT_DEBUG_INFO, ("\ndownload len = %d\n", patch_len));

#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT)
	/* switch to bypass mode */
	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value &= ~SCH_REG4_BYPASS_MODE_MASK;
	value |= SCH_REG4_BYPASS_MODE(1);
#ifdef RTMP_USB_SUPPORT
	value &= ~SCH_REG4_FORCE_QID_MASK;
	value |= SCH_REG4_FORCE_QID(8);
#endif
	RTMP_IO_WRITE32(ad, SCH_REG4, value);
#endif

#if 0
	ret = CmdPatchSemGet(ad, GET_PATCH_SEM);

	if (ret)
		goto done;

	if (Ctl->SemStatus != 2) {
		Ctl->Stage = FW_NO_INIT;
		DBGPRINT(RT_DEBUG_OFF, ("\nPatch download before or Get Sem Fail, Status (%d)\n", Ctl->SemStatus));
		goto done;
	}
#endif

	/* standard CMD procedure */
	/* 1. Config PDA phase */
	ret = CmdAddressLenReq(ad, ROM_PATCH_START_ADDRESS, patch_len, TARGET_ADDR_LEN_NEED_RSP);

	if (ret)
		goto done;

	/* 2. Loading rom patch image phase */
	ret = CmdFwScatters(ad, cap->rom_patch + PATCH_INFO_SIZE, patch_len);

	if (ret)
		goto done;

	/* 3. ROM patch start negotiation phase */
	ret = CmdPatchFinishReq(ad);

	DBGPRINT(RT_DEBUG_OFF, ("Send checksum req..\n"));

	pChipOps->AndesMTChkCrc(ad, patch_len);

	RtmpOsMsDelay(20);

	if (total_checksum != pChipOps->AndesMTGetCrc(ad)) {
		DBGPRINT(RT_DEBUG_OFF, ("checksum fail!, local(0x%x) <> fw(0x%x)\n", total_checksum,
										pChipOps->AndesMTGetCrc(ad)));

		ret = NDIS_STATUS_FAILURE;
	}

	DBGPRINT(RT_DEBUG_OFF, ("checksum=0x%x\n", pChipOps->AndesMTGetCrc(ad)));

#if 0
	ret = CmdPatchSemGet(ad, REL_PATCH_SEM);

	if (ret)
		goto done;
#endif

done:

#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT)
	/* Switch to normal mode */
	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value &= ~SCH_REG4_BYPASS_MODE_MASK;
	value |= SCH_REG4_BYPASS_MODE(0);
	value &= ~SCH_REG4_FORCE_QID_MASK;
	value |= SCH_REG4_FORCE_QID(0);
	RTMP_IO_WRITE32(ad, SCH_REG4, value);

	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value |= (1 << 8);
	RTMP_IO_WRITE32(ad, SCH_REG4, value);
	RTMP_IO_READ32(ad, SCH_REG4, &value);
	value &= ~(1 << 8);
	RTMP_IO_WRITE32(ad, SCH_REG4, value);
#endif

	return ret;
}


INT32 AndesMTEraseFw(RTMP_ADAPTER *pAd)
{
	RTMP_CHIP_CAP *cap = &pAd->chipCap;

	if (cap->load_code_method == BIN_FILE_METHOD) {

		if (cap->FWImageName)
        {
			os_free_mem(NULL, cap->FWImageName);
			cap->FWImageName = NULL;
        }
	}

	return 0;
}


static VOID EventChPrivilegeHandler(RTMP_ADAPTER *pAd, UINT8 *Data, UINT32 Length)
{
	//struct cmd_msg *msg, *msg_tmp;
	struct MCU_CTRL *ctl = &pAd->MCUCtrl;
	UINT32 Value;

	if (IS_MT7603(pAd) || IS_MT7628(pAd))
	{
		RTMP_IO_READ32(pAd, RMAC_RMCR, &Value);

		if (ctl->RxStream0 == 1)
			Value |= RMAC_RMCR_RX_STREAM_0;
		else
			Value &= ~RMAC_RMCR_RX_STREAM_0;

		if (ctl->RxStream1 == 1)
			Value |= RMAC_RMCR_RX_STREAM_1;
		else
			Value &= ~RMAC_RMCR_RX_STREAM_1;

		RTMP_IO_WRITE32(pAd, RMAC_RMCR, Value);
	}

	DBGPRINT(RT_DEBUG_INFO, ("%s\n", __FUNCTION__));
}

#ifdef CONFIG_STA_SUPPORT
static VOID ExtEventBeaconLostHandler(RTMP_ADAPTER *pAd, UINT8 *Data, UINT32 Length)
{
	struct _EXT_EVENT_BEACON_LOSS_T *pExtEventBeaconLoss = (struct _EXT_EVENT_BEACON_LOSS_T *)Data;

	pAd->StaCfg.PwrMgmt.bBeaconLost = TRUE;

	DBGPRINT(RT_DEBUG_TRACE, ("%s::FW LOG, Beacon lost (%x:%x:%x:%x:%x:%x)\n",
								__FUNCTION__,
								pExtEventBeaconLoss->aucBssid[0],
								pExtEventBeaconLoss->aucBssid[1],
								pExtEventBeaconLoss->aucBssid[2],
								pExtEventBeaconLoss->aucBssid[3],
								pExtEventBeaconLoss->aucBssid[4],
								pExtEventBeaconLoss->aucBssid[5]));
}
#endif /*CONFIG_STA_SUPPORT*/

static VOID ExtEventFwLog2HostHandler(RTMP_ADAPTER *pAd, UINT8 *Data, UINT32 Length)
{
	DBGPRINT(RT_DEBUG_TRACE, ("FW LOG: %s\n", Data));
}


static VOID EventExtEventHandler(RTMP_ADAPTER *pAd, UINT8 ExtEID, UINT8 *Data, UINT32 Length)
{
	switch (ExtEID)
	{
		case EXT_EVENT_CMD_RESULT:
			EventExtCmdResultHandler(pAd, Data, (UINT16)Length);
			break;
		case EXT_EVENT_FW_LOG_2_HOST:
			ExtEventFwLog2HostHandler(pAd, Data, Length);
			break;
#ifdef MT_PS
#if defined(MT7603) && defined(RTMP_PCI_SUPPORT)
		case EXT_CMD_PS_RETRIEVE_START:
			CmdPsRetrieveStartRspFromCR(pAd, Data, Length);
			break; 
#endif /* MT7603 */
#endif /* MT_PS */
#ifdef THERMAL_PROTECT_SUPPORT
		case EXT_EVENT_THERMAL_PROTECT:
			EventThermalProtect(pAd, Data, Length);
			break;
#endif
#ifdef BCN_OFFLOAD_SUPPORT
        case EXT_EVENT_BCN_UPDATE:
            ExtEventBcnUpdateHandler(pAd, Data, Length);
            break;
#endif

#ifdef CONFIG_STA_SUPPORT
	case EXT_EVENT_BEACON_LOSS:
		ExtEventBeaconLostHandler(pAd, Data, Length);
		break;
#endif /*CONFIG_STA_SUPPORT*/
		default:
			DBGPRINT(RT_DEBUG_OFF, ("%s: Unknown Ext Event(%x)\n", __FUNCTION__,
										ExtEID));
			break;
	}


}


static VOID UnsolicitedEventHandler(RTMP_ADAPTER *pAd, UINT8 EID, UINT8 ExtEID, UINT8 *Data, UINT32 Length)
{
	switch (EID)
	{
		case EVENT_CH_PRIVILEGE:
			EventChPrivilegeHandler(pAd, Data, Length);
			break;
		case EXT_EVENT:
			EventExtEventHandler(pAd, ExtEID, Data, Length);
			break;
		default:
			DBGPRINT(RT_DEBUG_OFF, ("%s: Unknown Event(%x)\n", __FUNCTION__, EID));
			break;
	}
}


static VOID AndesMTRxProcessEvent(RTMP_ADAPTER *pAd, struct cmd_msg *rx_msg)
{
	PNDIS_PACKET net_pkt = rx_msg->net_pkt;
	struct cmd_msg *msg, *msg_tmp;
	EVENT_RXD *event_rxd = (EVENT_RXD *)GET_OS_PKT_DATAPTR(net_pkt);
	struct MCU_CTRL *ctl = &pAd->MCUCtrl;
#ifdef RTMP_PCI_SUPPORT
	unsigned long flags;
#endif /* RTMP_PCI_SUPPORT */
	//event_rxd->fw_rxd_0.word = le2cpu32(event_rxd->fw_rxd_0.word);
	event_rxd->fw_rxd_1.word = le2cpu32(event_rxd->fw_rxd_1.word);
	event_rxd->fw_rxd_2.word = le2cpu32(event_rxd->fw_rxd_2.word);

#ifdef CONFIG_TRACE_SUPPORT
	TRACE_MCU_EVENT_INFO(event_rxd->fw_rxd_0.field.length, event_rxd->fw_rxd_0.field.pkt_type_id,
								event_rxd->fw_rxd_1.field.eid, event_rxd->fw_rxd_1.field.seq_num,
							event_rxd->fw_rxd_2.field.ext_eid, GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*event_rxd), event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd));
#endif


#if 0
	printk("event_rxd->fw_rxd_1.field.eid = %x, event_rxd->fw_rxd_1.field.seq_num = %x,\
			event_rxd->fw_rxd_2.field.ext_eid = %x\n", event_rxd->fw_rxd_1.field.eid,\
			event_rxd->fw_rxd_1.field.seq_num, event_rxd->fw_rxd_2.field.ext_eid);
#endif

	if ((event_rxd->fw_rxd_1.field.seq_num == 0) ||
			(event_rxd->fw_rxd_2.field.ext_eid == EXT_EVENT_FW_LOG_2_HOST) ||
			(event_rxd->fw_rxd_2.field.ext_eid == EXT_EVENT_THERMAL_PROTECT)) {
		/* if have callback function */
		UnsolicitedEventHandler(pAd, (UINT8)event_rxd->fw_rxd_1.field.eid
				, (UINT8)event_rxd->fw_rxd_2.field.ext_eid
				, GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*event_rxd)
				, event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd));
	}
	else
	{
#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT)
		RTMP_SPIN_LOCK_IRQ(&ctl->ackq_lock);
#endif

#ifdef RTMP_PCI_SUPPORT
		RTMP_SPIN_LOCK_IRQSAVE(&ctl->ackq_lock, &flags);
#endif
		DlListForEachSafe(msg, msg_tmp, &ctl->ackq, struct cmd_msg, list) {
			if (msg->seq == event_rxd->fw_rxd_1.field.seq_num)
			{
				_AndesUnlinkCmdMsg(msg, &ctl->ackq);
#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT)
				RTMP_SPIN_UNLOCK_IRQ(&ctl->ackq_lock);
#endif

#ifdef RTMP_PCI_SUPPORT
				RTMP_SPIN_UNLOCK_IRQRESTORE(&ctl->ackq_lock, &flags);
#endif

				if ((event_rxd->fw_rxd_1.field.eid == MT_FW_START_RSP)
						|| (event_rxd->fw_rxd_1.field.eid == MT_RESTART_DL_RSP)
						|| (event_rxd->fw_rxd_1.field.eid == MT_TARGET_ADDRESS_LEN_RSP)
						|| (event_rxd->fw_rxd_1.field.eid == MT_PATCH_SEM_RSP)) {
					msg->rsp_handler(msg, (char*)(GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*event_rxd) - 4),
											event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd) + 4);

				}
				else if ((msg->rsp_payload_len == event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd))
						&& (msg->rsp_payload_len != 0))
				{
					if (msg->rsp_handler == NULL)
					{
						DBGPRINT(RT_DEBUG_ERROR, ("%s(): rsp_handler is NULL!!!! (cmd_type = 0x%x, ext_cmd_type = 0x%x)\n", 
							__FUNCTION__, msg->cmd_type, msg->ext_cmd_type));
					}
					else
					{
						msg->rsp_handler(msg, GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*event_rxd), 
												event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd));
					}
				}
				else
				{
					DBGPRINT(RT_DEBUG_ERROR, ("expect response len(%d), command response len(%zu) invalid\n", msg->rsp_payload_len, event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd)));
					msg->rsp_payload_len =
					(UINT16)(event_rxd->fw_rxd_0.field.length -
					sizeof(*event_rxd));
				}

				if (msg->need_wait) {
					RTMP_OS_COMPLETE(&msg->ack_done);
				} else {
					AndesFreeCmdMsg(msg);
				}
#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT)
				RTMP_SPIN_LOCK_IRQ(&ctl->ackq_lock);
#endif

#ifdef RTMP_PCI_SUPPORT
				RTMP_SPIN_LOCK_IRQSAVE(&ctl->ackq_lock, &flags);
#endif

				break;
			}
		}

#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT)
		RTMP_SPIN_UNLOCK_IRQ(&ctl->ackq_lock);
#endif

#ifdef RTMP_PCI_SUPPORT
		RTMP_SPIN_UNLOCK_IRQRESTORE(&ctl->ackq_lock, &flags);
#endif
	}
}


VOID AndesMTRxEventHandler(RTMP_ADAPTER *pAd, UCHAR *data)
{
	struct cmd_msg *msg;
	struct MCU_CTRL *ctl = &pAd->MCUCtrl;
	EVENT_RXD *event_rxd = (EVENT_RXD *)data;

	if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) {
		return;
	}

	DBGPRINT(RT_DEBUG_INFO, ("%s\n", __FUNCTION__));

	msg = AndesAllocCmdMsg(pAd, event_rxd->fw_rxd_0.field.length);

	if (!msg)
		return;

	AndesAppendCmdMsg(msg, (char *)data, event_rxd->fw_rxd_0.field.length);

	AndesMTRxProcessEvent(pAd, msg);

#ifdef RTMP_PCI_SUPPORT
	if (msg->net_pkt)
		RTMPFreeNdisPacket(pAd, msg->net_pkt);
#endif
		
	AndesFreeCmdMsg(msg);
}


#ifdef RTMP_PCI_SUPPORT
VOID AndesMTPciFwInit(RTMP_ADAPTER *pAd)
{
	struct MCU_CTRL *Ctl = &pAd->MCUCtrl;

	DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
	Ctl->Stage = FW_NO_INIT;
	/* Enable Interrupt*/
	RTMP_IRQ_ENABLE(pAd);
	RT28XXDMAEnable(pAd);
	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP);
	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);
}


VOID AndesMTPciFwExit(RTMP_ADAPTER *pAd)
{
	DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP);
	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);
	RT28XXDMADisable(pAd);
	RTMP_ASIC_INTERRUPT_DISABLE(pAd);
}
#endif /* RTMP_PCI_SUPPORT */


#ifdef RTMP_USB_SUPPORT
VOID AndesMTUsbFwInit(RTMP_ADAPTER *pAd)
{
	struct MCU_CTRL *Ctl = &pAd->MCUCtrl;

	DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
	Ctl->Stage = FW_NO_INIT;
	RT28XXDMAEnable(pAd);
	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP);
	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);
	UsbRxCmdMsgsReceive(pAd);
	RTUSBBulkReceive(pAd);
}
#endif /* RTMP_USB_SUPPORT */


#ifdef RTMP_SDIO_SUPPORT
VOID AndesMTSdioFwInit(RTMP_ADAPTER *pAd)
{
	struct MCU_CTRL *Ctl = &pAd->MCUCtrl;
	UINT32 value;

	DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
	Ctl->Stage = FW_NO_INIT;
	/* Enable Interrupt*/
	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP);
	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);

	RTMP_SDIO_WRITE32(pAd, WHIER, (RX0_DONE_INT_EN |RX1_DONE_INT_EN));
	RTMP_SDIO_READ32(pAd, WHIER,&value);
	printk("%s(): MCR_WHIER: value:%x\n", __FUNCTION__,value);
	RTMP_SDIO_READ32(pAd, WHISR,&value);
	printk("%s(): MCR_WHISR1: value:%x\n", __FUNCTION__,value); 
	RTMP_SDIO_WRITE32(pAd, WHLPCR, W_INT_EN_SET);

}


VOID AndesMTSdioFwExit(RTMP_ADAPTER *pAd)
{
	DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP);
	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);
}
#endif


static VOID CmdEfuseBufferModeRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	struct _EVENT_EXT_CMD_RESULT_T *EventExtCmdResult = (struct _EVENT_EXT_CMD_RESULT_T *)Data;
	//RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv;

	DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.ucExTenCID = 0x%x\n",__FUNCTION__, EventExtCmdResult->ucExTenCID));
	EventExtCmdResult->u4Status = le2cpu32(EventExtCmdResult->u4Status);
	DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.u4Status = 0x%x\n",__FUNCTION__, EventExtCmdResult->u4Status));
}

static VOID CmdThemalSensorRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	struct _EXT_EVENT_GET_SENSOR_RESULT_T *EventExtCmdResult = (struct _EXT_EVENT_GET_SENSOR_RESULT_T *)Data;
	//RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv;

	EventExtCmdResult->u4SensorResult = le2cpu32(EventExtCmdResult->u4SensorResult);
	DBGPRINT(RT_DEBUG_OFF, ("ThemalSensor = 0x%x\n", EventExtCmdResult->u4SensorResult));
}


static inline VOID bufferModeFieldSet(RTMP_ADAPTER *pAd,EXT_CMD_EFUSE_BUFFER_MODE_T *pCmd,UINT16 addr)
{
	UINT32 i = pCmd->ucCount;
	
	if (i >= EFUSE_CONTENT_BUFFER_SIZE) {
		DBGPRINT(RT_DEBUG_ERROR,
			("%s: EFUSE_CONTENT_BUFFER_SIZE Overflow\n",
			__FUNCTION__));
		return;
	}
	
	pCmd->aBinContent[i].u2Addr = cpu2le16(addr);
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[addr] ;
	pCmd->ucCount++;	
}

static VOID CmdExtPmMgtBitRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	struct _EVENT_EXT_CMD_RESULT_T *EventExtCmdResult = (struct _EVENT_EXT_CMD_RESULT_T *)Data;
	//RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv;

	DBGPRINT(RT_DEBUG_OFF, ("%s: EventExtCmdResult.ucExTenCID = 0x%x\n",__FUNCTION__, EventExtCmdResult->ucExTenCID));
	EventExtCmdResult->u4Status = le2cpu32(EventExtCmdResult->u4Status);
	DBGPRINT(RT_DEBUG_OFF, ("%s: EventExtCmdResult.u4Status = 0x%x\n",__FUNCTION__, EventExtCmdResult->u4Status));
}

static VOID CmdExtPmStateCtrlRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	struct _EVENT_EXT_CMD_RESULT_T *EventExtCmdResult = (struct _EVENT_EXT_CMD_RESULT_T *)Data;
	//RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv;

	DBGPRINT(RT_DEBUG_OFF, ("%s: EventExtCmdResult.ucExTenCID = 0x%x\n",__FUNCTION__, EventExtCmdResult->ucExTenCID));
	EventExtCmdResult->u4Status = le2cpu32(EventExtCmdResult->u4Status);
	DBGPRINT(RT_DEBUG_OFF, ("%s: EventExtCmdResult.u4Status = 0x%x\n",__FUNCTION__, EventExtCmdResult->u4Status));
}

static VOID CmdFillEeprom(RTMP_ADAPTER *pAd,EXT_CMD_EFUSE_BUFFER_MODE_T *pCmd)
{
	UINT8 i = 0;
	pCmd->aBinContent[i].u2Addr = NIC_CONFIGURE_0_TOP;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[NIC_CONFIGURE_0_TOP] ;
	i++;
	pCmd->aBinContent[i].u2Addr = NIC_CONFIGURE_1;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[NIC_CONFIGURE_1];
	i++;
	pCmd->aBinContent[i].u2Addr = NIC_CONFIGURE_1_TOP;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[NIC_CONFIGURE_1_TOP];
	i++;
	pCmd->aBinContent[i].u2Addr = WIFI_RF_SETTING;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[WIFI_RF_SETTING];
	i++;
	pCmd->aBinContent[i].u2Addr = G_BAND_20_40_BW_PWR_DELTA;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[G_BAND_20_40_BW_PWR_DELTA];
	i++;
	pCmd->aBinContent[i].u2Addr = A_BAND_20_80_BW_PWR_DELTA_ANALOG;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[A_BAND_20_80_BW_PWR_DELTA_ANALOG];
	i++;
	pCmd->aBinContent[i].u2Addr = A_BAND_EXT_PA_SETTING;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[A_BAND_EXT_PA_SETTING];
	i++;
	pCmd->aBinContent[i].u2Addr = TEMP_SENSOR_CAL;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TEMP_SENSOR_CAL];
	i++;
	pCmd->aBinContent[i].u2Addr = TX0_G_BAND_TSSI_SLOPE;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_TSSI_SLOPE];
	i++;
	pCmd->aBinContent[i].u2Addr = TX0_G_BAND_TSSI_SLOPE_TOP;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_TSSI_SLOPE_TOP];
	i++;
	pCmd->aBinContent[i].u2Addr = TX0_G_BAND_TARGET_PWR;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_TARGET_PWR];
	i++;
	pCmd->aBinContent[i].u2Addr = TX0_G_BAND_OFFSET_LOW;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_OFFSET_LOW];
	i++;
	pCmd->aBinContent[i].u2Addr = TX0_G_BAND_CHL_PWR_DELTA_MID;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_CHL_PWR_DELTA_MID];
	i++;
	pCmd->aBinContent[i].u2Addr = TX0_G_BAND_OFFSET_HIGH;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_OFFSET_HIGH];
	i++;
	pCmd->aBinContent[i].u2Addr = TX1_G_BAND_TSSI_SLOPE;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_TSSI_SLOPE];
	i++;
	pCmd->aBinContent[i].u2Addr = TX1_G_BAND_TSSI_SLOPE_TOP;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_TSSI_SLOPE_TOP];
	i++;
	pCmd->aBinContent[i].u2Addr = TX1_G_BAND_TARGET_PWR;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_TARGET_PWR];
	i++;
	pCmd->aBinContent[i].u2Addr = TX1_G_BAND_CHL_PWR_DELATE_LOW;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELATE_LOW];
	i++;
	pCmd->aBinContent[i].u2Addr = TX1_G_BAND_CHL_PWR_DELTA_MID;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELTA_MID];
	i++;
	pCmd->aBinContent[i].u2Addr = TX1_G_BAND_CHL_PWR_DELTA_HIGH;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELTA_HIGH];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_CCK_1_2M;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_CCK_1_2M];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_CCK_5_11M;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_CCK_5_11M];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_G_BAND_OFDM_6_9M;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_G_BAND_OFDM_6_9M];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_OFDM_12_18M;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_OFDM_12_18M];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_G_BAND_OFDM_24_36M;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_G_BAND_OFDM_24_36M];
	i++;	
	pCmd->aBinContent[i].u2Addr = TX_PWR_G_BNAD_OFDM_48;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_G_BNAD_OFDM_48];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_G_BAND_OFDM_54M;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_G_BAND_OFDM_54M];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_HT_BPSK_MCS_0_8;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_BPSK_MCS_0_8];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_HT_BPSK_MCS_32;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_BPSK_MCS_32];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_HT_QPSK_MCS_1_2_9_10;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_QPSK_MCS_1_2_9_10];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_HT_16QAM_MCS_3_4_11_12;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_16QAM_MCS_3_4_11_12];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_HT_64QAM_MCS_5_13;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_64QAM_MCS_5_13];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_HT_64QAM_MCS_6_14;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_64QAM_MCS_6_14];
	i++;
	pCmd->aBinContent[i].u2Addr = TX_PWR_HT_64QAM_MCS_7_15;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_64QAM_MCS_7_15];
	i++;
	pCmd->aBinContent[i].u2Addr = ELAN_RX_MODE_GAIN;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_RX_MODE_GAIN];
	i++;
	pCmd->aBinContent[i].u2Addr = ELAN_RX_MODE_NF;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_RX_MODE_NF];
	i++;
	pCmd->aBinContent[i].u2Addr = ELAN_RX_MODE_P1DB;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_RX_MODE_P1DB];
	i++;
	pCmd->aBinContent[i].u2Addr = ELAN_BYPASS_MODE_GAIN;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_BYPASS_MODE_GAIN];
	i++;
	pCmd->aBinContent[i].u2Addr = ELAN_BYPASS_MODE_NF;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_BYPASS_MODE_NF];
	i++;
	pCmd->aBinContent[i].u2Addr = ELAN_BYPASS_MODE_P1DB;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_BYPASS_MODE_P1DB];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_7;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_7];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_6;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_6];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_5;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_5];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_4;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_4];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_3;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_3];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_2;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_2];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_1;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_1];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_0;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_0];
	i++;
	pCmd->aBinContent[i].u2Addr = REF_STEP_24G;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[REF_STEP_24G];
	i++;
	pCmd->aBinContent[i].u2Addr = REF_TEMP_24G;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[REF_TEMP_24G];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_1;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_1];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_2;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_2];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_3;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_3];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_4;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_4];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_5;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_5];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_6;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_6];
	i++;
	pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_7;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_7];
	i++;
	pCmd->aBinContent[i].u2Addr = XTAL_CALIB_FREQ_OFFSET;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[XTAL_CALIB_FREQ_OFFSET];
	i++;
	pCmd->aBinContent[i].u2Addr = XTAL_TRIM_2_COMP;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[XTAL_TRIM_2_COMP];
	i++;
	pCmd->aBinContent[i].u2Addr = XTAL_TRIM_3_COMP;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[XTAL_TRIM_3_COMP];
	i++;
	pCmd->aBinContent[i].u2Addr = WF_RCAL;
	pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[WF_RCAL];
	i++;

	pCmd->ucCount = i;
	/*check endian and transfer it is needed*/
	for(i=0;i<pCmd->ucCount ;i++)
	{
		pCmd->aBinContent[i].u2Addr = cpu2le16(pCmd->aBinContent[i].u2Addr);
	}

	/*extend for function requset, need backward compatible*/
	bufferModeFieldSet(pAd,pCmd,0x24);	
	bufferModeFieldSet(pAd,pCmd,0x25);
	bufferModeFieldSet(pAd,pCmd,0x34);
	bufferModeFieldSet(pAd,pCmd,0x39);
	bufferModeFieldSet(pAd,pCmd,0x3b);
	bufferModeFieldSet(pAd,pCmd,0x42);
	bufferModeFieldSet(pAd,pCmd,0x43);
	bufferModeFieldSet(pAd,pCmd,0x9e);
	bufferModeFieldSet(pAd,pCmd,0x9f);
	bufferModeFieldSet(pAd,pCmd,0xf2);
	bufferModeFieldSet(pAd,pCmd,0xf8);
	bufferModeFieldSet(pAd,pCmd,0xf9);
	bufferModeFieldSet(pAd,pCmd,0xfa);
	bufferModeFieldSet(pAd,pCmd,0x12e);	

	for(i=0;i<=0xf;i++)
	{
		bufferModeFieldSet(pAd,pCmd,0x130+i);
	}
	
	/*need minus 1 for add one more time*/
	pCmd->ucCount--;
	
}

VOID CmdEfusBufferModeSet(RTMP_ADAPTER *pAd)
{

	struct cmd_msg *msg;
	EXT_CMD_EFUSE_BUFFER_MODE_T CmdEfuseBufferMode;
	int ret = 0;
	msg = AndesAllocCmdMsg(pAd, sizeof(EXT_CMD_EFUSE_BUFFER_MODE_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_EFUSE_BUFFER_MODE, TRUE, 0,TRUE, TRUE, 8, NULL, CmdEfuseBufferModeRsp);
	memset(&CmdEfuseBufferMode, 0x00, sizeof(CmdEfuseBufferMode));
	switch(pAd->eeprom_type){
	case EEPROM_EFUSE:
	{
		CmdEfuseBufferMode.ucSourceMode = EEPROM_MODE_EFUSE;
		CmdEfuseBufferMode.ucCount = 0;
	}
	break;
	case EEPROM_FLASH:
	{
		CmdEfuseBufferMode.ucSourceMode = EEPROM_MODE_BUFFER;
		CmdFillEeprom(pAd,&CmdEfuseBufferMode);
	}
	break;
	default:
		goto error;
	break;
	}
	
	AndesAppendCmdMsg(msg, (char *)&CmdEfuseBufferMode, sizeof(CmdEfuseBufferMode));
	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ;

}

VOID CmdSetTxPowerCtrl(RTMP_ADAPTER *pAd, UINT8 central_chl)
{
	struct cmd_msg *msg;
	EXT_CMD_TX_POWER_CTRL_T CmdTxPwrCtrl;
	int ret = 0;
	USHORT i;
	int j;
	UINT8 PwrPercentageDelta = 0;
	USHORT Value;
	struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap;

	msg = AndesAllocCmdMsg(pAd, sizeof(EXT_CMD_TX_POWER_CTRL_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_SET_TX_POWER_CTRL, TRUE, 0,
		TRUE, TRUE, 8, NULL, EventExtCmdResult);
	memset(&CmdTxPwrCtrl, 0x00, sizeof(CmdTxPwrCtrl));

	CmdTxPwrCtrl.ucCenterChannel = central_chl;
	
	if (pAd->eeprom_type == EEPROM_EFUSE)
	{
		
		RT28xx_EEPROM_READ16(pAd, NIC_CONFIGURE_1, Value);
		CmdTxPwrCtrl.ucTSSIEnable = (UINT8)((Value & 0xff00) >> 8);

		RT28xx_EEPROM_READ16(pAd, NIC_CONFIGURE_1, Value);
		CmdTxPwrCtrl.ucTempCompEnable = (Value & 0xff);
	
		RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_TARGET_PWR, Value);
		CmdTxPwrCtrl.aucTargetPower[0] = Value & 0xff;
		RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_TARGET_PWR, Value);
		CmdTxPwrCtrl.aucTargetPower[1] = Value & 0xff;

		j = 0;

		for (i = 0; i < 7; i++)
		{
			RT28xx_EEPROM_READ16(pAd, TX_PWR_CCK_1_2M + (i * 2), Value);
			CmdTxPwrCtrl.aucRatePowerDelta[j] = Value & 0xff;
			j++;
			CmdTxPwrCtrl.aucRatePowerDelta[j] = (UINT8)((Value & 0xff00) >> 8);
			j++;
		}

		RT28xx_EEPROM_READ16(pAd, G_BAND_20_40_BW_PWR_DELTA, Value);
		CmdTxPwrCtrl.ucBWPowerDelta = Value & 0xff;

		RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_TARGET_PWR, Value);
		CmdTxPwrCtrl.aucCHPowerDelta[0] = (UINT8)((Value & 0xff00) >> 8);
		
		RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_CHL_PWR_DELTA_MID, Value);
		CmdTxPwrCtrl.aucCHPowerDelta[1] = Value & 0xff;
		
		CmdTxPwrCtrl.aucCHPowerDelta[2] = (UINT8)((Value & 0xff00) >> 8);
		
		RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_TARGET_PWR, Value);
		CmdTxPwrCtrl.aucCHPowerDelta[3] = (UINT8)((Value & 0xff00) >> 8);
		
		RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_CHL_PWR_DELTA_MID, Value);
		CmdTxPwrCtrl.aucCHPowerDelta[4] = Value & 0xff;
		
		CmdTxPwrCtrl.aucCHPowerDelta[5] = (UINT8)((Value & 0xff00) >> 8);
		
		j = 0;

		for (i = 0; i < 9; i++)
		{
			RT28xx_EEPROM_READ16(pAd, STEP_NUM_NEG_7 + (i * 2), Value);
			CmdTxPwrCtrl.aucTempCompPower[j] = Value & 0xff;
			j++;

			if (i != 8)
			{
				CmdTxPwrCtrl.aucTempCompPower[j] = (UINT8)((Value & 0xff00) >> 8);
				j++;
			}
		}
	}
	else
	{
		CmdTxPwrCtrl.ucTSSIEnable = pAd->EEPROMImage[NIC_CONFIGURE_1_TOP];
		CmdTxPwrCtrl.ucTempCompEnable = pAd->EEPROMImage[NIC_CONFIGURE_1];

		CmdTxPwrCtrl.aucTargetPower[0] = pAd->EEPROMImage[TX0_G_BAND_TARGET_PWR];
		CmdTxPwrCtrl.aucTargetPower[1] = pAd->EEPROMImage[TX1_G_BAND_TARGET_PWR];

#ifdef CONFIG_ATE
        /* Replace Target Power from QA Tool manual setting*/
		if (ATE_ON(pAd)) {
			DBGPRINT(RT_DEBUG_TRACE, ("%s,ATE set tx power\n", __FUNCTION__));
			CmdTxPwrCtrl.aucTargetPower[0] = pAd->ATECtrl.TxPower0;
			CmdTxPwrCtrl.aucTargetPower[1] = pAd->ATECtrl.TxPower1;
		}
#endif

		NdisCopyMemory(&CmdTxPwrCtrl.aucRatePowerDelta[0], &(pAd->EEPROMImage[TX_PWR_CCK_1_2M]), sizeof(CmdTxPwrCtrl.aucRatePowerDelta));
		CmdTxPwrCtrl.ucBWPowerDelta = pAd->EEPROMImage[G_BAND_20_40_BW_PWR_DELTA];
		NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[0], &(pAd->EEPROMImage[TX0_G_BAND_OFFSET_LOW]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[0]));
		NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[1], &(pAd->EEPROMImage[TX0_G_BAND_CHL_PWR_DELTA_MID]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[1]));
		NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[2], &(pAd->EEPROMImage[TX0_G_BAND_OFFSET_HIGH]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[2]));
		NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[3], &(pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELATE_LOW]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[3]));

		NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[4], &(pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELTA_MID]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[4]));

		NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[5], &(pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELTA_HIGH]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[5]));

		NdisCopyMemory(&CmdTxPwrCtrl.aucTempCompPower[0], &(pAd->EEPROMImage[STEP_NUM_NEG_7]), sizeof(CmdTxPwrCtrl.aucTempCompPower));
	}

	DBGPRINT(RT_DEBUG_INFO, ("PA type = %d\n", cap->pa_type));

//	if (!(cap->pa_type & (1 << 1)))
	if (1)
	{

		if (pAd->CommonCfg.TxPowerPercentage > 90)
		{
				PwrPercentageDelta = 0;
			}
		else if (pAd->CommonCfg.TxPowerPercentage > 60)	/* reduce Pwr for 1 dB. */
		{
			PwrPercentageDelta = 1;
		}
		else if (pAd->CommonCfg.TxPowerPercentage > 30)	/* reduce Pwr for 3 dB. */
		{
			PwrPercentageDelta = 3;
		}
		else if (pAd->CommonCfg.TxPowerPercentage > 15)	/* reduce Pwr for 6 dB. */
		{
			PwrPercentageDelta = 6;
		}
		else if (pAd->CommonCfg.TxPowerPercentage > 9)	/* reduce Pwr for 9 dB. */
		{
			PwrPercentageDelta = 9;
		}
		else /* reduce Pwr for 12 dB. */
		{
			PwrPercentageDelta = 12;
		}

		DBGPRINT(RT_DEBUG_INFO, ("Before apply tx pwr percentage, CmdTxPwrCtrl.aucTargetPower[0] = 0x%x\n", CmdTxPwrCtrl.aucTargetPower[0]));
		
		DBGPRINT(RT_DEBUG_INFO, ("Before apply tx pwr percentage, CmdTxPwrCtrl.aucTargetPower[1] = 0x%x\n", CmdTxPwrCtrl.aucTargetPower[1]));
		DBGPRINT(RT_DEBUG_INFO, ("Percentage = 0x%x\n", PwrPercentageDelta));

		CmdTxPwrCtrl.ucReserved = PwrPercentageDelta;
	}
	else
	{
#ifdef CONFIG_ATE
		if (!ATE_ON(pAd))
#endif
		{
			DBGPRINT(RT_DEBUG_TRACE, ("EPA, do not need to apply tx power percentage\n"));
			goto error;
		}
	}

	DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.ucCenterChannel=%x\n", CmdTxPwrCtrl.ucCenterChannel));
	DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.ucTSSIEnable=%x \n", CmdTxPwrCtrl.ucTSSIEnable));
	DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.ucTempCompEnable=%x\n", CmdTxPwrCtrl.ucTempCompEnable));
	DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.aucTargetPower[0]=%x\n", CmdTxPwrCtrl.aucTargetPower[0]));
	DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.aucTargetPower[1]=%x\n", CmdTxPwrCtrl.aucTargetPower[1]));
	for(i=0; i<14;i++)
		DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.aucRatePowerDelta[%d]=%x\n", i, CmdTxPwrCtrl.aucRatePowerDelta[i]));
	DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.ucBWPowerDelta=%x \n",CmdTxPwrCtrl.ucBWPowerDelta));
	for(i=0;i<6;i++)
		DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.aucCHPowerDelta[%d]=%x\n", i, CmdTxPwrCtrl.aucCHPowerDelta[i]));
	for(i=0;i<17;i++)
		DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.aucTempCompPower[%d]=%x\n", i, CmdTxPwrCtrl.aucTempCompPower[i]));

	AndesAppendCmdMsg(msg, (char *)&CmdTxPwrCtrl, sizeof(CmdTxPwrCtrl));
	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return;
}

VOID CmdGetThemalSensorResult(struct _RTMP_ADAPTER *pAd, UINT8 option)
{
	struct cmd_msg *msg;
	EXT_CMD_GET_SENSOR_RESULT_T CmdSensorResult;
	INT32 ret;
#ifdef CONFIG_QA
	ATE_CTRL *ATECtrl = &(pAd->ATECtrl);
#endif /* CONFIG_QA */
	ret = 0;
		
	msg = AndesAllocCmdMsg(pAd, sizeof(EXT_CMD_GET_SENSOR_RESULT_T));
	
	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}
#ifdef CONFIG_QA	
	//ATE_CTRL *ATECtrl = &(pAd->ATECtrl);
	if(ATECtrl->bQAEnabled){
		DBGPRINT(RT_DEBUG_OFF, ("%s: Call to qa_agent\n", __FUNCTION__));
		AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_GET_THEMAL_SENSOR, TRUE, 0, TRUE, TRUE, 8, NULL, HQA_GetThermalValue_CB);
	} else
#endif
	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_GET_THEMAL_SENSOR, TRUE, 0, TRUE, TRUE, 8, NULL, CmdThemalSensorRsp);

	CmdSensorResult.ucActionIdx = option;

	AndesAppendCmdMsg(msg, (char *)&CmdSensorResult, sizeof(CmdSensorResult));
	ret = AndesSendCmdMsg(pAd, msg);
	
error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ; 
}

#ifdef LED_CONTROL_SUPPORT
INT AndesLedOP(
	IN PRTMP_ADAPTER pAd,
	IN UCHAR LedIdx,
	IN UCHAR LinkStatus)
{
	struct cmd_msg *msg;
	CHAR *Pos, *pBuf;
	UINT32 VarLen;
	UINT32 arg0, arg1;
	INT32 ret;
	UINT32 blinkSel = 2; // 2 : data only, 0 : all Tx frames, 1 : Exclude Tx Beacon and TIM broadcast frames

	ret = 0;
	
	msg = AndesAllocCmdMsg(pAd, sizeof(LED_NMAC_CMD));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_LED_CTRL, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);
	//memset(&CmdEfuseBufferMode, 0x00, sizeof(CmdEfuseBufferMode));

	
	/* Calibration ID and Parameter */
	VarLen = 8;
	arg0 = cpu2le32(LedIdx);
	arg1 = cpu2le32(LinkStatus | (blinkSel << 24));
	os_alloc_mem(pAd, (UCHAR **)&pBuf, VarLen);
	if (pBuf == NULL)
	{
		return NDIS_STATUS_RESOURCES;
	}

	NdisZeroMemory(pBuf, VarLen);
	
	Pos = pBuf;
	/* Parameter */
	
	NdisMoveMemory(Pos, &arg0, 4);
	NdisMoveMemory(Pos+4, &arg1, 4);

	Pos += 4;

	hex_dump("AndesLedOP: ", pBuf, VarLen);
	AndesAppendCmdMsg(msg, (char *)pBuf, VarLen);
	

	ret = AndesSendCmdMsg(pAd, msg);

	os_free_mem(NULL, pBuf);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;	
}

INT AndesLedEnhanceOP(
	IN PRTMP_ADAPTER pAd,
	IN UCHAR LedIdx,
	IN UCHAR on_time,
	IN UCHAR off_time,
	IN UCHAR Led_Parameter
	)
{
	struct cmd_msg *msg;
	CHAR *Pos, *pBuf;
	UINT32 VarLen;
	UINT32 arg0/*, arg1*/;
	INT32 ret = 0;
	//UCHAR parameter[4]={0};
	
	LED_ENHANCE led_enhance;
	msg = AndesAllocCmdMsg(pAd, sizeof(LED_NMAC_CMD));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_LED_CTRL, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);
	//memset(&CmdEfuseBufferMode, 0x00, sizeof(CmdEfuseBufferMode));

	
	/* Calibration ID and Parameter */
	VarLen = 8;
	arg0 = LedIdx;
	//arg1 = LinkStatus;
	//parameter[1]=on_time;
	//parameter[2]=off_time;
	//parameter[3]=31;
	led_enhance.word = 0;
	led_enhance.field.on_time=on_time;
	led_enhance.field.off_time=off_time;
	led_enhance.field.idx = Led_Parameter;
	os_alloc_mem(pAd, (UCHAR **)&pBuf, VarLen);
	if (pBuf == NULL)
	{
		return NDIS_STATUS_RESOURCES;
	}

	NdisZeroMemory(pBuf, VarLen);
	
	Pos = pBuf;
	/* Parameter */
	
	NdisMoveMemory(Pos, &arg0, 4);
	//NdisMoveMemory(Pos+4, &arg1, 4);
	NdisMoveMemory(Pos+4, &led_enhance, sizeof(led_enhance));
	

	Pos += 4;

	hex_dump("AndesLedOPEnhance: ", pBuf, VarLen);
	AndesAppendCmdMsg(msg, (char *)pBuf, VarLen);
	

	ret = AndesSendCmdMsg(pAd, msg);

	os_free_mem(NULL, pBuf);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;	
}
#endif /*LED_CONTROL_SUPPORT*/

INT32 CmdExtPwrMgtBitWifi(RTMP_ADAPTER *pAd, UINT8 ucWlanIdx, UINT8 ucPwrMgtBit)
{
	struct cmd_msg *msg;
	EXT_CMD_PWR_MGT_BIT_T PwrMgtBitWifi = {0};
	INT32 Ret = 0;

	msg = AndesAllocCmdMsg(pAd, sizeof(EXT_CMD_PWR_MGT_BIT_T));

	if (!msg)
	{
		Ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	PwrMgtBitWifi.ucWlanIdx = (UINT8)cpu2le32(ucWlanIdx);
	PwrMgtBitWifi.ucPwrMgtBit = (UINT8)cpu2le32(ucPwrMgtBit);

	DBGPRINT(RT_DEBUG_OFF, ("%s:ucWlanIdx(%d), ucPwrMgtBit(%d)\n", __FUNCTION__, ucWlanIdx, ucPwrMgtBit));

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PWR_MGT_BIT_WIFI, TRUE, 0,TRUE, TRUE, 8, NULL, CmdExtPmMgtBitRsp);

	AndesAppendCmdMsg(msg, (char *)&PwrMgtBitWifi, sizeof(PwrMgtBitWifi));

	Ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_OFF, ("%s:(Ret = %d)\n", __FUNCTION__, Ret));
	return Ret;
}

 /*1: enter, 2: exit specific PM state*/
INT32 CmdExtPmStateCtrl(RTMP_ADAPTER *pAd, UINT8 ucWlanIdx, UINT8 ucPmNumber, UINT8 ucPmState)
{
#ifdef CONFIG_STA_SUPPORT
	static UINT32	u4RfCr = 0;
	UINT32	u4TempRfCr = 0;
	PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[ucWlanIdx];
#endif
	struct cmd_msg *msg = NULL;
	EXT_CMD_PM_STATE_CTRL_T CmdPmStateCtrl = {0};
	INT32 Ret = 0;
	msg = AndesAllocCmdMsg(pAd, sizeof(EXT_CMD_PM_STATE_CTRL_T));

	if (!msg)
	{
		Ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	/* Fill parameter here*/
	CmdPmStateCtrl.ucWlanIdx = (UINT8)cpu2le32(ucWlanIdx);
	CmdPmStateCtrl.ucPmNumber = (UINT8)cpu2le32(ucPmNumber);
	CmdPmStateCtrl.ucPmState = (UINT8)cpu2le32(ucPmState);
#ifdef CONFIG_STA_SUPPORT
	NdisMoveMemory(CmdPmStateCtrl.aucBssid, pEntry->Addr, MAC_ADDR_LEN);
	DBGPRINT(RT_DEBUG_OFF, ("%s:(%x, %x, %x, %x, %x, %x), BeaconPeriod(%d), DtimPeriod(%d), AID(%d)\n",
								__FUNCTION__,
								PRINT_MAC(pEntry->Addr),
								pAd->MlmeAux.BeaconPeriod,
								pAd->MlmeAux.DtimPeriod, 
								pAd->StaActive.Aid));
#endif /* CONFIG_STA_SUPPORT */

#ifdef CONFIG_STA_SUPPORT
	if (ucPmState == ENTER_PM_STATE)
	{
		CmdPmStateCtrl.ucDtimPeriod = (UINT8)cpu2le32(pAd->MlmeAux.DtimPeriod);
		CmdPmStateCtrl.u2BcnInterval = (UINT16)cpu2le32(pAd->MlmeAux.BeaconPeriod);
		CmdPmStateCtrl.u4Aid = cpu2le32(pAd->StaActive.Aid);

		RTMP_IO_READ32(pAd, RMAC_RFCR, &u4RfCr);
		DBGPRINT(RT_DEBUG_OFF, ("%s: RMAC_RFCR 0x%x\n", __FUNCTION__, u4RfCr));
		u4TempRfCr = u4RfCr;
		u4TempRfCr |= (DROP_PROBE_REQ | DROP_NOT_MY_BSSID | DROP_DIFF_BSSID_BCN);
		CmdPmStateCtrl.u4RxFilter = cpu2le32(u4TempRfCr);
		DBGPRINT(RT_DEBUG_OFF, ("%s: u4RxFilter 0x%x\n", __FUNCTION__, CmdPmStateCtrl.u4RxFilter));

		CmdPmStateCtrl.u4Feature = cpu2le32(PM_CMD_FEATURE_PSPOLL_OFFLOAD);
		CmdPmStateCtrl.ucOwnMacIdx = cpu2le32(0); //AsicSetDevMac
		// TODO: Hanmim 7636 psm
		CmdPmStateCtrl.ucWmmIdx = cpu2le32(0);		// 0: WMM1, 1: WMM2
		CmdPmStateCtrl.ucBcnLossCount = cpu2le32(5); // 2.5sec
		CmdPmStateCtrl.ucBcnSpDuration = cpu2le32(0);
	}
	else
	{
		CmdPmStateCtrl.u4RxFilter = cpu2le32(u4RfCr);
	}
#endif /* CONFIG_STA_SUPPORT */

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_PM_STATE_CTRL, TRUE, 0,TRUE, TRUE, 8, NULL, CmdExtPmStateCtrlRsp);

	AndesAppendCmdMsg(msg, (char *)&CmdPmStateCtrl, sizeof(CmdPmStateCtrl));

	Ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_OFF, ("%s:(Ret = %d)\n", __FUNCTION__, Ret));
	return Ret;
}

INT32 CmdEdcaParameterSet(RTMP_ADAPTER *pAd, CMD_EDCA_SET_T EdcaParam)
{
	struct cmd_msg *msg;
	INT32 ret=0,size=0;

	size = 4+sizeof(TX_AC_PARAM_T)*EdcaParam.ucTotalNum;

	msg = AndesAllocCmdMsg(pAd, size);

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_EDCA_SET, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);

	AndesAppendCmdMsg(msg, (char *)&EdcaParam,size);


	ret = AndesSendCmdMsg(pAd, msg);


error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}



INT32 CmdSlotTimeSet(RTMP_ADAPTER *pAd, UINT8 SlotTime,UINT8 SifsTime,UINT8 RifsTime,UINT16 EifsTime)
{
	struct cmd_msg *msg;
	INT32 ret=0;

	CMD_SLOT_TIME_SET_T cmdSlotTime;

	NdisZeroMemory(&cmdSlotTime,sizeof(CMD_SLOT_TIME_SET_T));

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_SLOT_TIME_SET_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_SLOT_TIME_SET, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);

	cmdSlotTime.u2Eifs = EifsTime;
	cmdSlotTime.ucRifs = RifsTime;
	cmdSlotTime.ucSifs = SifsTime;
	cmdSlotTime.ucSlotTime = SlotTime;

	AndesAppendCmdMsg(msg, (char *)&cmdSlotTime,sizeof(CMD_SLOT_TIME_SET_T));


	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}


INT32 CmdIdConfigInternalSetting(RTMP_ADAPTER *pAd, UINT8 SubOpCode, UINT8 Param)
{
	struct cmd_msg *msg;
	INT32 ret=0;
	CMD_CONFIG_INTERNAL_SETTING_T CmdConfigInternalSetting;

	NdisZeroMemory(&CmdConfigInternalSetting, sizeof(CMD_CONFIG_INTERNAL_SETTING_T));

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_CONFIG_INTERNAL_SETTING_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_CONFIG_INTERNAL_SETTING, FALSE, 0, FALSE, FALSE, 0, NULL, NULL);

	CmdConfigInternalSetting.ucSubOpcode = SubOpCode;
	CmdConfigInternalSetting.aucPara[0] = Param;

	AndesAppendCmdMsg(msg, (char *)&CmdConfigInternalSetting, sizeof(CMD_CONFIG_INTERNAL_SETTING_T));

	ret = AndesSendCmdMsg(pAd, msg);

error:
	DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret));
	return ret;
}

#ifdef BCN_OFFLOAD_SUPPORT
VOID RT28xx_UpdateBeaconToMcu(
    IN RTMP_ADAPTER *pAd,
    IN INT apidx,
    IN UCHAR HWBssidIdx,
    IN BOOLEAN Enable,
    IN ULONG FrameLen,
    IN ULONG UpdatePos)
{
    CMD_BCN_UPDATE_T bcn_update;

    NdisZeroMemory(&bcn_update, sizeof(CMD_BCN_UPDATE_T));

    bcn_update.ucHwBssidIdx = HWBssidIdx;
    if (HWBssidIdx > 0) //HWBssid > 0 case, no extendable bssid.
        bcn_update.ucExtBssidIdx = 0;
    else
		bcn_update.ucExtBssidIdx = (UINT8)apidx;

    bcn_update.ucEnable = Enable;
    //bcn_update.ucWlanIdx = 0;//hardcode at present
    bcn_update.u2BcnPeriod = pAd->CommonCfg.BeaconPeriod;

    CmdBcnUpdateSet(pAd, bcn_update);
}
#endif /*BCN_OFFLOAD_SUPPORT*/

#ifdef MT_WOW_SUPPORT
static VOID EventExtCmdPacketFilterRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	P_EXT_EVENT_PF_GENERAL_T pPFRsp = (P_EXT_EVENT_PF_GENERAL_T)Data;

	DBGPRINT(RT_DEBUG_OFF, ("%s: u4PfCmdType = 0x%x u4Status = 0x%x\n",
									__FUNCTION__, le2cpu32(pPFRsp->u4PfCmdType), le2cpu32(pPFRsp->u4Status)));
}

static VOID EventExtCmdWakeupOptionRsp(struct cmd_msg *msg, char *Data, UINT16 Len)
{
	P_EXT_EVENT_WAKEUP_OPTION_T pWakeOptRsp = (P_EXT_EVENT_WAKEUP_OPTION_T)Data;

	DBGPRINT(RT_DEBUG_OFF, ("%s: u4PfCmdType = 0x%x u4Status = 0x%x\n",
									__FUNCTION__, le2cpu32(pWakeOptRsp->u4PfCmdType), le2cpu32(pWakeOptRsp->u4Status)));

}

VOID MT76xxAndesWOWEnable(
	IN PRTMP_ADAPTER pAd)
{
	
	//hw-enable cmd
	//1. magic, parameter=enable
	//2. eapol , param = enable
	//3. bssid , param = bssid[3:0]
	//4. mode, parm = white
	//5. PF, param = enable
	//wakeup command param = choose usb. others dont' care

	struct wifi_dev *wdev = &pAd->StaCfg.wdev;
	MAC_TABLE_ENTRY *pEntry = NULL;

	struct cmd_msg *msg;
	INT32 ret = NDIS_STATUS_SUCCESS;


	//CMD_PACKET_FILTER_MAGIC_PACKET_T CmdMagicPacket;
	CMD_PACKET_FILTER_GLOBAL_T CmdPFGlobal;
	CMD_PACKET_FILTER_GTK_T CmdGTK;
	CMD_PACKET_FILTER_WAKEUP_OPTION_T CmdWakeupOption;
	
	DBGPRINT(RT_DEBUG_OFF, ("%s:\n", __FUNCTION__));

	/* security configuration */
	NdisZeroMemory(&CmdGTK, sizeof(CmdGTK));

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_GTK_T));
	
	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}
	
	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PACKET_FILTER, TRUE, 0,
							TRUE, TRUE, sizeof(EXT_EVENT_PF_GENERAL_T), NULL, EventExtCmdPacketFilterRsp);
	
	CmdGTK.PFType = cpu2le32(_ENUM_TYPE_GTK_REKEY);

	if (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)
		CmdGTK.WPAVersion = cpu2le32(0);
	else
		CmdGTK.WPAVersion = cpu2le32(1);
		
	pEntry = &pAd->MacTab.Content[BSSID_WCID];

#ifdef RT_BIG_ENDIAN
	{
		int index = 0;
		UINT32 *pKey = (UINT32 *)pEntry->PTK;
		for (index=0; index < 64; index += 4)
		{
			*pKey = SWAP32(*pKey);
			pKey++;
		}
	}
#else

#ifndef RT_CFG80211_SUPPORT
	NdisCopyMemory(CmdGTK.PTK, pEntry->PTK, LEN_PTK);
#else
	NdisCopyMemory(CmdGTK.PTK, pAd->WOW_Cfg.PTK, LEN_PTK);
	hex_dump("WOW_Cfg.KCK", pAd->WOW_Cfg.PTK, LEN_PTK_KCK);
	hex_dump("WOW_Cfg.KEK", &pAd->WOW_Cfg.PTK[LEN_PTK_KCK], LEN_PTK_KEK);
#endif

#endif

	CmdGTK.BssidIndex = cpu2le32(0);
	CmdGTK.OwnMacIndex = cpu2le32(0x0);
	CmdGTK.WmmIndex = cpu2le32(0);
	
	if (wdev->AuthMode >= Ndis802_11AuthModeWPAPSK){
		
#ifndef RT_CFG80211_SUPPORT
		NdisCopyMemory(CmdGTK.ReplayCounter, pEntry->ReplayCounter, LEN_KEY_DESC_REPLAY);
#else
		NdisCopyMemory(CmdGTK.ReplayCounter, pAd->WOW_Cfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
#endif

		CmdGTK.GroupKeyIndex = cpu2le32(MCAST_WCID);
		CmdGTK.PairKeyIndex = cpu2le32(pEntry->wcid);
	}
	
	DBGPRINT(RT_DEBUG_OFF, ("%s: BssidIndex %d, GroupKeyIndex %d, OwnMacIndex %d, PairKeyIndex %d, WmmIndex %d\n", 
			__FUNCTION__, CmdGTK.BssidIndex, CmdGTK.GroupKeyIndex, CmdGTK.OwnMacIndex, CmdGTK.PairKeyIndex, CmdGTK.WmmIndex));
	
	AndesAppendCmdMsg(msg, (char *)&CmdGTK, sizeof(CMD_PACKET_FILTER_GTK_T));
	
	ret = AndesSendCmdMsg(pAd, msg);

#if 0
	/* ARP offload */
	if (pAd->WOW_Cfg.IPAddress[0] || 
		pAd->WOW_Cfg.IPAddress[1] ||
		pAd->WOW_Cfg.IPAddress[2] ||
		pAd->WOW_Cfg.IPAddress[3]  )
	{
		os_zero_mem(&CmdARPNS, sizeof(CMD_PACKET_FILTER_ARPNS_T));

		msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_ARPNS_T));

		if (!msg)
		{
			ret = NDIS_STATUS_RESOURCES;
			goto error;
		}
		
		AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PACKET_FILTER, TRUE, 0,
								TRUE, TRUE, sizeof(EXT_EVENT_PF_GENERAL_T), NULL, EventExtCmdPacketFilterRsp);

		CmdARPNS.PFType = cpu2le32(_ENUM_TYPE_ARPNS);
		CmdARPNS.IPIndex = cpu2le32(0);                                 /* default use index 0 */
		CmdARPNS.Enable = cpu2le32(TRUE);
		CmdARPNS.BssidEnable = cpu2le32(BIT(0)|BIT(1)|BIT(2)|BIT(3));   /* enable all BSSID */
		CmdARPNS.Offload = cpu2le32(0);                                 /* IPv4 */
		CmdARPNS.Type = cpu2le32(0x7);                                  /* support all packet type */
		
		NdisCopyMemory(CmdARPNS.IPAddress, pAd->WOW_Cfg.IPAddress, sizeof(CmdARPNS.IPAddress));

		AndesAppendCmdMsg(msg, (char *)&CmdARPNS, sizeof(CMD_PACKET_FILTER_ARPNS_T));
		
		ret = AndesSendCmdMsg(pAd, msg);
	
	}
#endif
	// Wakeup option
	NdisZeroMemory(&CmdWakeupOption, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T));

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}
	
	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_WAKEUP_OPTION, TRUE, 0,
							TRUE, TRUE, sizeof(EXT_EVENT_WAKEUP_OPTION_T), NULL, EventExtCmdWakeupOptionRsp);

	CmdWakeupOption.WakeupInterface = cpu2le32(pAd->WOW_Cfg.nWakeupInterface); 
	CmdWakeupOption.GPIONumber = cpu2le32(pAd->WOW_Cfg.nSelectedGPIO);
	CmdWakeupOption.GPIOTimer = cpu2le32(pAd->WOW_Cfg.nHoldTime); // unit is us
	if (pAd->WOW_Cfg.nWakeupInterface == WOW_WAKEUP_BY_GPIO)
		CmdWakeupOption.GpioParameter |= 0x1;
	if (pAd->WOW_Cfg.bGPIOHighLow == WOW_GPIO_LOW_TO_HIGH)
		CmdWakeupOption.GpioParameter |= 0x4;
	else
		CmdWakeupOption.GpioParameter |= 0x2;
	
	DBGPRINT(RT_DEBUG_OFF, ("%s:(WakeupInterface=%d, GPIONumber=%d, GPIOTimer=%d, GpioParameter=0x%x)\n", __FUNCTION__, CmdWakeupOption.WakeupInterface, 
						CmdWakeupOption.GPIONumber, CmdWakeupOption.GPIOTimer, CmdWakeupOption.GpioParameter));

	AndesAppendCmdMsg(msg, (char *)&CmdWakeupOption, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T));
	
	ret = AndesSendCmdMsg(pAd, msg);

	
	// WOW enable
	NdisZeroMemory(&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T));

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_GLOBAL_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}
	
	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PACKET_FILTER, TRUE, 0,
							TRUE, TRUE, sizeof(EXT_EVENT_PF_GENERAL_T), NULL, EventExtCmdPacketFilterRsp);

	CmdPFGlobal.PFType = cpu2le32(_ENUM_TYPE_GLOBAL_EN);
	CmdPFGlobal.FunctionSelect = cpu2le32(_ENUM_GLOBAL_WOW_EN);
	CmdPFGlobal.Enable = cpu2le32(1); //bit0=1 mean BSS0 for staion mode
	/* if 0: NOT to configure. non-0: set value 1~15 */
	if (pAd->WOW_Cfg.nKeepAlivePeriod != 0) {
		CmdPFGlobal.extParam = ((FW_KEEP_ALIVE_ENABLE_MASK)
			| (pAd->WOW_Cfg.nKeepAlivePeriod & FW_KEEP_ALIVE_PERIOD_MASK));
	}

	AndesAppendCmdMsg(msg, (char *)&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T));
	
	ret = AndesSendCmdMsg(pAd, msg);
	
error:
	DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret));

	return;

}

VOID MT76xxAndesWOWDisable(
    IN PRTMP_ADAPTER pAd)
{
	CMD_PACKET_FILTER_GLOBAL_T CmdPFGlobal;
	MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
	struct cmd_msg *msg;
	INT32 ret = NDIS_STATUS_SUCCESS;
	
	DBGPRINT(RT_DEBUG_OFF, ("%s:\n", __FUNCTION__));

	// PF disable
	NdisZeroMemory(&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T));

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_GLOBAL_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PACKET_FILTER, TRUE, 0,
							TRUE, TRUE, sizeof(EXT_EVENT_PF_GENERAL_T), NULL, EventExtCmdPacketFilterRsp);

	CmdPFGlobal.PFType = cpu2le32(_ENUM_TYPE_GLOBAL_EN);
	CmdPFGlobal.FunctionSelect = cpu2le32(_ENUM_GLOBAL_WOW_EN);
	CmdPFGlobal.Enable = cpu2le32(0);

	AndesAppendCmdMsg(msg, (char *)&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T));

	ret = AndesSendCmdMsg(pAd, msg);
#if 0 //New architecture: just need one CMD to disable WOW.
	/* traffic to Host */
	NdisZeroMemory(&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T));

	msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_GLOBAL_T));

	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PACKET_FILTER, TRUE, 0,
							TRUE, TRUE, sizeof(EXT_EVENT_PF_GENERAL_T), NULL, EventExtCmdPacketFilterRsp);

	CmdPFGlobal.PFType = cpu2le32(_ENUM_TYPE_GLOBAL_EN);
	CmdPFGlobal.FunctionSelect = cpu2le32(_ENUM_GLOBAL_ALL_TOMCU);
	CmdPFGlobal.Enable = cpu2le32(0);

	AndesAppendCmdMsg(msg, (char *)&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T));

	ret = AndesSendCmdMsg(pAd, msg);


	/* Restore MAC TX/RX */
	//AsicSetMacTxRx(pAd, ASIC_MAC_TXRX, TRUE);

#endif

	/* Update GTK */
	AsicStaUpdateGroupKey(pAd);

	/* Reset CCMP RX BMC PN before start rx in case GTK is renewed. */
	pEntry->rx_ccmp_pn_bmc[1] = 0;
	pEntry->rx_ccmp_pn_bmc_zero[1] = TRUE;
	pEntry->rx_ccmp_pn_bmc[2] = 0;
	pEntry->rx_ccmp_pn_bmc_zero[2] = TRUE;

error:
	DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret));

	return;


}

VOID MT76xxAndesWOWInit(
	IN PRTMP_ADAPTER pAd)
{
	struct cmd_msg *msg;
	INT32 ret = NDIS_STATUS_SUCCESS;

	CMD_PACKET_FILTER_WAKEUP_OPTION_T CmdWakeupOption;
	
	if (!pAd->WOW_Cfg.bEnable)
		return;
	
	DBGPRINT(RT_DEBUG_OFF, ("%s:\n", __FUNCTION__));
		
		
	if (pAd->WOW_Cfg.nWakeupInterface == WOW_WAKEUP_BY_GPIO){	
			
		// Wakeup option
		NdisZeroMemory(&CmdWakeupOption, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T));

		msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T));

		if (!msg)
		{
			ret = NDIS_STATUS_RESOURCES;
			goto error;
		}
		
		AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_WAKEUP_OPTION, TRUE, 0,
								TRUE, TRUE, sizeof(EXT_EVENT_WAKEUP_OPTION_T), NULL, EventExtCmdWakeupOptionRsp);

		CmdWakeupOption.WakeupInterface = cpu2le32(pAd->WOW_Cfg.nWakeupInterface); 
		CmdWakeupOption.GPIONumber = cpu2le32(pAd->WOW_Cfg.nSelectedGPIO);
		CmdWakeupOption.GPIOTimer = cpu2le32(pAd->WOW_Cfg.nHoldTime); // unit is us
		if (pAd->WOW_Cfg.nWakeupInterface == WOW_WAKEUP_BY_GPIO)
			CmdWakeupOption.GpioParameter |= 0x1;
		if (pAd->WOW_Cfg.bGPIOHighLow == WOW_GPIO_LOW_TO_HIGH)
			CmdWakeupOption.GpioParameter |= 0x4;
		else
			CmdWakeupOption.GpioParameter |= 0x2;
		
		DBGPRINT(RT_DEBUG_OFF, ("%s:(WakeupInterface=%d, GPIONumber=%d, GPIOTimer=%d, GpioParameter=0x%x)\n", __FUNCTION__, CmdWakeupOption.WakeupInterface, 
							CmdWakeupOption.GPIONumber, CmdWakeupOption.GPIOTimer, CmdWakeupOption.GpioParameter));

		AndesAppendCmdMsg(msg, (char *)&CmdWakeupOption, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T));
		
		ret = AndesSendCmdMsg(pAd, msg);
	}
	
error:
	DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret));

	return;

}

#endif

INT32 CmdACQueue_Control
( IN struct _RTMP_ADAPTER *ad,
  IN UINT8 ucation,  // 0: stop; 1: flush; 2: start
  IN UINT8 BssidIdx,
  IN UINT32 u4AcQueueMap)
{
	struct cmd_msg *msg;
	EXT_CMD_AC_QUEUE_CONTROL_T  ac_queue_control;
	int ret;

	DBGPRINT(RT_DEBUG_TRACE, ("CmdACQueue_Control  ucation %d BssidIdx %d u4AcQueueMap %d\n",ucation,BssidIdx,u4AcQueueMap));

	msg = AndesAllocCmdMsg(ad, sizeof(EXT_CMD_AC_QUEUE_CONTROL_T));
	if (!msg)
	{
		ret = NDIS_STATUS_RESOURCES;
		goto error;
	}

	AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_AC_QUEUE_CONTROL, FALSE, 0,
		FALSE, FALSE, 0, NULL, NULL);

    	NdisZeroMemory(&ac_queue_control, sizeof(EXT_CMD_AC_QUEUE_CONTROL_T));
	ac_queue_control.ucAction = ucation;
	ac_queue_control.ucBssidIdx =BssidIdx;
	ac_queue_control.u4AcQueueMap =u4AcQueueMap;

	AndesAppendCmdMsg(msg, (char *)&ac_queue_control, sizeof(EXT_CMD_AC_QUEUE_CONTROL_T));
	ret = AndesSendCmdMsg(ad, msg);
error:
	DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret));

	return ret;


}


