root/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _is_fw_read_cmd_down
  2. FillH2CCmd_88E
  3. rtw_hal_add_ra_tid
  4. rtl8188e_set_FwPwrMode_cmd
  5. rtl8188e_set_FwMediaStatus_cmd
  6. ConstructBeacon
  7. ConstructPSPoll
  8. ConstructNullFunctionData
  9. ConstructProbeRsp
  10. SetFwRsvdPagePkt
  11. rtl8188e_set_FwJoinBssReport_cmd

   1 // SPDX-License-Identifier: GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   5  *
   6  ******************************************************************************/
   7 #define _RTL8188E_CMD_C_
   8 
   9 #include <osdep_service.h>
  10 #include <drv_types.h>
  11 #include <recv_osdep.h>
  12 #include <mlme_osdep.h>
  13 #include <rtw_ioctl_set.h>
  14 
  15 #include <rtl8188e_hal.h>
  16 
  17 #define RTL88E_MAX_H2C_BOX_NUMS         4
  18 #define RTL88E_MAX_CMD_LEN              7
  19 #define RTL88E_MESSAGE_BOX_SIZE         4
  20 #define RTL88E_EX_MESSAGE_BOX_SIZE      4
  21 
  22 static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num)
  23 {
  24         u8 read_down = false;
  25         int retry_cnts = 100;
  26 
  27         u8 valid;
  28 
  29         do {
  30                 valid = usb_read8(adapt, REG_HMETFR) & BIT(msgbox_num);
  31                 if (valid == 0)
  32                         read_down = true;
  33         } while ((!read_down) && (retry_cnts--));
  34 
  35         return read_down;
  36 }
  37 
  38 /*****************************************
  39 * H2C Msg format :
  40 * 0x1DF - 0x1D0
  41 *| 31 - 8       | 7-5    4 - 0  |
  42 *| h2c_msg      |Class_ID CMD_ID        |
  43 *
  44 * Extend 0x1FF - 0x1F0
  45 *|31 - 0          |
  46 *|ext_msg|
  47 ******************************************/
  48 static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
  49 {
  50         u8 bcmd_down = false;
  51         s32 retry_cnts = 100;
  52         u8 h2c_box_num;
  53         u32 msgbox_addr;
  54         u32 msgbox_ex_addr;
  55         u8 cmd_idx, ext_cmd_len;
  56         u32 h2c_cmd = 0;
  57         u32 h2c_cmd_ex = 0;
  58         s32 ret = _FAIL;
  59 
  60         if (!adapt->bFWReady) {
  61                 DBG_88E("%s(): return H2C cmd because fw is not ready\n",
  62                         __func__);
  63                 return ret;
  64         }
  65 
  66         if (!pCmdBuffer)
  67                 goto exit;
  68         if (CmdLen > RTL88E_MAX_CMD_LEN)
  69                 goto exit;
  70         if (adapt->bSurpriseRemoved)
  71                 goto exit;
  72 
  73         /* pay attention to if  race condition happened in  H2C cmd setting. */
  74         do {
  75                 h2c_box_num = adapt->HalData->LastHMEBoxNum;
  76 
  77                 if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) {
  78                         DBG_88E(" fw read cmd failed...\n");
  79                         goto exit;
  80                 }
  81 
  82                 *(u8 *)(&h2c_cmd) = ElementID;
  83 
  84                 if (CmdLen <= 3) {
  85                         memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
  86                 } else {
  87                         memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, 3);
  88                         ext_cmd_len = CmdLen-3;
  89                         memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer+3, ext_cmd_len);
  90 
  91                         /* Write Ext command */
  92                         msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * RTL88E_EX_MESSAGE_BOX_SIZE);
  93                         for (cmd_idx = 0; cmd_idx < ext_cmd_len; cmd_idx++)
  94                                 usb_write8(adapt, msgbox_ex_addr+cmd_idx, *((u8 *)(&h2c_cmd_ex)+cmd_idx));
  95                 }
  96                 /*  Write command */
  97                 msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * RTL88E_MESSAGE_BOX_SIZE);
  98                 for (cmd_idx = 0; cmd_idx < RTL88E_MESSAGE_BOX_SIZE; cmd_idx++)
  99                         usb_write8(adapt, msgbox_addr+cmd_idx, *((u8 *)(&h2c_cmd)+cmd_idx));
 100 
 101                 bcmd_down = true;
 102 
 103                 adapt->HalData->LastHMEBoxNum =
 104                         (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS;
 105 
 106         } while ((!bcmd_down) && (retry_cnts--));
 107 
 108         ret = _SUCCESS;
 109 
 110 exit:
 111         return ret;
 112 }
 113 
 114 /* bitmap[0:27] = tx_rate_bitmap */
 115 /* bitmap[28:31]= Rate Adaptive id */
 116 /* arg[0:4] = macid */
 117 /* arg[5] = Short GI */
 118 void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
 119 {
 120         struct odm_dm_struct *odmpriv = &pAdapter->HalData->odmpriv;
 121         u8 macid, init_rate, raid, shortGIrate = false;
 122 
 123         macid = arg&0x1f;
 124 
 125         raid = (bitmap>>28) & 0x0f;
 126         bitmap &= 0x0fffffff;
 127 
 128         if (rssi_level != DM_RATR_STA_INIT)
 129                 bitmap = ODM_Get_Rate_Bitmap(odmpriv, macid, bitmap, rssi_level);
 130 
 131         bitmap |= ((raid<<28)&0xf0000000);
 132 
 133         init_rate = get_highest_rate_idx(bitmap&0x0fffffff)&0x3f;
 134 
 135         shortGIrate = (arg & BIT(5)) ? true : false;
 136 
 137         if (shortGIrate)
 138                 init_rate |= BIT(6);
 139 
 140         raid = (bitmap>>28) & 0x0f;
 141 
 142         bitmap &= 0x0fffffff;
 143 
 144         DBG_88E("%s=> mac_id:%d, raid:%d, ra_bitmap=0x%x, shortGIrate=0x%02x\n",
 145                 __func__, macid, raid, bitmap, shortGIrate);
 146 
 147         ODM_RA_UpdateRateInfo_8188E(odmpriv, macid, raid, bitmap, shortGIrate);
 148 }
 149 
 150 void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode)
 151 {
 152         struct setpwrmode_parm H2CSetPwrMode;
 153         struct pwrctrl_priv *pwrpriv = &adapt->pwrctrlpriv;
 154         u8 RLBM = 0; /*  0:Min, 1:Max, 2:User define */
 155 
 156         DBG_88E("%s: Mode=%d SmartPS=%d UAPSD=%d\n", __func__,
 157                 Mode, pwrpriv->smart_ps, adapt->registrypriv.uapsd_enable);
 158 
 159         switch (Mode) {
 160         case PS_MODE_ACTIVE:
 161                 H2CSetPwrMode.Mode = 0;
 162                 break;
 163         case PS_MODE_MIN:
 164                 H2CSetPwrMode.Mode = 1;
 165                 break;
 166         case PS_MODE_MAX:
 167                 RLBM = 1;
 168                 H2CSetPwrMode.Mode = 1;
 169                 break;
 170         case PS_MODE_DTIM:
 171                 RLBM = 2;
 172                 H2CSetPwrMode.Mode = 1;
 173                 break;
 174         case PS_MODE_UAPSD_WMM:
 175                 H2CSetPwrMode.Mode = 2;
 176                 break;
 177         default:
 178                 H2CSetPwrMode.Mode = 0;
 179                 break;
 180         }
 181 
 182         H2CSetPwrMode.SmartPS_RLBM = (((pwrpriv->smart_ps<<4)&0xf0) | (RLBM & 0x0f));
 183 
 184         H2CSetPwrMode.AwakeInterval = 1;
 185 
 186         H2CSetPwrMode.bAllQueueUAPSD = adapt->registrypriv.uapsd_enable;
 187 
 188         if (Mode > 0)
 189                 H2CSetPwrMode.PwrState = 0x00;/*  AllON(0x0C), RFON(0x04), RFOFF(0x00) */
 190         else
 191                 H2CSetPwrMode.PwrState = 0x0C;/*  AllON(0x0C), RFON(0x04), RFOFF(0x00) */
 192 
 193         FillH2CCmd_88E(adapt, H2C_PS_PWR_MODE, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
 194 }
 195 
 196 void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt)
 197 {
 198         u8 opmode, macid;
 199         u16 mst_rpt = le16_to_cpu(mstatus_rpt);
 200 
 201         opmode = (u8)mst_rpt;
 202         macid = (u8)(mst_rpt >> 8);
 203 
 204         DBG_88E("### %s: MStatus=%x MACID=%d\n", __func__, opmode, macid);
 205         FillH2CCmd_88E(adapt, H2C_COM_MEDIA_STATUS_RPT, sizeof(mst_rpt), (u8 *)&mst_rpt);
 206 }
 207 
 208 static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength)
 209 {
 210         struct ieee80211_hdr *pwlanhdr;
 211         __le16 *fctrl;
 212         u32 rate_len, pktlen;
 213         struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
 214         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 215         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
 216         u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 217 
 218         pwlanhdr = (struct ieee80211_hdr *)pframe;
 219 
 220         fctrl = &pwlanhdr->frame_control;
 221         *(fctrl) = 0;
 222 
 223         ether_addr_copy(pwlanhdr->addr1, bc_addr);
 224         ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
 225         ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
 226 
 227         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
 228         SetFrameSubType(pframe, WIFI_BEACON);
 229 
 230         pframe += sizeof(struct ieee80211_hdr_3addr);
 231         pktlen = sizeof(struct ieee80211_hdr_3addr);
 232 
 233         /* timestamp will be inserted by hardware */
 234         pframe += 8;
 235         pktlen += 8;
 236 
 237         /*  beacon interval: 2 bytes */
 238         memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
 239 
 240         pframe += 2;
 241         pktlen += 2;
 242 
 243         /*  capability info: 2 bytes */
 244         memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
 245 
 246         pframe += 2;
 247         pktlen += 2;
 248 
 249         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
 250                 pktlen += cur_network->ie_length - sizeof(struct ndis_802_11_fixed_ie);
 251                 memcpy(pframe, cur_network->ies+sizeof(struct ndis_802_11_fixed_ie), pktlen);
 252 
 253                 goto _ConstructBeacon;
 254         }
 255 
 256         /* below for ad-hoc mode */
 257 
 258         /*  SSID */
 259         pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pktlen);
 260 
 261         /*  supported rates... */
 262         rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
 263         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(u32, rate_len, 8), cur_network->SupportedRates, &pktlen);
 264 
 265         /*  DS parameter set */
 266         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
 267 
 268         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
 269                 u32 ATIMWindow;
 270                 /*  IBSS Parameter Set... */
 271                 ATIMWindow = 0;
 272                 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
 273         }
 274 
 275         /* todo: ERP IE */
 276 
 277         /*  EXTERNDED SUPPORTED RATE */
 278         if (rate_len > 8)
 279                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
 280 
 281         /* todo:HT for adhoc */
 282 
 283 _ConstructBeacon:
 284 
 285         if ((pktlen + TXDESC_SIZE) > 512) {
 286                 DBG_88E("beacon frame too large\n");
 287                 return;
 288         }
 289 
 290         *pLength = pktlen;
 291 }
 292 
 293 static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength)
 294 {
 295         struct ieee80211_hdr *pwlanhdr;
 296         struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
 297         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 298         __le16 *fctrl;
 299         struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
 300 
 301         pwlanhdr = (struct ieee80211_hdr *)pframe;
 302 
 303         /*  Frame control. */
 304         fctrl = &pwlanhdr->frame_control;
 305         *(fctrl) = 0;
 306         SetPwrMgt(fctrl);
 307         SetFrameSubType(pframe, WIFI_PSPOLL);
 308 
 309         /*  AID. */
 310         SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
 311 
 312         /*  BSSID. */
 313         ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
 314 
 315         /*  TA. */
 316         ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
 317 
 318         *pLength = 16;
 319 }
 320 
 321 static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe,
 322         u32 *pLength,
 323         u8 *StaAddr,
 324         u8 bQoS,
 325         u8 AC,
 326         u8 bEosp,
 327         u8 bForcePowerSave)
 328 {
 329         struct ieee80211_hdr *pwlanhdr;
 330         __le16 *fctrl;
 331         u32 pktlen;
 332         struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
 333         struct wlan_network *cur_network = &pmlmepriv->cur_network;
 334         struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
 335         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 336         struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
 337 
 338         pwlanhdr = (struct ieee80211_hdr *)pframe;
 339 
 340         fctrl = &pwlanhdr->frame_control;
 341         *(fctrl) = 0;
 342         if (bForcePowerSave)
 343                 SetPwrMgt(fctrl);
 344 
 345         switch (cur_network->network.InfrastructureMode) {
 346         case Ndis802_11Infrastructure:
 347                 SetToDs(fctrl);
 348                 ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
 349                 ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
 350                 ether_addr_copy(pwlanhdr->addr3, StaAddr);
 351                 break;
 352         case Ndis802_11APMode:
 353                 SetFrDs(fctrl);
 354                 ether_addr_copy(pwlanhdr->addr1, StaAddr);
 355                 ether_addr_copy(pwlanhdr->addr2, pnetwork->MacAddress);
 356                 ether_addr_copy(pwlanhdr->addr3, myid(&adapt->eeprompriv));
 357                 break;
 358         case Ndis802_11IBSS:
 359         default:
 360                 ether_addr_copy(pwlanhdr->addr1, StaAddr);
 361                 ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
 362                 ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
 363                 break;
 364         }
 365 
 366         SetSeqNum(pwlanhdr, 0);
 367 
 368         if (bQoS) {
 369                 struct ieee80211_qos_hdr *pwlanqoshdr;
 370 
 371                 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
 372 
 373                 pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
 374                 SetPriority(&pwlanqoshdr->qos_ctrl, AC);
 375                 SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
 376 
 377                 pktlen = sizeof(struct ieee80211_qos_hdr);
 378         } else {
 379                 SetFrameSubType(pframe, WIFI_DATA_NULL);
 380 
 381                 pktlen = sizeof(struct ieee80211_hdr_3addr);
 382         }
 383 
 384         *pLength = pktlen;
 385 }
 386 
 387 static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
 388 {
 389         struct ieee80211_hdr *pwlanhdr;
 390         __le16 *fctrl;
 391         u8 *mac, *bssid;
 392         u32 pktlen;
 393         struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
 394         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 395         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
 396 
 397         pwlanhdr = (struct ieee80211_hdr *)pframe;
 398 
 399         mac = myid(&adapt->eeprompriv);
 400         bssid = cur_network->MacAddress;
 401 
 402         fctrl = &pwlanhdr->frame_control;
 403         *(fctrl) = 0;
 404         ether_addr_copy(pwlanhdr->addr1, StaAddr);
 405         ether_addr_copy(pwlanhdr->addr2, mac);
 406         ether_addr_copy(pwlanhdr->addr3, bssid);
 407 
 408         SetSeqNum(pwlanhdr, 0);
 409         SetFrameSubType(fctrl, WIFI_PROBERSP);
 410 
 411         pktlen = sizeof(struct ieee80211_hdr_3addr);
 412         pframe += pktlen;
 413 
 414         if (cur_network->ie_length > MAX_IE_SZ)
 415                 return;
 416 
 417         memcpy(pframe, cur_network->ies, cur_network->ie_length);
 418         pframe += cur_network->ie_length;
 419         pktlen += cur_network->ie_length;
 420 
 421         *pLength = pktlen;
 422 }
 423 
 424 /*  */
 425 /*  Description: Fill the reserved packets that FW will use to RSVD page. */
 426 /*                      Now we just send 4 types packet to rsvd page. */
 427 /*                      (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
 428 /*      Input: */
 429 /*          bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
 430 /*                                              so we need to set the packet length to total length. */
 431 /*                            true: At the second time, we should send the first packet (default:beacon) */
 432 /*                                              to Hw again and set the length in descriptor to the real beacon length. */
 433 /*  2009.10.15 by tynli. */
 434 static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
 435 {
 436         struct xmit_frame *pmgntframe;
 437         struct pkt_attrib *pattrib;
 438         struct xmit_priv *pxmitpriv;
 439         struct mlme_ext_priv *pmlmeext;
 440         struct mlme_ext_info *pmlmeinfo;
 441         u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength;
 442         u32 NullDataLength, QosNullLength;
 443         u8 *ReservedPagePacket;
 444         u8 PageNum, PageNeed, TxDescLen;
 445         u16 BufIndex;
 446         u32 TotalPacketLen;
 447         struct rsvdpage_loc RsvdPageLoc;
 448         struct wlan_bssid_ex *pnetwork;
 449 
 450         DBG_88E("%s\n", __func__);
 451         ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
 452         if (!ReservedPagePacket) {
 453                 DBG_88E("%s: alloc ReservedPagePacket fail!\n", __func__);
 454                 return;
 455         }
 456 
 457         pxmitpriv = &adapt->xmitpriv;
 458         pmlmeext = &adapt->mlmeextpriv;
 459         pmlmeinfo = &pmlmeext->mlmext_info;
 460         pnetwork = &pmlmeinfo->network;
 461 
 462         TxDescLen = TXDESC_SIZE;
 463         PageNum = 0;
 464 
 465         /* 3 (1) beacon * 2 pages */
 466         BufIndex = TXDESC_OFFSET;
 467         ConstructBeacon(adapt, &ReservedPagePacket[BufIndex], &BeaconLength);
 468 
 469         /*  When we count the first page size, we need to reserve description size for the RSVD */
 470         /*  packet, it will be filled in front of the packet in TXPKTBUF. */
 471         PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);
 472         /*  To reserved 2 pages for beacon buffer. 2010.06.24. */
 473         if (PageNeed == 1)
 474                 PageNeed += 1;
 475         PageNum += PageNeed;
 476         adapt->HalData->FwRsvdPageStartOffset = PageNum;
 477 
 478         BufIndex += PageNeed * 128;
 479 
 480         /* 3 (2) ps-poll *1 page */
 481         RsvdPageLoc.LocPsPoll = PageNum;
 482         ConstructPSPoll(adapt, &ReservedPagePacket[BufIndex], &PSPollLength);
 483         rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
 484 
 485         PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
 486         PageNum += PageNeed;
 487 
 488         BufIndex += PageNeed * 128;
 489 
 490         /* 3 (3) null data * 1 page */
 491         RsvdPageLoc.LocNullData = PageNum;
 492         ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], &NullDataLength, pnetwork->MacAddress, false, 0, 0, false);
 493         rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
 494 
 495         PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
 496         PageNum += PageNeed;
 497 
 498         BufIndex += PageNeed * 128;
 499 
 500         /* 3 (4) probe response * 1page */
 501         RsvdPageLoc.LocProbeRsp = PageNum;
 502         ConstructProbeRsp(adapt, &ReservedPagePacket[BufIndex], &ProbeRspLength, pnetwork->MacAddress, false);
 503         rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false);
 504 
 505         PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
 506         PageNum += PageNeed;
 507 
 508         BufIndex += PageNeed * 128;
 509 
 510         /* 3 (5) Qos null data */
 511         RsvdPageLoc.LocQosNull = PageNum;
 512         ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex],
 513                                   &QosNullLength, pnetwork->MacAddress, true, 0, 0, false);
 514         rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
 515 
 516         PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
 517         PageNum += PageNeed;
 518 
 519         TotalPacketLen = BufIndex + QosNullLength;
 520         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 521         if (!pmgntframe)
 522                 goto exit;
 523 
 524         /*  update attribute */
 525         pattrib = &pmgntframe->attrib;
 526         update_mgntframe_attrib(adapt, pattrib);
 527         pattrib->qsel = 0x10;
 528         pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
 529         pattrib->pktlen = pattrib->last_txcmdsz;
 530         memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
 531 
 532         rtw_hal_mgnt_xmit(adapt, pmgntframe);
 533 
 534         DBG_88E("%s: Set RSVD page location to Fw\n", __func__);
 535         FillH2CCmd_88E(adapt, H2C_COM_RSVD_PAGE, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
 536 
 537 exit:
 538         kfree(ReservedPagePacket);
 539 }
 540 
 541 void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 542 {
 543         struct hal_data_8188e *haldata = adapt->HalData;
 544         struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
 545         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 546         bool bSendBeacon = false;
 547         bool bcn_valid = false;
 548         u8 DLBcnCount = 0;
 549         u32 poll = 0;
 550 
 551         DBG_88E("%s mstatus(%x)\n", __func__, mstatus);
 552 
 553         if (mstatus == 1) {
 554                 /*  We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
 555                 /*  Suggested by filen. Added by tynli. */
 556                 usb_write16(adapt, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
 557                 /*  Do not set TSF again here or vWiFi beacon DMA INT will not work. */
 558 
 559                 /* Set REG_CR bit 8. DMA beacon by SW. */
 560                 haldata->RegCR_1 |= BIT(0);
 561                 usb_write8(adapt,  REG_CR+1, haldata->RegCR_1);
 562 
 563                 /*  Disable Hw protection for a time which revserd for Hw sending beacon. */
 564                 /*  Fix download reserved page packet fail that access collision with the protection time. */
 565                 /*  2010.05.11. Added by tynli. */
 566                 usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)&(~BIT(3)));
 567                 usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(4));
 568 
 569                 if (haldata->RegFwHwTxQCtrl & BIT(6)) {
 570                         DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
 571                         bSendBeacon = true;
 572                 }
 573 
 574                 /*  Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */
 575                 usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl&(~BIT(6))));
 576                 haldata->RegFwHwTxQCtrl &= (~BIT(6));
 577 
 578                 /*  Clear beacon valid check bit. */
 579                 rtw_hal_set_hwreg(adapt, HW_VAR_BCN_VALID, NULL);
 580                 DLBcnCount = 0;
 581                 poll = 0;
 582                 do {
 583                         /*  download rsvd page. */
 584                         SetFwRsvdPagePkt(adapt, false);
 585                         DLBcnCount++;
 586                         do {
 587                                 yield();
 588                                 /* mdelay(10); */
 589                                 /*  check rsvd page download OK. */
 590                                 rtw_hal_get_hwreg(adapt, HW_VAR_BCN_VALID, (u8 *)(&bcn_valid));
 591                                 poll++;
 592                         } while (!bcn_valid && (poll%10) != 0 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped);
 593                 } while (!bcn_valid && DLBcnCount <= 100 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped);
 594 
 595                 if (adapt->bSurpriseRemoved || adapt->bDriverStopped)
 596                         ;
 597                 else if (!bcn_valid)
 598                         DBG_88E("%s: 1 Download RSVD page failed! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll);
 599                 else
 600                         DBG_88E("%s: 1 Download RSVD success! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll);
 601                 /*  */
 602                 /*  We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower) */
 603                 /*  because we need to free the Tx BCN Desc which is used by the first reserved page packet. */
 604                 /*  At run time, we cannot get the Tx Desc until it is released in TxHandleInterrupt() so we will return */
 605                 /*  the beacon TCB in the following code. 2011.11.23. by tynli. */
 606                 /*  */
 607 
 608                 /*  Enable Bcn */
 609                 usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(3));
 610                 usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)&(~BIT(4)));
 611 
 612                 /*  To make sure that if there exists an adapter which would like to send beacon. */
 613                 /*  If exists, the origianl value of 0x422[6] will be 1, we should check this to */
 614                 /*  prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
 615                 /*  the beacon cannot be sent by HW. */
 616                 /*  2010.06.23. Added by tynli. */
 617                 if (bSendBeacon) {
 618                         usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl | BIT(6)));
 619                         haldata->RegFwHwTxQCtrl |= BIT(6);
 620                 }
 621 
 622                 /*  Update RSVD page location H2C to Fw. */
 623                 if (bcn_valid) {
 624                         rtw_hal_set_hwreg(adapt, HW_VAR_BCN_VALID, NULL);
 625                         DBG_88E("Set RSVD page location to Fw.\n");
 626                 }
 627 
 628                 /*  Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli. */
 629                 /*  Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
 630                 haldata->RegCR_1 &= (~BIT(0));
 631                 usb_write8(adapt,  REG_CR+1, haldata->RegCR_1);
 632         }
 633 }

/* [<][>][^][v][top][bottom][index][help] */