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 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
299 #ifdef CONFIG_STA_SUPPORT
300 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
301 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE);
302 #endif // CONFIG_STA_SUPPORT //
304 if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT)
306 pTxInfo->SwUseLastRound = 1;
307 bTxQLastRound = TRUE;
309 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
311 RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
312 #endif // RT_BIG_ENDIAN //
313 pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
315 // We unlock it here to prevent the first 8 bytes maybe over-writed issue.
316 // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext.
317 // 2. An interrupt break our routine and handle bulk-out complete.
318 // 3. In the bulk-out compllete, it need to do another bulk-out,
319 // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
320 // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
321 // 4. Interrupt complete.
322 // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
323 // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
324 // and the packet will wrong.
325 pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
326 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
328 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
329 pWirelessPacket += pTxBlk->SrcBufLen;
330 NdisZeroMemory(pWirelessPacket, padding + 8);
332 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
334 pHTTXContext->CurWritePosition += pTxBlk->Priv;
336 pHTTXContext->CurWritePosition = 8;
337 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
339 pHTTXContext->bCurWriting = FALSE;
343 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
346 // succeed and release the skb buffer
347 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
354 USHORT RtmpUSB_WriteMultiTxResource(
355 IN PRTMP_ADAPTER pAd,
358 OUT USHORT *FreeNumber)
360 HT_TX_CONTEXT *pHTTXContext;
361 USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length.
363 TXINFO_STRUC *pTxInfo;
365 PUCHAR pWirelessPacket = NULL;
368 unsigned long IrqFlags;
369 //UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
372 // get Tx Ring Resource & Dma Buffer address
374 QueIdx = pTxBlk->QueIdx;
375 pHTTXContext = &pAd->TxContext[QueIdx];
377 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
381 // Check if we have enough space for this bulk-out batch.
382 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
383 if (Status == NDIS_STATUS_SUCCESS)
385 pHTTXContext->bCurWriting = TRUE;
387 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
388 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
391 // Reserve space for 8 bytes padding.
392 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
395 pHTTXContext->CurWritePosition += 8;
396 pHTTXContext->ENextBulkOutPosition += 8;
398 fillOffset = pHTTXContext->CurWritePosition;
399 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
401 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
404 // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
406 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
407 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
408 hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
409 else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
410 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
411 hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
413 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
414 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
416 // Update the pTxBlk->Priv.
417 pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
419 // pTxInfo->USBDMApktLen now just a temp value and will to correct latter.
420 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE);
423 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv);
425 RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
426 #endif // RT_BIG_ENDIAN //
427 pHTTXContext->CurWriteRealPos += pTxBlk->Priv;
428 pWirelessPacket += pTxBlk->Priv;
432 { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.
434 Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
435 if (Status == NDIS_STATUS_SUCCESS)
437 fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv);
438 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
440 //hwHdrLen = pTxBlk->MpduHeaderLen;
441 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen);
442 pWirelessPacket += (pTxBlk->MpduHeaderLen);
443 pTxBlk->Priv += pTxBlk->MpduHeaderLen;
446 { // It should not happened now unless we are going to shutdown.
447 DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n"));
448 Status = NDIS_STATUS_FAILURE;
453 // We unlock it here to prevent the first 8 bytes maybe over-write issue.
454 // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext.
455 // 2. An interrupt break our routine and handle bulk-out complete.
456 // 3. In the bulk-out compllete, it need to do another bulk-out,
457 // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
458 // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
459 // 4. Interrupt complete.
460 // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
461 // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
462 // and the packet will wrong.
463 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
465 if (Status != NDIS_STATUS_SUCCESS)
467 DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
471 // Copy the frame content into DMA buffer and update the pTxBlk->Priv
472 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
473 pWirelessPacket += pTxBlk->SrcBufLen;
474 pTxBlk->Priv += pTxBlk->SrcBufLen;
477 // Release the skb buffer here
478 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
485 VOID RtmpUSB_FinalWriteTxResource(
486 IN PRTMP_ADAPTER pAd,
488 IN USHORT totalMPDUSize,
492 HT_TX_CONTEXT *pHTTXContext;
494 TXINFO_STRUC *pTxInfo;
496 UINT32 USBDMApktLen, padding;
497 unsigned long IrqFlags;
498 PUCHAR pWirelessPacket;
500 QueIdx = pTxBlk->QueIdx;
501 pHTTXContext = &pAd->TxContext[QueIdx];
503 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
505 if (pHTTXContext->bCurWriting == TRUE)
507 fillOffset = pHTTXContext->CurWritePosition;
508 if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition))
509 && (pHTTXContext->bCopySavePad == TRUE))
510 pWirelessPacket = (PUCHAR)(&pHTTXContext->SavedPad[0]);
512 pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]);
515 // Update TxInfo->USBDMApktLen ,
516 // the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding
518 pTxInfo = (PTXINFO_STRUC)(pWirelessPacket);
520 // Calculate the bulk-out padding
521 USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE;
522 padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment
523 USBDMApktLen += padding;
525 pTxInfo->USBDMATxPktLen = USBDMApktLen;
528 // Update TXWI->MPDUtotalByteCount ,
529 // the length = 802.11 header + payload_of_all_batch_frames
530 pTxWI= (PTXWI_STRUC)(pWirelessPacket + TXINFO_SIZE);
531 pTxWI->MPDUtotalByteCount = totalMPDUSize;
534 // Update the pHTTXContext->CurWritePosition
536 pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen);
537 if ((pHTTXContext->CurWritePosition + 3906)> MAX_TXBULK_LIMIT)
538 { // Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame.
539 pHTTXContext->CurWritePosition = 8;
540 pTxInfo->SwUseLastRound = 1;
542 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
546 // Zero the last padding.
548 pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]);
549 NdisZeroMemory(pWirelessPacket, padding + 8);
551 // Finally, set bCurWriting as FALSE
552 pHTTXContext->bCurWriting = FALSE;
556 { // It should not happened now unless we are going to shutdown.
557 DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n"));
560 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
565 VOID RtmpUSBDataLastTxIdx(
566 IN PRTMP_ADAPTER pAd,
570 // DO nothing for USB.
575 When can do bulk-out:
576 1. TxSwFreeIdx < TX_RING_SIZE;
577 It means has at least one Ring entity is ready for bulk-out, kick it out.
578 2. If TxSwFreeIdx == TX_RING_SIZE
579 Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out.
582 VOID RtmpUSBDataKickOut(
583 IN PRTMP_ADAPTER pAd,
587 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
588 RTUSBKickBulkOut(pAd);
594 Must be run in Interrupt context
595 This function handle RT2870 specific TxDesc and cpu index update and kick the packet out.
597 int RtmpUSBMgmtKickOut(
598 IN RTMP_ADAPTER *pAd,
600 IN PNDIS_PACKET pPacket,
604 PTXINFO_STRUC pTxInfo;
608 ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
609 PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa;
610 unsigned long IrqFlags;
613 pTxInfo = (PTXINFO_STRUC)(pSrcBufVA);
615 // Build our URB for USBD
616 BulkOutSize = SrcBufLen;
617 BulkOutSize = (BulkOutSize + 3) & (~3);
618 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
620 BulkOutSize += 4; // Always add 4 extra bytes at every packet.
622 // If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again.
623 if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0)
626 padLen = BulkOutSize - SrcBufLen;
627 ASSERT((padLen <= RTMP_PKT_TAIL_PADDING));
629 // Now memzero all extra padding bytes.
630 pDest = (PUCHAR)(pSrcBufVA + SrcBufLen);
631 skb_put(GET_OS_PKT_TYPE(pPacket), padLen);
632 NdisZeroMemory(pDest, padLen);
634 RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
636 pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket;
637 pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket));
639 // Length in TxInfo should be 8 less than bulkout size.
640 pMLMEContext->BulkOutSize = BulkOutSize;
641 pMLMEContext->InUse = TRUE;
642 pMLMEContext->bWaitingBulkOut = TRUE;
646 //hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize));
648 //pAd->RalinkCounters.KickTxCount++;
649 //pAd->RalinkCounters.OneSecTxDoneCount++;
651 //if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE)
652 // needKickOut = TRUE;
654 // Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX
655 pAd->MgmtRing.TxSwFreeIdx--;
656 INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
658 RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
660 RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
662 RTUSBKickBulkOut(pAd);
668 VOID RtmpUSBNullFrameKickOut(
669 IN RTMP_ADAPTER *pAd,
671 IN UCHAR *pNullFrame,
674 if (pAd->NullContext.InUse == FALSE)
676 PTX_CONTEXT pNullContext;
677 PTXINFO_STRUC pTxInfo;
681 pNullContext = &(pAd->NullContext);
683 // Set the in use bit
684 pNullContext->InUse = TRUE;
685 pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0];
687 RTMPZeroMemory(&pWirelessPkt[0], 100);
688 pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[0];
689 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
690 pTxInfo->QSEL = FIFO_EDCA;
691 pTxWI = (PTXWI_STRUC)&pWirelessPkt[TXINFO_SIZE];
692 RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)),
693 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
695 RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
696 #endif // RT_BIG_ENDIAN //
698 RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11));
700 RTMPFrameEndianChange(pAd, (PUCHAR)&pWirelessPkt[TXINFO_SIZE + TXWI_SIZE], DIR_WRITE, FALSE);
701 #endif // RT_BIG_ENDIAN //
702 pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4;
704 // Fill out frame length information for global Bulk out arbitor
705 //pNullContext->BulkOutSize = TransferBufferLength;
706 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - send NULL Frame @%d Mbps...\n", RateIdToMbps[pAd->CommonCfg.TxRate]));
707 RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL);
710 RTUSBKickBulkOut(pAd);
715 #ifdef CONFIG_STA_SUPPORT
717 ========================================================================
720 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
723 pRxD Pointer to the Rx descriptor
726 NDIS_STATUS_SUCCESS No err
727 NDIS_STATUS_FAILURE Error
731 ========================================================================
733 NDIS_STATUS RTMPCheckRxError(
734 IN PRTMP_ADAPTER pAd,
735 IN PHEADER_802_11 pHeader,
736 IN PRXWI_STRUC pRxWI,
737 IN PRT28XX_RXD_STRUC pRxINFO)
742 if (pAd->bPromiscuous == TRUE)
743 return(NDIS_STATUS_SUCCESS);
745 return(NDIS_STATUS_FAILURE);
747 // Phy errors & CRC errors
750 // Check RSSI for Noise Hist statistic collection.
751 dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
753 pAd->StaCfg.RPIDensity[0] += 1;
755 pAd->StaCfg.RPIDensity[1] += 1;
757 pAd->StaCfg.RPIDensity[2] += 1;
759 pAd->StaCfg.RPIDensity[3] += 1;
761 pAd->StaCfg.RPIDensity[4] += 1;
763 pAd->StaCfg.RPIDensity[5] += 1;
765 pAd->StaCfg.RPIDensity[6] += 1;
767 pAd->StaCfg.RPIDensity[7] += 1;
769 return(NDIS_STATUS_FAILURE);
772 // Add Rx size to channel load counter, we should ignore error counts
773 pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount+ 14);
775 // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
776 if (pHeader->FC.ToDs)
778 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n"));
779 return NDIS_STATUS_FAILURE;
782 // Paul 04-03 for OFDM Rx length issue
783 if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE)
785 DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n"));
786 return NDIS_STATUS_FAILURE;
789 // Drop not U2M frames, cant's drop here because we will drop beacon in this case
790 // I am kind of doubting the U2M bit operation
791 // if (pRxD->U2M == 0)
792 // return(NDIS_STATUS_FAILURE);
794 // drop decyption fail frame
795 if (pRxINFO->Decrypted && pRxINFO->CipherErr)
801 if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss)
803 pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
804 RTMPReportMicError(pAd, pWpaKey);
805 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
808 if (pRxINFO->Decrypted &&
809 (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == CIPHER_AES) &&
810 (pHeader->Sequence == pAd->FragFrame.Sequence))
813 // Acceptable since the First FragFrame no CipherErr problem.
815 return(NDIS_STATUS_SUCCESS);
818 return(NDIS_STATUS_FAILURE);
821 return(NDIS_STATUS_SUCCESS);
824 VOID RT28xxUsbStaAsicForceWakeup(
825 IN PRTMP_ADAPTER pAd,
828 AUTO_WAKEUP_STRUC AutoWakeupCfg;
830 AutoWakeupCfg.word = 0;
831 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
833 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
835 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
838 VOID RT28xxUsbStaAsicSleepThenAutoWakeup(
839 IN PRTMP_ADAPTER pAd,
840 IN USHORT TbttNumToNextWakeUp)
842 AUTO_WAKEUP_STRUC AutoWakeupCfg;
844 // we have decided to SLEEP, so at least do it for a BEACON period.
845 if (TbttNumToNextWakeUp == 0)
846 TbttNumToNextWakeUp = 1;
848 AutoWakeupCfg.word = 0;
849 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
851 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
852 AutoWakeupCfg.field.EnableAutoWakeup = 1;
853 AutoWakeupCfg.field.AutoLeadTime = 5;
854 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
856 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); // send POWER-SAVE command to MCU. Timeout 40us.
858 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
861 #endif // CONFIG_STA_SUPPORT //
863 VOID RT28xxUsbMlmeRadioOn(
864 IN PRTMP_ADAPTER pAd)
866 DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOn()\n"));
868 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
871 #ifdef CONFIG_STA_SUPPORT
872 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
874 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
875 RTMPusecDelay(10000);
877 #endif // CONFIG_STA_SUPPORT //
878 NICResetFromError(pAd);
886 RT30xxReverseRFSleepModeSetup(pAd);
890 // Clear Radio off flag
891 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
893 #ifdef CONFIG_STA_SUPPORT
894 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
895 RTUSBBulkReceive(pAd);
896 #endif // CONFIG_STA_SUPPORT //
899 RTMPSetLED(pAd, LED_RADIO_ON);
902 VOID RT28xxUsbMlmeRadioOFF(
903 IN PRTMP_ADAPTER pAd)
905 WPDMA_GLO_CFG_STRUC GloCfg;
908 DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOFF()\n"));
910 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
914 RTMPSetLED(pAd, LED_RADIO_OFF);
915 // Set Radio off flag
916 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
918 #ifdef CONFIG_STA_SUPPORT
919 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
921 // Link down first if any association exists
922 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
923 LinkDown(pAd, FALSE);
924 RTMPusecDelay(10000);
926 //==========================================
927 // Clean up old bss table
928 BssTableInit(&pAd->ScanTab);
930 #endif // CONFIG_STA_SUPPORT //
933 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
936 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
941 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
945 RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA
946 GloCfg.field.EnableTxDMA = 0;
947 GloCfg.field.EnableRxDMA = 0;
948 RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings
950 // Waiting for DMA idle
954 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
955 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
962 RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
963 Value &= (0xfffffff3);
964 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
966 // MAC_SYS_CTRL => value = 0x0 => 40mA
967 //RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
969 // PWR_PIN_CFG => value = 0x0 => 40mA
970 //RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
972 // TX_PIN_CFG => value = 0x0 => 20mA
973 //RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
975 #ifdef CONFIG_STA_SUPPORT
976 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
977 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
978 #endif // CONFIG_STA_SUPPORT //