1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
20 #define _RTL8812A_XMIT_C_
22 /* #include <drv_types.h> */
23 #include <rtl8812a_hal.h>
25 void _dbg_dump_tx_info(_adapter *padapter, int frame_tag, u8 *ptxdesc)
28 u8 bDumpTxDesc = _FALSE;
29 rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(bDumpTxPkt));
31 if (bDumpTxPkt == 1) { /* dump txdesc for data frame */
32 RTW_INFO("dump tx_desc for data frame\n");
33 if ((frame_tag & 0x0f) == DATA_FRAMETAG)
35 } else if (bDumpTxPkt == 2) { /* dump txdesc for mgnt frame */
36 RTW_INFO("dump tx_desc for mgnt frame\n");
37 if ((frame_tag & 0x0f) == MGNT_FRAMETAG)
39 } else if (bDumpTxPkt == 3) { /* dump early info */
43 /* ptxdesc->txdw4 = cpu_to_le32(0x00001006); */ /* RTS Rate=24M */
44 /* ptxdesc->txdw6 = 0x6666f800; */
45 RTW_INFO("=====================================\n");
46 RTW_INFO("Offset00(0x%08x)\n", *((u32 *)(ptxdesc)));
47 RTW_INFO("Offset04(0x%08x)\n", *((u32 *)(ptxdesc + 4)));
48 RTW_INFO("Offset08(0x%08x)\n", *((u32 *)(ptxdesc + 8)));
49 RTW_INFO("Offset12(0x%08x)\n", *((u32 *)(ptxdesc + 12)));
50 RTW_INFO("Offset16(0x%08x)\n", *((u32 *)(ptxdesc + 16)));
51 RTW_INFO("Offset20(0x%08x)\n", *((u32 *)(ptxdesc + 20)));
52 RTW_INFO("Offset24(0x%08x)\n", *((u32 *)(ptxdesc + 24)));
53 RTW_INFO("Offset28(0x%08x)\n", *((u32 *)(ptxdesc + 28)));
54 RTW_INFO("Offset32(0x%08x)\n", *((u32 *)(ptxdesc + 32)));
55 RTW_INFO("Offset36(0x%08x)\n", *((u32 *)(ptxdesc + 36)));
56 RTW_INFO("=====================================\n");
63 * Aggregation packets and send to hardware
67 * -1 Hardware resource(TX FIFO) not ready
68 * -2 Software resource(xmitbuf) not ready
70 #ifdef CONFIG_TX_EARLY_MODE
72 /* #define DBG_EMINFO */
74 #if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1
75 #define EARLY_MODE_MAX_PKT_NUM 10
77 #define EARLY_MODE_MAX_PKT_NUM 5
83 u16 EMPktLen[EARLY_MODE_MAX_PKT_NUM];
89 struct EMInfo *pEMInfo,
90 IN pu1Byte VirtualAddress)
93 #if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1
98 _rtw_memset(VirtualAddress, 0, EARLY_MODE_INFO_SIZE);
99 if (pEMInfo->EMPktNum == 0)
105 RTW_INFO("\n%s ==> pEMInfo->EMPktNum =%d\n", __FUNCTION__, pEMInfo->EMPktNum);
106 for (i = 0; i < EARLY_MODE_MAX_PKT_NUM; i++)
107 RTW_INFO("%s ==> pEMInfo->EMPktLen[%d] =%d\n", __FUNCTION__, i, pEMInfo->EMPktLen[i]);
112 #if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1
113 SET_EARLYMODE_PKTNUM(VirtualAddress, pEMInfo->EMPktNum);
115 if (pEMInfo->EMPktNum == 1)
116 dwtmp = pEMInfo->EMPktLen[0];
118 dwtmp = pEMInfo->EMPktLen[0];
119 dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
120 dwtmp += pEMInfo->EMPktLen[1];
122 SET_EARLYMODE_LEN0(VirtualAddress, dwtmp);
123 if (pEMInfo->EMPktNum <= 3)
124 dwtmp = pEMInfo->EMPktLen[2];
126 dwtmp = pEMInfo->EMPktLen[2];
127 dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
128 dwtmp += pEMInfo->EMPktLen[3];
130 SET_EARLYMODE_LEN1(VirtualAddress, dwtmp);
131 if (pEMInfo->EMPktNum <= 5)
132 dwtmp = pEMInfo->EMPktLen[4];
134 dwtmp = pEMInfo->EMPktLen[4];
135 dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
136 dwtmp += pEMInfo->EMPktLen[5];
138 SET_EARLYMODE_LEN2_1(VirtualAddress, dwtmp & 0xF);
139 SET_EARLYMODE_LEN2_2(VirtualAddress, dwtmp >> 4);
140 if (pEMInfo->EMPktNum <= 7)
141 dwtmp = pEMInfo->EMPktLen[6];
143 dwtmp = pEMInfo->EMPktLen[6];
144 dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
145 dwtmp += pEMInfo->EMPktLen[7];
147 SET_EARLYMODE_LEN3(VirtualAddress, dwtmp);
148 if (pEMInfo->EMPktNum <= 9)
149 dwtmp = pEMInfo->EMPktLen[8];
151 dwtmp = pEMInfo->EMPktLen[8];
152 dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
153 dwtmp += pEMInfo->EMPktLen[9];
155 SET_EARLYMODE_LEN4(VirtualAddress, dwtmp);
157 SET_EARLYMODE_PKTNUM(VirtualAddress, pEMInfo->EMPktNum);
158 SET_EARLYMODE_LEN0(VirtualAddress, pEMInfo->EMPktLen[0]);
159 SET_EARLYMODE_LEN1(VirtualAddress, pEMInfo->EMPktLen[1]);
160 SET_EARLYMODE_LEN2_1(VirtualAddress, pEMInfo->EMPktLen[2] & 0xF);
161 SET_EARLYMODE_LEN2_2(VirtualAddress, pEMInfo->EMPktLen[2] >> 4);
162 SET_EARLYMODE_LEN3(VirtualAddress, pEMInfo->EMPktLen[3]);
163 SET_EARLYMODE_LEN4(VirtualAddress, pEMInfo->EMPktLen[4]);
170 void UpdateEarlyModeInfo8812(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
172 /* _adapter *padapter, struct xmit_frame *pxmitframe,struct tx_servq *ptxservq */
175 PTXDESC_8812 ptxdesc;
177 u8 *pmem, *pEMInfo_mem;
178 s8 node_num_0 = 0, node_num_1 = 0;
179 struct EMInfo eminfo;
180 struct agg_pkt_info *paggpkt;
181 struct xmit_frame *pframe = (struct xmit_frame *)pxmitbuf->priv_data;
182 pmem = pframe->buf_addr;
185 RTW_INFO("\n%s ==> agg_num:%d\n", __FUNCTION__, pframe->agg_num);
186 for (index = 0; index < pframe->agg_num; index++) {
187 offset = pxmitpriv->agg_pkt[index].offset;
188 pktlen = pxmitpriv->agg_pkt[index].pkt_len;
189 RTW_INFO("%s ==> agg_pkt[%d].offset=%d\n", __FUNCTION__, index, offset);
190 RTW_INFO("%s ==> agg_pkt[%d].pkt_len=%d\n", __FUNCTION__, index, pktlen);
194 if (pframe->agg_num > EARLY_MODE_MAX_PKT_NUM) {
195 node_num_0 = pframe->agg_num;
196 node_num_1 = EARLY_MODE_MAX_PKT_NUM - 1;
199 for (index = 0; index < pframe->agg_num; index++) {
201 offset = pxmitpriv->agg_pkt[index].offset;
202 pktlen = pxmitpriv->agg_pkt[index].pkt_len;
204 _rtw_memset(&eminfo, 0, sizeof(struct EMInfo));
205 if (pframe->agg_num > EARLY_MODE_MAX_PKT_NUM) {
206 if (node_num_0 > EARLY_MODE_MAX_PKT_NUM) {
207 eminfo.EMPktNum = EARLY_MODE_MAX_PKT_NUM;
210 eminfo.EMPktNum = node_num_1;
214 eminfo.EMPktNum = pframe->agg_num - (index + 1);
215 for (j = 0; j < eminfo.EMPktNum ; j++) {
216 eminfo.EMPktLen[j] = pxmitpriv->agg_pkt[index + 1 + j].pkt_len + 4; /* 4 bytes CRC */
221 ptxdesc = (PTXDESC_8812)(pmem);
222 pEMInfo_mem = ((u8 *)ptxdesc) + TXDESC_SIZE;
224 pmem = pmem + pxmitpriv->agg_pkt[index - 1].offset;
225 ptxdesc = (PTXDESC_8812)(pmem);
226 pEMInfo_mem = ((u8 *)ptxdesc) + TXDESC_SIZE;
230 RTW_INFO("%s ==> desc.pkt_len=%d\n", __FUNCTION__, ptxdesc->pktlen);
232 InsertEMContent_8812(&eminfo, pEMInfo_mem);
237 _rtw_memset(pxmitpriv->agg_pkt, 0, sizeof(struct agg_pkt_info) * MAX_AGG_PKT_NUM);
242 void rtl8812a_cal_txdesc_chksum(u8 *ptxdesc)
250 usPtr = (u16 *)ptxdesc;
251 /* checksume is always calculated by first 32 bytes, */
252 /* and it doesn't depend on TX DESC length. */
253 /* Thomas,Lucas@SD4,20130515 */
257 SET_TX_DESC_TX_DESC_CHECKSUM_8812(ptxdesc, 0);
259 for (index = 0 ; index < count ; index++)
260 checksum = checksum ^ le16_to_cpu(*(usPtr + index));
262 SET_TX_DESC_TX_DESC_CHECKSUM_8812(ptxdesc, checksum);
266 * Description: In normal chip, we should send some packet to Hw which will be used by Fw
267 * in FW LPS mode. The function is to fill the Tx descriptor of this packets, then
268 * Fw can tell Hw to send these packet derectly.
270 void rtl8812a_fill_fake_txdesc(
278 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
281 /* Clear all status */
282 _rtw_memset(pDesc, 0, TXDESC_SIZE);
284 SET_TX_DESC_FIRST_SEG_8812(pDesc, 1);
285 SET_TX_DESC_LAST_SEG_8812(pDesc, 1);
287 SET_TX_DESC_OFFSET_8812(pDesc, TXDESC_SIZE);
289 SET_TX_DESC_PKT_SIZE_8812(pDesc, BufferLen);
291 SET_TX_DESC_QUEUE_SEL_8812(pDesc, QSLT_MGNT);
293 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
294 SET_TX_DESC_RATE_ID_8812(pDesc, RATEID_IDX_B);
296 SET_TX_DESC_RATE_ID_8812(pDesc, RATEID_IDX_G);
298 /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. */
300 SET_TX_DESC_NAV_USE_HDR_8812(pDesc, 1);
302 SET_TX_DESC_HWSEQ_EN_8812(pDesc, 1); /* Hw set sequence number */
306 SET_TX_DESC_BT_INT_8812(pDesc, 1);
308 SET_TX_DESC_USE_RATE_8812(pDesc, 1);
309 SET_TX_DESC_OWN_8812(pDesc, 1);
312 /* Encrypt the data frame if under security mode excepct null data. Suggested by CCW. */
314 if (_TRUE == bDataFrame) {
317 EncAlg = padapter->securitypriv.dot11PrivacyAlgrthm;
320 SET_TX_DESC_SEC_TYPE_8812(pDesc, 0x0);
325 SET_TX_DESC_SEC_TYPE_8812(pDesc, 0x1);
328 SET_TX_DESC_SEC_TYPE_8812(pDesc, 0x2);
331 SET_TX_DESC_SEC_TYPE_8812(pDesc, 0x3);
334 SET_TX_DESC_SEC_TYPE_8812(pDesc, 0x0);
338 SET_TX_DESC_TX_RATE_8812(pDesc, MRateToHwRate(pmlmeext->tx_rate));
340 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
341 /* USB interface drop packet if the checksum of descriptor isn't correct. */
342 /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */
343 rtl8812a_cal_txdesc_chksum(pDesc);
347 #if defined(CONFIG_CONCURRENT_MODE)
348 void fill_txdesc_force_bmc_camid(struct pkt_attrib *pattrib, u8 *ptxdesc)
350 if ((pattrib->encrypt > 0) && (!pattrib->bswenc)
351 && (pattrib->bmc_camid != INVALID_SEC_MAC_CAM_ID)) {
353 SET_TX_DESC_EN_DESC_ID_8812(ptxdesc, 1);
354 SET_TX_DESC_MACID_8812(ptxdesc, pattrib->bmc_camid);
359 void rtl8812a_fill_txdesc_sectype(struct pkt_attrib *pattrib, u8 *ptxdesc)
361 if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
362 switch (pattrib->encrypt) {
363 /* SEC_TYPE : 0:NO_ENC,1:WEP40/TKIP,2:WAPI,3:AES */
368 SET_TX_DESC_SEC_TYPE_8812(ptxdesc, 0x1);
370 #ifdef CONFIG_WAPI_SUPPORT
372 SET_TX_DESC_SEC_TYPE_8812(ptxdesc, 0x2);
376 SET_TX_DESC_SEC_TYPE_8812(ptxdesc, 0x3);
380 SET_TX_DESC_SEC_TYPE_8812(ptxdesc, 0x0);
389 void rtl8812a_fill_txdesc_vcs(PADAPTER padapter, struct pkt_attrib *pattrib, u8 *ptxdesc)
391 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
392 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
394 /* RTW_INFO("vcs_mode=%d\n", pattrib->vcs_mode); */
396 if (pattrib->vcs_mode) {
398 switch (pattrib->vcs_mode) {
400 SET_TX_DESC_RTS_ENABLE_8812(ptxdesc, 1);
403 SET_TX_DESC_CTS2SELF_8812(ptxdesc, 1);
410 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
411 SET_TX_DESC_RTS_SHORT_8812(ptxdesc, 1);
413 SET_TX_DESC_RTS_RATE_8812(ptxdesc, 0x8);/* RTS Rate=24M */
415 SET_TX_DESC_RTS_RATE_FB_LIMIT_8812(ptxdesc, 0xf);
418 if (IS_HARDWARE_TYPE_8821(padapter))
419 SET_TX_DESC_HW_RTS_ENABLE_8812(ptxdesc, 1);
423 void rtl8812a_fill_txdesc_phy(PADAPTER padapter, struct pkt_attrib *pattrib, u8 *ptxdesc)
425 /* RTW_INFO("bwmode=%d, ch_off=%d\n", pattrib->bwmode, pattrib->ch_offset); */
427 if (pattrib->ht_en) {
428 /* Set Bandwidth and sub-channel settings. */
429 SET_TX_DESC_DATA_BW_8812(ptxdesc, BWMapping_8812(padapter, pattrib));
431 SET_TX_DESC_DATA_SC_8812(ptxdesc, SCMapping_8812(padapter, pattrib));
438 IN struct pkt_attrib *pattrib
441 u8 BWSettingOfDesc = 0;
442 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
444 /* RTW_INFO("BWMapping pHalData->current_channel_bw %d, pattrib->bwmode %d\n",pHalData->current_channel_bw,pattrib->bwmode); */
446 if (pHalData->current_channel_bw == CHANNEL_WIDTH_80) {
447 if (pattrib->bwmode == CHANNEL_WIDTH_80)
449 else if (pattrib->bwmode == CHANNEL_WIDTH_40)
453 } else if (pHalData->current_channel_bw == CHANNEL_WIDTH_40) {
454 if ((pattrib->bwmode == CHANNEL_WIDTH_40) || (pattrib->bwmode == CHANNEL_WIDTH_80))
461 return BWSettingOfDesc;
467 IN struct pkt_attrib *pattrib
470 u8 SCSettingOfDesc = 0;
471 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
472 /* RTW_INFO("SCMapping: pHalData->current_channel_bw %d, pHalData->nCur80MhzPrimeSC %d, pHalData->nCur40MhzPrimeSC %d\n",pHalData->current_channel_bw,pHalData->nCur80MhzPrimeSC,pHalData->nCur40MhzPrimeSC); */
474 if (pHalData->current_channel_bw == CHANNEL_WIDTH_80) {
475 if (pattrib->bwmode == CHANNEL_WIDTH_80)
476 SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;
477 else if (pattrib->bwmode == CHANNEL_WIDTH_40) {
478 if (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER)
479 SCSettingOfDesc = VHT_DATA_SC_40_LOWER_OF_80MHZ;
480 else if (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER)
481 SCSettingOfDesc = VHT_DATA_SC_40_UPPER_OF_80MHZ;
483 RTW_INFO("SCMapping: DONOT CARE Mode Setting\n");
485 if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER))
486 SCSettingOfDesc = VHT_DATA_SC_20_LOWEST_OF_80MHZ;
487 else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER))
488 SCSettingOfDesc = VHT_DATA_SC_20_LOWER_OF_80MHZ;
489 else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER))
490 SCSettingOfDesc = VHT_DATA_SC_20_UPPER_OF_80MHZ;
491 else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER))
492 SCSettingOfDesc = VHT_DATA_SC_20_UPPERST_OF_80MHZ;
494 RTW_INFO("SCMapping: DONOT CARE Mode Setting\n");
496 } else if (pHalData->current_channel_bw == CHANNEL_WIDTH_40) {
497 /* RTW_INFO("SCMapping: HT Case: pHalData->current_channel_bw %d, pHalData->nCur40MhzPrimeSC %d\n",pHalData->current_channel_bw,pHalData->nCur40MhzPrimeSC); */
499 if (pattrib->bwmode == CHANNEL_WIDTH_40)
500 SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;
501 else if (pattrib->bwmode == CHANNEL_WIDTH_20) {
502 if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER)
503 SCSettingOfDesc = VHT_DATA_SC_20_UPPER_OF_80MHZ;
504 else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER)
505 SCSettingOfDesc = VHT_DATA_SC_20_LOWER_OF_80MHZ;
507 SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;
511 SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;
513 return SCSettingOfDesc;