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