staging: rt2860: '&pointer[0]' to 'pointer' fix
[pandora-kernel.git] / drivers / staging / rt2860 / common / cmm_mac_usb.c
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 #ifdef RTMP_MAC_USB
29
30 #include        "../rt_config.h"
31
32 /*
33 ========================================================================
34 Routine Description:
35     Initialize receive data structures.
36
37 Arguments:
38     pAd                                 Pointer to our adapter
39
40 Return Value:
41         NDIS_STATUS_SUCCESS
42         NDIS_STATUS_RESOURCES
43
44 Note:
45         Initialize all receive releated private buffer, include those define
46         in struct rt_rtmp_adapter structure and all private data structures. The mahor
47         work is to allocate buffer for each packet and chain buffer to
48         NDIS packet descriptor.
49 ========================================================================
50 */
51 int NICInitRecv(struct rt_rtmp_adapter *pAd)
52 {
53         u8 i;
54         int Status = NDIS_STATUS_SUCCESS;
55         struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie;
56
57         DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitRecv\n"));
58         pObj = pObj;
59
60         /*InterlockedExchange(&pAd->PendingRx, 0); */
61         pAd->PendingRx = 0;
62         pAd->NextRxBulkInReadIndex = 0; /* Next Rx Read index */
63         pAd->NextRxBulkInIndex = 0;     /*RX_RING_SIZE -1; // Rx Bulk pointer */
64         pAd->NextRxBulkInPosition = 0;
65
66         for (i = 0; i < (RX_RING_SIZE); i++) {
67                 struct rt_rx_context *pRxContext = &(pAd->RxContext[i]);
68
69                 /*Allocate URB */
70                 pRxContext->pUrb = RTUSB_ALLOC_URB(0);
71                 if (pRxContext->pUrb == NULL) {
72                         Status = NDIS_STATUS_RESOURCES;
73                         goto out1;
74                 }
75                 /* Allocate transfer buffer */
76                 pRxContext->TransferBuffer =
77                     RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE,
78                                            &pRxContext->data_dma);
79                 if (pRxContext->TransferBuffer == NULL) {
80                         Status = NDIS_STATUS_RESOURCES;
81                         goto out1;
82                 }
83
84                 NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE);
85
86                 pRxContext->pAd = pAd;
87                 pRxContext->pIrp = NULL;
88                 pRxContext->InUse = FALSE;
89                 pRxContext->IRPPending = FALSE;
90                 pRxContext->Readable = FALSE;
91                 /*pRxContext->ReorderInUse = FALSE; */
92                 pRxContext->bRxHandling = FALSE;
93                 pRxContext->BulkInOffset = 0;
94         }
95
96         DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitRecv(Status=%d)\n", Status));
97         return Status;
98
99 out1:
100         for (i = 0; i < (RX_RING_SIZE); i++) {
101                 struct rt_rx_context *pRxContext = &(pAd->RxContext[i]);
102
103                 if (NULL != pRxContext->TransferBuffer) {
104                         RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE,
105                                               pRxContext->TransferBuffer,
106                                               pRxContext->data_dma);
107                         pRxContext->TransferBuffer = NULL;
108                 }
109
110                 if (NULL != pRxContext->pUrb) {
111                         RTUSB_UNLINK_URB(pRxContext->pUrb);
112                         RTUSB_FREE_URB(pRxContext->pUrb);
113                         pRxContext->pUrb = NULL;
114                 }
115         }
116
117         return Status;
118 }
119
120 /*
121 ========================================================================
122 Routine Description:
123     Initialize transmit data structures.
124
125 Arguments:
126     pAd                                 Pointer to our adapter
127
128 Return Value:
129         NDIS_STATUS_SUCCESS
130         NDIS_STATUS_RESOURCES
131
132 Note:
133 ========================================================================
134 */
135 int NICInitTransmit(struct rt_rtmp_adapter *pAd)
136 {
137 #define LM_USB_ALLOC(pObj, Context, TB_Type, BufferSize, Status, msg1, err1, msg2, err2)        \
138         Context->pUrb = RTUSB_ALLOC_URB(0);             \
139         if (Context->pUrb == NULL) {                    \
140                 DBGPRINT(RT_DEBUG_ERROR, msg1);         \
141                 Status = NDIS_STATUS_RESOURCES;         \
142                 goto err1; }                                            \
143                                                                                         \
144         Context->TransferBuffer =                               \
145                 (TB_Type)RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, BufferSize, &Context->data_dma);        \
146         if (Context->TransferBuffer == NULL) {  \
147                 DBGPRINT(RT_DEBUG_ERROR, msg2);         \
148                 Status = NDIS_STATUS_RESOURCES;         \
149                 goto err2; }
150
151 #define LM_URB_FREE(pObj, Context, BufferSize)                          \
152         if (NULL != Context->pUrb) {                                                    \
153                 RTUSB_UNLINK_URB(Context->pUrb);                                        \
154                 RTUSB_FREE_URB(Context->pUrb);                                          \
155                 Context->pUrb = NULL; }                                                         \
156         if (NULL != Context->TransferBuffer) {                          \
157                 RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize,       \
158                                                                 Context->TransferBuffer,        \
159                                                                 Context->data_dma);                     \
160                 Context->TransferBuffer = NULL; }
161
162         u8 i, acidx;
163         int Status = NDIS_STATUS_SUCCESS;
164         struct rt_tx_context *pNullContext = &(pAd->NullContext);
165         struct rt_tx_context *pPsPollContext = &(pAd->PsPollContext);
166         struct rt_tx_context *pRTSContext = &(pAd->RTSContext);
167         struct rt_tx_context *pMLMEContext = NULL;
168 /*      struct rt_ht_tx_context *pHTTXContext = NULL; */
169         struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie;
170         void *RingBaseVa;
171 /*      struct rt_rtmp_tx_ring *pTxRing; */
172         struct rt_rtmp_mgmt_ring *pMgmtRing;
173
174         DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTransmit\n"));
175         pObj = pObj;
176
177         /* Init 4 set of Tx parameters */
178         for (acidx = 0; acidx < NUM_OF_TX_RING; acidx++) {
179                 /* Initialize all Transmit releated queues */
180                 InitializeQueueHeader(&pAd->TxSwQueue[acidx]);
181
182                 /* Next Local tx ring pointer waiting for buck out */
183                 pAd->NextBulkOutIndex[acidx] = acidx;
184                 pAd->BulkOutPending[acidx] = FALSE;     /* Buck Out control flag */
185                 /*pAd->DataBulkDoneIdx[acidx] = 0; */
186         }
187
188         /*pAd->NextMLMEIndex    = 0; */
189         /*pAd->PushMgmtIndex    = 0; */
190         /*pAd->PopMgmtIndex     = 0; */
191         /*InterlockedExchange(&pAd->MgmtQueueSize, 0); */
192         /*InterlockedExchange(&pAd->TxCount, 0); */
193
194         /*pAd->PrioRingFirstIndex       = 0; */
195         /*pAd->PrioRingTxCnt            = 0; */
196
197         do {
198                 /* */
199                 /* TX_RING_SIZE, 4 ACs */
200                 /* */
201                 for (acidx = 0; acidx < 4; acidx++) {
202                         struct rt_ht_tx_context *pHTTXContext = &(pAd->TxContext[acidx]);
203
204                         NdisZeroMemory(pHTTXContext, sizeof(struct rt_ht_tx_context));
205                         /*Allocate URB */
206                         LM_USB_ALLOC(pObj, pHTTXContext, struct rt_httx_buffer *,
207                                      sizeof(struct rt_httx_buffer), Status,
208                                      ("<-- ERROR in Alloc TX TxContext[%d] urb!\n",
209                                       acidx), done,
210                                      ("<-- ERROR in Alloc TX TxContext[%d] struct rt_httx_buffer!\n",
211                                       acidx), out1);
212
213                         NdisZeroMemory(pHTTXContext->TransferBuffer->
214                                        Aggregation, 4);
215                         pHTTXContext->pAd = pAd;
216                         pHTTXContext->pIrp = NULL;
217                         pHTTXContext->IRPPending = FALSE;
218                         pHTTXContext->NextBulkOutPosition = 0;
219                         pHTTXContext->ENextBulkOutPosition = 0;
220                         pHTTXContext->CurWritePosition = 0;
221                         pHTTXContext->CurWriteRealPos = 0;
222                         pHTTXContext->BulkOutSize = 0;
223                         pHTTXContext->BulkOutPipeId = acidx;
224                         pHTTXContext->bRingEmpty = TRUE;
225                         pHTTXContext->bCopySavePad = FALSE;
226                         pAd->BulkOutPending[acidx] = FALSE;
227                 }
228
229                 /* */
230                 /* MGMT_RING_SIZE */
231                 /* */
232
233                 /* Allocate MGMT ring descriptor's memory */
234                 pAd->MgmtDescRing.AllocSize =
235                     MGMT_RING_SIZE * sizeof(struct rt_tx_context);
236                 os_alloc_mem(pAd, (u8 **) (&pAd->MgmtDescRing.AllocVa),
237                              pAd->MgmtDescRing.AllocSize);
238                 if (pAd->MgmtDescRing.AllocVa == NULL) {
239                         DBGPRINT_ERR(("Failed to allocate a big buffer for MgmtDescRing!\n"));
240                         Status = NDIS_STATUS_RESOURCES;
241                         goto out1;
242                 }
243                 NdisZeroMemory(pAd->MgmtDescRing.AllocVa,
244                                pAd->MgmtDescRing.AllocSize);
245                 RingBaseVa = pAd->MgmtDescRing.AllocVa;
246
247                 /* Initialize MGMT Ring and associated buffer memory */
248                 pMgmtRing = &pAd->MgmtRing;
249                 for (i = 0; i < MGMT_RING_SIZE; i++) {
250                         /* link the pre-allocated Mgmt buffer to MgmtRing.Cell */
251                         pMgmtRing->Cell[i].AllocSize = sizeof(struct rt_tx_context);
252                         pMgmtRing->Cell[i].AllocVa = RingBaseVa;
253                         pMgmtRing->Cell[i].pNdisPacket = NULL;
254                         pMgmtRing->Cell[i].pNextNdisPacket = NULL;
255
256                         /*Allocate URB for MLMEContext */
257                         pMLMEContext =
258                             (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa;
259                         pMLMEContext->pUrb = RTUSB_ALLOC_URB(0);
260                         if (pMLMEContext->pUrb == NULL) {
261                                 DBGPRINT(RT_DEBUG_ERROR,
262                                          ("<-- ERROR in Alloc TX MLMEContext[%d] urb!\n",
263                                           i));
264                                 Status = NDIS_STATUS_RESOURCES;
265                                 goto out2;
266                         }
267                         pMLMEContext->pAd = pAd;
268                         pMLMEContext->pIrp = NULL;
269                         pMLMEContext->TransferBuffer = NULL;
270                         pMLMEContext->InUse = FALSE;
271                         pMLMEContext->IRPPending = FALSE;
272                         pMLMEContext->bWaitingBulkOut = FALSE;
273                         pMLMEContext->BulkOutSize = 0;
274                         pMLMEContext->SelfIdx = i;
275
276                         /* Offset to next ring descriptor address */
277                         RingBaseVa = (u8 *)RingBaseVa + sizeof(struct rt_tx_context);
278                 }
279                 DBGPRINT(RT_DEBUG_TRACE,
280                          ("MGMT Ring: total %d entry allocated\n", i));
281
282                 /*pAd->MgmtRing.TxSwFreeIdx = (MGMT_RING_SIZE - 1); */
283                 pAd->MgmtRing.TxSwFreeIdx = MGMT_RING_SIZE;
284                 pAd->MgmtRing.TxCpuIdx = 0;
285                 pAd->MgmtRing.TxDmaIdx = 0;
286
287                 /* */
288                 /* BEACON_RING_SIZE */
289                 /* */
290                 for (i = 0; i < BEACON_RING_SIZE; i++)  /* 2 */
291                 {
292                         struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]);
293
294                         NdisZeroMemory(pBeaconContext, sizeof(struct rt_tx_context));
295
296                         /*Allocate URB */
297                         LM_USB_ALLOC(pObj, pBeaconContext, struct rt_tx_buffer *,
298                                      sizeof(struct rt_tx_buffer), Status,
299                                      ("<-- ERROR in Alloc TX BeaconContext[%d] urb!\n",
300                                       i), out2,
301                                      ("<-- ERROR in Alloc TX BeaconContext[%d] struct rt_tx_buffer!\n",
302                                       i), out3);
303
304                         pBeaconContext->pAd = pAd;
305                         pBeaconContext->pIrp = NULL;
306                         pBeaconContext->InUse = FALSE;
307                         pBeaconContext->IRPPending = FALSE;
308                 }
309
310                 /* */
311                 /* NullContext */
312                 /* */
313                 NdisZeroMemory(pNullContext, sizeof(struct rt_tx_context));
314
315                 /*Allocate URB */
316                 LM_USB_ALLOC(pObj, pNullContext, struct rt_tx_buffer *, sizeof(struct rt_tx_buffer),
317                              Status,
318                              ("<-- ERROR in Alloc TX NullContext urb!\n"),
319                              out3,
320                              ("<-- ERROR in Alloc TX NullContext struct rt_tx_buffer!\n"),
321                              out4);
322
323                 pNullContext->pAd = pAd;
324                 pNullContext->pIrp = NULL;
325                 pNullContext->InUse = FALSE;
326                 pNullContext->IRPPending = FALSE;
327
328                 /* */
329                 /* RTSContext */
330                 /* */
331                 NdisZeroMemory(pRTSContext, sizeof(struct rt_tx_context));
332
333                 /*Allocate URB */
334                 LM_USB_ALLOC(pObj, pRTSContext, struct rt_tx_buffer *, sizeof(struct rt_tx_buffer),
335                              Status,
336                              ("<-- ERROR in Alloc TX RTSContext urb!\n"),
337                              out4,
338                              ("<-- ERROR in Alloc TX RTSContext struct rt_tx_buffer!\n"),
339                              out5);
340
341                 pRTSContext->pAd = pAd;
342                 pRTSContext->pIrp = NULL;
343                 pRTSContext->InUse = FALSE;
344                 pRTSContext->IRPPending = FALSE;
345
346                 /* */
347                 /* PsPollContext */
348                 /* */
349                 /*NdisZeroMemory(pPsPollContext, sizeof(struct rt_tx_context)); */
350                 /*Allocate URB */
351                 LM_USB_ALLOC(pObj, pPsPollContext, struct rt_tx_buffer *,
352                              sizeof(struct rt_tx_buffer), Status,
353                              ("<-- ERROR in Alloc TX PsPollContext urb!\n"),
354                              out5,
355                              ("<-- ERROR in Alloc TX PsPollContext struct rt_tx_buffer!\n"),
356                              out6);
357
358                 pPsPollContext->pAd = pAd;
359                 pPsPollContext->pIrp = NULL;
360                 pPsPollContext->InUse = FALSE;
361                 pPsPollContext->IRPPending = FALSE;
362                 pPsPollContext->bAggregatible = FALSE;
363                 pPsPollContext->LastOne = TRUE;
364
365         } while (FALSE);
366
367 done:
368         DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTransmit(Status=%d)\n", Status));
369
370         return Status;
371
372         /* --------------------------- ERROR HANDLE --------------------------- */
373 out6:
374         LM_URB_FREE(pObj, pPsPollContext, sizeof(struct rt_tx_buffer));
375
376 out5:
377         LM_URB_FREE(pObj, pRTSContext, sizeof(struct rt_tx_buffer));
378
379 out4:
380         LM_URB_FREE(pObj, pNullContext, sizeof(struct rt_tx_buffer));
381
382 out3:
383         for (i = 0; i < BEACON_RING_SIZE; i++) {
384                 struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]);
385                 if (pBeaconContext)
386                         LM_URB_FREE(pObj, pBeaconContext, sizeof(struct rt_tx_buffer));
387         }
388
389 out2:
390         if (pAd->MgmtDescRing.AllocVa) {
391                 pMgmtRing = &pAd->MgmtRing;
392                 for (i = 0; i < MGMT_RING_SIZE; i++) {
393                         pMLMEContext =
394                             (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa;
395                         if (pMLMEContext)
396                                 LM_URB_FREE(pObj, pMLMEContext,
397                                             sizeof(struct rt_tx_buffer));
398                 }
399                 os_free_mem(pAd, pAd->MgmtDescRing.AllocVa);
400                 pAd->MgmtDescRing.AllocVa = NULL;
401         }
402
403 out1:
404         for (acidx = 0; acidx < 4; acidx++) {
405                 struct rt_ht_tx_context *pTxContext = &(pAd->TxContext[acidx]);
406                 if (pTxContext)
407                         LM_URB_FREE(pObj, pTxContext, sizeof(struct rt_httx_buffer));
408         }
409
410         /* Here we didn't have any pre-allocated memory need to free. */
411
412         return Status;
413 }
414
415 /*
416 ========================================================================
417 Routine Description:
418     Allocate DMA memory blocks for send, receive.
419
420 Arguments:
421     pAd                                 Pointer to our adapter
422
423 Return Value:
424         NDIS_STATUS_SUCCESS
425         NDIS_STATUS_FAILURE
426         NDIS_STATUS_RESOURCES
427
428 Note:
429 ========================================================================
430 */
431 int RTMPAllocTxRxRingMemory(struct rt_rtmp_adapter *pAd)
432 {
433 /*      struct rt_counter_802_11  pCounter = &pAd->WlanCounters; */
434         int Status;
435         int num;
436
437         DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n"));
438
439         do {
440                 /* Init the struct rt_cmdq and CmdQLock */
441                 NdisAllocateSpinLock(&pAd->CmdQLock);
442                 NdisAcquireSpinLock(&pAd->CmdQLock);
443                 RTUSBInitializeCmdQ(&pAd->CmdQ);
444                 NdisReleaseSpinLock(&pAd->CmdQLock);
445
446                 NdisAllocateSpinLock(&pAd->MLMEBulkOutLock);
447                 /*NdisAllocateSpinLock(&pAd->MLMEWaitQueueLock); */
448                 NdisAllocateSpinLock(&pAd->BulkOutLock[0]);
449                 NdisAllocateSpinLock(&pAd->BulkOutLock[1]);
450                 NdisAllocateSpinLock(&pAd->BulkOutLock[2]);
451                 NdisAllocateSpinLock(&pAd->BulkOutLock[3]);
452                 NdisAllocateSpinLock(&pAd->BulkOutLock[4]);
453                 NdisAllocateSpinLock(&pAd->BulkOutLock[5]);
454                 NdisAllocateSpinLock(&pAd->BulkInLock);
455
456                 for (num = 0; num < NUM_OF_TX_RING; num++) {
457                         NdisAllocateSpinLock(&pAd->TxContextQueueLock[num]);
458                 }
459
460 /*              NdisAllocateSpinLock(&pAd->MemLock);    // Not used in RT28XX */
461
462 /*              NdisAllocateSpinLock(&pAd->MacTabLock); // init it in UserCfgInit() */
463 /*              NdisAllocateSpinLock(&pAd->BATabLock); // init it in BATableInit() */
464
465 /*              for(num=0; num<MAX_LEN_OF_BA_REC_TABLE; num++) */
466 /*              { */
467 /*                      NdisAllocateSpinLock(&pAd->BATable.BARecEntry[num].RxReRingLock); */
468 /*              } */
469
470                 /* */
471                 /* Init Mac Table */
472                 /* */
473 /*              MacTableInitialize(pAd); */
474
475                 /* */
476                 /* Init send data structures and related parameters */
477                 /* */
478                 Status = NICInitTransmit(pAd);
479                 if (Status != NDIS_STATUS_SUCCESS)
480                         break;
481
482                 /* */
483                 /* Init receive data structures and related parameters */
484                 /* */
485                 Status = NICInitRecv(pAd);
486                 if (Status != NDIS_STATUS_SUCCESS)
487                         break;
488
489                 pAd->PendingIoCount = 1;
490
491         } while (FALSE);
492
493         NdisZeroMemory(&pAd->FragFrame, sizeof(struct rt_fragment_frame));
494         pAd->FragFrame.pFragPacket =
495             RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
496
497         if (pAd->FragFrame.pFragPacket == NULL) {
498                 Status = NDIS_STATUS_RESOURCES;
499         }
500
501         DBGPRINT_S(Status,
502                    ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
503         return Status;
504 }
505
506 /*
507 ========================================================================
508 Routine Description:
509         Calls USB_InterfaceStop and frees memory allocated for the URBs
510     calls NdisMDeregisterDevice and frees the memory
511     allocated in VNetInitialize for the Adapter Object
512
513 Arguments:
514         *pAd                            the raxx interface data pointer
515
516 Return Value:
517         None
518
519 Note:
520 ========================================================================
521 */
522 void RTMPFreeTxRxRingMemory(struct rt_rtmp_adapter *pAd)
523 {
524 #define LM_URB_FREE(pObj, Context, BufferSize)                          \
525         if (NULL != Context->pUrb) {                                                    \
526                 RTUSB_UNLINK_URB(Context->pUrb);                                        \
527                 RTUSB_FREE_URB(Context->pUrb);                                          \
528                 Context->pUrb = NULL; }                                                         \
529         if (NULL != Context->TransferBuffer) {                                  \
530                 RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize,       \
531                                                                 Context->TransferBuffer,        \
532                                                                 Context->data_dma);                     \
533                 Context->TransferBuffer = NULL; }
534
535         u32 i, acidx;
536         struct rt_tx_context *pNullContext = &pAd->NullContext;
537         struct rt_tx_context *pPsPollContext = &pAd->PsPollContext;
538         struct rt_tx_context *pRTSContext = &pAd->RTSContext;
539 /*      struct rt_ht_tx_context *pHTTXContext; */
540         /*PRTMP_REORDERBUF      pReorderBuf; */
541         struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie;
542 /*      struct rt_rtmp_tx_ring *pTxRing; */
543
544         DBGPRINT(RT_DEBUG_ERROR, ("---> RTMPFreeTxRxRingMemory\n"));
545         pObj = pObj;
546
547         /* Free all resources for the RECEIVE buffer queue. */
548         for (i = 0; i < (RX_RING_SIZE); i++) {
549                 struct rt_rx_context *pRxContext = &(pAd->RxContext[i]);
550                 if (pRxContext)
551                         LM_URB_FREE(pObj, pRxContext, MAX_RXBULK_SIZE);
552         }
553
554         /* Free PsPoll frame resource */
555         LM_URB_FREE(pObj, pPsPollContext, sizeof(struct rt_tx_buffer));
556
557         /* Free NULL frame resource */
558         LM_URB_FREE(pObj, pNullContext, sizeof(struct rt_tx_buffer));
559
560         /* Free RTS frame resource */
561         LM_URB_FREE(pObj, pRTSContext, sizeof(struct rt_tx_buffer));
562
563         /* Free beacon frame resource */
564         for (i = 0; i < BEACON_RING_SIZE; i++) {
565                 struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]);
566                 if (pBeaconContext)
567                         LM_URB_FREE(pObj, pBeaconContext, sizeof(struct rt_tx_buffer));
568         }
569
570         /* Free mgmt frame resource */
571         for (i = 0; i < MGMT_RING_SIZE; i++) {
572                 struct rt_tx_context *pMLMEContext =
573                     (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa;
574                 /*LM_URB_FREE(pObj, pMLMEContext, sizeof(struct rt_tx_buffer)); */
575                 if (NULL != pAd->MgmtRing.Cell[i].pNdisPacket) {
576                         RTMPFreeNdisPacket(pAd,
577                                            pAd->MgmtRing.Cell[i].pNdisPacket);
578                         pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
579                         pMLMEContext->TransferBuffer = NULL;
580                 }
581
582                 if (pMLMEContext) {
583                         if (NULL != pMLMEContext->pUrb) {
584                                 RTUSB_UNLINK_URB(pMLMEContext->pUrb);
585                                 RTUSB_FREE_URB(pMLMEContext->pUrb);
586                                 pMLMEContext->pUrb = NULL;
587                         }
588                 }
589         }
590         if (pAd->MgmtDescRing.AllocVa)
591                 os_free_mem(pAd, pAd->MgmtDescRing.AllocVa);
592
593         /* Free Tx frame resource */
594         for (acidx = 0; acidx < 4; acidx++) {
595                 struct rt_ht_tx_context *pHTTXContext = &(pAd->TxContext[acidx]);
596                 if (pHTTXContext)
597                         LM_URB_FREE(pObj, pHTTXContext, sizeof(struct rt_httx_buffer));
598         }
599
600         if (pAd->FragFrame.pFragPacket)
601                 RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket,
602                                     NDIS_STATUS_SUCCESS);
603
604         for (i = 0; i < 6; i++) {
605                 NdisFreeSpinLock(&pAd->BulkOutLock[i]);
606         }
607
608         NdisFreeSpinLock(&pAd->BulkInLock);
609         NdisFreeSpinLock(&pAd->MLMEBulkOutLock);
610
611         NdisFreeSpinLock(&pAd->CmdQLock);
612         /* Clear all pending bulk-out request flags. */
613         RTUSB_CLEAR_BULK_FLAG(pAd, 0xffffffff);
614
615 /*      NdisFreeSpinLock(&pAd->MacTabLock); */
616
617 /*      for(i=0; i<MAX_LEN_OF_BA_REC_TABLE; i++) */
618 /*      { */
619 /*              NdisFreeSpinLock(&pAd->BATable.BARecEntry[i].RxReRingLock); */
620 /*      } */
621
622         DBGPRINT(RT_DEBUG_ERROR, ("<--- RTMPFreeTxRxRingMemory\n"));
623 }
624
625 /*
626 ========================================================================
627 Routine Description:
628     Write WLAN MAC address to USB 2870.
629
630 Arguments:
631     pAd                                 Pointer to our adapter
632
633 Return Value:
634         NDIS_STATUS_SUCCESS
635
636 Note:
637 ========================================================================
638 */
639 int RTUSBWriteHWMACAddress(struct rt_rtmp_adapter *pAd)
640 {
641         MAC_DW0_STRUC StaMacReg0;
642         MAC_DW1_STRUC StaMacReg1;
643         int Status = NDIS_STATUS_SUCCESS;
644         LARGE_INTEGER NOW;
645
646         /* initialize the random number generator */
647         RTMP_GetCurrentSystemTime(&NOW);
648
649         if (pAd->bLocalAdminMAC != TRUE) {
650                 pAd->CurrentAddress[0] = pAd->PermanentAddress[0];
651                 pAd->CurrentAddress[1] = pAd->PermanentAddress[1];
652                 pAd->CurrentAddress[2] = pAd->PermanentAddress[2];
653                 pAd->CurrentAddress[3] = pAd->PermanentAddress[3];
654                 pAd->CurrentAddress[4] = pAd->PermanentAddress[4];
655                 pAd->CurrentAddress[5] = pAd->PermanentAddress[5];
656         }
657         /* Write New MAC address to MAC_CSR2 & MAC_CSR3 & let ASIC know our new MAC */
658         StaMacReg0.field.Byte0 = pAd->CurrentAddress[0];
659         StaMacReg0.field.Byte1 = pAd->CurrentAddress[1];
660         StaMacReg0.field.Byte2 = pAd->CurrentAddress[2];
661         StaMacReg0.field.Byte3 = pAd->CurrentAddress[3];
662         StaMacReg1.field.Byte4 = pAd->CurrentAddress[4];
663         StaMacReg1.field.Byte5 = pAd->CurrentAddress[5];
664         StaMacReg1.field.U2MeMask = 0xff;
665         DBGPRINT_RAW(RT_DEBUG_TRACE,
666                 ("Local MAC = %pM\n", pAd->CurrentAddress));
667
668         RTUSBWriteMACRegister(pAd, MAC_ADDR_DW0, StaMacReg0.word);
669         RTUSBWriteMACRegister(pAd, MAC_ADDR_DW1, StaMacReg1.word);
670         return Status;
671 }
672
673 /*
674 ========================================================================
675 Routine Description:
676     Disable DMA.
677
678 Arguments:
679         *pAd                            the raxx interface data pointer
680
681 Return Value:
682         None
683
684 Note:
685 ========================================================================
686 */
687 void RT28XXDMADisable(struct rt_rtmp_adapter *pAd)
688 {
689         /* no use */
690 }
691
692 /*
693 ========================================================================
694 Routine Description:
695     Enable DMA.
696
697 Arguments:
698         *pAd                            the raxx interface data pointer
699
700 Return Value:
701         None
702
703 Note:
704 ========================================================================
705 */
706 void RT28XXDMAEnable(struct rt_rtmp_adapter *pAd)
707 {
708         WPDMA_GLO_CFG_STRUC GloCfg;
709         USB_DMA_CFG_STRUC UsbCfg;
710         int i = 0;
711
712         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
713         do {
714                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
715                 if ((GloCfg.field.TxDMABusy == 0)
716                     && (GloCfg.field.RxDMABusy == 0))
717                         break;
718
719                 DBGPRINT(RT_DEBUG_TRACE, ("==>  DMABusy\n"));
720                 RTMPusecDelay(1000);
721                 i++;
722         } while (i < 200);
723
724         RTMPusecDelay(50);
725         GloCfg.field.EnTXWriteBackDDONE = 1;
726         GloCfg.field.EnableRxDMA = 1;
727         GloCfg.field.EnableTxDMA = 1;
728         DBGPRINT(RT_DEBUG_TRACE,
729                  ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
730         RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
731
732         UsbCfg.word = 0;
733         UsbCfg.field.phyclear = 0;
734         /* usb version is 1.1,do not use bulk in aggregation */
735         if (pAd->BulkInMaxPacketSize == 512)
736                 UsbCfg.field.RxBulkAggEn = 1;
737         /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
738         UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE / 1024) - 3;
739         UsbCfg.field.RxBulkAggTOut = 0x80;      /* 2006-10-18 */
740         UsbCfg.field.RxBulkEn = 1;
741         UsbCfg.field.TxBulkEn = 1;
742
743         RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word);
744
745 }
746
747 /********************************************************************
748   *
749   *     2870 Beacon Update Related functions.
750   *
751   ********************************************************************/
752
753 /*
754 ========================================================================
755 Routine Description:
756     Write Beacon buffer to Asic.
757
758 Arguments:
759         *pAd                            the raxx interface data pointer
760
761 Return Value:
762         None
763
764 Note:
765 ========================================================================
766 */
767 void RT28xx_UpdateBeaconToAsic(struct rt_rtmp_adapter *pAd,
768                                int apidx,
769                                unsigned long FrameLen, unsigned long UpdatePos)
770 {
771         u8 *pBeaconFrame = NULL;
772         u8 *ptr;
773         u32 i, padding;
774         struct rt_beacon_sync *pBeaconSync = pAd->CommonCfg.pBeaconSync;
775         u32 longValue;
776 /*      u16                  shortValue; */
777         BOOLEAN bBcnReq = FALSE;
778         u8 bcn_idx = 0;
779
780         if (pBeaconFrame == NULL) {
781                 DBGPRINT(RT_DEBUG_ERROR, ("pBeaconFrame is NULL!\n"));
782                 return;
783         }
784
785         if (pBeaconSync == NULL) {
786                 DBGPRINT(RT_DEBUG_ERROR, ("pBeaconSync is NULL!\n"));
787                 return;
788         }
789         /*if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) || */
790         /*      ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) */
791         /*      ) */
792         if (bBcnReq == FALSE) {
793                 /* when the ra interface is down, do not send its beacon frame */
794                 /* clear all zero */
795                 for (i = 0; i < TXWI_SIZE; i += 4) {
796                         RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i,
797                                         0x00);
798                 }
799                 pBeaconSync->BeaconBitMap &=
800                     (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
801                 NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE);
802         } else {
803                 ptr = (u8 *)& pAd->BeaconTxWI;
804                 if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE) {  /* If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames. */
805                         pBeaconSync->BeaconBitMap &=
806                             (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
807                         NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx],
808                                        &pAd->BeaconTxWI, TXWI_SIZE);
809                 }
810
811                 if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) !=
812                     (1 << bcn_idx)) {
813                         for (i = 0; i < TXWI_SIZE; i += 4)      /* 16-byte TXWI field */
814                         {
815                                 longValue =
816                                     *ptr + (*(ptr + 1) << 8) +
817                                     (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
818                                 RTMP_IO_WRITE32(pAd,
819                                                 pAd->BeaconOffset[bcn_idx] + i,
820                                                 longValue);
821                                 ptr += 4;
822                         }
823                 }
824
825                 ptr = pBeaconSync->BeaconBuf[bcn_idx];
826                 padding = (FrameLen & 0x01);
827                 NdisZeroMemory((u8 *)(pBeaconFrame + FrameLen), padding);
828                 FrameLen += padding;
829                 for (i = 0; i < FrameLen /*HW_BEACON_OFFSET */ ; i += 2) {
830                         if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE) {
831                                 NdisMoveMemory(ptr, pBeaconFrame, 2);
832                                 /*shortValue = *ptr + (*(ptr+1)<<8); */
833                                 /*RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue); */
834                                 RTUSBMultiWrite(pAd,
835                                                 pAd->BeaconOffset[bcn_idx] +
836                                                 TXWI_SIZE + i, ptr, 2);
837                         }
838                         ptr += 2;
839                         pBeaconFrame += 2;
840                 }
841
842                 pBeaconSync->BeaconBitMap |= (1 << bcn_idx);
843
844                 /* For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame. */
845         }
846
847 }
848
849 void RTUSBBssBeaconStop(struct rt_rtmp_adapter *pAd)
850 {
851         struct rt_beacon_sync *pBeaconSync;
852         int i, offset;
853         BOOLEAN Cancelled = TRUE;
854
855         pBeaconSync = pAd->CommonCfg.pBeaconSync;
856         if (pBeaconSync && pBeaconSync->EnableBeacon) {
857                 int NumOfBcn;
858
859                 {
860                         NumOfBcn = MAX_MESH_NUM;
861                 }
862
863                 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
864
865                 for (i = 0; i < NumOfBcn; i++) {
866                         NdisZeroMemory(pBeaconSync->BeaconBuf[i],
867                                        HW_BEACON_OFFSET);
868                         NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
869
870                         for (offset = 0; offset < HW_BEACON_OFFSET; offset += 4)
871                                 RTMP_IO_WRITE32(pAd,
872                                                 pAd->BeaconOffset[i] + offset,
873                                                 0x00);
874
875                         pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
876                         pBeaconSync->TimIELocationInBeacon[i] = 0;
877                 }
878                 pBeaconSync->BeaconBitMap = 0;
879                 pBeaconSync->DtimBitOn = 0;
880         }
881 }
882
883 void RTUSBBssBeaconStart(struct rt_rtmp_adapter *pAd)
884 {
885         int apidx;
886         struct rt_beacon_sync *pBeaconSync;
887 /*      LARGE_INTEGER   tsfTime, deltaTime; */
888
889         pBeaconSync = pAd->CommonCfg.pBeaconSync;
890         if (pBeaconSync && pBeaconSync->EnableBeacon) {
891                 int NumOfBcn;
892
893                 {
894                         NumOfBcn = MAX_MESH_NUM;
895                 }
896
897                 for (apidx = 0; apidx < NumOfBcn; apidx++) {
898                         u8 CapabilityInfoLocationInBeacon = 0;
899                         u8 TimIELocationInBeacon = 0;
900
901                         NdisZeroMemory(pBeaconSync->BeaconBuf[apidx],
902                                        HW_BEACON_OFFSET);
903                         pBeaconSync->CapabilityInfoLocationInBeacon[apidx] =
904                             CapabilityInfoLocationInBeacon;
905                         pBeaconSync->TimIELocationInBeacon[apidx] =
906                             TimIELocationInBeacon;
907                         NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx],
908                                        TXWI_SIZE);
909                 }
910                 pBeaconSync->BeaconBitMap = 0;
911                 pBeaconSync->DtimBitOn = 0;
912                 pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE;
913
914                 pAd->CommonCfg.BeaconAdjust = 0;
915                 pAd->CommonCfg.BeaconFactor =
916                     0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10);
917                 pAd->CommonCfg.BeaconRemain =
918                     (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
919                 DBGPRINT(RT_DEBUG_TRACE,
920                          ("RTUSBBssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n",
921                           pAd->CommonCfg.BeaconFactor,
922                           pAd->CommonCfg.BeaconRemain));
923                 RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer,
924                              10 /*pAd->CommonCfg.BeaconPeriod */ );
925
926         }
927 }
928
929 void RTUSBBssBeaconInit(struct rt_rtmp_adapter *pAd)
930 {
931         struct rt_beacon_sync *pBeaconSync;
932         int i;
933
934         os_alloc_mem(pAd, (u8 **) (&pAd->CommonCfg.pBeaconSync),
935                      sizeof(struct rt_beacon_sync));
936         /*NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(struct rt_beacon_sync), MEM_ALLOC_FLAG); */
937         if (pAd->CommonCfg.pBeaconSync) {
938                 pBeaconSync = pAd->CommonCfg.pBeaconSync;
939                 NdisZeroMemory(pBeaconSync, sizeof(struct rt_beacon_sync));
940                 for (i = 0; i < HW_BEACON_MAX_COUNT; i++) {
941                         NdisZeroMemory(pBeaconSync->BeaconBuf[i],
942                                        HW_BEACON_OFFSET);
943                         pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
944                         pBeaconSync->TimIELocationInBeacon[i] = 0;
945                         NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
946                 }
947                 pBeaconSync->BeaconBitMap = 0;
948
949                 /*RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE); */
950                 pBeaconSync->EnableBeacon = TRUE;
951         }
952 }
953
954 void RTUSBBssBeaconExit(struct rt_rtmp_adapter *pAd)
955 {
956         struct rt_beacon_sync *pBeaconSync;
957         BOOLEAN Cancelled = TRUE;
958         int i;
959
960         if (pAd->CommonCfg.pBeaconSync) {
961                 pBeaconSync = pAd->CommonCfg.pBeaconSync;
962                 pBeaconSync->EnableBeacon = FALSE;
963                 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
964                 pBeaconSync->BeaconBitMap = 0;
965
966                 for (i = 0; i < HW_BEACON_MAX_COUNT; i++) {
967                         NdisZeroMemory(pBeaconSync->BeaconBuf[i],
968                                        HW_BEACON_OFFSET);
969                         pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
970                         pBeaconSync->TimIELocationInBeacon[i] = 0;
971                         NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
972                 }
973
974                 os_free_mem(pAd, pAd->CommonCfg.pBeaconSync);
975                 pAd->CommonCfg.pBeaconSync = NULL;
976         }
977 }
978
979 /*
980     ========================================================================
981     Routine Description:
982         For device work as AP mode but didn't have TBTT interrupt event, we need a mechanism
983         to update the beacon context in each Beacon interval. Here we use a periodical timer
984         to simulate the TBTT interrupt to handle the beacon context update.
985
986     Arguments:
987         SystemSpecific1         - Not used.
988         FunctionContext         - Pointer to our Adapter context.
989         SystemSpecific2         - Not used.
990         SystemSpecific3         - Not used.
991
992     Return Value:
993         None
994
995     ========================================================================
996 */
997 void BeaconUpdateExec(void *SystemSpecific1,
998                       void *FunctionContext,
999                       void *SystemSpecific2, void *SystemSpecific3)
1000 {
1001         struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
1002         LARGE_INTEGER tsfTime_a;        /*, tsfTime_b, deltaTime_exp, deltaTime_ab; */
1003         u32 delta, delta2MS, period2US, remain, remain_low, remain_high;
1004 /*      BOOLEAN                 positive; */
1005
1006         if (pAd->CommonCfg.IsUpdateBeacon == TRUE) {
1007                 ReSyncBeaconTime(pAd);
1008
1009         }
1010
1011         RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart);
1012         RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart);
1013
1014         /*positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp); */
1015         period2US = (pAd->CommonCfg.BeaconPeriod << 10);
1016         remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart;
1017         remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10);
1018         remain =
1019             (remain_high + remain_low) % (pAd->CommonCfg.BeaconPeriod << 10);
1020         delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain;
1021
1022         delta2MS = (delta >> 10);
1023         if (delta2MS > 150) {
1024                 pAd->CommonCfg.BeaconUpdateTimer.TimerValue = 100;
1025                 pAd->CommonCfg.IsUpdateBeacon = FALSE;
1026         } else {
1027                 pAd->CommonCfg.BeaconUpdateTimer.TimerValue = delta2MS + 10;
1028                 pAd->CommonCfg.IsUpdateBeacon = TRUE;
1029         }
1030
1031 }
1032
1033 /********************************************************************
1034   *
1035   *     2870 Radio on/off Related functions.
1036   *
1037   ********************************************************************/
1038 void RT28xxUsbMlmeRadioOn(struct rt_rtmp_adapter *pAd)
1039 {
1040         struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps;
1041
1042         DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbMlmeRadioOn()\n"));
1043
1044         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1045                 return;
1046
1047         {
1048                 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
1049                 RTMPusecDelay(10000);
1050         }
1051         /*NICResetFromError(pAd); */
1052
1053         /* Enable Tx/Rx */
1054         RTMPEnableRxTx(pAd);
1055
1056         if (pChipOps->AsicReverseRfFromSleepMode)
1057                 pChipOps->AsicReverseRfFromSleepMode(pAd);
1058
1059         /* Clear Radio off flag */
1060         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1061
1062         RTUSBBulkReceive(pAd);
1063
1064         /* Set LED */
1065         RTMPSetLED(pAd, LED_RADIO_ON);
1066 }
1067
1068 void RT28xxUsbMlmeRadioOFF(struct rt_rtmp_adapter *pAd)
1069 {
1070         WPDMA_GLO_CFG_STRUC GloCfg;
1071         u32 Value, i;
1072
1073         DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbMlmeRadioOFF()\n"));
1074
1075         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1076                 return;
1077
1078         /* Clear PMKID cache. */
1079         pAd->StaCfg.SavedPMKNum = 0;
1080         RTMPZeroMemory(pAd->StaCfg.SavedPMK, (PMKID_NO * sizeof(struct rt_bssid_info)));
1081
1082         /* Link down first if any association exists */
1083         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
1084                 if (INFRA_ON(pAd) || ADHOC_ON(pAd)) {
1085                         struct rt_mlme_disassoc_req DisReq;
1086                         struct rt_mlme_queue_elem *pMsgElem =
1087                             kmalloc(sizeof(struct rt_mlme_queue_elem),
1088                                                         MEM_ALLOC_FLAG);
1089
1090                         if (pMsgElem) {
1091                                 COPY_MAC_ADDR(&DisReq.Addr,
1092                                               pAd->CommonCfg.Bssid);
1093                                 DisReq.Reason = REASON_DISASSOC_STA_LEAVING;
1094
1095                                 pMsgElem->Machine = ASSOC_STATE_MACHINE;
1096                                 pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ;
1097                                 pMsgElem->MsgLen =
1098                                     sizeof(struct rt_mlme_disassoc_req);
1099                                 NdisMoveMemory(pMsgElem->Msg, &DisReq,
1100                                                sizeof
1101                                                (struct rt_mlme_disassoc_req));
1102
1103                                 MlmeDisassocReqAction(pAd, pMsgElem);
1104                                 kfree(pMsgElem);
1105
1106                                 RTMPusecDelay(1000);
1107                         }
1108                 }
1109         }
1110         /* Set Radio off flag */
1111         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1112
1113         {
1114                 /* Link down first if any association exists */
1115                 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1116                         LinkDown(pAd, FALSE);
1117                 RTMPusecDelay(10000);
1118
1119                 /*========================================== */
1120                 /* Clean up old bss table */
1121                 BssTableInit(&pAd->ScanTab);
1122         }
1123
1124         /* Set LED */
1125         RTMPSetLED(pAd, LED_RADIO_OFF);
1126
1127         if (pAd->CommonCfg.BBPCurrentBW == BW_40) {
1128                 /* Must using 40MHz. */
1129                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1130         } else {
1131                 /* Must using 20MHz. */
1132                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1133         }
1134
1135         /* Disable Tx/Rx DMA */
1136         RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */
1137         GloCfg.field.EnableTxDMA = 0;
1138         GloCfg.field.EnableRxDMA = 0;
1139         RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word); /* abort all TX rings */
1140
1141         /* Waiting for DMA idle */
1142         i = 0;
1143         do {
1144                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1145                 if ((GloCfg.field.TxDMABusy == 0)
1146                     && (GloCfg.field.RxDMABusy == 0))
1147                         break;
1148
1149                 RTMPusecDelay(1000);
1150         } while (i++ < 100);
1151
1152         /* Disable MAC Tx/Rx */
1153         RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
1154         Value &= (0xfffffff3);
1155         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
1156
1157         {
1158                 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
1159         }
1160 }
1161
1162 #endif /* RTMP_MAC_USB // */