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 /*
29    All functions in this file must be USB-depended, or you should out your function
30 	in other files.
31 
32 */
33 
34 #ifdef RTMP_MAC_USB
35 
36 #include	"../rt_config.h"
37 
38 /*
39 	We can do copy the frame into pTxContext when match following conditions.
40 		=>
41 		=>
42 		=>
43 */
RtmpUSBCanDoWrite(struct rt_rtmp_adapter * pAd,u8 QueIdx,struct rt_ht_tx_context * pHTTXContext)44 static inline int RtmpUSBCanDoWrite(struct rt_rtmp_adapter *pAd,
45 					    u8 QueIdx,
46 					    struct rt_ht_tx_context *pHTTXContext)
47 {
48 	int canWrite = NDIS_STATUS_RESOURCES;
49 
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"));
64 	} else {
65 		canWrite = NDIS_STATUS_SUCCESS;
66 	}
67 
68 	return canWrite;
69 }
70 
RtmpUSB_WriteSubTxResource(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,IN BOOLEAN bIsLast,u16 * FreeNumber)71 u16 RtmpUSB_WriteSubTxResource(struct rt_rtmp_adapter *pAd,
72 				  struct rt_tx_blk *pTxBlk,
73 				  IN BOOLEAN bIsLast, u16 * FreeNumber)
74 {
75 
76 	/* Dummy function. Should be removed in the future. */
77 	return 0;
78 
79 }
80 
RtmpUSB_WriteFragTxResource(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,u8 fragNum,u16 * FreeNumber)81 u16 RtmpUSB_WriteFragTxResource(struct rt_rtmp_adapter *pAd,
82 				   struct rt_tx_blk *pTxBlk,
83 				   u8 fragNum, u16 * FreeNumber)
84 {
85 	struct rt_ht_tx_context *pHTTXContext;
86 	u16 hwHdrLen;	/* The hwHdrLen consist of 802.11 header length plus the header padding length. */
87 	u32 fillOffset;
88 	struct rt_txinfo *pTxInfo;
89 	struct rt_txwi *pTxWI;
90 	u8 *pWirelessPacket = NULL;
91 	u8 QueIdx;
92 	int Status;
93 	unsigned long IrqFlags;
94 	u32 USBDMApktLen = 0, DMAHdrLen, padding;
95 	BOOLEAN TxQLastRound = FALSE;
96 
97 	/* */
98 	/* get Tx Ring Resource & Dma Buffer address */
99 	/* */
100 	QueIdx = pTxBlk->QueIdx;
101 	pHTTXContext = &pAd->TxContext[QueIdx];
102 
103 	RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
104 
105 	pHTTXContext = &pAd->TxContext[QueIdx];
106 	fillOffset = pHTTXContext->CurWritePosition;
107 
108 	if (fragNum == 0) {
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;
113 
114 			/* Reserve space for 8 bytes padding. */
115 			if ((pHTTXContext->ENextBulkOutPosition ==
116 			     pHTTXContext->CurWritePosition)) {
117 				pHTTXContext->ENextBulkOutPosition += 8;
118 				pHTTXContext->CurWritePosition += 8;
119 				fillOffset += 8;
120 			}
121 			pTxBlk->Priv = 0;
122 			pHTTXContext->CurWriteRealPos =
123 			    pHTTXContext->CurWritePosition;
124 		} else {
125 			RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx],
126 					IrqFlags);
127 
128 			RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
129 					    NDIS_STATUS_FAILURE);
130 			return (Status);
131 		}
132 	} else {
133 		/* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */
134 		Status =
135 		    ((pHTTXContext->bCurWriting ==
136 		      TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
137 		if (Status == NDIS_STATUS_SUCCESS) {
138 			fillOffset += pTxBlk->Priv;
139 		} else {
140 			RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx],
141 					IrqFlags);
142 
143 			RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
144 					    NDIS_STATUS_FAILURE);
145 			return (Status);
146 		}
147 	}
148 
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]);
152 
153 	pWirelessPacket =
154 	    &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
155 
156 	/* copy TXWI + WLAN Header + LLC into DMA Header Buffer */
157 	/*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
158 	hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
159 
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;
165 
166 	pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen);
167 
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);
171 
172 	if (fragNum == pTxBlk->TotalFragNum) {
173 		pTxInfo->USBDMATxburst = 0;
174 		if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906) >
175 		    MAX_TXBULK_LIMIT) {
176 			pTxInfo->SwUseLastRound = 1;
177 			TxQLastRound = TRUE;
178 		}
179 	} else {
180 		pTxInfo->USBDMATxburst = 1;
181 	}
182 
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);
187 
188 	RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
189 
190 	NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
191 
192 	/*      Zero the last padding. */
193 	pWirelessPacket += pTxBlk->SrcBufLen;
194 	NdisZeroMemory(pWirelessPacket, padding + 8);
195 
196 	if (fragNum == pTxBlk->TotalFragNum) {
197 		RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
198 
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;
204 
205 		/* Finally, set bCurWriting as FALSE */
206 		pHTTXContext->bCurWriting = FALSE;
207 
208 		RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
209 
210 		/* succeed and release the skb buffer */
211 		RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
212 	}
213 
214 	return (Status);
215 
216 }
217 
RtmpUSB_WriteSingleTxResource(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,IN BOOLEAN bIsLast,u16 * FreeNumber)218 u16 RtmpUSB_WriteSingleTxResource(struct rt_rtmp_adapter *pAd,
219 				     struct rt_tx_blk *pTxBlk,
220 				     IN BOOLEAN bIsLast,
221 				     u16 * FreeNumber)
222 {
223 	struct rt_ht_tx_context *pHTTXContext;
224 	u16 hwHdrLen;
225 	u32 fillOffset;
226 	struct rt_txinfo *pTxInfo;
227 	struct rt_txwi *pTxWI;
228 	u8 *pWirelessPacket;
229 	u8 QueIdx;
230 	unsigned long IrqFlags;
231 	int Status;
232 	u32 USBDMApktLen = 0, DMAHdrLen, padding;
233 	BOOLEAN bTxQLastRound = FALSE;
234 
235 	/* For USB, didn't need PCI_MAP_SINGLE() */
236 	/*SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); */
237 
238 	/* */
239 	/* get Tx Ring Resource & Dma Buffer address */
240 	/* */
241 	QueIdx = pTxBlk->QueIdx;
242 
243 	RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
244 	pHTTXContext = &pAd->TxContext[QueIdx];
245 	fillOffset = pHTTXContext->CurWritePosition;
246 
247 	/* Check ring full. */
248 	Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
249 	if (Status == NDIS_STATUS_SUCCESS) {
250 		pHTTXContext->bCurWriting = TRUE;
251 
252 		pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]);
253 		pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]);
254 
255 		/* Reserve space for 8 bytes padding. */
256 		if ((pHTTXContext->ENextBulkOutPosition ==
257 		     pHTTXContext->CurWritePosition)) {
258 			pHTTXContext->ENextBulkOutPosition += 8;
259 			pHTTXContext->CurWritePosition += 8;
260 			fillOffset += 8;
261 		}
262 		pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
263 
264 		pWirelessPacket =
265 		    &pHTTXContext->TransferBuffer->field.
266 		    WirelessPacket[fillOffset];
267 
268 		/* copy TXWI + WLAN Header + LLC into DMA Header Buffer */
269 		/*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
270 		hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
271 
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;
277 
278 		pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen);
279 
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);
283 
284 		if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) >
285 		    MAX_TXBULK_LIMIT) {
286 			pTxInfo->SwUseLastRound = 1;
287 			bTxQLastRound = TRUE;
288 		}
289 		NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf,
290 			       TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
291 		pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen);
292 
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);
306 
307 		NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData,
308 			       pTxBlk->SrcBufLen);
309 		pWirelessPacket += pTxBlk->SrcBufLen;
310 		NdisZeroMemory(pWirelessPacket, padding + 8);
311 
312 		RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
313 
314 		pHTTXContext->CurWritePosition += pTxBlk->Priv;
315 		if (bTxQLastRound)
316 			pHTTXContext->CurWritePosition = 8;
317 		pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
318 
319 		pHTTXContext->bCurWriting = FALSE;
320 	}
321 
322 	RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
323 
324 	/* succeed and release the skb buffer */
325 	RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
326 
327 	return (Status);
328 
329 }
330 
RtmpUSB_WriteMultiTxResource(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,u8 frameNum,u16 * FreeNumber)331 u16 RtmpUSB_WriteMultiTxResource(struct rt_rtmp_adapter *pAd,
332 				    struct rt_tx_blk *pTxBlk,
333 				    u8 frameNum, u16 * FreeNumber)
334 {
335 	struct rt_ht_tx_context *pHTTXContext;
336 	u16 hwHdrLen;	/* The hwHdrLen consist of 802.11 header length plus the header padding length. */
337 	u32 fillOffset;
338 	struct rt_txinfo *pTxInfo;
339 	struct rt_txwi *pTxWI;
340 	u8 *pWirelessPacket = NULL;
341 	u8 QueIdx;
342 	int Status;
343 	unsigned long IrqFlags;
344 	/*u32                        USBDMApktLen = 0, DMAHdrLen, padding; */
345 
346 	/* */
347 	/* get Tx Ring Resource & Dma Buffer address */
348 	/* */
349 	QueIdx = pTxBlk->QueIdx;
350 	pHTTXContext = &pAd->TxContext[QueIdx];
351 
352 	RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
353 
354 	if (frameNum == 0) {
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;
359 
360 			pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]);
361 			pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]);
362 
363 			/* Reserve space for 8 bytes padding. */
364 			if ((pHTTXContext->ENextBulkOutPosition ==
365 			     pHTTXContext->CurWritePosition)) {
366 
367 				pHTTXContext->CurWritePosition += 8;
368 				pHTTXContext->ENextBulkOutPosition += 8;
369 			}
370 			fillOffset = pHTTXContext->CurWritePosition;
371 			pHTTXContext->CurWriteRealPos =
372 			    pHTTXContext->CurWritePosition;
373 
374 			pWirelessPacket =
375 			    &pHTTXContext->TransferBuffer->field.
376 			    WirelessPacket[fillOffset];
377 
378 			/* */
379 			/* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */
380 			/* */
381 			if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
382 				/*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */
383 				hwHdrLen =
384 				    pTxBlk->MpduHeaderLen -
385 				    LENGTH_AMSDU_SUBFRAMEHEAD +
386 				    pTxBlk->HdrPadLen +
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; */
390 				hwHdrLen =
391 				    pTxBlk->MpduHeaderLen -
392 				    LENGTH_ARALINK_HEADER_FIELD +
393 				    pTxBlk->HdrPadLen +
394 				    LENGTH_ARALINK_HEADER_FIELD;
395 			else
396 				/*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
397 				hwHdrLen =
398 				    pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
399 
400 			/* Update the pTxBlk->Priv. */
401 			pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
402 
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 */ ,
406 					FALSE);
407 
408 			/* Copy it. */
409 			NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf,
410 				       pTxBlk->Priv);
411 			pHTTXContext->CurWriteRealPos += pTxBlk->Priv;
412 			pWirelessPacket += pTxBlk->Priv;
413 		}
414 	} else {		/* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */
415 
416 		Status =
417 		    ((pHTTXContext->bCurWriting ==
418 		      TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
419 		if (Status == NDIS_STATUS_SUCCESS) {
420 			fillOffset =
421 			    (pHTTXContext->CurWritePosition + pTxBlk->Priv);
422 			pWirelessPacket =
423 			    &pHTTXContext->TransferBuffer->field.
424 			    WirelessPacket[fillOffset];
425 
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;
435 		}
436 	}
437 
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);
449 
450 	if (Status != NDIS_STATUS_SUCCESS) {
451 		DBGPRINT(RT_DEBUG_ERROR,
452 			 ("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n",
453 			  pHTTXContext->CurWritePosition,
454 			  pHTTXContext->NextBulkOutPosition));
455 		goto done;
456 	}
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;
461 
462 done:
463 	/* Release the skb buffer here */
464 	RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
465 
466 	return (Status);
467 
468 }
469 
RtmpUSB_FinalWriteTxResource(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,u16 totalMPDUSize,u16 TxIdx)470 void RtmpUSB_FinalWriteTxResource(struct rt_rtmp_adapter *pAd,
471 				  struct rt_tx_blk *pTxBlk,
472 				  u16 totalMPDUSize, u16 TxIdx)
473 {
474 	u8 QueIdx;
475 	struct rt_ht_tx_context *pHTTXContext;
476 	u32 fillOffset;
477 	struct rt_txinfo *pTxInfo;
478 	struct rt_txwi *pTxWI;
479 	u32 USBDMApktLen, padding;
480 	unsigned long IrqFlags;
481 	u8 *pWirelessPacket;
482 
483 	QueIdx = pTxBlk->QueIdx;
484 	pHTTXContext = &pAd->TxContext[QueIdx];
485 
486 	RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
487 
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]);
496 		else
497 			pWirelessPacket =
498 			    (u8 *)(&pHTTXContext->TransferBuffer->field.
499 				      WirelessPacket[fillOffset]);
500 
501 		/* */
502 		/* Update TxInfo->USBDMApktLen , */
503 		/*              the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding */
504 		/* */
505 		pTxInfo = (struct rt_txinfo *)(pWirelessPacket);
506 
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;
511 
512 		pTxInfo->USBDMATxPktLen = USBDMApktLen;
513 
514 		/* */
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;
519 
520 		/* */
521 		/* Update the pHTTXContext->CurWritePosition */
522 		/* */
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;
527 		}
528 		pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
529 
530 		/* */
531 		/*      Zero the last padding. */
532 		/* */
533 		pWirelessPacket =
534 		    (&pHTTXContext->TransferBuffer->field.
535 		     WirelessPacket[fillOffset + pTxBlk->Priv]);
536 		NdisZeroMemory(pWirelessPacket, padding + 8);
537 
538 		/* Finally, set bCurWriting as FALSE */
539 		pHTTXContext->bCurWriting = FALSE;
540 
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"));
544 	}
545 
546 	RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
547 
548 }
549 
RtmpUSBDataLastTxIdx(struct rt_rtmp_adapter * pAd,u8 QueIdx,u16 TxIdx)550 void RtmpUSBDataLastTxIdx(struct rt_rtmp_adapter *pAd,
551 			  u8 QueIdx, u16 TxIdx)
552 {
553 	/* DO nothing for USB. */
554 }
555 
556 /*
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.
562 
563 */
RtmpUSBDataKickOut(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,u8 QueIdx)564 void RtmpUSBDataKickOut(struct rt_rtmp_adapter *pAd,
565 			struct rt_tx_blk *pTxBlk, u8 QueIdx)
566 {
567 	RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
568 	RTUSBKickBulkOut(pAd);
569 
570 }
571 
572 /*
573 	Must be run in Interrupt context
574 	This function handle RT2870 specific TxDesc and cpu index update and kick the packet out.
575  */
RtmpUSBMgmtKickOut(struct rt_rtmp_adapter * pAd,u8 QueIdx,void * pPacket,u8 * pSrcBufVA,u32 SrcBufLen)576 int RtmpUSBMgmtKickOut(struct rt_rtmp_adapter *pAd,
577 		       u8 QueIdx,
578 		       void *pPacket,
579 		       u8 *pSrcBufVA, u32 SrcBufLen)
580 {
581 	struct rt_txinfo *pTxInfo;
582 	unsigned long BulkOutSize;
583 	u8 padLen;
584 	u8 *pDest;
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;
589 
590 	pTxInfo = (struct rt_txinfo *)(pSrcBufVA);
591 
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);
597 
598 	BulkOutSize += 4;	/* Always add 4 extra bytes at every packet. */
599 
600 	/* If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again. */
601 	if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0)
602 		BulkOutSize += 4;
603 
604 	padLen = BulkOutSize - SrcBufLen;
605 	ASSERT((padLen <= RTMP_PKT_TAIL_PADDING));
606 
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);
611 
612 	RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
613 
614 	pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket;
615 	pMLMEContext->TransferBuffer =
616 	    (struct rt_tx_buffer *)(GET_OS_PKT_DATAPTR(pPacket));
617 
618 	/* Length in TxInfo should be 8 less than bulkout size. */
619 	pMLMEContext->BulkOutSize = BulkOutSize;
620 	pMLMEContext->InUse = TRUE;
621 	pMLMEContext->bWaitingBulkOut = TRUE;
622 
623 	/*for debug */
624 	/*hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize)); */
625 
626 	/*pAd->RalinkCounters.KickTxCount++; */
627 	/*pAd->RalinkCounters.OneSecTxDoneCount++; */
628 
629 	/*if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE) */
630 	/*      needKickOut = TRUE; */
631 
632 	/* Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX */
633 	pAd->MgmtRing.TxSwFreeIdx--;
634 	INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
635 
636 	RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
637 
638 	RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
639 	/*if (needKickOut) */
640 	RTUSBKickBulkOut(pAd);
641 
642 	return 0;
643 }
644 
RtmpUSBNullFrameKickOut(struct rt_rtmp_adapter * pAd,u8 QueIdx,u8 * pNullFrame,u32 frameLen)645 void RtmpUSBNullFrameKickOut(struct rt_rtmp_adapter *pAd,
646 			     u8 QueIdx,
647 			     u8 * pNullFrame, u32 frameLen)
648 {
649 	if (pAd->NullContext.InUse == FALSE) {
650 		struct rt_tx_context *pNullContext;
651 		struct rt_txinfo *pTxInfo;
652 		struct rt_txwi * pTxWI;
653 		u8 *pWirelessPkt;
654 
655 		pNullContext = &(pAd->NullContext);
656 
657 		/* Set the in use bit */
658 		pNullContext->InUse = TRUE;
659 		pWirelessPkt =
660 		    (u8 *)& pNullContext->TransferBuffer->field.
661 		    WirelessPacket[0];
662 
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);
674 
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;
679 
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);
686 
687 		/* Kick bulk out */
688 		RTUSBKickBulkOut(pAd);
689 	}
690 
691 }
692 
693 /*
694 ========================================================================
695 Routine Description:
696     Get a received packet.
697 
698 Arguments:
699 	pAd					device control block
700 	pSaveRxD			receive descriptor information
701 	*pbReschedule		need reschedule flag
702 	*pRxPending			pending received packet flag
703 
704 Return Value:
705     the received packet
706 
707 Note:
708 ========================================================================
709 */
GetPacketFromRxRing(struct rt_rtmp_adapter * pAd,OUT PRT28XX_RXD_STRUC pSaveRxD,OUT BOOLEAN * pbReschedule,IN u32 * pRxPending)710 void *GetPacketFromRxRing(struct rt_rtmp_adapter *pAd,
711 				 OUT PRT28XX_RXD_STRUC pSaveRxD,
712 				 OUT BOOLEAN * pbReschedule,
713 				 IN u32 * pRxPending)
714 {
715 	struct rt_rx_context *pRxContext;
716 	void *pSkb;
717 	u8 *pData;
718 	unsigned long ThisFrameLen;
719 	unsigned long RxBufferLength;
720 	struct rt_rxwi * pRxWI;
721 
722 	pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex];
723 	if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE))
724 		return NULL;
725 
726 	RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition;
727 	if (RxBufferLength <
728 	    (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxwi) +
729 	     sizeof(struct rt_rxinfo))) {
730 		goto label_null;
731 	}
732 
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));
741 		goto label_null;
742 	}
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));
748 		goto label_null;
749 	}
750 
751 	if ((ThisFrameLen + 8) > RxBufferLength)	/* 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxinfo)) */
752 	{
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,
757 			  pAd->ReadPosition));
758 
759 		/* error frame. finish this loop */
760 		goto label_null;
761 	}
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,
769 			  ThisFrameLen));
770 		goto label_null;
771 	}
772 	/* allocate a rx packet */
773 	pSkb = dev_alloc_skb(ThisFrameLen);
774 	if (pSkb == NULL) {
775 		DBGPRINT(RT_DEBUG_ERROR,
776 			 ("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n",
777 			  __FUNCTION__));
778 		goto label_null;
779 	}
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);
784 
785 	/* copy RxD */
786 	*pSaveRxD = *(struct rt_rxinfo *) (pData + ThisFrameLen);
787 
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)) */
790 
791 	return pSkb;
792 
793 label_null:
794 
795 	return NULL;
796 }
797 
798 /*
799 	========================================================================
800 
801 	Routine	Description:
802 		Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
803 
804 	Arguments:
805 		pRxD		Pointer	to the Rx descriptor
806 
807 	Return Value:
808 		NDIS_STATUS_SUCCESS		No err
809 		NDIS_STATUS_FAILURE		Error
810 
811 	Note:
812 
813 	========================================================================
814 */
RTMPCheckRxError(struct rt_rtmp_adapter * pAd,struct rt_header_802_11 * pHeader,struct rt_rxwi * pRxWI,IN PRT28XX_RXD_STRUC pRxINFO)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)
818 {
819 	struct rt_cipher_key *pWpaKey;
820 	int dBm;
821 
822 	if (pAd->bPromiscuous == TRUE)
823 		return (NDIS_STATUS_SUCCESS);
824 	if (pRxINFO == NULL)
825 		return (NDIS_STATUS_FAILURE);
826 
827 	/* Phy errors & CRC errors */
828 	if (pRxINFO->Crc) {
829 		/* Check RSSI for Noise Hist statistic collection. */
830 		dBm = (int)(pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
831 		if (dBm <= -87)
832 			pAd->StaCfg.RPIDensity[0] += 1;
833 		else if (dBm <= -82)
834 			pAd->StaCfg.RPIDensity[1] += 1;
835 		else if (dBm <= -77)
836 			pAd->StaCfg.RPIDensity[2] += 1;
837 		else if (dBm <= -72)
838 			pAd->StaCfg.RPIDensity[3] += 1;
839 		else if (dBm <= -67)
840 			pAd->StaCfg.RPIDensity[4] += 1;
841 		else if (dBm <= -62)
842 			pAd->StaCfg.RPIDensity[5] += 1;
843 		else if (dBm <= -57)
844 			pAd->StaCfg.RPIDensity[6] += 1;
845 		else if (dBm > -57)
846 			pAd->StaCfg.RPIDensity[7] += 1;
847 
848 		return (NDIS_STATUS_FAILURE);
849 	}
850 	/* Add Rx size to channel load counter, we should ignore error counts */
851 	pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount + 14);
852 
853 	/* Drop ToDs promiscuous 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;
857 	}
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;
862 	}
863 	/* Drop not U2M frames, can't 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); */
867 
868 	/* drop decyption fail frame */
869 	if (pRxINFO->Decrypted && pRxINFO->CipherErr) {
870 
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].
875 					      Addr, BSS0, 0);
876 
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].
881 					      Addr, BSS0, 0);
882 		/* */
883 		/* MIC Error */
884 		/* */
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"));
889 		}
890 
891 		if (pRxINFO->Decrypted &&
892 		    (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg ==
893 		     CIPHER_AES)
894 		    && (pHeader->Sequence == pAd->FragFrame.Sequence)) {
895 			/* */
896 			/* Acceptable since the First FragFrame no CipherErr problem. */
897 			/* */
898 			return (NDIS_STATUS_SUCCESS);
899 		}
900 
901 		return (NDIS_STATUS_FAILURE);
902 	}
903 
904 	return (NDIS_STATUS_SUCCESS);
905 }
906 
RtmpUsbStaAsicForceWakeupTimeout(void * SystemSpecific1,void * FunctionContext,void * SystemSpecific2,void * SystemSpecific3)907 void RtmpUsbStaAsicForceWakeupTimeout(void *SystemSpecific1,
908 				      void *FunctionContext,
909 				      void *SystemSpecific2,
910 				      void *SystemSpecific3)
911 {
912 	struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
913 
914 	if (pAd && pAd->Mlme.AutoWakeupTimerRunning) {
915 		AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
916 
917 		OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
918 		pAd->Mlme.AutoWakeupTimerRunning = FALSE;
919 	}
920 }
921 
RT28xxUsbStaAsicForceWakeup(struct rt_rtmp_adapter * pAd,IN BOOLEAN bFromTx)922 void RT28xxUsbStaAsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx)
923 {
924 	BOOLEAN Canceled;
925 
926 	if (pAd->Mlme.AutoWakeupTimerRunning)
927 		RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Canceled);
928 
929 	AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
930 
931 	OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
932 }
933 
RT28xxUsbStaAsicSleepThenAutoWakeup(struct rt_rtmp_adapter * pAd,u16 TbttNumToNextWakeUp)934 void RT28xxUsbStaAsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd,
935 					 u16 TbttNumToNextWakeUp)
936 {
937 
938 	/* we have decided to SLEEP, so at least do it for a BEACON period. */
939 	if (TbttNumToNextWakeUp == 0)
940 		TbttNumToNextWakeUp = 1;
941 
942 	RTMPSetTimer(&pAd->Mlme.AutoWakeupTimer, AUTO_WAKEUP_TIMEOUT);
943 	pAd->Mlme.AutoWakeupTimerRunning = TRUE;
944 
945 	AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);	/* send POWER-SAVE command to MCU. Timeout 40us. */
946 
947 	OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
948 
949 }
950 
951 #endif /* RTMP_MAC_USB // */
952