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