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