Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh...
[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 = %02x:%02x:%02x:%02x:%02x:%02x\n",
667                       pAd->CurrentAddress[0], pAd->CurrentAddress[1],
668                       pAd->CurrentAddress[2], pAd->CurrentAddress[3],
669                       pAd->CurrentAddress[4], pAd->CurrentAddress[5]));
670
671         RTUSBWriteMACRegister(pAd, MAC_ADDR_DW0, StaMacReg0.word);
672         RTUSBWriteMACRegister(pAd, MAC_ADDR_DW1, StaMacReg1.word);
673         return Status;
674 }
675
676 /*
677 ========================================================================
678 Routine Description:
679     Disable DMA.
680
681 Arguments:
682         *pAd                            the raxx interface data pointer
683
684 Return Value:
685         None
686
687 Note:
688 ========================================================================
689 */
690 void RT28XXDMADisable(struct rt_rtmp_adapter *pAd)
691 {
692         /* no use */
693 }
694
695 /*
696 ========================================================================
697 Routine Description:
698     Enable DMA.
699
700 Arguments:
701         *pAd                            the raxx interface data pointer
702
703 Return Value:
704         None
705
706 Note:
707 ========================================================================
708 */
709 void RT28XXDMAEnable(struct rt_rtmp_adapter *pAd)
710 {
711         WPDMA_GLO_CFG_STRUC GloCfg;
712         USB_DMA_CFG_STRUC UsbCfg;
713         int i = 0;
714
715         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
716         do {
717                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
718                 if ((GloCfg.field.TxDMABusy == 0)
719                     && (GloCfg.field.RxDMABusy == 0))
720                         break;
721
722                 DBGPRINT(RT_DEBUG_TRACE, ("==>  DMABusy\n"));
723                 RTMPusecDelay(1000);
724                 i++;
725         } while (i < 200);
726
727         RTMPusecDelay(50);
728         GloCfg.field.EnTXWriteBackDDONE = 1;
729         GloCfg.field.EnableRxDMA = 1;
730         GloCfg.field.EnableTxDMA = 1;
731         DBGPRINT(RT_DEBUG_TRACE,
732                  ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
733         RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
734
735         UsbCfg.word = 0;
736         UsbCfg.field.phyclear = 0;
737         /* usb version is 1.1,do not use bulk in aggregation */
738         if (pAd->BulkInMaxPacketSize == 512)
739                 UsbCfg.field.RxBulkAggEn = 1;
740         /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
741         UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE / 1024) - 3;
742         UsbCfg.field.RxBulkAggTOut = 0x80;      /* 2006-10-18 */
743         UsbCfg.field.RxBulkEn = 1;
744         UsbCfg.field.TxBulkEn = 1;
745
746         RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word);
747
748 }
749
750 /********************************************************************
751   *
752   *     2870 Beacon Update Related functions.
753   *
754   ********************************************************************/
755
756 /*
757 ========================================================================
758 Routine Description:
759     Write Beacon buffer to Asic.
760
761 Arguments:
762         *pAd                            the raxx interface data pointer
763
764 Return Value:
765         None
766
767 Note:
768 ========================================================================
769 */
770 void RT28xx_UpdateBeaconToAsic(struct rt_rtmp_adapter *pAd,
771                                int apidx,
772                                unsigned long FrameLen, unsigned long UpdatePos)
773 {
774         u8 *pBeaconFrame = NULL;
775         u8 *ptr;
776         u32 i, padding;
777         struct rt_beacon_sync *pBeaconSync = pAd->CommonCfg.pBeaconSync;
778         u32 longValue;
779 /*      u16                  shortValue; */
780         BOOLEAN bBcnReq = FALSE;
781         u8 bcn_idx = 0;
782
783         if (pBeaconFrame == NULL) {
784                 DBGPRINT(RT_DEBUG_ERROR, ("pBeaconFrame is NULL!\n"));
785                 return;
786         }
787
788         if (pBeaconSync == NULL) {
789                 DBGPRINT(RT_DEBUG_ERROR, ("pBeaconSync is NULL!\n"));
790                 return;
791         }
792         /*if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) || */
793         /*      ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) */
794         /*      ) */
795         if (bBcnReq == FALSE) {
796                 /* when the ra interface is down, do not send its beacon frame */
797                 /* clear all zero */
798                 for (i = 0; i < TXWI_SIZE; i += 4) {
799                         RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i,
800                                         0x00);
801                 }
802                 pBeaconSync->BeaconBitMap &=
803                     (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
804                 NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE);
805         } else {
806                 ptr = (u8 *)& pAd->BeaconTxWI;
807                 if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE) {  /* If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames. */
808                         pBeaconSync->BeaconBitMap &=
809                             (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
810                         NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx],
811                                        &pAd->BeaconTxWI, TXWI_SIZE);
812                 }
813
814                 if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) !=
815                     (1 << bcn_idx)) {
816                         for (i = 0; i < TXWI_SIZE; i += 4)      /* 16-byte TXWI field */
817                         {
818                                 longValue =
819                                     *ptr + (*(ptr + 1) << 8) +
820                                     (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
821                                 RTMP_IO_WRITE32(pAd,
822                                                 pAd->BeaconOffset[bcn_idx] + i,
823                                                 longValue);
824                                 ptr += 4;
825                         }
826                 }
827
828                 ptr = pBeaconSync->BeaconBuf[bcn_idx];
829                 padding = (FrameLen & 0x01);
830                 NdisZeroMemory((u8 *)(pBeaconFrame + FrameLen), padding);
831                 FrameLen += padding;
832                 for (i = 0; i < FrameLen /*HW_BEACON_OFFSET */ ; i += 2) {
833                         if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE) {
834                                 NdisMoveMemory(ptr, pBeaconFrame, 2);
835                                 /*shortValue = *ptr + (*(ptr+1)<<8); */
836                                 /*RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue); */
837                                 RTUSBMultiWrite(pAd,
838                                                 pAd->BeaconOffset[bcn_idx] +
839                                                 TXWI_SIZE + i, ptr, 2);
840                         }
841                         ptr += 2;
842                         pBeaconFrame += 2;
843                 }
844
845                 pBeaconSync->BeaconBitMap |= (1 << bcn_idx);
846
847                 /* For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame. */
848         }
849
850 }
851
852 void RTUSBBssBeaconStop(struct rt_rtmp_adapter *pAd)
853 {
854         struct rt_beacon_sync *pBeaconSync;
855         int i, offset;
856         BOOLEAN Cancelled = TRUE;
857
858         pBeaconSync = pAd->CommonCfg.pBeaconSync;
859         if (pBeaconSync && pBeaconSync->EnableBeacon) {
860                 int NumOfBcn;
861
862                 {
863                         NumOfBcn = MAX_MESH_NUM;
864                 }
865
866                 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
867
868                 for (i = 0; i < NumOfBcn; i++) {
869                         NdisZeroMemory(pBeaconSync->BeaconBuf[i],
870                                        HW_BEACON_OFFSET);
871                         NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
872
873                         for (offset = 0; offset < HW_BEACON_OFFSET; offset += 4)
874                                 RTMP_IO_WRITE32(pAd,
875                                                 pAd->BeaconOffset[i] + offset,
876                                                 0x00);
877
878                         pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
879                         pBeaconSync->TimIELocationInBeacon[i] = 0;
880                 }
881                 pBeaconSync->BeaconBitMap = 0;
882                 pBeaconSync->DtimBitOn = 0;
883         }
884 }
885
886 void RTUSBBssBeaconStart(struct rt_rtmp_adapter *pAd)
887 {
888         int apidx;
889         struct rt_beacon_sync *pBeaconSync;
890 /*      LARGE_INTEGER   tsfTime, deltaTime; */
891
892         pBeaconSync = pAd->CommonCfg.pBeaconSync;
893         if (pBeaconSync && pBeaconSync->EnableBeacon) {
894                 int NumOfBcn;
895
896                 {
897                         NumOfBcn = MAX_MESH_NUM;
898                 }
899
900                 for (apidx = 0; apidx < NumOfBcn; apidx++) {
901                         u8 CapabilityInfoLocationInBeacon = 0;
902                         u8 TimIELocationInBeacon = 0;
903
904                         NdisZeroMemory(pBeaconSync->BeaconBuf[apidx],
905                                        HW_BEACON_OFFSET);
906                         pBeaconSync->CapabilityInfoLocationInBeacon[apidx] =
907                             CapabilityInfoLocationInBeacon;
908                         pBeaconSync->TimIELocationInBeacon[apidx] =
909                             TimIELocationInBeacon;
910                         NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx],
911                                        TXWI_SIZE);
912                 }
913                 pBeaconSync->BeaconBitMap = 0;
914                 pBeaconSync->DtimBitOn = 0;
915                 pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE;
916
917                 pAd->CommonCfg.BeaconAdjust = 0;
918                 pAd->CommonCfg.BeaconFactor =
919                     0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10);
920                 pAd->CommonCfg.BeaconRemain =
921                     (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
922                 DBGPRINT(RT_DEBUG_TRACE,
923                          ("RTUSBBssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n",
924                           pAd->CommonCfg.BeaconFactor,
925                           pAd->CommonCfg.BeaconRemain));
926                 RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer,
927                              10 /*pAd->CommonCfg.BeaconPeriod */ );
928
929         }
930 }
931
932 void RTUSBBssBeaconInit(struct rt_rtmp_adapter *pAd)
933 {
934         struct rt_beacon_sync *pBeaconSync;
935         int i;
936
937         os_alloc_mem(pAd, (u8 **) (&pAd->CommonCfg.pBeaconSync),
938                      sizeof(struct rt_beacon_sync));
939         /*NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(struct rt_beacon_sync), MEM_ALLOC_FLAG); */
940         if (pAd->CommonCfg.pBeaconSync) {
941                 pBeaconSync = pAd->CommonCfg.pBeaconSync;
942                 NdisZeroMemory(pBeaconSync, sizeof(struct rt_beacon_sync));
943                 for (i = 0; i < HW_BEACON_MAX_COUNT; i++) {
944                         NdisZeroMemory(pBeaconSync->BeaconBuf[i],
945                                        HW_BEACON_OFFSET);
946                         pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
947                         pBeaconSync->TimIELocationInBeacon[i] = 0;
948                         NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
949                 }
950                 pBeaconSync->BeaconBitMap = 0;
951
952                 /*RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE); */
953                 pBeaconSync->EnableBeacon = TRUE;
954         }
955 }
956
957 void RTUSBBssBeaconExit(struct rt_rtmp_adapter *pAd)
958 {
959         struct rt_beacon_sync *pBeaconSync;
960         BOOLEAN Cancelled = TRUE;
961         int i;
962
963         if (pAd->CommonCfg.pBeaconSync) {
964                 pBeaconSync = pAd->CommonCfg.pBeaconSync;
965                 pBeaconSync->EnableBeacon = FALSE;
966                 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
967                 pBeaconSync->BeaconBitMap = 0;
968
969                 for (i = 0; i < HW_BEACON_MAX_COUNT; i++) {
970                         NdisZeroMemory(pBeaconSync->BeaconBuf[i],
971                                        HW_BEACON_OFFSET);
972                         pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
973                         pBeaconSync->TimIELocationInBeacon[i] = 0;
974                         NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
975                 }
976
977                 os_free_mem(pAd, pAd->CommonCfg.pBeaconSync);
978                 pAd->CommonCfg.pBeaconSync = NULL;
979         }
980 }
981
982 /*
983     ========================================================================
984     Routine Description:
985         For device work as AP mode but didn't have TBTT interrupt event, we need a mechanism
986         to update the beacon context in each Beacon interval. Here we use a periodical timer
987         to simulate the TBTT interrupt to handle the beacon context update.
988
989     Arguments:
990         SystemSpecific1         - Not used.
991         FunctionContext         - Pointer to our Adapter context.
992         SystemSpecific2         - Not used.
993         SystemSpecific3         - Not used.
994
995     Return Value:
996         None
997
998     ========================================================================
999 */
1000 void BeaconUpdateExec(void *SystemSpecific1,
1001                       void *FunctionContext,
1002                       void *SystemSpecific2, void *SystemSpecific3)
1003 {
1004         struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
1005         LARGE_INTEGER tsfTime_a;        /*, tsfTime_b, deltaTime_exp, deltaTime_ab; */
1006         u32 delta, delta2MS, period2US, remain, remain_low, remain_high;
1007 /*      BOOLEAN                 positive; */
1008
1009         if (pAd->CommonCfg.IsUpdateBeacon == TRUE) {
1010                 ReSyncBeaconTime(pAd);
1011
1012         }
1013
1014         RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart);
1015         RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart);
1016
1017         /*positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp); */
1018         period2US = (pAd->CommonCfg.BeaconPeriod << 10);
1019         remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart;
1020         remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10);
1021         remain =
1022             (remain_high + remain_low) % (pAd->CommonCfg.BeaconPeriod << 10);
1023         delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain;
1024
1025         delta2MS = (delta >> 10);
1026         if (delta2MS > 150) {
1027                 pAd->CommonCfg.BeaconUpdateTimer.TimerValue = 100;
1028                 pAd->CommonCfg.IsUpdateBeacon = FALSE;
1029         } else {
1030                 pAd->CommonCfg.BeaconUpdateTimer.TimerValue = delta2MS + 10;
1031                 pAd->CommonCfg.IsUpdateBeacon = TRUE;
1032         }
1033
1034 }
1035
1036 /********************************************************************
1037   *
1038   *     2870 Radio on/off Related functions.
1039   *
1040   ********************************************************************/
1041 void RT28xxUsbMlmeRadioOn(struct rt_rtmp_adapter *pAd)
1042 {
1043         struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps;
1044
1045         DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbMlmeRadioOn()\n"));
1046
1047         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1048                 return;
1049
1050         {
1051                 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
1052                 RTMPusecDelay(10000);
1053         }
1054         /*NICResetFromError(pAd); */
1055
1056         /* Enable Tx/Rx */
1057         RTMPEnableRxTx(pAd);
1058
1059         if (pChipOps->AsicReverseRfFromSleepMode)
1060                 pChipOps->AsicReverseRfFromSleepMode(pAd);
1061
1062         /* Clear Radio off flag */
1063         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1064
1065         RTUSBBulkReceive(pAd);
1066
1067         /* Set LED */
1068         RTMPSetLED(pAd, LED_RADIO_ON);
1069 }
1070
1071 void RT28xxUsbMlmeRadioOFF(struct rt_rtmp_adapter *pAd)
1072 {
1073         WPDMA_GLO_CFG_STRUC GloCfg;
1074         u32 Value, i;
1075
1076         DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbMlmeRadioOFF()\n"));
1077
1078         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1079                 return;
1080
1081         /* Clear PMKID cache. */
1082         pAd->StaCfg.SavedPMKNum = 0;
1083         RTMPZeroMemory(pAd->StaCfg.SavedPMK, (PMKID_NO * sizeof(struct rt_bssid_info)));
1084
1085         /* Link down first if any association exists */
1086         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
1087                 if (INFRA_ON(pAd) || ADHOC_ON(pAd)) {
1088                         struct rt_mlme_disassoc_req DisReq;
1089                         struct rt_mlme_queue_elem *pMsgElem =
1090                             kmalloc(sizeof(struct rt_mlme_queue_elem),
1091                                                         MEM_ALLOC_FLAG);
1092
1093                         if (pMsgElem) {
1094                                 COPY_MAC_ADDR(&DisReq.Addr,
1095                                               pAd->CommonCfg.Bssid);
1096                                 DisReq.Reason = REASON_DISASSOC_STA_LEAVING;
1097
1098                                 pMsgElem->Machine = ASSOC_STATE_MACHINE;
1099                                 pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ;
1100                                 pMsgElem->MsgLen =
1101                                     sizeof(struct rt_mlme_disassoc_req);
1102                                 NdisMoveMemory(pMsgElem->Msg, &DisReq,
1103                                                sizeof
1104                                                (struct rt_mlme_disassoc_req));
1105
1106                                 MlmeDisassocReqAction(pAd, pMsgElem);
1107                                 kfree(pMsgElem);
1108
1109                                 RTMPusecDelay(1000);
1110                         }
1111                 }
1112         }
1113         /* Set Radio off flag */
1114         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1115
1116         {
1117                 /* Link down first if any association exists */
1118                 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1119                         LinkDown(pAd, FALSE);
1120                 RTMPusecDelay(10000);
1121
1122                 /*========================================== */
1123                 /* Clean up old bss table */
1124                 BssTableInit(&pAd->ScanTab);
1125         }
1126
1127         /* Set LED */
1128         RTMPSetLED(pAd, LED_RADIO_OFF);
1129
1130         if (pAd->CommonCfg.BBPCurrentBW == BW_40) {
1131                 /* Must using 40MHz. */
1132                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1133         } else {
1134                 /* Must using 20MHz. */
1135                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1136         }
1137
1138         /* Disable Tx/Rx DMA */
1139         RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */
1140         GloCfg.field.EnableTxDMA = 0;
1141         GloCfg.field.EnableRxDMA = 0;
1142         RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word); /* abort all TX rings */
1143
1144         /* Waiting for DMA idle */
1145         i = 0;
1146         do {
1147                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1148                 if ((GloCfg.field.TxDMABusy == 0)
1149                     && (GloCfg.field.RxDMABusy == 0))
1150                         break;
1151
1152                 RTMPusecDelay(1000);
1153         } while (i++ < 100);
1154
1155         /* Disable MAC Tx/Rx */
1156         RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
1157         Value &= (0xfffffff3);
1158         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
1159
1160         {
1161                 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
1162         }
1163 }
1164
1165 #endif /* RTMP_MAC_USB // */