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