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);
193 RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
194 #endif // RT_BIG_ENDIAN //
195 pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
196 pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
198 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
200 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
202 // Zero the last padding.
203 pWirelessPacket += pTxBlk->SrcBufLen;
204 NdisZeroMemory(pWirelessPacket, padding + 8);
206 if (fragNum == pTxBlk->TotalFragNum)
208 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
210 // Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame.
211 pHTTXContext->CurWritePosition += pTxBlk->Priv;
212 if (TxQLastRound == TRUE)
213 pHTTXContext->CurWritePosition = 8;
214 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
217 // Finally, set bCurWriting as FALSE
218 pHTTXContext->bCurWriting = FALSE;
220 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
222 // succeed and release the skb buffer
223 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
232 USHORT RtmpUSB_WriteSingleTxResource(
233 IN PRTMP_ADAPTER pAd,
236 OUT USHORT *FreeNumber)
238 HT_TX_CONTEXT *pHTTXContext;
241 TXINFO_STRUC *pTxInfo;
243 PUCHAR pWirelessPacket;
245 unsigned long IrqFlags;
247 UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
248 BOOLEAN bTxQLastRound = FALSE;
250 // For USB, didn't need PCI_MAP_SINGLE()
251 //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE);
255 // get Tx Ring Resource & Dma Buffer address
257 QueIdx = pTxBlk->QueIdx;
259 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
260 pHTTXContext = &pAd->TxContext[QueIdx];
261 fillOffset = pHTTXContext->CurWritePosition;
266 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
267 if(Status == NDIS_STATUS_SUCCESS)
269 pHTTXContext->bCurWriting = TRUE;
271 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
272 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
274 // Reserve space for 8 bytes padding.
275 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
277 pHTTXContext->ENextBulkOutPosition += 8;
278 pHTTXContext->CurWritePosition += 8;
281 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
283 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
285 // copy TXWI + WLAN Header + LLC into DMA Header Buffer
286 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
287 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
289 // Build our URB for USBD
290 DMAHdrLen = TXWI_SIZE + hwHdrLen;
291 USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen;
292 padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment
293 USBDMApktLen += padding;
295 pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen);
297 // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload
298 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE);
300 if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT)
302 pTxInfo->SwUseLastRound = 1;
303 bTxQLastRound = TRUE;
305 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
307 RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
308 #endif // RT_BIG_ENDIAN //
309 pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
311 // We unlock it here to prevent the first 8 bytes maybe over-writed issue.
312 // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext.
313 // 2. An interrupt break our routine and handle bulk-out complete.
314 // 3. In the bulk-out compllete, it need to do another bulk-out,
315 // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
316 // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
317 // 4. Interrupt complete.
318 // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
319 // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
320 // and the packet will wrong.
321 pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
322 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
324 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
325 pWirelessPacket += pTxBlk->SrcBufLen;
326 NdisZeroMemory(pWirelessPacket, padding + 8);
328 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
330 pHTTXContext->CurWritePosition += pTxBlk->Priv;
332 pHTTXContext->CurWritePosition = 8;
333 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
335 pHTTXContext->bCurWriting = FALSE;
339 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
342 // succeed and release the skb buffer
343 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
350 USHORT RtmpUSB_WriteMultiTxResource(
351 IN PRTMP_ADAPTER pAd,
354 OUT USHORT *FreeNumber)
356 HT_TX_CONTEXT *pHTTXContext;
357 USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length.
359 TXINFO_STRUC *pTxInfo;
361 PUCHAR pWirelessPacket = NULL;
364 unsigned long IrqFlags;
365 //UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
368 // get Tx Ring Resource & Dma Buffer address
370 QueIdx = pTxBlk->QueIdx;
371 pHTTXContext = &pAd->TxContext[QueIdx];
373 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
377 // Check if we have enough space for this bulk-out batch.
378 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
379 if (Status == NDIS_STATUS_SUCCESS)
381 pHTTXContext->bCurWriting = TRUE;
383 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
384 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
387 // Reserve space for 8 bytes padding.
388 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
391 pHTTXContext->CurWritePosition += 8;
392 pHTTXContext->ENextBulkOutPosition += 8;
394 fillOffset = pHTTXContext->CurWritePosition;
395 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
397 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
400 // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
402 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
403 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
404 hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
405 else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
406 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
407 hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
409 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
410 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
412 // Update the pTxBlk->Priv.
413 pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
415 // pTxInfo->USBDMApktLen now just a temp value and will to correct latter.
416 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE);
419 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv);
421 RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
422 #endif // RT_BIG_ENDIAN //
423 pHTTXContext->CurWriteRealPos += pTxBlk->Priv;
424 pWirelessPacket += pTxBlk->Priv;
428 { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.
430 Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
431 if (Status == NDIS_STATUS_SUCCESS)
433 fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv);
434 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
436 //hwHdrLen = pTxBlk->MpduHeaderLen;
437 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen);
438 pWirelessPacket += (pTxBlk->MpduHeaderLen);
439 pTxBlk->Priv += pTxBlk->MpduHeaderLen;
442 { // It should not happened now unless we are going to shutdown.
443 DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n"));
444 Status = NDIS_STATUS_FAILURE;
449 // We unlock it here to prevent the first 8 bytes maybe over-write issue.
450 // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext.
451 // 2. An interrupt break our routine and handle bulk-out complete.
452 // 3. In the bulk-out compllete, it need to do another bulk-out,
453 // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
454 // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
455 // 4. Interrupt complete.
456 // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
457 // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
458 // and the packet will wrong.
459 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
461 if (Status != NDIS_STATUS_SUCCESS)
463 DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
467 // Copy the frame content into DMA buffer and update the pTxBlk->Priv
468 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
469 pWirelessPacket += pTxBlk->SrcBufLen;
470 pTxBlk->Priv += pTxBlk->SrcBufLen;
473 // Release the skb buffer here
474 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
481 VOID RtmpUSB_FinalWriteTxResource(
482 IN PRTMP_ADAPTER pAd,
484 IN USHORT totalMPDUSize,
488 HT_TX_CONTEXT *pHTTXContext;
490 TXINFO_STRUC *pTxInfo;
492 UINT32 USBDMApktLen, padding;
493 unsigned long IrqFlags;
494 PUCHAR pWirelessPacket;
496 QueIdx = pTxBlk->QueIdx;
497 pHTTXContext = &pAd->TxContext[QueIdx];
499 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
501 if (pHTTXContext->bCurWriting == TRUE)
503 fillOffset = pHTTXContext->CurWritePosition;
504 if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition))
505 && (pHTTXContext->bCopySavePad == TRUE))
506 pWirelessPacket = (PUCHAR)(&pHTTXContext->SavedPad[0]);
508 pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]);
511 // Update TxInfo->USBDMApktLen ,
512 // the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding
514 pTxInfo = (PTXINFO_STRUC)(pWirelessPacket);
516 // Calculate the bulk-out padding
517 USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE;
518 padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment
519 USBDMApktLen += padding;
521 pTxInfo->USBDMATxPktLen = USBDMApktLen;
524 // Update TXWI->MPDUtotalByteCount ,
525 // the length = 802.11 header + payload_of_all_batch_frames
526 pTxWI= (PTXWI_STRUC)(pWirelessPacket + TXINFO_SIZE);
527 pTxWI->MPDUtotalByteCount = totalMPDUSize;
530 // Update the pHTTXContext->CurWritePosition
532 pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen);
533 if ((pHTTXContext->CurWritePosition + 3906)> MAX_TXBULK_LIMIT)
534 { // Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame.
535 pHTTXContext->CurWritePosition = 8;
536 pTxInfo->SwUseLastRound = 1;
538 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
542 // Zero the last padding.
544 pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]);
545 NdisZeroMemory(pWirelessPacket, padding + 8);
547 // Finally, set bCurWriting as FALSE
548 pHTTXContext->bCurWriting = FALSE;
552 { // It should not happened now unless we are going to shutdown.
553 DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n"));
556 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
561 VOID RtmpUSBDataLastTxIdx(
562 IN PRTMP_ADAPTER pAd,
566 // DO nothing for USB.
571 When can do bulk-out:
572 1. TxSwFreeIdx < TX_RING_SIZE;
573 It means has at least one Ring entity is ready for bulk-out, kick it out.
574 2. If TxSwFreeIdx == TX_RING_SIZE
575 Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out.
578 VOID RtmpUSBDataKickOut(
579 IN PRTMP_ADAPTER pAd,
583 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
584 RTUSBKickBulkOut(pAd);
590 Must be run in Interrupt context
591 This function handle RT2870 specific TxDesc and cpu index update and kick the packet out.
593 int RtmpUSBMgmtKickOut(
594 IN RTMP_ADAPTER *pAd,
596 IN PNDIS_PACKET pPacket,
600 PTXINFO_STRUC pTxInfo;
604 ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
605 PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa;
606 unsigned long IrqFlags;
609 pTxInfo = (PTXINFO_STRUC)(pSrcBufVA);
611 // Build our URB for USBD
612 BulkOutSize = SrcBufLen;
613 BulkOutSize = (BulkOutSize + 3) & (~3);
614 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
616 BulkOutSize += 4; // Always add 4 extra bytes at every packet.
618 // If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again.
619 if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0)
622 padLen = BulkOutSize - SrcBufLen;
623 ASSERT((padLen <= RTMP_PKT_TAIL_PADDING));
625 // Now memzero all extra padding bytes.
626 pDest = (PUCHAR)(pSrcBufVA + SrcBufLen);
627 skb_put(GET_OS_PKT_TYPE(pPacket), padLen);
628 NdisZeroMemory(pDest, padLen);
630 RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
632 pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket;
633 pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket));
635 // Length in TxInfo should be 8 less than bulkout size.
636 pMLMEContext->BulkOutSize = BulkOutSize;
637 pMLMEContext->InUse = TRUE;
638 pMLMEContext->bWaitingBulkOut = TRUE;
642 //hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize));
644 //pAd->RalinkCounters.KickTxCount++;
645 //pAd->RalinkCounters.OneSecTxDoneCount++;
647 //if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE)
648 // needKickOut = TRUE;
650 // Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX
651 pAd->MgmtRing.TxSwFreeIdx--;
652 INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
654 RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
656 RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
658 RTUSBKickBulkOut(pAd);
664 VOID RtmpUSBNullFrameKickOut(
665 IN RTMP_ADAPTER *pAd,
667 IN UCHAR *pNullFrame,
670 if (pAd->NullContext.InUse == FALSE)
672 PTX_CONTEXT pNullContext;
673 PTXINFO_STRUC pTxInfo;
677 pNullContext = &(pAd->NullContext);
679 // Set the in use bit
680 pNullContext->InUse = TRUE;
681 pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0];
683 RTMPZeroMemory(&pWirelessPkt[0], 100);
684 pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[0];
685 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
686 pTxInfo->QSEL = FIFO_EDCA;
687 pTxWI = (PTXWI_STRUC)&pWirelessPkt[TXINFO_SIZE];
688 RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)),
689 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
691 RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
692 #endif // RT_BIG_ENDIAN //
694 RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11));
696 RTMPFrameEndianChange(pAd, (PUCHAR)&pWirelessPkt[TXINFO_SIZE + TXWI_SIZE], DIR_WRITE, FALSE);
697 #endif // RT_BIG_ENDIAN //
698 pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4;
700 // Fill out frame length information for global Bulk out arbitor
701 //pNullContext->BulkOutSize = TransferBufferLength;
702 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - send NULL Frame @%d Mbps...\n", RateIdToMbps[pAd->CommonCfg.TxRate]));
703 RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL);
706 RTUSBKickBulkOut(pAd);
711 #ifdef CONFIG_STA_SUPPORT
713 ========================================================================
716 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
719 pRxD Pointer to the Rx descriptor
722 NDIS_STATUS_SUCCESS No err
723 NDIS_STATUS_FAILURE Error
727 ========================================================================
729 NDIS_STATUS RTMPCheckRxError(
730 IN PRTMP_ADAPTER pAd,
731 IN PHEADER_802_11 pHeader,
732 IN PRXWI_STRUC pRxWI,
733 IN PRT28XX_RXD_STRUC pRxINFO)
738 if (pAd->bPromiscuous == TRUE)
739 return(NDIS_STATUS_SUCCESS);
741 return(NDIS_STATUS_FAILURE);
743 // Phy errors & CRC errors
746 // Check RSSI for Noise Hist statistic collection.
747 dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
749 pAd->StaCfg.RPIDensity[0] += 1;
751 pAd->StaCfg.RPIDensity[1] += 1;
753 pAd->StaCfg.RPIDensity[2] += 1;
755 pAd->StaCfg.RPIDensity[3] += 1;
757 pAd->StaCfg.RPIDensity[4] += 1;
759 pAd->StaCfg.RPIDensity[5] += 1;
761 pAd->StaCfg.RPIDensity[6] += 1;
763 pAd->StaCfg.RPIDensity[7] += 1;
765 return(NDIS_STATUS_FAILURE);
768 // Add Rx size to channel load counter, we should ignore error counts
769 pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount+ 14);
771 // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
772 if (pHeader->FC.ToDs)
774 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n"));
775 return NDIS_STATUS_FAILURE;
778 // Paul 04-03 for OFDM Rx length issue
779 if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE)
781 DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n"));
782 return NDIS_STATUS_FAILURE;
785 // Drop not U2M frames, cant's drop here because we will drop beacon in this case
786 // I am kind of doubting the U2M bit operation
787 // if (pRxD->U2M == 0)
788 // return(NDIS_STATUS_FAILURE);
790 // drop decyption fail frame
791 if (pRxINFO->Decrypted && pRxINFO->CipherErr)
797 if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss)
799 pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
800 RTMPReportMicError(pAd, pWpaKey);
801 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
804 if (pRxINFO->Decrypted &&
805 (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == CIPHER_AES) &&
806 (pHeader->Sequence == pAd->FragFrame.Sequence))
809 // Acceptable since the First FragFrame no CipherErr problem.
811 return(NDIS_STATUS_SUCCESS);
814 return(NDIS_STATUS_FAILURE);
817 return(NDIS_STATUS_SUCCESS);
820 VOID RT28xxUsbStaAsicForceWakeup(
821 IN PRTMP_ADAPTER pAd,
824 AUTO_WAKEUP_STRUC AutoWakeupCfg;
826 AutoWakeupCfg.word = 0;
827 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
829 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
831 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
834 VOID RT28xxUsbStaAsicSleepThenAutoWakeup(
835 IN PRTMP_ADAPTER pAd,
836 IN USHORT TbttNumToNextWakeUp)
838 AUTO_WAKEUP_STRUC AutoWakeupCfg;
840 // we have decided to SLEEP, so at least do it for a BEACON period.
841 if (TbttNumToNextWakeUp == 0)
842 TbttNumToNextWakeUp = 1;
844 AutoWakeupCfg.word = 0;
845 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
847 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
848 AutoWakeupCfg.field.EnableAutoWakeup = 1;
849 AutoWakeupCfg.field.AutoLeadTime = 5;
850 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
852 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); // send POWER-SAVE command to MCU. Timeout 40us.
854 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
857 #endif // CONFIG_STA_SUPPORT //
859 VOID RT28xxUsbMlmeRadioOn(
860 IN PRTMP_ADAPTER pAd)
862 DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOn()\n"));
864 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
867 #ifdef CONFIG_STA_SUPPORT
868 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
870 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
871 RTMPusecDelay(10000);
873 #endif // CONFIG_STA_SUPPORT //
874 NICResetFromError(pAd);
879 // Clear Radio off flag
880 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
882 #ifdef CONFIG_STA_SUPPORT
883 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
884 RTUSBBulkReceive(pAd);
885 #endif // CONFIG_STA_SUPPORT //
888 RTMPSetLED(pAd, LED_RADIO_ON);
891 VOID RT28xxUsbMlmeRadioOFF(
892 IN PRTMP_ADAPTER pAd)
894 WPDMA_GLO_CFG_STRUC GloCfg;
897 DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOFF()\n"));
899 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
903 RTMPSetLED(pAd, LED_RADIO_OFF);
904 // Set Radio off flag
905 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
907 #ifdef CONFIG_STA_SUPPORT
908 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
910 // Link down first if any association exists
911 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
912 LinkDown(pAd, FALSE);
913 RTMPusecDelay(10000);
915 //==========================================
916 // Clean up old bss table
917 BssTableInit(&pAd->ScanTab);
919 #endif // CONFIG_STA_SUPPORT //
923 RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
924 Value &= (0xfffffff3);
925 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
927 // MAC_SYS_CTRL => value = 0x0 => 40mA
928 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
930 // PWR_PIN_CFG => value = 0x0 => 40mA
931 RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
933 // TX_PIN_CFG => value = 0x0 => 20mA
934 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
936 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
939 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
944 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
947 // Waiting for DMA idle
951 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
952 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
958 #ifdef CONFIG_STA_SUPPORT
959 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
960 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
961 #endif // CONFIG_STA_SUPPORT //