- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/lmac/src/mm/mm_bcn.c

Go to the documentation of this file.

    00001
    00020 /*
    00021  * INCLUDE FILES
    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  * GLOBAL VARIABLES
    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     // No beacon transmission ongoing, proceed immediately to the update
    00078     if (param->aid == 0)
    00079     {
    00080         // Update BC/MC status bit
    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             // Compute the byte and bit numbers for this AID
    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             // Check if we have to set or reset a bit
    00101             if (param->tx_avail)
    00102             {
    00103                 // Check if the bit is already set
    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                 // Set the bit in the bitmap
    00111                 co_write8p(tim_bmp + n, val | mask);
    00112
    00113                 // One more bit is set
    00114                 vif->u.ap.tim_bitmap_set++;
    00115
    00116                 // Check if Lower limit of the partial virtual bitmap needs to be updated
    00117                 if (n < vif->u.ap.tim_n1)
    00118                 {
    00119                     // Lower limit shall be an even number
    00120                     vif->u.ap.tim_n1 = n & 0xFE;
    00121
    00122                     // Update the start pointer in the TBD
    00123                     pbd_bmp->datastartptr = tim_bmp + vif->u.ap.tim_n1;
    00124                 }
    00125
    00126                 // Check if Upper limit of the partial virtual bitmap needs to be updated
    00127                 if (n > vif->u.ap.tim_n2)
    00128                 {
    00129                     // Update Upper limit
    00130                     vif->u.ap.tim_n2 = n;
    00131
    00132                     // Update the end pointer in the TBD
    00133                     pbd_bmp->dataendptr = tim_bmp + vif->u.ap.tim_n2;
    00134                 }
    00135
    00136                 // Update the TIM length
    00137                 vif->u.ap.tim_len = vif->u.ap.tim_n2 - vif->u.ap.tim_n1 + 6;
    00138
    00139                 // Update the TIM PBD
    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                 // Check if the bit is already reset
    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                 // Reset the bit in the bitmap
    00155                 co_write8p(tim_bmp + n, val & ~mask);
    00156
    00157                 // One more bit is reset
    00158                 vif->u.ap.tim_bitmap_set--;
    00159
    00160                 // Check if the bitmap has still some bits set
    00161                 if (vif->u.ap.tim_bitmap_set)
    00162                 {
    00163                     // Check if we need to update the Lower Limit
    00164                     if ((n & 0xFE) == vif->u.ap.tim_n1)
    00165                     {
    00166                         // Search for the new Lower Limit
    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                         // Lower Limit shall be an even number
    00174                         vif->u.ap.tim_n1 &= 0xFE;
    00175
    00176                         // Update the start pointer in the TBD
    00177                         pbd_bmp->datastartptr = tim_bmp + vif->u.ap.tim_n1;
    00178                     }
    00179
    00180                     // Check if we need to update the Upper Limit
    00181                     if (n == vif->u.ap.tim_n2)
    00182                     {
    00183                         // Search for the new Upper Limit
    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                         // Update the end pointer in the TBD
    00191                         pbd_bmp->dataendptr = tim_bmp + vif->u.ap.tim_n2;
    00192                     }
    00193
    00194                     // Update the TIM length
    00195                     vif->u.ap.tim_len = vif->u.ap.tim_n2 - vif->u.ap.tim_n1 + 6;
    00196
    00197                     // Update the TIM PBD
    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                     // Update the TIM
    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                     // Update the TIM PBD
    00210                     pbd_tim->dataendptr = tim_ie + MAC_TIM_BMP_OFT;
    00211                     pbd_tim->next = CPU2HW(&txl_bcn_end_desc[param->inst_nbr]);
    00212                     // Update the end pointer in the TBD
    00213                     pbd_bmp->dataendptr = tim_bmp + vif->u.ap.tim_n2;
    00214                 }
    00215             }
    00216         } while(0);
    00217     }
    00218
    00219     // Confirm the TIM update to the host
    00220     ke_msg_send_basic(MM_TIM_UPDATE_CFM, ke_param2msg(param)->src_id, TASK_MM);
    00221
    00222     // Free the TIM parameters
    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     // Store the current beacon length for later update of the THD
    00250     vif->u.ap.bcn_len = bcn_len;
    00251
    00252     #if (NX_UMAC_PRESENT)
    00253     // Verify the protection and bandwidth status
    00254     me_beacon_check(vif->index, param->bcn_len, thd->datastartptr);
    00255     #endif
    00256
    00257     // Fill-up the TX header descriptor
    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     // Get band
    00264     band = vif_mgmt_get_band(vif);
    00265
    00266     #if (NX_P2P_GO)
    00267     // If the interface is a P2P interface we cannot use default 2.4GhHz policy table (11b rate forbidden)
    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     // Set TX power
    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     // The beacon is now configured for this VIF
    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     // reset value
    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     // Allocate the indication structure
    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     // Send the message
    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     // Update the THD length
    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         // Length of NOA Information Element
    00379         uint8_t noa_len = p2p_go_bcn_get_noa_len(vif->p2p_index);
    00380
    00381         if (noa_len)
    00382         {
    00383             // Get TX payload buffer descriptor
    00384             struct tx_pbd *noa_pbd = &txl_p2p_noa_desc[vif->index];
    00385
    00386             // Add length of P2P NOA Information Element if present
    00387             thd->frmlen += noa_len;
    00388
    00389             // Update NOA Payload descriptor Data End pointer
    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         // Update dynamic fields (Number of Peerings, ...)
    00401         mesh_update_beacon(vif);
    00402
    00403         // Check if IEs have to be added at the end of the beacon
    00404         if (mesh_ies_len)
    00405         {
    00406             // Get TX payload buffer descriptor
    00407             struct tx_pbd *add_ies_pbd = &txl_mesh_add_ies_desc[vif->mvif_idx];
    00408
    00409             // Update frame length
    00410             thd->frmlen += mesh_ies_len;
    00411
    00412             // Update NOA Payload descriptor Data End pointer
    00413             add_ies_pbd->dataendptr = add_ies_pbd->datastartptr + mesh_ies_len - 1;
    00414
    00415             // Add the additional element at beacon end
    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     // Update the sequence number in the beacon
    00426     co_write16(HW2CPU(thd->datastartptr + MAC_HEAD_CTRL_OFT), txl_get_seq_ctrl());
    00427     // Update the DTIM count and period
    00428     co_write8p(tim_ie + MAC_TIM_CNT_OFT, vif->u.ap.dtim_count);
    00429
    00430     // Update DTIM count for next beacon
    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         // TIM IE may have been updated since previous beacon, so need to reset
    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     // Update CSA counter in the beacon
    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         // keep csa_count to 1 until beacon is successfully transmistted
    00469         if (vif->u.ap.csa_count == 0)
    00470             vif->u.ap.csa_count = 1;
    00471         #endif
    00472     }
    00473
    00474     // update Tx power in policy table
    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     // Confirm the beacon update to the host
    00497     ke_msg_send_basic(MM_BCN_CHANGE_CFM, msg->src_id, TASK_MM);
    00498
    00499     // Update the frame descriptor
    00500     mm_bcn_desc_prep(vif, mm_bcn_env.param);
    00501
    00502     // Init CSA counter
    00503     mm_bcn_csa_init(vif, mm_bcn_env.param);
    00504
    00505     // Update status
    00506     mm_bcn_env.update_ongoing = false;
    00507     // Check if the beacons need to be sent immediately
    00508     if (mm_bcn_env.tx_pending)
    00509         mm_bcn_transmit();
    00510
    00511     // No more beacon data in memory
    00512     mm_bcn_env.param = NULL;
    00513
    00514     // Free the beacon parameters
    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     // Update status
    00534     mm_bcn_env.update_pending = false;
    00535     mm_bcn_env.update_ongoing = true;
    00536
    00537     #if (NX_UMAC_PRESENT && RW_MESH_EN)
    00538     // If the beacon is provided for a Mesh Point VIF, it does not come from the host
    00539     // memory. It has been filled by UMAC's Mesh Module and hence does not require
    00540     // any DMA transfer.
    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         // Fill in the DMA descriptor
    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         // Program the download
    00559         hal_dma_push(dma, DMA_DL);
    00560         #else
    00561
    00562         // Cannot use DMA for CPU mem to Shared memory transfer
    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     // Attached env is the VIF Entry on which beacon has been sent, get VIF index
    00585     struct vif_info_tag *vif = (struct vif_info_tag *)env;
    00586     #endif //(NX_P2P_GO) || (NX_UMAC_PRESENT)
    00587
    00588     // Sanity check - We shall be still waiting for at least one confirmation
    00589     ASSERT_ERR(mm_bcn_env.tx_cfm);
    00590
    00591     // One confirmation less to be expected
    00592     mm_bcn_env.tx_cfm--;
    00593
    00594     // Check if all confirmations have been received
    00595     if (mm_bcn_env.tx_cfm == 0)
    00596     {
    00597         // The beacon(s) were transmitted, ask the MM to allow the IDLE state again
    00598         mm_no_idle_stop();
    00599
    00600         // Check if we need to update a beacon
    00601         if (mm_bcn_env.update_pending)
    00602             mm_bcn_update(mm_bcn_env.param);
    00603
    00604         // Check if we need to update the TIM
    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         // Check if we have a pending NOA update
    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     // Get TX payload buffer descriptor
    00645     struct tx_pbd *pbd = &txl_p2p_noa_desc[vif_index];
    00646     // Get payload address
    00647     uint32_t p2p_noa_ie = CPU2HW(&txl_p2p_noa_ie_pool[vif_index][0]);
    00648
    00649     // Prepare the descriptor
    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         // Get TX payload buffer descriptor
    00669         struct tx_pbd *pbd = &txl_mesh_add_ies_desc[i];
    00670         // Get payload address
    00671         uint32_t mesh_add_ie = CPU2HW(&txl_mesh_add_ies[i].buf[0]);
    00672
    00673         // Prepare the descriptor
    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     // Initialize the DTIM count
    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     // First part of the TIM
    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); // Will be updated when receiving the beacon from host
    00715     co_write8p(tim_ie + MAC_TIM_BMPC_OFT, 0);
    00716     co_write8p(tim_ie + MAC_TIM_BMP_OFT, 0);
    00717
    00718     // Reset the TIM virtual bitmap
    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     // Initialize post-TIM TX PBD
    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  * PUBLIC FUNCTION DEFINITIONS
    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     // Reset the complete environment
    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         // Initialize NOA Beacon payload
    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     // Initialize the frame descriptor
    00775     txl_frame_init_desc(frame, buffer, hwdesc, bufctrl);
    00776
    00777     // Initialize the TIM buffer
    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     // Initialize some static fields of the THD
    00788     thd = &frame->txdesc.lmac.hw_desc->thd;
    00789     thd->phyctrlinfo = 0;
    00790     thd->macctrlinfo2 = 0;
    00791     thd->first_pbd_ptr = 0;
    00792
    00793     // Initialize callback function
    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     // Save the message for later handling
    00801     mm_bcn_env.param = param;
    00802
    00803     // Check if the beacon transmission is already ongoing
    00804     if (mm_bcn_env.tx_cfm)
    00805     {
    00806         mm_bcn_env.update_pending = true;
    00807     }
    00808     else
    00809     {
    00810         // No beacon transmission ongoing, proceed immediately to the update
    00811         mm_bcn_update(param);
    00812     }
    00813 }
    00814
    00815 void mm_tim_update(struct mm_tim_update_req const *param)
    00816 {
    00817     // Check if the beacon transmission is already ongoing
    00818     if (mm_bcn_env.tx_cfm)
    00819     {
    00820         // Push the request into the list for later handling
    00821         co_list_push_back(&mm_bcn_env.tim_list, &ke_param2msg(param)->hdr);
    00822     }
    00823     else
    00824     {
    00825         // Proceed immediately to the request
    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     // Sanity check - All previously chained beacons shall be transmitted
    00839     ASSERT_ERR(!mm_bcn_env.tx_cfm);
    00840
    00841     // Check if a beacon update is ongoing
    00842     if (mm_bcn_env.update_ongoing)
    00843     {
    00844         mm_bcn_env.tx_pending = true;
    00845         return;
    00846     }
    00847
    00848     // No more beacon transmission pending
    00849     mm_bcn_env.tx_pending = false;
    00850
    00851     next_tbtt = nxmac_next_tbtt_get() << 5;
    00852
    00853     // Go through the VIFs and send the beacons of the AP ones
    00854     while (vif != NULL)
    00855     {
    00856         // Check if VIF is an AP one
    00857         if (((vif->type == VIF_AP)
    00858             #if (RW_MESH_EN)
    00859                 || (vif->type == VIF_MESH_POINT)
    00860             #endif //(RW_MESH_EN)
    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 //(NX_UMAC_PRESENT)
    00865                   )
    00866         {
    00867             // Update the frame
    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                 // Set VIF and STA indexes
    00910                 vif->u.ap.bcn_desc.txdesc.host.vif_idx = vif->index;
    00911                 vif->u.ap.bcn_desc.txdesc.host.staid   = 0xFF;
    00912
    00913                 // Push the TX frame descriptor
    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                     // We have programmed one beacon for transmission, so ask the MM to
    00926                     // disallow the IDLE state
    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         // Go to next VIF
    00952         vif = vif_mgmt_next(vif);
    00953     }
    00954
    00955     #if !NX_UMAC_PRESENT
    00956     // Once all beacons have been programmed, go on with the BC/MC traffic
    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     // Check if the beacon transmission is already ongoing
    00966     if (mm_bcn_env.tx_cfm)
    00967     {
    00968         // Save the message for later handling
    00969         mm_bcn_env.p2p_noa_req[vif_index] = operation;
    00970     }
    00971     else
    00972     {
    00973         // Get VIF Info entry
    00974         struct vif_info_tag *vif = &vif_info_tab[vif_index];
    00975
    00976         // React accordingly with the operation code
    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                 // Let the P2P module fulfill the payload part
    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         // No P2P NOA update is pending
    01002         mm_bcn_env.p2p_noa_req[vif_index] = P2P_BCN_UPD_OP_NONE;
    01003
    01004         // Inform the P2P module about operation completion
    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