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