00001
00020
00021
00022
00023
00024 #include "mac_frame.h"
00025 #include "mm.h"
00026 #include "mm_timer.h"
00027 #include "mm_bcn.h"
00028 #include "co_endian.h"
00029 #include "sta_mgmt.h"
00030 #include "vif_mgmt.h"
00031 #include "phy.h"
00032 #include "dbg.h"
00033 #include "rd.h"
00034 #include "ps.h"
00035 #include "txl_cntrl.h"
00036 #include "txl_frame.h"
00037 #include "rxl_cntrl.h"
00038 #include "rxl_hwdesc.h"
00039 #include "hal_machw.h"
00040 #include "scan.h"
00041 #include "chan.h"
00042 #include "hal_dma.h"
00043 #if (NX_P2P)
00044 #include "p2p.h"
00045 #endif //(NX_P2P)
00046 #if (NX_TD)
00047 #include "td.h"
00048 #endif //(NX_TD)
00049 #if (RW_BFMER_EN)
00050 #include "bfr.h"
00051 #endif //(RW_BFMER_EN)
00052 #if (RW_UMESH_EN)
00053 #include "mesh.h"
00054 #endif //(RW_UMESH_EN)
00055 #if (NX_UMAC_PRESENT && NX_BEACONING)
00056 #include "apm.h"
00057 #endif // NX_BEACONING
00058
00059 #include "reg_mac_core.h"
00060 #include "reg_mac_pl.h"
00061
00062
00063 #include "mac_ie.h"
00064
00065
00067 #if NX_BEACONING
00068 #define MM_TBTT_EVT_MASK (KE_EVT_PRIMARY_TBTT_BIT | KE_EVT_SECONDARY_TBTT_BIT)
00069 #else
00070 #define MM_TBTT_EVT_MASK KE_EVT_PRIMARY_TBTT_BIT
00071 #endif
00072
00074 #define MM_BEACON_LOSS_THD 10
00075
00077 #define MM_KEEP_ALIVE_PERIOD (30 * 1000000)
00078
00080 #define MM_TBTT_IRQ_MASK (NXMAC_IMP_PRI_DTIM_BIT | NXMAC_IMP_PRI_TBTT_BIT)
00081
00083 #define MM_MAC_ADDR_MSK ((NX_VIRT_DEV_MAX - 1) << 8)
00084
00086 #define TXOP(limit) (((limit)==0) || ((limit) > MM_DEFAULT_MAX_AMPDU_DURATION))? \
00087 MM_DEFAULT_MAX_AMPDU_DURATION:(limit);
00088
00089 #if NX_MULTI_ROLE
00091 #define TBTT_DELAY 400
00092 #endif
00093
00106 #if !NX_MAC_HE
00107
00108 #define KEY_RAM_WR(key_idx, ctype, vif_idx, spp, usedefkey, clen) \
00109 { \
00110 nxmac_encr_cntrl_pack(0, 1, 0, 0, key_idx, ctype, vif_idx, spp, usedefkey, clen); \
00111 while(nxmac_new_write_getf()); \
00112 }
00113 #else
00114
00115 #define KEY_RAM_WR(key_idx, ctype, vif_idx, spp, usedefkey, clen) \
00116 { \
00117 nxmac_encr_cntrl_pack(0, 1, 0, 0, key_idx, clen, ctype, vif_idx, spp, usedefkey); \
00118 while(nxmac_new_write_getf()); \
00119 }
00120 #endif
00121
00122
00124 #if NX_CHNL_CTXT
00125 #define MM_TBTT_COMPUTE_MARGIN (CHAN_SWITCH_DELAY + 300)
00126 #else
00127 #define MM_TBTT_COMPUTE_MARGIN 300
00128 #endif
00129
00131 #if NX_UMAC_PRESENT
00132 #define TASK_IND TASK_SM
00133 #else
00134 #define TASK_IND TASK_API
00135 #endif
00136
00137
00138
00139
00140
00142
00145 struct mm_env_tag mm_env;
00146
00147
00159 static void mm_key_ram_param_get(uint8_t cipher_suite, struct mac_sec_key const *key,
00160 uint8_t *ctype, uint8_t *clen)
00161 {
00162 *clen = 1;
00163 *ctype = MM_SEC_CTYPE_NULL;
00164
00165
00166 switch(cipher_suite)
00167 {
00168 case MAC_CIPHER_WEP40:
00169 *clen = 0;
00170 case MAC_CIPHER_WEP104:
00171 *ctype = MM_SEC_CTYPE_WEP;
00172 break;
00173 case MAC_CIPHER_TKIP:
00174 *ctype = MM_SEC_CTYPE_TKIP;
00175 break;
00176 case MAC_CIPHER_CCMP:
00177 #if NX_MAC_HE
00178 switch (key->length)
00179 {
00180 case 16:
00181 *clen = 0;
00182 break;
00183 case 32:
00184 *clen = 2;
00185 break;
00186 default:
00187 break;
00188 }
00189 #endif
00190 *ctype = MM_SEC_CTYPE_CCMP;
00191 break;
00192 #if RW_WAPI_EN
00193 case MAC_CIPHER_WPI_SMS4:
00194 *ctype = MM_SEC_CTYPE_WPI_SMS4;
00195 break;
00196 #endif
00197 default:
00198 ASSERT_ERR(0);
00199 break;
00200 }
00201
00202
00203 }
00204
00205 #if NX_BEACONING
00206
00215 static void mm_ap_tbtt_move_cb(void *offset)
00216 {
00217
00218 struct mm_tbtt_move_req *req = KE_MSG_ALLOC(MM_TBTT_MOVE_REQ, TASK_MM, TASK_NONE, mm_tbtt_move_req);
00219
00220
00221 req->offset = (int32_t)offset;
00222
00223
00224 ke_msg_send(req);
00225 }
00226 #endif
00227
00228 void mm_env_max_ampdu_duration_set(void)
00229 {
00230
00231 mm_env.ampdu_max_dur[AC_BK] = TXOP(nxmac_tx_op_limit_0_getf());
00232 mm_env.ampdu_max_dur[AC_BE] = TXOP(nxmac_tx_op_limit_1_getf());
00233 mm_env.ampdu_max_dur[AC_VI] = TXOP(nxmac_tx_op_limit_2_getf());
00234 mm_env.ampdu_max_dur[AC_VO] = TXOP(nxmac_tx_op_limit_3_getf());
00235
00236 #if NX_BEACONING
00237
00238 mm_env.ampdu_max_dur[AC_BCN] = mm_env.ampdu_max_dur[AC_VO];
00239 #endif
00240 }
00241
00242 void mm_env_init(void)
00243 {
00244
00245 memset(&mm_env, 0, sizeof(mm_env));
00246
00247 mm_env.prev_mm_state = MM_IDLE;
00248 mm_env.prev_hw_state = HW_IDLE;
00249 #if NX_UMAC_PRESENT
00250 mm_env.host_idle = 1;
00251 #endif
00252 mm_env.rx_filter_lmac_enable = 0;
00253 mm_rx_filter_umac_set(MM_RX_FILTER_MONITOR);
00254
00255
00256 mm_env_max_ampdu_duration_set();
00257 #if NX_BEACONING
00258 mm_env.tbtt_move_tmr.cb = mm_ap_tbtt_move_cb;
00259 #endif
00260 }
00261
00265 void mm_init(void)
00266 {
00267
00268
00269
00270 hal_machw_init();
00271
00272
00273 mm_env_init();
00274
00275
00276 vif_mgmt_init();
00277
00278
00279 sta_mgmt_init();
00280
00281 #if (NX_TD)
00282
00283 td_init();
00284 #endif //(NX_TD)
00285
00286 #if NX_POWERSAVE
00287
00288 ps_init();
00289 #endif
00290
00291 #if (NX_P2P)
00292
00293 p2p_init();
00294 #endif //(NX_P2P)
00295
00296
00297 txl_cntrl_init();
00298
00299
00300 rxl_init();
00301
00302 #if NX_RADAR_DETECT
00303
00304 rd_init();
00305 #endif
00306
00307 #if NX_MM_TIMER
00308 mm_timer_init();
00309 #endif
00310
00311 #if NX_HW_SCAN
00312 scan_init();
00313 #endif
00314
00315 #if NX_CHNL_CTXT
00316 chan_init();
00317 #endif
00318
00319 #if NX_GP_DMA
00320 hal_dma_init();
00321 #endif
00322
00323 #if NX_BCN_AUTONOMOUS_TX
00324
00325 mm_bcn_init();
00326 #endif
00327
00328 #if (RW_BFMER_EN)
00329
00330 bfr_init();
00331 #endif //(RW_BFMER_EN)
00332 }
00333
00334 #if NX_MULTI_ROLE
00335 void mm_tbtt_compute(struct bcn_frame *bcn, uint16_t len, struct rx_hd *rhd,
00336 struct vif_info_tag *vif,
00337 struct sta_info_tag *sta, uint32_t tim)
00338 {
00339
00340 uint64_t tsf_start_local = ((uint64_t)rhd->tsflo) | (((uint64_t)rhd->tsfhi) << 32);
00341 uint64_t tsf_start_peer = bcn->tsf;
00342 int64_t tsf_offset;
00343 uint32_t next_tbtt;
00344 uint32_t duration_to_timestamp;
00345 uint32_t duration_of_frame;
00346 uint64_t next_tbtt_tsf;
00347 uint64_t tbtt_tsf;
00348 uint32_t bcn_int = (bcn->bcnint << 10);
00349 uint16_t interval = 1;
00350 uint32_t drift = 0;
00351
00352 #if NX_POWERSAVE
00353 if ((vif->type == VIF_STA) && (vif->u.sta.listen_interval))
00354 {
00355 interval = vif->u.sta.listen_interval;
00356 }
00357 else
00358 #endif
00359 if (tim)
00360 {
00361
00362 interval = co_read8p(tim + MAC_TIM_CNT_OFT);
00363 if (interval == 0)
00364 interval = co_read8p(tim + MAC_TIM_PERIOD_OFT);
00365 }
00366
00367 #if (NX_POWERSAVE)
00368 drift = sta->drift * interval;
00369 #endif //(NX_POWERSAVE)
00370
00371
00372 duration_of_frame = hal_machw_rx_bcn_duration(rhd, len);
00373 duration_to_timestamp = hal_machw_rx_bcn_duration(rhd, MAC_BEACON_TIMESTAMP_OFT);
00374 tsf_start_local -= (duration_of_frame - duration_to_timestamp);
00375
00376
00377 tsf_offset = tsf_start_peer - tsf_start_local;
00378
00379 #if (NX_P2P)
00380 if (vif->type == VIF_STA)
00381 {
00382 vif->u.sta.ctw_add_dur = drift + TBTT_DELAY;
00383 vif->u.sta.last_tsf_offset = tsf_offset;
00384 }
00385 #endif //(NX_P2P)
00386
00387
00388 tbtt_tsf = (tsf_start_peer / bcn_int) * bcn_int;
00389
00390
00391 if (tbtt_tsf > (tsf_start_peer - duration_to_timestamp))
00392 tbtt_tsf = tsf_start_peer - duration_to_timestamp;
00393
00394
00395 next_tbtt_tsf = tbtt_tsf + interval * bcn_int;
00396
00397
00398 next_tbtt = (uint32_t)(next_tbtt_tsf - tsf_offset) - TBTT_DELAY - drift;
00399
00400
00401 if (hal_machw_time_past(next_tbtt - MM_TBTT_COMPUTE_MARGIN))
00402 {
00403 next_tbtt += bcn_int;
00404 }
00405
00406
00407 next_tbtt += (ke_time() - nxmac_tsf_lo_get());
00408
00409 #if (RW_UMESH_EN)
00410 if (vif->type == VIF_MESH_POINT)
00411 {
00412
00413 sta->bcn_int = bcn_int;
00414 mesh_update_tbtt_info(vif, sta, next_tbtt);
00415 }
00416 else
00417 #endif //(RW_UMESH_EN)
00418 {
00419
00420 if (next_tbtt != vif->tbtt_timer.time)
00421 {
00422 mm_timer_set(&vif->tbtt_timer, next_tbtt);
00423 #if NX_CHNL_CTXT
00424 chan_tbtt_updated(vif);
00425 #endif
00426 }
00427 }
00428 }
00429 #endif
00430
00431 #if NX_CONNECTION_MONITOR
00432
00441 static void mm_ap_probe_cfm(void *env, uint32_t status)
00442 {
00443 struct vif_info_tag *vif = (struct vif_info_tag *) env;
00444
00445
00446 if (status & FRAME_SUCCESSFUL_TX_BIT)
00447 {
00448
00449 vif->u.sta.beacon_loss_cnt = 0;
00450 }
00451 else
00452 {
00453
00454 mm_send_connection_loss_ind(vif);
00455 }
00456 }
00457
00471 static uint32_t mm_compute_beacon_crc(struct bcn_frame *bcn, uint16_t len, uint32_t *tim)
00472 {
00473 uint32_t crc;
00474 uint32_t bcn_addr = CPU2HW(bcn);
00475 uint32_t addr = bcn_addr + MAC_BEACON_VARIABLE_PART_OFT;
00476
00477
00478 crc = co_crc32(bcn_addr + MAC_BEACON_INTERVAL_OFT, 4, 0);
00479
00480
00481 len -= MAC_BEACON_VARIABLE_PART_OFT;
00482
00483
00484 *tim = 0;
00485
00486
00487 while (len >= MAC_INFOELT_INFO_OFT)
00488 {
00489 uint8_t ie_id = co_read8p(addr++);
00490 uint8_t ie_len = co_read8p(addr++);
00491
00492
00493 if ((ie_len + MAC_INFOELT_INFO_OFT) > len)
00494 break;
00495
00496
00497 switch (ie_id)
00498 {
00499 case MAC_ELTID_TIM:
00500
00501 *tim = addr - MAC_INFOELT_INFO_OFT;
00502 break;
00503 default:
00504
00505 crc = co_crc32(addr, ie_len, crc);
00506 break;
00507 }
00508
00509
00510 len -= ie_len + MAC_INFOELT_INFO_OFT;
00511 addr += ie_len;
00512 }
00513
00514 return (crc);
00515 }
00516 #endif
00517
00518 #if NX_CONNECTION_MONITOR || NX_MULTI_ROLE
00519 bool mm_check_beacon(struct rx_hd *rhd, struct vif_info_tag *vif,
00520 struct sta_info_tag *sta, uint32_t *tim)
00521 {
00522 struct rx_pbd *pbd = HW2CPU(rhd->first_pbd_ptr);
00523 struct bcn_frame *bcn = HW2CPU(pbd->datastartptr);
00524 uint16_t len = rhd->frmlen;
00525
00526 #if NX_CONNECTION_MONITOR
00527 int8_t rssi;
00528 int8_t rx_rssi[2];
00529 uint32_t crc_prev = vif->u.sta.mon_last_crc;
00530
00531
00532 vif->u.sta.beacon_loss_cnt = 0;
00533
00534 #if NX_UMAC_PRESENT
00535 if (vif->u.sta.csa_occured)
00536 {
00537 mm_send_csa_traffic_ind(vif->index, true);
00538 vif->u.sta.csa_occured = false;
00539 }
00540 #endif
00541
00542 #if (NX_P2P_GO)
00543
00544 vif->u.sta.bcn_rcved = true;
00545 #endif //(NX_P2P_GO)
00546
00547
00548 if ((ke_time_past(vif->u.sta.mon_last_tx + MM_KEEP_ALIVE_PERIOD)) &&
00549 (txl_frame_send_null_frame(vif->u.sta.ap_id, NULL, NULL) == CO_OK))
00550 {
00551
00552 vif->u.sta.mon_last_tx = ke_time();
00553 }
00554
00555
00556 rssi = hal_desc_get_rssi(&rhd->rx_vec_1, rx_rssi);
00557
00558 #if (NX_ANT_DIV)
00559
00560 mm_ant_div_update_rssi(rx_rssi);
00561 #endif // (NX_ANT_DIV)
00562
00563
00564 mm_check_rssi(vif, rssi);
00565
00566
00567 vif->u.sta.mon_last_crc = mm_compute_beacon_crc(bcn, len, tim);
00568 #else // NX_CONNECTION_MONITOR
00569 *tim = mac_ie_tim_find(pbd->datastartptr + MAC_BEACON_VARIABLE_PART_OFT,
00570 len - MAC_BEACON_VARIABLE_PART_OFT);
00571 #endif // NX_CONNECTION_MONITOR
00572
00573 #if NX_MULTI_ROLE
00574
00575 mm_tbtt_compute(bcn, len, rhd, vif, sta, *tim);
00576 #endif
00577
00578 #if NX_CONNECTION_MONITOR
00579 return (crc_prev != vif->u.sta.mon_last_crc);
00580 #else
00581 return (true);
00582 #endif
00583 }
00584 #endif
00585
00586 void mm_reset(void)
00587 {
00588
00589 switch (ke_state_get(TASK_MM))
00590 {
00591 case MM_ACTIVE:
00592
00593 mm_active();
00594 break;
00595
00596 default:
00597
00598 ke_state_set(TASK_MM, MM_IDLE);
00599 break;
00600 }
00601 }
00602
00603 void mm_active(void)
00604 {
00605
00606 nxmac_next_state_setf(HW_ACTIVE);
00607 ke_state_set(TASK_MM, MM_ACTIVE);
00608 }
00609
00610 #if NX_POWERSAVE || NX_CONNECTION_MONITOR || NX_MULTI_ROLE
00611 void mm_sta_tbtt(void *env)
00612 {
00613
00614 struct vif_info_tag *vif = (struct vif_info_tag *)env;
00615 #if (NX_MULTI_ROLE || NX_CHNL_CTXT)
00616
00617 uint32_t tbtt_time, next_tbtt_time;
00618 #endif //(NX_MULTI_ROLE || NX_CHNL_CTXT)
00619
00620 PROF_STA_TBTT_SET();
00621 PROF_TBTT_IDX_SET(vif->chan_ctxt->idx);
00622
00623 do
00624 {
00625 if (!vif->active)
00626
00627 break;
00628
00629 #if NX_UMAC_PRESENT
00630 if (vif->u.sta.csa_count)
00631 {
00632 vif->u.sta.csa_count--;
00633 if (vif->u.sta.csa_count <= 1)
00634 {
00635 vif_mgmt_switch_channel(vif);
00636 break;
00637 }
00638 else if (vif->u.sta.csa_count == 2)
00639 {
00640 mm_send_csa_traffic_ind(vif->index, false);
00641 }
00642 }
00643 #endif
00644
00645 #if (NX_MULTI_ROLE || NX_CHNL_CTXT)
00646 tbtt_time = vif->tbtt_timer.time;
00647 next_tbtt_time = tbtt_time + sta_info_tab[vif->u.sta.ap_id].bcn_int;
00648 #endif //(NX_MULTI_ROLE || NX_CHNL_CTXT)
00649
00650 #if NX_MULTI_ROLE
00651
00652 mm_timer_set(&vif->tbtt_timer, next_tbtt_time);
00653 #endif
00654
00655 #if (NX_P2P || NX_CHNL_CTXT)
00656 vif_mgmt_bcn_to_prog(vif);
00657 #endif //(NX_P2P || NX_CHNL_CTXT)
00658
00659 #if (NX_P2P)
00660 p2p_tbtt_handle(vif, tbtt_time + vif->u.sta.ctw_add_dur);
00661 #endif //(NX_P2P)
00662
00663 #if (NX_CHNL_CTXT)
00664 if (chan_tbtt_start(vif, tbtt_time, next_tbtt_time))
00665 break;
00666 #endif //(NX_CHNL_CTXT)
00667
00668 #if NX_POWERSAVE
00669 vif->prevent_sleep |= PS_VIF_WAITING_BCN;
00670 #endif
00671
00672 #if NX_CONNECTION_MONITOR
00673
00674 vif->u.sta.beacon_loss_cnt++;
00675
00676
00677 if (vif->u.sta.beacon_loss_cnt > MM_BEACON_LOSS_THD)
00678 {
00679
00680 txl_frame_send_null_frame(vif->u.sta.ap_id, mm_ap_probe_cfm, vif);
00681 }
00682 #if (NX_CHNL_CTXT)
00683 else if (vif->u.sta.beacon_loss_cnt > (MM_BEACON_LOSS_THD - 1))
00684 {
00685
00686 chan_bcn_detect_start(vif);
00687 }
00688 #endif //(NX_CHNL_CTXT)
00689 #endif
00690
00691 #if (NX_ANT_DIV)
00692
00693 mm_ant_div_check(vif->u.sta.beacon_loss_cnt);
00694 #endif //(NX_ANT_DIV)
00695
00696 } while(0);
00697 PROF_STA_TBTT_CLR();
00698 }
00699 #endif
00700
00701 #if NX_BEACONING
00702
00712 static void mm_ap_tbtt(uint32_t evt)
00713 {
00714 struct vif_info_tag *vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
00715
00716 PROF_AP_TBTT_SET();
00717
00718
00719 GLOBAL_INT_DISABLE();
00720
00721
00722 txl_cntrl_halt_ac(AC_BCN);
00723
00724
00725 txl_cntrl_flush_ac(AC_BCN, DESC_DONE_SW_TX_BIT);
00726
00727
00728 GLOBAL_INT_RESTORE();
00729
00730 while (vif != NULL)
00731 {
00732 switch (vif->type)
00733 {
00734 case (VIF_AP):
00735 #if (RW_MESH_EN)
00736 case (VIF_MESH_POINT):
00737 #endif //(RW_MESH_EN)
00738 {
00739 #if (NX_CHNL_CTXT || NX_P2P_GO)
00740 uint32_t beacon_int;
00741 uint32_t next_tbtt;
00742 #endif //(NX_CHNL_CTXT || NX_P2P_GO)
00743
00744 #if (NX_UMAC_PRESENT)
00745 vif->u.ap.bcn_tbtt_cnt--;
00746
00747
00748 if (vif->u.ap.bcn_tbtt_cnt)
00749 {
00750 break;
00751 }
00752
00753
00754 vif->u.ap.bcn_tbtt_cnt = vif->u.ap.bcn_tbtt_ratio;
00755 #endif //(NX_UMAC_PRESENT)
00756
00757 #if (NX_CHNL_CTXT || NX_P2P_GO)
00758
00759 vif_mgmt_bcn_to_prog(vif);
00760 #endif //(NX_P2P || NX_CHNL_CTXT)
00761
00762 #if (NX_P2P_GO)
00763 p2p_tbtt_handle(vif, vif->tbtt_timer.time + HAL_MACHW_BCN_TX_DELAY_US +
00764 MM_PRE_AP_TBTT_DELAY_US);
00765 #endif //(NX_P2P_GO)
00766
00767 #if (NX_CHNL_CTXT || NX_P2P_GO)
00768 beacon_int = (uint32_t)vif->u.ap.bcn_int << 10;
00769 next_tbtt = nxmac_next_tbtt_get() << 5;
00770 if (next_tbtt < (HAL_MACHW_BCN_TX_DELAY_US + MM_PRE_AP_TBTT_DELAY_US))
00771 next_tbtt += beacon_int;
00772 next_tbtt += ke_time();
00773 next_tbtt -= (HAL_MACHW_BCN_TX_DELAY_US + MM_PRE_AP_TBTT_DELAY_US);
00774 #endif //(NX_CHNL_CTXT || NX_P2P_GO)
00775
00776 #if (NX_CHNL_CTXT)
00777 if (vif->chan_ctxt != NULL)
00778 {
00779 chan_tbtt_start(vif, vif->tbtt_timer.time, next_tbtt);
00780 }
00781 #endif //(NX_CHNL_CTXT)
00782
00783 #if (NX_P2P_GO)
00784 if (vif->p2p)
00785 {
00786
00787
00788
00789
00790 mm_timer_set(&vif->tbtt_timer, next_tbtt);
00791 }
00792 #endif //(NX_P2P_GO)
00793 } break;
00794
00795 default:
00796 {
00797 } break;
00798 }
00799
00800
00801 vif = vif_mgmt_next(vif);
00802 }
00803
00804 #if NX_BCN_AUTONOMOUS_TX
00805
00806 mm_bcn_transmit();
00807 #endif
00808
00809 PROF_AP_TBTT_CLR();
00810 }
00811 #endif
00812
00813 #if (NX_P2P_GO && NX_POWERSAVE)
00814 void mm_ap_pre_tbtt(void *env)
00815 {
00816
00817 struct vif_info_tag *vif = (struct vif_info_tag *)env;
00818
00819
00820 p2p_go_pre_tbtt(vif);
00821 }
00822 #endif //(NX_P2P_GO && NX_POWERSAVE)
00823
00824 #if NX_BEACONING && ((NX_POWERSAVE || NX_CONNECTION_MONITOR || NX_UMAC_PRESENT) && !NX_MULTI_ROLE)
00825 void mm_tbtt_evt(int dummy)
00826 {
00827 uint32_t evt = ke_evt_get() & MM_TBTT_EVT_MASK;
00828 #if NX_POWERSAVE || NX_CONNECTION_MONITOR || NX_UMAC_PRESENT
00829
00830
00831 struct vif_info_tag *vif =
00832 (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
00833 #endif
00834
00835 PROF_HW_TBTT_EVT_SET();
00836
00837
00838
00839 ASSERT_ERR(evt != MM_TBTT_EVT_MASK);
00840
00841
00842 ke_evt_clear(evt);
00843
00844 #if NX_POWERSAVE || NX_CONNECTION_MONITOR
00845
00846 if (vif->type == VIF_STA)
00847 {
00848
00849 mm_sta_tbtt(vif);
00850 }
00851 #if NX_BEACONING
00852 else
00853 #endif
00854 #endif
00855 {
00856 #if NX_BEACONING
00857
00858 if (mm_env.beaconing)
00859 {
00860 mm_ap_tbtt(evt);
00861 }
00862 #endif
00863 }
00864
00865 PROF_HW_TBTT_EVT_CLR();
00866 }
00867 #elif ((NX_POWERSAVE || NX_CONNECTION_MONITOR || NX_UMAC_PRESENT) && !NX_MULTI_ROLE)
00868 void mm_tbtt_evt(int dummy)
00869 {
00870 uint32_t evt = ke_evt_get() & MM_TBTT_EVT_MASK;
00871
00872
00873 struct vif_info_tag *vif =
00874 (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
00875
00876 PROF_HW_TBTT_EVT_SET();
00877
00878
00879
00880 ASSERT_ERR(evt != MM_TBTT_EVT_MASK);
00881
00882
00883 ke_evt_clear(evt);
00884
00885
00886 mm_sta_tbtt(vif);
00887
00888 PROF_HW_TBTT_EVT_CLR();
00889 }
00890 #elif NX_BEACONING
00891 void mm_tbtt_evt(int dummy)
00892 {
00893 uint32_t evt = ke_evt_get() & MM_TBTT_EVT_MASK;
00894
00895 PROF_HW_TBTT_EVT_SET();
00896
00897
00898
00899 ASSERT_ERR(evt != MM_TBTT_EVT_MASK);
00900
00901
00902 ke_evt_clear(evt);
00903
00904
00905 mm_ap_tbtt(evt);
00906
00907 PROF_HW_TBTT_EVT_CLR();
00908 }
00909 #endif
00910
00911 uint8_t mm_sec_machwaddr_wr(uint8_t sta_idx, uint8_t inst_nbr)
00912 {
00913 uint8_t hw_sta_idx;
00914 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
00915 uint32_t enc_cntrl;
00916
00917
00918 hw_sta_idx = MM_SEC_DEFAULT_KEY_COUNT + sta_idx;
00919
00920
00921 nxmac_encr_mac_addr_low_set(sta->mac_addr.array[0] | (((uint32_t)sta->mac_addr.array[1]) << 16));
00922 nxmac_encr_mac_addr_high_set(sta->mac_addr.array[2]);
00923
00924
00925 nxmac_encr_key_0_set(0);
00926 nxmac_encr_key_1_set(0);
00927 nxmac_encr_key_2_set(0);
00928 nxmac_encr_key_3_set(0);
00929
00930
00931
00932 nxmac_encr_cntrl_set(NXMAC_NEW_SEARCH_BIT);
00933 do
00934 {
00935 enc_cntrl = nxmac_encr_cntrl_get();
00936 } while(enc_cntrl & NXMAC_NEW_SEARCH_BIT);
00937
00938 if (!(enc_cntrl & NXMAC_SEARCH_ERROR_BIT))
00939 {
00940 uint8_t hw_sta_idx_prev = nxmac_key_index_ram_getf();
00941
00942 if (hw_sta_idx_prev != hw_sta_idx)
00943 {
00944 nxmac_encr_mac_addr_low_set(0xFFFFFFFF);
00945 nxmac_encr_mac_addr_high_set(0xFFFFFFFF);
00946 KEY_RAM_WR(hw_sta_idx_prev, 0, 0, 0, 0, 0);
00947 nxmac_encr_mac_addr_low_set(sta->mac_addr.array[0] | (((uint32_t)sta->mac_addr.array[1]) << 16));
00948 nxmac_encr_mac_addr_high_set(sta->mac_addr.array[2]);
00949 }
00950 }
00951
00952
00953
00954 KEY_RAM_WR(hw_sta_idx, 0, inst_nbr, 0, 1, 0);
00955
00956 return (hw_sta_idx);
00957 }
00958
00959 uint8_t mm_sec_machwkey_wr(struct mm_key_add_req const *param)
00960 {
00961 uint8_t clen = 1;
00962 uint8_t ctype = MM_SEC_CTYPE_NULL;
00963 uint8_t key_idx_hw;
00964 uint8_t sta_idx = param->sta_idx;
00965 struct mac_sec_key const *key = ¶m->key;
00966 uint8_t vlan_idx = param->inst_nbr;
00967
00968
00969 if (sta_idx == INVALID_STA_IDX)
00970 {
00971 #if NX_MFP
00972
00973 if (param->cipher_suite == MAC_CIPHER_BIP_CMAC_128)
00974 {
00975 key_idx_hw = MM_VIF_TO_MFP_KEY(param->key_idx, param->inst_nbr);
00976 vif_mgmt_add_key(param, key_idx_hw);
00977 return key_idx_hw;
00978 }
00979 #endif
00980
00981
00982 key_idx_hw = MM_VIF_TO_KEY(param->key_idx, param->inst_nbr);
00983
00984
00985 nxmac_encr_mac_addr_low_set(0xFFFFFFFF);
00986 nxmac_encr_mac_addr_high_set(0xFFFFFFFF);
00987
00988 #if (NX_UMAC_PRESENT)
00989
00990 vif_mgmt_add_key(param, key_idx_hw);
00991 #endif
00992 }
00993 else
00994 {
00995 #if (RW_MESH_EN)
00996
00997 struct vif_info_tag *vif = &vif_info_tab[param->inst_nbr];
00998 #endif //(RW_MESH_EN)
00999 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
01000
01001
01002 ASSERT_ERR(sta_idx < STA_MAX);
01003
01004
01005 key_idx_hw = MM_STA_TO_KEY(sta_idx);
01006
01007 #if (RW_MESH_EN)
01008 if (vif->type == VIF_MESH_POINT)
01009 {
01010 vlan_idx = sta->mlink_idx + NX_VIRT_DEV_MAX;
01011
01012 if (!param->pairwise)
01013 {
01014 if (param->cipher_suite == MAC_CIPHER_CCMP)
01015 {
01016
01017 key_idx_hw = MM_MLINK_TO_KEY(param->key_idx + 1, sta->mlink_idx);
01018
01019
01020 nxmac_encr_mac_addr_low_set(0xFFFFFFFF);
01021 nxmac_encr_mac_addr_high_set(0xFFFFFFFF);
01022 }
01023 #if (NX_UMAC_PRESENT)
01024 else
01025 {
01026 key_idx_hw = MM_STA_TO_MESH_MFP_KEY(param->key_idx, sta_idx);
01027
01028 sta_mgmt_add_key(param, key_idx_hw);
01029
01030 return (key_idx_hw);
01031 }
01032 #endif //(NX_UMAC_PRESENT)
01033 }
01034 }
01035
01036 if (param->pairwise)
01037 #endif //(RW_MESH_EN)
01038 {
01039 #if (NX_UMAC_PRESENT)
01040
01041 sta_mgmt_add_key(param, key_idx_hw);
01042 #endif
01043
01044
01045 nxmac_encr_mac_addr_low_set(sta->mac_addr.array[0] | (((uint32_t)sta->mac_addr.array[1]) << 16));
01046 nxmac_encr_mac_addr_high_set(sta->mac_addr.array[2]);
01047 }
01048 }
01049
01050
01051 mm_key_ram_param_get(param->cipher_suite, key, &ctype, &clen);
01052
01053
01054 nxmac_encr_key_0_set(key->array[0]);
01055 nxmac_encr_key_1_set(key->array[1]);
01056 nxmac_encr_key_2_set(key->array[2]);
01057 nxmac_encr_key_3_set(key->array[3]);
01058
01059 #if RW_WAPI_EN
01060 if (ctype == MM_SEC_CTYPE_WPI_SMS4)
01061 {
01062 nxmac_encr_wpi_int_key_0_set(key->array[4]);
01063 nxmac_encr_wpi_int_key_1_set(key->array[5]);
01064 nxmac_encr_wpi_int_key_2_set(key->array[6]);
01065 nxmac_encr_wpi_int_key_3_set(key->array[7]);
01066 }
01067 #endif
01068
01069
01070
01071 KEY_RAM_WR(key_idx_hw, ctype, vlan_idx, param->spp, 0, clen);
01072
01073 return (key_idx_hw);
01074 }
01075
01076 void mm_sec_machwkey_del(uint8_t hw_key_idx)
01077 {
01078
01079 #if NX_MFP
01080 if (hw_key_idx >= MM_SEC_MAX_KEY_NBR)
01081 {
01082 vif_mgmt_del_key(&vif_info_tab[MM_MFP_KEY_TO_VIF(hw_key_idx)],
01083 MM_MFP_KEY_TO_KEYID(hw_key_idx));
01084 return;
01085 }
01086 #endif
01087
01088
01089 if (hw_key_idx >= MM_SEC_DEFAULT_KEY_COUNT)
01090 {
01091
01092 uint8_t sta_idx = MM_KEY_TO_STA(hw_key_idx);
01093 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
01094 struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
01095
01096 #if (NX_UMAC_PRESENT)
01097 sta_mgmt_del_key(sta);
01098 #endif
01099
01100
01101
01102
01103 if (vif->type == VIF_AP)
01104 return;
01105
01106
01107 nxmac_encr_mac_addr_low_set(sta->mac_addr.array[0] | (((uint32_t)sta->mac_addr.array[1]) << 16));
01108 nxmac_encr_mac_addr_high_set(sta->mac_addr.array[2]);
01109 }
01110 else
01111 {
01112
01113 nxmac_encr_mac_addr_low_set(0xFFFFFFFF);
01114 nxmac_encr_mac_addr_high_set(0xFFFFFFFF);
01115
01116 #if (RW_MESH_EN)
01117 if (hw_key_idx < MM_SEC_DEFAULT_VIF_KEY_COUNT)
01118 #endif //(RW_MESH_EN)
01119 {
01120 #if (NX_UMAC_PRESENT)
01121 vif_mgmt_del_key(&vif_info_tab[MM_KEY_TO_VIF(hw_key_idx)],
01122 MM_KEY_TO_KEYID(hw_key_idx));
01123 #endif
01124 }
01125 }
01126
01127
01128 nxmac_encr_key_0_set(0);
01129 nxmac_encr_key_1_set(0);
01130 nxmac_encr_key_2_set(0);
01131 nxmac_encr_key_3_set(0);
01132
01133
01134
01135 KEY_RAM_WR(hw_key_idx, 0, 0, 0, 0, 0);
01136 }
01137
01138 void mm_sec_machwaddr_del(uint8_t sta_idx)
01139 {
01140 uint8_t hw_sta_idx;
01141
01142
01143 hw_sta_idx = MM_SEC_DEFAULT_KEY_COUNT + sta_idx;
01144
01145
01146 nxmac_encr_mac_addr_low_set(0xFFFFFFFF);
01147 nxmac_encr_mac_addr_high_set(0xFFFFFFFF);
01148
01149
01150 nxmac_encr_key_0_set(0);
01151 nxmac_encr_key_1_set(0);
01152 nxmac_encr_key_2_set(0);
01153 nxmac_encr_key_3_set(0);
01154
01155
01156
01157 KEY_RAM_WR(hw_sta_idx, 0, 0, 0, 0, 0);
01158 }
01159
01160 void mm_hw_idle_evt(int dummy)
01161 {
01162
01163 ke_evt_clear(KE_EVT_HW_IDLE_BIT);
01164
01165
01166 ke_state_set(TASK_MM, MM_IDLE);
01167 }
01168
01169 #if NX_MULTI_ROLE
01170 void mm_hw_info_set(struct mac_addr const *mac_addr)
01171 {
01172
01173 nxmac_ap_setf(0);
01174 nxmac_bss_type_setf(1);
01175 nxmac_mac_addr_hi_mask_set(MM_MAC_ADDR_MSK);
01176
01177
01178 nxmac_tsf_lo_set(0);
01179 nxmac_tsf_hi_set(0);
01180
01181
01182 nxmac_mac_addr_low_set(mac_addr->array[0] | (((uint32_t)mac_addr->array[1]) << 16));
01183 nxmac_mac_addr_hi_set(mac_addr->array[2]);
01184
01185
01186 nxmac_mac_cntrl_1_set(nxmac_mac_cntrl_1_get() & ~(NXMAC_DISABLE_ACK_RESP_BIT
01187 | NXMAC_DISABLE_CTS_RESP_BIT | NXMAC_DISABLE_BA_RESP_BIT));
01188
01189
01190 mm_rx_filter_umac_set(MM_RX_FILTER_ACTIVE);
01191
01192
01193 rxl_hwdesc_monitor(false);
01194 }
01195
01196 void mm_hw_ap_info_set(void)
01197 {
01198
01199 nxmac_ap_setf(1);
01200
01201 #if NX_UMAC_PRESENT
01202
01203 mm_rx_filter_umac_set(MM_RX_FILTER_ACTIVE | (NXMAC_ACCEPT_PS_POLL_BIT
01204 | NXMAC_ACCEPT_ALL_BEACON_BIT));
01205 #endif
01206
01207
01208 rxl_hwdesc_monitor(false);
01209
01210
01211 nxmac_gen_int_ack_clear(MM_TBTT_IRQ_MASK);
01212 nxmac_gen_int_enable_set(nxmac_gen_int_enable_get() | MM_TBTT_IRQ_MASK);
01213 }
01214
01215 void mm_hw_ap_info_reset(void)
01216 {
01217
01218 nxmac_ap_setf(0);
01219
01220 #if NX_UMAC_PRESENT
01221
01222 mm_rx_filter_umac_set(MM_RX_FILTER_ACTIVE);
01223 #endif
01224
01225
01226 rxl_hwdesc_monitor(false);
01227
01228
01229 nxmac_gen_int_ack_clear(MM_TBTT_IRQ_MASK);
01230 nxmac_gen_int_enable_set(nxmac_gen_int_enable_get() & ~MM_TBTT_IRQ_MASK);
01231 }
01232 #else
01233 void mm_hw_interface_info_set(uint8_t type, struct mac_addr const *mac_addr)
01234 {
01235
01236 switch (type)
01237 {
01238 case VIF_AP:
01239 nxmac_ap_setf(1);
01240 nxmac_bss_type_setf(1);
01241 nxmac_mac_addr_hi_mask_set(MM_MAC_ADDR_MSK);
01242 nxmac_gen_int_ack_clear(MM_TBTT_IRQ_MASK);
01243 nxmac_gen_int_enable_set(nxmac_gen_int_enable_get() | MM_TBTT_IRQ_MASK);
01244 break;
01245 case VIF_IBSS:
01246 nxmac_ap_setf(0);
01247 nxmac_bss_type_setf(0);
01248 nxmac_mac_addr_hi_mask_set(0);
01249 nxmac_gen_int_enable_set(nxmac_gen_int_enable_get() | MM_TBTT_IRQ_MASK);
01250 break;
01251 case VIF_MONITOR:
01252 case VIF_STA:
01253 nxmac_ap_setf(0);
01254 nxmac_bss_type_setf(1);
01255 nxmac_mac_addr_hi_mask_set(0);
01256 #if NX_POWERSAVE || NX_CONNECTION_MONITOR || NX_UMAC_PRESENT
01257 nxmac_gen_int_ack_clear(MM_TBTT_IRQ_MASK);
01258 nxmac_gen_int_enable_set(nxmac_gen_int_enable_get() | MM_TBTT_IRQ_MASK);
01259 #else
01260 nxmac_gen_int_enable_set(nxmac_gen_int_enable_get() & ~MM_TBTT_IRQ_MASK);
01261 #endif
01262 break;
01263 default:
01264 ASSERT_ERR(0);
01265 break;
01266 }
01267
01268
01269 nxmac_tsf_lo_set(0);
01270 nxmac_tsf_hi_set(0);
01271
01272
01273 nxmac_mac_addr_low_set(mac_addr->array[0] | (((uint32_t)mac_addr->array[1]) << 16));
01274 nxmac_mac_addr_hi_set(mac_addr->array[2]);
01275
01276
01277 nxmac_mac_cntrl_1_set(nxmac_mac_cntrl_1_get() & ~(NXMAC_DISABLE_ACK_RESP_BIT
01278 | NXMAC_DISABLE_CTS_RESP_BIT | NXMAC_DISABLE_BA_RESP_BIT));
01279
01280
01281 mm_rx_filter_umac_set(MM_RX_FILTER_ACTIVE);
01282
01283
01284 rxl_hwdesc_monitor(false);
01285 }
01286 #endif
01287
01288 #if (NX_AMPDU_TX)
01289 bool mm_ba_agmt_tx_exists(uint8_t sta_idx, uint8_t tid)
01290 {
01291 #if (NX_UMAC_PRESENT)
01292 return (sta_mgmt_get_tx_bam_idx(sta_idx, tid) != BAM_INVALID_TASK_IDX);
01293 #else
01294
01295 return (sta_mgmt_get_tx_buff_size(sta_idx, tid));
01296 #endif //(NX_UMAC_PRESENT)
01297 }
01298 #endif //(NX_AMPDU_TX)
01299
01300 #if (NX_REORD || NX_UMAC_PRESENT)
01301 bool mm_ba_agmt_rx_exists(uint8_t sta_idx, uint8_t tid)
01302 {
01303 #if (NX_UMAC_PRESENT)
01304 return (sta_mgmt_get_rx_bam_idx(sta_idx, tid) != BAM_INVALID_TASK_IDX);
01305 #else
01306
01307 return (sta_info_tab[sta_idx].ba_agmts_rx[tid] != NULL);
01308 #endif //(NX_UMAC_PRESENT)
01309 }
01310 #endif //(NX_REORD)
01311
01312 #if NX_BEACONING
01313 int32_t mm_ap_tbtt_move(int32_t offset)
01314 {
01315 uint32_t time_to_next;
01316 uint32_t tbtt_next;
01317 uint32_t beacon_int = nxmac_beacon_int_getf() * TU_DURATION;
01318 uint32_t prog_delay = beacon_int / 4;
01319 uint32_t abs_offset = co_abs(offset);
01320 uint32_t comp_margin = 100;
01321
01322
01323 if (mm_env.tbtt_move_ongoing || (offset == 0))
01324 return 0;
01325
01326 mm_env.tbtt_move_ongoing = true;
01327
01328
01329 if ((offset > 0) && (abs_offset > (beacon_int/2)))
01330 offset = (int32_t)(beacon_int/2);
01331 else if ((offset < 0) && (abs_offset > (beacon_int/2)))
01332 offset = -(int32_t)(beacon_int/2);
01333
01334 GLOBAL_INT_DISABLE();
01335 time_to_next = nxmac_next_tbtt_get() * 32;
01336 tbtt_next = hal_machw_time() + time_to_next;
01337
01338 if (offset > 0)
01339 {
01340
01341
01342
01343
01344 uint32_t time_from_prev = beacon_int - time_to_next;
01345
01346
01347
01348
01349 if (time_to_next < prog_delay)
01350 {
01351 mm_env.tbtt_move_tmr.env = (void *)offset;
01352 mm_timer_set(&mm_env.tbtt_move_tmr, tbtt_next + beacon_int - prog_delay);
01353 }
01354
01355
01356 else if (time_from_prev < (abs_offset + comp_margin))
01357 {
01358 mm_env.tbtt_move_tmr.env = (void *)offset;
01359 mm_timer_set(&mm_env.tbtt_move_tmr, tbtt_next - prog_delay);
01360 }
01361
01362 else
01363 {
01364 mm_ap_tbtt_move_cb((void *)offset);
01365 }
01366 }
01367 else
01368 {
01369
01370
01371
01372
01373
01374 if (time_to_next > (abs_offset + prog_delay))
01375 {
01376 mm_ap_tbtt_move_cb((void *)offset);
01377 }
01378
01379
01380 else
01381 {
01382 mm_env.tbtt_move_tmr.env = (void *)offset;
01383 mm_timer_set(&mm_env.tbtt_move_tmr, tbtt_next + comp_margin);
01384 }
01385 }
01386 GLOBAL_INT_RESTORE();
01387
01388 return offset;
01389 }
01390 #endif
01391
01392 void mm_back_to_host_idle(void)
01393 {
01394
01395 ASSERT_ERR(ke_state_get(TASK_MM) == MM_HOST_BYPASSED);
01396
01397
01398 if (mm_env.host_idle == 0)
01399 mm_active();
01400 else
01401 ke_state_set(TASK_MM, MM_IDLE);
01402 }
01403
01404 void mm_force_idle_req(void)
01405 {
01406
01407
01408
01409 ASSERT_ERR(ke_state_get(TASK_MM) != MM_NO_IDLE);
01410
01411
01412 GLOBAL_INT_DISABLE();
01413
01414
01415 hal_machw_reset();
01416
01417
01418 rxl_reset();
01419
01420
01421 txl_reset();
01422
01423
01424 ke_state_set(TASK_MM, MM_HOST_BYPASSED);
01425 mm_env.prev_mm_state = MM_IDLE;
01426 mm_env.prev_hw_state = HW_IDLE;
01427
01428
01429 GLOBAL_INT_RESTORE();
01430 }
01431
01432 void mm_no_idle_start(void)
01433 {
01434 ASSERT_ERR((ke_state_get(TASK_MM) != MM_HOST_BYPASSED) &&
01435 (ke_state_get(TASK_MM) != MM_IDLE));
01436
01437 if (ke_state_get(TASK_MM) == MM_GOING_TO_IDLE)
01438 {
01439 nxmac_next_state_setf(HW_ACTIVE);
01440 GLOBAL_INT_DISABLE();
01441 ke_evt_clear(KE_EVT_HW_IDLE_BIT);
01442 if (nxmac_status_idle_interrupt_getf())
01443 {
01444 nxmac_gen_int_ack_clear(NXMAC_IDLE_INTERRUPT_BIT);
01445 }
01446 GLOBAL_INT_RESTORE();
01447 }
01448 ke_state_set(TASK_MM, MM_NO_IDLE);
01449 }
01450
01451 void mm_no_idle_stop(void)
01452 {
01453 if (ke_state_get(TASK_MM) == MM_NO_IDLE)
01454 ke_state_set(TASK_MM, MM_ACTIVE);
01455 }
01456
01457 uint8_t mm_sta_add(struct mm_sta_add_req const *param, uint8_t *sta_idx,
01458 uint8_t *hw_sta_idx)
01459 {
01460 uint8_t status;
01461
01462
01463 status = sta_mgmt_register(param, sta_idx);
01464
01465
01466 if (status == CO_OK)
01467 {
01468 struct vif_info_tag *vif = &vif_info_tab[param->inst_nbr];
01469 struct sta_info_tag *sta = &sta_info_tab[*sta_idx];
01470
01471
01472 *hw_sta_idx = mm_sec_machwaddr_wr(*sta_idx, param->inst_nbr);
01473 if (sta->linked_sta)
01474 {
01475 mm_sec_machwaddr_wr(sta->linked_sta->staid, param->inst_nbr);
01476 }
01477
01478
01479 #if NX_TDLS
01480 if ((vif->type == VIF_STA) && (!param->tdls_sta))
01481 #else
01482 if (vif->type == VIF_STA)
01483 #endif
01484 {
01485
01486 vif->u.sta.ap_id = *sta_idx;
01487 vif->u.sta.bssid_index = param->bssid_index;
01488 vif->u.sta.max_bssid_ind = param->max_bssid_ind;
01489 }
01490 #if (RW_UMESH_EN)
01491 else if (vif->type == VIF_MESH_POINT)
01492 {
01493
01494 mesh_add_sta_cfm(param->inst_nbr, *sta_idx);
01495 }
01496 #endif //(RW_UMESH_EN)
01497 }
01498
01499 return (status);
01500 }
01501
01502 void mm_sta_del(uint8_t sta_idx)
01503 {
01504 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
01505 struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
01506
01507
01508 if ((vif->type == VIF_STA)
01509 #if NX_TDLS
01510 && !sta->is_tdls
01511 #endif
01512 )
01513 {
01514
01515 vif->u.sta.ap_id = INVALID_STA_IDX;
01516 }
01517 #if (NX_UMAC_PRESENT || NX_P2P_GO)
01518 else
01519 {
01520 #if (RW_UMESH_EN)
01521 if (vif->type == VIF_MESH_POINT)
01522 {
01523
01524 mesh_del_sta_cfm(sta->mlink_idx);
01525 }
01526 #endif //(RW_UMESH_EN)
01527
01528
01529 if (sta->ps_state == PS_MODE_ON)
01530 {
01531
01532 vif->u.ap.ps_sta_cnt--;
01533
01534 #if (NX_UMAC_PRESENT)
01535 if (!vif->u.ap.ps_sta_cnt)
01536 {
01537 PROF_PS_BCMC_STATE_SET();
01538 PROF_PS_STATE_VAL_SET(PS_MODE_OFF);
01539 mm_ps_change_ind(VIF_TO_BCMC_IDX(vif->index), PS_MODE_OFF);
01540 #if NX_BEACONING
01541 apm_tx_int_ps_clear(vif, VIF_TO_BCMC_IDX(vif->index));
01542 #endif // NX_BEACONING
01543 PROF_PS_BCMC_STATE_CLR();
01544 }
01545 #endif //(NX_UMAC_PRESENT)
01546 }
01547 }
01548 #endif //(NX_UMAC_PRESENT || NX_P2P_GO)
01549
01550
01551
01552 if (vif->type != VIF_AP)
01553 {
01554 mm_sec_machwaddr_del(sta_idx);
01555 if (sta->linked_sta)
01556 {
01557 mm_sec_machwaddr_del(sta->linked_sta->staid);
01558 }
01559 }
01560
01561
01562 sta_mgmt_unregister(sta_idx);
01563 }
01564
01565 #if (NX_CONNECTION_MONITOR)
01566 void mm_send_connection_loss_ind(struct vif_info_tag *vif)
01567 {
01568
01569 struct mm_connection_loss_ind *ind =
01570 KE_MSG_ALLOC(MM_CONNECTION_LOSS_IND, TASK_IND, TASK_MM, mm_connection_loss_ind);
01571
01572
01573 ind->inst_nbr = vif->index;
01574
01575
01576 ke_msg_send(ind);
01577 }
01578 #endif //(NX_CONNECTION_MONITOR)
01579
01580 void mm_check_rssi(struct vif_info_tag *vif, int8_t rssi)
01581 {
01582 int8_t rssi_old = vif->u.sta.rssi;
01583 int8_t rssi_thold = vif->u.sta.rssi_thold;
01584 int8_t rssi_hyst = vif->u.sta.rssi_hyst;
01585 bool rssi_status = vif->u.sta.rssi_status;
01586
01587
01588 vif->u.sta.rssi = rssi;
01589
01590
01591 if (rssi_thold == 0)
01592 return;
01593
01594
01595 if ((rssi_status == 0) && (rssi < rssi_old) && (rssi < (rssi_thold - rssi_hyst)))
01596 {
01597 rssi_status = 1;
01598 }
01599 else if ((rssi_status == 1) && (rssi > rssi_old) && (rssi > (rssi_thold + rssi_hyst)))
01600 {
01601 rssi_status = 0;
01602 }
01603
01604 if (rssi_status != vif->u.sta.rssi_status)
01605 {
01606
01607 struct mm_rssi_status_ind *ind =
01608 KE_MSG_ALLOC(MM_RSSI_STATUS_IND, TASK_API, TASK_MM, mm_rssi_status_ind);
01609
01610
01611 ind->vif_index = vif->index;
01612 ind->rssi_status = rssi_status;
01613 ind->rssi = rssi;
01614
01615
01616 ke_msg_send(ind);
01617 }
01618
01619
01620 vif->u.sta.rssi_status = rssi_status;
01621 }
01622
01623 #if NX_UMAC_PRESENT
01624 void mm_send_pktloss_ind(struct vif_info_tag *vif, uint8_t sta_idx, uint32_t num_pkts)
01625 {
01626
01627 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
01628 struct mm_pktloss_ind *ind =
01629 KE_MSG_ALLOC(MM_PKTLOSS_IND, TASK_API, TASK_MM, mm_pktloss_ind);
01630
01631
01632 ind->vif_index = vif->index;
01633 MAC_ADDR_CPY(&ind->mac_addr, &sta->mac_addr);
01634 ind->num_packets = num_pkts;
01635
01636
01637 ke_msg_send(ind);
01638 }
01639
01640 void mm_send_csa_traffic_ind(uint8_t vif_index, bool enable)
01641 {
01642 struct mm_csa_traffic_ind *ind = KE_MSG_ALLOC(MM_CSA_TRAFFIC_IND, TASK_API, TASK_MM,
01643 mm_csa_traffic_ind);
01644 ind->vif_index = vif_index;
01645 ind->enable = enable;
01646 ke_msg_send(ind);
01647 }
01648 #endif
01649
01650 #if (NX_ANT_DIV)
01651 void mm_ant_div_init(bool enable)
01652 {
01653
01654 mm_env.ant_div.enable = enable;
01655
01656 mm_env.ant_div.sw_enable = enable;
01657
01658 mm_env.ant_div.nvif_active = 0;
01659
01660 mm_ant_div_reset_rssi(0);
01661 mm_ant_div_reset_rssi(1);
01662 }
01663
01664 void mm_ant_div_switch_and_stop(void)
01665 {
01666
01667
01668 if (mm_env.ant_div.enable && (mm_env.ant_div.nvif_active == 0))
01669 {
01670
01671 mm_ant_div_switch_antenna();
01672 }
01673
01674 mm_env.ant_div.sw_enable = 0;
01675 }
01676
01677 void mm_ant_div_update(void)
01678 {
01679
01680 if (!mm_env.ant_div.enable || (mm_env.ant_div.nvif_active > 1))
01681 {
01682 mm_env.ant_div.sw_enable = 0;
01683 if (phy_get_nrx() == 0)
01684 {
01685
01686 mm_ant_div_reset_rssi(0);
01687 mm_ant_div_reset_rssi(1);
01688
01689 mm_env.ant_div.update_cnt = 0;
01690
01691 mm_env.ant_div.init_rssi_upd_req = 1;
01692 }
01693 }
01694 else
01695 {
01696 mm_env.ant_div.sw_enable = 1;
01697 }
01698 }
01699
01700 void mm_ant_div_restore(bool active)
01701 {
01702
01703 if (active)
01704 {
01705 mm_env.ant_div.nvif_active += 1;
01706 }
01707 else
01708 {
01709 mm_env.ant_div.nvif_active -= 1;
01710 }
01711
01712 mm_ant_div_update();
01713 }
01714
01715 void mm_ant_div_switch_antenna(void)
01716 {
01717
01718 if (!mm_env.ant_div.sw_enable)
01719 {
01720 return;
01721 }
01722 dbg(D_INF D_MM "Antenna diversity: switch antenna %d --> %d\n",
01723 mm_env.ant_div.cur_ant, !mm_env.ant_div.cur_ant);
01724
01725 mm_env.ant_div.cur_ant = phy_switch_antenna_paths();
01726 if (phy_get_nrx() == 0)
01727 {
01728
01729 mm_env.ant_div.update_cnt = 0;
01730
01731 mm_env.ant_div.init_rssi_upd_req = 1;
01732 }
01733 }
01734
01735 void mm_ant_div_reset_rssi(uint8_t ant)
01736 {
01737
01738 mm_env.ant_div.rssi[ant] = ANT_DIV_RSSI_RESET;
01739
01740 mm_env.ant_div.init_rssi[ant] = ANT_DIV_RSSI_RESET;
01741 }
01742
01743 void mm_ant_div_update_rssi(int8_t *rx_rssi)
01744 {
01745 ASSERT_ERR(rx_rssi != NULL);
01746
01747 struct antenna_diversity *ant_div = &mm_env.ant_div;
01748
01749 if (phy_get_nrx() == 0)
01750 {
01751
01752 ant_div->rssi[ant_div->cur_ant] = rx_rssi[0];
01753
01754 if (ant_div->init_rssi_upd_req)
01755 {
01756 ant_div->init_rssi[ant_div->cur_ant] = rx_rssi[0];
01757 ant_div->init_rssi_upd_req = 0;
01758 }
01759 }
01760 else
01761 {
01762
01763 ant_div->rssi[ant_div->cur_ant] = rx_rssi[0];
01764 ant_div->rssi[!ant_div->cur_ant] = rx_rssi[1];
01765 }
01766 }
01767
01768 void mm_ant_div_check(uint8_t beacon_loss_cnt)
01769 {
01770
01771 if (!mm_env.ant_div.sw_enable)
01772 {
01773 return;
01774 }
01775
01776 struct antenna_diversity *ant_div = &mm_env.ant_div;
01777
01778 if (phy_get_nrx() == 0)
01779 {
01780
01781 bool switch_antenna = 0;
01782
01783 uint8_t gr_dist_cur = 0;
01784
01785 uint8_t gr_dist_other = 0;
01786
01787 int8_t cur_rssi = ant_div->rssi[ant_div->cur_ant];
01788
01789 int8_t cur_init_rssi = ant_div->init_rssi[ant_div->cur_ant];
01790
01791 int8_t other_rssi = ant_div->rssi[!ant_div->cur_ant];
01792
01793
01794 ant_div->update_cnt++;
01795
01796
01797 gr_dist_cur = mm_get_golden_range_distance(cur_rssi);
01798
01799 gr_dist_other = mm_get_golden_range_distance(other_rssi);
01800
01801 if (beacon_loss_cnt > ANT_DIV_BEACON_LOSS_THD)
01802 {
01803
01804 mm_ant_div_reset_rssi(ant_div->cur_ant);
01805
01806 switch_antenna = 1;
01807 }
01808
01809
01810 else if (gr_dist_other < gr_dist_cur)
01811 {
01812 switch_antenna = 1;
01813 }
01814
01815
01816 else if ((cur_rssi < ANT_DIV_RSSI_GOLDEN_MIN) &&
01817 (cur_rssi < (cur_init_rssi - ANT_DIV_RSSI_STEP_CHANGE)))
01818 {
01819 switch_antenna = 1;
01820 }
01821 else if ((cur_rssi > ANT_DIV_RSSI_GOLDEN_MAX) &&
01822 (cur_rssi > (cur_init_rssi + ANT_DIV_RSSI_STEP_CHANGE)))
01823 {
01824 switch_antenna = 1;
01825 }
01826
01827
01828 else if (((cur_rssi < ANT_DIV_RSSI_GOLDEN_MIN) ||
01829 (cur_rssi > ANT_DIV_RSSI_GOLDEN_MAX)) &&
01830 (ant_div->update_cnt > ANT_DIV_UPDATE_CNT_THD))
01831 {
01832
01833 switch_antenna = 1;
01834 }
01835
01836 if (switch_antenna)
01837 {
01838 dbg(D_INF D_MM "Antenna diversity: "
01839 "Ant%d=%d(%d) Ant%d=%d(%d) / Gold_range=[%d:%d] / Upd_cnt=%d\n",
01840 ant_div->cur_ant, cur_rssi, cur_init_rssi,
01841 !ant_div->cur_ant, other_rssi, ant_div->init_rssi[!ant_div->cur_ant],
01842 ANT_DIV_RSSI_GOLDEN_MIN, ANT_DIV_RSSI_GOLDEN_MAX, mm_env.ant_div.update_cnt);
01843
01844 ke_msg_send_basic(MM_SWITCH_ANTENNA_REQ, TASK_MM, TASK_NONE);
01845 }
01846 }
01847
01848 else
01849 {
01850
01851 int8_t rssi_0 = ant_div->rssi[ant_div->cur_ant];
01852 int8_t rssi_1 = ant_div->rssi[!ant_div->cur_ant];
01853 if (rssi_1 > (rssi_0 + ANT_DIV_RSSI_THD))
01854 {
01855 dbg(D_INF D_MM "Antenna diversity: Ant%d=%d Ant%d=%d\n",
01856 ant_div->cur_ant, rssi_0, !ant_div->cur_ant, rssi_1);
01857
01858 mm_ant_div_switch_antenna();
01859 }
01860 }
01861 }
01862 #endif //(NX_ANT_DIV)
01863