wcmd.c revision 4e8a7e5fc29697f881f5c358f84df52914908703
1/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * File: wcmd.c
20 *
21 * Purpose: Handles the management command interface functions
22 *
23 * Author: Lyndon Chen
24 *
25 * Date: May 8, 2003
26 *
27 * Functions:
28 *      s_vProbeChannel - Active scan channel
29 *      s_MgrMakeProbeRequest - Make ProbeRequest packet
30 *      CommandTimer - Timer function to handle command
31 *      s_bCommandComplete - Command Complete function
32 *      bScheduleCommand - Push Command and wait Command Scheduler to do
33 *      vCommandTimer- Command call back functions
34 *      vCommandTimerWait- Call back timer
35 *      bClearBSSID_SCAN- Clear BSSID_SCAN cmd in CMD Queue
36 *
37 * Revision History:
38 *
39 */
40
41#include "ttype.h"
42#include "tmacro.h"
43#include "device.h"
44#include "mac.h"
45#include "card.h"
46#include "80211hdr.h"
47#include "wcmd.h"
48#include "wmgr.h"
49#include "power.h"
50#include "wctl.h"
51#include "baseband.h"
52#include "rxtx.h"
53#include "rf.h"
54#include "iowpa.h"
55#include "channel.h"
56
57/*---------------------  Static Definitions -------------------------*/
58
59/*---------------------  Static Classes  ----------------------------*/
60
61/*---------------------  Static Variables  --------------------------*/
62static int msglevel = MSG_LEVEL_INFO;
63/*---------------------  Static Functions  --------------------------*/
64
65static
66void
67s_vProbeChannel(
68	PSDevice pDevice
69);
70
71static
72PSTxMgmtPacket
73s_MgrMakeProbeRequest(
74	PSDevice pDevice,
75	PSMgmtObject pMgmt,
76	unsigned char *pScanBSSID,
77	PWLAN_IE_SSID pSSID,
78	PWLAN_IE_SUPP_RATES pCurrRates,
79	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
80);
81
82static
83bool
84s_bCommandComplete(
85	PSDevice pDevice
86);
87
88/*---------------------  Export Variables  --------------------------*/
89
90/*---------------------  Export Functions  --------------------------*/
91
92/*
93 * Description:
94 *      Stop AdHoc beacon during scan process
95 *
96 * Parameters:
97 *  In:
98 *      pDevice     - Pointer to the adapter
99 *  Out:
100 *      none
101 *
102 * Return Value: none
103 *
104 */
105static
106void
107vAdHocBeaconStop(PSDevice  pDevice)
108{
109	PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
110	bool bStop;
111
112	/*
113	 * temporarily stop Beacon packet for AdHoc Server
114	 * if all of the following conditions are met:
115	 *  (1) STA is in AdHoc mode
116	 *  (2) VT3253 is programmed as automatic Beacon Transmitting
117	 *  (3) One of the following conditions is met
118	 *      (3.1) AdHoc channel is in B/G band and the
119	 *      current scan channel is in A band
120	 *      or
121	 *      (3.2) AdHoc channel is in A mode
122	 */
123	bStop = false;
124	if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
125	    (pMgmt->eCurrState >= WMAC_STATE_STARTED)) {
126		if ((pMgmt->uIBSSChannel <=  CB_MAX_CHANNEL_24G) &&
127		    (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) {
128			bStop = true;
129		}
130		if (pMgmt->uIBSSChannel >  CB_MAX_CHANNEL_24G) {
131			bStop = true;
132		}
133	}
134
135	if (bStop) {
136		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
137	}
138} /* vAdHocBeaconStop */
139
140/*
141 * Description:
142 *      Restart AdHoc beacon after scan process complete
143 *
144 * Parameters:
145 *  In:
146 *      pDevice     - Pointer to the adapter
147 *  Out:
148 *      none
149 *
150 * Return Value: none
151 *
152 */
153static
154void
155vAdHocBeaconRestart(PSDevice pDevice)
156{
157	PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
158
159	/*
160	 * Restart Beacon packet for AdHoc Server
161	 * if all of the following coditions are met:
162	 *  (1) STA is in AdHoc mode
163	 *  (2) VT3253 is programmed as automatic Beacon Transmitting
164	 */
165	if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
166	    (pMgmt->eCurrState >= WMAC_STATE_STARTED)) {
167		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
168	}
169}
170
171/*+
172 *
173 * Routine Description:
174 *   Prepare and send probe request management frames.
175 *
176 *
177 * Return Value:
178 *    none.
179 *
180 -*/
181
182static
183void
184s_vProbeChannel(
185	PSDevice pDevice
186)
187{
188	//1M,   2M,   5M,   11M,  18M,  24M,  36M,  54M
189	unsigned char abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C};
190	unsigned char abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60};
191	//6M,   9M,   12M,  48M
192	unsigned char abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
193	unsigned char abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
194	unsigned char *pbyRate;
195	PSTxMgmtPacket  pTxPacket;
196	PSMgmtObject    pMgmt = pDevice->pMgmt;
197	unsigned int ii;
198
199	if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
200		pbyRate = &abyCurrSuppRatesA[0];
201	} else if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
202		pbyRate = &abyCurrSuppRatesB[0];
203	} else {
204		pbyRate = &abyCurrSuppRatesG[0];
205	}
206	// build an assocreq frame and send it
207	pTxPacket = s_MgrMakeProbeRequest
208		(
209			pDevice,
210			pMgmt,
211			pMgmt->abyScanBSSID,
212			(PWLAN_IE_SSID)pMgmt->abyScanSSID,
213			(PWLAN_IE_SUPP_RATES)pbyRate,
214			(PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG
215			);
216
217	if (pTxPacket != NULL) {
218		for (ii = 0; ii < 2; ii++) {
219			if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
220				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail.. \n");
221			} else {
222				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request is sending.. \n");
223			}
224		}
225	}
226}
227
228/*+
229 *
230 * Routine Description:
231 *  Constructs an probe request frame
232 *
233 *
234 * Return Value:
235 *    A ptr to Tx frame or NULL on allocation failure
236 *
237 -*/
238
239PSTxMgmtPacket
240s_MgrMakeProbeRequest(
241	PSDevice pDevice,
242	PSMgmtObject pMgmt,
243	unsigned char *pScanBSSID,
244	PWLAN_IE_SSID pSSID,
245	PWLAN_IE_SUPP_RATES pCurrRates,
246	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
247
248)
249{
250	PSTxMgmtPacket      pTxPacket = NULL;
251	WLAN_FR_PROBEREQ    sFrame;
252
253	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
254	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBEREQ_FR_MAXLEN);
255	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
256	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
257	sFrame.len = WLAN_PROBEREQ_FR_MAXLEN;
258	vMgrEncodeProbeRequest(&sFrame);
259	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
260		(
261			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
262			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBEREQ)
263));
264	memcpy(sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN);
265	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
266	memcpy(sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN);
267	// Copy the SSID, pSSID->len=0 indicate broadcast SSID
268	sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
269	sFrame.len += pSSID->len + WLAN_IEHDR_LEN;
270	memcpy(sFrame.pSSID, pSSID, pSSID->len + WLAN_IEHDR_LEN);
271	sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
272	sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN;
273	memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
274	// Copy the extension rate set
275	if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
276		sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
277		sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN;
278		memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN);
279	}
280	pTxPacket->cbMPDULen = sFrame.len;
281	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
282
283	return pTxPacket;
284}
285
286void
287vCommandTimerWait(
288	void *hDeviceContext,
289	unsigned int MSecond
290)
291{
292	PSDevice        pDevice = (PSDevice)hDeviceContext;
293
294	init_timer(&pDevice->sTimerCommand);
295	pDevice->sTimerCommand.data = (unsigned long) pDevice;
296	pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
297	// RUN_AT :1 msec ~= (HZ/1024)
298	pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10);
299	add_timer(&pDevice->sTimerCommand);
300	return;
301}
302
303void
304vCommandTimer(
305	void *hDeviceContext
306)
307{
308	PSDevice        pDevice = (PSDevice)hDeviceContext;
309	PSMgmtObject    pMgmt = pDevice->pMgmt;
310	PWLAN_IE_SSID   pItemSSID;
311	PWLAN_IE_SSID   pItemSSIDCurr;
312	CMD_STATUS      Status;
313	unsigned int ii;
314	unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
315	struct sk_buff  *skb;
316
317	if (pDevice->dwDiagRefCount != 0)
318		return;
319	if (!pDevice->bCmdRunning)
320		return;
321
322	spin_lock_irq(&pDevice->lock);
323
324	switch (pDevice->eCommandState) {
325	case WLAN_CMD_SCAN_START:
326
327		pDevice->byReAssocCount = 0;
328		if (pDevice->bRadioOff) {
329			s_bCommandComplete(pDevice);
330			spin_unlock_irq(&pDevice->lock);
331			return;
332		}
333
334		if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
335			s_bCommandComplete(pDevice);
336			CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_AP);
337			spin_unlock_irq(&pDevice->lock);
338			return;
339		}
340
341		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState= WLAN_CMD_SCAN_START\n");
342		pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID;
343		// wait all Data TD complete
344		if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
345			spin_unlock_irq(&pDevice->lock);
346			vCommandTimerWait((void *)pDevice, 10);
347			return;
348		}
349
350		if (pMgmt->uScanChannel == 0) {
351			pMgmt->uScanChannel = pDevice->byMinChannel;
352			// Set Baseband to be more sensitive.
353
354		}
355		if (pMgmt->uScanChannel > pDevice->byMaxChannel) {
356			pMgmt->eScanState = WMAC_NO_SCANNING;
357
358			// Set Baseband's sensitivity back.
359			// Set channel back
360			set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
361			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel);
362			if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
363				CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC);
364			} else {
365				CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_INFRASTRUCTURE);
366			}
367			vAdHocBeaconRestart(pDevice);
368			s_bCommandComplete(pDevice);
369
370		} else {
371//2008-8-4 <add> by chester
372			if (!is_channel_valid(pMgmt->uScanChannel)) {
373				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n", pMgmt->uScanChannel);
374				s_bCommandComplete(pDevice);
375				spin_unlock_irq(&pDevice->lock);
376				return;
377			}
378			if (pMgmt->uScanChannel == pDevice->byMinChannel) {
379				pMgmt->abyScanBSSID[0] = 0xFF;
380				pMgmt->abyScanBSSID[1] = 0xFF;
381				pMgmt->abyScanBSSID[2] = 0xFF;
382				pMgmt->abyScanBSSID[3] = 0xFF;
383				pMgmt->abyScanBSSID[4] = 0xFF;
384				pMgmt->abyScanBSSID[5] = 0xFF;
385				pItemSSID->byElementID = WLAN_EID_SSID;
386				pMgmt->eScanState = WMAC_IS_SCANNING;
387
388			}
389
390			vAdHocBeaconStop(pDevice);
391
392			if (set_channel(pMgmt->pAdapter, pMgmt->uScanChannel)) {
393				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SCAN Channel: %d\n", pMgmt->uScanChannel);
394			} else {
395				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SET SCAN Channel Fail: %d\n", pMgmt->uScanChannel);
396			}
397			CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_UNKNOWN);
398			pMgmt->uScanChannel++;
399//2008-8-4 <modify> by chester
400			if (!is_channel_valid(pMgmt->uScanChannel) &&
401			    pMgmt->uScanChannel <= pDevice->byMaxChannel) {
402				pMgmt->uScanChannel = pDevice->byMaxChannel + 1;
403				pMgmt->eCommandState = WLAN_CMD_SCAN_END;
404
405			}
406
407			if (!pMgmt->b11hEnable ||
408			    (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) {
409				s_vProbeChannel(pDevice);
410				spin_unlock_irq(&pDevice->lock);
411				vCommandTimerWait((void *)pDevice, WCMD_ACTIVE_SCAN_TIME);
412				return;
413			} else {
414				spin_unlock_irq(&pDevice->lock);
415				vCommandTimerWait((void *)pDevice, WCMD_PASSIVE_SCAN_TIME);
416				return;
417			}
418
419		}
420
421		break;
422
423	case WLAN_CMD_SCAN_END:
424
425		// Set Baseband's sensitivity back.
426		// Set channel back
427		set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
428		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel);
429		if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
430			CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC);
431		} else {
432			CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_INFRASTRUCTURE);
433		}
434
435		pMgmt->eScanState = WMAC_NO_SCANNING;
436		vAdHocBeaconRestart(pDevice);
437//2008-0409-07, <Add> by Einsn Liu
438#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
439		if (pMgmt->eScanType == WMAC_SCAN_PASSIVE)
440		{//send scan event to wpa_Supplicant
441			union iwreq_data wrqu;
442			memset(&wrqu, 0, sizeof(wrqu));
443			wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
444		}
445#endif
446		s_bCommandComplete(pDevice);
447		break;
448
449	case WLAN_CMD_DISASSOCIATE_START:
450		pDevice->byReAssocCount = 0;
451		if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
452		    (pMgmt->eCurrState != WMAC_STATE_ASSOC)) {
453			s_bCommandComplete(pDevice);
454			spin_unlock_irq(&pDevice->lock);
455			return;
456		} else {
457			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send Disassociation Packet..\n");
458			// reason = 8 : disassoc because sta has left
459			vMgrDisassocBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (8), &Status);
460			pDevice->bLinkPass = false;
461			// unlock command busy
462			pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
463			pItemSSID->len = 0;
464			memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN);
465			pMgmt->eCurrState = WMAC_STATE_IDLE;
466			pMgmt->sNodeDBTable[0].bActive = false;
467		}
468		netif_stop_queue(pDevice->dev);
469		pDevice->eCommandState = WLAN_DISASSOCIATE_WAIT;
470		// wait all Control TD complete
471		if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
472			vCommandTimerWait((void *)pDevice, 10);
473			spin_unlock_irq(&pDevice->lock);
474			return;
475		}
476		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " CARDbRadioPowerOff\n");
477		//2008-09-02  <mark>	by chester
478		s_bCommandComplete(pDevice);
479		break;
480
481	case WLAN_DISASSOCIATE_WAIT:
482		// wait all Control TD complete
483		if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
484			vCommandTimerWait((void *)pDevice, 10);
485			spin_unlock_irq(&pDevice->lock);
486			return;
487		}
488//2008-09-02  <mark> by chester
489		s_bCommandComplete(pDevice);
490		break;
491
492	case WLAN_CMD_SSID_START:
493		pDevice->byReAssocCount = 0;
494		if (pDevice->bRadioOff) {
495			s_bCommandComplete(pDevice);
496			spin_unlock_irq(&pDevice->lock);
497			return;
498		}
499		printk("chester-abyDesireSSID=%s\n", ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID);
500		pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
501		pItemSSIDCurr = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
502		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " cmd: desire ssid = %s\n", pItemSSID->abySSID);
503		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID);
504
505		if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
506			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n");
507			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " pItemSSID->len =%d\n", pItemSSID->len);
508			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " pItemSSIDCurr->len = %d\n", pItemSSIDCurr->len);
509			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " desire ssid = %s\n", pItemSSID->abySSID);
510			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " curr ssid = %s\n", pItemSSIDCurr->abySSID);
511		}
512
513		if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
514		    ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
515			if (pItemSSID->len == pItemSSIDCurr->len) {
516				if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) {
517					s_bCommandComplete(pDevice);
518					spin_unlock_irq(&pDevice->lock);
519					return;
520				}
521			}
522
523			netif_stop_queue(pDevice->dev);
524			pDevice->bLinkPass = false;
525		}
526		// set initial state
527		pMgmt->eCurrState = WMAC_STATE_IDLE;
528		pMgmt->eCurrMode = WMAC_MODE_STANDBY;
529		PSvDisablePowerSaving((void *)pDevice);
530		BSSvClearNodeDBTable(pDevice, 0);
531
532		vMgrJoinBSSBegin((void *)pDevice, &Status);
533		// if Infra mode
534		if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) {
535			// Call mgr to begin the deauthentication
536			// reason = (3) because sta has left ESS
537			if (pMgmt->eCurrState >= WMAC_STATE_AUTH) {
538				vMgrDeAuthenBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (3), &Status);
539			}
540			// Call mgr to begin the authentication
541			vMgrAuthenBeginSta((void *)pDevice, pMgmt, &Status);
542			if (Status == CMD_STATUS_SUCCESS) {
543				pDevice->byLinkWaitCount = 0;
544				pDevice->eCommandState = WLAN_AUTHENTICATE_WAIT;
545				vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT);
546				spin_unlock_irq(&pDevice->lock);
547				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set eCommandState = WLAN_AUTHENTICATE_WAIT\n");
548				return;
549			}
550		}
551		// if Adhoc mode
552		else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
553			if (pMgmt->eCurrState == WMAC_STATE_JOINTED) {
554				if (netif_queue_stopped(pDevice->dev)) {
555					netif_wake_queue(pDevice->dev);
556				}
557				pDevice->bLinkPass = true;
558
559				pMgmt->sNodeDBTable[0].bActive = true;
560				pMgmt->sNodeDBTable[0].uInActiveCount = 0;
561				bClearBSSID_SCAN(pDevice);
562			} else {
563				// start own IBSS
564				vMgrCreateOwnIBSS((void *)pDevice, &Status);
565				if (Status != CMD_STATUS_SUCCESS) {
566					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " WLAN_CMD_IBSS_CREATE fail ! \n");
567				}
568				BSSvAddMulticastNode(pDevice);
569			}
570		}
571		// if SSID not found
572		else if (pMgmt->eCurrMode == WMAC_MODE_STANDBY) {
573			if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA ||
574			    pMgmt->eConfigMode == WMAC_CONFIG_AUTO) {
575				// start own IBSS
576				vMgrCreateOwnIBSS((void *)pDevice, &Status);
577				if (Status != CMD_STATUS_SUCCESS) {
578					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " WLAN_CMD_IBSS_CREATE fail ! \n");
579				}
580				BSSvAddMulticastNode(pDevice);
581				if (netif_queue_stopped(pDevice->dev)) {
582					netif_wake_queue(pDevice->dev);
583				}
584				pDevice->bLinkPass = true;
585			} else {
586				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disconnect SSID none\n");
587#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
588				{
589					union iwreq_data  wrqu;
590					memset(&wrqu, 0, sizeof(wrqu));
591					wrqu.ap_addr.sa_family = ARPHRD_ETHER;
592					printk("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n");
593					wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
594				}
595#endif
596
597			}
598		}
599		s_bCommandComplete(pDevice);
600		break;
601
602	case WLAN_AUTHENTICATE_WAIT:
603		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState == WLAN_AUTHENTICATE_WAIT\n");
604		if (pMgmt->eCurrState == WMAC_STATE_AUTH) {
605			// Call mgr to begin the association
606			pDevice->byLinkWaitCount = 0;
607			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCurrState == WMAC_STATE_AUTH\n");
608			vMgrAssocBeginSta((void *)pDevice, pMgmt, &Status);
609			if (Status == CMD_STATUS_SUCCESS) {
610				pDevice->byLinkWaitCount = 0;
611				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState = WLAN_ASSOCIATE_WAIT\n");
612				pDevice->eCommandState = WLAN_ASSOCIATE_WAIT;
613				vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT);
614				spin_unlock_irq(&pDevice->lock);
615				return;
616			}
617		}
618
619		else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) {
620			printk("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n");
621		} else if (pDevice->byLinkWaitCount <= 4) {    //mike add:wait another 2 sec if authenticated_frame delay!
622			pDevice->byLinkWaitCount++;
623			printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount);
624			spin_unlock_irq(&pDevice->lock);
625			vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT/2);
626			return;
627		}
628		pDevice->byLinkWaitCount = 0;
629		s_bCommandComplete(pDevice);
630		break;
631
632	case WLAN_ASSOCIATE_WAIT:
633		if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
634			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCurrState == WMAC_STATE_ASSOC\n");
635			if (pDevice->ePSMode != WMAC_POWER_CAM) {
636				PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
637			}
638			if (pMgmt->eAuthenMode >= WMAC_AUTH_WPA) {
639				KeybRemoveAllKey(&(pDevice->sKey), pDevice->abyBSSID, pDevice->PortOffset);
640			}
641			pDevice->bLinkPass = true;
642			pDevice->byLinkWaitCount = 0;
643			pDevice->byReAssocCount = 0;
644			bClearBSSID_SCAN(pDevice);
645			if (pDevice->byFOETuning) {
646				BBvSetFOE(pDevice->PortOffset);
647				PSbSendNullPacket(pDevice);
648			}
649			if (netif_queue_stopped(pDevice->dev)) {
650				netif_wake_queue(pDevice->dev);
651			}
652#ifdef TxInSleep
653			if (pDevice->IsTxDataTrigger) {    //TxDataTimer is not triggered at the first time
654				del_timer(&pDevice->sTimerTxData);
655				init_timer(&pDevice->sTimerTxData);
656				pDevice->sTimerTxData.data = (unsigned long) pDevice;
657				pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData;
658				pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
659				pDevice->fTxDataInSleep = false;
660				pDevice->nTxDataTimeCout = 0;
661			} else {
662			}
663			pDevice->IsTxDataTrigger = true;
664			add_timer(&pDevice->sTimerTxData);
665#endif
666		} else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) {
667			printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n");
668		} else if (pDevice->byLinkWaitCount <= 4) {    //mike add:wait another 2 sec if associated_frame delay!
669			pDevice->byLinkWaitCount++;
670			printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount);
671			spin_unlock_irq(&pDevice->lock);
672			vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT/2);
673			return;
674		}
675		pDevice->byLinkWaitCount = 0;
676
677		s_bCommandComplete(pDevice);
678		break;
679
680	case WLAN_CMD_AP_MODE_START:
681		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState == WLAN_CMD_AP_MODE_START\n");
682
683		if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
684			del_timer(&pMgmt->sTimerSecondCallback);
685			pMgmt->eCurrState = WMAC_STATE_IDLE;
686			pMgmt->eCurrMode = WMAC_MODE_STANDBY;
687			pDevice->bLinkPass = false;
688			if (pDevice->bEnableHostWEP)
689				BSSvClearNodeDBTable(pDevice, 1);
690			else
691				BSSvClearNodeDBTable(pDevice, 0);
692			pDevice->uAssocCount = 0;
693			pMgmt->eCurrState = WMAC_STATE_IDLE;
694			pDevice->bFixRate = false;
695
696			vMgrCreateOwnIBSS((void *)pDevice, &Status);
697			if (Status != CMD_STATUS_SUCCESS) {
698				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " vMgrCreateOwnIBSS fail ! \n");
699			}
700			// alway turn off unicast bit
701			MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_UNICAST);
702			pDevice->byRxMode &= ~RCR_UNICAST;
703			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode);
704			BSSvAddMulticastNode(pDevice);
705			if (netif_queue_stopped(pDevice->dev)) {
706				netif_wake_queue(pDevice->dev);
707			}
708			pDevice->bLinkPass = true;
709			add_timer(&pMgmt->sTimerSecondCallback);
710		}
711		s_bCommandComplete(pDevice);
712		break;
713
714	case WLAN_CMD_TX_PSPACKET_START:
715		// DTIM Multicast tx
716		if (pMgmt->sNodeDBTable[0].bRxPSPoll) {
717			while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) {
718				if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) {
719					pMgmt->abyPSTxMap[0] &= ~byMask[0];
720					pDevice->bMoreData = false;
721				} else {
722					pDevice->bMoreData = true;
723				}
724				if (!device_dma0_xmit(pDevice, skb, 0)) {
725					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Multicast ps tx fail \n");
726				}
727				pMgmt->sNodeDBTable[0].wEnQueueCnt--;
728			}
729		}
730
731		// PS nodes tx
732		for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
733			if (pMgmt->sNodeDBTable[ii].bActive &&
734			    pMgmt->sNodeDBTable[ii].bRxPSPoll) {
735				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d Enqueu Cnt= %d\n",
736					ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt);
737				while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) {
738					if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
739						// clear tx map
740						pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
741							~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
742						pDevice->bMoreData = false;
743					} else {
744						pDevice->bMoreData = true;
745					}
746					if (!device_dma0_xmit(pDevice, skb, ii)) {
747						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail \n");
748					}
749					pMgmt->sNodeDBTable[ii].wEnQueueCnt--;
750					// check if sta ps enabled, and wait next pspoll.
751					// if sta ps disable, then send all pending buffers.
752					if (pMgmt->sNodeDBTable[ii].bPSEnable)
753						break;
754				}
755				if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
756					// clear tx map
757					pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
758						~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
759					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d PS queue clear \n", ii);
760				}
761				pMgmt->sNodeDBTable[ii].bRxPSPoll = false;
762			}
763		}
764
765		s_bCommandComplete(pDevice);
766		break;
767
768	case WLAN_CMD_RADIO_START:
769		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState == WLAN_CMD_RADIO_START\n");
770		if (pDevice->bRadioCmd)
771			CARDbRadioPowerOn(pDevice);
772		else
773			CARDbRadioPowerOff(pDevice);
774
775		s_bCommandComplete(pDevice);
776		break;
777
778	case WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE:
779		// wait all TD complete
780		if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
781			vCommandTimerWait((void *)pDevice, 10);
782			spin_unlock_irq(&pDevice->lock);
783			return;
784		}
785		if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
786			vCommandTimerWait((void *)pDevice, 10);
787			spin_unlock_irq(&pDevice->lock);
788			return;
789		}
790		pDevice->byBBVGACurrent = pDevice->byBBVGANew;
791		BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
792		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SetVGAGainOffset %02X\n", pDevice->byBBVGACurrent);
793		s_bCommandComplete(pDevice);
794		break;
795
796	default:
797		s_bCommandComplete(pDevice);
798		break;
799
800	} //switch
801	spin_unlock_irq(&pDevice->lock);
802	return;
803}
804
805static
806bool
807s_bCommandComplete(
808	PSDevice pDevice
809)
810{
811	PWLAN_IE_SSID pSSID;
812	bool bRadioCmd = false;
813	bool bForceSCAN = true;
814	PSMgmtObject  pMgmt = pDevice->pMgmt;
815
816	pDevice->eCommandState = WLAN_CMD_IDLE;
817	if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) {
818		//Command Queue Empty
819		pDevice->bCmdRunning = false;
820		return true;
821	} else {
822		pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd;
823		pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID;
824		bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd;
825		bForceSCAN = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bForceSCAN;
826		ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE);
827		pDevice->cbFreeCmdQueue++;
828		pDevice->bCmdRunning = true;
829		switch (pDevice->eCommand) {
830		case WLAN_CMD_BSSID_SCAN:
831			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState= WLAN_CMD_BSSID_SCAN\n");
832			pDevice->eCommandState = WLAN_CMD_SCAN_START;
833			pMgmt->uScanChannel = 0;
834			if (pSSID->len != 0) {
835				memcpy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
836			} else {
837				memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
838			}
839			break;
840		case WLAN_CMD_SSID:
841			pDevice->eCommandState = WLAN_CMD_SSID_START;
842			if (pSSID->len > WLAN_SSID_MAXLEN)
843				pSSID->len = WLAN_SSID_MAXLEN;
844			if (pSSID->len != 0)
845				memcpy(pDevice->pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
846			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState= WLAN_CMD_SSID_START\n");
847			break;
848		case WLAN_CMD_DISASSOCIATE:
849			pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START;
850			break;
851		case WLAN_CMD_RX_PSPOLL:
852			pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START;
853			break;
854		case WLAN_CMD_RUN_AP:
855			pDevice->eCommandState = WLAN_CMD_AP_MODE_START;
856			break;
857		case WLAN_CMD_RADIO:
858			pDevice->eCommandState = WLAN_CMD_RADIO_START;
859			pDevice->bRadioCmd = bRadioCmd;
860			break;
861		case WLAN_CMD_CHANGE_BBSENSITIVITY:
862			pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
863			break;
864
865		default:
866			break;
867
868		}
869
870		vCommandTimerWait((void *)pDevice, 0);
871	}
872
873	return true;
874}
875
876bool bScheduleCommand(
877	void *hDeviceContext,
878	CMD_CODE    eCommand,
879	unsigned char *pbyItem0
880)
881{
882	PSDevice        pDevice = (PSDevice)hDeviceContext;
883
884	if (pDevice->cbFreeCmdQueue == 0) {
885		return false;
886	}
887	pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand;
888	pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true;
889	memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
890
891	if (pbyItem0 != NULL) {
892		switch (eCommand) {
893		case WLAN_CMD_BSSID_SCAN:
894			memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
895			       pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
896			pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = false;
897			break;
898
899		case WLAN_CMD_SSID:
900			memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
901			       pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
902			break;
903
904		case WLAN_CMD_DISASSOCIATE:
905			pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((int *)pbyItem0);
906			break;
907
908		case WLAN_CMD_RX_PSPOLL:
909			break;
910
911		case WLAN_CMD_RADIO:
912			pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((int *)pbyItem0);
913			break;
914
915		case WLAN_CMD_CHANGE_BBSENSITIVITY:
916			pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
917			break;
918
919		default:
920			break;
921		}
922	}
923
924	ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE);
925	pDevice->cbFreeCmdQueue--;
926
927	if (!pDevice->bCmdRunning)
928		s_bCommandComplete(pDevice);
929
930	return true;
931}
932
933/*
934 * Description:
935 *      Clear BSSID_SCAN cmd in CMD Queue
936 *
937 * Parameters:
938 *  In:
939 *      hDeviceContext  - Pointer to the adapter
940 *      eCommand        - Command
941 *  Out:
942 *      none
943 *
944 * Return Value: true if success; otherwise false
945 *
946 */
947bool bClearBSSID_SCAN(
948	void *hDeviceContext
949)
950{
951	PSDevice        pDevice = (PSDevice)hDeviceContext;
952	unsigned int uCmdDequeueIdx = pDevice->uCmdDequeueIdx;
953	unsigned int ii;
954
955	if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) {
956		for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii++) {
957			if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN)
958				pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE;
959			ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE);
960			if (uCmdDequeueIdx == pDevice->uCmdEnqueueIdx)
961				break;
962		}
963	}
964	return true;
965}
966
967//mike add:reset command timer
968void
969vResetCommandTimer(
970	void *hDeviceContext
971)
972{
973	PSDevice        pDevice = (PSDevice)hDeviceContext;
974
975	//delete timer
976	del_timer(&pDevice->sTimerCommand);
977	//init timer
978	init_timer(&pDevice->sTimerCommand);
979	pDevice->sTimerCommand.data = (unsigned long) pDevice;
980	pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
981	pDevice->sTimerCommand.expires = RUN_AT(HZ);
982	pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
983	pDevice->uCmdDequeueIdx = 0;
984	pDevice->uCmdEnqueueIdx = 0;
985	pDevice->eCommandState = WLAN_CMD_IDLE;
986	pDevice->bCmdRunning = false;
987	pDevice->bCmdClear = false;
988}
989
990#ifdef TxInSleep
991void
992BSSvSecondTxData(
993	void *hDeviceContext
994)
995{
996	PSDevice        pDevice = (PSDevice)hDeviceContext;
997	PSMgmtObject  pMgmt = &(pDevice->sMgmtObj);
998	pDevice->nTxDataTimeCout++;
999
1000	if (pDevice->nTxDataTimeCout < 4)     //don't tx data if timer less than 40s
1001	{
1002		pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
1003		add_timer(&pDevice->sTimerTxData);
1004		return;
1005	}
1006
1007	spin_lock_irq(&pDevice->lock);
1008#if 1
1009	if ((pDevice->bLinkPass && (pMgmt->eAuthenMode < WMAC_AUTH_WPA)) ||  //open && sharekey linking
1010	    pDevice->fWPA_Authened) {   //wpa linking
1011#else
1012		if (pDevice->bLinkPass == true) {
1013#endif
1014			pDevice->fTxDataInSleep = true;
1015			PSbSendNullPacket(pDevice);      //send null packet
1016			pDevice->fTxDataInSleep = false;
1017		}
1018		spin_unlock_irq(&pDevice->lock);
1019
1020		pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
1021		add_timer(&pDevice->sTimerTxData);
1022		return;
1023	}
1024#endif
1025