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