00001
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stddef.h>
00025 #include "txl_cntrl.h"
00026 #include "txl_frame.h"
00027 #include "ke_event.h"
00028 #include "mac_frame.h"
00029 #include "dbg.h"
00030 #include "txl_buffer.h"
00031 #include "co_utils.h"
00032 #include "reg_mac_core.h"
00033 #include "vif_mgmt.h"
00034 #include "phy.h"
00035 #include "tpc.h"
00036 #include "tdls.h"
00037
00038 #if NX_TX_FRAME
00039
00040
00041
00042
00043
00044
00045
00046
00048 static struct txl_frame_desc_tag txl_frame_desc[NX_TXFRAME_CNT];
00049
00051 struct txl_frame_env_tag txl_frame_env;
00052
00053
00054
00055
00056
00057 void txl_frame_init_desc(struct txl_frame_desc_tag *frame,
00058 struct txl_buffer_tag *buffer,
00059 struct tx_hw_desc *hwdesc,
00060 struct txl_buffer_control *bufctrl)
00061 {
00062 struct tx_hd *thd = &hwdesc->thd;
00063
00064
00065 memset(frame, 0, sizeof(*frame));
00066
00067
00068 #if NX_AMSDU_TX
00069 frame->txdesc.lmac.buffer[0] = buffer;
00070 #else
00071 frame->txdesc.lmac.buffer = buffer;
00072 #endif
00073 #if NX_UMAC_PRESENT
00074 frame->txdesc.umac.buf_control = bufctrl;
00075 #endif
00076 frame->txdesc.lmac.hw_desc = hwdesc;
00077 frame->type = TX_EXT;
00078
00079
00080 thd->upatterntx = TX_HEADER_DESC_PATTERN;
00081 thd->datastartptr = CPU2HW(txl_buffer_payload_get(&frame->txdesc));
00082 thd->frmlifetime = 0;
00083 thd->optlen[0] = 0;
00084 thd->optlen[1] = 0;
00085 thd->optlen[2] = 0;
00086 bufctrl->policy_tbl.upatterntx = POLICY_TABLE_PATTERN;
00087 }
00088
00089 void txl_frame_init(bool reset)
00090 {
00091 int i;
00092
00093 struct tx_policy_tbl *pol_tbl;
00094
00095
00096 co_list_init(&txl_frame_env.desc_free);
00097 co_list_init(&txl_frame_env.desc_done);
00098
00099
00100 for (i=0; i<NX_TXFRAME_CNT; i++)
00101 {
00102 struct txl_frame_desc_tag *frame = &txl_frame_desc[i];
00103 struct txl_buffer_tag *buffer = (struct txl_buffer_tag *)&txl_frame_pool[i];
00104 struct tx_hw_desc *hwdesc = &txl_frame_hwdesc_pool[i];
00105 struct tx_hd *thd = &hwdesc->thd;
00106 #if NX_UMAC_PRESENT
00107 struct txl_buffer_control *bufctrl = &txl_frame_buf_ctrl[i];
00108 #else
00109 struct txl_buffer_control *bufctrl = &buffer->buffer_control;
00110 #endif
00111
00112
00113 if (!reset || !frame->postponed)
00114 {
00115
00116 memset(frame, 0, sizeof(struct txl_frame_desc_tag));
00117
00118
00119 #if NX_AMSDU_TX
00120 frame->txdesc.lmac.buffer[0] = buffer;
00121 #else
00122 frame->txdesc.lmac.buffer = buffer;
00123 #endif
00124 #if NX_UMAC_PRESENT
00125 frame->txdesc.umac.buf_control = bufctrl;
00126 #endif
00127 frame->txdesc.lmac.hw_desc = hwdesc;
00128 frame->type = TX_INT;
00129
00130
00131 thd->upatterntx = TX_HEADER_DESC_PATTERN;
00132 thd->datastartptr = CPU2HW(txl_buffer_payload_get(&frame->txdesc));
00133 thd->frmlifetime = 0;
00134 thd->optlen[0] = 0;
00135 thd->optlen[1] = 0;
00136 thd->optlen[2] = 0;
00137 bufctrl->policy_tbl.upatterntx = POLICY_TABLE_PATTERN;
00138
00139
00140 co_list_push_back(&txl_frame_env.desc_free, &frame->txdesc.list_hdr);
00141 }
00142 }
00143
00144
00145 #if (NX_UMAC_PRESENT)
00146 pol_tbl = &txl_buffer_control_24G.policy_tbl;
00147
00148 txl_buffer_control_24G.mac_control_info = 0;
00149 txl_buffer_control_24G.phy_control_info = 0;
00150 #else
00151 pol_tbl = &txl_frame_pol_24G;
00152 #endif //(NX_UMAC_PRESENT)
00153
00154 pol_tbl->upatterntx = POLICY_TABLE_PATTERN;
00155 pol_tbl->phycntrlinfo1 = phy_get_ntx() << NX_TX_PT_OFT;
00156 pol_tbl->phycntrlinfo2 = TX_NTX_2_ANTENNA_SET(phy_get_ntx());
00157 pol_tbl->maccntrlinfo1 = 0;
00158 pol_tbl->maccntrlinfo2 = 0xFFFF0704;
00159 pol_tbl->ratecntrlinfo[0] = (HW_RATE_1MBPS << MCS_INDEX_TX_RCX_OFT) | PRE_TYPE_TX_RCX_MASK;
00160 pol_tbl->ratecntrlinfo[1] = 0;
00161 pol_tbl->ratecntrlinfo[2] = 0;
00162 pol_tbl->ratecntrlinfo[3] = 0;
00163 pol_tbl->powercntrlinfo[1] = 0;
00164 pol_tbl->powercntrlinfo[2] = 0;
00165 pol_tbl->powercntrlinfo[3] = 0;
00166
00167
00168 #if (NX_UMAC_PRESENT)
00169 pol_tbl = &txl_buffer_control_5G.policy_tbl;
00170
00171 txl_buffer_control_5G.mac_control_info = 0;
00172 txl_buffer_control_5G.phy_control_info = 0;
00173 #else
00174 pol_tbl = &txl_frame_pol_5G;
00175 #endif //(NX_UMAC_PRESENT)
00176
00177 pol_tbl->upatterntx = POLICY_TABLE_PATTERN;
00178 pol_tbl->phycntrlinfo1 = phy_get_ntx() << NX_TX_PT_OFT;
00179 pol_tbl->phycntrlinfo2 = TX_NTX_2_ANTENNA_SET(phy_get_ntx());
00180 pol_tbl->maccntrlinfo1 = 0;
00181 pol_tbl->maccntrlinfo2 = 0xFFFF0704;
00182 pol_tbl->ratecntrlinfo[0] = HW_RATE_6MBPS << MCS_INDEX_TX_RCX_OFT;
00183 pol_tbl->ratecntrlinfo[1] = 0;
00184 pol_tbl->ratecntrlinfo[2] = 0;
00185 pol_tbl->ratecntrlinfo[3] = 0;
00186 pol_tbl->powercntrlinfo[1] = 0;
00187 pol_tbl->powercntrlinfo[2] = 0;
00188 pol_tbl->powercntrlinfo[3] = 0;
00189
00190 #if (RW_BFMER_EN)
00191 #if (NX_UMAC_PRESENT)
00192 pol_tbl = &txl_buffer_control_ndpa_brp.policy_tbl;
00193
00194 txl_buffer_control_ndpa_brp.mac_control_info = 0;
00195 txl_buffer_control_ndpa_brp.phy_control_info = 0;
00196 #else
00197 pol_tbl = &txl_frame_pol_ndpa_brp;
00198 #endif //(NX_UMAC_PRESENT)
00199
00200 pol_tbl->upatterntx = POLICY_TABLE_PATTERN;
00201 pol_tbl->phycntrlinfo1 = phy_get_ntx() << NX_TX_PT_OFT;
00202 pol_tbl->phycntrlinfo2 = TX_NTX_2_ANTENNA_SET(phy_get_ntx());
00203 pol_tbl->maccntrlinfo1 = 0;
00204 pol_tbl->maccntrlinfo2 = 0xFFFF0000;
00205 pol_tbl->ratecntrlinfo[0] = BW_80MHZ << BW_TX_RCX_OFT;
00206 pol_tbl->ratecntrlinfo[0] |= FORMATMOD_VHT << FORMAT_MOD_TX_RCX_OFT;
00207 pol_tbl->ratecntrlinfo[0] |= (0x0 << 4) << MCS_INDEX_TX_RCX_OFT;
00208 pol_tbl->ratecntrlinfo[1] = 0;
00209 pol_tbl->ratecntrlinfo[2] = 0;
00210 pol_tbl->ratecntrlinfo[3] = 0;
00211 pol_tbl->powercntrlinfo[1] = 0;
00212 pol_tbl->powercntrlinfo[2] = 0;
00213 pol_tbl->powercntrlinfo[3] = 0;
00214
00215 #if (NX_UMAC_PRESENT)
00216 pol_tbl = &txl_buffer_control_ndp.policy_tbl;
00217
00218 txl_buffer_control_ndp.mac_control_info = 0;
00219 txl_buffer_control_ndp.phy_control_info = 0;
00220 #else
00221 pol_tbl = &txl_frame_pol_ndp;
00222 #endif //(NX_UMAC_PRESENT)
00223
00224 pol_tbl->upatterntx = POLICY_TABLE_PATTERN;
00225 pol_tbl->phycntrlinfo1 = phy_get_ntx() << NX_TX_PT_OFT;
00226 pol_tbl->phycntrlinfo2 = TX_NTX_2_ANTENNA_SET(phy_get_ntx());
00227 pol_tbl->maccntrlinfo1 = 0;
00228 pol_tbl->maccntrlinfo2 = 0xFFFF0000;
00229 pol_tbl->ratecntrlinfo[0] = 0;
00230 pol_tbl->ratecntrlinfo[0] |= FORMATMOD_VHT << FORMAT_MOD_TX_RCX_OFT;
00231 pol_tbl->ratecntrlinfo[0] |= (phy_get_nss() << 4) << MCS_INDEX_TX_RCX_OFT;
00232 pol_tbl->ratecntrlinfo[1] = 0;
00233 pol_tbl->ratecntrlinfo[2] = 0;
00234 pol_tbl->ratecntrlinfo[3] = 0;
00235 pol_tbl->powercntrlinfo[1] = 0;
00236 pol_tbl->powercntrlinfo[2] = 0;
00237 pol_tbl->powercntrlinfo[3] = 0;
00238 #endif //(RW_BFMER_EN)
00239 }
00240
00241 struct txl_frame_desc_tag *txl_frame_get(int type, int len)
00242 {
00243
00244 struct txl_frame_desc_tag *frame;
00245
00246
00247 frame = (struct txl_frame_desc_tag *)co_list_pop_front(&txl_frame_env.desc_free);
00248
00249
00250 if (frame != NULL)
00251 {
00252 txl_frame_prepare(frame, type, len);
00253 }
00254
00255 return frame;
00256 }
00257
00258 void txl_frame_prepare(struct txl_frame_desc_tag *frame, int type, int len)
00259 {
00260 struct txl_buffer_control *bufctrl = txl_buffer_control_get(&frame->txdesc);
00261 struct tx_hd *thd = &frame->txdesc.lmac.hw_desc->thd;
00262 struct tx_policy_tbl *pol;
00263
00264
00265 #if (RW_BFMER_EN)
00266 thd->frmlen = len;
00267
00268 if (len == 0)
00269 {
00270 thd->datastartptr = 0;
00271 thd->dataendptr = 0;
00272 }
00273 else
00274 {
00275
00276 struct txl_buffer_tag *buffer = txl_buffer_get(&frame->txdesc);
00277
00278 thd->frmlen += MAC_FCS_LEN;
00279 thd->datastartptr = CPU2HW(buffer->payload);
00280 thd->dataendptr = (uint32_t)thd->datastartptr + len - 1;
00281 }
00282 #else
00283 thd->dataendptr = (uint32_t)thd->datastartptr + len - 1;
00284 thd->frmlen = len + MAC_FCS_LEN;
00285 #endif
00286
00287 switch (type)
00288 {
00289 case TX_DEFAULT_24G:
00290 #if (NX_UMAC_PRESENT)
00291 pol = &txl_buffer_control_24G.policy_tbl;
00292 #else
00293 pol = &txl_frame_pol_24G;
00294 #endif //(NX_UMAC_PRESENT)
00295 break;
00296 case TX_DEFAULT_5G:
00297 #if (NX_UMAC_PRESENT)
00298 pol = &txl_buffer_control_5G.policy_tbl;
00299 #else
00300 pol = &txl_frame_pol_5G;
00301 #endif //(NX_UMAC_PRESENT)
00302 break;
00303 #if (RW_BFMER_EN)
00304 case TX_DEFAULT_NDPA_BRP:
00305 #if (NX_UMAC_PRESENT)
00306 pol = &txl_buffer_control_ndpa_brp.policy_tbl;
00307 #else
00308 pol = &txl_frame_pol_ndpa_brp;
00309 #endif //(NX_UMAC_PRESENT)
00310 break;
00311 case TX_DEFAULT_NDP:
00312 #if (NX_UMAC_PRESENT)
00313 pol = &txl_buffer_control_ndp.policy_tbl;
00314 #else
00315 pol = &txl_frame_pol_ndp;
00316 #endif //(NX_UMAC_PRESENT)
00317 break;
00318 #endif //(RW_BFMER_EN)
00319 default:
00320 pol = &bufctrl->policy_tbl;
00321 break;
00322 }
00323
00324
00325
00326 memcpy(&bufctrl->policy_tbl, pol, sizeof(struct tx_policy_tbl));
00327 pol = &bufctrl->policy_tbl;
00328
00329
00330 pol->powercntrlinfo[0] = TX_PWR_LEVEL_SET(nxmac_ofdm_max_pwr_level_getf());
00331 thd->policyentryaddr = CPU2HW(pol);
00332 thd->phyctrlinfo = 0;
00333 thd->macctrlinfo2 = 0;
00334 thd->first_pbd_ptr = 0;
00335
00336
00337 frame->cfm.cfm_func = NULL;
00338 frame->cfm.env = NULL;
00339 }
00340
00341 bool txl_frame_push(struct txl_frame_desc_tag *frame, uint8_t ac)
00342 {
00343 struct tx_hd *thd = &frame->txdesc.lmac.hw_desc->thd;
00344 struct mac_hdr *hdr;
00345
00346
00347 ASSERT_ERR(frame != NULL);
00348 ASSERT_ERR((thd->datastartptr & 0x01) == 0);
00349
00350
00351 hdr = HW2CPU(thd->datastartptr);
00352 thd->nextfrmexseq_ptr = 0;
00353 thd->nextmpdudesc_ptr = 0;
00354 thd->macctrlinfo2 &= ~(WHICHDESC_MSK | UNDER_BA_SETUP_BIT);
00355 if (MAC_ADDR_GROUP(&hdr->addr1))
00356 thd->macctrlinfo1 = EXPECTED_ACK_NO_ACK;
00357 else
00358 thd->macctrlinfo1 = EXPECTED_ACK_NORMAL_ACK;
00359
00360 thd->statinfo = 0;
00361
00362
00363 return (txl_cntrl_push_int((struct txdesc *)frame, ac));
00364 }
00365
00366 void txl_frame_cfm(struct txdesc *txdesc)
00367 {
00368
00369 co_list_push_back(&txl_frame_env.desc_done, &txdesc->list_hdr);
00370
00371
00372 ke_evt_set(KE_EVT_TXFRAME_CFM_BIT);
00373 }
00374
00375 void txl_frame_release(struct txdesc *txdesc, bool postponed)
00376 {
00377 struct txl_frame_desc_tag *frame = (struct txl_frame_desc_tag *)txdesc;
00378
00379
00380 if (frame->type == TX_INT)
00381 {
00382
00383 co_list_push_back(&txl_frame_env.desc_free, &txdesc->list_hdr);
00384 }
00385
00386
00387 if (postponed)
00388 {
00389
00390 if (frame->cfm.cfm_func != NULL)
00391 {
00392
00393 frame->cfm.cfm_func(frame->cfm.env, 0);
00394 }
00395 }
00396 }
00397
00398 void txl_frame_evt(int dummy)
00399 {
00400 struct txl_frame_desc_tag *frame;
00401
00402
00403 ke_evt_clear(KE_EVT_TXFRAME_CFM_BIT);
00404
00405
00406 while (1)
00407 {
00408
00409 GLOBAL_INT_DISABLE();
00410 frame = (struct txl_frame_desc_tag *)co_list_pop_front(&txl_frame_env.desc_done);
00411 GLOBAL_INT_RESTORE();
00412
00413
00414 if (frame == NULL)
00415 break;
00416
00417
00418 PROF_TX_FRAME_CFM_SET();
00419
00420 #if NX_POWERSAVE
00421
00422 txl_cntrl_env.pck_cnt--;
00423 #endif
00424
00425
00426 if (frame->cfm.cfm_func != NULL)
00427 {
00428 frame->cfm.cfm_func(frame->cfm.env, frame->txdesc.lmac.hw_desc->thd.statinfo);
00429
00430 #if (NX_UMAC_PRESENT)
00431
00432
00433
00434
00435 if (frame->keep_desc)
00436 {
00437
00438 frame->keep_desc = false;
00439
00440 continue;
00441 }
00442 #endif //(NX_UMAC_PRESENT)
00443 }
00444
00445
00446 PROF_TX_FRAME_CFM_CLR();
00447
00448
00449 if (frame->type == TX_INT)
00450 {
00451
00452 co_list_push_back(&txl_frame_env.desc_free, &frame->txdesc.list_hdr);
00453 }
00454 }
00455 }
00456
00457 uint8_t txl_frame_send_null_frame(uint8_t sta_idx, cfm_func_ptr cfm, void *env)
00458 {
00459 struct txl_frame_desc_tag *frame;
00460 struct mac_hdr *buf;
00461 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
00462 struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
00463 int txtype;
00464
00465
00466 txtype = vif_mgmt_get_txtype(vif);
00467 frame = txl_frame_get(txtype, MAC_NULL_FRAME_SIZE);
00468 if (frame == NULL)
00469 return CO_FAIL;
00470
00471
00472 tpc_update_frame_tx_power(vif, frame);
00473
00474
00475 buf = txl_buffer_payload_get(&frame->txdesc);
00476
00477
00478 buf->fctl = MAC_FCTRL_NULL_FUNCTION | MAC_FCTRL_TODS;
00479 buf->durid = 0;
00480 buf->addr1 = sta->mac_addr;
00481 buf->addr2 = vif->mac_addr;
00482 buf->addr3 = sta->mac_addr;
00483 buf->seq = txl_get_seq_ctrl();
00484
00485
00486 frame->cfm.cfm_func = cfm;
00487 frame->cfm.env = env;
00488
00489 #if (NX_CHNL_CTXT || NX_P2P)
00490
00491 frame->txdesc.host.vif_idx = sta->inst_nbr;
00492 frame->txdesc.host.staid = sta_idx;
00493 #endif //(NX_CHNL_CTXT || NX_P2P)
00494
00495
00496 txl_frame_push(frame, AC_VO);
00497
00498 return CO_OK;
00499 }
00500
00501
00502 uint8_t txl_frame_send_qosnull_frame(uint8_t sta_idx, uint16_t qos, cfm_func_ptr cfm, void *env)
00503 {
00504 struct txl_frame_desc_tag *frame;
00505 struct mac_hdr_qos *buf;
00506 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
00507 struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
00508 int txtype;
00509
00510
00511 txtype = vif_mgmt_get_txtype(vif);
00512 frame = txl_frame_get(txtype, MAC_QOS_NULL_FRAME_SIZE);
00513 if (frame == NULL)
00514 return CO_FAIL;
00515
00516
00517 tpc_update_frame_tx_power(vif, frame);
00518
00519
00520 buf = txl_buffer_payload_get(&frame->txdesc);
00521
00522
00523 buf->fctl = MAC_FCTRL_QOS_NULL;
00524 buf->durid = 0;
00525 buf->addr1 = sta->mac_addr;
00526 buf->addr2 = vif->mac_addr;
00527 if (vif->type == VIF_STA)
00528 {
00529 #if NX_TDLS
00530 if (sta->is_tdls)
00531 {
00532 buf->addr3 = vif->bssid;
00533 }
00534 else
00535 #endif
00536 {
00537 buf->fctl |= MAC_FCTRL_TODS;
00538 buf->addr3 = sta->mac_addr;
00539 }
00540 }
00541 else
00542 {
00543 buf->fctl |= MAC_FCTRL_FROMDS;
00544 buf->addr3 = vif->mac_addr;
00545 }
00546 buf->seq = 0;
00547 buf->qos = qos;
00548
00549
00550 frame->cfm.cfm_func = cfm;
00551 frame->cfm.env = env;
00552
00553 #if (NX_CHNL_CTXT || NX_P2P)
00554
00555 frame->txdesc.host.vif_idx = sta->inst_nbr;
00556 frame->txdesc.host.staid = sta_idx;
00557 #endif //(NX_CHNL_CTXT || NX_P2P)
00558
00559
00560 txl_frame_push(frame, AC_VO);
00561
00562 return CO_OK;
00563 }
00564
00565 #if NX_TDLS && NX_UMAC_PRESENT
00566
00575 static void txl_frame_tdls_add_security_header(struct txl_frame_desc_tag *frame,
00576 struct mac_hdr_qos *buf,
00577 struct key_info_tag *key)
00578 {
00579 struct txl_buffer_control *bufctrl = txl_buffer_control_get(&frame->txdesc);
00580 struct tx_policy_tbl *pol = &bufctrl->policy_tbl;
00581 uint32_t mac_control_info1 = pol->maccntrlinfo1 & KEYSRAM_INDEX_RA_MASK;
00582 uint16_t *iv = (&buf->qos) + 1;
00583
00584 key->tx_pn++;
00585 iv[0] = (uint16_t)(key->tx_pn & 0xFFFF);
00586 iv[1] = EIV_PRESENT | (key->key_idx << 14);
00587 iv[2] = (uint16_t)((key->tx_pn >> 16) & 0xFFFF);
00588 iv[3] = (uint16_t)((key->tx_pn >> 32) & 0xFFFF);;
00589 buf->fctl |= MAC_FCTRL_PROTECTEDFRAME;
00590
00591 pol->maccntrlinfo1 = mac_control_info1 | key->hw_key_idx;
00592 }
00593
00594
00595 uint8_t txl_frame_send_tdls_channel_switch_req_frame(struct tdls_chan_switch_req const *param,
00596 cfm_func_ptr cfm)
00597 {
00598 struct txl_frame_desc_tag *frame;
00599 struct mac_hdr_qos *buf;
00600 struct vif_info_tag *vif = &vif_info_tab[param->vif_index];
00601 struct sta_info_tag *sta = &sta_info_tab[param->sta_idx];
00602 struct key_info_tag *key = *sta->sta_sec_info.cur_key;
00603 uint8_t tid = TID_5;
00604 int txtype;
00605 int head_len = 0;
00606 int tail_len = 0;
00607 uint32_t payload;
00608 uint8_t i;
00609 uint16_t ch_switch_time = TDLS_CHSW_SWITCH_TIME_US;
00610 uint16_t ch_switch_timeout = tdls_get_dt_us(vif->tbtt_timer.time, hal_machw_time()) -
00611 2*ch_switch_time -
00612 3*TDLS_CHSW_TX_FRAME_TIME_US;
00613
00614 if (ch_switch_timeout > TDLS_MAX_CHSW_SWITCH_TIME_US)
00615 {
00616 ch_switch_timeout = TDLS_MAX_CHSW_SWITCH_TIME_US;
00617 }
00618
00619 PROF_TDLS_CHSW_REQ_TX_SET();
00620
00621
00622 if (key)
00623 {
00624 ASSERT_ERR(key->cipher == MAC_CIPHER_CCMP);
00625 head_len = IV_LEN + EIV_LEN;
00626 tail_len = MIC_LEN;
00627 }
00628
00629
00630 txtype = vif_mgmt_get_txtype(vif);
00631 frame = txl_frame_get(txtype, MAC_SHORT_QOS_MAC_HDR_LEN + head_len +
00632 MAC_ENCAPSULATED_PAYLOAD_OFT + 38);
00633 if (frame == NULL)
00634 {
00635 PROF_TDLS_CHSW_REQ_TX_CLR();
00636 return CO_FAIL;
00637 }
00638
00639
00640 tpc_update_frame_tx_power(vif, frame);
00641
00642
00643 buf = txl_buffer_payload_get(&frame->txdesc);
00644
00645
00646 buf->fctl = MAC_FCTRL_QOS_DATA;
00647 buf->durid = 0;
00648 MAC_ADDR_CPY(&buf->addr1, ¶m->peer_mac_addr);
00649 MAC_ADDR_CPY(&buf->addr2, &vif->mac_addr);
00650 MAC_ADDR_CPY(&buf->addr3, &vif->bssid);
00651 buf->seq = sta_mgmt_get_tx_ssn_and_inc(param->sta_idx, tid) << MAC_SEQCTRL_NUM_OFT;
00652 buf->qos = tid << MAC_QOSCTRL_UP_OFT;
00653
00654
00655 if (key)
00656 {
00657 txl_frame_tdls_add_security_header(frame, buf, key);
00658 }
00659
00660 payload = CPU2HW(buf) + MAC_SHORT_QOS_MAC_HDR_LEN + head_len;
00661
00662
00663 co_write32p(payload, FRAME_BODY_LLC_H);
00664 co_write32p(payload + MAC_ENCAPSULATED_LLC_L_OFT, FRAME_BODY_LLC_L);
00665 co_write8p(payload + MAC_ENCAPSULATED_PAYLOAD_TYPE_OFT, PAYLOAD_TYPE_TDLS);
00666
00667
00668 payload += MAC_ENCAPSULATED_PAYLOAD_OFT;
00669
00670 co_write8p(payload, MAC_TDLS_ACTION_CATEGORY);
00671
00672 co_write8p(payload + MAC_ACTION_ACTION_OFT, MAC_TDLS_ACTION_CHANSW_REQ);
00673
00674 co_write8p(payload + TDLS_CHANSW_REQ_TARGET_CH_OFFSET,
00675 (uint8_t)phy_freq_to_channel(param->chan.band, param->chan.prim20_freq));
00676
00677 co_write8p(payload + TDLS_CHANSW_REQ_OP_CLASS, param->op_class);
00678
00679 payload += TDLS_CHANSW_REQ_IES_OFFSET;
00680
00681 if (param->chan.type == PHY_CHNL_BW_40)
00682 {
00683 co_write8p(payload, MAC_ELTID_SEC_CH_OFFSET);
00684 co_write8p(payload + MAC_INFOELT_LEN_OFT, MAC_INFOELT_SEC_CH_OFFSET_INFO_LEN);
00685 if (param->chan.center1_freq > param->chan.prim20_freq)
00686 {
00687 co_write8p(payload + MAC_INFOELT_SEC_CH_OFFSET_SEC_CH_OFT,
00688 MAC_INFOELT_SEC_CH_OFFSET_SEC_ABOVE);
00689 }
00690 else
00691 {
00692 co_write8p(payload + MAC_INFOELT_SEC_CH_OFFSET_SEC_CH_OFT,
00693 MAC_INFOELT_SEC_CH_OFFSET_SEC_BELOW);
00694 }
00695 payload += TDLS_CHANSW_REQ_IE_SEC_CH_OFT_LEN;
00696 }
00697
00698
00699 co_write8p(payload, MAC_ELTID_LINK_IDENTIFIER);
00700 co_write8p(payload + MAC_INFOELT_LEN_OFT, MAC_INFOELT_LINK_ID_LEN);
00701 for (i = 0; i < MAC_ADDR_LEN/2; i++)
00702 {
00703 co_write16p(payload + MAC_INFOELT_LINK_ID_BSSID_OFT + 2*i, vif->bssid.array[i]);
00704 if (param->initiator)
00705 {
00706 co_write16p(payload + MAC_INFOELT_LINK_ID_INIT_STA_OFT + 2*i,
00707 sta->mac_addr.array[i]);
00708 co_write16p(payload + MAC_INFOELT_LINK_ID_RESP_STA_OFT + 2*i,
00709 vif->mac_addr.array[i]);
00710 }
00711 else
00712 {
00713 co_write16p(payload + MAC_INFOELT_LINK_ID_INIT_STA_OFT + 2*i,
00714 vif->mac_addr.array[i]);
00715 co_write16p(payload + MAC_INFOELT_LINK_ID_RESP_STA_OFT + 2*i,
00716 sta->mac_addr.array[i]);
00717 }
00718 }
00719 payload += TDLS_CHANSW_REQ_IE_LINK_ID_LEN;
00720
00721 co_write8p(payload, MAC_ELTID_CHANNEL_SWITCH_TIMING);
00722 co_write8p(payload + MAC_INFOELT_LEN_OFT, MAC_INFOELT_CH_SWITCH_TIMING_LEN);
00723 co_write16p(payload + MAC_INFOELT_CH_SWITCH_TIMING_SWTIME_OFT, ch_switch_time);
00724 co_write16p(payload + MAC_INFOELT_CH_SWITCH_TIMING_SWTOUT_OFT, ch_switch_timeout);
00725 payload += TDLS_CHANSW_REQ_IE_CH_SWITCH_TIMING_LEN;
00726 if (param->chan.type > PHY_CHNL_BW_40)
00727 {
00728
00729 co_write8p(payload, MAC_ELTID_WIDE_BANDWIDTH_CHAN_SWITCH);
00730 co_write8p(payload + MAC_INFOELT_LEN_OFT, MAC_INFOELT_WIDE_BW_CHAN_SWITCH_INFO_LEN);
00731 co_write8p(payload + MAC_INFOELT_WIDE_BW_CHAN_SWITCH_NEW_CW_OFT,
00732 (param->chan.type == PHY_CHNL_BW_20) ? 0 : (param->chan.type - 1));
00733 co_write8p(payload + MAC_INFOELT_WIDE_BW_CHAN_SWITCH_NEW_CENTER1_OFT,
00734 param->chan.center1_freq);
00735 co_write8p(payload + MAC_INFOELT_WIDE_BW_CHAN_SWITCH_NEW_CENTER2_OFT,
00736 param->chan.center2_freq);
00737 payload += TDLS_CHANSW_REQ_IE_WIDE_BW_CHAN_SWITCH_LEN;
00738
00739
00740
00741
00742 }
00743
00744
00745 frame->txdesc.lmac.hw_desc->thd.dataendptr = payload - 1;
00746 frame->txdesc.lmac.hw_desc->thd.frmlen = payload - CPU2HW(buf) + MAC_FCS_LEN + tail_len;
00747
00748
00749 frame->cfm.cfm_func = cfm;
00750 frame->cfm.env = vif;
00751
00752
00753 frame->txdesc.host.vif_idx = vif->index;
00754 frame->txdesc.host.staid = vif->u.sta.ap_id;
00755
00756
00757 txl_frame_push(frame, mac_tid2ac[tid]);
00758
00759 PROF_TDLS_CHSW_REQ_TX_CLR();
00760 return CO_OK;
00761 }
00762
00763 uint8_t txl_frame_send_tdls_channel_switch_rsp_frame(struct vif_info_tag *vif,
00764 uint16_t status_code, cfm_func_ptr cfm)
00765 {
00766 struct txl_frame_desc_tag *frame;
00767 struct mac_hdr_qos *buf;
00768 uint8_t status = CO_FAIL;
00769 int txtype;
00770 uint32_t payload;
00771 uint8_t i;
00772 struct sta_info_tag *sta = &sta_info_tab[vif->u.sta.tdls_chsw_sta_idx];
00773 struct key_info_tag *key = *sta->sta_sec_info.cur_key;
00774 uint8_t tid = TID_5;
00775 int head_len = 0;
00776 int tail_len = 0;
00777
00778 PROF_TDLS_CHSW_RESP_TX_SET();
00779
00780
00781 if (key)
00782 {
00783 ASSERT_ERR(key->cipher == MAC_CIPHER_CCMP);
00784 head_len = IV_LEN + EIV_LEN;
00785 tail_len = MIC_LEN;
00786 }
00787
00788
00789 txtype = vif_mgmt_get_txtype(vif);
00790 frame = txl_frame_get(txtype, MAC_SHORT_QOS_MAC_HDR_LEN + head_len +
00791 MAC_ENCAPSULATED_PAYLOAD_OFT + 30);
00792 if (frame == NULL)
00793 {
00794 PROF_TDLS_CHSW_RESP_TX_CLR();
00795 return status;
00796 }
00797
00798
00799 tpc_update_frame_tx_power(vif, frame);
00800
00801
00802 buf = txl_buffer_payload_get(&frame->txdesc);
00803
00804
00805 buf->fctl = MAC_FCTRL_QOS_DATA;
00806 buf->durid = 0;
00807 MAC_ADDR_CPY(&buf->addr1, &sta->mac_addr);
00808 MAC_ADDR_CPY(&buf->addr2, &vif->mac_addr);
00809 MAC_ADDR_CPY(&buf->addr3, &vif->bssid);
00810 buf->seq = sta_mgmt_get_tx_ssn_and_inc(sta->staid, tid) << MAC_SEQCTRL_NUM_OFT;
00811 buf->qos = tid << MAC_QOSCTRL_UP_OFT;
00812
00813
00814 if (key)
00815 {
00816 txl_frame_tdls_add_security_header(frame, buf, key);
00817 }
00818
00819 payload = CPU2HW(buf) + MAC_SHORT_QOS_MAC_HDR_LEN + head_len;
00820
00821
00822 co_write32p(payload, FRAME_BODY_LLC_H);
00823 co_write32p(payload + MAC_ENCAPSULATED_LLC_L_OFT, FRAME_BODY_LLC_L);
00824 co_write8p(payload + MAC_ENCAPSULATED_PAYLOAD_TYPE_OFT, PAYLOAD_TYPE_TDLS);
00825
00826
00827 payload += MAC_ENCAPSULATED_PAYLOAD_OFT;
00828 co_write8p(payload, MAC_TDLS_ACTION_CATEGORY);
00829
00830 co_write8p(payload + MAC_ACTION_ACTION_OFT, MAC_TDLS_ACTION_CHANSW_RSP);
00831 co_write16p(payload + TDLS_CHANSW_RSP_STATUS_OFFSET, status_code);
00832 payload += TDLS_CHANSW_RSP_IES_OFFSET;
00833
00834 co_write8p(payload, MAC_ELTID_LINK_IDENTIFIER);
00835 co_write8p(payload + MAC_INFOELT_LEN_OFT, MAC_INFOELT_LINK_ID_LEN);
00836 for (i = 0; i < MAC_ADDR_LEN/2; i++)
00837 {
00838 co_write16p(payload + MAC_INFOELT_LINK_ID_BSSID_OFT + 2*i, vif->bssid.array[i]);
00839 if (sta->tdls.initiator)
00840 {
00841 co_write16p(payload + MAC_INFOELT_LINK_ID_INIT_STA_OFT + 2*i,
00842 sta->mac_addr.array[i]);
00843 co_write16p(payload + MAC_INFOELT_LINK_ID_RESP_STA_OFT + 2*i,
00844 vif->mac_addr.array[i]);
00845 }
00846 else
00847 {
00848 co_write16p(payload + MAC_INFOELT_LINK_ID_INIT_STA_OFT + 2*i,
00849 vif->mac_addr.array[i]);
00850 co_write16p(payload + MAC_INFOELT_LINK_ID_RESP_STA_OFT + 2*i,
00851 sta->mac_addr.array[i]);
00852 }
00853 }
00854 payload += TDLS_CHANSW_REQ_IE_LINK_ID_LEN;
00855 co_write8p(payload, MAC_ELTID_CHANNEL_SWITCH_TIMING);
00856 co_write8p(payload + MAC_INFOELT_LEN_OFT, MAC_INFOELT_CH_SWITCH_TIMING_LEN);
00857 co_write16p(payload + MAC_INFOELT_CH_SWITCH_TIMING_SWTIME_OFT, sta->tdls.chsw_time);
00858 co_write16p(payload + MAC_INFOELT_CH_SWITCH_TIMING_SWTOUT_OFT, sta->tdls.chsw_timeout);
00859 payload += TDLS_CHANSW_REQ_IE_CH_SWITCH_TIMING_LEN;
00860
00861
00862 frame->txdesc.lmac.hw_desc->thd.dataendptr = payload - 1;
00863 frame->txdesc.lmac.hw_desc->thd.frmlen = payload - CPU2HW(buf) + MAC_FCS_LEN + tail_len;
00864
00865
00866 frame->txdesc.host.vif_idx = vif->index;
00867 frame->txdesc.host.staid = vif->u.sta.ap_id;
00868
00869 if (status_code == 0)
00870 {
00871
00872 frame->cfm.cfm_func = cfm;
00873 frame->cfm.env = vif;
00874 status = CO_OK;
00875 }
00876
00877
00878 txl_frame_push(frame, mac_tid2ac[tid]);
00879
00880 PROF_TDLS_CHSW_RESP_TX_CLR();
00881 return (status);
00882 }
00883
00884 uint8_t txl_frame_send_tdls_peer_traffic_ind_frame(struct tdls_peer_traffic_ind_req const *param,
00885 cfm_func_ptr cfm)
00886 {
00887 struct txl_frame_desc_tag *frame;
00888 struct mac_hdr_qos *buf;
00889 struct vif_info_tag *vif = &vif_info_tab[param->vif_index];
00890 struct sta_info_tag *sta = &sta_info_tab[param->sta_idx];
00891 struct sta_info_tag *ap = &sta_info_tab[vif->u.sta.ap_id];
00892 struct key_info_tag *key = *ap->sta_sec_info.cur_key;
00893 int txtype;
00894
00895 uint32_t payload;
00896 uint8_t i;
00897 uint8_t tid = TID_5;
00898 int head_len = 0;
00899 int tail_len = 0;
00900
00901
00902 if (key)
00903 {
00904 ASSERT_ERR(key->cipher == MAC_CIPHER_CCMP);
00905 head_len = IV_LEN + EIV_LEN;
00906 tail_len = MIC_LEN;
00907 }
00908
00909
00910 txtype = vif_mgmt_get_txtype(vif);
00911 frame = txl_frame_get(txtype, MAC_SHORT_QOS_MAC_HDR_LEN + head_len +
00912 MAC_ENCAPSULATED_PAYLOAD_OFT + 32);
00913 if (frame == NULL)
00914 {
00915 return CO_FAIL;
00916 }
00917
00918
00919 tpc_update_frame_tx_power(vif, frame);
00920
00921
00922 buf = txl_buffer_payload_get(&frame->txdesc);
00923
00924
00925 buf->fctl = MAC_FCTRL_QOS_DATA;
00926 buf->durid = 0;
00927 MAC_ADDR_CPY(&buf->addr1, &vif->bssid);
00928 MAC_ADDR_CPY(&buf->addr2, &vif->mac_addr);
00929 buf->fctl |= MAC_FCTRL_TODS;
00930 MAC_ADDR_CPY(&buf->addr3, ¶m->peer_mac_addr);
00931 buf->seq = sta_mgmt_get_tx_ssn_and_inc(sta->staid, tid) << MAC_SEQCTRL_NUM_OFT;
00932 buf->qos = tid << MAC_QOSCTRL_UP_OFT;
00933
00934
00935 if (key)
00936 {
00937 txl_frame_tdls_add_security_header(frame, buf, key);
00938 }
00939
00940 payload = CPU2HW(buf) + MAC_SHORT_QOS_MAC_HDR_LEN + head_len;
00941
00942
00943 co_write32p(payload, FRAME_BODY_LLC_H);
00944 co_write32p(payload + MAC_ENCAPSULATED_LLC_L_OFT, FRAME_BODY_LLC_L);
00945 co_write8p(payload + MAC_ENCAPSULATED_PAYLOAD_TYPE_OFT, PAYLOAD_TYPE_TDLS);
00946
00947
00948 payload += MAC_ENCAPSULATED_PAYLOAD_OFT;
00949
00950 co_write8p(payload, MAC_TDLS_ACTION_CATEGORY);
00951
00952 co_write8p(payload + MAC_ACTION_ACTION_OFT, MAC_TDLS_ACTION_PEER_TRAFFIC_IND);
00953
00954 co_write16p(payload + MAC_ACTION_TOKEN_OFT, param->dialog_token);
00955
00956
00957 payload += TDLS_PEER_TRAFFIC_IND_IES_OFFSET;
00958
00959 co_write8p(payload, MAC_ELTID_LINK_IDENTIFIER);
00960 co_write8p(payload + MAC_INFOELT_LEN_OFT, MAC_INFOELT_LINK_ID_LEN);
00961 for (i = 0; i < MAC_ADDR_LEN/2; i++)
00962 {
00963 co_write16p(payload + MAC_INFOELT_LINK_ID_BSSID_OFT + 2*i, vif->bssid.array[i]);
00964 if (sta->tdls.initiator)
00965 {
00966 co_write16p(payload + MAC_INFOELT_LINK_ID_INIT_STA_OFT + 2*i,
00967 param->peer_mac_addr.array[i]);
00968 co_write16p(payload + MAC_INFOELT_LINK_ID_RESP_STA_OFT + 2*i,
00969 vif->mac_addr.array[i]);
00970 }
00971 else
00972 {
00973 co_write16p(payload + MAC_INFOELT_LINK_ID_INIT_STA_OFT + 2*i,
00974 vif->mac_addr.array[i]);
00975 co_write16p(payload + MAC_INFOELT_LINK_ID_RESP_STA_OFT + 2*i,
00976 param->peer_mac_addr.array[i]);
00977 }
00978 }
00979 payload += TDLS_PEER_TRAFFIC_IND_IE_LINK_ID_LEN;
00980
00981 co_write8p(payload, MAC_ELTID_PTI_CONTROL);
00982 co_write8p(payload + MAC_INFOELT_LEN_OFT, MAC_INFOELT_PTI_CONTROL_LEN);
00983 co_write8p(payload + MAC_INFOELT_PTI_CONTROL_TID_OFT, param->last_tid);
00984 co_write16p(payload + MAC_INFOELT_PTI_CONTROL_SEQ_CTRL_OFT, param->last_sn);
00985 payload += TDLS_PEER_TRAFFIC_IND_IE_PTI_CTRL_LEN;
00986
00987 co_write8p(payload, MAC_ELTID_TPU_BUFFER_STATUS);
00988 co_write8p(payload + MAC_INFOELT_LEN_OFT, MAC_INFOELT_TPU_BUF_STATUS_LEN);
00989 co_write8p(payload + MAC_INFOELT_TPU_BUF_STATUS_AC_STATUS, vif->u.sta.uapsd_queues);
00990 payload += TDLS_PEER_TRAFFIC_IND_IE_TPU_BUF_STATUS_LEN;
00991
00992
00993 frame->txdesc.lmac.hw_desc->thd.dataendptr = payload - 1;
00994 frame->txdesc.lmac.hw_desc->thd.frmlen = payload - CPU2HW(buf) + MAC_FCS_LEN + tail_len;
00995
00996
00997 frame->cfm.cfm_func = cfm;
00998 frame->cfm.env = sta;
00999
01000
01001 frame->txdesc.host.vif_idx = vif->index;
01002 frame->txdesc.host.staid = vif->u.sta.ap_id;
01003
01004
01005 txl_frame_push(frame, AC_VI);
01006
01007 return CO_OK;
01008 }
01009 #endif // NX_TDLS && NX_UMAC_PRESENT
01010
01011 #if NX_MAC_HE && NX_UMAC_PRESENT && NX_BEACONING
01012 uint8_t txl_frame_send_he_trigger(uint8_t sta_idx, uint8_t type, uint16_t ul_length,
01013 uint8_t ru_alloc, uint8_t mcs, uint8_t pref_ac,
01014 cfm_func_ptr cfm, void *env)
01015 {
01016 struct txl_frame_desc_tag *frame;
01017 struct he_trigger_base *buf;
01018 struct he_user_info_base *user_info;
01019 struct mac_hdr_ctrl *hdr;
01020 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
01021 struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
01022 int txtype;
01023 struct txl_buffer_control *bufctrl;
01024 struct tx_policy_tbl *pol;
01025 struct mac_hecapability *hecap = &sta->info.he_cap;
01026 struct mac_hecapability *hecaploc = &me_env.he_cap;
01027 uint32_t coding_bit = 0;
01028 uint8_t user_info_len = 0;
01029
01030 if (type == HE_TRIG_TYPE_BASIC)
01031 user_info_len = sizeof_b(struct he_basic_trigger_user_info);
01032 else
01033 user_info_len = sizeof_b(struct he_user_info_base);
01034
01035
01036 txtype = vif_mgmt_get_txtype(vif);
01037 frame = txl_frame_get(txtype, sizeof_b(struct he_trigger_base) + user_info_len);
01038 if (frame == NULL)
01039 return CO_FAIL;
01040
01041 bufctrl = txl_buffer_control_get(&frame->txdesc);
01042 pol = &bufctrl->policy_tbl;
01043
01044
01045 tpc_update_frame_tx_power(vif, frame);
01046
01047
01048 buf = txl_buffer_payload_get(&frame->txdesc);
01049 user_info = (struct he_user_info_base *)(buf + 1);
01050 hdr = &buf->h;
01051
01052
01053 pol->maccntrlinfo2 &= ~(LONG_RETRY_LIMIT_MASK | SHORT_RETRY_LIMIT_MASK);
01054
01055
01056 hdr->fctl = MAC_FCTRL_HE_TRIGGER;
01057 hdr->durid = 0;
01058 hdr->addr1 = mac_addr_bcst;
01059 hdr->addr2 = vif->mac_addr;
01060
01061 buf->common[0] = type | (ul_length << HE_TRIG_UL_LENGTH_OFT);
01062 buf->common[1] = 0;
01063
01064 if (HE_PHY_CAPA_BIT_IS_SET(hecaploc, LDPC_CODING_IN_PAYLOAD) &&
01065 HE_PHY_CAPA_BIT_IS_SET(hecap, LDPC_CODING_IN_PAYLOAD))
01066 coding_bit = HE_TRIG_FEC_CODING_BIT;
01067
01068 user_info->user_info1 = (sta->aid << HE_TRIG_AID12_OFT) |
01069 (ru_alloc << HE_TRIG_RU_ALLOC_OFT) |
01070 (mcs << HE_TRIG_UL_MCS_OFT) |
01071 coding_bit;
01072
01073 user_info->ul_target_rssi = (uint8_t)-40;
01074 if (type == HE_TRIG_TYPE_BASIC)
01075 {
01076 struct he_basic_trigger_user_info *basic_user_info =
01077 (struct he_basic_trigger_user_info *)user_info;
01078 basic_user_info->user_info2 = mac_ac2aci[pref_ac] << HE_TRIG_PREF_AC_OFT;
01079 }
01080
01081
01082 frame->cfm.cfm_func = cfm;
01083 frame->cfm.env = env;
01084
01085
01086 if (!txl_frame_push(frame, pref_ac))
01087 return CO_FAIL;
01088
01089 return CO_OK;
01090 }
01091 #endif // NX_MAC_HE && NX_UMAC_PRESENT && NX_BEACONING
01092
01093 #endif
01094
01095
01097