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