• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/staging/rt2860/common/
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========================================================================
34Routine Description:
35    Initialize receive data structures.
36
37Arguments:
38    pAd					Pointer to our adapter
39
40Return Value:
41	NDIS_STATUS_SUCCESS
42	NDIS_STATUS_RESOURCES
43
44Note:
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*/
51int 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
99out1:
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========================================================================
122Routine Description:
123    Initialize transmit data structures.
124
125Arguments:
126    pAd					Pointer to our adapter
127
128Return Value:
129	NDIS_STATUS_SUCCESS
130	NDIS_STATUS_RESOURCES
131
132Note:
133========================================================================
134*/
135int 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
367done:
368	DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTransmit(Status=%d)\n", Status));
369
370	return Status;
371
372	/* --------------------------- ERROR HANDLE --------------------------- */
373out6:
374	LM_URB_FREE(pObj, pPsPollContext, sizeof(struct rt_tx_buffer));
375
376out5:
377	LM_URB_FREE(pObj, pRTSContext, sizeof(struct rt_tx_buffer));
378
379out4:
380	LM_URB_FREE(pObj, pNullContext, sizeof(struct rt_tx_buffer));
381
382out3:
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
389out2:
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
403out1:
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========================================================================
417Routine Description:
418    Allocate DMA memory blocks for send, receive.
419
420Arguments:
421    pAd					Pointer to our adapter
422
423Return Value:
424	NDIS_STATUS_SUCCESS
425	NDIS_STATUS_FAILURE
426	NDIS_STATUS_RESOURCES
427
428Note:
429========================================================================
430*/
431int 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========================================================================
508Routine 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
513Arguments:
514	*pAd				the raxx interface data pointer
515
516Return Value:
517	None
518
519Note:
520========================================================================
521*/
522void 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========================================================================
627Routine Description:
628    Write WLAN MAC address to USB 2870.
629
630Arguments:
631    pAd					Pointer to our adapter
632
633Return Value:
634	NDIS_STATUS_SUCCESS
635
636Note:
637========================================================================
638*/
639int 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========================================================================
678Routine Description:
679    Disable DMA.
680
681Arguments:
682	*pAd				the raxx interface data pointer
683
684Return Value:
685	None
686
687Note:
688========================================================================
689*/
690void RT28XXDMADisable(struct rt_rtmp_adapter *pAd)
691{
692	/* no use */
693}
694
695/*
696========================================================================
697Routine Description:
698    Enable DMA.
699
700Arguments:
701	*pAd				the raxx interface data pointer
702
703Return Value:
704	None
705
706Note:
707========================================================================
708*/
709void 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========================================================================
758Routine Description:
759    Write Beacon buffer to Asic.
760
761Arguments:
762	*pAd				the raxx interface data pointer
763
764Return Value:
765	None
766
767Note:
768========================================================================
769*/
770void 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
852void 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
886void 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
932void 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
957void 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*/
1000void 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  ********************************************************************/
1041void 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
1071void 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 // */
1166