linux/drivers/staging/otus/80211core/cagg.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2007-2008 Atheros Communications Inc.
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16/*                                                                      */
  17/*  Module Name : cagg.c                                                */
  18/*                                                                      */
  19/*  Abstract                                                            */
  20/*      This module contains A-MPDU aggregation related functions.      */
  21/*                                                                      */
  22/*  NOTES                                                               */
  23/*      None                                                            */
  24/*                                                                      */
  25/************************************************************************/
  26
  27#include "cprecomp.h"
  28
  29extern u8_t zcUpToAc[8];
  30const u8_t pri[] = {3,3,2,3,2,1,3,2,1,0};
  31
  32
  33u16_t aggr_count;
  34u32_t success_mpdu;
  35u32_t total_mpdu;
  36
  37void zfAggInit(zdev_t* dev)
  38{
  39    u16_t i,j;
  40
  41    zmw_get_wlan_dev(dev);
  42
  43    zmw_declare_for_critical_section();
  44    /*
  45     * reset sta information
  46     */
  47
  48    zmw_enter_critical_section(dev);
  49    wd->aggInitiated = 0;
  50    wd->addbaComplete = 0;
  51    wd->addbaCount = 0;
  52    wd->reorder = 1;
  53    for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
  54    {
  55        for (j=0; j<ZM_AC; j++)
  56        {
  57            //wd->aggSta[i].aggQNumber[j] = ZM_AGG_POOL_SIZE;
  58            wd->aggSta[i].aggFlag[j] = wd->aggSta[i].count[j] = 0;
  59            wd->aggSta[i].tid_tx[j] = NULL;
  60            wd->aggSta[i].tid_tx[j+1] = NULL;
  61
  62        }
  63    }
  64
  65    /*
  66     * reset Tx/Rx aggregation queue information
  67     */
  68    wd->aggState = 0;
  69    for (i=0; i<ZM_AGG_POOL_SIZE; i++)
  70    {
  71        /*
  72         * reset tx aggregation queue
  73         */
  74        wd->aggQPool[i] = zfwMemAllocate(dev, sizeof(struct aggQueue));
  75        if(!wd->aggQPool[i])
  76        {
  77            zmw_leave_critical_section(dev);
  78            return;
  79        }
  80        wd->aggQPool[i]->aggHead = wd->aggQPool[i]->aggTail =
  81        wd->aggQPool[i]->aggQEnabled = wd->aggQPool[i]->aggReady =
  82        wd->aggQPool[i]->clearFlag = wd->aggQPool[i]->deleteFlag = 0;
  83        //wd->aggQPool[i]->aggSize = 16;
  84
  85        /*
  86         * reset rx aggregation queue
  87         */
  88        wd->tid_rx[i] = zfwMemAllocate(dev, sizeof(struct agg_tid_rx));
  89        if (!wd->tid_rx[i])
  90        {
  91            zmw_leave_critical_section(dev);
  92            return;
  93        }
  94        wd->tid_rx[i]->aid = ZM_MAX_STA_SUPPORT;
  95        wd->tid_rx[i]->seq_start = wd->tid_rx[i]->baw_head = \
  96        wd->tid_rx[i]->baw_tail = 0;
  97        wd->tid_rx[i]->sq_exceed_count = wd->tid_rx[i]->sq_behind_count = 0;
  98        for (j=0; j<=ZM_AGG_BAW_SIZE; j++)
  99            wd->tid_rx[i]->frame[j].buf = 0;
 100        /*
 101         * reset ADDBA exchange status code
 102         * 0: NULL
 103         * 1: ADDBA Request sent/received
 104         * 2: ACK for ADDBA Request sent/received
 105         * 3: ADDBA Response sent/received
 106         * 4: ACK for ADDBA Response sent/received
 107         */
 108        wd->tid_rx[i]->addBaExchangeStatusCode = 0;
 109
 110    }
 111    zmw_leave_critical_section(dev);
 112    zfAggTallyReset(dev);
 113    DESTQ.init = zfAggDestInit;
 114    DESTQ.init(dev);
 115    wd->aggInitiated = 1;
 116    aggr_count = 0;
 117    success_mpdu = 0;
 118    total_mpdu = 0;
 119#ifdef ZM_ENABLE_AGGREGATION
 120#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
 121    BAW = zfwMemAllocate(dev, sizeof(struct baw_enabler));
 122    if(!BAW)
 123    {
 124        return;
 125    }
 126    BAW->init = zfBawInit;
 127    BAW->init(dev);
 128#endif //disable BAW
 129#endif
 130}
 131
 132/************************************************************************/
 133/*                                                                      */
 134/*    FUNCTION DESCRIPTION                  zfAggGetSta                 */
 135/*      return STA AID.                                                 */
 136/*      take buf as input, use the dest address of buf as index to      */
 137/*      search STA AID.                                                 */
 138/*                                                                      */
 139/*    INPUTS                                                            */
 140/*      dev : device pointer                                            */
 141/*      buf : buffer for one particular packet                          */
 142/*                                                                      */
 143/*    OUTPUTS                                                           */
 144/*      AID                                                             */
 145/*                                                                      */
 146/*    AUTHOR                                                            */
 147/*      Honda               ZyDAS Technology Corporation    2006.11     */
 148/*                                                                      */
 149/************************************************************************/
 150
 151
 152
 153u16_t zfAggGetSta(zdev_t* dev, zbuf_t* buf)
 154{
 155    u16_t id;
 156    u16_t dst[3];
 157
 158    zmw_get_wlan_dev(dev);
 159
 160    zmw_declare_for_critical_section();
 161
 162    dst[0] = zmw_rx_buf_readh(dev, buf, 0);
 163    dst[1] = zmw_rx_buf_readh(dev, buf, 2);
 164    dst[2] = zmw_rx_buf_readh(dev, buf, 4);
 165
 166    zmw_enter_critical_section(dev);
 167
 168    if(wd->wlanMode == ZM_MODE_AP) {
 169        id = zfApFindSta(dev, dst);
 170    }
 171    else {
 172        id = 0;
 173    }
 174    zmw_leave_critical_section(dev);
 175
 176#if ZM_AGG_FPGA_DEBUG
 177    id = 0;
 178#endif
 179
 180    return id;
 181}
 182
 183
 184/************************************************************************/
 185/*                                                                      */
 186/*    FUNCTION DESCRIPTION                  zfAggTxGetQueue             */
 187/*      return Queue Pool index.                                        */
 188/*      take aid as input, look for the queue index associated          */
 189/*      with this aid.                                                  */
 190/*                                                                      */
 191/*    INPUTS                                                            */
 192/*      dev : device pointer                                            */
 193/*      aid : associated id                                             */
 194/*                                                                      */
 195/*    OUTPUTS                                                           */
 196/*      Queue number                                                    */
 197/*                                                                      */
 198/*    AUTHOR                                                            */
 199/*      Honda               ZyDAS Technology Corporation    2006.11     */
 200/*                                                                      */
 201/************************************************************************/
 202TID_TX zfAggTxGetQueue(zdev_t* dev, u16_t aid, u16_t tid)
 203{
 204    //u16_t   i;
 205    TID_TX  tid_tx;
 206    zmw_get_wlan_dev(dev);
 207
 208    //zmw_declare_for_critical_section();
 209
 210    /*
 211     * not a STA aid
 212     */
 213    if (0xffff == aid)
 214        return NULL;
 215
 216    //zmw_enter_critical_section(dev);
 217
 218    tid_tx = wd->aggSta[aid].tid_tx[tid];
 219    if (!tid_tx) return NULL;
 220    if (0 == tid_tx->aggQEnabled)
 221        return NULL;
 222
 223    //zmw_leave_critical_section(dev);
 224
 225    return tid_tx;
 226}
 227
 228/************************************************************************/
 229/*                                                                      */
 230/*    FUNCTION DESCRIPTION                  zfAggTxNewQueue             */
 231/*      return Queue Pool index.                                        */
 232/*      take aid as input, find a new queue for this aid.               */
 233/*                                                                      */
 234/*    INPUTS                                                            */
 235/*      dev : device pointer                                            */
 236/*      aid : associated id                                             */
 237/*                                                                      */
 238/*    OUTPUTS                                                           */
 239/*      Queue number                                                    */
 240/*                                                                      */
 241/*    AUTHOR                                                            */
 242/*      Honda               ZyDAS Technology Corporation    2006.12     */
 243/*                                                                      */
 244/************************************************************************/
 245TID_TX zfAggTxNewQueue(zdev_t* dev, u16_t aid, u16_t tid, zbuf_t* buf)
 246{
 247    u16_t   i;
 248    TID_TX  tid_tx=NULL;
 249    u16_t   ac = zcUpToAc[tid&0x7] & 0x3;
 250    zmw_get_wlan_dev(dev);
 251
 252    zmw_declare_for_critical_section();
 253
 254    /*
 255     * not a STA aid
 256     */
 257    if (0xffff == aid)
 258        return NULL;
 259
 260    zmw_enter_critical_section(dev);
 261
 262    /*
 263     * find one new queue for sta
 264     */
 265    for (i=0; i<ZM_AGG_POOL_SIZE; i++)
 266    {
 267        if (wd->aggQPool[i]->aggQEnabled)
 268        {
 269                /*
 270                 * this q is enabled
 271                 */
 272        }
 273        else
 274        {
 275            tid_tx = wd->aggQPool[i];
 276            tid_tx->aggQEnabled = 1;
 277            tid_tx->aggQSTA = aid;
 278            tid_tx->ac = ac;
 279            tid_tx->tid = tid;
 280            tid_tx->aggHead = tid_tx->aggTail = tid_tx->size = 0;
 281            tid_tx->aggReady = 0;
 282            wd->aggSta[aid].tid_tx[tid] = tid_tx;
 283            tid_tx->dst[0] = zmw_rx_buf_readh(dev, buf, 0);
 284            tid_tx->dst[1] = zmw_rx_buf_readh(dev, buf, 2);
 285            tid_tx->dst[2] = zmw_rx_buf_readh(dev, buf, 4);
 286            break;
 287        }
 288    }
 289
 290    zmw_leave_critical_section(dev);
 291
 292    return tid_tx;
 293}
 294
 295
 296
 297/************************************************************************/
 298/*                                                                      */
 299/*    FUNCTION DESCRIPTION                  zfAggTxEnqueue              */
 300/*      return Status code ZM_SUCCESS or error code                     */
 301/*      take (aid,ac,qnum,buf) as input                                 */
 302/*                                                                      */
 303/*    INPUTS                                                            */
 304/*      dev : device pointer                                            */
 305/*      aid : associated id                                             */
 306/*      ac  : access category                                           */
 307/*      qnum: the queue number to which will be enqueued                */
 308/*      buf : the packet to be queued                                   */
 309/*                                                                      */
 310/*    OUTPUTS                                                           */
 311/*      status code                                                     */
 312/*                                                                      */
 313/*    AUTHOR                                                            */
 314/*      Honda               Atheros Communications, INC.    2006.12     */
 315/*                                                                      */
 316/************************************************************************/
 317u16_t zfAggTxEnqueue(zdev_t* dev, zbuf_t* buf, u16_t aid, TID_TX tid_tx)
 318{
 319    //u16_t   qlen, frameLen;
 320    u32_t   time;
 321
 322    zmw_get_wlan_dev(dev);
 323
 324    zmw_declare_for_critical_section();
 325
 326    zmw_enter_critical_section(dev);
 327
 328    tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
 329
 330    if (tid_tx->size < (ZM_AGGQ_SIZE - 2))
 331    {
 332        /* Queue not full */
 333
 334
 335        /*
 336         * buffer copy
 337         * in zfwBufFree will return a ndismsendcomplete
 338         * to resolve the synchronize problem in aggregate
 339         */
 340
 341        u8_t    sendComplete = 0;
 342
 343        tid_tx->aggvtxq[tid_tx->aggHead].buf = buf;
 344        time = zm_agg_GetTime();
 345        tid_tx->aggvtxq[tid_tx->aggHead].arrivalTime = time;
 346        tid_tx->aggvtxq[tid_tx->aggHead].baw_retransmit = 0;
 347
 348        tid_tx->aggHead = ((tid_tx->aggHead + 1) & ZM_AGGQ_SIZE_MASK);
 349        tid_tx->lastArrival = time;
 350        tid_tx->size++;
 351        tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
 352        if (buf && (tid_tx->size < (ZM_AGGQ_SIZE - 10))) {
 353            tid_tx->complete = tid_tx->aggHead;
 354            sendComplete = 1;
 355        }
 356        zmw_leave_critical_section(dev);
 357
 358        if (!DESTQ.exist(dev, 0, tid_tx->ac, tid_tx, NULL)) {
 359            DESTQ.insert(dev, 0, tid_tx->ac, tid_tx, NULL);
 360        }
 361
 362        zm_msg1_agg(ZM_LV_0, "tid_tx->size=", tid_tx->size);
 363        //zm_debug_msg1("tid_tx->size=", tid_tx->size);
 364
 365        if (buf && sendComplete && wd->zfcbSendCompleteIndication) {
 366            //zmw_leave_critical_section(dev);
 367            wd->zfcbSendCompleteIndication(dev, buf);
 368        }
 369
 370        /*if (tid_tx->size >= 16 && zfHpGetFreeTxdCount(dev) > 20)
 371            zfAggTxSend(dev, zfHpGetFreeTxdCount(dev), tid_tx);
 372        */
 373        return ZM_SUCCESS;
 374    }
 375    else
 376    {
 377        zm_msg1_agg(ZM_LV_0, "can't enqueue, tid_tx->size=", tid_tx->size);
 378        /*
 379         * Queue Full
 380         */
 381
 382        /*
 383         * zm_msg1_agg(ZM_LV_0, "Queue full, qnum = ", qnum);
 384         * wd->commTally.txQosDropCount[ac]++;
 385         * zfwBufFree(dev, buf, ZM_SUCCESS);
 386         * zm_msg1_agg(ZM_LV_1, "Packet discarded, VTXQ full, ac=", ac);
 387         *
 388         * return ZM_ERR_EXCEED_PRIORITY_THRESHOLD;
 389         */
 390    }
 391
 392    zmw_leave_critical_section(dev);
 393
 394    if (!DESTQ.exist(dev, 0, tid_tx->ac, tid_tx, NULL)) {
 395            DESTQ.insert(dev, 0, tid_tx->ac, tid_tx, NULL);
 396    }
 397
 398    return ZM_ERR_EXCEED_PRIORITY_THRESHOLD;
 399}
 400
 401u16_t    zfAggDestExist(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq) {
 402    struct dest* dest;
 403    u16_t   exist = 0;
 404    zmw_get_wlan_dev(dev);
 405
 406    zmw_declare_for_critical_section();
 407
 408    zmw_enter_critical_section(dev);
 409    if (!DESTQ.Head[ac]) {
 410        exist = 0;
 411    }
 412    else {
 413        dest = DESTQ.Head[ac];
 414        if (dest->tid_tx == tid_tx) {
 415            exist = 1;
 416        }
 417        else {
 418            while (dest->next != DESTQ.Head[ac]) {
 419                dest = dest->next;
 420                if (dest->tid_tx == tid_tx){
 421                    exist = 1;
 422                    break;
 423                }
 424            }
 425        }
 426    }
 427
 428    zmw_leave_critical_section(dev);
 429
 430    return exist;
 431}
 432
 433void    zfAggDestInsert(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq)
 434{
 435    struct dest* new_dest;
 436    zmw_get_wlan_dev(dev);
 437
 438    zmw_declare_for_critical_section();
 439
 440    new_dest = zfwMemAllocate(dev, sizeof(struct dest));
 441    if(!new_dest)
 442    {
 443        return;
 444    }
 445    new_dest->Qtype = Qtype;
 446    new_dest->tid_tx = tid_tx;
 447    if (0 == Qtype)
 448        new_dest->tid_tx = tid_tx;
 449    else
 450        new_dest->vtxq = vtxq;
 451    if (!DESTQ.Head[ac]) {
 452
 453        zmw_enter_critical_section(dev);
 454        new_dest->next = new_dest;
 455        DESTQ.Head[ac] = DESTQ.dest[ac] = new_dest;
 456        zmw_leave_critical_section(dev);
 457    }
 458    else {
 459
 460        zmw_enter_critical_section(dev);
 461        new_dest->next = DESTQ.dest[ac]->next;
 462        DESTQ.dest[ac]->next = new_dest;
 463        zmw_leave_critical_section(dev);
 464    }
 465
 466
 467    //DESTQ.size[ac]++;
 468    return;
 469}
 470
 471void    zfAggDestDelete(zdev_t* dev, u16_t Qtype, TID_TX tid_tx, void* vtxq)
 472{
 473    struct dest* dest, *temp;
 474    u16_t   i;
 475
 476    zmw_get_wlan_dev(dev);
 477
 478    zmw_declare_for_critical_section();
 479
 480    zmw_enter_critical_section(dev);
 481    if (wd->destLock) {
 482        zmw_leave_critical_section(dev);
 483        return;
 484    }
 485
 486
 487    //zmw_declare_for_critical_section();
 488    for (i=0; i<4; i++) {
 489        if (!DESTQ.Head[i]) continue;
 490        dest = DESTQ.Head[i];
 491        if (!dest) continue;
 492
 493
 494        while (dest && (dest->next != DESTQ.Head[i])) {
 495            if (Qtype == 0 && dest->next->tid_tx == tid_tx){
 496                break;
 497            }
 498            if (Qtype == 1 && dest->next->vtxq == vtxq) {
 499                break;
 500            }
 501            dest = dest->next;
 502        }
 503
 504        if ((Qtype == 0 && dest->next->tid_tx == tid_tx) || (Qtype == 1 && dest->next->vtxq == vtxq)) {
 505
 506            tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
 507            if (tid_tx->size) {
 508                zmw_leave_critical_section(dev);
 509                return;
 510            }
 511            if (!DESTQ.Head[i]) {
 512                temp = NULL;
 513            }
 514            else {
 515                temp = dest->next;
 516                if (temp == dest) {
 517                    DESTQ.Head[i] = DESTQ.dest[i] = NULL;
 518                    //DESTQ.size[i] = 0;
 519                }
 520                else {
 521                    dest->next = dest->next->next;
 522                }
 523            }
 524
 525            if (temp == NULL)
 526                {/* do nothing */} //zfwMemFree(dev, temp, sizeof(struct dest));
 527            else
 528                zfwMemFree(dev, temp, sizeof(struct dest));
 529
 530            /*zmw_enter_critical_section(dev);
 531            if (DESTQ.size[i] > 0)
 532                DESTQ.size[i]--;
 533            zmw_leave_critical_section(dev);
 534            */
 535        }
 536
 537    }
 538    zmw_leave_critical_section(dev);
 539    return;
 540}
 541
 542void    zfAggDestInit(zdev_t* dev)
 543{
 544    u16_t i;
 545    zmw_get_wlan_dev(dev);
 546
 547    //zmw_declare_for_critical_section();
 548
 549    for (i=0; i<4; i++) {
 550        //wd->destQ.Head[i].next = wd->destQ.Head[i];
 551        //wd->destQ.dest[i] = wd->destQ.Head[i];
 552        //DESTQ.size[i] = 0;
 553        DESTQ.Head[i] = NULL;
 554    }
 555    DESTQ.insert  = zfAggDestInsert;
 556    DESTQ.delete  = zfAggDestDelete;
 557    DESTQ.init    = zfAggDestInit;
 558    DESTQ.getNext = zfAggDestGetNext;
 559    DESTQ.exist   = zfAggDestExist;
 560    DESTQ.ppri = 0;
 561    return;
 562}
 563
 564struct dest* zfAggDestGetNext(zdev_t* dev, u16_t ac)
 565{
 566    struct dest *dest = NULL;
 567    zmw_get_wlan_dev(dev);
 568
 569    zmw_declare_for_critical_section();
 570
 571    zmw_enter_critical_section(dev);
 572    if (DESTQ.dest[ac]) {
 573        dest = DESTQ.dest[ac];
 574        DESTQ.dest[ac] = DESTQ.dest[ac]->next;
 575    }
 576    else {
 577        dest = NULL;
 578    }
 579    zmw_leave_critical_section(dev);
 580
 581    return dest;
 582}
 583
 584#ifdef ZM_ENABLE_AGGREGATION
 585#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
 586u16_t   zfAggTidTxInsertHead(zdev_t* dev, struct bufInfo *buf_info,TID_TX tid_tx)
 587{
 588    zbuf_t* buf;
 589    u32_t time;
 590    struct baw_header *baw_header;
 591
 592    zmw_get_wlan_dev(dev);
 593
 594    zmw_declare_for_critical_section();
 595
 596
 597    buf = buf_info->buf;
 598
 599    zmw_enter_critical_section(dev);
 600    tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
 601    zmw_leave_critical_section(dev);
 602
 603    if (tid_tx->size >= (ZM_AGGQ_SIZE - 2)) {
 604        zfwBufFree(dev, buf, ZM_SUCCESS);
 605        return 0;
 606    }
 607
 608    zmw_enter_critical_section(dev);
 609    tid_tx->aggTail = (tid_tx->aggTail == 0)? ZM_AGGQ_SIZE_MASK: tid_tx->aggTail - 1;
 610    tid_tx->aggvtxq[tid_tx->aggTail].buf = buf;
 611    //time = zm_agg_GetTime();
 612    tid_tx->aggvtxq[tid_tx->aggTail].arrivalTime = buf_info->timestamp;
 613    tid_tx->aggvtxq[tid_tx->aggTail].baw_retransmit = buf_info->baw_retransmit;
 614
 615    baw_header = &tid_tx->aggvtxq[tid_tx->aggTail].baw_header;
 616    baw_header->headerLen   = buf_info->baw_header->headerLen;
 617    baw_header->micLen      = buf_info->baw_header->micLen;
 618    baw_header->snapLen     = buf_info->baw_header->snapLen;
 619    baw_header->removeLen   = buf_info->baw_header->removeLen;
 620    baw_header->keyIdx      = buf_info->baw_header->keyIdx;
 621    zfwMemoryCopy((u8_t *)baw_header->header, (u8_t *)buf_info->baw_header->header, 58);
 622    zfwMemoryCopy((u8_t *)baw_header->mic   , (u8_t *)buf_info->baw_header->mic   , 8);
 623    zfwMemoryCopy((u8_t *)baw_header->snap  , (u8_t *)buf_info->baw_header->snap  , 8);
 624
 625    tid_tx->size++;
 626    tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
 627    zmw_leave_critical_section(dev);
 628
 629    //tid_tx->lastArrival = time;
 630    if (1 == tid_tx->size) {
 631        DESTQ.insert(dev, 0, tid_tx->ac, tid_tx, NULL);
 632    }
 633
 634
 635    zm_msg1_agg(ZM_LV_0, "0xC2:insertHead, tid_tx->size=", tid_tx->size);
 636
 637    return TRUE;
 638}
 639#endif //disable BAW
 640#endif
 641
 642void    zfiTxComplete(zdev_t* dev)
 643{
 644
 645    zmw_get_wlan_dev(dev);
 646
 647    //zmw_declare_for_critical_section();
 648
 649    if( (wd->wlanMode == ZM_MODE_AP) ||
 650        (wd->wlanMode == ZM_MODE_INFRASTRUCTURE && wd->sta.EnableHT) ||
 651        (wd->wlanMode == ZM_MODE_PSEUDO) ) {
 652        zfAggTxScheduler(dev, 0);
 653    }
 654
 655    return;
 656}
 657
 658TID_TX  zfAggTxReady(zdev_t* dev) {
 659    //struct dest* dest;
 660    u16_t   i;
 661    TID_TX  tid_tx = NULL;
 662    zmw_get_wlan_dev(dev);
 663
 664    zmw_declare_for_critical_section();
 665
 666    zmw_enter_critical_section(dev);
 667    for (i=0; i<ZM_AGG_POOL_SIZE; i++)
 668    {
 669        if (wd->aggQPool[i]->aggQEnabled)
 670        {
 671            if (wd->aggQPool[i]->size >= 16) {
 672                tid_tx = wd->aggQPool[i];
 673                break;
 674            }
 675        }
 676        else {
 677        }
 678    }
 679    zmw_leave_critical_section(dev);
 680    return tid_tx;
 681}
 682
 683u16_t   zfAggValidTidTx(zdev_t* dev, TID_TX tid_tx) {
 684    u16_t   i, valid = 0;
 685    zmw_get_wlan_dev(dev);
 686
 687    zmw_declare_for_critical_section();
 688
 689    zmw_enter_critical_section(dev);
 690    for (i=0; i<ZM_AGG_POOL_SIZE; i++)
 691    {
 692        if (wd->aggQPool[i] == tid_tx)
 693        {
 694            valid = 1;
 695            break;
 696        }
 697        else {
 698        }
 699    }
 700    zmw_leave_critical_section(dev);
 701
 702    return valid;
 703}
 704
 705void    zfAggTxScheduler(zdev_t* dev, u8_t ScanAndClear)
 706{
 707    TID_TX  tid_tx = NULL;
 708    void*   vtxq;
 709    struct dest* dest;
 710    zbuf_t*  buf;
 711    u32_t txql, min_txql;
 712    //u16_t aggr_size = 1;
 713    u16_t txq_threshold;
 714    zmw_get_wlan_dev(dev);
 715
 716    zmw_declare_for_critical_section();
 717
 718    if (!wd->aggInitiated)
 719    {
 720        return;
 721    }
 722
 723    /* debug */
 724    txql = TXQL;
 725    min_txql = AGG_MIN_TXQL;
 726
 727    if(wd->txq_threshold)
 728        txq_threshold = wd->txq_threshold;
 729    else
 730        txq_threshold = AGG_MIN_TXQL;
 731
 732    tid_tx = zfAggTxReady(dev);
 733    if (tid_tx) ScanAndClear = 0;
 734    while (zfHpGetFreeTxdCount(dev) > 20 && (TXQL < txq_threshold || tid_tx)) {
 735    //while (zfHpGetFreeTxdCount(dev) > 20 && (ScanAndClear || tid_tx)) {
 736    //while (TXQL < txq_threshold) {
 737        u16_t i;
 738        u8_t ac;
 739        s8_t destQ_count = 0;
 740    //while ((zfHpGetFreeTxdCount(dev)) > 32) {
 741
 742        //DbgPrint("zfAggTxScheduler: in while loop");
 743        for (i=0; i<4; i++) {
 744            if (DESTQ.Head[i]) destQ_count++;
 745        }
 746        if (0 >= destQ_count) break;
 747
 748        zmw_enter_critical_section(dev);
 749        ac = pri[DESTQ.ppri]; DESTQ.ppri = (DESTQ.ppri + 1) % 10;
 750        zmw_leave_critical_section(dev);
 751
 752        for (i=0; i<10; i++){
 753            if(DESTQ.Head[ac]) break;
 754
 755            zmw_enter_critical_section(dev);
 756            ac = pri[DESTQ.ppri]; DESTQ.ppri = (DESTQ.ppri + 1) % 10;
 757            zmw_leave_critical_section(dev);
 758        }
 759        if (i == 10) break;
 760        //DbgPrint("zfAggTxScheduler: have dest Q");
 761        zmw_enter_critical_section(dev);
 762        wd->destLock = 1;
 763        zmw_leave_critical_section(dev);
 764
 765        dest = DESTQ.getNext(dev, ac);
 766        if (!dest) {
 767            zmw_enter_critical_section(dev);
 768            wd->destLock = 0;
 769            zmw_leave_critical_section(dev);
 770
 771            DbgPrint("bug report! DESTQ.getNext got nothing!");
 772            break;
 773        }
 774        if (dest->Qtype == 0) {
 775            tid_tx = dest->tid_tx;
 776
 777            //DbgPrint("zfAggTxScheduler: have tid_tx Q");
 778
 779            if(tid_tx && zfAggValidTidTx(dev, tid_tx))
 780                tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
 781            else {
 782                zmw_enter_critical_section(dev);
 783                wd->destLock = 0;
 784                zmw_leave_critical_section(dev);
 785
 786                tid_tx = zfAggTxReady(dev);
 787                continue;
 788            }
 789
 790            zmw_enter_critical_section(dev);
 791            wd->destLock = 0;
 792            zmw_leave_critical_section(dev);
 793            //zmw_enter_critical_section(dev);
 794            if (tid_tx && !tid_tx->size) {
 795
 796                //zmw_leave_critical_section(dev);
 797                //DESTQ.delete(dev, 0, tid_tx, NULL);
 798            }
 799            else if(wd->aggState == 0){
 800                //wd->aggState = 1;
 801                //zmw_leave_critical_section(dev);
 802                zfAggTxSend(dev, zfHpGetFreeTxdCount(dev), tid_tx);
 803                //wd->aggState = 0;
 804            }
 805            else {
 806                //zmw_leave_critical_section(dev);
 807                break;
 808            }
 809        }
 810        else {
 811            vtxq = dest->vtxq;
 812            buf = zfGetVtxq(dev, ac);
 813            zm_assert( buf != 0 );
 814
 815            zfTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
 816
 817        }
 818        /*flush all but < 16 frames in tid_tx to TXQ*/
 819        tid_tx = zfAggTxReady(dev);
 820    }
 821
 822    /*while ((zfHpGetFreeTxdCount(dev)) > 32) {
 823    //while ((zfHpGetFreeTxdCount(dev)) > 32) {
 824
 825        destQ_count = 0;
 826        for (i=0; i<4; i++) destQ_count += wd->destQ.size[i];
 827        if (0 >= destQ_count) break;
 828
 829        ac = pri[wd->destQ.ppri]; wd->destQ.ppri = (wd->destQ.ppri + 1) % 10;
 830        for (i=0; i<10; i++){
 831            if(wd->destQ.size[ac]!=0) break;
 832            ac = pri[wd->destQ.ppri]; wd->destQ.ppri = (wd->destQ.ppri + 1) % 10;
 833        }
 834        if (i == 10) break;
 835        dest = wd->destQ.getNext(dev, ac);
 836        if (dest->Qtype == 0) {
 837            tid_tx = dest->tid_tx;
 838            tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
 839            if (!tid_tx->size) {
 840                wd->destQ.delete(dev, 0, tid_tx, NULL);
 841                break;
 842            }
 843            else if((wd->aggState == 0) && (tid_tx->size >= 16)){
 844                zfAggTxSend(dev, zfHpGetFreeTxdCount(dev), tid_tx);
 845            }
 846            else {
 847                break;
 848            }
 849        }
 850
 851    }
 852    */
 853    return;
 854}
 855
 856/************************************************************************/
 857/*                                                                      */
 858/*    FUNCTION DESCRIPTION                  zfAggTx                     */
 859/*      return Status code ZM_SUCCESS or error code                     */
 860/*      management A-MPDU aggregation function,                         */
 861/*      management aggregation queue, calculate arrivalrate,            */
 862/*      add/delete an aggregation queue of a stream,                    */
 863/*      enqueue packets into responsible aggregate queue.               */
 864/*      take (dev, buf, ac) as input                                    */
 865/*                                                                      */
 866/*    INPUTS                                                            */
 867/*      dev : device pointer                                            */
 868/*      buf : packet buff                                               */
 869/*      ac  : access category                                           */
 870/*                                                                      */
 871/*    OUTPUTS                                                           */
 872/*      status code                                                     */
 873/*                                                                      */
 874/*    AUTHOR                                                            */
 875/*      Honda               Atheros Communications, INC.    2006.12     */
 876/*                                                                      */
 877/************************************************************************/
 878u16_t zfAggTx(zdev_t* dev, zbuf_t* buf, u16_t tid)
 879{
 880    u16_t aid;
 881    //u16_t qnum;
 882    //u16_t aggflag = 0;
 883    //u16_t arrivalrate = 0;
 884    TID_TX tid_tx;
 885
 886    zmw_get_wlan_dev(dev);
 887
 888    zmw_declare_for_critical_section();
 889
 890    if(!wd->aggInitiated)
 891    {
 892        return ZM_ERR_TX_BUFFER_UNAVAILABLE;
 893    }
 894
 895    aid = zfAggGetSta(dev, buf);
 896
 897    //arrivalrate = zfAggTxArrivalRate(dev, aid, tid);
 898
 899    if (0xffff == aid)
 900    {
 901        /*
 902         * STA not associated, this is a BC/MC or STA->AP packet
 903         */
 904
 905        return ZM_ERR_TX_BUFFER_UNAVAILABLE;
 906    }
 907
 908    /*
 909     * STA associated, a unicast packet
 910     */
 911
 912    tid_tx = zfAggTxGetQueue(dev, aid, tid);
 913
 914    /*tid_q.tid_tx = tid_tx;
 915    wd->destQ.insert = zfAggDestInsert;
 916    wd->destQ.insert(dev, 0, tid_q);
 917    */
 918    if (tid_tx != NULL)
 919    {
 920        /*
 921         * this (aid, ac) is aggregated
 922         */
 923
 924        //if (arrivalrate < ZM_AGG_LOW_THRESHOLD)
 925        if (0)
 926        {
 927            /*
 928             * arrival rate too low
 929             * delete this aggregate queue
 930             */
 931
 932            zmw_enter_critical_section(dev);
 933
 934            //wd->aggQPool[qnum]->clearFlag = wd->aggQPool[qnum]->deleteFlag =1;
 935
 936            zmw_leave_critical_section(dev);
 937
 938        }
 939
 940        return zfAggTxEnqueue(dev, buf, aid, tid_tx);
 941
 942    }
 943    else
 944    {
 945        /*
 946         * this (aid, ac) not yet aggregated
 947         * queue not found
 948         */
 949
 950        //if (arrivalrate > ZM_AGG_HIGH_THRESHOLD)
 951        if (1)
 952        {
 953            /*
 954             * arrivalrate high enough to get a new agg queue
 955             */
 956
 957            tid_tx = zfAggTxNewQueue(dev, aid, tid, buf);
 958
 959            //zm_msg1_agg(ZM_LV_0, "get new AggQueue qnum = ", tid_tx->);
 960
 961            if (tid_tx)
 962            {
 963                /*
 964                 * got a new aggregate queue
 965                 */
 966
 967                //zmw_enter_critical_section(dev);
 968
 969                //wd->aggSta[aid].aggFlag[ac] = 1;
 970
 971                //zmw_leave_critical_section(dev);
 972
 973                /*
 974                 * add ADDBA functions here
 975                 * return ZM_ERR_TX_BUFFER_UNAVAILABLE;
 976                 */
 977
 978
 979                //zfAggSendAddbaRequest(dev, tid_tx->dst, tid_tx->ac, tid_tx->tid);
 980                //zmw_enter_critical_section(dev);
 981
 982                //wd->aggSta[aid].aggFlag[ac] = 0;
 983
 984                //zmw_leave_critical_section(dev);
 985
 986                return zfAggTxEnqueue(dev, buf, aid, tid_tx);
 987
 988            }
 989            else
 990            {
 991                /*
 992                 * just can't get a new aggregate queue
 993                 */
 994
 995                return ZM_ERR_TX_BUFFER_UNAVAILABLE;
 996            }
 997        }
 998        else
 999        {
1000            /*
1001             * arrival rate is not high enough to get a new agg queue
1002             */
1003
1004            return ZM_ERR_TX_BUFFER_UNAVAILABLE;
1005        }
1006    }
1007
1008
1009
1010}
1011
1012
1013/************************************************************************/
1014/*                                                                      */
1015/*    FUNCTION DESCRIPTION                  zfAggTxReadyCount           */
1016/*      return counter of ready to aggregate queues.                    */
1017/*      take (dev, ac) as input, only calculate the ready to aggregate  */
1018/*      queues of one particular ac.                                    */
1019/*                                                                      */
1020/*    INPUTS                                                            */
1021/*      dev : device pointer                                            */
1022/*      ac  : access category                                           */
1023/*                                                                      */
1024/*    OUTPUTS                                                           */
1025/*      counter of ready to aggregate queues                            */
1026/*                                                                      */
1027/*    AUTHOR                                                            */
1028/*      Honda               Atheros Communications, INC.    2006.12     */
1029/*                                                                      */
1030/************************************************************************/
1031u16_t zfAggTxReadyCount(zdev_t* dev, u16_t ac)
1032{
1033    u16_t i;
1034    u16_t readycount = 0;
1035
1036    zmw_get_wlan_dev(dev);
1037
1038    zmw_declare_for_critical_section();
1039
1040    zmw_enter_critical_section(dev);
1041
1042    for (i=0 ; i<ZM_AGG_POOL_SIZE; i++)
1043    {
1044        if (wd->aggQPool[i]->aggQEnabled && (wd->aggQPool[i]->aggReady || \
1045                wd->aggQPool[i]->clearFlag) && ac == wd->aggQPool[i]->ac)
1046            readycount++;
1047    }
1048
1049    zmw_leave_critical_section(dev);
1050
1051    return readycount;
1052}
1053
1054/************************************************************************/
1055/*                                                                      */
1056/*    FUNCTION DESCRIPTION                  zfAggTxPartial              */
1057/*      return the number that Vtxq has to send.                        */
1058/*      take (dev, ac, readycount) as input, calculate the ratio of     */
1059/*      Vtxq length to (Vtxq length + readycount) of a particular ac,   */
1060/*      and returns the Vtxq length * the ratio                         */
1061/*                                                                      */
1062/*    INPUTS                                                            */
1063/*      dev : device pointer                                            */
1064/*      ac  : access category                                           */
1065/*      readycount: the number of ready to aggregate queues of this ac  */
1066/*                                                                      */
1067/*    OUTPUTS                                                           */
1068/*      Vtxq length * ratio                                             */
1069/*                                                                      */
1070/*    AUTHOR                                                            */
1071/*      Honda               Atheros Communications, INC.    2006.12     */
1072/*                                                                      */
1073/************************************************************************/
1074u16_t zfAggTxPartial(zdev_t* dev, u16_t ac, u16_t readycount)
1075{
1076    u16_t qlen;
1077    u16_t partial;
1078
1079    zmw_get_wlan_dev(dev);
1080
1081    zmw_declare_for_critical_section();
1082
1083    zmw_enter_critical_section(dev);
1084
1085    qlen = zm_agg_qlen(dev, wd->vtxqHead[ac], wd->vtxqTail[ac]);
1086
1087    if ((qlen + readycount) > 0)
1088    {
1089        partial = (u16_t)( zm_agg_weight(ac) * ((u16_t)qlen/(qlen + \
1090                        readycount)) );
1091    }
1092    else
1093    {
1094        partial = 0;
1095    }
1096
1097    zmw_leave_critical_section(dev);
1098
1099    if (partial > qlen)
1100        partial = qlen;
1101
1102    return partial;
1103}
1104
1105
1106/************************************************************************/
1107/*                                                                      */
1108/*    FUNCTION DESCRIPTION                  zfAggTxSend                 */
1109/*      return sentcount                                                */
1110/*      take (dev, ac, n) as input, n is the number of scheduled agg    */
1111/*      queues to be sent of the particular ac.                         */
1112/*                                                                      */
1113/*    INPUTS                                                            */
1114/*      dev : device pointer                                            */
1115/*      ac  : access category                                           */
1116/*      n   : the number of scheduled aggregation queues to be sent     */
1117/*                                                                      */
1118/*    OUTPUTS                                                           */
1119/*      sentcount                                                       */
1120/*                                                                      */
1121/*    AUTHOR                                                            */
1122/*      Honda               Atheros Communications, INC.    2006.12     */
1123/*                                                                      */
1124/************************************************************************/
1125u16_t zfAggTxSend(zdev_t* dev, u32_t freeTxd, TID_TX tid_tx)
1126{
1127    //u16_t   qnum;
1128    //u16_t   qlen;
1129    u16_t   j;
1130    //u16_t   sentcount = 0;
1131    zbuf_t* buf;
1132    struct  aggControl aggControl;
1133    u16_t   aggLen;
1134    //zbuf_t*  newBuf;
1135    //u16_t   bufLen;
1136    //TID_BAW tid_baw = NULL;
1137    //struct bufInfo *buf_info;
1138
1139    zmw_get_wlan_dev(dev);
1140
1141    zmw_declare_for_critical_section();
1142
1143    //while (tid_tx->size > 0)
1144
1145    zmw_enter_critical_section(dev);
1146    tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
1147    aggLen = zm_agg_min(16, zm_agg_min(tid_tx->size, (u16_t)(freeTxd - 2)));
1148    zmw_leave_critical_section(dev);
1149
1150            /*
1151             * why there have to be 2 free Txd?
1152             */
1153    if (aggLen <=0 )
1154        return 0;
1155
1156
1157    if (aggLen == 1) {
1158        buf = zfAggTxGetVtxq(dev, tid_tx);
1159        if (buf)
1160            zfTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
1161        if (tid_tx->size == 0) {
1162            //DESTQ.delete(dev, 0, tid_tx, NULL);
1163        }
1164
1165        return 1;
1166    }
1167                /*
1168                 * Free Txd queue is big enough to put aggregation
1169                 */
1170    zmw_enter_critical_section(dev);
1171    if (wd->aggState == 1) {
1172        zmw_leave_critical_section(dev);
1173        return 0;
1174    }
1175    wd->aggState = 1;
1176    zmw_leave_critical_section(dev);
1177
1178
1179    zm_msg1_agg(ZM_LV_0, "aggLen=", aggLen);
1180    tid_tx->aggFrameSize = 0;
1181    for (j=0; j < aggLen; j++) {
1182        buf = zfAggTxGetVtxq(dev, tid_tx);
1183
1184        zmw_enter_critical_section(dev);
1185        tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
1186        zmw_leave_critical_section(dev);
1187
1188        if ( buf ) {
1189            //struct aggTally *agg_tal;
1190            u16_t completeIndex;
1191
1192            if (0 == j) {
1193                aggControl.ampduIndication = ZM_AGG_FIRST_MPDU;
1194
1195            }
1196            else if ((j == (aggLen - 1)) || tid_tx->size == 0)
1197            {
1198                aggControl.ampduIndication = ZM_AGG_LAST_MPDU;
1199                //wd->aggState = 0;
1200
1201            }
1202            else
1203            {
1204                aggControl.ampduIndication = ZM_AGG_MIDDLE_MPDU;
1205                /* the packet is delayed more than 500 ms, drop it */
1206
1207            }
1208            tid_tx->aggFrameSize += zfwBufGetSize(dev, buf);
1209            aggControl.addbaIndication = 0;
1210            aggControl.aggEnabled = 1;
1211
1212#ifdef ZM_AGG_TALLY
1213            agg_tal = &wd->agg_tal;
1214            agg_tal->sent_packets_sum++;
1215
1216#endif
1217
1218            zfAggTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0, &aggControl, tid_tx);
1219
1220            zmw_enter_critical_section(dev);
1221            completeIndex = tid_tx->complete;
1222            if(zm_agg_inQ(tid_tx, tid_tx->complete))
1223                zm_agg_plus(tid_tx->complete);
1224            zmw_leave_critical_section(dev);
1225
1226            if(zm_agg_inQ(tid_tx, completeIndex) && wd->zfcbSendCompleteIndication
1227                    && tid_tx->aggvtxq[completeIndex].buf) {
1228                wd->zfcbSendCompleteIndication(dev, tid_tx->aggvtxq[completeIndex].buf);
1229                zm_debug_msg0("in queue complete worked!");
1230            }
1231
1232        }
1233        else {
1234            /*
1235             * this aggregation queue is empty
1236             */
1237            zm_msg1_agg(ZM_LV_0, "aggLen not reached, but no more frame, j=", j);
1238
1239            break;
1240        }
1241    }
1242    zmw_enter_critical_section(dev);
1243    wd->aggState = 0;
1244    zmw_leave_critical_section(dev);
1245
1246    //zm_acquire_agg_spin_lock(Adapter);
1247    tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
1248    //zm_release_agg_spin_lock(Adapter);
1249
1250    if (tid_tx->size == 0) {
1251        //DESTQ.delete(dev, 0, tid_tx, NULL);
1252    }
1253
1254
1255
1256    //zfAggInvokeBar(dev, tid_tx);
1257    if(j>0) {
1258        aggr_count++;
1259        zm_msg1_agg(ZM_LV_0, "0xC2:sent 1 aggr, aggr_count=", aggr_count);
1260        zm_msg1_agg(ZM_LV_0, "0xC2:sent 1 aggr, aggr_size=", j);
1261    }
1262    return j;
1263}
1264
1265
1266/************************************************************************/
1267/*                                                                      */
1268/*    FUNCTION DESCRIPTION                  zfAggTxGetReadyQueue        */
1269/*      return the number of the aggregation queue                      */
1270/*      take (dev, ac) as input, find the agg queue with smallest       */
1271/*      arrival time (waited longest) among those ready or clearFlag    */
1272/*      set queues.                                                     */
1273/*                                                                      */
1274/*    INPUTS                                                            */
1275/*      dev : device pointer                                            */
1276/*      ac  : access category                                           */
1277/*                                                                      */
1278/*    OUTPUTS                                                           */
1279/*      aggregation queue number                                        */
1280/*                                                                      */
1281/*    AUTHOR                                                            */
1282/*      Honda               Atheros Communications, INC.    2006.12     */
1283/*                                                                      */
1284/************************************************************************/
1285TID_TX zfAggTxGetReadyQueue(zdev_t* dev, u16_t ac)
1286{
1287    //u16_t       qnum = ZM_AGG_POOL_SIZE;
1288    u16_t       i;
1289    u32_t       time = 0;
1290    TID_TX      tid_tx = NULL;
1291
1292    zmw_get_wlan_dev(dev);
1293
1294    zmw_declare_for_critical_section();
1295
1296    zmw_enter_critical_section(dev);
1297
1298    for (i=0 ;i<ZM_AGG_POOL_SIZE; i++)
1299    {
1300        if (1 == wd->aggQPool[i]->aggQEnabled && ac == wd->aggQPool[i]->ac &&
1301                (wd->aggQPool[i]->size > 0))
1302        {
1303            if (0 == time || time > wd->aggQPool[i]->aggvtxq[ \
1304                            wd->aggQPool[i]->aggHead ].arrivalTime)
1305            {
1306                tid_tx = wd->aggQPool[i];
1307                time = tid_tx->aggvtxq[ tid_tx->aggHead ].arrivalTime;
1308            }
1309        }
1310    }
1311
1312    zmw_leave_critical_section(dev);
1313
1314    return tid_tx;
1315}
1316
1317
1318
1319/************************************************************************/
1320/*                                                                      */
1321/*    FUNCTION DESCRIPTION                  zfAggTxGetVtxq              */
1322/*      return an MSDU                                                  */
1323/*      take (dev, qnum) as input, return an MSDU out of the agg queue. */
1324/*                                                                      */
1325/*    INPUTS                                                            */
1326/*      dev : device pointer                                            */
1327/*      qnum: queue number                                              */
1328/*                                                                      */
1329/*    OUTPUTS                                                           */
1330/*      a MSDU                                                          */
1331/*                                                                      */
1332/*    AUTHOR                                                            */
1333/*      Honda               Atheros Communications, INC.    2006.12     */
1334/*                                                                      */
1335/************************************************************************/
1336zbuf_t* zfAggTxGetVtxq(zdev_t* dev, TID_TX tid_tx)
1337{
1338    zbuf_t* buf = NULL;
1339
1340    zmw_declare_for_critical_section();
1341
1342    if (tid_tx->aggHead != tid_tx->aggTail)
1343    {
1344        buf = tid_tx->aggvtxq[ tid_tx->aggTail ].buf;
1345
1346        tid_tx->aggvtxq[tid_tx->aggTail].buf = NULL;
1347
1348        zmw_enter_critical_section(dev);
1349        tid_tx->aggTail = ((tid_tx->aggTail + 1) & ZM_AGGQ_SIZE_MASK);
1350        if(tid_tx->size > 0) tid_tx->size--;
1351        tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
1352        if (NULL == buf) {
1353            //tid_tx->aggTail = tid_tx->aggHead = tid_tx->size = 0;
1354            //zm_msg1_agg(ZM_LV_0, "GetVtxq buf == NULL, tid_tx->size=", tid_tx->size);
1355        }
1356        zmw_leave_critical_section(dev);
1357    }
1358    else
1359    {
1360        /*
1361         * queue is empty
1362         */
1363        zm_msg1_agg(ZM_LV_0, "tid_tx->aggHead == tid_tx->aggTail, tid_tx->size=", tid_tx->size);
1364
1365    }
1366
1367    if (zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail) != tid_tx->size)
1368        zm_msg1_agg(ZM_LV_0, "qlen!=tid_tx->size! tid_tx->size=", tid_tx->size);
1369    return buf;
1370}
1371
1372
1373/************************************************************************/
1374/*                                                                      */
1375/*    FUNCTION DESCRIPTION                  zfAggTxDeleteQueue          */
1376/*      return ZM_SUCCESS (can't fail)                                  */
1377/*      take (dev, qnum) as input, reset (delete) this aggregate queue, */
1378/*      this queue is virtually returned to the aggregate queue pool.   */
1379/*                                                                      */
1380/*    INPUTS                                                            */
1381/*      dev : device pointer                                            */
1382/*      qnum: queue number                                              */
1383/*                                                                      */
1384/*    OUTPUTS                                                           */
1385/*      ZM_SUCCESS                                                      */
1386/*                                                                      */
1387/*    AUTHOR                                                            */
1388/*      Honda               Atheros Communications, INC.    2006.12     */
1389/*                                                                      */
1390/************************************************************************/
1391u16_t zfAggTxDeleteQueue(zdev_t* dev, u16_t qnum)
1392{
1393    u16_t ac, tid;
1394    struct aggQueue *tx_tid;
1395    struct aggSta   *agg_sta;
1396
1397    zmw_get_wlan_dev(dev);
1398
1399    zmw_declare_for_critical_section();
1400
1401    tx_tid = wd->aggQPool[qnum];
1402    agg_sta = &wd->aggSta[tx_tid->aggQSTA];
1403    ac = tx_tid->ac;
1404    tid = tx_tid->tid;
1405
1406    zmw_enter_critical_section(dev);
1407
1408    tx_tid->aggQEnabled = 0;
1409    tx_tid->aggHead = tx_tid->aggTail = 0;
1410    tx_tid->aggReady = 0;
1411    tx_tid->clearFlag = tx_tid->deleteFlag = 0;
1412    tx_tid->size = 0;
1413    agg_sta->count[ac] = 0;
1414
1415    agg_sta->tid_tx[tid] = NULL;
1416    agg_sta->aggFlag[ac] = 0;
1417
1418    zmw_leave_critical_section(dev);
1419
1420    zm_msg1_agg(ZM_LV_0, "queue deleted! qnum=", qnum);
1421
1422    return ZM_SUCCESS;
1423}
1424
1425#ifdef ZM_ENABLE_AGGREGATION
1426#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
1427void zfBawCore(zdev_t* dev, u16_t baw_seq, u32_t bitmap, u16_t aggLen) {
1428    TID_BAW tid_baw;
1429    s16_t i;
1430    zbuf_t* buf;
1431    struct bufInfo *buf_info;
1432
1433    zmw_get_wlan_dev(dev);
1434    //zmw_declare_for_critical_section();
1435    tid_baw = BAW->getQ(dev, baw_seq);
1436    //tid_baw = NULL;
1437    if (NULL == tid_baw)
1438        return;
1439
1440    total_mpdu += aggLen;
1441    for (i = aggLen - 1; i>=0; i--) {
1442        if (((bitmap >> i) & 0x1) == 0) {
1443            buf_info = BAW->pop(dev, i, tid_baw);
1444            buf = buf_info->buf;
1445            if (buf) {
1446                //wd->zfcbSetBawQ(dev, buf, 0);
1447                zfAggTidTxInsertHead(dev, buf_info, tid_baw->tid_tx);
1448            }
1449        }
1450        else {
1451            success_mpdu++;
1452        }
1453    }
1454    BAW->disable(dev, tid_baw);
1455    zfAggTxScheduler(dev);
1456    zm_debug_msg1("success_mpdu = ", success_mpdu);
1457    zm_debug_msg1("  total_mpdu = ", total_mpdu);
1458}
1459
1460void    zfBawInit(zdev_t* dev) {
1461    TID_BAW tid_baw;
1462    u16_t i,j;
1463    zmw_get_wlan_dev(dev);
1464    //zmw_declare_for_critical_section();
1465
1466    for (i=0; i<ZM_BAW_POOL_SIZE; i++){
1467        tid_baw = &BAW->tid_baw[i];
1468        for (j=0; j<ZM_VTXQ_SIZE; j++) {
1469            tid_baw->frame[j].buf = NULL;
1470        }
1471        tid_baw->enabled = tid_baw->head = tid_baw->tail = tid_baw->size = 0;
1472        tid_baw->start_seq = 0;
1473    }
1474    BAW->delPoint = 0;
1475    BAW->core = zfBawCore;
1476    BAW->getNewQ = zfBawGetNewQ;
1477    BAW->insert = zfBawInsert;
1478    BAW->pop = zfBawPop;
1479    BAW->enable = zfBawEnable;
1480    BAW->disable = zfBawDisable;
1481    BAW->getQ = zfBawGetQ;
1482}
1483
1484
1485
1486TID_BAW zfBawGetNewQ(zdev_t* dev, u16_t start_seq, TID_TX tid_tx) {
1487    TID_BAW tid_baw=NULL;
1488    TID_BAW next_baw=NULL;
1489    u16_t i;
1490    zmw_get_wlan_dev(dev);
1491    //zmw_declare_for_critical_section();
1492
1493    /*
1494    for (i=0; i<ZM_BAW_POOL_SIZE; i++){
1495        tid_baw = &BAW->tid_baw[i];
1496        if (FALSE == tid_baw->enabled)
1497            break;
1498    }
1499    */
1500
1501    tid_baw = &BAW->tid_baw[BAW->delPoint];
1502    i = BAW->delPoint;
1503    //if (ZM_BAW_POOL_SIZE == i) {
1504        //return NULL;
1505    //    u8_t temp = BAW->delPoint;
1506    //    tid_baw = &BAW->tid_baw[BAW->delPoint];
1507    //    BAW->disable(dev, tid_baw);
1508    //    BAW->delPoint = (BAW->delPoint < (ZM_BAW_POOL_SIZE - 1))? (BAW->delPoint + 1): 0;
1509    //    temp = BAW->delPoint;
1510    //}
1511
1512    zm_msg1_agg(ZM_LV_0, "get new tid_baw, index=", i);
1513    BAW->delPoint = (i < (ZM_BAW_POOL_SIZE -1))? (i + 1): 0;
1514    next_baw = &BAW->tid_baw[BAW->delPoint];
1515    if (1 == next_baw->enabled) BAW->disable(dev, next_baw);
1516
1517    BAW->enable(dev, tid_baw, start_seq);
1518    tid_baw->tid_tx = tid_tx;
1519
1520    return tid_baw;
1521}
1522
1523u16_t   zfBawInsert(zdev_t* dev, zbuf_t* buf, u16_t baw_seq, TID_BAW tid_baw, u8_t baw_retransmit, struct baw_header_r *header_r) {
1524    //TID_BAW tid_baw;
1525    //u16_t   bufLen;
1526
1527    //zmw_get_wlan_dev(dev);
1528    //zmw_declare_for_critical_section();
1529
1530    if(tid_baw->size < (ZM_VTXQ_SIZE - 1)) {
1531        struct baw_header *baw_header = &tid_baw->frame[tid_baw->head].baw_header;
1532
1533        baw_header->headerLen   = header_r->headerLen;
1534        baw_header->micLen      = header_r->micLen;
1535        baw_header->snapLen     = header_r->snapLen;
1536        baw_header->removeLen   = header_r->removeLen;
1537        baw_header->keyIdx      = header_r->keyIdx;
1538        zfwMemoryCopy((u8_t *)baw_header->header, (u8_t *)header_r->header, 58);
1539        zfwMemoryCopy((u8_t *)baw_header->mic   , (u8_t *)header_r->mic   , 8);
1540        zfwMemoryCopy((u8_t *)baw_header->snap  , (u8_t *)header_r->snap  , 8);
1541        //wd->zfcbSetBawQ(dev, buf, 1);
1542        tid_baw->frame[tid_baw->head].buf = buf;
1543        tid_baw->frame[tid_baw->head].baw_seq = baw_seq;
1544        tid_baw->frame[tid_baw->head].baw_retransmit = baw_retransmit + 1;
1545
1546        //tid_baw->frame[tid_baw->head].data = pBuf->data;
1547        tid_baw->head++;
1548        tid_baw->size++;
1549    }
1550    else {
1551        //wd->zfcbSetBawQ(dev, buf, 0);
1552        zfwBufFree(dev, buf, ZM_SUCCESS);
1553        return FALSE;
1554    }
1555    return TRUE;
1556}
1557
1558struct bufInfo* zfBawPop(zdev_t* dev, u16_t index, TID_BAW tid_baw) {
1559    //TID_BAW tid_baw;
1560    //zbuf_t* buf;
1561    struct bufInfo *buf_info;
1562    zmw_get_wlan_dev(dev);
1563
1564    buf_info = &wd->buf_info;
1565    buf_info->baw_header = NULL;
1566
1567    if (NULL == (buf_info->buf = tid_baw->frame[index].buf))
1568        return buf_info;
1569
1570    buf_info->baw_retransmit = tid_baw->frame[index].baw_retransmit;
1571    buf_info->baw_header = &tid_baw->frame[index].baw_header;
1572    buf_info->timestamp = tid_baw->frame[index].timestamp;
1573    //pBuf->data = pBuf->buffer;
1574    //wd->zfcbRestoreBufData(dev, buf);
1575    tid_baw->frame[index].buf = NULL;
1576
1577    return buf_info;
1578}
1579
1580void    zfBawEnable(zdev_t* dev, TID_BAW tid_baw, u16_t start_seq) {
1581    //TID_BAW tid_baw;
1582
1583    //zmw_get_wlan_dev(dev);
1584    //zmw_declare_for_critical_section();
1585
1586    tid_baw->enabled = TRUE;
1587    tid_baw->head = tid_baw->tail = tid_baw->size = 0;
1588    tid_baw->start_seq = start_seq;
1589}
1590
1591void    zfBawDisable(zdev_t* dev, TID_BAW tid_baw) {
1592    //TID_BAW tid_baw;
1593    u16_t i;
1594
1595    //zmw_get_wlan_dev(dev);
1596    //zmw_declare_for_critical_section();
1597    for (i=0; i<ZM_VTXQ_SIZE; i++) {
1598        if (tid_baw->frame[i].buf) {
1599
1600            //wd->zfcbSetBawQ(dev, tid_baw->frame[i].buf, 0);
1601            zfwBufFree(dev, tid_baw->frame[i].buf, ZM_SUCCESS);
1602            tid_baw->frame[i].buf = NULL;
1603        }
1604    }
1605
1606    tid_baw->enabled = FALSE;
1607}
1608
1609TID_BAW zfBawGetQ(zdev_t* dev, u16_t baw_seq) {
1610    TID_BAW tid_baw=NULL;
1611    u16_t i;
1612
1613    zmw_get_wlan_dev(dev);
1614    //zmw_declare_for_critical_section();
1615    for (i=0; i<ZM_BAW_POOL_SIZE; i++){
1616        tid_baw = &BAW->tid_baw[i];
1617        if (TRUE == tid_baw->enabled)
1618        {
1619            zm_msg1_agg(ZM_LV_0, "get an old tid_baw, baw_seq=", baw_seq);
1620            zm_msg1_agg(ZM_LV_0, "check a  tid_baw->start_seq=", tid_baw->start_seq);
1621            if(baw_seq == tid_baw->start_seq)
1622                break;
1623        }
1624
1625    }
1626    if (ZM_BAW_POOL_SIZE == i)
1627        return NULL;
1628    return tid_baw;
1629}
1630#endif //disable BAW
1631#endif
1632
1633u16_t zfAggTallyReset(zdev_t* dev)
1634{
1635    struct aggTally* agg_tal;
1636
1637    zmw_get_wlan_dev(dev);
1638
1639    //zmw_declare_for_critical_section();
1640
1641    agg_tal = &wd->agg_tal;
1642    agg_tal->got_packets_sum = 0;
1643    agg_tal->got_bytes_sum = 0;
1644    agg_tal->sent_bytes_sum = 0;
1645    agg_tal->sent_packets_sum = 0;
1646    agg_tal->avg_got_packets = 0;
1647    agg_tal->avg_got_bytes = 0;
1648    agg_tal->avg_sent_packets = 0;
1649    agg_tal->avg_sent_bytes = 0;
1650    agg_tal->time = 0;
1651    return 0;
1652}
1653
1654
1655/************************************************************************/
1656/*                                                                      */
1657/*    FUNCTION DESCRIPTION                  zfAggScanAndClear           */
1658/*      If the packets in a queue have waited for too long, clear and   */
1659/*      delete this aggregation queue.                                  */
1660/*                                                                      */
1661/*    INPUTS                                                            */
1662/*      dev     : device pointer                                        */
1663/*      time    : current time                                          */
1664/*                                                                      */
1665/*    OUTPUTS                                                           */
1666/*      ZM_SUCCESS                                                      */
1667/*                                                                      */
1668/*    AUTHOR                                                            */
1669/*      Honda               Atheros Communications, INC.    2006.12     */
1670/*                                                                      */
1671/************************************************************************/
1672u16_t   zfAggScanAndClear(zdev_t* dev, u32_t time)
1673{
1674    u16_t i;
1675    u16_t head;
1676    u16_t tail;
1677    u32_t tick;
1678    u32_t arrivalTime;
1679    //u16_t aid, ac;
1680    TID_TX tid_tx;
1681
1682    zmw_get_wlan_dev(dev);
1683
1684    zmw_declare_for_critical_section();
1685
1686    if(!(wd->state == ZM_WLAN_STATE_ENABLED)) return 0;
1687    zfAggTxScheduler(dev, 1);
1688    tick = zm_agg_GetTime();
1689    for (i=0; i<ZM_AGG_POOL_SIZE; i++)
1690    {
1691        if (!wd->aggQPool[i]) return 0;
1692        if (1 == wd->aggQPool[i]->aggQEnabled)
1693        {
1694            tid_tx = wd->aggQPool[i];
1695            zmw_enter_critical_section(dev);
1696
1697            head = tid_tx->aggHead;
1698            tail = tid_tx->aggTail;
1699
1700            arrivalTime = (u32_t)tid_tx->aggvtxq[tid_tx->aggTail].arrivalTime;
1701
1702
1703            if((tick - arrivalTime) <= ZM_AGG_CLEAR_TIME)
1704            {
1705
1706            }
1707            else if((tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail)) > 0)
1708            {
1709
1710                tid_tx->clearFlag = 1;
1711
1712                //zm_msg1_agg(ZM_LV_0, "clear queue    tick =", tick);
1713                //zm_msg1_agg(ZM_LV_0, "clear queue arrival =", arrivalTime);
1714
1715
1716                //zmw_leave_critical_section(dev);
1717                //zfAggTxScheduler(dev);
1718                //zmw_enter_critical_section(dev);
1719
1720            }
1721
1722            if (tid_tx->size == 0)
1723            {
1724                /*
1725                 * queue empty
1726                 */
1727                if (tick - tid_tx->lastArrival > ZM_AGG_DELETE_TIME)
1728                {
1729                    zm_msg1_agg(ZM_LV_0, "delete queue, idle for n sec. n = ", \
1730                            ZM_AGG_DELETE_TIME/10);
1731
1732                    zmw_leave_critical_section(dev);
1733                    zfAggTxDeleteQueue(dev, i);
1734                    zmw_enter_critical_section(dev);
1735                }
1736            }
1737
1738            zmw_leave_critical_section(dev);
1739        }
1740    }
1741
1742        zfAggRxClear(dev, time);
1743
1744#ifdef ZM_AGG_TALLY
1745    if((wd->tick % 100) == 0) {
1746        zfAggPrintTally(dev);
1747    }
1748#endif
1749
1750    return ZM_SUCCESS;
1751}
1752
1753u16_t   zfAggPrintTally(zdev_t* dev)
1754{
1755    struct aggTally* agg_tal;
1756
1757    zmw_get_wlan_dev(dev);
1758
1759    //zmw_declare_for_critical_section();
1760
1761    agg_tal = &wd->agg_tal;
1762
1763    if(agg_tal->got_packets_sum < 10)
1764    {
1765        zfAggTallyReset(dev);
1766        return 0;
1767    }
1768
1769    agg_tal->time++;
1770    agg_tal->avg_got_packets = (agg_tal->avg_got_packets * (agg_tal->time - 1) +
1771            agg_tal->got_packets_sum) / agg_tal->time;
1772    agg_tal->avg_got_bytes = (agg_tal->avg_got_bytes * (agg_tal->time - 1) +
1773            agg_tal->got_bytes_sum) / agg_tal->time;
1774    agg_tal->avg_sent_packets = (agg_tal->avg_sent_packets * (agg_tal->time - 1)
1775            + agg_tal->sent_packets_sum) / agg_tal->time;
1776    agg_tal->avg_sent_bytes = (agg_tal->avg_sent_bytes * (agg_tal->time - 1) +
1777            agg_tal->sent_bytes_sum) / agg_tal->time;
1778    zm_msg1_agg(ZM_LV_0, "got_packets_sum =", agg_tal->got_packets_sum);
1779    zm_msg1_agg(ZM_LV_0, "  got_bytes_sum =", agg_tal->got_bytes_sum);
1780    zm_msg1_agg(ZM_LV_0, "sent_packets_sum=", agg_tal->sent_packets_sum);
1781    zm_msg1_agg(ZM_LV_0, " sent_bytes_sum =", agg_tal->sent_bytes_sum);
1782    agg_tal->got_packets_sum = agg_tal->got_bytes_sum =agg_tal->sent_packets_sum
1783                = agg_tal->sent_bytes_sum = 0;
1784    zm_msg1_agg(ZM_LV_0, "avg_got_packets =", agg_tal->avg_got_packets);
1785    zm_msg1_agg(ZM_LV_0, "  avg_got_bytes =", agg_tal->avg_got_bytes);
1786    zm_msg1_agg(ZM_LV_0, "avg_sent_packets=", agg_tal->avg_sent_packets);
1787    zm_msg1_agg(ZM_LV_0, " avg_sent_bytes =", agg_tal->avg_sent_bytes);
1788    if ((wd->commTally.BA_Fail == 0) || (wd->commTally.Hw_Tx_MPDU == 0))
1789    {
1790        zm_msg1_agg(ZM_LV_0, "Hardware Tx MPDU=", wd->commTally.Hw_Tx_MPDU);
1791        zm_msg1_agg(ZM_LV_0, "  BA Fail number=", wd->commTally.BA_Fail);
1792    }
1793    else
1794        zm_msg1_agg(ZM_LV_0, "1/(BA fail rate)=", wd->commTally.Hw_Tx_MPDU/wd->commTally.BA_Fail);
1795
1796    return 0;
1797}
1798
1799u16_t zfAggRxClear(zdev_t* dev, u32_t time)
1800{
1801    u16_t   i;
1802    struct agg_tid_rx *tid_rx;
1803
1804    zmw_get_wlan_dev(dev);
1805
1806    zmw_declare_for_critical_section();
1807
1808    for (i=0; i<ZM_AGG_POOL_SIZE; i++)
1809    {
1810        zmw_enter_critical_section(dev);
1811        tid_rx = wd->tid_rx[i];
1812        if (tid_rx->baw_head != tid_rx->baw_tail)
1813        {
1814            u16_t j = tid_rx->baw_tail;
1815            while ((j != tid_rx->baw_head) && !tid_rx->frame[j].buf) {
1816                j = (j + 1) & ZM_AGG_BAW_MASK;
1817            }
1818            if ((j != tid_rx->baw_head) && (time - tid_rx->frame[j].arrivalTime) >
1819                    (ZM_AGG_CLEAR_TIME - 5))
1820            {
1821                zmw_leave_critical_section(dev);
1822                zm_msg0_agg(ZM_LV_1, "queue RxFlush by RxClear");
1823                zfAggRxFlush(dev, 0, tid_rx);
1824                zmw_enter_critical_section(dev);
1825            }
1826        }
1827        zmw_leave_critical_section(dev);
1828    }
1829
1830    return ZM_SUCCESS;
1831}
1832
1833struct agg_tid_rx* zfAggRxEnabled(zdev_t* dev, zbuf_t* buf)
1834{
1835    u16_t   dst0, src[3], ac, aid, fragOff;
1836    u8_t    up;
1837    u16_t   offset = 0;
1838    u16_t   seq_no;
1839    u16_t frameType;
1840    u16_t frameCtrl;
1841    u16_t frameSubtype;
1842    u32_t tcp_seq;
1843    //struct aggSta *agg_sta;
1844#if ZM_AGG_FPGA_REORDERING
1845    struct agg_tid_rx *tid_rx;
1846#endif
1847    zmw_get_wlan_dev(dev);
1848
1849    //zmw_declare_for_critical_section();
1850    seq_no = zmw_rx_buf_readh(dev, buf, 22) >> 4;
1851    //DbgPrint("Rx seq=%d\n", seq_no);
1852    if (wd->sta.EnableHT == 0)
1853    {
1854        return NULL;
1855    }
1856
1857    frameCtrl = zmw_rx_buf_readb(dev, buf, 0);
1858    frameType = frameCtrl & 0xf;
1859    frameSubtype = frameCtrl & 0xf0;
1860
1861
1862    if (frameType != ZM_WLAN_DATA_FRAME) //non-Qos Data? (frameSubtype&0x80)
1863    {
1864        return NULL;
1865    }
1866#ifdef ZM_ENABLE_PERFORMANCE_EVALUATION
1867    tcp_seq = zmw_rx_buf_readb(dev, buf, 22+36) << 24;
1868    tcp_seq += zmw_rx_buf_readb(dev, buf, 22+37) << 16;
1869    tcp_seq += zmw_rx_buf_readb(dev, buf, 22+38) << 8;
1870    tcp_seq += zmw_rx_buf_readb(dev, buf, 22+39);
1871#endif
1872
1873    ZM_SEQ_DEBUG("In                   %5d, %12u\n", seq_no, tcp_seq);
1874    dst0 = zmw_rx_buf_readh(dev, buf, offset+4);
1875
1876    src[0] = zmw_rx_buf_readh(dev, buf, offset+10);
1877    src[1] = zmw_rx_buf_readh(dev, buf, offset+12);
1878    src[2] = zmw_rx_buf_readh(dev, buf, offset+14);
1879
1880#if ZM_AGG_FPGA_DEBUG
1881    aid = 0;
1882#else
1883    aid = zfApFindSta(dev, src);
1884#endif
1885
1886    //agg_sta = &wd->aggSta[aid];
1887    //zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
1888    //ac = zcUpToAc[up&0x7] & 0x3;
1889
1890    /*
1891     * Filter unicast frame only, aid == 0 is for debug only
1892     */
1893    if ((dst0 & 0x1) == 0 && aid == 0)
1894    {
1895#if ZM_AGG_FPGA_REORDERING
1896        tid_rx = zfAggRxGetQueue(dev, buf) ;
1897        if(!tid_rx)
1898            return NULL;
1899        else
1900        {
1901            //if (tid_rx->addBaExchangeStatusCode == ZM_AGG_ADDBA_RESPONSE)
1902            return tid_rx;
1903        }
1904#else
1905        return NULL;
1906#endif
1907    }
1908
1909    return NULL;
1910}
1911
1912u16_t zfAggRx(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo *addInfo, struct agg_tid_rx *tid_rx)
1913{
1914    u16_t   seq_no;
1915    s16_t   index;
1916    u16_t   offset = 0;
1917    zbuf_t* pbuf;
1918    u8_t    frameSubType;
1919
1920    zmw_get_wlan_dev(dev);
1921
1922    zmw_declare_for_critical_section();
1923
1924    ZM_BUFFER_TRACE(dev, buf)
1925
1926    ZM_PERFORMANCE_RX_REORDER(dev);
1927
1928    seq_no = zmw_rx_buf_readh(dev, buf, offset+22) >> 4;
1929
1930    index = seq_no - tid_rx->seq_start;
1931    /*
1932     * for debug
1933     */
1934
1935    /* zm_msg2_agg(ZM_LV_0, "queue seq = ", seq_no);
1936     * DbgPrint("%s:%s%lxh %s%lxh\n", __func__, "queue seq=", seq_no,
1937     *   "; seq_start=", tid_rx->seq_start);
1938     */
1939
1940    //DbgPrint("seq_no=%d, seq_start=%d\n", seq_no, tid_rx->seq_start);
1941
1942    /* In some APs, we found that it might transmit NULL data whose sequence number
1943       is out or order. In order to avoid this problem, we ignore these NULL data.
1944     */
1945
1946    frameSubType = (zmw_rx_buf_readh(dev, buf, 0) & 0xF0) >> 4;
1947
1948    /* If this is a NULL data instead of Qos NULL data */
1949    if ((frameSubType & 0x0C) == 0x04)
1950    {
1951        s16_t seq_diff;
1952
1953        seq_diff = (seq_no > tid_rx->seq_start) ?
1954                       seq_no - tid_rx->seq_start : tid_rx->seq_start - seq_no;
1955
1956        if (seq_diff > ZM_AGG_BAW_SIZE)
1957        {
1958            zm_debug_msg0("Free Rx NULL data in zfAggRx");
1959
1960            /* Free Rx buffer */
1961            zfwBufFree(dev, buf, 0);
1962            return ZM_ERR_OUT_OF_ORDER_NULL_DATA;
1963        }
1964    }
1965
1966    /*
1967     * sequence number wrap at 4k
1968     */
1969    if (tid_rx->seq_start > seq_no)
1970    {
1971        //index += 4096;
1972
1973        zmw_enter_critical_section(dev);
1974        if (tid_rx->seq_start >= 4096) {
1975            tid_rx->seq_start = 0;
1976        }
1977        zmw_leave_critical_section(dev);
1978
1979    }
1980
1981    if (tid_rx->seq_start == seq_no) {
1982        zmw_enter_critical_section(dev);
1983        if (((tid_rx->baw_head - tid_rx->baw_tail) & ZM_AGG_BAW_MASK) > 0) {
1984            //DbgPrint("head=%d, tail=%d", tid_rx->baw_head, tid_rx->baw_tail);
1985            tid_rx->baw_tail = (tid_rx->baw_tail + 1) & ZM_AGG_BAW_MASK;
1986        }
1987        tid_rx->seq_start = (tid_rx->seq_start + 1) & (4096 - 1);
1988        zmw_leave_critical_section(dev);
1989
1990        ZM_PERFORMANCE_RX_SEQ(dev, buf);
1991
1992        if (wd->zfcbRecv80211 != NULL) {
1993            //seq_no = zmw_rx_buf_readh(dev, buf, offset+22) >> 4;
1994            //DbgPrint("Recv indicate seq=%d\n", seq_no);
1995            //DbgPrint("1. seq=%d\n", seq_no);
1996
1997            wd->zfcbRecv80211(dev, buf, addInfo);
1998        }
1999        else {
2000            zfiRecv80211(dev, buf, addInfo);
2001        }
2002    }
2003    else if (!zfAggRxEnqueue(dev, buf, tid_rx, addInfo))
2004    {
2005        /*
2006         * duplicated packet
2007         */
2008        return 1;
2009    }
2010
2011    while (tid_rx->baw_head != tid_rx->baw_tail) {// && tid_rx->frame[tid_rx->baw_tail].buf)
2012        u16_t tailIndex;
2013
2014        zmw_enter_critical_section(dev);
2015
2016        tailIndex = tid_rx->baw_tail;
2017        pbuf = tid_rx->frame[tailIndex].buf;
2018        tid_rx->frame[tailIndex].buf = 0;
2019        if (!pbuf)
2020        {
2021            zmw_leave_critical_section(dev);
2022            break;
2023        }
2024
2025        tid_rx->baw_tail = (tid_rx->baw_tail + 1) & ZM_AGG_BAW_MASK;
2026        tid_rx->seq_start = (tid_rx->seq_start + 1) & (4096 - 1);
2027
2028
2029        //if(pbuf && tid_rx->baw_size > 0)
2030        //    tid_rx->baw_size--;
2031
2032        zmw_leave_critical_section(dev);
2033
2034        ZM_PERFORMANCE_RX_SEQ(dev, pbuf);
2035
2036        if (wd->zfcbRecv80211 != NULL)
2037        {
2038            //seq_no = zmw_rx_buf_readh(dev, pbuf, offset+22) >> 4;
2039            //DbgPrint("Recv indicate seq=%d\n", seq_no);
2040            //DbgPrint("1. seq=%d\n", seq_no);
2041            wd->zfcbRecv80211(dev, pbuf, addInfo);
2042        }
2043        else
2044        {
2045            //seq_no = zmw_rx_buf_readh(dev, pbuf, offset+22) >> 4;
2046            //DbgPrint("Recv indicate seq=%d\n", seq_no);
2047            zfiRecv80211(dev, pbuf, addInfo);
2048        }
2049    }
2050
2051    return 1;
2052}
2053
2054struct agg_tid_rx *zfAggRxGetQueue(zdev_t* dev, zbuf_t* buf)
2055{
2056    u16_t   src[3];
2057    u16_t   aid, ac, i;
2058    u16_t   offset = 0;
2059    struct agg_tid_rx *tid_rx = NULL;
2060
2061    zmw_get_wlan_dev(dev);
2062
2063    //zmw_declare_for_critical_section();
2064
2065    src[0] = zmw_rx_buf_readh(dev, buf, offset+10);
2066    src[1] = zmw_rx_buf_readh(dev, buf, offset+12);
2067    src[2] = zmw_rx_buf_readh(dev, buf, offset+14);
2068    aid = zfApFindSta(dev, src);
2069
2070    ac = (zmw_rx_buf_readh(dev, buf, 24) & 0xF);
2071
2072    // mark by spin lock debug
2073    //zmw_enter_critical_section(dev);
2074
2075    for (i=0; i<ZM_AGG_POOL_SIZE ; i++)
2076    {
2077        if((wd->tid_rx[i]->aid == aid) && (wd->tid_rx[i]->ac == ac))
2078        {
2079            tid_rx = wd->tid_rx[i];
2080            break;
2081        }
2082    }
2083
2084    // mark by spin lock debug
2085    //zmw_leave_critical_section(dev);
2086    return tid_rx;
2087}
2088
2089
2090u16_t   zfAggRxEnqueue(zdev_t* dev, zbuf_t* buf, struct agg_tid_rx *tid_rx, struct zsAdditionInfo *addInfo)
2091{
2092    u16_t seq_no, offset = 0;
2093    u16_t q_index;
2094    s16_t index;
2095    u8_t  bdropframe = 0;
2096
2097    zmw_get_wlan_dev(dev);
2098
2099    zmw_declare_for_critical_section();
2100
2101    ZM_BUFFER_TRACE(dev, buf)
2102
2103    seq_no = zmw_rx_buf_readh(dev, buf, offset+22) >> 4;
2104    index  = seq_no - tid_rx->seq_start;
2105
2106    /*
2107     * sequence number wrap at 4k
2108     * -1000: check for duplicate past packet
2109     */
2110    bdropframe = 0;
2111    if (tid_rx->seq_start > seq_no) {
2112        if ((tid_rx->seq_start > 3967) && (seq_no < 128)) {
2113            index += 4096;
2114        } else if (tid_rx->seq_start - seq_no > 70) {
2115            zmw_enter_critical_section(dev);
2116            tid_rx->sq_behind_count++;
2117            if (tid_rx->sq_behind_count > 3) {
2118                tid_rx->sq_behind_count = 0;
2119            } else {
2120                bdropframe = 1;
2121            }
2122            zmw_leave_critical_section(dev);
2123        } else {
2124            bdropframe = 1;
2125        }
2126    } else {
2127        if (seq_no - tid_rx->seq_start > 70) {
2128            zmw_enter_critical_section(dev);
2129            tid_rx->sq_exceed_count++;
2130            if (tid_rx->sq_exceed_count > 3) {
2131                tid_rx->sq_exceed_count = 0;
2132            } else {
2133                bdropframe = 1;
2134            }
2135            zmw_leave_critical_section(dev);
2136        }
2137    }
2138
2139    if (bdropframe == 1) {
2140        /*if (wd->zfcbRecv80211 != NULL) {
2141            wd->zfcbRecv80211(dev, buf, addInfo);
2142        }
2143        else {
2144            zfiRecv80211(dev, buf, addInfo);
2145        }*/
2146
2147        ZM_PERFORMANCE_FREE(dev, buf);
2148
2149        zfwBufFree(dev, buf, 0);
2150        /*zfAggRxFlush(dev, seq_no, tid_rx);
2151        tid_rx->seq_start = seq_no;
2152        index = seq_no - tid_rx->seq_start;
2153        */
2154
2155        //DbgPrint("Free an old packet, seq_start=%d, seq_no=%d\n", tid_rx->seq_start, seq_no);
2156
2157        /*
2158         * duplicate past packet
2159         * happens only in simulated aggregation environment
2160         */
2161        return 0;
2162    } else {
2163        zmw_enter_critical_section(dev);
2164        if (tid_rx->sq_exceed_count > 0){
2165            tid_rx->sq_exceed_count--;
2166        }
2167
2168        if (tid_rx->sq_behind_count > 0) {
2169            tid_rx->sq_behind_count--;
2170        }
2171        zmw_leave_critical_section(dev);
2172    }
2173
2174    if (index < 0) {
2175        zfAggRxFlush(dev, seq_no, tid_rx);
2176        tid_rx->seq_start = seq_no;
2177        index = 0;
2178    }
2179
2180    //if (index >= (ZM_AGG_BAW_SIZE - 1))
2181    if (index >= (ZM_AGG_BAW_MASK))
2182    {
2183        /*
2184         * queue full
2185         */
2186        //DbgPrint("index >= 64, seq_start=%d, seq_no=%d\n", tid_rx->seq_start, seq_no);
2187        zfAggRxFlush(dev, seq_no, tid_rx);
2188        //tid_rx->seq_start = seq_no;
2189        index = seq_no - tid_rx->seq_start;
2190        if ((tid_rx->seq_start > seq_no) && (tid_rx->seq_start > 1000) && (tid_rx->seq_start - 1000) > seq_no)
2191        {
2192        //index = seq_no - tid_rx->seq_start;
2193            index += 4096;
2194        }
2195        //index = seq_no - tid_rx->seq_start;
2196        while (index >= (ZM_AGG_BAW_MASK)) {
2197            //DbgPrint("index >= 64, seq_start=%d, seq_no=%d\n", tid_rx->seq_start, seq_no);
2198            tid_rx->seq_start = (tid_rx->seq_start + ZM_AGG_BAW_MASK) & (4096 - 1);
2199            index = seq_no - tid_rx->seq_start;
2200            if ((tid_rx->seq_start > seq_no) && (tid_rx->seq_start > 1000) && (tid_rx->seq_start - 1000) > seq_no)
2201            {
2202                index += 4096;
2203            }
2204        }
2205    }
2206
2207
2208    q_index = (tid_rx->baw_tail + index) & ZM_AGG_BAW_MASK;
2209    if (tid_rx->frame[q_index].buf && (((tid_rx->baw_head - tid_rx->baw_tail) & ZM_AGG_BAW_MASK) >
2210                (((q_index) - tid_rx->baw_tail) & ZM_AGG_BAW_MASK)))
2211    {
2212
2213        ZM_PERFORMANCE_DUP(dev, tid_rx->frame[q_index].buf, buf);
2214        zfwBufFree(dev, buf, 0);
2215        //DbgPrint("Free a duplicate packet, seq_start=%d, seq_no=%d\n", tid_rx->seq_start, seq_no);
2216        //DbgPrint("head=%d, tail=%d", tid_rx->baw_head, tid_rx->baw_tail);
2217        /*
2218         * duplicate packet
2219         */
2220        return 0;
2221    }
2222
2223    zmw_enter_critical_section(dev);
2224    if(tid_rx->frame[q_index].buf) {
2225        zfwBufFree(dev, tid_rx->frame[q_index].buf, 0);
2226        tid_rx->frame[q_index].buf = 0;
2227    }
2228
2229    tid_rx->frame[q_index].buf = buf;
2230    tid_rx->frame[q_index].arrivalTime = zm_agg_GetTime();
2231    zfwMemoryCopy((void*)&tid_rx->frame[q_index].addInfo, (void*)addInfo, sizeof(struct zsAdditionInfo));
2232
2233    /*
2234     * for debug simulated aggregation only,
2235     * should be done in rx of ADDBA Request
2236     */
2237    //tid_rx->addInfo = addInfo;
2238
2239
2240    if (((tid_rx->baw_head - tid_rx->baw_tail) & ZM_AGG_BAW_MASK) <= index)
2241    {
2242        //tid_rx->baw_size = index + 1;
2243        if (((tid_rx->baw_head - tid_rx->baw_tail) & ZM_AGG_BAW_MASK) <=
2244                //((q_index + 1) & ZM_AGG_BAW_MASK))
2245                (((q_index) - tid_rx->baw_tail) & ZM_AGG_BAW_MASK))//tid_rx->baw_size )
2246            tid_rx->baw_head = (q_index + 1) & ZM_AGG_BAW_MASK;
2247    }
2248    zmw_leave_critical_section(dev);
2249
2250    /*
2251     * success
2252     */
2253    //DbgPrint("head=%d, tail=%d, start=%d", tid_rx->baw_head, tid_rx->baw_tail, tid_rx->seq_start);
2254    return 1;
2255}
2256
2257u16_t zfAggRxFlush(zdev_t* dev, u16_t seq_no, struct agg_tid_rx *tid_rx)
2258{
2259    zbuf_t* pbuf;
2260    u16_t   seq;
2261    struct zsAdditionInfo addInfo;
2262    zmw_get_wlan_dev(dev);
2263    zmw_declare_for_critical_section();
2264
2265    ZM_PERFORMANCE_RX_FLUSH(dev);
2266
2267    while (1)
2268    {
2269        zmw_enter_critical_section(dev);
2270        if (tid_rx->baw_tail == tid_rx->baw_head) {
2271            zmw_leave_critical_section(dev);
2272            break;
2273        }
2274
2275        pbuf = tid_rx->frame[tid_rx->baw_tail].buf;
2276        zfwMemoryCopy((void*)&addInfo, (void*)&tid_rx->frame[tid_rx->baw_tail].addInfo, sizeof(struct zsAdditionInfo));
2277        tid_rx->frame[tid_rx->baw_tail].buf = 0;
2278        //if(pbuf && tid_rx->baw_size > 0) tid_rx->baw_size--;
2279        tid_rx->baw_tail = (tid_rx->baw_tail + 1) & ZM_AGG_BAW_MASK;
2280        tid_rx->seq_start = (tid_rx->seq_start + 1) & (4096 - 1);
2281            zmw_leave_critical_section(dev);
2282
2283        if (pbuf)
2284        {
2285
2286            ZM_PERFORMANCE_RX_SEQ(dev, pbuf);
2287
2288            if (wd->zfcbRecv80211 != NULL)
2289            {
2290                seq = zmw_rx_buf_readh(dev, pbuf, 22) >> 4;
2291                //DbgPrint("Recv indicate seq=%d\n", seq);
2292                //DbgPrint("2. seq=%d\n", seq);
2293                wd->zfcbRecv80211(dev, pbuf, &addInfo);
2294            }
2295            else
2296            {
2297                seq = zmw_rx_buf_readh(dev, pbuf, 22) >> 4;
2298                //DbgPrint("Recv indicate seq=%d\n", seq);
2299                zfiRecv80211(dev, pbuf, &addInfo);
2300            }
2301        }
2302    }
2303
2304    zmw_enter_critical_section(dev);
2305    tid_rx->baw_head = tid_rx->baw_tail = 0;
2306    zmw_leave_critical_section(dev);
2307    return 1;
2308}
2309
2310
2311
2312/************************************************************************/
2313/*                                                                      */
2314/*    FUNCTION DESCRIPTION                  zfAggRxFreeBuf              */
2315/*      Frees all queued packets in buffer when the driver is down.     */
2316/*      The zfFreeResource() will check if the buffer is all freed.     */
2317/*                                                                      */
2318/*    INPUTS                                                            */
2319/*      dev     : device pointer                                        */
2320/*                                                                      */
2321/*    OUTPUTS                                                           */
2322/*      ZM_SUCCESS                                                      */
2323/*                                                                      */
2324/*    AUTHOR                                                            */
2325/*      Honda               Atheros Communications, INC.    2006.12     */
2326/*                                                                      */
2327/************************************************************************/
2328u16_t   zfAggRxFreeBuf(zdev_t* dev, u16_t destroy)
2329{
2330    u16_t   i;
2331    zbuf_t* buf;
2332    struct agg_tid_rx *tid_rx;
2333
2334    TID_TX  tid_tx;
2335    //struct bufInfo *buf_info;
2336
2337    zmw_get_wlan_dev(dev);
2338    zmw_declare_for_critical_section();
2339
2340    for (i=0; i<ZM_AGG_POOL_SIZE; i++)
2341    {
2342        u16_t j;
2343
2344        tid_rx = wd->tid_rx[i];
2345
2346        for(j=0; j <= ZM_AGG_BAW_SIZE; j++)
2347        {
2348            zmw_enter_critical_section(dev);
2349            buf = tid_rx->frame[j].buf;
2350            tid_rx->frame[j].buf = 0;
2351            zmw_leave_critical_section(dev);
2352
2353            if (buf)
2354            {
2355                zfwBufFree(dev, buf, 0);
2356            }
2357        }
2358
2359        #if 0
2360        if ( tid_rx->baw_head != tid_rx->baw_tail )
2361        {
2362            while (tid_rx->baw_head != tid_rx->baw_tail)
2363            {
2364                buf = tid_rx->frame[tid_rx->baw_tail].buf;
2365                tid_rx->frame[tid_rx->baw_tail].buf = 0;
2366                if (buf)
2367                {
2368                    zfwBufFree(dev, buf, 0);
2369
2370                    zmw_enter_critical_section(dev);
2371                    tid_rx->frame[tid_rx->baw_tail].buf = 0;
2372                    zmw_leave_critical_section(dev);
2373                }
2374                zmw_enter_critical_section(dev);
2375                //if (tid_rx->baw_size > 0)tid_rx->baw_size--;
2376                tid_rx->baw_tail = (tid_rx->baw_tail + 1) & ZM_AGG_BAW_MASK;
2377                tid_rx->seq_start++;
2378                zmw_leave_critical_section(dev);
2379            }
2380        }
2381        #endif
2382
2383        zmw_enter_critical_section(dev);
2384        tid_rx->seq_start = 0;
2385        tid_rx->baw_head = tid_rx->baw_tail = 0;
2386        tid_rx->aid = ZM_MAX_STA_SUPPORT;
2387        zmw_leave_critical_section(dev);
2388
2389        #ifdef ZM_ENABLE_AGGREGATION
2390        #ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
2391        if (tid_baw->enabled) {
2392            zm_msg1_agg(ZM_LV_0, "Device down, clear BAW queue:", i);
2393            BAW->disable(dev, tid_baw);
2394        }
2395        #endif
2396        #endif
2397        if (1 == wd->aggQPool[i]->aggQEnabled) {
2398            tid_tx = wd->aggQPool[i];
2399            buf = zfAggTxGetVtxq(dev, tid_tx);
2400            while (buf) {
2401                zfwBufFree(dev, buf, 0);
2402                buf = zfAggTxGetVtxq(dev, tid_tx);
2403            }
2404        }
2405
2406        if(destroy) {
2407            zfwMemFree(dev, wd->aggQPool[i], sizeof(struct aggQueue));
2408            zfwMemFree(dev, wd->tid_rx[i], sizeof(struct agg_tid_rx));
2409        }
2410    }
2411    #ifdef ZM_ENABLE_AGGREGATION
2412    #ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
2413    if(destroy) zfwMemFree(dev, BAW, sizeof(struct baw_enabler));
2414    #endif
2415    #endif
2416    return ZM_SUCCESS;
2417}
2418
2419
2420void zfAggRecvBAR(zdev_t* dev, zbuf_t *buf) {
2421    u16_t start_seq, len;
2422    u8_t i, bitmap[8];
2423    len = zfwBufGetSize(dev, buf);
2424    start_seq = zmw_rx_buf_readh(dev, buf, len-2);
2425    DbgPrint("Received a BAR Control frame, start_seq=%d", start_seq>>4);
2426    /* todo: set the bitmap by reordering buffer! */
2427    for (i=0; i<8; i++) bitmap[i]=0;
2428    zfSendBA(dev, start_seq, bitmap);
2429}
2430
2431#ifdef ZM_ENABLE_AGGREGATION
2432#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
2433void zfAggTxRetransmit(zdev_t* dev, struct bufInfo *buf_info, struct aggControl *aggControl, TID_TX tid_tx) {
2434    u16_t removeLen;
2435    u16_t err;
2436
2437    zmw_get_wlan_dev(dev);
2438    if (aggControl && (ZM_AGG_FIRST_MPDU == aggControl->ampduIndication) ) {
2439        tid_tx->bar_ssn = buf_info->baw_header->header[15];
2440        aggControl->tid_baw->start_seq = tid_tx->bar_ssn >> 4;
2441        zm_msg1_agg(ZM_LV_0, "start seq=", tid_tx->bar_ssn >> 4);
2442    }
2443    buf_info->baw_header->header[4] |= (1 << 11);
2444    if (aggControl && aggControl->aggEnabled) {
2445        //if (wd->enableAggregation==0 && !(buf_info->baw_header->header[6]&0x1))
2446        //{
2447            //if (((buf_info->baw_header->header[2] & 0x3) == 2))
2448            //{
2449                /* Enable aggregation */
2450                buf_info->baw_header->header[1] |= 0x20;
2451                if (ZM_AGG_LAST_MPDU == aggControl->ampduIndication) {
2452                    buf_info->baw_header->header[1] |= 0x4000;
2453                }
2454                else {
2455                    buf_info->baw_header->header[1] &= ~0x4000;
2456                    //zm_debug_msg0("ZM_AGG_LAST_MPDU");
2457                }
2458            //}
2459            //else {
2460            //    zm_debug_msg1("no aggr, header[2]&0x3 = ",buf_info->baw_header->header[2] & 0x3)
2461            //    aggControl->aggEnabled = 0;
2462            //}
2463        //}
2464        //else {
2465        //    zm_debug_msg1("no aggr, wd->enableAggregation = ", wd->enableAggregation);
2466        //    zm_debug_msg1("no aggr, !header[6]&0x1 = ",!(buf_info->baw_header->header[6]&0x1));
2467        //    aggControl->aggEnabled = 0;
2468        //}
2469    }
2470
2471    /*if (aggControl->tid_baw) {
2472        struct baw_header_r header_r;
2473
2474        header_r.header      = buf_info->baw_header->header;
2475        header_r.mic         = buf_info->baw_header->mic;
2476        header_r.snap        = buf_info->baw_header->snap;
2477        header_r.headerLen   = buf_info->baw_header->headerLen;
2478        header_r.micLen      = buf_info->baw_header->micLen;
2479        header_r.snapLen     = buf_info->baw_header->snapLen;
2480        header_r.removeLen   = buf_info->baw_header->removeLen;
2481        header_r.keyIdx      = buf_info->baw_header->keyIdx;
2482
2483        BAW->insert(dev, buf_info->buf, tid_tx->bar_ssn >> 4, aggControl->tid_baw, buf_info->baw_retransmit, &header_r);
2484    }*/
2485
2486    if ((err = zfHpSend(dev,
2487                    buf_info->baw_header->header,
2488                    buf_info->baw_header->headerLen,
2489                    buf_info->baw_header->snap,
2490                    buf_info->baw_header->snapLen,
2491                    buf_info->baw_header->mic,
2492                    buf_info->baw_header->micLen,
2493                    buf_info->buf,
2494                    buf_info->baw_header->removeLen,
2495                    ZM_EXTERNAL_ALLOC_BUF,
2496                    (u8_t)tid_tx->ac,
2497                    buf_info->baw_header->keyIdx)) != ZM_SUCCESS)
2498    {
2499        goto zlError;
2500    }
2501
2502    return;
2503
2504zlError:
2505    zfwBufFree(dev, buf_info->buf, 0);
2506    return;
2507
2508}
2509#endif //disable BAW
2510#endif
2511/************************************************************************/
2512/*                                                                      */
2513/*    FUNCTION DESCRIPTION                  zfAggTxSendEth              */
2514/*      Called to transmit Ethernet frame from upper elayer.            */
2515/*                                                                      */
2516/*    INPUTS                                                            */
2517/*      dev : device pointer                                            */
2518/*      buf : buffer pointer                                            */
2519/*      port : WLAN port, 0=>standard, 0x10-0x17=>VAP, 0x20-0x25=>WDS   */
2520/*                                                                      */
2521/*    OUTPUTS                                                           */
2522/*      error code                                                      */
2523/*                                                                      */
2524/*    AUTHOR                                                            */
2525/*      Stephen, Honda      Atheros Communications, Inc.    2006.12     */
2526/*                                                                      */
2527/************************************************************************/
2528u16_t zfAggTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port, u16_t bufType, u8_t flag, struct aggControl *aggControl, TID_TX tid_tx)
2529{
2530    u16_t err;
2531    //u16_t addrTblSize;
2532    //struct zsAddrTbl addrTbl;
2533    u16_t removeLen;
2534    u16_t header[(8+30+2+18)/2];    /* ctr+(4+a1+a2+a3+2+a4)+qos+iv */
2535    u16_t headerLen;
2536    u16_t mic[8/2];
2537    u16_t micLen;
2538    u16_t snap[8/2];
2539    u16_t snapLen;
2540    u16_t fragLen;
2541    u16_t frameLen;
2542    u16_t fragNum;
2543    struct zsFrag frag;
2544    u16_t i, id;
2545    u16_t da[3];
2546    u16_t sa[3];
2547    u8_t up;
2548    u8_t qosType, keyIdx = 0;
2549    u16_t fragOff;
2550
2551    zmw_get_wlan_dev(dev);
2552
2553    zmw_declare_for_critical_section();
2554
2555    zm_msg1_tx(ZM_LV_2, "zfTxSendEth(), port=", port);
2556
2557    /* Get IP TOS for QoS AC and IP frag offset */
2558    zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
2559
2560#ifdef ZM_ENABLE_NATIVE_WIFI
2561    if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
2562    {
2563        /* DA */
2564        da[0] = zmw_tx_buf_readh(dev, buf, 16);
2565        da[1] = zmw_tx_buf_readh(dev, buf, 18);
2566        da[2] = zmw_tx_buf_readh(dev, buf, 20);
2567        /* SA */
2568        sa[0] = zmw_tx_buf_readh(dev, buf, 10);
2569        sa[1] = zmw_tx_buf_readh(dev, buf, 12);
2570        sa[2] = zmw_tx_buf_readh(dev, buf, 14);
2571    }
2572    else if ( wd->wlanMode == ZM_MODE_IBSS )
2573    {
2574        /* DA */
2575        da[0] = zmw_tx_buf_readh(dev, buf, 4);
2576        da[1] = zmw_tx_buf_readh(dev, buf, 6);
2577        da[2] = zmw_tx_buf_readh(dev, buf, 8);
2578        /* SA */
2579        sa[0] = zmw_tx_buf_readh(dev, buf, 10);
2580        sa[1] = zmw_tx_buf_readh(dev, buf, 12);
2581        sa[2] = zmw_tx_buf_readh(dev, buf, 14);
2582    }
2583    else if ( wd->wlanMode == ZM_MODE_AP )
2584    {
2585        /* DA */
2586        da[0] = zmw_tx_buf_readh(dev, buf, 4);
2587        da[1] = zmw_tx_buf_readh(dev, buf, 6);
2588        da[2] = zmw_tx_buf_readh(dev, buf, 8);
2589        /* SA */
2590        sa[0] = zmw_tx_buf_readh(dev, buf, 16);
2591        sa[1] = zmw_tx_buf_readh(dev, buf, 18);
2592        sa[2] = zmw_tx_buf_readh(dev, buf, 20);
2593    }
2594    else
2595    {
2596        //
2597    }
2598#else
2599    /* DA */
2600    da[0] = zmw_tx_buf_readh(dev, buf, 0);
2601    da[1] = zmw_tx_buf_readh(dev, buf, 2);
2602    da[2] = zmw_tx_buf_readh(dev, buf, 4);
2603    /* SA */
2604    sa[0] = zmw_tx_buf_readh(dev, buf, 6);
2605    sa[1] = zmw_tx_buf_readh(dev, buf, 8);
2606    sa[2] = zmw_tx_buf_readh(dev, buf, 10);
2607#endif
2608    //Decide Key Index in ATOM, No meaning in OTUS--CWYang(m)
2609    if (wd->wlanMode == ZM_MODE_AP)
2610    {
2611        keyIdx = wd->ap.bcHalKeyIdx[port];
2612        id = zfApFindSta(dev, da);
2613        if (id != 0xffff)
2614        {
2615            switch (wd->ap.staTable[id].encryMode)
2616            {
2617            case ZM_AES:
2618            case ZM_TKIP:
2619#ifdef ZM_ENABLE_CENC
2620            case ZM_CENC:
2621#endif //ZM_ENABLE_CENC
2622                keyIdx = wd->ap.staTable[id].keyIdx;
2623                break;
2624            }
2625        }
2626    }
2627    else
2628    {
2629        switch (wd->sta.encryMode)
2630        {
2631        case ZM_WEP64:
2632        case ZM_WEP128:
2633        case ZM_WEP256:
2634            keyIdx = wd->sta.keyId;
2635            break;
2636        case ZM_AES:
2637        case ZM_TKIP:
2638            if ((da[0]& 0x1))
2639                keyIdx = 5;
2640            else
2641                keyIdx = 4;
2642            break;
2643#ifdef ZM_ENABLE_CENC
2644        case ZM_CENC:
2645            keyIdx = wd->sta.cencKeyId;
2646            break;
2647#endif //ZM_ENABLE_CENC
2648        }
2649    }
2650
2651    /* Create SNAP */
2652    removeLen = zfTxGenWlanSnap(dev, buf, snap, &snapLen);
2653    //zm_msg1_tx(ZM_LV_0, "fragOff=", fragOff);
2654
2655    fragLen = wd->fragThreshold;
2656    frameLen = zfwBufGetSize(dev, buf);
2657    frameLen -= removeLen;
2658
2659#if 0
2660    /* Create MIC */
2661    if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)&&
2662         (wd->sta.encryMode == ZM_TKIP) )
2663    {
2664        if ( frameLen > fragLen )
2665        {
2666            micLen = zfTxGenWlanTail(dev, buf, snap, snapLen, mic);
2667        }
2668        else
2669        {
2670            /* append MIC by HMAC */
2671            micLen = 8;
2672        }
2673    }
2674    else
2675    {
2676        micLen = 0;
2677    }
2678#else
2679    if ( frameLen > fragLen )
2680    {
2681        micLen = zfTxGenWlanTail(dev, buf, snap, snapLen, mic);
2682    }
2683    else
2684    {
2685        /* append MIC by HMAC */
2686        micLen = 0;
2687    }
2688#endif
2689
2690    /* Access Category */
2691    if (wd->wlanMode == ZM_MODE_AP)
2692    {
2693        zfApGetStaQosType(dev, da, &qosType);
2694        if (qosType == 0)
2695        {
2696            up = 0;
2697        }
2698    }
2699    else if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
2700    {
2701        if (wd->sta.wmeConnected == 0)
2702        {
2703            up = 0;
2704        }
2705    }
2706    else
2707    {
2708        /* TODO : STA QoS control field */
2709        up = 0;
2710    }
2711
2712    /* Assign sequence number */
2713    zmw_enter_critical_section(dev);
2714    frag.seq[0] = ((wd->seq[zcUpToAc[up&0x7]]++) << 4);
2715    if (aggControl && (ZM_AGG_FIRST_MPDU == aggControl->ampduIndication) ) {
2716        tid_tx->bar_ssn = frag.seq[0];
2717
2718        zm_msg1_agg(ZM_LV_0, "start seq=", tid_tx->bar_ssn >> 4);
2719    }
2720    //tid_tx->baw_buf[tid_tx->baw_head-1].baw_seq=frag.seq[0];
2721    zmw_leave_critical_section(dev);
2722
2723
2724        frag.buf[0] = buf;
2725        frag.bufType[0] = bufType;
2726        frag.flag[0] = flag;
2727        fragNum = 1;
2728
2729    for (i=0; i<fragNum; i++)
2730    {
2731        /* Create WLAN header(Control Setting + 802.11 header + IV) */
2732        if (up !=0 ) zm_debug_msg1("up not 0, up=",up);
2733        headerLen = zfTxGenWlanHeader(dev, frag.buf[i], header, frag.seq[i],
2734                                      frag.flag[i], snapLen+micLen, removeLen,
2735                                      port, da, sa, up, &micLen, snap, snapLen,
2736                                      aggControl);
2737
2738        /* Get buffer DMA address */
2739        //if ((addrTblSize = zfwBufMapDma(dev, frag.buf[i], &addrTbl)) == 0)
2740        //if ((addrTblSize = zfwMapTxDma(dev, frag.buf[i], &addrTbl)) == 0)
2741        //{
2742        //    err = ZM_ERR_BUFFER_DMA_ADDR;
2743        //    goto zlError;
2744        //}
2745
2746        /* Flush buffer on cache */
2747        //zfwBufFlush(dev, frag.buf[i]);
2748
2749#if 0
2750        zm_msg1_tx(ZM_LV_0, "headerLen=", headerLen);
2751        zm_msg1_tx(ZM_LV_0, "snapLen=", snapLen);
2752        zm_msg1_tx(ZM_LV_0, "micLen=", micLen);
2753        zm_msg1_tx(ZM_LV_0, "removeLen=", removeLen);
2754        zm_msg1_tx(ZM_LV_0, "addrTblSize=", addrTblSize);
2755        zm_msg1_tx(ZM_LV_0, "frag.bufType[0]=", frag.bufType[0]);
2756#endif
2757
2758        fragLen = zfwBufGetSize(dev, frag.buf[i]);
2759        if ((da[0]&0x1) == 0)
2760        {
2761            wd->commTally.txUnicastFrm++;
2762            wd->commTally.txUnicastOctets += (fragLen+snapLen);
2763        }
2764        else if ((da[0]& 0x1))
2765        {
2766            wd->commTally.txBroadcastFrm++;
2767            wd->commTally.txBroadcastOctets += (fragLen+snapLen);
2768        }
2769        else
2770        {
2771            wd->commTally.txMulticastFrm++;
2772            wd->commTally.txMulticastOctets += (fragLen+snapLen);
2773        }
2774        wd->ledStruct.txTraffic++;
2775
2776#if 0 //Who care this?
2777        if ( (i)&&(i == (fragNum-1)) )
2778        {
2779            wd->trafTally.txDataByteCount -= micLen;
2780        }
2781#endif
2782
2783        /*if (aggControl->tid_baw && aggControl->aggEnabled) {
2784            struct baw_header_r header_r;
2785
2786            header_r.header      = header;
2787            header_r.mic         = mic;
2788            header_r.snap        = snap;
2789            header_r.headerLen   = headerLen;
2790            header_r.micLen      = micLen;
2791            header_r.snapLen     = snapLen;
2792            header_r.removeLen   = removeLen;
2793            header_r.keyIdx      = keyIdx;
2794
2795            BAW->insert(dev, buf, tid_tx->bar_ssn >> 4, aggControl->tid_baw, 0, &header_r);
2796        }*/
2797
2798        if ((err = zfHpSend(dev, header, headerLen, snap, snapLen,
2799                             mic, micLen, frag.buf[i], removeLen,
2800                             frag.bufType[i], zcUpToAc[up&0x7], keyIdx)) != ZM_SUCCESS)
2801        {
2802            goto zlError;
2803        }
2804
2805
2806        continue;
2807
2808zlError:
2809        if (frag.bufType[i] == ZM_EXTERNAL_ALLOC_BUF)
2810        {
2811            zfwBufFree(dev, frag.buf[i], err);
2812        }
2813        else if (frag.bufType[i] == ZM_INTERNAL_ALLOC_BUF)
2814        {
2815            zfwBufFree(dev, frag.buf[i], 0);
2816        }
2817        else
2818        {
2819            zm_assert(0);
2820        }
2821    } /* for (i=0; i<fragNum; i++) */
2822
2823    return ZM_SUCCESS;
2824}
2825
2826/*
2827 * zfAggSendADDBA() refers zfSendMmFrame() in cmm.c
2828 */
2829u16_t   zfAggSendAddbaRequest(zdev_t* dev, u16_t *dst, u16_t ac, u16_t up)
2830{
2831    zbuf_t* buf;
2832    //u16_t addrTblSize;
2833    //struct zsAddrTbl addrTbl;
2834    //u16_t err;
2835    u16_t offset = 0;
2836    u16_t hlen = 32;
2837    u16_t header[(24+25+1)/2];
2838    u16_t vap = 0;
2839    u16_t i;
2840    u8_t encrypt = 0;
2841
2842    //zmw_get_wlan_dev(dev);
2843
2844    //zmw_declare_for_critical_section();
2845
2846
2847    /*
2848     * TBD : Maximum size of management frame
2849     */
2850    if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
2851    {
2852        zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
2853        return ZM_SUCCESS;
2854    }
2855
2856    /*
2857     * Reserve room for wlan header
2858     */
2859    offset = hlen;
2860
2861    /*
2862     * add addba frame body
2863     */
2864    offset = zfAggSetAddbaFrameBody(dev, buf, offset, ac, up);
2865
2866
2867    zfwBufSetSize(dev, buf, offset);
2868
2869    /*
2870     * Copy wlan header
2871     */
2872    zfAggGenAddbaHeader(dev, dst, header, offset-hlen, buf, vap, encrypt);
2873    for (i=0; i<(hlen>>1); i++)
2874    {
2875        zmw_tx_buf_writeh(dev, buf, i*2, header[i]);
2876    }
2877
2878    /* Get buffer DMA address */
2879    //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
2880    //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
2881    //{
2882    //    goto zlError;
2883    //}
2884
2885    //zm_msg2_mm(ZM_LV_2, "offset=", offset);
2886    //zm_msg2_mm(ZM_LV_2, "hlen=", hlen);
2887    //zm_msg2_mm(ZM_LV_2, "addrTblSize=", addrTblSize);
2888    //zm_msg2_mm(ZM_LV_2, "addrTbl.len[0]=", addrTbl.len[0]);
2889    //zm_msg2_mm(ZM_LV_2, "addrTbl.physAddrl[0]=", addrTbl.physAddrl[0]);
2890    //zm_msg2_mm(ZM_LV_2, "buf->data=", buf->data);
2891
2892    #if 0
2893    if ((err = zfHpSend(dev, NULL, 0, NULL, 0, NULL, 0, buf, 0,
2894            ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
2895    {
2896        goto zlError;
2897    }
2898    #else
2899    zfPutVmmq(dev, buf);
2900    zfPushVtxq(dev);
2901    #endif
2902
2903    return ZM_SUCCESS;
2904
2905}
2906
2907u16_t   zfAggSetAddbaFrameBody(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t ac, u16_t up)
2908{
2909    u16_t ba_parameter, start_seq;
2910
2911    zmw_get_wlan_dev(dev);
2912
2913    //zmw_declare_for_critical_section();
2914    /*
2915     * ADDBA Request frame body
2916     */
2917
2918    /*
2919     * Category
2920     */
2921    zmw_tx_buf_writeb(dev, buf, offset++, 3);
2922    /*
2923     * Action details = 0
2924     */
2925    zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_ADDBA_REQUEST_FRAME);
2926    /*
2927     * Dialog Token = nonzero
2928     * TBD: define how to get dialog token?
2929     */
2930    zmw_tx_buf_writeb(dev, buf, offset++, 2);
2931    /*
2932     * Block Ack parameter set
2933     * BA policy = 1 for immediate BA, 0 for delayed BA
2934     * TID(4bits) & buffer size(4bits) (TID=up & buffer size=0x80)
2935     * TBD: how to get buffer size?
2936     * ¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{
2937     * ¢x    B0    ¢x    B1     ¢x B2  B5 ¢x B6      B15 ¢x
2938     * ¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t
2939     * ¢x Reserved ¢x BA policy ¢x  TID   ¢x Buffer size ¢x
2940     * ¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}
2941     */
2942    ba_parameter = 1 << 12;     // buffer size = 0x40(64)
2943    ba_parameter |= up << 2;    // tid = up
2944    ba_parameter |= 2;          // ba policy = 1
2945    zmw_tx_buf_writeh(dev, buf, offset, ba_parameter);
2946    offset+=2;
2947    /*
2948     * BA timeout value
2949     */
2950    zmw_tx_buf_writeh(dev, buf, offset, 0);
2951    offset+=2;
2952    /*
2953     * BA starting sequence number
2954     * ¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{
2955     * ¢x B0       B3 ¢x B4              B15 ¢x
2956     * ¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t
2957     * ¢x Frag num(0) ¢x BA starting seq num ¢x
2958     * ¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}
2959     */
2960    start_seq = ((wd->seq[ac]) << 4) & 0xFFF0;
2961    zmw_tx_buf_writeh(dev, buf, offset, start_seq);
2962    offset+=2;
2963
2964    return offset;
2965}
2966
2967u16_t zfAggGenAddbaHeader(zdev_t* dev, u16_t* dst,
2968        u16_t* header, u16_t len, zbuf_t* buf, u16_t vap, u8_t encrypt)
2969{
2970    u8_t  hlen = 32;        // MAC ctrl + PHY ctrl + 802.11 MM header
2971    //u8_t frameType = ZM_WLAN_FRAME_TYPE_ACTION;
2972
2973    zmw_get_wlan_dev(dev);
2974
2975    zmw_declare_for_critical_section();
2976
2977    /*
2978     * Generate control setting
2979     */
2980    //bodyLen = zfwBufGetSize(dev, buf);
2981    header[0] = 24+len+4;   //Length
2982    header[1] = 0x8;        //MAC control, backoff + (ack)
2983
2984#if 0
2985    /* CCK 1M */
2986    header[2] = 0x0f00;          //PHY control L
2987    header[3] = 0x0000;          //PHY control H
2988#else
2989    /* OFDM 6M */
2990    header[2] = 0x0f01;          //PHY control L
2991    header[3] = 0x000B;          //PHY control H
2992#endif
2993
2994    /*
2995     * Generate WLAN header
2996     * Frame control frame type and subtype
2997     */
2998    header[4+0] = ZM_WLAN_FRAME_TYPE_ACTION;
2999    /*
3000     * Duration
3001     */
3002    header[4+1] = 0;
3003
3004    if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
3005    {
3006        header[4+8] = wd->sta.bssid[0];
3007        header[4+9] = wd->sta.bssid[1];
3008        header[4+10] = wd->sta.bssid[2];
3009    }
3010    else if (wd->wlanMode == ZM_MODE_PSEUDO)
3011    {
3012        /* Address 3 = 00:00:00:00:00:00 */
3013        header[4+8] = 0;
3014        header[4+9] = 0;
3015        header[4+10] = 0;
3016    }
3017    else if (wd->wlanMode == ZM_MODE_IBSS)
3018    {
3019        header[4+8] = wd->sta.bssid[0];
3020        header[4+9] = wd->sta.bssid[1];
3021        header[4+10] = wd->sta.bssid[2];
3022    }
3023    else if (wd->wlanMode == ZM_MODE_AP)
3024    {
3025        /* Address 3 = BSSID */
3026        header[4+8] = wd->macAddr[0];
3027        header[4+9] = wd->macAddr[1];
3028        header[4+10] = wd->macAddr[2] + (vap<<8);
3029    }
3030
3031    /* Address 1 = DA */
3032    header[4+2] = dst[0];
3033    header[4+3] = dst[1];
3034    header[4+4] = dst[2];
3035
3036    /* Address 2 = SA */
3037    header[4+5] = wd->macAddr[0];
3038    header[4+6] = wd->macAddr[1];
3039    if (wd->wlanMode == ZM_MODE_AP)
3040    {
3041        header[4+7] = wd->macAddr[2] + (vap<<8);
3042    }
3043    else
3044    {
3045        header[4+7] = wd->macAddr[2];
3046    }
3047
3048    /* Sequence Control */
3049    zmw_enter_critical_section(dev);
3050    header[4+11] = ((wd->mmseq++)<<4);
3051    zmw_leave_critical_section(dev);
3052
3053
3054    return hlen;
3055}
3056
3057
3058u16_t   zfAggProcessAction(zdev_t* dev, zbuf_t* buf)
3059{
3060    u16_t category;
3061
3062    //zmw_get_wlan_dev(dev);
3063
3064    //zmw_declare_for_critical_section();
3065
3066    category = zmw_rx_buf_readb(dev, buf, 24);
3067
3068    switch (category)
3069    {
3070    case ZM_WLAN_BLOCK_ACK_ACTION_FRAME:
3071        zfAggBlockAckActionFrame(dev, buf);
3072        break;
3073
3074    }
3075
3076    return ZM_SUCCESS;
3077}
3078
3079
3080u16_t   zfAggBlockAckActionFrame(zdev_t* dev, zbuf_t* buf)
3081{
3082    u8_t action;
3083
3084    //zmw_get_wlan_dev(dev);
3085
3086    //zmw_declare_for_critical_section();
3087
3088    action = zmw_rx_buf_readb(dev, buf, 25);
3089#ifdef ZM_ENABLE_AGGREGATION
3090    switch (action)
3091    {
3092    case ZM_WLAN_ADDBA_REQUEST_FRAME:
3093        zm_msg0_agg(ZM_LV_0, "Received BA Action frame is ADDBA request");
3094        zfAggRecvAddbaRequest(dev, buf);
3095        break;
3096    case ZM_WLAN_ADDBA_RESPONSE_FRAME:
3097        zm_msg0_agg(ZM_LV_0, "Received BA Action frame is ADDBA response");
3098        zfAggRecvAddbaResponse(dev, buf);
3099        break;
3100    case ZM_WLAN_DELBA_FRAME:
3101        zfAggRecvDelba(dev, buf);
3102        break;
3103    }
3104#endif
3105    return ZM_SUCCESS;
3106}
3107
3108u16_t   zfAggRecvAddbaRequest(zdev_t* dev, zbuf_t* buf)
3109{
3110    //u16_t dialog;
3111    struct aggBaFrameParameter bf;
3112    u16_t i;
3113    //zmw_get_wlan_dev(dev);
3114
3115    //zmw_declare_for_critical_section();
3116
3117    bf.buf = buf;
3118    bf.dialog = zmw_rx_buf_readb(dev, buf, 26);
3119    /*
3120     * ba parameter set
3121     */
3122    bf.ba_parameter = zmw_rx_buf_readh(dev, buf, 27);
3123    bf.ba_policy   = (bf.ba_parameter >> 1) & 1;
3124    bf.tid         = (bf.ba_parameter >> 2) & 0xF;
3125    bf.buffer_size = (bf.ba_parameter >> 6);
3126    /*
3127     * BA timeout value
3128     */
3129    bf.ba_timeout = zmw_rx_buf_readh(dev, buf, 29);
3130    /*
3131     * BA starting sequence number
3132     */
3133    bf.ba_start_seq = zmw_rx_buf_readh(dev, buf, 31) >> 4;
3134
3135    i=26;
3136    while(i < 32) {
3137        zm_debug_msg2("Recv ADDBA Req:", zmw_rx_buf_readb(dev,buf,i));
3138        i++;
3139    }
3140
3141    zfAggSendAddbaResponse(dev, &bf);
3142
3143    zfAggAddbaSetTidRx(dev, buf, &bf);
3144
3145    return ZM_SUCCESS;
3146}
3147
3148u16_t   zfAggAddbaSetTidRx(zdev_t* dev, zbuf_t* buf, struct aggBaFrameParameter *bf)
3149{
3150    u16_t i, ac, aid, fragOff;
3151    u16_t src[3];
3152    u16_t offset = 0;
3153    u8_t  up;
3154    struct agg_tid_rx *tid_rx = NULL;
3155
3156    zmw_get_wlan_dev(dev);
3157
3158    zmw_declare_for_critical_section();
3159
3160    src[0] = zmw_rx_buf_readh(dev, buf, offset+10);
3161    src[1] = zmw_rx_buf_readh(dev, buf, offset+12);
3162    src[2] = zmw_rx_buf_readh(dev, buf, offset+14);
3163    aid = zfApFindSta(dev, src);
3164
3165    zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
3166    ac = zcUpToAc[up&0x7] & 0x3;
3167
3168    ac = bf->tid;
3169
3170    for (i=0; i<ZM_AGG_POOL_SIZE ; i++)
3171    {
3172        if((wd->tid_rx[i]->aid == aid) && (wd->tid_rx[i]->ac == ac))
3173        {
3174            tid_rx = wd->tid_rx[i];
3175            break;
3176        }
3177    }
3178
3179    if (!tid_rx)
3180    {
3181        for (i=0; i<ZM_AGG_POOL_SIZE; i++)
3182        {
3183            if (wd->tid_rx[i]->aid == ZM_MAX_STA_SUPPORT)
3184            {
3185                tid_rx = wd->tid_rx[i];
3186                break;
3187            }
3188        }
3189        if (!tid_rx)
3190            return 0;
3191    }
3192
3193    zmw_enter_critical_section(dev);
3194
3195    tid_rx->aid = aid;
3196    tid_rx->ac = ac;
3197    tid_rx->addBaExchangeStatusCode = ZM_AGG_ADDBA_RESPONSE;
3198    tid_rx->seq_start = bf->ba_start_seq;
3199    tid_rx->baw_head = tid_rx->baw_tail = 0;
3200    tid_rx->sq_exceed_count = tid_rx->sq_behind_count = 0;
3201    zmw_leave_critical_section(dev);
3202
3203    return 0;
3204}
3205
3206u16_t   zfAggRecvAddbaResponse(zdev_t* dev, zbuf_t* buf)
3207{
3208    u16_t i,ac, aid=0;
3209    u16_t src[3];
3210    struct aggBaFrameParameter bf;
3211
3212    zmw_get_wlan_dev(dev);
3213
3214    //zmw_declare_for_critical_section();
3215
3216    src[0] = zmw_rx_buf_readh(dev, buf, 10);
3217    src[1] = zmw_rx_buf_readh(dev, buf, 12);
3218    src[2] = zmw_rx_buf_readh(dev, buf, 14);
3219
3220    if (wd->wlanMode == ZM_MODE_AP)
3221        aid = zfApFindSta(dev, src);
3222
3223
3224    bf.buf = buf;
3225    bf.dialog = zmw_rx_buf_readb(dev, buf, 26);
3226    bf.status_code = zmw_rx_buf_readh(dev, buf, 27);
3227    if (!bf.status_code)
3228    {
3229        wd->addbaComplete=1;
3230    }
3231
3232    /*
3233     * ba parameter set
3234     */
3235    bf.ba_parameter = zmw_rx_buf_readh(dev, buf, 29);
3236    bf.ba_policy   = (bf.ba_parameter >> 1) & 1;
3237    bf.tid         = (bf.ba_parameter >> 2) & 0xF;
3238    bf.buffer_size = (bf.ba_parameter >> 6);
3239    /*
3240     * BA timeout value
3241     */
3242    bf.ba_timeout = zmw_rx_buf_readh(dev, buf, 31);
3243
3244    i=26;
3245    while(i < 32) {
3246        zm_debug_msg2("Recv ADDBA Rsp:", zmw_rx_buf_readb(dev,buf,i));
3247        i++;
3248    }
3249
3250    ac = zcUpToAc[bf.tid&0x7] & 0x3;
3251
3252    //zmw_enter_critical_section(dev);
3253
3254    //wd->aggSta[aid].aggFlag[ac] = 0;
3255
3256    //zmw_leave_critical_section(dev);
3257
3258    return ZM_SUCCESS;
3259}
3260
3261u16_t   zfAggRecvDelba(zdev_t* dev, zbuf_t* buf)
3262{
3263    //zmw_get_wlan_dev(dev);
3264
3265    //zmw_declare_for_critical_section();
3266    return ZM_SUCCESS;
3267}
3268
3269u16_t   zfAggSendAddbaResponse(zdev_t* dev, struct aggBaFrameParameter *bf)
3270{
3271    zbuf_t* buf;
3272    //u16_t addrTblSize;
3273    //struct zsAddrTbl addrTbl;
3274    //u16_t err;
3275    u16_t offset = 0;
3276    u16_t hlen = 32;
3277    u16_t header[(24+25+1)/2];
3278    u16_t vap = 0;
3279    u16_t i;
3280    u8_t encrypt = 0;
3281    u16_t dst[3];
3282
3283    //zmw_get_wlan_dev(dev);
3284
3285    //zmw_declare_for_critical_section();
3286
3287
3288    /*
3289     * TBD : Maximum size of management frame
3290     */
3291    if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
3292    {
3293        zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
3294        return ZM_SUCCESS;
3295    }
3296
3297    /*
3298     * Reserve room for wlan header
3299     */
3300    offset = hlen;
3301
3302    /*
3303     * add addba frame body
3304     */
3305    offset = zfAggSetAddbaResponseFrameBody(dev, buf, bf, offset);
3306
3307
3308    zfwBufSetSize(dev, buf, offset);
3309
3310    /*
3311     * Copy wlan header
3312     */
3313
3314    dst[0] = zmw_rx_buf_readh(dev, bf->buf, 10);
3315    dst[1] = zmw_rx_buf_readh(dev, bf->buf, 12);
3316    dst[2] = zmw_rx_buf_readh(dev, bf->buf, 14);
3317    zfAggGenAddbaHeader(dev, dst, header, offset-hlen, buf, vap, encrypt);
3318    for (i=0; i<(hlen>>1); i++)
3319    {
3320        zmw_tx_buf_writeh(dev, buf, i*2, header[i]);
3321    }
3322
3323    /* Get buffer DMA address */
3324    //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
3325    //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
3326    //{
3327    //    goto zlError;
3328    //}
3329
3330    //zm_msg2_mm(ZM_LV_2, "offset=", offset);
3331    //zm_msg2_mm(ZM_LV_2, "hlen=", hlen);
3332    //zm_msg2_mm(ZM_LV_2, "addrTblSize=", addrTblSize);
3333    //zm_msg2_mm(ZM_LV_2, "addrTbl.len[0]=", addrTbl.len[0]);
3334    //zm_msg2_mm(ZM_LV_2, "addrTbl.physAddrl[0]=", addrTbl.physAddrl[0]);
3335    //zm_msg2_mm(ZM_LV_2, "buf->data=", buf->data);
3336
3337    #if 0
3338    if ((err = zfHpSend(dev, NULL, 0, NULL, 0, NULL, 0, buf, 0,
3339            ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
3340    {
3341        goto zlError;
3342    }
3343    #else
3344    zfPutVmmq(dev, buf);
3345    zfPushVtxq(dev);
3346    #endif
3347
3348    //zfAggSendAddbaRequest(dev, dst, zcUpToAc[bf->tid&0x7] & 0x3, bf->tid);
3349    return ZM_SUCCESS;
3350
3351}
3352
3353u16_t   zfAggSetAddbaResponseFrameBody(zdev_t* dev, zbuf_t* buf,
3354                struct aggBaFrameParameter *bf, u16_t offset)
3355{
3356
3357    //zmw_get_wlan_dev(dev);
3358
3359    //zmw_declare_for_critical_section();
3360    /*
3361     * ADDBA Request frame body
3362     */
3363
3364    /*
3365     * Category
3366     */
3367    zmw_tx_buf_writeb(dev, buf, offset++, 3);
3368    /*
3369     * Action details = 0
3370     */
3371    zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_ADDBA_RESPONSE_FRAME);
3372    /*
3373     * Dialog Token = nonzero
3374     */
3375    zmw_tx_buf_writeb(dev, buf, offset++, bf->dialog);
3376    /*
3377     * Status code
3378     */
3379    zmw_tx_buf_writeh(dev, buf, offset, 0);
3380    offset+=2;
3381    /*
3382     * Block Ack parameter set
3383     * BA policy = 1 for immediate BA, 0 for delayed BA
3384     * TID(4bits) & buffer size(4bits) (TID=0x1 & buffer size=0x80)
3385     * TBD: how to get TID number and buffer size?
3386     * ¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{
3387     * ¢x    B0    ¢x    B1     ¢x B2  B5 ¢x B6      B15 ¢x
3388     * ¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t
3389     * ¢x Reserved ¢x BA policy ¢x  TID   ¢x Buffer size ¢x
3390     * ¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}
3391     */
3392    zmw_tx_buf_writeh(dev, buf, offset, bf->ba_parameter);
3393    offset+=2;
3394    /*
3395     * BA timeout value
3396     */
3397    zmw_tx_buf_writeh(dev, buf, offset, bf->ba_timeout);
3398    offset+=2;
3399
3400    return offset;
3401}
3402
3403void   zfAggInvokeBar(zdev_t* dev, TID_TX tid_tx)
3404{
3405    struct aggBarControl aggBarControl;
3406    //zmw_get_wlan_dev(dev);
3407
3408    //zmw_declare_for_critical_section();
3409    //bar_control = aggBarControl->tid_info << 12 | aggBarControl->compressed_bitmap << 2
3410    //        | aggBarControl->multi_tid << 1 | aggBarControl->bar_ack_policy;
3411    aggBarControl.bar_ack_policy = 0;
3412    aggBarControl.multi_tid = 0;
3413    aggBarControl.compressed_bitmap = 0;
3414    aggBarControl.tid_info = tid_tx->tid;
3415    zfAggSendBar(dev, tid_tx, &aggBarControl);
3416
3417    return;
3418
3419}
3420/*
3421 * zfAggSendBar() refers zfAggSendAddbaRequest()
3422 */
3423u16_t   zfAggSendBar(zdev_t* dev, TID_TX tid_tx, struct aggBarControl *aggBarControl)
3424{
3425    zbuf_t* buf;
3426    //u16_t addrTblSize;
3427    //struct zsAddrTbl addrTbl;
3428    //u16_t err;
3429    u16_t offset = 0;
3430    u16_t hlen = 16+8;  /* mac header + control headers*/
3431    u16_t header[(8+24+1)/2];
3432    u16_t vap = 0;
3433    u16_t i;
3434    u8_t encrypt = 0;
3435
3436    //zmw_get_wlan_dev(dev);
3437
3438    //zmw_declare_for_critical_section();
3439
3440
3441    /*
3442     * TBD : Maximum size of management frame
3443     */
3444    if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
3445    {
3446        zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
3447        return ZM_SUCCESS;
3448    }
3449
3450    /*
3451     * Reserve room for wlan header
3452     */
3453    offset = hlen;
3454
3455    /*
3456     * add addba frame body
3457     */
3458    offset = zfAggSetBarBody(dev, buf, offset, tid_tx, aggBarControl);
3459
3460
3461    zfwBufSetSize(dev, buf, offset);
3462
3463    /*
3464     * Copy wlan header
3465     */
3466    zfAggGenBarHeader(dev, tid_tx->dst, header, offset-hlen, buf, vap, encrypt);
3467    for (i=0; i<(hlen>>1); i++)
3468    {
3469        zmw_tx_buf_writeh(dev, buf, i*2, header[i]);
3470    }
3471
3472    /* Get buffer DMA address */
3473    //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
3474    //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
3475    //{
3476    //    goto zlError;
3477    //}
3478
3479    //zm_msg2_mm(ZM_LV_2, "offset=", offset);
3480    //zm_msg2_mm(ZM_LV_2, "hlen=", hlen);
3481    //zm_msg2_mm(ZM_LV_2, "addrTblSize=", addrTblSize);
3482    //zm_msg2_mm(ZM_LV_2, "addrTbl.len[0]=", addrTbl.len[0]);
3483    //zm_msg2_mm(ZM_LV_2, "addrTbl.physAddrl[0]=", addrTbl.physAddrl[0]);
3484    //zm_msg2_mm(ZM_LV_2, "buf->data=", buf->data);
3485
3486    #if 0
3487    if ((err = zfHpSend(dev, NULL, 0, NULL, 0, NULL, 0, buf, 0,
3488            ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
3489    {
3490        goto zlError;
3491    }
3492    #else
3493    zfPutVmmq(dev, buf);
3494    zfPushVtxq(dev);
3495    #endif
3496
3497    return ZM_SUCCESS;
3498
3499}
3500
3501u16_t   zfAggSetBarBody(zdev_t* dev, zbuf_t* buf, u16_t offset, TID_TX tid_tx, struct aggBarControl *aggBarControl)
3502{
3503    u16_t bar_control, start_seq;
3504
3505    //zmw_get_wlan_dev(dev);
3506
3507    //zmw_declare_for_critical_section();
3508    /*
3509     * BAR Control frame body
3510     */
3511
3512    /*
3513     * BAR Control Field
3514     * ¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{
3515     * ¢x    B0   ¢x    B1     ¢x     B2     ¢x B3   B11 ¢x B12  B15 ¢x
3516     * ¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t
3517     * ¢x BAR Ack ¢x Multi-TID ¢x Compressed ¢x Reserved ¢x TID_INFO ¢x
3518     * ¢x  Policy ¢x           ¢x   Bitmap   ¢x          ¢x          ¢x
3519     * ¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}
3520     */
3521    bar_control = aggBarControl->tid_info << 12 | aggBarControl->compressed_bitmap << 2
3522            | aggBarControl->multi_tid << 1 | aggBarControl->bar_ack_policy;
3523
3524    zmw_tx_buf_writeh(dev, buf, offset, bar_control);
3525    offset+=2;
3526    if (0 == aggBarControl->multi_tid) {
3527        /*
3528         * BA starting sequence number
3529         * ¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{
3530         * ¢x B0       B3 ¢x B4              B15 ¢x
3531         * ¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t
3532         * ¢x Frag num(0) ¢x BA starting seq num ¢x
3533         * ¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}
3534         */
3535        start_seq = (tid_tx->bar_ssn << 4) & 0xFFF0;
3536        zmw_tx_buf_writeh(dev, buf, offset, start_seq);
3537        offset+=2;
3538    }
3539    if (1 == aggBarControl->multi_tid && 1 == aggBarControl->compressed_bitmap) {
3540        /* multi-tid BlockAckReq variant, not implemented*/
3541    }
3542
3543    return offset;
3544}
3545
3546u16_t zfAggGenBarHeader(zdev_t* dev, u16_t* dst,
3547        u16_t* header, u16_t len, zbuf_t* buf, u16_t vap, u8_t encrypt)
3548{
3549    u8_t  hlen = 16+8;        // MAC ctrl + PHY ctrl + 802.11 MM header
3550    //u8_t frameType = ZM_WLAN_FRAME_TYPE_ACTION;
3551
3552    zmw_get_wlan_dev(dev);
3553
3554    zmw_declare_for_critical_section();
3555
3556    /*
3557     * Generate control setting
3558     */
3559    //bodyLen = zfwBufGetSize(dev, buf);
3560    header[0] = 16+len+4;   //Length
3561    header[1] = 0x8;        //MAC control, backoff + (ack)
3562
3563#if 1
3564    /* CCK 1M */
3565    header[2] = 0x0f00;          //PHY control L
3566    header[3] = 0x0000;          //PHY control H
3567#else
3568    /* CCK 6M */
3569    header[2] = 0x0f01;          //PHY control L
3570    header[3] = 0x000B;          //PHY control H
3571
3572#endif
3573    /*
3574     * Generate WLAN header
3575     * Frame control frame type and subtype
3576     */
3577    header[4+0] = ZM_WLAN_FRAME_TYPE_BAR;
3578    /*
3579     * Duration
3580     */
3581    header[4+1] = 0;
3582
3583    /* Address 1 = DA */
3584    header[4+2] = dst[0];
3585    header[4+3] = dst[1];
3586    header[4+4] = dst[2];
3587
3588    /* Address 2 = SA */
3589    header[4+5] = wd->macAddr[0];
3590    header[4+6] = wd->macAddr[1];
3591    if (wd->wlanMode == ZM_MODE_AP)
3592    {
3593#ifdef ZM_VAPMODE_MULTILE_SSID
3594        header[4+7] = wd->macAddr[2]; //Multiple SSID
3595#else
3596        header[4+7] = wd->macAddr[2] + (vap<<8); //VAP
3597#endif
3598    }
3599    else
3600    {
3601        header[4+7] = wd->macAddr[2];
3602    }
3603
3604    /* Sequence Control */
3605    zmw_enter_critical_section(dev);
3606    header[4+11] = ((wd->mmseq++)<<4);
3607    zmw_leave_critical_section(dev);
3608
3609
3610    return hlen;
3611}
3612