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