linux/drivers/staging/rt2870/common/cmm_data_2870.c
<<
>>
Prefs
   1/*
   2 *************************************************************************
   3 * Ralink Tech Inc.
   4 * 5F., No.36, Taiyuan St., Jhubei City,
   5 * Hsinchu County 302,
   6 * Taiwan, R.O.C.
   7 *
   8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
   9 *
  10 * This program is free software; you can redistribute it and/or modify  *
  11 * it under the terms of the GNU General Public License as published by  *
  12 * the Free Software Foundation; either version 2 of the License, or     *
  13 * (at your option) any later version.                                   *
  14 *                                                                       *
  15 * This program is distributed in the hope that it will be useful,       *
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  18 * GNU General Public License for more details.                          *
  19 *                                                                       *
  20 * You should have received a copy of the GNU General Public License     *
  21 * along with this program; if not, write to the                         *
  22 * Free Software Foundation, Inc.,                                       *
  23 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  24 *                                                                       *
  25 *************************************************************************
  26*/
  27/*
  28   All functions in this file must be USB-depended, or you should out your function
  29        in other files.
  30
  31*/
  32#include "../rt_config.h"
  33
  34
  35/*
  36        We can do copy the frame into pTxContext when match following conditions.
  37                =>
  38                =>
  39                =>
  40*/
  41static inline NDIS_STATUS RtmpUSBCanDoWrite(
  42        IN RTMP_ADAPTER         *pAd,
  43        IN UCHAR                        QueIdx,
  44        IN HT_TX_CONTEXT        *pHTTXContext)
  45{
  46        NDIS_STATUS     canWrite = NDIS_STATUS_RESOURCES;
  47
  48        if (((pHTTXContext->CurWritePosition) < pHTTXContext->NextBulkOutPosition) && (pHTTXContext->CurWritePosition + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)
  49        {
  50                DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c1!\n"));
  51                RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
  52        }
  53        else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < LOCAL_TXBUF_SIZE))
  54        {
  55                DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c2!\n"));
  56                RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
  57        }
  58        else if (pHTTXContext->bCurWriting == TRUE)
  59        {
  60                DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c3!\n"));
  61        }
  62        else
  63        {
  64                canWrite = NDIS_STATUS_SUCCESS;
  65        }
  66
  67
  68        return canWrite;
  69}
  70
  71
  72USHORT RtmpUSB_WriteSubTxResource(
  73        IN      PRTMP_ADAPTER   pAd,
  74        IN      TX_BLK                  *pTxBlk,
  75        IN      BOOLEAN                 bIsLast,
  76        OUT     USHORT                  *FreeNumber)
  77{
  78
  79        // Dummy function. Should be removed in the future.
  80        return 0;
  81
  82}
  83
  84USHORT  RtmpUSB_WriteFragTxResource(
  85        IN      PRTMP_ADAPTER   pAd,
  86        IN      TX_BLK                  *pTxBlk,
  87        IN      UCHAR                   fragNum,
  88        OUT     USHORT                  *FreeNumber)
  89{
  90        HT_TX_CONTEXT   *pHTTXContext;
  91        USHORT                  hwHdrLen;       // The hwHdrLen consist of 802.11 header length plus the header padding length.
  92        UINT32                  fillOffset;
  93        TXINFO_STRUC    *pTxInfo;
  94        TXWI_STRUC              *pTxWI;
  95        PUCHAR                  pWirelessPacket = NULL;
  96        UCHAR                   QueIdx;
  97        NDIS_STATUS             Status;
  98        unsigned long   IrqFlags;
  99        UINT32                  USBDMApktLen = 0, DMAHdrLen, padding;
 100        BOOLEAN                 TxQLastRound = FALSE;
 101
 102        //
 103        // get Tx Ring Resource & Dma Buffer address
 104        //
 105        QueIdx = pTxBlk->QueIdx;
 106        pHTTXContext  = &pAd->TxContext[QueIdx];
 107
 108        RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 109
 110        pHTTXContext  = &pAd->TxContext[QueIdx];
 111        fillOffset = pHTTXContext->CurWritePosition;
 112
 113        if(fragNum == 0)
 114        {
 115                // Check if we have enough space for this bulk-out batch.
 116                Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
 117                if (Status == NDIS_STATUS_SUCCESS)
 118                {
 119                        pHTTXContext->bCurWriting = TRUE;
 120
 121                        // Reserve space for 8 bytes padding.
 122                        if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
 123                        {
 124                                pHTTXContext->ENextBulkOutPosition += 8;
 125                                pHTTXContext->CurWritePosition += 8;
 126                                fillOffset += 8;
 127                        }
 128                        pTxBlk->Priv = 0;
 129                        pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
 130                }
 131                else
 132                {
 133                        RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 134
 135                        RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
 136                        return(Status);
 137                }
 138        }
 139        else
 140        {
 141                // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.
 142                Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
 143                if (Status == NDIS_STATUS_SUCCESS)
 144                {
 145                        fillOffset += pTxBlk->Priv;
 146                }
 147                else
 148                {
 149                        RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 150
 151                        RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
 152                        return(Status);
 153                }
 154        }
 155
 156        NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE);
 157        pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
 158        pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
 159
 160        pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
 161
 162        // copy TXWI + WLAN Header + LLC into DMA Header Buffer
 163        //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
 164        hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
 165
 166        // Build our URB for USBD
 167        DMAHdrLen = TXWI_SIZE + hwHdrLen;
 168        USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen;
 169        padding = (4 - (USBDMApktLen % 4)) & 0x03;      // round up to 4 byte alignment
 170        USBDMApktLen += padding;
 171
 172        pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen);
 173
 174        // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload
 175        RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/,  FALSE);
 176
 177        if (fragNum == pTxBlk->TotalFragNum)
 178        {
 179                pTxInfo->USBDMATxburst = 0;
 180                if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT)
 181                {
 182                        pTxInfo->SwUseLastRound = 1;
 183                        TxQLastRound = TRUE;
 184                }
 185        }
 186        else
 187        {
 188                pTxInfo->USBDMATxburst = 1;
 189        }
 190
 191        NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
 192        pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
 193        pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
 194
 195        RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 196
 197        NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
 198
 199        //      Zero the last padding.
 200        pWirelessPacket += pTxBlk->SrcBufLen;
 201        NdisZeroMemory(pWirelessPacket, padding + 8);
 202
 203        if (fragNum == pTxBlk->TotalFragNum)
 204        {
 205                RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 206
 207                // Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame.
 208                pHTTXContext->CurWritePosition += pTxBlk->Priv;
 209                if (TxQLastRound == TRUE)
 210                        pHTTXContext->CurWritePosition = 8;
 211                pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
 212
 213
 214                // Finally, set bCurWriting as FALSE
 215        pHTTXContext->bCurWriting = FALSE;
 216
 217                RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 218
 219                // succeed and release the skb buffer
 220                RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
 221        }
 222
 223
 224        return(Status);
 225
 226}
 227
 228
 229USHORT RtmpUSB_WriteSingleTxResource(
 230        IN      PRTMP_ADAPTER   pAd,
 231        IN      TX_BLK                  *pTxBlk,
 232        IN      BOOLEAN                 bIsLast,
 233        OUT     USHORT                  *FreeNumber)
 234{
 235        HT_TX_CONTEXT   *pHTTXContext;
 236        USHORT                  hwHdrLen;
 237        UINT32                  fillOffset;
 238        TXINFO_STRUC    *pTxInfo;
 239        TXWI_STRUC              *pTxWI;
 240        PUCHAR                  pWirelessPacket;
 241        UCHAR                   QueIdx;
 242        unsigned long   IrqFlags;
 243        NDIS_STATUS             Status;
 244        UINT32                  USBDMApktLen = 0, DMAHdrLen, padding;
 245        BOOLEAN                 bTxQLastRound = FALSE;
 246
 247        // For USB, didn't need PCI_MAP_SINGLE()
 248        //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE);
 249
 250
 251        //
 252        // get Tx Ring Resource & Dma Buffer address
 253        //
 254        QueIdx = pTxBlk->QueIdx;
 255
 256        RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 257        pHTTXContext  = &pAd->TxContext[QueIdx];
 258        fillOffset = pHTTXContext->CurWritePosition;
 259
 260
 261
 262        // Check ring full.
 263        Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
 264        if(Status == NDIS_STATUS_SUCCESS)
 265        {
 266                pHTTXContext->bCurWriting = TRUE;
 267
 268                pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
 269                pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
 270
 271                // Reserve space for 8 bytes padding.
 272                if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
 273                {
 274                        pHTTXContext->ENextBulkOutPosition += 8;
 275                        pHTTXContext->CurWritePosition += 8;
 276                        fillOffset += 8;
 277                }
 278                pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
 279
 280                pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
 281
 282                // copy TXWI + WLAN Header + LLC into DMA Header Buffer
 283                //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
 284                hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
 285
 286                // Build our URB for USBD
 287                DMAHdrLen = TXWI_SIZE + hwHdrLen;
 288                USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen;
 289                padding = (4 - (USBDMApktLen % 4)) & 0x03;      // round up to 4 byte alignment
 290                USBDMApktLen += padding;
 291
 292                pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen);
 293
 294                // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload
 295                //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
 296                RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/,  FALSE);
 297
 298                if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT)
 299                {
 300                        pTxInfo->SwUseLastRound = 1;
 301                        bTxQLastRound = TRUE;
 302                }
 303                NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
 304                pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
 305
 306                // We unlock it here to prevent the first 8 bytes maybe over-writed issue.
 307                //      1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext.
 308                //      2. An interrupt break our routine and handle bulk-out complete.
 309                //      3. In the bulk-out compllete, it need to do another bulk-out,
 310                //                      if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
 311                //                      but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
 312                //      4. Interrupt complete.
 313                //  5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
 314                //      6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
 315                //              and the packet will wrong.
 316                pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
 317                RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 318
 319                NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
 320                pWirelessPacket += pTxBlk->SrcBufLen;
 321                NdisZeroMemory(pWirelessPacket, padding + 8);
 322
 323                RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 324
 325                pHTTXContext->CurWritePosition += pTxBlk->Priv;
 326                if (bTxQLastRound)
 327                        pHTTXContext->CurWritePosition = 8;
 328                pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
 329
 330        pHTTXContext->bCurWriting = FALSE;
 331        }
 332
 333
 334        RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 335
 336
 337        // succeed and release the skb buffer
 338        RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
 339
 340        return(Status);
 341
 342}
 343
 344
 345USHORT RtmpUSB_WriteMultiTxResource(
 346        IN      PRTMP_ADAPTER   pAd,
 347        IN      TX_BLK                  *pTxBlk,
 348        IN      UCHAR                   frameNum,
 349        OUT     USHORT                  *FreeNumber)
 350{
 351        HT_TX_CONTEXT   *pHTTXContext;
 352        USHORT                  hwHdrLen;       // The hwHdrLen consist of 802.11 header length plus the header padding length.
 353        UINT32                  fillOffset;
 354        TXINFO_STRUC    *pTxInfo;
 355        TXWI_STRUC              *pTxWI;
 356        PUCHAR                  pWirelessPacket = NULL;
 357        UCHAR                   QueIdx;
 358        NDIS_STATUS             Status;
 359        unsigned long   IrqFlags;
 360        //UINT32                        USBDMApktLen = 0, DMAHdrLen, padding;
 361
 362        //
 363        // get Tx Ring Resource & Dma Buffer address
 364        //
 365        QueIdx = pTxBlk->QueIdx;
 366        pHTTXContext  = &pAd->TxContext[QueIdx];
 367
 368        RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 369
 370        if(frameNum == 0)
 371        {
 372                // Check if we have enough space for this bulk-out batch.
 373                Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
 374                if (Status == NDIS_STATUS_SUCCESS)
 375                {
 376                        pHTTXContext->bCurWriting = TRUE;
 377
 378                        pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
 379                        pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
 380
 381
 382                        // Reserve space for 8 bytes padding.
 383                        if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
 384                        {
 385
 386                                pHTTXContext->CurWritePosition += 8;
 387                                pHTTXContext->ENextBulkOutPosition += 8;
 388                        }
 389                        fillOffset = pHTTXContext->CurWritePosition;
 390                        pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
 391
 392                        pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
 393
 394                        //
 395                        // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
 396                        //
 397                        if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
 398                                //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
 399                                hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
 400                        else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
 401                                //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
 402                                hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
 403                        else
 404                                //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
 405                                hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
 406
 407                        // Update the pTxBlk->Priv.
 408                        pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
 409
 410                        //      pTxInfo->USBDMApktLen now just a temp value and will to correct latter.
 411                        RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/,  FALSE);
 412
 413                        // Copy it.
 414                        NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv);
 415                        pHTTXContext->CurWriteRealPos += pTxBlk->Priv;
 416                        pWirelessPacket += pTxBlk->Priv;
 417                }
 418        }
 419        else
 420        {       // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.
 421
 422                Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
 423                if (Status == NDIS_STATUS_SUCCESS)
 424                {
 425                        fillOffset =  (pHTTXContext->CurWritePosition + pTxBlk->Priv);
 426                        pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
 427
 428                        //hwHdrLen = pTxBlk->MpduHeaderLen;
 429                        NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen);
 430                        pWirelessPacket += (pTxBlk->MpduHeaderLen);
 431                        pTxBlk->Priv += pTxBlk->MpduHeaderLen;
 432                }
 433                else
 434                {       // It should not happened now unless we are going to shutdown.
 435                        DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n"));
 436                        Status = NDIS_STATUS_FAILURE;
 437                }
 438        }
 439
 440
 441        // We unlock it here to prevent the first 8 bytes maybe over-write issue.
 442        //      1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext.
 443        //      2. An interrupt break our routine and handle bulk-out complete.
 444        //      3. In the bulk-out compllete, it need to do another bulk-out,
 445        //                      if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
 446        //                      but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
 447        //      4. Interrupt complete.
 448        //  5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
 449        //      6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
 450        //              and the packet will wrong.
 451        RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 452
 453        if (Status != NDIS_STATUS_SUCCESS)
 454        {
 455                DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
 456                goto done;
 457        }
 458
 459        // Copy the frame content into DMA buffer and update the pTxBlk->Priv
 460        NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
 461        pWirelessPacket += pTxBlk->SrcBufLen;
 462        pTxBlk->Priv += pTxBlk->SrcBufLen;
 463
 464done:
 465        // Release the skb buffer here
 466        RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
 467
 468        return(Status);
 469
 470}
 471
 472
 473VOID RtmpUSB_FinalWriteTxResource(
 474        IN      PRTMP_ADAPTER   pAd,
 475        IN      TX_BLK                  *pTxBlk,
 476        IN      USHORT                  totalMPDUSize,
 477        IN      USHORT                  TxIdx)
 478{
 479        UCHAR                   QueIdx;
 480        HT_TX_CONTEXT   *pHTTXContext;
 481        UINT32                  fillOffset;
 482        TXINFO_STRUC    *pTxInfo;
 483        TXWI_STRUC              *pTxWI;
 484        UINT32                  USBDMApktLen, padding;
 485        unsigned long   IrqFlags;
 486        PUCHAR                  pWirelessPacket;
 487
 488        QueIdx = pTxBlk->QueIdx;
 489        pHTTXContext  = &pAd->TxContext[QueIdx];
 490
 491        RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 492
 493        if (pHTTXContext->bCurWriting == TRUE)
 494        {
 495                fillOffset = pHTTXContext->CurWritePosition;
 496                if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition))
 497                        && (pHTTXContext->bCopySavePad == TRUE))
 498                        pWirelessPacket = (PUCHAR)(&pHTTXContext->SavedPad[0]);
 499                else
 500                        pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]);
 501
 502                //
 503                // Update TxInfo->USBDMApktLen ,
 504                //              the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding
 505                //
 506                pTxInfo = (PTXINFO_STRUC)(pWirelessPacket);
 507
 508                // Calculate the bulk-out padding
 509                USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE;
 510                padding = (4 - (USBDMApktLen % 4)) & 0x03;      // round up to 4 byte alignment
 511                USBDMApktLen += padding;
 512
 513                pTxInfo->USBDMATxPktLen = USBDMApktLen;
 514
 515                //
 516                // Update TXWI->MPDUtotalByteCount ,
 517                //              the length = 802.11 header + payload_of_all_batch_frames
 518                pTxWI= (PTXWI_STRUC)(pWirelessPacket + TXINFO_SIZE);
 519                pTxWI->MPDUtotalByteCount = totalMPDUSize;
 520
 521                //
 522                // Update the pHTTXContext->CurWritePosition
 523                //
 524                pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen);
 525                if ((pHTTXContext->CurWritePosition + 3906)> MAX_TXBULK_LIMIT)
 526                {       // Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame.
 527                        pHTTXContext->CurWritePosition = 8;
 528                        pTxInfo->SwUseLastRound = 1;
 529                }
 530                pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
 531
 532
 533                //
 534                //      Zero the last padding.
 535                //
 536                pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]);
 537                NdisZeroMemory(pWirelessPacket, padding + 8);
 538
 539                // Finally, set bCurWriting as FALSE
 540                pHTTXContext->bCurWriting = FALSE;
 541
 542        }
 543        else
 544        {       // It should not happened now unless we are going to shutdown.
 545                DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n"));
 546        }
 547
 548        RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
 549
 550}
 551
 552
 553VOID RtmpUSBDataLastTxIdx(
 554        IN      PRTMP_ADAPTER   pAd,
 555        IN      UCHAR                   QueIdx,
 556        IN      USHORT                  TxIdx)
 557{
 558        // DO nothing for USB.
 559}
 560
 561
 562/*
 563        When can do bulk-out:
 564                1. TxSwFreeIdx < TX_RING_SIZE;
 565                        It means has at least one Ring entity is ready for bulk-out, kick it out.
 566                2. If TxSwFreeIdx == TX_RING_SIZE
 567                        Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out.
 568
 569*/
 570VOID RtmpUSBDataKickOut(
 571        IN      PRTMP_ADAPTER   pAd,
 572        IN      TX_BLK                  *pTxBlk,
 573        IN      UCHAR                   QueIdx)
 574{
 575        RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
 576        RTUSBKickBulkOut(pAd);
 577
 578}
 579
 580
 581/*
 582        Must be run in Interrupt context
 583        This function handle RT2870 specific TxDesc and cpu index update and kick the packet out.
 584 */
 585int RtmpUSBMgmtKickOut(
 586        IN RTMP_ADAPTER         *pAd,
 587        IN UCHAR                        QueIdx,
 588        IN PNDIS_PACKET         pPacket,
 589        IN PUCHAR                       pSrcBufVA,
 590        IN UINT                         SrcBufLen)
 591{
 592        PTXINFO_STRUC   pTxInfo;
 593        ULONG                   BulkOutSize;
 594        UCHAR                   padLen;
 595        PUCHAR                  pDest;
 596        ULONG                   SwIdx = pAd->MgmtRing.TxCpuIdx;
 597        PTX_CONTEXT             pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa;
 598        unsigned long   IrqFlags;
 599
 600
 601        pTxInfo = (PTXINFO_STRUC)(pSrcBufVA);
 602
 603        // Build our URB for USBD
 604        BulkOutSize = SrcBufLen;
 605        BulkOutSize = (BulkOutSize + 3) & (~3);
 606        RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE,  FALSE);
 607
 608        BulkOutSize += 4; // Always add 4 extra bytes at every packet.
 609
 610        // If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again.
 611        if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0)
 612                BulkOutSize += 4;
 613
 614        padLen = BulkOutSize - SrcBufLen;
 615        ASSERT((padLen <= RTMP_PKT_TAIL_PADDING));
 616
 617        // Now memzero all extra padding bytes.
 618        pDest = (PUCHAR)(pSrcBufVA + SrcBufLen);
 619        skb_put(GET_OS_PKT_TYPE(pPacket), padLen);
 620        NdisZeroMemory(pDest, padLen);
 621
 622        RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
 623
 624        pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket;
 625        pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket));
 626
 627        // Length in TxInfo should be 8 less than bulkout size.
 628        pMLMEContext->BulkOutSize = BulkOutSize;
 629        pMLMEContext->InUse = TRUE;
 630        pMLMEContext->bWaitingBulkOut = TRUE;
 631
 632
 633        //for debug
 634        //hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize));
 635
 636        //pAd->RalinkCounters.KickTxCount++;
 637        //pAd->RalinkCounters.OneSecTxDoneCount++;
 638
 639        //if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE)
 640        //      needKickOut = TRUE;
 641
 642        // Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX
 643        pAd->MgmtRing.TxSwFreeIdx--;
 644        INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
 645
 646        RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
 647
 648        RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
 649        //if (needKickOut)
 650        RTUSBKickBulkOut(pAd);
 651
 652        return 0;
 653}
 654
 655
 656VOID RtmpUSBNullFrameKickOut(
 657        IN RTMP_ADAPTER *pAd,
 658        IN UCHAR                QueIdx,
 659        IN UCHAR                *pNullFrame,
 660        IN UINT32               frameLen)
 661{
 662        if (pAd->NullContext.InUse == FALSE)
 663        {
 664                PTX_CONTEXT             pNullContext;
 665                PTXINFO_STRUC   pTxInfo;
 666                PTXWI_STRUC             pTxWI;
 667                PUCHAR                  pWirelessPkt;
 668
 669                pNullContext = &(pAd->NullContext);
 670
 671                // Set the in use bit
 672                pNullContext->InUse = TRUE;
 673                pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0];
 674
 675                RTMPZeroMemory(&pWirelessPkt[0], 100);
 676                pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[0];
 677                RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE,  FALSE);
 678                pTxInfo->QSEL = FIFO_EDCA;
 679                pTxWI = (PTXWI_STRUC)&pWirelessPkt[TXINFO_SIZE];
 680                RTMPWriteTxWI(pAd, pTxWI,  FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)),
 681                        0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
 682                RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11));
 683                pAd->NullContext.BulkOutSize =  TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4;
 684
 685                // Fill out frame length information for global Bulk out arbitor
 686                //pNullContext->BulkOutSize = TransferBufferLength;
 687                DBGPRINT(RT_DEBUG_TRACE, ("SYNC - send NULL Frame @%d Mbps...\n", RateIdToMbps[pAd->CommonCfg.TxRate]));
 688                RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL);
 689
 690                // Kick bulk out
 691                RTUSBKickBulkOut(pAd);
 692        }
 693
 694}
 695
 696/*
 697        ========================================================================
 698
 699        Routine Description:
 700                Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
 701
 702        Arguments:
 703                pRxD            Pointer to the Rx descriptor
 704
 705        Return Value:
 706                NDIS_STATUS_SUCCESS             No err
 707                NDIS_STATUS_FAILURE             Error
 708
 709        Note:
 710
 711        ========================================================================
 712*/
 713NDIS_STATUS     RTMPCheckRxError(
 714        IN      PRTMP_ADAPTER   pAd,
 715        IN      PHEADER_802_11  pHeader,
 716        IN      PRXWI_STRUC     pRxWI,
 717        IN      PRT28XX_RXD_STRUC       pRxINFO)
 718{
 719        PCIPHER_KEY pWpaKey;
 720        INT     dBm;
 721
 722        if (pAd->bPromiscuous == TRUE)
 723                return(NDIS_STATUS_SUCCESS);
 724        if(pRxINFO == NULL)
 725                return(NDIS_STATUS_FAILURE);
 726
 727        // Phy errors & CRC errors
 728        if (pRxINFO->Crc)
 729        {
 730                // Check RSSI for Noise Hist statistic collection.
 731                dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
 732                if (dBm <= -87)
 733                        pAd->StaCfg.RPIDensity[0] += 1;
 734                else if (dBm <= -82)
 735                        pAd->StaCfg.RPIDensity[1] += 1;
 736                else if (dBm <= -77)
 737                        pAd->StaCfg.RPIDensity[2] += 1;
 738                else if (dBm <= -72)
 739                        pAd->StaCfg.RPIDensity[3] += 1;
 740                else if (dBm <= -67)
 741                        pAd->StaCfg.RPIDensity[4] += 1;
 742                else if (dBm <= -62)
 743                        pAd->StaCfg.RPIDensity[5] += 1;
 744                else if (dBm <= -57)
 745                        pAd->StaCfg.RPIDensity[6] += 1;
 746                else if (dBm > -57)
 747                        pAd->StaCfg.RPIDensity[7] += 1;
 748
 749                return(NDIS_STATUS_FAILURE);
 750        }
 751
 752        // Add Rx size to channel load counter, we should ignore error counts
 753        pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount+ 14);
 754
 755        // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
 756        if (pHeader->FC.ToDs)
 757        {
 758                DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n"));
 759                return NDIS_STATUS_FAILURE;
 760        }
 761
 762        // Paul 04-03 for OFDM Rx length issue
 763        if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE)
 764        {
 765                DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n"));
 766                return NDIS_STATUS_FAILURE;
 767        }
 768
 769        // Drop not U2M frames, cant's drop here because we will drop beacon in this case
 770        // I am kind of doubting the U2M bit operation
 771        // if (pRxD->U2M == 0)
 772        //      return(NDIS_STATUS_FAILURE);
 773
 774        // drop decyption fail frame
 775        if (pRxINFO->Decrypted && pRxINFO->CipherErr)
 776        {
 777
 778                //
 779                // MIC Error
 780                //
 781                if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss)
 782                {
 783                        pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
 784                        RTMPReportMicError(pAd, pWpaKey);
 785                        DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
 786                }
 787
 788                if (pRxINFO->Decrypted &&
 789                        (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == CIPHER_AES) &&
 790                        (pHeader->Sequence == pAd->FragFrame.Sequence))
 791                {
 792                        //
 793                        // Acceptable since the First FragFrame no CipherErr problem.
 794                        //
 795                        return(NDIS_STATUS_SUCCESS);
 796                }
 797
 798                return(NDIS_STATUS_FAILURE);
 799        }
 800
 801        return(NDIS_STATUS_SUCCESS);
 802}
 803
 804VOID RT28xxUsbStaAsicForceWakeup(
 805        IN PRTMP_ADAPTER pAd,
 806        IN BOOLEAN       bFromTx)
 807{
 808    AUTO_WAKEUP_STRUC   AutoWakeupCfg;
 809
 810        AutoWakeupCfg.word = 0;
 811        RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
 812
 813        AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
 814
 815        OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
 816}
 817
 818VOID RT28xxUsbStaAsicSleepThenAutoWakeup(
 819        IN PRTMP_ADAPTER pAd,
 820        IN USHORT TbttNumToNextWakeUp)
 821{
 822        AUTO_WAKEUP_STRUC       AutoWakeupCfg;
 823
 824        // we have decided to SLEEP, so at least do it for a BEACON period.
 825        if (TbttNumToNextWakeUp == 0)
 826                TbttNumToNextWakeUp = 1;
 827
 828        AutoWakeupCfg.word = 0;
 829        RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
 830
 831        AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
 832        AutoWakeupCfg.field.EnableAutoWakeup = 1;
 833        AutoWakeupCfg.field.AutoLeadTime = 5;
 834        RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
 835
 836        AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);   // send POWER-SAVE command to MCU. Timeout 40us.
 837
 838        OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
 839
 840}
 841
 842VOID RT28xxUsbMlmeRadioOn(
 843        IN PRTMP_ADAPTER pAd)
 844{
 845    DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOn()\n"));
 846
 847        if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
 848                return;
 849
 850        AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
 851                RTMPusecDelay(10000);
 852
 853        NICResetFromError(pAd);
 854
 855        // Enable Tx/Rx
 856        RTMPEnableRxTx(pAd);
 857
 858#ifdef RT3070
 859        if (IS_RT3071(pAd))
 860        {
 861                RT30xxReverseRFSleepModeSetup(pAd);
 862        }
 863#endif // RT3070 //
 864
 865        // Clear Radio off flag
 866        RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
 867
 868        RTUSBBulkReceive(pAd);
 869
 870        // Set LED
 871        RTMPSetLED(pAd, LED_RADIO_ON);
 872}
 873
 874VOID RT28xxUsbMlmeRadioOFF(
 875        IN PRTMP_ADAPTER pAd)
 876{
 877        WPDMA_GLO_CFG_STRUC     GloCfg;
 878        UINT32  Value, i;
 879
 880        DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOFF()\n"));
 881
 882        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
 883                return;
 884
 885        // Set LED
 886        RTMPSetLED(pAd, LED_RADIO_OFF);
 887        // Set Radio off flag
 888        RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
 889
 890        {
 891                // Link down first if any association exists
 892                if (INFRA_ON(pAd) || ADHOC_ON(pAd))
 893                        LinkDown(pAd, FALSE);
 894                RTMPusecDelay(10000);
 895
 896                //==========================================
 897                // Clean up old bss table
 898                BssTableInit(&pAd->ScanTab);
 899        }
 900
 901        if (pAd->CommonCfg.BBPCurrentBW == BW_40)
 902        {
 903                // Must using 40MHz.
 904                AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
 905        }
 906        else
 907        {
 908                // Must using 20MHz.
 909                AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
 910        }
 911
 912        // Disable Tx/Rx DMA
 913        RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word);    // disable DMA
 914        GloCfg.field.EnableTxDMA = 0;
 915        GloCfg.field.EnableRxDMA = 0;
 916        RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word);    // abort all TX rings
 917
 918        // Waiting for DMA idle
 919        i = 0;
 920        do
 921        {
 922                RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
 923                if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
 924                        break;
 925
 926                RTMPusecDelay(1000);
 927        }while (i++ < 100);
 928
 929        // Disable MAC Tx/Rx
 930        RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
 931        Value &= (0xfffffff3);
 932        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
 933
 934        AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
 935}
 936
 937