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