• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* src/prism2/driver/prism2mgmt.c
2  *
3  * Management request handler functions.
4  *
5  * Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
6  * --------------------------------------------------------------------
7  *
8  * linux-wlan
9  *
10  *   The contents of this file are subject to the Mozilla Public
11  *   License Version 1.1 (the "License"); you may not use this file
12  *   except in compliance with the License. You may obtain a copy of
13  *   the License at http://www.mozilla.org/MPL/
14  *
15  *   Software distributed under the License is distributed on an "AS
16  *   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17  *   implied. See the License for the specific language governing
18  *   rights and limitations under the License.
19  *
20  *   Alternatively, the contents of this file may be used under the
21  *   terms of the GNU Public License version 2 (the "GPL"), in which
22  *   case the provisions of the GPL are applicable instead of the
23  *   above.  If you wish to allow the use of your version of this file
24  *   only under the terms of the GPL and not to allow others to use
25  *   your version of this file under the MPL, indicate your decision
26  *   by deleting the provisions above and replace them with the notice
27  *   and other provisions required by the GPL.  If you do not delete
28  *   the provisions above, a recipient may use your version of this
29  *   file under either the MPL or the GPL.
30  *
31  * --------------------------------------------------------------------
32  *
33  * Inquiries regarding the linux-wlan Open Source project can be
34  * made directly to:
35  *
36  * AbsoluteValue Systems Inc.
37  * info@linux-wlan.com
38  * http://www.linux-wlan.com
39  *
40  * --------------------------------------------------------------------
41  *
42  * Portions of the development of this software were funded by
43  * Intersil Corporation as part of PRISM(R) chipset product development.
44  *
45  * --------------------------------------------------------------------
46  *
47  * The functions in this file handle management requests sent from
48  * user mode.
49  *
50  * Most of these functions have two separate blocks of code that are
51  * conditional on whether this is a station or an AP.  This is used
52  * to separate out the STA and AP responses to these management primitives.
53  * It's a choice (good, bad, indifferent?) to have the code in the same
54  * place so it's clear that the same primitive is implemented in both
55  * cases but has different behavior.
56  *
57  * --------------------------------------------------------------------
58  */
59 
60 #include <linux/if_arp.h>
61 #include <linux/module.h>
62 #include <linux/kernel.h>
63 #include <linux/wait.h>
64 #include <linux/sched.h>
65 #include <linux/types.h>
66 #include <linux/wireless.h>
67 #include <linux/netdevice.h>
68 #include <linux/delay.h>
69 #include <linux/io.h>
70 #include <asm/byteorder.h>
71 #include <linux/random.h>
72 #include <linux/usb.h>
73 #include <linux/bitops.h>
74 
75 #include "p80211types.h"
76 #include "p80211hdr.h"
77 #include "p80211mgmt.h"
78 #include "p80211conv.h"
79 #include "p80211msg.h"
80 #include "p80211netdev.h"
81 #include "p80211metadef.h"
82 #include "p80211metastruct.h"
83 #include "hfa384x.h"
84 #include "prism2mgmt.h"
85 
86 /* Converts 802.11 format rate specifications to prism2 */
87 #define p80211rate_to_p2bit(n)	((((n) & ~BIT(7)) == 2) ? BIT(0) :  \
88 				 (((n) & ~BIT(7)) == 4) ? BIT(1) : \
89 				 (((n) & ~BIT(7)) == 11) ? BIT(2) : \
90 				 (((n) & ~BIT(7)) == 22) ? BIT(3) : 0)
91 
92 /*----------------------------------------------------------------
93  * prism2mgmt_scan
94  *
95  * Initiate a scan for BSSs.
96  *
97  * This function corresponds to MLME-scan.request and part of
98  * MLME-scan.confirm.  As far as I can tell in the standard, there
99  * are no restrictions on when a scan.request may be issued.  We have
100  * to handle in whatever state the driver/MAC happen to be.
101  *
102  * Arguments:
103  *	wlandev		wlan device structure
104  *	msgp		ptr to msg buffer
105  *
106  * Returns:
107  *	0	success and done
108  *	<0	success, but we're waiting for something to finish.
109  *	>0	an error occurred while handling the message.
110  * Side effects:
111  *
112  * Call context:
113  *	process thread  (usually)
114  *	interrupt
115  *----------------------------------------------------------------
116  */
prism2mgmt_scan(struct wlandevice * wlandev,void * msgp)117 int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp)
118 {
119 	int result = 0;
120 	struct hfa384x *hw = wlandev->priv;
121 	struct p80211msg_dot11req_scan *msg = msgp;
122 	u16 roamingmode, word;
123 	int i, timeout;
124 	int istmpenable = 0;
125 
126 	struct hfa384x_host_scan_request_data scanreq;
127 
128 	/* gatekeeper check */
129 	if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
130 				     hw->ident_sta_fw.minor,
131 				     hw->ident_sta_fw.variant) <
132 	    HFA384x_FIRMWARE_VERSION(1, 3, 2)) {
133 		netdev_err(wlandev->netdev,
134 			   "HostScan not supported with current firmware (<1.3.2).\n");
135 		result = 1;
136 		msg->resultcode.data = P80211ENUM_resultcode_not_supported;
137 		goto exit;
138 	}
139 
140 	memset(&scanreq, 0, sizeof(scanreq));
141 
142 	/* save current roaming mode */
143 	result = hfa384x_drvr_getconfig16(hw,
144 					  HFA384x_RID_CNFROAMINGMODE,
145 					  &roamingmode);
146 	if (result) {
147 		netdev_err(wlandev->netdev,
148 			   "getconfig(ROAMMODE) failed. result=%d\n", result);
149 		msg->resultcode.data =
150 		    P80211ENUM_resultcode_implementation_failure;
151 		goto exit;
152 	}
153 
154 	/* drop into mode 3 for the scan */
155 	result = hfa384x_drvr_setconfig16(hw,
156 					  HFA384x_RID_CNFROAMINGMODE,
157 					  HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
158 	if (result) {
159 		netdev_err(wlandev->netdev,
160 			   "setconfig(ROAMINGMODE) failed. result=%d\n",
161 			   result);
162 		msg->resultcode.data =
163 		    P80211ENUM_resultcode_implementation_failure;
164 		goto exit;
165 	}
166 
167 	/* active or passive? */
168 	if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
169 				     hw->ident_sta_fw.minor,
170 				     hw->ident_sta_fw.variant) >
171 	    HFA384x_FIRMWARE_VERSION(1, 5, 0)) {
172 		if (msg->scantype.data != P80211ENUM_scantype_active)
173 			word = msg->maxchanneltime.data;
174 		else
175 			word = 0;
176 
177 		result =
178 		    hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL,
179 					     word);
180 		if (result) {
181 			netdev_warn(wlandev->netdev,
182 				    "Passive scan not supported with current firmware.  (<1.5.1)\n");
183 		}
184 	}
185 
186 	/* set up the txrate to be 2MBPS. Should be fastest basicrate... */
187 	word = HFA384x_RATEBIT_2;
188 	scanreq.tx_rate = cpu_to_le16(word);
189 
190 	/* set up the channel list */
191 	word = 0;
192 	for (i = 0; i < msg->channellist.data.len; i++) {
193 		u8 channel = msg->channellist.data.data[i];
194 
195 		if (channel > 14)
196 			continue;
197 		/* channel 1 is BIT 0 ... channel 14 is BIT 13 */
198 		word |= (1 << (channel - 1));
199 	}
200 	scanreq.channel_list = cpu_to_le16(word);
201 
202 	/* set up the ssid, if present. */
203 	scanreq.ssid.len = cpu_to_le16(msg->ssid.data.len);
204 	memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
205 
206 	/* Enable the MAC port if it's not already enabled  */
207 	result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
208 	if (result) {
209 		netdev_err(wlandev->netdev,
210 			   "getconfig(PORTSTATUS) failed. result=%d\n", result);
211 		msg->resultcode.data =
212 		    P80211ENUM_resultcode_implementation_failure;
213 		goto exit;
214 	}
215 	if (word == HFA384x_PORTSTATUS_DISABLED) {
216 		__le16 wordbuf[17];
217 
218 		result = hfa384x_drvr_setconfig16(hw,
219 					HFA384x_RID_CNFROAMINGMODE,
220 					HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
221 		if (result) {
222 			netdev_err(wlandev->netdev,
223 				   "setconfig(ROAMINGMODE) failed. result=%d\n",
224 				   result);
225 			msg->resultcode.data =
226 			    P80211ENUM_resultcode_implementation_failure;
227 			goto exit;
228 		}
229 		/* Construct a bogus SSID and assign it to OwnSSID and
230 		 * DesiredSSID
231 		 */
232 		wordbuf[0] = cpu_to_le16(WLAN_SSID_MAXLEN);
233 		get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
234 		result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
235 						wordbuf,
236 						HFA384x_RID_CNFOWNSSID_LEN);
237 		if (result) {
238 			netdev_err(wlandev->netdev, "Failed to set OwnSSID.\n");
239 			msg->resultcode.data =
240 			    P80211ENUM_resultcode_implementation_failure;
241 			goto exit;
242 		}
243 		result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
244 						wordbuf,
245 						HFA384x_RID_CNFDESIREDSSID_LEN);
246 		if (result) {
247 			netdev_err(wlandev->netdev,
248 				   "Failed to set DesiredSSID.\n");
249 			msg->resultcode.data =
250 			    P80211ENUM_resultcode_implementation_failure;
251 			goto exit;
252 		}
253 		/* bsstype */
254 		result = hfa384x_drvr_setconfig16(hw,
255 						  HFA384x_RID_CNFPORTTYPE,
256 						  HFA384x_PORTTYPE_IBSS);
257 		if (result) {
258 			netdev_err(wlandev->netdev,
259 				   "Failed to set CNFPORTTYPE.\n");
260 			msg->resultcode.data =
261 			    P80211ENUM_resultcode_implementation_failure;
262 			goto exit;
263 		}
264 		/* ibss options */
265 		result = hfa384x_drvr_setconfig16(hw,
266 					HFA384x_RID_CREATEIBSS,
267 					HFA384x_CREATEIBSS_JOINCREATEIBSS);
268 		if (result) {
269 			netdev_err(wlandev->netdev,
270 				   "Failed to set CREATEIBSS.\n");
271 			msg->resultcode.data =
272 			    P80211ENUM_resultcode_implementation_failure;
273 			goto exit;
274 		}
275 		result = hfa384x_drvr_enable(hw, 0);
276 		if (result) {
277 			netdev_err(wlandev->netdev,
278 				   "drvr_enable(0) failed. result=%d\n",
279 				   result);
280 			msg->resultcode.data =
281 			    P80211ENUM_resultcode_implementation_failure;
282 			goto exit;
283 		}
284 		istmpenable = 1;
285 	}
286 
287 	/* Figure out our timeout first Kus, then HZ */
288 	timeout = msg->channellist.data.len * msg->maxchanneltime.data;
289 	timeout = (timeout * HZ) / 1000;
290 
291 	/* Issue the scan request */
292 	hw->scanflag = 0;
293 
294 	result = hfa384x_drvr_setconfig(hw,
295 					HFA384x_RID_HOSTSCAN, &scanreq,
296 					sizeof(scanreq));
297 	if (result) {
298 		netdev_err(wlandev->netdev,
299 			   "setconfig(SCANREQUEST) failed. result=%d\n",
300 			   result);
301 		msg->resultcode.data =
302 		    P80211ENUM_resultcode_implementation_failure;
303 		goto exit;
304 	}
305 
306 	/* sleep until info frame arrives */
307 	wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
308 
309 	msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
310 	if (hw->scanflag == -1)
311 		hw->scanflag = 0;
312 
313 	msg->numbss.data = hw->scanflag;
314 
315 	hw->scanflag = 0;
316 
317 	/* Disable port if we temporarily enabled it. */
318 	if (istmpenable) {
319 		result = hfa384x_drvr_disable(hw, 0);
320 		if (result) {
321 			netdev_err(wlandev->netdev,
322 				   "drvr_disable(0) failed. result=%d\n",
323 				   result);
324 			msg->resultcode.data =
325 			    P80211ENUM_resultcode_implementation_failure;
326 			goto exit;
327 		}
328 	}
329 
330 	/* restore original roaming mode */
331 	result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
332 					  roamingmode);
333 	if (result) {
334 		netdev_err(wlandev->netdev,
335 			   "setconfig(ROAMMODE) failed. result=%d\n", result);
336 		msg->resultcode.data =
337 		    P80211ENUM_resultcode_implementation_failure;
338 		goto exit;
339 	}
340 
341 	result = 0;
342 	msg->resultcode.data = P80211ENUM_resultcode_success;
343 
344 exit:
345 	msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
346 
347 	return result;
348 }
349 
350 /*----------------------------------------------------------------
351  * prism2mgmt_scan_results
352  *
353  * Retrieve the BSS description for one of the BSSs identified in
354  * a scan.
355  *
356  * Arguments:
357  *	wlandev		wlan device structure
358  *	msgp		ptr to msg buffer
359  *
360  * Returns:
361  *	0	success and done
362  *	<0	success, but we're waiting for something to finish.
363  *	>0	an error occurred while handling the message.
364  * Side effects:
365  *
366  * Call context:
367  *	process thread  (usually)
368  *	interrupt
369  *----------------------------------------------------------------
370  */
prism2mgmt_scan_results(struct wlandevice * wlandev,void * msgp)371 int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp)
372 {
373 	int result = 0;
374 	struct p80211msg_dot11req_scan_results *req;
375 	struct hfa384x *hw = wlandev->priv;
376 	struct hfa384x_hscan_result_sub *item = NULL;
377 
378 	int count;
379 
380 	req = msgp;
381 
382 	req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
383 
384 	if (!hw->scanresults) {
385 		netdev_err(wlandev->netdev,
386 			   "dot11req_scan_results can only be used after a successful dot11req_scan.\n");
387 		result = 2;
388 		req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
389 		goto exit;
390 	}
391 
392 	count = (hw->scanresults->framelen - 3) / 32;
393 	if (count > HFA384x_SCANRESULT_MAX)
394 		count = HFA384x_SCANRESULT_MAX;
395 
396 	if (req->bssindex.data >= count) {
397 		pr_debug("requested index (%d) out of range (%d)\n",
398 			 req->bssindex.data, count);
399 		result = 2;
400 		req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
401 		goto exit;
402 	}
403 
404 	item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
405 	/* signal and noise */
406 	req->signal.status = P80211ENUM_msgitem_status_data_ok;
407 	req->noise.status = P80211ENUM_msgitem_status_data_ok;
408 	req->signal.data = le16_to_cpu(item->sl);
409 	req->noise.data = le16_to_cpu(item->anl);
410 
411 	/* BSSID */
412 	req->bssid.status = P80211ENUM_msgitem_status_data_ok;
413 	req->bssid.data.len = WLAN_BSSID_LEN;
414 	memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
415 
416 	/* SSID */
417 	req->ssid.status = P80211ENUM_msgitem_status_data_ok;
418 	req->ssid.data.len = le16_to_cpu(item->ssid.len);
419 	req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN);
420 	memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
421 
422 	/* supported rates */
423 	for (count = 0; count < 10; count++)
424 		if (item->supprates[count] == 0)
425 			break;
426 
427 #define REQBASICRATE(N) \
428 	do { \
429 		if ((count >= N) && DOT11_RATE5_ISBASIC_GET( \
430 			item->supprates[(N) - 1])) { \
431 			req->basicrate ## N .data = item->supprates[(N) - 1]; \
432 			req->basicrate ## N .status = \
433 				P80211ENUM_msgitem_status_data_ok; \
434 		} \
435 	} while (0)
436 
437 	REQBASICRATE(1);
438 	REQBASICRATE(2);
439 	REQBASICRATE(3);
440 	REQBASICRATE(4);
441 	REQBASICRATE(5);
442 	REQBASICRATE(6);
443 	REQBASICRATE(7);
444 	REQBASICRATE(8);
445 
446 #define REQSUPPRATE(N) \
447 	do { \
448 		if (count >= N) { \
449 			req->supprate ## N .data = item->supprates[(N) - 1]; \
450 			req->supprate ## N .status = \
451 				P80211ENUM_msgitem_status_data_ok; \
452 		} \
453 	} while (0)
454 
455 	REQSUPPRATE(1);
456 	REQSUPPRATE(2);
457 	REQSUPPRATE(3);
458 	REQSUPPRATE(4);
459 	REQSUPPRATE(5);
460 	REQSUPPRATE(6);
461 	REQSUPPRATE(7);
462 	REQSUPPRATE(8);
463 
464 	/* beacon period */
465 	req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
466 	req->beaconperiod.data = le16_to_cpu(item->bcnint);
467 
468 	/* timestamps */
469 	req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
470 	req->timestamp.data = jiffies;
471 	req->localtime.status = P80211ENUM_msgitem_status_data_ok;
472 	req->localtime.data = jiffies;
473 
474 	/* atim window */
475 	req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
476 	req->ibssatimwindow.data = le16_to_cpu(item->atim);
477 
478 	/* Channel */
479 	req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
480 	req->dschannel.data = le16_to_cpu(item->chid);
481 
482 	/* capinfo bits */
483 	count = le16_to_cpu(item->capinfo);
484 	req->capinfo.status = P80211ENUM_msgitem_status_data_ok;
485 	req->capinfo.data = count;
486 
487 	/* privacy flag */
488 	req->privacy.status = P80211ENUM_msgitem_status_data_ok;
489 	req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
490 
491 	/* cfpollable */
492 	req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
493 	req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
494 
495 	/* cfpollreq */
496 	req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
497 	req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
498 
499 	/* bsstype */
500 	req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
501 	req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
502 	    P80211ENUM_bsstype_infrastructure : P80211ENUM_bsstype_independent;
503 
504 	result = 0;
505 	req->resultcode.data = P80211ENUM_resultcode_success;
506 
507 exit:
508 	return result;
509 }
510 
511 /*----------------------------------------------------------------
512  * prism2mgmt_start
513  *
514  * Start a BSS.  Any station can do this for IBSS, only AP for ESS.
515  *
516  * Arguments:
517  *	wlandev		wlan device structure
518  *	msgp		ptr to msg buffer
519  *
520  * Returns:
521  *	0	success and done
522  *	<0	success, but we're waiting for something to finish.
523  *	>0	an error occurred while handling the message.
524  * Side effects:
525  *
526  * Call context:
527  *	process thread  (usually)
528  *	interrupt
529  *----------------------------------------------------------------
530  */
prism2mgmt_start(struct wlandevice * wlandev,void * msgp)531 int prism2mgmt_start(struct wlandevice *wlandev, void *msgp)
532 {
533 	int result = 0;
534 	struct hfa384x *hw = wlandev->priv;
535 	struct p80211msg_dot11req_start *msg = msgp;
536 
537 	struct p80211pstrd *pstr;
538 	u8 bytebuf[80];
539 	struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *)bytebuf;
540 	u16 word;
541 
542 	wlandev->macmode = WLAN_MACMODE_NONE;
543 
544 	/* Set the SSID */
545 	memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
546 
547 	/*** ADHOC IBSS ***/
548 	/* see if current f/w is less than 8c3 */
549 	if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
550 				     hw->ident_sta_fw.minor,
551 				     hw->ident_sta_fw.variant) <
552 	    HFA384x_FIRMWARE_VERSION(0, 8, 3)) {
553 		/* Ad-Hoc not quite supported on Prism2 */
554 		msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
555 		msg->resultcode.data = P80211ENUM_resultcode_not_supported;
556 		goto done;
557 	}
558 
559 	msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
560 
561 	/*** STATION ***/
562 	/* Set the REQUIRED config items */
563 	/* SSID */
564 	pstr = (struct p80211pstrd *)&(msg->ssid.data);
565 	prism2mgmt_pstr2bytestr(p2bytestr, pstr);
566 	result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
567 					bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
568 	if (result) {
569 		netdev_err(wlandev->netdev, "Failed to set CnfOwnSSID\n");
570 		goto failed;
571 	}
572 	result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
573 					bytebuf,
574 					HFA384x_RID_CNFDESIREDSSID_LEN);
575 	if (result) {
576 		netdev_err(wlandev->netdev, "Failed to set CnfDesiredSSID\n");
577 		goto failed;
578 	}
579 
580 	/* bsstype - we use the default in the ap firmware */
581 	/* IBSS port */
582 	hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
583 
584 	/* beacon period */
585 	word = msg->beaconperiod.data;
586 	result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word);
587 	if (result) {
588 		netdev_err(wlandev->netdev,
589 			   "Failed to set beacon period=%d.\n", word);
590 		goto failed;
591 	}
592 
593 	/* dschannel */
594 	word = msg->dschannel.data;
595 	result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
596 	if (result) {
597 		netdev_err(wlandev->netdev,
598 			   "Failed to set channel=%d.\n", word);
599 		goto failed;
600 	}
601 	/* Basic rates */
602 	word = p80211rate_to_p2bit(msg->basicrate1.data);
603 	if (msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok)
604 		word |= p80211rate_to_p2bit(msg->basicrate2.data);
605 
606 	if (msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok)
607 		word |= p80211rate_to_p2bit(msg->basicrate3.data);
608 
609 	if (msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok)
610 		word |= p80211rate_to_p2bit(msg->basicrate4.data);
611 
612 	if (msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok)
613 		word |= p80211rate_to_p2bit(msg->basicrate5.data);
614 
615 	if (msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok)
616 		word |= p80211rate_to_p2bit(msg->basicrate6.data);
617 
618 	if (msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok)
619 		word |= p80211rate_to_p2bit(msg->basicrate7.data);
620 
621 	if (msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok)
622 		word |= p80211rate_to_p2bit(msg->basicrate8.data);
623 
624 	result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
625 	if (result) {
626 		netdev_err(wlandev->netdev,
627 			   "Failed to set basicrates=%d.\n", word);
628 		goto failed;
629 	}
630 
631 	/* Operational rates (supprates and txratecontrol) */
632 	word = p80211rate_to_p2bit(msg->operationalrate1.data);
633 	if (msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok)
634 		word |= p80211rate_to_p2bit(msg->operationalrate2.data);
635 
636 	if (msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok)
637 		word |= p80211rate_to_p2bit(msg->operationalrate3.data);
638 
639 	if (msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok)
640 		word |= p80211rate_to_p2bit(msg->operationalrate4.data);
641 
642 	if (msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok)
643 		word |= p80211rate_to_p2bit(msg->operationalrate5.data);
644 
645 	if (msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok)
646 		word |= p80211rate_to_p2bit(msg->operationalrate6.data);
647 
648 	if (msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok)
649 		word |= p80211rate_to_p2bit(msg->operationalrate7.data);
650 
651 	if (msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok)
652 		word |= p80211rate_to_p2bit(msg->operationalrate8.data);
653 
654 	result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
655 	if (result) {
656 		netdev_err(wlandev->netdev,
657 			   "Failed to set supprates=%d.\n", word);
658 		goto failed;
659 	}
660 
661 	result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
662 	if (result) {
663 		netdev_err(wlandev->netdev, "Failed to set txrates=%d.\n",
664 			   word);
665 		goto failed;
666 	}
667 
668 	/* Set the macmode so the frame setup code knows what to do */
669 	if (msg->bsstype.data == P80211ENUM_bsstype_independent) {
670 		wlandev->macmode = WLAN_MACMODE_IBSS_STA;
671 		/* lets extend the data length a bit */
672 		hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
673 	}
674 
675 	/* Enable the Port */
676 	result = hfa384x_drvr_enable(hw, 0);
677 	if (result) {
678 		netdev_err(wlandev->netdev,
679 			   "Enable macport failed, result=%d.\n", result);
680 		goto failed;
681 	}
682 
683 	msg->resultcode.data = P80211ENUM_resultcode_success;
684 
685 	goto done;
686 failed:
687 	pr_debug("Failed to set a config option, result=%d\n", result);
688 	msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
689 
690 done:
691 	return 0;
692 }
693 
694 /*----------------------------------------------------------------
695  * prism2mgmt_readpda
696  *
697  * Collect the PDA data and put it in the message.
698  *
699  * Arguments:
700  *	wlandev		wlan device structure
701  *	msgp		ptr to msg buffer
702  *
703  * Returns:
704  *	0	success and done
705  *	<0	success, but we're waiting for something to finish.
706  *	>0	an error occurred while handling the message.
707  * Side effects:
708  *
709  * Call context:
710  *	process thread  (usually)
711  *----------------------------------------------------------------
712  */
prism2mgmt_readpda(struct wlandevice * wlandev,void * msgp)713 int prism2mgmt_readpda(struct wlandevice *wlandev, void *msgp)
714 {
715 	struct hfa384x *hw = wlandev->priv;
716 	struct p80211msg_p2req_readpda *msg = msgp;
717 	int result;
718 
719 	/* We only support collecting the PDA when in the FWLOAD
720 	 * state.
721 	 */
722 	if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
723 		netdev_err(wlandev->netdev,
724 			   "PDA may only be read in the fwload state.\n");
725 		msg->resultcode.data =
726 		    P80211ENUM_resultcode_implementation_failure;
727 		msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
728 	} else {
729 		/*  Call drvr_readpda(), it handles the auxport enable
730 		 *  and validating the returned PDA.
731 		 */
732 		result = hfa384x_drvr_readpda(hw,
733 					      msg->pda.data,
734 					      HFA384x_PDA_LEN_MAX);
735 		if (result) {
736 			netdev_err(wlandev->netdev,
737 				   "hfa384x_drvr_readpda() failed, result=%d\n",
738 				   result);
739 
740 			msg->resultcode.data =
741 			    P80211ENUM_resultcode_implementation_failure;
742 			msg->resultcode.status =
743 			    P80211ENUM_msgitem_status_data_ok;
744 			return 0;
745 		}
746 		msg->pda.status = P80211ENUM_msgitem_status_data_ok;
747 		msg->resultcode.data = P80211ENUM_resultcode_success;
748 		msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
749 	}
750 
751 	return 0;
752 }
753 
754 /*----------------------------------------------------------------
755  * prism2mgmt_ramdl_state
756  *
757  * Establishes the beginning/end of a card RAM download session.
758  *
759  * It is expected that the ramdl_write() function will be called
760  * one or more times between the 'enable' and 'disable' calls to
761  * this function.
762  *
763  * Note: This function should not be called when a mac comm port
764  *       is active.
765  *
766  * Arguments:
767  *	wlandev		wlan device structure
768  *	msgp		ptr to msg buffer
769  *
770  * Returns:
771  *	0	success and done
772  *	<0	success, but we're waiting for something to finish.
773  *	>0	an error occurred while handling the message.
774  * Side effects:
775  *
776  * Call context:
777  *	process thread  (usually)
778  *----------------------------------------------------------------
779  */
prism2mgmt_ramdl_state(struct wlandevice * wlandev,void * msgp)780 int prism2mgmt_ramdl_state(struct wlandevice *wlandev, void *msgp)
781 {
782 	struct hfa384x *hw = wlandev->priv;
783 	struct p80211msg_p2req_ramdl_state *msg = msgp;
784 
785 	if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
786 		netdev_err(wlandev->netdev,
787 			   "ramdl_state(): may only be called in the fwload state.\n");
788 		msg->resultcode.data =
789 		    P80211ENUM_resultcode_implementation_failure;
790 		msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
791 		return 0;
792 	}
793 
794 	/*
795 	 ** Note: Interrupts are locked out if this is an AP and are NOT
796 	 ** locked out if this is a station.
797 	 */
798 
799 	msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
800 	if (msg->enable.data == P80211ENUM_truth_true) {
801 		if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) {
802 			msg->resultcode.data =
803 			    P80211ENUM_resultcode_implementation_failure;
804 		} else {
805 			msg->resultcode.data = P80211ENUM_resultcode_success;
806 		}
807 	} else {
808 		hfa384x_drvr_ramdl_disable(hw);
809 		msg->resultcode.data = P80211ENUM_resultcode_success;
810 	}
811 
812 	return 0;
813 }
814 
815 /*----------------------------------------------------------------
816  * prism2mgmt_ramdl_write
817  *
818  * Writes a buffer to the card RAM using the download state.  This
819  * is for writing code to card RAM.  To just read or write raw data
820  * use the aux functions.
821  *
822  * Arguments:
823  *	wlandev		wlan device structure
824  *	msgp		ptr to msg buffer
825  *
826  * Returns:
827  *	0	success and done
828  *	<0	success, but we're waiting for something to finish.
829  *	>0	an error occurred while handling the message.
830  * Side effects:
831  *
832  * Call context:
833  *	process thread  (usually)
834  *----------------------------------------------------------------
835  */
prism2mgmt_ramdl_write(struct wlandevice * wlandev,void * msgp)836 int prism2mgmt_ramdl_write(struct wlandevice *wlandev, void *msgp)
837 {
838 	struct hfa384x *hw = wlandev->priv;
839 	struct p80211msg_p2req_ramdl_write *msg = msgp;
840 	u32 addr;
841 	u32 len;
842 	u8 *buf;
843 
844 	if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
845 		netdev_err(wlandev->netdev,
846 			   "ramdl_write(): may only be called in the fwload state.\n");
847 		msg->resultcode.data =
848 		    P80211ENUM_resultcode_implementation_failure;
849 		msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
850 		return 0;
851 	}
852 
853 	msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
854 	/* first validate the length */
855 	if (msg->len.data > sizeof(msg->data.data)) {
856 		msg->resultcode.status =
857 		    P80211ENUM_resultcode_invalid_parameters;
858 		return 0;
859 	}
860 	/* call the hfa384x function to do the write */
861 	addr = msg->addr.data;
862 	len = msg->len.data;
863 	buf = msg->data.data;
864 	if (hfa384x_drvr_ramdl_write(hw, addr, buf, len))
865 		msg->resultcode.data = P80211ENUM_resultcode_refused;
866 
867 	msg->resultcode.data = P80211ENUM_resultcode_success;
868 
869 	return 0;
870 }
871 
872 /*----------------------------------------------------------------
873  * prism2mgmt_flashdl_state
874  *
875  * Establishes the beginning/end of a card Flash download session.
876  *
877  * It is expected that the flashdl_write() function will be called
878  * one or more times between the 'enable' and 'disable' calls to
879  * this function.
880  *
881  * Note: This function should not be called when a mac comm port
882  *       is active.
883  *
884  * Arguments:
885  *	wlandev		wlan device structure
886  *	msgp		ptr to msg buffer
887  *
888  * Returns:
889  *	0	success and done
890  *	<0	success, but we're waiting for something to finish.
891  *	>0	an error occurred while handling the message.
892  * Side effects:
893  *
894  * Call context:
895  *	process thread  (usually)
896  *----------------------------------------------------------------
897  */
prism2mgmt_flashdl_state(struct wlandevice * wlandev,void * msgp)898 int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp)
899 {
900 	int result = 0;
901 	struct hfa384x *hw = wlandev->priv;
902 	struct p80211msg_p2req_flashdl_state *msg = msgp;
903 
904 	if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
905 		netdev_err(wlandev->netdev,
906 			   "flashdl_state(): may only be called in the fwload state.\n");
907 		msg->resultcode.data =
908 		    P80211ENUM_resultcode_implementation_failure;
909 		msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
910 		return 0;
911 	}
912 
913 	/*
914 	 ** Note: Interrupts are locked out if this is an AP and are NOT
915 	 ** locked out if this is a station.
916 	 */
917 
918 	msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
919 	if (msg->enable.data == P80211ENUM_truth_true) {
920 		if (hfa384x_drvr_flashdl_enable(hw)) {
921 			msg->resultcode.data =
922 			    P80211ENUM_resultcode_implementation_failure;
923 		} else {
924 			msg->resultcode.data = P80211ENUM_resultcode_success;
925 		}
926 	} else {
927 		hfa384x_drvr_flashdl_disable(hw);
928 		msg->resultcode.data = P80211ENUM_resultcode_success;
929 		/* NOTE: At this point, the MAC is in the post-reset
930 		 * state and the driver is in the fwload state.
931 		 * We need to get the MAC back into the fwload
932 		 * state.  To do this, we set the nsdstate to HWPRESENT
933 		 * and then call the ifstate function to redo everything
934 		 * that got us into the fwload state.
935 		 */
936 		wlandev->msdstate = WLAN_MSD_HWPRESENT;
937 		result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
938 		if (result != P80211ENUM_resultcode_success) {
939 			netdev_err(wlandev->netdev,
940 				   "prism2sta_ifstate(fwload) failed, P80211ENUM_resultcode=%d\n",
941 				   result);
942 			msg->resultcode.data =
943 			    P80211ENUM_resultcode_implementation_failure;
944 			result = -1;
945 		}
946 	}
947 
948 	return result;
949 }
950 
951 /*----------------------------------------------------------------
952  * prism2mgmt_flashdl_write
953  *
954  *
955  *
956  * Arguments:
957  *	wlandev		wlan device structure
958  *	msgp		ptr to msg buffer
959  *
960  * Returns:
961  *	0	success and done
962  *	<0	success, but we're waiting for something to finish.
963  *	>0	an error occurred while handling the message.
964  * Side effects:
965  *
966  * Call context:
967  *	process thread  (usually)
968  *----------------------------------------------------------------
969  */
prism2mgmt_flashdl_write(struct wlandevice * wlandev,void * msgp)970 int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp)
971 {
972 	struct hfa384x *hw = wlandev->priv;
973 	struct p80211msg_p2req_flashdl_write *msg = msgp;
974 	u32 addr;
975 	u32 len;
976 	u8 *buf;
977 
978 	if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
979 		netdev_err(wlandev->netdev,
980 			   "flashdl_write(): may only be called in the fwload state.\n");
981 		msg->resultcode.data =
982 		    P80211ENUM_resultcode_implementation_failure;
983 		msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
984 		return 0;
985 	}
986 
987 	/*
988 	 ** Note: Interrupts are locked out if this is an AP and are NOT
989 	 ** locked out if this is a station.
990 	 */
991 
992 	msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
993 	/* first validate the length */
994 	if (msg->len.data > sizeof(msg->data.data)) {
995 		msg->resultcode.status =
996 		    P80211ENUM_resultcode_invalid_parameters;
997 		return 0;
998 	}
999 	/* call the hfa384x function to do the write */
1000 	addr = msg->addr.data;
1001 	len = msg->len.data;
1002 	buf = msg->data.data;
1003 	if (hfa384x_drvr_flashdl_write(hw, addr, buf, len))
1004 		msg->resultcode.data = P80211ENUM_resultcode_refused;
1005 
1006 	msg->resultcode.data = P80211ENUM_resultcode_success;
1007 
1008 	return 0;
1009 }
1010 
1011 /*----------------------------------------------------------------
1012  * prism2mgmt_autojoin
1013  *
1014  * Associate with an ESS.
1015  *
1016  * Arguments:
1017  *	wlandev		wlan device structure
1018  *	msgp		ptr to msg buffer
1019  *
1020  * Returns:
1021  *	0	success and done
1022  *	<0	success, but we're waiting for something to finish.
1023  *	>0	an error occurred while handling the message.
1024  * Side effects:
1025  *
1026  * Call context:
1027  *	process thread  (usually)
1028  *	interrupt
1029  *----------------------------------------------------------------
1030  */
prism2mgmt_autojoin(struct wlandevice * wlandev,void * msgp)1031 int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp)
1032 {
1033 	struct hfa384x *hw = wlandev->priv;
1034 	int result = 0;
1035 	u16 reg;
1036 	u16 port_type;
1037 	struct p80211msg_lnxreq_autojoin *msg = msgp;
1038 	struct p80211pstrd *pstr;
1039 	u8 bytebuf[256];
1040 	struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *)bytebuf;
1041 
1042 	wlandev->macmode = WLAN_MACMODE_NONE;
1043 
1044 	/* Set the SSID */
1045 	memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1046 
1047 	/* Disable the Port */
1048 	hfa384x_drvr_disable(hw, 0);
1049 
1050 	/*** STATION ***/
1051 	/* Set the TxRates */
1052 	hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
1053 
1054 	/* Set the auth type */
1055 	if (msg->authtype.data == P80211ENUM_authalg_sharedkey)
1056 		reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
1057 	else
1058 		reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
1059 
1060 	hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
1061 
1062 	/* Set the ssid */
1063 	memset(bytebuf, 0, 256);
1064 	pstr = (struct p80211pstrd *)&(msg->ssid.data);
1065 	prism2mgmt_pstr2bytestr(p2bytestr, pstr);
1066 	result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
1067 					bytebuf,
1068 					HFA384x_RID_CNFDESIREDSSID_LEN);
1069 	port_type = HFA384x_PORTTYPE_BSS;
1070 	/* Set the PortType */
1071 	hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
1072 
1073 	/* Enable the Port */
1074 	hfa384x_drvr_enable(hw, 0);
1075 
1076 	/* Set the resultcode */
1077 	msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1078 	msg->resultcode.data = P80211ENUM_resultcode_success;
1079 
1080 	return result;
1081 }
1082 
1083 /*----------------------------------------------------------------
1084  * prism2mgmt_wlansniff
1085  *
1086  * Start or stop sniffing.
1087  *
1088  * Arguments:
1089  *	wlandev		wlan device structure
1090  *	msgp		ptr to msg buffer
1091  *
1092  * Returns:
1093  *	0	success and done
1094  *	<0	success, but we're waiting for something to finish.
1095  *	>0	an error occurred while handling the message.
1096  * Side effects:
1097  *
1098  * Call context:
1099  *	process thread  (usually)
1100  *	interrupt
1101  *----------------------------------------------------------------
1102  */
prism2mgmt_wlansniff(struct wlandevice * wlandev,void * msgp)1103 int prism2mgmt_wlansniff(struct wlandevice *wlandev, void *msgp)
1104 {
1105 	int result = 0;
1106 	struct p80211msg_lnxreq_wlansniff *msg = msgp;
1107 
1108 	struct hfa384x *hw = wlandev->priv;
1109 	u16 word;
1110 
1111 	msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1112 	switch (msg->enable.data) {
1113 	case P80211ENUM_truth_false:
1114 		/* Confirm that we're in monitor mode */
1115 		if (wlandev->netdev->type == ARPHRD_ETHER) {
1116 			msg->resultcode.data =
1117 			    P80211ENUM_resultcode_invalid_parameters;
1118 			return 0;
1119 		}
1120 		/* Disable monitor mode */
1121 		result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
1122 		if (result) {
1123 			pr_debug("failed to disable monitor mode, result=%d\n",
1124 				 result);
1125 			goto failed;
1126 		}
1127 		/* Disable port 0 */
1128 		result = hfa384x_drvr_disable(hw, 0);
1129 		if (result) {
1130 			pr_debug
1131 			("failed to disable port 0 after sniffing, result=%d\n",
1132 			     result);
1133 			goto failed;
1134 		}
1135 		/* Clear the driver state */
1136 		wlandev->netdev->type = ARPHRD_ETHER;
1137 
1138 		/* Restore the wepflags */
1139 		result = hfa384x_drvr_setconfig16(hw,
1140 						  HFA384x_RID_CNFWEPFLAGS,
1141 						  hw->presniff_wepflags);
1142 		if (result) {
1143 			pr_debug
1144 			    ("failed to restore wepflags=0x%04x, result=%d\n",
1145 			     hw->presniff_wepflags, result);
1146 			goto failed;
1147 		}
1148 
1149 		/* Set the port to its prior type and enable (if necessary) */
1150 		if (hw->presniff_port_type != 0) {
1151 			word = hw->presniff_port_type;
1152 			result = hfa384x_drvr_setconfig16(hw,
1153 						  HFA384x_RID_CNFPORTTYPE,
1154 						  word);
1155 			if (result) {
1156 				pr_debug
1157 				    ("failed to restore porttype, result=%d\n",
1158 				     result);
1159 				goto failed;
1160 			}
1161 
1162 			/* Enable the port */
1163 			result = hfa384x_drvr_enable(hw, 0);
1164 			if (result) {
1165 				pr_debug("failed to enable port to presniff setting, result=%d\n",
1166 					 result);
1167 				goto failed;
1168 			}
1169 		} else {
1170 			result = hfa384x_drvr_disable(hw, 0);
1171 		}
1172 
1173 		netdev_info(wlandev->netdev, "monitor mode disabled\n");
1174 		msg->resultcode.data = P80211ENUM_resultcode_success;
1175 		return 0;
1176 	case P80211ENUM_truth_true:
1177 		/* Disable the port (if enabled), only check Port 0 */
1178 		if (hw->port_enabled[0]) {
1179 			if (wlandev->netdev->type == ARPHRD_ETHER) {
1180 				/* Save macport 0 state */
1181 				result = hfa384x_drvr_getconfig16(hw,
1182 						  HFA384x_RID_CNFPORTTYPE,
1183 						  &(hw->presniff_port_type));
1184 				if (result) {
1185 					pr_debug
1186 					("failed to read porttype, result=%d\n",
1187 					     result);
1188 					goto failed;
1189 				}
1190 				/* Save the wepflags state */
1191 				result = hfa384x_drvr_getconfig16(hw,
1192 						  HFA384x_RID_CNFWEPFLAGS,
1193 						  &(hw->presniff_wepflags));
1194 				if (result) {
1195 					pr_debug
1196 					("failed to read wepflags, result=%d\n",
1197 					     result);
1198 					goto failed;
1199 				}
1200 				hfa384x_drvr_stop(hw);
1201 				result = hfa384x_drvr_start(hw);
1202 				if (result) {
1203 					pr_debug("failed to restart the card for sniffing, result=%d\n",
1204 						 result);
1205 					goto failed;
1206 				}
1207 			} else {
1208 				/* Disable the port */
1209 				result = hfa384x_drvr_disable(hw, 0);
1210 				if (result) {
1211 					pr_debug("failed to enable port for sniffing, result=%d\n",
1212 						 result);
1213 					goto failed;
1214 				}
1215 			}
1216 		} else {
1217 			hw->presniff_port_type = 0;
1218 		}
1219 
1220 		/* Set the channel we wish to sniff  */
1221 		word = msg->channel.data;
1222 		result = hfa384x_drvr_setconfig16(hw,
1223 						  HFA384x_RID_CNFOWNCHANNEL,
1224 						  word);
1225 		hw->sniff_channel = word;
1226 
1227 		if (result) {
1228 			pr_debug("failed to set channel %d, result=%d\n",
1229 				 word, result);
1230 			goto failed;
1231 		}
1232 
1233 		/* Now if we're already sniffing, we can skip the rest */
1234 		if (wlandev->netdev->type != ARPHRD_ETHER) {
1235 			/* Set the port type to pIbss */
1236 			word = HFA384x_PORTTYPE_PSUEDOIBSS;
1237 			result = hfa384x_drvr_setconfig16(hw,
1238 						  HFA384x_RID_CNFPORTTYPE,
1239 						  word);
1240 			if (result) {
1241 				pr_debug
1242 				    ("failed to set porttype %d, result=%d\n",
1243 				     word, result);
1244 				goto failed;
1245 			}
1246 			if ((msg->keepwepflags.status ==
1247 			     P80211ENUM_msgitem_status_data_ok)
1248 			    && (msg->keepwepflags.data !=
1249 				P80211ENUM_truth_true)) {
1250 				/* Set the wepflags for no decryption */
1251 				word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
1252 				    HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
1253 				result =
1254 				    hfa384x_drvr_setconfig16(hw,
1255 						     HFA384x_RID_CNFWEPFLAGS,
1256 						     word);
1257 			}
1258 
1259 			if (result) {
1260 				pr_debug
1261 				  ("failed to set wepflags=0x%04x, result=%d\n",
1262 				   word, result);
1263 				goto failed;
1264 			}
1265 		}
1266 
1267 		/* Do we want to strip the FCS in monitor mode? */
1268 		if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok)
1269 		    && (msg->stripfcs.data == P80211ENUM_truth_true)) {
1270 			hw->sniff_fcs = 0;
1271 		} else {
1272 			hw->sniff_fcs = 1;
1273 		}
1274 
1275 		/* Do we want to truncate the packets? */
1276 		if (msg->packet_trunc.status ==
1277 		    P80211ENUM_msgitem_status_data_ok) {
1278 			hw->sniff_truncate = msg->packet_trunc.data;
1279 		} else {
1280 			hw->sniff_truncate = 0;
1281 		}
1282 
1283 		/* Enable the port */
1284 		result = hfa384x_drvr_enable(hw, 0);
1285 		if (result) {
1286 			pr_debug
1287 			    ("failed to enable port for sniffing, result=%d\n",
1288 			     result);
1289 			goto failed;
1290 		}
1291 		/* Enable monitor mode */
1292 		result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
1293 		if (result) {
1294 			pr_debug("failed to enable monitor mode, result=%d\n",
1295 				 result);
1296 			goto failed;
1297 		}
1298 
1299 		if (wlandev->netdev->type == ARPHRD_ETHER)
1300 			netdev_info(wlandev->netdev, "monitor mode enabled\n");
1301 
1302 		/* Set the driver state */
1303 		/* Do we want the prism2 header? */
1304 		if ((msg->prismheader.status ==
1305 		     P80211ENUM_msgitem_status_data_ok) &&
1306 		    (msg->prismheader.data == P80211ENUM_truth_true)) {
1307 			hw->sniffhdr = 0;
1308 			wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1309 		} else if ((msg->wlanheader.status ==
1310 			    P80211ENUM_msgitem_status_data_ok) &&
1311 			   (msg->wlanheader.data == P80211ENUM_truth_true)) {
1312 			hw->sniffhdr = 1;
1313 			wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1314 		} else {
1315 			wlandev->netdev->type = ARPHRD_IEEE80211;
1316 		}
1317 
1318 		msg->resultcode.data = P80211ENUM_resultcode_success;
1319 		return 0;
1320 	default:
1321 		msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1322 		return 0;
1323 	}
1324 
1325 failed:
1326 	msg->resultcode.data = P80211ENUM_resultcode_refused;
1327 	return 0;
1328 }
1329