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