]>
Commit | Line | Data |
---|---|---|
ca97b838 | 1 | /* |
c55519ff GKH |
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 | Module Name: | |
28 | rtusb_bulk.c | |
29 | ||
30 | Abstract: | |
31 | ||
32 | Revision History: | |
33 | Who When What | |
34 | -------- ---------- ---------------------------------------------- | |
35 | Name Date Modification logs | |
36 | Paul Lin 06-25-2004 created | |
37 | ||
38 | */ | |
39 | ||
ca97b838 BZ |
40 | #ifdef RTMP_MAC_USB |
41 | ||
c55519ff | 42 | #include "../rt_config.h" |
9f548a2a | 43 | /* Match total 6 bulkout endpoint to corresponding queue. */ |
51126deb | 44 | u8 EpToQueue[6] = |
66cd8d6e | 45 | { FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_MGMT }; |
c55519ff | 46 | |
9f548a2a | 47 | /*static BOOLEAN SingleBulkOut = FALSE; */ |
c55519ff | 48 | |
66cd8d6e BZ |
49 | void RTUSB_FILL_BULK_URB(struct urb *pUrb, |
50 | struct usb_device *pUsb_Dev, | |
51 | unsigned int bulkpipe, | |
52 | void *pTransferBuf, | |
53 | int BufSize, usb_complete_t Complete, void *pContext) | |
c55519ff GKH |
54 | { |
55 | ||
66cd8d6e BZ |
56 | usb_fill_bulk_urb(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, |
57 | (usb_complete_t) Complete, pContext); | |
c55519ff GKH |
58 | |
59 | } | |
60 | ||
51126deb | 61 | void RTUSBInitTxDesc(IN PRTMP_ADAPTER pAd, |
66cd8d6e | 62 | IN PTX_CONTEXT pTxContext, |
51126deb | 63 | u8 BulkOutPipeId, IN usb_complete_t Func) |
c55519ff | 64 | { |
66cd8d6e | 65 | PURB pUrb; |
51126deb | 66 | u8 *pSrc = NULL; |
66cd8d6e | 67 | POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; |
c55519ff GKH |
68 | |
69 | pUrb = pTxContext->pUrb; | |
70 | ASSERT(pUrb); | |
71 | ||
9f548a2a | 72 | /* Store BulkOut PipeId */ |
c55519ff GKH |
73 | pTxContext->BulkOutPipeId = BulkOutPipeId; |
74 | ||
66cd8d6e | 75 | if (pTxContext->bAggregatible) { |
c55519ff | 76 | pSrc = &pTxContext->TransferBuffer->Aggregation[2]; |
66cd8d6e BZ |
77 | } else { |
78 | pSrc = | |
51126deb | 79 | (u8 *)pTxContext->TransferBuffer->field.WirelessPacket; |
c55519ff GKH |
80 | } |
81 | ||
9f548a2a | 82 | /*Initialize a tx bulk urb */ |
c55519ff | 83 | RTUSB_FILL_BULK_URB(pUrb, |
66cd8d6e BZ |
84 | pObj->pUsb_Dev, |
85 | usb_sndbulkpipe(pObj->pUsb_Dev, | |
86 | pAd->BulkOutEpAddr[BulkOutPipeId]), | |
87 | pSrc, pTxContext->BulkOutSize, Func, pTxContext); | |
c55519ff | 88 | |
c55519ff | 89 | if (pTxContext->bAggregatible) |
66cd8d6e BZ |
90 | pUrb->transfer_dma = |
91 | (pTxContext->data_dma + TX_BUFFER_NORMSIZE + 2); | |
c55519ff | 92 | else |
66cd8d6e | 93 | pUrb->transfer_dma = pTxContext->data_dma; |
c55519ff GKH |
94 | |
95 | pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | |
c55519ff GKH |
96 | |
97 | } | |
98 | ||
51126deb | 99 | void RTUSBInitHTTxDesc(IN PRTMP_ADAPTER pAd, |
66cd8d6e | 100 | IN PHT_TX_CONTEXT pTxContext, |
51126deb BZ |
101 | u8 BulkOutPipeId, |
102 | unsigned long BulkOutSize, IN usb_complete_t Func) | |
c55519ff | 103 | { |
66cd8d6e | 104 | PURB pUrb; |
51126deb | 105 | u8 *pSrc = NULL; |
66cd8d6e | 106 | POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; |
c55519ff GKH |
107 | |
108 | pUrb = pTxContext->pUrb; | |
109 | ASSERT(pUrb); | |
110 | ||
9f548a2a | 111 | /* Store BulkOut PipeId */ |
c55519ff GKH |
112 | pTxContext->BulkOutPipeId = BulkOutPipeId; |
113 | ||
66cd8d6e BZ |
114 | pSrc = |
115 | &pTxContext->TransferBuffer->field.WirelessPacket[pTxContext-> | |
116 | NextBulkOutPosition]; | |
c55519ff | 117 | |
9f548a2a | 118 | /*Initialize a tx bulk urb */ |
c55519ff | 119 | RTUSB_FILL_BULK_URB(pUrb, |
66cd8d6e BZ |
120 | pObj->pUsb_Dev, |
121 | usb_sndbulkpipe(pObj->pUsb_Dev, | |
122 | pAd->BulkOutEpAddr[BulkOutPipeId]), | |
123 | pSrc, BulkOutSize, Func, pTxContext); | |
124 | ||
125 | pUrb->transfer_dma = | |
126 | (pTxContext->data_dma + pTxContext->NextBulkOutPosition); | |
c55519ff | 127 | pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
c55519ff GKH |
128 | |
129 | } | |
130 | ||
51126deb | 131 | void RTUSBInitRxDesc(IN PRTMP_ADAPTER pAd, IN PRX_CONTEXT pRxContext) |
c55519ff | 132 | { |
66cd8d6e BZ |
133 | PURB pUrb; |
134 | POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; | |
51126deb | 135 | unsigned long RX_bulk_size; |
c55519ff GKH |
136 | |
137 | pUrb = pRxContext->pUrb; | |
138 | ASSERT(pUrb); | |
139 | ||
66cd8d6e | 140 | if (pAd->BulkInMaxPacketSize == 64) |
c55519ff GKH |
141 | RX_bulk_size = 4096; |
142 | else | |
143 | RX_bulk_size = MAX_RXBULK_SIZE; | |
144 | ||
9f548a2a | 145 | /*Initialize a rx bulk urb */ |
c55519ff | 146 | RTUSB_FILL_BULK_URB(pUrb, |
66cd8d6e BZ |
147 | pObj->pUsb_Dev, |
148 | usb_rcvbulkpipe(pObj->pUsb_Dev, pAd->BulkInEpAddr), | |
149 | &(pRxContext-> | |
150 | TransferBuffer[pAd->NextRxBulkInPosition]), | |
151 | RX_bulk_size - (pAd->NextRxBulkInPosition), | |
152 | (usb_complete_t) RTUSBBulkRxComplete, | |
153 | (void *)pRxContext); | |
154 | ||
155 | pUrb->transfer_dma = pRxContext->data_dma + pAd->NextRxBulkInPosition; | |
c55519ff | 156 | pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
c55519ff | 157 | |
c55519ff GKH |
158 | } |
159 | ||
160 | /* | |
161 | ======================================================================== | |
162 | ||
163 | Routine Description: | |
164 | ||
165 | Arguments: | |
166 | ||
167 | Return Value: | |
168 | ||
169 | Note: | |
170 | ||
171 | ======================================================================== | |
172 | */ | |
173 | ||
174 | #define BULK_OUT_LOCK(pLock, IrqFlags) \ | |
175 | if(1 /*!(in_interrupt() & 0xffff0000)*/) \ | |
176 | RTMP_IRQ_LOCK((pLock), IrqFlags); | |
177 | ||
178 | #define BULK_OUT_UNLOCK(pLock, IrqFlags) \ | |
179 | if(1 /*!(in_interrupt() & 0xffff0000)*/) \ | |
180 | RTMP_IRQ_UNLOCK((pLock), IrqFlags); | |
181 | ||
51126deb BZ |
182 | void RTUSBBulkOutDataPacket(IN PRTMP_ADAPTER pAd, |
183 | u8 BulkOutPipeId, u8 Index) | |
c55519ff GKH |
184 | { |
185 | ||
66cd8d6e BZ |
186 | PHT_TX_CONTEXT pHTTXContext; |
187 | PURB pUrb; | |
188 | int ret = 0; | |
189 | PTXINFO_STRUC pTxInfo, pLastTxInfo = NULL; | |
190 | PTXWI_STRUC pTxWI; | |
51126deb | 191 | unsigned long TmpBulkEndPos, ThisBulkSize; |
66cd8d6e | 192 | unsigned long IrqFlags = 0, IrqFlags2 = 0; |
51126deb | 193 | u8 *pWirelessPkt, *pAppendant; |
66cd8d6e | 194 | BOOLEAN bTxQLastRound = FALSE; |
51126deb | 195 | u8 allzero[4] = { 0x0, 0x0, 0x0, 0x0 }; |
c55519ff GKH |
196 | |
197 | BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); | |
66cd8d6e BZ |
198 | if ((pAd->BulkOutPending[BulkOutPipeId] == TRUE) |
199 | || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { | |
c55519ff GKH |
200 | BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); |
201 | return; | |
202 | } | |
203 | pAd->BulkOutPending[BulkOutPipeId] = TRUE; | |
204 | ||
205 | if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) | |
66cd8d6e | 206 | ) { |
c55519ff GKH |
207 | pAd->BulkOutPending[BulkOutPipeId] = FALSE; |
208 | BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); | |
209 | return; | |
210 | } | |
211 | BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); | |
212 | ||
c55519ff GKH |
213 | pHTTXContext = &(pAd->TxContext[BulkOutPipeId]); |
214 | ||
215 | BULK_OUT_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); | |
66cd8d6e BZ |
216 | if ((pHTTXContext->ENextBulkOutPosition == |
217 | pHTTXContext->CurWritePosition) | |
218 | || ((pHTTXContext->ENextBulkOutPosition - 8) == | |
219 | pHTTXContext->CurWritePosition)) { | |
220 | BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], | |
221 | IrqFlags2); | |
c55519ff GKH |
222 | |
223 | BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); | |
224 | pAd->BulkOutPending[BulkOutPipeId] = FALSE; | |
225 | ||
9f548a2a | 226 | /* Clear Data flag */ |
66cd8d6e BZ |
227 | RTUSB_CLEAR_BULK_FLAG(pAd, |
228 | (fRTUSB_BULK_OUT_DATA_FRAG << | |
229 | BulkOutPipeId)); | |
230 | RTUSB_CLEAR_BULK_FLAG(pAd, | |
231 | (fRTUSB_BULK_OUT_DATA_NORMAL << | |
232 | BulkOutPipeId)); | |
c55519ff GKH |
233 | |
234 | BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); | |
235 | return; | |
236 | } | |
9f548a2a | 237 | /* Clear Data flag */ |
66cd8d6e BZ |
238 | RTUSB_CLEAR_BULK_FLAG(pAd, |
239 | (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId)); | |
240 | RTUSB_CLEAR_BULK_FLAG(pAd, | |
241 | (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); | |
c55519ff | 242 | |
9f548a2a BZ |
243 | /*DBGPRINT(RT_DEBUG_TRACE,("BulkOut-B:I=0x%lx, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", in_interrupt(), */ |
244 | /* pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, */ | |
245 | /* pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); */ | |
c55519ff GKH |
246 | pHTTXContext->NextBulkOutPosition = pHTTXContext->ENextBulkOutPosition; |
247 | ThisBulkSize = 0; | |
248 | TmpBulkEndPos = pHTTXContext->NextBulkOutPosition; | |
249 | pWirelessPkt = &pHTTXContext->TransferBuffer->field.WirelessPacket[0]; | |
250 | ||
66cd8d6e BZ |
251 | if ((pHTTXContext->bCopySavePad == TRUE)) { |
252 | if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero, 4)) { | |
253 | DBGPRINT_RAW(RT_DEBUG_ERROR, | |
254 | ("e1, allzero : %x %x %x %x %x %x %x %x \n", | |
255 | pHTTXContext->SavedPad[0], | |
256 | pHTTXContext->SavedPad[1], | |
257 | pHTTXContext->SavedPad[2], | |
258 | pHTTXContext->SavedPad[3] | |
259 | , pHTTXContext->SavedPad[4], | |
260 | pHTTXContext->SavedPad[5], | |
261 | pHTTXContext->SavedPad[6], | |
262 | pHTTXContext->SavedPad[7])); | |
c55519ff | 263 | } |
66cd8d6e BZ |
264 | NdisMoveMemory(&pWirelessPkt[TmpBulkEndPos], |
265 | pHTTXContext->SavedPad, 8); | |
c55519ff GKH |
266 | pHTTXContext->bCopySavePad = FALSE; |
267 | if (pAd->bForcePrintTX == TRUE) | |
66cd8d6e BZ |
268 | DBGPRINT(RT_DEBUG_TRACE, |
269 | ("RTUSBBulkOutDataPacket --> COPY PAD. CurWrite = %ld, NextBulk = %ld. ENextBulk = %ld.\n", | |
270 | pHTTXContext->CurWritePosition, | |
271 | pHTTXContext->NextBulkOutPosition, | |
272 | pHTTXContext->ENextBulkOutPosition)); | |
c55519ff GKH |
273 | } |
274 | ||
66cd8d6e BZ |
275 | do { |
276 | pTxInfo = (PTXINFO_STRUC) & pWirelessPkt[TmpBulkEndPos]; | |
277 | pTxWI = | |
278 | (PTXWI_STRUC) & pWirelessPkt[TmpBulkEndPos + TXINFO_SIZE]; | |
c55519ff GKH |
279 | |
280 | if (pAd->bForcePrintTX == TRUE) | |
66cd8d6e BZ |
281 | DBGPRINT(RT_DEBUG_TRACE, |
282 | ("RTUSBBulkOutDataPacket AMPDU = %d.\n", | |
283 | pTxWI->AMPDU)); | |
c55519ff | 284 | |
9f548a2a BZ |
285 | /* add by Iverson, limit BulkOut size to 4k to pass WMM b mode 2T1R test items */ |
286 | /*if ((ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) */ | |
66cd8d6e BZ |
287 | if ((ThisBulkSize != 0) && (pTxWI->PHYMODE == MODE_CCK)) { |
288 | if (((ThisBulkSize & 0xffff8000) != 0) | |
289 | || ((ThisBulkSize & 0x1000) == 0x1000)) { | |
9f548a2a | 290 | /* Limit BulkOut size to about 4k bytes. */ |
66cd8d6e BZ |
291 | pHTTXContext->ENextBulkOutPosition = |
292 | TmpBulkEndPos; | |
c55519ff | 293 | break; |
66cd8d6e BZ |
294 | } else |
295 | if (((pAd->BulkOutMaxPacketSize < 512) | |
296 | && ((ThisBulkSize & 0xfffff800) != | |
297 | 0)) | |
298 | /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) */ | |
299 | ) { | |
9f548a2a BZ |
300 | /* For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. */ |
301 | /* For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. */ | |
66cd8d6e BZ |
302 | pHTTXContext->ENextBulkOutPosition = |
303 | TmpBulkEndPos; | |
c55519ff GKH |
304 | break; |
305 | } | |
306 | } | |
9f548a2a | 307 | /* end Iverson */ |
66cd8d6e | 308 | else { |
9f548a2a | 309 | if (((ThisBulkSize & 0xffff8000) != 0) || ((ThisBulkSize & 0x6000) == 0x6000)) { /* Limit BulkOut size to about 24k bytes. */ |
66cd8d6e BZ |
310 | pHTTXContext->ENextBulkOutPosition = |
311 | TmpBulkEndPos; | |
c55519ff | 312 | break; |
9f548a2a BZ |
313 | } else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize & 0xfffff800) != 0)) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) */ ) { /* For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. */ |
314 | /* For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. */ | |
66cd8d6e BZ |
315 | pHTTXContext->ENextBulkOutPosition = |
316 | TmpBulkEndPos; | |
c55519ff GKH |
317 | break; |
318 | } | |
319 | } | |
320 | ||
66cd8d6e | 321 | if (TmpBulkEndPos == pHTTXContext->CurWritePosition) { |
c55519ff GKH |
322 | pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; |
323 | break; | |
324 | } | |
325 | ||
66cd8d6e BZ |
326 | if (pTxInfo->QSEL != FIFO_EDCA) { |
327 | DBGPRINT(RT_DEBUG_ERROR, | |
328 | ("%s(): ====> pTxInfo->QueueSel(%d)!= FIFO_EDCA!!!!\n", | |
329 | __FUNCTION__, pTxInfo->QSEL)); | |
330 | DBGPRINT(RT_DEBUG_ERROR, | |
331 | ("\tCWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", | |
332 | pHTTXContext->CurWritePosition, | |
333 | pHTTXContext->NextBulkOutPosition, | |
334 | pHTTXContext->ENextBulkOutPosition, | |
335 | pHTTXContext->bCopySavePad)); | |
336 | hex_dump("Wrong QSel Pkt:", | |
51126deb | 337 | (u8 *)& pWirelessPkt[TmpBulkEndPos], |
66cd8d6e BZ |
338 | (pHTTXContext->CurWritePosition - |
339 | pHTTXContext->NextBulkOutPosition)); | |
c55519ff GKH |
340 | } |
341 | ||
66cd8d6e BZ |
342 | if (pTxInfo->USBDMATxPktLen <= 8) { |
343 | BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], | |
344 | IrqFlags2); | |
345 | DBGPRINT(RT_DEBUG_ERROR /*RT_DEBUG_TRACE */ , | |
346 | ("e2, USBDMATxPktLen==0, Size=%ld, bCSPad=%d, CWPos=%ld, NBPos=%ld, CWRPos=%ld!\n", | |
347 | pHTTXContext->BulkOutSize, | |
348 | pHTTXContext->bCopySavePad, | |
349 | pHTTXContext->CurWritePosition, | |
350 | pHTTXContext->NextBulkOutPosition, | |
351 | pHTTXContext->CurWriteRealPos)); | |
c55519ff | 352 | { |
66cd8d6e BZ |
353 | DBGPRINT_RAW(RT_DEBUG_ERROR /*RT_DEBUG_TRACE */ |
354 | , | |
355 | ("%x %x %x %x %x %x %x %x \n", | |
356 | pHTTXContext->SavedPad[0], | |
357 | pHTTXContext->SavedPad[1], | |
358 | pHTTXContext->SavedPad[2], | |
359 | pHTTXContext->SavedPad[3] | |
360 | , pHTTXContext->SavedPad[4], | |
361 | pHTTXContext->SavedPad[5], | |
362 | pHTTXContext->SavedPad[6], | |
363 | pHTTXContext->SavedPad[7])); | |
c55519ff GKH |
364 | } |
365 | pAd->bForcePrintTX = TRUE; | |
66cd8d6e BZ |
366 | BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], |
367 | IrqFlags); | |
c55519ff | 368 | pAd->BulkOutPending[BulkOutPipeId] = FALSE; |
66cd8d6e BZ |
369 | BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], |
370 | IrqFlags); | |
9f548a2a | 371 | /*DBGPRINT(RT_DEBUG_LOUD,("Out:pTxInfo->USBDMATxPktLen=%d!\n", pTxInfo->USBDMATxPktLen)); */ |
c55519ff GKH |
372 | return; |
373 | } | |
9f548a2a | 374 | /* Increase Total transmit byte counter */ |
66cd8d6e BZ |
375 | pAd->RalinkCounters.OneSecTransmittedByteCount += |
376 | pTxWI->MPDUtotalByteCount; | |
377 | pAd->RalinkCounters.TransmittedByteCount += | |
378 | pTxWI->MPDUtotalByteCount; | |
c55519ff GKH |
379 | |
380 | pLastTxInfo = pTxInfo; | |
381 | ||
9f548a2a | 382 | /* Make sure we use EDCA QUEUE. */ |
ca97b838 | 383 | pTxInfo->QSEL = FIFO_EDCA; |
66cd8d6e BZ |
384 | ThisBulkSize += (pTxInfo->USBDMATxPktLen + 4); |
385 | TmpBulkEndPos += (pTxInfo->USBDMATxPktLen + 4); | |
c55519ff GKH |
386 | |
387 | if (TmpBulkEndPos != pHTTXContext->CurWritePosition) | |
388 | pTxInfo->USBDMANextVLD = 1; | |
389 | ||
66cd8d6e | 390 | if (pTxInfo->SwUseLastRound == 1) { |
c55519ff GKH |
391 | if (pHTTXContext->CurWritePosition == 8) |
392 | pTxInfo->USBDMANextVLD = 0; | |
393 | pTxInfo->SwUseLastRound = 0; | |
394 | ||
395 | bTxQLastRound = TRUE; | |
396 | pHTTXContext->ENextBulkOutPosition = 8; | |
397 | ||
c55519ff GKH |
398 | break; |
399 | } | |
ca97b838 | 400 | |
66cd8d6e | 401 | } while (TRUE); |
c55519ff | 402 | |
9f548a2a | 403 | /* adjust the pTxInfo->USBDMANextVLD value of last pTxInfo. */ |
66cd8d6e | 404 | if (pLastTxInfo) { |
c55519ff | 405 | pLastTxInfo->USBDMANextVLD = 0; |
c55519ff GKH |
406 | } |
407 | ||
408 | /* | |
66cd8d6e BZ |
409 | We need to copy SavedPad when following condition matched! |
410 | 1. Not the last round of the TxQueue and | |
411 | 2. any match of following cases: | |
412 | (1). The End Position of this bulk out is reach to the Currenct Write position and | |
413 | the TxInfo and related header already write to the CurWritePosition. | |
414 | =>(ENextBulkOutPosition == CurWritePosition) && (CurWriteRealPos > CurWritePosition) | |
415 | ||
416 | (2). The EndPosition of the bulk out is not reach to the Current Write Position. | |
417 | =>(ENextBulkOutPosition != CurWritePosition) | |
418 | */ | |
c55519ff | 419 | if ((bTxQLastRound == FALSE) && |
66cd8d6e BZ |
420 | (((pHTTXContext->ENextBulkOutPosition == |
421 | pHTTXContext->CurWritePosition) | |
422 | && (pHTTXContext->CurWriteRealPos > | |
423 | pHTTXContext->CurWritePosition)) | |
424 | || (pHTTXContext->ENextBulkOutPosition != | |
425 | pHTTXContext->CurWritePosition)) | |
426 | ) { | |
427 | NdisMoveMemory(pHTTXContext->SavedPad, | |
428 | &pWirelessPkt[pHTTXContext-> | |
429 | ENextBulkOutPosition], 8); | |
c55519ff | 430 | pHTTXContext->bCopySavePad = TRUE; |
66cd8d6e | 431 | if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero, 4)) { |
51126deb | 432 | u8 *pBuf = &pHTTXContext->SavedPad[0]; |
66cd8d6e BZ |
433 | DBGPRINT_RAW(RT_DEBUG_ERROR, |
434 | ("WARNING-Zero-3:%02x%02x%02x%02x%02x%02x%02x%02x,CWPos=%ld, CWRPos=%ld, bCW=%d, NBPos=%ld, TBPos=%ld, TBSize=%ld\n", | |
435 | pBuf[0], pBuf[1], pBuf[2], pBuf[3], | |
436 | pBuf[4], pBuf[5], pBuf[6], pBuf[7], | |
437 | pHTTXContext->CurWritePosition, | |
438 | pHTTXContext->CurWriteRealPos, | |
439 | pHTTXContext->bCurWriting, | |
440 | pHTTXContext->NextBulkOutPosition, | |
441 | TmpBulkEndPos, ThisBulkSize)); | |
c55519ff GKH |
442 | |
443 | pBuf = &pWirelessPkt[pHTTXContext->CurWritePosition]; | |
66cd8d6e BZ |
444 | DBGPRINT_RAW(RT_DEBUG_ERROR, |
445 | ("\tCWPos=%02x%02x%02x%02x%02x%02x%02x%02x\n", | |
446 | pBuf[0], pBuf[1], pBuf[2], pBuf[3], | |
447 | pBuf[4], pBuf[5], pBuf[6], pBuf[7])); | |
c55519ff | 448 | } |
9f548a2a | 449 | /*DBGPRINT(RT_DEBUG_LOUD,("ENPos==CWPos=%ld, CWRPos=%ld, bCSPad=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->bCopySavePad)); */ |
c55519ff GKH |
450 | } |
451 | ||
452 | if (pAd->bForcePrintTX == TRUE) | |
66cd8d6e BZ |
453 | DBGPRINT(RT_DEBUG_TRACE, |
454 | ("BulkOut-A:Size=%ld, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", | |
455 | ThisBulkSize, pHTTXContext->CurWritePosition, | |
456 | pHTTXContext->NextBulkOutPosition, | |
457 | pHTTXContext->ENextBulkOutPosition, | |
458 | pHTTXContext->bCopySavePad)); | |
9f548a2a | 459 | /*DBGPRINT(RT_DEBUG_LOUD,("BulkOut-A:Size=%ld, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, bLRound=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, bTxQLastRound)); */ |
c55519ff | 460 | |
9f548a2a | 461 | /* USB DMA engine requires to pad extra 4 bytes. This pad doesn't count into real bulkoutsize. */ |
c55519ff GKH |
462 | pAppendant = &pWirelessPkt[TmpBulkEndPos]; |
463 | NdisZeroMemory(pAppendant, 8); | |
66cd8d6e BZ |
464 | ThisBulkSize += 4; |
465 | pHTTXContext->LastOne = TRUE; | |
466 | if ((ThisBulkSize % pAd->BulkOutMaxPacketSize) == 0) | |
c55519ff | 467 | ThisBulkSize += 4; |
c55519ff GKH |
468 | pHTTXContext->BulkOutSize = ThisBulkSize; |
469 | ||
470 | pAd->watchDogTxPendingCnt[BulkOutPipeId] = 1; | |
471 | BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); | |
472 | ||
9f548a2a | 473 | /* Init Tx context descriptor */ |
66cd8d6e BZ |
474 | RTUSBInitHTTxDesc(pAd, pHTTXContext, BulkOutPipeId, ThisBulkSize, |
475 | (usb_complete_t) RTUSBBulkOutDataPacketComplete); | |
c55519ff GKH |
476 | |
477 | pUrb = pHTTXContext->pUrb; | |
66cd8d6e BZ |
478 | if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { |
479 | DBGPRINT(RT_DEBUG_ERROR, | |
480 | ("RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", | |
481 | ret)); | |
c55519ff GKH |
482 | |
483 | BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); | |
484 | pAd->BulkOutPending[BulkOutPipeId] = FALSE; | |
485 | pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; | |
486 | BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); | |
487 | ||
488 | return; | |
489 | } | |
490 | ||
491 | BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); | |
492 | pHTTXContext->IRPPending = TRUE; | |
493 | BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); | |
494 | pAd->BulkOutReq++; | |
495 | ||
496 | } | |
497 | ||
51126deb | 498 | void RTUSBBulkOutDataPacketComplete(purbb_t pUrb, struct pt_regs * pt_regs) |
c55519ff | 499 | { |
66cd8d6e BZ |
500 | PHT_TX_CONTEXT pHTTXContext; |
501 | PRTMP_ADAPTER pAd; | |
502 | POS_COOKIE pObj; | |
51126deb | 503 | u8 BulkOutPipeId; |
c55519ff | 504 | |
66cd8d6e BZ |
505 | pHTTXContext = (PHT_TX_CONTEXT) pUrb->context; |
506 | pAd = pHTTXContext->pAd; | |
507 | pObj = (POS_COOKIE) pAd->OS_Cookie; | |
c55519ff | 508 | |
9f548a2a | 509 | /* Store BulkOut PipeId */ |
66cd8d6e | 510 | BulkOutPipeId = pHTTXContext->BulkOutPipeId; |
c55519ff GKH |
511 | pAd->BulkOutDataOneSecCount++; |
512 | ||
66cd8d6e BZ |
513 | switch (BulkOutPipeId) { |
514 | case 0: | |
515 | pObj->ac0_dma_done_task.data = (unsigned long)pUrb; | |
516 | tasklet_hi_schedule(&pObj->ac0_dma_done_task); | |
517 | break; | |
518 | case 1: | |
519 | pObj->ac1_dma_done_task.data = (unsigned long)pUrb; | |
520 | tasklet_hi_schedule(&pObj->ac1_dma_done_task); | |
521 | break; | |
522 | case 2: | |
523 | pObj->ac2_dma_done_task.data = (unsigned long)pUrb; | |
524 | tasklet_hi_schedule(&pObj->ac2_dma_done_task); | |
525 | break; | |
526 | case 3: | |
527 | pObj->ac3_dma_done_task.data = (unsigned long)pUrb; | |
528 | tasklet_hi_schedule(&pObj->ac3_dma_done_task); | |
529 | break; | |
c55519ff | 530 | } |
ca97b838 | 531 | |
c55519ff | 532 | } |
c55519ff | 533 | |
c55519ff GKH |
534 | /* |
535 | ======================================================================== | |
536 | ||
537 | Routine Description: | |
538 | ||
539 | Arguments: | |
540 | ||
541 | Return Value: | |
542 | ||
543 | Note: NULL frame use BulkOutPipeId = 0 | |
544 | ||
545 | ======================================================================== | |
546 | */ | |
51126deb | 547 | void RTUSBBulkOutNullFrame(IN PRTMP_ADAPTER pAd) |
c55519ff | 548 | { |
66cd8d6e BZ |
549 | PTX_CONTEXT pNullContext = &(pAd->NullContext); |
550 | PURB pUrb; | |
551 | int ret = 0; | |
552 | unsigned long IrqFlags; | |
c55519ff GKH |
553 | |
554 | RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); | |
66cd8d6e BZ |
555 | if ((pAd->BulkOutPending[0] == TRUE) |
556 | || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { | |
c55519ff GKH |
557 | RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); |
558 | return; | |
559 | } | |
560 | pAd->BulkOutPending[0] = TRUE; | |
561 | pAd->watchDogTxPendingCnt[0] = 1; | |
562 | pNullContext->IRPPending = TRUE; | |
563 | RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); | |
564 | ||
9f548a2a | 565 | /* Increase Total transmit byte counter */ |
66cd8d6e | 566 | pAd->RalinkCounters.TransmittedByteCount += pNullContext->BulkOutSize; |
c55519ff | 567 | |
9f548a2a | 568 | /* Clear Null frame bulk flag */ |
c55519ff GKH |
569 | RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); |
570 | ||
9f548a2a | 571 | /* Init Tx context descriptor */ |
66cd8d6e BZ |
572 | RTUSBInitTxDesc(pAd, pNullContext, 0, |
573 | (usb_complete_t) RTUSBBulkOutNullFrameComplete); | |
c55519ff GKH |
574 | |
575 | pUrb = pNullContext->pUrb; | |
66cd8d6e | 576 | if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { |
c55519ff GKH |
577 | RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); |
578 | pAd->BulkOutPending[0] = FALSE; | |
579 | pAd->watchDogTxPendingCnt[0] = 0; | |
580 | pNullContext->IRPPending = FALSE; | |
581 | RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); | |
582 | ||
66cd8d6e BZ |
583 | DBGPRINT(RT_DEBUG_ERROR, |
584 | ("RTUSBBulkOutNullFrame: Submit Tx URB failed %d\n", | |
585 | ret)); | |
c55519ff GKH |
586 | return; |
587 | } | |
588 | ||
589 | } | |
590 | ||
9f548a2a | 591 | /* NULL frame use BulkOutPipeId = 0 */ |
51126deb | 592 | void RTUSBBulkOutNullFrameComplete(purbb_t pUrb, struct pt_regs * pt_regs) |
c55519ff | 593 | { |
66cd8d6e BZ |
594 | PRTMP_ADAPTER pAd; |
595 | PTX_CONTEXT pNullContext; | |
51126deb | 596 | int Status; |
66cd8d6e | 597 | POS_COOKIE pObj; |
c55519ff | 598 | |
66cd8d6e BZ |
599 | pNullContext = (PTX_CONTEXT) pUrb->context; |
600 | pAd = pNullContext->pAd; | |
601 | Status = pUrb->status; | |
c55519ff | 602 | |
c55519ff GKH |
603 | pObj = (POS_COOKIE) pAd->OS_Cookie; |
604 | pObj->null_frame_complete_task.data = (unsigned long)pUrb; | |
605 | tasklet_hi_schedule(&pObj->null_frame_complete_task); | |
c55519ff GKH |
606 | } |
607 | ||
c55519ff GKH |
608 | /* |
609 | ======================================================================== | |
610 | ||
611 | Routine Description: | |
612 | ||
613 | Arguments: | |
614 | ||
615 | Return Value: | |
616 | ||
617 | Note: MLME use BulkOutPipeId = 0 | |
618 | ||
619 | ======================================================================== | |
620 | */ | |
51126deb | 621 | void RTUSBBulkOutMLMEPacket(IN PRTMP_ADAPTER pAd, u8 Index) |
c55519ff | 622 | { |
66cd8d6e BZ |
623 | PTX_CONTEXT pMLMEContext; |
624 | PURB pUrb; | |
625 | int ret = 0; | |
626 | unsigned long IrqFlags; | |
c55519ff | 627 | |
66cd8d6e BZ |
628 | pMLMEContext = |
629 | (PTX_CONTEXT) pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa; | |
c55519ff GKH |
630 | pUrb = pMLMEContext->pUrb; |
631 | ||
632 | if ((pAd->MgmtRing.TxSwFreeIdx >= MGMT_RING_SIZE) || | |
66cd8d6e BZ |
633 | (pMLMEContext->InUse == FALSE) || |
634 | (pMLMEContext->bWaitingBulkOut == FALSE)) { | |
c55519ff | 635 | |
9f548a2a | 636 | /* Clear MLME bulk flag */ |
c55519ff GKH |
637 | RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); |
638 | ||
639 | return; | |
640 | } | |
641 | ||
c55519ff | 642 | RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); |
66cd8d6e BZ |
643 | if ((pAd->BulkOutPending[MGMTPIPEIDX] == TRUE) |
644 | || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { | |
c55519ff GKH |
645 | RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); |
646 | return; | |
647 | } | |
648 | ||
649 | pAd->BulkOutPending[MGMTPIPEIDX] = TRUE; | |
650 | pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 1; | |
651 | pMLMEContext->IRPPending = TRUE; | |
652 | pMLMEContext->bWaitingBulkOut = FALSE; | |
653 | RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); | |
654 | ||
9f548a2a | 655 | /* Increase Total transmit byte counter */ |
66cd8d6e | 656 | pAd->RalinkCounters.TransmittedByteCount += pMLMEContext->BulkOutSize; |
c55519ff | 657 | |
9f548a2a | 658 | /* Clear MLME bulk flag */ |
c55519ff GKH |
659 | RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); |
660 | ||
9f548a2a | 661 | /* Init Tx context descriptor */ |
66cd8d6e BZ |
662 | RTUSBInitTxDesc(pAd, pMLMEContext, MGMTPIPEIDX, |
663 | (usb_complete_t) RTUSBBulkOutMLMEPacketComplete); | |
c55519ff | 664 | |
9f548a2a | 665 | /*For mgmt urb buffer, because we use sk_buff, so we need to notify the USB controller do dma mapping. */ |
66cd8d6e | 666 | pUrb->transfer_dma = 0; |
c55519ff | 667 | pUrb->transfer_flags &= (~URB_NO_TRANSFER_DMA_MAP); |
c55519ff GKH |
668 | |
669 | pUrb = pMLMEContext->pUrb; | |
66cd8d6e BZ |
670 | if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { |
671 | DBGPRINT(RT_DEBUG_ERROR, | |
672 | ("RTUSBBulkOutMLMEPacket: Submit MLME URB failed %d\n", | |
673 | ret)); | |
c55519ff GKH |
674 | RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); |
675 | pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; | |
676 | pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 0; | |
677 | pMLMEContext->IRPPending = FALSE; | |
678 | pMLMEContext->bWaitingBulkOut = TRUE; | |
679 | RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); | |
680 | ||
681 | return; | |
682 | } | |
9f548a2a BZ |
683 | /*DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutMLMEPacket \n")); */ |
684 | /* printk("<---RTUSBBulkOutMLMEPacket,Cpu=%d!, Dma=%d, SwIdx=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx); */ | |
c55519ff GKH |
685 | } |
686 | ||
51126deb | 687 | void RTUSBBulkOutMLMEPacketComplete(purbb_t pUrb, struct pt_regs * pt_regs) |
c55519ff | 688 | { |
66cd8d6e BZ |
689 | PTX_CONTEXT pMLMEContext; |
690 | PRTMP_ADAPTER pAd; | |
51126deb | 691 | int Status; |
66cd8d6e BZ |
692 | POS_COOKIE pObj; |
693 | int index; | |
c55519ff | 694 | |
9f548a2a | 695 | /*DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutMLMEPacketComplete\n")); */ |
66cd8d6e BZ |
696 | pMLMEContext = (PTX_CONTEXT) pUrb->context; |
697 | pAd = pMLMEContext->pAd; | |
698 | pObj = (POS_COOKIE) pAd->OS_Cookie; | |
699 | Status = pUrb->status; | |
700 | index = pMLMEContext->SelfIdx; | |
c55519ff | 701 | |
c55519ff GKH |
702 | pObj->mgmt_dma_done_task.data = (unsigned long)pUrb; |
703 | tasklet_hi_schedule(&pObj->mgmt_dma_done_task); | |
c55519ff GKH |
704 | } |
705 | ||
c55519ff GKH |
706 | /* |
707 | ======================================================================== | |
708 | ||
709 | Routine Description: | |
710 | ||
711 | Arguments: | |
712 | ||
713 | Return Value: | |
714 | ||
715 | Note: PsPoll use BulkOutPipeId = 0 | |
716 | ||
717 | ======================================================================== | |
718 | */ | |
51126deb | 719 | void RTUSBBulkOutPsPoll(IN PRTMP_ADAPTER pAd) |
c55519ff | 720 | { |
66cd8d6e BZ |
721 | PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext); |
722 | PURB pUrb; | |
723 | int ret = 0; | |
724 | unsigned long IrqFlags; | |
c55519ff GKH |
725 | |
726 | RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); | |
66cd8d6e BZ |
727 | if ((pAd->BulkOutPending[0] == TRUE) |
728 | || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { | |
c55519ff GKH |
729 | RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); |
730 | return; | |
731 | } | |
732 | pAd->BulkOutPending[0] = TRUE; | |
733 | pAd->watchDogTxPendingCnt[0] = 1; | |
734 | pPsPollContext->IRPPending = TRUE; | |
735 | RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); | |
736 | ||
9f548a2a | 737 | /* Clear PS-Poll bulk flag */ |
c55519ff GKH |
738 | RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL); |
739 | ||
9f548a2a | 740 | /* Init Tx context descriptor */ |
66cd8d6e BZ |
741 | RTUSBInitTxDesc(pAd, pPsPollContext, MGMTPIPEIDX, |
742 | (usb_complete_t) RTUSBBulkOutPsPollComplete); | |
c55519ff GKH |
743 | |
744 | pUrb = pPsPollContext->pUrb; | |
66cd8d6e | 745 | if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { |
c55519ff GKH |
746 | RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); |
747 | pAd->BulkOutPending[0] = FALSE; | |
748 | pAd->watchDogTxPendingCnt[0] = 0; | |
749 | pPsPollContext->IRPPending = FALSE; | |
750 | RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); | |
751 | ||
66cd8d6e BZ |
752 | DBGPRINT(RT_DEBUG_ERROR, |
753 | ("RTUSBBulkOutPsPoll: Submit Tx URB failed %d\n", | |
754 | ret)); | |
c55519ff GKH |
755 | return; |
756 | } | |
757 | ||
758 | } | |
759 | ||
9f548a2a | 760 | /* PS-Poll frame use BulkOutPipeId = 0 */ |
51126deb | 761 | void RTUSBBulkOutPsPollComplete(purbb_t pUrb, struct pt_regs * pt_regs) |
c55519ff | 762 | { |
66cd8d6e BZ |
763 | PRTMP_ADAPTER pAd; |
764 | PTX_CONTEXT pPsPollContext; | |
51126deb | 765 | int Status; |
66cd8d6e | 766 | POS_COOKIE pObj; |
c55519ff | 767 | |
66cd8d6e | 768 | pPsPollContext = (PTX_CONTEXT) pUrb->context; |
c55519ff GKH |
769 | pAd = pPsPollContext->pAd; |
770 | Status = pUrb->status; | |
771 | ||
c55519ff GKH |
772 | pObj = (POS_COOKIE) pAd->OS_Cookie; |
773 | pObj->pspoll_frame_complete_task.data = (unsigned long)pUrb; | |
774 | tasklet_hi_schedule(&pObj->pspoll_frame_complete_task); | |
c55519ff GKH |
775 | } |
776 | ||
51126deb | 777 | void DoBulkIn(IN RTMP_ADAPTER * pAd) |
c55519ff | 778 | { |
66cd8d6e BZ |
779 | PRX_CONTEXT pRxContext; |
780 | PURB pUrb; | |
781 | int ret = 0; | |
782 | unsigned long IrqFlags; | |
c55519ff GKH |
783 | |
784 | RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); | |
785 | pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]); | |
66cd8d6e BZ |
786 | if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) |
787 | || (pRxContext->InUse == TRUE)) { | |
c55519ff GKH |
788 | RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); |
789 | return; | |
790 | } | |
791 | pRxContext->InUse = TRUE; | |
792 | pRxContext->IRPPending = TRUE; | |
793 | pAd->PendingRx++; | |
794 | pAd->BulkInReq++; | |
795 | RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); | |
796 | ||
9f548a2a | 797 | /* Init Rx context descriptor */ |
c55519ff GKH |
798 | NdisZeroMemory(pRxContext->TransferBuffer, pRxContext->BulkInOffset); |
799 | RTUSBInitRxDesc(pAd, pRxContext); | |
800 | ||
801 | pUrb = pRxContext->pUrb; | |
9f548a2a | 802 | if ((ret = RTUSB_SUBMIT_URB(pUrb)) != 0) { /* fail */ |
c55519ff GKH |
803 | |
804 | RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); | |
805 | pRxContext->InUse = FALSE; | |
806 | pRxContext->IRPPending = FALSE; | |
807 | pAd->PendingRx--; | |
808 | pAd->BulkInReq--; | |
809 | RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); | |
66cd8d6e BZ |
810 | DBGPRINT(RT_DEBUG_ERROR, |
811 | ("RTUSBBulkReceive: Submit Rx URB failed %d\n", ret)); | |
9f548a2a | 812 | } else { /* success */ |
c55519ff | 813 | ASSERT((pRxContext->InUse == pRxContext->IRPPending)); |
9f548a2a | 814 | /*printk("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex); */ |
c55519ff GKH |
815 | } |
816 | } | |
817 | ||
c55519ff GKH |
818 | /* |
819 | ======================================================================== | |
820 | ||
821 | Routine Description: | |
822 | USB_RxPacket initializes a URB and uses the Rx IRP to submit it | |
823 | to USB. It checks if an Rx Descriptor is available and passes the | |
824 | the coresponding buffer to be filled. If no descriptor is available | |
825 | fails the request. When setting the completion routine we pass our | |
826 | Adapter Object as Context. | |
827 | ||
828 | Arguments: | |
829 | ||
830 | Return Value: | |
831 | TRUE found matched tuple cache | |
832 | FALSE no matched found | |
833 | ||
834 | Note: | |
835 | ||
836 | ======================================================================== | |
837 | */ | |
838 | #define fRTMP_ADAPTER_NEED_STOP_RX \ | |
839 | (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \ | |
840 | fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \ | |
841 | fRTMP_ADAPTER_REMOVE_IN_PROGRESS | fRTMP_ADAPTER_BULKIN_RESET) | |
842 | ||
843 | #define fRTMP_ADAPTER_NEED_STOP_HANDLE_RX \ | |
844 | (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \ | |
845 | fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \ | |
846 | fRTMP_ADAPTER_REMOVE_IN_PROGRESS) | |
847 | ||
51126deb | 848 | void RTUSBBulkReceive(IN PRTMP_ADAPTER pAd) |
c55519ff | 849 | { |
66cd8d6e BZ |
850 | PRX_CONTEXT pRxContext; |
851 | unsigned long IrqFlags; | |
c55519ff GKH |
852 | |
853 | /* sanity check */ | |
854 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_HANDLE_RX)) | |
855 | return; | |
856 | ||
66cd8d6e | 857 | while (1) { |
c55519ff GKH |
858 | |
859 | RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); | |
860 | pRxContext = &(pAd->RxContext[pAd->NextRxBulkInReadIndex]); | |
66cd8d6e BZ |
861 | if (((pRxContext->InUse == FALSE) |
862 | && (pRxContext->Readable == TRUE)) | |
863 | && (pRxContext->bRxHandling == FALSE)) { | |
c55519ff GKH |
864 | pRxContext->bRxHandling = TRUE; |
865 | RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); | |
866 | ||
9f548a2a | 867 | /* read RxContext, Since not */ |
303ee97d | 868 | STARxDoneInterruptHandle(pAd, TRUE); |
c55519ff | 869 | |
9f548a2a | 870 | /* Finish to handle this bulkIn buffer. */ |
c55519ff GKH |
871 | RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); |
872 | pRxContext->BulkInOffset = 0; | |
873 | pRxContext->Readable = FALSE; | |
874 | pRxContext->bRxHandling = FALSE; | |
875 | pAd->ReadPosition = 0; | |
876 | pAd->TransferBufferLength = 0; | |
66cd8d6e BZ |
877 | INC_RING_INDEX(pAd->NextRxBulkInReadIndex, |
878 | RX_RING_SIZE); | |
c55519ff GKH |
879 | RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); |
880 | ||
66cd8d6e | 881 | } else { |
c55519ff GKH |
882 | RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); |
883 | break; | |
884 | } | |
885 | } | |
886 | ||
887 | if (!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_RX))) | |
888 | DoBulkIn(pAd); | |
889 | ||
890 | } | |
891 | ||
c55519ff GKH |
892 | /* |
893 | ======================================================================== | |
894 | ||
895 | Routine Description: | |
896 | This routine process Rx Irp and call rx complete function. | |
897 | ||
898 | Arguments: | |
899 | DeviceObject Pointer to the device object for next lower | |
900 | device. DeviceObject passed in here belongs to | |
901 | the next lower driver in the stack because we | |
902 | were invoked via IoCallDriver in USB_RxPacket | |
903 | AND it is not OUR device object | |
904 | Irp Ptr to completed IRP | |
905 | Context Ptr to our Adapter object (context specified | |
906 | in IoSetCompletionRoutine | |
907 | ||
908 | Return Value: | |
909 | Always returns STATUS_MORE_PROCESSING_REQUIRED | |
910 | ||
911 | Note: | |
912 | Always returns STATUS_MORE_PROCESSING_REQUIRED | |
913 | ======================================================================== | |
914 | */ | |
51126deb | 915 | void RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs) |
c55519ff | 916 | { |
9f548a2a BZ |
917 | /* use a receive tasklet to handle received packets; */ |
918 | /* or sometimes hardware IRQ will be disabled here, so we can not */ | |
919 | /* use spin_lock_bh()/spin_unlock_bh() after IRQ is disabled. :< */ | |
66cd8d6e BZ |
920 | PRX_CONTEXT pRxContext; |
921 | PRTMP_ADAPTER pAd; | |
922 | POS_COOKIE pObj; | |
c55519ff | 923 | |
66cd8d6e BZ |
924 | pRxContext = (PRX_CONTEXT) pUrb->context; |
925 | pAd = pRxContext->pAd; | |
926 | pObj = (POS_COOKIE) pAd->OS_Cookie; | |
c55519ff GKH |
927 | |
928 | pObj->rx_done_task.data = (unsigned long)pUrb; | |
929 | tasklet_hi_schedule(&pObj->rx_done_task); | |
930 | ||
931 | } | |
932 | ||
c55519ff GKH |
933 | /* |
934 | ======================================================================== | |
935 | ||
936 | Routine Description: | |
937 | ||
938 | Arguments: | |
939 | ||
940 | Return Value: | |
941 | ||
942 | Note: | |
943 | ||
944 | ======================================================================== | |
945 | */ | |
51126deb | 946 | void RTUSBKickBulkOut(IN PRTMP_ADAPTER pAd) |
c55519ff | 947 | { |
9f548a2a | 948 | /* BulkIn Reset will reset whole USB PHY. So we need to make sure fRTMP_ADAPTER_BULKIN_RESET not flaged. */ |
66cd8d6e BZ |
949 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX) |
950 | ) { | |
9f548a2a | 951 | /* 2. PS-Poll frame is next */ |
66cd8d6e | 952 | if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL)) { |
c55519ff GKH |
953 | RTUSBBulkOutPsPoll(pAd); |
954 | } | |
9f548a2a | 955 | /* 5. Mlme frame is next */ |
ca97b838 | 956 | else if ((RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME)) || |
66cd8d6e | 957 | (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE)) { |
c55519ff GKH |
958 | RTUSBBulkOutMLMEPacket(pAd, pAd->MgmtRing.TxDmaIdx); |
959 | } | |
9f548a2a | 960 | /* 6. Data frame normal is next */ |
66cd8d6e BZ |
961 | if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL)) { |
962 | if (((!RTMP_TEST_FLAG | |
963 | (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | |
964 | || | |
965 | (!OPSTATUS_TEST_FLAG | |
966 | (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) | |
967 | )) { | |
968 | RTUSBBulkOutDataPacket(pAd, 0, | |
969 | pAd-> | |
970 | NextBulkOutIndex[0]); | |
c55519ff GKH |
971 | } |
972 | } | |
66cd8d6e BZ |
973 | if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_2)) { |
974 | if (((!RTMP_TEST_FLAG | |
975 | (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | |
976 | || | |
977 | (!OPSTATUS_TEST_FLAG | |
978 | (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) | |
979 | )) { | |
980 | RTUSBBulkOutDataPacket(pAd, 1, | |
981 | pAd-> | |
982 | NextBulkOutIndex[1]); | |
c55519ff GKH |
983 | } |
984 | } | |
66cd8d6e BZ |
985 | if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_3)) { |
986 | if (((!RTMP_TEST_FLAG | |
987 | (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | |
988 | || | |
989 | (!OPSTATUS_TEST_FLAG | |
990 | (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) | |
991 | )) { | |
992 | RTUSBBulkOutDataPacket(pAd, 2, | |
993 | pAd-> | |
994 | NextBulkOutIndex[2]); | |
c55519ff GKH |
995 | } |
996 | } | |
66cd8d6e BZ |
997 | if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_4)) { |
998 | if (((!RTMP_TEST_FLAG | |
999 | (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | |
1000 | || | |
1001 | (!OPSTATUS_TEST_FLAG | |
1002 | (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) | |
1003 | )) { | |
1004 | RTUSBBulkOutDataPacket(pAd, 3, | |
1005 | pAd-> | |
1006 | NextBulkOutIndex[3]); | |
c55519ff GKH |
1007 | } |
1008 | } | |
9f548a2a | 1009 | /* 7. Null frame is the last */ |
66cd8d6e BZ |
1010 | else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL)) { |
1011 | if (!RTMP_TEST_FLAG | |
1012 | (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { | |
c55519ff GKH |
1013 | RTUSBBulkOutNullFrame(pAd); |
1014 | } | |
1015 | } | |
9f548a2a | 1016 | /* 8. No data avaliable */ |
66cd8d6e | 1017 | else { |
c55519ff GKH |
1018 | |
1019 | } | |
1020 | } | |
c55519ff GKH |
1021 | } |
1022 | ||
1023 | /* | |
1024 | ======================================================================== | |
1025 | ||
1026 | Routine Description: | |
1027 | Call from Reset action after BulkOut failed. | |
1028 | Arguments: | |
1029 | ||
1030 | Return Value: | |
1031 | ||
1032 | Note: | |
1033 | ||
1034 | ======================================================================== | |
1035 | */ | |
51126deb | 1036 | void RTUSBCleanUpDataBulkOutQueue(IN PRTMP_ADAPTER pAd) |
c55519ff | 1037 | { |
51126deb | 1038 | u8 Idx; |
66cd8d6e | 1039 | PHT_TX_CONTEXT pTxContext; |
c55519ff GKH |
1040 | |
1041 | DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpDataBulkOutQueue\n")); | |
1042 | ||
66cd8d6e | 1043 | for (Idx = 0; Idx < 4; Idx++) { |
c55519ff GKH |
1044 | pTxContext = &pAd->TxContext[Idx]; |
1045 | ||
1046 | pTxContext->CurWritePosition = pTxContext->NextBulkOutPosition; | |
1047 | pTxContext->LastOne = FALSE; | |
1048 | NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]); | |
1049 | pAd->BulkOutPending[Idx] = FALSE; | |
1050 | NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]); | |
1051 | } | |
1052 | ||
1053 | DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpDataBulkOutQueue\n")); | |
1054 | } | |
1055 | ||
1056 | /* | |
1057 | ======================================================================== | |
1058 | ||
1059 | Routine Description: | |
1060 | ||
1061 | Arguments: | |
1062 | ||
1063 | Return Value: | |
1064 | ||
1065 | Note: | |
1066 | ||
1067 | ======================================================================== | |
1068 | */ | |
51126deb | 1069 | void RTUSBCleanUpMLMEBulkOutQueue(IN PRTMP_ADAPTER pAd) |
c55519ff GKH |
1070 | { |
1071 | DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpMLMEBulkOutQueue\n")); | |
c55519ff GKH |
1072 | DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpMLMEBulkOutQueue\n")); |
1073 | } | |
1074 | ||
c55519ff GKH |
1075 | /* |
1076 | ======================================================================== | |
1077 | ||
1078 | Routine Description: | |
1079 | ||
1080 | Arguments: | |
1081 | ||
1082 | Return Value: | |
1083 | ||
c55519ff GKH |
1084 | Note: |
1085 | ||
1086 | ======================================================================== | |
1087 | */ | |
51126deb | 1088 | void RTUSBCancelPendingIRPs(IN PRTMP_ADAPTER pAd) |
c55519ff GKH |
1089 | { |
1090 | RTUSBCancelPendingBulkInIRP(pAd); | |
1091 | RTUSBCancelPendingBulkOutIRP(pAd); | |
1092 | } | |
1093 | ||
1094 | /* | |
1095 | ======================================================================== | |
1096 | ||
1097 | Routine Description: | |
1098 | ||
1099 | Arguments: | |
1100 | ||
1101 | Return Value: | |
1102 | ||
1103 | Note: | |
1104 | ||
1105 | ======================================================================== | |
1106 | */ | |
51126deb | 1107 | void RTUSBCancelPendingBulkInIRP(IN PRTMP_ADAPTER pAd) |
c55519ff | 1108 | { |
66cd8d6e | 1109 | PRX_CONTEXT pRxContext; |
51126deb | 1110 | u32 i; |
c55519ff GKH |
1111 | |
1112 | DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->RTUSBCancelPendingBulkInIRP\n")); | |
66cd8d6e | 1113 | for (i = 0; i < (RX_RING_SIZE); i++) { |
c55519ff | 1114 | pRxContext = &(pAd->RxContext[i]); |
66cd8d6e | 1115 | if (pRxContext->IRPPending == TRUE) { |
c55519ff GKH |
1116 | RTUSB_UNLINK_URB(pRxContext->pUrb); |
1117 | pRxContext->IRPPending = FALSE; | |
1118 | pRxContext->InUse = FALSE; | |
9f548a2a BZ |
1119 | /*NdisInterlockedDecrement(&pAd->PendingRx); */ |
1120 | /*pAd->PendingRx--; */ | |
c55519ff GKH |
1121 | } |
1122 | } | |
1123 | DBGPRINT_RAW(RT_DEBUG_TRACE, ("<---RTUSBCancelPendingBulkInIRP\n")); | |
1124 | } | |
1125 | ||
c55519ff GKH |
1126 | /* |
1127 | ======================================================================== | |
1128 | ||
1129 | Routine Description: | |
1130 | ||
1131 | Arguments: | |
1132 | ||
1133 | Return Value: | |
1134 | ||
1135 | Note: | |
1136 | ||
1137 | ======================================================================== | |
1138 | */ | |
51126deb | 1139 | void RTUSBCancelPendingBulkOutIRP(IN PRTMP_ADAPTER pAd) |
c55519ff | 1140 | { |
66cd8d6e BZ |
1141 | PHT_TX_CONTEXT pHTTXContext; |
1142 | PTX_CONTEXT pMLMEContext; | |
1143 | PTX_CONTEXT pBeaconContext; | |
1144 | PTX_CONTEXT pNullContext; | |
1145 | PTX_CONTEXT pPsPollContext; | |
1146 | PTX_CONTEXT pRTSContext; | |
51126deb | 1147 | u32 i, Idx; |
9f548a2a BZ |
1148 | /* unsigned int IrqFlags; */ |
1149 | /* NDIS_SPIN_LOCK *pLock; */ | |
1150 | /* BOOLEAN *pPending; */ | |
66cd8d6e | 1151 | |
9f548a2a BZ |
1152 | /* pLock = &pAd->BulkOutLock[MGMTPIPEIDX]; */ |
1153 | /* pPending = &pAd->BulkOutPending[MGMTPIPEIDX]; */ | |
66cd8d6e BZ |
1154 | |
1155 | for (Idx = 0; Idx < 4; Idx++) { | |
c55519ff GKH |
1156 | pHTTXContext = &(pAd->TxContext[Idx]); |
1157 | ||
66cd8d6e | 1158 | if (pHTTXContext->IRPPending == TRUE) { |
c55519ff | 1159 | |
9f548a2a BZ |
1160 | /* Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself */ |
1161 | /* remove it from the HeadPendingSendList and NULL out HeadPendingSendList */ | |
1162 | /* when the last IRP on the list has been cancelled; that's how we exit this loop */ | |
1163 | /* */ | |
c55519ff GKH |
1164 | |
1165 | RTUSB_UNLINK_URB(pHTTXContext->pUrb); | |
1166 | ||
9f548a2a | 1167 | /* Sleep 200 microseconds to give cancellation time to work */ |
c55519ff GKH |
1168 | RTMPusecDelay(200); |
1169 | } | |
1170 | ||
c55519ff GKH |
1171 | pAd->BulkOutPending[Idx] = FALSE; |
1172 | } | |
1173 | ||
9f548a2a | 1174 | /*RTMP_IRQ_LOCK(pLock, IrqFlags); */ |
66cd8d6e BZ |
1175 | for (i = 0; i < MGMT_RING_SIZE; i++) { |
1176 | pMLMEContext = (PTX_CONTEXT) pAd->MgmtRing.Cell[i].AllocVa; | |
1177 | if (pMLMEContext && (pMLMEContext->IRPPending == TRUE)) { | |
c55519ff | 1178 | |
9f548a2a BZ |
1179 | /* Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself */ |
1180 | /* remove it from the HeadPendingSendList and NULL out HeadPendingSendList */ | |
1181 | /* when the last IRP on the list has been cancelled; that's how we exit this loop */ | |
1182 | /* */ | |
c55519ff GKH |
1183 | |
1184 | RTUSB_UNLINK_URB(pMLMEContext->pUrb); | |
1185 | pMLMEContext->IRPPending = FALSE; | |
1186 | ||
9f548a2a | 1187 | /* Sleep 200 microsecs to give cancellation time to work */ |
c55519ff GKH |
1188 | RTMPusecDelay(200); |
1189 | } | |
1190 | } | |
1191 | pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; | |
9f548a2a | 1192 | /*RTMP_IRQ_UNLOCK(pLock, IrqFlags); */ |
c55519ff | 1193 | |
66cd8d6e | 1194 | for (i = 0; i < BEACON_RING_SIZE; i++) { |
c55519ff GKH |
1195 | pBeaconContext = &(pAd->BeaconContext[i]); |
1196 | ||
66cd8d6e | 1197 | if (pBeaconContext->IRPPending == TRUE) { |
c55519ff | 1198 | |
9f548a2a BZ |
1199 | /* Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself */ |
1200 | /* remove it from the HeadPendingSendList and NULL out HeadPendingSendList */ | |
1201 | /* when the last IRP on the list has been cancelled; that's how we exit this loop */ | |
1202 | /* */ | |
c55519ff GKH |
1203 | |
1204 | RTUSB_UNLINK_URB(pBeaconContext->pUrb); | |
1205 | ||
9f548a2a | 1206 | /* Sleep 200 microsecs to give cancellation time to work */ |
c55519ff GKH |
1207 | RTMPusecDelay(200); |
1208 | } | |
1209 | } | |
1210 | ||
1211 | pNullContext = &(pAd->NullContext); | |
1212 | if (pNullContext->IRPPending == TRUE) | |
1213 | RTUSB_UNLINK_URB(pNullContext->pUrb); | |
1214 | ||
1215 | pRTSContext = &(pAd->RTSContext); | |
1216 | if (pRTSContext->IRPPending == TRUE) | |
1217 | RTUSB_UNLINK_URB(pRTSContext->pUrb); | |
1218 | ||
1219 | pPsPollContext = &(pAd->PsPollContext); | |
1220 | if (pPsPollContext->IRPPending == TRUE) | |
1221 | RTUSB_UNLINK_URB(pPsPollContext->pUrb); | |
1222 | ||
66cd8d6e | 1223 | for (Idx = 0; Idx < 4; Idx++) { |
c55519ff GKH |
1224 | NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]); |
1225 | pAd->BulkOutPending[Idx] = FALSE; | |
1226 | NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]); | |
1227 | } | |
1228 | } | |
1229 | ||
9f548a2a | 1230 | #endif /* RTMP_MAC_USB // */ |