- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/lmac/src/tx/txl/txl_frame.c

Go to the documentation of this file.

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