Path: blob/master/ALFA-W1F1/RTL8814AU/hal/rtl8814a/rtl8814a_xmit.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/14#define _RTL8814A_XMIT_C_1516/* #include <drv_types.h> */17#include <rtl8814a_hal.h>1819void _dbg_dump_tx_info(_adapter *padapter, int frame_tag, u8 *ptxdesc)20{21u8 bDumpTxPkt;22u8 bDumpTxDesc = _FALSE;23rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(bDumpTxPkt));2425if (bDumpTxPkt == 1) { /* dump txdesc for data frame */26RTW_INFO("dump tx_desc for data frame\n");27if ((frame_tag & 0x0f) == DATA_FRAMETAG)28bDumpTxDesc = _TRUE;29} else if (bDumpTxPkt == 2) { /* dump txdesc for mgnt frame */30RTW_INFO("dump tx_desc for mgnt frame\n");31if ((frame_tag & 0x0f) == MGNT_FRAMETAG)32bDumpTxDesc = _TRUE;33} else if (bDumpTxPkt == 3) { /* dump early info */34}3536if (bDumpTxDesc) {37/* ptxdesc->txdw4 = cpu_to_le32(0x00001006); */ /* RTS Rate=24M */38/* ptxdesc->txdw6 = 0x6666f800; */39RTW_INFO("=====================================\n");40RTW_INFO("Offset00(0x%08x)\n", *((u32 *)(ptxdesc)));41RTW_INFO("Offset04(0x%08x)\n", *((u32 *)(ptxdesc + 4)));42RTW_INFO("Offset08(0x%08x)\n", *((u32 *)(ptxdesc + 8)));43RTW_INFO("Offset12(0x%08x)\n", *((u32 *)(ptxdesc + 12)));44RTW_INFO("Offset16(0x%08x)\n", *((u32 *)(ptxdesc + 16)));45RTW_INFO("Offset20(0x%08x)\n", *((u32 *)(ptxdesc + 20)));46RTW_INFO("Offset24(0x%08x)\n", *((u32 *)(ptxdesc + 24)));47RTW_INFO("Offset28(0x%08x)\n", *((u32 *)(ptxdesc + 28)));48RTW_INFO("Offset32(0x%08x)\n", *((u32 *)(ptxdesc + 32)));49RTW_INFO("Offset36(0x%08x)\n", *((u32 *)(ptxdesc + 36)));50RTW_INFO("=====================================\n");51}5253}5455/*56* Description:57* Aggregation packets and send to hardware58*59* Return:60* 0 Success61* -1 Hardware resource(TX FIFO) not ready62* -2 Software resource(xmitbuf) not ready63*/64#ifdef CONFIG_TX_EARLY_MODE6566/* #define DBG_EMINFO */6768#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 169#define EARLY_MODE_MAX_PKT_NUM 1070#else71#define EARLY_MODE_MAX_PKT_NUM 572#endif737475struct EMInfo {76u8 EMPktNum;77u16 EMPktLen[EARLY_MODE_MAX_PKT_NUM];78};798081void82InsertEMContent_8814(83struct EMInfo *pEMInfo,84u8 *VirtualAddress)85{8687#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 188u8 index = 0;89u32 dwtmp = 0;90#endif9192_rtw_memset(VirtualAddress, 0, EARLY_MODE_INFO_SIZE);93if (pEMInfo->EMPktNum == 0)94return;9596#ifdef DBG_EMINFO97{98int i;99RTW_INFO("\n%s ==> pEMInfo->EMPktNum =%d\n", __FUNCTION__, pEMInfo->EMPktNum);100for (i = 0; i < EARLY_MODE_MAX_PKT_NUM; i++)101RTW_INFO("%s ==> pEMInfo->EMPktLen[%d] =%d\n", __FUNCTION__, i, pEMInfo->EMPktLen[i]);102103}104#endif105106#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1107SET_EARLYMODE_PKTNUM(VirtualAddress, pEMInfo->EMPktNum);108109if (pEMInfo->EMPktNum == 1)110dwtmp = pEMInfo->EMPktLen[0];111else {112dwtmp = pEMInfo->EMPktLen[0];113dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;114dwtmp += pEMInfo->EMPktLen[1];115}116SET_EARLYMODE_LEN0(VirtualAddress, dwtmp);117if (pEMInfo->EMPktNum <= 3)118dwtmp = pEMInfo->EMPktLen[2];119else {120dwtmp = pEMInfo->EMPktLen[2];121dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;122dwtmp += pEMInfo->EMPktLen[3];123}124SET_EARLYMODE_LEN1(VirtualAddress, dwtmp);125if (pEMInfo->EMPktNum <= 5)126dwtmp = pEMInfo->EMPktLen[4];127else {128dwtmp = pEMInfo->EMPktLen[4];129dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;130dwtmp += pEMInfo->EMPktLen[5];131}132SET_EARLYMODE_LEN2_1(VirtualAddress, dwtmp & 0xF);133SET_EARLYMODE_LEN2_2(VirtualAddress, dwtmp >> 4);134if (pEMInfo->EMPktNum <= 7)135dwtmp = pEMInfo->EMPktLen[6];136else {137dwtmp = pEMInfo->EMPktLen[6];138dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;139dwtmp += pEMInfo->EMPktLen[7];140}141SET_EARLYMODE_LEN3(VirtualAddress, dwtmp);142if (pEMInfo->EMPktNum <= 9)143dwtmp = pEMInfo->EMPktLen[8];144else {145dwtmp = pEMInfo->EMPktLen[8];146dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;147dwtmp += pEMInfo->EMPktLen[9];148}149SET_EARLYMODE_LEN4(VirtualAddress, dwtmp);150#else151SET_EARLYMODE_PKTNUM(VirtualAddress, pEMInfo->EMPktNum);152SET_EARLYMODE_LEN0(VirtualAddress, pEMInfo->EMPktLen[0]);153SET_EARLYMODE_LEN1(VirtualAddress, pEMInfo->EMPktLen[1]);154SET_EARLYMODE_LEN2_1(VirtualAddress, pEMInfo->EMPktLen[2] & 0xF);155SET_EARLYMODE_LEN2_2(VirtualAddress, pEMInfo->EMPktLen[2] >> 4);156SET_EARLYMODE_LEN3(VirtualAddress, pEMInfo->EMPktLen[3]);157SET_EARLYMODE_LEN4(VirtualAddress, pEMInfo->EMPktLen[4]);158#endif159160}161162163164void UpdateEarlyModeInfo8814(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)165{166/* _adapter *padapter, struct xmit_frame *pxmitframe,struct tx_servq *ptxservq */167int index, j;168u16 offset, pktlen;169PTXDESC_8814 ptxdesc;170171u8 *pmem, *pEMInfo_mem;172s8 node_num_0 = 0, node_num_1 = 0;173struct EMInfo eminfo;174struct agg_pkt_info *paggpkt;175struct xmit_frame *pframe = (struct xmit_frame *)pxmitbuf->priv_data;176pmem = pframe->buf_addr;177178#ifdef DBG_EMINFO179RTW_INFO("\n%s ==> agg_num:%d\n", __FUNCTION__, pframe->agg_num);180for (index = 0; index < pframe->agg_num; index++) {181offset = pxmitpriv->agg_pkt[index].offset;182pktlen = pxmitpriv->agg_pkt[index].pkt_len;183RTW_INFO("%s ==> agg_pkt[%d].offset=%d\n", __FUNCTION__, index, offset);184RTW_INFO("%s ==> agg_pkt[%d].pkt_len=%d\n", __FUNCTION__, index, pktlen);185}186#endif187188if (pframe->agg_num > EARLY_MODE_MAX_PKT_NUM) {189node_num_0 = pframe->agg_num;190node_num_1 = EARLY_MODE_MAX_PKT_NUM - 1;191}192193for (index = 0; index < pframe->agg_num; index++) {194195offset = pxmitpriv->agg_pkt[index].offset;196pktlen = pxmitpriv->agg_pkt[index].pkt_len;197198_rtw_memset(&eminfo, 0, sizeof(struct EMInfo));199if (pframe->agg_num > EARLY_MODE_MAX_PKT_NUM) {200if (node_num_0 > EARLY_MODE_MAX_PKT_NUM) {201eminfo.EMPktNum = EARLY_MODE_MAX_PKT_NUM;202node_num_0--;203} else {204eminfo.EMPktNum = node_num_1;205node_num_1--;206}207} else208eminfo.EMPktNum = pframe->agg_num - (index + 1);209for (j = 0; j < eminfo.EMPktNum ; j++) {210eminfo.EMPktLen[j] = pxmitpriv->agg_pkt[index + 1 + j].pkt_len + 4; /* 4 bytes CRC */211}212213if (pmem) {214if (index == 0) {215ptxdesc = (PTXDESC_8814)(pmem);216pEMInfo_mem = ((u8 *)ptxdesc) + TXDESC_SIZE;217} else {218pmem = pmem + pxmitpriv->agg_pkt[index - 1].offset;219ptxdesc = (PTXDESC_8814)(pmem);220pEMInfo_mem = ((u8 *)ptxdesc) + TXDESC_SIZE;221}222223#ifdef DBG_EMINFO224RTW_INFO("%s ==> desc.pkt_len=%d\n", __FUNCTION__, ptxdesc->pktlen);225#endif226InsertEMContent_8814(&eminfo, pEMInfo_mem);227}228229230}231_rtw_memset(pxmitpriv->agg_pkt, 0, sizeof(struct agg_pkt_info) * MAX_AGG_PKT_NUM);232233}234#endif235236#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)237void rtl8814a_cal_txdesc_chksum(u8 *ptxdesc)238{239u16 *usPtr;240u32 count;241u32 index;242u16 checksum = 0;243244245usPtr = (u16 *)ptxdesc;246/* checksume is always calculated by first 32 bytes, */247/* and it doesn't depend on TX DESC length. */248/* Thomas,Lucas@SD4,20130515 */249count = 16;250251/* Clear first */252SET_TX_DESC_TX_DESC_CHECKSUM_8814A(ptxdesc, 0);253254for (index = 0 ; index < count ; index++)255checksum = checksum ^ le16_to_cpu(*(usPtr + index));256257SET_TX_DESC_TX_DESC_CHECKSUM_8814A(ptxdesc, checksum);258}259#endif260261/*262* Description: In normal chip, we should send some packet to Hw which will be used by Fw263* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then264* Fw can tell Hw to send these packet derectly.265* */266void rtl8814a_fill_fake_txdesc(267PADAPTER padapter,268u8 *pDesc,269u32 BufferLen,270u8 IsPsPoll,271u8 IsBTQosNull,272u8 bDataFrame)273{274struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;275276277/* Clear all status */278_rtw_memset(pDesc, 0, TXDESC_SIZE);279280SET_TX_DESC_LAST_SEG_8814A(pDesc, 1);281282SET_TX_DESC_OFFSET_8814A(pDesc, TXDESC_SIZE);283284SET_TX_DESC_PKT_SIZE_8814A(pDesc, BufferLen);285286SET_TX_DESC_QUEUE_SEL_8814A(pDesc, QSLT_MGNT);287288if (pmlmeext->cur_wireless_mode & WIRELESS_11B)289SET_TX_DESC_RATE_ID_8814A(pDesc, RATEID_IDX_B);290else291SET_TX_DESC_RATE_ID_8814A(pDesc, RATEID_IDX_G);292293/* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. */294if (IsPsPoll)295SET_TX_DESC_NAV_USE_HDR_8814A(pDesc, 1);296else {297SET_TX_DESC_HWSEQ_EN_8814A(pDesc, 1); /* Hw set sequence number */298}299#if 0 /* todo */300if (IsBTQosNull)301SET_TX_DESC_BT_INT_8812(pDesc, 1);302#endif /* 0 */303304SET_TX_DESC_USE_RATE_8814A(pDesc, 1);305306/* 8814 no OWN bit? */307/* SET_TX_DESC_OWN_8812(pDesc, 1); */308309/* */310/* Encrypt the data frame if under security mode excepct null data. Suggested by CCW. */311/* */312if (_TRUE == bDataFrame) {313u32 EncAlg;314315EncAlg = padapter->securitypriv.dot11PrivacyAlgrthm;316switch (EncAlg) {317case _NO_PRIVACY_:318SET_TX_DESC_SEC_TYPE_8814A(pDesc, 0x0);319break;320case _WEP40_:321case _WEP104_:322case _TKIP_:323SET_TX_DESC_SEC_TYPE_8814A(pDesc, 0x1);324break;325case _SMS4_:326SET_TX_DESC_SEC_TYPE_8814A(pDesc, 0x2);327break;328case _AES_:329SET_TX_DESC_SEC_TYPE_8814A(pDesc, 0x3);330break;331default:332SET_TX_DESC_SEC_TYPE_8814A(pDesc, 0x0);333break;334}335}336SET_TX_DESC_TX_RATE_8814A(pDesc, MRateToHwRate(pmlmeext->tx_rate));337338#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)339/* USB interface drop packet if the checksum of descriptor isn't correct. */340/* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */341rtl8814a_cal_txdesc_chksum(pDesc);342#endif343}344345#if defined(CONFIG_CONCURRENT_MODE)346void fill_txdesc_force_bmc_camid(struct pkt_attrib *pattrib, u8 *ptxdesc)347{348if ((pattrib->encrypt > 0) && (!pattrib->bswenc)349&& (pattrib->bmc_camid != INVALID_SEC_MAC_CAM_ID)) {350351SET_TX_DESC_EN_DESC_ID_8814A(ptxdesc, 1);352SET_TX_DESC_MACID_8814A(ptxdesc, pattrib->bmc_camid);353}354}355#endif356void fill_txdesc_bmc_tx_rate(struct pkt_attrib *pattrib, u8 *ptxdesc)357{358SET_TX_DESC_USE_RATE_8814A(ptxdesc, 1);359SET_TX_DESC_TX_RATE_8814A(ptxdesc, MRateToHwRate(pattrib->rate));360SET_TX_DESC_DISABLE_FB_8814A(ptxdesc, 1);361}362363void rtl8814a_fill_txdesc_sectype(struct pkt_attrib *pattrib, u8 *ptxdesc)364{365if ((pattrib->encrypt > 0) && !pattrib->bswenc) {366switch (pattrib->encrypt) {367/* SEC_TYPE : 0:NO_ENC,1:WEP40/TKIP,2:WAPI,3:AES */368case _WEP40_:369case _WEP104_:370case _TKIP_:371case _TKIP_WTMIC_:372SET_TX_DESC_SEC_TYPE_8814A(ptxdesc, 0x1);373break;374#ifdef CONFIG_WAPI_SUPPORT375case _SMS4_:376SET_TX_DESC_SEC_TYPE_8814A(ptxdesc, 0x2);377break;378#endif379case _AES_:380SET_TX_DESC_SEC_TYPE_8814A(ptxdesc, 0x3);381break;382case _NO_PRIVACY_:383default:384SET_TX_DESC_SEC_TYPE_8814A(ptxdesc, 0x0);385break;386387}388389}390391}392393void rtl8814a_fill_txdesc_vcs(PADAPTER padapter, struct pkt_attrib *pattrib, u8 *ptxdesc)394{395struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;396struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);397398/* RTW_INFO("vcs_mode=%d\n", pattrib->vcs_mode); */399400if (pattrib->vcs_mode) {401402switch (pattrib->vcs_mode) {403case RTS_CTS:404SET_TX_DESC_RTS_ENABLE_8814A(ptxdesc, 1);405break;406case CTS_TO_SELF:407SET_TX_DESC_CTS2SELF_8814A(ptxdesc, 1);408break;409case NONE_VCS:410default:411break;412}413414if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)415SET_TX_DESC_RTS_SHORT_8814A(ptxdesc, 1);416417/* RTS Rate=24M */418SET_TX_DESC_RTS_RATE_8814A(ptxdesc, 0x8);419420/* compatibility for MCC consideration, use pmlmeext->cur_channel */421if (pmlmeext->cur_channel > 14)422/* RTS retry to rate OFDM 6M for 5G */423SET_TX_DESC_RTS_RATE_FB_LIMIT_8814A(ptxdesc, 4);424else425/* RTS retry to rate CCK 1M for 2.4G */426SET_TX_DESC_RTS_RATE_FB_LIMIT_8814A(ptxdesc, 0);427}428}429430431u8432BWMapping_8814(433PADAPTER Adapter,434struct pkt_attrib *pattrib435)436{437u8 BWSettingOfDesc = 0;438PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);439440/* RTW_INFO("BWMapping pHalData->current_channel_bw %d, pattrib->bwmode %d\n",pHalData->current_channel_bw,pattrib->bwmode); */441442if (pHalData->current_channel_bw == CHANNEL_WIDTH_80) {443if (pattrib->bwmode == CHANNEL_WIDTH_80)444BWSettingOfDesc = 2;445else if (pattrib->bwmode == CHANNEL_WIDTH_40)446BWSettingOfDesc = 1;447else448BWSettingOfDesc = 0;449} else if (pHalData->current_channel_bw == CHANNEL_WIDTH_40) {450if ((pattrib->bwmode == CHANNEL_WIDTH_40) || (pattrib->bwmode == CHANNEL_WIDTH_80))451BWSettingOfDesc = 1;452else453BWSettingOfDesc = 0;454} else455BWSettingOfDesc = 0;456457return BWSettingOfDesc;458}459460u8461SCMapping_8814(462PADAPTER Adapter,463struct pkt_attrib *pattrib464)465{466u8 SCSettingOfDesc = 0;467PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);468/* RTW_INFO("SCMapping: pHalData->current_channel_bw %d, pHalData->nCur80MhzPrimeSC %d, pHalData->nCur40MhzPrimeSC %d\n",pHalData->current_channel_bw,pHalData->nCur80MhzPrimeSC,pHalData->nCur40MhzPrimeSC); */469470if (pHalData->current_channel_bw == CHANNEL_WIDTH_80) {471if (pattrib->bwmode == CHANNEL_WIDTH_80)472SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;473else if (pattrib->bwmode == CHANNEL_WIDTH_40) {474if (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER)475SCSettingOfDesc = VHT_DATA_SC_40_LOWER_OF_80MHZ;476else if (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER)477SCSettingOfDesc = VHT_DATA_SC_40_UPPER_OF_80MHZ;478else479RTW_INFO("SCMapping: DONOT CARE Mode Setting\n");480} else {481if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER))482SCSettingOfDesc = VHT_DATA_SC_20_LOWEST_OF_80MHZ;483else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER))484SCSettingOfDesc = VHT_DATA_SC_20_LOWER_OF_80MHZ;485else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER))486SCSettingOfDesc = VHT_DATA_SC_20_UPPER_OF_80MHZ;487else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER))488SCSettingOfDesc = VHT_DATA_SC_20_UPPERST_OF_80MHZ;489else490RTW_INFO("SCMapping: DONOT CARE Mode Setting\n");491}492} else if (pHalData->current_channel_bw == CHANNEL_WIDTH_40) {493/* RTW_INFO("SCMapping: HT Case: pHalData->current_channel_bw %d, pHalData->nCur40MhzPrimeSC %d\n",pHalData->current_channel_bw,pHalData->nCur40MhzPrimeSC); */494495if (pattrib->bwmode == CHANNEL_WIDTH_40)496SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;497else if (pattrib->bwmode == CHANNEL_WIDTH_20) {498if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER)499SCSettingOfDesc = VHT_DATA_SC_20_UPPER_OF_80MHZ;500else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER)501SCSettingOfDesc = VHT_DATA_SC_20_LOWER_OF_80MHZ;502else503SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;504505}506} else507SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;508509return SCSettingOfDesc;510}511512513void rtl8814a_fill_txdesc_phy(PADAPTER padapter, struct pkt_attrib *pattrib, u8 *ptxdesc)514{515/* RTW_INFO("bwmode=%d, ch_off=%d\n", pattrib->bwmode, pattrib->ch_offset); */516517if (pattrib->ht_en) {518/* Set Bandwidth and sub-channel settings. */519SET_TX_DESC_DATA_BW_8814A(ptxdesc, BWMapping_8814(padapter, pattrib));520521SET_TX_DESC_DATA_SC_8814A(ptxdesc, SCMapping_8814(padapter, pattrib));522}523}524525526