1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26 */
27 /*
28 All functions in this file must be USB-depended, or you should out your function
29 in other files.
30
31 */
32 #include "../rt_config.h"
33
34
35 /*
36 We can do copy the frame into pTxContext when match following conditions.
37 =>
38 =>
39 =>
40 */
41 static inline NDIS_STATUS RtmpUSBCanDoWrite(
42 IN RTMP_ADAPTER *pAd,
43 IN UCHAR QueIdx,
44 IN HT_TX_CONTEXT *pHTTXContext)
45 {
46 NDIS_STATUS canWrite = NDIS_STATUS_RESOURCES;
47
48 if (((pHTTXContext->CurWritePosition) < pHTTXContext->NextBulkOutPosition) && (pHTTXContext->CurWritePosition + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)
49 {
50 DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c1!\n"));
51 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
52 }
53 else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < LOCAL_TXBUF_SIZE))
54 {
55 DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c2!\n"));
56 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
57 }
58 else if (pHTTXContext->bCurWriting == TRUE)
59 {
60 DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c3!\n"));
61 }
62 else
63 {
64 canWrite = NDIS_STATUS_SUCCESS;
65 }
66
67
68 return canWrite;
69 }
70
71
72 USHORT RtmpUSB_WriteSubTxResource(
73 IN PRTMP_ADAPTER pAd,
74 IN TX_BLK *pTxBlk,
75 IN BOOLEAN bIsLast,
76 OUT USHORT *FreeNumber)
77 {
78
79 // Dummy function. Should be removed in the future.
80 return 0;
81
82 }
83
84 USHORT RtmpUSB_WriteFragTxResource(
85 IN PRTMP_ADAPTER pAd,
86 IN TX_BLK *pTxBlk,
87 IN UCHAR fragNum,
88 OUT USHORT *FreeNumber)
89 {
90 HT_TX_CONTEXT *pHTTXContext;
91 USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length.
92 UINT32 fillOffset;
93 TXINFO_STRUC *pTxInfo;
94 TXWI_STRUC *pTxWI;
95 PUCHAR pWirelessPacket = NULL;
96 UCHAR QueIdx;
97 NDIS_STATUS Status;
98 unsigned long IrqFlags;
99 UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
100 BOOLEAN TxQLastRound = FALSE;
101
102 //
103 // get Tx Ring Resource & Dma Buffer address
104 //
105 QueIdx = pTxBlk->QueIdx;
106 pHTTXContext = &pAd->TxContext[QueIdx];
107
108 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
109
110 pHTTXContext = &pAd->TxContext[QueIdx];
111 fillOffset = pHTTXContext->CurWritePosition;
112
113 if(fragNum == 0)
114 {
115 // Check if we have enough space for this bulk-out batch.
116 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
117 if (Status == NDIS_STATUS_SUCCESS)
118 {
119 pHTTXContext->bCurWriting = TRUE;
120
121 // Reserve space for 8 bytes padding.
122 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
123 {
124 pHTTXContext->ENextBulkOutPosition += 8;
125 pHTTXContext->CurWritePosition += 8;
126 fillOffset += 8;
127 }
128 pTxBlk->Priv = 0;
129 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
130 }
131 else
132 {
133 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
134
135 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
136 return(Status);
137 }
138 }
139 else
140 {
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)
144 {
145 fillOffset += pTxBlk->Priv;
146 }
147 else
148 {
149 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
150
151 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
152 return(Status);
153 }
154 }
155
156 NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE);
157 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
158 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
159
160 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
161
162 // copy TXWI + WLAN Header + LLC into DMA Header Buffer
163 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
164 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
165
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;
171
172 pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen);
173
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);
176
177 if (fragNum == pTxBlk->TotalFragNum)
178 {
179 pTxInfo->USBDMATxburst = 0;
180 if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT)
181 {
182 pTxInfo->SwUseLastRound = 1;
183 TxQLastRound = TRUE;
184 }
185 }
186 else
187 {
188 pTxInfo->USBDMATxburst = 1;
189 }
190
191 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
192 pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
193 pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
194
195 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
196
197 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
198
199 // Zero the last padding.
200 pWirelessPacket += pTxBlk->SrcBufLen;
201 NdisZeroMemory(pWirelessPacket, padding + 8);
202
203 if (fragNum == pTxBlk->TotalFragNum)
204 {
205 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
206
207 // Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame.
208 pHTTXContext->CurWritePosition += pTxBlk->Priv;
209 if (TxQLastRound == TRUE)
210 pHTTXContext->CurWritePosition = 8;
211 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
212
213
214 // Finally, set bCurWriting as FALSE
215 pHTTXContext->bCurWriting = FALSE;
216
217 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
218
219 // succeed and release the skb buffer
220 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
221 }
222
223
224 return(Status);
225
226 }
227
228
229 USHORT RtmpUSB_WriteSingleTxResource(
230 IN PRTMP_ADAPTER pAd,
231 IN TX_BLK *pTxBlk,
232 IN BOOLEAN bIsLast,
233 OUT USHORT *FreeNumber)
234 {
235 HT_TX_CONTEXT *pHTTXContext;
236 USHORT hwHdrLen;
237 UINT32 fillOffset;
238 TXINFO_STRUC *pTxInfo;
239 TXWI_STRUC *pTxWI;
240 PUCHAR pWirelessPacket;
241 UCHAR QueIdx;
242 unsigned long IrqFlags;
243 NDIS_STATUS Status;
244 UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
245 BOOLEAN bTxQLastRound = FALSE;
246
247 // For USB, didn't need PCI_MAP_SINGLE()
248 //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE);
249
250
251 //
252 // get Tx Ring Resource & Dma Buffer address
253 //
254 QueIdx = pTxBlk->QueIdx;
255
256 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
257 pHTTXContext = &pAd->TxContext[QueIdx];
258 fillOffset = pHTTXContext->CurWritePosition;
259
260
261
262 // Check ring full.
263 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
264 if(Status == NDIS_STATUS_SUCCESS)
265 {
266 pHTTXContext->bCurWriting = TRUE;
267
268 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
269 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
270
271 // Reserve space for 8 bytes padding.
272 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
273 {
274 pHTTXContext->ENextBulkOutPosition += 8;
275 pHTTXContext->CurWritePosition += 8;
276 fillOffset += 8;
277 }
278 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
279
280 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
281
282 // copy TXWI + WLAN Header + LLC into DMA Header Buffer
283 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
284 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
285
286 // Build our URB for USBD
287 DMAHdrLen = TXWI_SIZE + hwHdrLen;
288 USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen;
289 padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment
290 USBDMApktLen += padding;
291
292 pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen);
293
294 // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload
295 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
296 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE);
297
298 if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT)
299 {
300 pTxInfo->SwUseLastRound = 1;
301 bTxQLastRound = TRUE;
302 }
303 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
304 pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
305
306 // We unlock it here to prevent the first 8 bytes maybe over-writed issue.
307 // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext.
308 // 2. An interrupt break our routine and handle bulk-out complete.
309 // 3. In the bulk-out compllete, it need to do another bulk-out,
310 // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
311 // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
312 // 4. Interrupt complete.
313 // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
314 // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
315 // and the packet will wrong.
316 pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
317 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
318
319 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
320 pWirelessPacket += pTxBlk->SrcBufLen;
321 NdisZeroMemory(pWirelessPacket, padding + 8);
322
323 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
324
325 pHTTXContext->CurWritePosition += pTxBlk->Priv;
326 if (bTxQLastRound)
327 pHTTXContext->CurWritePosition = 8;
328 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
329
330 pHTTXContext->bCurWriting = FALSE;
331 }
332
333
334 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
335
336
337 // succeed and release the skb buffer
338 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
339
340 return(Status);
341
342 }
343
344
345 USHORT RtmpUSB_WriteMultiTxResource(
346 IN PRTMP_ADAPTER pAd,
347 IN TX_BLK *pTxBlk,
348 IN UCHAR frameNum,
349 OUT USHORT *FreeNumber)
350 {
351 HT_TX_CONTEXT *pHTTXContext;
352 USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length.
353 UINT32 fillOffset;
354 TXINFO_STRUC *pTxInfo;
355 TXWI_STRUC *pTxWI;
356 PUCHAR pWirelessPacket = NULL;
357 UCHAR QueIdx;
358 NDIS_STATUS Status;
359 unsigned long IrqFlags;
360 //UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
361
362 //
363 // get Tx Ring Resource & Dma Buffer address
364 //
365 QueIdx = pTxBlk->QueIdx;
366 pHTTXContext = &pAd->TxContext[QueIdx];
367
368 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
369
370 if(frameNum == 0)
371 {
372 // Check if we have enough space for this bulk-out batch.
373 Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
374 if (Status == NDIS_STATUS_SUCCESS)
375 {
376 pHTTXContext->bCurWriting = TRUE;
377
378 pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]);
379 pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
380
381
382 // Reserve space for 8 bytes padding.
383 if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
384 {
385
386 pHTTXContext->CurWritePosition += 8;
387 pHTTXContext->ENextBulkOutPosition += 8;
388 }
389 fillOffset = pHTTXContext->CurWritePosition;
390 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
391
392 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
393
394 //
395 // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
396 //
397 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
398 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
399 hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
400 else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
401 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
402 hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
403 else
404 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
405 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
406
407 // Update the pTxBlk->Priv.
408 pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
409
410 // pTxInfo->USBDMApktLen now just a temp value and will to correct latter.
411 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE);
412
413 // Copy it.
414 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv);
415 pHTTXContext->CurWriteRealPos += pTxBlk->Priv;
416 pWirelessPacket += pTxBlk->Priv;
417 }
418 }
419 else
420 { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.
421
422 Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
423 if (Status == NDIS_STATUS_SUCCESS)
424 {
425 fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv);
426 pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
427
428 //hwHdrLen = pTxBlk->MpduHeaderLen;
429 NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen);
430 pWirelessPacket += (pTxBlk->MpduHeaderLen);
431 pTxBlk->Priv += pTxBlk->MpduHeaderLen;
432 }
433 else
434 { // It should not happened now unless we are going to shutdown.
435 DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n"));
436 Status = NDIS_STATUS_FAILURE;
437 }
438 }
439
440
441 // We unlock it here to prevent the first 8 bytes maybe over-write issue.
442 // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext.
443 // 2. An interrupt break our routine and handle bulk-out complete.
444 // 3. In the bulk-out compllete, it need to do another bulk-out,
445 // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
446 // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
447 // 4. Interrupt complete.
448 // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
449 // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
450 // and the packet will wrong.
451 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
452
453 if (Status != NDIS_STATUS_SUCCESS)
454 {
455 DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
456 goto done;
457 }
458
459 // Copy the frame content into DMA buffer and update the pTxBlk->Priv
460 NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
461 pWirelessPacket += pTxBlk->SrcBufLen;
462 pTxBlk->Priv += pTxBlk->SrcBufLen;
463
464 done:
465 // Release the skb buffer here
466 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
467
468 return(Status);
469
470 }
471
472
473 VOID RtmpUSB_FinalWriteTxResource(
474 IN PRTMP_ADAPTER pAd,
475 IN TX_BLK *pTxBlk,
476 IN USHORT totalMPDUSize,
477 IN USHORT TxIdx)
478 {
479 UCHAR QueIdx;
480 HT_TX_CONTEXT *pHTTXContext;
481 UINT32 fillOffset;
482 TXINFO_STRUC *pTxInfo;
483 TXWI_STRUC *pTxWI;
484 UINT32 USBDMApktLen, padding;
485 unsigned long IrqFlags;
486 PUCHAR pWirelessPacket;
487
488 QueIdx = pTxBlk->QueIdx;
489 pHTTXContext = &pAd->TxContext[QueIdx];
490
491 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
492
493 if (pHTTXContext->bCurWriting == TRUE)
494 {
495 fillOffset = pHTTXContext->CurWritePosition;
496 if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition))
497 && (pHTTXContext->bCopySavePad == TRUE))
498 pWirelessPacket = (PUCHAR)(&pHTTXContext->SavedPad[0]);
499 else
500 pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]);
501
502 //
503 // Update TxInfo->USBDMApktLen ,
504 // the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding
505 //
506 pTxInfo = (PTXINFO_STRUC)(pWirelessPacket);
507
508 // Calculate the bulk-out padding
509 USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE;
510 padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment
511 USBDMApktLen += padding;
512
513 pTxInfo->USBDMATxPktLen = USBDMApktLen;
514
515 //
516 // Update TXWI->MPDUtotalByteCount ,
517 // the length = 802.11 header + payload_of_all_batch_frames
518 pTxWI= (PTXWI_STRUC)(pWirelessPacket + TXINFO_SIZE);
519 pTxWI->MPDUtotalByteCount = totalMPDUSize;
520
521 //
522 // Update the pHTTXContext->CurWritePosition
523 //
524 pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen);
525 if ((pHTTXContext->CurWritePosition + 3906)> MAX_TXBULK_LIMIT)
526 { // Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame.
527 pHTTXContext->CurWritePosition = 8;
528 pTxInfo->SwUseLastRound = 1;
529 }
530 pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
531
532
533 //
534 // Zero the last padding.
535 //
536 pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]);
537 NdisZeroMemory(pWirelessPacket, padding + 8);
538
539 // Finally, set bCurWriting as FALSE
540 pHTTXContext->bCurWriting = FALSE;
541
542 }
543 else
544 { // It should not happened now unless we are going to shutdown.
545 DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n"));
546 }
547
548 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
549
550 }
551
552
553 VOID RtmpUSBDataLastTxIdx(
554 IN PRTMP_ADAPTER pAd,
555 IN UCHAR QueIdx,
556 IN USHORT TxIdx)
557 {
558 // DO nothing for USB.
559 }
560
561
562 /*
563 When can do bulk-out:
564 1. TxSwFreeIdx < TX_RING_SIZE;
565 It means has at least one Ring entity is ready for bulk-out, kick it out.
566 2. If TxSwFreeIdx == TX_RING_SIZE
567 Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out.
568
569 */
570 VOID RtmpUSBDataKickOut(
571 IN PRTMP_ADAPTER pAd,
572 IN TX_BLK *pTxBlk,
573 IN UCHAR QueIdx)
574 {
575 RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
576 RTUSBKickBulkOut(pAd);
577
578 }
579
580
581 /*
582 Must be run in Interrupt context
583 This function handle RT2870 specific TxDesc and cpu index update and kick the packet out.
584 */
585 int RtmpUSBMgmtKickOut(
586 IN RTMP_ADAPTER *pAd,
587 IN UCHAR QueIdx,
588 IN PNDIS_PACKET pPacket,
589 IN PUCHAR pSrcBufVA,
590 IN UINT SrcBufLen)
591 {
592 PTXINFO_STRUC pTxInfo;
593 ULONG BulkOutSize;
594 UCHAR padLen;
595 PUCHAR pDest;
596 ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
597 PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa;
598 unsigned long IrqFlags;
599
600
601 pTxInfo = (PTXINFO_STRUC)(pSrcBufVA);
602
603 // Build our URB for USBD
604 BulkOutSize = SrcBufLen;
605 BulkOutSize = (BulkOutSize + 3) & (~3);
606 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
607
608 BulkOutSize += 4; // Always add 4 extra bytes at every packet.
609
610 // If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again.
611 if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0)
612 BulkOutSize += 4;
613
614 padLen = BulkOutSize - SrcBufLen;
615 ASSERT((padLen <= RTMP_PKT_TAIL_PADDING));
616
617 // Now memzero all extra padding bytes.
618 pDest = (PUCHAR)(pSrcBufVA + SrcBufLen);
619 skb_put(GET_OS_PKT_TYPE(pPacket), padLen);
620 NdisZeroMemory(pDest, padLen);
621
622 RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
623
624 pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket;
625 pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket));
626
627 // Length in TxInfo should be 8 less than bulkout size.
628 pMLMEContext->BulkOutSize = BulkOutSize;
629 pMLMEContext->InUse = TRUE;
630 pMLMEContext->bWaitingBulkOut = TRUE;
631
632
633 //for debug
634 //hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize));
635
636 //pAd->RalinkCounters.KickTxCount++;
637 //pAd->RalinkCounters.OneSecTxDoneCount++;
638
639 //if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE)
640 // needKickOut = TRUE;
641
642 // Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX
643 pAd->MgmtRing.TxSwFreeIdx--;
644 INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
645
646 RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
647
648 RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
649 //if (needKickOut)
650 RTUSBKickBulkOut(pAd);
651
652 return 0;
653 }
654
655
656 VOID RtmpUSBNullFrameKickOut(
657 IN RTMP_ADAPTER *pAd,
658 IN UCHAR QueIdx,
659 IN UCHAR *pNullFrame,
660 IN UINT32 frameLen)
661 {
662 if (pAd->NullContext.InUse == FALSE)
663 {
664 PTX_CONTEXT pNullContext;
665 PTXINFO_STRUC pTxInfo;
666 PTXWI_STRUC pTxWI;
667 PUCHAR pWirelessPkt;
668
669 pNullContext = &(pAd->NullContext);
670
671 // Set the in use bit
672 pNullContext->InUse = TRUE;
673 pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0];
674
675 RTMPZeroMemory(&pWirelessPkt[0], 100);
676 pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[0];
677 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
678 pTxInfo->QSEL = FIFO_EDCA;
679 pTxWI = (PTXWI_STRUC)&pWirelessPkt[TXINFO_SIZE];
680 RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)),
681 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
682 RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11));
683 pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4;
684
685 // Fill out frame length information for global Bulk out arbitor
686 //pNullContext->BulkOutSize = TransferBufferLength;
687 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - send NULL Frame @%d Mbps...\n", RateIdToMbps[pAd->CommonCfg.TxRate]));
688 RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL);
689
690 // Kick bulk out
691 RTUSBKickBulkOut(pAd);
692 }
693
694 }
695
696 /*
697 ========================================================================
698
699 Routine Description:
700 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
701
702 Arguments:
703 pRxD Pointer to the Rx descriptor
704
705 Return Value:
706 NDIS_STATUS_SUCCESS No err
707 NDIS_STATUS_FAILURE Error
708
709 Note:
710
711 ========================================================================
712 */
713 NDIS_STATUS RTMPCheckRxError(
714 IN PRTMP_ADAPTER pAd,
715 IN PHEADER_802_11 pHeader,
716 IN PRXWI_STRUC pRxWI,
717 IN PRT28XX_RXD_STRUC pRxINFO)
718 {
719 PCIPHER_KEY pWpaKey;
720 INT dBm;
721
722 if (pAd->bPromiscuous == TRUE)
723 return(NDIS_STATUS_SUCCESS);
724 if(pRxINFO == NULL)
725 return(NDIS_STATUS_FAILURE);
726
727 // Phy errors & CRC errors
728 if (pRxINFO->Crc)
729 {
730 // Check RSSI for Noise Hist statistic collection.
731 dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
732 if (dBm <= -87)
733 pAd->StaCfg.RPIDensity[0] += 1;
734 else if (dBm <= -82)
735 pAd->StaCfg.RPIDensity[1] += 1;
736 else if (dBm <= -77)
737 pAd->StaCfg.RPIDensity[2] += 1;
738 else if (dBm <= -72)
739 pAd->StaCfg.RPIDensity[3] += 1;
740 else if (dBm <= -67)
741 pAd->StaCfg.RPIDensity[4] += 1;
742 else if (dBm <= -62)
743 pAd->StaCfg.RPIDensity[5] += 1;
744 else if (dBm <= -57)
745 pAd->StaCfg.RPIDensity[6] += 1;
746 else if (dBm > -57)
747 pAd->StaCfg.RPIDensity[7] += 1;
748
749 return(NDIS_STATUS_FAILURE);
750 }
751
752 // Add Rx size to channel load counter, we should ignore error counts
753 pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount+ 14);
754
755 // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
756 if (pHeader->FC.ToDs)
757 {
758 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n"));
759 return NDIS_STATUS_FAILURE;
760 }
761
762 // Paul 04-03 for OFDM Rx length issue
763 if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE)
764 {
765 DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n"));
766 return NDIS_STATUS_FAILURE;
767 }
768
769 // Drop not U2M frames, cant's drop here because we will drop beacon in this case
770 // I am kind of doubting the U2M bit operation
771 // if (pRxD->U2M == 0)
772 // return(NDIS_STATUS_FAILURE);
773
774 // drop decyption fail frame
775 if (pRxINFO->Decrypted && pRxINFO->CipherErr)
776 {
777
778 //
779 // MIC Error
780 //
781 if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss)
782 {
783 pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
784 RTMPReportMicError(pAd, pWpaKey);
785 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
786 }
787
788 if (pRxINFO->Decrypted &&
789 (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == CIPHER_AES) &&
790 (pHeader->Sequence == pAd->FragFrame.Sequence))
791 {
792 //
793 // Acceptable since the First FragFrame no CipherErr problem.
794 //
795 return(NDIS_STATUS_SUCCESS);
796 }
797
798 return(NDIS_STATUS_FAILURE);
799 }
800
801 return(NDIS_STATUS_SUCCESS);
802 }
803
804 VOID RT28xxUsbStaAsicForceWakeup(
805 IN PRTMP_ADAPTER pAd,
806 IN BOOLEAN bFromTx)
807 {
808 AUTO_WAKEUP_STRUC AutoWakeupCfg;
809
810 AutoWakeupCfg.word = 0;
811 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
812
813 #ifndef RT30xx
814 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
815 #endif
816 #ifdef RT30xx
817 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
818 #endif
819
820 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
821 }
822
823 VOID RT28xxUsbStaAsicSleepThenAutoWakeup(
824 IN PRTMP_ADAPTER pAd,
825 IN USHORT TbttNumToNextWakeUp)
826 {
827 AUTO_WAKEUP_STRUC AutoWakeupCfg;
828
829 // we have decided to SLEEP, so at least do it for a BEACON period.
830 if (TbttNumToNextWakeUp == 0)
831 TbttNumToNextWakeUp = 1;
832
833 AutoWakeupCfg.word = 0;
834 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
835
836 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
837 AutoWakeupCfg.field.EnableAutoWakeup = 1;
838 AutoWakeupCfg.field.AutoLeadTime = 5;
839 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
840
841 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); // send POWER-SAVE command to MCU. Timeout 40us.
842
843 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
844
845 }
846
847 VOID RT28xxUsbMlmeRadioOn(
848 IN PRTMP_ADAPTER pAd)
849 {
850 DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOn()\n"));
851
852 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
853 return;
854
855 #ifndef RT30xx
856 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
857 #endif
858 #ifdef RT30xx
859 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
860 #endif
861 RTMPusecDelay(10000);
862
863 NICResetFromError(pAd);
864
865 // Enable Tx/Rx
866 RTMPEnableRxTx(pAd);
867
868 #ifdef RT3070
869 if (IS_RT3071(pAd))
870 {
871 RT30xxReverseRFSleepModeSetup(pAd);
872 }
873 #endif // RT3070 //
874
875 // Clear Radio off flag
876 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
877
878 RTUSBBulkReceive(pAd);
879
880 // Set LED
881 RTMPSetLED(pAd, LED_RADIO_ON);
882 }
883
884 VOID RT28xxUsbMlmeRadioOFF(
885 IN PRTMP_ADAPTER pAd)
886 {
887 WPDMA_GLO_CFG_STRUC GloCfg;
888 UINT32 Value, i;
889
890 DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOFF()\n"));
891
892 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
893 return;
894
895 // Set LED
896 RTMPSetLED(pAd, LED_RADIO_OFF);
897 // Set Radio off flag
898 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
899
900 {
901 // Link down first if any association exists
902 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
903 LinkDown(pAd, FALSE);
904 RTMPusecDelay(10000);
905
906 //==========================================
907 // Clean up old bss table
908 BssTableInit(&pAd->ScanTab);
909 }
910
911 #ifndef RT30xx
912 // Disable MAC Tx/Rx
913 RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
914 Value &= (0xfffffff3);
915 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
916
917 // MAC_SYS_CTRL => value = 0x0 => 40mA
918 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
919
920 // PWR_PIN_CFG => value = 0x0 => 40mA
921 RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
922
923 // TX_PIN_CFG => value = 0x0 => 20mA
924 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
925 #endif
926
927 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
928 {
929 // Must using 40MHz.
930 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
931 }
932 else
933 {
934 // Must using 20MHz.
935 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
936 }
937
938 #ifdef RT30xx
939 // Disable Tx/Rx DMA
940 RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA
941 GloCfg.field.EnableTxDMA = 0;
942 GloCfg.field.EnableRxDMA = 0;
943 RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings
944 #endif
945
946 // Waiting for DMA idle
947 i = 0;
948 do
949 {
950 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
951 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
952 break;
953
954 RTMPusecDelay(1000);
955 }while (i++ < 100);
956
957 #ifdef RT30xx
958 // Disable MAC Tx/Rx
959 RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
960 Value &= (0xfffffff3);
961 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
962 #endif
963
964 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
965 }
966
967
|
This page was automatically generated by the
LXR engine.
|