Staging: rt3070: remove dead code
[linux-2.6] / drivers / staging / rt3070 / common / cmm_data_2870.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    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 */
41 static 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
72 USHORT 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
84 USHORT  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
229 USHORT 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
345 USHORT 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
464 done:
465         // Release the skb buffer here
466         RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
467
468         return(Status);
469
470 }
471
472
473 VOID 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
553 VOID 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 */
570 VOID 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  */
585 int 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
656 VOID 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 */
713 NDIS_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
804 VOID 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
818 VOID 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
842 VOID 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
874 VOID 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