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