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
36 #include "../rt_config.h"
39 We can do copy the frame into pTxContext when match following conditions.
44 static inline int RtmpUSBCanDoWrite(struct rt_rtmp_adapter
*pAd
,
46 struct rt_ht_tx_context
*pHTTXContext
)
48 int canWrite
= NDIS_STATUS_RESOURCES
;
50 if (((pHTTXContext
->CurWritePosition
) <
51 pHTTXContext
->NextBulkOutPosition
)
52 && (pHTTXContext
->CurWritePosition
+ LOCAL_TXBUF_SIZE
) >
53 pHTTXContext
->NextBulkOutPosition
) {
54 DBGPRINT(RT_DEBUG_ERROR
, ("RtmpUSBCanDoWrite c1!\n"));
55 RTUSB_SET_BULK_FLAG(pAd
,
56 (fRTUSB_BULK_OUT_DATA_NORMAL
<< QueIdx
));
57 } else if ((pHTTXContext
->CurWritePosition
== 8)
58 && (pHTTXContext
->NextBulkOutPosition
< LOCAL_TXBUF_SIZE
)) {
59 DBGPRINT(RT_DEBUG_ERROR
, ("RtmpUSBCanDoWrite c2!\n"));
60 RTUSB_SET_BULK_FLAG(pAd
,
61 (fRTUSB_BULK_OUT_DATA_NORMAL
<< QueIdx
));
62 } else if (pHTTXContext
->bCurWriting
== TRUE
) {
63 DBGPRINT(RT_DEBUG_ERROR
, ("RtmpUSBCanDoWrite c3!\n"));
65 canWrite
= NDIS_STATUS_SUCCESS
;
71 u16
RtmpUSB_WriteSubTxResource(struct rt_rtmp_adapter
*pAd
,
72 struct rt_tx_blk
*pTxBlk
,
73 IN BOOLEAN bIsLast
, u16
* FreeNumber
)
76 /* Dummy function. Should be removed in the future. */
81 u16
RtmpUSB_WriteFragTxResource(struct rt_rtmp_adapter
*pAd
,
82 struct rt_tx_blk
*pTxBlk
,
83 u8 fragNum
, u16
* FreeNumber
)
85 struct rt_ht_tx_context
*pHTTXContext
;
86 u16 hwHdrLen
; /* The hwHdrLen consist of 802.11 header length plus the header padding length. */
88 struct rt_txinfo
*pTxInfo
;
89 struct rt_txwi
*pTxWI
;
90 u8
*pWirelessPacket
= NULL
;
93 unsigned long IrqFlags
;
94 u32 USBDMApktLen
= 0, DMAHdrLen
, padding
;
95 BOOLEAN TxQLastRound
= FALSE
;
98 /* get Tx Ring Resource & Dma Buffer address */
100 QueIdx
= pTxBlk
->QueIdx
;
101 pHTTXContext
= &pAd
->TxContext
[QueIdx
];
103 RTMP_IRQ_LOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
105 pHTTXContext
= &pAd
->TxContext
[QueIdx
];
106 fillOffset
= pHTTXContext
->CurWritePosition
;
109 /* Check if we have enough space for this bulk-out batch. */
110 Status
= RtmpUSBCanDoWrite(pAd
, QueIdx
, pHTTXContext
);
111 if (Status
== NDIS_STATUS_SUCCESS
) {
112 pHTTXContext
->bCurWriting
= TRUE
;
114 /* Reserve space for 8 bytes padding. */
115 if ((pHTTXContext
->ENextBulkOutPosition
==
116 pHTTXContext
->CurWritePosition
)) {
117 pHTTXContext
->ENextBulkOutPosition
+= 8;
118 pHTTXContext
->CurWritePosition
+= 8;
122 pHTTXContext
->CurWriteRealPos
=
123 pHTTXContext
->CurWritePosition
;
125 RTMP_IRQ_UNLOCK(&pAd
->TxContextQueueLock
[QueIdx
],
128 RELEASE_NDIS_PACKET(pAd
, pTxBlk
->pPacket
,
129 NDIS_STATUS_FAILURE
);
133 /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */
135 ((pHTTXContext
->bCurWriting
==
136 TRUE
) ? NDIS_STATUS_SUCCESS
: NDIS_STATUS_FAILURE
);
137 if (Status
== NDIS_STATUS_SUCCESS
) {
138 fillOffset
+= pTxBlk
->Priv
;
140 RTMP_IRQ_UNLOCK(&pAd
->TxContextQueueLock
[QueIdx
],
143 RELEASE_NDIS_PACKET(pAd
, pTxBlk
->pPacket
,
144 NDIS_STATUS_FAILURE
);
149 NdisZeroMemory((u8
*)(&pTxBlk
->HeaderBuf
[0]), TXINFO_SIZE
);
150 pTxInfo
= (struct rt_txinfo
*)(&pTxBlk
->HeaderBuf
[0]);
151 pTxWI
= (struct rt_txwi
*) (&pTxBlk
->HeaderBuf
[TXINFO_SIZE
]);
154 &pHTTXContext
->TransferBuffer
->field
.WirelessPacket
[fillOffset
];
156 /* copy TXWI + WLAN Header + LLC into DMA Header Buffer */
157 /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
158 hwHdrLen
= pTxBlk
->MpduHeaderLen
+ pTxBlk
->HdrPadLen
;
160 /* Build our URB for USBD */
161 DMAHdrLen
= TXWI_SIZE
+ hwHdrLen
;
162 USBDMApktLen
= DMAHdrLen
+ pTxBlk
->SrcBufLen
;
163 padding
= (4 - (USBDMApktLen
% 4)) & 0x03; /* round up to 4 byte alignment */
164 USBDMApktLen
+= padding
;
166 pTxBlk
->Priv
+= (TXINFO_SIZE
+ USBDMApktLen
);
168 /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload */
169 RTMPWriteTxInfo(pAd
, pTxInfo
, (u16
)(USBDMApktLen
), FALSE
, FIFO_EDCA
,
170 FALSE
/*NextValid */ , FALSE
);
172 if (fragNum
== pTxBlk
->TotalFragNum
) {
173 pTxInfo
->USBDMATxburst
= 0;
174 if ((pHTTXContext
->CurWritePosition
+ pTxBlk
->Priv
+ 3906) >
176 pTxInfo
->SwUseLastRound
= 1;
180 pTxInfo
->USBDMATxburst
= 1;
183 NdisMoveMemory(pWirelessPacket
, pTxBlk
->HeaderBuf
,
184 TXINFO_SIZE
+ TXWI_SIZE
+ hwHdrLen
);
185 pWirelessPacket
+= (TXINFO_SIZE
+ TXWI_SIZE
+ hwHdrLen
);
186 pHTTXContext
->CurWriteRealPos
+= (TXINFO_SIZE
+ TXWI_SIZE
+ hwHdrLen
);
188 RTMP_IRQ_UNLOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
190 NdisMoveMemory(pWirelessPacket
, pTxBlk
->pSrcBufData
, pTxBlk
->SrcBufLen
);
192 /* Zero the last padding. */
193 pWirelessPacket
+= pTxBlk
->SrcBufLen
;
194 NdisZeroMemory(pWirelessPacket
, padding
+ 8);
196 if (fragNum
== pTxBlk
->TotalFragNum
) {
197 RTMP_IRQ_LOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
199 /* Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame. */
200 pHTTXContext
->CurWritePosition
+= pTxBlk
->Priv
;
201 if (TxQLastRound
== TRUE
)
202 pHTTXContext
->CurWritePosition
= 8;
203 pHTTXContext
->CurWriteRealPos
= pHTTXContext
->CurWritePosition
;
205 /* Finally, set bCurWriting as FALSE */
206 pHTTXContext
->bCurWriting
= FALSE
;
208 RTMP_IRQ_UNLOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
210 /* succeed and release the skb buffer */
211 RELEASE_NDIS_PACKET(pAd
, pTxBlk
->pPacket
, NDIS_STATUS_SUCCESS
);
218 u16
RtmpUSB_WriteSingleTxResource(struct rt_rtmp_adapter
*pAd
,
219 struct rt_tx_blk
*pTxBlk
,
223 struct rt_ht_tx_context
*pHTTXContext
;
226 struct rt_txinfo
*pTxInfo
;
227 struct rt_txwi
*pTxWI
;
230 unsigned long IrqFlags
;
232 u32 USBDMApktLen
= 0, DMAHdrLen
, padding
;
233 BOOLEAN bTxQLastRound
= FALSE
;
235 /* For USB, didn't need PCI_MAP_SINGLE() */
236 /*SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); */
239 /* get Tx Ring Resource & Dma Buffer address */
241 QueIdx
= pTxBlk
->QueIdx
;
243 RTMP_IRQ_LOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
244 pHTTXContext
= &pAd
->TxContext
[QueIdx
];
245 fillOffset
= pHTTXContext
->CurWritePosition
;
247 /* Check ring full. */
248 Status
= RtmpUSBCanDoWrite(pAd
, QueIdx
, pHTTXContext
);
249 if (Status
== NDIS_STATUS_SUCCESS
) {
250 pHTTXContext
->bCurWriting
= TRUE
;
252 pTxInfo
= (struct rt_txinfo
*)(&pTxBlk
->HeaderBuf
[0]);
253 pTxWI
= (struct rt_txwi
*) (&pTxBlk
->HeaderBuf
[TXINFO_SIZE
]);
255 /* Reserve space for 8 bytes padding. */
256 if ((pHTTXContext
->ENextBulkOutPosition
==
257 pHTTXContext
->CurWritePosition
)) {
258 pHTTXContext
->ENextBulkOutPosition
+= 8;
259 pHTTXContext
->CurWritePosition
+= 8;
262 pHTTXContext
->CurWriteRealPos
= pHTTXContext
->CurWritePosition
;
265 &pHTTXContext
->TransferBuffer
->field
.
266 WirelessPacket
[fillOffset
];
268 /* copy TXWI + WLAN Header + LLC into DMA Header Buffer */
269 /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
270 hwHdrLen
= pTxBlk
->MpduHeaderLen
+ pTxBlk
->HdrPadLen
;
272 /* Build our URB for USBD */
273 DMAHdrLen
= TXWI_SIZE
+ hwHdrLen
;
274 USBDMApktLen
= DMAHdrLen
+ pTxBlk
->SrcBufLen
;
275 padding
= (4 - (USBDMApktLen
% 4)) & 0x03; /* round up to 4 byte alignment */
276 USBDMApktLen
+= padding
;
278 pTxBlk
->Priv
= (TXINFO_SIZE
+ USBDMApktLen
);
280 /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload */
281 RTMPWriteTxInfo(pAd
, pTxInfo
, (u16
)(USBDMApktLen
), FALSE
,
282 FIFO_EDCA
, FALSE
/*NextValid */ , FALSE
);
284 if ((pHTTXContext
->CurWritePosition
+ 3906 + pTxBlk
->Priv
) >
286 pTxInfo
->SwUseLastRound
= 1;
287 bTxQLastRound
= TRUE
;
289 NdisMoveMemory(pWirelessPacket
, pTxBlk
->HeaderBuf
,
290 TXINFO_SIZE
+ TXWI_SIZE
+ hwHdrLen
);
291 pWirelessPacket
+= (TXINFO_SIZE
+ TXWI_SIZE
+ hwHdrLen
);
293 /* We unlock it here to prevent the first 8 bytes maybe over-writed issue. */
294 /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext. */
295 /* 2. An interrupt break our routine and handle bulk-out complete. */
296 /* 3. In the bulk-out compllete, it need to do another bulk-out, */
297 /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, */
298 /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. */
299 /* 4. Interrupt complete. */
300 /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. */
301 /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. */
302 /* and the packet will wrong. */
303 pHTTXContext
->CurWriteRealPos
+=
304 (TXINFO_SIZE
+ TXWI_SIZE
+ hwHdrLen
);
305 RTMP_IRQ_UNLOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
307 NdisMoveMemory(pWirelessPacket
, pTxBlk
->pSrcBufData
,
309 pWirelessPacket
+= pTxBlk
->SrcBufLen
;
310 NdisZeroMemory(pWirelessPacket
, padding
+ 8);
312 RTMP_IRQ_LOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
314 pHTTXContext
->CurWritePosition
+= pTxBlk
->Priv
;
316 pHTTXContext
->CurWritePosition
= 8;
317 pHTTXContext
->CurWriteRealPos
= pHTTXContext
->CurWritePosition
;
319 pHTTXContext
->bCurWriting
= FALSE
;
322 RTMP_IRQ_UNLOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
324 /* succeed and release the skb buffer */
325 RELEASE_NDIS_PACKET(pAd
, pTxBlk
->pPacket
, NDIS_STATUS_SUCCESS
);
331 u16
RtmpUSB_WriteMultiTxResource(struct rt_rtmp_adapter
*pAd
,
332 struct rt_tx_blk
*pTxBlk
,
333 u8 frameNum
, u16
* FreeNumber
)
335 struct rt_ht_tx_context
*pHTTXContext
;
336 u16 hwHdrLen
; /* The hwHdrLen consist of 802.11 header length plus the header padding length. */
338 struct rt_txinfo
*pTxInfo
;
339 struct rt_txwi
*pTxWI
;
340 u8
*pWirelessPacket
= NULL
;
343 unsigned long IrqFlags
;
344 /*u32 USBDMApktLen = 0, DMAHdrLen, padding; */
347 /* get Tx Ring Resource & Dma Buffer address */
349 QueIdx
= pTxBlk
->QueIdx
;
350 pHTTXContext
= &pAd
->TxContext
[QueIdx
];
352 RTMP_IRQ_LOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
355 /* Check if we have enough space for this bulk-out batch. */
356 Status
= RtmpUSBCanDoWrite(pAd
, QueIdx
, pHTTXContext
);
357 if (Status
== NDIS_STATUS_SUCCESS
) {
358 pHTTXContext
->bCurWriting
= TRUE
;
360 pTxInfo
= (struct rt_txinfo
*)(&pTxBlk
->HeaderBuf
[0]);
361 pTxWI
= (struct rt_txwi
*) (&pTxBlk
->HeaderBuf
[TXINFO_SIZE
]);
363 /* Reserve space for 8 bytes padding. */
364 if ((pHTTXContext
->ENextBulkOutPosition
==
365 pHTTXContext
->CurWritePosition
)) {
367 pHTTXContext
->CurWritePosition
+= 8;
368 pHTTXContext
->ENextBulkOutPosition
+= 8;
370 fillOffset
= pHTTXContext
->CurWritePosition
;
371 pHTTXContext
->CurWriteRealPos
=
372 pHTTXContext
->CurWritePosition
;
375 &pHTTXContext
->TransferBuffer
->field
.
376 WirelessPacket
[fillOffset
];
379 /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */
381 if (pTxBlk
->TxFrameType
== TX_AMSDU_FRAME
)
382 /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */
384 pTxBlk
->MpduHeaderLen
-
385 LENGTH_AMSDU_SUBFRAMEHEAD
+
387 LENGTH_AMSDU_SUBFRAMEHEAD
;
388 else if (pTxBlk
->TxFrameType
== TX_RALINK_FRAME
)
389 /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; */
391 pTxBlk
->MpduHeaderLen
-
392 LENGTH_ARALINK_HEADER_FIELD
+
394 LENGTH_ARALINK_HEADER_FIELD
;
396 /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
398 pTxBlk
->MpduHeaderLen
+ pTxBlk
->HdrPadLen
;
400 /* Update the pTxBlk->Priv. */
401 pTxBlk
->Priv
= TXINFO_SIZE
+ TXWI_SIZE
+ hwHdrLen
;
403 /* pTxInfo->USBDMApktLen now just a temp value and will to correct latter. */
404 RTMPWriteTxInfo(pAd
, pTxInfo
, (u16
)(pTxBlk
->Priv
),
405 FALSE
, FIFO_EDCA
, FALSE
/*NextValid */ ,
409 NdisMoveMemory(pWirelessPacket
, pTxBlk
->HeaderBuf
,
411 pHTTXContext
->CurWriteRealPos
+= pTxBlk
->Priv
;
412 pWirelessPacket
+= pTxBlk
->Priv
;
414 } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */
417 ((pHTTXContext
->bCurWriting
==
418 TRUE
) ? NDIS_STATUS_SUCCESS
: NDIS_STATUS_FAILURE
);
419 if (Status
== NDIS_STATUS_SUCCESS
) {
421 (pHTTXContext
->CurWritePosition
+ pTxBlk
->Priv
);
423 &pHTTXContext
->TransferBuffer
->field
.
424 WirelessPacket
[fillOffset
];
426 /*hwHdrLen = pTxBlk->MpduHeaderLen; */
427 NdisMoveMemory(pWirelessPacket
, pTxBlk
->HeaderBuf
,
428 pTxBlk
->MpduHeaderLen
);
429 pWirelessPacket
+= (pTxBlk
->MpduHeaderLen
);
430 pTxBlk
->Priv
+= pTxBlk
->MpduHeaderLen
;
431 } else { /* It should not happened now unless we are going to shutdown. */
432 DBGPRINT(RT_DEBUG_ERROR
,
433 ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n"));
434 Status
= NDIS_STATUS_FAILURE
;
438 /* We unlock it here to prevent the first 8 bytes maybe over-write issue. */
439 /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext. */
440 /* 2. An interrupt break our routine and handle bulk-out complete. */
441 /* 3. In the bulk-out compllete, it need to do another bulk-out, */
442 /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, */
443 /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. */
444 /* 4. Interrupt complete. */
445 /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. */
446 /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. */
447 /* and the packet will wrong. */
448 RTMP_IRQ_UNLOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
450 if (Status
!= NDIS_STATUS_SUCCESS
) {
451 DBGPRINT(RT_DEBUG_ERROR
,
452 ("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n",
453 pHTTXContext
->CurWritePosition
,
454 pHTTXContext
->NextBulkOutPosition
));
457 /* Copy the frame content into DMA buffer and update the pTxBlk->Priv */
458 NdisMoveMemory(pWirelessPacket
, pTxBlk
->pSrcBufData
, pTxBlk
->SrcBufLen
);
459 pWirelessPacket
+= pTxBlk
->SrcBufLen
;
460 pTxBlk
->Priv
+= pTxBlk
->SrcBufLen
;
463 /* Release the skb buffer here */
464 RELEASE_NDIS_PACKET(pAd
, pTxBlk
->pPacket
, NDIS_STATUS_SUCCESS
);
470 void RtmpUSB_FinalWriteTxResource(struct rt_rtmp_adapter
*pAd
,
471 struct rt_tx_blk
*pTxBlk
,
472 u16 totalMPDUSize
, u16 TxIdx
)
475 struct rt_ht_tx_context
*pHTTXContext
;
477 struct rt_txinfo
*pTxInfo
;
478 struct rt_txwi
*pTxWI
;
479 u32 USBDMApktLen
, padding
;
480 unsigned long IrqFlags
;
483 QueIdx
= pTxBlk
->QueIdx
;
484 pHTTXContext
= &pAd
->TxContext
[QueIdx
];
486 RTMP_IRQ_LOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
488 if (pHTTXContext
->bCurWriting
== TRUE
) {
489 fillOffset
= pHTTXContext
->CurWritePosition
;
490 if (((pHTTXContext
->ENextBulkOutPosition
==
491 pHTTXContext
->CurWritePosition
)
492 || ((pHTTXContext
->ENextBulkOutPosition
- 8) ==
493 pHTTXContext
->CurWritePosition
))
494 && (pHTTXContext
->bCopySavePad
== TRUE
))
495 pWirelessPacket
= (u8
*)(&pHTTXContext
->SavedPad
[0]);
498 (u8
*)(&pHTTXContext
->TransferBuffer
->field
.
499 WirelessPacket
[fillOffset
]);
502 /* Update TxInfo->USBDMApktLen , */
503 /* the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding */
505 pTxInfo
= (struct rt_txinfo
*)(pWirelessPacket
);
507 /* Calculate the bulk-out padding */
508 USBDMApktLen
= pTxBlk
->Priv
- TXINFO_SIZE
;
509 padding
= (4 - (USBDMApktLen
% 4)) & 0x03; /* round up to 4 byte alignment */
510 USBDMApktLen
+= padding
;
512 pTxInfo
->USBDMATxPktLen
= USBDMApktLen
;
515 /* Update TXWI->MPDUtotalByteCount , */
516 /* the length = 802.11 header + payload_of_all_batch_frames */
517 pTxWI
= (struct rt_txwi
*) (pWirelessPacket
+ TXINFO_SIZE
);
518 pTxWI
->MPDUtotalByteCount
= totalMPDUSize
;
521 /* Update the pHTTXContext->CurWritePosition */
523 pHTTXContext
->CurWritePosition
+= (TXINFO_SIZE
+ USBDMApktLen
);
524 if ((pHTTXContext
->CurWritePosition
+ 3906) > MAX_TXBULK_LIMIT
) { /* Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame. */
525 pHTTXContext
->CurWritePosition
= 8;
526 pTxInfo
->SwUseLastRound
= 1;
528 pHTTXContext
->CurWriteRealPos
= pHTTXContext
->CurWritePosition
;
531 /* Zero the last padding. */
534 (&pHTTXContext
->TransferBuffer
->field
.
535 WirelessPacket
[fillOffset
+ pTxBlk
->Priv
]);
536 NdisZeroMemory(pWirelessPacket
, padding
+ 8);
538 /* Finally, set bCurWriting as FALSE */
539 pHTTXContext
->bCurWriting
= FALSE
;
541 } else { /* It should not happened now unless we are going to shutdown. */
542 DBGPRINT(RT_DEBUG_ERROR
,
543 ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n"));
546 RTMP_IRQ_UNLOCK(&pAd
->TxContextQueueLock
[QueIdx
], IrqFlags
);
550 void RtmpUSBDataLastTxIdx(struct rt_rtmp_adapter
*pAd
,
551 u8 QueIdx
, u16 TxIdx
)
553 /* DO nothing for USB. */
557 When can do bulk-out:
558 1. TxSwFreeIdx < TX_RING_SIZE;
559 It means has at least one Ring entity is ready for bulk-out, kick it out.
560 2. If TxSwFreeIdx == TX_RING_SIZE
561 Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out.
564 void RtmpUSBDataKickOut(struct rt_rtmp_adapter
*pAd
,
565 struct rt_tx_blk
*pTxBlk
, u8 QueIdx
)
567 RTUSB_SET_BULK_FLAG(pAd
, (fRTUSB_BULK_OUT_DATA_NORMAL
<< QueIdx
));
568 RTUSBKickBulkOut(pAd
);
573 Must be run in Interrupt context
574 This function handle RT2870 specific TxDesc and cpu index update and kick the packet out.
576 int RtmpUSBMgmtKickOut(struct rt_rtmp_adapter
*pAd
,
579 u8
*pSrcBufVA
, u32 SrcBufLen
)
581 struct rt_txinfo
*pTxInfo
;
582 unsigned long BulkOutSize
;
585 unsigned long SwIdx
= pAd
->MgmtRing
.TxCpuIdx
;
586 struct rt_tx_context
*pMLMEContext
=
587 (struct rt_tx_context
*)pAd
->MgmtRing
.Cell
[SwIdx
].AllocVa
;
588 unsigned long IrqFlags
;
590 pTxInfo
= (struct rt_txinfo
*)(pSrcBufVA
);
592 /* Build our URB for USBD */
593 BulkOutSize
= SrcBufLen
;
594 BulkOutSize
= (BulkOutSize
+ 3) & (~3);
595 RTMPWriteTxInfo(pAd
, pTxInfo
, (u16
)(BulkOutSize
- TXINFO_SIZE
),
596 TRUE
, EpToQueue
[MGMTPIPEIDX
], FALSE
, FALSE
);
598 BulkOutSize
+= 4; /* Always add 4 extra bytes at every packet. */
600 /* If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again. */
601 if ((BulkOutSize
% pAd
->BulkOutMaxPacketSize
) == 0)
604 padLen
= BulkOutSize
- SrcBufLen
;
605 ASSERT((padLen
<= RTMP_PKT_TAIL_PADDING
));
607 /* Now memzero all extra padding bytes. */
608 pDest
= (u8
*)(pSrcBufVA
+ SrcBufLen
);
609 skb_put(GET_OS_PKT_TYPE(pPacket
), padLen
);
610 NdisZeroMemory(pDest
, padLen
);
612 RTMP_IRQ_LOCK(&pAd
->MLMEBulkOutLock
, IrqFlags
);
614 pAd
->MgmtRing
.Cell
[pAd
->MgmtRing
.TxCpuIdx
].pNdisPacket
= pPacket
;
615 pMLMEContext
->TransferBuffer
=
616 (struct rt_tx_buffer
*)(GET_OS_PKT_DATAPTR(pPacket
));
618 /* Length in TxInfo should be 8 less than bulkout size. */
619 pMLMEContext
->BulkOutSize
= BulkOutSize
;
620 pMLMEContext
->InUse
= TRUE
;
621 pMLMEContext
->bWaitingBulkOut
= TRUE
;
624 /*hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize)); */
626 /*pAd->RalinkCounters.KickTxCount++; */
627 /*pAd->RalinkCounters.OneSecTxDoneCount++; */
629 /*if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE) */
630 /* needKickOut = TRUE; */
632 /* Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX */
633 pAd
->MgmtRing
.TxSwFreeIdx
--;
634 INC_RING_INDEX(pAd
->MgmtRing
.TxCpuIdx
, MGMT_RING_SIZE
);
636 RTMP_IRQ_UNLOCK(&pAd
->MLMEBulkOutLock
, IrqFlags
);
638 RTUSB_SET_BULK_FLAG(pAd
, fRTUSB_BULK_OUT_MLME
);
639 /*if (needKickOut) */
640 RTUSBKickBulkOut(pAd
);
645 void RtmpUSBNullFrameKickOut(struct rt_rtmp_adapter
*pAd
,
647 u8
* pNullFrame
, u32 frameLen
)
649 if (pAd
->NullContext
.InUse
== FALSE
) {
650 struct rt_tx_context
*pNullContext
;
651 struct rt_txinfo
*pTxInfo
;
652 struct rt_txwi
* pTxWI
;
655 pNullContext
= &(pAd
->NullContext
);
657 /* Set the in use bit */
658 pNullContext
->InUse
= TRUE
;
660 (u8
*)& pNullContext
->TransferBuffer
->field
.
663 RTMPZeroMemory(&pWirelessPkt
[0], 100);
664 pTxInfo
= (struct rt_txinfo
*)& pWirelessPkt
[0];
665 RTMPWriteTxInfo(pAd
, pTxInfo
,
666 (u16
)(sizeof(struct rt_header_802_11
) + TXWI_SIZE
),
667 TRUE
, EpToQueue
[MGMTPIPEIDX
], FALSE
, FALSE
);
668 pTxInfo
->QSEL
= FIFO_EDCA
;
669 pTxWI
= (struct rt_txwi
*) & pWirelessPkt
[TXINFO_SIZE
];
670 RTMPWriteTxWI(pAd
, pTxWI
, FALSE
, FALSE
, FALSE
, FALSE
, TRUE
,
671 FALSE
, 0, BSSID_WCID
, (sizeof(struct rt_header_802_11
)), 0,
672 0, (u8
)pAd
->CommonCfg
.MlmeTransmit
.field
.MCS
,
673 IFS_HTTXOP
, FALSE
, &pAd
->CommonCfg
.MlmeTransmit
);
675 RTMPMoveMemory(&pWirelessPkt
[TXWI_SIZE
+ TXINFO_SIZE
],
676 &pAd
->NullFrame
, sizeof(struct rt_header_802_11
));
677 pAd
->NullContext
.BulkOutSize
=
678 TXINFO_SIZE
+ TXWI_SIZE
+ sizeof(pAd
->NullFrame
) + 4;
680 /* Fill out frame length information for global Bulk out arbitor */
681 /*pNullContext->BulkOutSize = TransferBufferLength; */
682 DBGPRINT(RT_DEBUG_TRACE
,
683 ("SYNC - send NULL Frame @%d Mbps...\n",
684 RateIdToMbps
[pAd
->CommonCfg
.TxRate
]));
685 RTUSB_SET_BULK_FLAG(pAd
, fRTUSB_BULK_OUT_DATA_NULL
);
688 RTUSBKickBulkOut(pAd
);
694 ========================================================================
696 Get a received packet.
699 pAd device control block
700 pSaveRxD receive descriptor information
701 *pbReschedule need reschedule flag
702 *pRxPending pending received packet flag
708 ========================================================================
710 void *GetPacketFromRxRing(struct rt_rtmp_adapter
*pAd
,
711 OUT PRT28XX_RXD_STRUC pSaveRxD
,
712 OUT BOOLEAN
* pbReschedule
,
715 struct rt_rx_context
*pRxContext
;
718 unsigned long ThisFrameLen
;
719 unsigned long RxBufferLength
;
720 struct rt_rxwi
* pRxWI
;
722 pRxContext
= &pAd
->RxContext
[pAd
->NextRxBulkInReadIndex
];
723 if ((pRxContext
->Readable
== FALSE
) || (pRxContext
->InUse
== TRUE
))
726 RxBufferLength
= pRxContext
->BulkInOffset
- pAd
->ReadPosition
;
728 (RT2870_RXDMALEN_FIELD_SIZE
+ sizeof(struct rt_rxwi
) +
729 sizeof(struct rt_rxinfo
))) {
733 pData
= &pRxContext
->TransferBuffer
[pAd
->ReadPosition
]; /* 4KB */
734 /* The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding) */
735 ThisFrameLen
= *pData
+ (*(pData
+ 1) << 8);
736 if (ThisFrameLen
== 0) {
737 DBGPRINT(RT_DEBUG_TRACE
,
738 ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n",
739 pAd
->NextRxBulkInReadIndex
, ThisFrameLen
,
740 pRxContext
->BulkInOffset
));
743 if ((ThisFrameLen
& 0x3) != 0) {
744 DBGPRINT(RT_DEBUG_ERROR
,
745 ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n",
746 pAd
->NextRxBulkInReadIndex
, ThisFrameLen
,
747 pRxContext
->BulkInOffset
));
751 if ((ThisFrameLen
+ 8) > RxBufferLength
) /* 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxinfo)) */
753 DBGPRINT(RT_DEBUG_TRACE
,
754 ("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n",
755 pAd
->NextRxBulkInReadIndex
, ThisFrameLen
,
756 pRxContext
->BulkInOffset
, RxBufferLength
,
759 /* error frame. finish this loop */
762 /* skip USB frame length field */
763 pData
+= RT2870_RXDMALEN_FIELD_SIZE
;
764 pRxWI
= (struct rt_rxwi
*) pData
;
765 if (pRxWI
->MPDUtotalByteCount
> ThisFrameLen
) {
766 DBGPRINT(RT_DEBUG_ERROR
,
767 ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n",
768 __FUNCTION__
, pRxWI
->MPDUtotalByteCount
,
772 /* allocate a rx packet */
773 pSkb
= dev_alloc_skb(ThisFrameLen
);
775 DBGPRINT(RT_DEBUG_ERROR
,
776 ("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n",
780 /* copy the rx packet */
781 memcpy(skb_put(pSkb
, ThisFrameLen
), pData
, ThisFrameLen
);
782 RTPKT_TO_OSPKT(pSkb
)->dev
= get_netdev_from_bssid(pAd
, BSS0
);
783 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pSkb
), PKTSRC_NDIS
);
786 *pSaveRxD
= *(struct rt_rxinfo
*) (pData
+ ThisFrameLen
);
788 /* update next packet read position. */
789 pAd
->ReadPosition
+= (ThisFrameLen
+ RT2870_RXDMALEN_FIELD_SIZE
+ RXINFO_SIZE
); /* 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxinfo)) */
799 ========================================================================
802 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
805 pRxD Pointer to the Rx descriptor
808 NDIS_STATUS_SUCCESS No err
809 NDIS_STATUS_FAILURE Error
813 ========================================================================
815 int RTMPCheckRxError(struct rt_rtmp_adapter
*pAd
,
816 struct rt_header_802_11
* pHeader
,
817 struct rt_rxwi
* pRxWI
, IN PRT28XX_RXD_STRUC pRxINFO
)
819 struct rt_cipher_key
*pWpaKey
;
822 if (pAd
->bPromiscuous
== TRUE
)
823 return (NDIS_STATUS_SUCCESS
);
825 return (NDIS_STATUS_FAILURE
);
827 /* Phy errors & CRC errors */
829 /* Check RSSI for Noise Hist statistic collection. */
830 dBm
= (int)(pRxWI
->RSSI0
) - pAd
->BbpRssiToDbmDelta
;
832 pAd
->StaCfg
.RPIDensity
[0] += 1;
834 pAd
->StaCfg
.RPIDensity
[1] += 1;
836 pAd
->StaCfg
.RPIDensity
[2] += 1;
838 pAd
->StaCfg
.RPIDensity
[3] += 1;
840 pAd
->StaCfg
.RPIDensity
[4] += 1;
842 pAd
->StaCfg
.RPIDensity
[5] += 1;
844 pAd
->StaCfg
.RPIDensity
[6] += 1;
846 pAd
->StaCfg
.RPIDensity
[7] += 1;
848 return (NDIS_STATUS_FAILURE
);
850 /* Add Rx size to channel load counter, we should ignore error counts */
851 pAd
->StaCfg
.CLBusyBytes
+= (pRxWI
->MPDUtotalByteCount
+ 14);
853 /* Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics */
854 if (pHeader
->FC
.ToDs
) {
855 DBGPRINT_RAW(RT_DEBUG_ERROR
, ("Err;FC.ToDs\n"));
856 return NDIS_STATUS_FAILURE
;
858 /* Paul 04-03 for OFDM Rx length issue */
859 if (pRxWI
->MPDUtotalByteCount
> MAX_AGGREGATION_SIZE
) {
860 DBGPRINT_RAW(RT_DEBUG_ERROR
, ("received packet too long\n"));
861 return NDIS_STATUS_FAILURE
;
863 /* Drop not U2M frames, cant's drop here because we will drop beacon in this case */
864 /* I am kind of doubting the U2M bit operation */
865 /* if (pRxD->U2M == 0) */
866 /* return(NDIS_STATUS_FAILURE); */
868 /* drop decyption fail frame */
869 if (pRxINFO
->Decrypted
&& pRxINFO
->CipherErr
) {
871 if (((pRxINFO
->CipherErr
& 1) == 1)
872 && pAd
->CommonCfg
.bWirelessEvent
&& INFRA_ON(pAd
))
873 RTMPSendWirelessEvent(pAd
, IW_ICV_ERROR_EVENT_FLAG
,
874 pAd
->MacTab
.Content
[BSSID_WCID
].
877 if (((pRxINFO
->CipherErr
& 2) == 2)
878 && pAd
->CommonCfg
.bWirelessEvent
&& INFRA_ON(pAd
))
879 RTMPSendWirelessEvent(pAd
, IW_MIC_ERROR_EVENT_FLAG
,
880 pAd
->MacTab
.Content
[BSSID_WCID
].
885 if ((pRxINFO
->CipherErr
== 2) && pRxINFO
->MyBss
) {
886 pWpaKey
= &pAd
->SharedKey
[BSS0
][pRxWI
->KeyIndex
];
887 RTMPReportMicError(pAd
, pWpaKey
);
888 DBGPRINT_RAW(RT_DEBUG_ERROR
, ("Rx MIC Value error\n"));
891 if (pRxINFO
->Decrypted
&&
892 (pAd
->SharedKey
[BSS0
][pRxWI
->KeyIndex
].CipherAlg
==
894 && (pHeader
->Sequence
== pAd
->FragFrame
.Sequence
)) {
896 /* Acceptable since the First FragFrame no CipherErr problem. */
898 return (NDIS_STATUS_SUCCESS
);
901 return (NDIS_STATUS_FAILURE
);
904 return (NDIS_STATUS_SUCCESS
);
907 void RtmpUsbStaAsicForceWakeupTimeout(void *SystemSpecific1
,
908 void *FunctionContext
,
909 void *SystemSpecific2
,
910 void *SystemSpecific3
)
912 struct rt_rtmp_adapter
*pAd
= (struct rt_rtmp_adapter
*)FunctionContext
;
914 if (pAd
&& pAd
->Mlme
.AutoWakeupTimerRunning
) {
915 AsicSendCommandToMcu(pAd
, 0x31, 0xff, 0x00, 0x02);
917 OPSTATUS_CLEAR_FLAG(pAd
, fOP_STATUS_DOZE
);
918 pAd
->Mlme
.AutoWakeupTimerRunning
= FALSE
;
922 void RT28xxUsbStaAsicForceWakeup(struct rt_rtmp_adapter
*pAd
, IN BOOLEAN bFromTx
)
926 if (pAd
->Mlme
.AutoWakeupTimerRunning
)
927 RTMPCancelTimer(&pAd
->Mlme
.AutoWakeupTimer
, &Canceled
);
929 AsicSendCommandToMcu(pAd
, 0x31, 0xff, 0x00, 0x02);
931 OPSTATUS_CLEAR_FLAG(pAd
, fOP_STATUS_DOZE
);
934 void RT28xxUsbStaAsicSleepThenAutoWakeup(struct rt_rtmp_adapter
*pAd
,
935 u16 TbttNumToNextWakeUp
)
938 /* we have decided to SLEEP, so at least do it for a BEACON period. */
939 if (TbttNumToNextWakeUp
== 0)
940 TbttNumToNextWakeUp
= 1;
942 RTMPSetTimer(&pAd
->Mlme
.AutoWakeupTimer
, AUTO_WAKEUP_TIMEOUT
);
943 pAd
->Mlme
.AutoWakeupTimerRunning
= TRUE
;
945 AsicSendCommandToMcu(pAd
, 0x30, 0xff, 0xff, 0x02); /* send POWER-SAVE command to MCU. Timeout 40us. */
947 OPSTATUS_SET_FLAG(pAd
, fOP_STATUS_DOZE
);
951 #endif /* RTMP_MAC_USB // */