Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 #ifndef RT30xx
814         AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
815 #endif
816 #ifdef RT30xx
817         AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
818 #endif
819 
820         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
821 }
822 
823 VOID RT28xxUsbStaAsicSleepThenAutoWakeup(
824         IN PRTMP_ADAPTER pAd,
825         IN USHORT TbttNumToNextWakeUp)
826 {
827         AUTO_WAKEUP_STRUC       AutoWakeupCfg;
828 
829         // we have decided to SLEEP, so at least do it for a BEACON period.
830         if (TbttNumToNextWakeUp == 0)
831                 TbttNumToNextWakeUp = 1;
832 
833         AutoWakeupCfg.word = 0;
834         RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
835 
836         AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
837         AutoWakeupCfg.field.EnableAutoWakeup = 1;
838         AutoWakeupCfg.field.AutoLeadTime = 5;
839         RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
840 
841         AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);   // send POWER-SAVE command to MCU. Timeout 40us.
842 
843         OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
844 
845 }
846 
847 VOID RT28xxUsbMlmeRadioOn(
848         IN PRTMP_ADAPTER pAd)
849 {
850     DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOn()\n"));
851 
852         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
853                 return;
854 
855 #ifndef RT30xx
856         AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
857 #endif
858 #ifdef RT30xx
859         AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
860 #endif
861                 RTMPusecDelay(10000);
862 
863         NICResetFromError(pAd);
864 
865         // Enable Tx/Rx
866         RTMPEnableRxTx(pAd);
867 
868 #ifdef RT3070
869         if (IS_RT3071(pAd))
870         {
871                 RT30xxReverseRFSleepModeSetup(pAd);
872         }
873 #endif // RT3070 //
874 
875         // Clear Radio off flag
876         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
877 
878         RTUSBBulkReceive(pAd);
879 
880         // Set LED
881         RTMPSetLED(pAd, LED_RADIO_ON);
882 }
883 
884 VOID RT28xxUsbMlmeRadioOFF(
885         IN PRTMP_ADAPTER pAd)
886 {
887         WPDMA_GLO_CFG_STRUC     GloCfg;
888         UINT32  Value, i;
889 
890         DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOFF()\n"));
891 
892         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
893                 return;
894 
895         // Set LED
896         RTMPSetLED(pAd, LED_RADIO_OFF);
897         // Set Radio off flag
898         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
899 
900         {
901                 // Link down first if any association exists
902                 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
903                         LinkDown(pAd, FALSE);
904                 RTMPusecDelay(10000);
905 
906                 //==========================================
907                 // Clean up old bss table
908                 BssTableInit(&pAd->ScanTab);
909         }
910 
911 #ifndef RT30xx
912         // Disable MAC Tx/Rx
913         RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
914         Value &= (0xfffffff3);
915         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
916 
917         // MAC_SYS_CTRL => value = 0x0 => 40mA
918         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
919 
920         // PWR_PIN_CFG => value = 0x0 => 40mA
921         RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
922 
923         // TX_PIN_CFG => value = 0x0 => 20mA
924         RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
925 #endif
926 
927         if (pAd->CommonCfg.BBPCurrentBW == BW_40)
928         {
929                 // Must using 40MHz.
930                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
931         }
932         else
933         {
934                 // Must using 20MHz.
935                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
936         }
937 
938 #ifdef RT30xx
939         // Disable Tx/Rx DMA
940         RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word);    // disable DMA
941         GloCfg.field.EnableTxDMA = 0;
942         GloCfg.field.EnableRxDMA = 0;
943         RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word);    // abort all TX rings
944 #endif
945 
946         // Waiting for DMA idle
947         i = 0;
948         do
949         {
950                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
951                 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
952                         break;
953 
954                 RTMPusecDelay(1000);
955         }while (i++ < 100);
956 
957 #ifdef RT30xx
958         // Disable MAC Tx/Rx
959         RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
960         Value &= (0xfffffff3);
961         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
962 #endif
963 
964         AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
965 }
966 
967 
  This page was automatically generated by the LXR engine.