- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/umac/src/bam/bam.c

Go to the documentation of this file.

    00001
    00013 /*
    00014  * INCLUDE FILES
    00015  ****************************************************************************************
    00016  */
    00017
    00018 #include "bam.h"
    00019 #include "bam_task.h"
    00020 #include "mac_frame.h"
    00021 #include "me_mgmtframe.h"
    00022 #include "mm_task.h"
    00023 #include "ke_timer.h"
    00024 #include "sta_mgmt.h"
    00025 #include "vif_mgmt.h"
    00026 #include "txu_cntrl.h"
    00027 #include "txl_cfm.h"
    00028 #include "ps.h"
    00029 #if NX_MFP
    00030 #include "mfp.h"
    00031 #endif
    00032 #include "tpc.h"
    00038 /*
    00039  * GLOBAL VARIABLES
    00040  ****************************************************************************************
    00041  */
    00043 static struct bam_baw bam_baws[NX_MAX_BA_TX];
    00044
    00046 struct bam_env_tag bam_env[BAM_IDX_MAX];
    00047
    00048 /*
    00049  * FUNCTION DEFINITIONS
    00050  ****************************************************************************************
    00051  */
    00052 #if NX_AMPDU_TX
    00053 #ifdef CFG_RWTL
    00055 uint16_t tl_tudiff;
    00056 #endif
    00057
    00066 static uint16_t bam_time_get(void)
    00067 {
    00068     // Get the current system time and convert it in TUs
    00069     return((hal_machw_time() >> 10) & 0xFFFF);
    00070 }
    00071
    00082 static bool bam_time_cmp(uint16_t time1, uint16_t time2)
    00083 {
    00084     uint16_t diff = time1 - time2;
    00085
    00086     #ifdef CFG_RWTL
    00088     tl_tudiff = diff;
    00089     #endif
    00090
    00091     return (((int16_t)diff) < 0);
    00092 }
    00093
    00103 static bool bam_time_past(uint32_t time)
    00104 {
    00105     return (bam_time_cmp(time, bam_time_get()));
    00106 }
    00107
    00108
    00120 static unsigned int bam_baw_index_compute(struct bam_baw *baw, unsigned int offset)
    00121 {
    00122     return ((baw->fsn_idx + offset) % baw->buf_size);
    00123 }
    00124
    00136 static unsigned int bam_baw_index_compute_opt(struct bam_baw *baw, unsigned int offset)
    00137 {
    00138     return ((baw->fsn_idx + offset) & baw->mask);
    00139 }
    00140
    00153 static int8_t bam_move_baw(struct bam_baw *baw)
    00154 {
    00155     int8_t credits = 0;
    00156
    00157     while (baw->states[baw->fsn_idx] == BAW_CONFIRMED) {
    00158         baw->states[baw->fsn_idx] = BAW_FREE;
    00159         baw->fsn = (baw->fsn + 1) & ((1 << 12) - 1);
    00160         baw->fsn_idx = baw->idx_compute(baw, 1);
    00161         credits++;
    00162     }
    00163
    00164     return(credits);
    00165 }
    00166
    00176 static void bam_set_baw_state(struct bam_baw *baw, uint16_t sn, uint8_t state)
    00177 {
    00178     uint16_t baw_offset;
    00179     int index;
    00180
    00181     baw_offset = ((uint16_t)(sn - baw->fsn)) & ((1 << 12) - 1);
    00182
    00183     ASSERT_ERR(baw_offset < baw->buf_size);
    00184
    00185     index = baw->idx_compute(baw, baw_offset);
    00186
    00187     baw->states[index] = state;
    00188 }
    00189
    00204 static int8_t bam_check_tx_baw(struct txdesc *txdesc, uint8_t bam_idx,
    00205                                bool success)
    00206 {
    00207     struct bam_baw *baw = bam_env[bam_idx].baw;
    00208     struct tx_cfm_tag *cfm = txl_cfm_tag_get(txdesc);
    00209     struct hostdesc *host = &txdesc->host;
    00210
    00211     do
    00212     {
    00213         // First check if the MPDU was part of an A-MPDU
    00214         if ((!(txdesc->umac.flags & AMPDU_BIT))
    00215                 #if NX_AMSDU_TX
    00216                 && (!is_mpdu_split(txdesc))
    00217                 #endif
    00218            )
    00219             break;
    00220
    00221         // Then check if the MPDU was successful or not
    00222         if (!success && !bam_time_past(host->timestamp))
    00223         {
    00224             // Update the confirmation descriptor
    00225             cfm->status |= TX_STATUS_RETRY_REQUIRED;
    00226             #if !NX_FULLY_HOSTED
    00227             cfm->pn[0] = host->pn[0];
    00228             cfm->pn[1] = host->pn[1];
    00229             cfm->pn[2] = host->pn[2];
    00230             cfm->pn[3] = host->pn[3];
    00231             cfm->sn = host->sn;
    00232             cfm->timestamp = host->timestamp;
    00233             #endif
    00234             return 0;
    00235         }
    00236     } while (0);
    00237
    00238     // Update the state in the BAW
    00239     bam_set_baw_state(baw, host->sn, BAW_CONFIRMED);
    00240
    00241     // Move the transmission window
    00242     return (bam_move_baw(baw));
    00243 }
    00244
    00258 static uint8_t bam_create_ba_agg(uint8_t sta_idx, uint8_t tid, uint16_t ssn)
    00259 {
    00260     uint8_t bam_idx = bam_alloc_new_task(true);
    00261
    00262     if (bam_idx == BAM_INVALID_TASK_IDX)
    00263         return  CO_FULL;
    00264
    00265     TRACE_LMAC(BA, "{BAM-%d} Start TX agreement with {STA-%d}: tid=%d ssn=%d",
    00266                bam_idx, sta_idx, tid, ssn);
    00267
    00268     // Store the useful information in the environment
    00269     bam_env[bam_idx].sta_idx          = sta_idx;
    00270     bam_env[bam_idx].tid              = tid;
    00271     bam_env[bam_idx].dialog_token     = co_rand_byte();
    00272     bam_env[bam_idx].ba_timeout       = BAM_INACTIVITY_TO_DURATION;
    00273     bam_env[bam_idx].ba_policy        = 1;
    00274     bam_env[bam_idx].dev_type         = BA_ORIGINATOR;
    00275     bam_env[bam_idx].buffer_size      = nx_txdesc_cnt[mac_tid2ac[tid]];
    00276     bam_env[bam_idx].ssn              = ssn;
    00277     bam_env[bam_idx].pkt_cnt          = 0;
    00278
    00279     // Set the BAM Task Index and device type in the lmac_sta_info_tag
    00280     sta_info_tab[sta_idx].ba_info[tid].bam_idx_tx = bam_idx;
    00281
    00282     // Send MAC_BA_ACTION_DELBA in order to ensure that the two stations are synchronized
    00283     // before sending a new block ack agreement request.
    00284     // In fact, it could happen that a block ack agreement is already set up for this
    00285     // TID on the responder station, which might not reply to the ADDBA_REQ, causing
    00286     // the BA agreement is not established anymore.
    00287     // This loss of synchronisation could happen in case, for example, the originator
    00288     // sent a ADDBA_REQ but it didn't receive the ADDBA_RSP, or in case the originator
    00289     // didn't receive the acknowledgment of a DELBA frame.
    00290     bam_send_air_action_frame(sta_idx, &bam_env[bam_idx], MAC_BA_ACTION_DELBA, 0, 0,
    00291                               MAC_RS_TIMEOUT, NULL);
    00292
    00293     // Send ADDBA Request packet
    00294     bam_send_air_action_frame(sta_idx, &bam_env[bam_idx], MAC_BA_ACTION_ADDBA_REQ, 0, 0, 0, NULL);
    00295
    00296     // Store current time
    00297     sta_mgmt_set_add_ba_time(sta_idx, tid, ke_time());
    00298
    00299     // Start the ADDBA RSP Timeout timer
    00300     ke_timer_set(BAM_ADD_BA_RSP_TIMEOUT_IND, KE_BUILD_ID(TASK_BAM, bam_idx),
    00301                  (BAM_RESPONSE_TO_DURATION * TU_DURATION));
    00302
    00303     // Set state as wait_rsp
    00304     ke_state_set(KE_BUILD_ID(TASK_BAM, bam_idx), BAM_WAIT_RSP);
    00305
    00306     return CO_OK;
    00307 }
    00308 #endif
    00309
    00310 void bam_init(void)
    00311 {
    00312     for (int bam_idx = 0; bam_idx < BAM_IDX_MAX; bam_idx++)
    00313     {
    00314         bam_env[bam_idx].sta_idx     = INVALID_STA_IDX;
    00315
    00316         // Set pointer to BAW for TX BA structures
    00317         if (bam_idx >= BAM_FIRST_TX_IDX)
    00318         {
    00319             bam_env[bam_idx].baw = &bam_baws[bam_idx - BAM_FIRST_TX_IDX];
    00320         }
    00321
    00322         // Go to IDLE state
    00323         ke_state_set(KE_BUILD_ID(TASK_BAM, bam_idx), BAM_IDLE);
    00324     }
    00325 }
    00326
    00327 #if NX_AMPDU_TX || NX_REORD
    00328 void bam_param_sta_info_tab_reset(uint16_t bam_idx)
    00329 {
    00330     uint16_t sta_idx = bam_env[bam_idx].sta_idx;
    00331     uint8_t tid      = bam_env[bam_idx].tid;
    00332
    00333     // Initialize the parameters of the BA in the station info table
    00334     switch (bam_env[bam_idx].dev_type)
    00335     {
    00336         case BA_RESPONDER:
    00337         {
    00338             sta_info_tab[sta_idx].ba_info[tid].bam_idx_rx = BAM_INVALID_TASK_IDX;
    00339         } break;
    00340
    00341         case BA_ORIGINATOR:
    00342         {
    00343             sta_info_tab[sta_idx].ba_info[tid].bam_idx_tx = BAM_INVALID_TASK_IDX;
    00344         } break;
    00345
    00346         default:
    00347         {
    00348             // Should not happen
    00349         } break;
    00350     }
    00351 }
    00352
    00353 uint16_t bam_alloc_new_task(bool tx)
    00354 {
    00355     uint8_t start, cnt;
    00356
    00357     // The first indexes are reserved for RX BA, while the last ones are for TX
    00358     if (tx)
    00359     {
    00360         start = BAM_FIRST_TX_IDX;
    00361         cnt = BAM_NB_TX_IDX;
    00362     }
    00363     else
    00364     {
    00365         start = BAM_FIRST_RX_IDX;
    00366         cnt = BAM_NB_RX_IDX;
    00367     }
    00368
    00369     // Loop on the BAM IDX
    00370     for (int i = start; i < (start + cnt); i++)
    00371     {
    00372         // Check if the BAM task is Idle or not
    00373         if (bam_state[i] == BAM_IDLE)
    00374         {
    00375             // Return bam_task_idx
    00376             return i;
    00377         }
    00378     }
    00379
    00380     TRACE_LMAC(BA, "No more BA (TX=%d) task available", tx);
    00381     return BAM_INVALID_TASK_IDX;
    00382 }
    00383
    00384 void bam_delete_ba_agg(uint8_t bam_idx)
    00385 {
    00386     // BAM Task id
    00387     ke_task_id_t task_id = KE_BUILD_ID(TASK_BAM, bam_idx);
    00388
    00389     TRACE_LMAC(BA, "{BAM-%d} agreement deleted", bam_idx);
    00390
    00391     // Stop Inactivity Timeout timer
    00392     ke_timer_clear(BAM_ADD_BA_RSP_TIMEOUT_IND, task_id);
    00393     // Stop Inactivity Timeout timer
    00394     ke_timer_clear(BAM_INACTIVITY_TIMEOUT_IND, task_id);
    00395
    00396     // Clear information stored in the STA_MGMT module
    00397     bam_param_sta_info_tab_reset(bam_idx);
    00398
    00399     // Go back to idle state
    00400     ke_state_set(task_id, BAM_IDLE);
    00401 }
    00402
    00403 void bam_delete_all_ba_agg(uint8_t sta_idx)
    00404 {
    00405     // Loop on the BAM IDX (Instance 0 is BAM Manager)
    00406     for (int i = 0; i < BAM_IDX_MAX; i++)
    00407     {
    00408         // Check if the BAM task is Idle or not
    00409         if (bam_state[i] == BAM_IDLE)
    00410         {
    00411             continue;
    00412         }
    00413
    00414         // Check STAID
    00415         if (bam_env[i].sta_idx != sta_idx)
    00416         {
    00417             continue;
    00418         }
    00419
    00420         // Go to delete state
    00421         ke_state_set(KE_BUILD_ID(TASK_BAM, i), BAM_DELETE);
    00422
    00423         // Delete
    00424         bam_send_mm_ba_del_req(sta_idx, i);
    00425     }
    00426 }
    00427
    00428 void bam_start_inactivity_timer(uint16_t bam_idx)
    00429 {
    00430     ke_timer_set(BAM_INACTIVITY_TIMEOUT_IND, KE_BUILD_ID(TASK_BAM, bam_idx),
    00431                  bam_env[bam_idx].ba_timeout * TU_DURATION);
    00432 }
    00433
    00434 void bam_send_mm_ba_add_req(uint16_t sta_idx, uint16_t bam_idx)
    00435 {
    00436     // Allocate the message
    00437     struct mm_ba_add_req *req = KE_MSG_ALLOC(MM_BA_ADD_REQ,
    00438                                              TASK_MM, KE_BUILD_ID(TASK_BAM, bam_idx),
    00439                                              mm_ba_add_req);
    00440
    00441     // Fill the message parameters
    00442     req->type      = (bam_env[bam_idx].dev_type == BA_ORIGINATOR) ? 0 : 1;
    00443     req->sta_idx   = sta_idx;
    00444     req->tid       = bam_env[bam_idx].tid;
    00445     req->bufsz     = bam_env[bam_idx].buffer_size;
    00446     req->ssn       = bam_env[bam_idx].ssn;
    00447
    00448     // Send the message to the task
    00449     ke_msg_send(req);
    00450 }
    00451
    00452 void bam_send_mm_ba_del_req(uint16_t sta_idx, uint16_t bam_idx)
    00453 {
    00454     // Allocate the message
    00455     struct mm_ba_del_req *req = KE_MSG_ALLOC(MM_BA_DEL_REQ,
    00456                                              TASK_MM, KE_BUILD_ID(TASK_BAM, bam_idx),
    00457                                              mm_ba_del_req);
    00458
    00459     // Sanity check - The BAM task shall be in BAM_DELETE state when the BA deletion
    00460     // request is sent to the LMAC
    00461     ASSERT_ERR(ke_state_get(KE_BUILD_ID(TASK_BAM, bam_idx)) == BAM_DELETE);
    00462
    00463     // Fill the message parameters
    00464     req->type      = (bam_env[bam_idx].dev_type == BA_ORIGINATOR) ? 0 : 1;
    00465     req->sta_idx   = sta_idx;
    00466     req->tid       = bam_env[bam_idx].tid;
    00467
    00468     // Send the message
    00469     ke_msg_send(req);
    00470 }
    00471 #endif
    00472
    00473 void bam_send_air_action_frame(uint8_t sta_idx,
    00474                                struct bam_env_tag *bam_env,
    00475                                uint8_t action,
    00476                                uint8_t dialog_token,
    00477                                uint16_t param,
    00478                                uint16_t status_code,
    00479                                void (*cfm_func)(void *, uint32_t))
    00480 {
    00481     struct txl_frame_desc_tag *frame;
    00482     struct mac_hdr *buf;
    00483     struct tx_hd *thd;
    00484     uint8_t ac = AC_VO;
    00485     int txtype;
    00486     uint8_t vif_idx = sta_mgmt_get_vif_idx(sta_idx);
    00487     struct vif_info_tag *vif = &vif_info_tab[vif_idx];
    00488     uint32_t length = 0;
    00489
    00490     // Allocate a frame descriptor from the TX path
    00491     txtype = vif_mgmt_get_txtype(vif);
    00492     frame = txl_frame_get(txtype, NX_TXFRAME_LEN);
    00493
    00494     if (!frame)
    00495         return;
    00496
    00497     // update Tx power in policy table
    00498     tpc_update_frame_tx_power(vif, frame);
    00499
    00500     // Get the buffer pointer
    00501     buf = txl_buffer_payload_get(&frame->txdesc);
    00502
    00503     // Fill-in the frame
    00504     buf->fctl  = MAC_FCTRL_ACTION;
    00505     // TODO[LT] - Set duration
    00506     buf->durid = 0;
    00507     // Set RA
    00508     MAC_ADDR_CPY(&buf->addr1, sta_mgmt_get_peer_addr(sta_idx));
    00509     // Set TA
    00510     MAC_ADDR_CPY(&buf->addr2, vif_mgmt_get_addr(vif_idx));
    00511     // Set ADDR3
    00512     if (vif_mgmt_get_type(vif_idx) == VIF_AP)
    00513     {
    00514         MAC_ADDR_CPY(&buf->addr3, vif_mgmt_get_addr(vif_idx));
    00515     }
    00516     else
    00517     {
    00518         // STA or IBSS
    00519         MAC_ADDR_CPY(&buf->addr3, sta_mgmt_get_peer_addr(sta_idx));
    00520     }
    00521     // Update the sequence number in the frame
    00522     buf->seq = txl_get_seq_ctrl();
    00523
    00524     // Set VIF and STA indexes
    00525     frame->txdesc.host.vif_idx = vif_idx;
    00526     frame->txdesc.host.staid   = sta_idx;
    00527
    00528     length = MAC_SHORT_MAC_HDR_LEN;
    00529
    00530     #if NX_MFP
    00531     frame->txdesc.umac.head_len = 0;
    00532     frame->txdesc.umac.tail_len = 0;
    00533     if (MFP_UNICAST_PROT == mfp_protect_mgmt_frame(&frame->txdesc, buf->fctl,
    00534                                                    MAC_BA_ACTION_CATEGORY))
    00535     {
    00536         txu_cntrl_protect_mgmt_frame(&frame->txdesc, buf, MAC_SHORT_MAC_HDR_LEN);
    00537         length += frame->txdesc.umac.head_len;
    00538     }
    00539     #endif
    00540
    00541     // Build the payload
    00542     switch (action)
    00543     {
    00544         case MAC_BA_ACTION_ADDBA_REQ:
    00545         {
    00546             ac = mac_tid2ac[bam_env->tid];
    00547             length += me_build_add_ba_req(CPU2HW(buf) + length, bam_env);
    00548         } break;
    00549
    00550         case MAC_BA_ACTION_ADDBA_RSP:
    00551         {
    00552             length += me_build_add_ba_rsp(CPU2HW(buf) + length, bam_env,
    00553                                           param, dialog_token, status_code);
    00554         } break;
    00555
    00556         case MAC_BA_ACTION_DELBA:
    00557         {
    00558             ac = mac_tid2ac[bam_env->tid];
    00559             length += me_build_del_ba(CPU2HW(buf) + length, bam_env,
    00560                                       status_code);
    00561         } break;
    00562
    00563         default:
    00564         {
    00565             ASSERT_WARN(0);
    00566         } break;
    00567     }
    00568
    00569     #if NX_MFP
    00570     length += frame->txdesc.umac.tail_len;
    00571     #endif
    00572     thd             = &frame->txdesc.lmac.hw_desc->thd;
    00573     thd->dataendptr = (uint32_t)thd->datastartptr + length - 1;
    00574     thd->frmlen     = length + MAC_FCS_LEN;
    00575
    00576     if (cfm_func) {
    00577         frame->cfm.cfm_func = cfm_func;
    00578         frame->cfm.env = bam_env;
    00579     }
    00580
    00581     // Push the frame for TX
    00582     txl_frame_push(frame, ac);
    00583 }
    00584
    00585 #if NX_AMPDU_TX
    00586 void bam_check_ba_agg(struct txdesc *txdesc)
    00587 {
    00588     // Get current time
    00589     uint32_t current_time = hal_machw_time();
    00590     uint8_t sta_idx = txdesc->host.staid;
    00591     uint8_t tid = txdesc->host.tid;
    00592     uint8_t bam_idx;
    00593     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    00594
    00595     // Check if peer device supports HT
    00596     if (!STA_CAPA(sta, HT))
    00597         return;
    00598
    00599     // Increase the number of data packets for this STA/TID
    00600     sta_mgmt_ba_tx_cnt_inc(sta_idx, tid);
    00601
    00602     // No BlockAck agreement established for the 4-way Handshake
    00603     if (sta->ctrl_port_state != PORT_OPEN)
    00604         return;
    00605
    00606     // Get matching BAM index in order to know if a BA Agreement already exists
    00607     bam_idx = sta_mgmt_get_tx_bam_idx(sta_idx, tid);
    00608
    00609     if (bam_idx != BAM_INVALID_TASK_IDX)
    00610     {
    00611         // Update the last activity time
    00612         bam_env[bam_idx].last_activity_time = current_time;
    00613
    00614         // Check the current BAM task state in order to know if establishment is over
    00615         if (ke_state_get(KE_BUILD_ID(TASK_BAM, bam_idx)) == BAM_ACTIVE)
    00616         {
    00617             // An agreement already exists, the packet can be part of an A-MPDU
    00618             struct bam_baw *baw = bam_env[bam_idx].baw;
    00619             txdesc->umac.sn_win = baw->fsn;
    00620             if (rc_check_aggregation(sta))
    00621             {
    00622                 txdesc->umac.flags |= AMPDU_BIT;
    00623             }
    00624             txdesc->host.flags |= TXU_CNTRL_UNDER_BA;
    00625             bam_set_baw_state(baw, txdesc->host.sn, BAW_PENDING);
    00626             if (!(txdesc->host.flags & TXU_CNTRL_RETRY))
    00627                 txdesc->host.timestamp = bam_time_get() + me_tx_lft_get();
    00628
    00629             // Update the packet counter
    00630             bam_env[bam_idx].pkt_cnt++;
    00631         }
    00632     }
    00633     else
    00634     {
    00635         /*
    00636          * Check if we should establish a BlockAck agreement for this STA/TID. For that,
    00637          * we check these three conditions:
    00638          * -> Check if latest trial to establish a BA agreement for this pair is not too
    00639          *    recent, in order to avoid wasting time and power trying to establish the
    00640          *    agreement again and again with a peer consistently rejecting it
    00641          * -> Check if a minimum packet count is available in the TX path for this
    00642          *    STA/TID, indicating that non-negligible traffic is present (e.g not only a
    00643          *    ping)
    00644          * -> Check if peer is not in PS state (we consider that a peer in PS does not
    00645          *    require a lot of traffic and would exit PS if it was the case)
    00646          */
    00647         uint32_t last_ba_time = sta_mgmt_get_add_ba_time(sta_idx, tid);
    00648         if (!hal_machw_time_cmp(current_time, last_ba_time + BAM_ADDBA_REQ_INTERVAL) &&
    00649             (sta_mgmt_ba_tx_cnt_get(sta_idx, tid) >= BAM_BA_AGG_TX_CNT_THRES) &&
    00650             (sta->ps_state != PS_MODE_ON))
    00651         {
    00652             // Try to get a free instance of BAM task
    00653             bam_create_ba_agg(sta_idx, tid, txdesc->host.sn);
    00654         }
    00655     }
    00656 }
    00657
    00658 int8_t bam_tx_cfm(struct txdesc *txdesc, bool success)
    00659 {
    00660     uint8_t sta_idx = txdesc->host.staid;
    00661     uint8_t tid = txdesc->host.tid;
    00662     uint8_t bam_idx;
    00663     int8_t credits = 1;
    00664     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    00665
    00666     do
    00667     {
    00668         // Check if peer device supports HT
    00669         if (!STA_CAPA(sta, HT))
    00670             break;
    00671
    00672         // Decrease the number of data packets for this STA/TID
    00673         sta_mgmt_ba_tx_cnt_dec(sta_idx, tid);
    00674
    00675         // Check if the frame was transmitted under BA agreement
    00676         if (!(txdesc->host.flags & TXU_CNTRL_UNDER_BA))
    00677             break;
    00678
    00679         // Get matching BAM index in order to know if the BA Agreement still exists
    00680         bam_idx = sta_mgmt_get_tx_bam_idx(sta_idx, tid);
    00681
    00682         // Check if we have an agreement
    00683         if (bam_idx == BAM_INVALID_TASK_IDX)
    00684             break;
    00685
    00686         // Check the current BAM task state in order to know if the agreement is active
    00687         if (ke_state_get(KE_BUILD_ID(TASK_BAM, bam_idx)) != BAM_ACTIVE)
    00688             break;
    00689
    00690         // Update the packet counter
    00691         bam_env[bam_idx].pkt_cnt--;
    00692
    00693         // We have an active agreement, so we need to check the state of our transmission
    00694         // window
    00695         credits = bam_check_tx_baw(txdesc, bam_idx, success);
    00696     } while (0);
    00697
    00698     return credits;
    00699 }
    00700
    00701 void bam_baw_init(struct bam_env_tag *bam_env)
    00702 {
    00703     struct bam_baw *baw = bam_env->baw;
    00704
    00705     // Reset the BAW states
    00706     memset(&baw->states, BAW_FREE, BAM_MAX_TX_WIN_SIZE * sizeof(uint8_t));
    00707
    00708     // Initializes the BAW
    00709     baw->fsn = sta_mgmt_get_tx_ssn(bam_env->sta_idx, bam_env->tid);
    00710     baw->fsn_idx = 0;
    00711     baw->buf_size = bam_env->buffer_size;
    00712
    00713     // Check if the buffer size is a power of 2 or not
    00714     if (baw->buf_size & (baw->buf_size - 1))
    00715     {
    00716         baw->idx_compute = bam_baw_index_compute;
    00717     }
    00718     else
    00719     {
    00720         baw->mask = baw->buf_size - 1;
    00721         baw->idx_compute = bam_baw_index_compute_opt;
    00722     }
    00723 }
    00724
    00725 int8_t bam_flush_baw(struct bam_baw *baw)
    00726 {
    00727     int8_t credits = 0;
    00728     int i;
    00729
    00730     for (i = 0; i < baw->buf_size; i++) {
    00731         if (baw->states[i] == BAW_CONFIRMED)
    00732             credits++;
    00733     }
    00734
    00735     return(credits);
    00736 }
    00737
    00738 #endif
    00739
    00740 #if NX_REORD
    00741 void bam_rx_active(uint8_t sta_idx, uint8_t tid)
    00742 {
    00743     // Retrieve BAM instance index
    00744     uint8_t bam_idx = sta_mgmt_get_rx_bam_idx(sta_idx, tid);
    00745
    00746     ASSERT_ERR(bam_idx < BAM_INVALID_TASK_IDX);
    00747
    00748     bam_env[bam_idx].last_activity_time = hal_machw_time();
    00749 }
    00750
    00751 void bam_send_del_ba_agg(uint8_t sta_idx, uint8_t tid)
    00752 {
    00753     struct bam_env_tag bam;
    00754     bam.sta_idx          = sta_idx;
    00755     bam.tid              = tid;
    00756     bam.dialog_token     = 0;
    00757     bam.ba_timeout       = BAM_INACTIVITY_TO_DURATION;
    00758     bam.ba_policy        = 1;
    00759     bam.dev_type         = BA_RESPONDER;
    00760     bam.buffer_size      = 64;
    00761     bam.ssn              = 0;
    00762     bam.pkt_cnt          = 0;
    00763
    00764     bam_send_air_action_frame(sta_idx, &bam, MAC_BA_ACTION_DELBA,
    00765                               0, 0, MAC_BA_ST_INVALID_PARAMETERS, NULL);
    00766 }
    00767 #endif
    00768