00001
00020
00021
00022
00023
00024 #include "mac_frame.h"
00025 #include "mm.h"
00026 #include "mm_timer.h"
00027 #include "co_endian.h"
00028 #include "sta_mgmt.h"
00029 #include "vif_mgmt.h"
00030 #include "phy.h"
00031 #include "dbg.h"
00032 #include "rd.h"
00033 #include "ps.h"
00034 #include "txl_cntrl.h"
00035 #include "txl_frame.h"
00036 #include "rxl_cntrl.h"
00037 #include "hal_machw.h"
00038 #include "scan.h"
00039 #include "chan.h"
00040 #include "mm_bcn.h"
00041 #include "hal_dma.h"
00042 #include "macif.h"
00043 #include "tpc.h"
00044
00045 #include "reg_mac_core.h"
00046 #include "reg_mac_pl.h"
00047 #if (NX_UMAC_PRESENT)
00048 #include "me_utils.h"
00049 #endif
00050
00051 #if NX_BCN_AUTONOMOUS_TX
00052
00053
00054
00055
00056
00058
00061 struct mm_bcn_env_tag mm_bcn_env;
00062
00073 static void mm_tim_update_proceed(struct mm_tim_update_req const *param)
00074 {
00075 struct vif_info_tag *vif = &vif_info_tab[param->inst_nbr];
00076
00077
00078 if (param->aid == 0)
00079 {
00080
00081 if (param->tx_avail)
00082 vif->u.ap.bc_mc_status = VIF_AP_BCMC_BUFFERED;
00083 else
00084 vif->u.ap.bc_mc_status = 0;
00085 }
00086 else
00087 {
00088 do
00089 {
00090 struct tx_pbd *pbd_tim = &txl_tim_desc[param->inst_nbr][0];
00091 struct tx_pbd *pbd_bmp = &txl_tim_desc[param->inst_nbr][1];
00092 uint32_t tim_ie = CPU2HW(&txl_tim_ie_pool[param->inst_nbr][0]);
00093 uint32_t tim_bmp = CPU2HW(&txl_tim_bitmap_pool[param->inst_nbr][0]);
00094
00095
00096 uint8_t n = param->aid / 8;
00097 uint8_t mask = CO_BIT(param->aid % 8);
00098 uint8_t val = co_read8p(tim_bmp + n);
00099
00100
00101 if (param->tx_avail)
00102 {
00103
00104 if (val & mask)
00105 break;
00106
00107 TRACE_AP(PS, "{VIF-%d} Traffic buffered for STA aid=%d",
00108 param->inst_nbr, param->aid);
00109
00110
00111 co_write8p(tim_bmp + n, val | mask);
00112
00113
00114 vif->u.ap.tim_bitmap_set++;
00115
00116
00117 if (n < vif->u.ap.tim_n1)
00118 {
00119
00120 vif->u.ap.tim_n1 = n & 0xFE;
00121
00122
00123 pbd_bmp->datastartptr = tim_bmp + vif->u.ap.tim_n1;
00124 }
00125
00126
00127 if (n > vif->u.ap.tim_n2)
00128 {
00129
00130 vif->u.ap.tim_n2 = n;
00131
00132
00133 pbd_bmp->dataendptr = tim_bmp + vif->u.ap.tim_n2;
00134 }
00135
00136
00137 vif->u.ap.tim_len = vif->u.ap.tim_n2 - vif->u.ap.tim_n1 + 6;
00138
00139
00140 co_write8p(tim_ie + MAC_TIM_LEN_OFT, vif->u.ap.tim_len - 2);
00141 co_write8p(tim_ie + MAC_TIM_BMPC_OFT, vif->u.ap.tim_n1);
00142 pbd_tim->dataendptr = tim_ie + MAC_TIM_BMPC_OFT;
00143 pbd_tim->next = CPU2HW(pbd_bmp);
00144 }
00145 else
00146 {
00147
00148 if (!(val & mask))
00149 break;
00150
00151 TRACE_AP(PS, "{VIF-%d} No more traffic buffered for STA aid=%d",
00152 param->inst_nbr, param->aid);
00153
00154
00155 co_write8p(tim_bmp + n, val & ~mask);
00156
00157
00158 vif->u.ap.tim_bitmap_set--;
00159
00160
00161 if (vif->u.ap.tim_bitmap_set)
00162 {
00163
00164 if ((n & 0xFE) == vif->u.ap.tim_n1)
00165 {
00166
00167 while ((vif->u.ap.tim_n1 != MAC_TIM_SIZE) &&
00168 (co_read8p(tim_bmp + vif->u.ap.tim_n1) == 0))
00169 {
00170 vif->u.ap.tim_n1++;
00171 }
00172
00173
00174 vif->u.ap.tim_n1 &= 0xFE;
00175
00176
00177 pbd_bmp->datastartptr = tim_bmp + vif->u.ap.tim_n1;
00178 }
00179
00180
00181 if (n == vif->u.ap.tim_n2)
00182 {
00183
00184 while ((vif->u.ap.tim_n2 != 0) &&
00185 (co_read8p(tim_bmp + vif->u.ap.tim_n2) == 0))
00186 {
00187 vif->u.ap.tim_n2--;
00188 }
00189
00190
00191 pbd_bmp->dataendptr = tim_bmp + vif->u.ap.tim_n2;
00192 }
00193
00194
00195 vif->u.ap.tim_len = vif->u.ap.tim_n2 - vif->u.ap.tim_n1 + 6;
00196
00197
00198 co_write8p(tim_ie + MAC_TIM_LEN_OFT, vif->u.ap.tim_len - 2);
00199 co_write8p(tim_ie + MAC_TIM_BMPC_OFT, vif->u.ap.tim_n1);
00200 }
00201 else
00202 {
00203
00204 vif->u.ap.tim_len = MAC_TIM_BMP_OFT + 1;
00205 vif->u.ap.tim_n1 = -1;
00206 vif->u.ap.tim_n2 = 0;
00207 co_write8p(tim_ie + MAC_TIM_LEN_OFT, vif->u.ap.tim_len - 2);
00208 co_write8p(tim_ie + MAC_TIM_BMPC_OFT, 0);
00209
00210 pbd_tim->dataendptr = tim_ie + MAC_TIM_BMP_OFT;
00211 pbd_tim->next = CPU2HW(&txl_bcn_end_desc[param->inst_nbr]);
00212
00213 pbd_bmp->dataendptr = tim_bmp + vif->u.ap.tim_n2;
00214 }
00215 }
00216 } while(0);
00217 }
00218
00219
00220 ke_msg_send_basic(MM_TIM_UPDATE_CFM, ke_param2msg(param)->src_id, TASK_MM);
00221
00222
00223 ke_msg_free(ke_param2msg(param));
00224 }
00225
00237 static void mm_bcn_desc_prep(struct vif_info_tag *vif,
00238 struct mm_bcn_change_req const *param)
00239 {
00240 struct txl_frame_desc_tag *frame = &vif->u.ap.bcn_desc;
00241 struct tx_hd *thd = &frame->txdesc.lmac.hw_desc->thd;
00242 struct tx_pbd *pbd_bcn = &txl_bcn_end_desc[vif->index];
00243 uint32_t tim_bcn = thd->datastartptr + param->tim_oft;
00244 uint32_t tim_ie = CPU2HW(&txl_tim_ie_pool[vif->index][0]);
00245 struct tx_policy_tbl *pol;
00246 uint8_t band;
00247 uint32_t bcn_len = param->bcn_len - param->tim_len;
00248
00249
00250 vif->u.ap.bcn_len = bcn_len;
00251
00252 #if (NX_UMAC_PRESENT)
00253
00254 me_beacon_check(vif->index, param->bcn_len, thd->datastartptr);
00255 #endif
00256
00257
00258 thd->dataendptr = thd->datastartptr + param->tim_oft - 1;
00259 pbd_bcn->datastartptr = thd->dataendptr + param->tim_len + 1;
00260 pbd_bcn->dataendptr = pbd_bcn->datastartptr + bcn_len - param->tim_oft - 1;
00261 pbd_bcn->bufctrlinfo = 0;
00262
00263
00264 band = vif_mgmt_get_band(vif);
00265
00266 #if (NX_P2P_GO)
00267
00268 if (vif->p2p)
00269 {
00270 #if (NX_UMAC_PRESENT)
00271 pol = &txl_buffer_control_5G.policy_tbl;
00272 #else
00273 pol = &txl_frame_pol_5G;
00274 #endif //(NX_UMAC_PRESENT)
00275 }
00276 else
00277 #endif //(NX_P2P_GO)
00278 {
00279 #if (NX_UMAC_PRESENT)
00280 pol = (band == PHY_BAND_2G4) ? &txl_buffer_control_24G.policy_tbl : &txl_buffer_control_5G.policy_tbl;
00281 #else
00282 pol = (band == PHY_BAND_2G4) ? &txl_frame_pol_24G : &txl_frame_pol_5G;
00283 #endif //(NX_UMAC_PRESENT)
00284 }
00285
00286
00287 pol->powercntrlinfo[0] = TX_PWR_LEVEL_SET(nxmac_ofdm_max_pwr_level_getf());
00288 thd->policyentryaddr = CPU2HW(pol);
00289 thd->phyctrlinfo = 0;
00290 thd->macctrlinfo2 = 0;
00291 thd->first_pbd_ptr = CPU2HW(&txl_tim_desc[vif->index][0]);
00292
00293
00294 vif->u.ap.bcn_configured = true;
00295 co_write8p(tim_ie + MAC_TIM_PERIOD_OFT, co_read8p(tim_bcn + MAC_TIM_PERIOD_OFT));
00296 }
00297
00308 static void mm_bcn_csa_init(struct vif_info_tag *vif,
00309 struct mm_bcn_change_req const *param)
00310 {
00311 struct txl_frame_desc_tag *frame = &vif->u.ap.bcn_desc;
00312 struct tx_hd *thd = &frame->txdesc.lmac.hw_desc->thd;
00313 uint8_t i;
00314
00315
00316 vif->u.ap.csa_count = 0;
00317 for (i = 0; i < BCN_MAX_CSA_CPT; i++)
00318 {
00319 vif->u.ap.csa_oft[i] = param->csa_oft[i];
00320 }
00321
00322 if (param->csa_oft[0] > 0)
00323 {
00324 vif->u.ap.csa_count = co_read8p(thd->datastartptr + param->csa_oft[0]);
00325 vif->u.ap.csa_count++;
00326 }
00327 }
00328
00340 static void mm_bcn_send_csa_counter_ind(uint8_t vif_index, uint8_t csa_count)
00341 {
00342
00343 struct mm_csa_counter_ind *ind = KE_MSG_ALLOC(MM_CSA_COUNTER_IND, TASK_API,
00344 TASK_MM, mm_csa_counter_ind);
00345
00346 ind->vif_index = vif_index;
00347 ind->csa_count = csa_count;
00348
00349
00350 ke_msg_send(ind);
00351 }
00352
00365 static uint8_t mm_bcn_build(struct vif_info_tag *vif)
00366 {
00367 struct txl_frame_desc_tag *frame = &vif->u.ap.bcn_desc;
00368 struct tx_hd *thd = &frame->txdesc.lmac.hw_desc->thd;
00369 uint32_t tim_ie = CPU2HW(&txl_tim_ie_pool[vif->index][0]);
00370 uint8_t bmpc = co_read8p(tim_ie + MAC_TIM_BMPC_OFT);
00371
00372
00373 thd->frmlen = vif->u.ap.bcn_len + vif->u.ap.tim_len + MAC_FCS_LEN;
00374
00375 #if (NX_P2P_GO)
00376 if (vif->p2p)
00377 {
00378
00379 uint8_t noa_len = p2p_go_bcn_get_noa_len(vif->p2p_index);
00380
00381 if (noa_len)
00382 {
00383
00384 struct tx_pbd *noa_pbd = &txl_p2p_noa_desc[vif->index];
00385
00386
00387 thd->frmlen += noa_len;
00388
00389
00390 noa_pbd->dataendptr = noa_pbd->datastartptr + noa_len - 1;
00391 }
00392 }
00393 #endif //(NX_P2P_GO)
00394
00395 #if (RW_UMESH_EN)
00396 if (vif->type == VIF_MESH_POINT)
00397 {
00398 uint8_t mesh_ies_len = mesh_get_vendor_ies_len(vif->mvif_idx);
00399
00400
00401 mesh_update_beacon(vif);
00402
00403
00404 if (mesh_ies_len)
00405 {
00406
00407 struct tx_pbd *add_ies_pbd = &txl_mesh_add_ies_desc[vif->mvif_idx];
00408
00409
00410 thd->frmlen += mesh_ies_len;
00411
00412
00413 add_ies_pbd->dataendptr = add_ies_pbd->datastartptr + mesh_ies_len - 1;
00414
00415
00416 txl_bcn_end_desc[vif->index].next = CPU2HW(add_ies_pbd);
00417 }
00418 else
00419 {
00420 txl_bcn_end_desc[vif->index].next = CPU2HW(NULL);
00421 }
00422 }
00423 #endif //(RW_UMESH_EN)
00424
00425
00426 co_write16(HW2CPU(thd->datastartptr + MAC_HEAD_CTRL_OFT), txl_get_seq_ctrl());
00427
00428 co_write8p(tim_ie + MAC_TIM_CNT_OFT, vif->u.ap.dtim_count);
00429
00430
00431 if (vif->u.ap.dtim_count == 0)
00432 {
00433 if (vif->u.ap.bc_mc_status || macif_tx_q_has_data(AC_BCN))
00434 bmpc |= MAC_TIM_BCMC_PRESENT;
00435 else
00436 bmpc &= ~MAC_TIM_BCMC_PRESENT;
00437 vif->u.ap.dtim_count = co_read8p(tim_ie + MAC_TIM_PERIOD_OFT);
00438 }
00439 else if (vif->u.ap.bc_mc_status & VIF_AP_BCMC_MOREDATA)
00440 {
00441
00442 bmpc |= MAC_TIM_BCMC_PRESENT;
00443 }
00444 else
00445 {
00446 bmpc &= ~MAC_TIM_BCMC_PRESENT;
00447 }
00448 co_write8p(tim_ie + MAC_TIM_BMPC_OFT, bmpc);
00449 vif->u.ap.dtim_count--;
00450
00451
00452 if (vif->u.ap.csa_count)
00453 {
00454 uint8_t i;
00455 vif->u.ap.csa_count --;
00456 for (i = 0; i < BCN_MAX_CSA_CPT; i++)
00457 {
00458 if (vif->u.ap.csa_oft[i] == 0)
00459 break;
00460 co_write8p((uint32_t)HW2CPU(thd->datastartptr) + vif->u.ap.csa_oft[i],
00461 vif->u.ap.csa_count);
00462 }
00463 if (vif->u.ap.csa_count)
00464 {
00465 mm_bcn_send_csa_counter_ind(vif->index, vif->u.ap.csa_count);
00466 }
00467 #if NX_UMAC_PRESENT
00468
00469 if (vif->u.ap.csa_count == 0)
00470 vif->u.ap.csa_count = 1;
00471 #endif
00472 }
00473
00474
00475 tpc_update_frame_tx_power(vif, frame);
00476
00477 return(bmpc & MAC_TIM_BCMC_PRESENT);
00478 }
00479
00491 static void mm_bcn_updated(void *env, int dma_queue)
00492 {
00493 struct vif_info_tag *vif = (struct vif_info_tag *) env;
00494 struct ke_msg *msg = ke_param2msg(mm_bcn_env.param);
00495
00496
00497 ke_msg_send_basic(MM_BCN_CHANGE_CFM, msg->src_id, TASK_MM);
00498
00499
00500 mm_bcn_desc_prep(vif, mm_bcn_env.param);
00501
00502
00503 mm_bcn_csa_init(vif, mm_bcn_env.param);
00504
00505
00506 mm_bcn_env.update_ongoing = false;
00507
00508 if (mm_bcn_env.tx_pending)
00509 mm_bcn_transmit();
00510
00511
00512 mm_bcn_env.param = NULL;
00513
00514
00515 ke_msg_free(msg);
00516 }
00517
00529 static void mm_bcn_update(struct mm_bcn_change_req const *param)
00530 {
00531 struct vif_info_tag *vif = &vif_info_tab[param->inst_nbr];
00532
00533
00534 mm_bcn_env.update_pending = false;
00535 mm_bcn_env.update_ongoing = true;
00536
00537 #if (NX_UMAC_PRESENT && RW_MESH_EN)
00538
00539
00540
00541 if (vif->type == VIF_MESH_POINT)
00542 {
00543 mm_bcn_updated(vif, DMA_DL);
00544 }
00545 else
00546 #endif //(NX_UMAC_PRESENT && RW_MESH_EN)
00547 {
00548 struct txl_buffer_tag *buffer = (struct txl_buffer_tag *)&txl_bcn_pool[param->inst_nbr][0];
00549 #if ! NX_FULLY_HOSTED
00550 struct hal_dma_desc_tag *dma = &mm_bcn_env.dma;
00551
00552
00553 dma->env = vif;
00554 dma->dma_desc->src = param->bcn_ptr;
00555 dma->dma_desc->dest = CPU2HW(buffer->payload);
00556 dma->dma_desc->length = param->bcn_len;
00557
00558
00559 hal_dma_push(dma, DMA_DL);
00560 #else
00561
00562
00563 memcpy(buffer->payload, (void *)param->bcn_ptr, param->bcn_len);
00564 mm_bcn_updated(vif, DMA_DL);
00565 #endif // NX_FULLY_HOSTED
00566 }
00567 }
00568
00581 static void mm_bcn_transmitted(void *env, uint32_t status)
00582 {
00583 #if (NX_P2P_GO) || (NX_UMAC_PRESENT)
00584
00585 struct vif_info_tag *vif = (struct vif_info_tag *)env;
00586 #endif //(NX_P2P_GO) || (NX_UMAC_PRESENT)
00587
00588
00589 ASSERT_ERR(mm_bcn_env.tx_cfm);
00590
00591
00592 mm_bcn_env.tx_cfm--;
00593
00594
00595 if (mm_bcn_env.tx_cfm == 0)
00596 {
00597
00598 mm_no_idle_stop();
00599
00600
00601 if (mm_bcn_env.update_pending)
00602 mm_bcn_update(mm_bcn_env.param);
00603
00604
00605 while (!co_list_is_empty(&mm_bcn_env.tim_list))
00606 {
00607 mm_tim_update_proceed(ke_msg2param((struct ke_msg *)
00608 co_list_pop_front(&mm_bcn_env.tim_list)));
00609 }
00610
00611 #if (NX_P2P_GO)
00612
00613 if (mm_bcn_env.p2p_noa_req[vif->index] != P2P_BCN_UPD_OP_NONE)
00614 {
00615 mm_bcn_update_p2p_noa(vif->index, mm_bcn_env.p2p_noa_req[vif->index]);
00616 }
00617 #endif //(NX_P2P_GO)
00618
00619 #if NX_UMAC_PRESENT
00620 if (vif->u.ap.csa_count == 1)
00621 {
00622 vif_mgmt_switch_channel(vif);
00623 }
00624 #endif // NX_UMAC_PRESENT
00625
00626 #if (RW_UMESH_EN)
00627 mesh_ps_beacon_cfm_handle(vif);
00628 #endif //(RW_UMESH_EN)
00629 }
00630
00631 }
00632
00633 #if (NX_P2P_GO)
00634
00642 static void mm_bcn_init_p2p_noa(uint8_t vif_index)
00643 {
00644
00645 struct tx_pbd *pbd = &txl_p2p_noa_desc[vif_index];
00646
00647 uint32_t p2p_noa_ie = CPU2HW(&txl_p2p_noa_ie_pool[vif_index][0]);
00648
00649
00650 pbd->upatterntx = TX_PAYLOAD_DESC_PATTERN;
00651 pbd->datastartptr = p2p_noa_ie;
00652 pbd->next = (uint32_t)NULL;
00653 pbd->bufctrlinfo = 0;
00654 }
00655 #endif //(NX_P2P_GO)
00656
00657 #if (RW_UMESH_EN)
00658
00664 static void mm_bcn_init_mesh_add_ies_desc(void)
00665 {
00666 for (int i = 0; i < RW_MESH_VIF_NB; i++)
00667 {
00668
00669 struct tx_pbd *pbd = &txl_mesh_add_ies_desc[i];
00670
00671 uint32_t mesh_add_ie = CPU2HW(&txl_mesh_add_ies[i].buf[0]);
00672
00673
00674 pbd->upatterntx = TX_PAYLOAD_DESC_PATTERN;
00675 pbd->datastartptr = mesh_add_ie;
00676 pbd->next = (uint32_t)NULL;
00677 pbd->bufctrlinfo = 0;
00678 }
00679 }
00680 #endif //(RW_UMESH_EN)
00681
00690 static void mm_bcn_init_tim(struct vif_info_tag *vif)
00691 {
00692 uint8_t inst_nbr = vif->index;
00693 struct tx_pbd *pbd = &txl_tim_desc[inst_nbr][0];
00694 uint32_t tim_ie = CPU2HW(&txl_tim_ie_pool[inst_nbr][0]);
00695 uint32_t tim_bmp = CPU2HW(&txl_tim_bitmap_pool[inst_nbr][0]);
00696
00697
00698 vif->u.ap.dtim_count = 0;
00699 vif->u.ap.tim_len = MAC_TIM_BMP_OFT + 1;
00700 vif->u.ap.tim_bitmap_set = 0;
00701 vif->u.ap.tim_n1 = -1;
00702 vif->u.ap.tim_n2 = 0;
00703 vif->u.ap.bc_mc_status = 0;
00704
00705
00706 pbd->upatterntx = TX_PAYLOAD_DESC_PATTERN;
00707 pbd->datastartptr = tim_ie + MAC_TIM_ID_OFT;
00708 pbd->dataendptr = tim_ie + MAC_TIM_BMP_OFT;
00709 pbd->next = CPU2HW(&txl_bcn_end_desc[inst_nbr]);
00710 pbd->bufctrlinfo = 0;
00711 co_write8p(tim_ie + MAC_TIM_ID_OFT, MAC_ELTID_TIM);
00712 co_write8p(tim_ie + MAC_TIM_LEN_OFT, 4);
00713 co_write8p(tim_ie + MAC_TIM_CNT_OFT, vif->u.ap.dtim_count);
00714 co_write8p(tim_ie + MAC_TIM_PERIOD_OFT, 1);
00715 co_write8p(tim_ie + MAC_TIM_BMPC_OFT, 0);
00716 co_write8p(tim_ie + MAC_TIM_BMP_OFT, 0);
00717
00718
00719 pbd = &txl_tim_desc[inst_nbr][1];
00720 pbd->upatterntx = TX_PAYLOAD_DESC_PATTERN;
00721 pbd->dataendptr = tim_bmp + vif->u.ap.tim_n2;
00722 pbd->next = CPU2HW(&txl_bcn_end_desc[inst_nbr]);
00723 memset(txl_tim_bitmap_pool[inst_nbr], 0, sizeof(txl_tim_bitmap_pool[inst_nbr]));
00724
00725
00726 pbd = &txl_bcn_end_desc[inst_nbr];
00727 pbd->upatterntx = TX_PAYLOAD_DESC_PATTERN;
00728 pbd->next = 0;
00729 pbd->bufctrlinfo = 0;
00730 }
00731
00732
00733
00734
00735
00736 void mm_bcn_init(void)
00737 {
00738 #if (NX_P2P_GO)
00739 uint8_t counter;
00740 #endif //(NX_P2P_GO)
00741
00742
00743 memset(&mm_bcn_env, 0, sizeof(mm_bcn_env));
00744
00745 mm_bcn_env.dma.dma_desc = &bcn_dwnld_desc;
00746 mm_bcn_env.dma.cb = mm_bcn_updated;
00747 co_list_init(&mm_bcn_env.tim_list);
00748
00749 #if (NX_P2P_GO)
00750 for (counter = 0; counter < NX_VIRT_DEV_MAX; counter++)
00751 {
00752
00753 p2p_go_bcn_init_noa_pyld(CPU2HW(&txl_p2p_noa_ie_pool[counter][0]));
00754 }
00755 #endif //(NX_P2P_GO)
00756
00757 #if (RW_UMESH_EN)
00758 mm_bcn_init_mesh_add_ies_desc();
00759 #endif //(RW_UMESH_EN)
00760 }
00761
00762 void mm_bcn_init_vif(struct vif_info_tag *vif)
00763 {
00764 struct txl_frame_desc_tag *frame = &vif->u.ap.bcn_desc;
00765 struct txl_buffer_tag *buffer = (struct txl_buffer_tag *)&txl_bcn_pool[vif->index][0];
00766 struct tx_hw_desc *hwdesc = &txl_bcn_hwdesc_pool[vif->index];
00767 #if NX_UMAC_PRESENT
00768 struct txl_buffer_control *bufctrl = &txl_bcn_buf_ctrl[vif->index];
00769 #else
00770 struct txl_buffer_control *bufctrl = &buffer->buffer_control;
00771 #endif
00772 struct tx_hd *thd;
00773
00774
00775 txl_frame_init_desc(frame, buffer, hwdesc, bufctrl);
00776
00777
00778 mm_bcn_init_tim(vif);
00779
00780 #if (NX_P2P_GO)
00781 if (vif->p2p)
00782 {
00783 mm_bcn_init_p2p_noa(vif->index);
00784 }
00785 #endif //(NX_P2P_GO)
00786
00787
00788 thd = &frame->txdesc.lmac.hw_desc->thd;
00789 thd->phyctrlinfo = 0;
00790 thd->macctrlinfo2 = 0;
00791 thd->first_pbd_ptr = 0;
00792
00793
00794 frame->cfm.cfm_func = mm_bcn_transmitted;
00795 frame->cfm.env = vif;
00796 }
00797
00798 void mm_bcn_change(struct mm_bcn_change_req const *param)
00799 {
00800
00801 mm_bcn_env.param = param;
00802
00803
00804 if (mm_bcn_env.tx_cfm)
00805 {
00806 mm_bcn_env.update_pending = true;
00807 }
00808 else
00809 {
00810
00811 mm_bcn_update(param);
00812 }
00813 }
00814
00815 void mm_tim_update(struct mm_tim_update_req const *param)
00816 {
00817
00818 if (mm_bcn_env.tx_cfm)
00819 {
00820
00821 co_list_push_back(&mm_bcn_env.tim_list, &ke_param2msg(param)->hdr);
00822 }
00823 else
00824 {
00825
00826 mm_tim_update_proceed(param);
00827 }
00828 }
00829
00830 void mm_bcn_transmit(void)
00831 {
00832 struct vif_info_tag *vif = vif_mgmt_first_used();
00833 uint32_t next_tbtt;
00834 bool first_vif = true;
00835 bool tbtt_missed = false;
00836 uint8_t bc_mc = 0;
00837
00838
00839 ASSERT_ERR(!mm_bcn_env.tx_cfm);
00840
00841
00842 if (mm_bcn_env.update_ongoing)
00843 {
00844 mm_bcn_env.tx_pending = true;
00845 return;
00846 }
00847
00848
00849 mm_bcn_env.tx_pending = false;
00850
00851 next_tbtt = nxmac_next_tbtt_get() << 5;
00852
00853
00854 while (vif != NULL)
00855 {
00856
00857 if (((vif->type == VIF_AP)
00858 #if (RW_MESH_EN)
00859 || (vif->type == VIF_MESH_POINT)
00860 #endif
00861 ) && vif->u.ap.bcn_configured && vif->active
00862 #if (NX_UMAC_PRESENT)
00863 && (vif->u.ap.bcn_tbtt_cnt == vif->u.ap.bcn_tbtt_ratio)
00864 #endif
00865 )
00866 {
00867
00868 if (mm_bcn_build(vif))
00869 {
00870 bc_mc++;
00871 }
00872
00873 if (first_vif &&
00874 (next_tbtt > (HAL_MACHW_BCN_TX_DELAY_US + MM_PRE_AP_TBTT_DELAY_US) ||
00875 next_tbtt < 50))
00876 {
00877 #if NX_CHNL_CTXT
00878 if (chan_is_on_operational_channel(vif))
00879 #endif
00880 {
00881 TRACE_CHAN(ERR, "{VIF-%d} Don't push beacon as TBTT is already passed",
00882 vif->index);
00883 }
00884 tbtt_missed = true;
00885 }
00886 first_vif = false;
00887
00888 if (tbtt_missed)
00889 {
00890 bc_mc = 0;
00891 vif = vif_mgmt_next(vif);
00892 continue;
00893 }
00894
00895 #if NX_CHNL_CTXT
00896 if (chan_is_on_operational_channel(vif))
00897 #endif
00898 {
00899 if (bc_mc)
00900 {
00901 #if NX_UMAC_PRESENT
00902 mm_traffic_req_ind(VIF_TO_BCMC_IDX(vif->index), 0, false);
00903 #else
00904 vif->u.ap.bc_mc_nb = macif_tx_q_len(AC_BCN, vif->index);
00905 #endif
00906 }
00907
00908 #if NX_CHNL_CTXT
00909
00910 vif->u.ap.bcn_desc.txdesc.host.vif_idx = vif->index;
00911 vif->u.ap.bcn_desc.txdesc.host.staid = 0xFF;
00912
00913
00914 if (txl_frame_push(&vif->u.ap.bcn_desc, AC_BCN))
00915 {
00916 mm_bcn_env.tx_cfm++;
00917 }
00918 #else
00919 txl_frame_push(&vif->u.ap.bcn_desc, AC_BCN);
00920 mm_bcn_env.tx_cfm++;
00921 #endif //(NX_CHNL_CTXT)
00922
00923 if (mm_bcn_env.tx_cfm == 1)
00924 {
00925
00926
00927 mm_no_idle_start();
00928 }
00929
00930 #if NX_UMAC_PRESENT
00931 if (bc_mc) {
00932 struct sta_info_tag *sta_bcmc = &sta_info_tab[VIF_TO_BCMC_IDX(vif->index)];
00933 if (sta_bcmc->traffic_avail & PS_TRAFFIC_INT)
00934 {
00935 sta_bcmc->ps_service_period = (PS_SERVICE_PERIOD | BCN_SERVICE_PERIOD);
00936 sta_mgmt_send_postponed_frame(vif, sta_bcmc, 0);
00937 sta_bcmc->ps_service_period = NO_SERVICE_PERIOD;
00938 }
00939 bc_mc = 0;
00940 }
00941 #endif // NX_UMAC_PRESENT
00942 }
00943 #if NX_CHNL_CTXT
00944 else
00945 {
00946 bc_mc = 0;
00947 }
00948 #endif
00949 }
00950
00951
00952 vif = vif_mgmt_next(vif);
00953 }
00954
00955 #if !NX_UMAC_PRESENT
00956
00957 if (bc_mc)
00958 macif_tx_evt(AC_BCN);
00959 #endif
00960 }
00961
00962 #if (NX_P2P_GO)
00963 void mm_bcn_update_p2p_noa(uint8_t vif_index, uint8_t operation)
00964 {
00965
00966 if (mm_bcn_env.tx_cfm)
00967 {
00968
00969 mm_bcn_env.p2p_noa_req[vif_index] = operation;
00970 }
00971 else
00972 {
00973
00974 struct vif_info_tag *vif = &vif_info_tab[vif_index];
00975
00976
00977 switch (operation)
00978 {
00979 case (P2P_BCN_UPD_OP_NOA_ADD):
00980 {
00981 txl_bcn_end_desc[vif_index].next = CPU2HW(&txl_p2p_noa_desc[vif_index]);
00982 } break;
00983
00984 case (P2P_BCN_UPD_OP_NOA_RMV):
00985 {
00986 txl_bcn_end_desc[vif_index].next = (uint32_t)NULL;
00987 } break;
00988
00989 case (P2P_BCN_UPD_OP_NOA_UPD):
00990 {
00991
00992 p2p_go_bcn_upd_noa_pyld(vif->p2p_index, CPU2HW(&txl_p2p_noa_ie_pool[vif_index][0]));
00993 } break;
00994
00995 default:
00996 {
00997 ASSERT_ERR(0);
00998 }
00999 }
01000
01001
01002 mm_bcn_env.p2p_noa_req[vif_index] = P2P_BCN_UPD_OP_NONE;
01003
01004
01005 p2p_go_bcn_op_done(vif->p2p_index, operation);
01006 }
01007 }
01008 #endif //(NX_P2P_GO)
01009
01010 #if (NX_UMAC_PRESENT && RW_MESH_EN)
01011 struct txl_buffer_tag *mm_bcn_get_buffer(uint8_t vif_index)
01012 {
01013 return (struct txl_buffer_tag *)&txl_bcn_pool[vif_index][0];
01014 }
01015 #endif //(NX_UMAC_PRESENT && RW_MESH_EN)
01016
01017 #endif //(NX_BCN_AUTONOMOUS_TX)
01018