- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/lmac/src/tx/txl/txl_buffer.h

Go to the documentation of this file.

    00001
    00013 #ifndef _TXL_BUFFER_H_
    00014 #define _TXL_BUFFER_H_
    00015
    00025 /*
    00026  * INCLUDE FILES
    00027  ****************************************************************************************
    00028  */
    00029 #include "co_int.h"
    00030 #include "co_bool.h"
    00031 #include "rwnx_config.h"
    00032 #include "co_list.h"
    00033 #include "txl_cntrl.h"
    00034 #include "tx_swdesc.h"
    00035 #include "txl_agg.h"
    00036 #include "txl_he.h"
    00037 #include "co_utils.h"
    00038 #if NX_UMAC_PRESENT
    00039 #include "me_mic.h"
    00040 #include "txu_cntrl.h"
    00041 #include "rc.h"
    00042 #endif
    00043
    00044
    00045 /*
    00046  * CONSTANTS
    00047  ****************************************************************************************
    00048  */
    00050 #define TX_BUFFER_MTU 1536
    00051
    00053 #define TX_ADD_BUFFER 64
    00054
    00056 #define TX_MPDU_LEN_MAX  (TX_BUFFER_MTU + TX_ADD_BUFFER)
    00057
    00059 #define TX_BUFFER_MAX (sizeof_b(struct txl_buffer_tag) + TX_MPDU_LEN_MAX)
    00060
    00062 #define TX_BUFFER_POOL_MAX (AC_MAX * RW_USER_MAX + NX_BEACONING)
    00063
    00065 #if NX_AMPDU_TX
    00066 #if defined(CFG_VIRTEX7) && !defined(CFG_FHOST)
    00068 #define TX_MIN_DOWNLOAD_CNT   8
    00069 #else
    00070 #if NX_AMSDU_TX
    00072 #define TX_MIN_DOWNLOAD_CNT   4
    00073 #else
    00075 #define TX_MIN_DOWNLOAD_CNT   3
    00076 #endif // NX_AMSDU_TX
    00077 #endif // defined(CFG_VIRTEX7)
    00079 #define TX_BUFFER_POOL_SIZE     ((TX_MIN_DOWNLOAD_CNT * TX_BUFFER_MAX) / 4)
    00080 #else
    00082 #define TX_MIN_DOWNLOAD_CNT   2
    00084 #define TX_BUFFER_POOL_SIZE     ((TX_MIN_DOWNLOAD_CNT * TX_BUFFER_MAX) / 4)
    00085 #endif // NX_AMPDU_TX
    00086
    00088 #define TX_BUFFER_NULL          0xFFFFFFFF
    00089
    00090 #if NX_UMAC_PRESENT
    00092 #define TX_BUFFER_PADDING_MAX   0
    00093 #else
    00095 #define TX_BUFFER_PADDING_MAX   3
    00096 #endif
    00097
    00099 #define TX_BUFFER_PADDING_MASK  0x00000003
    00100
    00102 #define TX_BUFFER_PADDING_OFT   0
    00103
    00105 #define TX_BUFFER_MIN_SIZE      256
    00106
    00108 #define TX_BUFFER_MIN_AMPDU_DWNLD   500
    00109
    00111 #if NX_UMAC_PRESENT && NX_AMSDU_TX
    00112 #define TX_DMA_DESC_MAX  NX_TX_PAYLOAD_MAX
    00113 #elif NX_MFP
    00114 #define TX_DMA_DESC_MAX  2
    00115 #else
    00116 #define TX_DMA_DESC_MAX  1
    00117 #endif
    00118
    00119 #if NX_FULLY_HOSTED
    00120
    00122 #define TX_PBD_CNT            3
    00123 #endif
    00124
    00126 enum
    00127 {
    00129     BUF_FRONTIER = CO_BIT(0),
    00131     BUF_SPLIT = CO_BIT(1),
    00133     BUF_ALLOC_OK = CO_BIT(2),
    00135     BUF_INT_MSDU = CO_BIT(3),
    00136     #if NX_MAC_HE
    00138     BUF_SINGLETON_READY = CO_BIT(4),
    00139     #endif
    00140 };
    00141
    00142 /*
    00143  * TYPE and STRUCT DEFINITIONS
    00144  ****************************************************************************************
    00145  */
    00147 struct txl_buffer_hw_desc_tag
    00148 {
    00150     struct dma_desc dma_desc;
    00152     struct tx_pbd   pbd;
    00153 };
    00154
    00156 struct txl_buffer_list_tag
    00157 {
    00159     struct txl_buffer_tag *first;
    00161     struct txl_buffer_tag *last;
    00162 };
    00163
    00165 struct txl_buffer_idx_tag
    00166 {
    00168     uint32_t used_area;
    00170     uint32_t free;
    00172     uint32_t free_size;
    00174     uint32_t last;
    00177     uint32_t next_needed;
    00179     uint32_t buf_size;
    00181     uint32_t *pool;
    00183     struct txl_buffer_hw_desc_tag *desc;
    00185     uint8_t count;
    00186 };
    00187
    00188
    00190 struct txl_buffer_env_tag
    00191 {
    00193     struct txl_buffer_idx_tag buf_idx[NX_TXQ_CNT][RW_USER_MAX];
    00195     struct txl_buffer_list_tag list[NX_TXQ_CNT];
    00196 };
    00197
    00199 struct txl_buffer_tag
    00200 {
    00201     #if !NX_FULLY_HOSTED
    00203     uint32_t length;
    00205     struct txl_buffer_tag *next;
    00207     struct txdesc *txdesc;
    00209     struct dma_desc dma_desc[TX_DMA_DESC_MAX];
    00211     struct dma_desc dma_desc_pat;
    00212     #if (RW_BFMER_EN)
    00214     struct dma_desc dma_desc_bfr;
    00215     #endif //(RW_BFMER_EN)
    00217     struct tx_pbd tbd;
    00219     uint8_t user_idx;
    00220     #endif
    00221
    00222     uint32_t flags;
    00224     struct txl_buffer_control buffer_control;
    00225     #if NX_FULLY_HOSTED
    00227     struct tx_pbd pbd[TX_PBD_CNT];
    00229     struct tx_pbd pbd_tail;
    00231     uint8_t sec_tail[MIC_LEN];
    00233     uint8_t headers[MAC_LONG_QOS_MAC_HDR_LEN + LLC_802_2_HDR_LEN + WPI_IV_LEN - LLC_ETHER_HDR_LEN];
    00234     #endif
    00236     uint32_t payload[];
    00237 };
    00238
    00239
    00240 /*
    00241  * GLOBAL VARIABLES
    00242  ****************************************************************************************
    00243  */
    00245 extern uint32_t txl_buffer_pool[TX_BUFFER_POOL_MAX][TX_BUFFER_POOL_SIZE];
    00246
    00248 extern struct txl_buffer_hw_desc_tag txl_buffer_hw_desc[TX_BUFFER_POOL_MAX];
    00249
    00251 extern struct txl_buffer_env_tag txl_buffer_env;
    00252
    00253 #if NX_UMAC_PRESENT
    00255 extern struct txl_buffer_control txl_buffer_control_desc[NX_REMOTE_STA_MAX];
    00257 extern struct txl_buffer_control txl_buffer_control_desc_bcmc[NX_VIRT_DEV_MAX];
    00258 #endif
    00259
    00260 /*
    00261  * FUNCTION PROTOTYPES
    00262  ****************************************************************************************
    00263  */
    00264
    00267
    00268 #if !NX_FULLY_HOSTED
    00269
    00279 __INLINE void txl_buffer_push(uint8_t access_category, struct txl_buffer_tag *buf)
    00280 {
    00281     struct txl_buffer_list_tag *list = &txl_buffer_env.list[access_category];
    00282
    00283     // check if list is empty
    00284     if (list->first == NULL)
    00285     {
    00286         // list empty => pushed element is also head
    00287         list->first = buf;
    00288     }
    00289     else
    00290     {
    00291         // list not empty => update next of last
    00292         list->last->next = buf;
    00293     }
    00294
    00295     // add element at the end of the list
    00296     list->last = buf;
    00297     buf->next = NULL;
    00298 }
    00299
    00311 __INLINE struct txl_buffer_tag *txl_buffer_pop(uint8_t access_category)
    00312 {
    00313     struct txl_buffer_list_tag *list = &txl_buffer_env.list[access_category];
    00314     struct txl_buffer_tag *buf;
    00315
    00316     // check if list is empty
    00317     buf = list->first;
    00318     if (buf != NULL)
    00319     {
    00320         // The list isn't empty : extract the first element
    00321         list->first = list->first->next;
    00322     }
    00323
    00324     return buf;
    00325 }
    00326
    00337 __INLINE struct txl_buffer_tag *txl_buffer_pick(uint8_t access_category)
    00338 {
    00339     struct txl_buffer_list_tag *list = &txl_buffer_env.list[access_category];
    00340
    00341     return list->first;
    00342 }
    00343
    00353 __INLINE bool txl_buffer_list_empty(uint8_t access_category)
    00354 {
    00355     struct txl_buffer_list_tag *list = &txl_buffer_env.list[access_category];
    00356
    00357     return (list->first == NULL);
    00358 }
    00359 #endif
    00360
    00361
    00372 __INLINE struct txl_buffer_tag *txl_buffer_get(struct txdesc *txdesc)
    00373 {
    00374     #if NX_AMSDU_TX
    00375     struct txl_buffer_tag *buffer = txdesc->lmac.buffer[0];
    00376     #else
    00377     struct txl_buffer_tag *buffer = txdesc->lmac.buffer;
    00378     #endif
    00379     return (buffer);
    00380 }
    00381
    00382
    00393 __INLINE struct txl_buffer_control *txl_buffer_control_get(struct txdesc *txdesc)
    00394 {
    00395     struct txl_buffer_tag *buffer = txl_buffer_get(txdesc);
    00396     return (&buffer->buffer_control);
    00397 }
    00398
    00409 __INLINE void *txl_buffer_payload_get(struct txdesc *txdesc)
    00410 {
    00411     struct txl_buffer_tag *buffer = txl_buffer_get(txdesc);
    00412     return ((void *)buffer->payload);
    00413 }
    00414
    00426 __INLINE uint32_t txl_buffer_machdr_get(struct txdesc *txdesc)
    00427 {
    00428     struct tx_hd *thd = &txdesc->lmac.hw_desc->thd;
    00429     struct tx_pbd *pbd;
    00430
    00431     // A buffer shall be available
    00432     ASSERT_ERR(txl_buffer_get(txdesc) != NULL);
    00433
    00434     // Check if the frame buffer is at least partly pointed by the THD
    00435     if (thd->datastartptr)
    00436         return (thd->datastartptr);
    00437
    00438     // Sanity check - If the MAC header is not pointed by the THD, a PBD shall be present
    00439     ASSERT_ERR(thd->first_pbd_ptr);
    00440     pbd = HW2CPU(thd->first_pbd_ptr);
    00441
    00442     return (pbd->datastartptr);
    00443 }
    00444
    00445 #if NX_UMAC_PRESENT
    00446
    00456 __INLINE void txl_buffer_control_trial(struct txdesc *txdesc, struct txl_buffer_tag *buf)
    00457 {
    00458     // Set ratecntrlinfo for trial rate transmission
    00459     if (txdesc->host.flags & TXU_CNTRL_RC_TRIAL)
    00460     {
    00461         struct txl_buffer_control *buf_ctrl_src = txdesc->umac.buf_control;
    00462         struct txl_buffer_control *buf_ctrl_dest = &buf->buffer_control;
    00463         // get RC station statistics
    00464         struct rc_sta_stats *rc_ss = rc_get_sta_stats(txdesc->host.staid);
    00465
    00466         PROF_RC_SET_TRIAL_BUFFER_SET();
    00467
    00468         // Move step 0 to step 1
    00469         buf_ctrl_dest->policy_tbl.ratecntrlinfo[1] = buf_ctrl_src->policy_tbl.ratecntrlinfo[0];
    00470         #if NX_MAC_HE
    00471         buf_ctrl_dest->policy_tbl.powercntrlinfo[1] = buf_ctrl_src->policy_tbl.powercntrlinfo[0];
    00472         #endif
    00473
    00474         // Replace step 0 by trial rate
    00475         buf_ctrl_dest->policy_tbl.ratecntrlinfo[0] = rc_ss->trial_rate;
    00476         #if NX_MAC_HE
    00477         if (txl_he_is_he_su(rc_ss->trial_rate))
    00478         {
    00479             txl_he_ltf_type_set(rc_ss->trial_rate,
    00480                                 &buf_ctrl_dest->policy_tbl.powercntrlinfo[0]);
    00481         }
    00482         #endif
    00483
    00484         // Disable the STBC
    00485         if ((buf_ctrl_src->tx_flags & TX_SWDESC_UMAC_TRIAL_STBC_BIT) == 0)
    00486         {
    00487             buf_ctrl_dest->policy_tbl.phycntrlinfo1 &= ~STBC_PT_MASK;
    00488         }
    00489
    00490         PROF_RC_SET_TRIAL_BUFFER_CLR();
    00491     }
    00492 }
    00493
    00503 __INLINE void txl_buffer_control_copy(struct txdesc *txdesc,
    00504                                       struct txl_buffer_tag *buf)
    00505 {
    00506     uint32_t *dst = (uint32_t *)&buf->buffer_control;
    00507     uint32_t *src = (uint32_t *)txdesc->umac.buf_control;
    00508     unsigned int i;
    00509
    00510     // Copy the policy table
    00511     for (i = 0; i < (sizeof_b(struct txl_buffer_control)/sizeof_b(uint32_t)); i++)
    00512     {
    00513         *dst++ = *src++;
    00514     }
    00515
    00516     // Set the trial rate if a trial tx is requested
    00517     txl_buffer_control_trial(txdesc, buf);
    00518
    00519 }
    00520 #endif
    00521
    00522
    00534 __INLINE int txl_buffer_padding(struct txdesc *txdesc)
    00535 {
    00536     #if NX_UMAC_PRESENT
    00537     return (0);
    00538     #else
    00539     return (txdesc->host.padding);
    00540     #endif
    00541 }
    00542
    00543 #if NX_AMSDU_TX
    00544
    00554 __INLINE bool txl_buffer_is_amsdu_multi_buf(struct txdesc *txdesc)
    00555 {
    00556     return (is_mpdu_split(txdesc) && (txdesc->lmac.hw_desc->thd.frmlen > TX_MPDU_LEN_MAX));
    00557 }
    00568 __INLINE bool txl_buffer_is_amsdu_single_buf(struct txdesc *txdesc)
    00569 {
    00570     return (is_mpdu_split(txdesc) && (txdesc->lmac.hw_desc->thd.frmlen <= TX_MPDU_LEN_MAX));
    00571 }
    00572 #endif
    00573
    00574 #if NX_MAC_HE
    00575
    00590 __INLINE void txl_buffer_remove_htc(struct tx_hd *thd)
    00591 {
    00592     #if NX_UMAC_PRESENT
    00593     uint32_t mac_hdr_addr = thd->datastartptr;
    00594     uint16_t framectl = co_read16p(mac_hdr_addr);
    00595
    00596     // Check if the order bit is set in the MAC Header, indicating if the +HTC is present
    00597     // or not
    00598     if ((framectl & MAC_FCTRL_ORDER) == 0)
    00599         return;
    00600
    00601     framectl &= ~MAC_FCTRL_ORDER;
    00602     co_write16p(mac_hdr_addr, framectl);
    00603
    00604     thd->frmlen -= MAC_HTC_LEN;
    00605     thd->dataendptr -= MAC_HTC_LEN;
    00606     #endif
    00607 }
    00608
    00626 __INLINE void txl_buffer_add_htc(struct tx_hd *thd)
    00627 {
    00628     #if NX_UMAC_PRESENT
    00629     uint32_t mac_hdr_addr = thd->datastartptr;
    00630     uint16_t framectl;
    00631
    00632     if (!mac_hdr_addr || ((framectl = co_read16p(mac_hdr_addr)) & MAC_FCTRL_ORDER))
    00633         return;
    00634
    00635     framectl |= MAC_FCTRL_ORDER;
    00636     co_write16p(mac_hdr_addr, framectl);
    00637
    00638     thd->frmlen += MAC_HTC_LEN;
    00639     thd->dataendptr += MAC_HTC_LEN;
    00640     #endif
    00641 }
    00642
    00657 __INLINE bool txl_buffer_update_htc(struct tx_hd *thd, uint32_t htc)
    00658 {
    00659     #if NX_UMAC_PRESENT
    00660     // Ensure we have a buffer already allocated
    00661     if (!thd->datastartptr)
    00662         return false;
    00663
    00664     co_write32p(thd->dataendptr - MAC_HTC_LEN + 1, htc);
    00665     return true;
    00666     #else
    00667     return false;
    00668     #endif
    00669 }
    00670
    00671
    00672 #endif
    00673
    00674 #if !NX_FULLY_HOSTED
    00675
    00688 __INLINE void txl_buffer_update_thd(struct txdesc *txdesc,
    00689                                     uint8_t access_category)
    00690 {
    00691     struct tx_hd *thd = &txdesc->lmac.hw_desc->thd;
    00692     #if NX_AMSDU_TX
    00693     struct txl_list *txlist = &txl_cntrl_env.txlist[access_category];
    00694     #endif
    00695     struct txl_buffer_tag *buffer = txl_buffer_get(txdesc);
    00696     struct txl_buffer_idx_tag *idx = &txl_buffer_env.buf_idx[access_category][buffer->user_idx];
    00697     uint32_t pool_size = TX_BUFFER_POOL_SIZE * sizeof_b(uint32_t);
    00698     uint32_t pool_start = CPU2HW(idx->pool);
    00699     uint32_t pool_end = pool_start + pool_size - 1;
    00700     uint32_t start = CPU2HW(buffer->payload) + txl_buffer_padding(txdesc);
    00701     #if NX_UMAC_PRESENT
    00702     uint16_t add_len;
    00703     uint32_t payl = start + txdesc->umac.machead_len;
    00704     #else
    00705     uint32_t payl = start;
    00706     #endif
    00707     #if NX_AMSDU_TX
    00708     uint32_t pkt_len = txdesc->host.packet_len[0];
    00709     #else
    00710     uint32_t pkt_len = txdesc->host.packet_len;
    00711     #endif
    00712     uint32_t end;
    00713     struct tx_pbd *pbd = &buffer->tbd;
    00714     struct tx_pbd *add_pbd = NULL;
    00715     struct tx_pbd *last_pbd = pbd;
    00716
    00717     #if NX_UMAC_PRESENT
    00718     #if NX_AMSDU_TX
    00719     if (txl_buffer_is_amsdu_single_buf(txdesc))
    00720         pkt_len = txdesc->lmac.hw_desc->thd.frmlen - MAC_FCS_LEN;
    00721     else
    00722     #endif
    00723     {
    00724         add_len = txdesc->umac.head_len;
    00725         #if NX_AMSDU_TX
    00726         if (!is_mpdu_split(txdesc))
    00727         #endif
    00728             add_len += txdesc->umac.tail_len;
    00729         pkt_len += add_len;
    00730     }
    00731     #endif
    00732     end = start + pkt_len - 1;
    00733
    00734     // By default we consider that the buffer is not split
    00735     buffer->flags &= ~BUF_SPLIT;
    00736
    00737     // Check if buffer padding has caused a buffer wrap
    00738     ASSERT_ERR(start < pool_end);
    00739
    00740     // Check if buffer is split
    00741     if (end > pool_end)
    00742     {
    00743         // Buffer is split
    00744         end = pool_end;
    00745
    00746         // We use the PBD of the pool to handle the split
    00747         add_pbd = &idx->desc->pbd;
    00748         add_pbd->datastartptr = pool_start;
    00749         add_pbd->dataendptr = pool_start + pkt_len - (end - start) - 2;
    00750
    00751         last_pbd = add_pbd;
    00752
    00753         // Buffer is split
    00754         buffer->flags |= BUF_SPLIT;
    00755     }
    00756
    00757     // Set start and end pointers to the beginning and end of the frame
    00758     #if NX_UMAC_PRESENT
    00759     if (txdesc->umac.machead_len)
    00760     {
    00761         thd->datastartptr = start;
    00762         thd->dataendptr = start + txdesc->umac.machead_len - 1;
    00763     }
    00764     #endif
    00765     pbd->datastartptr = payl;
    00766     pbd->dataendptr = end;
    00767     pbd->next = CPU2HW(add_pbd);
    00768     pbd->bufctrlinfo = 0;
    00769
    00770     thd->first_pbd_ptr = CPU2HW(pbd);
    00771     last_pbd->bufctrlinfo = 0;
    00772     #if NX_AMPDU_TX
    00773     if ((buffer->flags & BUF_FRONTIER) || is_mpdu_last(txdesc) || !is_mpdu_agg(txdesc))
    00774     {
    00775         if (!(buffer->flags & BUF_FRONTIER))
    00776         {
    00777             #if NX_AMSDU_TX
    00778             if (!is_mpdu_split(txdesc))
    00779             {
    00780             #endif
    00781                 buffer->flags |= BUF_FRONTIER;
    00782                 idx->count++;
    00783             #if NX_AMSDU_TX
    00784             }
    00785             #endif
    00786             // Set WhichDescriptor field
    00787             thd->macctrlinfo2 |= INTERRUPT_EN_TX;
    00788         }
    00789         else
    00790         {
    00791             #if NX_AMSDU_TX
    00792             if (txl_buffer_is_amsdu_multi_buf(txdesc))
    00793             {
    00794                 // Enable interrupt on the last PBD
    00795                 last_pbd->bufctrlinfo = TBD_INTERRUPT_EN;
    00796
    00797                 // For singleton we need to enable the IRQ on packet completion
    00798                 if (!is_mpdu_agg(txdesc))
    00799                     thd->macctrlinfo2 |= INTERRUPT_EN_TX;
    00800             }
    00801             else
    00802             #endif
    00803             {
    00804                 // Set WhichDescriptor field
    00805                 thd->macctrlinfo2 |= INTERRUPT_EN_TX;
    00806             }
    00807         }
    00808     }
    00809     #else
    00810     // Set WhichDescriptor field
    00811     thd->macctrlinfo2 = WHICHDESC_UNFRAGMENTED_MSDU | INTERRUPT_EN_TX;
    00812     #endif
    00813     last_pbd->next = 0;
    00814
    00815     #if NX_AMSDU_TX
    00816     // Store the new value of last PBD
    00817     txlist->last_pbd[buffer->user_idx] = last_pbd;
    00818     #endif
    00819 }
    00820
    00821 #if NX_AMSDU_TX
    00822
    00836 __INLINE void txl_buffer_update_tbd(struct txdesc *txdesc,
    00837                                     uint8_t access_category,
    00838                                     uint8_t pkt_idx)
    00839 {
    00840     struct txl_list *txlist = &txl_cntrl_env.txlist[access_category];
    00841     struct txl_buffer_tag *buffer = txdesc->lmac.buffer[pkt_idx];
    00842     struct tx_pbd *tbd = &buffer->tbd;
    00843     uint32_t pkt_len = txdesc->host.packet_len[pkt_idx];
    00844     struct txl_buffer_idx_tag *idx = &txl_buffer_env.buf_idx[access_category][buffer->user_idx];
    00845     uint32_t pool_size = TX_BUFFER_POOL_SIZE * sizeof_b(uint32_t);
    00846     uint32_t pool_start = CPU2HW(idx->pool);
    00847     uint32_t pool_end = pool_start + pool_size - 1;
    00848     uint32_t start = CPU2HW(buffer->payload);
    00849     uint32_t end = start + pkt_len - 1;
    00850     struct tx_pbd *pbd = NULL;
    00851     struct tx_pbd *last = tbd;
    00852
    00853     #if NX_UMAC_PRESENT
    00854     if ((pkt_idx + 1) == txdesc->host.packet_cnt) {
    00855        pkt_len += txdesc->umac.tail_len;
    00856        end += txdesc->umac.tail_len;
    00857     }
    00858     #endif
    00859
    00860     // By default we consider that the buffer is not split
    00861     buffer->flags &= ~BUF_SPLIT;
    00862
    00863     // Check if buffer padding has caused a buffer wrap
    00864     if (start > pool_end)
    00865     {
    00866         start -= pool_size;
    00867         end -= pool_size;
    00868     }
    00869     else
    00870     {
    00871         // Check if buffer is split
    00872         if (end > pool_end)
    00873         {
    00874             // Buffer is split
    00875             end = pool_end;
    00876
    00877             // We use the PBD of the pool to handle the split
    00878             pbd = &idx->desc->pbd;
    00879             pbd->datastartptr = pool_start;
    00880             pbd->dataendptr = pool_start + pkt_len - (end - start) - 2;
    00881
    00882             last = pbd;
    00883
    00884             // Buffer is split
    00885             buffer->flags |= BUF_SPLIT;
    00886         }
    00887     }
    00888
    00889     // Set start and end pointers to the beginning and end of the frame
    00890     tbd->datastartptr = start;
    00891     tbd->dataendptr = end;
    00892     tbd->next = CPU2HW(pbd);
    00893     tbd->bufctrlinfo = 0;
    00894
    00895     if ((buffer->flags & BUF_FRONTIER) ||
    00896         (is_mpdu_last(txdesc) && ((pkt_idx + 1) == txdesc->host.packet_cnt)))
    00897         // Enable interrupt on the last PBD
    00898         last->bufctrlinfo = TBD_INTERRUPT_EN;
    00899     else
    00900         last->bufctrlinfo = 0;
    00901
    00902     // Chain the descriptor(s) to the previous one(s)
    00903     ASSERT_ERR(txlist->last_pbd[buffer->user_idx] != NULL);
    00904     txlist->last_pbd[buffer->user_idx]->next = CPU2HW(tbd);
    00905
    00906     // Store the new value of last PBD
    00907     last->next = 0;
    00908     txlist->last_pbd[buffer->user_idx] = last;
    00909 }
    00910 #endif
    00911
    00912
    00913 #if NX_UMAC_PRESENT
    00914
    00927 __INLINE void txl_buffer_mic_compute(struct txdesc *txdesc,
    00928                                      uint32_t *mic_key,
    00929                                      uint32_t start,
    00930                                      uint32_t len,
    00931                                      uint8_t access_category)
    00932 {
    00933     struct hostdesc *host = &txdesc->host;
    00934     struct mic_calc mic;
    00935     struct txl_buffer_tag *buffer = txl_buffer_get(txdesc);
    00936     struct txl_buffer_idx_tag *idx = &txl_buffer_env.buf_idx[access_category][buffer->user_idx];
    00937     uint32_t pool_size = TX_BUFFER_POOL_SIZE * sizeof_b(uint32_t);
    00938     uint32_t pool_start = CPU2HW(idx->pool);
    00939     uint32_t pool_end = pool_start + pool_size - 1;
    00940     uint32_t end = start + len - 1;
    00941     uint32_t clen = len;
    00942     uint32_t mic_start = end + 1, mic_end;
    00943     uint32_t mic_addr = CPU2HW(&mic.mic_key_least);
    00944
    00945     // Initialize MIC computation
    00946     me_mic_init(&mic, mic_key, &host->eth_dest_addr, &host->eth_src_addr, host->tid);
    00947
    00948     // Check if buffer is split
    00949     if (end > pool_end)
    00950     {
    00951         clen = pool_end - start + 1;
    00952
    00953         // Buffer is split
    00954         me_mic_calc(&mic, start, clen);
    00955
    00956         // Compute the parameters of the next computation
    00957         clen = len - clen;
    00958         start = pool_start;
    00959     }
    00960
    00961     me_mic_calc(&mic, start, clen);
    00962
    00963     // End the MIC computation
    00964     me_mic_end(&mic);
    00965
    00966     // Copy the MIC in the packet
    00967     if (mic_start > pool_end)
    00968         mic_start -= pool_size;
    00969     mic_end = mic_start + 7;
    00970     clen = 8;
    00971     if (mic_end > pool_end)
    00972     {
    00973         clen = pool_end - mic_start + 1;
    00974
    00975         // Copy the first part of the MIC in the TX buffer
    00976         co_copy8p(mic_start, mic_addr, clen);
    00977
    00978         // Compute the parameters of the next computation
    00979         mic_addr += clen;
    00980         clen = 8 - clen;
    00981         mic_start = pool_start;
    00982     }
    00983
    00984     // Copy the remaining part of the MIC in the TX buffer
    00985     co_copy8p(mic_start, mic_addr, clen);
    00986 }
    00987 #endif //NX_UMAC_PRESENT
    00988
    00995 void txl_buffer_reinit(void);
    00996
    01007 void txl_buffer_reset(uint8_t access_category);
    01008
    01029 #if NX_AMSDU_TX
    01030 struct txl_buffer_tag *txl_buffer_alloc(struct txdesc *txdesc, uint8_t access_category,
    01031                                         uint8_t user_idx, uint8_t pkt_idx);
    01032 #else
    01033 struct txl_buffer_tag *txl_buffer_alloc(struct txdesc *txdesc, uint8_t access_category,
    01034                                         uint8_t user_idx);
    01035 #endif
    01036
    01048 bool txl_buffer_free(struct txl_buffer_tag *buf, uint8_t access_category);
    01049
    01058 void txl_buffer_free_all(struct txdesc *txdesc, uint8_t access_category);
    01059
    01071 __INLINE uint32_t txl_buffer_used(uint8_t access_category, uint8_t user_idx)
    01072 {
    01073     return txl_buffer_env.buf_idx[access_category][user_idx].used_area;
    01074 }
    01075
    01087 __INLINE uint8_t txl_buffer_count(uint8_t access_category, uint8_t user_idx)
    01088 {
    01089     struct txl_buffer_idx_tag *idx = &txl_buffer_env.buf_idx[access_category][user_idx];
    01090
    01091     return(idx->count);
    01092 }
    01093 #endif
    01094
    01095
    01101 void txl_buffer_init(void);
    01102
    01103
    01104
    01107
    01108 #endif