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 *************************************************************************
29 All functions in this file must be USB-depended, or you should out your function
37 #include "../rt_config.h"
41 We can do copy the frame into pTxContext when match following conditions.
46 static inline NDIS_STATUS RtmpUSBCanDoWrite(
49 IN HT_TX_CONTEXT *pHTTXContext)
51 NDIS_STATUS canWrite = NDIS_STATUS_RESOURCES;
53 if (((pHTTXContext->CurWritePosition) < pHTTXContext->NextBulkOutPosition) && (pHTTXContext->CurWritePosition + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)
55 DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c1!\n"));
56 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
58 else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < LOCAL_TXBUF_SIZE))
60 DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c2!\n"));
61 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
63 else if (pHTTXContext->bCurWriting == TRUE)
65 DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c3!\n"));
69 canWrite = NDIS_STATUS_SUCCESS;
77 USHORT RtmpUSB_WriteSubTxResource(
81 OUT USHORT *FreeNumber)
84 // Dummy function. Should be removed in the future.
89 USHORT RtmpUSB_WriteFragTxResource(
93 OUT USHORT *FreeNumber)
95 HT_TX_CONTEXT *pHTTXContext;
96 USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length.
98 TXINFO_STRUC *pTxInfo;
100 PUCHAR pWirelessPacket = NULL;
103 unsigned long IrqFlags;
104 UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
105 BOOLEAN TxQLastRound = FALSE;
108 // get Tx Ring Resource & Dma Buffer address
110 QueIdx = pTxBlk->QueIdx;
111 pHTTXContext = &pAd->TxContext[QueIdx];
113 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
115 pHTTXContext = &pAd->TxContext[QueIdx];
116 fillOffset = pHTTXContext->CurWritePosition;
120 // Check if we have enough space for this bulk-out batch.
121 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
122 if (Status == NDIS_STATUS_SUCCESS)
124 pHTTXContext->bCurWriting = TRUE;
126 // Reserve space for 8 bytes padding.
127 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
129 pHTTXContext->ENextBulkOutPosition += 8;
130 pHTTXContext->CurWritePosition += 8;
134 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
138 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
140 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
146 // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.
147 Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
148 if (Status == NDIS_STATUS_SUCCESS)
150 fillOffset += pTxBlk->Priv;
154 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
156 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
161 NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE);
162 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
163 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
165 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
167 // copy TXWI + WLAN Header + LLC into DMA Header Buffer
168 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
169 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
171 // Build our URB for USBD
172 DMAHdrLen = TXWI_SIZE + hwHdrLen;
173 USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen;
174 padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment
175 USBDMApktLen += padding;
177 pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen);
179 // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload
180 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE);
182 if (fragNum == pTxBlk->TotalFragNum)
184 pTxInfo->USBDMATxburst = 0;
185 if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT)
187 pTxInfo->SwUseLastRound = 1;
193 pTxInfo->USBDMATxburst = 1;
196 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
197 pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
198 pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
200 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
202 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
204 // Zero the last padding.
205 pWirelessPacket += pTxBlk->SrcBufLen;
206 NdisZeroMemory(pWirelessPacket, padding + 8);
208 if (fragNum == pTxBlk->TotalFragNum)
210 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
212 // Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame.
213 pHTTXContext->CurWritePosition += pTxBlk->Priv;
214 if (TxQLastRound == TRUE)
215 pHTTXContext->CurWritePosition = 8;
216 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
219 // Finally, set bCurWriting as FALSE
220 pHTTXContext->bCurWriting = FALSE;
222 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
224 // succeed and release the skb buffer
225 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
234 USHORT RtmpUSB_WriteSingleTxResource(
235 IN PRTMP_ADAPTER pAd,
238 OUT USHORT *FreeNumber)
240 HT_TX_CONTEXT *pHTTXContext;
243 TXINFO_STRUC *pTxInfo;
245 PUCHAR pWirelessPacket;
247 unsigned long IrqFlags;
249 UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
250 BOOLEAN bTxQLastRound = FALSE;
252 // For USB, didn't need PCI_MAP_SINGLE()
253 //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE);
257 // get Tx Ring Resource & Dma Buffer address
259 QueIdx = pTxBlk->QueIdx;
261 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
262 pHTTXContext = &pAd->TxContext[QueIdx];
263 fillOffset = pHTTXContext->CurWritePosition;
268 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
269 if(Status == NDIS_STATUS_SUCCESS)
271 pHTTXContext->bCurWriting = TRUE;
273 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
274 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
276 // Reserve space for 8 bytes padding.
277 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
279 pHTTXContext->ENextBulkOutPosition += 8;
280 pHTTXContext->CurWritePosition += 8;
283 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
285 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
287 // copy TXWI + WLAN Header + LLC into DMA Header Buffer
288 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
289 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
291 // Build our URB for USBD
292 DMAHdrLen = TXWI_SIZE + hwHdrLen;
293 USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen;
294 padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment
295 USBDMApktLen += padding;
297 pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen);
299 // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload
300 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE);
302 if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT)
304 pTxInfo->SwUseLastRound = 1;
305 bTxQLastRound = TRUE;
307 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
308 pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
310 // We unlock it here to prevent the first 8 bytes maybe over-writed issue.
311 // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext.
312 // 2. An interrupt break our routine and handle bulk-out complete.
313 // 3. In the bulk-out compllete, it need to do another bulk-out,
314 // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
315 // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
316 // 4. Interrupt complete.
317 // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
318 // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
319 // and the packet will wrong.
320 pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
321 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
323 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
324 pWirelessPacket += pTxBlk->SrcBufLen;
325 NdisZeroMemory(pWirelessPacket, padding + 8);
327 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
329 pHTTXContext->CurWritePosition += pTxBlk->Priv;
331 pHTTXContext->CurWritePosition = 8;
332 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
334 pHTTXContext->bCurWriting = FALSE;
338 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
341 // succeed and release the skb buffer
342 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
349 USHORT RtmpUSB_WriteMultiTxResource(
350 IN PRTMP_ADAPTER pAd,
353 OUT USHORT *FreeNumber)
355 HT_TX_CONTEXT *pHTTXContext;
356 USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length.
358 TXINFO_STRUC *pTxInfo;
360 PUCHAR pWirelessPacket = NULL;
363 unsigned long IrqFlags;
364 //UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
367 // get Tx Ring Resource & Dma Buffer address
369 QueIdx = pTxBlk->QueIdx;
370 pHTTXContext = &pAd->TxContext[QueIdx];
372 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
376 // Check if we have enough space for this bulk-out batch.
377 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
378 if (Status == NDIS_STATUS_SUCCESS)
380 pHTTXContext->bCurWriting = TRUE;
382 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
383 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
386 // Reserve space for 8 bytes padding.
387 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
390 pHTTXContext->CurWritePosition += 8;
391 pHTTXContext->ENextBulkOutPosition += 8;
393 fillOffset = pHTTXContext->CurWritePosition;
394 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
396 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
399 // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
401 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
402 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
403 hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
404 else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
405 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
406 hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
408 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
409 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
411 // Update the pTxBlk->Priv.
412 pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
414 // pTxInfo->USBDMApktLen now just a temp value and will to correct latter.
415 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE);
418 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv);
419 pHTTXContext->CurWriteRealPos += pTxBlk->Priv;
420 pWirelessPacket += pTxBlk->Priv;
424 { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.
426 Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
427 if (Status == NDIS_STATUS_SUCCESS)
429 fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv);
430 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
432 //hwHdrLen = pTxBlk->MpduHeaderLen;
433 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen);
434 pWirelessPacket += (pTxBlk->MpduHeaderLen);
435 pTxBlk->Priv += pTxBlk->MpduHeaderLen;
438 { // It should not happened now unless we are going to shutdown.
439 DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n"));
440 Status = NDIS_STATUS_FAILURE;
445 // We unlock it here to prevent the first 8 bytes maybe over-write issue.
446 // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext.
447 // 2. An interrupt break our routine and handle bulk-out complete.
448 // 3. In the bulk-out compllete, it need to do another bulk-out,
449 // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
450 // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
451 // 4. Interrupt complete.
452 // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
453 // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
454 // and the packet will wrong.
455 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
457 if (Status != NDIS_STATUS_SUCCESS)
459 DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
463 // Copy the frame content into DMA buffer and update the pTxBlk->Priv
464 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
465 pWirelessPacket += pTxBlk->SrcBufLen;
466 pTxBlk->Priv += pTxBlk->SrcBufLen;
469 // Release the skb buffer here
470 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
477 VOID RtmpUSB_FinalWriteTxResource(
478 IN PRTMP_ADAPTER pAd,
480 IN USHORT totalMPDUSize,
484 HT_TX_CONTEXT *pHTTXContext;
486 TXINFO_STRUC *pTxInfo;
488 UINT32 USBDMApktLen, padding;
489 unsigned long IrqFlags;
490 PUCHAR pWirelessPacket;
492 QueIdx = pTxBlk->QueIdx;
493 pHTTXContext = &pAd->TxContext[QueIdx];
495 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
497 if (pHTTXContext->bCurWriting == TRUE)
499 fillOffset = pHTTXContext->CurWritePosition;
500 if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition))
501 && (pHTTXContext->bCopySavePad == TRUE))
502 pWirelessPacket = (PUCHAR)(&pHTTXContext->SavedPad[0]);
504 pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]);
507 // Update TxInfo->USBDMApktLen ,
508 // the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding
510 pTxInfo = (PTXINFO_STRUC)(pWirelessPacket);
512 // Calculate the bulk-out padding
513 USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE;
514 padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment
515 USBDMApktLen += padding;
517 pTxInfo->USBDMATxPktLen = USBDMApktLen;
520 // Update TXWI->MPDUtotalByteCount ,
521 // the length = 802.11 header + payload_of_all_batch_frames
522 pTxWI= (PTXWI_STRUC)(pWirelessPacket + TXINFO_SIZE);
523 pTxWI->MPDUtotalByteCount = totalMPDUSize;
526 // Update the pHTTXContext->CurWritePosition
528 pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen);
529 if ((pHTTXContext->CurWritePosition + 3906)> MAX_TXBULK_LIMIT)
530 { // Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame.
531 pHTTXContext->CurWritePosition = 8;
532 pTxInfo->SwUseLastRound = 1;
534 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
538 // Zero the last padding.
540 pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]);
541 NdisZeroMemory(pWirelessPacket, padding + 8);
543 // Finally, set bCurWriting as FALSE
544 pHTTXContext->bCurWriting = FALSE;
548 { // It should not happened now unless we are going to shutdown.
549 DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n"));
552 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
557 VOID RtmpUSBDataLastTxIdx(
558 IN PRTMP_ADAPTER pAd,
562 // DO nothing for USB.
567 When can do bulk-out:
568 1. TxSwFreeIdx < TX_RING_SIZE;
569 It means has at least one Ring entity is ready for bulk-out, kick it out.
570 2. If TxSwFreeIdx == TX_RING_SIZE
571 Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out.
574 VOID RtmpUSBDataKickOut(
575 IN PRTMP_ADAPTER pAd,
579 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
580 RTUSBKickBulkOut(pAd);
586 Must be run in Interrupt context
587 This function handle RT2870 specific TxDesc and cpu index update and kick the packet out.
589 int RtmpUSBMgmtKickOut(
590 IN RTMP_ADAPTER *pAd,
592 IN PNDIS_PACKET pPacket,
596 PTXINFO_STRUC pTxInfo;
600 ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
601 PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa;
602 unsigned long IrqFlags;
605 pTxInfo = (PTXINFO_STRUC)(pSrcBufVA);
607 // Build our URB for USBD
608 BulkOutSize = SrcBufLen;
609 BulkOutSize = (BulkOutSize + 3) & (~3);
610 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
612 BulkOutSize += 4; // Always add 4 extra bytes at every packet.
614 // If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again.
615 if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0)
618 padLen = BulkOutSize - SrcBufLen;
619 ASSERT((padLen <= RTMP_PKT_TAIL_PADDING));
621 // Now memzero all extra padding bytes.
622 pDest = (PUCHAR)(pSrcBufVA + SrcBufLen);
623 skb_put(GET_OS_PKT_TYPE(pPacket), padLen);
624 NdisZeroMemory(pDest, padLen);
626 RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
628 pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket;
629 pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket));
631 // Length in TxInfo should be 8 less than bulkout size.
632 pMLMEContext->BulkOutSize = BulkOutSize;
633 pMLMEContext->InUse = TRUE;
634 pMLMEContext->bWaitingBulkOut = TRUE;
638 //hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize));
640 //pAd->RalinkCounters.KickTxCount++;
641 //pAd->RalinkCounters.OneSecTxDoneCount++;
643 //if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE)
644 // needKickOut = TRUE;
646 // Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX
647 pAd->MgmtRing.TxSwFreeIdx--;
648 INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
650 RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
652 RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
654 RTUSBKickBulkOut(pAd);
660 VOID RtmpUSBNullFrameKickOut(
661 IN RTMP_ADAPTER *pAd,
663 IN UCHAR *pNullFrame,
666 if (pAd->NullContext.InUse == FALSE)
668 PTX_CONTEXT pNullContext;
669 PTXINFO_STRUC pTxInfo;
673 pNullContext = &(pAd->NullContext);
675 // Set the in use bit
676 pNullContext->InUse = TRUE;
677 pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0];
679 RTMPZeroMemory(&pWirelessPkt[0], 100);
680 pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[0];
681 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
682 pTxInfo->QSEL = FIFO_EDCA;
683 pTxWI = (PTXWI_STRUC)&pWirelessPkt[TXINFO_SIZE];
684 RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)),
685 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
687 RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11));
688 pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4;
690 // Fill out frame length information for global Bulk out arbitor
691 //pNullContext->BulkOutSize = TransferBufferLength;
692 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - send NULL Frame @%d Mbps...\n", RateIdToMbps[pAd->CommonCfg.TxRate]));
693 RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL);
696 RTUSBKickBulkOut(pAd);
703 ========================================================================
705 Get a received packet.
708 pAd device control block
709 pSaveRxD receive descriptor information
710 *pbReschedule need reschedule flag
711 *pRxPending pending received packet flag
717 ========================================================================
719 PNDIS_PACKET GetPacketFromRxRing(
720 IN PRTMP_ADAPTER pAd,
721 OUT PRT28XX_RXD_STRUC pSaveRxD,
722 OUT BOOLEAN *pbReschedule,
723 IN OUT UINT32 *pRxPending)
725 PRX_CONTEXT pRxContext;
729 ULONG RxBufferLength;
732 pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex];
733 if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE))
736 RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition;
737 if (RxBufferLength < (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXWI_STRUC) + sizeof(RXINFO_STRUC)))
742 pData = &pRxContext->TransferBuffer[pAd->ReadPosition]; /* 4KB */
743 // The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding)
744 ThisFrameLen = *pData + (*(pData+1)<<8);
745 if (ThisFrameLen == 0)
747 DBGPRINT(RT_DEBUG_TRACE, ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n",
748 pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset));
751 if ((ThisFrameLen&0x3) != 0)
753 DBGPRINT(RT_DEBUG_ERROR, ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n",
754 pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset));
758 if ((ThisFrameLen + 8)> RxBufferLength) // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC))
760 DBGPRINT(RT_DEBUG_TRACE,("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n",
761 pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset, RxBufferLength, pAd->ReadPosition));
763 // error frame. finish this loop
767 // skip USB frame length field
768 pData += RT2870_RXDMALEN_FIELD_SIZE;
769 pRxWI = (PRXWI_STRUC)pData;
770 if (pRxWI->MPDUtotalByteCount > ThisFrameLen)
772 DBGPRINT(RT_DEBUG_ERROR, ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n",
773 __FUNCTION__, pRxWI->MPDUtotalByteCount, ThisFrameLen));
777 // allocate a rx packet
778 pSkb = dev_alloc_skb(ThisFrameLen);
781 DBGPRINT(RT_DEBUG_ERROR,("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n", __FUNCTION__));
785 // copy the rx packet
786 memcpy(skb_put(pSkb, ThisFrameLen), pData, ThisFrameLen);
787 RTPKT_TO_OSPKT(pSkb)->dev = get_netdev_from_bssid(pAd, BSS0);
788 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pSkb), PKTSRC_NDIS);
791 *pSaveRxD = *(PRXINFO_STRUC)(pData + ThisFrameLen);
793 // update next packet read position.
794 pAd->ReadPosition += (ThisFrameLen + RT2870_RXDMALEN_FIELD_SIZE + RXINFO_SIZE); // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC))
805 ========================================================================
808 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
811 pRxD Pointer to the Rx descriptor
814 NDIS_STATUS_SUCCESS No err
815 NDIS_STATUS_FAILURE Error
819 ========================================================================
821 NDIS_STATUS RTMPCheckRxError(
822 IN PRTMP_ADAPTER pAd,
823 IN PHEADER_802_11 pHeader,
824 IN PRXWI_STRUC pRxWI,
825 IN PRT28XX_RXD_STRUC pRxINFO)
830 if (pAd->bPromiscuous == TRUE)
831 return(NDIS_STATUS_SUCCESS);
833 return(NDIS_STATUS_FAILURE);
835 // Phy errors & CRC errors
838 // Check RSSI for Noise Hist statistic collection.
839 dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
841 pAd->StaCfg.RPIDensity[0] += 1;
843 pAd->StaCfg.RPIDensity[1] += 1;
845 pAd->StaCfg.RPIDensity[2] += 1;
847 pAd->StaCfg.RPIDensity[3] += 1;
849 pAd->StaCfg.RPIDensity[4] += 1;
851 pAd->StaCfg.RPIDensity[5] += 1;
853 pAd->StaCfg.RPIDensity[6] += 1;
855 pAd->StaCfg.RPIDensity[7] += 1;
857 return(NDIS_STATUS_FAILURE);
860 // Add Rx size to channel load counter, we should ignore error counts
861 pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount+ 14);
863 // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
864 if (pHeader->FC.ToDs)
866 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n"));
867 return NDIS_STATUS_FAILURE;
870 // Paul 04-03 for OFDM Rx length issue
871 if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE)
873 DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n"));
874 return NDIS_STATUS_FAILURE;
877 // Drop not U2M frames, cant's drop here because we will drop beacon in this case
878 // I am kind of doubting the U2M bit operation
879 // if (pRxD->U2M == 0)
880 // return(NDIS_STATUS_FAILURE);
882 // drop decyption fail frame
883 if (pRxINFO->Decrypted && pRxINFO->CipherErr)
886 if (((pRxINFO->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
887 RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
889 if (((pRxINFO->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
890 RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
894 if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss)
896 pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
897 RTMPReportMicError(pAd, pWpaKey);
898 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
901 if (pRxINFO->Decrypted &&
902 (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == CIPHER_AES) &&
903 (pHeader->Sequence == pAd->FragFrame.Sequence))
906 // Acceptable since the First FragFrame no CipherErr problem.
908 return(NDIS_STATUS_SUCCESS);
911 return(NDIS_STATUS_FAILURE);
914 return(NDIS_STATUS_SUCCESS);
917 VOID RtmpUsbStaAsicForceWakeupTimeout(
918 IN PVOID SystemSpecific1,
919 IN PVOID FunctionContext,
920 IN PVOID SystemSpecific2,
921 IN PVOID SystemSpecific3)
923 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
926 if (pAd && pAd->Mlme.AutoWakeupTimerRunning)
928 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
930 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
931 pAd->Mlme.AutoWakeupTimerRunning = FALSE;
935 VOID RT28xxUsbStaAsicForceWakeup(
936 IN PRTMP_ADAPTER pAd,
941 if (pAd->Mlme.AutoWakeupTimerRunning)
942 RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Canceled);
944 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
946 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
949 VOID RT28xxUsbStaAsicSleepThenAutoWakeup(
950 IN PRTMP_ADAPTER pAd,
951 IN USHORT TbttNumToNextWakeUp)
955 // we have decided to SLEEP, so at least do it for a BEACON period.
956 if (TbttNumToNextWakeUp == 0)
957 TbttNumToNextWakeUp = 1;
959 RTMPSetTimer(&pAd->Mlme.AutoWakeupTimer, AUTO_WAKEUP_TIMEOUT);
960 pAd->Mlme.AutoWakeupTimerRunning = TRUE;
962 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); // send POWER-SAVE command to MCU. Timeout 40us.
964 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
968 #endif // RTMP_MAC_USB //