2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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. *
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. *
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. *
25 *************************************************************************
28 All functions in this file must be USB-depended, or you should out your function
32 #include "../rt_config.h"
36 We can do copy the frame into pTxContext when match following conditions.
41 static inline NDIS_STATUS RtmpUSBCanDoWrite(
44 IN HT_TX_CONTEXT *pHTTXContext)
46 NDIS_STATUS canWrite = NDIS_STATUS_RESOURCES;
48 if (((pHTTXContext->CurWritePosition) < pHTTXContext->NextBulkOutPosition) && (pHTTXContext->CurWritePosition + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)
50 DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c1!\n"));
51 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
53 else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < LOCAL_TXBUF_SIZE))
55 DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c2!\n"));
56 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
58 else if (pHTTXContext->bCurWriting == TRUE)
60 DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c3!\n"));
64 canWrite = NDIS_STATUS_SUCCESS;
72 USHORT RtmpUSB_WriteSubTxResource(
76 OUT USHORT *FreeNumber)
79 // Dummy function. Should be removed in the future.
84 USHORT RtmpUSB_WriteFragTxResource(
88 OUT USHORT *FreeNumber)
90 HT_TX_CONTEXT *pHTTXContext;
91 USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length.
93 TXINFO_STRUC *pTxInfo;
95 PUCHAR pWirelessPacket = NULL;
98 unsigned long IrqFlags;
99 UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
100 BOOLEAN TxQLastRound = FALSE;
103 // get Tx Ring Resource & Dma Buffer address
105 QueIdx = pTxBlk->QueIdx;
106 pHTTXContext = &pAd->TxContext[QueIdx];
108 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
110 pHTTXContext = &pAd->TxContext[QueIdx];
111 fillOffset = pHTTXContext->CurWritePosition;
115 // Check if we have enough space for this bulk-out batch.
116 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
117 if (Status == NDIS_STATUS_SUCCESS)
119 pHTTXContext->bCurWriting = TRUE;
121 // Reserve space for 8 bytes padding.
122 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
124 pHTTXContext->ENextBulkOutPosition += 8;
125 pHTTXContext->CurWritePosition += 8;
129 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
133 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
135 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
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)
145 fillOffset += pTxBlk->Priv;
149 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
151 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
156 NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE);
157 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
158 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
160 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
162 // copy TXWI + WLAN Header + LLC into DMA Header Buffer
163 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
164 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
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;
172 pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen);
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);
177 if (fragNum == pTxBlk->TotalFragNum)
179 pTxInfo->USBDMATxburst = 0;
180 if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT)
182 pTxInfo->SwUseLastRound = 1;
188 pTxInfo->USBDMATxburst = 1;
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);
195 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
197 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
199 // Zero the last padding.
200 pWirelessPacket += pTxBlk->SrcBufLen;
201 NdisZeroMemory(pWirelessPacket, padding + 8);
203 if (fragNum == pTxBlk->TotalFragNum)
205 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
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;
214 // Finally, set bCurWriting as FALSE
215 pHTTXContext->bCurWriting = FALSE;
217 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
219 // succeed and release the skb buffer
220 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
229 USHORT RtmpUSB_WriteSingleTxResource(
230 IN PRTMP_ADAPTER pAd,
233 OUT USHORT *FreeNumber)
235 HT_TX_CONTEXT *pHTTXContext;
238 TXINFO_STRUC *pTxInfo;
240 PUCHAR pWirelessPacket;
242 unsigned long IrqFlags;
244 UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
245 BOOLEAN bTxQLastRound = FALSE;
247 // For USB, didn't need PCI_MAP_SINGLE()
248 //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE);
252 // get Tx Ring Resource & Dma Buffer address
254 QueIdx = pTxBlk->QueIdx;
256 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
257 pHTTXContext = &pAd->TxContext[QueIdx];
258 fillOffset = pHTTXContext->CurWritePosition;
263 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
264 if(Status == NDIS_STATUS_SUCCESS)
266 pHTTXContext->bCurWriting = TRUE;
268 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
269 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
271 // Reserve space for 8 bytes padding.
272 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
274 pHTTXContext->ENextBulkOutPosition += 8;
275 pHTTXContext->CurWritePosition += 8;
278 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
280 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
282 // copy TXWI + WLAN Header + LLC into DMA Header Buffer
283 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
284 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
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;
292 pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen);
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);
298 if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT)
300 pTxInfo->SwUseLastRound = 1;
301 bTxQLastRound = TRUE;
303 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
304 pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
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);
319 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
320 pWirelessPacket += pTxBlk->SrcBufLen;
321 NdisZeroMemory(pWirelessPacket, padding + 8);
323 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
325 pHTTXContext->CurWritePosition += pTxBlk->Priv;
327 pHTTXContext->CurWritePosition = 8;
328 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
330 pHTTXContext->bCurWriting = FALSE;
334 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
337 // succeed and release the skb buffer
338 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
345 USHORT RtmpUSB_WriteMultiTxResource(
346 IN PRTMP_ADAPTER pAd,
349 OUT USHORT *FreeNumber)
351 HT_TX_CONTEXT *pHTTXContext;
352 USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length.
354 TXINFO_STRUC *pTxInfo;
356 PUCHAR pWirelessPacket = NULL;
359 unsigned long IrqFlags;
360 //UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
363 // get Tx Ring Resource & Dma Buffer address
365 QueIdx = pTxBlk->QueIdx;
366 pHTTXContext = &pAd->TxContext[QueIdx];
368 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
372 // Check if we have enough space for this bulk-out batch.
373 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
374 if (Status == NDIS_STATUS_SUCCESS)
376 pHTTXContext->bCurWriting = TRUE;
378 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
379 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
382 // Reserve space for 8 bytes padding.
383 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
386 pHTTXContext->CurWritePosition += 8;
387 pHTTXContext->ENextBulkOutPosition += 8;
389 fillOffset = pHTTXContext->CurWritePosition;
390 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
392 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
395 // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
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;
404 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
405 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
407 // Update the pTxBlk->Priv.
408 pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
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);
414 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv);
415 pHTTXContext->CurWriteRealPos += pTxBlk->Priv;
416 pWirelessPacket += pTxBlk->Priv;
420 { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.
422 Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
423 if (Status == NDIS_STATUS_SUCCESS)
425 fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv);
426 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
428 //hwHdrLen = pTxBlk->MpduHeaderLen;
429 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen);
430 pWirelessPacket += (pTxBlk->MpduHeaderLen);
431 pTxBlk->Priv += pTxBlk->MpduHeaderLen;
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;
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);
453 if (Status != NDIS_STATUS_SUCCESS)
455 DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
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;
465 // Release the skb buffer here
466 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
473 VOID RtmpUSB_FinalWriteTxResource(
474 IN PRTMP_ADAPTER pAd,
476 IN USHORT totalMPDUSize,
480 HT_TX_CONTEXT *pHTTXContext;
482 TXINFO_STRUC *pTxInfo;
484 UINT32 USBDMApktLen, padding;
485 unsigned long IrqFlags;
486 PUCHAR pWirelessPacket;
488 QueIdx = pTxBlk->QueIdx;
489 pHTTXContext = &pAd->TxContext[QueIdx];
491 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
493 if (pHTTXContext->bCurWriting == TRUE)
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]);
500 pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]);
503 // Update TxInfo->USBDMApktLen ,
504 // the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding
506 pTxInfo = (PTXINFO_STRUC)(pWirelessPacket);
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;
513 pTxInfo->USBDMATxPktLen = USBDMApktLen;
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;
522 // Update the pHTTXContext->CurWritePosition
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;
530 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
534 // Zero the last padding.
536 pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]);
537 NdisZeroMemory(pWirelessPacket, padding + 8);
539 // Finally, set bCurWriting as FALSE
540 pHTTXContext->bCurWriting = FALSE;
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"));
548 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
553 VOID RtmpUSBDataLastTxIdx(
554 IN PRTMP_ADAPTER pAd,
558 // DO nothing for USB.
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.
570 VOID RtmpUSBDataKickOut(
571 IN PRTMP_ADAPTER pAd,
575 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
576 RTUSBKickBulkOut(pAd);
582 Must be run in Interrupt context
583 This function handle RT2870 specific TxDesc and cpu index update and kick the packet out.
585 int RtmpUSBMgmtKickOut(
586 IN RTMP_ADAPTER *pAd,
588 IN PNDIS_PACKET pPacket,
592 PTXINFO_STRUC pTxInfo;
596 ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
597 PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa;
598 unsigned long IrqFlags;
601 pTxInfo = (PTXINFO_STRUC)(pSrcBufVA);
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);
608 BulkOutSize += 4; // Always add 4 extra bytes at every packet.
610 // If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again.
611 if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0)
614 padLen = BulkOutSize - SrcBufLen;
615 ASSERT((padLen <= RTMP_PKT_TAIL_PADDING));
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);
622 RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
624 pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket;
625 pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket));
627 // Length in TxInfo should be 8 less than bulkout size.
628 pMLMEContext->BulkOutSize = BulkOutSize;
629 pMLMEContext->InUse = TRUE;
630 pMLMEContext->bWaitingBulkOut = TRUE;
634 //hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize));
636 //pAd->RalinkCounters.KickTxCount++;
637 //pAd->RalinkCounters.OneSecTxDoneCount++;
639 //if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE)
640 // needKickOut = TRUE;
642 // Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX
643 pAd->MgmtRing.TxSwFreeIdx--;
644 INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
646 RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
648 RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
650 RTUSBKickBulkOut(pAd);
656 VOID RtmpUSBNullFrameKickOut(
657 IN RTMP_ADAPTER *pAd,
659 IN UCHAR *pNullFrame,
662 if (pAd->NullContext.InUse == FALSE)
664 PTX_CONTEXT pNullContext;
665 PTXINFO_STRUC pTxInfo;
669 pNullContext = &(pAd->NullContext);
671 // Set the in use bit
672 pNullContext->InUse = TRUE;
673 pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0];
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;
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);
691 RTUSBKickBulkOut(pAd);
697 ========================================================================
700 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
703 pRxD Pointer to the Rx descriptor
706 NDIS_STATUS_SUCCESS No err
707 NDIS_STATUS_FAILURE Error
711 ========================================================================
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)
722 if (pAd->bPromiscuous == TRUE)
723 return(NDIS_STATUS_SUCCESS);
725 return(NDIS_STATUS_FAILURE);
727 // Phy errors & CRC errors
730 // Check RSSI for Noise Hist statistic collection.
731 dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
733 pAd->StaCfg.RPIDensity[0] += 1;
735 pAd->StaCfg.RPIDensity[1] += 1;
737 pAd->StaCfg.RPIDensity[2] += 1;
739 pAd->StaCfg.RPIDensity[3] += 1;
741 pAd->StaCfg.RPIDensity[4] += 1;
743 pAd->StaCfg.RPIDensity[5] += 1;
745 pAd->StaCfg.RPIDensity[6] += 1;
747 pAd->StaCfg.RPIDensity[7] += 1;
749 return(NDIS_STATUS_FAILURE);
752 // Add Rx size to channel load counter, we should ignore error counts
753 pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount+ 14);
755 // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
756 if (pHeader->FC.ToDs)
758 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n"));
759 return NDIS_STATUS_FAILURE;
762 // Paul 04-03 for OFDM Rx length issue
763 if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE)
765 DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n"));
766 return NDIS_STATUS_FAILURE;
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);
774 // drop decyption fail frame
775 if (pRxINFO->Decrypted && pRxINFO->CipherErr)
781 if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss)
783 pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
784 RTMPReportMicError(pAd, pWpaKey);
785 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
788 if (pRxINFO->Decrypted &&
789 (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == CIPHER_AES) &&
790 (pHeader->Sequence == pAd->FragFrame.Sequence))
793 // Acceptable since the First FragFrame no CipherErr problem.
795 return(NDIS_STATUS_SUCCESS);
798 return(NDIS_STATUS_FAILURE);
801 return(NDIS_STATUS_SUCCESS);
804 VOID RT28xxUsbStaAsicForceWakeup(
805 IN PRTMP_ADAPTER pAd,
808 AUTO_WAKEUP_STRUC AutoWakeupCfg;
810 AutoWakeupCfg.word = 0;
811 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
813 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
815 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
818 VOID RT28xxUsbStaAsicSleepThenAutoWakeup(
819 IN PRTMP_ADAPTER pAd,
820 IN USHORT TbttNumToNextWakeUp)
822 AUTO_WAKEUP_STRUC AutoWakeupCfg;
824 // we have decided to SLEEP, so at least do it for a BEACON period.
825 if (TbttNumToNextWakeUp == 0)
826 TbttNumToNextWakeUp = 1;
828 AutoWakeupCfg.word = 0;
829 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
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);
836 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); // send POWER-SAVE command to MCU. Timeout 40us.
838 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
842 VOID RT28xxUsbMlmeRadioOn(
843 IN PRTMP_ADAPTER pAd)
845 DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOn()\n"));
847 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
850 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
851 RTMPusecDelay(10000);
853 NICResetFromError(pAd);
861 RT30xxReverseRFSleepModeSetup(pAd);
865 // Clear Radio off flag
866 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
868 RTUSBBulkReceive(pAd);
871 RTMPSetLED(pAd, LED_RADIO_ON);
874 VOID RT28xxUsbMlmeRadioOFF(
875 IN PRTMP_ADAPTER pAd)
877 WPDMA_GLO_CFG_STRUC GloCfg;
880 DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOFF()\n"));
882 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
886 RTMPSetLED(pAd, LED_RADIO_OFF);
887 // Set Radio off flag
888 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
891 // Link down first if any association exists
892 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
893 LinkDown(pAd, FALSE);
894 RTMPusecDelay(10000);
896 //==========================================
897 // Clean up old bss table
898 BssTableInit(&pAd->ScanTab);
901 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
904 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
909 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
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
918 // Waiting for DMA idle
922 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
923 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
930 RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
931 Value &= (0xfffffff3);
932 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
934 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);